@zauru-sdk/utils 6.19.1 → 6.20.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,6 +1,7 @@
|
|
|
1
1
|
import { handlePossibleAxiosErrors } from "@zauru-sdk/common";
|
|
2
2
|
import { createWebAppTableRegister, getVariablesByName, getWebAppTableRegisters, updateWebAppTableRegister, } from "@zauru-sdk/services";
|
|
3
3
|
const TABLE_VAR = "price_adjustment_rules_web_app_table_id";
|
|
4
|
+
export const PRICE_ADJUSTMENT_REVERSAL_RULES_TABLE_VAR = "price_adjustment_reversal_rules_web_app_table_id";
|
|
4
5
|
const DEFAULT_FILTERS = {
|
|
5
6
|
itemMode: "all",
|
|
6
7
|
itemIds: [],
|
|
@@ -44,6 +45,29 @@ export const updatePriceAdjustmentRule = (headers, session, id, body) => {
|
|
|
44
45
|
return updateWebAppTableRegister(headers, tableId, Number(id), body);
|
|
45
46
|
});
|
|
46
47
|
};
|
|
48
|
+
const getReversalTableId = async (headers, session) => {
|
|
49
|
+
const vars = await getVariablesByName(headers, session, [
|
|
50
|
+
PRICE_ADJUSTMENT_REVERSAL_RULES_TABLE_VAR,
|
|
51
|
+
]);
|
|
52
|
+
return vars[PRICE_ADJUSTMENT_REVERSAL_RULES_TABLE_VAR];
|
|
53
|
+
};
|
|
54
|
+
export const filterActivePriceAdjustmentReversalRules = (rules) => (rules ?? []).filter((rule) => !rule.data?.fechaEliminacion && rule.data?.activa !== false);
|
|
55
|
+
export const getPriceAdjustmentReversalRules = (headers, session) => handlePossibleAxiosErrors(async () => {
|
|
56
|
+
const tableId = await getReversalTableId(headers, session);
|
|
57
|
+
const response = await getWebAppTableRegisters(session, tableId);
|
|
58
|
+
if (response.error) {
|
|
59
|
+
throw new Error(`Ocurrió un error al consultar las reglas de reversión de precio: ${response.userMsg}`);
|
|
60
|
+
}
|
|
61
|
+
return response.data ?? [];
|
|
62
|
+
});
|
|
63
|
+
export const createPriceAdjustmentReversalRule = (headers, session, body) => handlePossibleAxiosErrors(async () => {
|
|
64
|
+
const tableId = await getReversalTableId(headers, session);
|
|
65
|
+
return createWebAppTableRegister(headers, tableId, body);
|
|
66
|
+
});
|
|
67
|
+
export const updatePriceAdjustmentReversalRule = (headers, session, id, body) => handlePossibleAxiosErrors(async () => {
|
|
68
|
+
const tableId = await getReversalTableId(headers, session);
|
|
69
|
+
return updateWebAppTableRegister(headers, tableId, Number(id), body);
|
|
70
|
+
});
|
|
47
71
|
export const normalizeComparableValue = (value) => String(value ?? "").replace(/\s+/g, " ").trim();
|
|
48
72
|
export const formatReceptionTypeValue = (type) => [type?.Nombre, type?.Codigo]
|
|
49
73
|
.map((part) => String(part ?? "").trim())
|
|
@@ -104,11 +128,15 @@ export const applyPriceAdjustmentRules = (basePrice, rules, ctx) => {
|
|
|
104
128
|
let runningTotal = safeBase;
|
|
105
129
|
const steps = [];
|
|
106
130
|
const normalized = rules
|
|
107
|
-
.map((rule) => (
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
131
|
+
.map((rule) => ({
|
|
132
|
+
rule: "data" in rule ? rule.data : rule,
|
|
133
|
+
ruleId: "data" in rule ? rule.id : undefined,
|
|
134
|
+
}))
|
|
135
|
+
.filter((entry) => Boolean(entry.rule));
|
|
136
|
+
const activeRules = normalized
|
|
137
|
+
.filter(({ rule }) => !rule.fechaEliminacion && rule.activa !== false)
|
|
138
|
+
.sort((a, b) => (a.rule.prioridad ?? 0) - (b.rule.prioridad ?? 0));
|
|
139
|
+
for (const { rule, ruleId } of activeRules) {
|
|
112
140
|
if (!priceAdjustmentRuleMatches(rule, ctx)) {
|
|
113
141
|
continue;
|
|
114
142
|
}
|
|
@@ -125,6 +153,7 @@ export const applyPriceAdjustmentRules = (basePrice, rules, ctx) => {
|
|
|
125
153
|
}
|
|
126
154
|
runningTotal = roundMoney(runningTotal);
|
|
127
155
|
steps.push({
|
|
156
|
+
...(ruleId !== undefined ? { ruleId } : {}),
|
|
128
157
|
ruleName: rule.nombre,
|
|
129
158
|
operation: rule.operacion,
|
|
130
159
|
valueType: rule.tipoValor,
|
|
@@ -142,3 +171,78 @@ export const applyPriceAdjustmentRules = (basePrice, rules, ctx) => {
|
|
|
142
171
|
result.description = formatPriceAdjustmentDescription(result);
|
|
143
172
|
return result;
|
|
144
173
|
};
|
|
174
|
+
const sameMoney = (left, right) => Math.abs(roundMoney(left, 2) - roundMoney(right, 2)) < 0.000001;
|
|
175
|
+
export const buildPriceAdjustmentReversalPlan = ({ calculation, currentPrice, reversalRules, history, }) => {
|
|
176
|
+
const base = {
|
|
177
|
+
calculationId: calculation.calculationId,
|
|
178
|
+
detailId: calculation.detailId,
|
|
179
|
+
itemId: calculation.itemId,
|
|
180
|
+
previousPrice: roundMoney(currentPrice, 2),
|
|
181
|
+
finalPrice: roundMoney(currentPrice, 2),
|
|
182
|
+
penaltyAmount: 0,
|
|
183
|
+
matches: [],
|
|
184
|
+
};
|
|
185
|
+
if (!calculation.calculationId || calculation.detailId == null) {
|
|
186
|
+
return {
|
|
187
|
+
...base,
|
|
188
|
+
status: "ineligible",
|
|
189
|
+
reason: "El cálculo no contiene calculationId y detailId.",
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
const activeRules = filterActivePriceAdjustmentReversalRules(reversalRules);
|
|
193
|
+
const reversalBySource = new Map(activeRules.map((entry) => [entry.data.sourceRuleId, entry]));
|
|
194
|
+
const applicable = calculation.steps.flatMap((step) => {
|
|
195
|
+
if (step.ruleId == null ||
|
|
196
|
+
step.operation !== "add" ||
|
|
197
|
+
step.appliedAmount <= 0) {
|
|
198
|
+
return [];
|
|
199
|
+
}
|
|
200
|
+
const reversal = reversalBySource.get(step.ruleId);
|
|
201
|
+
if (!reversal)
|
|
202
|
+
return [];
|
|
203
|
+
return [
|
|
204
|
+
{
|
|
205
|
+
sourceRuleId: step.ruleId,
|
|
206
|
+
sourceRuleName: step.ruleName,
|
|
207
|
+
reversalRuleId: reversal.id,
|
|
208
|
+
reversalRuleName: reversal.data.nombre,
|
|
209
|
+
appliedAmount: roundMoney(step.appliedAmount),
|
|
210
|
+
},
|
|
211
|
+
];
|
|
212
|
+
});
|
|
213
|
+
if (applicable.length === 0) {
|
|
214
|
+
return {
|
|
215
|
+
...base,
|
|
216
|
+
status: "ineligible",
|
|
217
|
+
reason: "Ningún paso del cálculo tiene una regla de reversión activa.",
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
const calculationHistory = (history ?? []).filter((entry) => entry.calculationId === calculation.calculationId &&
|
|
221
|
+
entry.detailId === calculation.detailId);
|
|
222
|
+
const alreadyAppliedSourceIds = new Set(calculationHistory.map((entry) => entry.sourceRuleId));
|
|
223
|
+
const pending = applicable.filter((match) => !alreadyAppliedSourceIds.has(match.sourceRuleId));
|
|
224
|
+
if (pending.length === 0) {
|
|
225
|
+
return {
|
|
226
|
+
...base,
|
|
227
|
+
status: "already_applied",
|
|
228
|
+
reason: "Todas las reglas vinculadas ya fueron penalizadas.",
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
const expectedCurrentPrice = roundMoney(Number(calculation.finalPrice) +
|
|
232
|
+
calculationHistory.reduce((sum, entry) => sum + entry.amount, 0), 2);
|
|
233
|
+
if (!sameMoney(currentPrice, expectedCurrentPrice)) {
|
|
234
|
+
return {
|
|
235
|
+
...base,
|
|
236
|
+
status: "price_changed",
|
|
237
|
+
reason: `El precio actual ${roundMoney(currentPrice, 2)} no coincide con el precio esperado ${expectedCurrentPrice}.`,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
const penaltyAmount = roundMoney(-pending.reduce((sum, match) => sum + match.appliedAmount, 0));
|
|
241
|
+
return {
|
|
242
|
+
...base,
|
|
243
|
+
status: "eligible",
|
|
244
|
+
finalPrice: roundMoney(currentPrice + penaltyAmount, 2),
|
|
245
|
+
penaltyAmount,
|
|
246
|
+
matches: pending,
|
|
247
|
+
};
|
|
248
|
+
};
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import type { Session } from "@remix-run/node";
|
|
2
|
-
import { AxiosUtilsResponse, PriceAdjustmentContext, PriceAdjustmentFilters, PriceAdjustmentResult, PriceAdjustmentRule, WebAppRowGraphQL, WebAppTableUpdateResponse } from "@zauru-sdk/types";
|
|
2
|
+
import { AxiosUtilsResponse, PriceAdjustmentContext, PriceAdjustmentFilters, PriceAdjustmentResult, PriceAdjustmentRule, PriceAdjustmentReversalPlan, PriceAdjustmentReversalRule, PriceAdjustmentStep, CertificationPenaltyHistoryEntry, WebAppRowGraphQL, WebAppTableUpdateResponse } from "@zauru-sdk/types";
|
|
3
|
+
export declare const PRICE_ADJUSTMENT_REVERSAL_RULES_TABLE_VAR = "price_adjustment_reversal_rules_web_app_table_id";
|
|
3
4
|
export declare const defaultPriceAdjustmentFilters: () => PriceAdjustmentFilters;
|
|
4
5
|
export declare const filterActivePriceAdjustmentRules: (rules?: WebAppRowGraphQL<PriceAdjustmentRule>[]) => WebAppRowGraphQL<PriceAdjustmentRule>[];
|
|
5
6
|
export declare const getPriceAdjustmentRules: (headers: any, session: Session) => Promise<AxiosUtilsResponse<WebAppRowGraphQL<PriceAdjustmentRule>[]>>;
|
|
6
7
|
export declare const createPriceAdjustmentRule: (headers: any, session: Session, body: PriceAdjustmentRule) => Promise<AxiosUtilsResponse<WebAppTableUpdateResponse>>;
|
|
7
8
|
export declare const updatePriceAdjustmentRule: (headers: any, session: Session, id: string, body: Partial<PriceAdjustmentRule>) => Promise<AxiosUtilsResponse<WebAppTableUpdateResponse>>;
|
|
9
|
+
export declare const filterActivePriceAdjustmentReversalRules: (rules?: WebAppRowGraphQL<PriceAdjustmentReversalRule>[]) => WebAppRowGraphQL<PriceAdjustmentReversalRule>[];
|
|
10
|
+
export declare const getPriceAdjustmentReversalRules: (headers: any, session: Session) => Promise<AxiosUtilsResponse<WebAppRowGraphQL<PriceAdjustmentReversalRule>[]>>;
|
|
11
|
+
export declare const createPriceAdjustmentReversalRule: (headers: any, session: Session, body: PriceAdjustmentReversalRule) => Promise<AxiosUtilsResponse<WebAppTableUpdateResponse>>;
|
|
12
|
+
export declare const updatePriceAdjustmentReversalRule: (headers: any, session: Session, id: string | number, body: Partial<PriceAdjustmentReversalRule>) => Promise<AxiosUtilsResponse<WebAppTableUpdateResponse>>;
|
|
8
13
|
export declare const normalizeComparableValue: (value: string | number | undefined | null) => string;
|
|
9
14
|
export declare const formatReceptionTypeValue: (type?: {
|
|
10
15
|
Nombre?: string;
|
|
@@ -13,3 +18,15 @@ export declare const formatReceptionTypeValue: (type?: {
|
|
|
13
18
|
export declare const priceAdjustmentRuleMatches: (rule: PriceAdjustmentRule, ctx: PriceAdjustmentContext) => boolean;
|
|
14
19
|
export declare const formatPriceAdjustmentDescription: (result: Pick<PriceAdjustmentResult, "basePrice" | "finalPrice" | "steps">, baseLabel?: string) => string;
|
|
15
20
|
export declare const applyPriceAdjustmentRules: (basePrice: number, rules: Array<PriceAdjustmentRule | WebAppRowGraphQL<PriceAdjustmentRule>>, ctx: PriceAdjustmentContext) => PriceAdjustmentResult;
|
|
21
|
+
export declare const buildPriceAdjustmentReversalPlan: ({ calculation, currentPrice, reversalRules, history, }: {
|
|
22
|
+
calculation: {
|
|
23
|
+
calculationId?: string;
|
|
24
|
+
detailId?: number;
|
|
25
|
+
itemId: number;
|
|
26
|
+
finalPrice: number;
|
|
27
|
+
steps: PriceAdjustmentStep[];
|
|
28
|
+
};
|
|
29
|
+
currentPrice: number;
|
|
30
|
+
reversalRules: WebAppRowGraphQL<PriceAdjustmentReversalRule>[];
|
|
31
|
+
history?: CertificationPenaltyHistoryEntry[];
|
|
32
|
+
}) => PriceAdjustmentReversalPlan;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zauru-sdk/utils",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.20.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",
|
|
@@ -71,12 +71,12 @@
|
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"@aws-sdk/client-cloudwatch-logs": "^3.1123.0",
|
|
73
73
|
"@remix-run/node": "^2.8.1",
|
|
74
|
-
"@zauru-sdk/common": "^6.8.
|
|
74
|
+
"@zauru-sdk/common": "^6.8.3",
|
|
75
75
|
"@zauru-sdk/config": "^6.0.0",
|
|
76
76
|
"@zauru-sdk/graphql": "^6.8.0",
|
|
77
|
-
"@zauru-sdk/services": "^6.11.
|
|
78
|
-
"@zauru-sdk/types": "^6.
|
|
77
|
+
"@zauru-sdk/services": "^6.11.6",
|
|
78
|
+
"@zauru-sdk/types": "^6.21.0",
|
|
79
79
|
"moment": "^2.30.1"
|
|
80
80
|
},
|
|
81
|
-
"gitHead": "
|
|
81
|
+
"gitHead": "7d373b9f5c25ab0198e72590c661bc9eb17cf80f"
|
|
82
82
|
}
|