@classytic/promo 0.2.1 → 0.2.2
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.
- package/dist/constants-BB5O8zlN.mjs +192 -0
- package/dist/index.mjs +2 -137
- package/dist/schemas/index.mjs +1 -1
- package/package.json +3 -3
- package/dist/constants-D0Rntp2f.mjs +0 -43
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { defineStateMachine } from "@classytic/primitives/state-machine";
|
|
2
|
+
//#region src/domain/errors/base.ts
|
|
3
|
+
var PromoError = class extends Error {
|
|
4
|
+
constructor(message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = this.constructor.name;
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/domain/errors/domain-errors.ts
|
|
11
|
+
var ValidationError = class extends PromoError {
|
|
12
|
+
code = "VALIDATION_ERROR";
|
|
13
|
+
};
|
|
14
|
+
var ProgramNotFoundError = class extends PromoError {
|
|
15
|
+
code = "PROGRAM_NOT_FOUND";
|
|
16
|
+
constructor(id) {
|
|
17
|
+
super(id ? `Program '${id}' not found` : "Program not found");
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Raised when a commit-time atomic CAS on `usedCount < maxUsageTotal`
|
|
22
|
+
* fails — i.e. the program's cap was exhausted by another concurrent
|
|
23
|
+
* commit between this caller's evaluate and its commit. The host should
|
|
24
|
+
* surface this as a "promo no longer available" failure to the user; the
|
|
25
|
+
* order itself can still proceed without the discount if the host wishes.
|
|
26
|
+
*/
|
|
27
|
+
var ProgramUsageCapExceededError = class extends PromoError {
|
|
28
|
+
code = "PROGRAM_USAGE_CAP_EXCEEDED";
|
|
29
|
+
constructor(programId, maxUsageTotal) {
|
|
30
|
+
super(`Program '${programId}' has reached its usage cap of ${maxUsageTotal}`);
|
|
31
|
+
this.programId = programId;
|
|
32
|
+
this.maxUsageTotal = maxUsageTotal;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
var RuleNotFoundError = class extends PromoError {
|
|
36
|
+
code = "RULE_NOT_FOUND";
|
|
37
|
+
constructor(id) {
|
|
38
|
+
super(id ? `Rule '${id}' not found` : "Rule not found");
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
var RewardNotFoundError = class extends PromoError {
|
|
42
|
+
code = "REWARD_NOT_FOUND";
|
|
43
|
+
constructor(id) {
|
|
44
|
+
super(id ? `Reward '${id}' not found` : "Reward not found");
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
var VoucherNotFoundError = class extends PromoError {
|
|
48
|
+
code = "VOUCHER_NOT_FOUND";
|
|
49
|
+
constructor(codeOrId) {
|
|
50
|
+
super(codeOrId ? `Voucher '${codeOrId}' not found` : "Voucher not found");
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
var InvalidTransitionError = class extends PromoError {
|
|
54
|
+
code = "INVALID_TRANSITION";
|
|
55
|
+
constructor(from, to) {
|
|
56
|
+
super(`Cannot transition from '${from}' to '${to}'`);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
var VoucherExpiredError = class extends PromoError {
|
|
60
|
+
code = "VOUCHER_EXPIRED";
|
|
61
|
+
constructor(code) {
|
|
62
|
+
super(`Voucher '${code}' has expired`);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
var VoucherExhaustedError = class extends PromoError {
|
|
66
|
+
code = "VOUCHER_EXHAUSTED";
|
|
67
|
+
constructor(code) {
|
|
68
|
+
super(`Voucher '${code}' has reached its usage limit`);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Thrown when a gift card's balance has been fully spent and its status
|
|
73
|
+
* flipped to `'used'`. Distinct from `VoucherExhaustedError` (usage-limit
|
|
74
|
+
* exhaustion on a discount voucher) so hosts can show "top up" vs "retry
|
|
75
|
+
* later" messaging.
|
|
76
|
+
*/
|
|
77
|
+
var GiftCardExhaustedError = class extends PromoError {
|
|
78
|
+
code = "GIFT_CARD_EXHAUSTED";
|
|
79
|
+
constructor(code) {
|
|
80
|
+
super(`Gift card '${code}' has been fully spent`);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Thrown when a MongoDB WriteConflict surfaces under voucher-spend
|
|
85
|
+
* contention. Losers see a stable domain shape rather than the raw
|
|
86
|
+
* `"Write conflict during plan execution"` string. Hosts can translate
|
|
87
|
+
* this to HTTP 409 + retry.
|
|
88
|
+
*/
|
|
89
|
+
var ConcurrencyConflictError = class extends PromoError {
|
|
90
|
+
code = "CONCURRENCY_CONFLICT";
|
|
91
|
+
status = 409;
|
|
92
|
+
constructor(resource, resourceId, cause) {
|
|
93
|
+
super(`Concurrent modification on ${resource} '${resourceId}'`);
|
|
94
|
+
this.resource = resource;
|
|
95
|
+
this.resourceId = resourceId;
|
|
96
|
+
this.cause = cause;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
var InsufficientBalanceError = class extends PromoError {
|
|
100
|
+
code = "INSUFFICIENT_BALANCE";
|
|
101
|
+
constructor(code, available, requested) {
|
|
102
|
+
super(`Voucher '${code}' has insufficient balance: ${available} available, ${requested} requested`);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
var TenantIsolationError = class extends PromoError {
|
|
106
|
+
code = "TENANT_ISOLATION";
|
|
107
|
+
constructor() {
|
|
108
|
+
super("Tenant context is required but was not provided");
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
var DuplicateRedemptionError = class extends PromoError {
|
|
112
|
+
code = "DUPLICATE_REDEMPTION";
|
|
113
|
+
constructor(key) {
|
|
114
|
+
super(`Duplicate redemption detected for idempotency key '${key}'`);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
var EvaluationNotFoundError = class extends PromoError {
|
|
118
|
+
code = "EVALUATION_NOT_FOUND";
|
|
119
|
+
constructor(id) {
|
|
120
|
+
super(`Evaluation '${id}' not found or already committed`);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Thrown by `EvaluationService.commit` when the cart hash provided by the
|
|
125
|
+
* caller does not match the cart hash computed at evaluation time. Guards
|
|
126
|
+
* against cart-tampering attacks where a user previews a large discount on
|
|
127
|
+
* a heavy cart, mutates the cart to something cheaper before committing, and
|
|
128
|
+
* tries to apply the stale discount to the altered order.
|
|
129
|
+
*/
|
|
130
|
+
var CartHashMismatchError = class extends PromoError {
|
|
131
|
+
code = "CART_HASH_MISMATCH";
|
|
132
|
+
constructor(evaluationId) {
|
|
133
|
+
super(`Evaluation '${evaluationId}' cart hash mismatch — the cart changed between evaluate and commit. Re-evaluate with the current cart.`);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
//#endregion
|
|
137
|
+
//#region src/constants.ts
|
|
138
|
+
const PROGRAM_TYPES = [
|
|
139
|
+
"promotion",
|
|
140
|
+
"coupon",
|
|
141
|
+
"discount_code",
|
|
142
|
+
"buy_x_get_y",
|
|
143
|
+
"gift_card"
|
|
144
|
+
];
|
|
145
|
+
const TRIGGER_MODES = ["auto", "code"];
|
|
146
|
+
const PROGRAM_STATUSES = [
|
|
147
|
+
"draft",
|
|
148
|
+
"active",
|
|
149
|
+
"paused",
|
|
150
|
+
"expired",
|
|
151
|
+
"archived"
|
|
152
|
+
];
|
|
153
|
+
const STACKING_MODES = ["exclusive", "stackable"];
|
|
154
|
+
const REWARD_TYPES = ["discount", "free_product"];
|
|
155
|
+
const DISCOUNT_MODES = ["percentage", "fixed"];
|
|
156
|
+
const DISCOUNT_SCOPES = [
|
|
157
|
+
"order",
|
|
158
|
+
"cheapest",
|
|
159
|
+
"specific_products"
|
|
160
|
+
];
|
|
161
|
+
const VOUCHER_STATUSES = [
|
|
162
|
+
"active",
|
|
163
|
+
"used",
|
|
164
|
+
"expired",
|
|
165
|
+
"cancelled"
|
|
166
|
+
];
|
|
167
|
+
/**
|
|
168
|
+
* Program status machine — single throw site, declarative table.
|
|
169
|
+
*
|
|
170
|
+
* Wires promo's domain `InvalidTransitionError` (carries `from` + `to`)
|
|
171
|
+
* via `errorFactory` so existing catch sites keep working. The
|
|
172
|
+
* primitive's `entityId` field is dropped at the boundary — promo's
|
|
173
|
+
* error doesn't include it. If a future caller needs structured entity
|
|
174
|
+
* fields, extend the error first.
|
|
175
|
+
*/
|
|
176
|
+
const PROGRAM_MACHINE = defineStateMachine({
|
|
177
|
+
name: "Program",
|
|
178
|
+
transitions: {
|
|
179
|
+
draft: ["active", "archived"],
|
|
180
|
+
active: [
|
|
181
|
+
"paused",
|
|
182
|
+
"expired",
|
|
183
|
+
"archived"
|
|
184
|
+
],
|
|
185
|
+
paused: ["active", "archived"],
|
|
186
|
+
expired: ["archived"],
|
|
187
|
+
archived: []
|
|
188
|
+
},
|
|
189
|
+
errorFactory: ({ from, to }) => new InvalidTransitionError(from, to)
|
|
190
|
+
});
|
|
191
|
+
//#endregion
|
|
192
|
+
export { VoucherExhaustedError as C, PromoError as E, ValidationError as S, VoucherNotFoundError as T, ProgramNotFoundError as _, PROGRAM_TYPES as a, RuleNotFoundError as b, TRIGGER_MODES as c, ConcurrencyConflictError as d, DuplicateRedemptionError as f, InvalidTransitionError as g, InsufficientBalanceError as h, PROGRAM_STATUSES as i, VOUCHER_STATUSES as l, GiftCardExhaustedError as m, DISCOUNT_SCOPES as n, REWARD_TYPES as o, EvaluationNotFoundError as p, PROGRAM_MACHINE as r, STACKING_MODES as s, DISCOUNT_MODES as t, CartHashMismatchError as u, ProgramUsageCapExceededError as v, VoucherExpiredError as w, TenantIsolationError as x, RewardNotFoundError as y };
|
package/dist/index.mjs
CHANGED
|
@@ -1,145 +1,10 @@
|
|
|
1
|
-
import { a as PROGRAM_TYPES, c as TRIGGER_MODES, i as
|
|
1
|
+
import { C as VoucherExhaustedError, E as PromoError, S as ValidationError, T as VoucherNotFoundError, _ as ProgramNotFoundError, a as PROGRAM_TYPES, b as RuleNotFoundError, c as TRIGGER_MODES, d as ConcurrencyConflictError, f as DuplicateRedemptionError, g as InvalidTransitionError, h as InsufficientBalanceError, i as PROGRAM_STATUSES, l as VOUCHER_STATUSES, m as GiftCardExhaustedError, n as DISCOUNT_SCOPES, o as REWARD_TYPES, p as EvaluationNotFoundError, r as PROGRAM_MACHINE, s as STACKING_MODES, t as DISCOUNT_MODES, u as CartHashMismatchError, v as ProgramUsageCapExceededError, w as VoucherExpiredError, x as TenantIsolationError, y as RewardNotFoundError } from "./constants-BB5O8zlN.mjs";
|
|
2
2
|
import { Repository, multiTenantPlugin, withTransaction } from "@classytic/mongokit";
|
|
3
3
|
import { resolveTenantConfig } from "@classytic/primitives/tenant";
|
|
4
4
|
import { createEvent, matchEventPattern } from "@classytic/primitives/events";
|
|
5
5
|
import mongoose, { Schema } from "mongoose";
|
|
6
6
|
import { createHash, randomBytes } from "node:crypto";
|
|
7
7
|
import { z } from "zod";
|
|
8
|
-
//#region src/domain/errors/base.ts
|
|
9
|
-
var PromoError = class extends Error {
|
|
10
|
-
constructor(message) {
|
|
11
|
-
super(message);
|
|
12
|
-
this.name = this.constructor.name;
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
//#endregion
|
|
16
|
-
//#region src/domain/errors/domain-errors.ts
|
|
17
|
-
var ValidationError = class extends PromoError {
|
|
18
|
-
code = "VALIDATION_ERROR";
|
|
19
|
-
};
|
|
20
|
-
var ProgramNotFoundError = class extends PromoError {
|
|
21
|
-
code = "PROGRAM_NOT_FOUND";
|
|
22
|
-
constructor(id) {
|
|
23
|
-
super(id ? `Program '${id}' not found` : "Program not found");
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* Raised when a commit-time atomic CAS on `usedCount < maxUsageTotal`
|
|
28
|
-
* fails — i.e. the program's cap was exhausted by another concurrent
|
|
29
|
-
* commit between this caller's evaluate and its commit. The host should
|
|
30
|
-
* surface this as a "promo no longer available" failure to the user; the
|
|
31
|
-
* order itself can still proceed without the discount if the host wishes.
|
|
32
|
-
*/
|
|
33
|
-
var ProgramUsageCapExceededError = class extends PromoError {
|
|
34
|
-
code = "PROGRAM_USAGE_CAP_EXCEEDED";
|
|
35
|
-
constructor(programId, maxUsageTotal) {
|
|
36
|
-
super(`Program '${programId}' has reached its usage cap of ${maxUsageTotal}`);
|
|
37
|
-
this.programId = programId;
|
|
38
|
-
this.maxUsageTotal = maxUsageTotal;
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
var RuleNotFoundError = class extends PromoError {
|
|
42
|
-
code = "RULE_NOT_FOUND";
|
|
43
|
-
constructor(id) {
|
|
44
|
-
super(id ? `Rule '${id}' not found` : "Rule not found");
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
var RewardNotFoundError = class extends PromoError {
|
|
48
|
-
code = "REWARD_NOT_FOUND";
|
|
49
|
-
constructor(id) {
|
|
50
|
-
super(id ? `Reward '${id}' not found` : "Reward not found");
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
var VoucherNotFoundError = class extends PromoError {
|
|
54
|
-
code = "VOUCHER_NOT_FOUND";
|
|
55
|
-
constructor(codeOrId) {
|
|
56
|
-
super(codeOrId ? `Voucher '${codeOrId}' not found` : "Voucher not found");
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
var InvalidTransitionError = class extends PromoError {
|
|
60
|
-
code = "INVALID_TRANSITION";
|
|
61
|
-
constructor(from, to) {
|
|
62
|
-
super(`Cannot transition from '${from}' to '${to}'`);
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
var VoucherExpiredError = class extends PromoError {
|
|
66
|
-
code = "VOUCHER_EXPIRED";
|
|
67
|
-
constructor(code) {
|
|
68
|
-
super(`Voucher '${code}' has expired`);
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
var VoucherExhaustedError = class extends PromoError {
|
|
72
|
-
code = "VOUCHER_EXHAUSTED";
|
|
73
|
-
constructor(code) {
|
|
74
|
-
super(`Voucher '${code}' has reached its usage limit`);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
/**
|
|
78
|
-
* Thrown when a gift card's balance has been fully spent and its status
|
|
79
|
-
* flipped to `'used'`. Distinct from `VoucherExhaustedError` (usage-limit
|
|
80
|
-
* exhaustion on a discount voucher) so hosts can show "top up" vs "retry
|
|
81
|
-
* later" messaging.
|
|
82
|
-
*/
|
|
83
|
-
var GiftCardExhaustedError = class extends PromoError {
|
|
84
|
-
code = "GIFT_CARD_EXHAUSTED";
|
|
85
|
-
constructor(code) {
|
|
86
|
-
super(`Gift card '${code}' has been fully spent`);
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
/**
|
|
90
|
-
* Thrown when a MongoDB WriteConflict surfaces under voucher-spend
|
|
91
|
-
* contention. Losers see a stable domain shape rather than the raw
|
|
92
|
-
* `"Write conflict during plan execution"` string. Hosts can translate
|
|
93
|
-
* this to HTTP 409 + retry.
|
|
94
|
-
*/
|
|
95
|
-
var ConcurrencyConflictError = class extends PromoError {
|
|
96
|
-
code = "CONCURRENCY_CONFLICT";
|
|
97
|
-
status = 409;
|
|
98
|
-
constructor(resource, resourceId, cause) {
|
|
99
|
-
super(`Concurrent modification on ${resource} '${resourceId}'`);
|
|
100
|
-
this.resource = resource;
|
|
101
|
-
this.resourceId = resourceId;
|
|
102
|
-
this.cause = cause;
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
var InsufficientBalanceError = class extends PromoError {
|
|
106
|
-
code = "INSUFFICIENT_BALANCE";
|
|
107
|
-
constructor(code, available, requested) {
|
|
108
|
-
super(`Voucher '${code}' has insufficient balance: ${available} available, ${requested} requested`);
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
var TenantIsolationError = class extends PromoError {
|
|
112
|
-
code = "TENANT_ISOLATION";
|
|
113
|
-
constructor() {
|
|
114
|
-
super("Tenant context is required but was not provided");
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
var DuplicateRedemptionError = class extends PromoError {
|
|
118
|
-
code = "DUPLICATE_REDEMPTION";
|
|
119
|
-
constructor(key) {
|
|
120
|
-
super(`Duplicate redemption detected for idempotency key '${key}'`);
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
var EvaluationNotFoundError = class extends PromoError {
|
|
124
|
-
code = "EVALUATION_NOT_FOUND";
|
|
125
|
-
constructor(id) {
|
|
126
|
-
super(`Evaluation '${id}' not found or already committed`);
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
/**
|
|
130
|
-
* Thrown by `EvaluationService.commit` when the cart hash provided by the
|
|
131
|
-
* caller does not match the cart hash computed at evaluation time. Guards
|
|
132
|
-
* against cart-tampering attacks where a user previews a large discount on
|
|
133
|
-
* a heavy cart, mutates the cart to something cheaper before committing, and
|
|
134
|
-
* tries to apply the stale discount to the altered order.
|
|
135
|
-
*/
|
|
136
|
-
var CartHashMismatchError = class extends PromoError {
|
|
137
|
-
code = "CART_HASH_MISMATCH";
|
|
138
|
-
constructor(evaluationId) {
|
|
139
|
-
super(`Evaluation '${evaluationId}' cart hash mismatch — the cart changed between evaluate and commit. Re-evaluate with the current cart.`);
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
//#endregion
|
|
143
8
|
//#region src/events/in-process-bus.ts
|
|
144
9
|
var InProcessPromoBus = class {
|
|
145
10
|
name = "in-process-promo";
|
|
@@ -701,7 +566,7 @@ var ProgramRepository = class extends Repository {
|
|
|
701
566
|
...ctx
|
|
702
567
|
});
|
|
703
568
|
if (!program) throw new ProgramNotFoundError(id);
|
|
704
|
-
|
|
569
|
+
PROGRAM_MACHINE.assertTransition(String(program._id), program.status, targetStatus);
|
|
705
570
|
const updated = await this.update(id, { status: targetStatus }, {
|
|
706
571
|
throwOnNotFound: true,
|
|
707
572
|
lean: true,
|
package/dist/schemas/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as PROGRAM_TYPES, c as TRIGGER_MODES, l as VOUCHER_STATUSES, n as DISCOUNT_SCOPES, o as REWARD_TYPES,
|
|
1
|
+
import { a as PROGRAM_TYPES, c as TRIGGER_MODES, i as PROGRAM_STATUSES, l as VOUCHER_STATUSES, n as DISCOUNT_SCOPES, o as REWARD_TYPES, s as STACKING_MODES, t as DISCOUNT_MODES } from "../constants-BB5O8zlN.mjs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
//#region src/schemas/index.ts
|
|
4
4
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@classytic/promo",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Production-grade promotion, coupon, and discount engine for MongoDB — programs, rules, rewards, vouchers, gift cards, buy-x-get-y",
|
|
5
5
|
"author": "Classytic",
|
|
6
6
|
"homepage": "https://www.npmjs.com/package/@classytic/promo",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
60
|
"@classytic/mongokit": ">=3.11.0",
|
|
61
|
-
"@classytic/primitives": ">=0.
|
|
61
|
+
"@classytic/primitives": ">=0.2.0",
|
|
62
62
|
"mongoose": ">=9.4.1",
|
|
63
63
|
"zod": ">=4.0.0"
|
|
64
64
|
},
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"@biomejs/biome": "^2.4.9",
|
|
67
67
|
"@classytic/dev-tools": "^0.2.0",
|
|
68
68
|
"@classytic/mongokit": ">=3.11.0",
|
|
69
|
-
"@classytic/primitives": ">=0.
|
|
69
|
+
"@classytic/primitives": ">=0.2.0",
|
|
70
70
|
"@types/node": "^25.5.0",
|
|
71
71
|
"@vitest/coverage-v8": "^3.2.4",
|
|
72
72
|
"knip": "^6.3.0",
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
//#region src/constants.ts
|
|
2
|
-
const PROGRAM_TYPES = [
|
|
3
|
-
"promotion",
|
|
4
|
-
"coupon",
|
|
5
|
-
"discount_code",
|
|
6
|
-
"buy_x_get_y",
|
|
7
|
-
"gift_card"
|
|
8
|
-
];
|
|
9
|
-
const TRIGGER_MODES = ["auto", "code"];
|
|
10
|
-
const PROGRAM_STATUSES = [
|
|
11
|
-
"draft",
|
|
12
|
-
"active",
|
|
13
|
-
"paused",
|
|
14
|
-
"expired",
|
|
15
|
-
"archived"
|
|
16
|
-
];
|
|
17
|
-
const STACKING_MODES = ["exclusive", "stackable"];
|
|
18
|
-
const REWARD_TYPES = ["discount", "free_product"];
|
|
19
|
-
const DISCOUNT_MODES = ["percentage", "fixed"];
|
|
20
|
-
const DISCOUNT_SCOPES = [
|
|
21
|
-
"order",
|
|
22
|
-
"cheapest",
|
|
23
|
-
"specific_products"
|
|
24
|
-
];
|
|
25
|
-
const VOUCHER_STATUSES = [
|
|
26
|
-
"active",
|
|
27
|
-
"used",
|
|
28
|
-
"expired",
|
|
29
|
-
"cancelled"
|
|
30
|
-
];
|
|
31
|
-
const PROGRAM_TRANSITIONS = {
|
|
32
|
-
draft: ["active", "archived"],
|
|
33
|
-
active: [
|
|
34
|
-
"paused",
|
|
35
|
-
"expired",
|
|
36
|
-
"archived"
|
|
37
|
-
],
|
|
38
|
-
paused: ["active", "archived"],
|
|
39
|
-
expired: ["archived"],
|
|
40
|
-
archived: []
|
|
41
|
-
};
|
|
42
|
-
//#endregion
|
|
43
|
-
export { PROGRAM_TYPES as a, TRIGGER_MODES as c, PROGRAM_TRANSITIONS as i, VOUCHER_STATUSES as l, DISCOUNT_SCOPES as n, REWARD_TYPES as o, PROGRAM_STATUSES as r, STACKING_MODES as s, DISCOUNT_MODES as t };
|