mumz-strapi-plugin-coupon 1.1.1 → 3.0.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 (46) hide show
  1. package/README.md +15 -13
  2. package/dist/admin/index.js +677 -0
  3. package/dist/admin/index.mjs +678 -0
  4. package/dist/server/index.js +1201 -0
  5. package/dist/server/index.mjs +1202 -0
  6. package/package.json +44 -20
  7. package/strapi-admin.js +3 -0
  8. package/strapi-server.js +3 -1
  9. package/dist/bootstrap.d.ts +0 -5
  10. package/dist/bootstrap.js +0 -6
  11. package/dist/config/index.d.ts +0 -5
  12. package/dist/config/index.js +0 -6
  13. package/dist/content-types/coupon/index.d.ts +0 -96
  14. package/dist/content-types/coupon/index.js +0 -9
  15. package/dist/content-types/coupon/schema.d.ts +0 -94
  16. package/dist/content-types/coupon/schema.js +0 -117
  17. package/dist/content-types/index.d.ts +0 -161
  18. package/dist/content-types/index.js +0 -11
  19. package/dist/content-types/redemption/index.d.ts +0 -64
  20. package/dist/content-types/redemption/index.js +0 -9
  21. package/dist/content-types/redemption/schema.d.ts +0 -62
  22. package/dist/content-types/redemption/schema.js +0 -74
  23. package/dist/controllers/coupon.d.ts +0 -41
  24. package/dist/controllers/coupon.js +0 -154
  25. package/dist/controllers/index.d.ts +0 -5
  26. package/dist/controllers/index.js +0 -9
  27. package/dist/destroy.d.ts +0 -5
  28. package/dist/destroy.js +0 -6
  29. package/dist/index.d.ts +0 -207
  30. package/dist/index.js +0 -24
  31. package/dist/middlewares/index.d.ts +0 -4
  32. package/dist/middlewares/index.js +0 -9
  33. package/dist/middlewares/rate-limit.d.ts +0 -6
  34. package/dist/middlewares/rate-limit.js +0 -42
  35. package/dist/register.d.ts +0 -5
  36. package/dist/register.js +0 -6
  37. package/dist/routes/content-api/index.d.ts +0 -23
  38. package/dist/routes/content-api/index.js +0 -76
  39. package/dist/routes/index.d.ts +0 -25
  40. package/dist/routes/index.js +0 -9
  41. package/dist/services/coupon.d.ts +0 -64
  42. package/dist/services/coupon.js +0 -432
  43. package/dist/services/index.d.ts +0 -5
  44. package/dist/services/index.js +0 -9
  45. package/dist/utils/validators.d.ts +0 -14
  46. package/dist/utils/validators.js +0 -41
