quickbooks-medusa-plugin 0.0.1

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 (44) hide show
  1. package/.medusa/server/src/admin/index.js +1832 -0
  2. package/.medusa/server/src/admin/index.mjs +1831 -0
  3. package/.medusa/server/src/api/admin/plugin/route.js +7 -0
  4. package/.medusa/server/src/api/admin/quickbooks/callback/route.js +95 -0
  5. package/.medusa/server/src/api/admin/quickbooks/connect/route.js +12 -0
  6. package/.medusa/server/src/api/admin/quickbooks/connection/route.js +32 -0
  7. package/.medusa/server/src/api/admin/quickbooks/disconnect/route.js +16 -0
  8. package/.medusa/server/src/api/admin/quickbooks/settings/route.js +33 -0
  9. package/.medusa/server/src/api/admin/quickbooks/webhooks/route.js +95 -0
  10. package/.medusa/server/src/api/store/plugin/route.js +7 -0
  11. package/.medusa/server/src/modules/quickbooks/index.js +13 -0
  12. package/.medusa/server/src/modules/quickbooks/migrations/Migration20260107000000.js +19 -0
  13. package/.medusa/server/src/modules/quickbooks/models/index.js +10 -0
  14. package/.medusa/server/src/modules/quickbooks/models/quickbooks-connection.js +20 -0
  15. package/.medusa/server/src/modules/quickbooks/models/quickbooks-settings.js +27 -0
  16. package/.medusa/server/src/modules/quickbooks/models/quickbooks-sync-mapping.js +20 -0
  17. package/.medusa/server/src/modules/quickbooks/services/quickbooks-service.js +425 -0
  18. package/.medusa/server/src/subscribers/quickbooks-order-sync.js +18 -0
  19. package/.medusa/server/src/subscribers/quickbooks-product-sync.js +26 -0
  20. package/.medusa/server/src/subscribers/quickbooks-sync.js +22 -0
  21. package/.medusa/server/src/workflows/index.js +23 -0
  22. package/.medusa/server/src/workflows/steps/order/sync-order-to-quickbooks.js +41 -0
  23. package/.medusa/server/src/workflows/steps/order/transform-order.js +78 -0
  24. package/.medusa/server/src/workflows/steps/order/update-order-mapping.js +17 -0
  25. package/.medusa/server/src/workflows/steps/order/validate-order-sync.js +23 -0
  26. package/.medusa/server/src/workflows/steps/reverse-sync/sync-customer-from-quickbooks.js +102 -0
  27. package/.medusa/server/src/workflows/steps/reverse-sync/sync-inventory-from-quickbooks.js +62 -0
  28. package/.medusa/server/src/workflows/steps/reverse-sync/sync-order-status-from-quickbooks.js +76 -0
  29. package/.medusa/server/src/workflows/steps/sync-customer-to-quickbooks.js +55 -0
  30. package/.medusa/server/src/workflows/steps/sync-product-to-quickbooks.js +59 -0
  31. package/.medusa/server/src/workflows/steps/transform-customer.js +41 -0
  32. package/.medusa/server/src/workflows/steps/transform-product.js +39 -0
  33. package/.medusa/server/src/workflows/steps/update-product-sync-mapping.js +17 -0
  34. package/.medusa/server/src/workflows/steps/update-sync-mapping.js +17 -0
  35. package/.medusa/server/src/workflows/steps/validate-customer-sync.js +17 -0
  36. package/.medusa/server/src/workflows/steps/validate-product-sync.js +17 -0
  37. package/.medusa/server/src/workflows/sync-customer-from-quickbooks.js +10 -0
  38. package/.medusa/server/src/workflows/sync-customer-to-quickbooks.js +32 -0
  39. package/.medusa/server/src/workflows/sync-inventory-from-quickbooks.js +10 -0
  40. package/.medusa/server/src/workflows/sync-order-status-from-quickbooks.js +10 -0
  41. package/.medusa/server/src/workflows/sync-order-to-quickbooks.js +28 -0
  42. package/.medusa/server/src/workflows/sync-product-to-quickbooks.js +31 -0
  43. package/README.md +104 -0
  44. package/package.json +75 -0
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.transformOrderStep = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const quickbooks_1 = require("../../../modules/quickbooks");
6
+ exports.transformOrderStep = (0, workflows_sdk_1.createStep)("transform-order", async (input, { container }) => {
7
+ const service = container.resolve(quickbooks_1.QUICKBOOKS_MODULE);
8
+ const { order } = input;
9
+ // 1. Resolve Customer
10
+ const customerMapping = await service.getMapping(order.customer_id, "customer");
11
+ let qbCustomerId = customerMapping?.quickbooks_entity_id;
12
+ // If not mapped, maybe try to find by email or fail?
13
+ // We'll rely on workflow to handle missing customer?
14
+ // Ideally we should sync customer first.
15
+ // For now, if no ID, we return null CustomerRef and let sync step fail or handle it.
16
+ // 2. Resolve Items
17
+ const lines = [];
18
+ for (const item of order.items) {
19
+ if (!item.variant_id)
20
+ continue;
21
+ const itemMapping = await service.getMapping(item.variant_id, "product");
22
+ const qbItemId = itemMapping?.quickbooks_entity_id;
23
+ // If not mapped, we can't add line easily without knowing QB Item ID.
24
+ // We could create generic "Sales Item" but better to skip or fail.
25
+ if (qbItemId) {
26
+ lines.push({
27
+ Amount: item.unit_price * item.quantity / 100, // Medusa is in cents usually? Wait, node-quickbooks handles amount?
28
+ // QB API expects decimal usually. Medusa is Integer cents.
29
+ // Need to convert cents to decimal.
30
+ DetailType: "SalesItemLineDetail",
31
+ SalesItemLineDetail: {
32
+ ItemRef: { value: qbItemId },
33
+ Qty: item.quantity,
34
+ UnitPrice: item.unit_price / 100
35
+ },
36
+ Description: item.title
37
+ });
38
+ }
39
+ }
40
+ // 3. Construct Payload
41
+ // Decide Invoice vs SalesReceipt
42
+ // If payment_status is 'captured', use SalesReceipt?
43
+ // Let's assume Invoice for now as safe default, or SalesReceipt if paid.
44
+ const isPaid = order.payment_status === 'captured';
45
+ const type = isPaid ? "SalesReceipt" : "Invoice";
46
+ const qbData = {
47
+ DocNumber: order.display_id ? String(order.display_id) : undefined,
48
+ TxnDate: order.created_at.split('T')[0],
49
+ CustomerRef: qbCustomerId ? { value: qbCustomerId } : undefined,
50
+ Line: lines,
51
+ TotalAmt: order.total / 100,
52
+ PrivateNote: `Medusa Order ${order.id}`,
53
+ // Add addresses
54
+ // Payment Method Mapping
55
+ PaymentMethodRef: (isPaid && order.payment_collections?.[0]?.payment_sessions?.[0]) ? {
56
+ name: mapPaymentProviderToQB(order.payment_collections[0].payment_sessions[0].provider_id)
57
+ } : undefined,
58
+ BillAddr: order.billing_address ? {
59
+ Line1: order.billing_address.address_1,
60
+ Line2: order.billing_address.address_2,
61
+ City: order.billing_address.city,
62
+ CountrySubDivisionCode: order.billing_address.province,
63
+ PostalCode: order.billing_address.postal_code,
64
+ Country: order.billing_address.country_code?.toUpperCase(),
65
+ } : undefined,
66
+ };
67
+ return new workflows_sdk_1.StepResponse({ qbData, type });
68
+ });
69
+ function mapPaymentProviderToQB(providerId) {
70
+ const mapping = {
71
+ "manual": "Cash",
72
+ "pp_stripe": "Credit Card",
73
+ "stripe": "Credit Card",
74
+ "pp_system_default": "Cash"
75
+ };
76
+ return mapping[providerId] || providerId;
77
+ }
78
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmb3JtLW9yZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9zdGVwcy9vcmRlci90cmFuc2Zvcm0tb3JkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscUVBQTRFO0FBQzVFLDREQUErRDtBQU9sRCxRQUFBLGtCQUFrQixHQUFHLElBQUEsMEJBQVUsRUFDeEMsaUJBQWlCLEVBQ2pCLEtBQUssRUFBRSxLQUEwQixFQUFFLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRTtJQUNoRCxNQUFNLE9BQU8sR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLDhCQUFpQixDQUE0QixDQUFBO0lBQy9FLE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxLQUFLLENBQUE7SUFFdkIsc0JBQXNCO0lBQ3RCLE1BQU0sZUFBZSxHQUFHLE1BQU0sT0FBTyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFLFVBQVUsQ0FBQyxDQUFBO0lBQy9FLElBQUksWUFBWSxHQUFHLGVBQWUsRUFBRSxvQkFBb0IsQ0FBQTtJQUV4RCxxREFBcUQ7SUFDckQsc0RBQXNEO0lBQ3RELHlDQUF5QztJQUN6QyxxRkFBcUY7SUFFckYsbUJBQW1CO0lBQ25CLE1BQU0sS0FBSyxHQUFVLEVBQUUsQ0FBQTtJQUN2QixLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUM3QixJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVU7WUFBRSxTQUFRO1FBRTlCLE1BQU0sV0FBVyxHQUFHLE1BQU0sT0FBTyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLFNBQVMsQ0FBQyxDQUFBO1FBQ3hFLE1BQU0sUUFBUSxHQUFHLFdBQVcsRUFBRSxvQkFBb0IsQ0FBQTtRQUVsRCxzRUFBc0U7UUFDdEUsbUVBQW1FO1FBQ25FLElBQUksUUFBUSxFQUFFLENBQUM7WUFDWCxLQUFLLENBQUMs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
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.updateOrderSyncMappingStep = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const quickbooks_1 = require("../../../modules/quickbooks");
6
+ exports.updateOrderSyncMappingStep = (0, workflows_sdk_1.createStep)("update-order-sync-mapping", async (input, { container }) => {
7
+ const service = container.resolve(quickbooks_1.QUICKBOOKS_MODULE);
8
+ await service.createOrUpdateMapping({
9
+ medusa_entity_id: input.medusaOrderId,
10
+ medusa_entity_type: "order",
11
+ quickbooks_entity_id: input.quickbooksOrder.Id,
12
+ quickbooks_entity_type: input.type,
13
+ sync_status: "synced"
14
+ });
15
+ return new workflows_sdk_1.StepResponse({ success: true });
16
+ });
17
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBkYXRlLW9yZGVyLW1hcHBpbmcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL3N0ZXBzL29yZGVyL3VwZGF0ZS1vcmRlci1tYXBwaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHFFQUE0RTtBQUM1RSw0REFBK0Q7QUFTbEQsUUFBQSwwQkFBMEIsR0FBRyxJQUFBLDBCQUFVLEVBQ2hELDJCQUEyQixFQUMzQixLQUFLLEVBQUUsS0FBa0MsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUU7SUFDeEQsTUFBTSxPQUFPLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyw4QkFBaUIsQ0FBNEIsQ0FBQTtJQUUvRSxNQUFNLE9BQU8sQ0FBQyxxQkFBcUIsQ0FBQztRQUNoQyxnQkFBZ0IsRUFBRSxLQUFLLENBQUMsYUFBYTtRQUNyQyxrQkFBa0IsRUFBRSxPQUFPO1FBQzNCLG9CQUFvQixFQUFFLEtBQUssQ0FBQyxlQUFlLENBQUMsRUFBRTtRQUM5QyxzQkFBc0IsRUFBRSxLQUFLLENBQUMsSUFBa0M7UUFDaEUsV0FBVyxFQUFFLFFBQVE7S0FDeEIsQ0FBQyxDQUFBO0lBRUYsT0FBTyxJQUFJLDRCQUFZLENBQUMsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQTtBQUM5QyxDQUFDLENBQ0osQ0FBQSJ9
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateOrderSyncStep = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const quickbooks_1 = require("../../../modules/quickbooks");
6
+ exports.validateOrderSyncStep = (0, workflows_sdk_1.createStep)("validate-order-sync", async (input, { container }) => {
7
+ const service = container.resolve(quickbooks_1.QUICKBOOKS_MODULE);
8
+ const settings = await service.getOrCreateSettings();
9
+ if (!settings.auto_sync_orders) {
10
+ return new workflows_sdk_1.StepResponse({ success: false, reason: "Auto-sync disabled", order: null });
11
+ }
12
+ if (!input.order) {
13
+ return new workflows_sdk_1.StepResponse({ success: false, reason: "No order provided", order: null });
14
+ }
15
+ // Check if already mapped?
16
+ const mapping = await service.getMapping(input.order.id, "order");
17
+ if (mapping && mapping.sync_status === 'synced') {
18
+ // Already synced? Maybe we update?
19
+ // For now, let's allow updates.
20
+ }
21
+ return new workflows_sdk_1.StepResponse({ success: true, order: input.order, reason: null });
22
+ });
23
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGUtb3JkZXItc3luYy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy93b3JrZmxvd3Mvc3RlcHMvb3JkZXIvdmFsaWRhdGUtb3JkZXItc3luYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxxRUFBNEU7QUFDNUUsNERBQStEO0FBYWxELFFBQUEscUJBQXFCLEdBQUcsSUFBQSwwQkFBVSxFQUMzQyxxQkFBcUIsRUFDckIsS0FBSyxFQUFFLEtBQTZCLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFO0lBQ25ELE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsOEJBQWlCLENBQTRCLENBQUE7SUFDL0UsTUFBTSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsbUJBQW1CLEVBQUUsQ0FBQTtJQUVwRCxJQUFJLENBQUMsUUFBUSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDN0IsT0FBTyxJQUFJLDRCQUFZLENBQTBCLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsb0JBQW9CLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUE7SUFDbkgsQ0FBQztJQUVELElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDZixPQUFPLElBQUksNEJBQVksQ0FBMEIsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxtQkFBbUIsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQTtJQUNsSCxDQUFDO0lBRUQsMkJBQTJCO0lBQzNCLE1BQU0sT0FBTyxHQUFHLE1BQU0sT0FBTyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FBQTtJQUNqRSxJQUFJLE9BQU8sSUFBSSxPQUFPLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzlDLG1DQUFtQztRQUNuQyxnQ0FBZ0M7SUFDcEMsQ0FBQztJQUVELE9BQU8sSUFBSSw0QkFBWSxDQUEwQixFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUE7QUFDekcsQ0FBQyxDQUNKLENBQUEifQ==
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.syncCustomerFromQuickBooksStep = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const utils_1 = require("@medusajs/framework/utils");
6
+ const quickbooks_1 = require("../../../modules/quickbooks");
7
+ exports.syncCustomerFromQuickBooksStep = (0, workflows_sdk_1.createStep)("sync-customer-from-quickbooks-step", async (input, { container }) => {
8
+ const service = container.resolve(quickbooks_1.QUICKBOOKS_MODULE);
9
+ const customerModuleService = container.resolve(utils_1.Modules.CUSTOMER);
10
+ // 1. Get QB Customer
11
+ const qbCustomer = await service.getCustomer(input.quickbooksCustomerId);
12
+ if (!qbCustomer)
13
+ throw new Error(`QuickBooks Customer not found: ${input.quickbooksCustomerId}`);
14
+ // 2. Check Mapping
15
+ const mapping = await service.getMappingByQuickbooksId(input.quickbooksCustomerId, "Customer");
16
+ let medusaCustomer;
17
+ const updateData = {
18
+ first_name: qbCustomer.GivenName,
19
+ last_name: qbCustomer.FamilyName,
20
+ company_name: qbCustomer.CompanyName,
21
+ phone: qbCustomer.PrimaryPhone?.FreeFormNumber,
22
+ };
23
+ // Helper to map address
24
+ const mapAddress = (addr) => ({
25
+ address_1: addr.Line1,
26
+ address_2: addr.Line2,
27
+ city: addr.City,
28
+ province: addr.CountrySubDivisionCode,
29
+ postal_code: addr.PostalCode,
30
+ country_code: addr.Country ? addr.Country.toLowerCase().substring(0, 2) : undefined,
31
+ first_name: qbCustomer.GivenName,
32
+ last_name: qbCustomer.FamilyName,
33
+ phone: qbCustomer.PrimaryPhone?.FreeFormNumber,
34
+ company: qbCustomer.CompanyName,
35
+ });
36
+ if (qbCustomer.BillAddr) {
37
+ // We can't easily update "billing_address" directly via updateCustomers in some setups without ID.
38
+ // But we can try passing it if the module sports upsert or just ignored.
39
+ // Strategy: Add to 'addresses' list?
40
+ // Or leave address sync one-way (Medusa -> QB) to avoid overwriting?
41
+ // User asked for "proper cross sync".
42
+ // We will attempt to create an address payload.
43
+ // Is there a way to set billing address?
44
+ // Intuit uses specific BillAddr.
45
+ // We will create a new address in Medusa and link it?
46
+ // For now, let's skip address updates on existing customers to avoid duplication unless we match.
47
+ }
48
+ // Actually, let's update basic fields first.
49
+ try {
50
+ if (mapping) {
51
+ medusaCustomer = await customerModuleService.updateCustomers(mapping.medusa_entity_id, updateData);
52
+ }
53
+ else {
54
+ // 3. Match by Email
55
+ const email = qbCustomer.PrimaryEmailAddr?.Address;
56
+ if (!email) {
57
+ console.warn("Skipping sync from QB: Customer has no email");
58
+ return new workflows_sdk_1.StepResponse({ success: false, reason: "No email", customer: null });
59
+ }
60
+ const existing = await customerModuleService.listCustomers({ email: [email] });
61
+ if (existing.length > 0) {
62
+ // Map and Update
63
+ medusaCustomer = existing[0];
64
+ await service.createOrUpdateMapping({
65
+ medusa_entity_id: medusaCustomer.id,
66
+ medusa_entity_type: "customer",
67
+ quickbooks_entity_id: qbCustomer.Id,
68
+ quickbooks_entity_type: "Customer",
69
+ sync_status: "synced"
70
+ });
71
+ await customerModuleService.updateCustomers(medusaCustomer.id, updateData);
72
+ }
73
+ else {
74
+ // Creation
75
+ // We can pass addresses on creation
76
+ const addresses = [];
77
+ if (qbCustomer.BillAddr)
78
+ addresses.push({ ...mapAddress(qbCustomer.BillAddr), is_default_billing: true });
79
+ if (qbCustomer.ShipAddr)
80
+ addresses.push({ ...mapAddress(qbCustomer.ShipAddr), is_default_shipping: true });
81
+ medusaCustomer = await customerModuleService.createCustomers({
82
+ email: qbCustomer.PrimaryEmailAddr?.Address,
83
+ ...updateData,
84
+ addresses
85
+ });
86
+ await service.createOrUpdateMapping({
87
+ medusa_entity_id: medusaCustomer.id,
88
+ medusa_entity_type: "customer",
89
+ quickbooks_entity_id: qbCustomer.Id,
90
+ quickbooks_entity_type: "Customer",
91
+ sync_status: "synced"
92
+ });
93
+ }
94
+ }
95
+ }
96
+ catch (e) {
97
+ console.error("Failed to sync customer from QB", e);
98
+ return new workflows_sdk_1.StepResponse({ success: false, reason: e.message, customer: null });
99
+ }
100
+ return new workflows_sdk_1.StepResponse({ success: true, customer: medusaCustomer, reason: null });
101
+ });
102
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1jdXN0b21lci1mcm9tLXF1aWNrYm9va3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL3N0ZXBzL3JldmVyc2Utc3luYy9zeW5jLWN1c3RvbWVyLWZyb20tcXVpY2tib29rcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxxRUFBNEU7QUFDNUUscURBQW1EO0FBQ25ELDREQUErRDtBQU9sRCxRQUFBLDhCQUE4QixHQUFHLElBQUEsMEJBQVUsRUFDcEQsb0NBQW9DLEVBQ3BDLEtBQUssRUFBRSxLQUFzQyxFQUFFLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRTtJQUM1RCxNQUFNLE9BQU8sR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLDhCQUFpQixDQUE0QixDQUFBO0lBQy9FLE1BQU0scUJBQXFCLEdBQVEsU0FBUyxDQUFDLE9BQU8sQ0FBQyxlQUFPLENBQUMsUUFBUSxDQUFDLENBQUE7SUFFdEUscUJBQXFCO0lBQ3JCLE1BQU0sVUFBVSxHQUFHLE1BQU0sT0FBTyxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsb0JBQW9CLENBQUMsQ0FBQTtJQUN4RSxJQUFJLENBQUMsVUFBVTtRQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsa0NBQWtDLEtBQUssQ0FBQyxvQkFBb0IsRUFBRSxDQUFDLENBQUE7SUFFaEcsbUJBQW1CO0lBQ25CLE1BQU0sT0FBTyxHQUFHLE1BQU0sT0FBTyxDQUFDLHdCQUF3QixDQUFDLEtBQUssQ0FBQyxvQkFBb0IsRUFBRSxVQUFVLENBQUMsQ0FBQTtJQUU5RixJQUFJLGNBQWMsQ0FBQTtJQUVsQixNQUFNLFVBQVUsR0FBUTtRQUNwQixVQUFVLEVBQUUsVUFBVSxDQUFDLFNBQVM7UUFDaEMsU0FBUyxFQUFFLFVBQVUsQ0FBQyxVQUFVO1FBQ2hDLFlBQVksRUFBRSxVQUFVLENBQUMsV0FBVztRQUNwQyxLQUFLLEVBQUUsVUFBVSxDQUFDLFlBQVksRUFBRSxj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
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.syncInventoryFromQuickBooksStep = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const utils_1 = require("@medusajs/framework/utils");
6
+ const quickbooks_1 = require("../../../modules/quickbooks");
7
+ exports.syncInventoryFromQuickBooksStep = (0, workflows_sdk_1.createStep)("sync-inventory-from-quickbooks-step", async (input, { container }) => {
8
+ const service = container.resolve(quickbooks_1.QUICKBOOKS_MODULE);
9
+ const productModuleService = container.resolve(utils_1.Modules.PRODUCT);
10
+ const logger = container.resolve(utils_1.ContainerRegistrationKeys.LOGGER);
11
+ // 1. Get QB Item
12
+ const qbItem = await service.getItem(input.quickbooksItemId);
13
+ if (!qbItem)
14
+ throw new Error(`QuickBooks Item not found: ${input.quickbooksItemId}`);
15
+ // 2. Check Mapping
16
+ // Note: We used "product" for variant mapping in forward sync.
17
+ const mapping = await service.getMappingByQuickbooksId(input.quickbooksItemId, "Item");
18
+ if (mapping && mapping.medusa_entity_type === "product") { // "product" here means variant id
19
+ // Update Inventory in Medusa
20
+ // Medusa v2 Inventory Management is via InventoryModule usually, but ProductService can update variant inventory if using simple inventory?
21
+ // Medusa v2 decouples inventory. We should find the InventoryItem associated with the Variant.
22
+ // Or if using "manage_inventory" on variant directly (less common in v2 full setup but supported for simple cases).
23
+ // Actually, we should check `inventoryModuleService`?
24
+ // Let's assume standard Product Module usage.
25
+ // Retrieving variant to get associated inventory items is complex.
26
+ // SIMPLIFICATION for MVP:
27
+ // We will assert `manage_inventory` and try to update if possible.
28
+ // However, updating inventory directly on variant in v2 requires updating the Inventory Level.
29
+ // Strategy:
30
+ // 1. Get Variant.
31
+ // 2. Resolve Inventory Item ID (via Link Request? or Variant.inventory_items relation).
32
+ // 3. Update InventoryLevel.
33
+ // This is complex without "inventoryModuleService" access and knowing the location.
34
+ // We'll log a "TODO" or try to update `variant.inventory_quantity` which works if stock location module is not strictly enforced or if handling simple cases.
35
+ // Medusa v2 `updateProductVariants` doesn't strictly support `inventory_quantity` if inventory module is active?
36
+ // It DOES support it if `medusa-fulfillment-stock-location` is not blocking.
37
+ // Let's try simple update.
38
+ try {
39
+ // Update SKU/UPC if changed
40
+ await productModuleService.updateProductVariants(mapping.medusa_entity_id, {
41
+ sku: qbItem.Sku,
42
+ upc: qbItem.UPC
43
+ });
44
+ // Logging for Inventory
45
+ // Since actual inventory update is complex (requires location), we log it.
46
+ // However, updated SKU/UPC is valuable.
47
+ logger.info(`[QuickBooks] Synced Variant ${mapping.medusa_entity_id} details (SKU: ${qbItem.Sku}, UPC: ${qbItem.UPC}) from QB Item.`);
48
+ if (qbItem.QtyOnHand !== undefined) {
49
+ // Log inventory mismatch for manual checking
50
+ logger.info(`[QuickBooks] Item ${qbItem.Name} Qty: ${qbItem.QtyOnHand}. Ensure Medusa stock matches.`);
51
+ }
52
+ }
53
+ catch (e) {
54
+ logger.error(`Failed to update variant details: ${e.message}`);
55
+ }
56
+ }
57
+ else {
58
+ logger.info(`[QuickBooks] Item ${qbItem.Name} not mapped to any Medusa variant. Skipping.`);
59
+ }
60
+ return new workflows_sdk_1.StepResponse({ success: true });
61
+ });
62
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1pbnZlbnRvcnktZnJvbS1xdWlja2Jvb2tzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9zdGVwcy9yZXZlcnNlLXN5bmMvc3luYy1pbnZlbnRvcnktZnJvbS1xdWlja2Jvb2tzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHFFQUE0RTtBQUM1RSxxREFBOEU7QUFDOUUsNERBQStEO0FBT2xELFFBQUEsK0JBQStCLEdBQUcsSUFBQSwwQkFBVSxFQUNyRCxxQ0FBcUMsRUFDckMsS0FBSyxFQUFFLEtBQXVDLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFO0lBQzdELE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsOEJBQWlCLENBQTRCLENBQUE7SUFDL0UsTUFBTSxvQkFBb0IsR0FBUSxTQUFTLENBQUMsT0FBTyxDQUFDLGVBQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQTtJQUNwRSxNQUFNLE1BQU0sR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBRWxFLGlCQUFpQjtJQUNqQixNQUFNLE1BQU0sR0FBRyxNQUFNLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLGdCQUFnQixDQUFDLENBQUE7SUFDNUQsSUFBSSxDQUFDLE1BQU07UUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLDhCQUE4QixLQUFLLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFBO0lBRXBGLG1CQUFtQjtJQUNuQiwrREFBK0Q7SUFDL0QsTUFBTSxPQUFPLEdBQUcsTUFBTSxPQUFPLENBQUMsd0JBQXdCLENBQUMsS0FBSyxDQUFDLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxDQUFBO0lBRXRGLElBQUksT0FBTyxJQUFJLE9BQU8sQ0FBQyxrQkFBa0IsS0FBSyxTQUFTLEVBQUUsQ0FBQyxDQUFDLGtDQUFrQztRQUN6Riw2QkFBNkI7UUFDN0IsNElBQTRJO1FBQzVJLCtGQUErRjtRQUMvRixvSEFBb0g7UUFFcEgsc0RBQXNEO1FBQ3RELDhDQUE4QztRQUM5QyxtRUFBbUU7UUFFbkUsMEJBQTBCO1FBQzFCLG1FQUFtRTtRQUNuRSwrRkFBK0Y7UUFFL0YsYUFBYTtRQUNiLGtCQUFrQjtRQUNsQix3RkFBd0Y7UUFDeEYsNEJBQTRCO1FBRTVCLG9GQUFvRjtRQUNwRiw4SkFBOEo7UUFDOUosaUhBQWlIO1FBQ2pILDZFQUE2RTtRQUU3RSwyQkFBMkI7UUFDM0IsSUFBSSxDQUFDO1lBQ0QsNEJBQTRCO1lBQzVCLE1BQU0sb0JBQW9CLENBQUMscUJBQXFCLENBQUMsT0FBTyxDQUFDLGdCQUFnQixFQUFFO2dCQUN2RSxHQUFHLEVBQUUsTUFBTSxDQUFDLEdBQUc7Z0JBQ2YsR0FBRyxFQUFFLE1BQU0sQ0FBQyxHQUFHO2FBQ2xCLENBQUMsQ0FBQTtZQUVGLHdCQUF3QjtZQUN4QiwyRUFBMkU7WUFDM0Usd0NBQXdDO1lBQ3hDLE1BQU0sQ0FBQyxJQUFJLENBQUMsK0JBQStCLE9BQU8sQ0FBQyxnQkFBZ0Isa0JBQWtCLE1BQU0sQ0FBQyxHQUFHLFVBQVUsTUFBTSxDQUFDLEdBQUcsaUJBQWlCLENBQUMsQ0FBQTtZQUVySSxJQUFJLE1BQU0sQ0FBQyxTQUFTLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQ2pDLDZDQUE2QztnQkFDN0MsTUFBTSxDQUFDLElBQUksQ0FBQyxxQkFBcUIsTUFBTSxDQUFDLElBQUksU0FBUyxNQUFNLENBQUMsU0FBUyxnQ0FBZ0MsQ0FBQyxDQUFBO1lBQzFHLENBQUM7UUFFTCxDQUFDO1FBQUMsT0FBTyxDQUFNLEVBQUUsQ0FBQztZQUNkLE1BQU0sQ0FBQyxLQUFLLENBQUMscUNBQXFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFBO1FBQ2xFLENBQUM7SUFDTCxDQUFDO1NBQU0sQ0FBQztRQUNKLE1BQU0sQ0FBQyxJQUFJLENBQUMscUJBQXFCLE1BQU0sQ0FBQyxJQUFJLDhDQUE4QyxDQUFDLENBQUE7SUFDL0YsQ0FBQztJQUVELE9BQU8sSUFBSSw0QkFBWSxDQUFDLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUE7QUFDOUMsQ0FBQyxDQUNKLENBQUEifQ==
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.syncOrderStatusFromQuickBooksStep = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const utils_1 = require("@medusajs/framework/utils");
6
+ const quickbooks_1 = require("../../../modules/quickbooks");
7
+ exports.syncOrderStatusFromQuickBooksStep = (0, workflows_sdk_1.createStep)("sync-order-status-from-quickbooks-step", async (input, { container }) => {
8
+ const service = container.resolve(quickbooks_1.QUICKBOOKS_MODULE);
9
+ const orderModuleService = container.resolve(utils_1.Modules.ORDER);
10
+ const paymentModuleService = container.resolve(utils_1.Modules.PAYMENT);
11
+ const logger = container.resolve("logger");
12
+ // 1. Get QB Entity
13
+ let qbEntity;
14
+ if (input.entityType === "Invoice") {
15
+ qbEntity = await service.getInvoice(input.quickbooksEntityId);
16
+ }
17
+ else {
18
+ qbEntity = await service.getSalesReceipt(input.quickbooksEntityId);
19
+ }
20
+ if (!qbEntity) {
21
+ throw new Error(`${input.entityType} not found in QB: ${input.quickbooksEntityId}`);
22
+ }
23
+ // 2. Check Balance (If 0, it's paid)
24
+ // SalesReceipt is always paid (Balance 0 usually or implicit).
25
+ // Invoice has Balance.
26
+ const isPaid = input.entityType === "SalesReceipt" || (qbEntity.Balance === 0 && qbEntity.LinkedTxn?.length > 0);
27
+ if (!isPaid) {
28
+ return new workflows_sdk_1.StepResponse({ success: false, reason: "Invoice not paid", order: null });
29
+ }
30
+ // 3. Find Mapping
31
+ const mapping = await service.getMappingByQuickbooksId(input.quickbooksEntityId, input.entityType);
32
+ if (!mapping) {
33
+ return new workflows_sdk_1.StepResponse({ success: false, reason: "No mapping found", order: null });
34
+ }
35
+ // 4. Update Medusa Order
36
+ // If paid, we should Capture the payment.
37
+ // Medusa v2: Retrieve order -> Get Payment Collections -> Capture.
38
+ try {
39
+ const order = await orderModuleService.retrieveOrder(mapping.medusa_entity_id, {
40
+ relations: ["payment_collections"]
41
+ });
42
+ if (order.payment_status === "captured") {
43
+ return new workflows_sdk_1.StepResponse({ success: true, reason: "Already captured", order });
44
+ }
45
+ // Iterate payment collections to find authorized ones to capture
46
+ if (order.payment_collections) {
47
+ for (const collection of order.payment_collections) {
48
+ if (collection.status === "authorized") {
49
+ // Find authorized payment
50
+ // In Medusa v2, we might not have 'payments' relation loaded by default unless requested.
51
+ // But we requested relations: ["payment_collections"].
52
+ // Check nested relations usage in retrieveOrder?
53
+ // Assuming we can target the payment collection or its payment.
54
+ // We will attempt to use paymentModuleService to list payments for this collection.
55
+ const payments = await paymentModuleService.listPayments({
56
+ payment_collection_id: collection.id,
57
+ // status: "authorized"?
58
+ });
59
+ const authorizedPayment = payments.find((p) => !p.captured_at && !p.canceled_at);
60
+ if (authorizedPayment) {
61
+ logger.info(`[QB Sync] Capturing payment ${authorizedPayment.id} for Order ${order.id}`);
62
+ await paymentModuleService.capturePayment({ payment_id: authorizedPayment.id });
63
+ return new workflows_sdk_1.StepResponse({ success: true, reason: "Payment Captured", order });
64
+ }
65
+ }
66
+ }
67
+ }
68
+ logger.info(`[QB Sync] Detected payment in QB but found no authorized payment to capture in Medusa Order ${order.id}.`);
69
+ }
70
+ catch (e) {
71
+ logger.error(`Failed to update order status: ${e.message}`);
72
+ throw e;
73
+ }
74
+ return new workflows_sdk_1.StepResponse({ success: true, reason: "Synced status (Logged)", order: null });
75
+ });
76
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1vcmRlci1zdGF0dXMtZnJvbS1xdWlja2Jvb2tzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9zdGVwcy9yZXZlcnNlLXN5bmMvc3luYy1vcmRlci1zdGF0dXMtZnJvbS1xdWlja2Jvb2tzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHFFQUE0RTtBQUM1RSxxREFBbUQ7QUFDbkQsNERBQStEO0FBUWxELFFBQUEsaUNBQWlDLEdBQUcsSUFBQSwwQkFBVSxFQUN2RCx3Q0FBd0MsRUFDeEMsS0FBSyxFQUFFLEtBQXlDLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFO0lBQy9ELE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsOEJBQWlCLENBQTRCLENBQUE7SUFDL0UsTUFBTSxrQkFBa0IsR0FBUSxTQUFTLENBQUMsT0FBTyxDQUFDLGVBQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUNoRSxNQUFNLG9CQUFvQixHQUFRLFNBQVMsQ0FBQyxPQUFPLENBQUMsZUFBTyxDQUFDLE9BQU8sQ0FBQyxDQUFBO0lBQ3BFLE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFRLENBQUE7SUFFakQsbUJBQW1CO0lBQ25CLElBQUksUUFBUSxDQUFBO0lBQ1osSUFBSSxLQUFLLENBQUMsVUFBVSxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQ2pDLFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLENBQUE7SUFDakUsQ0FBQztTQUFNLENBQUM7UUFDSixRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFBO0lBQ3RFLENBQUM7SUFFRCxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDWixNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsS0FB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
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.syncCustomerToQuickBooksStep = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const quickbooks_1 = require("../../modules/quickbooks");
6
+ exports.syncCustomerToQuickBooksStep = (0, workflows_sdk_1.createStep)("sync-customer-to-quickbooks", async (input, { container }) => {
7
+ const service = container.resolve(quickbooks_1.QUICKBOOKS_MODULE);
8
+ // Check if mapping exists to decide update vs create
9
+ const mapping = await service.getMapping(input.medusaCustomerId, "customer");
10
+ let result;
11
+ if (mapping && mapping.quickbooks_entity_id) {
12
+ // Update existing
13
+ // Need to fetch current sync token first for QB updates
14
+ try {
15
+ const currentQbCustomer = await service.getCustomer(mapping.quickbooks_entity_id);
16
+ const updateData = {
17
+ ...input.qbCustomerData,
18
+ Id: mapping.quickbooks_entity_id,
19
+ SyncToken: currentQbCustomer.SyncToken
20
+ };
21
+ result = await service.updateCustomer(updateData);
22
+ }
23
+ catch (error) {
24
+ // If not found, fall back to create? Or error?
25
+ // If 404, maybe create new?
26
+ if (error.message?.includes("Object Not Found")) {
27
+ console.warn("QB Customer not found despite mapping, creating new...");
28
+ result = await service.createCustomer(input.qbCustomerData);
29
+ }
30
+ else {
31
+ throw error;
32
+ }
33
+ }
34
+ }
35
+ else {
36
+ // Create new
37
+ // First check by email to avoid duplicates if mapping is missing
38
+ const existingCustomers = await service.findCustomerByEmail(input.qbCustomerData.PrimaryEmailAddr.Address);
39
+ if (existingCustomers && existingCustomers.length > 0) {
40
+ const existing = existingCustomers[0];
41
+ // Update existing found by email
42
+ const updateData = {
43
+ ...input.qbCustomerData,
44
+ Id: existing.Id,
45
+ SyncToken: existing.SyncToken
46
+ };
47
+ result = await service.updateCustomer(updateData);
48
+ }
49
+ else {
50
+ result = await service.createCustomer(input.qbCustomerData);
51
+ }
52
+ }
53
+ return new workflows_sdk_1.StepResponse(result);
54
+ });
55
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1jdXN0b21lci10by1xdWlja2Jvb2tzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9zdGVwcy9zeW5jLWN1c3RvbWVyLXRvLXF1aWNrYm9va3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscUVBQTRFO0FBQzVFLHlEQUE0RDtBQVEvQyxRQUFBLDRCQUE0QixHQUFHLElBQUEsMEJBQVUsRUFDbEQsNkJBQTZCLEVBQzdCLEtBQUssRUFBRSxLQUFvQyxFQUFFLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRTtJQUMxRCxNQUFNLE9BQU8sR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLDhCQUFpQixDQUE0QixDQUFBO0lBRS9FLHFEQUFxRDtJQUNyRCxNQUFNLE9BQU8sR0FBRyxNQUFNLE9BQU8sQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLGdCQUFnQixFQUFFLFVBQVUsQ0FBQyxDQUFBO0lBRTVFLElBQUksTUFBTSxDQUFBO0lBQ1YsSUFBSSxPQUFPLElBQUksT0FBTyxDQUFDLG9CQUFvQixFQUFFLENBQUM7UUFDMUMsa0JBQWtCO1FBQ2xCLHdEQUF3RDtRQUN4RCxJQUFJLENBQUM7WUFDRCxNQUFNLGlCQUFpQixHQUFHLE1BQU0sT0FBTyxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsb0JBQW9CLENBQUMsQ0FBQTtZQUNqRixNQUFNLFVBQVUsR0FBRztnQkFDZixHQUFHLEtBQUssQ0FBQyxjQUFjO2dCQUN2QixFQUFFLEVBQUUsT0FBTyxDQUFDLG9CQUFvQjtnQkFDaEMsU0FBUyxFQUFFLGlCQUFpQixDQUFDLFNBQVM7YUFDekMsQ0FBQTtZQUNELE1BQU0sR0FBRyxNQUFNLE9BQU8sQ0FBQyxjQUFjLENBQUMsVUFBVSxDQUFDLENBQUE7UUFDckQsQ0FBQztRQUFDLE9BQU8sS0FBVSxFQUFFLENBQUM7WUFDbEIsK0NBQStDO1lBQy9DLDRCQUE0QjtZQUM1QixJQUFJLEtBQUssQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsQ0FBQztnQkFDOUMsT0FBTyxDQUFDLElBQUksQ0FBQyx3REFBd0QsQ0FBQyxDQUFBO2dCQUN0RSxNQUFNLEdBQUcsTUFBTSxPQUFPLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQTtZQUMvRCxDQUFDO2lCQUFNLENBQUM7Z0JBQ0osTUFBTSxLQUFLLENBQUE7WUFDZixDQUFDO1FBQ0wsQ0FBQztJQUNMLENBQUM7U0FBTSxDQUFDO1FBQ0osYUFBYTtRQUNiLGlFQUFpRTtRQUNqRSxNQUFNLGlCQUFpQixHQUFHLE1BQU0sT0FBTyxDQUFDLG1CQUFtQixDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUE7UUFDMUcsSUFBSSxpQkFBaUIsSUFBSSxpQkFBaUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDcEQsTUFBTSxRQUFRLEdBQUcsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFDckMsaUNBQWlDO1lBQ2pDLE1BQU0sVUFBVSxHQUFHO2dCQUNmLEdBQUcsS0FBSyxDQUFDLGNBQWM7Z0JBQ3ZCLEVBQUUsRUFBRSxRQUFRLENBQUMsRUFBRTtnQkFDZixTQUFTLEVBQUUsUUFBUSxDQUFDLFNBQVM7YUFDaEMsQ0FBQTtZQUNELE1BQU0sR0FBRyxNQUFNLE9BQU8sQ0FBQyxjQUFjLENBQUMsVUFBVSxDQUFDLENBQUE7UUFDckQsQ0FBQzthQUFNLENBQUM7WUFDSixNQUFNLEdBQUcsTUFBTSxPQUFPLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQTtRQUMvRCxDQUFDO0lBQ0wsQ0FBQztJQUVELE9BQU8sSUFBSSw0QkFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFBO0FBQ25DLENBQUMsQ0FDSixDQUFBIn0=
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.syncProductToQuickBooksStep = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const quickbooks_1 = require("../../modules/quickbooks");
6
+ exports.syncProductToQuickBooksStep = (0, workflows_sdk_1.createStep)("sync-product-to-quickbooks", async (input, { container }) => {
7
+ const service = container.resolve(quickbooks_1.QUICKBOOKS_MODULE);
8
+ // Check if mapping exists
9
+ const mapping = await service.getMapping(input.medusaVariantId, "variant"); // Using "variant" or "product"? MappingService allowed "product". Let's use "product" to keep it simple or "variant" if I update types?
10
+ // Types in MappingService/Model were "product". I should reuse "product" but store variant ID.
11
+ const mappingParams = { id: input.medusaVariantId, type: "product" };
12
+ const existingMapping = await service.getMapping(input.medusaVariantId, "product");
13
+ let result;
14
+ if (existingMapping && existingMapping.quickbooks_entity_id) {
15
+ // Update
16
+ try {
17
+ const currentItem = await service.getItem(existingMapping.quickbooks_entity_id);
18
+ const updateData = {
19
+ ...input.qbItemData,
20
+ Id: existingMapping.quickbooks_entity_id,
21
+ SyncToken: currentItem.SyncToken
22
+ };
23
+ // QtyOnHand cannot be updated via Item update for Inventory items usually.
24
+ // It requires InventoryAdjustment.
25
+ // We should remove QtyOnHand from update payload.
26
+ delete updateData.QtyOnHand;
27
+ delete updateData.InvStartDate;
28
+ result = await service.updateItem(updateData);
29
+ }
30
+ catch (error) {
31
+ if (error.message?.includes("Object Not Found")) {
32
+ result = await service.createItem(input.qbItemData);
33
+ }
34
+ else {
35
+ throw error;
36
+ }
37
+ }
38
+ }
39
+ else {
40
+ // Create
41
+ // Check by name/sku
42
+ const existingItem = await service.findItemBySku(input.qbItemData.Sku);
43
+ if (existingItem) {
44
+ const updateData = {
45
+ ...input.qbItemData,
46
+ Id: existingItem.Id,
47
+ SyncToken: existingItem.SyncToken
48
+ };
49
+ delete updateData.QtyOnHand;
50
+ delete updateData.InvStartDate;
51
+ result = await service.updateItem(updateData);
52
+ }
53
+ else {
54
+ result = await service.createItem(input.qbItemData);
55
+ }
56
+ }
57
+ return new workflows_sdk_1.StepResponse(result);
58
+ });
59
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1wcm9kdWN0LXRvLXF1aWNrYm9va3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL3N0ZXBzL3N5bmMtcHJvZHVjdC10by1xdWlja2Jvb2tzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHFFQUE0RTtBQUM1RSx5REFBNEQ7QUFRL0MsUUFBQSwyQkFBMkIsR0FBRyxJQUFBLDBCQUFVLEVBQ2pELDRCQUE0QixFQUM1QixLQUFLLEVBQUUsS0FBbUMsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUU7SUFDekQsTUFBTSxPQUFPLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyw4QkFBaUIsQ0FBNEIsQ0FBQTtJQUUvRSwwQkFBMEI7SUFDMUIsTUFBTSxPQUFPLEdBQUcsTUFBTSxPQUFPLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxlQUFlLEVBQUUsU0FBUyxDQUFDLENBQUEsQ0FBQyx5SUFBeUk7SUFDcE4sK0ZBQStGO0lBQy9GLE1BQU0sYUFBYSxHQUFHLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxlQUFlLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxDQUFBO0lBRXBFLE1BQU0sZUFBZSxHQUFHLE1BQU0sT0FBTyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsZUFBZSxFQUFFLFNBQVMsQ0FBQyxDQUFBO0lBRWxGLElBQUksTUFBTSxDQUFBO0lBQ1YsSUFBSSxlQUFlLElBQUksZUFBZSxDQUFDLG9CQUFvQixFQUFFLENBQUM7UUFDMUQsU0FBUztRQUNULElBQUksQ0FBQztZQUNELE1BQU0sV0FBVyxHQUFHLE1BQU0sT0FBTyxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsb0JBQW9CLENBQUMsQ0FBQTtZQUMvRSxNQUFNLFVBQVUsR0FBRztnQkFDZixHQUFHLEtBQUssQ0FBQyxVQUFVO2dCQUNuQixFQUFFLEVBQUUsZUFBZSxDQUFDLG9CQUFvQjtnQkFDeEMsU0FBUyxFQUFFLFdBQVcsQ0FBQyxTQUFTO2FBQ25DLENBQUE7WUFDRCw0RUFBNEU7WUFDNUUsbUNBQW1DO1lBQ25DLGtEQUFrRDtZQUNsRCxPQUFPLFVBQVUsQ0FBQyxTQUFTLENBQUE7WUFDM0IsT0FBTyxVQUFVLENBQUMsWUFBWSxDQUFBO1lBRTlCLE1BQU0sR0FBRyxNQUFNLE9BQU8sQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUE7UUFDakQsQ0FBQztRQUFDLE9BQU8sS0FBVSxFQUFFLENBQUM7WUFDbEIsSUFBSSxLQUFLLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLENBQUM7Z0JBQzlDLE1BQU0sR0FBRyxNQUFNLE9BQU8sQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFBO1lBQ3ZELENBQUM7aUJBQU0sQ0FBQztnQkFDSixNQUFNLEtBQUssQ0FBQTtZQUNmLENBQUM7UUFDTCxDQUFDO0lBQ0wsQ0FBQztTQUFNLENBQUM7UUFDSixTQUFTO1FBQ1Qsb0JBQW9CO1FBQ3BCLE1BQU0sWUFBWSxHQUFHLE1BQU0sT0FBTyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFBO1FBQ3RFLElBQUksWUFBWSxFQUFFLENBQUM7WUFDZixNQUFNLFVBQVUsR0FBRztnQkFDZixHQUFHLEtBQUssQ0FBQyxVQUFVO2dCQUNuQixFQUFFLEVBQUUsWUFBWSxDQUFDLEVBQUU7Z0JBQ25CLFNBQVMsRUFBRSxZQUFZLENBQUMsU0FBUzthQUNwQyxDQUFBO1lBQ0QsT0FBTyxVQUFVLENBQUMsU0FBUyxDQUFBO1lBQzNCLE9BQU8sVUFBVSxDQUFDLFlBQVksQ0FBQTtZQUM5QixNQUFNLEdBQUcsTUFBTSxPQUFPLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFBO1FBQ2pELENBQUM7YUFBTSxDQUFDO1lBQ0osTUFBTSxHQUFHLE1BQU0sT0FBTyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUE7UUFDdkQsQ0FBQztJQUNMLENBQUM7SUFFRCxPQUFPLElBQUksNEJBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQTtBQUNuQyxDQUFDLENBQ0osQ0FBQSJ9
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.transformCustomerStep = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ exports.transformCustomerStep = (0, workflows_sdk_1.createStep)("transform-customer", async (input) => {
6
+ const { customer } = input;
7
+ // Map Medusa customer to QuickBooks customer format
8
+ // Note: node-quickbooks expects specific field names
9
+ const qbCustomer = {
10
+ GivenName: customer.first_name || "Guest",
11
+ FamilyName: customer.last_name || "Customer",
12
+ PrimaryEmailAddr: {
13
+ Address: customer.email,
14
+ },
15
+ // Maps DisplayName to something unique if possible, or let QB handle it (might duplicate)
16
+ // QB requires unique DisplayName.
17
+ DisplayName: `${customer.first_name || "Guest"} ${customer.last_name || "Customer"} (${customer.email})`,
18
+ CompanyName: customer.company_name || undefined,
19
+ BillAddr: customer.billing_address ? {
20
+ Line1: customer.billing_address.address_1,
21
+ Line2: customer.billing_address.address_2,
22
+ City: customer.billing_address.city,
23
+ CountrySubDivisionCode: customer.billing_address.province,
24
+ PostalCode: customer.billing_address.postal_code,
25
+ Country: customer.billing_address.country_code?.toUpperCase(),
26
+ } : undefined,
27
+ ShipAddr: customer.shipping_addresses?.[0] ? {
28
+ Line1: customer.shipping_addresses[0].address_1,
29
+ Line2: customer.shipping_addresses[0].address_2,
30
+ City: customer.shipping_addresses[0].city,
31
+ CountrySubDivisionCode: customer.shipping_addresses[0].province,
32
+ PostalCode: customer.shipping_addresses[0].postal_code,
33
+ Country: customer.shipping_addresses[0].country_code?.toUpperCase(),
34
+ } : undefined,
35
+ PrimaryPhone: customer.phone ? {
36
+ FreeFormNumber: customer.phone,
37
+ } : undefined,
38
+ };
39
+ return new workflows_sdk_1.StepResponse(qbCustomer);
40
+ });
41
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmb3JtLWN1c3RvbWVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9zdGVwcy90cmFuc2Zvcm0tY3VzdG9tZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscUVBQTRFO0FBTS9ELFFBQUEscUJBQXFCLEdBQUcsSUFBQSwwQkFBVSxFQUMzQyxvQkFBb0IsRUFDcEIsS0FBSyxFQUFFLEtBQTZCLEVBQUUsRUFBRTtJQUNwQyxNQUFNLEVBQUUsUUFBUSxFQUFFLEdBQUcsS0FBSyxDQUFBO0lBRTFCLG9EQUFvRDtJQUNwRCxxREFBcUQ7SUFDckQsTUFBTSxVQUFVLEdBQUc7UUFDZixTQUFTLEVBQUUsUUFBUSxDQUFDLFVBQVUsSUFBSSxPQUFPO1FBQ3pDLFVBQVUsRUFBRSxRQUFRLENBQUMsU0FBUyxJQUFJLFVBQVU7UUFDNUMsZ0JBQWdCLEVBQUU7WUFDZCxPQUFPLEVBQUUsUUFBUSxDQUFDLEtBQUs7U0FDMUI7UUFDRCwwRkFBMEY7UUFDMUYsbUNBQW1DO1FBQ25DLFdBQVcsRUFBRSxHQUFHLFFBQVEsQ0FBQyxVQUFVLElBQUksT0FBTyxJQUFJLFFBQVEsQ0FBQyxTQUFTLElBQUksVUFBVSxLQUFLLFFBQVEsQ0FBQyxLQUFLLEdBQUc7UUFDeEcsV0FBVyxFQUFFLFFBQVEsQ0FBQyxZQUFZLElBQUksU0FBUztRQUMvQyxRQUFRLEVBQUUsUUFBUSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUM7WUFDakMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxlQUFlLENBQUMsU0FBUztZQUN6QyxLQUFLLEVBQUUsUUFBUSxDQUFDLGVBQWUsQ0FBQyxTQUFTO1lBQ3pDLElBQUksRUFBRSxRQUFRLENBQUMsZUFBZSxDQUFDLElBQUk7WUFDbkMsc0JBQXNCLEVBQUUsUUFBUSxDQUFDLGVBQWUsQ0FBQyxRQUFRO1lBQ3pELFVBQVUsRUFBRSxRQUFRLENBQUMsZUFBZSxDQUFDLFdBQVc7WUFDaEQsT0FBTyxFQUFFLFFBQVEsQ0FBQyxlQUFlLENBQUMsWUFBWSxFQUFFLFdBQVcsRUFBRTtTQUNoRSxDQUFDLENBQUMsQ0FBQyxTQUFTO1FBQ2IsUUFBUSxFQUFFLFFBQVEsQ0FBQyxrQkFBa0IsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN6QyxLQUFLLEVBQUUsUUFBUSxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVM7WUFDL0MsS0FBSyxFQUFFLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTO1lBQy9DLElBQUksRUFBRSxRQUFRLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSTtZQUN6QyxzQkFBc0IsRUFBRSxRQUFRLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUTtZQUMvRCxVQUFVLEVBQUUsUUFBUSxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVc7WUFDdEQsT0FBTyxFQUFFLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLEVBQUUsV0FBVyxFQUFFO1NBQ3RFLENBQUMsQ0FBQyxDQUFDLFNBQVM7UUFDYixZQUFZLEVBQUUsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDM0IsY0FBYyxFQUFFLFFBQVEsQ0FBQyxLQUFLO1NBQ2pDLENBQUMsQ0FBQyxDQUFDLFNBQVM7S0FDaEIsQ0FBQTtJQUVELE9BQU8sSUFBSSw0QkFBWSxDQUFDLFVBQVUsQ0FBQyxDQUFBO0FBQ3ZDLENBQUMsQ0FDSixDQUFBIn0=
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.transformProductStep = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const quickbooks_1 = require("../../modules/quickbooks");
6
+ exports.transformProductStep = (0, workflows_sdk_1.createStep)("transform-product", async (input, { container }) => {
7
+ const service = container.resolve(quickbooks_1.QUICKBOOKS_MODULE);
8
+ const settings = await service.getOrCreateSettings();
9
+ const { product, variant } = input;
10
+ // If variant is provided, we map variant to QB Item
11
+ // Use SKU as Name, or Product Title + Variant Title
12
+ const name = variant.sku || `${product.title} - ${variant.title}`;
13
+ const sku = variant.sku || variant.id;
14
+ const qbItem = {
15
+ Name: name.substring(0, 100), // QB Name limit
16
+ Sku: sku.substring(0, 100),
17
+ UPC: (variant.upc || variant.ean || variant.barcode)?.substring(0, 50),
18
+ Description: product.description,
19
+ Type: "Inventory", // or NonInventory, Service. Defaulting to Inventory if manage_inventory is true?
20
+ TrackQtyOnHand: variant.manage_inventory || false,
21
+ QtyOnHand: variant.inventory_quantity || 0,
22
+ InvStartDate: new Date().toISOString().split('T')[0], // Required for Inventory
23
+ UnitPrice: variant.prices?.[0]?.amount || 0, // Simplified price picking
24
+ IncomeAccountRef: settings.income_account_id ? { value: settings.income_account_id } : undefined,
25
+ AssetAccountRef: settings.asset_account_id ? { value: settings.asset_account_id } : undefined,
26
+ ExpenseAccountRef: settings.cogs_account_id ? { value: settings.cogs_account_id } : undefined,
27
+ };
28
+ // If not tracking quantity, change type to NonInventory to avoid InvStartDate/QtyOnHand issues if accounts not set?
29
+ // Actually, stick to NonInventory if accounts are missing to be safe?
30
+ // For now, let's assume Inventory if manage_inventory is true.
31
+ if (!variant.manage_inventory) {
32
+ qbItem.Type = "NonInventory";
33
+ delete qbItem.QtyOnHand;
34
+ delete qbItem.InvStartDate;
35
+ delete qbItem.AssetAccountRef;
36
+ }
37
+ return new workflows_sdk_1.StepResponse(qbItem);
38
+ });
39
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmb3JtLXByb2R1Y3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL3N0ZXBzL3RyYW5zZm9ybS1wcm9kdWN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHFFQUE0RTtBQUM1RSx5REFBNEQ7QUFRL0MsUUFBQSxvQkFBb0IsR0FBRyxJQUFBLDBCQUFVLEVBQzFDLG1CQUFtQixFQUNuQixLQUFLLEVBQUUsS0FBNEIsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUU7SUFDbEQsTUFBTSxPQUFPLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyw4QkFBaUIsQ0FBNEIsQ0FBQTtJQUMvRSxNQUFNLFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxtQkFBbUIsRUFBRSxDQUFBO0lBRXBELE1BQU0sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLEdBQUcsS0FBSyxDQUFBO0lBRWxDLG9EQUFvRDtJQUNwRCxvREFBb0Q7SUFDcEQsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLEdBQUcsSUFBSSxHQUFHLE9BQU8sQ0FBQyxLQUFLLE1BQU0sT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFBO0lBQ2pFLE1BQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxHQUFHLElBQUksT0FBTyxDQUFDLEVBQUUsQ0FBQTtJQUVyQyxNQUFNLE1BQU0sR0FBRztRQUNYLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsRUFBRSxnQkFBZ0I7UUFDOUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQztRQUMxQixHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxJQUFJLE9BQU8sQ0FBQyxHQUFHLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ3RFLFdBQVcsRUFBRSxPQUFPLENBQUMsV0FBVztRQUNoQyxJQUFJLEVBQUUsV0FBVyxFQUFFLGlGQUFpRjtRQUNwRyxjQUFjLEVBQUUsT0FBTyxDQUFDLGdCQUFnQixJQUFJLEtBQUs7UUFDakQsU0FBUyxFQUFFLE9BQU8sQ0FBQyxrQkFBa0IsSUFBSSxDQUFDO1FBQzFDLFlBQVksRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSx5QkFBeUI7UUFDL0UsU0FBUyxFQUFFLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLElBQUksQ0FBQyxFQUFFLDJCQUEyQjtRQUN4RSxnQkFBZ0IsRUFBRSxRQUFRLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLFFBQVEsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTO1FBQ2hHLGVBQWUsRUFBRSxRQUFRLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTO1FBQzdGLGlCQUFpQixFQUFFLFFBQVEsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLFFBQVEsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDLENBQUMsU0FBUztLQUNoRyxDQUFBO0lBRUQsb0hBQW9IO0lBQ3BILHNFQUFzRTtJQUN0RSwrREFBK0Q7SUFDL0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBQzVCLE1BQU0sQ0FBQyxJQUFJLEdBQUcsY0FBYyxDQUFBO1FBQzVCLE9BQVEsTUFBYyxDQUFDLFNBQVMsQ0FBQTtRQUNoQyxPQUFRLE1BQWMsQ0FBQyxZQUFZLENBQUE7UUFDbkMsT0FBUSxNQUFjLENBQUMsZUFBZSxDQUFBO0lBQzFDLENBQUM7SUFFRCxPQUFPLElBQUksNEJBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQTtBQUNuQyxDQUFDLENBQ0osQ0FBQSJ9
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.updateProductSyncMappingStep = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const quickbooks_1 = require("../../modules/quickbooks");
6
+ exports.updateProductSyncMappingStep = (0, workflows_sdk_1.createStep)("update-product-sync-mapping", async (input, { container }) => {
7
+ const service = container.resolve(quickbooks_1.QUICKBOOKS_MODULE);
8
+ await service.createOrUpdateMapping({
9
+ medusa_entity_id: input.medusaVariantId,
10
+ medusa_entity_type: "product", // Using generic "product" type
11
+ quickbooks_entity_id: input.quickbooksItem.Id,
12
+ quickbooks_entity_type: "Item",
13
+ sync_status: "synced"
14
+ });
15
+ return new workflows_sdk_1.StepResponse({ success: true });
16
+ });
17
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBkYXRlLXByb2R1Y3Qtc3luYy1tYXBwaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9zdGVwcy91cGRhdGUtcHJvZHVjdC1zeW5jLW1hcHBpbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscUVBQTRFO0FBQzVFLHlEQUE0RDtBQVEvQyxRQUFBLDRCQUE0QixHQUFHLElBQUEsMEJBQVUsRUFDbEQsNkJBQTZCLEVBQzdCLEtBQUssRUFBRSxLQUFvQyxFQUFFLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRTtJQUMxRCxNQUFNLE9BQU8sR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLDhCQUFpQixDQUE0QixDQUFBO0lBRS9FLE1BQU0sT0FBTyxDQUFDLHFCQUFxQixDQUFDO1FBQ2hDLGdCQUFnQixFQUFFLEtBQUssQ0FBQyxlQUFlO1FBQ3ZDLGtCQUFrQixFQUFFLFNBQVMsRUFBRSxnQ0FBZ0M7UUFDL0Qsb0JBQW9CLEVBQUUsS0FBSyxDQUFDLGNBQWMsQ0FBQyxFQUFFO1FBQzdDLHNCQUFzQixFQUFFLE1BQU07UUFDOUIsV0FBVyxFQUFFLFFBQVE7S0FDeEIsQ0FBQyxDQUFBO0lBRUYsT0FBTyxJQUFJLDRCQUFZLENBQUMsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQTtBQUM5QyxDQUFDLENBQ0osQ0FBQSJ9