@merchi/sdk 1.42.15 → 1.42.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (265) hide show
  1. package/dist/constants/auto_assign_production_on_actions.d.ts +6 -0
  2. package/dist/constants/call_to_actions.d.ts +14 -0
  3. package/dist/constants/call_to_actions.test.d.ts +1 -0
  4. package/dist/constants/discount_types.d.ts +5 -0
  5. package/dist/constants/discount_types.test.d.ts +1 -0
  6. package/dist/constants/domain_types.d.ts +12 -0
  7. package/dist/constants/domain_types.test.d.ts +1 -0
  8. package/dist/constants/errors.d.ts +26 -0
  9. package/dist/constants/event_types.d.ts +5 -0
  10. package/dist/constants/event_types.test.d.ts +1 -0
  11. package/dist/constants/field_types.d.ts +18 -0
  12. package/dist/constants/field_types.js +1 -0
  13. package/dist/constants/field_types.test.d.ts +1 -0
  14. package/dist/constants/index.d.ts +25 -0
  15. package/dist/constants/input_types.d.ts +13 -0
  16. package/dist/constants/input_types.test.d.ts +1 -0
  17. package/dist/constants/inventory_status.test.d.ts +1 -0
  18. package/dist/constants/inventory_statuses.d.ts +6 -0
  19. package/dist/constants/invoice_types.d.ts +5 -0
  20. package/dist/constants/invoice_types.test.d.ts +1 -0
  21. package/dist/constants/item_types.d.ts +5 -0
  22. package/dist/constants/item_types.test.d.ts +1 -0
  23. package/dist/constants/job/drafting_status.d.ts +7 -0
  24. package/dist/constants/job/drafting_status.test.d.ts +1 -0
  25. package/dist/constants/job/payment_status.d.ts +7 -0
  26. package/dist/constants/job/payment_status.test.d.ts +1 -0
  27. package/dist/constants/job/production_status.d.ts +12 -0
  28. package/dist/constants/job/production_status.test.d.ts +1 -0
  29. package/dist/constants/job/shipment_status.d.ts +11 -0
  30. package/dist/constants/job/shipment_status.test.d.ts +1 -0
  31. package/dist/constants/job/supply_chain_request_status.d.ts +6 -0
  32. package/dist/constants/job/supply_chain_request_status.test.d.ts +1 -0
  33. package/dist/constants/job_priorities.d.ts +6 -0
  34. package/dist/constants/job_priorities.test.d.ts +1 -0
  35. package/dist/constants/job_status.d.ts +45 -0
  36. package/dist/constants/job_status.test.d.ts +1 -0
  37. package/dist/constants/job_types.d.ts +16 -0
  38. package/dist/constants/job_types.test.d.ts +1 -0
  39. package/dist/constants/notification_sections.d.ts +13 -0
  40. package/dist/constants/notification_sections.test.d.ts +1 -0
  41. package/dist/constants/notification_types.d.ts +101 -0
  42. package/dist/constants/notification_types.test.d.ts +1 -0
  43. package/dist/constants/notification_urgencies.d.ts +6 -0
  44. package/dist/constants/notification_urgencies.test.d.ts +1 -0
  45. package/dist/constants/payment_types.d.ts +10 -0
  46. package/dist/constants/payment_types.test.d.ts +1 -0
  47. package/dist/constants/platform.d.ts +5 -0
  48. package/dist/constants/platform.test.d.ts +1 -0
  49. package/dist/constants/product_types.d.ts +26 -0
  50. package/dist/constants/product_types.test.d.ts +1 -0
  51. package/dist/constants/rights.d.ts +5 -0
  52. package/dist/constants/rights.test.d.ts +1 -0
  53. package/dist/constants/robots_meta_directives.d.ts +1 -0
  54. package/dist/constants/robots_meta_directives.test.d.ts +1 -0
  55. package/dist/constants/roles.d.ts +21 -0
  56. package/dist/constants/roles.js +3 -0
  57. package/dist/constants/roles.test.d.ts +1 -0
  58. package/dist/constants/shipment_companies.d.ts +19 -0
  59. package/dist/constants/shipment_companies.test.d.ts +1 -0
  60. package/dist/constants/shipment_services.d.ts +3 -0
  61. package/dist/constants/shipment_services.test.d.ts +1 -0
  62. package/dist/constants/system_roles.d.ts +3 -0
  63. package/dist/constants/system_roles.test.d.ts +1 -0
  64. package/dist/constants/theme_status.d.ts +5 -0
  65. package/dist/constants/theme_status.test.d.ts +1 -0
  66. package/dist/constants/user_types.d.ts +17 -0
  67. package/dist/constants/user_types.test.d.ts +1 -0
  68. package/dist/constants/white_label_accessibilities.d.ts +5 -0
  69. package/dist/constants/white_label_accessibilities.test.d.ts +1 -0
  70. package/dist/cookie.d.ts +1 -0
  71. package/dist/cookie.test.d.ts +1 -0
  72. package/dist/entities/address.d.ts +30 -0
  73. package/dist/entities/address.test.d.ts +1 -0
  74. package/dist/entities/agent_conversation.d.ts +18 -0
  75. package/dist/entities/agent_conversation.test.d.ts +1 -0
  76. package/dist/entities/agent_skill.d.ts +33 -0
  77. package/dist/entities/agent_skill.test.d.ts +1 -0
  78. package/dist/entities/agent_skill_approval.d.ts +13 -0
  79. package/dist/entities/agent_skill_version.d.ts +18 -0
  80. package/dist/entities/agent_token_analytics.d.ts +50 -0
  81. package/dist/entities/agent_token_usage.d.ts +31 -0
  82. package/dist/entities/agent_token_usage.test.d.ts +1 -0
  83. package/dist/entities/assignment.d.ts +40 -0
  84. package/dist/entities/assignment.test.d.ts +1 -0
  85. package/dist/entities/automatic_payment_relationship.d.ts +14 -0
  86. package/dist/entities/automatic_payment_relationship.test.d.ts +1 -0
  87. package/dist/entities/bank.d.ts +20 -0
  88. package/dist/entities/bank.test.d.ts +1 -0
  89. package/dist/entities/cart.d.ts +50 -0
  90. package/dist/entities/cart.test.d.ts +1 -0
  91. package/dist/entities/cart_item.d.ts +33 -0
  92. package/dist/entities/cart_item.test.d.ts +1 -0
  93. package/dist/entities/cart_shipment_group.d.ts +12 -0
  94. package/dist/entities/cart_shipment_quote.d.ts +16 -0
  95. package/dist/entities/category.d.ts +26 -0
  96. package/dist/entities/category.test.d.ts +1 -0
  97. package/dist/entities/company.d.ts +137 -0
  98. package/dist/entities/company.test.d.ts +1 -0
  99. package/dist/entities/company_invitation.d.ts +16 -0
  100. package/dist/entities/company_invitation.test.d.ts +1 -0
  101. package/dist/entities/country_tax.d.ts +20 -0
  102. package/dist/entities/country_tax.test.d.ts +1 -0
  103. package/dist/entities/discount.d.ts +19 -0
  104. package/dist/entities/discount.test.d.ts +1 -0
  105. package/dist/entities/discount_group.d.ts +20 -0
  106. package/dist/entities/discount_group.test.d.ts +1 -0
  107. package/dist/entities/domain.d.ts +629 -0
  108. package/dist/entities/domain.test.d.ts +1 -0
  109. package/dist/entities/domain_chat_settings.d.ts +33 -0
  110. package/dist/entities/domain_chat_settings.test.d.ts +1 -0
  111. package/dist/entities/domain_invitation.d.ts +17 -0
  112. package/dist/entities/domain_invitation.test.d.ts +1 -0
  113. package/dist/entities/domain_tag.d.ts +21 -0
  114. package/dist/entities/domain_tag.test.d.ts +1 -0
  115. package/dist/entities/draft.d.ts +31 -0
  116. package/dist/entities/draft.test.d.ts +1 -0
  117. package/dist/entities/draft_comment.d.ts +28 -0
  118. package/dist/entities/draft_comment.test.d.ts +1 -0
  119. package/dist/entities/draft_preview.d.ts +18 -0
  120. package/dist/entities/draft_preview.test.d.ts +1 -0
  121. package/dist/entities/draft_preview_layer.d.ts +12 -0
  122. package/dist/entities/draft_preview_layer.test.d.ts +1 -0
  123. package/dist/entities/draft_template.d.ts +31 -0
  124. package/dist/entities/draft_template.js +8 -0
  125. package/dist/entities/draft_template.test.d.ts +1 -0
  126. package/dist/entities/email_address.d.ts +13 -0
  127. package/dist/entities/email_address.test.d.ts +1 -0
  128. package/dist/entities/email_counter.d.ts +11 -0
  129. package/dist/entities/email_counter.test.d.ts +1 -0
  130. package/dist/entities/enrolled_domain.d.ts +16 -0
  131. package/dist/entities/enrolled_domain.test.d.ts +1 -0
  132. package/dist/entities/exchange_rate.d.ts +11 -0
  133. package/dist/entities/exchange_rate.test.d.ts +1 -0
  134. package/dist/entities/file.d.ts +65 -0
  135. package/dist/entities/file.test.d.ts +1 -0
  136. package/dist/entities/internal_tag.d.ts +26 -0
  137. package/dist/entities/internal_tag.test.d.ts +1 -0
  138. package/dist/entities/inventory.d.ts +27 -0
  139. package/dist/entities/inventory.test.d.ts +1 -0
  140. package/dist/entities/inventory_group.d.ts +19 -0
  141. package/dist/entities/inventory_group.test.d.ts +1 -0
  142. package/dist/entities/inventory_unit_variation.d.ts +13 -0
  143. package/dist/entities/inventory_unit_variation.test.d.ts +1 -0
  144. package/dist/entities/invoice.d.ts +80 -0
  145. package/dist/entities/invoice.test.d.ts +1 -0
  146. package/dist/entities/item.d.ts +24 -0
  147. package/dist/entities/item.test.d.ts +1 -0
  148. package/dist/entities/job.d.ts +156 -0
  149. package/dist/entities/job.test.d.ts +1 -0
  150. package/dist/entities/job_comment.d.ts +24 -0
  151. package/dist/entities/job_comment.test.d.ts +1 -0
  152. package/dist/entities/job_note.d.ts +19 -0
  153. package/dist/entities/job_operation_log.d.ts +18 -0
  154. package/dist/entities/job_operation_log.test.d.ts +1 -0
  155. package/dist/entities/matching_inventory.d.ts +16 -0
  156. package/dist/entities/notification.d.ts +47 -0
  157. package/dist/entities/notification.test.d.ts +1 -0
  158. package/dist/entities/payment.d.ts +28 -0
  159. package/dist/entities/payment.test.d.ts +1 -0
  160. package/dist/entities/payment_device.d.ts +14 -0
  161. package/dist/entities/payment_device.test.d.ts +1 -0
  162. package/dist/entities/phone_number.d.ts +17 -0
  163. package/dist/entities/phone_number.test.d.ts +1 -0
  164. package/dist/entities/product.d.ts +148 -0
  165. package/dist/entities/product.test.d.ts +1 -0
  166. package/dist/entities/product_form.d.ts +22 -0
  167. package/dist/entities/product_form_version.d.ts +20 -0
  168. package/dist/entities/product_review.d.ts +74 -0
  169. package/dist/entities/production_comment.d.ts +24 -0
  170. package/dist/entities/production_comment.test.d.ts +1 -0
  171. package/dist/entities/quote.d.ts +29 -0
  172. package/dist/entities/quote.test.d.ts +1 -0
  173. package/dist/entities/quote_item.d.ts +24 -0
  174. package/dist/entities/quote_item.test.d.ts +1 -0
  175. package/dist/entities/reminder.d.ts +35 -0
  176. package/dist/entities/reminder.test.d.ts +1 -0
  177. package/dist/entities/session.d.ts +15 -0
  178. package/dist/entities/session.test.d.ts +1 -0
  179. package/dist/entities/shipment.d.ts +76 -0
  180. package/dist/entities/shipment.test.d.ts +1 -0
  181. package/dist/entities/shipment_item.d.ts +10 -0
  182. package/dist/entities/shipment_item.test.d.ts +1 -0
  183. package/dist/entities/shipment_item_fulfillment.d.ts +10 -0
  184. package/dist/entities/shipment_item_fulfillment.test.d.ts +1 -0
  185. package/dist/entities/shipment_log.d.ts +15 -0
  186. package/dist/entities/shipment_method.d.ts +28 -0
  187. package/dist/entities/shipment_method.test.d.ts +1 -0
  188. package/dist/entities/shipment_method_variation.d.ts +18 -0
  189. package/dist/entities/shipment_method_variation.test.d.ts +1 -0
  190. package/dist/entities/short_url.d.ts +17 -0
  191. package/dist/entities/short_url.test.d.ts +1 -0
  192. package/dist/entities/subscription_plan.d.ts +30 -0
  193. package/dist/entities/subscription_plan.test.d.ts +1 -0
  194. package/dist/entities/supply_domain.d.ts +14 -0
  195. package/dist/entities/supply_domain.test.d.ts +1 -0
  196. package/dist/entities/support_conversation.d.ts +30 -0
  197. package/dist/entities/support_conversation.test.d.ts +1 -0
  198. package/dist/entities/support_message.d.ts +15 -0
  199. package/dist/entities/support_message.test.d.ts +1 -0
  200. package/dist/entities/system_role.d.ts +10 -0
  201. package/dist/entities/system_role.test.d.ts +1 -0
  202. package/dist/entities/theme.d.ts +26 -0
  203. package/dist/entities/theme.test.d.ts +1 -0
  204. package/dist/entities/theme_css_setting.d.ts +12 -0
  205. package/dist/entities/theme_css_setting.test.d.ts +1 -0
  206. package/dist/entities/user.d.ts +142 -0
  207. package/dist/entities/user.test.d.ts +1 -0
  208. package/dist/entities/user_company.d.ts +14 -0
  209. package/dist/entities/user_company.test.d.ts +1 -0
  210. package/dist/entities/variation.d.ts +29 -0
  211. package/dist/entities/variation.test.d.ts +1 -0
  212. package/dist/entities/variation_field.d.ts +87 -0
  213. package/dist/entities/variation_field.js +33 -0
  214. package/dist/entities/variation_field.test.d.ts +1 -0
  215. package/dist/entities/variation_fields_option.d.ts +36 -0
  216. package/dist/entities/variation_fields_option.test.d.ts +1 -0
  217. package/dist/entities/variation_option.d.ts +23 -0
  218. package/dist/entities/variation_option.test.d.ts +1 -0
  219. package/dist/entities/variations_group.d.ts +20 -0
  220. package/dist/entities/variations_group.test.d.ts +1 -0
  221. package/dist/entity.d.ts +208 -0
  222. package/dist/index.d.ts +88 -0
  223. package/dist/merchi.d.ts +179 -0
  224. package/dist/merchi.test.d.ts +1 -0
  225. package/dist/pricing/discount.d.ts +2 -0
  226. package/dist/pricing/discount.test.d.ts +1 -0
  227. package/dist/pricing/estimate.d.ts +2 -0
  228. package/dist/pricing/estimate.js +56 -0
  229. package/dist/pricing/estimate.test.d.ts +1 -0
  230. package/dist/pricing/estimate.test.js +81 -0
  231. package/dist/pricing/golden.test.d.ts +1 -0
  232. package/dist/pricing/index.d.ts +7 -0
  233. package/dist/pricing/index.test.d.ts +1 -0
  234. package/dist/pricing/inventory.d.ts +2 -0
  235. package/dist/pricing/inventory.test.d.ts +1 -0
  236. package/dist/pricing/matrix.d.ts +10 -0
  237. package/dist/pricing/matrix.test.d.ts +1 -0
  238. package/dist/pricing/round.d.ts +13 -0
  239. package/dist/pricing/round.test.d.ts +1 -0
  240. package/dist/pricing/types.d.ts +137 -0
  241. package/dist/pricing/visibility.d.ts +3 -0
  242. package/dist/pricing/visibility.test.d.ts +1 -0
  243. package/dist/request.d.ts +56 -0
  244. package/dist/request.test.d.ts +1 -0
  245. package/dist/test_util.d.ts +3 -0
  246. package/dist/toasts.d.ts +14 -0
  247. package/dist/toasts.test.d.ts +1 -0
  248. package/dist/util/float.d.ts +1 -0
  249. package/dist/util/index.d.ts +3 -0
  250. package/dist/util/query_string.d.ts +1 -0
  251. package/dist/util/query_string.test.d.ts +1 -0
  252. package/dist/util/validation.d.ts +1 -0
  253. package/dist/util/validation.test.d.ts +1 -0
  254. package/dist/uuid.d.ts +1 -0
  255. package/dist/uuid.test.d.ts +1 -0
  256. package/package.json +2 -1
  257. package/src/constants/field_types.ts +1 -0
  258. package/src/constants/roles.ts +3 -0
  259. package/src/entities/draft_template.ts +6 -0
  260. package/src/entities/variation_field.ts +25 -0
  261. package/src/entity.ts +1 -1
  262. package/src/pricing/estimate.test.ts +95 -0
  263. package/src/pricing/estimate.ts +73 -0
  264. package/src/pricing/types.ts +10 -0
  265. package/tsconfig.json +1 -0
