@merchi/sdk 1.42.5 → 1.42.6
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.
package/dist/pricing/estimate.js
CHANGED
|
@@ -120,6 +120,36 @@ function areaCostFactor(field, sel, groupQuantities) {
|
|
|
120
120
|
});
|
|
121
121
|
return { setup: setup, unitList: unitList };
|
|
122
122
|
}
|
|
123
|
+
function colourExtractCostFactor(field, sel, groupQuantities) {
|
|
124
|
+
var _a, _b, _c, _d;
|
|
125
|
+
var n = groupQuantities.length;
|
|
126
|
+
var zeros = { setup: 0, unitList: new Array(n).fill(0) };
|
|
127
|
+
// Extracted colours are not in the static options list. Count them, then
|
|
128
|
+
// apply the field fee once and the per-colour fee once per colour.
|
|
129
|
+
var colourCount = (sel === null || sel === void 0 ? void 0 : sel.colourCount) != null
|
|
130
|
+
? sel.colourCount
|
|
131
|
+
: (_b = (_a = sel === null || sel === void 0 ? void 0 : sel.selectedOptionIds) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
|
|
132
|
+
var active = colourCount > 0 || Boolean(sel === null || sel === void 0 ? void 0 : sel.hasFiles);
|
|
133
|
+
if (!active)
|
|
134
|
+
return zeros;
|
|
135
|
+
var totalQty = groupQuantities.reduce(function (a, b) { return a + b; }, 0);
|
|
136
|
+
var setup = variationSetupCost(field, totalQty);
|
|
137
|
+
var unitList = variationUnitCosts(field, groupQuantities);
|
|
138
|
+
if (colourCount > 0) {
|
|
139
|
+
var colourSetup = variationSetupCost({
|
|
140
|
+
variationCost: field.colourVariationCost || 0,
|
|
141
|
+
variationCostDiscountGroup: (_c = field.colourVariationCostDiscountGroup) !== null && _c !== void 0 ? _c : null,
|
|
142
|
+
}, totalQty);
|
|
143
|
+
var colourUnits = variationUnitCosts({
|
|
144
|
+
variationUnitCost: field.colourVariationUnitCost || 0,
|
|
145
|
+
variationUnitCostDiscountGroup: (_d = field.colourVariationUnitCostDiscountGroup) !== null && _d !== void 0 ? _d : null,
|
|
146
|
+
}, groupQuantities);
|
|
147
|
+
setup += colourSetup * colourCount;
|
|
148
|
+
for (var i = 0; i < n; i++)
|
|
149
|
+
unitList[i] += colourUnits[i] * colourCount;
|
|
150
|
+
}
|
|
151
|
+
return { setup: setup, unitList: unitList };
|
|
152
|
+
}
|
|
123
153
|
function costFactor(field, sel, groupQuantities) {
|
|
124
154
|
var e_1, _a, e_2, _b;
|
|
125
155
|
var n = groupQuantities.length;
|
|
@@ -127,6 +157,9 @@ function costFactor(field, sel, groupQuantities) {
|
|
|
127
157
|
if (Number(field.fieldType) === FieldType.AREA) {
|
|
128
158
|
return areaCostFactor(field, sel, groupQuantities);
|
|
129
159
|
}
|
|
160
|
+
if (Number(field.fieldType) === FieldType.COLOUR_EXTRACT) {
|
|
161
|
+
return colourExtractCostFactor(field, sel, groupQuantities);
|
|
162
|
+
}
|
|
130
163
|
if (isEmpty(field, sel)) {
|
|
131
164
|
return { setup: 0, unitList: new Array(n).fill(0) };
|
|
132
165
|
}
|
|
@@ -72,6 +72,56 @@ test('hidden conditional field is not costed', function () {
|
|
|
72
72
|
var r = estimateQuote(rules, { quantity: 10, fieldValues: { 2: { selectedOptionIds: [201] } } });
|
|
73
73
|
expect(r.cost).toBe(100);
|
|
74
74
|
});
|
|
75
|
+
function colourExtractField() {
|
|
76
|
+
return {
|
|
77
|
+
id: 13, originalId: 13, position: 0, fieldType: 13, independent: true,
|
|
78
|
+
isSelectable: true, selectedBy: [],
|
|
79
|
+
variationCost: 180, variationUnitCost: 6.52,
|
|
80
|
+
variationCostDiscountGroup: null, variationUnitCostDiscountGroup: null,
|
|
81
|
+
colourVariationCost: 60, colourVariationUnitCost: 0.8,
|
|
82
|
+
colourVariationCostDiscountGroup: null,
|
|
83
|
+
colourVariationUnitCostDiscountGroup: null,
|
|
84
|
+
options: [],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
test('colour extract with no colours or file does not add a charge', function () {
|
|
88
|
+
var rules = __assign(__assign({}, base), { product: { unitPrice: 1, minimumPrice: null, discountGroup: null }, fields: [colourExtractField()] });
|
|
89
|
+
var r = estimateQuote(rules, {
|
|
90
|
+
quantity: 30,
|
|
91
|
+
fieldValues: { 13: { selectedOptionIds: [], colourCount: 0, hasFiles: false } },
|
|
92
|
+
});
|
|
93
|
+
expect(r.cost).toBe(30);
|
|
94
|
+
expect(r.totalCost).toBe(33);
|
|
95
|
+
});
|
|
96
|
+
test('colour extract adds the field fee and each selected colour', function () {
|
|
97
|
+
var rules = __assign(__assign({}, base), { product: { unitPrice: 1, minimumPrice: null, discountGroup: null }, fields: [colourExtractField()] });
|
|
98
|
+
var r = estimateQuote(rules, {
|
|
99
|
+
quantity: 30,
|
|
100
|
+
fieldValues: { 13: { selectedOptionIds: [1, 2, 3], colourCount: 3 } },
|
|
101
|
+
});
|
|
102
|
+
// 30*1 + 180 + 6.52*30 + 3*60 + 3*0.80*30 = 657.6
|
|
103
|
+
expect(r.cost).toBe(657.6);
|
|
104
|
+
expect(r.taxAmount).toBe(65.76);
|
|
105
|
+
expect(r.totalCost).toBe(723.36);
|
|
106
|
+
});
|
|
107
|
+
test('colour extract counts selected option ids when colourCount is omitted', function () {
|
|
108
|
+
var rules = __assign(__assign({}, base), { product: { unitPrice: 1, minimumPrice: null, discountGroup: null }, fields: [colourExtractField()] });
|
|
109
|
+
var r = estimateQuote(rules, {
|
|
110
|
+
quantity: 30,
|
|
111
|
+
fieldValues: { 13: { selectedOptionIds: [9, 8] } },
|
|
112
|
+
});
|
|
113
|
+
// 30 + 180 + 195.6 + 2*60 + 2*0.8*30 = 573.6
|
|
114
|
+
expect(r.cost).toBe(573.6);
|
|
115
|
+
});
|
|
116
|
+
test('colour extract file without colours still charges the field fee', function () {
|
|
117
|
+
var rules = __assign(__assign({}, base), { product: { unitPrice: 1, minimumPrice: null, discountGroup: null }, fields: [colourExtractField()] });
|
|
118
|
+
var r = estimateQuote(rules, {
|
|
119
|
+
quantity: 30,
|
|
120
|
+
fieldValues: { 13: { colourCount: 0, hasFiles: true } },
|
|
121
|
+
});
|
|
122
|
+
// 30 + 180 + 6.52*30 = 405.6
|
|
123
|
+
expect(r.cost).toBe(405.6);
|
|
124
|
+
});
|
|
75
125
|
test('area field multiplies height/width rate cards when dimensions set', function () {
|
|
76
126
|
var rules = __assign(__assign({}, base), { product: { unitPrice: 1, minimumPrice: null, discountGroup: null }, fields: [{
|
|
77
127
|
id: 14, originalId: 14, position: 0, fieldType: 14, independent: true,
|
package/package.json
CHANGED
|
@@ -79,6 +79,77 @@ test('hidden conditional field is not costed', () => {
|
|
|
79
79
|
expect(r.cost).toBe(100);
|
|
80
80
|
});
|
|
81
81
|
|
|
82
|
+
function colourExtractField(): PricingRules['fields'][number] {
|
|
83
|
+
return {
|
|
84
|
+
id: 13, originalId: 13, position: 0, fieldType: 13, independent: true,
|
|
85
|
+
isSelectable: true, selectedBy: [],
|
|
86
|
+
variationCost: 180, variationUnitCost: 6.52,
|
|
87
|
+
variationCostDiscountGroup: null, variationUnitCostDiscountGroup: null,
|
|
88
|
+
colourVariationCost: 60, colourVariationUnitCost: 0.8,
|
|
89
|
+
colourVariationCostDiscountGroup: null,
|
|
90
|
+
colourVariationUnitCostDiscountGroup: null,
|
|
91
|
+
options: [],
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
test('colour extract with no colours or file does not add a charge', () => {
|
|
96
|
+
const rules: PricingRules = {
|
|
97
|
+
...base,
|
|
98
|
+
product: { unitPrice: 1, minimumPrice: null, discountGroup: null },
|
|
99
|
+
fields: [colourExtractField()],
|
|
100
|
+
};
|
|
101
|
+
const r = estimateQuote(rules, {
|
|
102
|
+
quantity: 30,
|
|
103
|
+
fieldValues: { 13: { selectedOptionIds: [], colourCount: 0, hasFiles: false } },
|
|
104
|
+
}) as QuoteResult;
|
|
105
|
+
expect(r.cost).toBe(30);
|
|
106
|
+
expect(r.totalCost).toBe(33);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('colour extract adds the field fee and each selected colour', () => {
|
|
110
|
+
const rules: PricingRules = {
|
|
111
|
+
...base,
|
|
112
|
+
product: { unitPrice: 1, minimumPrice: null, discountGroup: null },
|
|
113
|
+
fields: [colourExtractField()],
|
|
114
|
+
};
|
|
115
|
+
const r = estimateQuote(rules, {
|
|
116
|
+
quantity: 30,
|
|
117
|
+
fieldValues: { 13: { selectedOptionIds: [1, 2, 3], colourCount: 3 } },
|
|
118
|
+
}) as QuoteResult;
|
|
119
|
+
// 30*1 + 180 + 6.52*30 + 3*60 + 3*0.80*30 = 657.6
|
|
120
|
+
expect(r.cost).toBe(657.6);
|
|
121
|
+
expect(r.taxAmount).toBe(65.76);
|
|
122
|
+
expect(r.totalCost).toBe(723.36);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('colour extract counts selected option ids when colourCount is omitted', () => {
|
|
126
|
+
const rules: PricingRules = {
|
|
127
|
+
...base,
|
|
128
|
+
product: { unitPrice: 1, minimumPrice: null, discountGroup: null },
|
|
129
|
+
fields: [colourExtractField()],
|
|
130
|
+
};
|
|
131
|
+
const r = estimateQuote(rules, {
|
|
132
|
+
quantity: 30,
|
|
133
|
+
fieldValues: { 13: { selectedOptionIds: [9, 8] } },
|
|
134
|
+
}) as QuoteResult;
|
|
135
|
+
// 30 + 180 + 195.6 + 2*60 + 2*0.8*30 = 573.6
|
|
136
|
+
expect(r.cost).toBe(573.6);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test('colour extract file without colours still charges the field fee', () => {
|
|
140
|
+
const rules: PricingRules = {
|
|
141
|
+
...base,
|
|
142
|
+
product: { unitPrice: 1, minimumPrice: null, discountGroup: null },
|
|
143
|
+
fields: [colourExtractField()],
|
|
144
|
+
};
|
|
145
|
+
const r = estimateQuote(rules, {
|
|
146
|
+
quantity: 30,
|
|
147
|
+
fieldValues: { 13: { colourCount: 0, hasFiles: true } },
|
|
148
|
+
}) as QuoteResult;
|
|
149
|
+
// 30 + 180 + 6.52*30 = 405.6
|
|
150
|
+
expect(r.cost).toBe(405.6);
|
|
151
|
+
});
|
|
152
|
+
|
|
82
153
|
test('area field multiplies height/width rate cards when dimensions set', () => {
|
|
83
154
|
const rules: PricingRules = {
|
|
84
155
|
...base,
|
package/src/pricing/estimate.ts
CHANGED
|
@@ -142,6 +142,47 @@ function areaCostFactor(
|
|
|
142
142
|
return { setup, unitList };
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
+
function colourExtractCostFactor(
|
|
146
|
+
field: PricingField,
|
|
147
|
+
sel: FieldSelection | undefined,
|
|
148
|
+
groupQuantities: number[]
|
|
149
|
+
): { setup: number; unitList: number[] } {
|
|
150
|
+
const n = groupQuantities.length;
|
|
151
|
+
const zeros = { setup: 0, unitList: new Array(n).fill(0) };
|
|
152
|
+
// Extracted colours are not in the static options list. Count them, then
|
|
153
|
+
// apply the field fee once and the per-colour fee once per colour.
|
|
154
|
+
const colourCount =
|
|
155
|
+
sel?.colourCount != null
|
|
156
|
+
? sel.colourCount
|
|
157
|
+
: sel?.selectedOptionIds?.length ?? 0;
|
|
158
|
+
const active = colourCount > 0 || Boolean(sel?.hasFiles);
|
|
159
|
+
if (!active) return zeros;
|
|
160
|
+
|
|
161
|
+
const totalQty = groupQuantities.reduce((a, b) => a + b, 0);
|
|
162
|
+
let setup = variationSetupCost(field, totalQty);
|
|
163
|
+
const unitList = variationUnitCosts(field, groupQuantities);
|
|
164
|
+
if (colourCount > 0) {
|
|
165
|
+
const colourSetup = variationSetupCost(
|
|
166
|
+
{
|
|
167
|
+
variationCost: field.colourVariationCost || 0,
|
|
168
|
+
variationCostDiscountGroup: field.colourVariationCostDiscountGroup ?? null,
|
|
169
|
+
},
|
|
170
|
+
totalQty
|
|
171
|
+
);
|
|
172
|
+
const colourUnits = variationUnitCosts(
|
|
173
|
+
{
|
|
174
|
+
variationUnitCost: field.colourVariationUnitCost || 0,
|
|
175
|
+
variationUnitCostDiscountGroup:
|
|
176
|
+
field.colourVariationUnitCostDiscountGroup ?? null,
|
|
177
|
+
},
|
|
178
|
+
groupQuantities
|
|
179
|
+
);
|
|
180
|
+
setup += colourSetup * colourCount;
|
|
181
|
+
for (let i = 0; i < n; i++) unitList[i] += colourUnits[i] * colourCount;
|
|
182
|
+
}
|
|
183
|
+
return { setup, unitList };
|
|
184
|
+
}
|
|
185
|
+
|
|
145
186
|
function costFactor(
|
|
146
187
|
field: PricingField,
|
|
147
188
|
sel: FieldSelection | undefined,
|
|
@@ -152,6 +193,9 @@ function costFactor(
|
|
|
152
193
|
if (Number(field.fieldType) === FieldType.AREA) {
|
|
153
194
|
return areaCostFactor(field, sel, groupQuantities);
|
|
154
195
|
}
|
|
196
|
+
if (Number(field.fieldType) === FieldType.COLOUR_EXTRACT) {
|
|
197
|
+
return colourExtractCostFactor(field, sel, groupQuantities);
|
|
198
|
+
}
|
|
155
199
|
if (isEmpty(field, sel)) {
|
|
156
200
|
return { setup: 0, unitList: new Array(n).fill(0) };
|
|
157
201
|
}
|
package/src/pricing/types.ts
CHANGED
|
@@ -45,6 +45,11 @@ export interface PricingField {
|
|
|
45
45
|
heightVariationUnitCostDiscountGroup?: DiscountGroup | null;
|
|
46
46
|
widthVariationCostDiscountGroup?: DiscountGroup | null;
|
|
47
47
|
widthVariationUnitCostDiscountGroup?: DiscountGroup | null;
|
|
48
|
+
/** Colour extract (fieldType 13): per selected colour, not a static option. */
|
|
49
|
+
colourVariationCost?: number;
|
|
50
|
+
colourVariationUnitCost?: number;
|
|
51
|
+
colourVariationCostDiscountGroup?: DiscountGroup | null;
|
|
52
|
+
colourVariationUnitCostDiscountGroup?: DiscountGroup | null;
|
|
48
53
|
options: PricingOption[];
|
|
49
54
|
}
|
|
50
55
|
|
|
@@ -82,6 +87,10 @@ export interface InventoryUnit {
|
|
|
82
87
|
export interface FieldSelection {
|
|
83
88
|
selectedOptionIds?: number[];
|
|
84
89
|
value?: string | number | null;
|
|
90
|
+
/** Colour extract: number of chosen colours when ids are not in the rules. */
|
|
91
|
+
colourCount?: number;
|
|
92
|
+
/** Colour extract: an artwork file is attached, even if no colour was kept. */
|
|
93
|
+
hasFiles?: boolean;
|
|
85
94
|
}
|
|
86
95
|
|
|
87
96
|
export interface GroupSelection {
|