Ver código fonte

refactor: Use an enum for ConfigArgType, add it to input object

Michael Bromley 6 anos atrás
pai
commit
071d3ecf19
34 arquivos alterados com 273 adições e 131 exclusões
  1. 1 0
      admin-ui/src/app/catalog/components/collection-detail/collection-detail.component.ts
  2. 9 9
      admin-ui/src/app/common/utilities/interpolate-description.spec.ts
  3. 3 3
      admin-ui/src/app/common/utilities/interpolate-description.ts
  4. 1 0
      admin-ui/src/app/marketing/components/promotion-detail/promotion-detail.component.ts
  5. 7 12
      admin-ui/src/app/settings/components/payment-method-detail/payment-method-detail.component.ts
  6. 1 0
      admin-ui/src/app/settings/components/shipping-method-detail/shipping-method-detail.component.ts
  7. 6 6
      admin-ui/src/app/shared/components/configurable-input/configurable-input.component.html
  8. 2 1
      admin-ui/src/app/shared/components/configurable-input/configurable-input.component.ts
  9. 0 0
      schema-admin.json
  10. 0 0
      schema-shop.json
  11. 68 5
      schema.json
  12. 1 1
      server/e2e/__snapshots__/collection.e2e-spec.ts.snap
  13. 8 8
      server/e2e/__snapshots__/promotion.e2e-spec.ts.snap
  14. 15 2
      server/e2e/collection.e2e-spec.ts
  15. 7 6
      server/e2e/promotion.e2e-spec.ts
  16. 8 3
      server/src/api/resolvers/admin/collection.resolver.ts
  17. 22 2
      server/src/api/schema/common/common-types.graphql
  18. 14 26
      server/src/common/configurable-operation.ts
  19. 2 2
      server/src/config/collection/collection-filter.ts
  20. 3 1
      server/src/config/collection/default-collection-filters.ts
  21. 3 1
      server/src/config/payment-method/example-payment-method-config.ts
  22. 3 2
      server/src/config/payment-method/payment-method-handler.ts
  23. 6 4
      server/src/config/promotion/default-promotion-actions.ts
  24. 6 5
      server/src/config/promotion/default-promotion-conditions.ts
  25. 6 2
      server/src/config/promotion/promotion-action.ts
  26. 8 2
      server/src/config/promotion/promotion-condition.ts
  27. 3 1
      server/src/config/shipping-method/default-shipping-calculator.ts
  28. 6 2
      server/src/config/shipping-method/shipping-calculator.ts
  29. 6 2
      server/src/config/shipping-method/shipping-eligibility-checker.ts
  30. 2 2
      server/src/data-import/providers/populator/populator.ts
  31. 10 9
      server/src/service/helpers/order-calculator/order-calculator.spec.ts
  32. 4 4
      server/src/service/services/payment-method.service.ts
  33. 15 3
      shared/generated-shop-types.ts
  34. 17 5
      shared/generated-types.ts

+ 1 - 0
admin-ui/src/app/catalog/components/collection-detail/collection-detail.component.ts

@@ -241,6 +241,7 @@ export class CollectionDetailComponent extends BaseDetailComponent<Collection.Fr
                 arguments: Object.values(formValueOperations[i].args).map((value, j) => ({
                 arguments: Object.values(formValueOperations[i].args).map((value, j) => ({
                     name: o.args[j].name,
                     name: o.args[j].name,
                     value: value.toString(),
                     value: value.toString(),
+                    type: o.args[j].type,
                 })),
                 })),
             };
             };
         });
         });

+ 9 - 9
admin-ui/src/app/common/utilities/interpolate-description.spec.ts