package/dist/uuid.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function generateUUID(): string;
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@merchi/sdk",
3
- "version": "1.42.15",
3
+ "version": "1.42.17",
4
4
  "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
5
6
  "type": "module",
6
7
  "repository": {
7
8
  "type": "git",
@@ -14,4 +14,5 @@ export enum FieldType {
14
14
  COLOUR_EXTRACT = 13,
15
15
  AREA = 14,
16
16
  PANTONE_COLOUR_SELECT = 15,
17
+ EMBROIDERY = 16,
17
18
  }
@@ -10,6 +10,7 @@ export enum Role {
10
10
  THEME_EDITOR = 8,
11
11
  REFERRER = 9,
12
12
  FULFILLMENT = 10,
13
+ ANALYTICS = 11,
13
14
  }
14
15
 
15
16
  export const DOMAIN_MANAGERS = [Role.ADMIN, Role.MANAGER];
@@ -27,6 +28,7 @@ export const BUSINESS_ACCOUNTS = [
27
28
  Role.FULFILLMENT,
28
29
  Role.THEME_EDITOR,
29
30
  Role.REFERRER,
31
+ Role.ANALYTICS,
30
32
  ];
31
33
 
32
34
  export const MANAGEMENT_ROLES = [Role.ADMIN, Role.MANAGER];
@@ -35,6 +37,7 @@ export const THEME_ROLES = [...MANAGEMENT_ROLES, Role.THEME_EDITOR];
35
37
  export const ROLES_RANK = [
36
38
  Role.PUBLIC,
37
39
  Role.CLIENT,
40
+ Role.ANALYTICS,
38
41
  Role.REFERRER,
39
42
  Role.THEME_EDITOR,
40
43
  Role.ACCOUNTANT,
@@ -41,6 +41,12 @@ export class DraftTemplate extends Entity {
41
41
  @DraftTemplate.property()
42
42
  public width?: number;
43
43
 
44
+ @DraftTemplate.property({type: Number})
45
+ public widthMm?: number | null;
46
+
47
+ @DraftTemplate.property({type: Number})
48
+ public heightMm?: number | null;
49
+
44
50
  @DraftTemplate.property({type: MerchiFile})
45
51
  public file?: MerchiFile;
46
52
 
@@ -192,6 +192,27 @@ export class VariationField extends Entity {
192
192
  @VariationField.property({type: Number})
193
193
  public aspectRatio?: number | null;
194
194
 
195
+ @VariationField.property()
196
+ public embroideryInputMode?: string;
197
+
198
+ @VariationField.property({type: Number})
199
+ public stitchDensity?: number;
200
+
201
+ @VariationField.property({type: Number})
202
+ public averageStitchLengthMm?: number;
203
+
204
+ @VariationField.property()
205
+ public stitchVariationCost?: number;
206
+
207
+ @VariationField.property({type: 'DiscountGroup'})
208
+ public stitchVariationCostDiscountGroup?: DiscountGroup | null;
209
+
210
+ @VariationField.property()
211
+ public stitchVariationUnitCost?: number;
212
+
213
+ @VariationField.property({type: 'DiscountGroup'})
214
+ public stitchVariationUnitCostDiscountGroup?: DiscountGroup | null;
215
+
195
216
  @VariationField.property()
196
217
  public product?: Product;
197
218
 
@@ -252,6 +273,10 @@ export class VariationField extends Entity {
252
273
  } else if (this.fieldType === FieldType.AREA) {
253
274
  result.value = this.defaultValue;
254
275
  result.onceOffCost = 0;
276
+ } else if (this.fieldType === FieldType.EMBROIDERY) {
277
+ result.value = '';
278
+ result.onceOffCost = 0;
279
+ result.variationFiles = [];
255
280
  } else if (this.isSelectable()) {
256
281
  let onceOffCost = 0;
257
282
  const value = [];
package/src/entity.ts CHANGED
@@ -45,7 +45,7 @@ interface FromJsonOptions {
45
45
  makeDirty?: boolean;
46
46
  }
47
47
 
48
- interface CreateOptions {
48
+ export interface CreateOptions {
49
49
  withRights?: boolean;
50
50
  embed?: EmbedDescriptor;
51
51
  }
@@ -555,3 +555,98 @@ test('group field visibility is scoped per group (no cross-group leak)', () => {
555
555
  expect(r.groupCosts).toEqual([0, 5]);
556
556
  expect(r.cost).toBe(5);
557
557
  });
558
+
559
+ test('embroidery prices stitches and colours from the saved size', () => {
560
+ const rules: PricingRules = {
561
+ ...base,
562
+ fields: [{
563
+ id: 16, originalId: 16, position: 0, fieldType: 16, independent: true,
564
+ isSelectable: false, selectedBy: [],
565
+ variationCost: 15, variationUnitCost: 0,
566
+ variationCostDiscountGroup: null, variationUnitCostDiscountGroup: null,
567
+ stitchDensity: 2.5,
568
+ stitchVariationCost: 12, stitchVariationUnitCost: 0.8,
569
+ stitchVariationCostDiscountGroup: null, stitchVariationUnitCostDiscountGroup: null,
570
+ colourVariationCost: 5, colourVariationUnitCost: 0.4,
571
+ colourVariationCostDiscountGroup: null, colourVariationUnitCostDiscountGroup: null,
572
+ options: [],
573
+ }],
574
+ };
575
+ const value = JSON.stringify({
576
+ text: 'ACME', widthMm: 80, heightMm: 40, colours: ['#111111', '#CC0000'], coverage: 0.5,
577
+ });
578
+ const r = estimateQuote(rules, {
579
+ quantity: 1,
580
+ fieldValues: { 16: { value, colourCount: 2, coverage: 0.5 } },
581
+ }) as QuoteResult;
582
+ expect(r.cost).toBe(87);
583
+ });
584
+
585
+ test('embroidery counts colours on the saved value when colourCount is omitted', () => {
586
+ const rules: PricingRules = {
587
+ ...base,
588
+ fields: [{
589
+ id: 16, originalId: 16, position: 0, fieldType: 16, independent: true,
590
+ isSelectable: false, selectedBy: [],
591
+ variationCost: 15, variationUnitCost: 0,
592
+ variationCostDiscountGroup: null, variationUnitCostDiscountGroup: null,
593
+ stitchDensity: 2.5,
594
+ stitchVariationCost: 12, stitchVariationUnitCost: 0.8,
595
+ stitchVariationCostDiscountGroup: null, stitchVariationUnitCostDiscountGroup: null,
596
+ colourVariationCost: 5, colourVariationUnitCost: 0.4,
597
+ colourVariationCostDiscountGroup: null, colourVariationUnitCostDiscountGroup: null,
598
+ options: [],
599
+ }],
600
+ };
601
+ const value = JSON.stringify({
602
+ text: 'ACME', widthMm: 80, heightMm: 40, colours: ['#111111', '#CC0000'], coverage: 0.5,
603
+ });
604
+ const r = estimateQuote(rules, {
605
+ quantity: 1,
606
+ fieldValues: { 16: { value, coverage: 0.5 } },
607
+ }) as QuoteResult;
608
+ expect(r.cost).toBe(87);
609
+ });
610
+
611
+ test('embroidery ignores a null or non-array colour list', () => {
612
+ const rules: PricingRules = {
613
+ ...base,
614
+ fields: [{
615
+ id: 16, originalId: 16, position: 0, fieldType: 16, independent: true,
616
+ isSelectable: false, selectedBy: [],
617
+ variationCost: 15, variationUnitCost: 0,
618
+ variationCostDiscountGroup: null, variationUnitCostDiscountGroup: null,
619
+ stitchDensity: 2.5,
620
+ stitchVariationCost: 12, stitchVariationUnitCost: 0.8,
621
+ stitchVariationCostDiscountGroup: null, stitchVariationUnitCostDiscountGroup: null,
622
+ colourVariationCost: 5, colourVariationUnitCost: 0.4,
623
+ colourVariationCostDiscountGroup: null, colourVariationUnitCostDiscountGroup: null,
624
+ options: [],
625
+ }],
626
+ };
627
+ const missing = estimateQuote(rules, {
628
+ quantity: 1,
629
+ fieldValues: { 16: { value: null, colourCount: 2, coverage: 0.5 } },
630
+ }) as QuoteResult;
631
+ // No saved size, so the stitch price cannot be calculated.
632
+ expect(missing.cost).toBe(10);
633
+
634
+ const notColours = JSON.stringify({
635
+ text: 'ACME', widthMm: 80, heightMm: 40, colours: 'red', coverage: 0.5,
636
+ });
637
+ const uncounted = estimateQuote(rules, {
638
+ quantity: 1,
639
+ fieldValues: { 16: { value: notColours, coverage: 0.5 } },
640
+ }) as QuoteResult;
641
+ // 10 + 15 + 12*4 + 0.8*4 = 76.2; a non-array colour list adds no colour fee.
642
+ expect(uncounted.cost).toBe(76.2);
643
+
644
+ const explicitZero = JSON.stringify({
645
+ text: 'ACME', widthMm: 80, heightMm: 40, colours: ['#111111', '#CC0000'], coverage: 0.5,
646
+ });
647
+ const zero = estimateQuote(rules, {
648
+ quantity: 1,
649
+ fieldValues: { 16: { value: explicitZero, colourCount: 0, coverage: 0.5 } },
650
+ }) as QuoteResult;
651
+ expect(zero.cost).toBe(76.2);
652
+ });
@@ -183,6 +183,76 @@ function colourExtractCostFactor(
183
183
  return { setup, unitList };
184
184
  }
185
185
 
186
+ function parseEmbroidery(value: string | number | null | undefined): Record<string, any> | null {
187
+ if (value === undefined || value === null || value === '') return null;
188
+ try {
189
+ const parsed = JSON.parse(String(value));
190
+ return parsed && typeof parsed === 'object' ? parsed : null;
191
+ } catch {
192
+ return null;
193
+ }
194
+ }
195
+
196
+ function embroideryCostFactor(
197
+ field: PricingField,
198
+ sel: FieldSelection | undefined,
199
+ groupQuantities: number[]
200
+ ): { setup: number; unitList: number[] } {
201
+ const n = groupQuantities.length;
202
+ const zeros = { setup: 0, unitList: new Array(n).fill(0) };
203
+ const parsed = parseEmbroidery(sel?.value ?? null);
204
+ const width = Number(parsed?.widthMm);
205
+ const height = Number(parsed?.heightMm);
206
+ const coverage = Number(sel?.coverage ?? parsed?.coverage);
207
+ // An explicit colourCount, including 0, wins. Otherwise count the saved
208
+ // colour list. A null value or a non-array list contributes no colours.
209
+ const savedColours = parsed?.colours;
210
+ const colourCount = Number(
211
+ sel?.colourCount ?? (Array.isArray(savedColours) ? savedColours.length : 0)
212
+ );
213
+ const hasDesign = Boolean(String(parsed?.text || '').trim()) || Boolean(sel?.hasFiles) || colourCount > 0;
214
+ if (!(width > 0) || !(height > 0) || !(coverage > 0) || !hasDesign) return zeros;
215
+
216
+ const density = Number(field.stitchDensity) > 0 ? Number(field.stitchDensity) : 2.5;
217
+ const thousands = Math.round(width * height * coverage * density) / 1000;
218
+ const totalQty = groupQuantities.reduce((a, b) => a + b, 0);
219
+ let setup = variationSetupCost(field, totalQty);
220
+ const unitList = variationUnitCosts(field, groupQuantities);
221
+ const stitchSetup = variationSetupCost(
222
+ {
223
+ variationCost: field.stitchVariationCost || 0,
224
+ variationCostDiscountGroup: field.stitchVariationCostDiscountGroup ?? null,
225
+ },
226
+ totalQty
227
+ );
228
+ const stitchUnits = variationUnitCosts(
229
+ {
230
+ variationUnitCost: field.stitchVariationUnitCost || 0,
231
+ variationUnitCostDiscountGroup: field.stitchVariationUnitCostDiscountGroup ?? null,
232
+ },
233
+ groupQuantities
234
+ );
235
+ const colourSetup = variationSetupCost(
236
+ {
237
+ variationCost: field.colourVariationCost || 0,
238
+ variationCostDiscountGroup: field.colourVariationCostDiscountGroup ?? null,
239
+ },
240
+ totalQty
241
+ );
242
+ const colourUnits = variationUnitCosts(
243
+ {
244
+ variationUnitCost: field.colourVariationUnitCost || 0,
245
+ variationUnitCostDiscountGroup: field.colourVariationUnitCostDiscountGroup ?? null,
246
+ },
247
+ groupQuantities
248
+ );
249
+ setup += stitchSetup * thousands + colourSetup * colourCount;
250
+ for (let i = 0; i < n; i++) {
251
+ unitList[i] += stitchUnits[i] * thousands + colourUnits[i] * colourCount;
252
+ }
253
+ return { setup, unitList };
254
+ }
255
+
186
256
  function costFactor(
187
257
  field: PricingField,
188
258
  sel: FieldSelection | undefined,
@@ -196,6 +266,9 @@ function costFactor(
196
266
  if (Number(field.fieldType) === FieldType.COLOUR_EXTRACT) {
197
267
  return colourExtractCostFactor(field, sel, groupQuantities);
198
268
  }
269
+ if (Number(field.fieldType) === FieldType.EMBROIDERY) {
270
+ return embroideryCostFactor(field, sel, groupQuantities);
271
+ }
199
272
  if (isEmpty(field, sel)) {
200
273
  return { setup: 0, unitList: new Array(n).fill(0) };
201
274
  }
@@ -50,6 +50,14 @@ export interface PricingField {
50
50
  colourVariationUnitCost?: number;
51
51
  colourVariationCostDiscountGroup?: DiscountGroup | null;
52
52
  colourVariationUnitCostDiscountGroup?: DiscountGroup | null;
53
+ /** Embroidery (fieldType 16): per 1,000 stitches, plus the per-colour rates. */
54
+ embroideryInputMode?: 'text' | 'file' | string;
55
+ stitchDensity?: number;
56
+ averageStitchLengthMm?: number;
57
+ stitchVariationCost?: number;
58
+ stitchVariationUnitCost?: number;
59
+ stitchVariationCostDiscountGroup?: DiscountGroup | null;
60
+ stitchVariationUnitCostDiscountGroup?: DiscountGroup | null;
53
61
  options: PricingOption[];
54
62
  }
55
63
 
@@ -91,6 +99,8 @@ export interface FieldSelection {
91
99
  colourCount?: number;
92
100
  /** Colour extract: an artwork file is attached, even if no colour was kept. */
93
101
  hasFiles?: boolean;
102
+ /** Embroidery: fraction of the size box that is ink. */
103
+ coverage?: number;
94
104
  }
95
105
 
96
106
  export interface GroupSelection {
package/tsconfig.json CHANGED
@@ -8,6 +8,7 @@
8
8
  "moduleResolution": "node",
9
9
  "rootDir": "./src",
10
10
  "outDir": "dist",
11
+ "declaration": true,
11
12
  "module": "ES6",
12
13
  "types": ["node", "jest"],
13
14
  "baseUrl": ".",