@yoryoboy/bi-mcp 1.10.0 → 1.13.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.
- package/README.md +4 -5
- package/dist/.tsbuildinfo +1 -1
- package/dist/index.js +398 -8
- package/dist/index.js.map +2 -2
- package/dist/mcp-use.json +2 -2
- package/dist/src/config/__tests__/meta.test.js +35 -0
- package/dist/src/config/__tests__/meta.test.js.map +7 -0
- package/dist/src/config/mercadolibre-profile-store.js +25 -0
- package/dist/src/config/mercadolibre-profile-store.js.map +2 -2
- package/dist/src/config/meta-store.js +109 -0
- package/dist/src/config/meta-store.js.map +7 -0
- package/dist/src/config/meta.js +0 -2
- package/dist/src/config/meta.js.map +2 -2
- package/dist/src/meta/__tests__/meta-utils.test.js +155 -0
- package/dist/src/meta/__tests__/meta-utils.test.js.map +7 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-api.test.js +265 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-api.test.js.map +7 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-items.test.js +311 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-items.test.js.map +7 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-orders.test.js +220 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-orders.test.js.map +7 -0
- package/dist/src/services/meta/__tests__/meta-ads.test.js +126 -0
- package/dist/src/services/meta/__tests__/meta-ads.test.js.map +7 -0
- package/dist/src/services/meta/__tests__/meta-api.test.js +70 -0
- package/dist/src/services/meta/__tests__/meta-api.test.js.map +7 -0
- package/dist/src/services/meta/meta-ads.js +94 -40
- package/dist/src/services/meta/meta-ads.js.map +2 -2
- package/dist/src/services/meta/meta-api.js +8 -6
- package/dist/src/services/meta/meta-api.js.map +2 -2
- package/dist/src/services/vtex/__tests__/vtex-catalog-write-batch.test.js +165 -0
- package/dist/src/services/vtex/__tests__/vtex-catalog-write-batch.test.js.map +7 -0
- package/dist/src/services/vtex/__tests__/vtex-catalog-write-eans.test.js +92 -0
- package/dist/src/services/vtex/__tests__/vtex-catalog-write-eans.test.js.map +7 -0
- package/dist/src/services/vtex/__tests__/vtex-catalog-write-products.test.js +41 -0
- package/dist/src/services/vtex/__tests__/vtex-catalog-write-products.test.js.map +7 -0
- package/dist/src/services/vtex/__tests__/vtex-catalog.test.js +80 -0
- package/dist/src/services/vtex/__tests__/vtex-catalog.test.js.map +7 -0
- package/dist/src/services/vtex/__tests__/vtex-orders-write-http.test.js +85 -0
- package/dist/src/services/vtex/__tests__/vtex-orders-write-http.test.js.map +7 -0
- package/dist/src/services/vtex/__tests__/vtex-orders-write-state-validation.test.js +251 -0
- package/dist/src/services/vtex/__tests__/vtex-orders-write-state-validation.test.js.map +7 -0
- package/dist/src/services/vtex/__tests__/vtex-write.test.js +111 -0
- package/dist/src/services/vtex/__tests__/vtex-write.test.js.map +7 -0
- package/dist/src/services/vtex/vtex-catalog-write.js +194 -1
- package/dist/src/services/vtex/vtex-catalog-write.js.map +2 -2
- package/dist/src/services/vtex/vtex-catalog.js +118 -1
- package/dist/src/services/vtex/vtex-catalog.js.map +2 -2
- package/dist/src/services/vtex/vtex-pricing-write.js +5 -0
- package/dist/src/services/vtex/vtex-pricing-write.js.map +2 -2
- package/dist/src/services/vtex/vtex-write.js +67 -1
- package/dist/src/services/vtex/vtex-write.js.map +2 -2
- package/dist/src/tools/config/list-profiles.js +85 -11
- package/dist/src/tools/config/list-profiles.js.map +2 -2
- package/dist/src/tools/index.js.map +2 -2
- package/dist/src/tools/mercadolibre/__tests__/helpers.test.js +37 -0
- package/dist/src/tools/mercadolibre/__tests__/helpers.test.js.map +7 -0
- package/dist/src/tools/mercadolibre/__tests__/profile-resolution.test.js +30 -0
- package/dist/src/tools/mercadolibre/__tests__/profile-resolution.test.js.map +7 -0
- package/dist/src/tools/mercadolibre/profile-resolution.js +4 -50
- package/dist/src/tools/mercadolibre/profile-resolution.js.map +2 -2
- package/dist/src/tools/meta/__tests__/pagination.test.js +133 -0
- package/dist/src/tools/meta/__tests__/pagination.test.js.map +7 -0
- package/dist/src/tools/meta/__tests__/profile-access.test.js +262 -0
- package/dist/src/tools/meta/__tests__/profile-access.test.js.map +7 -0
- package/dist/src/tools/meta/__tests__/read-tools.test.js +722 -0
- package/dist/src/tools/meta/__tests__/read-tools.test.js.map +7 -0
- package/dist/src/tools/meta/__tests__/schemas.test.js +103 -0
- package/dist/src/tools/meta/__tests__/schemas.test.js.map +7 -0
- package/dist/src/tools/meta/account-overview.js +37 -19
- package/dist/src/tools/meta/account-overview.js.map +2 -2
- package/dist/src/tools/meta/ad-account-info.js +31 -6
- package/dist/src/tools/meta/ad-account-info.js.map +2 -2
- package/dist/src/tools/meta/ads-performance.js +35 -21
- package/dist/src/tools/meta/ads-performance.js.map +2 -2
- package/dist/src/tools/meta/campaign-performance.js +35 -18
- package/dist/src/tools/meta/campaign-performance.js.map +2 -2
- package/dist/src/tools/meta/list-accessible-ad-accounts.js +39 -10
- package/dist/src/tools/meta/list-accessible-ad-accounts.js.map +2 -2
- package/dist/src/tools/meta/list-accessible-businesses.js +37 -13
- package/dist/src/tools/meta/list-accessible-businesses.js.map +2 -2
- package/dist/src/tools/meta/placement-mix.js +37 -22
- package/dist/src/tools/meta/placement-mix.js.map +2 -2
- package/dist/src/tools/meta/profile-access.js +215 -0
- package/dist/src/tools/meta/profile-access.js.map +7 -0
- package/dist/src/tools/meta/schema-helpers.js +19 -0
- package/dist/src/tools/meta/schema-helpers.js.map +7 -0
- package/dist/src/tools/meta/time-series.js +40 -23
- package/dist/src/tools/meta/time-series.js.map +2 -2
- package/dist/src/tools/vtex/__tests__/catalog-admin-batch.test.js +233 -0
- package/dist/src/tools/vtex/__tests__/catalog-admin-batch.test.js.map +7 -0
- package/dist/src/tools/vtex/__tests__/catalog-admin-categories.test.js +649 -0
- package/dist/src/tools/vtex/__tests__/catalog-admin-categories.test.js.map +7 -0
- package/dist/src/tools/vtex/__tests__/catalog-admin-product-specifications.test.js +339 -0
- package/dist/src/tools/vtex/__tests__/catalog-admin-product-specifications.test.js.map +7 -0
- package/dist/src/tools/vtex/__tests__/catalog-admin-products-skus.test.js +235 -0
- package/dist/src/tools/vtex/__tests__/catalog-admin-products-skus.test.js.map +7 -0
- package/dist/src/tools/vtex/__tests__/catalog-navigation-reads.test.js +372 -0
- package/dist/src/tools/vtex/__tests__/catalog-navigation-reads.test.js.map +7 -0
- package/dist/src/tools/vtex/__tests__/catalog-navigation-surface.test.js +57 -0
- package/dist/src/tools/vtex/__tests__/catalog-navigation-surface.test.js.map +7 -0
- package/dist/src/tools/vtex/__tests__/write-helpers.test.js +97 -0
- package/dist/src/tools/vtex/__tests__/write-helpers.test.js.map +7 -0
- package/dist/src/tools/vtex/activate-sku.js +1 -48
- package/dist/src/tools/vtex/activate-sku.js.map +2 -2
- package/dist/src/tools/vtex/associate-specification.js +3 -54
- package/dist/src/tools/vtex/associate-specification.js.map +2 -2
- package/dist/src/tools/vtex/attach-catalog-image.js +3 -57
- package/dist/src/tools/vtex/attach-catalog-image.js.map +2 -2
- package/dist/src/tools/vtex/catalog-admin-batch.js +298 -0
- package/dist/src/tools/vtex/catalog-admin-batch.js.map +7 -0
- package/dist/src/tools/vtex/catalog-admin-categories.js +542 -0
- package/dist/src/tools/vtex/catalog-admin-categories.js.map +7 -0
- package/dist/src/tools/vtex/catalog-admin-product-specifications.js +275 -0
- package/dist/src/tools/vtex/catalog-admin-product-specifications.js.map +7 -0
- package/dist/src/tools/vtex/catalog-admin-products-skus.js +475 -0
- package/dist/src/tools/vtex/catalog-admin-products-skus.js.map +7 -0
- package/dist/src/tools/vtex/catalog-navigation-reads.js +430 -0
- package/dist/src/tools/vtex/catalog-navigation-reads.js.map +7 -0
- package/dist/src/tools/vtex/create-brand.js +1 -64
- package/dist/src/tools/vtex/create-brand.js.map +2 -2
- package/dist/src/tools/vtex/create-category.js +1 -76
- package/dist/src/tools/vtex/create-category.js.map +2 -2
- package/dist/src/tools/vtex/create-product-with-sku.js +3 -114
- package/dist/src/tools/vtex/create-product-with-sku.js.map +2 -2
- package/dist/src/tools/vtex/create-specification-value.js +3 -47
- package/dist/src/tools/vtex/create-specification-value.js.map +2 -2
- package/dist/src/tools/vtex/create-specification.js +1 -80
- package/dist/src/tools/vtex/create-specification.js.map +2 -2
- package/dist/src/tools/vtex/deactivate-sku.js +1 -48
- package/dist/src/tools/vtex/deactivate-sku.js.map +2 -2
- package/dist/src/tools/vtex/delete-all-product-specifications.js +9 -0
- package/dist/src/tools/vtex/delete-all-product-specifications.js.map +7 -0
- package/dist/src/tools/vtex/delete-all-sku-specifications.js +9 -0
- package/dist/src/tools/vtex/delete-all-sku-specifications.js.map +7 -0
- package/dist/src/tools/vtex/delete-brand.js +9 -0
- package/dist/src/tools/vtex/delete-brand.js.map +7 -0
- package/dist/src/tools/vtex/delete-catalog-image.js +9 -0
- package/dist/src/tools/vtex/delete-catalog-image.js.map +7 -0
- package/dist/src/tools/vtex/delete-product-specification.js +9 -0
- package/dist/src/tools/vtex/delete-product-specification.js.map +7 -0
- package/dist/src/tools/vtex/delete-sku-price.js +55 -0
- package/dist/src/tools/vtex/delete-sku-price.js.map +7 -0
- package/dist/src/tools/vtex/delete-sku-specification.js +9 -0
- package/dist/src/tools/vtex/delete-sku-specification.js.map +7 -0
- package/dist/src/tools/vtex/get-brand.js +6 -0
- package/dist/src/tools/vtex/get-brand.js.map +7 -0
- package/dist/src/tools/vtex/get-category-tree.js +6 -0
- package/dist/src/tools/vtex/get-category-tree.js.map +7 -0
- package/dist/src/tools/vtex/get-category.js +6 -0
- package/dist/src/tools/vtex/get-category.js.map +7 -0
- package/dist/src/tools/vtex/get-product-specifications.js +9 -0
- package/dist/src/tools/vtex/get-product-specifications.js.map +7 -0
- package/dist/src/tools/vtex/get-product.js +6 -0
- package/dist/src/tools/vtex/get-product.js.map +7 -0
- package/dist/src/tools/vtex/get-sku.js +6 -0
- package/dist/src/tools/vtex/get-sku.js.map +7 -0
- package/dist/src/tools/vtex/index.js +23 -1
- package/dist/src/tools/vtex/index.js.map +2 -2
- package/dist/src/tools/vtex/list-brands.js +6 -0
- package/dist/src/tools/vtex/list-brands.js.map +7 -0
- package/dist/src/tools/vtex/list-categories.js +6 -0
- package/dist/src/tools/vtex/list-categories.js.map +7 -0
- package/dist/src/tools/vtex/list-products-by-category.js +6 -0
- package/dist/src/tools/vtex/list-products-by-category.js.map +7 -0
- package/dist/src/tools/vtex/list-products.js +6 -0
- package/dist/src/tools/vtex/list-products.js.map +7 -0
- package/dist/src/tools/vtex/list-skus-by-product.js +6 -0
- package/dist/src/tools/vtex/list-skus-by-product.js.map +7 -0
- package/dist/src/tools/vtex/list-specification-groups.js +9 -0
- package/dist/src/tools/vtex/list-specification-groups.js.map +7 -0
- package/dist/src/tools/vtex/move-category.js +6 -0
- package/dist/src/tools/vtex/move-category.js.map +7 -0
- package/dist/src/tools/vtex/profile-resolution.js +4 -51
- package/dist/src/tools/vtex/profile-resolution.js.map +2 -2
- package/dist/src/tools/vtex/update-brand.js +6 -0
- package/dist/src/tools/vtex/update-brand.js.map +7 -0
- package/dist/src/tools/vtex/update-category.js +6 -0
- package/dist/src/tools/vtex/update-category.js.map +7 -0
- package/dist/src/tools/vtex/update-product-basic-fields.js +3 -65
- package/dist/src/tools/vtex/update-product-basic-fields.js.map +2 -2
- package/dist/src/tools/vtex/update-sku-basic-fields.js +1 -87
- package/dist/src/tools/vtex/update-sku-basic-fields.js.map +2 -2
- package/dist/src/tools/vtex/update-sku-price.js +21 -1
- package/dist/src/tools/vtex/update-sku-price.js.map +2 -2
- package/dist/src/tools/vtex/write-helpers.js +104 -14
- package/dist/src/tools/vtex/write-helpers.js.map +2 -2
- package/dist/src/utils/provider-profile-selection.js +117 -0
- package/dist/src/utils/provider-profile-selection.js.map +7 -0
- package/dist/tests/meli/mercadolibre-tool-handlers-medium-batch4.test.js +678 -0
- package/dist/tests/meli/mercadolibre-tool-handlers-medium-batch4.test.js.map +7 -0
- package/dist/tests/meli/mercadolibre-tool-handlers-monster-batch5.test.js +564 -0
- package/dist/tests/meli/mercadolibre-tool-handlers-monster-batch5.test.js.map +7 -0
- package/dist/tests/meli/mercadolibre-tool-handlers-monster-batch6.test.js +387 -0
- package/dist/tests/meli/mercadolibre-tool-handlers-monster-batch6.test.js.map +7 -0
- package/dist/tests/meli/mercadolibre-tool-handlers-monster-batch7.test.js +368 -0
- package/dist/tests/meli/mercadolibre-tool-handlers-monster-batch7.test.js.map +7 -0
- package/dist/tests/meli/mercadolibre-tool-handlers-small.test.js +626 -0
- package/dist/tests/meli/mercadolibre-tool-handlers-small.test.js.map +7 -0
- package/dist/tests/meli/mercadolibre-tool-handlers-write-batch8.test.js +480 -0
- package/dist/tests/meli/mercadolibre-tool-handlers-write-batch8.test.js.map +7 -0
- package/dist/tests/setup.js +2 -0
- package/dist/tests/setup.js.map +7 -0
- package/dist/tests/smoke/test-harness.test.js +7 -0
- package/dist/tests/smoke/test-harness.test.js.map +7 -0
- package/dist/tests/vtex/read-only-utils.test.js +161 -0
- package/dist/tests/vtex/read-only-utils.test.js.map +7 -0
- package/dist/tests/vtex/vtex-catalog-admin-docs.test.js +24 -0
- package/dist/tests/vtex/vtex-catalog-admin-docs.test.js.map +7 -0
- package/dist/tests/vtex/vtex-catalog-admin-surface.test.js +30 -0
- package/dist/tests/vtex/vtex-catalog-admin-surface.test.js.map +7 -0
- package/dist/tests/vtex/vtex-catalog-write-tools.test.js +712 -0
- package/dist/tests/vtex/vtex-catalog-write-tools.test.js.map +7 -0
- package/dist/tests/vtex/vtex-catalog.service.test.js +51 -0
- package/dist/tests/vtex/vtex-catalog.service.test.js.map +7 -0
- package/dist/tests/vtex/vtex-inventory-tools.test.js +201 -0
- package/dist/tests/vtex/vtex-inventory-tools.test.js.map +7 -0
- package/dist/tests/vtex/vtex-logistics.service.test.js +134 -0
- package/dist/tests/vtex/vtex-logistics.service.test.js.map +7 -0
- package/dist/tests/vtex/vtex-order-details.tool.test.js +141 -0
- package/dist/tests/vtex/vtex-order-details.tool.test.js.map +7 -0
- package/dist/tests/vtex/vtex-order-write-tools.test.js +483 -0
- package/dist/tests/vtex/vtex-order-write-tools.test.js.map +7 -0
- package/dist/tests/vtex/vtex-orders-summary.tool.test.js +185 -0
- package/dist/tests/vtex/vtex-orders-summary.tool.test.js.map +7 -0
- package/dist/tests/vtex/vtex-orders.service.test.js +120 -0
- package/dist/tests/vtex/vtex-orders.service.test.js.map +7 -0
- package/dist/tests/vtex/vtex-pricing-write-tools.test.js +202 -0
- package/dist/tests/vtex/vtex-pricing-write-tools.test.js.map +7 -0
- package/dist/tests/vtex/vtex-pricing-write.service.test.js +106 -0
- package/dist/tests/vtex/vtex-pricing-write.service.test.js.map +7 -0
- package/dist/tests/vtex/vtex-pricing.service.test.js +88 -0
- package/dist/tests/vtex/vtex-pricing.service.test.js.map +7 -0
- package/dist/tests/vtex/vtex-small-tools.test.js +190 -0
- package/dist/tests/vtex/vtex-small-tools.test.js.map +7 -0
- package/dist/tests/vtex/vtex-write-simple-tools.test.js +647 -0
- package/dist/tests/vtex/vtex-write-simple-tools.test.js.map +7 -0
- package/dist/vitest.config.js +15 -0
- package/dist/vitest.config.js.map +7 -0
- package/package.json +6 -2
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
const getOrderDocumentMock = vi.fn();
|
|
3
|
+
vi.mock("../vtex-orders.js", () => ({
|
|
4
|
+
getOrderDocument: getOrderDocumentMock
|
|
5
|
+
}));
|
|
6
|
+
const ordersWrite = await import("../vtex-orders-write.js");
|
|
7
|
+
describe("VTEX order write state validation", () => {
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
vi.clearAllMocks();
|
|
10
|
+
});
|
|
11
|
+
describe("getOrderStateSnapshot", () => {
|
|
12
|
+
it("shapes the snapshot and extracts invoice numbers from invoices and outputs", async () => {
|
|
13
|
+
getOrderDocumentMock.mockResolvedValueOnce({
|
|
14
|
+
status: "handling",
|
|
15
|
+
state: "payment-approved",
|
|
16
|
+
allowCancellation: true,
|
|
17
|
+
invoicedDate: 1717171717,
|
|
18
|
+
invoiceData: {
|
|
19
|
+
invoices: [
|
|
20
|
+
{ invoiceNumber: 1234 },
|
|
21
|
+
{ number: "A-100" },
|
|
22
|
+
{ invoiceId: "INV-9" },
|
|
23
|
+
{ receipt: "RCPT-1" },
|
|
24
|
+
{ invoiceNumber: 1234 }
|
|
25
|
+
],
|
|
26
|
+
invoiceOutput: ["A-100", 555, null]
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
const snapshot = await ordersWrite.getOrderStateSnapshot(
|
|
30
|
+
"profile-1",
|
|
31
|
+
"order-1",
|
|
32
|
+
"validation-reason"
|
|
33
|
+
);
|
|
34
|
+
expect(getOrderDocumentMock).toHaveBeenCalledWith(
|
|
35
|
+
"profile-1",
|
|
36
|
+
"order-1",
|
|
37
|
+
"validation-reason"
|
|
38
|
+
);
|
|
39
|
+
expect(snapshot).toEqual({
|
|
40
|
+
orderId: "order-1",
|
|
41
|
+
status: "handling",
|
|
42
|
+
state: "payment-approved",
|
|
43
|
+
allowCancellation: true,
|
|
44
|
+
invoicedDate: "1717171717",
|
|
45
|
+
invoiceNumbers: ["1234", "A-100", "INV-9", "RCPT-1", "555"]
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
it("returns an empty invoice list when invoice data is missing or malformed", async () => {
|
|
49
|
+
getOrderDocumentMock.mockResolvedValueOnce({
|
|
50
|
+
status: null,
|
|
51
|
+
state: void 0,
|
|
52
|
+
allowCancellation: "yes",
|
|
53
|
+
invoicedDate: null,
|
|
54
|
+
invoiceData: "unexpected"
|
|
55
|
+
});
|
|
56
|
+
const snapshot = await ordersWrite.getOrderStateSnapshot("profile-1", "order-2");
|
|
57
|
+
expect(snapshot).toEqual({
|
|
58
|
+
orderId: "order-2",
|
|
59
|
+
status: void 0,
|
|
60
|
+
state: void 0,
|
|
61
|
+
allowCancellation: void 0,
|
|
62
|
+
invoicedDate: void 0,
|
|
63
|
+
invoiceNumbers: []
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
describe("validateOrderForCancellation", () => {
|
|
68
|
+
it("returns the snapshot when the order is still cancelable", async () => {
|
|
69
|
+
getOrderDocumentMock.mockResolvedValueOnce({
|
|
70
|
+
status: "handling",
|
|
71
|
+
state: "handling",
|
|
72
|
+
allowCancellation: true
|
|
73
|
+
});
|
|
74
|
+
await expect(
|
|
75
|
+
ordersWrite.validateOrderForCancellation("profile-1", "order-1", "customer-request")
|
|
76
|
+
).resolves.toEqual({
|
|
77
|
+
orderId: "order-1",
|
|
78
|
+
status: "handling",
|
|
79
|
+
state: "handling",
|
|
80
|
+
allowCancellation: true,
|
|
81
|
+
invoicedDate: void 0,
|
|
82
|
+
invoiceNumbers: []
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
it("rejects cancellation for orders already canceled", async () => {
|
|
86
|
+
getOrderDocumentMock.mockResolvedValueOnce({ status: "canceled", state: "cancelled" });
|
|
87
|
+
await expect(
|
|
88
|
+
ordersWrite.validateOrderForCancellation("profile-1", "order-1")
|
|
89
|
+
).rejects.toMatchObject({
|
|
90
|
+
name: "VtexOperationError",
|
|
91
|
+
code: "INVALID_ORDER_STATE",
|
|
92
|
+
message: "Order is already canceled.",
|
|
93
|
+
details: {
|
|
94
|
+
status: "canceled",
|
|
95
|
+
state: "cancelled"
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
it("rejects cancellation when VTEX disallows it", async () => {
|
|
100
|
+
getOrderDocumentMock.mockResolvedValueOnce({
|
|
101
|
+
status: "handling",
|
|
102
|
+
state: "handling",
|
|
103
|
+
allowCancellation: false
|
|
104
|
+
});
|
|
105
|
+
await expect(
|
|
106
|
+
ordersWrite.validateOrderForCancellation("profile-1", "order-1")
|
|
107
|
+
).rejects.toMatchObject({
|
|
108
|
+
name: "VtexOperationError",
|
|
109
|
+
code: "INVALID_ORDER_STATE",
|
|
110
|
+
message: "VTEX reports that this order can no longer be canceled."
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
it("rejects cancellation for invoiced orders", async () => {
|
|
114
|
+
getOrderDocumentMock.mockResolvedValueOnce({
|
|
115
|
+
status: "handling",
|
|
116
|
+
state: "handling",
|
|
117
|
+
allowCancellation: true,
|
|
118
|
+
invoicedDate: "2026-06-06T10:00:00.000Z"
|
|
119
|
+
});
|
|
120
|
+
await expect(
|
|
121
|
+
ordersWrite.validateOrderForCancellation("profile-1", "order-1")
|
|
122
|
+
).rejects.toMatchObject({
|
|
123
|
+
name: "VtexOperationError",
|
|
124
|
+
code: "INVALID_ORDER_STATE",
|
|
125
|
+
message: "Order is already invoiced, so VTEX no longer allows cancellation.",
|
|
126
|
+
details: {
|
|
127
|
+
invoiced_date: "2026-06-06T10:00:00.000Z"
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
describe("validateOrderForInvoice", () => {
|
|
133
|
+
it("returns the snapshot when the order can be invoiced", async () => {
|
|
134
|
+
getOrderDocumentMock.mockResolvedValueOnce({ status: "ready-for-handling", state: "ready" });
|
|
135
|
+
await expect(ordersWrite.validateOrderForInvoice("profile-1", "order-3")).resolves.toEqual({
|
|
136
|
+
orderId: "order-3",
|
|
137
|
+
status: "ready-for-handling",
|
|
138
|
+
state: "ready",
|
|
139
|
+
allowCancellation: void 0,
|
|
140
|
+
invoicedDate: void 0,
|
|
141
|
+
invoiceNumbers: []
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
it("rejects invoicing for canceled orders", async () => {
|
|
145
|
+
getOrderDocumentMock.mockResolvedValueOnce({ status: "canceling", state: "handling" });
|
|
146
|
+
await expect(ordersWrite.validateOrderForInvoice("profile-1", "order-3")).rejects.toMatchObject({
|
|
147
|
+
name: "VtexOperationError",
|
|
148
|
+
code: "INVALID_ORDER_STATE",
|
|
149
|
+
message: "Canceled orders cannot be invoiced."
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
it("rejects invoicing when invoice data already exists", async () => {
|
|
153
|
+
getOrderDocumentMock.mockResolvedValueOnce({
|
|
154
|
+
status: "handling",
|
|
155
|
+
state: "handling",
|
|
156
|
+
invoicedDate: "2026-06-06",
|
|
157
|
+
invoiceData: {
|
|
158
|
+
invoices: [{ invoiceNumber: "INV-1" }]
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
await expect(ordersWrite.validateOrderForInvoice("profile-1", "order-3")).rejects.toMatchObject({
|
|
162
|
+
name: "VtexOperationError",
|
|
163
|
+
code: "INVALID_ORDER_STATE",
|
|
164
|
+
message: "Order already contains invoice data.",
|
|
165
|
+
details: {
|
|
166
|
+
invoiced_date: "2026-06-06",
|
|
167
|
+
invoice_numbers: ["INV-1"]
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
describe("validateOrderForTracking", () => {
|
|
173
|
+
it("returns the snapshot when the invoice exists on the order", async () => {
|
|
174
|
+
getOrderDocumentMock.mockResolvedValueOnce({
|
|
175
|
+
status: "invoiced",
|
|
176
|
+
state: "handling",
|
|
177
|
+
invoiceData: {
|
|
178
|
+
invoices: [{ invoiceNumber: "INV-10" }]
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
await expect(
|
|
182
|
+
ordersWrite.validateOrderForTracking("profile-1", "order-4", "INV-10")
|
|
183
|
+
).resolves.toEqual({
|
|
184
|
+
orderId: "order-4",
|
|
185
|
+
status: "invoiced",
|
|
186
|
+
state: "handling",
|
|
187
|
+
allowCancellation: void 0,
|
|
188
|
+
invoicedDate: void 0,
|
|
189
|
+
invoiceNumbers: ["INV-10"]
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
it("allows tracking when VTEX marks the order invoiced even without invoice numbers", async () => {
|
|
193
|
+
getOrderDocumentMock.mockResolvedValueOnce({
|
|
194
|
+
status: "invoiced",
|
|
195
|
+
state: "handling",
|
|
196
|
+
invoicedDate: "2026-06-06T10:00:00.000Z"
|
|
197
|
+
});
|
|
198
|
+
await expect(
|
|
199
|
+
ordersWrite.validateOrderForTracking("profile-1", "order-5", "INV-MISSING")
|
|
200
|
+
).resolves.toEqual({
|
|
201
|
+
orderId: "order-5",
|
|
202
|
+
status: "invoiced",
|
|
203
|
+
state: "handling",
|
|
204
|
+
allowCancellation: void 0,
|
|
205
|
+
invoicedDate: "2026-06-06T10:00:00.000Z",
|
|
206
|
+
invoiceNumbers: []
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
it("rejects tracking for canceled orders", async () => {
|
|
210
|
+
getOrderDocumentMock.mockResolvedValueOnce({ status: "canceled", state: "handling" });
|
|
211
|
+
await expect(
|
|
212
|
+
ordersWrite.validateOrderForTracking("profile-1", "order-4", "INV-10")
|
|
213
|
+
).rejects.toMatchObject({
|
|
214
|
+
name: "VtexOperationError",
|
|
215
|
+
code: "INVALID_ORDER_STATE",
|
|
216
|
+
message: "Canceled orders cannot receive tracking updates."
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
it("rejects tracking when the order is not invoiced yet", async () => {
|
|
220
|
+
getOrderDocumentMock.mockResolvedValueOnce({ status: "handling", state: "handling" });
|
|
221
|
+
await expect(
|
|
222
|
+
ordersWrite.validateOrderForTracking("profile-1", "order-4", "INV-10")
|
|
223
|
+
).rejects.toMatchObject({
|
|
224
|
+
name: "VtexOperationError",
|
|
225
|
+
code: "INVALID_ORDER_STATE",
|
|
226
|
+
message: "Order is not invoiced yet, so tracking cannot be added."
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
it("rejects tracking when the provided invoice number does not exist in VTEX", async () => {
|
|
230
|
+
getOrderDocumentMock.mockResolvedValueOnce({
|
|
231
|
+
status: "invoiced",
|
|
232
|
+
state: "handling",
|
|
233
|
+
invoiceData: {
|
|
234
|
+
invoices: [{ invoiceNumber: "INV-11" }]
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
await expect(
|
|
238
|
+
ordersWrite.validateOrderForTracking("profile-1", "order-4", "INV-99")
|
|
239
|
+
).rejects.toMatchObject({
|
|
240
|
+
name: "VtexOperationError",
|
|
241
|
+
code: "INVALID_OPERATION",
|
|
242
|
+
message: "The provided invoice number is not present in VTEX for this order.",
|
|
243
|
+
details: {
|
|
244
|
+
provided_invoice_number: "INV-99",
|
|
245
|
+
known_invoice_numbers: ["INV-11"]
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
//# sourceMappingURL=vtex-orders-write-state-validation.test.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/services/vtex/__tests__/vtex-orders-write-state-validation.test.ts"],
|
|
4
|
+
"sourcesContent": ["import { beforeEach, describe, expect, it, vi } from \"vitest\";\n\nconst getOrderDocumentMock = vi.fn();\n\nvi.mock(\"../vtex-orders.js\", () => ({\n getOrderDocument: getOrderDocumentMock,\n}));\n\nconst ordersWrite = await import(\"../vtex-orders-write.js\");\n\ndescribe(\"VTEX order write state validation\", () => {\n beforeEach(() => {\n vi.clearAllMocks();\n });\n\n describe(\"getOrderStateSnapshot\", () => {\n it(\"shapes the snapshot and extracts invoice numbers from invoices and outputs\", async () => {\n getOrderDocumentMock.mockResolvedValueOnce({\n status: \"handling\",\n state: \"payment-approved\",\n allowCancellation: true,\n invoicedDate: 1717171717,\n invoiceData: {\n invoices: [\n { invoiceNumber: 1234 },\n { number: \"A-100\" },\n { invoiceId: \"INV-9\" },\n { receipt: \"RCPT-1\" },\n { invoiceNumber: 1234 },\n ],\n invoiceOutput: [\"A-100\", 555, null],\n },\n });\n\n const snapshot = await ordersWrite.getOrderStateSnapshot(\n \"profile-1\",\n \"order-1\",\n \"validation-reason\"\n );\n\n expect(getOrderDocumentMock).toHaveBeenCalledWith(\n \"profile-1\",\n \"order-1\",\n \"validation-reason\"\n );\n expect(snapshot).toEqual({\n orderId: \"order-1\",\n status: \"handling\",\n state: \"payment-approved\",\n allowCancellation: true,\n invoicedDate: \"1717171717\",\n invoiceNumbers: [\"1234\", \"A-100\", \"INV-9\", \"RCPT-1\", \"555\"],\n });\n });\n\n it(\"returns an empty invoice list when invoice data is missing or malformed\", async () => {\n getOrderDocumentMock.mockResolvedValueOnce({\n status: null,\n state: undefined,\n allowCancellation: \"yes\",\n invoicedDate: null,\n invoiceData: \"unexpected\",\n });\n\n const snapshot = await ordersWrite.getOrderStateSnapshot(\"profile-1\", \"order-2\");\n\n expect(snapshot).toEqual({\n orderId: \"order-2\",\n status: undefined,\n state: undefined,\n allowCancellation: undefined,\n invoicedDate: undefined,\n invoiceNumbers: [],\n });\n });\n });\n\n describe(\"validateOrderForCancellation\", () => {\n it(\"returns the snapshot when the order is still cancelable\", async () => {\n getOrderDocumentMock.mockResolvedValueOnce({\n status: \"handling\",\n state: \"handling\",\n allowCancellation: true,\n });\n\n await expect(\n ordersWrite.validateOrderForCancellation(\"profile-1\", \"order-1\", \"customer-request\")\n ).resolves.toEqual({\n orderId: \"order-1\",\n status: \"handling\",\n state: \"handling\",\n allowCancellation: true,\n invoicedDate: undefined,\n invoiceNumbers: [],\n });\n });\n\n it(\"rejects cancellation for orders already canceled\", async () => {\n getOrderDocumentMock.mockResolvedValueOnce({ status: \"canceled\", state: \"cancelled\" });\n\n await expect(\n ordersWrite.validateOrderForCancellation(\"profile-1\", \"order-1\")\n ).rejects.toMatchObject({\n name: \"VtexOperationError\",\n code: \"INVALID_ORDER_STATE\",\n message: \"Order is already canceled.\",\n details: {\n status: \"canceled\",\n state: \"cancelled\",\n },\n });\n });\n\n it(\"rejects cancellation when VTEX disallows it\", async () => {\n getOrderDocumentMock.mockResolvedValueOnce({\n status: \"handling\",\n state: \"handling\",\n allowCancellation: false,\n });\n\n await expect(\n ordersWrite.validateOrderForCancellation(\"profile-1\", \"order-1\")\n ).rejects.toMatchObject({\n name: \"VtexOperationError\",\n code: \"INVALID_ORDER_STATE\",\n message: \"VTEX reports that this order can no longer be canceled.\",\n });\n });\n\n it(\"rejects cancellation for invoiced orders\", async () => {\n getOrderDocumentMock.mockResolvedValueOnce({\n status: \"handling\",\n state: \"handling\",\n allowCancellation: true,\n invoicedDate: \"2026-06-06T10:00:00.000Z\",\n });\n\n await expect(\n ordersWrite.validateOrderForCancellation(\"profile-1\", \"order-1\")\n ).rejects.toMatchObject({\n name: \"VtexOperationError\",\n code: \"INVALID_ORDER_STATE\",\n message: \"Order is already invoiced, so VTEX no longer allows cancellation.\",\n details: {\n invoiced_date: \"2026-06-06T10:00:00.000Z\",\n },\n });\n });\n });\n\n describe(\"validateOrderForInvoice\", () => {\n it(\"returns the snapshot when the order can be invoiced\", async () => {\n getOrderDocumentMock.mockResolvedValueOnce({ status: \"ready-for-handling\", state: \"ready\" });\n\n await expect(ordersWrite.validateOrderForInvoice(\"profile-1\", \"order-3\")).resolves.toEqual({\n orderId: \"order-3\",\n status: \"ready-for-handling\",\n state: \"ready\",\n allowCancellation: undefined,\n invoicedDate: undefined,\n invoiceNumbers: [],\n });\n });\n\n it(\"rejects invoicing for canceled orders\", async () => {\n getOrderDocumentMock.mockResolvedValueOnce({ status: \"canceling\", state: \"handling\" });\n\n await expect(ordersWrite.validateOrderForInvoice(\"profile-1\", \"order-3\")).rejects.toMatchObject({\n name: \"VtexOperationError\",\n code: \"INVALID_ORDER_STATE\",\n message: \"Canceled orders cannot be invoiced.\",\n });\n });\n\n it(\"rejects invoicing when invoice data already exists\", async () => {\n getOrderDocumentMock.mockResolvedValueOnce({\n status: \"handling\",\n state: \"handling\",\n invoicedDate: \"2026-06-06\",\n invoiceData: {\n invoices: [{ invoiceNumber: \"INV-1\" }],\n },\n });\n\n await expect(ordersWrite.validateOrderForInvoice(\"profile-1\", \"order-3\")).rejects.toMatchObject({\n name: \"VtexOperationError\",\n code: \"INVALID_ORDER_STATE\",\n message: \"Order already contains invoice data.\",\n details: {\n invoiced_date: \"2026-06-06\",\n invoice_numbers: [\"INV-1\"],\n },\n });\n });\n });\n\n describe(\"validateOrderForTracking\", () => {\n it(\"returns the snapshot when the invoice exists on the order\", async () => {\n getOrderDocumentMock.mockResolvedValueOnce({\n status: \"invoiced\",\n state: \"handling\",\n invoiceData: {\n invoices: [{ invoiceNumber: \"INV-10\" }],\n },\n });\n\n await expect(\n ordersWrite.validateOrderForTracking(\"profile-1\", \"order-4\", \"INV-10\")\n ).resolves.toEqual({\n orderId: \"order-4\",\n status: \"invoiced\",\n state: \"handling\",\n allowCancellation: undefined,\n invoicedDate: undefined,\n invoiceNumbers: [\"INV-10\"],\n });\n });\n\n it(\"allows tracking when VTEX marks the order invoiced even without invoice numbers\", async () => {\n getOrderDocumentMock.mockResolvedValueOnce({\n status: \"invoiced\",\n state: \"handling\",\n invoicedDate: \"2026-06-06T10:00:00.000Z\",\n });\n\n await expect(\n ordersWrite.validateOrderForTracking(\"profile-1\", \"order-5\", \"INV-MISSING\")\n ).resolves.toEqual({\n orderId: \"order-5\",\n status: \"invoiced\",\n state: \"handling\",\n allowCancellation: undefined,\n invoicedDate: \"2026-06-06T10:00:00.000Z\",\n invoiceNumbers: [],\n });\n });\n\n it(\"rejects tracking for canceled orders\", async () => {\n getOrderDocumentMock.mockResolvedValueOnce({ status: \"canceled\", state: \"handling\" });\n\n await expect(\n ordersWrite.validateOrderForTracking(\"profile-1\", \"order-4\", \"INV-10\")\n ).rejects.toMatchObject({\n name: \"VtexOperationError\",\n code: \"INVALID_ORDER_STATE\",\n message: \"Canceled orders cannot receive tracking updates.\",\n });\n });\n\n it(\"rejects tracking when the order is not invoiced yet\", async () => {\n getOrderDocumentMock.mockResolvedValueOnce({ status: \"handling\", state: \"handling\" });\n\n await expect(\n ordersWrite.validateOrderForTracking(\"profile-1\", \"order-4\", \"INV-10\")\n ).rejects.toMatchObject({\n name: \"VtexOperationError\",\n code: \"INVALID_ORDER_STATE\",\n message: \"Order is not invoiced yet, so tracking cannot be added.\",\n });\n });\n\n it(\"rejects tracking when the provided invoice number does not exist in VTEX\", async () => {\n getOrderDocumentMock.mockResolvedValueOnce({\n status: \"invoiced\",\n state: \"handling\",\n invoiceData: {\n invoices: [{ invoiceNumber: \"INV-11\" }],\n },\n });\n\n await expect(\n ordersWrite.validateOrderForTracking(\"profile-1\", \"order-4\", \"INV-99\")\n ).rejects.toMatchObject({\n name: \"VtexOperationError\",\n code: \"INVALID_OPERATION\",\n message: \"The provided invoice number is not present in VTEX for this order.\",\n details: {\n provided_invoice_number: \"INV-99\",\n known_invoice_numbers: [\"INV-11\"],\n },\n });\n });\n });\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
classifyVtexWriteRisk,
|
|
4
|
+
getPreviewRequirements
|
|
5
|
+
} from "../vtex-write.js";
|
|
6
|
+
describe("vtex-write risk and preview contracts", () => {
|
|
7
|
+
describe("classifyVtexWriteRisk", () => {
|
|
8
|
+
it("keeps low-risk operations as low", () => {
|
|
9
|
+
const result = classifyVtexWriteRisk({
|
|
10
|
+
requestedRiskLevel: "low",
|
|
11
|
+
preflight: {
|
|
12
|
+
entities: 1,
|
|
13
|
+
entityTypes: ["product"],
|
|
14
|
+
destructive: false,
|
|
15
|
+
hasDeleteOrReplaceAll: false,
|
|
16
|
+
dependencyFailureCount: 0,
|
|
17
|
+
multiEntityCriticalReassignment: false
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
expect(result.requested_risk_level).toBe("low");
|
|
21
|
+
expect(result.effective_risk_level).toBe("low");
|
|
22
|
+
expect(result.escalated).toBe(false);
|
|
23
|
+
expect(result.escalation_reasons).toEqual([]);
|
|
24
|
+
});
|
|
25
|
+
it("keeps medium-risk operations as medium when preflight is under thresholds", () => {
|
|
26
|
+
const result = classifyVtexWriteRisk({
|
|
27
|
+
requestedRiskLevel: "medium",
|
|
28
|
+
preflight: {
|
|
29
|
+
entities: 3,
|
|
30
|
+
entityTypes: ["product", "sku"],
|
|
31
|
+
destructive: false,
|
|
32
|
+
hasDeleteOrReplaceAll: false,
|
|
33
|
+
dependencyFailureCount: 0,
|
|
34
|
+
multiEntityCriticalReassignment: false
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
expect(result.effective_risk_level).toBe("medium");
|
|
38
|
+
expect(result.escalated).toBe(false);
|
|
39
|
+
expect(result.escalation_reasons).toEqual([]);
|
|
40
|
+
});
|
|
41
|
+
it("keeps high-risk operations as high", () => {
|
|
42
|
+
const result = classifyVtexWriteRisk({
|
|
43
|
+
requestedRiskLevel: "high",
|
|
44
|
+
preflight: {
|
|
45
|
+
entities: 1,
|
|
46
|
+
entityTypes: ["product"],
|
|
47
|
+
destructive: false,
|
|
48
|
+
hasDeleteOrReplaceAll: false,
|
|
49
|
+
dependencyFailureCount: 0,
|
|
50
|
+
multiEntityCriticalReassignment: false
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
expect(result.effective_risk_level).toBe("high");
|
|
54
|
+
expect(result.escalated).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
it("escalates medium-risk to high when entity threshold is exceeded", () => {
|
|
57
|
+
const result = classifyVtexWriteRisk({
|
|
58
|
+
requestedRiskLevel: "medium",
|
|
59
|
+
preflight: {
|
|
60
|
+
entities: 11,
|
|
61
|
+
entityTypes: ["product"],
|
|
62
|
+
destructive: false,
|
|
63
|
+
hasDeleteOrReplaceAll: false,
|
|
64
|
+
dependencyFailureCount: 0,
|
|
65
|
+
multiEntityCriticalReassignment: false
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
expect(result.effective_risk_level).toBe("high");
|
|
69
|
+
expect(result.escalated).toBe(true);
|
|
70
|
+
expect(result.escalation_reasons).toContain("entities_threshold_exceeded");
|
|
71
|
+
});
|
|
72
|
+
it("escalates medium-risk to high when operation is destructive", () => {
|
|
73
|
+
const result = classifyVtexWriteRisk({
|
|
74
|
+
requestedRiskLevel: "medium",
|
|
75
|
+
preflight: {
|
|
76
|
+
entities: 2,
|
|
77
|
+
entityTypes: ["product"],
|
|
78
|
+
destructive: true,
|
|
79
|
+
hasDeleteOrReplaceAll: false,
|
|
80
|
+
dependencyFailureCount: 0,
|
|
81
|
+
multiEntityCriticalReassignment: false
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
expect(result.effective_risk_level).toBe("high");
|
|
85
|
+
expect(result.escalated).toBe(true);
|
|
86
|
+
expect(result.escalation_reasons).toContain("destructive_operation_detected");
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
describe("getPreviewRequirements", () => {
|
|
90
|
+
it("does not require preview for low risk", () => {
|
|
91
|
+
const result = getPreviewRequirements("low");
|
|
92
|
+
expect(result.preview_required).toBe(false);
|
|
93
|
+
expect(result.apply_requires_confirmation).toBe(false);
|
|
94
|
+
expect(result.preview_id_required_for_apply).toBe(false);
|
|
95
|
+
});
|
|
96
|
+
it("does not require preview for medium risk", () => {
|
|
97
|
+
const result = getPreviewRequirements("medium");
|
|
98
|
+
expect(result.preview_required).toBe(false);
|
|
99
|
+
expect(result.apply_requires_confirmation).toBe(false);
|
|
100
|
+
expect(result.preview_id_required_for_apply).toBe(false);
|
|
101
|
+
});
|
|
102
|
+
it("requires preview and confirmation for high risk", () => {
|
|
103
|
+
const result = getPreviewRequirements("high");
|
|
104
|
+
expect(result.preview_required).toBe(true);
|
|
105
|
+
expect(result.apply_requires_confirmation).toBe(true);
|
|
106
|
+
expect(result.preview_id_required_for_apply).toBe(true);
|
|
107
|
+
expect(result.reason).toContain("high-risk");
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
//# sourceMappingURL=vtex-write.test.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/services/vtex/__tests__/vtex-write.test.ts"],
|
|
4
|
+
"sourcesContent": ["import { describe, expect, it } from \"vitest\";\n\nimport {\n classifyVtexWriteRisk,\n getPreviewRequirements,\n} from \"../vtex-write.js\";\n\ndescribe(\"vtex-write risk and preview contracts\", () => {\n describe(\"classifyVtexWriteRisk\", () => {\n it(\"keeps low-risk operations as low\", () => {\n const result = classifyVtexWriteRisk({\n requestedRiskLevel: \"low\",\n preflight: {\n entities: 1,\n entityTypes: [\"product\"],\n destructive: false,\n hasDeleteOrReplaceAll: false,\n dependencyFailureCount: 0,\n multiEntityCriticalReassignment: false,\n },\n });\n\n expect(result.requested_risk_level).toBe(\"low\");\n expect(result.effective_risk_level).toBe(\"low\");\n expect(result.escalated).toBe(false);\n expect(result.escalation_reasons).toEqual([]);\n });\n\n it(\"keeps medium-risk operations as medium when preflight is under thresholds\", () => {\n const result = classifyVtexWriteRisk({\n requestedRiskLevel: \"medium\",\n preflight: {\n entities: 3,\n entityTypes: [\"product\", \"sku\"],\n destructive: false,\n hasDeleteOrReplaceAll: false,\n dependencyFailureCount: 0,\n multiEntityCriticalReassignment: false,\n },\n });\n\n expect(result.effective_risk_level).toBe(\"medium\");\n expect(result.escalated).toBe(false);\n expect(result.escalation_reasons).toEqual([]);\n });\n\n it(\"keeps high-risk operations as high\", () => {\n const result = classifyVtexWriteRisk({\n requestedRiskLevel: \"high\",\n preflight: {\n entities: 1,\n entityTypes: [\"product\"],\n destructive: false,\n hasDeleteOrReplaceAll: false,\n dependencyFailureCount: 0,\n multiEntityCriticalReassignment: false,\n },\n });\n\n expect(result.effective_risk_level).toBe(\"high\");\n expect(result.escalated).toBe(false);\n });\n\n it(\"escalates medium-risk to high when entity threshold is exceeded\", () => {\n const result = classifyVtexWriteRisk({\n requestedRiskLevel: \"medium\",\n preflight: {\n entities: 11,\n entityTypes: [\"product\"],\n destructive: false,\n hasDeleteOrReplaceAll: false,\n dependencyFailureCount: 0,\n multiEntityCriticalReassignment: false,\n },\n });\n\n expect(result.effective_risk_level).toBe(\"high\");\n expect(result.escalated).toBe(true);\n expect(result.escalation_reasons).toContain(\"entities_threshold_exceeded\");\n });\n\n it(\"escalates medium-risk to high when operation is destructive\", () => {\n const result = classifyVtexWriteRisk({\n requestedRiskLevel: \"medium\",\n preflight: {\n entities: 2,\n entityTypes: [\"product\"],\n destructive: true,\n hasDeleteOrReplaceAll: false,\n dependencyFailureCount: 0,\n multiEntityCriticalReassignment: false,\n },\n });\n\n expect(result.effective_risk_level).toBe(\"high\");\n expect(result.escalated).toBe(true);\n expect(result.escalation_reasons).toContain(\"destructive_operation_detected\");\n });\n });\n\n describe(\"getPreviewRequirements\", () => {\n it(\"does not require preview for low risk\", () => {\n const result = getPreviewRequirements(\"low\");\n\n expect(result.preview_required).toBe(false);\n expect(result.apply_requires_confirmation).toBe(false);\n expect(result.preview_id_required_for_apply).toBe(false);\n });\n\n it(\"does not require preview for medium risk\", () => {\n const result = getPreviewRequirements(\"medium\");\n\n expect(result.preview_required).toBe(false);\n expect(result.apply_requires_confirmation).toBe(false);\n expect(result.preview_id_required_for_apply).toBe(false);\n });\n\n it(\"requires preview and confirmation for high risk\", () => {\n const result = getPreviewRequirements(\"high\");\n\n expect(result.preview_required).toBe(true);\n expect(result.apply_requires_confirmation).toBe(true);\n expect(result.preview_id_required_for_apply).toBe(true);\n expect(result.reason).toContain(\"high-risk\");\n });\n });\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -151,6 +151,37 @@ async function deleteAllSkuEans(profileId, skuId) {
|
|
|
151
151
|
const { vtexApi } = await getVtexApiClients(profileId);
|
|
152
152
|
await vtexApi.delete(`/api/catalog/pvt/stockkeepingunit/${skuId}/ean`);
|
|
153
153
|
}
|
|
154
|
+
function normalizeEans(eans) {
|
|
155
|
+
const normalized = eans.map((ean) => ean.trim()).filter(Boolean);
|
|
156
|
+
return [...new Set(normalized)];
|
|
157
|
+
}
|
|
158
|
+
async function addSkuEan(profileId, skuId, ean) {
|
|
159
|
+
const normalized = ean.trim();
|
|
160
|
+
if (!normalized) {
|
|
161
|
+
return getSkuEans(profileId, skuId);
|
|
162
|
+
}
|
|
163
|
+
await createSkuEan(profileId, skuId, normalized);
|
|
164
|
+
return getSkuEans(profileId, skuId);
|
|
165
|
+
}
|
|
166
|
+
async function replaceSkuEans(profileId, skuId, eans) {
|
|
167
|
+
await deleteAllSkuEans(profileId, skuId);
|
|
168
|
+
for (const ean of normalizeEans(eans)) {
|
|
169
|
+
await createSkuEan(profileId, skuId, ean);
|
|
170
|
+
}
|
|
171
|
+
return getSkuEans(profileId, skuId);
|
|
172
|
+
}
|
|
173
|
+
async function updateProductBasicFields(profileId, productId, updates) {
|
|
174
|
+
const before = await getProduct(profileId, productId);
|
|
175
|
+
const payload = buildProductUpdatePayload(before, updates);
|
|
176
|
+
const after = await updateProduct(profileId, productId, payload);
|
|
177
|
+
return { before, payload, after };
|
|
178
|
+
}
|
|
179
|
+
async function updateSkuBasicFields(profileId, skuId, updates) {
|
|
180
|
+
const before = await getSku(profileId, skuId);
|
|
181
|
+
const payload = buildSkuUpdatePayload(before, updates);
|
|
182
|
+
const after = await updateSku(profileId, skuId, payload);
|
|
183
|
+
return { before, payload, after };
|
|
184
|
+
}
|
|
154
185
|
async function createBrand(profileId, payload) {
|
|
155
186
|
const { vtexApi } = await getVtexApiClients(profileId);
|
|
156
187
|
const response = await vtexApi.post("/api/catalog/pvt/brand", payload);
|
|
@@ -161,6 +192,35 @@ async function getBrand(profileId, brandId) {
|
|
|
161
192
|
const response = await vtexApi.get(`/api/catalog/pvt/brand/${brandId}`);
|
|
162
193
|
return response.data;
|
|
163
194
|
}
|
|
195
|
+
async function updateBrand(profileId, brandId, payload) {
|
|
196
|
+
const { vtexApi } = await getVtexApiClients(profileId);
|
|
197
|
+
const response = await vtexApi.put(`/api/catalog/pvt/brand/${brandId}`, payload);
|
|
198
|
+
return response.data;
|
|
199
|
+
}
|
|
200
|
+
function buildBrandUpdatePayload(current, updates) {
|
|
201
|
+
const payload = pickRecord(current, [
|
|
202
|
+
"Id",
|
|
203
|
+
"Name",
|
|
204
|
+
"Text",
|
|
205
|
+
"Keywords",
|
|
206
|
+
"SiteTitle",
|
|
207
|
+
"Active",
|
|
208
|
+
"MenuHome",
|
|
209
|
+
"LinkId",
|
|
210
|
+
"Score",
|
|
211
|
+
"AdWordsRemarketingCode",
|
|
212
|
+
"LomadeeCampaignCode"
|
|
213
|
+
]);
|
|
214
|
+
if (updates.name !== void 0) payload.Name = updates.name;
|
|
215
|
+
if (updates.text !== void 0) payload.Text = updates.text;
|
|
216
|
+
if (updates.keywords !== void 0) payload.Keywords = updates.keywords;
|
|
217
|
+
if (updates.siteTitle !== void 0) payload.SiteTitle = updates.siteTitle;
|
|
218
|
+
if (updates.active !== void 0) payload.Active = updates.active;
|
|
219
|
+
if (updates.menuHome !== void 0) payload.MenuHome = updates.menuHome;
|
|
220
|
+
if (updates.linkId !== void 0) payload.LinkId = updates.linkId;
|
|
221
|
+
if (updates.score !== void 0) payload.Score = updates.score;
|
|
222
|
+
return payload;
|
|
223
|
+
}
|
|
164
224
|
async function createCategory(profileId, payload) {
|
|
165
225
|
const { vtexApi } = await getVtexApiClients(profileId);
|
|
166
226
|
const response = await vtexApi.post("/api/catalog/pvt/category", payload);
|
|
@@ -171,11 +231,54 @@ async function getCategory(profileId, categoryId) {
|
|
|
171
231
|
const response = await vtexApi.get(`/api/catalog/pvt/category/${categoryId}`);
|
|
172
232
|
return response.data;
|
|
173
233
|
}
|
|
234
|
+
async function updateCategory(profileId, categoryId, payload) {
|
|
235
|
+
const { vtexApi } = await getVtexApiClients(profileId);
|
|
236
|
+
const response = await vtexApi.put(`/api/catalog/pvt/category/${categoryId}`, payload);
|
|
237
|
+
return response.data;
|
|
238
|
+
}
|
|
239
|
+
function buildCategoryUpdatePayload(current, updates) {
|
|
240
|
+
const payload = pickRecord(current, [
|
|
241
|
+
"Id",
|
|
242
|
+
"Name",
|
|
243
|
+
"Keywords",
|
|
244
|
+
"Title",
|
|
245
|
+
"Description",
|
|
246
|
+
"AdWordsRemarketingCode",
|
|
247
|
+
"LomadeeCampaignCode",
|
|
248
|
+
"FatherCategoryId",
|
|
249
|
+
"GlobalCategoryId",
|
|
250
|
+
"ShowInStoreFront",
|
|
251
|
+
"IsActive",
|
|
252
|
+
"ActiveStoreFrontLink",
|
|
253
|
+
"ShowBrandFilter",
|
|
254
|
+
"Score",
|
|
255
|
+
"StockKeepingUnitSelectionMode"
|
|
256
|
+
]);
|
|
257
|
+
if (updates.name !== void 0) payload.Name = updates.name;
|
|
258
|
+
if (updates.title !== void 0) payload.Title = updates.title;
|
|
259
|
+
if (updates.description !== void 0) payload.Description = updates.description;
|
|
260
|
+
if (updates.keywords !== void 0) payload.Keywords = updates.keywords;
|
|
261
|
+
if (updates.isActive !== void 0) payload.IsActive = updates.isActive;
|
|
262
|
+
if (updates.fatherCategoryId !== void 0) {
|
|
263
|
+
payload.FatherCategoryId = updates.fatherCategoryId;
|
|
264
|
+
}
|
|
265
|
+
return payload;
|
|
266
|
+
}
|
|
174
267
|
async function createSpecification(profileId, payload) {
|
|
175
268
|
const { vtexApi } = await getVtexApiClients(profileId);
|
|
176
269
|
const response = await vtexApi.post("/api/catalog/pvt/specification", payload);
|
|
177
270
|
return response.data;
|
|
178
271
|
}
|
|
272
|
+
async function getSpecification(profileId, fieldId) {
|
|
273
|
+
const { vtexApi } = await getVtexApiClients(profileId);
|
|
274
|
+
const response = await vtexApi.get(`/api/catalog/pvt/specification/${fieldId}`);
|
|
275
|
+
return response.data;
|
|
276
|
+
}
|
|
277
|
+
async function updateSpecification(profileId, fieldId, payload) {
|
|
278
|
+
const { vtexApi } = await getVtexApiClients(profileId);
|
|
279
|
+
const response = await vtexApi.put(`/api/catalog/pvt/specification/${fieldId}`, payload);
|
|
280
|
+
return response.data;
|
|
281
|
+
}
|
|
179
282
|
async function createSpecificationValue(profileId, payload) {
|
|
180
283
|
const { vtexApi } = await getVtexApiClients(profileId);
|
|
181
284
|
const response = await vtexApi.post(
|
|
@@ -184,6 +287,21 @@ async function createSpecificationValue(profileId, payload) {
|
|
|
184
287
|
);
|
|
185
288
|
return response.data;
|
|
186
289
|
}
|
|
290
|
+
async function getSpecificationValue(profileId, fieldValueId) {
|
|
291
|
+
const { vtexApi } = await getVtexApiClients(profileId);
|
|
292
|
+
const response = await vtexApi.get(
|
|
293
|
+
`/api/catalog/pvt/specificationvalue/${fieldValueId}`
|
|
294
|
+
);
|
|
295
|
+
return response.data;
|
|
296
|
+
}
|
|
297
|
+
async function updateSpecificationValue(profileId, fieldValueId, payload) {
|
|
298
|
+
const { vtexApi } = await getVtexApiClients(profileId);
|
|
299
|
+
const response = await vtexApi.put(
|
|
300
|
+
`/api/catalog/pvt/specificationvalue/${fieldValueId}`,
|
|
301
|
+
payload
|
|
302
|
+
);
|
|
303
|
+
return response.data;
|
|
304
|
+
}
|
|
187
305
|
async function associateProductSpecification(profileId, productId, payload) {
|
|
188
306
|
const { vtexApi } = await getVtexApiClients(profileId);
|
|
189
307
|
const response = await vtexApi.post(
|
|
@@ -192,6 +310,39 @@ async function associateProductSpecification(profileId, productId, payload) {
|
|
|
192
310
|
);
|
|
193
311
|
return response.data;
|
|
194
312
|
}
|
|
313
|
+
async function getProductSpecifications(profileId, productId) {
|
|
314
|
+
const { vtexApi } = await getVtexApiClients(profileId);
|
|
315
|
+
const response = await vtexApi.get(`/api/catalog/pvt/product/${productId}/specification`);
|
|
316
|
+
const data = response.data;
|
|
317
|
+
if (!Array.isArray(data)) {
|
|
318
|
+
return [];
|
|
319
|
+
}
|
|
320
|
+
return data.filter((item) => item !== null && typeof item === "object");
|
|
321
|
+
}
|
|
322
|
+
async function deleteProductSpecification(profileId, productId, specificationId) {
|
|
323
|
+
const { vtexApi } = await getVtexApiClients(profileId);
|
|
324
|
+
await vtexApi.delete(`/api/catalog/pvt/product/${productId}/specification/${specificationId}`);
|
|
325
|
+
}
|
|
326
|
+
async function deleteAllProductSpecifications(profileId, productId) {
|
|
327
|
+
const { vtexApi } = await getVtexApiClients(profileId);
|
|
328
|
+
await vtexApi.delete(`/api/catalog/pvt/product/${productId}/specification`);
|
|
329
|
+
}
|
|
330
|
+
async function deleteBrand(profileId, brandId) {
|
|
331
|
+
const { vtexApi } = await getVtexApiClients(profileId);
|
|
332
|
+
await vtexApi.delete(`/api/catalog/pvt/brand/${brandId}`);
|
|
333
|
+
}
|
|
334
|
+
async function deleteSkuFile(profileId, skuId, fileId) {
|
|
335
|
+
const { vtexApi } = await getVtexApiClients(profileId);
|
|
336
|
+
await vtexApi.delete(`/api/catalog/pvt/stockkeepingunit/${skuId}/file/${fileId}`);
|
|
337
|
+
}
|
|
338
|
+
async function deleteSkuSpecification(profileId, skuId, specificationId) {
|
|
339
|
+
const { vtexApi } = await getVtexApiClients(profileId);
|
|
340
|
+
await vtexApi.delete(`/api/catalog/pvt/stockkeepingunit/${skuId}/specification/${specificationId}`);
|
|
341
|
+
}
|
|
342
|
+
async function deleteAllSkuSpecifications(profileId, skuId) {
|
|
343
|
+
const { vtexApi } = await getVtexApiClients(profileId);
|
|
344
|
+
await vtexApi.delete(`/api/catalog/pvt/stockkeepingunit/${skuId}/specification`);
|
|
345
|
+
}
|
|
195
346
|
async function associateSkuSpecification(profileId, skuId, payload) {
|
|
196
347
|
const { vtexApi } = await getVtexApiClients(profileId);
|
|
197
348
|
const response = await vtexApi.post(
|
|
@@ -208,9 +359,33 @@ async function createSkuFile(profileId, skuId, payload) {
|
|
|
208
359
|
);
|
|
209
360
|
return response.data;
|
|
210
361
|
}
|
|
362
|
+
async function getSkuImages(profileId, skuId) {
|
|
363
|
+
const { vtexApi } = await getVtexApiClients(profileId);
|
|
364
|
+
const response = await vtexApi.get(`/api/catalog/pvt/stockkeepingunit/${skuId}/file`);
|
|
365
|
+
const data = response.data;
|
|
366
|
+
if (!Array.isArray(data)) {
|
|
367
|
+
return [];
|
|
368
|
+
}
|
|
369
|
+
return data.filter((item) => item !== null && typeof item === "object");
|
|
370
|
+
}
|
|
371
|
+
async function attachSkuImage(profileId, skuId, payload) {
|
|
372
|
+
return createSkuFile(profileId, skuId, { ...payload });
|
|
373
|
+
}
|
|
374
|
+
async function updateSkuImage(profileId, skuId, imageId, payload) {
|
|
375
|
+
const { vtexApi } = await getVtexApiClients(profileId);
|
|
376
|
+
const response = await vtexApi.put(
|
|
377
|
+
`/api/catalog/pvt/stockkeepingunit/${skuId}/file/${imageId}`,
|
|
378
|
+
payload
|
|
379
|
+
);
|
|
380
|
+
return response.data;
|
|
381
|
+
}
|
|
211
382
|
export {
|
|
383
|
+
addSkuEan,
|
|
212
384
|
associateProductSpecification,
|
|
213
385
|
associateSkuSpecification,
|
|
386
|
+
attachSkuImage,
|
|
387
|
+
buildBrandUpdatePayload,
|
|
388
|
+
buildCategoryUpdatePayload,
|
|
214
389
|
buildProductUpdatePayload,
|
|
215
390
|
buildSkuUpdatePayload,
|
|
216
391
|
createBrand,
|
|
@@ -221,13 +396,31 @@ export {
|
|
|
221
396
|
createSkuFile,
|
|
222
397
|
createSpecification,
|
|
223
398
|
createSpecificationValue,
|
|
399
|
+
deleteAllProductSpecifications,
|
|
224
400
|
deleteAllSkuEans,
|
|
401
|
+
deleteAllSkuSpecifications,
|
|
402
|
+
deleteBrand,
|
|
403
|
+
deleteProductSpecification,
|
|
404
|
+
deleteSkuFile,
|
|
405
|
+
deleteSkuSpecification,
|
|
225
406
|
getBrand,
|
|
226
407
|
getCategory,
|
|
227
408
|
getProduct,
|
|
409
|
+
getProductSpecifications,
|
|
228
410
|
getSku,
|
|
229
411
|
getSkuEans,
|
|
412
|
+
getSkuImages,
|
|
413
|
+
getSpecification,
|
|
414
|
+
getSpecificationValue,
|
|
415
|
+
replaceSkuEans,
|
|
416
|
+
updateBrand,
|
|
417
|
+
updateCategory,
|
|
230
418
|
updateProduct,
|
|
231
|
-
|
|
419
|
+
updateProductBasicFields,
|
|
420
|
+
updateSku,
|
|
421
|
+
updateSkuBasicFields,
|
|
422
|
+
updateSkuImage,
|
|
423
|
+
updateSpecification,
|
|
424
|
+
updateSpecificationValue
|
|
232
425
|
};
|
|
233
426
|
//# sourceMappingURL=vtex-catalog-write.js.map
|