@@ -1,11 +1,11 @@
-import { ConfigurableOperation } from 'shared/generated-types';
+import { ConfigArgType, ConfigurableOperation } from 'shared/generated-types';
 
 
 import { interpolateDescription } from './interpolate-description';
 import { interpolateDescription } from './interpolate-description';
 
 
 describe('interpolateDescription()', () => {
 describe('interpolateDescription()', () => {
     it('works for single argument', () => {
     it('works for single argument', () => {
         const operation: Partial<ConfigurableOperation> = {
         const operation: Partial<ConfigurableOperation> = {
-            args: [{ name: 'foo', type: 'string' }],
+            args: [{ name: 'foo', type: ConfigArgType.STRING }],
             description: 'The value is { foo }',
             description: 'The value is { foo }',
         };
         };
         const result = interpolateDescription(operation as any, { foo: 'val' });
         const result = interpolateDescription(operation as any, { foo: 'val' });
@@ -15,7 +15,7 @@ describe('interpolateDescription()', () => {
 
 
     it('works for multiple arguments', () => {
     it('works for multiple arguments', () => {
         const operation: Partial<ConfigurableOperation> = {
         const operation: Partial<ConfigurableOperation> = {
-            args: [{ name: 'foo', type: 'string' }, { name: 'bar', type: 'string' }],
+            args: [{ name: 'foo', type: ConfigArgType.STRING }, { name: 'bar', type: ConfigArgType.STRING }],
             description: 'The value is { foo } and { bar }',
             description: 'The value is { foo } and { bar }',
         };
         };
         const result = interpolateDescription(operation as any, { foo: 'val1', bar: 'val2' });
         const result = interpolateDescription(operation as any, { foo: 'val1', bar: 'val2' });
@@ -25,7 +25,7 @@ describe('interpolateDescription()', () => {
 
 
     it('is case-insensitive', () => {
     it('is case-insensitive', () => {
         const operation: Partial<ConfigurableOperation> = {
         const operation: Partial<ConfigurableOperation> = {
-            args: [{ name: 'foo', type: 'string' }],
+            args: [{ name: 'foo', type: ConfigArgType.STRING }],
             description: 'The value is { FOo }',
             description: 'The value is { FOo }',
         };
         };
         const result = interpolateDescription(operation as any, { foo: 'val' });
         const result = interpolateDescription(operation as any, { foo: 'val' });
@@ -35,7 +35,7 @@ describe('interpolateDescription()', () => {
 
 
     it('ignores whitespaces in interpolation', () => {
     it('ignores whitespaces in interpolation', () => {
         const operation: Partial<ConfigurableOperation> = {
         const operation: Partial<ConfigurableOperation> = {
-            args: [{ name: 'foo', type: 'string' }, { name: 'bar', type: 'string' }],
+            args: [{ name: 'foo', type: ConfigArgType.STRING }, { name: 'bar', type: ConfigArgType.STRING }],
             description: 'The value is {foo} and {      bar    }',
             description: 'The value is {foo} and {      bar    }',
         };
         };
         const result = interpolateDescription(operation as any, { foo: 'val1', bar: 'val2' });
         const result = interpolateDescription(operation as any, { foo: 'val1', bar: 'val2' });
@@ -45,7 +45,7 @@ describe('interpolateDescription()', () => {
 
 
     it('formats money as a decimal', () => {
     it('formats money as a decimal', () => {
         const operation: Partial<ConfigurableOperation> = {
         const operation: Partial<ConfigurableOperation> = {
-            args: [{ name: 'price', type: 'money' }],
+            args: [{ name: 'price', type: ConfigArgType.MONEY }],
             description: 'The price is { price }',
             description: 'The price is { price }',
         };
         };
         const result = interpolateDescription(operation as any, { price: 1234 });
         const result = interpolateDescription(operation as any, { price: 1234 });
@@ -55,7 +55,7 @@ describe('interpolateDescription()', () => {
 
 
     it('formats Date object as human-readable', () => {
     it('formats Date object as human-readable', () => {
         const operation: Partial<ConfigurableOperation> = {
         const operation: Partial<ConfigurableOperation> = {
-            args: [{ name: 'date', type: 'datetime' }],
+            args: [{ name: 'date', type: ConfigArgType.DATETIME }],
             description: 'The date is { date }',
             description: 'The date is { date }',
         };
         };
         const date = new Date('2017-09-15 00:00:00');
         const date = new Date('2017-09-15 00:00:00');
@@ -66,7 +66,7 @@ describe('interpolateDescription()', () => {
 
 
     it('formats date string object as human-readable', () => {
     it('formats date string object as human-readable', () => {
         const operation: Partial<ConfigurableOperation> = {
         const operation: Partial<ConfigurableOperation> = {
-            args: [{ name: 'date', type: 'datetime' }],
+            args: [{ name: 'date', type: ConfigArgType.DATETIME }],
             description: 'The date is { date }',
             description: 'The date is { date }',
         };
         };
         const date = '2017-09-15';
         const date = '2017-09-15';
@@ -77,7 +77,7 @@ describe('interpolateDescription()', () => {
 
 
     it('correctly interprets falsy-looking values', () => {
     it('correctly interprets falsy-looking values', () => {
         const operation: Partial<ConfigurableOperation> = {
         const operation: Partial<ConfigurableOperation> = {
-            args: [{ name: 'foo', type: 'int' }],
+            args: [{ name: 'foo', type: ConfigArgType.INT }],
             description: 'The value is { foo }',
             description: 'The value is { foo }',
         };
         };
         const result = interpolateDescription(operation as any, { foo: 0 });
         const result = interpolateDescription(operation as any, { foo: 0 });

+ 3 - 3
admin-ui/src/app/common/utilities/interpolate-description.ts

@@ -1,4 +1,4 @@
-import { ConfigurableOperation } from 'shared/generated-types';
+import { ConfigArgType, ConfigurableOperation } from 'shared/generated-types';
 
 
 /**
 /**
  * Interpolates the description of an ConfigurableOperation with the given values.
  * Interpolates the description of an ConfigurableOperation with the given values.
@@ -19,10 +19,10 @@ export function interpolateDescription(
         }
         }
         let formatted = value;
         let formatted = value;
         const argDef = operation.args.find(arg => arg.name === normalizedArgName);
         const argDef = operation.args.find(arg => arg.name === normalizedArgName);
-        if (argDef && argDef.type === 'money') {
+        if (argDef && argDef.type === ConfigArgType.MONEY) {
             formatted = value / 100;
             formatted = value / 100;
         }
         }
-        if (argDef && argDef.type === 'datetime' && value instanceof Date) {
+        if (argDef && argDef.type === ConfigArgType.DATETIME && value instanceof Date) {
             formatted = value.toLocaleDateString();
             formatted = value.toLocaleDateString();
         }
         }
         return formatted;
         return formatted;

+ 1 - 0
admin-ui/src/app/marketing/components/promotion-detail/promotion-detail.component.ts

@@ -196,6 +196,7 @@ export class PromotionDetailComponent extends BaseDetailComponent<Promotion.Frag
                 arguments: Object.values(formValueOperations[i].args).map((value, j) => ({
                 arguments: Object.values(formValueOperations[i].args).map((value, j) => ({
                     name: o.args[j].name,
                     name: o.args[j].name,
                     value: value.toString(),
                     value: value.toString(),
+                    type: o.args[j].type,
                 })),
                 })),
             };
             };
         });
         });

+ 7 - 12
admin-ui/src/app/settings/components/payment-method-detail/payment-method-detail.component.ts

@@ -1,14 +1,8 @@
 import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
 import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
-import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
 import { ActivatedRoute, Router } from '@angular/router';
 import { ActivatedRoute, Router } from '@angular/router';
 import { mergeMap, take } from 'rxjs/operators';
 import { mergeMap, take } from 'rxjs/operators';
-import {
-    ConfigArg,
-    ConfigurableOperation,
-    ConfigurableOperationInput,
-    PaymentMethod,
-    UpdatePaymentMethodInput,
-} from 'shared/generated-types';
+import { ConfigArg, ConfigArgType, PaymentMethod, UpdatePaymentMethodInput } from 'shared/generated-types';
 
 
 import { BaseDetailComponent } from '../../../common/base-detail.component';
 import { BaseDetailComponent } from '../../../common/base-detail.component';
 import { _ } from '../../../core/providers/i18n/mark-for-extraction';
 import { _ } from '../../../core/providers/i18n/mark-for-extraction';
@@ -55,15 +49,16 @@ export class PaymentMethodDetailComponent extends BaseDetailComponent<PaymentMet
         this.entity$
         this.entity$
             .pipe(
             .pipe(
                 take(1),
                 take(1),
-                mergeMap(({ id }) => {
+                mergeMap(({ id, configArgs }) => {
                     const formValue = this.detailForm.value;
                     const formValue = this.detailForm.value;
                     const input: UpdatePaymentMethodInput = {
                     const input: UpdatePaymentMethodInput = {
                         id,
                         id,
                         code: formValue.code,
                         code: formValue.code,
                         enabled: formValue.enabled,
                         enabled: formValue.enabled,
-                        configArgs: Object.entries(formValue.configArgs).map(([name, value]) => ({
+                        configArgs: Object.entries(formValue.configArgs).map(([name, value], i) => ({
                             name,
                             name,
                             value: value.toString(),
                             value: value.toString(),
+                            type: configArgs[i].type,
                         })),
                         })),
                     };
                     };
                     return this.dataService.settings.updatePaymentMethod(input);
                     return this.dataService.settings.updatePaymentMethod(input);
@@ -105,9 +100,9 @@ export class PaymentMethodDetailComponent extends BaseDetailComponent<PaymentMet
 
 
     private parseArgValue(arg: ConfigArg): string | number | boolean {
     private parseArgValue(arg: ConfigArg): string | number | boolean {
         switch (arg.type) {
         switch (arg.type) {
-            case 'int':
+            case ConfigArgType.INT:
                 return Number.parseInt(arg.value || '0', 10);
                 return Number.parseInt(arg.value || '0', 10);
-            case 'boolean':
+            case ConfigArgType.BOOLEAN:
                 return arg.value === 'false' ? false : true;
                 return arg.value === 'false' ? false : true;
             default:
             default:
                 return arg.value || '';
                 return arg.value || '';

+ 1 - 0
admin-ui/src/app/settings/components/shipping-method-detail/shipping-method-detail.component.ts

@@ -147,6 +147,7 @@ export class ShippingMethodDetailComponent extends BaseDetailComponent<ShippingM
             arguments: Object.values(formValueOperations.args || {}).map((value, j) => ({
             arguments: Object.values(formValueOperations.args || {}).map((value, j) => ({
                 name: operation.args[j].name,
                 name: operation.args[j].name,
                 value: value.toString(),
                 value: value.toString(),
+                type: operation.args[j].type,
             })),
             })),
         };
         };
     }
     }

+ 6 - 6
admin-ui/src/app/shared/components/configurable-input/configurable-input.component.html

@@ -9,36 +9,36 @@
                     <label [for]="arg.name"></label>
                     <label [for]="arg.name"></label>
                 </div>
                 </div>
                 <input
                 <input
-                    *ngIf="arg.type === 'int'"
+                    *ngIf="arg.type === ConfigArgType.INT"
                     [name]="arg.name"
                     [name]="arg.name"
                     type="number"
                     type="number"
                     step="1"
                     step="1"
                     [formControlName]="arg.name"
                     [formControlName]="arg.name"
                 />
                 />
                 <input
                 <input
-                    *ngIf="arg.type === 'string'"
+                    *ngIf="arg.type === ConfigArgType.STRING"
                     [name]="arg.name"
                     [name]="arg.name"
                     type="text"
                     type="text"
                     [formControlName]="arg.name"
                     [formControlName]="arg.name"
                 />
                 />
                 <input
                 <input
-                    *ngIf="arg.type === 'datetime'"
+                    *ngIf="arg.type === ConfigArgType.DATETIME"
                     [name]="arg.name"
                     [name]="arg.name"
                     type="date"
                     type="date"
                     [formControlName]="arg.name"
                     [formControlName]="arg.name"
                 />
                 />
                 <vdr-currency-input
                 <vdr-currency-input
-                    *ngIf="arg.type === 'money'"
+                    *ngIf="arg.type === ConfigArgType.MONEY"
                     [formControlName]="arg.name"
                     [formControlName]="arg.name"
                 ></vdr-currency-input>
                 ></vdr-currency-input>
                 <vdr-percentage-suffix-input
                 <vdr-percentage-suffix-input
-                    *ngIf="arg.type === 'percentage'"
+                    *ngIf="arg.type === ConfigArgType.PERCENTAGE"
                     [formControlName]="arg.name"
                     [formControlName]="arg.name"
                 ></vdr-percentage-suffix-input>
                 ></vdr-percentage-suffix-input>
                 <vdr-facet-value-selector
                 <vdr-facet-value-selector
                     [facets]="facets"
                     [facets]="facets"
                     [formControlName]="arg.name"
                     [formControlName]="arg.name"
-                    *ngIf="arg.type === 'facetValueIds' && facets"
+                    *ngIf="arg.type === ConfigArgType.FACET_VALUE_IDS && facets"
                 ></vdr-facet-value-selector>
                 ></vdr-facet-value-selector>
             </div>
             </div>
         </form>
         </form>

+ 2 - 1
admin-ui/src/app/shared/components/configurable-input/configurable-input.component.ts

@@ -21,7 +21,7 @@ import {
     Validators,
     Validators,
 } from '@angular/forms';
 } from '@angular/forms';
 import { Subscription } from 'rxjs';
 import { Subscription } from 'rxjs';
-import { ConfigurableOperation, FacetWithValues } from 'shared/generated-types';
+import { ConfigArgType, ConfigurableOperation, FacetWithValues } from 'shared/generated-types';
 
 
 import { interpolateDescription } from '../../../common/utilities/interpolate-description';
 import { interpolateDescription } from '../../../common/utilities/interpolate-description';
 
 
@@ -54,6 +54,7 @@ export class ConfigurableInputComponent implements OnChanges, OnDestroy, Control
     onChange: (val: any) => void;
     onChange: (val: any) => void;
     onTouch: () => void;
     onTouch: () => void;
     form = new FormGroup({});
     form = new FormGroup({});
+    ConfigArgType = ConfigArgType;
     private subscription: Subscription;
     private subscription: Subscription;
 
 
     interpolateDescription(): string {
     interpolateDescription(): string {

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
schema-admin.json


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
schema-shop.json


+ 68 - 5
schema.json

@@ -6458,8 +6458,8 @@
               "kind": "NON_NULL",
               "kind": "NON_NULL",
               "name": null,
               "name": null,
               "ofType": {
               "ofType": {
-                "kind": "SCALAR",
-                "name": "String",
+                "kind": "ENUM",
+                "name": "ConfigArgType",
                 "ofType": null
                 "ofType": null
               }
               }
             },
             },
@@ -6484,6 +6484,59 @@
         "enumValues": null,
         "enumValues": null,
         "possibleTypes": null
         "possibleTypes": null
       },
       },
+      {
+        "kind": "ENUM",
+        "name": "ConfigArgType",
+        "description": "Certain entities allow arbitrary configuration arguments to be specified which can then\nbe set in the admin-ui and used in the business logic of the app. These are the valid\ndata types of such arguments. The data type influences:\n\n1. How the argument form field is rendered in the admin-ui\n2. The JavaScript type into which the value is coerced before being passed to the business logic.",
+        "fields": null,
+        "inputFields": null,
+        "interfaces": null,
+        "enumValues": [
+          {
+            "name": "PERCENTAGE",
+            "description": null,
+            "isDeprecated": false,
+            "deprecationReason": null
+          },
+          {
+            "name": "MONEY",
+            "description": null,
+            "isDeprecated": false,
+            "deprecationReason": null
+          },
+          {
+            "name": "INT",
+            "description": null,
+            "isDeprecated": false,
+            "deprecationReason": null
+          },
+          {
+            "name": "STRING",
+            "description": null,
+            "isDeprecated": false,
+            "deprecationReason": null
+          },
+          {
+            "name": "DATETIME",
+            "description": null,
+            "isDeprecated": false,
+            "deprecationReason": null
+          },
+          {
+            "name": "BOOLEAN",
+            "description": null,
+            "isDeprecated": false,
+            "deprecationReason": null
+          },
+          {
+            "name": "FACET_VALUE_IDS",
+            "description": null,
+            "isDeprecated": false,
+            "deprecationReason": null
+          }
+        ],
+        "possibleTypes": null
+      },
       {
       {
         "kind": "OBJECT",
         "kind": "OBJECT",
         "name": "CollectionTranslation",
         "name": "CollectionTranslation",
@@ -17226,18 +17279,28 @@
             "defaultValue": null
             "defaultValue": null
           },
           },
           {
           {
-            "name": "value",
+            "name": "type",
             "description": null,
             "description": null,
             "type": {
             "type": {
               "kind": "NON_NULL",
               "kind": "NON_NULL",
               "name": null,
               "name": null,
               "ofType": {
               "ofType": {
-                "kind": "SCALAR",
-                "name": "String",
+                "kind": "ENUM",
+                "name": "ConfigArgType",
                 "ofType": null
                 "ofType": null
               }
               }
             },
             },
             "defaultValue": null
             "defaultValue": null
+          },
+          {
+            "name": "value",
+            "description": null,
+            "type": {
+              "kind": "SCALAR",
+              "name": "String",
+              "ofType": null
+            },
+            "defaultValue": null
           }
           }
         ],
         ],
         "interfaces": null,
         "interfaces": null,

+ 1 - 1
server/e2e/__snapshots__/collection.e2e-spec.ts.snap

@@ -38,7 +38,7 @@ Object {
       "args": Array [
       "args": Array [
         Object {
         Object {
           "name": "facetValueIds",
           "name": "facetValueIds",
-          "type": "facetValueIds",
+          "type": "FACET_VALUE_IDS",
           "value": "[\\"T_1\\"]",
           "value": "[\\"T_1\\"]",
         },
         },
       ],
       ],

+ 8 - 8
server/e2e/__snapshots__/promotion.e2e-spec.ts.snap

@@ -7,7 +7,7 @@ Object {
       "args": Array [
       "args": Array [
         Object {
         Object {
           "name": "percentage",
           "name": "percentage",
-          "type": "percentage",
+          "type": "PERCENTAGE",
           "value": null,
           "value": null,
         },
         },
       ],
       ],
@@ -20,7 +20,7 @@ Object {
       "args": Array [
       "args": Array [
         Object {
         Object {
           "name": "arg",
           "name": "arg",
-          "type": "money",
+          "type": "MONEY",
           "value": null,
           "value": null,
         },
         },
       ],
       ],
@@ -31,7 +31,7 @@ Object {
       "args": Array [
       "args": Array [
         Object {
         Object {
           "name": "arg",
           "name": "arg",
-          "type": "money",
+          "type": "MONEY",
           "value": null,
           "value": null,
         },
         },
       ],
       ],
@@ -49,7 +49,7 @@ Object {
       "args": Array [
       "args": Array [
         Object {
         Object {
           "name": "percentage",
           "name": "percentage",
-          "type": "percentage",
+          "type": "PERCENTAGE",
           "value": "50",
           "value": "50",
         },
         },
       ],
       ],
@@ -62,7 +62,7 @@ Object {
       "args": Array [
       "args": Array [
         Object {
         Object {
           "name": "arg",
           "name": "arg",
-          "type": "money",
+          "type": "MONEY",
           "value": "500",
           "value": "500",
         },
         },
       ],
       ],
@@ -82,7 +82,7 @@ Object {
       "args": Array [
       "args": Array [
         Object {
         Object {
           "name": "percentage",
           "name": "percentage",
-          "type": "percentage",
+          "type": "PERCENTAGE",
           "value": "50",
           "value": "50",
         },
         },
       ],
       ],
@@ -95,7 +95,7 @@ Object {
       "args": Array [
       "args": Array [
         Object {
         Object {
           "name": "arg",
           "name": "arg",
-          "type": "money",
+          "type": "MONEY",
           "value": "90",
           "value": "90",
         },
         },
       ],
       ],
@@ -106,7 +106,7 @@ Object {
       "args": Array [
       "args": Array [
         Object {
         Object {
           "name": "arg",
           "name": "arg",
-          "type": "money",
+          "type": "MONEY",
           "value": "10",
           "value": "10",
         },
         },
       ],
       ],

+ 15 - 2
server/e2e/collection.e2e-spec.ts

@@ -10,6 +10,7 @@ import {
 } from '../../admin-ui/src/app/data/definitions/product-definitions';
 } from '../../admin-ui/src/app/data/definitions/product-definitions';
 import {
 import {
     Collection,
     Collection,
+    ConfigArgType,
     CreateCollection,
     CreateCollection,
     GetAssetList,
     GetAssetList,
     GetCollection,
     GetCollection,
@@ -67,7 +68,13 @@ describe('Collection resolver', () => {
                         filters: [
                         filters: [
                             {
                             {
                                 code: facetValueCollectionFilter.code,
                                 code: facetValueCollectionFilter.code,
-                                arguments: [{ name: 'facetValueIds', value: `["T_1"]` }],
+                                arguments: [
+                                    {
+                                        name: 'facetValueIds',
+                                        value: `["T_1"]`,
+                                        type: ConfigArgType.FACET_VALUE_IDS,
+                                    },
+                                ],
                             },
                             },
                         ],
                         ],
                         translations: [
                         translations: [
@@ -92,7 +99,13 @@ describe('Collection resolver', () => {
                         filters: [
                         filters: [
                             {
                             {
                                 code: facetValueCollectionFilter.code,
                                 code: facetValueCollectionFilter.code,
-                                arguments: [{ name: 'facetValueIds', value: `["T_2"]` }],
+                                arguments: [
+                                    {
+                                        name: 'facetValueIds',
+                                        value: `["T_2"]`,
+                                        type: ConfigArgType.FACET_VALUE_IDS,
+                                    },
+                                ],
                             },
                             },
                         ],
                         ],
                     },
                     },

+ 7 - 6
server/e2e/promotion.e2e-spec.ts

@@ -9,6 +9,7 @@ import {
     UPDATE_PROMOTION,
     UPDATE_PROMOTION,
 } from '../../admin-ui/src/app/data/definitions/promotion-definitions';
 } from '../../admin-ui/src/app/data/definitions/promotion-definitions';
 import {
 import {
+    ConfigArgType,
     CreatePromotion,
     CreatePromotion,
     DeletionResult,
     DeletionResult,
     GetAdjustmentOperations,
     GetAdjustmentOperations,
@@ -72,13 +73,13 @@ describe('Promotion resolver', () => {
                     conditions: [
                     conditions: [
                         {
                         {
                             code: promoCondition.code,
                             code: promoCondition.code,
-                            arguments: [{ name: 'arg', value: '500' }],
+                            arguments: [{ name: 'arg', value: '500', type: ConfigArgType.MONEY }],
                         },
                         },
                     ],
                     ],
                     actions: [
                     actions: [
                         {
                         {
                             code: promoAction.code,
                             code: promoAction.code,
-                            arguments: [{ name: 'percentage', value: '50' }],
+                            arguments: [{ name: 'percentage', value: '50', type: ConfigArgType.PERCENTAGE }],
                         },
                         },
                     ],
                     ],
                 },
                 },
@@ -97,11 +98,11 @@ describe('Promotion resolver', () => {
                     conditions: [
                     conditions: [
                         {
                         {
                             code: promoCondition.code,
                             code: promoCondition.code,
-                            arguments: [{ name: 'arg', value: '90' }],
+                            arguments: [{ name: 'arg', value: '90', type: ConfigArgType.MONEY }],
                         },
                         },
                         {
                         {
                             code: promoCondition2.code,
                             code: promoCondition2.code,
-                            arguments: [{ name: 'arg', value: '10' }],
+                            arguments: [{ name: 'arg', value: '10', type: ConfigArgType.MONEY }],
                         },
                         },
                     ],
                     ],
                 },
                 },
@@ -187,7 +188,7 @@ function generateTestCondition(code: string): PromotionCondition<any> {
     return new PromotionCondition({
     return new PromotionCondition({
         code,
         code,
         description: `description for ${code}`,
         description: `description for ${code}`,
-        args: { arg: 'money' },
+        args: { arg: ConfigArgType.MONEY },
         check: (order, args) => true,
         check: (order, args) => true,
     });
     });
 }
 }
@@ -196,7 +197,7 @@ function generateTestAction(code: string): PromotionAction<any> {
     return new PromotionOrderAction({
     return new PromotionOrderAction({
         code,
         code,
         description: `description for ${code}`,
         description: `description for ${code}`,
-        args: { percentage: 'percentage' },
+        args: { percentage: ConfigArgType.PERCENTAGE },
         execute: (order, args) => {
         execute: (order, args) => {
             return 42;
             return 42;
         },
         },

+ 8 - 3
server/src/api/resolvers/admin/collection.resolver.ts

@@ -15,6 +15,7 @@ import { CollectionFilter } from '../../../config/collection/collection-filter';
 import { Collection } from '../../../entity/collection/collection.entity';
 import { Collection } from '../../../entity/collection/collection.entity';
 import { CollectionService } from '../../../service/services/collection.service';
 import { CollectionService } from '../../../service/services/collection.service';
 import { FacetValueService } from '../../../service/services/facet-value.service';
 import { FacetValueService } from '../../../service/services/facet-value.service';
+import { IdCodecService } from '../../common/id-codec.service';
 import { RequestContext } from '../../common/request-context';
 import { RequestContext } from '../../common/request-context';
 import { Allow } from '../../decorators/allow.decorator';
 import { Allow } from '../../decorators/allow.decorator';
 import { Decode } from '../../decorators/decode.decorator';
 import { Decode } from '../../decorators/decode.decorator';
@@ -22,7 +23,11 @@ import { Ctx } from '../../decorators/request-context.decorator';
 
 
 @Resolver()
 @Resolver()
 export class CollectionResolver {
 export class CollectionResolver {
-    constructor(private collectionService: CollectionService, private facetValueService: FacetValueService) {}
+    constructor(
+        private collectionService: CollectionService,
+        private facetValueService: FacetValueService,
+        private idCodecService: IdCodecService,
+    ) {}
 
 
     @Query()
     @Query()
     @Allow(Permission.ReadCatalog)
     @Allow(Permission.ReadCatalog)
@@ -53,7 +58,7 @@ export class CollectionResolver {
 
 
     @Mutation()
     @Mutation()
     @Allow(Permission.CreateCatalog)
     @Allow(Permission.CreateCatalog)
-    @Decode('assetIds', 'featuredAssetId', 'parentId', 'facetValueIds')
+    @Decode('assetIds', 'featuredAssetId', 'parentId')
     async createCollection(
     async createCollection(
         @Ctx() ctx: RequestContext,
         @Ctx() ctx: RequestContext,
         @Args() args: CreateCollectionMutationArgs,
         @Args() args: CreateCollectionMutationArgs,
@@ -64,7 +69,7 @@ export class CollectionResolver {
 
 
     @Mutation()
     @Mutation()
     @Allow(Permission.UpdateCatalog)
     @Allow(Permission.UpdateCatalog)
-    @Decode('assetIds', 'featuredAssetId', 'facetValueIds')
+    @Decode('assetIds', 'featuredAssetId')
     async updateCollection(
     async updateCollection(
         @Ctx() ctx: RequestContext,
         @Ctx() ctx: RequestContext,
         @Args() args: UpdateCollectionMutationArgs,
         @Args() args: UpdateCollectionMutationArgs,

+ 22 - 2
server/src/api/schema/common/common-types.graphql

@@ -20,9 +20,28 @@ type Adjustment {
     amount: Int!
     amount: Int!
 }
 }
 
 
+"""
+Certain entities allow arbitrary configuration arguments to be specified which can then
+be set in the admin-ui and used in the business logic of the app. These are the valid
+data types of such arguments. The data type influences:
+
+1. How the argument form field is rendered in the admin-ui
+2. The JavaScript type into which the value is coerced before being passed to the business logic.
+
+"""
+enum ConfigArgType {
+    PERCENTAGE
+    MONEY
+    INT
+    STRING
+    DATETIME
+    BOOLEAN
+    FACET_VALUE_IDS
+}
+
 type ConfigArg {
 type ConfigArg {
     name: String!
     name: String!
-    type: String!
+    type: ConfigArgType!
     value: String
     value: String
 }
 }
 
 
@@ -46,7 +65,8 @@ type DeletionResponse {
 
 
 input ConfigArgInput {
 input ConfigArgInput {
     name: String!
     name: String!
-    value: String!
+    type: ConfigArgType!
+    value: String
 }
 }
 
 
 input ConfigurableOperationInput {
 input ConfigurableOperationInput {

+ 14 - 26
server/src/common/configurable-operation.ts

@@ -1,24 +1,8 @@
 // prettier-ignore
 // prettier-ignore
-import { ConfigArg, ConfigurableOperation } from '../../../shared/generated-types';
+import { ConfigArg, ConfigArgType, ConfigurableOperation } from '../../../shared/generated-types';
 
 
 import { InternalServerError } from './error/errors';
 import { InternalServerError } from './error/errors';
 
 
-/**
- * Certain entities allow arbitrary configuration arguments to be specified which can then
- * be set in the admin-ui and used in the business logic of the app. These are the valid
- * data types of such arguments. The data type influences:
- * 1. How the argument form field is rendered in the admin-ui
- * 2. The JavaScript type into which the value is coerced before being passed to the business logic.
- */
-export type ConfigArgType =
-    | 'percentage'
-    | 'money'
-    | 'int'
-    | 'string'
-    | 'datetime'
-    | 'boolean'
-    | 'facetValueIds';
-
 export type ConfigArgs<T extends ConfigArgType> = {
 export type ConfigArgs<T extends ConfigArgType> = {
     [name: string]: T;
     [name: string]: T;
 };
 };
@@ -28,13 +12,13 @@ export type ConfigArgs<T extends ConfigArgType> = {
  * in business logic.
  * in business logic.
  */
  */
 export type ConfigArgValues<T extends ConfigArgs<any>> = {
 export type ConfigArgValues<T extends ConfigArgs<any>> = {
-    [K in keyof T]: T[K] extends 'int' | 'money' | 'percentage'
+    [K in keyof T]: T[K] extends ConfigArgType.INT | ConfigArgType.MONEY | ConfigArgType.PERCENTAGE
         ? number
         ? number
-        : T[K] extends 'datetime'
+        : T[K] extends ConfigArgType.DATETIME
         ? Date
         ? Date
-        : T[K] extends 'boolean'
+        : T[K] extends ConfigArgType.BOOLEAN
         ? boolean
         ? boolean
-        : T[K] extends 'facetValueIds'
+        : T[K] extends ConfigArgType.FACET_VALUE_IDS
         ? string[]
         ? string[]
         : string
         : string
 };
 };
@@ -82,14 +66,18 @@ export function argsArrayToHash<T>(args: ConfigArg[]): ConfigArgValues<T> {
 
 
 function coerceValueToType<T>(arg: ConfigArg): ConfigArgValues<T>[keyof T] {
 function coerceValueToType<T>(arg: ConfigArg): ConfigArgValues<T>[keyof T] {
     switch (arg.type as ConfigArgType) {
     switch (arg.type as ConfigArgType) {
-        case 'int':
-        case 'money':
+        case ConfigArgType.STRING:
+            return arg.value as any;
+        case ConfigArgType.INT:
+        case ConfigArgType.MONEY:
             return Number.parseInt(arg.value || '', 10) as any;
             return Number.parseInt(arg.value || '', 10) as any;
-        case 'datetime':
+        case ConfigArgType.DATETIME:
             return Date.parse(arg.value || '') as any;
             return Date.parse(arg.value || '') as any;
-        case 'boolean':
+        case ConfigArgType.BOOLEAN:
             return !!arg.value as any;
             return !!arg.value as any;
-        case 'facetValueIds':
+        case ConfigArgType.PERCENTAGE:
+            return arg.value as any;
+        case ConfigArgType.FACET_VALUE_IDS:
             try {
             try {
                 return JSON.parse(arg.value as any);
                 return JSON.parse(arg.value as any);
             } catch (err) {
             } catch (err) {

+ 2 - 2
server/src/config/collection/collection-filter.ts

@@ -1,6 +1,6 @@
 import { SelectQueryBuilder } from 'typeorm';
 import { SelectQueryBuilder } from 'typeorm';
 
 
-import { ConfigArg } from '../../../../shared/generated-types';
+import { ConfigArg, ConfigArgType } from '../../../../shared/generated-types';
 import {
 import {
     argsArrayToHash,
     argsArrayToHash,
     ConfigArgs,
     ConfigArgs,
@@ -9,7 +9,7 @@ import {
 } from '../../common/configurable-operation';
 } from '../../common/configurable-operation';
 import { ProductVariant } from '../../entity/product-variant/product-variant.entity';
 import { ProductVariant } from '../../entity/product-variant/product-variant.entity';
 
 
-export type CollectionFilterArgType = 'facetValueIds';
+export type CollectionFilterArgType = ConfigArgType.FACET_VALUE_IDS;
 export type CollectionFilterArgs = ConfigArgs<CollectionFilterArgType>;
 export type CollectionFilterArgs = ConfigArgs<CollectionFilterArgType>;
 
 
 export type ApplyCollectionFilterFn<T extends CollectionFilterArgs> = (
 export type ApplyCollectionFilterFn<T extends CollectionFilterArgs> = (

+ 3 - 1
server/src/config/collection/default-collection-filters.ts

@@ -1,5 +1,7 @@
 import { Brackets } from 'typeorm';
 import { Brackets } from 'typeorm';
 
 
+import { ConfigArgType } from '../../../../shared/generated-types';
+
 import { CollectionFilter } from './collection-filter';
 import { CollectionFilter } from './collection-filter';
 
 
 /**
 /**
@@ -7,7 +9,7 @@ import { CollectionFilter } from './collection-filter';
  */
  */
 export const facetValueCollectionFilter = new CollectionFilter({
 export const facetValueCollectionFilter = new CollectionFilter({
     args: {
     args: {
-        facetValueIds: 'facetValueIds',
+        facetValueIds: ConfigArgType.FACET_VALUE_IDS,
     },
     },
     code: 'facet-value-filter',
     code: 'facet-value-filter',
     description: 'Filter by FacetValues',
     description: 'Filter by FacetValues',

+ 3 - 1
server/src/config/payment-method/example-payment-method-config.ts

@@ -1,3 +1,5 @@
+import { ConfigArgType } from '../../../../shared/generated-types';
+
 import { PaymentConfig, PaymentMethodHandler } from './payment-method-handler';
 import { PaymentConfig, PaymentMethodHandler } from './payment-method-handler';
 
 
 /**
 /**
@@ -23,7 +25,7 @@ export const examplePaymentHandler = new PaymentMethodHandler({
     code: 'example-payment-provider',
     code: 'example-payment-provider',
     name: 'Example Payment Provider',
     name: 'Example Payment Provider',
     args: {
     args: {
-        apiKey: 'string',
+        apiKey: ConfigArgType.STRING,
     },
     },
     createPayment: async (order, args, metadata): Promise<PaymentConfig> => {
     createPayment: async (order, args, metadata): Promise<PaymentConfig> => {
         try {
         try {

+ 3 - 2
server/src/config/payment-method/payment-method-handler.ts

@@ -1,4 +1,4 @@
-import { ConfigArg } from '../../../../shared/generated-types';
+import { ConfigArg, ConfigArgType } from '../../../../shared/generated-types';
 
 
 import { argsArrayToHash, ConfigArgs, ConfigArgValues } from '../../common/configurable-operation';
 import { argsArrayToHash, ConfigArgs, ConfigArgValues } from '../../common/configurable-operation';
 import { StateMachineConfig } from '../../common/finite-state-machine';
 import { StateMachineConfig } from '../../common/finite-state-machine';
@@ -9,7 +9,7 @@ import {
     PaymentTransitionData,
     PaymentTransitionData,
 } from '../../service/helpers/payment-state-machine/payment-state';
 } from '../../service/helpers/payment-state-machine/payment-state';
 
 
-export type PaymentMethodArgType = 'int' | 'string' | 'boolean';
+export type PaymentMethodArgType = ConfigArgType.INT | ConfigArgType.STRING | ConfigArgType.BOOLEAN;
 export type PaymentMethodArgs = ConfigArgs<PaymentMethodArgType>;
 export type PaymentMethodArgs = ConfigArgs<PaymentMethodArgType>;
 export type OnTransitionStartReturnType = ReturnType<Required<StateMachineConfig<any>>['onTransitionStart']>;
 export type OnTransitionStartReturnType = ReturnType<Required<StateMachineConfig<any>>['onTransitionStart']>;
 
 
@@ -134,6 +134,7 @@ export interface PaymentMethodConfigOptions<T extends PaymentMethodArgs = Paymen
  *     },
  *     },
  * });
  * });
  * ```
  * ```
+ * // TODO: Refactor to implement ConfigurableOperationDef interface
  *
  *
  * @docsCategory payment
  * @docsCategory payment
  */
  */

+ 6 - 4
server/src/config/promotion/default-promotion-actions.ts

@@ -1,8 +1,10 @@
-import { PromotionAction, PromotionItemAction, PromotionOrderAction } from './promotion-action';
+import { ConfigArgType } from '../../../../shared/generated-types';
+
+import { PromotionItemAction, PromotionOrderAction } from './promotion-action';
 
 
 export const orderPercentageDiscount = new PromotionOrderAction({
 export const orderPercentageDiscount = new PromotionOrderAction({
     code: 'order_percentage_discount',
     code: 'order_percentage_discount',
-    args: { discount: 'percentage' },
+    args: { discount: ConfigArgType.PERCENTAGE },
     execute(order, args) {
     execute(order, args) {
         return -order.subTotal * (args.discount / 100);
         return -order.subTotal * (args.discount / 100);
     },
     },
@@ -11,7 +13,7 @@ export const orderPercentageDiscount = new PromotionOrderAction({
 
 
 export const itemPercentageDiscount = new PromotionItemAction({
 export const itemPercentageDiscount = new PromotionItemAction({
     code: 'item_percentage_discount',
     code: 'item_percentage_discount',
-    args: { discount: 'percentage' },
+    args: { discount: ConfigArgType.PERCENTAGE },
     execute(orderItem, orderLine, args) {
     execute(orderItem, orderLine, args) {
         return -orderLine.unitPrice * (args.discount / 100);
         return -orderLine.unitPrice * (args.discount / 100);
     },
     },
@@ -35,7 +37,7 @@ export const buy1Get1Free = new PromotionItemAction({
 
 
 export const discountOnItemWithFacets = new PromotionItemAction({
 export const discountOnItemWithFacets = new PromotionItemAction({
     code: 'facet_based_discount',
     code: 'facet_based_discount',
-    args: { discount: 'percentage', facets: 'facetValueIds' },
+    args: { discount: ConfigArgType.PERCENTAGE, facets: ConfigArgType.FACET_VALUE_IDS },
     async execute(orderItem, orderLine, args, { hasFacetValues }) {
     async execute(orderItem, orderLine, args, { hasFacetValues }) {
         if (await hasFacetValues(orderLine, args.facets)) {
         if (await hasFacetValues(orderLine, args.facets)) {
             return -orderLine.unitPrice * (args.discount / 100);
             return -orderLine.unitPrice * (args.discount / 100);

+ 6 - 5
server/src/config/promotion/default-promotion-conditions.ts

@@ -1,3 +1,4 @@
+import { ConfigArgType } from '../../../../shared/generated-types';
 import { Order } from '../../entity/order/order.entity';
 import { Order } from '../../entity/order/order.entity';
 
 
 import { PromotionCondition } from './promotion-condition';
 import { PromotionCondition } from './promotion-condition';
@@ -6,8 +7,8 @@ export const minimumOrderAmount = new PromotionCondition({
     description: 'If order total is greater than { amount }',
     description: 'If order total is greater than { amount }',
     code: 'minimum_order_amount',
     code: 'minimum_order_amount',
     args: {
     args: {
-        amount: 'money',
-        taxInclusive: 'boolean',
+        amount: ConfigArgType.MONEY,
+        taxInclusive: ConfigArgType.BOOLEAN,
     },
     },
     check(order, args) {
     check(order, args) {
         if (args.taxInclusive) {
         if (args.taxInclusive) {
@@ -22,7 +23,7 @@ export const minimumOrderAmount = new PromotionCondition({
 export const dateRange = new PromotionCondition({
 export const dateRange = new PromotionCondition({
     code: 'date_range',
     code: 'date_range',
     description: 'If Order placed between { start } and { end }',
     description: 'If Order placed between { start } and { end }',
-    args: { start: 'datetime', end: 'datetime' },
+    args: { start: ConfigArgType.DATETIME, end: ConfigArgType.DATETIME },
     check(order: Order, args) {
     check(order: Order, args) {
         const now = new Date();
         const now = new Date();
         return args.start < now && now < args.end;
         return args.start < now && now < args.end;
@@ -32,7 +33,7 @@ export const dateRange = new PromotionCondition({
 export const atLeastNOfProduct = new PromotionCondition({
 export const atLeastNOfProduct = new PromotionCondition({
     code: 'at_least_n_of_product',
     code: 'at_least_n_of_product',
     description: 'Buy at least { minimum } of any product',
     description: 'Buy at least { minimum } of any product',
-    args: { minimum: 'int' },
+    args: { minimum: ConfigArgType.INT },
     check(order: Order, args) {
     check(order: Order, args) {
         return order.lines.reduce((result, item) => {
         return order.lines.reduce((result, item) => {
             return result || item.quantity >= args.minimum;
             return result || item.quantity >= args.minimum;
@@ -43,7 +44,7 @@ export const atLeastNOfProduct = new PromotionCondition({
 export const atLeastNWithFacets = new PromotionCondition({
 export const atLeastNWithFacets = new PromotionCondition({
     code: 'at_least_n_with_facets',
     code: 'at_least_n_with_facets',
     description: 'Buy at least { minimum } products with the given facets',
     description: 'Buy at least { minimum } products with the given facets',
-    args: { minimum: 'int', facets: 'facetValueIds' },
+    args: { minimum: ConfigArgType.INT, facets: ConfigArgType.FACET_VALUE_IDS },
     async check(order: Order, args, { hasFacetValues }) {
     async check(order: Order, args, { hasFacetValues }) {
         let matches = 0;
         let matches = 0;
         for (const line of order.lines) {
         for (const line of order.lines) {

+ 6 - 2
server/src/config/promotion/promotion-action.ts

@@ -1,4 +1,4 @@
-import { ConfigArg } from '../../../../shared/generated-types';
+import { ConfigArg, ConfigArgType } from '../../../../shared/generated-types';
 import {
 import {
     argsArrayToHash,
     argsArrayToHash,
     ConfigArgs,
     ConfigArgs,
@@ -11,7 +11,11 @@ import { Order } from '../../entity/order/order.entity';
 
 
 import { PromotionUtils } from './promotion-condition';
 import { PromotionUtils } from './promotion-condition';
 
 
-export type PromotionActionArgType = 'percentage' | 'money' | 'int' | 'facetValueIds';
+export type PromotionActionArgType =
+    | ConfigArgType.PERCENTAGE
+    | ConfigArgType.MONEY
+    | ConfigArgType.INT
+    | ConfigArgType.FACET_VALUE_IDS;
 export type PromotionActionArgs = ConfigArgs<PromotionActionArgType>;
 export type PromotionActionArgs = ConfigArgs<PromotionActionArgType>;
 
 
 export type ExecutePromotionItemActionFn<T extends PromotionActionArgs> = (
 export type ExecutePromotionItemActionFn<T extends PromotionActionArgs> = (

+ 8 - 2
server/src/config/promotion/promotion-condition.ts

@@ -1,4 +1,4 @@
-import { ConfigArg } from '../../../../shared/generated-types';
+import { ConfigArg, ConfigArgType } from '../../../../shared/generated-types';
 
 
 import { ID } from '../../../../shared/shared-types';
 import { ID } from '../../../../shared/shared-types';
 import {
 import {
@@ -10,7 +10,13 @@ import {
 import { OrderLine } from '../../entity';
 import { OrderLine } from '../../entity';
 import { Order } from '../../entity/order/order.entity';
 import { Order } from '../../entity/order/order.entity';
 
 
-export type PromotionConditionArgType = 'int' | 'money' | 'string' | 'datetime' | 'boolean' | 'facetValueIds';
+export type PromotionConditionArgType =
+    | ConfigArgType.INT
+    | ConfigArgType.MONEY
+    | ConfigArgType.STRING
+    | ConfigArgType.DATETIME
+    | ConfigArgType.BOOLEAN
+    | ConfigArgType.FACET_VALUE_IDS;
 export type PromotionConditionArgs = ConfigArgs<PromotionConditionArgType>;
 export type PromotionConditionArgs = ConfigArgs<PromotionConditionArgType>;
 
 
 /**
 /**

+ 3 - 1
server/src/config/shipping-method/default-shipping-calculator.ts

@@ -1,10 +1,12 @@
+import { ConfigArgType } from '../../../../shared/generated-types';
+
 import { ShippingCalculator } from './shipping-calculator';
 import { ShippingCalculator } from './shipping-calculator';
 
 
 export const defaultShippingCalculator = new ShippingCalculator({
 export const defaultShippingCalculator = new ShippingCalculator({
     code: 'default-shipping-calculator',
     code: 'default-shipping-calculator',
     description: 'Default Flat-Rate Shipping Calculator',
     description: 'Default Flat-Rate Shipping Calculator',
     args: {
     args: {
-        rate: 'money',
+        rate: ConfigArgType.MONEY,
     },
     },
     calculate: (order, args) => {
     calculate: (order, args) => {
         return args.rate;
         return args.rate;

+ 6 - 2
server/src/config/shipping-method/shipping-calculator.ts

@@ -1,10 +1,14 @@
-import { ConfigArg } from '../../../../shared/generated-types';
+import { ConfigArg, ConfigArgType } from '../../../../shared/generated-types';
 
 
 import { ConfigArgs, ConfigurableOperationDef } from '../../common/configurable-operation';
 import { ConfigArgs, ConfigurableOperationDef } from '../../common/configurable-operation';
 import { argsArrayToHash, ConfigArgValues } from '../../common/configurable-operation';
 import { argsArrayToHash, ConfigArgValues } from '../../common/configurable-operation';
 import { Order } from '../../entity/order/order.entity';
 import { Order } from '../../entity/order/order.entity';
 
 
-export type ShippingCalculatorArgType = 'int' | 'money' | 'string' | 'boolean';
+export type ShippingCalculatorArgType =
+    | ConfigArgType.INT
+    | ConfigArgType.MONEY
+    | ConfigArgType.STRING
+    | ConfigArgType.BOOLEAN;
 export type ShippingCalculatorArgs = ConfigArgs<ShippingCalculatorArgType>;
 export type ShippingCalculatorArgs = ConfigArgs<ShippingCalculatorArgType>;
 export type CalculateShippingFn<T extends ShippingCalculatorArgs> = (
 export type CalculateShippingFn<T extends ShippingCalculatorArgs> = (
     order: Order,
     order: Order,

+ 6 - 2
server/src/config/shipping-method/shipping-eligibility-checker.ts

@@ -1,10 +1,14 @@
-import { ConfigArg } from '../../../../shared/generated-types';
+import { ConfigArg, ConfigArgType } from '../../../../shared/generated-types';
 
 
 import { ConfigArgs, ConfigurableOperationDef } from '../../common/configurable-operation';
 import { ConfigArgs, ConfigurableOperationDef } from '../../common/configurable-operation';
 import { argsArrayToHash, ConfigArgValues } from '../../common/configurable-operation';
 import { argsArrayToHash, ConfigArgValues } from '../../common/configurable-operation';
 import { Order } from '../../entity/order/order.entity';
 import { Order } from '../../entity/order/order.entity';
 
 
-export type ShippingEligibilityCheckerArgType = 'int' | 'money' | 'string' | 'boolean';
+export type ShippingEligibilityCheckerArgType =
+    | ConfigArgType.INT
+    | ConfigArgType.MONEY
+    | ConfigArgType.STRING
+    | ConfigArgType.BOOLEAN;
 export type ShippingEligibilityCheckerArgs = ConfigArgs<ShippingEligibilityCheckerArgType>;
 export type ShippingEligibilityCheckerArgs = ConfigArgs<ShippingEligibilityCheckerArgType>;
 export type CheckShippingEligibilityCheckerFn<T extends ShippingEligibilityCheckerArgs> = (
 export type CheckShippingEligibilityCheckerFn<T extends ShippingEligibilityCheckerArgs> = (
     order: Order,
     order: Order,

+ 2 - 2
server/src/data-import/providers/populator/populator.ts

@@ -1,6 +1,6 @@
 import { Injectable } from '@nestjs/common';
 import { Injectable } from '@nestjs/common';
 
 
-import { LanguageCode } from '../../../../../shared/generated-types';
+import { ConfigArgType, LanguageCode } from '../../../../../shared/generated-types';
 import { normalizeString } from '../../../../../shared/normalize-string';
 import { normalizeString } from '../../../../../shared/normalize-string';
 import { RequestContext } from '../../../api/common/request-context';
 import { RequestContext } from '../../../api/common/request-context';
 import { defaultShippingCalculator, defaultShippingEligibilityChecker } from '../../../config';
 import { defaultShippingCalculator, defaultShippingEligibilityChecker } from '../../../config';
@@ -135,7 +135,7 @@ export class Populator {
                 },
                 },
                 calculator: {
                 calculator: {
                     code: defaultShippingCalculator.code,
                     code: defaultShippingCalculator.code,
-                    arguments: [{ name: 'rate', value: method.price.toString() }],
+                    arguments: [{ name: 'rate', value: method.price.toString(), type: ConfigArgType.MONEY }],
                 },
                 },
                 description: method.name,
                 description: method.name,
                 code: normalizeString(method.name, '-'),
                 code: normalizeString(method.name, '-'),

+ 10 - 9
server/src/service/helpers/order-calculator/order-calculator.spec.ts

@@ -1,8 +1,9 @@
 import { Test } from '@nestjs/testing';
 import { Test } from '@nestjs/testing';
 import { Connection } from 'typeorm';
 import { Connection } from 'typeorm';
 
 
+import { ConfigArgType } from '../../../../../shared/generated-types';
 import { Omit } from '../../../../../shared/omit';
 import { Omit } from '../../../../../shared/omit';
-import { PromotionAction, PromotionItemAction, PromotionOrderAction } from '../../../config';
+import { PromotionItemAction, PromotionOrderAction } from '../../../config';
 import { ConfigService } from '../../../config/config.service';
 import { ConfigService } from '../../../config/config.service';
 import { MockConfigService } from '../../../config/config.service.mock';
 import { MockConfigService } from '../../../config/config.service.mock';
 import { PromotionCondition } from '../../../config/promotion/promotion-condition';
 import { PromotionCondition } from '../../../config/promotion/promotion-condition';
@@ -135,7 +136,7 @@ describe('OrderCalculator', () => {
         });
         });
 
 
         const orderTotalCondition = new PromotionCondition({
         const orderTotalCondition = new PromotionCondition({
-            args: { minimum: 'money' },
+            args: { minimum: ConfigArgType.MONEY },
             code: 'order_total_condition',
             code: 'order_total_condition',
             description: '',
             description: '',
             check(order, args) {
             check(order, args) {
@@ -187,7 +188,7 @@ describe('OrderCalculator', () => {
                 conditions: [
                 conditions: [
                     {
                     {
                         code: orderTotalCondition.code,
                         code: orderTotalCondition.code,
-                        args: [{ name: 'minimum', type: 'money', value: '100' }],
+                        args: [{ name: 'minimum', type: ConfigArgType.MONEY, value: '100' }],
                     },
                     },
                 ],
                 ],
                 promotionConditions: [orderTotalCondition],
                 promotionConditions: [orderTotalCondition],
@@ -219,7 +220,7 @@ describe('OrderCalculator', () => {
 
 
         it('interaction between promotions', async () => {
         it('interaction between promotions', async () => {
             const orderQuantityCondition = new PromotionCondition({
             const orderQuantityCondition = new PromotionCondition({
-                args: { minimum: 'int' },
+                args: { minimum: ConfigArgType.INT },
                 code: 'order_quantity_condition',
                 code: 'order_quantity_condition',
                 description: 'Passes if any order line has at least the minimum quantity',
                 description: 'Passes if any order line has at least the minimum quantity',
                 check(_order, args) {
                 check(_order, args) {
@@ -234,7 +235,7 @@ describe('OrderCalculator', () => {
 
 
             const orderPercentageDiscount = new PromotionOrderAction({
             const orderPercentageDiscount = new PromotionOrderAction({
                 code: 'order_percentage_discount',
                 code: 'order_percentage_discount',
-                args: { discount: 'percentage' },
+                args: { discount: ConfigArgType.PERCENTAGE },
                 execute(_order, args) {
                 execute(_order, args) {
                     return -_order.subTotal * (args.discount / 100);
                     return -_order.subTotal * (args.discount / 100);
                 },
                 },
@@ -247,14 +248,14 @@ describe('OrderCalculator', () => {
                 conditions: [
                 conditions: [
                     {
                     {
                         code: orderQuantityCondition.code,
                         code: orderQuantityCondition.code,
-                        args: [{ name: 'minimum', type: 'int', value: '3' }],
+                        args: [{ name: 'minimum', type: ConfigArgType.INT, value: '3' }],
                     },
                     },
                 ],
                 ],
                 promotionConditions: [orderQuantityCondition],
                 promotionConditions: [orderQuantityCondition],
                 actions: [
                 actions: [
                     {
                     {
                         code: orderPercentageDiscount.code,
                         code: orderPercentageDiscount.code,
-                        args: [{ name: 'discount', type: 'percentage', value: '50' }],
+                        args: [{ name: 'discount', type: ConfigArgType.PERCENTAGE, value: '50' }],
                     },
                     },
                 ],
                 ],
                 promotionActions: [orderPercentageDiscount],
                 promotionActions: [orderPercentageDiscount],
@@ -266,14 +267,14 @@ describe('OrderCalculator', () => {
                 conditions: [
                 conditions: [
                     {
                     {
                         code: orderTotalCondition.code,
                         code: orderTotalCondition.code,
-                        args: [{ name: 'minimum', type: 'money', value: '100' }],
+                        args: [{ name: 'minimum', type: ConfigArgType.MONEY, value: '100' }],
                     },
                     },
                 ],
                 ],
                 promotionConditions: [orderTotalCondition],
                 promotionConditions: [orderTotalCondition],
                 actions: [
                 actions: [
                     {
                     {
                         code: orderPercentageDiscount.code,
                         code: orderPercentageDiscount.code,
-                        args: [{ name: 'discount', type: 'percentage', value: '10' }],
+                        args: [{ name: 'discount', type: ConfigArgType.PERCENTAGE, value: '10' }],
                     },
                     },
                 ],
                 ],
                 promotionActions: [orderPercentageDiscount],
                 promotionActions: [orderPercentageDiscount],

+ 4 - 4
server/src/service/services/payment-method.service.ts

@@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
 import { InjectConnection } from '@nestjs/typeorm';
 import { InjectConnection } from '@nestjs/typeorm';
 import { Connection } from 'typeorm';
 import { Connection } from 'typeorm';
 
 
-import { UpdatePaymentMethodInput } from '../../../../shared/generated-types';
+import { ConfigArgType, UpdatePaymentMethodInput } from '../../../../shared/generated-types';
 import { omit } from '../../../../shared/omit';
 import { omit } from '../../../../shared/omit';
 import { ID, PaginatedList } from '../../../../shared/shared-types';
 import { ID, PaginatedList } from '../../../../shared/shared-types';
 import { assertNever } from '../../../../shared/shared-utils';
 import { assertNever } from '../../../../shared/shared-utils';
@@ -120,11 +120,11 @@ export class PaymentMethodService {
 
 
     private getDefaultValue(type: PaymentMethodArgType): string {
     private getDefaultValue(type: PaymentMethodArgType): string {
         switch (type) {
         switch (type) {
-            case 'string':
+            case ConfigArgType.STRING:
                 return '';
                 return '';
-            case 'boolean':
+            case ConfigArgType.BOOLEAN:
                 return 'false';
                 return 'false';
-            case 'int':
+            case ConfigArgType.INT:
                 return '0';
                 return '0';
             default:
             default:
                 assertNever(type);
                 assertNever(type);

+ 15 - 3
shared/generated-shop-types.ts

@@ -1,5 +1,5 @@
 // tslint:disable
 // tslint:disable
-// Generated in 2019-03-05T20:52:07+01:00
+// Generated in 2019-03-06T10:36:47+01:00
 export type Maybe<T> = T | null;
 export type Maybe<T> = T | null;
 
 
 export interface OrderListOptions {
 export interface OrderListOptions {
@@ -349,7 +349,9 @@ export interface UpdateAddressInput {
 export interface ConfigArgInput {
 export interface ConfigArgInput {
     name: string;
     name: string;
 
 
-    value: string;
+    type: ConfigArgType;
+
+    value?: Maybe<string>;
 }
 }
 
 
 export interface ConfigurableOperationInput {
 export interface ConfigurableOperationInput {
@@ -725,6 +727,16 @@ export enum AdjustmentType {
     PROMOTION_REFUND = 'PROMOTION_REFUND',
     PROMOTION_REFUND = 'PROMOTION_REFUND',
     SHIPPING_REFUND = 'SHIPPING_REFUND',
     SHIPPING_REFUND = 'SHIPPING_REFUND',
 }
 }
+/** Certain entities allow arbitrary configuration arguments to be specified which can then be set in the admin-ui and used in the business logic of the app. These are the valid data types of such arguments. The data type influences: 1. How the argument form field is rendered in the admin-ui 2. The JavaScript type into which the value is coerced before being passed to the business logic. */
+export enum ConfigArgType {
+    PERCENTAGE = 'PERCENTAGE',
+    MONEY = 'MONEY',
+    INT = 'INT',
+    STRING = 'STRING',
+    DATETIME = 'DATETIME',
+    BOOLEAN = 'BOOLEAN',
+    FACET_VALUE_IDS = 'FACET_VALUE_IDS',
+}
 /** Permissions for administrators and customers */
 /** Permissions for administrators and customers */
 export enum Permission {
 export enum Permission {
     Authenticated = 'Authenticated',
     Authenticated = 'Authenticated',
@@ -1282,7 +1294,7 @@ export interface ConfigurableOperation {
 export interface ConfigArg {
 export interface ConfigArg {
     name: string;
     name: string;
 
 
-    type: string;
+    type: ConfigArgType;
 
 
     value?: Maybe<string>;
     value?: Maybe<string>;
 }
 }

+ 17 - 5
shared/generated-types.ts

@@ -1,5 +1,5 @@
 // tslint:disable
 // tslint:disable
-// Generated in 2019-03-05T20:52:08+01:00
+// Generated in 2019-03-06T10:36:48+01:00
 export type Maybe<T> = T | null;
 export type Maybe<T> = T | null;
 
 
 
 
@@ -730,7 +730,9 @@ export interface ConfigArgInput {
   
   
   name: string;
   name: string;
   
   
-  value: string;
+  type: ConfigArgType;
+  
+  value?: Maybe<string>;
 }
 }
 
 
 export interface CollectionTranslationInput {
 export interface CollectionTranslationInput {
@@ -1653,6 +1655,16 @@ export interface ProductOptionTranslationInput {
     VIDEO = "VIDEO",
     VIDEO = "VIDEO",
     BINARY = "BINARY",
     BINARY = "BINARY",
   }
   }
+/** Certain entities allow arbitrary configuration arguments to be specified which can then be set in the admin-ui and used in the business logic of the app. These are the valid data types of such arguments. The data type influences: 1. How the argument form field is rendered in the admin-ui 2. The JavaScript type into which the value is coerced before being passed to the business logic. */
+  export enum ConfigArgType {
+    PERCENTAGE = "PERCENTAGE",
+    MONEY = "MONEY",
+    INT = "INT",
+    STRING = "STRING",
+    DATETIME = "DATETIME",
+    BOOLEAN = "BOOLEAN",
+    FACET_VALUE_IDS = "FACET_VALUE_IDS",
+  }
 
 
   export enum AdjustmentType {
   export enum AdjustmentType {
     TAX = "TAX",
     TAX = "TAX",
@@ -4200,7 +4212,7 @@ export namespace ConfigurableOperation {
     
     
     name: string;
     name: string;
     
     
-    type: string;
+    type: ConfigArgType;
     
     
     value: Maybe<string>;
     value: Maybe<string>;
   }
   }
@@ -4380,7 +4392,7 @@ export namespace PaymentMethod {
     
     
     name: string;
     name: string;
     
     
-    type: string;
+    type: ConfigArgType;
     
     
     value: Maybe<string>;
     value: Maybe<string>;
   }
   }
@@ -4783,7 +4795,7 @@ export interface ConfigArg {
   
   
   name: string;
   name: string;
   
   
-  type: string;
+  type: ConfigArgType;
   
   
   value?: Maybe<string>;
   value?: Maybe<string>;
 }
 }

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff