@monkeyplus/payscope 1.0.1 → 1.0.3
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/dist/_chunks/database.mjs +1 -1
- package/dist/_chunks/db.d.mts +9 -5
- package/dist/_chunks/taxes.mjs +214 -0
- package/dist/server/router.d.mts +8 -5
- package/dist/server/router.mjs +19 -218
- package/dist/server/taxes.d.mts +131 -0
- package/dist/server/taxes.mjs +2 -0
- package/package.json +1 -1
- package/storefront/cart/ShoppinCart.vue +3 -12
- package/storefront/cart/ShoppinCartItem.vue +13 -11
- package/storefront/checkout/App.vue +1 -1
- package/storefront/checkout/AppCart.vue +31 -24
- package/storefront/checkout/AppCartTotals.vue +19 -15
- package/storefront/checkout/pages/Auth.vue +8 -0
- package/storefront/checkout/pages/Basic/BasicBillingForm.vue +95 -0
- package/storefront/checkout/pages/Basic/BasicCustomerForm.vue +188 -0
- package/storefront/checkout/pages/Basic/BasicShippingForm.vue +93 -0
- package/storefront/checkout/pages/Basic/BasicSummary.vue +63 -0
- package/storefront/checkout/pages/Basic.vue +82 -0
- package/storefront/checkout/pages/Pay/Pay.vue +3 -50
- package/storefront/checkout/pages/Pay/PayForms.vue +55 -0
- package/storefront/checkout/pages/Payment/Payment.vue +1 -1
- package/storefront/checkout/router.ts +49 -39
- package/storefront/product/AddProduct.vue +87 -103
- package/storefront/product/composables.ts +0 -0
- package/storefront/stores.ts +27 -5
|
@@ -84,7 +84,7 @@ const customBigSerial = customType({
|
|
|
84
84
|
codec: "bigint:string"
|
|
85
85
|
});
|
|
86
86
|
const checkouts = buys.table("checkouts", {
|
|
87
|
-
id:
|
|
87
|
+
id: customBigSerial().primaryKey().notNull(),
|
|
88
88
|
total: p.numeric({ mode: "number" }).default(0).notNull(),
|
|
89
89
|
base: p.numeric({ mode: "number" }),
|
|
90
90
|
items: p.jsonb().notNull().$type(),
|
package/dist/_chunks/db.d.mts
CHANGED
|
@@ -971,14 +971,18 @@ declare const checkouts: p.PgTableWithColumns<{
|
|
|
971
971
|
name: "checkouts";
|
|
972
972
|
schema: "buys";
|
|
973
973
|
columns: {
|
|
974
|
-
id: p.PgBuildColumn<"checkouts", p.SetNotNull<p.SetIsPrimaryKey<p.
|
|
974
|
+
id: p.PgBuildColumn<"checkouts", p.SetNotNull<p.SetIsPrimaryKey<p.PgCustomColumnBuilder<{
|
|
975
|
+
dataType: "custom";
|
|
976
|
+
data: string;
|
|
977
|
+
driverParam: unknown;
|
|
978
|
+
}>>>, {
|
|
975
979
|
name: string;
|
|
976
980
|
tableName: "checkouts";
|
|
977
|
-
dataType: "
|
|
978
|
-
data:
|
|
979
|
-
driverParam:
|
|
981
|
+
dataType: "custom";
|
|
982
|
+
data: string;
|
|
983
|
+
driverParam: unknown;
|
|
980
984
|
notNull: true;
|
|
981
|
-
hasDefault:
|
|
985
|
+
hasDefault: false;
|
|
982
986
|
isPrimaryKey: false;
|
|
983
987
|
isAutoincrement: false;
|
|
984
988
|
hasRuntimeDefault: false;
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
function roundNum(v, r = 2) {
|
|
2
|
+
return Number(Number(v).toFixed(r));
|
|
3
|
+
}
|
|
4
|
+
function calcPercentaje(value, percentaje, hasInclude) {
|
|
5
|
+
const val = +value;
|
|
6
|
+
const per = +percentaje;
|
|
7
|
+
if (hasInclude) return roundNum(val * per / (100 + per));
|
|
8
|
+
else return roundNum(val / 100 * per);
|
|
9
|
+
}
|
|
10
|
+
function calcDiscount(amount, discount) {
|
|
11
|
+
if ("percent" in discount) return {
|
|
12
|
+
amount: calcPercentaje(amount, discount.percent),
|
|
13
|
+
percent: +discount.percent
|
|
14
|
+
};
|
|
15
|
+
else return { amount: +discount.amount };
|
|
16
|
+
}
|
|
17
|
+
const sum = (arr) => arr.reduce((a, b) => a + b, 0);
|
|
18
|
+
const flatten = (arr) => arr.reduce((a, b) => a.concat(b), []);
|
|
19
|
+
function groupBy(fn, arr) {
|
|
20
|
+
return arr.reduce((acc, value) => {
|
|
21
|
+
const key = fn(value);
|
|
22
|
+
if (!acc[key]) acc[key] = [];
|
|
23
|
+
acc[key].push(value);
|
|
24
|
+
return acc;
|
|
25
|
+
}, {});
|
|
26
|
+
}
|
|
27
|
+
function calcAmount(_itemDiscount, _parentDiscount, taxIncluded) {
|
|
28
|
+
return (price) => {
|
|
29
|
+
if (!taxIncluded) {
|
|
30
|
+
const itemDiscount = calcDiscount(price, _itemDiscount);
|
|
31
|
+
const parentDiscount = calcDiscount(price - itemDiscount.amount, _parentDiscount);
|
|
32
|
+
const unitBase = price - (itemDiscount.amount + parentDiscount.amount);
|
|
33
|
+
return {
|
|
34
|
+
price,
|
|
35
|
+
discounts: {
|
|
36
|
+
itemDiscount,
|
|
37
|
+
parentDiscount
|
|
38
|
+
},
|
|
39
|
+
unitAmount: unitBase,
|
|
40
|
+
unitBase
|
|
41
|
+
};
|
|
42
|
+
} else {
|
|
43
|
+
const parentDiscount = calcDiscount(price, _parentDiscount);
|
|
44
|
+
const itemDiscount = calcDiscount(price - parentDiscount.amount, _itemDiscount);
|
|
45
|
+
return {
|
|
46
|
+
price,
|
|
47
|
+
discounts: {
|
|
48
|
+
itemDiscount,
|
|
49
|
+
parentDiscount
|
|
50
|
+
},
|
|
51
|
+
unitAmount: price - (itemDiscount.amount + parentDiscount.amount),
|
|
52
|
+
unitBase: 0
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function calcSingleItem(parentDiscount = { amount: 0 }) {
|
|
58
|
+
return (item) => {
|
|
59
|
+
const quantity = +item.quantity;
|
|
60
|
+
const taxes = item.taxes || [];
|
|
61
|
+
const calcRawTax = (base, rate) => base * rate / 100;
|
|
62
|
+
const calculateTaxesForward = (originalBase, finalBase, raw = false) => {
|
|
63
|
+
const firstTaxes = [];
|
|
64
|
+
const latestTaxes = [];
|
|
65
|
+
let totalFirstTaxesAmount = 0;
|
|
66
|
+
let totalLatestTaxesAmount = 0;
|
|
67
|
+
for (const t of taxes) if (t.beforeTaxes) {
|
|
68
|
+
const baseToUse = t.excludeDiscount ? originalBase : finalBase;
|
|
69
|
+
const amount = raw ? calcRawTax(baseToUse, +t.value) : calcPercentaje(baseToUse, t.value, false);
|
|
70
|
+
firstTaxes.push({
|
|
71
|
+
...t,
|
|
72
|
+
base: baseToUse,
|
|
73
|
+
amount,
|
|
74
|
+
totalBase: baseToUse * quantity,
|
|
75
|
+
totalAmount: amount * quantity
|
|
76
|
+
});
|
|
77
|
+
totalFirstTaxesAmount += amount;
|
|
78
|
+
}
|
|
79
|
+
for (const t of taxes) if (!t.beforeTaxes) {
|
|
80
|
+
const baseToUse = (t.excludeDiscount ? originalBase : finalBase) + totalFirstTaxesAmount;
|
|
81
|
+
const amount = raw ? calcRawTax(baseToUse, +t.value) : calcPercentaje(baseToUse, t.value, false);
|
|
82
|
+
latestTaxes.push({
|
|
83
|
+
...t,
|
|
84
|
+
base: baseToUse,
|
|
85
|
+
amount,
|
|
86
|
+
totalBase: baseToUse * quantity,
|
|
87
|
+
totalAmount: amount * quantity
|
|
88
|
+
});
|
|
89
|
+
totalLatestTaxesAmount += amount;
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
firstTaxes,
|
|
93
|
+
latestTaxes,
|
|
94
|
+
totalTaxes: totalFirstTaxesAmount + totalLatestTaxesAmount,
|
|
95
|
+
totalPrice: finalBase + totalFirstTaxesAmount + totalLatestTaxesAmount
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
if (!item.taxIncluded) {
|
|
99
|
+
const amounts = calcAmount(item.discount, parentDiscount, false)(+item.price);
|
|
100
|
+
const originalBase = amounts.price;
|
|
101
|
+
const finalBase = amounts.unitBase;
|
|
102
|
+
const result = calculateTaxesForward(originalBase, finalBase, false);
|
|
103
|
+
amounts.total = amounts.unitBase * quantity + result.totalTaxes * quantity;
|
|
104
|
+
return {
|
|
105
|
+
id: item.id,
|
|
106
|
+
title: item.title,
|
|
107
|
+
taxIncluded: item.taxIncluded,
|
|
108
|
+
item: amounts,
|
|
109
|
+
taxes: [...result.firstTaxes, ...result.latestTaxes],
|
|
110
|
+
quantity,
|
|
111
|
+
product: item.product,
|
|
112
|
+
variant: item.variant,
|
|
113
|
+
discountAllocations: item.discountAllocations
|
|
114
|
+
};
|
|
115
|
+
} else {
|
|
116
|
+
const amounts = calcAmount(item.discount, parentDiscount, true)(+item.price);
|
|
117
|
+
const originalPriceWithTaxes = amounts.price;
|
|
118
|
+
const finalPriceWithTaxes = amounts.unitAmount;
|
|
119
|
+
const T1_1 = calculateTaxesForward(1, 1, true).totalPrice;
|
|
120
|
+
const originalBaseRaw = originalPriceWithTaxes / (T1_1 === 0 ? 1 : T1_1);
|
|
121
|
+
const T0 = calculateTaxesForward(originalBaseRaw, 0, true).totalPrice;
|
|
122
|
+
const M = calculateTaxesForward(originalBaseRaw, 1, true).totalPrice - T0;
|
|
123
|
+
const result = calculateTaxesForward(originalBaseRaw, M === 0 ? finalPriceWithTaxes - T0 : (finalPriceWithTaxes - T0) / M, false);
|
|
124
|
+
const adjustedFinalBase = finalPriceWithTaxes - result.totalTaxes;
|
|
125
|
+
amounts.unitBase = adjustedFinalBase;
|
|
126
|
+
amounts.total = finalPriceWithTaxes * quantity;
|
|
127
|
+
for (const t of result.firstTaxes) if (!t.excludeDiscount) {
|
|
128
|
+
t.base = adjustedFinalBase;
|
|
129
|
+
t.totalBase = adjustedFinalBase * quantity;
|
|
130
|
+
}
|
|
131
|
+
const firstTotal = sum(result.firstTaxes.map((t) => t.amount));
|
|
132
|
+
for (const t of result.latestTaxes) if (!t.excludeDiscount) {
|
|
133
|
+
t.base = adjustedFinalBase + firstTotal;
|
|
134
|
+
t.totalBase = t.base * quantity;
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
id: item.id,
|
|
138
|
+
title: item.title,
|
|
139
|
+
taxIncluded: item.taxIncluded,
|
|
140
|
+
item: amounts,
|
|
141
|
+
taxes: [...result.firstTaxes, ...result.latestTaxes],
|
|
142
|
+
quantity,
|
|
143
|
+
product: item.product,
|
|
144
|
+
variant: item.variant,
|
|
145
|
+
discountAllocations: item.discountAllocations
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function calcItems(items, parentDiscount = { amount: 0 }) {
|
|
151
|
+
return items.map(calcSingleItem(parentDiscount));
|
|
152
|
+
}
|
|
153
|
+
function buildInvoice(items) {
|
|
154
|
+
const base = sum(items.map((item) => item.item.unitBase * item.quantity));
|
|
155
|
+
const lineItemsSubtotalPrice = sum(items.filter((item) => !["_envio"].includes(item.id)).map((item) => item.item.price * item.quantity));
|
|
156
|
+
const shipping = sum(items.filter((item) => ["_envio"].includes(item.id)).map((item) => item.item.price * item.quantity));
|
|
157
|
+
const totalDiscount = sum(items.map((item) => {
|
|
158
|
+
const discounts = item.item.discounts;
|
|
159
|
+
if (!discounts) return 0;
|
|
160
|
+
return ((discounts.itemDiscount?.amount || 0) + (discounts.parentDiscount?.amount || 0)) * item.quantity;
|
|
161
|
+
}));
|
|
162
|
+
const imp = groupBy((tax) => {
|
|
163
|
+
return `${tax.type.code}_${tax.code}`;
|
|
164
|
+
}, flatten(items.map((item) => item.taxes)));
|
|
165
|
+
const _taxes = Object.values(imp).map((taxes) => {
|
|
166
|
+
let taxBase = 0;
|
|
167
|
+
let value = 0;
|
|
168
|
+
const type = taxes[0].type.code;
|
|
169
|
+
const title = taxes[0].type.name;
|
|
170
|
+
const code = taxes[0].code;
|
|
171
|
+
const rate = +taxes[0].value;
|
|
172
|
+
for (const iterator of taxes) {
|
|
173
|
+
taxBase += +iterator.totalBase;
|
|
174
|
+
value += +iterator.totalAmount;
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
type,
|
|
178
|
+
code,
|
|
179
|
+
base: taxBase,
|
|
180
|
+
value,
|
|
181
|
+
rate,
|
|
182
|
+
title
|
|
183
|
+
};
|
|
184
|
+
});
|
|
185
|
+
return {
|
|
186
|
+
total: base + sum(_taxes.map((tax) => tax.value)),
|
|
187
|
+
totalTax: sum(_taxes.map((t) => t.value)),
|
|
188
|
+
totalDiscount,
|
|
189
|
+
base,
|
|
190
|
+
items,
|
|
191
|
+
taxes: _taxes,
|
|
192
|
+
lineItemsSubtotalPrice,
|
|
193
|
+
shipping
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
function calculateFormula(expression, variables) {
|
|
197
|
+
if (!/^[\w+\-*/().\s<>=?:&|"']+$/.test(expression)) throw new TypeError("Formula contains invalid characters");
|
|
198
|
+
const context = { ...variables };
|
|
199
|
+
try {
|
|
200
|
+
let processedExpression = expression;
|
|
201
|
+
for (const [key, value] of Object.entries(context)) {
|
|
202
|
+
const regex = new RegExp(`\\b${key}\\b`, "g");
|
|
203
|
+
const safeValue = typeof value === "string" ? `"${value}"` : String(value);
|
|
204
|
+
processedExpression = processedExpression.replace(regex, safeValue);
|
|
205
|
+
}
|
|
206
|
+
const result = new Function(`return ${processedExpression}`)();
|
|
207
|
+
if (typeof result !== "number" || Number.isNaN(result)) throw new TypeError("Formula result is not a valid number");
|
|
208
|
+
return result;
|
|
209
|
+
} catch (error) {
|
|
210
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
211
|
+
throw new Error(`Error evaluating formula "${expression}": ${errorMessage}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
export { buildInvoice, calcAmount, calcItems, calcSingleItem, calculateFormula };
|
package/dist/server/router.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Database, Store } from "../_chunks/db.mjs";
|
|
2
|
-
import { Payment } from "../_chunks/index.mjs";
|
|
2
|
+
import { Graphql, Payment } from "../_chunks/index.mjs";
|
|
3
3
|
import { MiddlewareInputContext, MiddlewareOptions, StrictEndpoint } from "../_chunks/libs/better-call.mjs";
|
|
4
4
|
import { H3, H3Event } from "h3";
|
|
5
5
|
interface OptionsAccount$2 {
|
|
@@ -117,7 +117,7 @@ declare const _auth: import("better-auth").Auth<{
|
|
|
117
117
|
$Infer: {
|
|
118
118
|
body: {
|
|
119
119
|
userId: string;
|
|
120
|
-
role: "
|
|
120
|
+
role: "user" | "admin" | ("user" | "admin")[];
|
|
121
121
|
};
|
|
122
122
|
};
|
|
123
123
|
};
|
|
@@ -206,7 +206,7 @@ declare const _auth: import("better-auth").Auth<{
|
|
|
206
206
|
email: string;
|
|
207
207
|
password?: string | undefined;
|
|
208
208
|
name: string;
|
|
209
|
-
role?: "
|
|
209
|
+
role?: "user" | "admin" | ("user" | "admin")[];
|
|
210
210
|
data?: Record<string, any> | undefined;
|
|
211
211
|
};
|
|
212
212
|
};
|
|
@@ -829,7 +829,7 @@ declare const _auth: import("better-auth").Auth<{
|
|
|
829
829
|
};
|
|
830
830
|
} & {
|
|
831
831
|
userId?: string | undefined;
|
|
832
|
-
role?: "
|
|
832
|
+
role?: "user" | "admin";
|
|
833
833
|
};
|
|
834
834
|
};
|
|
835
835
|
};
|
|
@@ -1162,6 +1162,7 @@ interface Product {
|
|
|
1162
1162
|
id: any;
|
|
1163
1163
|
originalPrice: number;
|
|
1164
1164
|
}[];
|
|
1165
|
+
noVariants?: boolean;
|
|
1165
1166
|
}
|
|
1166
1167
|
interface LineItemsCart {
|
|
1167
1168
|
id: string;
|
|
@@ -1214,5 +1215,7 @@ declare function registerPayment(app: H3, db: Database, {
|
|
|
1214
1215
|
preset,
|
|
1215
1216
|
providerOptions,
|
|
1216
1217
|
redirect: globalRedirect
|
|
1217
|
-
}: OptionsAccount):
|
|
1218
|
+
}: OptionsAccount): {
|
|
1219
|
+
graphql: Graphql;
|
|
1220
|
+
};
|
|
1218
1221
|
export { LineItemsCart, getCheckoutId, getTax, registerAccount, registerAuth, registerAuthMiddleware, registerCache, registerCart, registerCheckout, registerPayment, safeParams, useProducts, useUser };
|
package/dist/server/router.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { buildInvoice, calcItems, calculateFormula } from "../_chunks/taxes.mjs";
|
|
1
2
|
import { checkouts, customerAddresses, customerBillings, customerWhislists } from "../_chunks/database.mjs";
|
|
2
3
|
import { GRAPHQL_TOKEN, TASKS_ENDPOINT, URL } from "./env.mjs";
|
|
3
4
|
import { createGraphql, createPayment } from "../_chunks/lib.mjs";
|
|
@@ -191,6 +192,7 @@ function normalizeProduct(opts) {
|
|
|
191
192
|
return (product) => {
|
|
192
193
|
const image = product?.images?.[0];
|
|
193
194
|
const discount = product?.discount || 0;
|
|
195
|
+
console.log("product", product);
|
|
194
196
|
const options = product?.variants?.options?.map((option) => {
|
|
195
197
|
return {
|
|
196
198
|
id: option?.option?.name?.toLowerCase(),
|
|
@@ -209,7 +211,6 @@ function normalizeProduct(opts) {
|
|
|
209
211
|
sku: variant?.sku || product?.sku || "",
|
|
210
212
|
image: imageVariant || image,
|
|
211
213
|
price,
|
|
212
|
-
showPrice: priceWithTaxt(price),
|
|
213
214
|
priceWithTax: priceWithTaxt(price),
|
|
214
215
|
comparedPrice: product.comparedPrice,
|
|
215
216
|
title: product.title,
|
|
@@ -223,6 +224,7 @@ function normalizeProduct(opts) {
|
|
|
223
224
|
};
|
|
224
225
|
});
|
|
225
226
|
let price = product.price;
|
|
227
|
+
console.log({ price });
|
|
226
228
|
if (discount) price = calcPrice(price, discount);
|
|
227
229
|
const taxes = product.taxes?.length ? product.taxes.map((tax) => {
|
|
228
230
|
return {
|
|
@@ -236,7 +238,6 @@ function normalizeProduct(opts) {
|
|
|
236
238
|
return {
|
|
237
239
|
...product,
|
|
238
240
|
price,
|
|
239
|
-
showPrice: priceWithTaxt(price),
|
|
240
241
|
priceWithTax: priceWithTaxt(price),
|
|
241
242
|
comparedPrice: product.comparedPrice || priceWithTaxt(+(product.price || 0)),
|
|
242
243
|
image,
|
|
@@ -289,7 +290,17 @@ function useProducts(db) {
|
|
|
289
290
|
title: true,
|
|
290
291
|
variants: true,
|
|
291
292
|
extras: true,
|
|
292
|
-
discount: true
|
|
293
|
+
discount: true,
|
|
294
|
+
price: true,
|
|
295
|
+
comparedPrice: true,
|
|
296
|
+
sku: true,
|
|
297
|
+
description: true,
|
|
298
|
+
images: true,
|
|
299
|
+
slug: true,
|
|
300
|
+
subtitle: true,
|
|
301
|
+
type: true,
|
|
302
|
+
weight: true,
|
|
303
|
+
order: true
|
|
293
304
|
},
|
|
294
305
|
with: { taxes: {
|
|
295
306
|
columns: {
|
|
@@ -391,7 +402,8 @@ async function getLineItems(cart, getProducts) {
|
|
|
391
402
|
taxes: product.taxes,
|
|
392
403
|
category: product.extras?.category || "none",
|
|
393
404
|
originalPrice: variant?.originalPrice || product?.originalPrice || 0,
|
|
394
|
-
originalDiscount: product?.discount || 0
|
|
405
|
+
originalDiscount: product?.discount || 0,
|
|
406
|
+
noVariants: product.noVariants ?? void 0
|
|
395
407
|
};
|
|
396
408
|
});
|
|
397
409
|
});
|
|
@@ -444,219 +456,6 @@ function registerCart(app, { getProducts, path }) {
|
|
|
444
456
|
return await returnCart(event, cart, getProducts);
|
|
445
457
|
}));
|
|
446
458
|
}
|
|
447
|
-
function roundNum(v, r = 2) {
|
|
448
|
-
return Number(Number(v).toFixed(r));
|
|
449
|
-
}
|
|
450
|
-
function calcPercentaje(value, percentaje, hasInclude) {
|
|
451
|
-
const val = +value;
|
|
452
|
-
const per = +percentaje;
|
|
453
|
-
if (hasInclude) return roundNum(val * per / (100 + per));
|
|
454
|
-
else return roundNum(val / 100 * per);
|
|
455
|
-
}
|
|
456
|
-
function calcDiscount(amount, discount) {
|
|
457
|
-
if ("percent" in discount) return {
|
|
458
|
-
amount: calcPercentaje(amount, discount.percent),
|
|
459
|
-
percent: +discount.percent
|
|
460
|
-
};
|
|
461
|
-
else return { amount: +discount.amount };
|
|
462
|
-
}
|
|
463
|
-
const sum = (arr) => arr.reduce((a, b) => a + b, 0);
|
|
464
|
-
const flatten = (arr) => arr.reduce((a, b) => a.concat(b), []);
|
|
465
|
-
function groupBy(fn, arr) {
|
|
466
|
-
return arr.reduce((acc, value) => {
|
|
467
|
-
const key = fn(value);
|
|
468
|
-
if (!acc[key]) acc[key] = [];
|
|
469
|
-
acc[key].push(value);
|
|
470
|
-
return acc;
|
|
471
|
-
}, {});
|
|
472
|
-
}
|
|
473
|
-
function calcAmount(_itemDiscount, _parentDiscount, taxIncluded) {
|
|
474
|
-
return (price) => {
|
|
475
|
-
if (!taxIncluded) {
|
|
476
|
-
const itemDiscount = calcDiscount(price, _itemDiscount);
|
|
477
|
-
const parentDiscount = calcDiscount(price - itemDiscount.amount, _parentDiscount);
|
|
478
|
-
const unitBase = price - (itemDiscount.amount + parentDiscount.amount);
|
|
479
|
-
return {
|
|
480
|
-
price,
|
|
481
|
-
discounts: {
|
|
482
|
-
itemDiscount,
|
|
483
|
-
parentDiscount
|
|
484
|
-
},
|
|
485
|
-
unitAmount: unitBase,
|
|
486
|
-
unitBase
|
|
487
|
-
};
|
|
488
|
-
} else {
|
|
489
|
-
const parentDiscount = calcDiscount(price, _parentDiscount);
|
|
490
|
-
const itemDiscount = calcDiscount(price - parentDiscount.amount, _itemDiscount);
|
|
491
|
-
return {
|
|
492
|
-
price,
|
|
493
|
-
discounts: {
|
|
494
|
-
itemDiscount,
|
|
495
|
-
parentDiscount
|
|
496
|
-
},
|
|
497
|
-
unitAmount: price - (itemDiscount.amount + parentDiscount.amount),
|
|
498
|
-
unitBase: 0
|
|
499
|
-
};
|
|
500
|
-
}
|
|
501
|
-
};
|
|
502
|
-
}
|
|
503
|
-
function calcSingleItem(parentDiscount = { amount: 0 }) {
|
|
504
|
-
return (item) => {
|
|
505
|
-
const quantity = +item.quantity;
|
|
506
|
-
const taxes = item.taxes || [];
|
|
507
|
-
const calcRawTax = (base, rate) => base * rate / 100;
|
|
508
|
-
const calculateTaxesForward = (originalBase, finalBase, raw = false) => {
|
|
509
|
-
const firstTaxes = [];
|
|
510
|
-
const latestTaxes = [];
|
|
511
|
-
let totalFirstTaxesAmount = 0;
|
|
512
|
-
let totalLatestTaxesAmount = 0;
|
|
513
|
-
for (const t of taxes) if (t.beforeTaxes) {
|
|
514
|
-
const baseToUse = t.excludeDiscount ? originalBase : finalBase;
|
|
515
|
-
const amount = raw ? calcRawTax(baseToUse, +t.value) : calcPercentaje(baseToUse, t.value, false);
|
|
516
|
-
firstTaxes.push({
|
|
517
|
-
...t,
|
|
518
|
-
base: baseToUse,
|
|
519
|
-
amount,
|
|
520
|
-
totalBase: baseToUse * quantity,
|
|
521
|
-
totalAmount: amount * quantity
|
|
522
|
-
});
|
|
523
|
-
totalFirstTaxesAmount += amount;
|
|
524
|
-
}
|
|
525
|
-
for (const t of taxes) if (!t.beforeTaxes) {
|
|
526
|
-
const baseToUse = (t.excludeDiscount ? originalBase : finalBase) + totalFirstTaxesAmount;
|
|
527
|
-
const amount = raw ? calcRawTax(baseToUse, +t.value) : calcPercentaje(baseToUse, t.value, false);
|
|
528
|
-
latestTaxes.push({
|
|
529
|
-
...t,
|
|
530
|
-
base: baseToUse,
|
|
531
|
-
amount,
|
|
532
|
-
totalBase: baseToUse * quantity,
|
|
533
|
-
totalAmount: amount * quantity
|
|
534
|
-
});
|
|
535
|
-
totalLatestTaxesAmount += amount;
|
|
536
|
-
}
|
|
537
|
-
return {
|
|
538
|
-
firstTaxes,
|
|
539
|
-
latestTaxes,
|
|
540
|
-
totalTaxes: totalFirstTaxesAmount + totalLatestTaxesAmount,
|
|
541
|
-
totalPrice: finalBase + totalFirstTaxesAmount + totalLatestTaxesAmount
|
|
542
|
-
};
|
|
543
|
-
};
|
|
544
|
-
if (!item.taxIncluded) {
|
|
545
|
-
const amounts = calcAmount(item.discount, parentDiscount, false)(+item.price);
|
|
546
|
-
const originalBase = amounts.price;
|
|
547
|
-
const finalBase = amounts.unitBase;
|
|
548
|
-
const result = calculateTaxesForward(originalBase, finalBase, false);
|
|
549
|
-
amounts.total = amounts.unitBase * quantity + result.totalTaxes * quantity;
|
|
550
|
-
return {
|
|
551
|
-
id: item.id,
|
|
552
|
-
title: item.title,
|
|
553
|
-
taxIncluded: item.taxIncluded,
|
|
554
|
-
item: amounts,
|
|
555
|
-
taxes: [...result.firstTaxes, ...result.latestTaxes],
|
|
556
|
-
quantity,
|
|
557
|
-
product: item.product,
|
|
558
|
-
variant: item.variant,
|
|
559
|
-
discountAllocations: item.discountAllocations
|
|
560
|
-
};
|
|
561
|
-
} else {
|
|
562
|
-
const amounts = calcAmount(item.discount, parentDiscount, true)(+item.price);
|
|
563
|
-
const originalPriceWithTaxes = amounts.price;
|
|
564
|
-
const finalPriceWithTaxes = amounts.unitAmount;
|
|
565
|
-
const T1_1 = calculateTaxesForward(1, 1, true).totalPrice;
|
|
566
|
-
const originalBaseRaw = originalPriceWithTaxes / (T1_1 === 0 ? 1 : T1_1);
|
|
567
|
-
const T0 = calculateTaxesForward(originalBaseRaw, 0, true).totalPrice;
|
|
568
|
-
const M = calculateTaxesForward(originalBaseRaw, 1, true).totalPrice - T0;
|
|
569
|
-
const result = calculateTaxesForward(originalBaseRaw, M === 0 ? finalPriceWithTaxes - T0 : (finalPriceWithTaxes - T0) / M, false);
|
|
570
|
-
const adjustedFinalBase = finalPriceWithTaxes - result.totalTaxes;
|
|
571
|
-
amounts.unitBase = adjustedFinalBase;
|
|
572
|
-
amounts.total = finalPriceWithTaxes * quantity;
|
|
573
|
-
for (const t of result.firstTaxes) if (!t.excludeDiscount) {
|
|
574
|
-
t.base = adjustedFinalBase;
|
|
575
|
-
t.totalBase = adjustedFinalBase * quantity;
|
|
576
|
-
}
|
|
577
|
-
const firstTotal = sum(result.firstTaxes.map((t) => t.amount));
|
|
578
|
-
for (const t of result.latestTaxes) if (!t.excludeDiscount) {
|
|
579
|
-
t.base = adjustedFinalBase + firstTotal;
|
|
580
|
-
t.totalBase = t.base * quantity;
|
|
581
|
-
}
|
|
582
|
-
return {
|
|
583
|
-
id: item.id,
|
|
584
|
-
title: item.title,
|
|
585
|
-
taxIncluded: item.taxIncluded,
|
|
586
|
-
item: amounts,
|
|
587
|
-
taxes: [...result.firstTaxes, ...result.latestTaxes],
|
|
588
|
-
quantity,
|
|
589
|
-
product: item.product,
|
|
590
|
-
variant: item.variant,
|
|
591
|
-
discountAllocations: item.discountAllocations
|
|
592
|
-
};
|
|
593
|
-
}
|
|
594
|
-
};
|
|
595
|
-
}
|
|
596
|
-
function calcItems(items, parentDiscount = { amount: 0 }) {
|
|
597
|
-
return items.map(calcSingleItem(parentDiscount));
|
|
598
|
-
}
|
|
599
|
-
function buildInvoice(items) {
|
|
600
|
-
const base = sum(items.map((item) => item.item.unitBase * item.quantity));
|
|
601
|
-
const lineItemsSubtotalPrice = sum(items.filter((item) => !["_envio"].includes(item.id)).map((item) => item.item.price * item.quantity));
|
|
602
|
-
const shipping = sum(items.filter((item) => ["_envio"].includes(item.id)).map((item) => item.item.price * item.quantity));
|
|
603
|
-
const totalDiscount = sum(items.map((item) => {
|
|
604
|
-
const discounts = item.item.discounts;
|
|
605
|
-
if (!discounts) return 0;
|
|
606
|
-
return ((discounts.itemDiscount?.amount || 0) + (discounts.parentDiscount?.amount || 0)) * item.quantity;
|
|
607
|
-
}));
|
|
608
|
-
const imp = groupBy((tax) => {
|
|
609
|
-
return `${tax.type.code}_${tax.code}`;
|
|
610
|
-
}, flatten(items.map((item) => item.taxes)));
|
|
611
|
-
const _taxes = Object.values(imp).map((taxes) => {
|
|
612
|
-
let taxBase = 0;
|
|
613
|
-
let value = 0;
|
|
614
|
-
const type = taxes[0].type.code;
|
|
615
|
-
const title = taxes[0].type.name;
|
|
616
|
-
const code = taxes[0].code;
|
|
617
|
-
const rate = +taxes[0].value;
|
|
618
|
-
for (const iterator of taxes) {
|
|
619
|
-
taxBase += +iterator.totalBase;
|
|
620
|
-
value += +iterator.totalAmount;
|
|
621
|
-
}
|
|
622
|
-
return {
|
|
623
|
-
type,
|
|
624
|
-
code,
|
|
625
|
-
base: taxBase,
|
|
626
|
-
value,
|
|
627
|
-
rate,
|
|
628
|
-
title
|
|
629
|
-
};
|
|
630
|
-
});
|
|
631
|
-
return {
|
|
632
|
-
total: base + sum(_taxes.map((tax) => tax.value)),
|
|
633
|
-
totalTax: sum(_taxes.map((t) => t.value)),
|
|
634
|
-
totalDiscount,
|
|
635
|
-
base,
|
|
636
|
-
items,
|
|
637
|
-
taxes: _taxes,
|
|
638
|
-
lineItemsSubtotalPrice,
|
|
639
|
-
shipping
|
|
640
|
-
};
|
|
641
|
-
}
|
|
642
|
-
function calculateFormula(expression, variables) {
|
|
643
|
-
if (!/^[\w+\-*/().\s<>=?:&|"']+$/.test(expression)) throw new TypeError("Formula contains invalid characters");
|
|
644
|
-
const context = { ...variables };
|
|
645
|
-
try {
|
|
646
|
-
let processedExpression = expression;
|
|
647
|
-
for (const [key, value] of Object.entries(context)) {
|
|
648
|
-
const regex = new RegExp(`\\b${key}\\b`, "g");
|
|
649
|
-
const safeValue = typeof value === "string" ? `"${value}"` : String(value);
|
|
650
|
-
processedExpression = processedExpression.replace(regex, safeValue);
|
|
651
|
-
}
|
|
652
|
-
const result = new Function(`return ${processedExpression}`)();
|
|
653
|
-
if (typeof result !== "number" || Number.isNaN(result)) throw new TypeError("Formula result is not a valid number");
|
|
654
|
-
return result;
|
|
655
|
-
} catch (error) {
|
|
656
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
657
|
-
throw new Error(`Error evaluating formula "${expression}": ${errorMessage}`);
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
459
|
function getCheckoutId(event) {
|
|
661
460
|
const cookie = getCookie(event, "eCheckout");
|
|
662
461
|
if (!cookie) throw new HTTPError({
|
|
@@ -1054,8 +853,9 @@ const presets = { ecommerce: { prepare: { preHandle: async (event, payment) => {
|
|
|
1054
853
|
event.context.card = card;
|
|
1055
854
|
} } } };
|
|
1056
855
|
function registerPayment(app, db, { path, storeId, providers, preset, providerOptions, redirect: globalRedirect }) {
|
|
856
|
+
const graphql = createGraphql(db);
|
|
1057
857
|
const instance = createPayment({
|
|
1058
|
-
graphql
|
|
858
|
+
graphql,
|
|
1059
859
|
storeId,
|
|
1060
860
|
providers,
|
|
1061
861
|
secret: "secret",
|
|
@@ -1153,5 +953,6 @@ function registerPayment(app, db, { path, storeId, providers, preset, providerOp
|
|
|
1153
953
|
const provider = safeParams(event.context.params?.provider || "");
|
|
1154
954
|
return await payment?.webhook?.(provider, uid, body);
|
|
1155
955
|
}));
|
|
956
|
+
return { graphql };
|
|
1156
957
|
}
|
|
1157
958
|
export { getCheckoutId, getTax, registerAccount, registerAuth, registerAuthMiddleware, registerCache, registerCart, registerCheckout, registerPayment, safeParams, useProducts, useUser };
|