@open-mercato/core 0.6.6-develop.6525.1.e9a4b56963 → 0.6.6-develop.6526.1.6df9b3dd84

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.
@@ -92,6 +92,7 @@ import {
92
92
  loadPaymentSnapshot,
93
93
  restorePaymentSnapshot
94
94
  } from "./payments.js";
95
+ import { loadShippedQuantityByLine } from "../lib/shipments/snapshots.js";
95
96
  import { resolveDictionaryEntryValue } from "../lib/dictionaries.js";
96
97
  import { resolveStatusEntryIdByValue } from "../lib/statusHelpers.js";
97
98
  import { loadSalesSettings } from "./settings.js";
@@ -4874,6 +4875,48 @@ const quoteAdjustmentDeleteSchema = z.object({
4874
4875
  id: z.string().uuid(),
4875
4876
  quoteId: z.string().uuid()
4876
4877
  });
4878
+ const SHIPPED_QUANTITY_TOLERANCE = 1e-6;
4879
+ const hasNumericChange = (next, previous) => {
4880
+ if (next === void 0 || next === null) return false;
4881
+ if (previous === void 0 || previous === null) return true;
4882
+ return Math.abs(next - previous) > SHIPPED_QUANTITY_TOLERANCE;
4883
+ };
4884
+ const hasUnitChange = (next, previous) => {
4885
+ if (next === void 0 || next === null) return false;
4886
+ const normalizedPrevious = (previous ?? "").trim().toLowerCase();
4887
+ if (!normalizedPrevious) return false;
4888
+ return next.trim().toLowerCase() !== normalizedPrevious;
4889
+ };
4890
+ async function assertShippedOrderLineEditable(em, order, existingSnapshot, parsed) {
4891
+ const lineId = existingSnapshot?.id;
4892
+ if (!existingSnapshot || !lineId) return;
4893
+ const shippedByLine = await loadShippedQuantityByLine(em, order.id, {
4894
+ tenantId: order.tenantId,
4895
+ organizationId: order.organizationId
4896
+ });
4897
+ const shippedQuantity = shippedByLine.get(lineId) ?? 0;
4898
+ if (shippedQuantity <= 0) return;
4899
+ const { translate } = await resolveTranslations();
4900
+ const nextQuantity = parsed.quantity ?? existingSnapshot.quantity;
4901
+ if (nextQuantity < shippedQuantity - SHIPPED_QUANTITY_TOLERANCE) {
4902
+ throw new CrudHttpError(409, {
4903
+ error: translate(
4904
+ "sales.documents.items.errorQuantityBelowShipped",
4905
+ "You cannot lower the quantity below the {{shipped}} already shipped.",
4906
+ { shipped: shippedQuantity }
4907
+ )
4908
+ });
4909
+ }
4910
+ const pricingChanged = hasNumericChange(parsed.unitPriceNet, existingSnapshot.unitPriceNet) || hasNumericChange(parsed.unitPriceGross, existingSnapshot.unitPriceGross) || hasNumericChange(parsed.taxRate, existingSnapshot.taxRate) || hasUnitChange(parsed.quantityUnit, existingSnapshot.quantityUnit);
4911
+ if (pricingChanged) {
4912
+ throw new CrudHttpError(409, {
4913
+ error: translate(
4914
+ "sales.documents.items.errorPriceShipped",
4915
+ "You cannot change the price or unit of a line that has shipped items."
4916
+ )
4917
+ });
4918
+ }
4919
+ }
4877
4920
  const orderLineUpsertCommand = {
4878
4921
  id: "sales.orders.lines.upsert",
4879
4922
  async prepare(input, ctx) {
@@ -4912,6 +4955,7 @@ const orderLineUpsertCommand = {
4912
4955
  ]);
4913
4956
  const lineSnapshots = existingLines.map(mapOrderLineEntityToSnapshot);
4914
4957
  const existingSnapshot = parsed.id ? lineSnapshots.find((line) => line.id === parsed.id) ?? null : null;
4958
+ await assertShippedOrderLineEditable(em, order, existingSnapshot, parsed);
4915
4959
  const priceMode = parsed.priceMode === "gross" ? "gross" : parsed.priceMode === "net" ? "net" : null;
4916
4960
  let unitPriceNet = parsed.unitPriceNet ?? existingSnapshot?.unitPriceNet ?? null;
4917
4961
  let unitPriceGross = parsed.unitPriceGross ?? existingSnapshot?.unitPriceGross ?? null;