@lodashventure/medusa-campaign 1.3.12 → 1.4.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 (54) hide show
  1. package/.medusa/server/src/admin/index.js +1238 -16
  2. package/.medusa/server/src/admin/index.mjs +1240 -18
  3. package/.medusa/server/src/api/admin/campaigns/[id]/detail/route.js +67 -0
  4. package/.medusa/server/src/api/admin/campaigns/[id]/image/route.js +80 -0
  5. package/.medusa/server/src/api/admin/campaigns/[id]/thumbnail/route.js +80 -0
  6. package/.medusa/server/src/api/admin/campaigns/sync/route.js +8 -6
  7. package/.medusa/server/src/api/admin/flash-sales/[id]/route.js +22 -4
  8. package/.medusa/server/src/api/middlewares.js +24 -1
  9. package/.medusa/server/src/api/store/buy-x-get-y/[id]/route.js +1 -1
  10. package/.medusa/server/src/api/store/buy-x-get-y/products/[productId]/route.js +1 -1
  11. package/.medusa/server/src/api/store/buy-x-get-y/route.js +3 -1
  12. package/.medusa/server/src/api/store/campaigns/[id]/route.js +40 -12
  13. package/.medusa/server/src/modules/custom-campaigns/migrations/Migration20251024000000.js +53 -0
  14. package/.medusa/server/src/modules/custom-campaigns/migrations/Migration20251025000000.js +22 -0
  15. package/.medusa/server/src/modules/custom-campaigns/models/campaign-detail.js +26 -0
  16. package/.medusa/server/src/modules/custom-campaigns/service.js +3 -1
  17. package/.medusa/server/src/subscribers/order-placed.js +2 -2
  18. package/.medusa/server/src/workflows/buy-x-get-y/applyBuyXGetYToCartWorkflow.js +16 -4
  19. package/.medusa/server/src/workflows/campaign-detail/update-campaign-detail.js +55 -0
  20. package/.medusa/server/src/workflows/campaign-detail/upload-campaign-images.js +120 -0
  21. package/.medusa/server/src/workflows/custom-campaign/createBuyXGetYCampaignWorkflow.js +13 -14
  22. package/package.json +7 -5
  23. package/src/admin/components/campaign-detail-form.tsx +407 -0
  24. package/src/admin/components/campaign-image-uploader.tsx +313 -0
  25. package/src/admin/components/markdown-editor.tsx +298 -0
  26. package/src/admin/routes/flash-sales/[id]/page.tsx +51 -14
  27. package/src/admin/widgets/campaign-detail-widget.tsx +299 -0
  28. package/src/admin/widgets/campaign-stats-widget.tsx +238 -0
  29. package/src/api/admin/campaigns/[id]/detail/route.ts +77 -0
  30. package/src/api/admin/campaigns/[id]/image/route.ts +87 -0
  31. package/src/api/admin/campaigns/[id]/thumbnail/route.ts +87 -0
  32. package/src/api/admin/campaigns/sync/route.ts +53 -28
  33. package/src/api/admin/flash-sales/[id]/route.ts +50 -19
  34. package/src/api/middlewares.ts +21 -0
  35. package/src/api/store/buy-x-get-y/[id]/route.ts +10 -10
  36. package/src/api/store/buy-x-get-y/products/[productId]/route.ts +11 -12
  37. package/src/api/store/buy-x-get-y/route.ts +12 -5
  38. package/src/api/store/campaigns/[id]/route.ts +54 -24
  39. package/src/modules/custom-campaigns/migrations/Migration20251024000000.ts +53 -0
  40. package/src/modules/custom-campaigns/migrations/Migration20251025000000.ts +19 -0
  41. package/src/modules/custom-campaigns/models/campaign-detail.ts +25 -0
  42. package/src/modules/custom-campaigns/service.ts +2 -0
  43. package/src/subscribers/order-placed.ts +0 -2
  44. package/src/types/index.d.ts +46 -0
  45. package/src/workflows/buy-x-get-y/applyBuyXGetYToCartWorkflow.ts +41 -18
  46. package/src/workflows/campaign-detail/update-campaign-detail.ts +85 -0
  47. package/src/workflows/campaign-detail/upload-campaign-images.ts +163 -0
  48. package/src/workflows/custom-campaign/createBuyXGetYCampaignWorkflow.ts +23 -22
  49. package/.medusa/server/src/api/admin/campaigns/fix-dates/route.js +0 -103
  50. package/.medusa/server/src/api/admin/force-fix/route.js +0 -176
  51. package/.medusa/server/src/api/admin/test-campaign/route.js +0 -132
  52. package/src/api/admin/campaigns/fix-dates/route.ts +0 -107
  53. package/src/api/admin/force-fix/route.ts +0 -184
  54. package/src/api/admin/test-campaign/route.ts +0 -141
