@pisell/pisellos 2.2.193 → 2.2.194

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.
@@ -42,6 +42,31 @@ function toDecimal(value) {
42
42
  function toFixed2(value) {
43
43
  return new import_decimal.default(value || 0).toFixed(2);
44
44
  }
45
+ function toAmountFormat(value) {
46
+ return new import_decimal.default(value || 0).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP);
47
+ }
48
+ function toBackendTaxFee(value) {
49
+ return toBcScale(value, 2);
50
+ }
51
+ function toBcScale(value, scale) {
52
+ const factor = new import_decimal.default(10).pow(scale);
53
+ return new import_decimal.default(value || 0).times(factor).toDecimalPlaces(0, import_decimal.default.ROUND_DOWN).div(factor);
54
+ }
55
+ function bcAdd(left, right, scale) {
56
+ return toBcScale(new import_decimal.default(left || 0).plus(right || 0), scale);
57
+ }
58
+ function bcSub(left, right, scale) {
59
+ return toBcScale(new import_decimal.default(left || 0).minus(right || 0), scale);
60
+ }
61
+ function bcMul(left, right, scale) {
62
+ return toBcScale(new import_decimal.default(left || 0).times(right || 0), scale);
63
+ }
64
+ function bcDiv(left, right, scale) {
65
+ const divisor = new import_decimal.default(right || 0);
66
+ if (divisor.eq(0))
67
+ return new import_decimal.default(0);
68
+ return toBcScale(new import_decimal.default(left || 0).div(divisor), scale);
69
+ }
45
70
  function getSafeNum(num) {
46
71
  if (!num || Number.isNaN(num))
47
72
  return 1;
@@ -71,6 +96,11 @@ function getUnitOriginalTotal(product) {
71
96
  const basePrice = mainOriginal !== void 0 ? toDecimal(mainOriginal) : mainSelling !== void 0 ? toDecimal(mainSelling) : toDecimal(product.original_price || product.selling_price);
72
97
  return basePrice.plus(getBundleUnitPrice(product, true));
73
98
  }
99
+ function isGeneratedVoucherProduct(product) {
100
+ const record = product;
101
+ const metadata = (record == null ? void 0 : record.metadata) || {};
102
+ return (record == null ? void 0 : record.extension_type) === "product_voucher" || metadata.parent_order_detail_id !== void 0 || metadata.gift_card_type !== void 0;
103
+ }
74
104
  function buildSurchargeServiceItems(products) {
75
105
  return products.map((product) => {
76
106
  var _a, _b;
@@ -101,6 +131,252 @@ function buildSurchargeServiceItems(products) {
101
131
  };
102
132
  });
103
133
  }
134
+ function getRelationSurchargeIds(item) {
135
+ var _a;
136
+ const ids = (item == null ? void 0 : item.relation_surcharge_ids) ?? ((_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a.relation_surcharge_ids);
137
+ if (!Array.isArray(ids))
138
+ return [];
139
+ return ids.filter((id) => id !== void 0 && id !== null && id !== "");
140
+ }
141
+ function getSurchargeConfigId(config) {
142
+ return (config == null ? void 0 : config.id) ?? (config == null ? void 0 : config.surcharge_id);
143
+ }
144
+ function getSurchargeConfigById(surchargeList) {
145
+ const map = /* @__PURE__ */ new Map();
146
+ for (const config of surchargeList || []) {
147
+ const id = getSurchargeConfigId(config);
148
+ if (id !== void 0)
149
+ map.set(id, config);
150
+ }
151
+ return map;
152
+ }
153
+ function getMainSurchargeUnitAmount(product) {
154
+ var _a, _b;
155
+ const record = product;
156
+ return toDecimal(
157
+ ((_a = record.metadata) == null ? void 0 : _a.main_product_attached_bundle_selling_price) ?? ((_b = record.metadata) == null ? void 0 : _b.main_product_selling_price) ?? record.selling_price ?? 0
158
+ );
159
+ }
160
+ function getBundleSurchargeUnitAmount(bundle) {
161
+ return toDecimal((bundle == null ? void 0 : bundle.bundle_selling_price) ?? (bundle == null ? void 0 : bundle.bundle_sum_price) ?? (bundle == null ? void 0 : bundle.price) ?? 0);
162
+ }
163
+ function getBundleProductId(bundle) {
164
+ const id = (bundle == null ? void 0 : bundle.bundle_product_id) ?? (bundle == null ? void 0 : bundle._bundle_product_id) ?? (bundle == null ? void 0 : bundle.product_id);
165
+ if (id === void 0 || id === null || id === "")
166
+ return null;
167
+ const parsed = Number(id);
168
+ if (!Number.isFinite(parsed))
169
+ return null;
170
+ return parsed;
171
+ }
172
+ function createSurchargeAllocationNodes(products, sourceItems) {
173
+ var _a;
174
+ const nodes = [];
175
+ for (let productIndex = 0; productIndex < products.length; productIndex++) {
176
+ const product = products[productIndex];
177
+ const sourceItem = sourceItems[productIndex] || {};
178
+ const productQuantity = new import_decimal.default(getSafeNum(product.num));
179
+ for (let bundleIndex = 0; bundleIndex < (product.product_bundle || []).length; bundleIndex++) {
180
+ const bundle = product.product_bundle[bundleIndex];
181
+ if (!isBundleOriginalPrice(bundle))
182
+ continue;
183
+ const sourceBundle = ((_a = sourceItem == null ? void 0 : sourceItem.bundle) == null ? void 0 : _a[bundleIndex]) || {};
184
+ nodes.push({
185
+ kind: "bundle",
186
+ target: bundle,
187
+ source: sourceBundle,
188
+ productId: getBundleProductId(bundle),
189
+ unitAmount: getBundleSurchargeUnitAmount(bundle),
190
+ quantity: new import_decimal.default(getSafeNum((bundle == null ? void 0 : bundle.num) ?? (bundle == null ? void 0 : bundle.quantity))).times(productQuantity),
191
+ relationSurchargeIds: getRelationSurchargeIds(sourceBundle)
192
+ });
193
+ }
194
+ nodes.push({
195
+ kind: "main",
196
+ target: product,
197
+ source: sourceItem,
198
+ productId: product.product_id ?? null,
199
+ unitAmount: getMainSurchargeUnitAmount(product),
200
+ quantity: productQuantity,
201
+ relationSurchargeIds: getRelationSurchargeIds(sourceItem)
202
+ });
203
+ }
204
+ return nodes;
205
+ }
206
+ function resetProductSurchargeFields(products) {
207
+ for (const product of products) {
208
+ product.surcharge_fee = 0;
209
+ product.main_product_attached_bundle_surcharge_fee = "0.00";
210
+ product.surcharge_rounding_remainder = 0;
211
+ product.relation_surcharge_ids = [];
212
+ for (const bundle of product.product_bundle || []) {
213
+ bundle.surcharge_fee = 0;
214
+ bundle.relation_surcharge_ids = [];
215
+ bundle.metadata = {
216
+ ...bundle.metadata || {},
217
+ surcharge_fee: "0.00",
218
+ surcharge_rounding_remainder: "0.00",
219
+ relation_surcharge_ids: []
220
+ };
221
+ }
222
+ }
223
+ }
224
+ function buildSurchargeQuantityTotals(nodes) {
225
+ const totals = /* @__PURE__ */ new Map();
226
+ for (const node of nodes) {
227
+ for (const surchargeId of node.relationSurchargeIds) {
228
+ totals.set(
229
+ surchargeId,
230
+ (totals.get(surchargeId) || new import_decimal.default(0)).plus(node.quantity)
231
+ );
232
+ }
233
+ }
234
+ return totals;
235
+ }
236
+ function getFallbackAllProductSurchargeIds(surchargeList) {
237
+ return (surchargeList || []).reduce((ids, config) => {
238
+ const id = getSurchargeConfigId(config);
239
+ if (id === void 0)
240
+ return ids;
241
+ if (Number(config.open_product ?? 0) === 0)
242
+ return ids;
243
+ if (Number(config.is_all ?? 0) !== 1)
244
+ return ids;
245
+ ids.push(id);
246
+ return ids;
247
+ }, []);
248
+ }
249
+ function getBackendSurchargeState(stateMap, surchargeId, config) {
250
+ let state = stateMap.get(surchargeId);
251
+ if (!state) {
252
+ state = {
253
+ config,
254
+ amount: new import_decimal.default(0),
255
+ totalOffsetFee: new import_decimal.default(0),
256
+ calculatedQuantity: new import_decimal.default(0),
257
+ fixedIncluded: false,
258
+ fixedRemainderAssigned: false
259
+ };
260
+ stateMap.set(surchargeId, state);
261
+ }
262
+ return state;
263
+ }
264
+ function applySurchargeNodeResult(node, params) {
265
+ const { unitSurchargeFee, roundingRemainder, surchargeIds } = params;
266
+ if (node.kind === "main") {
267
+ node.target.surcharge_fee = unitSurchargeFee.toNumber();
268
+ node.target.main_product_attached_bundle_surcharge_fee = toFixed2(unitSurchargeFee);
269
+ node.target.surcharge_rounding_remainder = roundingRemainder.toNumber();
270
+ node.target.relation_surcharge_ids = surchargeIds;
271
+ return;
272
+ }
273
+ node.target.surcharge_fee = unitSurchargeFee.toNumber();
274
+ node.target.relation_surcharge_ids = surchargeIds;
275
+ node.target.metadata = {
276
+ ...node.target.metadata || {},
277
+ surcharge_fee: toFixed2(unitSurchargeFee),
278
+ surcharge_rounding_remainder: toFixed2(roundingRemainder),
279
+ relation_surcharge_ids: surchargeIds
280
+ };
281
+ }
282
+ function calculateBackendProductSurcharges(params) {
283
+ const { products, sourceItems, surchargeList } = params;
284
+ resetProductSurchargeFields(products);
285
+ const configById = getSurchargeConfigById(surchargeList);
286
+ const nodes = createSurchargeAllocationNodes(products, sourceItems);
287
+ const fallbackAllProductSurchargeIds = getFallbackAllProductSurchargeIds(surchargeList);
288
+ for (const node of nodes) {
289
+ if (node.relationSurchargeIds.length === 0) {
290
+ node.relationSurchargeIds = fallbackAllProductSurchargeIds;
291
+ }
292
+ }
293
+ const quantityTotals = buildSurchargeQuantityTotals(nodes);
294
+ const stateMap = /* @__PURE__ */ new Map();
295
+ for (const node of nodes) {
296
+ let unitSurchargeFee = new import_decimal.default(0);
297
+ let roundingRemainder = new import_decimal.default(0);
298
+ const appliedSurchargeIds = [];
299
+ for (const surchargeId of node.relationSurchargeIds) {
300
+ const config = configById.get(surchargeId);
301
+ const totalQuantity = quantityTotals.get(surchargeId) || new import_decimal.default(0);
302
+ if (!config || totalQuantity.lte(0))
303
+ continue;
304
+ const percentage = new import_decimal.default(config.percentage || 0);
305
+ const fixed = new import_decimal.default(config.fixed || 0);
306
+ const unitPercentageFee = import_decimal.default.max(0, bcMul(node.unitAmount, percentage, 2));
307
+ const percentageTotalFee = bcMul(node.quantity, unitPercentageFee, 2);
308
+ let unitFixedFee = new import_decimal.default(0);
309
+ let fixedRemainder = new import_decimal.default(0);
310
+ if (fixed.gt(0)) {
311
+ unitFixedFee = bcDiv(fixed, totalQuantity, 2);
312
+ const distributedFixed = bcMul(unitFixedFee, totalQuantity, 2);
313
+ fixedRemainder = bcSub(fixed, distributedFixed, 2);
314
+ }
315
+ const currentUnitSurcharge = import_decimal.default.max(
316
+ 0,
317
+ bcAdd(unitPercentageFee, unitFixedFee, 2)
318
+ );
319
+ if (currentUnitSurcharge.lte(0))
320
+ continue;
321
+ const state = getBackendSurchargeState(stateMap, surchargeId, config);
322
+ state.amount = bcAdd(state.amount, percentageTotalFee, 2);
323
+ const precisePercentage = import_decimal.default.max(0, bcMul(node.unitAmount, percentage, 6));
324
+ const offsetBaseFee = import_decimal.default.max(0, bcSub(precisePercentage, unitPercentageFee, 6));
325
+ state.totalOffsetFee = bcAdd(
326
+ state.totalOffsetFee,
327
+ bcMul(offsetBaseFee, node.quantity, 6),
328
+ 6
329
+ );
330
+ state.calculatedQuantity = bcAdd(state.calculatedQuantity, node.quantity, 6);
331
+ if (!state.fixedIncluded && fixed.gt(0)) {
332
+ state.amount = bcAdd(state.amount, fixed, 2);
333
+ state.fixedIncluded = true;
334
+ }
335
+ if (!state.fixedRemainderAssigned && !fixedRemainder.eq(0)) {
336
+ state.fixedRemainderAssigned = true;
337
+ roundingRemainder = bcAdd(roundingRemainder, fixedRemainder, 2);
338
+ }
339
+ if (state.calculatedQuantity.gte(totalQuantity) && state.totalOffsetFee.gt(0)) {
340
+ const totalOffsetFee = toAmountFormat(state.totalOffsetFee);
341
+ state.amount = bcAdd(state.amount, totalOffsetFee, 2);
342
+ roundingRemainder = bcAdd(roundingRemainder, totalOffsetFee, 2);
343
+ state.totalOffsetFee = new import_decimal.default(0);
344
+ }
345
+ unitSurchargeFee = bcAdd(unitSurchargeFee, currentUnitSurcharge, 2);
346
+ appliedSurchargeIds.push(surchargeId);
347
+ }
348
+ applySurchargeNodeResult(node, {
349
+ unitSurchargeFee,
350
+ roundingRemainder,
351
+ surchargeIds: appliedSurchargeIds
352
+ });
353
+ }
354
+ return (surchargeList || []).reduce((result, config, index) => {
355
+ const surchargeId = getSurchargeConfigId(config);
356
+ if (surchargeId === void 0)
357
+ return result;
358
+ const state = stateMap.get(surchargeId);
359
+ if (!state || state.amount.lte(0))
360
+ return result;
361
+ const name = config.name || config.label || {};
362
+ result.push({
363
+ key: `custom_surcharge_${index}`,
364
+ label: name,
365
+ name,
366
+ value: state.amount.toNumber(),
367
+ surcharge_id: surchargeId,
368
+ description: config.description,
369
+ type: "default",
370
+ fixed: config.fixed,
371
+ amount: state.amount.toNumber(),
372
+ percentage: config.percentage,
373
+ metadata: {
374
+ open_product: config.open_product
375
+ }
376
+ });
377
+ return result;
378
+ }, []);
379
+ }
104
380
  function getProductDepositData(product) {
105
381
  var _a, _b, _c;
106
382
  const rootDepositData = (_a = product._origin) == null ? void 0 : _a.custom_deposit_data;
@@ -219,47 +495,85 @@ function getMainProductPaymentTotal(product) {
219
495
  }
220
496
  return import_decimal.default.max(total, 0);
221
497
  }
498
+ function getExplicitTaxRemainder(item) {
499
+ var _a;
500
+ const value = (item == null ? void 0 : item.tax_fee_rounding_remainder) ?? ((_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a.tax_fee_rounding_remainder);
501
+ if (value === void 0 || value === null || value === "")
502
+ return null;
503
+ return new import_decimal.default(value || 0);
504
+ }
505
+ function getPersistedTaxRemainder(item, parentProduct) {
506
+ const isPersistedLine = (item == null ? void 0 : item.order_detail_id) !== void 0 && (item == null ? void 0 : item.order_detail_id) !== null || (parentProduct == null ? void 0 : parentProduct.order_detail_id) !== void 0 && (parentProduct == null ? void 0 : parentProduct.order_detail_id) !== null;
507
+ if (!isPersistedLine)
508
+ return null;
509
+ return getExplicitTaxRemainder(item);
510
+ }
511
+ function writeTaxRemainder(item, roundingRemainder) {
512
+ item.tax_fee_rounding_remainder = roundingRemainder.toNumber();
513
+ if (item.metadata && typeof item.metadata === "object") {
514
+ item.metadata.tax_fee_rounding_remainder = roundingRemainder.toFixed(2);
515
+ }
516
+ }
517
+ function resetTaxRemainderFields(products) {
518
+ for (const product of products) {
519
+ const productRemainder = getPersistedTaxRemainder(product);
520
+ product.tax_fee_rounding_remainder = (productRemainder == null ? void 0 : productRemainder.toNumber()) ?? 0;
521
+ product.original_tax_fee_rounding_remainder = 0;
522
+ for (const bundle of product.product_bundle || []) {
523
+ const bundleRemainder = getPersistedTaxRemainder(bundle, product);
524
+ bundle.metadata = {
525
+ ...bundle.metadata || {},
526
+ tax_fee_rounding_remainder: (bundleRemainder == null ? void 0 : bundleRemainder.toFixed(2)) ?? "0.00"
527
+ };
528
+ bundle.tax_fee_rounding_remainder = (bundleRemainder == null ? void 0 : bundleRemainder.toNumber()) ?? 0;
529
+ bundle.original_tax_fee_rounding_remainder = 0;
530
+ }
531
+ }
532
+ }
533
+ function getBundlePaymentPrice(bundle, product) {
534
+ var _a;
535
+ if ((bundle == null ? void 0 : bundle.bundle_payment_price) !== void 0)
536
+ return toDecimal(bundle.bundle_payment_price);
537
+ const basePrice = toDecimal((bundle == null ? void 0 : bundle.bundle_selling_price) ?? (bundle == null ? void 0 : bundle.bundle_sum_price) ?? (bundle == null ? void 0 : bundle.price) ?? 0);
538
+ if (!isBundleOriginalPrice(bundle))
539
+ return basePrice;
540
+ const averageDiscountRate = toDecimal(
541
+ ((_a = product.metadata) == null ? void 0 : _a.average_discount_amount_rate) ?? 1
542
+ );
543
+ return toAmountFormat(bcMul(basePrice, averageDiscountRate, 6));
544
+ }
545
+ function applyBackendTaxRemainder(params) {
546
+ const { target, rawTax, formattedTax, quantity, state } = params;
547
+ const taxFeeDifference = bcMul(
548
+ bcSub(rawTax, formattedTax, 6),
549
+ quantity,
550
+ 6
551
+ );
552
+ state.difference = bcAdd(state.difference, taxFeeDifference, 6);
553
+ if (state.difference.lt(5e-3))
554
+ return new import_decimal.default(0);
555
+ const roundingRemainder = toAmountFormat(state.difference);
556
+ writeTaxRemainder(target, roundingRemainder);
557
+ state.difference = bcSub(state.difference, roundingRemainder, 6);
558
+ return roundingRemainder;
559
+ }
222
560
  function calculateProductsTax(products, taxRate, isPriceIncludeTax) {
223
561
  const rate = new import_decimal.default(taxRate);
224
- let preciseTax = new import_decimal.default(0);
225
- let roundedTax = new import_decimal.default(0);
226
- let preciseOriginTax = new import_decimal.default(0);
227
- let roundedOriginTax = new import_decimal.default(0);
228
- let lastTaxableItem = null;
562
+ const taxRemainderState = { difference: new import_decimal.default(0) };
563
+ let totalTax = new import_decimal.default(0);
564
+ let totalOriginTax = new import_decimal.default(0);
565
+ resetTaxRemainderFields(products);
229
566
  for (const product of products) {
230
567
  const quantity = new import_decimal.default(getSafeNum(product.num));
231
- const mainTotal = getMainProductPaymentTotal(product);
232
- const surchargeFee = toDecimal(product.surcharge_fee);
233
- const mainTaxableBase = mainTotal.lte(0) ? surchargeFee : mainTotal.plus(surchargeFee);
234
- const mainTaxPrecise = calculateSingleItemTax({
235
- price: mainTaxableBase,
236
- taxRate: rate,
237
- isPriceIncludeTax,
238
- isChargeTax: product.is_charge_tax ?? 0
239
- });
240
- const mainTaxRounded = mainTaxPrecise.toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP);
241
- product.main_product_attached_bundle_tax_fee = mainTaxRounded.toFixed(2);
242
- if (mainTaxPrecise.gt(0)) {
243
- lastTaxableItem = { type: "main", item: product };
244
- }
245
- const originalTotal = getUnitOriginalTotal(product);
246
- const originalTaxableBase = originalTotal.lte(0) ? surchargeFee : originalTotal.plus(surchargeFee);
247
- const originalTaxPrecise = calculateSingleItemTax({
248
- price: originalTaxableBase,
249
- taxRate: rate,
250
- isPriceIncludeTax,
251
- isChargeTax: product.is_charge_tax ?? 0
252
- });
253
- let bundlePreciseTax = new import_decimal.default(0);
254
- let bundleRoundedTax = new import_decimal.default(0);
255
- let bundlePreciseOriginTax = new import_decimal.default(0);
256
- let bundleRoundedOriginTax = new import_decimal.default(0);
568
+ let productUnitTax = new import_decimal.default(0);
569
+ let productUnitOriginTax = new import_decimal.default(0);
257
570
  const bundleItems = product.product_bundle || [];
258
571
  for (const bundleItem of bundleItems) {
259
572
  if (!isBundleOriginalPrice(bundleItem))
260
573
  continue;
261
574
  const bundleQuantity = new import_decimal.default(getSafeNum(bundleItem.num ?? bundleItem.quantity));
262
- const bundlePrice = toDecimal(bundleItem.bundle_selling_price ?? bundleItem.price ?? 0);
575
+ const totalBundleQuantity = bundleQuantity.times(quantity);
576
+ const bundlePrice = getBundlePaymentPrice(bundleItem, product);
263
577
  const bundleOriginalPrice = toDecimal(bundleItem.original_price ?? bundleItem.product_price ?? bundleItem.price ?? 0);
264
578
  const bundleSurchargeFee = toDecimal(bundleItem.surcharge_fee);
265
579
  const bundleTaxPrecise = calculateSingleItemTax({
@@ -268,48 +582,72 @@ function calculateProductsTax(products, taxRate, isPriceIncludeTax) {
268
582
  isPriceIncludeTax,
269
583
  isChargeTax: bundleItem.is_charge_tax ?? product.is_charge_tax ?? 0
270
584
  });
271
- const bundleTaxRounded = bundleTaxPrecise.toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP);
585
+ const bundleTaxRounded = toBackendTaxFee(bundleTaxPrecise);
586
+ bundleItem.tax_fee = bundleTaxRounded.toNumber();
587
+ const persistedBundleRemainder = getPersistedTaxRemainder(bundleItem, product);
588
+ const bundleRemainder = persistedBundleRemainder ?? applyBackendTaxRemainder({
589
+ target: bundleItem,
590
+ rawTax: bundleTaxPrecise,
591
+ formattedTax: bundleTaxRounded,
592
+ quantity: totalBundleQuantity,
593
+ state: taxRemainderState
594
+ });
595
+ if (persistedBundleRemainder)
596
+ writeTaxRemainder(bundleItem, persistedBundleRemainder);
272
597
  const bundleOrigTaxPrecise = calculateSingleItemTax({
273
598
  price: bundleOriginalPrice.plus(bundleSurchargeFee),
274
599
  taxRate: rate,
275
600
  isPriceIncludeTax,
276
601
  isChargeTax: bundleItem.is_charge_tax ?? product.is_charge_tax ?? 0
277
602
  });
278
- const bundleOrigTaxRounded = bundleOrigTaxPrecise.toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP);
279
- bundleItem.tax_fee = bundleTaxRounded.toNumber();
603
+ const bundleOrigTaxRounded = toAmountFormat(bundleOrigTaxPrecise);
280
604
  bundleItem.original_tax_fee = bundleOrigTaxRounded.toNumber();
281
- bundlePreciseTax = bundlePreciseTax.plus(bundleTaxPrecise.times(bundleQuantity));
282
- bundleRoundedTax = bundleRoundedTax.plus(bundleTaxRounded.times(bundleQuantity));
283
- bundlePreciseOriginTax = bundlePreciseOriginTax.plus(bundleOrigTaxPrecise.times(bundleQuantity));
284
- bundleRoundedOriginTax = bundleRoundedOriginTax.plus(bundleOrigTaxRounded.times(bundleQuantity));
285
- if (bundleTaxPrecise.gt(0)) {
286
- lastTaxableItem = { type: "bundle", item: bundleItem };
287
- }
288
- }
289
- const itemTaxPrecise = mainTaxPrecise.plus(bundlePreciseTax);
290
- const itemTaxRounded = mainTaxRounded.plus(bundleRoundedTax);
291
- const itemOriginTaxPrecise = originalTaxPrecise.plus(bundlePreciseOriginTax);
292
- const itemOriginTaxRounded = originalTaxPrecise.toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).plus(bundleRoundedOriginTax);
293
- product.tax_fee = itemTaxRounded.toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toFixed(2);
294
- product.original_tax_fee = itemOriginTaxRounded.toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber();
295
- preciseTax = preciseTax.plus(itemTaxPrecise.times(quantity));
296
- roundedTax = roundedTax.plus(itemTaxRounded.times(quantity));
297
- preciseOriginTax = preciseOriginTax.plus(itemOriginTaxPrecise.times(quantity));
298
- roundedOriginTax = roundedOriginTax.plus(itemOriginTaxRounded.times(quantity));
299
- }
300
- const expectedTax = preciseTax.toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP);
301
- const expectedOriginTax = preciseOriginTax.toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP);
302
- const taxRemainder = expectedTax.minus(roundedTax).toNumber();
303
- const originTaxRemainder = expectedOriginTax.minus(roundedOriginTax).toNumber();
304
- if (lastTaxableItem) {
305
- if (taxRemainder !== 0) {
306
- lastTaxableItem.item.tax_fee_rounding_remainder = taxRemainder;
307
- }
308
- if (originTaxRemainder !== 0) {
309
- lastTaxableItem.item.original_tax_fee_rounding_remainder = originTaxRemainder;
605
+ productUnitTax = productUnitTax.plus(bundleTaxRounded.times(bundleQuantity));
606
+ productUnitOriginTax = productUnitOriginTax.plus(bundleOrigTaxRounded.times(bundleQuantity));
607
+ totalTax = totalTax.plus(bundleTaxRounded.times(totalBundleQuantity)).plus(bundleRemainder);
608
+ totalOriginTax = totalOriginTax.plus(bundleOrigTaxRounded.times(totalBundleQuantity));
310
609
  }
610
+ const mainTotal = getMainProductPaymentTotal(product);
611
+ const surchargeFee = toDecimal(product.surcharge_fee);
612
+ const mainTaxableBase = mainTotal.lte(0) ? surchargeFee : mainTotal.plus(surchargeFee);
613
+ const mainTaxPrecise = calculateSingleItemTax({
614
+ price: mainTaxableBase,
615
+ taxRate: rate,
616
+ isPriceIncludeTax,
617
+ isChargeTax: product.is_charge_tax ?? 0
618
+ });
619
+ const mainTaxRounded = toBackendTaxFee(mainTaxPrecise);
620
+ product.main_product_attached_bundle_tax_fee = mainTaxRounded.toFixed(2);
621
+ const persistedMainRemainder = getPersistedTaxRemainder(product);
622
+ const mainRemainder = persistedMainRemainder ?? applyBackendTaxRemainder({
623
+ target: product,
624
+ rawTax: mainTaxPrecise,
625
+ formattedTax: mainTaxRounded,
626
+ quantity,
627
+ state: taxRemainderState
628
+ });
629
+ if (persistedMainRemainder)
630
+ writeTaxRemainder(product, persistedMainRemainder);
631
+ const originalTotal = getUnitOriginalTotal(product);
632
+ const originalTaxableBase = originalTotal.lte(0) ? surchargeFee : originalTotal.plus(surchargeFee);
633
+ const originalTaxPrecise = calculateSingleItemTax({
634
+ price: originalTaxableBase,
635
+ taxRate: rate,
636
+ isPriceIncludeTax,
637
+ isChargeTax: product.is_charge_tax ?? 0
638
+ });
639
+ const originalTaxRounded = toAmountFormat(originalTaxPrecise);
640
+ productUnitTax = productUnitTax.plus(mainTaxRounded);
641
+ productUnitOriginTax = productUnitOriginTax.plus(originalTaxRounded);
642
+ product.tax_fee = productUnitTax.toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toFixed(2);
643
+ product.original_tax_fee = productUnitOriginTax.toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber();
644
+ totalTax = totalTax.plus(mainTaxRounded.times(quantity)).plus(mainRemainder);
645
+ totalOriginTax = totalOriginTax.plus(originalTaxRounded.times(quantity));
311
646
  }
