diff --git a/python/dune/codegen/sumfact/permutation.py b/python/dune/codegen/sumfact/permutation.py
index 0c98b3689f506741acfdd01a2162ad1d7dbc1e5d..1f775eba4e8ddf4cc5df8c5a8295e4794ea24d87 100644
--- a/python/dune/codegen/sumfact/permutation.py
+++ b/python/dune/codegen/sumfact/permutation.py
@@ -4,6 +4,7 @@ import itertools
 
 from dune.codegen.options import get_option
 from dune.codegen.sumfact.switch import get_facedir, get_facemod
+from dune.codegen.ufl.modified_terminals import Restriction
 
 
 def sumfact_permutation_heuristic(permutations, stage):
@@ -116,26 +117,34 @@ def sumfact_quadrature_permutation_strategy(dim, restriction):
     # Use a simpler convention for structured grids. In this case we can always
     # go through the directions in the normal order. The same is true for 2D
     # and sum factorization on volumes.
-    if (not get_option('grid_unstructured')) or dim == 2 or restriction == 0:
+    if (not get_option('grid_unstructured')) or dim == 2 or restriction == Restriction.NONE:
         return tuple(range(dim))
     else:
+        # Draw a cube with edge orientations. We always do the normal direction
+        # first. The first case for facedir=0, facemod=0 was chosen that way,
+        # all others can be derived by rotating the cube and matching edge
+        # directions.
         def _order_on_self(restriction):
             facedir = get_facedir(restriction)
             facemod = get_facemod(restriction)
 
-            # Here we specify the convention
-            if (facedir, facemod) in [(0, 0), (1, 1), (2, 0)]:
-                return tuple(range(dim))
-            else:
-                l = list(range(dim))
-                l.reverse()
-                return tuple(l)
-
-        # On neighbor we need the reverse order
-        if restriction == 1:
+            quadrature_order = {
+                (0, 0): (0, 1, 2),
+                (0, 1): (0, 2, 1),
+                (1, 0): (1, 2, 0),
+                (1, 1): (1, 0, 2),
+                (2, 0): (2, 0, 1),
+                (2, 1): (2, 1, 0),
+            }
+
+            return quadrature_order[(facedir, facemod)]
+
+        # On neighbor we also do the normal direction first. The other two can
+        # be derived by putting a second edge oriented cube besides the first
+        # one. Then rotate and match edge directions.
+        if restriction == Restriction.POSITIVE:
             return _order_on_self(restriction)
         else:
-            assert restriction == 2
+            assert restriction == Restriction.NEGATIVE
             l = list(_order_on_self(restriction))
-            l.reverse()
-            return tuple(l)
+            return (l[0], l[2], l[1])