@@ -0,0 +1,163 @@
1
+ import {
2
+ createStep,
3
+ createWorkflow,
4
+ StepResponse,
5
+ WorkflowResponse,
6
+ } from "@medusajs/framework/workflows-sdk";
7
+ import { CUSTOM_CAMPAIGN_MODULE } from "../../modules/custom-campaigns";
8
+ import CustomCampaignModuleService from "../../modules/custom-campaigns/service";
9
+ import {
10
+ deleteFilesWorkflow,
11
+ uploadFilesWorkflow,
12
+ UploadFilesWorkflowInput,
13
+ } from "@medusajs/medusa/core-flows";
14
+
15
+ type UploadCampaignImagesWorkflowInput = {
16
+ campaign_id: string;
17
+ files: UploadFilesWorkflowInput["files"];
18
+ image_type: "image" | "thumbnail";
19
+ };
20
+
21
+ const uploadCampaignImagesStep = createStep(
22
+ "upload-campaign-images",
23
+ async (
24
+ { campaign_id, files, image_type }: UploadCampaignImagesWorkflowInput,
25
+ { container },
26
+ ) => {
27
+ const logger = container.resolve("logger");
28
+ const customCampaignModuleService: CustomCampaignModuleService =
29
+ container.resolve(CUSTOM_CAMPAIGN_MODULE);
30
+
31
+ if (files.length === 0) {
32
+ throw new Error("at least 1 file is required");
33
+ }
34
+
35
+ logger.info(`Uploading ${files.length} campaign ${image_type}(s)`);
36
+
37
+ const { result } = await uploadFilesWorkflow(container).run({
38
+ input: {
39
+ files: files.map((file) => ({
40
+ ...file,
41
+ filename: `campaign-${campaign_id}-${image_type}-${file.filename.replace(/ /g, "_")}`,
42
+ })),
43
+ },
44
+ });
45
+
46
+ if (result.some((file) => !file.id || !file.url)) {
47
+ throw new Error(`some files don't have an id or url`);
48
+ }
49
+
50
+ // Decode the URL to fix path separators (%2F -> /)
51
+ const decodedUrl = decodeURIComponent(result[0].url);
52
+
53
+ // Get or create campaign detail
54
+ const [existingDetail] =
55
+ await customCampaignModuleService.listCampaignDetails({
56
+ campaign_id,
57
+ });
58
+
59
+ let campaignDetail;
60
+
61
+ if (existingDetail) {
62
+ // Delete old image if exists
63
+ const oldFileId =
64
+ image_type === "image"
65
+ ? existingDetail.image_file_id
66
+ : existingDetail.thumbnail_file_id;
67
+
68
+ if (oldFileId) {
69
+ try {
70
+ await deleteFilesWorkflow(container).run({
71
+ input: {
72
+ ids: [oldFileId],
73
+ },
74
+ });
75
+ } catch (error) {
76
+ logger.warn(`Failed to delete old ${image_type} file: ${oldFileId}`);
77
+ }
78
+ }
79
+
80
+ // Update existing detail
81
+ const updateData =
82
+ image_type === "image"
83
+ ? {
84
+ id: existingDetail.id,
85
+ image_url: decodedUrl,
86
+ image_file_id: result[0].id,
87
+ }
88
+ : {
89
+ id: existingDetail.id,
90
+ thumbnail_url: decodedUrl,
91
+ thumbnail_file_id: result[0].id,
92
+ };
93
+
94
+ const updated = await customCampaignModuleService.updateCampaignDetails([
95
+ updateData,
96
+ ]);
97
+ campaignDetail = updated[0];
98
+ } else {
99
+ // Create new detail
100
+ const createData =
101
+ image_type === "image"
102
+ ? {
103
+ campaign_id,
104
+ image_url: decodedUrl,
105
+ image_file_id: result[0].id,
106
+ }
107
+ : {
108
+ campaign_id,
109
+ thumbnail_url: decodedUrl,
110
+ thumbnail_file_id: result[0].id,
111
+ };
112
+
113
+ campaignDetail =
114
+ await customCampaignModuleService.createCampaignDetails(createData);
115
+ }
116
+
117
+ return new StepResponse(campaignDetail, {
118
+ fileId: result[0].id,
119
+ oldDetail: existingDetail,
120
+ });
121
+ },
122
+ async (rollbackData, { container }) => {
123
+ const logger = container.resolve("logger");
124
+ const customCampaignModuleService: CustomCampaignModuleService =
125
+ container.resolve(CUSTOM_CAMPAIGN_MODULE);
126
+
127
+ if (rollbackData) {
128
+ // Delete the newly uploaded file
129
+ try {
130
+ await deleteFilesWorkflow(container).run({
131
+ input: {
132
+ ids: [rollbackData.fileId],
133
+ },
134
+ });
135
+ } catch (error) {
136
+ logger.warn(
137
+ `Failed to delete file during rollback: ${rollbackData.fileId}`,
138
+ );
139
+ }
140
+
141
+ // Restore old detail if existed
142
+ if (rollbackData.oldDetail) {
143
+ try {
144
+ await customCampaignModuleService.updateCampaignDetails([
145
+ {
146
+ ...rollbackData.oldDetail,
147
+ },
148
+ ]);
149
+ } catch (error) {
150
+ logger.warn("Failed to restore old campaign detail during rollback");
151
+ }
152
+ }
153
+ }
154
+ },
155
+ );
156
+
157
+ export const uploadCampaignImagesWorkflow = createWorkflow(
158
+ "upload-campaign-images",
159
+ (input: UploadCampaignImagesWorkflowInput) => {
160
+ const detail = uploadCampaignImagesStep(input);
161
+ return new WorkflowResponse(detail);
162
+ },
163
+ );
@@ -106,8 +106,10 @@ const createBuyXGetYCampaignStep = createStep(
106
106
  application_method: {
107
107
  target_type: "items",
108
108
  allocation: "each",
109
- type: rule.rewardType === "percentage" ? "percentage" : "fixed",
110
- value: rule.rewardType === "free" ? 0 : (rule.rewardValue ?? 0),
109
+ type:
110
+ rule.rewardType === "percentage" ? "percentage" : "fixed",
111
+ value:
112
+ rule.rewardType === "free" ? 0 : (rule.rewardValue ?? 0),
111
113
  buy_rules_min_quantity: rule.triggerQuantity,
112
114
  apply_to_quantity: rule.rewardQuantity,
113
115
  target_rules: [
@@ -118,7 +120,7 @@ const createBuyXGetYCampaignStep = createStep(
118
120
  },
119
121
  ],
120
122
  } satisfies CreateApplicationMethodDTO,
121
- } satisfies CreatePromotionDTO)
123
+ }) satisfies CreatePromotionDTO,
122
124
  ),