312
- return { tax: expectedTax, originTax: expectedOriginTax };
647
+ return {
648
+ tax: totalTax.toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP),
649
+ originTax: totalOriginTax.toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP)
650
+ };
313
651
  }
314
652
  function createEmptySalesSummary() {
315
653
  return {
@@ -347,20 +685,23 @@ function calculateSalesSummary(params) {
347
685
  } = params;
348
686
  if (!(products == null ? void 0 : products.length))
349
687
  return createEmptySalesSummary();
350
- const productQuantity = products.reduce(
688
+ const summaryProducts = products.filter((product) => !isGeneratedVoucherProduct(product));
689
+ if (!summaryProducts.length)
690
+ return createEmptySalesSummary();
691
+ const productQuantity = summaryProducts.reduce(
351
692
  (sum, item) => sum + getSafeNum(item.num),
352
693
  0
353
694
  );
354
- const productOriginalAmount = products.reduce(
695
+ const productOriginalAmount = summaryProducts.reduce(
355
696
  (sum, item) => sum.plus(getUnitOriginalTotal(item).times(getSafeNum(item.num))),
356
697
  new import_decimal.default(0)
357
698
  );
358
- const productAmount = products.reduce(
699
+ const productAmount = summaryProducts.reduce(
359
700
  (sum, item) => sum.plus(getUnitPaymentTotal(item).times(getSafeNum(item.num))),
360
701
  new import_decimal.default(0)
361
702
  );
362
- const surchargeServiceItems = buildSurchargeServiceItems(products);
363
- const surcharge = (0, import_utils.getSurcharge)(
703
+ const surchargeServiceItems = buildSurchargeServiceItems(summaryProducts);
704
+ (0, import_utils.getSurcharge)(
364
705
  {
365
706
  service: surchargeServiceItems,
366
707
  addons: [],
@@ -374,6 +715,11 @@ function calculateSalesSummary(params) {
374
715
  scheduleById
375
716
  }
376
717
  );
718
+ const surcharge = calculateBackendProductSurcharges({
719
+ products: summaryProducts,
720
+ sourceItems: surchargeServiceItems,
721
+ surchargeList
722
+ });
377
723
  const surchargeAmount = new import_decimal.default(
378
724
  (0, import_utils.getSurchargeAmount)(
379
725
  { bookingDetail: null, bookingId: void 0 },
@@ -381,29 +727,13 @@ function calculateSalesSummary(params) {
381
727
  { isEdit: false }
382
728
  ) || 0
383
729
  );
384
- for (let i = 0; i < products.length; i++) {
385
- const sourceItem = surchargeServiceItems[i] || {};
386
- const product = products[i];
387
- product.surcharge_fee = sourceItem.surcharge_fee || 0;
388
- const relationSurchargeIds = Array.isArray(sourceItem.relation_surcharge_ids) ? sourceItem.relation_surcharge_ids : [];
389
- const hasSurcharge = new import_decimal.default(product.surcharge_fee || 0).gt(0) || relationSurchargeIds.length > 0;
390
- if (hasSurcharge) {
391
- product.main_product_attached_bundle_surcharge_fee = toFixed2(product.surcharge_fee);
392
- }
393
- if (relationSurchargeIds.length > 0) {
394
- product.relation_surcharge_ids = sourceItem.relation_surcharge_ids;
395
- }
396
- if (hasSurcharge && sourceItem.surcharge_rounding_remainder !== void 0) {
397
- product.surcharge_rounding_remainder = sourceItem.surcharge_rounding_remainder;
398
- }
399
- }
400
730
  const hasTaxRate = taxRate !== void 0 && taxRate !== null && taxRate > 0;
401
731
  let productTaxFee;
402
732
  if (hasTaxRate) {
403
- const taxResult = calculateProductsTax(products, taxRate, isPriceIncludeTax);
733
+ const taxResult = calculateProductsTax(summaryProducts, taxRate, isPriceIncludeTax);
404
734
  productTaxFee = taxResult.tax;
405
735
  } else {
406
- productTaxFee = products.reduce(
736
+ productTaxFee = summaryProducts.reduce(
407
737
  (sum, item) => sum.plus(toDecimal(item.tax_fee).times(getSafeNum(item.num))),
408
738
  new import_decimal.default(0)
409
739
  );
@@ -411,7 +741,7 @@ function calculateSalesSummary(params) {
411
741
  const shopDiscountAmount = import_decimal.default.max(new import_decimal.default(Number(shopDiscount) || 0), 0);
412
742
  const preTaxExpectAmount = import_decimal.default.max(0, productAmount.plus(surchargeAmount).minus(shopDiscountAmount));
413
743
  const totalAmount = isPriceIncludeTax === 1 ? preTaxExpectAmount : preTaxExpectAmount.plus(productTaxFee);
414
- const deposit = calculateProductsDeposit(products);
744
+ const deposit = calculateProductsDeposit(summaryProducts);
415
745
  return {
416
746
  product_quantity: productQuantity,
417
747
  product_original_amount: toFixed2(productOriginalAmount),
@@ -945,11 +945,11 @@ var Server = class {
945
945
  async setupProductsQuotationPriceBridge() {
946
946
  var _a;
947
947
  if (!this.products) {
948
- this.logWarning("setupProductsQuotationPriceBridge: Products 模块未注册");
948
+ this.logInfo("setupProductsQuotationPriceBridge: Products 模块未注册");
949
949
  return;
950
950
  }
951
951
  if (!this.schedule) {
952
- this.logWarning("setupProductsQuotationPriceBridge: Schedule 模块未注册");
952
+ this.logInfo("setupProductsQuotationPriceBridge: Schedule 模块未注册");
953
953
  return;
954
954
  }
955
955
  try {
@@ -1170,10 +1170,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1170
1170
  this.productDataSource.run({
1171
1171
  pubsub: {
1172
1172
  callback: (res) => {
1173
- console.log("sse_products_callback", res);
1174
- this.logInfo("sse_products_callback: 收到同步消息", {
1175
- data: res == null ? void 0 : res.data
1176
- });
1177
1173
  if (!(res == null ? void 0 : res.data))
1178
1174
  return;
1179
1175
  const data = res.data;
@@ -311,7 +311,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
311
311
  date: string;
312
312
  status: string;
313
313
  week: string;
314
- weekNum: 0 | 1 | 2 | 6 | 3 | 5 | 4;
314
+ weekNum: 0 | 2 | 1 | 5 | 3 | 4 | 6;
315
315
  }[]>;
316
316
  submitTimeSlot(timeSlots: TimeSliceItem): void;
317
317
  private getScheduleDataByIds;
@@ -279,7 +279,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
279
279
  * 获取当前的客户搜索条件
280
280
  * @returns 当前搜索条件
281
281
  */
282
- getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "skip" | "num">;
282
+ getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "num" | "skip">;
283
283
  /**
284
284
  * 获取客户列表状态(包含滚动加载相关状态)
285
285
  * @returns 客户状态
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "2.2.193",
4
+ "version": "2.2.194",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",