@odooconnector/medusa-odoo-connector 0.1.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.
Files changed (42) hide show
  1. package/.medusa/server/src/admin/index.js +2211 -0
  2. package/.medusa/server/src/admin/index.mjs +2212 -0
  3. package/.medusa/server/src/api/admin/odoo/billing/route.js +15 -0
  4. package/.medusa/server/src/api/admin/odoo/clear-orders/route.js +33 -0
  5. package/.medusa/server/src/api/admin/odoo/clear-products/route.js +30 -0
  6. package/.medusa/server/src/api/admin/odoo/config/route.js +44 -0
  7. package/.medusa/server/src/api/admin/odoo/customer-options/route.js +15 -0
  8. package/.medusa/server/src/api/admin/odoo/inventory-options/route.js +15 -0
  9. package/.medusa/server/src/api/admin/odoo/jobs/[id]/route.js +25 -0
  10. package/.medusa/server/src/api/admin/odoo/logs/route.js +27 -0
  11. package/.medusa/server/src/api/admin/odoo/options/route.js +15 -0
  12. package/.medusa/server/src/api/admin/odoo/order-options/route.js +15 -0
  13. package/.medusa/server/src/api/admin/odoo/product-options/route.js +15 -0
  14. package/.medusa/server/src/api/admin/odoo/sections/[section]/route.js +55 -0
  15. package/.medusa/server/src/api/admin/odoo/settings/route.js +91 -0
  16. package/.medusa/server/src/api/admin/odoo/stripe/change/route.js +20 -0
  17. package/.medusa/server/src/api/admin/odoo/stripe/checkout/route.js +20 -0
  18. package/.medusa/server/src/api/admin/odoo/stripe/portal/route.js +16 -0
  19. package/.medusa/server/src/api/admin/odoo/sync/[entity]/route.js +99 -0
  20. package/.medusa/server/src/api/admin/odoo/sync-order/[id]/route.js +17 -0
  21. package/.medusa/server/src/api/admin/odoo/verify-connection/route.js +39 -0
  22. package/.medusa/server/src/api/odoo/billing/sync/route.js +42 -0
  23. package/.medusa/server/src/index.js +3 -0
  24. package/.medusa/server/src/jobs/import-worker.js +61 -0
  25. package/.medusa/server/src/lib/export-products.js +141 -0
  26. package/.medusa/server/src/lib/import-products.js +304 -0
  27. package/.medusa/server/src/lib/odoo-api-client.js +32 -0
  28. package/.medusa/server/src/lib/plan.js +83 -0
  29. package/.medusa/server/src/lib/queue.js +79 -0
  30. package/.medusa/server/src/lib/sync-customers.js +183 -0
  31. package/.medusa/server/src/lib/sync-inventory.js +135 -0
  32. package/.medusa/server/src/lib/sync-order.js +134 -0
  33. package/.medusa/server/src/lib/sync-products.js +32 -0
  34. package/.medusa/server/src/modules/odoo/index.js +13 -0
  35. package/.medusa/server/src/modules/odoo/migrations/Migration20260619101616.js +17 -0
  36. package/.medusa/server/src/modules/odoo/models/odoo-setting.js +19 -0
  37. package/.medusa/server/src/modules/odoo/service.js +28 -0
  38. package/.medusa/server/src/subscribers/order-placed.js +24 -0
  39. package/.medusa/server/src/workflows/index.js +3 -0
  40. package/LICENSE +21 -0
  41. package/README.md +106 -0
  42. package/package.json +81 -0
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = void 0;
4
+ const odoo_api_client_1 = require("../../../../lib/odoo-api-client");
5
+ // GET /admin/odoo/billing — current subscription state (proxied from odoo-api).
6
+ const GET = async (_req, res) => {
7
+ try {
8
+ res.json(await (0, odoo_api_client_1.odooApi)("/odoo/billing"));
9
+ }
10
+ catch (e) {
11
+ res.status(400).json({ message: e?.message ?? "Could not load billing state" });
12
+ }
13
+ };
14
+ exports.GET = GET;
15
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29kb28vYmlsbGluZy9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxxRUFBeUQ7QUFFekQsZ0ZBQWdGO0FBQ3pFLE1BQU0sR0FBRyxHQUFHLEtBQUssRUFBRSxJQUFtQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNwRSxJQUFJLENBQUM7UUFDSCxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBQSx5QkFBTyxFQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUE7SUFDMUMsQ0FBQztJQUFDLE9BQU8sQ0FBTSxFQUFFLENBQUM7UUFDaEIsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLE9BQU8sSUFBSSw4QkFBOEIsRUFBRSxDQUFDLENBQUE7SUFDakYsQ0FBQztBQUNILENBQUMsQ0FBQTtBQU5ZLFFBQUEsR0FBRyxPQU1mIn0=
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ /**
6
+ * POST /admin/odoo/clear-orders
7
+ * Removes the Odoo link (metadata.odoo_order_id) from synced orders. The orders
8
+ * are kept — only the link is cleared, so they become eligible to sync again.
9
+ * (Does NOT delete or modify anything in Odoo.)
10
+ */
11
+ const POST = async (req, res) => {
12
+ const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
13
+ const { data } = await query.graph({
14
+ entity: "order",
15
+ fields: ["id", "metadata"],
16
+ pagination: { take: 1000 },
17
+ });
18
+ // The Order module MERGES metadata on update, so omitting a key does not
19
+ // delete it — we must explicitly null it out to break the Odoo link.
20
+ const orders = data
21
+ .filter((o) => o.metadata?.odoo_order_id != null)
22
+ .map((o) => ({
23
+ id: o.id,
24
+ metadata: { ...o.metadata, odoo_order_id: null },
25
+ }));
26
+ if (orders.length) {
27
+ const orderModule = req.scope.resolve(utils_1.Modules.ORDER);
28
+ await orderModule.updateOrders(orders);
29
+ }
30
+ res.json({ cleared: orders.length });
31
+ };
32
+ exports.POST = POST;
33
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29kb28vY2xlYXItb3JkZXJzL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHFEQUE4RTtBQUU5RTs7Ozs7R0FLRztBQUNJLE1BQU0sSUFBSSxHQUFHLEtBQUssRUFBRSxHQUFrQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNwRSxNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUVoRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDO1FBQ2pDLE1BQU0sRUFBRSxPQUFPO1FBQ2YsTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQztRQUMxQixVQUFVLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFO0tBQzNCLENBQUMsQ0FBQTtJQUVGLHlFQUF5RTtJQUN6RSxxRUFBcUU7SUFDckUsTUFBTSxNQUFNLEdBQUcsSUFBSTtTQUNoQixNQUFNLENBQUMsQ0FBQyxDQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsYUFBYSxJQUFJLElBQUksQ0FBQztTQUNyRCxHQUFHLENBQUMsQ0FBQyxDQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDaEIsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFO1FBQ1IsUUFBUSxFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUMsUUFBUSxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUU7S0FDakQsQ0FBQyxDQUFDLENBQUE7SUFFTCxJQUFJLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNsQixNQUFNLFdBQVcsR0FBUSxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxlQUFPLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDekQsTUFBTSxXQUFXLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBQ3hDLENBQUM7SUFFRCxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFBO0FBQ3RDLENBQUMsQ0FBQTtBQXhCWSxRQUFBLElBQUksUUF3QmhCIn0=
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const core_flows_1 = require("@medusajs/medusa/core-flows");
6
+ /**
7
+ * POST /admin/odoo/clear-products
8
+ * Removes the Odoo link (metadata.odoo_id) from imported products. The products
9
+ * are kept — only the link is cleared, so they're no longer matched on import.
10
+ */
11
+ const POST = async (req, res) => {
12
+ const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
13
+ const { data } = await query.graph({
14
+ entity: "product",
15
+ fields: ["id", "metadata"],
16
+ pagination: { take: 1000 },
17
+ });
18
+ const products = data
19
+ .filter((p) => p.metadata?.odoo_id != null)
20
+ .map((p) => {
21
+ const { odoo_id, ...rest } = p.metadata;
22
+ return { id: p.id, metadata: rest };
23
+ });
24
+ if (products.length) {
25
+ await (0, core_flows_1.updateProductsWorkflow)(req.scope).run({ input: { products } });
26
+ }
27
+ res.json({ cleared: products.length });
28
+ };
29
+ exports.POST = POST;
30
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29kb28vY2xlYXItcHJvZHVjdHMvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EscURBQXFFO0FBQ3JFLDREQUFvRTtBQUVwRTs7OztHQUlHO0FBQ0ksTUFBTSxJQUFJLEdBQUcsS0FBSyxFQUFFLEdBQWtCLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ3BFLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLEtBQUssQ0FBQyxDQUFBO0lBRWhFLE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUM7UUFDakMsTUFBTSxFQUFFLFNBQVM7UUFDakIsTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQztRQUMxQixVQUFVLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFO0tBQzNCLENBQUMsQ0FBQTtJQUVGLE1BQU0sUUFBUSxHQUFHLElBQUk7U0FDbEIsTUFBTSxDQUFDLENBQUMsQ0FBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLE9BQU8sSUFBSSxJQUFJLENBQUM7U0FDL0MsR0FBRyxDQUFDLENBQUMsQ0FBTSxFQUFFLEVBQUU7UUFDZCxNQUFNLEVBQUUsT0FBTyxFQUFFLEdBQUcsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQTtRQUN2QyxPQUFPLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFBO0lBQ3JDLENBQUMsQ0FBQyxDQUFBO0lBRUosSUFBSSxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDcEIsTUFBTSxJQUFBLG1DQUFzQixFQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUE7SUFDdEUsQ0FBQztJQUVELEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUE7QUFDeEMsQ0FBQyxDQUFBO0FBckJZLFFBQUEsSUFBSSxRQXFCaEIifQ==
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = exports.GET = void 0;
4
+ const odoo_1 = require("../../../../modules/odoo");
5
+ const odoo_api_client_1 = require("../../../../lib/odoo-api-client");
6
+ const KEY = "config";
7
+ const DEFAULTS = {
8
+ sku_mapping: "sku",
9
+ company_id: null,
10
+ company_label: null,
11
+ sale_journal_id: null,
12
+ sale_journal_label: null,
13
+ fixed_tax_mapping: false,
14
+ };
15
+ // GET /admin/odoo/config — general configuration (Medusa-stored).
16
+ const GET = async (req, res) => {
17
+ const svc = req.scope.resolve(odoo_1.ODOO_MODULE);
18
+ const config = (await svc.getValue(KEY)) ?? null;
19
+ res.json({ configured: Boolean(config), config: config ?? { ...DEFAULTS } });
20
+ };
21
+ exports.GET = GET;
22
+ // POST /admin/odoo/config — save in Medusa + push to odoo-api cache.
23
+ const POST = async (req, res) => {
24
+ const svc = req.scope.resolve(odoo_1.ODOO_MODULE);
25
+ const b = (req.body ?? {});
26
+ const config = {
27
+ sku_mapping: b.sku_mapping === "barcode" ? "barcode" : "sku",
28
+ company_id: b.company_id != null ? Number(b.company_id) : null,
29
+ company_label: b.company_label ?? null,
30
+ sale_journal_id: b.sale_journal_id != null ? Number(b.sale_journal_id) : null,
31
+ sale_journal_label: b.sale_journal_label ?? null,
32
+ fixed_tax_mapping: Boolean(b.fixed_tax_mapping),
33
+ };
34
+ await svc.setValue(KEY, config);
35
+ try {
36
+ await (0, odoo_api_client_1.odooApi)("/odoo/config", { method: "POST", body: JSON.stringify(config) });
37
+ }
38
+ catch {
39
+ /* cache sync non-critical */
40
+ }
41
+ res.json({ configured: true, config });
42
+ };
43
+ exports.POST = POST;
44
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29kb28vY29uZmlnL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLG1EQUFzRDtBQUV0RCxxRUFBeUQ7QUFFekQsTUFBTSxHQUFHLEdBQUcsUUFBUSxDQUFBO0FBRXBCLE1BQU0sUUFBUSxHQUFHO0lBQ2YsV0FBVyxFQUFFLEtBQUs7SUFDbEIsVUFBVSxFQUFFLElBQUk7SUFDaEIsYUFBYSxFQUFFLElBQUk7SUFDbkIsZUFBZSxFQUFFLElBQUk7SUFDckIsa0JBQWtCLEVBQUUsSUFBSTtJQUN4QixpQkFBaUIsRUFBRSxLQUFLO0NBQ3pCLENBQUE7QUFFRCxrRUFBa0U7QUFDM0QsTUFBTSxHQUFHLEdBQUcsS0FBSyxFQUFFLEdBQWtCLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ25FLE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFxQixrQkFBVyxDQUFDLENBQUE7SUFDOUQsTUFBTSxNQUFNLEdBQUcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUE7SUFDaEQsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLFVBQVUsRUFBRSxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUUsTUFBTSxFQUFFLE1BQU0sSUFBSSxFQUFFLEdBQUcsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFBO0FBQzlFLENBQUMsQ0FBQTtBQUpZLFFBQUEsR0FBRyxPQUlmO0FBRUQscUVBQXFFO0FBQzlELE1BQU0sSUFBSSxHQUFHLEtBQUssRUFBRSxHQUFrQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNwRSxNQUFNLEdBQUcsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBcUIsa0JBQVcsQ0FBQyxDQUFBO0lBQzlELE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksSUFBSSxFQUFFLENBQXdCLENBQUE7SUFDakQsTUFBTSxNQUFNLEdBQUc7UUFDYixXQUFXLEVBQUUsQ0FBQyxDQUFDLFdBQVcsS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSztRQUM1RCxVQUFVLEVBQUUsQ0FBQyxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUk7UUFDOUQsYUFBYSxFQUFFLENBQUMsQ0FBQyxhQUFhLElBQUksSUFBSTtRQUN0QyxlQUFlLEVBQUUsQ0FBQyxDQUFDLGVBQWUsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUk7UUFDN0Usa0JBQWtCLEVBQUUsQ0FBQyxDQUFDLGtCQUFrQixJQUFJLElBQUk7UUFDaEQsaUJBQWlCLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQztLQUNoRCxDQUFBO0lBQ0QsTUFBTSxHQUFHLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQTtJQUMvQixJQUFJLENBQUM7UUFDSCxNQUFNLElBQUEseUJBQU8sRUFBQyxjQUFjLEVBQUUsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQTtJQUNqRixDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsNkJBQTZCO0lBQy9CLENBQUM7SUFDRCxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFBO0FBQ3hDLENBQUMsQ0FBQTtBQWxCWSxRQUFBLElBQUksUUFrQmhCIn0=
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = void 0;
4
+ const odoo_api_client_1 = require("../../../../lib/odoo-api-client");
5
+ // GET /admin/odoo/customer-options — proxy to odoo-api (Odoo partner tags).
6
+ const GET = async (_req, res) => {
7
+ try {
8
+ res.json(await (0, odoo_api_client_1.odooApi)("/odoo/customer-options"));
9
+ }
10
+ catch (e) {
11
+ res.json({ connected: false, error: e?.message, tags: [] });
12
+ }
13
+ };
14
+ exports.GET = GET;
15
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29kb28vY3VzdG9tZXItb3B0aW9ucy9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxxRUFBeUQ7QUFFekQsNEVBQTRFO0FBQ3JFLE1BQU0sR0FBRyxHQUFHLEtBQUssRUFBRSxJQUFtQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNwRSxJQUFJLENBQUM7UUFDSCxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBQSx5QkFBTyxFQUFDLHdCQUF3QixDQUFDLENBQUMsQ0FBQTtJQUNuRCxDQUFDO0lBQUMsT0FBTyxDQUFNLEVBQUUsQ0FBQztRQUNoQixHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQTtJQUM3RCxDQUFDO0FBQ0gsQ0FBQyxDQUFBO0FBTlksUUFBQSxHQUFHLE9BTWYifQ==
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = void 0;
4
+ const odoo_api_client_1 = require("../../../../lib/odoo-api-client");
5
+ // GET /admin/odoo/inventory-options — proxy to odoo-api (Odoo warehouses).
6
+ const GET = async (_req, res) => {
7
+ try {
8
+ res.json(await (0, odoo_api_client_1.odooApi)("/odoo/inventory-options"));
9
+ }
10
+ catch (e) {
11
+ res.json({ connected: false, error: e?.message, warehouses: [] });
12
+ }
13
+ };
14
+ exports.GET = GET;
15
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29kb28vaW52ZW50b3J5LW9wdGlvbnMvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EscUVBQXlEO0FBRXpELDJFQUEyRTtBQUNwRSxNQUFNLEdBQUcsR0FBRyxLQUFLLEVBQUUsSUFBbUIsRUFBRSxHQUFtQixFQUFFLEVBQUU7SUFDcEUsSUFBSSxDQUFDO1FBQ0gsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUEseUJBQU8sRUFBQyx5QkFBeUIsQ0FBQyxDQUFDLENBQUE7SUFDcEQsQ0FBQztJQUFDLE9BQU8sQ0FBTSxFQUFFLENBQUM7UUFDaEIsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUE7SUFDbkUsQ0FBQztBQUNILENBQUMsQ0FBQTtBQU5ZLFFBQUEsR0FBRyxPQU1mIn0=
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = void 0;
4
+ const queue_1 = require("../../../../../lib/queue");
5
+ // GET /admin/odoo/jobs/:id — status of a background import job.
6
+ const GET = async (req, res) => {
7
+ try {
8
+ const job = await (0, queue_1.getProductImportQueue)().getJob(req.params.id);
9
+ if (!job) {
10
+ return res.status(404).json({ message: "Job not found" });
11
+ }
12
+ const state = await job.getState(); // waiting | active | completed | failed | delayed
13
+ res.json({
14
+ id: job.id,
15
+ state,
16
+ result: job.returnvalue ?? null,
17
+ failedReason: job.failedReason ?? null,
18
+ });
19
+ }
20
+ catch (e) {
21
+ res.status(500).json({ message: e?.message ?? "Could not read job" });
22
+ }
23
+ };
24
+ exports.GET = GET;
25
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29kb28vam9icy9baWRdL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLG9EQUFnRTtBQUVoRSxnRUFBZ0U7QUFDekQsTUFBTSxHQUFHLEdBQUcsS0FBSyxFQUFFLEdBQWtCLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ25FLElBQUksQ0FBQztRQUNILE1BQU0sR0FBRyxHQUFHLE1BQU0sSUFBQSw2QkFBcUIsR0FBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFBO1FBQy9ELElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNULE9BQU8sR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxPQUFPLEVBQUUsZUFBZSxFQUFFLENBQUMsQ0FBQTtRQUMzRCxDQUFDO1FBQ0QsTUFBTSxLQUFLLEdBQUcsTUFBTSxHQUFHLENBQUMsUUFBUSxFQUFFLENBQUEsQ0FBQyxrREFBa0Q7UUFDckYsR0FBRyxDQUFDLElBQUksQ0FBQztZQUNQLEVBQUUsRUFBRSxHQUFHLENBQUMsRUFBRTtZQUNWLEtBQUs7WUFDTCxNQUFNLEVBQUUsR0FBRyxDQUFDLFdBQVcsSUFBSSxJQUFJO1lBQy9CLFlBQVksRUFBRSxHQUFHLENBQUMsWUFBWSxJQUFJLElBQUk7U0FDdkMsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUFDLE9BQU8sQ0FBTSxFQUFFLENBQUM7UUFDaEIsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLE9BQU8sSUFBSSxvQkFBb0IsRUFBRSxDQUFDLENBQUE7SUFDdkUsQ0FBQztBQUNILENBQUMsQ0FBQTtBQWhCWSxRQUFBLEdBQUcsT0FnQmYifQ==
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DELETE = exports.GET = void 0;
4
+ const odoo_api_client_1 = require("../../../../lib/odoo-api-client");
5
+ // GET /admin/odoo/logs — proxy to odoo-api (paged/filterable sync history).
6
+ const GET = async (req, res) => {
7
+ const qs = new URLSearchParams(req.query).toString();
8
+ try {
9
+ res.json(await (0, odoo_api_client_1.odooApi)(`/odoo/logs${qs ? `?${qs}` : ""}`));
10
+ }
11
+ catch (e) {
12
+ res.status(400).json({ message: e?.message ?? "Failed to load logs" });
13
+ }
14
+ };
15
+ exports.GET = GET;
16
+ // DELETE /admin/odoo/logs — clear sync history (forwards type/status filters).
17
+ const DELETE = async (req, res) => {
18
+ const qs = new URLSearchParams(req.query).toString();
19
+ try {
20
+ res.json(await (0, odoo_api_client_1.odooApi)(`/odoo/logs${qs ? `?${qs}` : ""}`, { method: "DELETE" }));
21
+ }
22
+ catch (e) {
23
+ res.status(400).json({ message: e?.message ?? "Failed to clear logs" });
24
+ }
25
+ };
26
+ exports.DELETE = DELETE;
27
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29kb28vbG9ncy9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxxRUFBeUQ7QUFFekQsNEVBQTRFO0FBQ3JFLE1BQU0sR0FBRyxHQUFHLEtBQUssRUFBRSxHQUFrQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNuRSxNQUFNLEVBQUUsR0FBRyxJQUFJLGVBQWUsQ0FDNUIsR0FBRyxDQUFDLEtBQStCLENBQ3BDLENBQUMsUUFBUSxFQUFFLENBQUE7SUFDWixJQUFJLENBQUM7UUFDSCxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBQSx5QkFBTyxFQUFDLGFBQWEsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUE7SUFDNUQsQ0FBQztJQUFDLE9BQU8sQ0FBTSxFQUFFLENBQUM7UUFDaEIsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLE9BQU8sSUFBSSxxQkFBcUIsRUFBRSxDQUFDLENBQUE7SUFDeEUsQ0FBQztBQUNILENBQUMsQ0FBQTtBQVRZLFFBQUEsR0FBRyxPQVNmO0FBRUQsK0VBQStFO0FBQ3hFLE1BQU0sTUFBTSxHQUFHLEtBQUssRUFBRSxHQUFrQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUN0RSxNQUFNLEVBQUUsR0FBRyxJQUFJLGVBQWUsQ0FDNUIsR0FBRyxDQUFDLEtBQStCLENBQ3BDLENBQUMsUUFBUSxFQUFFLENBQUE7SUFDWixJQUFJLENBQUM7UUFDSCxHQUFHLENBQUMsSUFBSSxDQUNOLE1BQU0sSUFBQSx5QkFBTyxFQUFDLGFBQWEsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUN2RSxDQUFBO0lBQ0gsQ0FBQztJQUFDLE9BQU8sQ0FBTSxFQUFFLENBQUM7UUFDaEIsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLE9BQU8sSUFBSSxzQkFBc0IsRUFBRSxDQUFDLENBQUE7SUFDekUsQ0FBQztBQUNILENBQUMsQ0FBQTtBQVhZLFFBQUEsTUFBTSxVQVdsQiJ9
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = void 0;
4
+ const odoo_api_client_1 = require("../../../../lib/odoo-api-client");
5
+ // GET /admin/odoo/options — proxy to odoo-api (companies + sale journals).
6
+ const GET = async (_req, res) => {
7
+ try {
8
+ res.json(await (0, odoo_api_client_1.odooApi)("/odoo/options"));
9
+ }
10
+ catch (e) {
11
+ res.json({ connected: false, error: e?.message, companies: [], saleJournals: [] });
12
+ }
13
+ };
14
+ exports.GET = GET;
15
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29kb28vb3B0aW9ucy9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxxRUFBeUQ7QUFFekQsMkVBQTJFO0FBQ3BFLE1BQU0sR0FBRyxHQUFHLEtBQUssRUFBRSxJQUFtQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNwRSxJQUFJLENBQUM7UUFDSCxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBQSx5QkFBTyxFQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUE7SUFDMUMsQ0FBQztJQUFDLE9BQU8sQ0FBTSxFQUFFLENBQUM7UUFDaEIsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxZQUFZLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQTtJQUNwRixDQUFDO0FBQ0gsQ0FBQyxDQUFBO0FBTlksUUFBQSxHQUFHLE9BTWYifQ==
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = void 0;
4
+ const odoo_api_client_1 = require("../../../../lib/odoo-api-client");
5
+ // GET /admin/odoo/order-options — proxy to odoo-api (Odoo journals).
6
+ const GET = async (_req, res) => {
7
+ try {
8
+ res.json(await (0, odoo_api_client_1.odooApi)("/odoo/order-options"));
9
+ }
10
+ catch (e) {
11
+ res.json({ connected: false, error: e?.message, journals: [] });
12
+ }
13
+ };
14
+ exports.GET = GET;
15
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29kb28vb3JkZXItb3B0aW9ucy9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxxRUFBeUQ7QUFFekQscUVBQXFFO0FBQzlELE1BQU0sR0FBRyxHQUFHLEtBQUssRUFBRSxJQUFtQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNwRSxJQUFJLENBQUM7UUFDSCxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBQSx5QkFBTyxFQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQTtJQUNoRCxDQUFDO0lBQUMsT0FBTyxDQUFNLEVBQUUsQ0FBQztRQUNoQixHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQTtJQUNqRSxDQUFDO0FBQ0gsQ0FBQyxDQUFBO0FBTlksUUFBQSxHQUFHLE9BTWYifQ==
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = void 0;
4
+ const odoo_api_client_1 = require("../../../../lib/odoo-api-client");
5
+ // GET /admin/odoo/product-options — proxy to odoo-api (categories + pricelists).
6
+ const GET = async (_req, res) => {
7
+ try {
8
+ res.json(await (0, odoo_api_client_1.odooApi)("/odoo/product-options"));
9
+ }
10
+ catch (e) {
11
+ res.json({ connected: false, error: e?.message, categories: [], pricelists: [] });
12
+ }
13
+ };
14
+ exports.GET = GET;
15
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29kb28vcHJvZHVjdC1vcHRpb25zL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHFFQUF5RDtBQUV6RCxpRkFBaUY7QUFDMUUsTUFBTSxHQUFHLEdBQUcsS0FBSyxFQUFFLElBQW1CLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ3BFLElBQUksQ0FBQztRQUNILEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFBLHlCQUFPLEVBQUMsdUJBQXVCLENBQUMsQ0FBQyxDQUFBO0lBQ2xELENBQUM7SUFBQyxPQUFPLENBQU0sRUFBRSxDQUFDO1FBQ2hCLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxFQUFFLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUE7SUFDbkYsQ0FBQztBQUNILENBQUMsQ0FBQTtBQU5ZLFFBQUEsR0FBRyxPQU1mIn0=
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = exports.GET = void 0;
4
+ const odoo_1 = require("../../../../../modules/odoo");
5
+ const odoo_api_client_1 = require("../../../../../lib/odoo-api-client");
6
+ const queue_1 = require("../../../../../lib/queue");
7
+ const plan_1 = require("../../../../../lib/plan");
8
+ const ALLOWED = new Set(["product", "inventory", "orders", "customers", "plans"]);
9
+ // GET /admin/odoo/sections/:section — a settings page's saved JSON (Medusa-stored).
10
+ const GET = async (req, res) => {
11
+ const section = req.params.section;
12
+ if (!ALLOWED.has(section)) {
13
+ return res.status(404).json({ message: `Unknown section "${section}".` });
14
+ }
15
+ const svc = req.scope.resolve(odoo_1.ODOO_MODULE);
16
+ const data = await svc.getValue(`section:${section}`);
17
+ res.json({ configured: Boolean(data), data: data ?? null });
18
+ };
19
+ exports.GET = GET;
20
+ // POST /admin/odoo/sections/:section — save in Medusa + push to odoo-api cache.
21
+ const POST = async (req, res) => {
22
+ const section = req.params.section;
23
+ if (!ALLOWED.has(section)) {
24
+ return res.status(404).json({ message: `Unknown section "${section}".` });
25
+ }
26
+ const svc = req.scope.resolve(odoo_1.ODOO_MODULE);
27
+ const data = (req.body ?? {});
28
+ // Billing guard: the plan tier is controlled by Stripe (via /odoo/billing/sync).
29
+ // The Plans page may only persist UI state (e.g. cycle) and self-downgrade to
30
+ // Free — a paid planId can never be set directly here.
31
+ if (section === "plans" && data.planId && data.planId !== "free") {
32
+ delete data.planId;
33
+ }
34
+ await svc.setValue(`section:${section}`, data);
35
+ try {
36
+ await (0, odoo_api_client_1.odooApi)(`/odoo/sections/${section}`, {
37
+ method: "POST",
38
+ body: JSON.stringify(data),
39
+ });
40
+ }
41
+ catch {
42
+ /* cache sync non-critical */
43
+ }
44
+ // Keep the repeatable import schedule in sync — clamped to the active plan.
45
+ // Re-reconcile both when the product schedule changes AND when the plan
46
+ // changes (e.g. a downgrade must drop a too-frequent schedule).
47
+ if (section === "product" || section === "plans") {
48
+ const plan = await (0, plan_1.getPlanLimits)(req.scope);
49
+ const prod = (await svc.getValue("section:product")) ?? {};
50
+ await (0, queue_1.reconcileProductSchedule)((0, plan_1.clampSchedule)(prod.importSchedule, plan)).catch(() => { });
51
+ }
52
+ res.json({ configured: true, data });
53
+ };
54
+ exports.POST = POST;
55
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29kb28vc2VjdGlvbnMvW3NlY3Rpb25dL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHNEQUF5RDtBQUV6RCx3RUFBNEQ7QUFDNUQsb0RBQW1FO0FBQ25FLGtEQUFzRTtBQUV0RSxNQUFNLE9BQU8sR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDLFNBQVMsRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFBO0FBRWpGLG9GQUFvRjtBQUM3RSxNQUFNLEdBQUcsR0FBRyxLQUFLLEVBQUUsR0FBa0IsRUFBRSxHQUFtQixFQUFFLEVBQUU7SUFDbkUsTUFBTSxPQUFPLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUE7SUFDbEMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUMxQixPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxFQUFFLG9CQUFvQixPQUFPLElBQUksRUFBRSxDQUFDLENBQUE7SUFDM0UsQ0FBQztJQUNELE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFxQixrQkFBVyxDQUFDLENBQUE7SUFDOUQsTUFBTSxJQUFJLEdBQUcsTUFBTSxHQUFHLENBQUMsUUFBUSxDQUFDLFdBQVcsT0FBTyxFQUFFLENBQUMsQ0FBQTtJQUNyRCxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsVUFBVSxFQUFFLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxJQUFJLElBQUksRUFBRSxDQUFDLENBQUE7QUFDN0QsQ0FBQyxDQUFBO0FBUlksUUFBQSxHQUFHLE9BUWY7QUFFRCxnRkFBZ0Y7QUFDekUsTUFBTSxJQUFJLEdBQUcsS0FBSyxFQUFFLEdBQWtCLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ3BFLE1BQU0sT0FBTyxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFBO0lBQ2xDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDMUIsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLE9BQU8sRUFBRSxvQkFBb0IsT0FBTyxJQUFJLEVBQUUsQ0FBQyxDQUFBO0lBQzNFLENBQUM7SUFDRCxNQUFNLEdBQUcsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBcUIsa0JBQVcsQ0FBQyxDQUFBO0lBQzlELE1BQU0sSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksSUFBSSxFQUFFLENBQTRCLENBQUE7SUFFeEQsaUZBQWlGO0lBQ2pGLDhFQUE4RTtJQUM5RSx1REFBdUQ7SUFDdkQsSUFBSSxPQUFPLEtBQUssT0FBTyxJQUFJLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxNQUFNLEVBQUUsQ0FBQztRQUNqRSxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUE7SUFDcEIsQ0FBQztJQUVELE1BQU0sR0FBRyxDQUFDLFFBQVEsQ0FBQyxXQUFXLE9BQU8sRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFBO0lBQzlDLElBQUksQ0FBQztRQUNILE1BQU0sSUFBQSx5QkFBTyxFQUFDLGtCQUFrQixPQUFPLEVBQUUsRUFBRTtZQUN6QyxNQUFNLEVBQUUsTUFBTTtZQUNkLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQztTQUMzQixDQUFDLENBQUE7SUFDSixDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsNkJBQTZCO0lBQy9CLENBQUM7SUFFRCw0RUFBNEU7SUFDNUUsd0VBQXdFO0lBQ3hFLGdFQUFnRTtJQUNoRSxJQUFJLE9BQU8sS0FBSyxTQUFTLElBQUksT0FBTyxLQUFLLE9BQU8sRUFBRSxDQUFDO1FBQ2pELE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBQSxvQkFBYSxFQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUMzQyxNQUFNLElBQUksR0FBRyxDQUFDLE1BQU0sR0FBRyxDQUFDLFFBQVEsQ0FBOEIsaUJBQWlCLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQTtRQUN2RixNQUFNLElBQUEsZ0NBQXdCLEVBQUMsSUFBQSxvQkFBYSxFQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDLENBQUE7SUFDMUYsQ0FBQztJQUVELEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUE7QUFDdEMsQ0FBQyxDQUFBO0FBbkNZLFFBQUEsSUFBSSxRQW1DaEIifQ==
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = exports.GET = void 0;
4
+ const odoo_1 = require("../../../../modules/odoo");
5
+ const odoo_api_client_1 = require("../../../../lib/odoo-api-client");
6
+ const MASK = "••••••••";
7
+ const KEY = "connection";
8
+ function serialize(conn) {
9
+ if (!conn) {
10
+ return {
11
+ configured: false,
12
+ settings: {
13
+ url: "",
14
+ database: "",
15
+ username: "",
16
+ api_key: "",
17
+ has_api_key: false,
18
+ last_tested_at: null,
19
+ last_test_ok: null,
20
+ },
21
+ };
22
+ }
23
+ return {
24
+ configured: true,
25
+ settings: {
26
+ url: conn.url,
27
+ database: conn.database,
28
+ username: conn.username,
29
+ api_key: conn.api_key ? MASK : "",
30
+ has_api_key: Boolean(conn.api_key),
31
+ last_tested_at: conn.last_tested_at ?? null,
32
+ last_test_ok: conn.last_test_ok ?? null,
33
+ },
34
+ };
35
+ }
36
+ // GET /admin/odoo/settings — Medusa-stored connection (api_key masked).
37
+ const GET = async (req, res) => {
38
+ const svc = req.scope.resolve(odoo_1.ODOO_MODULE);
39
+ const conn = await svc.getValue(KEY);
40
+ res.json(serialize(conn));
41
+ };
42
+ exports.GET = GET;
43
+ // POST /admin/odoo/settings — save in Medusa (source of truth) + push to odoo-api cache.
44
+ const POST = async (req, res) => {
45
+ const svc = req.scope.resolve(odoo_1.ODOO_MODULE);
46
+ const body = (req.body ?? {});
47
+ const url = String(body.url ?? "").trim();
48
+ const database = String(body.database ?? "").trim();
49
+ const username = String(body.username ?? "").trim();
50
+ let api_key = String(body.api_key ?? "").trim();
51
+ try {
52
+ // eslint-disable-next-line no-new
53
+ new URL(url);
54
+ }
55
+ catch {
56
+ return res.status(400).json({ message: "Odoo URL must be a valid URL." });
57
+ }
58
+ if (!database || !username) {
59
+ return res.status(400).json({ message: "Database and username are required." });
60
+ }
61
+ const existing = await svc.getValue(KEY);
62
+ // Reusing the masked/blank key: keep the stored one.
63
+ if ((!api_key || api_key === MASK) && existing?.api_key) {
64
+ api_key = existing.api_key;
65
+ }
66
+ if (!api_key) {
67
+ return res.status(400).json({ message: "API key is required." });
68
+ }
69
+ const stored = {
70
+ url,
71
+ database,
72
+ username,
73
+ api_key,
74
+ last_tested_at: null,
75
+ last_test_ok: null,
76
+ };
77
+ await svc.setValue(KEY, stored);
78
+ // Keep odoo-api's cache in sync (best-effort).
79
+ try {
80
+ await (0, odoo_api_client_1.odooApi)("/odoo/settings", {
81
+ method: "POST",
82
+ body: JSON.stringify({ url, database, username, api_key }),
83
+ });
84
+ }
85
+ catch {
86
+ // Cache sync is non-critical for the save itself.
87
+ }
88
+ res.json(serialize(stored));
89
+ };
90
+ exports.POST = POST;
91
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29kb28vc2V0dGluZ3Mvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EsbURBQXNEO0FBRXRELHFFQUF5RDtBQUV6RCxNQUFNLElBQUksR0FBRyxVQUFVLENBQUE7QUFDdkIsTUFBTSxHQUFHLEdBQUcsWUFBWSxDQUFBO0FBV3hCLFNBQVMsU0FBUyxDQUFDLElBQTZCO0lBQzlDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNWLE9BQU87WUFDTCxVQUFVLEVBQUUsS0FBSztZQUNqQixRQUFRLEVBQUU7Z0JBQ1IsR0FBRyxFQUFFLEVBQUU7Z0JBQ1AsUUFBUSxFQUFFLEVBQUU7Z0JBQ1osUUFBUSxFQUFFLEVBQUU7Z0JBQ1osT0FBTyxFQUFFLEVBQUU7Z0JBQ1gsV0FBVyxFQUFFLEtBQUs7Z0JBQ2xCLGNBQWMsRUFBRSxJQUFJO2dCQUNwQixZQUFZLEVBQUUsSUFBSTthQUNuQjtTQUNGLENBQUE7SUFDSCxDQUFDO0lBQ0QsT0FBTztRQUNMLFVBQVUsRUFBRSxJQUFJO1FBQ2hCLFFBQVEsRUFBRTtZQUNSLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRztZQUNiLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBUTtZQUN2QixRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVE7WUFDdkIsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUNqQyxXQUFXLEVBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7WUFDbEMsY0FBYyxFQUFFLElBQUksQ0FBQyxjQUFjLElBQUksSUFBSTtZQUMzQyxZQUFZLEVBQUUsSUFBSSxDQUFDLFlBQVksSUFBSSxJQUFJO1NBQ3hDO0tBQ0YsQ0FBQTtBQUNILENBQUM7QUFFRCx3RUFBd0U7QUFDakUsTUFBTSxHQUFH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
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ const odoo_api_client_1 = require("../../../../../lib/odoo-api-client");
5
+ // POST /admin/odoo/stripe/change — switch plans. Proxies to odoo-api, which
6
+ // updates the existing subscription in place (proration) or returns a Checkout
7
+ // URL for a first-time subscriber. Returns { updated } | { url } | { error }.
8
+ const POST = async (req, res) => {
9
+ try {
10
+ res.json(await (0, odoo_api_client_1.odooApi)("/odoo/stripe/change", {
11
+ method: "POST",
12
+ body: JSON.stringify(req.body ?? {}),
13
+ }));
14
+ }
15
+ catch (e) {
16
+ res.status(400).json({ error: e?.message ?? "Plan change failed" });
17
+ }
18
+ };
19
+ exports.POST = POST;
20
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29kb28vc3RyaXBlL2NoYW5nZS9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSx3RUFBNEQ7QUFFNUQsNEVBQTRFO0FBQzVFLCtFQUErRTtBQUMvRSw4RUFBOEU7QUFDdkUsTUFBTSxJQUFJLEdBQUcsS0FBSyxFQUFFLEdBQWtCLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ3BFLElBQUksQ0FBQztRQUNILEdBQUcsQ0FBQyxJQUFJLENBQ04sTUFBTSxJQUFBLHlCQUFPLEVBQUMscUJBQXFCLEVBQUU7WUFDbkMsTUFBTSxFQUFFLE1BQU07WUFDZCxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQztTQUNyQyxDQUFDLENBQ0gsQ0FBQTtJQUNILENBQUM7SUFBQyxPQUFPLENBQU0sRUFBRSxDQUFDO1FBQ2hCLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxPQUFPLElBQUksb0JBQW9CLEVBQUUsQ0FBQyxDQUFBO0lBQ3JFLENBQUM7QUFDSCxDQUFDLENBQUE7QUFYWSxRQUFBLElBQUksUUFXaEIifQ==
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ const odoo_api_client_1 = require("../../../../../lib/odoo-api-client");
5
+ // POST /admin/odoo/stripe/checkout — proxy to odoo-api to create a Stripe
6
+ // Checkout Session for the chosen plan. Returns { url } or { error }.
7
+ const POST = async (req, res) => {
8
+ try {
9
+ const result = await (0, odoo_api_client_1.odooApi)("/odoo/stripe/checkout", {
10
+ method: "POST",
11
+ body: JSON.stringify(req.body ?? {}),
12
+ });
13
+ res.json(result);
14
+ }
15
+ catch (e) {
16
+ res.status(400).json({ error: e?.message ?? "Checkout failed" });
17
+ }
18
+ };
19
+ exports.POST = POST;
20
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29kb28vc3RyaXBlL2NoZWNrb3V0L3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHdFQUE0RDtBQUU1RCwwRUFBMEU7QUFDMUUsc0VBQXNFO0FBQy9ELE1BQU0sSUFBSSxHQUFHLEtBQUssRUFBRSxHQUFrQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNwRSxJQUFJLENBQUM7UUFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUEseUJBQU8sRUFBQyx1QkFBdUIsRUFBRTtZQUNwRCxNQUFNLEVBQUUsTUFBTTtZQUNkLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDO1NBQ3JDLENBQUMsQ0FBQTtRQUNGLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUE7SUFDbEIsQ0FBQztJQUFDLE9BQU8sQ0FBTSxFQUFFLENBQUM7UUFDaEIsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLE9BQU8sSUFBSSxpQkFBaUIsRUFBRSxDQUFDLENBQUE7SUFDbEUsQ0FBQztBQUNILENBQUMsQ0FBQTtBQVZZLFFBQUEsSUFBSSxRQVVoQiJ9
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ const odoo_api_client_1 = require("../../../../../lib/odoo-api-client");
5
+ // POST /admin/odoo/stripe/portal — proxy to odoo-api to open the Stripe Billing
6
+ // Portal so the customer can manage or cancel their subscription.
7
+ const POST = async (_req, res) => {
8
+ try {
9
+ res.json(await (0, odoo_api_client_1.odooApi)("/odoo/stripe/portal", { method: "POST", body: "{}" }));
10
+ }
11
+ catch (e) {
12
+ res.status(400).json({ error: e?.message ?? "Could not open billing portal" });
13
+ }
14
+ };
15
+ exports.POST = POST;
16
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29kb28vc3RyaXBlL3BvcnRhbC9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSx3RUFBNEQ7QUFFNUQsZ0ZBQWdGO0FBQ2hGLGtFQUFrRTtBQUMzRCxNQUFNLElBQUksR0FBRyxLQUFLLEVBQUUsSUFBbUIsRUFBRSxHQUFtQixFQUFFLEVBQUU7SUFDckUsSUFBSSxDQUFDO1FBQ0gsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUEseUJBQU8sRUFBQyxxQkFBcUIsRUFBRSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQTtJQUNoRixDQUFDO0lBQUMsT0FBTyxDQUFNLEVBQUUsQ0FBQztRQUNoQixHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsT0FBTyxJQUFJLCtCQUErQixFQUFFLENBQUMsQ0FBQTtJQUNoRixDQUFDO0FBQ0gsQ0FBQyxDQUFBO0FBTlksUUFBQSxJQUFJLFFBTWhCIn0=
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const odoo_api_client_1 = require("../../../../../lib/odoo-api-client");
6
+ const queue_1 = require("../../../../../lib/queue");
7
+ const plan_1 = require("../../../../../lib/plan");
8
+ // POST /admin/odoo/sync/:entity
9
+ // - products: enqueue a background import job → returns jobId
10
+ // - orders: enqueue recent unsynced orders → returns how many were queued
11
+ // - customers: enqueue a direction-aware customer sync → returns jobId
12
+ // - inventory: enqueue a direction-aware stock sync → returns jobId
13
+ // - others: proxied to odoo-api's mock until their engines are built
14
+ const POST = async (req, res) => {
15
+ const entity = req.params.entity;
16
+ // Plan gate: refuse entities the active plan doesn't include.
17
+ const gated = ["products", "orders", "inventory", "customers"];
18
+ if (gated.includes(entity)) {
19
+ const plan = await (0, plan_1.getPlanLimits)(req.scope);
20
+ if (!plan.entities[entity]) {
21
+ return res.status(403).json({
22
+ message: `${entity[0].toUpperCase()}${entity.slice(1)} sync requires the ${plan_1.ENTITY_MIN_PLAN[entity]} plan or higher. You're on ${plan.name}.`,
23
+ upgradeRequired: plan_1.ENTITY_MIN_PLAN[entity],
24
+ });
25
+ }
26
+ }
27
+ if (entity === "products") {
28
+ try {
29
+ const job = await (0, queue_1.getProductImportQueue)().add("import", {}, { removeOnComplete: 50, removeOnFail: 50 });
30
+ return res.status(202).json({ entity, queued: true, jobId: job.id });
31
+ }
32
+ catch (e) {
33
+ return res.status(500).json({ message: e?.message ?? "Could not queue import" });
34
+ }
35
+ }
36
+ if (entity === "orders") {
37
+ try {
38
+ const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
39
+ const { data: orders } = await query.graph({
40
+ entity: "order",
41
+ fields: ["id", "display_id", "metadata"],
42
+ pagination: { take: 100, order: { created_at: "DESC" } },
43
+ });
44
+ const queue = (0, queue_1.getOrderSyncQueue)();
45
+ let queued = 0;
46
+ let skipped = 0;
47
+ for (const o of orders) {
48
+ const odooId = o.metadata?.odoo_order_id;
49
+ if (!odooId) {
50
+ await queue.add("sync", { orderId: o.id }, { removeOnComplete: 100, removeOnFail: 100 });
51
+ queued++;
52
+ }
53
+ else {
54
+ // Already synced — surface it on the Logs page instead of silently dropping it.
55
+ skipped++;
56
+ (0, odoo_api_client_1.odooApi)("/odoo/logs", {
57
+ method: "POST",
58
+ body: JSON.stringify({
59
+ type: "order_sync",
60
+ status: "skipped",
61
+ message: `Order #${o.display_id ?? o.id}: skipped — already synced (Odoo order ${odooId}).`,
62
+ }),
63
+ }).catch(() => { });
64
+ }
65
+ }
66
+ return res.status(202).json({ entity, queued: true, count: queued, skipped });
67
+ }
68
+ catch (e) {
69
+ return res.status(500).json({ message: e?.message ?? "Could not queue orders" });
70
+ }
71
+ }
72
+ if (entity === "customers") {
73
+ try {
74
+ const job = await (0, queue_1.getCustomerSyncQueue)().add("sync", {}, { removeOnComplete: 50, removeOnFail: 50 });
75
+ return res.status(202).json({ entity, queued: true, jobId: job.id });
76
+ }
77
+ catch (e) {
78
+ return res.status(500).json({ message: e?.message ?? "Could not queue customer sync" });
79
+ }
80
+ }
81
+ if (entity === "inventory") {
82
+ try {
83
+ const job = await (0, queue_1.getInventorySyncQueue)().add("sync", {}, { removeOnComplete: 50, removeOnFail: 50 });
84
+ return res.status(202).json({ entity, queued: true, jobId: job.id });
85
+ }
86
+ catch (e) {
87
+ return res.status(500).json({ message: e?.message ?? "Could not queue inventory sync" });
88
+ }
89
+ }
90
+ try {
91
+ const result = await (0, odoo_api_client_1.odooApi)(`/odoo/sync/${entity}`, { method: "POST" });
92
+ res.status(202).json(result);
93
+ }
94
+ catch (e) {
95
+ res.status(400).json({ message: e?.message ?? "Sync failed" });
96
+ }
97
+ };
98
+ exports.POST = POST;
99
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29kb28vc3luYy9bZW50aXR5XS9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxxREFBcUU7QUFDckUsd0VBQTREO0FBQzVELG9EQUtpQztBQUNqQyxrREFBMEY7QUFFMUYsZ0NBQWdDO0FBQ2hDLCtEQUErRDtBQUMvRCw2RUFBNkU7QUFDN0UsdUVBQXVFO0FBQ3ZFLG9FQUFvRTtBQUNwRSx3RUFBd0U7QUFDakUsTUFBTSxJQUFJLEdBQUcsS0FBSyxFQUFFLEdBQWtCLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ3BFLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFBO0lBRWhDLDhEQUE4RDtJQUM5RCxNQUFNLEtBQUssR0FBRyxDQUFDLFVBQVUsRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLFdBQVcsQ0FBQyxDQUFBO0lBQzlELElBQUksS0FBSyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQzNCLE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBQSxvQkFBYSxFQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUMzQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFxQixDQUFDLEVBQUUsQ0FBQztZQUMxQyxPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUMxQixPQUFPLEVBQUUsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsc0JBQ25ELHNCQUFlLENBQUMsTUFBcUIsQ0FDdkMsOEJBQThCLElBQUksQ0FBQyxJQUFJLEdBQUc7Z0JBQzFDLGVBQWUsRUFBRSxzQkFBZSxDQUFDLE1BQXFCLENBQUM7YUFDeEQs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
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ const sync_order_1 = require("../../../../../lib/sync-order");
5
+ // POST /admin/odoo/sync-order/:id — sync ONE order to Odoo on demand (manual,
6
+ // so it ignores the auto-sync toggle but still respects the plan gate).
7
+ const POST = async (req, res) => {
8
+ try {
9
+ const result = await (0, sync_order_1.syncOrder)(req.scope, req.params.id, { manual: true });
10
+ res.json(result);
11
+ }
12
+ catch (e) {
13
+ res.status(500).json({ ok: false, message: e?.message ?? "Order sync failed" });
14
+ }
15
+ };
16
+ exports.POST = POST;
17
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL29kb28vc3luYy1vcmRlci9baWRdL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLDhEQUF5RDtBQUV6RCw4RUFBOEU7QUFDOUUsd0VBQXdFO0FBQ2pFLE1BQU0sSUFBSSxHQUFHLEtBQUssRUFBRSxHQUFrQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNwRSxJQUFJLENBQUM7UUFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUEsc0JBQVMsRUFBQyxHQUFHLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUE7UUFDMUUsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQTtJQUNsQixDQUFDO0lBQUMsT0FBTyxDQUFNLEVBQUUsQ0FBQztRQUNoQixHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxPQUFPLElBQUksbUJBQW1CLEVBQUUsQ0FBQyxDQUFBO0lBQ2pGLENBQUM7QUFDSCxDQUFDLENBQUE7QUFQWSxRQUFBLElBQUksUUFPaEIifQ==