123
125
  },
124
126
  });
@@ -132,21 +134,20 @@ const createBuyXGetYCampaignStep = createStep(
132
134
  });
133
135
 
134
136
  // Create Buy X Get Y configurations
135
- buyXGetYConfigs =
136
- await customCampaignModuleService.createBuyXGetYConfigs(
137
- data.rules.map((rule, index) => ({
138
- campaign_id: campaign.id,
139
- promotion_id: promotions[index].id,
140
- trigger_product_id: rule.triggerProduct.id,
141
- trigger_quantity: rule.triggerQuantity,
142
- reward_product_id: rule.rewardProduct.id,
143
- reward_quantity: rule.rewardQuantity,
144
- reward_type: rule.rewardType,
145
- reward_value: rule.rewardValue ?? null,
146
- limit: rule.limit ?? null,
147
- used: 0,
148
- }))
149
- );
137
+ buyXGetYConfigs = await customCampaignModuleService.createBuyXGetYConfigs(
138
+ data.rules.map((rule, index) => ({
139
+ campaign_id: campaign.id,
140
+ promotion_id: promotions![index].id,
141
+ trigger_product_id: rule.triggerProduct.id,
142
+ trigger_quantity: rule.triggerQuantity,
143
+ reward_product_id: rule.rewardProduct.id,
144
+ reward_quantity: rule.rewardQuantity,
145
+ reward_type: rule.rewardType,
146
+ reward_value: rule.rewardValue ?? null,
147
+ limit: rule.limit ?? null,
148
+ used: 0,
149
+ })),
150
+ );
150
151
 
