@lodashventure/medusa-campaign 1.1.4 → 1.1.6

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 (50) hide show
  1. package/.medusa/server/src/api/admin/buy-x-get-y/[id]/route.js +116 -0
  2. package/.medusa/server/src/api/admin/buy-x-get-y/route.js +83 -0
  3. package/.medusa/server/src/api/admin/campaigns/fix-dates/route.js +103 -0
  4. package/.medusa/server/src/api/admin/campaigns/sync/route.js +138 -0
  5. package/.medusa/server/src/api/admin/flash-sales/[id]/route.js +49 -34
  6. package/.medusa/server/src/api/admin/flash-sales/route.js +46 -19
  7. package/.medusa/server/src/api/admin/force-fix/route.js +176 -0
  8. package/.medusa/server/src/api/admin/test-campaign/route.js +132 -0
  9. package/.medusa/server/src/api/store/buy-x-get-y/[id]/route.js +109 -0
  10. package/.medusa/server/src/api/store/buy-x-get-y/products/[productId]/route.js +94 -0
  11. package/.medusa/server/src/api/store/buy-x-get-y/route.js +114 -0
  12. package/.medusa/server/src/api/store/campaigns/[id]/route.js +132 -70
  13. package/.medusa/server/src/api/store/campaigns/route.js +119 -26
  14. package/.medusa/server/src/index.js +15 -0
  15. package/.medusa/server/src/modules/custom-campaigns/migrations/Migration20251018000000.js +40 -0
  16. package/.medusa/server/src/modules/custom-campaigns/models/buy-x-get-y-config.js +20 -0
  17. package/.medusa/server/src/modules/custom-campaigns/service.js +3 -1
  18. package/.medusa/server/src/modules/custom-campaigns/types/campaign-type.enum.js +2 -1
  19. package/.medusa/server/src/subscribers/cart-updated.js +23 -0
  20. package/.medusa/server/src/subscribers/order-placed.js +9 -2
  21. package/.medusa/server/src/workflows/buy-x-get-y/applyBuyXGetYToCartWorkflow.js +150 -0
  22. package/.medusa/server/src/workflows/custom-campaign/createBuyXGetYCampaignWorkflow.js +127 -0
  23. package/.medusa/server/src/workflows/custom-campaign/updateBuyXGetYCampaignWorkflow.js +114 -0
  24. package/.medusa/server/src/workflows/custom-campaign/updateBuyXGetYUsageWorkflow.js +51 -0
  25. package/package.json +2 -2
  26. package/src/admin/components/BuyXGetYForm.tsx +422 -0
  27. package/src/api/admin/buy-x-get-y/[id]/route.ts +164 -0
  28. package/src/api/admin/buy-x-get-y/route.ts +104 -0
  29. package/src/api/admin/campaigns/fix-dates/route.ts +107 -0
  30. package/src/api/admin/campaigns/sync/route.ts +153 -0
  31. package/src/api/admin/flash-sales/[id]/route.ts +62 -36
  32. package/src/api/admin/flash-sales/route.ts +57 -21
  33. package/src/api/admin/force-fix/route.ts +184 -0
  34. package/src/api/admin/test-campaign/route.ts +141 -0
  35. package/src/api/store/buy-x-get-y/[id]/route.ts +146 -0
  36. package/src/api/store/buy-x-get-y/products/[productId]/route.ts +129 -0
  37. package/src/api/store/buy-x-get-y/route.ts +134 -0
  38. package/src/api/store/campaigns/[id]/route.ts +159 -79
  39. package/src/api/store/campaigns/route.ts +141 -30
  40. package/src/index.ts +10 -0
  41. package/src/modules/custom-campaigns/migrations/Migration20251018000000.ts +42 -0
  42. package/src/modules/custom-campaigns/models/buy-x-get-y-config.ts +19 -0
  43. package/src/modules/custom-campaigns/service.ts +2 -0
  44. package/src/modules/custom-campaigns/types/campaign-type.enum.ts +1 -0
  45. package/src/subscribers/cart-updated.ts +23 -0
  46. package/src/subscribers/order-placed.ts +9 -1
  47. package/src/workflows/buy-x-get-y/applyBuyXGetYToCartWorkflow.ts +222 -0
  48. package/src/workflows/custom-campaign/createBuyXGetYCampaignWorkflow.ts +210 -0
  49. package/src/workflows/custom-campaign/updateBuyXGetYCampaignWorkflow.ts +190 -0
  50. package/src/workflows/custom-campaign/updateBuyXGetYUsageWorkflow.ts +86 -0
@@ -10,6 +10,7 @@ const validators_1 = require("@medusajs/medusa/api/utils/validators");
10
10
  const zod_1 = __importDefault(require("zod"));
11
11
  const campaign_type_enum_1 = require("../../../modules/custom-campaigns/types/campaign-type.enum");
12
12
  const createCustomCampaignWorkflow_1 = require("../../../workflows/custom-campaign/createCustomCampaignWorkflow");
