@zauru-sdk/utils 6.10.0 → 6.11.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.
@@ -1,5 +1,6 @@
1
- import { CURRENCY_PREFIX, calculatePurchaseOrderFinancials, getNewDateByFormat, getStringFullDate, getZauruDateByText, handlePossibleAxiosErrors, setRejectionPercentage, } from "@zauru-sdk/common";
1
+ import { CURRENCY_PREFIX, applyRejectionPercentageRulesToFinancials, calculatePurchaseOrderFinancials, getNewDateByFormat, getStringFullDate, getZauruDateByText, handlePossibleAxiosErrors, setRejectionPercentage, } from "@zauru-sdk/common";
2
2
  import { commitSession, createNewPurchaseOrder, deleteDelivery, deletePurchaseOrder, deleteReception, getLotesWithPurchaseFormated, getPurchase, getPurchaseOrder, getPurchasesListDataTables, getVariablesByName, inactivarLote, updateReceivedPurchaseOrder, } from "@zauru-sdk/services";
3
+ import { getActiveRejectionPercentageAdjustmentRules } from "./rejectionPercentageAdjustmentRules.utils.js";
3
4
  /**
4
5
  * Obtiene el listado de ordenes de compra, formateado especialmente para armar la tabla de edición de porcentajes y tolerancia
5
6
  * @param headers
@@ -188,6 +189,23 @@ const extractPurchaseOrderFinancialDetails = (purchase) => {
188
189
  }
189
190
  return [];
190
191
  };
192
+ const extractPurchaseOrderItemIds = (purchase) => {
193
+ if (purchase == null || typeof purchase !== "object")
194
+ return [];
195
+ const record = purchase;
196
+ const raw = record.purchase_order_details ??
197
+ record.purchase_order_details_attributes ??
198
+ record.details ??
199
+ [];
200
+ const list = Array.isArray(raw)
201
+ ? raw
202
+ : raw && typeof raw === "object"
203
+ ? Object.values(raw)
204
+ : [];
205
+ return list
206
+ .map((detail) => Number(detail.item_id))
207
+ .filter((itemId) => Number.isFinite(itemId));
208
+ };
191
209
  /**
192
210
  * updateOchAndDis
193
211
  * Updates rejectionPercentage in purchase_order.memo and the monetary
@@ -199,8 +217,10 @@ export const updateOchAndDis = async (headers, data, purchase_id, session) => {
199
217
  const rejectionPercentage = Number(data?.rejectionPercentage ?? data?.discount ?? 0);
200
218
  let currentMemo = data.memo;
201
219
  let details = [];
220
+ let loadedPurchase;
202
221
  const restPurchaseResponse = await getPurchase(headers, purchase_id);
203
222
  if (!restPurchaseResponse.error && restPurchaseResponse.data) {
223
+ loadedPurchase = restPurchaseResponse.data;
204
224
  if (currentMemo === undefined) {
205
225
  currentMemo = restPurchaseResponse.data.memo;
206
226
  }
@@ -209,7 +229,7 @@ export const updateOchAndDis = async (headers, data, purchase_id, session) => {
209
229
  if ((currentMemo === undefined || details.length === 0) && session) {
210
230
  const purchaseOrderResponse = await getPurchaseOrder(session, purchase_id, {
211
231
  withLotStocksToMyAgency: false,
212
- withPayee: false,
232
+ withPayee: true,
213
233
  withReceptions: false,
214
234
  });
215
235
  if (purchaseOrderResponse.error || !purchaseOrderResponse.data) {
@@ -222,6 +242,9 @@ export const updateOchAndDis = async (headers, data, purchase_id, session) => {
222
242
  if (details.length === 0) {
223
243
  details = extractPurchaseOrderFinancialDetails(purchaseOrderResponse.data);
224
244
  }
245
+ if (loadedPurchase == null) {
246
+ loadedPurchase = purchaseOrderResponse.data;
247
+ }
225
248
  }
226
249
  if (currentMemo === undefined) {
227
250
  throw new Error("memo or session is required to update rejectionPercentage");
@@ -230,14 +253,37 @@ export const updateOchAndDis = async (headers, data, purchase_id, session) => {
230
253
  throw new Error(restPurchaseResponse.userMsg ||
231
254
  "No se pudieron obtener los detalles de la orden de compra para calcular el descuento");
232
255
  }
233
- const { discount } = calculatePurchaseOrderFinancials({
234
- details,
235
- rejectionPercentage,
236
- });
256
+ const rules = await getActiveRejectionPercentageAdjustmentRules(headers, session);
257
+ const purchaseRecord = loadedPurchase;
258
+ const payee = purchaseRecord?.payee;
259
+ const itemIds = extractPurchaseOrderItemIds(loadedPurchase);
260
+ const tipo = purchaseRecord?.reference;
261
+ const adjusted = rules.length > 0
262
+ ? applyRejectionPercentageRulesToFinancials({
263
+ memo: currentMemo,
264
+ originPercentage: rejectionPercentage,
265
+ details,
266
+ rules,
267
+ ctx: {
268
+ itemIds,
269
+ tipo,
270
+ providerCategoryId: payee?.payee_category_id ??
271
+ purchaseRecord
272
+ ?.payee_category_id,
273
+ },
274
+ })
275
+ : {
276
+ memo: setRejectionPercentage(currentMemo, rejectionPercentage),
277
+ discount: calculatePurchaseOrderFinancials({
278
+ details,
279
+ rejectionPercentage,
280
+ }).discount,
281
+ finalPercentage: rejectionPercentage,
282
+ };
237
283
  const body = {
238
284
  purchase_order: {
239
- memo: setRejectionPercentage(currentMemo, rejectionPercentage),
240
- discount,
285
+ memo: adjusted.memo,
286
+ discount: adjusted.discount,
241
287
  },
242
288
  };
243
289
  if (data.other_charges !== undefined && data.other_charges !== null) {
@@ -1,17 +1,12 @@
1
- import { getRejectionPercentage, handlePossibleAxiosErrors, parseJsonMemo, } from "@zauru-sdk/common";
2
- import { createWebAppTableRegister, getVariablesByName, getWebAppTableRegisters, updateWebAppTableRegister, } from "@zauru-sdk/services";
3
- import { defaultPriceAdjustmentFilters, priceAdjustmentRuleMatches, } from "./priceAdjustmentRules.utils.js";
4
- const TABLE_VAR = "rejection_percentage_adjustment_rules_web_app_table_id";
5
- const asPriceAdjustmentRule = (rule) => ({
6
- ...rule,
7
- tipoValor: "percentage",
8
- });
9
- export const filterActiveRejectionPercentageAdjustmentRules = (rules) => (rules ?? [])
10
- .filter((rule) => !rule.data?.fechaEliminacion && rule.data?.activa !== false)
11
- .sort((a, b) => (a.data?.prioridad ?? 0) - (b.data?.prioridad ?? 0) || a.id - b.id);
1
+ import { handlePossibleAxiosErrors } from "@zauru-sdk/common";
2
+ import { createWebAppTableRegister, getRejectionPercentageAdjustmentRulesByHeaders, getVariablesByName, getWebAppTableRegisters, updateWebAppTableRegister, } from "@zauru-sdk/services";
3
+ export { applyRejectionPercentageAdjustmentRules, applyRejectionPercentageRulesToFinancials, filterActiveRejectionPercentageAdjustmentRules, formatRejectionPercentageAdjustmentDescription, rejectionPercentageAdjustmentRuleMatches, resolveRejectionPercentageBase, resolveRejectionPercentageOrigin, REJECTION_PERCENTAGE_ADJUSTMENT_RULES_TABLE_VAR, } from "@zauru-sdk/common";
4
+ import { filterActiveRejectionPercentageAdjustmentRules, REJECTION_PERCENTAGE_ADJUSTMENT_RULES_TABLE_VAR, } from "@zauru-sdk/common";
12
5
  const getTableId = async (headers, session) => {
13
- const vars = await getVariablesByName(headers, session, [TABLE_VAR]);
14
- return vars[TABLE_VAR];
6
+ const vars = await getVariablesByName(headers, session, [
7
+ REJECTION_PERCENTAGE_ADJUSTMENT_RULES_TABLE_VAR,
8
+ ]);
9
+ return vars[REJECTION_PERCENTAGE_ADJUSTMENT_RULES_TABLE_VAR];
15
10
  };
16
11
  export const getRejectionPercentageAdjustmentRules = (headers, session) => {
17
12
  return handlePossibleAxiosErrors(async () => {
@@ -23,6 +18,25 @@ export const getRejectionPercentageAdjustmentRules = (headers, session) => {
23
18
  return response.data ?? [];
24
19
  });
25
20
  };
21
+ export const getActiveRejectionPercentageAdjustmentRules = async (headers, session) => {
22
+ try {
23
+ if (session) {
24
+ const response = await getRejectionPercentageAdjustmentRules(headers, session);
25
+ if (response.error) {
26
+ return [];
27
+ }
28
+ return filterActiveRejectionPercentageAdjustmentRules(response.data);
29
+ }
30
+ const response = await getRejectionPercentageAdjustmentRulesByHeaders(headers);
31
+ if (response.error) {
32
+ return [];
33
+ }
34
+ return filterActiveRejectionPercentageAdjustmentRules(response.data);
35
+ }
36
+ catch {
37
+ return [];
38
+ }
39
+ };
26
40
  export const createRejectionPercentageAdjustmentRule = (headers, session, body) => {
27
41
  return handlePossibleAxiosErrors(async () => {
28
42
  const tableId = await getTableId(headers, session);
@@ -35,90 +49,3 @@ export const updateRejectionPercentageAdjustmentRule = (headers, session, id, bo
35
49
  return updateWebAppTableRegister(headers, tableId, Number(id), body);
36
50
  });
37
51
  };
38
- export const rejectionPercentageAdjustmentRuleMatches = (rule, ctx) => {
39
- const filtros = rule.filtros ?? defaultPriceAdjustmentFilters();
40
- const priceRule = asPriceAdjustmentRule(rule);
41
- const itemIds = ctx.itemIds ?? [];
42
- if (filtros.itemMode === "all") {
43
- return priceAdjustmentRuleMatches(priceRule, {
44
- itemId: 0,
45
- tipo: ctx.tipo,
46
- providerCategoryId: ctx.providerCategoryId,
47
- });
48
- }
49
- if (itemIds.length === 0) {
50
- return false;
51
- }
52
- return itemIds.some((itemId) => priceAdjustmentRuleMatches(priceRule, {
53
- itemId,
54
- tipo: ctx.tipo,
55
- providerCategoryId: ctx.providerCategoryId,
56
- }));
57
- };
58
- const roundPercentage = (value, digits = 4) => {
59
- const factor = 10 ** digits;
60
- return Math.round((value + Number.EPSILON) * factor) / factor;
61
- };
62
- const clampPercentage = (value) => Math.min(100, Math.max(0, value));
63
- const formatPercentage = (value) => Number.isInteger(value) ? String(value) : String(roundPercentage(value));
64
- const formatFinalPercentage = (value) => roundPercentage(value, 2).toFixed(2);
65
- const formatRuleEffect = (step) => {
66
- const sign = step.operation === "subtract" ? "-" : "+";
67
- return `${sign} ${formatPercentage(step.value)}% (${step.ruleName})`;
68
- };
69
- export const formatRejectionPercentageAdjustmentDescription = (result, baseLabel = "origen") => {
70
- const base = `${formatPercentage(result.basePercentage)} (${baseLabel})`;
71
- if (result.steps.length === 0) {
72
- return base;
73
- }
74
- return `${base} ${result.steps.map(formatRuleEffect).join(" ")} = ${formatFinalPercentage(result.finalPercentage)}`;
75
- };
76
- export const resolveRejectionPercentageBase = (memo) => {
77
- const parsed = parseJsonMemo(memo);
78
- const current = clampPercentage(getRejectionPercentage(parsed));
79
- const calc = parsed.rejectionCalculations;
80
- if (calc &&
81
- Number.isFinite(Number(calc.finalPercentage)) &&
82
- roundPercentage(current, 2) ===
83
- roundPercentage(Number(calc.finalPercentage), 2)) {
84
- const base = Number(calc.basePercentage);
85
- return Number.isFinite(base) ? clampPercentage(base) : current;
86
- }
87
- return current;
88
- };
89
- export const applyRejectionPercentageAdjustmentRules = (basePercentage, rules, ctx) => {
90
- const start = Number(basePercentage);
91
- const safeBase = Number.isFinite(start) ? clampPercentage(start) : 0;
92
- let runningTotal = safeBase;
93
- const steps = [];
94
- const normalized = rules
95
- .map((rule) => ("data" in rule ? rule.data : rule))
96
- .filter((rule) => Boolean(rule))
97
- .filter((rule) => !rule.fechaEliminacion && rule.activa !== false)
98
- .sort((a, b) => (a.prioridad ?? 0) - (b.prioridad ?? 0));
99
- for (const rule of normalized) {
100
- if (!rejectionPercentageAdjustmentRuleMatches(rule, ctx)) {
101
- continue;
102
- }
103
- const value = Number(rule.valor) || 0;
104
- const previous = runningTotal;
105
- runningTotal =
106
- rule.operacion === "subtract" ? previous - value : previous + value;
107
- runningTotal = clampPercentage(roundPercentage(runningTotal));
108
- steps.push({
109
- ruleName: rule.nombre,
110
- operation: rule.operacion,
111
- value,
112
- appliedAmount: roundPercentage(runningTotal - previous),
113
- runningTotal,
114
- });
115
- }
116
- const result = {
117
- basePercentage: roundPercentage(safeBase),
118
- finalPercentage: roundPercentage(runningTotal, 2),
119
- description: "",
120
- steps,
121
- };
122
- result.description = formatRejectionPercentageAdjustmentDescription(result);
123
- return result;
124
- };
@@ -1,10 +1,7 @@
1
1
  import type { Session } from "@remix-run/node";
2
- import { AxiosUtilsResponse, RejectionPercentageAdjustmentContext, RejectionPercentageAdjustmentResult, RejectionPercentageAdjustmentRule, WebAppRowGraphQL, WebAppTableUpdateResponse } from "@zauru-sdk/types";
3
- export declare const filterActiveRejectionPercentageAdjustmentRules: (rules?: WebAppRowGraphQL<RejectionPercentageAdjustmentRule>[]) => WebAppRowGraphQL<RejectionPercentageAdjustmentRule>[];
2
+ import { AxiosUtilsResponse, RejectionPercentageAdjustmentRule, WebAppRowGraphQL, WebAppTableUpdateResponse } from "@zauru-sdk/types";
3
+ export { applyRejectionPercentageAdjustmentRules, applyRejectionPercentageRulesToFinancials, filterActiveRejectionPercentageAdjustmentRules, formatRejectionPercentageAdjustmentDescription, rejectionPercentageAdjustmentRuleMatches, resolveRejectionPercentageBase, resolveRejectionPercentageOrigin, REJECTION_PERCENTAGE_ADJUSTMENT_RULES_TABLE_VAR, } from "@zauru-sdk/common";
4
4
  export declare const getRejectionPercentageAdjustmentRules: (headers: any, session: Session) => Promise<AxiosUtilsResponse<WebAppRowGraphQL<RejectionPercentageAdjustmentRule>[]>>;
5
+ export declare const getActiveRejectionPercentageAdjustmentRules: (headers: any, session?: Session) => Promise<WebAppRowGraphQL<RejectionPercentageAdjustmentRule>[]>;
5
6
  export declare const createRejectionPercentageAdjustmentRule: (headers: any, session: Session, body: RejectionPercentageAdjustmentRule) => Promise<AxiosUtilsResponse<WebAppTableUpdateResponse>>;
6
7
  export declare const updateRejectionPercentageAdjustmentRule: (headers: any, session: Session, id: string, body: Partial<RejectionPercentageAdjustmentRule>) => Promise<AxiosUtilsResponse<WebAppTableUpdateResponse>>;
7
- export declare const rejectionPercentageAdjustmentRuleMatches: (rule: RejectionPercentageAdjustmentRule, ctx: RejectionPercentageAdjustmentContext) => boolean;
8
- export declare const formatRejectionPercentageAdjustmentDescription: (result: Pick<RejectionPercentageAdjustmentResult, "basePercentage" | "finalPercentage" | "steps">, baseLabel?: string) => string;
9
- export declare const resolveRejectionPercentageBase: (memo?: string | object) => number;
10
- export declare const applyRejectionPercentageAdjustmentRules: (basePercentage: number, rules: Array<RejectionPercentageAdjustmentRule | WebAppRowGraphQL<RejectionPercentageAdjustmentRule>>, ctx: RejectionPercentageAdjustmentContext) => RejectionPercentageAdjustmentResult;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zauru-sdk/utils",
3
- "version": "6.10.0",
3
+ "version": "6.11.0",
4
4
  "description": "Utilidades, parseo de request y demás para desarrollo de webapps de Zauru",
5
5
  "main": "./dist/esm/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -25,12 +25,12 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@remix-run/node": "^2.8.1",
28
- "@zauru-sdk/common": "^6.4.1",
28
+ "@zauru-sdk/common": "^6.5.0",
29
29
  "@zauru-sdk/config": "^6.0.0",
30
30
  "@zauru-sdk/graphql": "^6.7.0",
31
- "@zauru-sdk/services": "^6.9.1",
31
+ "@zauru-sdk/services": "^6.10.0",
32
32
  "@zauru-sdk/types": "^6.15.0",
33
33
  "moment": "^2.30.1"
34
34
  },
35
- "gitHead": "ab1ff7197a4688c0e887942b4e7a1f6b729a510e"
35
+ "gitHead": "2dceb781cae3f4c45ceecb915977c6d142bca6b9"
36
36
  }