151
152
  // Link campaign type
152
153
  await link.create([
@@ -185,19 +186,19 @@ const createBuyXGetYCampaignStep = createStep(
185
186
 
186
187
  if (customCampaignType) {
187
188
  await customCampaignModuleService.deleteCustomCampaignTypes(
188
- customCampaignType.id
189
+ customCampaignType.id,
189
190
  );
190
191
  }
191
192
 
192
193
  if (buyXGetYConfigs) {
193
194
  await customCampaignModuleService.deleteBuyXGetYConfigs(
194
- buyXGetYConfigs.map((config) => config.id)
195
+ buyXGetYConfigs.map((config) => config.id),
195
196
  );
196
197
  }
197
198
 
198
199
  throw error;
199
200
  }
200
- }
201
+ },
201
202
  );
202
203
 
203
204
  export const createBuyXGetYCampaignWorkflow = createWorkflow(
@@ -206,5 +207,5 @@ export const createBuyXGetYCampaignWorkflow = createWorkflow(
206
207
  const campaign = createBuyXGetYCampaignStep(data);
207
208
 
208
209
  return new WorkflowResponse(campaign);
209
- }
210
+ },
210
211
  );
@@ -1,103 +0,0 @@
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 core_flows_1 = require("@medusajs/medusa/core-flows");
7
- /**
8
- * POST handler to fix campaign dates - makes all campaigns active for testing
9
- */
10
- const POST = async (req, res) => {
11
- const promotionService = framework_1.container.resolve(utils_1.Modules.PROMOTION);
12
- try {
13
- // Get all campaigns
14
- const allCampaigns = await promotionService.listCampaigns({});
15
- console.log(`Found ${allCampaigns.length} campaigns to fix`);
16
- const updatedCampaigns = [];
17
- // Update each campaign to be active for the whole year
18
- for (const campaign of allCampaigns) {
19
- try {
20
- const result = await core_flows_1.updateCampaignsWorkflow.run({
21
- input: {
22
- campaignsData: [
23
- {
24
- id: campaign.id,
25
- starts_at: new Date("2024-01-01T00:00:00Z"),
26
- ends_at: new Date("2025-12-31T23:59:59Z"),
27
- },
28
- ],
29
- },
30
- });
31
- updatedCampaigns.push({
32
- id: campaign.id,
33
- name: campaign.name,
34
- old_starts_at: campaign.starts_at,
35
- old_ends_at: campaign.ends_at,
36
- new_starts_at: "2024-01-01T00:00:00Z",
37
- new_ends_at: "2025-12-31T23:59:59Z",
38
- });
39
- console.log(`✅ Fixed dates for campaign: ${campaign.name}`);
40
- }
41
- catch (error) {
42
- console.error(`❌ Failed to update campaign ${campaign.id}:`, error);
43
- }
44
- }
45
- res.status(200).json({
46
- success: true,
47
- message: `Updated ${updatedCampaigns.length} campaigns`,
48
- campaigns: updatedCampaigns,
49
- });
50
- }
51
- catch (error) {
52
- console.error("Error fixing campaign dates:", error);
53
- res.status(500).json({
54
- error: "Failed to fix campaign dates",
55
- details: error instanceof Error ? error.message : String(error),
56
- });
57
- }
58
- };
59
- exports.POST = POST;
60
- /**
61
- * GET handler to show current campaign dates
62
- */
63
- const GET = async (req, res) => {
64
- const promotionService = framework_1.container.resolve(utils_1.Modules.PROMOTION);
65
- const now = new Date();
66
- try {
67
- const allCampaigns = await promotionService.listCampaigns({});
68
- const campaignDates = allCampaigns.map((campaign) => {
69
- const startsAt = new Date(campaign.starts_at);
70
- const endsAt = new Date(campaign.ends_at);
71
- const isActive = startsAt <= now && endsAt >= now;
72
- return {
73
- id: campaign.id,
74
- name: campaign.name,
75
- starts_at: campaign.starts_at,
76
- ends_at: campaign.ends_at,
77
- isActive,
78
- reason: !isActive
79
- ? (startsAt > now ? "Not started yet" : "Already ended")
80
- : "Active",
81
- };
82
- });
83
- res.status(200).json({
84
- currentTime: now.toISOString(),
85
- campaigns: campaignDates,
86
- summary: {
87
- total: campaignDates.length,
88
- active: campaignDates.filter((c) => c.isActive).length,
89
- notStarted: campaignDates.filter((c) => c.reason === "Not started yet").length,
90
- ended: campaignDates.filter((c) => c.reason === "Already ended").length,
91
- },
92
- });
93
- }
94
- catch (error) {
95
- console.error("Error checking campaign dates:", error);
96
- res.status(500).json({
97
- error: "Failed to check campaign dates",
98
- details: error instanceof Error ? error.message : String(error),
99
- });
100
- }
101
- };
102
- exports.GET = GET;
103
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2NhbXBhaWducy9maXgtZGF0ZXMvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbURBQStFO0FBQy9FLHFEQUFvRDtBQUNwRCw0REFBc0U7QUFFdEU7O0dBRUc7QUFDSSxNQUFNLElBQUksR0FBRyxLQUFLLEVBQUUsR0FBa0IsRUFBRSxHQUFtQixFQUFFLEVBQUU7SUFDcEUsTUFBTSxnQkFBZ0IsR0FBRyxxQkFBUyxDQUFDLE9BQU8sQ0FBQyxlQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7SUFFOUQsSUFBSSxDQUFDO1FBQ0gsb0JBQW9CO1FBQ3BCLE1BQU0sWUFBWSxHQUFHLE1BQU0sZ0JBQWdCLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRTlELE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxZQUFZLENBQUMsTUFBTSxtQkFBbUIsQ0FBQyxDQUFDO1FBRTdELE1BQU0sZ0JBQWdCLEdBQUcsRUFBRSxDQUFDO1FBRTVCLHVEQUF1RDtRQUN2RCxLQUFLLE1BQU0sUUFBUSxJQUFJLFlBQVksRUFBRSxDQUFDO1lBQ3BDLElBQUksQ0FBQztnQkFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLG9DQUF1QixDQUFDLEdBQUcsQ0FBQztvQkFDL0MsS0FBSyxFQUFFO3dCQUNMLGFBQWEsRUFBRTs0QkFDYjtnQ0FDRSxFQUFFLEVBQUUsUUFBUSxDQUFDLEVBQUU7Z0NBQ2YsU0FBUyxFQUFFLElBQUksSUFBSSxDQUFDLHNCQUFzQixDQUFDO2dDQUMzQyxPQUFPLEVBQUUsSUFBSSxJQUFJLENBQUMsc0JBQXNCLENBQUM7NkJBQzFDO3lCQUNGO3FCQUNGO2lCQUNGLENBQUMsQ0FBQztnQkFFSCxnQkFBZ0IsQ0FBQyxJQUFJLENBQUM7b0JBQ3BCLEVBQUUsRUFBRSxRQUFRLENBQUMsRUFBRTtvQkFDZixJQUFJLEVBQUUs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
@@ -1,176 +0,0 @@
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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