@@ -1,42 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- // Simple in-memory rate limiter
4
- // Uses in-memory storage - suitable for single-instance deployments
5
- const rateLimitStore = new Map();
6
- // Clean up old entries every hour
7
- setInterval(() => {
8
- const now = Date.now();
9
- for (const [key, value] of rateLimitStore.entries()) {
10
- if (now > value.resetAt) {
11
- rateLimitStore.delete(key);
12
- }
13
- }
14
- }, 3600000); // 1 hour
15
- exports.default = (config) => {
16
- return async (ctx, next) => {
17
- const identifier = ctx.ip || ctx.request.ip || 'unknown';
18
- const now = Date.now();
19
- const record = rateLimitStore.get(identifier);
20
- // No record or expired, create new
21
- if (!record || now > record.resetAt) {
22
- rateLimitStore.set(identifier, {
23
- count: 1,
24
- resetAt: now + config.windowMs,
25
- });
26
- return next();
27
- }
28
- // Check if limit reached
29
- if (record.count >= config.maxRequests) {
30
- ctx.status = 429;
31
- ctx.body = {
32
- error: 'Too many requests',
33
- message: `Rate limit exceeded. Please try again in ${Math.ceil((record.resetAt - now) / 1000)} seconds.`,
34
- retryAfter: Math.ceil((record.resetAt - now) / 1000),
35
- };
36
- return;
37
- }
38
- // Increment counter
39
- record.count++;
40
- return next();
41
- };
42
- };
@@ -1,5 +0,0 @@
1
- import type { Core } from '@strapi/strapi';
2
- declare const _default: ({ strapi }: {
3
- strapi: Core.Strapi;
4
- }) => void;
5
- export default _default;
package/dist/register.js DELETED
@@ -1,6 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = ({ strapi }) => {
4
- // Register plugin custom logic here
5
- strapi.log.info('Coupon plugin registered');
6
- };
@@ -1,23 +0,0 @@
1
- declare const _default: {
2
- type: string;
3
- routes: ({
4
- method: string;
5
- path: string;
6
- handler: string;
7
- config: {
8
- policies: never[];
9
- middlewares: ((ctx: any, next: any) => Promise<any>)[];
10
- auth: boolean;
11
- };
12
- } | {
13
- method: string;
14
- path: string;
15
- handler: string;
16
- config: {
17
- policies: never[];
18
- auth: boolean;
19
- middlewares?: undefined;
20
- };
21
- })[];
22
- };
23
- export default _default;
@@ -1,76 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const rate_limit_1 = __importDefault(require("../../middlewares/rate-limit"));
7
- exports.default = {
8
- type: 'content-api',
9
- routes: [
10
- {
11
- method: 'POST',
12
- path: '/validate',
13
- handler: 'coupon.validate',
14
- config: {
15
- policies: [],
16
- middlewares: [(0, rate_limit_1.default)({ maxRequests: 10, windowMs: 60000 })], // 10 requests per minute
17
- auth: false,
18
- },
19
- },
20
- {
21
- method: 'POST',
22
- path: '/redeem',
23
- handler: 'coupon.redeem',
24
- config: {
25
- policies: [],
26
- middlewares: [(0, rate_limit_1.default)({ maxRequests: 5, windowMs: 60000 })], // 5 requests per minute
27
- auth: false,
28
- },
29
- },
30
- {
31
- method: 'POST',
32
- path: '/',
33
- handler: 'coupon.create',
34
- config: {
35
- policies: [],
36
- auth: false,
37
- },
38
- },
39
- {
40
- method: 'GET',
41
- path: '/',
42
- handler: 'coupon.find',
43
- config: {
44
- policies: [],
45
- auth: false,
46
- },
47
- },
48
- {
49
- method: 'GET',
50
- path: '/:id',
51
- handler: 'coupon.findOne',
52
- config: {
53
- policies: [],
54
- auth: false,
55
- },
56
- },
57
- {
58
- method: 'PUT',
59
- path: '/:id',
60
- handler: 'coupon.update',
61
- config: {
62
- policies: [],
63
- auth: false,
64
- },
65
- },
66
- {
67
- method: 'DELETE',
68
- path: '/:id',
69
- handler: 'coupon.delete',
70
- config: {
71
- policies: [],
72
- auth: false,
73
- },
74
- },
75
- ],
76
- };
@@ -1,25 +0,0 @@
1
- declare const _default: {
2
- 'content-api': {
3
- type: string;
4
- routes: ({
5
- method: string;
6
- path: string;
7
- handler: string;
8
- config: {
9
- policies: never[];
10
- middlewares: ((ctx: any, next: any) => Promise<any>)[];
11
- auth: boolean;
12
- };
13
- } | {
14
- method: string;
15
- path: string;
16
- handler: string;
17
- config: {
18
- policies: never[];
19
- auth: boolean;
20
- middlewares?: undefined;
21
- };
22
- })[];
23
- };
24
- };
25
- export default _default;
@@ -1,9 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const content_api_1 = __importDefault(require("./content-api"));
7
- exports.default = {
8
- 'content-api': content_api_1.default,
9
- };
@@ -1,64 +0,0 @@
1
- import type { Core } from "@strapi/strapi";
2
- export declare const ERROR_CODES: {
3
- readonly COUPON_NOT_FOUND: "COUPON_NOT_FOUND";
4
- readonly COUPON_EXPIRED: "COUPON_EXPIRED";
5
- readonly COUPON_ALREADY_USED: "COUPON_ALREADY_USED";
6
- readonly USAGE_LIMIT_REACHED: "USAGE_LIMIT_REACHED";
7
- readonly INVALID_REQUEST: "INVALID_REQUEST";
8
- readonly USER_RESTRICTED: "USER_RESTRICTED";
9
- };
10
- export declare const ERROR_MESSAGES: {
11
- readonly COUPON_NOT_FOUND: "Coupon code does not exist.";
12
- readonly COUPON_EXPIRED: "This coupon has expired.";
13
- readonly COUPON_ALREADY_USED: "This coupon has been already used.";
14
- readonly USAGE_LIMIT_REACHED: "Coupon usage limit has been reached.";
15
- readonly INVALID_REQUEST: "Invalid request parameters.";
16
- readonly USER_RESTRICTED: "This coupon is not available for your phone number.";
17
- };
18
- export interface ValidateCouponRequest {
19
- couponCode: string;
20
- phoneNumber: string;
21
- orderAmount?: number;
22
- }
23
- export interface RedeemCouponRequest {
24
- couponCode: string;
25
- phoneNumber: string;
26
- orderId: string;
27
- orderAmount?: number;
28
- }
29
- export interface CreateCouponRequest {
30
- code: string;
31
- discountType: "percentage" | "flat";
32
- discountValue: number;
33
- maxUsage?: number;
34
- maxUsagePerUser?: number;
35
- validFrom: string;
36
- validTo: string;
37
- description?: string;
38
- userRestrictions?: string[];
39
- }
40
- export interface ValidationResponse {
41
- isValid: boolean;
42
- errorCode?: string;
43
- message: string;
44
- discountType?: string;
45
- discountValue?: number;
46
- discountAmount?: number;
47
- finalAmount?: number;
48
- }
49
- export interface RedemptionResponse {
50
- success: boolean;
51
- errorCode?: string;
52
- message: string;
53
- redemptionId?: string;
54
- }
55
- export interface CreateResponse {
56
- success: boolean;
57
- errorCode?: string;
58
- message: string;
59
- couponId?: string;
60
- }
61
- declare const couponService: ({ strapi }: {
62
- strapi: Core.Strapi;
63
- }) => any;
64
- export default couponService;
@@ -1,432 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ERROR_MESSAGES = exports.ERROR_CODES = void 0;
4
- const validators_1 = require("../utils/validators");
5
- // Error codes as per specification
6
- exports.ERROR_CODES = {
7
- COUPON_NOT_FOUND: "COUPON_NOT_FOUND",
8
- COUPON_EXPIRED: "COUPON_EXPIRED",
9
- COUPON_ALREADY_USED: "COUPON_ALREADY_USED",
10
- USAGE_LIMIT_REACHED: "USAGE_LIMIT_REACHED",
11
- INVALID_REQUEST: "INVALID_REQUEST",
12
- USER_RESTRICTED: "USER_RESTRICTED",
13
- };
14
- exports.ERROR_MESSAGES = {
15
- COUPON_NOT_FOUND: "Coupon code does not exist.",
16
- COUPON_EXPIRED: "This coupon has expired.",
17
- COUPON_ALREADY_USED: "This coupon has been already used.",
18
- USAGE_LIMIT_REACHED: "Coupon usage limit has been reached.",
19
- INVALID_REQUEST: "Invalid request parameters.",
20
- USER_RESTRICTED: "This coupon is not available for your phone number.",
21
- };
22
- const couponService = ({ strapi }) => ({
23
- /**
24
- * Validate a coupon for a specific service and user
25
- */
26
- async validate(params) {
27
- const { couponCode, phoneNumber, orderAmount = 0 } = params;
28
- try {
29
- // Validate inputs
30
- if (!(0, validators_1.validateCouponCode)(couponCode)) {
31
- return {
32
- isValid: false,
33
- errorCode: exports.ERROR_CODES.INVALID_REQUEST,
34
- message: "Invalid coupon code format",
35
- };
36
- }
37
- if (!(0, validators_1.validatePhoneNumber)(phoneNumber)) {
38
- return {
39
- isValid: false,
40
- errorCode: exports.ERROR_CODES.INVALID_REQUEST,
41
- message: "Invalid phone number format",
42
- };
43
- }
44
- if (orderAmount < 0) {
45
- return {
46
- isValid: false,
47
- errorCode: exports.ERROR_CODES.INVALID_REQUEST,
48
- message: "Order amount cannot be negative",
49
- };
50
- }
51
- // Find the coupon by code
52
- const coupons = await strapi.entityService.findMany("plugin::coupon.coupon", {
53
- filters: {
54
- code: couponCode,
55
- },
56
- });
57
- const coupon = Array.isArray(coupons) && coupons.length > 0 ? coupons[0] : null;
58
- // Check if coupon exists
59
- if (!coupon) {
60
- return {
61
- isValid: false,
62
- errorCode: exports.ERROR_CODES.COUPON_NOT_FOUND,
63
- message: exports.ERROR_MESSAGES.COUPON_NOT_FOUND,
64
- };
65
- }
66
- // Check if coupon is active
67
- if (!coupon.isActive) {
68
- return {
69
- isValid: false,
70
- errorCode: exports.ERROR_CODES.COUPON_EXPIRED,
71
- message: exports.ERROR_MESSAGES.COUPON_EXPIRED,
72
- };
73
- }
74
- // Check validity period
75
- const now = new Date();
76
- const validFrom = new Date(coupon.validFrom);
77
- const validTo = new Date(coupon.validTo);
78
- if (now < validFrom || now > validTo) {
79
- return {
80
- isValid: false,
81
- errorCode: exports.ERROR_CODES.COUPON_EXPIRED,
82
- message: exports.ERROR_MESSAGES.COUPON_EXPIRED,
83
- };
84
- }
85
- // Check usage limit
86
- if (coupon.maxUsage && coupon.currentUsage >= coupon.maxUsage) {
87
- return {
88
- isValid: false,
89
- errorCode: exports.ERROR_CODES.USAGE_LIMIT_REACHED,
90
- message: exports.ERROR_MESSAGES.USAGE_LIMIT_REACHED,
91
- };
92
- }
93
- // Check per-user usage limit
94
- const existingRedemptions = await strapi.entityService.findMany("plugin::coupon.redemption", {
95
- filters: {
96
- coupon: coupon.id,
97
- phoneNumber,
98
- },
99
- });
100
- const userRedemptionCount = Array.isArray(existingRedemptions)
101
- ? existingRedemptions.length
102
- : 0;
103
- // maxUsagePerUser: 0 = disabled, null/undefined = 1, N = N uses per user
104
- const perUserLimit = coupon.maxUsagePerUser ?? 1;
105
- if (perUserLimit === 0 || userRedemptionCount >= perUserLimit) {
106
- return {
107
- isValid: false,
108
- errorCode: exports.ERROR_CODES.COUPON_ALREADY_USED,
109
- message: exports.ERROR_MESSAGES.COUPON_ALREADY_USED,
110
- };
111
- }
112
- // Calculate discount
113
- let discountAmount = 0;
114
- let finalAmount = orderAmount;
115
- if (coupon.discountType === "percentage") {
116
- discountAmount = (orderAmount * coupon.discountValue) / 100;
117
- finalAmount = orderAmount - discountAmount;
118
- }
119
- else if (coupon.discountType === "flat") {
120
- discountAmount = coupon.discountValue;
121
- finalAmount = Math.max(0, orderAmount - discountAmount);
122
- }
123
- // Return valid response
124
- return {
125
- isValid: true,
126
- discountType: coupon.discountType,
127
- discountValue: coupon.discountValue,
128
- discountAmount,
129
- finalAmount,
130
- message: "Coupon applied successfully.",
131
- };
132
- }
133
- catch (error) {
134
- strapi.log.error("Error validating coupon:", error);
135
- throw error;
136
- }
137
- },
138
- /**
139
- * Redeem a coupon after successful payment
140
- * Uses database transaction to prevent race conditions
141
- */
142
- async redeem(params) {
143
- const { couponCode, phoneNumber, orderId, orderAmount = 0 } = params;
144
- try {
145
- // Validate inputs
146
- if (!(0, validators_1.validateOrderId)(orderId)) {
147
- return {
148
- success: false,
149
- errorCode: exports.ERROR_CODES.INVALID_REQUEST,
150
- message: "Invalid order ID format",
151
- };
152
- }
153
- // Find and validate the coupon
154
- const coupons = await strapi.db.query("plugin::coupon.coupon").findMany({
155
- where: { code: couponCode },
156
- });
157
- const coupon = Array.isArray(coupons) && coupons.length > 0 ? coupons[0] : null;
158
- if (!coupon) {
159
- return {
160
- success: false,
161
- errorCode: exports.ERROR_CODES.COUPON_NOT_FOUND,
162
- message: exports.ERROR_MESSAGES.COUPON_NOT_FOUND,
163
- };
164
- }
165
- // Validate phone number
166
- if (!(0, validators_1.validatePhoneNumber)(phoneNumber)) {
167
- return {
168
- success: false,
169
- errorCode: exports.ERROR_CODES.INVALID_REQUEST,
170
- message: "Invalid phone number format",
171
- };
172
- }
173
- // Perform all validations
174
- if (!coupon.isActive) {
175
- return {
176
- success: false,
177
- errorCode: exports.ERROR_CODES.COUPON_EXPIRED,
178
- message: exports.ERROR_MESSAGES.COUPON_EXPIRED,
179
- };
180
- }
181
- const now = new Date();
182
- const validFrom = new Date(coupon.validFrom);
183
- const validTo = new Date(coupon.validTo);
184
- if (now < validFrom || now > validTo) {
185
- return {
186
- success: false,
187
- errorCode: exports.ERROR_CODES.COUPON_EXPIRED,
188
- message: exports.ERROR_MESSAGES.COUPON_EXPIRED,
189
- };
190
- }
191
- // Check user restrictions (blocked phone numbers)
192
- if (coupon.userRestrictions && Array.isArray(coupon.userRestrictions)) {
193
- if (coupon.userRestrictions.includes(phoneNumber)) {
194
- return {
195
- success: false,
196
- errorCode: exports.ERROR_CODES.USER_RESTRICTED,
197
- message: exports.ERROR_MESSAGES.USER_RESTRICTED,
198
- };
199
- }
200
- }
201
- // Check per-user usage limit
202
- const existingRedemptions = await strapi.db
203
- .query("plugin::coupon.redemption")
204
- .findMany({
205
- where: {
206
- coupon: coupon.id,
207
- phoneNumber,
208
- },
209
- });
210
- const userRedemptionCount = Array.isArray(existingRedemptions)
211
- ? existingRedemptions.length
212
- : 0;
213
- // maxUsagePerUser: 0 = disabled, null/undefined = 1, N = N uses per user
214
- const perUserLimit = coupon.maxUsagePerUser ?? 1;
215
- if (perUserLimit === 0 || userRedemptionCount >= perUserLimit) {
216
- return {
217
- success: false,
218
- errorCode: exports.ERROR_CODES.COUPON_ALREADY_USED,
219
- message: exports.ERROR_MESSAGES.COUPON_ALREADY_USED,
220
- };
221
- }
222
- // Check usage limit before attempting redemption
223
- if (coupon.maxUsage && coupon.currentUsage >= coupon.maxUsage) {
224
- return {
225
- success: false,
226
- errorCode: exports.ERROR_CODES.USAGE_LIMIT_REACHED,
227
- message: exports.ERROR_MESSAGES.USAGE_LIMIT_REACHED,
228
- };
229
- }
230
- // Calculate discount
231
- let discountAmount = 0;
232
- let finalAmount = orderAmount;
233
- if (coupon.discountType === "percentage") {
234
- discountAmount = (orderAmount * coupon.discountValue) / 100;
235
- finalAmount = orderAmount - discountAmount;
236
- }
237
- else if (coupon.discountType === "flat") {
238
- discountAmount = coupon.discountValue;
239
- finalAmount = Math.max(0, orderAmount - discountAmount);
240
- }
241
- // Use transaction for atomic redemption
242
- let redemptionId;
243
- try {
244
- // Atomic increment with optimistic locking
245
- const updateResult = await strapi.db
246
- .query("plugin::coupon.coupon")
247
- .update({
248
- where: {
249
- id: coupon.id,
250
- currentUsage: coupon.currentUsage, // Optimistic lock
251
- },
252
- data: {
253
- currentUsage: coupon.currentUsage + 1,
254
- },
255
- });
256
- // If update failed due to concurrent modification, check usage limit
257
- if (!updateResult ||
258
- (coupon.maxUsage && coupon.currentUsage + 1 > coupon.maxUsage)) {
259
- return {
260
- success: false,
261
- errorCode: exports.ERROR_CODES.USAGE_LIMIT_REACHED,
262
- message: exports.ERROR_MESSAGES.USAGE_LIMIT_REACHED,
263
- };
264
- }
265
- // Create redemption record
266
- const redemption = await strapi.db
267
- .query("plugin::coupon.redemption")
268
- .create({
269
- data: {
270
- coupon: coupon.id,
271
- phoneNumber,
272
- orderId,
273
- discountType: coupon.discountType,
274
- discountValue: coupon.discountValue,
275
- redemptionDate: new Date(),
276
- metadata: {
277
- orderAmount,
278
- finalAmount,
279
- discountAmount,
280
- },
281
- },
282
- });
283
- redemptionId = `redeem_${redemption.id}`;
284
- }
285
- catch (error) {
286
- strapi.log.error("Transaction error during redemption:", error);
287
- throw error;
288
- }
289
- return {
290
- success: true,
291
- message: "Coupon redeemed successfully.",
292
- redemptionId,
293
- };
294
- }
295
- catch (error) {
296
- strapi.log.error("Error redeeming coupon:", error);
297
- throw error;
298
- }
299
- },
300
- /**
301
- * Create a new coupon (Admin only)
302
- */
303
- async create(params) {
304
- try {
305
- const { code, discountType, discountValue, maxUsage, maxUsagePerUser, validFrom, validTo, description, userRestrictions, } = params;
306
- // Validate coupon code
307
- if (!(0, validators_1.validateCouponCode)(code)) {
308
- return {
309
- success: false,
310
- errorCode: "INVALID_COUPON_CODE",
311
- message: "Coupon code must be 3-50 uppercase alphanumeric characters",
312
- };
313
- }
314
- // Validate discount value
315
- const discountValidation = (0, validators_1.validateDiscountValue)(discountType, discountValue);
316
- if (!discountValidation.valid) {
317
- return {
318
- success: false,
319
- errorCode: "INVALID_DISCOUNT",
320
- message: discountValidation.error || "Invalid discount value",
321
- };
322
- }
323
- // Validate date range
324
- const dateValidation = (0, validators_1.validateDateRange)(validFrom, validTo);
325
- if (!dateValidation.valid) {
326
- return {
327
- success: false,
328
- errorCode: "INVALID_DATE_RANGE",
329
- message: dateValidation.error || "Invalid date range",
330
- };
331
- }
332
- // Validate maxUsage
333
- if (maxUsage !== undefined &&
334
- (typeof maxUsage !== "number" || maxUsage < 1)) {
335
- return {
336
- success: false,
337
- errorCode: "INVALID_MAX_USAGE",
338
- message: "maxUsage must be a positive number",
339
- };
340
- }
341
- // Check if coupon code already exists
342
- const existingCoupons = await strapi.entityService.findMany("plugin::coupon.coupon", {
343
- filters: {
344
- code,
345
- },
346
- });
347
- if (Array.isArray(existingCoupons) && existingCoupons.length > 0) {
348
- return {
349
- success: false,
350
- errorCode: "COUPON_ALREADY_EXISTS",
351
- message: "A coupon with this code already exists.",
352
- };
353
- }
354
- // Create the coupon
355
- const coupon = await strapi.entityService.create("plugin::coupon.coupon", {
356
- data: {
357
- code,
358
- discountType,
359
- discountValue,
360
- maxUsage: maxUsage || null,
361
- maxUsagePerUser: maxUsagePerUser ?? null,
362
- currentUsage: 0,
363
- validFrom,
364
- validTo,
365
- isActive: true,
366
- description: description || null,
367
- userRestrictions: userRestrictions || null,
368
- },
369
- });
370
- return {
371
- success: true,
372
- couponId: `coupon_${coupon.id}`,
373
- message: "Coupon created successfully.",
374
- };
375
- }
376
- catch (error) {
377
- strapi.log.error("Error creating coupon:", error);
378
- throw error;
379
- }
380
- },
381
- /**
382
- * Get all coupons
383
- */
384
- async findAll(query = {}) {
385
- try {
386
- return await strapi.entityService.findMany("plugin::coupon.coupon", query);
387
- }
388
- catch (error) {
389
- strapi.log.error("Error finding coupons:", error);
390
- throw error;
391
- }
392
- },
393
- /**
394
- * Get a single coupon
395
- */
396
- async findOne(id) {
397
- try {
398
- return await strapi.entityService.findOne("plugin::coupon.coupon", id);
399
- }
400
- catch (error) {
401
- strapi.log.error("Error finding coupon:", error);
402
- throw error;
403
- }
404
- },
405
- /**
406
- * Update a coupon
407
- */
408
- async update(id, data) {
409
- try {
410
- return await strapi.entityService.update("plugin::coupon.coupon", id, {
411
- data,
412
- });
413
- }
414
- catch (error) {
415
- strapi.log.error("Error updating coupon:", error);
416
- throw error;
417
- }
418
- },
419
- /**
420
- * Delete a coupon
421
- */
422
- async delete(id) {
423
- try {
424
- return await strapi.entityService.delete("plugin::coupon.coupon", id);
425
- }
426
- catch (error) {
427
- strapi.log.error("Error deleting coupon:", error);
428
- throw error;
429
- }
430
- },
431
- });
432
- exports.default = couponService;
@@ -1,5 +0,0 @@
1
- import type { Core } from '@strapi/strapi';
2
- declare const _default: Record<string, (params: {
3
- strapi: Core.Strapi;
4
- }) => any>;
5
- export default _default;