@the-apparel-lab/pricing-engine 1.0.0
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/config/pricing-config.json +23 -0
- package/dist/audit/actuals-comparison.d.ts +10 -0
- package/dist/audit/actuals-comparison.d.ts.map +1 -0
- package/dist/audit/actuals-comparison.js +96 -0
- package/dist/audit/actuals-comparison.js.map +1 -0
- package/dist/audit/margin.d.ts +20 -0
- package/dist/audit/margin.d.ts.map +1 -0
- package/dist/audit/margin.js +34 -0
- package/dist/audit/margin.js.map +1 -0
- package/dist/audit-runner.d.ts +11 -0
- package/dist/audit-runner.d.ts.map +1 -0
- package/dist/audit-runner.js +277 -0
- package/dist/audit-runner.js.map +1 -0
- package/dist/calculators/blanks.d.ts +18 -0
- package/dist/calculators/blanks.d.ts.map +1 -0
- package/dist/calculators/blanks.js +26 -0
- package/dist/calculators/blanks.js.map +1 -0
- package/dist/calculators/decoration.d.ts +32 -0
- package/dist/calculators/decoration.d.ts.map +1 -0
- package/dist/calculators/decoration.js +63 -0
- package/dist/calculators/decoration.js.map +1 -0
- package/dist/calculators/setup-fees.d.ts +27 -0
- package/dist/calculators/setup-fees.d.ts.map +1 -0
- package/dist/calculators/setup-fees.js +60 -0
- package/dist/calculators/setup-fees.js.map +1 -0
- package/dist/calculators/shipping.d.ts +14 -0
- package/dist/calculators/shipping.d.ts.map +1 -0
- package/dist/calculators/shipping.js +17 -0
- package/dist/calculators/shipping.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +192 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +224 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +368 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +295 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +230 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/blanks-lookup.d.ts +42 -0
- package/dist/utils/blanks-lookup.d.ts.map +1 -0
- package/dist/utils/blanks-lookup.js +99 -0
- package/dist/utils/blanks-lookup.js.map +1 -0
- package/dist/utils/money.d.ts +21 -0
- package/dist/utils/money.d.ts.map +1 -0
- package/dist/utils/money.js +38 -0
- package/dist/utils/money.js.map +1 -0
- package/dist/utils/vendor-lookup.d.ts +49 -0
- package/dist/utils/vendor-lookup.d.ts.map +1 -0
- package/dist/utils/vendor-lookup.js +308 -0
- package/dist/utils/vendor-lookup.js.map +1 -0
- package/package.json +28 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"multipliers": {
|
|
3
|
+
"blanks": 1.40,
|
|
4
|
+
"decoration": {
|
|
5
|
+
"screen_printing": 1.75,
|
|
6
|
+
"embroidery": 1.60,
|
|
7
|
+
"dtf": 1.40,
|
|
8
|
+
"dtg": 1.60,
|
|
9
|
+
"sublimation": 1.60,
|
|
10
|
+
"screen_print_transfers": 1.60
|
|
11
|
+
},
|
|
12
|
+
"setup_fees": {
|
|
13
|
+
"digitizing": 1.00,
|
|
14
|
+
"screen_setup": 1.20
|
|
15
|
+
},
|
|
16
|
+
"shipping": 1.00
|
|
17
|
+
},
|
|
18
|
+
"payment_processing_rate": {
|
|
19
|
+
"percentage": 0.029,
|
|
20
|
+
"flat_fee": 0.30,
|
|
21
|
+
"_note": "NOT added to customer price. Used only for internal margin calculations. Factor this cost into your multipliers when setting them."
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { PriceBreakdown, ActualCosts, EstimateVsActual } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Compare an estimate (PriceBreakdown) to populated actuals (ActualCosts).
|
|
4
|
+
* Returns per-component deltas, total cost variance, and margin comparison.
|
|
5
|
+
*
|
|
6
|
+
* All dollar amounts in the output are in dollars (not cents),
|
|
7
|
+
* matching the spec's comparison output format.
|
|
8
|
+
*/
|
|
9
|
+
export declare function compareEstimateToActuals(estimate: PriceBreakdown, actuals: ActualCosts): EstimateVsActual;
|
|
10
|
+
//# sourceMappingURL=actuals-comparison.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actuals-comparison.d.ts","sourceRoot":"","sources":["../../src/audit/actuals-comparison.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,gBAAgB,EAAqB,MAAM,UAAU,CAAC;AAGjG;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,WAAW,GACnB,gBAAgB,CA+FlB"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.compareEstimateToActuals = compareEstimateToActuals;
|
|
4
|
+
const money_1 = require("../utils/money");
|
|
5
|
+
/**
|
|
6
|
+
* Compare an estimate (PriceBreakdown) to populated actuals (ActualCosts).
|
|
7
|
+
* Returns per-component deltas, total cost variance, and margin comparison.
|
|
8
|
+
*
|
|
9
|
+
* All dollar amounts in the output are in dollars (not cents),
|
|
10
|
+
* matching the spec's comparison output format.
|
|
11
|
+
*/
|
|
12
|
+
function compareEstimateToActuals(estimate, actuals) {
|
|
13
|
+
// Guard: line item counts must match for a meaningful comparison
|
|
14
|
+
if (estimate.line_items.length !== actuals.actuals.line_items.length) {
|
|
15
|
+
const estSkus = estimate.line_items.map(li => `${li.brand_sku} (${li.quantity})`).join(', ');
|
|
16
|
+
const actSkus = actuals.actuals.line_items.map(li => `${li.brand_sku} (${li.quantity})`).join(', ');
|
|
17
|
+
throw new Error(`Line item count mismatch: estimate has ${estimate.line_items.length} line item(s) [${estSkus}] ` +
|
|
18
|
+
`but actuals has ${actuals.actuals.line_items.length} [${actSkus}]. ` +
|
|
19
|
+
`Each estimate line item must have a corresponding actual.`);
|
|
20
|
+
}
|
|
21
|
+
// Aggregate estimated costs per component from line items
|
|
22
|
+
let estBlanksCents = 0;
|
|
23
|
+
let estDecorationCents = 0;
|
|
24
|
+
let estSetupFeesCents = 0;
|
|
25
|
+
for (const item of estimate.line_items) {
|
|
26
|
+
estBlanksCents += item.cost_breakdown.blanks.estimated_cost;
|
|
27
|
+
estDecorationCents += item.cost_breakdown.decoration.estimated_cost;
|
|
28
|
+
if (item.cost_breakdown.screen_setup) {
|
|
29
|
+
estSetupFeesCents += item.cost_breakdown.screen_setup.estimated_cost;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// Add digitizing from separate charges (it's a setup fee)
|
|
33
|
+
if (estimate.separate_charges.digitizing) {
|
|
34
|
+
estSetupFeesCents += estimate.separate_charges.digitizing.estimated_cost;
|
|
35
|
+
}
|
|
36
|
+
const estShippingCents = estimate.separate_charges.shipping.estimated_cost;
|
|
37
|
+
// Aggregate actual costs per component from actuals line items
|
|
38
|
+
let actBlanksCents = 0;
|
|
39
|
+
let actDecorationCents = 0;
|
|
40
|
+
let actSetupFeesCents = 0;
|
|
41
|
+
let actShippingCents = 0;
|
|
42
|
+
for (const item of actuals.actuals.line_items) {
|
|
43
|
+
actBlanksCents += item.cost_breakdown.blanks.actual_cost;
|
|
44
|
+
actDecorationCents += item.cost_breakdown.decoration.actual_cost;
|
|
45
|
+
actSetupFeesCents += item.cost_breakdown.setup_fees.actual_cost;
|
|
46
|
+
actShippingCents += item.cost_breakdown.shipping.actual_cost;
|
|
47
|
+
}
|
|
48
|
+
const customerPaidCents = estimate.order_summary.total_customer_price;
|
|
49
|
+
// Use the pre-computed total from the estimate so this stays in sync with index.ts
|
|
50
|
+
const estimatedTotalCostCents = estimate.order_summary.total_estimated_cost;
|
|
51
|
+
const actualTotalCostCents = actuals.actuals.total_actual_cost;
|
|
52
|
+
const costVarianceCents = actualTotalCostCents - estimatedTotalCostCents;
|
|
53
|
+
const costVariancePercent = estimatedTotalCostCents !== 0
|
|
54
|
+
? roundToTwoDecimals((costVarianceCents / estimatedTotalCostCents) * 100)
|
|
55
|
+
: 0;
|
|
56
|
+
// Estimated net margin: uses the estimate's processing fee
|
|
57
|
+
const estProcessingFeeCents = estimate.order_summary.estimated_processing_fee;
|
|
58
|
+
const estimatedNetMarginPercent = customerPaidCents !== 0
|
|
59
|
+
? roundToOneDecimal(((customerPaidCents - estProcessingFeeCents - estimatedTotalCostCents) / customerPaidCents) * 100)
|
|
60
|
+
: 0;
|
|
61
|
+
// Actual net margin: uses the actual processing fee
|
|
62
|
+
const actProcessingFeeCents = actuals.actuals.actual_processing_fee;
|
|
63
|
+
const actualNetMarginPercent = customerPaidCents !== 0
|
|
64
|
+
? roundToOneDecimal(((customerPaidCents - actProcessingFeeCents - actualTotalCostCents) / customerPaidCents) * 100)
|
|
65
|
+
: 0;
|
|
66
|
+
function makeVariance(estimatedCents, actualCents) {
|
|
67
|
+
return {
|
|
68
|
+
estimated: (0, money_1.toDollars)(estimatedCents),
|
|
69
|
+
actual: (0, money_1.toDollars)(actualCents),
|
|
70
|
+
delta: (0, money_1.toDollars)(actualCents - estimatedCents),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
order_id: actuals.order_id,
|
|
75
|
+
customer_paid: (0, money_1.toDollars)(customerPaidCents),
|
|
76
|
+
estimated_total_cost: (0, money_1.toDollars)(estimatedTotalCostCents),
|
|
77
|
+
actual_total_cost: (0, money_1.toDollars)(actualTotalCostCents),
|
|
78
|
+
cost_variance: (0, money_1.toDollars)(costVarianceCents),
|
|
79
|
+
cost_variance_percent: costVariancePercent,
|
|
80
|
+
estimated_net_margin_percent: estimatedNetMarginPercent,
|
|
81
|
+
actual_net_margin_percent: actualNetMarginPercent,
|
|
82
|
+
component_variances: {
|
|
83
|
+
blanks: makeVariance(estBlanksCents, actBlanksCents),
|
|
84
|
+
decoration: makeVariance(estDecorationCents, actDecorationCents),
|
|
85
|
+
setup_fees: makeVariance(estSetupFeesCents, actSetupFeesCents),
|
|
86
|
+
shipping: makeVariance(estShippingCents, actShippingCents),
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function roundToOneDecimal(value) {
|
|
91
|
+
return Math.round(value * 10) / 10;
|
|
92
|
+
}
|
|
93
|
+
function roundToTwoDecimals(value) {
|
|
94
|
+
return Math.round(value * 100) / 100;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=actuals-comparison.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actuals-comparison.js","sourceRoot":"","sources":["../../src/audit/actuals-comparison.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { PaymentProcessingRate } from '../types';
|
|
2
|
+
export interface MarginInput {
|
|
3
|
+
/** Total customer-facing price in cents. */
|
|
4
|
+
totalCustomerPriceCents: number;
|
|
5
|
+
/** Total estimated cost (sum of all raw costs before markup) in cents. */
|
|
6
|
+
totalEstimatedCostCents: number;
|
|
7
|
+
paymentProcessingRate: PaymentProcessingRate;
|
|
8
|
+
}
|
|
9
|
+
export interface MarginResult {
|
|
10
|
+
/** Estimated Stripe fee in cents: (price × rate) + flat fee. */
|
|
11
|
+
estimatedProcessingFeeCents: number;
|
|
12
|
+
/** Customer price minus estimated processing fee, in cents. */
|
|
13
|
+
trueNetRevenueCents: number;
|
|
14
|
+
/** (customer_price − total_cost) / customer_price × 100 */
|
|
15
|
+
grossMarginPercent: number;
|
|
16
|
+
/** (true_net_revenue − total_cost) / customer_price × 100 */
|
|
17
|
+
netMarginPercent: number;
|
|
18
|
+
}
|
|
19
|
+
export declare function calculateMargin(input: MarginInput): MarginResult;
|
|
20
|
+
//# sourceMappingURL=margin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"margin.d.ts","sourceRoot":"","sources":["../../src/audit/margin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAGtD,MAAM,WAAW,WAAW;IAC1B,4CAA4C;IAC5C,uBAAuB,EAAE,MAAM,CAAC;IAChC,0EAA0E;IAC1E,uBAAuB,EAAE,MAAM,CAAC;IAChC,qBAAqB,EAAE,qBAAqB,CAAC;CAC9C;AAED,MAAM,WAAW,YAAY;IAC3B,gEAAgE;IAChE,2BAA2B,EAAE,MAAM,CAAC;IACpC,+DAA+D;IAC/D,mBAAmB,EAAE,MAAM,CAAC;IAC5B,2DAA2D;IAC3D,kBAAkB,EAAE,MAAM,CAAC;IAC3B,6DAA6D;IAC7D,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY,CAmChE"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calculateMargin = calculateMargin;
|
|
4
|
+
const money_1 = require("../utils/money");
|
|
5
|
+
function calculateMargin(input) {
|
|
6
|
+
const { totalCustomerPriceCents, totalEstimatedCostCents, paymentProcessingRate } = input;
|
|
7
|
+
if (totalCustomerPriceCents === 0) {
|
|
8
|
+
return {
|
|
9
|
+
estimatedProcessingFeeCents: 0,
|
|
10
|
+
trueNetRevenueCents: 0,
|
|
11
|
+
grossMarginPercent: 0,
|
|
12
|
+
netMarginPercent: 0,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
// Processing fee is calculated in dollars then converted back to cents,
|
|
16
|
+
// matching Stripe's actual billing: (price × 2.9%) + $0.30
|
|
17
|
+
const customerPriceDollars = (0, money_1.toDollars)(totalCustomerPriceCents);
|
|
18
|
+
const processingFeeDollars = customerPriceDollars * paymentProcessingRate.percentage + paymentProcessingRate.flat_fee;
|
|
19
|
+
const estimatedProcessingFeeCents = Math.round(processingFeeDollars * 100);
|
|
20
|
+
const trueNetRevenueCents = totalCustomerPriceCents - estimatedProcessingFeeCents;
|
|
21
|
+
// Margins as percentages, rounded to 1 decimal place
|
|
22
|
+
const grossMarginPercent = roundToOneDecimal(((totalCustomerPriceCents - totalEstimatedCostCents) / totalCustomerPriceCents) * 100);
|
|
23
|
+
const netMarginPercent = roundToOneDecimal(((trueNetRevenueCents - totalEstimatedCostCents) / totalCustomerPriceCents) * 100);
|
|
24
|
+
return {
|
|
25
|
+
estimatedProcessingFeeCents,
|
|
26
|
+
trueNetRevenueCents,
|
|
27
|
+
grossMarginPercent,
|
|
28
|
+
netMarginPercent,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function roundToOneDecimal(value) {
|
|
32
|
+
return Math.round(value * 10) / 10;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=margin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"margin.js","sourceRoot":"","sources":["../../src/audit/margin.ts"],"names":[],"mappings":";;AAsBA,0CAmCC;AAxDD,0CAAuD;AAqBvD,SAAgB,eAAe,CAAC,KAAkB;IAChD,MAAM,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,GAAG,KAAK,CAAC;IAE1F,IAAI,uBAAuB,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO;YACL,2BAA2B,EAAE,CAAC;YAC9B,mBAAmB,EAAE,CAAC;YACtB,kBAAkB,EAAE,CAAC;YACrB,gBAAgB,EAAE,CAAC;SACpB,CAAC;IACJ,CAAC;IAED,wEAAwE;IACxE,2DAA2D;IAC3D,MAAM,oBAAoB,GAAG,IAAA,iBAAS,EAAC,uBAAuB,CAAC,CAAC;IAChE,MAAM,oBAAoB,GAAG,oBAAoB,GAAG,qBAAqB,CAAC,UAAU,GAAG,qBAAqB,CAAC,QAAQ,CAAC;IACtH,MAAM,2BAA2B,GAAG,IAAI,CAAC,KAAK,CAAC,oBAAoB,GAAG,GAAG,CAAC,CAAC;IAE3E,MAAM,mBAAmB,GAAG,uBAAuB,GAAG,2BAA2B,CAAC;IAElF,qDAAqD;IACrD,MAAM,kBAAkB,GAAG,iBAAiB,CAC1C,CAAC,CAAC,uBAAuB,GAAG,uBAAuB,CAAC,GAAG,uBAAuB,CAAC,GAAG,GAAG,CACtF,CAAC;IAEF,MAAM,gBAAgB,GAAG,iBAAiB,CACxC,CAAC,CAAC,mBAAmB,GAAG,uBAAuB,CAAC,GAAG,uBAAuB,CAAC,GAAG,GAAG,CAClF,CAAC;IAEF,OAAO;QACL,2BAA2B;QAC3B,mBAAmB;QACnB,kBAAkB;QAClB,gBAAgB;KACjB,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAa;IACtC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
/**
|
|
3
|
+
* Scenario Audit Runner
|
|
4
|
+
*
|
|
5
|
+
* Batch-processes order scenarios through calculatePrice() using production config,
|
|
6
|
+
* outputs a terminal summary table and saves full results to a timestamped JSON file.
|
|
7
|
+
*
|
|
8
|
+
* Usage: npx ts-node src/audit-runner.ts
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=audit-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-runner.d.ts","sourceRoot":"","sources":["../src/audit-runner.ts"],"names":[],"mappings":";AAEA;;;;;;;GAOG"}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* Scenario Audit Runner
|
|
5
|
+
*
|
|
6
|
+
* Batch-processes order scenarios through calculatePrice() using production config,
|
|
7
|
+
* outputs a terminal summary table and saves full results to a timestamped JSON file.
|
|
8
|
+
*
|
|
9
|
+
* Usage: npx ts-node src/audit-runner.ts
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
46
|
+
const path = __importStar(require("path"));
|
|
47
|
+
const index_1 = require("./index");
|
|
48
|
+
const money_1 = require("./utils/money");
|
|
49
|
+
// ─── Helpers ───
|
|
50
|
+
const $ = (dollars) => `$${dollars.toFixed(2)}`;
|
|
51
|
+
function padRight(str, len) {
|
|
52
|
+
return str.length >= len ? str.slice(0, len) : str + ' '.repeat(len - str.length);
|
|
53
|
+
}
|
|
54
|
+
function padLeft(str, len) {
|
|
55
|
+
return str.length >= len ? str : ' '.repeat(len - str.length) + str;
|
|
56
|
+
}
|
|
57
|
+
// ─── Load Scenarios ───
|
|
58
|
+
const scenariosDir = path.resolve(__dirname, '..', 'scenarios');
|
|
59
|
+
const resultsDir = path.resolve(__dirname, '..', 'audit-results');
|
|
60
|
+
if (!fs.existsSync(scenariosDir)) {
|
|
61
|
+
console.error(`Scenarios directory not found: ${scenariosDir}`);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
const scenarioFiles = fs.readdirSync(scenariosDir)
|
|
65
|
+
.filter(f => f.endsWith('.json'))
|
|
66
|
+
.sort();
|
|
67
|
+
if (scenarioFiles.length === 0) {
|
|
68
|
+
console.error('No scenario files found in scenarios/');
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
// ─── Run All Scenarios ───
|
|
72
|
+
const results = [];
|
|
73
|
+
let configSnapshot = null;
|
|
74
|
+
for (const file of scenarioFiles) {
|
|
75
|
+
const filePath = path.join(scenariosDir, file);
|
|
76
|
+
const raw = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
77
|
+
// Extract scenario metadata
|
|
78
|
+
const meta = raw._scenario || {
|
|
79
|
+
name: file.replace('.json', ''),
|
|
80
|
+
description: '',
|
|
81
|
+
tags: [],
|
|
82
|
+
};
|
|
83
|
+
// Strip _scenario before passing to engine
|
|
84
|
+
const { _scenario, ...orderInput } = raw;
|
|
85
|
+
try {
|
|
86
|
+
const result = (0, index_1.calculatePrice)(orderInput);
|
|
87
|
+
// Capture config from first successful result
|
|
88
|
+
if (!configSnapshot) {
|
|
89
|
+
configSnapshot = result.multipliers_used;
|
|
90
|
+
}
|
|
91
|
+
// Build summary
|
|
92
|
+
const totalQty = result.line_items.reduce((sum, li) => sum + li.quantity + (li.oversized_quantity ?? 0), 0);
|
|
93
|
+
const methods = [...new Set(result.line_items.map(li => li.decoration_method))];
|
|
94
|
+
const primaryMethod = methods.length === 1 ? methods[0] : 'mixed';
|
|
95
|
+
// Standard unit price from first line item (null for multi-line)
|
|
96
|
+
const stdUnitPrice = result.line_items.length === 1
|
|
97
|
+
? result.line_items[0].customer_facing.standard_sizes.unit_price
|
|
98
|
+
: null;
|
|
99
|
+
const oversizedUnitPrice = result.line_items.length === 1 && result.line_items[0].customer_facing.oversized
|
|
100
|
+
? result.line_items[0].customer_facing.oversized.unit_price
|
|
101
|
+
: null;
|
|
102
|
+
results.push({
|
|
103
|
+
scenario_name: meta.name,
|
|
104
|
+
scenario_file: file,
|
|
105
|
+
tags: meta.tags,
|
|
106
|
+
description: meta.description,
|
|
107
|
+
input: orderInput,
|
|
108
|
+
result,
|
|
109
|
+
summary: {
|
|
110
|
+
total_quantity: totalQty,
|
|
111
|
+
line_count: result.line_items.length,
|
|
112
|
+
primary_method: primaryMethod,
|
|
113
|
+
standard_unit_price: stdUnitPrice,
|
|
114
|
+
oversized_unit_price: oversizedUnitPrice,
|
|
115
|
+
total_customer_price: (0, money_1.toDollars)(result.order_summary.total_customer_price),
|
|
116
|
+
total_estimated_cost: (0, money_1.toDollars)(result.order_summary.total_estimated_cost),
|
|
117
|
+
gross_margin_percent: result.order_summary.gross_margin_percent,
|
|
118
|
+
net_margin_percent: result.order_summary.net_margin_percent,
|
|
119
|
+
warnings_count: result.warnings.length,
|
|
120
|
+
},
|
|
121
|
+
error: null,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
results.push({
|
|
126
|
+
scenario_name: meta.name,
|
|
127
|
+
scenario_file: file,
|
|
128
|
+
tags: meta.tags,
|
|
129
|
+
description: meta.description,
|
|
130
|
+
input: orderInput,
|
|
131
|
+
result: null,
|
|
132
|
+
summary: null,
|
|
133
|
+
error: err.message,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// ─── Terminal Output ───
|
|
138
|
+
const now = new Date();
|
|
139
|
+
const dateStr = now.toISOString().slice(0, 16).replace('T', ' ');
|
|
140
|
+
console.log('');
|
|
141
|
+
console.log('╔══════════════════════════════════════════════════════════════════════════════════════════════════╗');
|
|
142
|
+
console.log(`║ SCENARIO AUDIT — ${dateStr}${' '.repeat(78 - dateStr.length)}║`);
|
|
143
|
+
if (configSnapshot) {
|
|
144
|
+
const dec = configSnapshot.decoration;
|
|
145
|
+
const cfgLine = `Config: blanks=${configSnapshot.blanks} sp=${dec.screen_printing} emb=${dec.embroidery} dtf=${dec.dtf} dtg=${dec.dtg} sub=${dec.sublimation} spt=${dec.screen_print_transfers}`;
|
|
146
|
+
console.log(`║ ${padRight(cfgLine, 94)}║`);
|
|
147
|
+
}
|
|
148
|
+
console.log('╚══════════════════════════════════════════════════════════════════════════════════════════════════╝');
|
|
149
|
+
console.log('');
|
|
150
|
+
// Header
|
|
151
|
+
const HDR = ` ${padRight('#', 4)}${padRight('Scenario', 50)}${padRight('Qty', 6)}${padRight('Method', 14)}${padRight('Std $/unit', 12)}${padRight('Total $', 12)}${padRight('Margin%', 10)}Warnings`;
|
|
152
|
+
console.log(HDR);
|
|
153
|
+
console.log(' ' + '─'.repeat(HDR.length - 2));
|
|
154
|
+
for (let i = 0; i < results.length; i++) {
|
|
155
|
+
const r = results[i];
|
|
156
|
+
const num = padRight(String(i + 1), 4);
|
|
157
|
+
if (r.error) {
|
|
158
|
+
console.log(` ${num}${padRight(r.scenario_name.slice(0, 48), 50)}${'ERROR: ' + r.error.slice(0, 60)}`);
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
const s = r.summary;
|
|
162
|
+
const qty = padRight(String(s.total_quantity), 6);
|
|
163
|
+
const method = padRight(s.primary_method, 14);
|
|
164
|
+
const unitPrice = s.standard_unit_price != null
|
|
165
|
+
? padRight($(s.standard_unit_price), 12)
|
|
166
|
+
: padRight('—', 12);
|
|
167
|
+
const total = padRight($(s.total_customer_price), 12);
|
|
168
|
+
const margin = padRight(s.gross_margin_percent.toFixed(1) + '%', 10);
|
|
169
|
+
const warnings = s.warnings_count > 0 ? `${s.warnings_count} warning${s.warnings_count > 1 ? 's' : ''}` : '—';
|
|
170
|
+
console.log(` ${num}${padRight(r.scenario_name.slice(0, 48), 50)}${qty}${method}${unitPrice}${total}${margin}${warnings}`);
|
|
171
|
+
}
|
|
172
|
+
// ─── Detailed per-scenario output ───
|
|
173
|
+
console.log('');
|
|
174
|
+
console.log('═'.repeat(96));
|
|
175
|
+
console.log(' DETAILED BREAKDOWNS');
|
|
176
|
+
console.log('═'.repeat(96));
|
|
177
|
+
for (let i = 0; i < results.length; i++) {
|
|
178
|
+
const r = results[i];
|
|
179
|
+
console.log('');
|
|
180
|
+
console.log(` ┌─ ${i + 1}. ${r.scenario_name}`);
|
|
181
|
+
console.log(` │ ${r.description}`);
|
|
182
|
+
if (r.error) {
|
|
183
|
+
console.log(` │ ERROR: ${r.error}`);
|
|
184
|
+
console.log(' └─');
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
const result = r.result;
|
|
188
|
+
for (const li of result.line_items) {
|
|
189
|
+
const totalQty = li.quantity + (li.oversized_quantity ?? 0);
|
|
190
|
+
console.log(` │`);
|
|
191
|
+
console.log(` │ ${li.brand_sku} — ${li.garment_type} (${li.color})`);
|
|
192
|
+
console.log(` │ Method: ${li.decoration_method} Qty: ${totalQty}${li.oversized_quantity ? ` (${li.quantity} std + ${li.oversized_quantity} oversized)` : ''}`);
|
|
193
|
+
if (li.blanks_source) {
|
|
194
|
+
console.log(` │ Blanks: ${li.blanks_source}${li.blanks_supplier ? ` (${li.blanks_supplier})` : ''}`);
|
|
195
|
+
}
|
|
196
|
+
// Placements
|
|
197
|
+
if (li.placements.length > 0) {
|
|
198
|
+
const placementStrs = li.placements.map(p => {
|
|
199
|
+
let s = p.location;
|
|
200
|
+
if (p.color_count != null)
|
|
201
|
+
s += ` (${p.color_count}c)`;
|
|
202
|
+
if (p.stitch_count != null)
|
|
203
|
+
s += ` (${p.stitch_count.toLocaleString()} st)`;
|
|
204
|
+
return s;
|
|
205
|
+
});
|
|
206
|
+
console.log(` │ Placements: ${placementStrs.join(', ')}`);
|
|
207
|
+
}
|
|
208
|
+
// Cost breakdown
|
|
209
|
+
const b = li.cost_breakdown;
|
|
210
|
+
console.log(` │ Blanks: ${padLeft($((0, money_1.toDollars)(b.blanks.estimated_cost)), 9)} ×${b.blanks.multiplier.toFixed(2)} → ${$((0, money_1.toDollars)(b.blanks.marked_up))}`);
|
|
211
|
+
console.log(` │ Decoration: ${padLeft($((0, money_1.toDollars)(b.decoration.estimated_cost)), 9)} ×${b.decoration.multiplier.toFixed(2)} → ${$((0, money_1.toDollars)(b.decoration.marked_up))}`);
|
|
212
|
+
if (b.screen_setup) {
|
|
213
|
+
console.log(` │ Setup: ${padLeft($((0, money_1.toDollars)(b.screen_setup.estimated_cost)), 9)} ×${b.screen_setup.multiplier.toFixed(2)} → ${$((0, money_1.toDollars)(b.screen_setup.marked_up))}`);
|
|
214
|
+
}
|
|
215
|
+
// Customer-facing
|
|
216
|
+
const cf = li.customer_facing;
|
|
217
|
+
console.log(` │ → ${cf.standard_sizes.label}: ${cf.standard_sizes.quantity} × ${$(cf.standard_sizes.unit_price)} = ${$(cf.standard_sizes.line_total)}`);
|
|
218
|
+
if (cf.oversized) {
|
|
219
|
+
console.log(` │ → ${cf.oversized.label}: ${cf.oversized.quantity} × ${$(cf.oversized.unit_price)} = ${$(cf.oversized.line_total)}`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// Separate charges
|
|
223
|
+
if (result.separate_charges.digitizing) {
|
|
224
|
+
const d = result.separate_charges.digitizing;
|
|
225
|
+
console.log(` │ Digitizing: ${$((0, money_1.toDollars)(d.estimated_cost))} → ${$((0, money_1.toDollars)(d.customer_price))}`);
|
|
226
|
+
}
|
|
227
|
+
const ship = result.separate_charges.shipping;
|
|
228
|
+
console.log(` │ Shipping: ${$((0, money_1.toDollars)(ship.estimated_cost))} → ${$((0, money_1.toDollars)(ship.customer_price))}`);
|
|
229
|
+
// Order summary
|
|
230
|
+
const os = result.order_summary;
|
|
231
|
+
console.log(` │`);
|
|
232
|
+
console.log(` │ TOTAL: ${$((0, money_1.toDollars)(os.total_customer_price))} Cost: ${$((0, money_1.toDollars)(os.total_estimated_cost))} Gross: ${os.gross_margin_percent.toFixed(1)}% Net: ${os.net_margin_percent.toFixed(1)}%`);
|
|
233
|
+
// Warnings
|
|
234
|
+
if (result.warnings.length > 0) {
|
|
235
|
+
console.log(` │ ⚠ ${result.warnings.join('; ')}`);
|
|
236
|
+
}
|
|
237
|
+
console.log(' └─');
|
|
238
|
+
}
|
|
239
|
+
// ─── Totals ───
|
|
240
|
+
const passed = results.filter(r => !r.error);
|
|
241
|
+
const errored = results.filter(r => r.error);
|
|
242
|
+
const avgGross = passed.length > 0
|
|
243
|
+
? passed.reduce((sum, r) => sum + r.summary.gross_margin_percent, 0) / passed.length
|
|
244
|
+
: 0;
|
|
245
|
+
const avgNet = passed.length > 0
|
|
246
|
+
? passed.reduce((sum, r) => sum + r.summary.net_margin_percent, 0) / passed.length
|
|
247
|
+
: 0;
|
|
248
|
+
console.log('');
|
|
249
|
+
console.log('═'.repeat(96));
|
|
250
|
+
console.log(` ${passed.length}/${results.length} scenarios passed | Avg Gross Margin: ${avgGross.toFixed(1)}% | Avg Net Margin: ${avgNet.toFixed(1)}%`);
|
|
251
|
+
if (errored.length > 0) {
|
|
252
|
+
console.log(` ERRORS: ${errored.map(r => r.scenario_file).join(', ')}`);
|
|
253
|
+
}
|
|
254
|
+
console.log('═'.repeat(96));
|
|
255
|
+
// ─── Save JSON Results ───
|
|
256
|
+
if (!fs.existsSync(resultsDir)) {
|
|
257
|
+
fs.mkdirSync(resultsDir, { recursive: true });
|
|
258
|
+
}
|
|
259
|
+
const timestamp = now.toISOString().replace(/:/g, '-').slice(0, 19);
|
|
260
|
+
const outputFile = path.join(resultsDir, `${timestamp}.json`);
|
|
261
|
+
const output = {
|
|
262
|
+
timestamp: now.toISOString(),
|
|
263
|
+
config_snapshot: configSnapshot,
|
|
264
|
+
scenarios: results,
|
|
265
|
+
totals: {
|
|
266
|
+
scenarios_run: results.length,
|
|
267
|
+
scenarios_passed: passed.length,
|
|
268
|
+
scenarios_errored: errored.length,
|
|
269
|
+
avg_gross_margin: Math.round(avgGross * 10) / 10,
|
|
270
|
+
avg_net_margin: Math.round(avgNet * 10) / 10,
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
fs.writeFileSync(outputFile, JSON.stringify(output, null, 2));
|
|
274
|
+
console.log('');
|
|
275
|
+
console.log(` Full details saved to: ${path.relative(process.cwd(), outputFile)}`);
|
|
276
|
+
console.log('');
|
|
277
|
+
//# sourceMappingURL=audit-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-runner.js","sourceRoot":"","sources":["../src/audit-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface BlanksInput {
|
|
2
|
+
quantity: number;
|
|
3
|
+
unitCostCents: number;
|
|
4
|
+
blanksMultiplier: number;
|
|
5
|
+
hasOversized: boolean;
|
|
6
|
+
oversizedQuantity?: number;
|
|
7
|
+
oversizedUnitCostCents?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface BlanksResult {
|
|
10
|
+
standardCostCents: number;
|
|
11
|
+
standardMarkedUpCents: number;
|
|
12
|
+
oversizedCostCents: number;
|
|
13
|
+
oversizedMarkedUpCents: number;
|
|
14
|
+
totalCostCents: number;
|
|
15
|
+
totalMarkedUpCents: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function calculateBlanks(input: BlanksInput): BlanksResult;
|
|
18
|
+
//# sourceMappingURL=blanks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blanks.d.ts","sourceRoot":"","sources":["../../src/calculators/blanks.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,YAAY;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY,CAyBhE"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calculateBlanks = calculateBlanks;
|
|
4
|
+
const money_1 = require("../utils/money");
|
|
5
|
+
function calculateBlanks(input) {
|
|
6
|
+
const standardCostCents = input.unitCostCents * input.quantity;
|
|
7
|
+
const standardMarkedUpCents = (0, money_1.multiplyCents)(standardCostCents, input.blanksMultiplier);
|
|
8
|
+
let oversizedCostCents = 0;
|
|
9
|
+
let oversizedMarkedUpCents = 0;
|
|
10
|
+
if (input.hasOversized) {
|
|
11
|
+
if (input.oversizedQuantity == null || input.oversizedUnitCostCents == null) {
|
|
12
|
+
throw new Error('oversizedQuantity and oversizedUnitCostCents are required when hasOversized is true');
|
|
13
|
+
}
|
|
14
|
+
oversizedCostCents = input.oversizedUnitCostCents * input.oversizedQuantity;
|
|
15
|
+
oversizedMarkedUpCents = (0, money_1.multiplyCents)(oversizedCostCents, input.blanksMultiplier);
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
standardCostCents,
|
|
19
|
+
standardMarkedUpCents,
|
|
20
|
+
oversizedCostCents,
|
|
21
|
+
oversizedMarkedUpCents,
|
|
22
|
+
totalCostCents: standardCostCents + oversizedCostCents,
|
|
23
|
+
totalMarkedUpCents: standardMarkedUpCents + oversizedMarkedUpCents,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=blanks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blanks.js","sourceRoot":"","sources":["../../src/calculators/blanks.ts"],"names":[],"mappings":";;AAoBA,0CAyBC;AA7CD,0CAA+C;AAoB/C,SAAgB,eAAe,CAAC,KAAkB;IAChD,MAAM,iBAAiB,GAAG,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,QAAQ,CAAC;IAC/D,MAAM,qBAAqB,GAAG,IAAA,qBAAa,EAAC,iBAAiB,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAEvF,IAAI,kBAAkB,GAAG,CAAC,CAAC;IAC3B,IAAI,sBAAsB,GAAG,CAAC,CAAC;IAE/B,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACvB,IAAI,KAAK,CAAC,iBAAiB,IAAI,IAAI,IAAI,KAAK,CAAC,sBAAsB,IAAI,IAAI,EAAE,CAAC;YAC5E,MAAM,IAAI,KAAK,CACb,qFAAqF,CACtF,CAAC;QACJ,CAAC;QACD,kBAAkB,GAAG,KAAK,CAAC,sBAAsB,GAAG,KAAK,CAAC,iBAAiB,CAAC;QAC5E,sBAAsB,GAAG,IAAA,qBAAa,EAAC,kBAAkB,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACrF,CAAC;IAED,OAAO;QACL,iBAAiB;QACjB,qBAAqB;QACrB,kBAAkB;QAClB,sBAAsB;QACtB,cAAc,EAAE,iBAAiB,GAAG,kBAAkB;QACtD,kBAAkB,EAAE,qBAAqB,GAAG,sBAAsB;KACnE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { DesignPlacement, DecorationMethod } from '../types';
|
|
2
|
+
import type { VendorPricingData } from '../config';
|
|
3
|
+
export interface DecorationInput {
|
|
4
|
+
designs: DesignPlacement[];
|
|
5
|
+
/** Total quantity across all sizes (standard + oversized). */
|
|
6
|
+
totalQuantity: number;
|
|
7
|
+
decorationMethod: DecorationMethod;
|
|
8
|
+
decorationMultiplier: number;
|
|
9
|
+
vendorData: VendorPricingData;
|
|
10
|
+
/** Manual cost override per unit in cents (used when vendor pricing is unavailable). */
|
|
11
|
+
manualCostPerUnitCents?: number;
|
|
12
|
+
/** For sublimation: product key to look up in vendor pricing. */
|
|
13
|
+
sublimationProductKey?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface PerDesignCost {
|
|
16
|
+
location: string;
|
|
17
|
+
perUnitCostCents: number;
|
|
18
|
+
totalCostCents: number;
|
|
19
|
+
/** The vendor whose pricing was selected for this placement. */
|
|
20
|
+
vendorId?: string;
|
|
21
|
+
warning?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface DecorationResult {
|
|
24
|
+
perDesignCosts: PerDesignCost[];
|
|
25
|
+
totalCostCents: number;
|
|
26
|
+
totalMarkedUpCents: number;
|
|
27
|
+
/** Distinct vendor IDs selected across all placements. Usually just one. */
|
|
28
|
+
vendorIds: string[];
|
|
29
|
+
warnings: string[];
|
|
30
|
+
}
|
|
31
|
+
export declare function calculateDecoration(input: DecorationInput): DecorationResult;
|
|
32
|
+
//# sourceMappingURL=decoration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoration.d.ts","sourceRoot":"","sources":["../../src/calculators/decoration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAInD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,8DAA8D;IAC9D,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,UAAU,EAAE,iBAAiB,CAAC;IAC9B,wFAAwF;IACxF,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,iEAAiE;IACjE,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,4EAA4E;IAC5E,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,gBAAgB,CA+E5E"}
|