13
+ const custom_campaigns_1 = require("../../../modules/custom-campaigns");
13
14
  exports.createCustomCampaignSchema = zod_1.default.object({
14
15
  name: zod_1.default.string().min(1, "Name is required"),
15
16
  description: zod_1.default.string().min(1, "Description is required"),
@@ -48,24 +49,50 @@ const POST = async (req, res) => {
48
49
  };
49
50
  exports.POST = POST;
50
51
  const GET = async (req, res) => {
51
- const query = framework_1.container.resolve(utils_1.ContainerRegistrationKeys.QUERY);
52
- const { data: customCampaigns, metadata: { count, take, skip } = {
53
- count: 0,
54
- take: 20,
55
- skip: 0,
56
- }, } = await query.graph({
57
- entity: "custom_campaign_type",
58
- ...req.queryConfig,
59
- fields: ["id", "campaign.*", "campaign.promotions.*"],
60
- filters: { type: campaign_type_enum_1.CampaignTypeEnum.FlashSale },
61
- });
62
- const campaigns = customCampaigns.map((campaign) => campaign.campaign);
63
- res.status(200).json({
64
- campaigns,
65
- count,
66
- limit: take,
67
- offset: skip,
68
- });
52
+ const customCampaignModuleService = framework_1.container.resolve(custom_campaigns_1.CUSTOM_CAMPAIGN_MODULE);
53
+ const promotionService = framework_1.container.resolve(utils_1.Modules.PROMOTION);
54
+ try {
55
+ console.log("Fetching flash sale campaigns...");
56
+ // Get all flash sale campaign types
57
+ const customCampaignTypes = await customCampaignModuleService.listCustomCampaignTypes({
58
+ type: campaign_type_enum_1.CampaignTypeEnum.FlashSale,
59
+ });
60
+ console.log(`Found ${customCampaignTypes.length} flash sale campaign types`);
61
+ if (customCampaignTypes.length === 0) {
62
+ return res.status(200).json({
63
+ campaigns: [],
64
+ count: 0,
65
+ limit: 20,
66
+ offset: 0,
67
+ });
68
+ }
69
+ // Get campaign IDs
70
+ const campaignIds = customCampaignTypes.map((ct) => ct.campaign_id);
71
+ // Fetch campaigns from promotion service
72
+ const campaigns = await promotionService.listCampaigns({
73
+ id: campaignIds,
74
+ }, {
75
+ relations: ["promotions"],
76
+ });
77
+ console.log(`Found ${campaigns.length} campaigns from promotion service`);
78
+ res.status(200).json({
79
+ campaigns,
80
+ count: campaigns.length,
81
+ limit: 20,
82
+ offset: 0,
83
+ });
84
+ }
85
+ catch (error) {
86
+ console.error("Error fetching flash sales:", error);
87
+ res.status(500).json({
88
+ campaigns: [],
89
+ count: 0,
90
+ limit: 20,
91
+ offset: 0,
92
+ error: "Failed to fetch flash sales",
93
+ details: error instanceof Error ? error.message : String(error),
94
+ });
95
+ }
69
96
  };
70
97
  exports.GET = GET;
71
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2ZsYXNoLXNhbGVzL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLG1EQUErRTtBQUMvRSxxREFHbUM7QUFDbkMsc0VBQXlFO0FBQ3pFLDhDQUFvQjtBQUNwQixtR0FBOEY7QUFDOUYsa0hBQStHO0FBRWxHLFFBQUEsMEJBQTBCLEdBQUcsYUFBQyxDQUFDLE1BQU0sQ0FBQztJQUNqRCxJQUFJLEVBQUUsYUFBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsa0JBQWtCLENBQUM7SUFDM0MsV0FBVyxFQUFFLGFBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLHlCQUF5QixDQUFDO0lBQ3pELElBQUksRUFBRSxhQUFDLENBQUMsVUFBVSxDQUFDLHFDQUFnQixDQUFDO0lBQ3BDLFNBQVMsRUFBRSxhQUFDLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRTtJQUMxQixPQUFPLEVBQUUsYUFBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUU7SUFDeEIsUUFBUSxFQUFFLGFBQUM7U0FDUixLQUFLLENBQ0osYUFBQyxDQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sRUFBRSxhQUFDLENBQUMsTUFBTSxDQUFDO1lBQ2hCLEVBQUUsRUFBRSxhQUFDLENBQUMsTUFBTSxFQUFFO1lBQ2QsS0FBSyxFQUFFLGFBQUMsQ0FBQyxNQUFNLEVBQUU7U0FDbEIsQ0FBQztRQUNGLFlBQVksRUFBRSxhQUFDLENBQUMsSUFBSSxDQUFDO1lBQ25CLFlBQVk7WUFDWiw2Q0FBNkM7WUFDN0MsV0FBVztTQUNaLENBQUM7UUFDRixhQUFhLEVBQUUsYUFBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDaEMsS0FBSyxFQUFFLGFBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3hCLE1BQU0sRUFBRSxhQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztLQUMxQixDQUFDLENBQ0g7U0FDQSxHQUFHLENBQUMsQ0FBQyxFQUFFLGtDQUFrQyxDQUFDO0NBQzlDLENBQUMsQ0FBQztBQUlVLFFBQUEsbUJBQW1CLEdBQUcsSUFBQSw2QkFBZ0IsRUFBQztJQUNsRCxLQUFLLEVBQUUsYUFBYTtDQUNyQixDQUFDLENBQUM7QUFFSSxNQUFNLElBQUksR0FBRyxLQUFLLEVBQ3ZCLEdBQWtDLEVBQ2xDLEdBQW1CLEVBQ25CLEVBQUU7SUFDRixNQUFNLElBQUksR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDO0lBRXRCLElBQUksSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1FBQ3RELE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLG1DQUFtQyxDQUNwQyxDQUFDO0lBQ0osQ0FBQztJQUVELE1BQU0sY0FBYyxHQUFHLE1BQU0sMkRBQTRCLENBQUMsR0FBRyxDQUFDO1FBQzVELEtBQUssRUFBRSxJQUFJO0tBQ1osQ0FBQyxDQUFDO0lBRUgsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7QUFDdkMsQ0FBQyxDQUFDO0FBbEJXLFFBQUEsSUFBSSxRQWtCZjtBQUVLLE1BQU0sR0FBRyxHQUFHLEtBQUssRUFBRSxHQUFrQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNuRSxNQUFNLEtBQUssR0FBRyxxQkFBUyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNqRSxNQUFNLEVBQ0osSUFBSSxFQUFFLGVBQWUsRUFDckIsUUFBUSxFQUFFLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsR0FBRztRQUNoQyxLQUFLLEVBQUUsQ0FBQztRQUNSLElBQUksRUFBRSxFQUFFO1FBQ1IsSUFBSSxFQUFFLENBQUM7S0FDUixHQUNGLEdBQUcsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDO1FBQ3BCLE1BQU0sRUFBRSxzQkFBc0I7UUFDOUIsR0FBRyxHQUFHLENBQUMsV0FBVztRQUNsQixNQUFNLEVBQUUsQ0FBQyxJQUFJLEVBQUUsWUFBWSxFQUFFLHVCQUF1QixDQUFDO1FBQ3JELE9BQU8sRUFBRSxFQUFFLElBQUksRUFBRSxxQ0FBZ0IsQ0FBQyxTQUFTLEVBQUU7S0FDOUMsQ0FBQyxDQUFDO0lBRUgsTUFBTSxTQUFTLEdBQUcsZUFBZSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBRXZFLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQ25CLFNBQVM7UUFDVCxLQUFLO1FBQ0wsS0FBSyxFQUFFLElBQUk7UUFDWCxNQUFNLEVBQUUsSUFBSTtLQUNiLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQztBQXhCVyxRQUFBLEdBQUcsT0F3QmQifQ==
98
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2ZsYXNoLXNhbGVzL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLG1EQUErRTtBQUMvRSxxREFJbUM7QUFDbkMsc0VBQXlFO0FBQ3pFLDhDQUFvQjtBQUNwQixtR0FBOEY7QUFDOUYsa0hBQStHO0FBQy9HLHdFQUEyRTtBQUc5RCxRQUFBLDBCQUEwQixHQUFHLGFBQUMsQ0FBQyxNQUFNLENBQUM7SUFDakQsSUFBSSxFQUFFLGFBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLGtCQUFrQixDQUFDO0lBQzNDLFdBQVcsRUFBRSxhQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSx5QkFBeUIsQ0FBQztJQUN6RCxJQUFJLEVBQUUsYUFBQyxDQUFDLFVBQVUsQ0FBQyxxQ0FBZ0IsQ0FBQztJQUNwQyxTQUFTLEVBQUUsYUFBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUU7SUFDMUIsT0FBTyxFQUFFLGFBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFO0lBQ3hCLFFBQVEsRUFBRSxhQUFDO1NBQ1IsS0FBSyxDQUNKLGFBQUMsQ0FBQyxNQUFNLENBQUM7UUFDUCxPQUFPLEVBQUUsYUFBQyxDQUFDLE1BQU0sQ0FBQztZQUNoQixFQUFFLEVBQUUsYUFBQyxDQUFDLE1BQU0sRUFBRTtZQUNkLEtBQUssRUFBRSxhQUFDLENBQUMsTUFBTSxFQUFFO1NBQ2xCLENBQUM7UUFDRixZQUFZLEVBQUUsYUFBQyxDQUFDLElBQUksQ0FBQztZQUNuQixZQUFZO1lBQ1osNkNBQTZDO1lBQzdDLFdBQVc7U0FDWixDQUFDO1FBQ0YsYUFBYSxFQUFFLGFBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ2hDLEtBQUssRUFBRSxhQUFDLENBQUMs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
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ const framework_1 = require("@medusajs/framework");
5
+ const utils_1 = require("@medusajs/framework/utils");
6
+ const core_flows_1 = require("@medusajs/medusa/core-flows");
7
+ const campaign_type_enum_1 = require("../../../modules/custom-campaigns/types/campaign-type.enum");
8
+ /**
9
+ * POST handler to force fix all campaigns in one go
10
+ * This will sync types and fix dates
11
+ */
12
+ const POST = async (req, res) => {
13
+ const promotionService = framework_1.container.resolve(utils_1.Modules.PROMOTION);
14
+ const results = {
15
+ timestamp: new Date().toISOString(),
16
+ steps: []
17
+ };
18
+ try {
19
+ // Step 1: Get all campaigns
20
+ const allCampaigns = await promotionService.listCampaigns({});
21
+ results.steps.push({
22
+ step: "Get campaigns",
23
+ status: "✅",
24
+ count: allCampaigns.length
25
+ });
26
+ if (allCampaigns.length === 0) {
27
+ return res.status(200).json({
28
+ ...results,
29
+ message: "No campaigns found to fix"
30
+ });
31
+ }
32
+ // Step 2: Try to get custom campaign module
33
+ let customModule;
34
+ try {
35
+ customModule = framework_1.container.resolve("customCampaign");
36
+ results.steps.push({
37
+ step: "Resolve custom module",
38
+ status: "✅"
39
+ });
40
+ }
41
+ catch {
42
+ results.steps.push({
43
+ step: "Resolve custom module",
44
+ status: "❌",
45
+ message: "Module not available - creating types manually"
46
+ });
47
+ }
48
+ // Step 3: Fix dates for all campaigns
49
+ const dateFixResults = [];
50
+ for (const campaign of allCampaigns) {
51
+ try {
52
+ await core_flows_1.updateCampaignsWorkflow.run({
53
+ input: {
54
+ campaignsData: [{
55
+ id: campaign.id,
56
+ starts_at: new Date("2024-01-01T00:00:00Z"),
57
+ ends_at: new Date("2025-12-31T23:59:59Z")
58
+ }]
59
+ }
60
+ });
61
+ dateFixResults.push({
62
+ id: campaign.id,
63
+ name: campaign.name,
64
+ status: "✅ Dates fixed"
65
+ });
66
+ }
67
+ catch (e) {
68
+ dateFixResults.push({
69
+ id: campaign.id,
70
+ name: campaign.name,
71
+ status: "❌ Failed",
72
+ error: e instanceof Error ? e.message : String(e)
73
+ });
74
+ }
75
+ }
76
+ results.steps.push({
77
+ step: "Fix campaign dates",
78
+ status: "✅",
79
+ fixed: dateFixResults.filter(r => r.status.includes("✅")).length,
80
+ failed: dateFixResults.filter(r => r.status.includes("❌")).length,
81
+ details: dateFixResults
82
+ });
83
+ // Step 4: Create custom types if module is available
84
+ if (customModule) {
85
+ const existingTypes = await customModule.listCustomCampaignTypes({});
86
+ const existingCampaignIds = new Set(existingTypes.map((t) => t.campaign_id));
87
+ const typeCreationResults = [];
88
+ for (const campaign of allCampaigns) {
89
+ if (existingCampaignIds.has(campaign.id)) {
90
+ typeCreationResults.push({
91
+ id: campaign.id,
92
+ name: campaign.name,
93
+ status: "⏭️ Already has type"
94
+ });
95
+ continue;
96
+ }
97
+ try {
98
+ // Determine type based on name
99
+ const type = campaign.name?.toLowerCase().includes("bogo") ||
100
+ campaign.name?.toLowerCase().includes("buy") && campaign.name?.toLowerCase().includes("get")
101
+ ? campaign_type_enum_1.CampaignTypeEnum.BuyXGetY
102
+ : campaign_type_enum_1.CampaignTypeEnum.FlashSale;
103
+ await customModule.createCustomCampaignTypes({
104
+ campaign_id: campaign.id,
105
+ type: type
106
+ });
107
+ typeCreationResults.push({
108
+ id: campaign.id,
109
+ name: campaign.name,
110
+ type: type,
111
+ status: "✅ Type created"
112
+ });
113
+ }
114
+ catch (e) {
115
+ typeCreationResults.push({
116
+ id: campaign.id,
117
+ name: campaign.name,
118
+ status: "❌ Failed",
119
+ error: e instanceof Error ? e.message : String(e)
120
+ });
121
+ }
122
+ }
123
+ results.steps.push({
124
+ step: "Create custom types",
125
+ status: "✅",
126
+ created: typeCreationResults.filter(r => r.status.includes("✅")).length,
127
+ skipped: typeCreationResults.filter(r => r.status.includes("⏭️")).length,
128
+ failed: typeCreationResults.filter(r => r.status.includes("❌")).length,
129
+ details: typeCreationResults
130
+ });
131
+ }
132
+ // Step 5: Direct database update as fallback
133
+ if (!customModule) {
134
+ try {
135
+ const db = framework_1.container.resolve("__pg_connection__");
136
+ for (const campaign of allCampaigns) {
137
+ const type = campaign.name?.toLowerCase().includes("bogo") ||
138
+ campaign.name?.toLowerCase().includes("buy") && campaign.name?.toLowerCase().includes("get")
139
+ ? "buy-x-get-y"
140
+ : "flash-sale";
141
+ await db.raw(`
142
+ INSERT INTO custom_campaign_type (id, campaign_id, type, created_at, updated_at)
143
+ VALUES (?, ?, ?, NOW(), NOW())
144
+ ON CONFLICT (campaign_id) WHERE deleted_at IS NULL
145
+ DO UPDATE SET type = EXCLUDED.type, updated_at = NOW()
146
+ `, [`cct_${Date.now()}_${campaign.id}`, campaign.id, type]);
147
+ }
148
+ results.steps.push({
149
+ step: "Direct DB insert for custom types",
150
+ status: "✅"
151
+ });
152
+ }
153
+ catch (e) {
154
+ results.steps.push({
155
+ step: "Direct DB insert for custom types",
156
+ status: "❌",
157
+ error: e instanceof Error ? e.message : String(e)
158
+ });
159
+ }
160
+ }
161
+ results.success = true;
162
+ results.message = "Force fix completed";
163
+ res.status(200).json(results);
164
+ }
165
+ catch (error) {
166
+ res.status(500).json({
167
+ ...results,
168
+ success: false,
169
+ error: "Failed to force fix campaigns",
170
+ details: error instanceof Error ? error.message : String(error),
171
+ stack: error instanceof Error ? error.stack : undefined
172
+ });
173
+ }
174
+ };
175
+ exports.POST = POST;
176
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2ZvcmNlLWZpeC9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxtREFBK0U7QUFDL0UscURBQW9EO0FBQ3BELDREQUFzRTtBQUN0RSxtR0FBOEY7QUFFOUY7OztHQUdHO0FBQ0ksTUFBTSxJQUFJLEdBQUcsS0FBSyxFQUFFLEdBQWtCLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ3BFLE1BQU0sZ0JBQWdCLEdBQUcscUJBQVMsQ0FBQyxPQUFPLENBQUMsZUFBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzlELE1BQU0sT0FBTyxHQUFRO1FBQ25CLFNBQVMsRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRTtRQUNuQyxLQUFLLEVBQUUsRUFBRTtLQUNWLENBQUM7SUFFRixJQUFJLENBQUM7UUFDSCw0QkFBNEI7UUFDNUIsTUFBTSxZQUFZLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDOUQsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUM7WUFDakIsSUFBSSxFQUFFLGVBQWU7WUFDckIsTUFBTSxFQUFFLEdBQUc7WUFDWCxLQUFLLEVBQUUsWUFBWSxDQUFDLE1BQU07U0FDM0IsQ0FBQyxDQUFDO1FBRUgsSUFBSSxZQUFZLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQzlCLE9BQU8sR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBQzFCLEdBQUcsT0FBTztnQkFDVixPQUFPLEVBQUUsMkJBQTJCO2FBQ3JDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCw0Q0FBNEM7UUFDNUMsSUFBSSxZQUFpQixDQUFDO1FBQ3RCLElBQUksQ0FBQztZQUNILFlBQVksR0FBRyxxQkFBUyxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0Is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
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = exports.POST = void 0;
4
+ const framework_1 = require("@medusajs/framework");
5
+ const utils_1 = require("@medusajs/framework/utils");
6
+ const custom_campaigns_1 = require("../../../modules/custom-campaigns");
7
+ const campaign_type_enum_1 = require("../../../modules/custom-campaigns/types/campaign-type.enum");
8
+ const createBuyXGetYCampaignWorkflow_1 = require("../../../workflows/custom-campaign/createBuyXGetYCampaignWorkflow");
9
+ /**
10
+ * POST handler to create a test Buy X Get Y campaign
11
+ * This creates a campaign with test data to verify the system is working
12
+ */
13
+ const POST = async (req, res) => {
14
+ const productService = framework_1.container.resolve(utils_1.Modules.PRODUCT);
15
+ try {
16
+ // Get first two products from the system
17
+ const products = await productService.listProducts({}, { take: 2 });
18
+ if (products.length < 2) {
19
+ return res.status(400).json({
20
+ error: "Need at least 2 products in the system to create a test campaign",
21
+ productsFound: products.length
22
+ });
23
+ }
24
+ const [triggerProduct, rewardProduct] = products;
25
+ // Create a test campaign that is active for the whole year
26
+ const testCampaignData = {
27
+ name: `Test BOGO Campaign ${Date.now()}`,
28
+ description: "Test Buy 1 Get 1 Free campaign for debugging",
29
+ type: campaign_type_enum_1.CampaignTypeEnum.BuyXGetY,
30
+ starts_at: new Date("2024-01-01T00:00:00Z"),
31
+ ends_at: new Date("2025-12-31T23:59:59Z"),
32
+ rules: [
33
+ {
34
+ triggerProduct: {
35
+ id: triggerProduct.id,
36
+ title: triggerProduct.title || "Test Product A"
37
+ },
38
+ triggerQuantity: 1,
39
+ rewardProduct: {
40
+ id: rewardProduct.id,
41
+ title: rewardProduct.title || "Test Product B"
42
+ },
43
+ rewardQuantity: 1,
44
+ rewardType: "free",
45
+ rewardValue: undefined,
46
+ limit: undefined
47
+ }
48
+ ]
49
+ };
50
+ console.log("Creating test campaign with data:", JSON.stringify(testCampaignData, null, 2));
51
+ const result = await createBuyXGetYCampaignWorkflow_1.createBuyXGetYCampaignWorkflow.run({
52
+ input: testCampaignData
53
+ });
54
+ console.log("Test campaign created successfully:", result);
55
+ res.status(201).json({
56
+ success: true,
57
+ message: "Test campaign created successfully",
58
+ campaign: result.result?.campaign,
59
+ promotions: result.result?.promotions,
60
+ configs: result.result?.buyXGetYConfigs,
61
+ testData: {
62
+ triggerProduct: {
63
+ id: triggerProduct.id,
64
+ title: triggerProduct.title
65
+ },
66
+ rewardProduct: {
67
+ id: rewardProduct.id,
68
+ title: rewardProduct.title
69
+ }
70
+ }
71
+ });
72
+ }
73
+ catch (error) {
74
+ console.error("Error creating test campaign:", error);
75
+ res.status(500).json({
76
+ error: "Failed to create test campaign",
77
+ details: error instanceof Error ? error.message : String(error),
78
+ stack: error instanceof Error ? error.stack : undefined
79
+ });
80
+ }
81
+ };
82
+ exports.POST = POST;
83
+ /**
84
+ * GET handler to verify test campaign exists
85
+ */
86
+ const GET = async (req, res) => {
87
+ const customCampaignModuleService = framework_1.container.resolve(custom_campaigns_1.CUSTOM_CAMPAIGN_MODULE);
88
+ const promotionService = framework_1.container.resolve(utils_1.Modules.PROMOTION);
89
+ try {
90
+ // Get all Buy X Get Y campaigns
91
+ const customCampaignTypes = await customCampaignModuleService.listCustomCampaignTypes({
92
+ type: campaign_type_enum_1.CampaignTypeEnum.BuyXGetY
93
+ });
94
+ const campaignDetails = [];
95
+ for (const ct of customCampaignTypes) {
96
+ try {
97
+ const campaign = await promotionService.retrieveCampaign(ct.campaign_id);
98
+ const configs = await customCampaignModuleService.listBuyXGetYConfigs({
99
+ campaign_id: ct.campaign_id
100
+ });
101
+ campaignDetails.push({
102
+ customCampaignType: ct,
103
+ campaign: {
104
+ id: campaign.id,
105
+ name: campaign.name,
106
+ description: campaign.description,
107
+ starts_at: campaign.starts_at,
108
+ ends_at: campaign.ends_at,
109
+ campaign_identifier: campaign.campaign_identifier
110
+ },
111
+ bogoConfigs: configs
112
+ });
113
+ }
114
+ catch (e) {
115
+ console.error(`Error fetching campaign ${ct.campaign_id}:`, e);
116
+ }
117
+ }
118
+ res.status(200).json({
119
+ totalBuyXGetYCampaigns: customCampaignTypes.length,
120
+ campaigns: campaignDetails
121
+ });
122
+ }
123
+ catch (error) {
124
+ console.error("Error verifying test campaigns:", error);
125
+ res.status(500).json({
126
+ error: "Failed to verify test campaigns",
127
+ details: error instanceof Error ? error.message : String(error)
128
+ });
129
+ }
130
+ };
131
+ exports.GET = GET;
132
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3Rlc3QtY2FtcGFpZ24vcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbURBQStFO0FBQy9FLHFEQUFvRDtBQUNwRCx3RUFBMkU7QUFFM0UsbUdBQThGO0FBQzlGLHNIQUFtSDtBQUVuSDs7O0dBR0c7QUFDSSxNQUFNLElBQUksR0FBRyxLQUFLLEVBQUUsR0FBa0IsRUFBRSxHQUFtQixFQUFFLEVBQUU7SUFDcEUsTUFBTSxjQUFjLEdBQUcscUJBQVMsQ0FBQyxPQUFPLENBQUMsZUFBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBRTFELElBQUksQ0FBQztRQUNILHlDQUF5QztRQUN6QyxNQUFNLFFBQVEsR0FBRyxNQUFNLGNBQWMsQ0FBQyxZQUFZLENBQUMsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFcEUsSUFBSSxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3hCLE9BQU8sR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBQzFCLEtBQUssRUFBRSxrRUFBa0U7Z0JBQ3pFLGFBQWEsRUFBRSxRQUFRLENBQUMsTUFBTTthQUMvQixDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsTUFBTSxDQUFDLGNBQWMsRUFBRSxhQUFhLENBQUMsR0FBRyxRQUFRLENBQUM7UUFFakQsMkRBQTJEO1FBQzNELE1BQU0sZ0JBQWdCLEdBQUc7WUFDdkIsSUFBSSxFQUFFLHNCQUFzQixJQUFJLENBQUMsR0FBRyxFQUFFLEVBQUU7WUFDeEMsV0FBVyxFQUFFLDhDQUE4QztZQUMzRCxJQUFJLEVBQUUscUNBQWdCLENBQUMsUUFBUTtZQUMvQixTQUFTLEVBQUUsSUFBSSxJQUFJLENBQUMsc0JBQXNCLENBQUM7WUFDM0MsT0FBTyxFQUFFLElBQUks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
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = void 0;
4
+ const framework_1 = require("@medusajs/framework");
5
+ const utils_1 = require("@medusajs/framework/utils");
6
+ const campaign_type_enum_1 = require("../../../../modules/custom-campaigns/types/campaign-type.enum");
7
+ const custom_campaigns_1 = require("../../../../modules/custom-campaigns");
8
+ /**
9
+ * GET handler for fetching a specific Buy X Get Y campaign for storefront
10
+ */
11
+ const GET = async (req, res) => {
12
+ const { id } = req.params;
13
+ if (!id) {
14
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Campaign ID is required");
15
+ }
16
+ const customCampaignModuleService = framework_1.container.resolve(custom_campaigns_1.CUSTOM_CAMPAIGN_MODULE);
17
+ const productService = framework_1.container.resolve(utils_1.Modules.PRODUCT);
18
+ const promotionService = framework_1.container.resolve(utils_1.Modules.PROMOTION);
19
+ try {
20
+ const now = new Date();
21
+ // Find the custom campaign type by campaign ID
22
+ const customCampaignTypes = await customCampaignModuleService.listCustomCampaignTypes({
23
+ type: campaign_type_enum_1.CampaignTypeEnum.BuyXGetY,
24
+ campaign_id: id,
25
+ });
26
+ if (customCampaignTypes.length === 0) {
27
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_FOUND, `Buy X Get Y campaign with ID ${id} not found`);
28
+ }
29
+ // Get campaign from promotion service
30
+ const campaign = await promotionService.retrieveCampaign(id);
31
+ if (!campaign) {
32
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_FOUND, `Buy X Get Y campaign with ID ${id} not found`);
33
+ }
34
+ // Check if campaign is active
35
+ const startsAt = new Date(campaign.starts_at);
36
+ const endsAt = new Date(campaign.ends_at);
37
+ const isActive = startsAt <= now && endsAt >= now;
38
+ if (!isActive) {
39
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "This campaign is not currently active");
40
+ }
41
+ // Get BOGO configs for this campaign
42
+ const buyXGetYConfigs = await customCampaignModuleService.listBuyXGetYConfigs({
43
+ campaign_id: id,
44
+ });
45
+ // Filter out configs that have reached their limit
46
+ const availableConfigs = buyXGetYConfigs.filter((config) => !config.limit || config.used < config.limit);
47
+ if (availableConfigs.length === 0) {
48
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "This campaign has no available promotions");
49
+ }
50
+ // Build rules with product details
51
+ const rules = await Promise.all(availableConfigs.map(async (config) => {
52
+ const [triggerProduct, rewardProduct] = await Promise.all([
53
+ productService.retrieveProduct(config.trigger_product_id, {
54
+ select: ["id", "title", "description", "thumbnail", "handle"],
55
+ relations: ["images", "variants"],
56
+ }),
57
+ productService.retrieveProduct(config.reward_product_id, {
58
+ select: ["id", "title", "description", "thumbnail", "handle"],
59
+ relations: ["images", "variants"],
60
+ }),
61
+ ]);
62
+ return {
63
+ id: config.id,
64
+ triggerProduct: {
65
+ id: triggerProduct.id,
66
+ title: triggerProduct.title,
67
+ description: triggerProduct.description,
68
+ thumbnail: triggerProduct.thumbnail,
69
+ handle: triggerProduct.handle,
70
+ images: triggerProduct.images,
71
+ variants: triggerProduct.variants,
72
+ },
73
+ triggerQuantity: config.trigger_quantity,
74
+ rewardProduct: {
75
+ id: rewardProduct.id,
76
+ title: rewardProduct.title,
77
+ description: rewardProduct.description,
78
+ thumbnail: rewardProduct.thumbnail,
79
+ handle: rewardProduct.handle,
80
+ images: rewardProduct.images,
81
+ variants: rewardProduct.variants,
82
+ },
83
+ rewardQuantity: config.reward_quantity,
84
+ rewardType: config.reward_type,
85
+ rewardValue: config.reward_value,
86
+ remaining: config.limit ? config.limit - config.used : null,
87
+ };
88
+ }));
89
+ res.status(200).json({
90
+ campaign: {
91
+ id: campaign.id,
92
+ name: campaign.name,
93
+ description: campaign.description,
94
+ starts_at: campaign.starts_at,
95
+ ends_at: campaign.ends_at,
96
+ rules,
97
+ },
98
+ });
99
+ }
100
+ catch (error) {
101
+ if (error instanceof utils_1.MedusaError) {
102
+ throw error;
103
+ }
104
+ console.error("Error fetching Buy X Get Y campaign:", error);
105
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "An error occurred while fetching the campaign");
106
+ }
107
+ };
108
+ exports.GET = GET;
109
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL2J1eS14LWdldC15L1tpZF0vcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbURBQStFO0FBQy9FLHFEQUFpRTtBQUNqRSxzR0FBaUc7QUFDakcsMkVBQThFO0FBRzlFOztHQUVHO0FBQ0ksTUFBTSxHQUFHLEdBQUcsS0FBSyxFQUFFLEdBQWtCLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ25FLE1BQU0sRUFBRSxFQUFFLEVBQUUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDO0lBRTFCLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUNSLE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLHlCQUF5QixDQUMxQixDQUFDO0lBQ0osQ0FBQztJQUVELE1BQU0sMkJBQTJCLEdBQy9CLHFCQUFTLENBQUMsT0FBTyxDQUE4Qix5Q0FBc0IsQ0FBQyxDQUFDO0lBQ3pFLE1BQU0sY0FBYyxHQUFHLHFCQUFTLENBQUMsT0FBTyxDQUFDLGVBQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMxRCxNQUFNLGdCQUFnQixHQUFHLHFCQUFTLENBQUMsT0FBTyxDQUFDLGVBQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUU5RCxJQUFJLENBQUM7UUFDSCxNQUFNLEdBQUcsR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO1FBRXZCLCtDQUErQztRQUMvQyxNQUFNLG1CQUFtQixHQUN2QixNQUFNLDJCQUEyQixDQUFDLHVCQUF1QixDQUFDO1lBQ3hELElBQUksRUFBRSxxQ0FBZ0IsQ0FBQyxRQUFRO1lBQy9CLFdBQVcsRUFBRSxFQUFFO1NBQ2hCLENBQUMsQ0FBQztRQUVMLElBQUksbUJBQW1CLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3JDLE1BQU0sSUFBSSxtQkFBVyxDQUNu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
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = void 0;
4
+ const framework_1 = require("@medusajs/framework");
5
+ const utils_1 = require("@medusajs/framework/utils");
6
+ const custom_campaigns_1 = require("../../../../../modules/custom-campaigns");
7
+ /**
8
+ * GET handler to check if a product has any active BOGO promotions
9
+ * Useful for displaying BOGO badges on product cards and detail pages
10
+ */
11
+ const GET = async (req, res) => {
12
+ const { productId } = req.params;
13
+ if (!productId) {
14
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Product ID is required");
15
+ }
16
+ const customCampaignModuleService = framework_1.container.resolve(custom_campaigns_1.CUSTOM_CAMPAIGN_MODULE);
17
+ const productService = framework_1.container.resolve(utils_1.Modules.PRODUCT);
18
+ const promotionService = framework_1.container.resolve(utils_1.Modules.PROMOTION);
19
+ try {
20
+ const now = new Date();
21
+ // Verify product exists
22
+ await productService.retrieveProduct(productId, {
23
+ select: ["id"],
24
+ });
25
+ // Get all BOGO configs where this product is the trigger
26
+ const buyXGetYConfigs = await customCampaignModuleService.listBuyXGetYConfigs({
27
+ trigger_product_id: productId,
28
+ });
29
+ if (buyXGetYConfigs.length === 0) {
30
+ return res.status(200).json({
31
+ has_promotions: false,
32
+ promotions: [],
33
+ });
34
+ }
35
+ // Get campaign details for each config
36
+ const campaignIds = Array.from(new Set(buyXGetYConfigs.map((config) => config.campaign_id)));
37
+ const campaigns = await promotionService.listCampaigns({
38
+ id: campaignIds,
39
+ });
40
+ // Filter for active campaigns
41
+ const activeCampaignIds = new Set(campaigns
42
+ .filter((campaign) => {
43
+ const startsAt = new Date(campaign.starts_at);
44
+ const endsAt = new Date(campaign.ends_at);
45
+ return startsAt <= now && endsAt >= now;
46
+ })
47
+ .map((campaign) => campaign.id));
48
+ // Filter configs by active campaigns and availability
49
+ const activeConfigs = buyXGetYConfigs.filter((config) => activeCampaignIds.has(config.campaign_id) &&
50
+ (!config.limit || config.used < config.limit));
51
+ if (activeConfigs.length === 0) {
52
+ return res.status(200).json({
53
+ has_promotions: false,
54
+ promotions: [],
55
+ });
56
+ }
57
+ // Build promotion details
58
+ const promotions = await Promise.all(activeConfigs.map(async (config) => {
59
+ const campaign = campaigns.find((c) => c.id === config.campaign_id);
60
+ const rewardProduct = await productService.retrieveProduct(config.reward_product_id, {
61
+ select: ["id", "title", "thumbnail", "handle"],
62
+ });
63
+ return {
64
+ campaign_id: campaign.id,
65
+ campaign_name: campaign.name,
66
+ trigger_quantity: config.trigger_quantity,
67
+ reward_product: {
68
+ id: rewardProduct.id,
69
+ title: rewardProduct.title,
70
+ thumbnail: rewardProduct.thumbnail,
71
+ handle: rewardProduct.handle,
72
+ },
73
+ reward_quantity: config.reward_quantity,
74
+ reward_type: config.reward_type,
75
+ reward_value: config.reward_value,
76
+ remaining: config.limit ? config.limit - config.used : null,
77
+ ends_at: campaign.ends_at,
78
+ };
79
+ }));
80
+ res.status(200).json({
81
+ has_promotions: true,
82
+ promotions,
83
+ });
84
+ }
85
+ catch (error) {
86
+ if (error instanceof utils_1.MedusaError) {
87
+ throw error;
88
+ }
89
+ console.error("Error checking product BOGO promotions:", error);
90
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "An error occurred while checking promotions");
91
+ }
92
+ };
93
+ exports.GET = GET;
94
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL2J1eS14LWdldC15L3Byb2R1Y3RzL1twcm9kdWN0SWRdL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLG1EQUErRTtBQUMvRSxxREFBaUU7QUFDakUsOEVBQWlGO0FBSWpGOzs7R0FHRztBQUNJLE1BQU0sR0FBRyxHQUFHLEtBQUssRUFBRSxHQUFrQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNuRSxNQUFNLEVBQUUsU0FBUyxFQUFFLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQztJQUVqQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDZixNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUM5Qix3QkFBd0IsQ0FDekIsQ0FBQztJQUNKLENBQUM7SUFFRCxNQUFNLDJCQUEyQixHQUMvQixxQkFBUyxDQUFDLE9BQU8sQ0FBOEIseUNBQXNCLENBQUMsQ0FBQztJQUN6RSxNQUFNLGNBQWMsR0FBRyxxQkFBUyxDQUFDLE9BQU8sQ0FBQyxlQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDMUQsTUFBTSxnQkFBZ0IsR0FBRyxxQkFBUyxDQUFDLE9BQU8sQ0FBQyxlQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7SUFFOUQsSUFBSSxDQUFDO1FBQ0gsTUFBTSxHQUFHLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUV2Qix3QkFBd0I7UUFDeEIsTUFBTSxjQUFjLENBQUMsZUFBZSxDQUFDLFNBQVMsRUFBRTtZQUM5QyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUM7U0FDZixDQUFDLENBQUM7UUFFSCx5REFBeUQ7UUFDekQsTUFBTSxlQUFlLEdBQ25CLE1BQU0sMkJBQTJCLENBQUMsbUJBQW1CLENBQUM7WUFDcEQsa0JBQWtCLEVBQUUsU0FBUztTQUM5QixDQUFDLENBQUM7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