Commit Graph

4 Commits

Author SHA1 Message Date
Oli Juhl
b5ecdfcd12 feat: Add allocation method type ONCE (#13700)
### What
Add a new `once` allocation strategy to promotions that limits application to a maximum number of items across the entire cart, rather than per line item.

### Why
Merchants want to create promotions that apply to a limited number of items across the entire cart. For example:
- "Get $10 off, applied to one item only"
- "20% off up to 2 items in your cart"

Current allocation strategies:
- `each`: Applies to each line item independently (respects `max_quantity` per item)
- `across`: Distributes proportionally across all items

Neither supports limiting total applications across the entire cart.

### How

Add `once` to the `ApplicationMethodAllocation` enum.

Behavior:
- Applies promotion to maximum `max_quantity` items across entire cart
- Always prioritizes lowest-priced eligible items first
- Distributes sequentially across items until quota exhausted
- Requires `max_quantity` field to be set

### Example Usage

**Scenario 1: Fixed discount**
```javascript
{
  type: "fixed",
  allocation: "once",
  value: 10,        // $10 off
  max_quantity: 2   // Apply to 2 items max across cart
}

Cart:
- Item A: 3 units @ $100/unit
- Item B: 5 units @ $50/unit (lowest price)

Result: $20 discount on Item B (2 units × $10)
```

**Scenario 2: Distribution across items**
```javascript
{
  type: "fixed",
  allocation: "once",
  value: 5,
  max_quantity: 4
}

Cart:
- Item A: 2 units @ $50/unit
- Item B: 3 units @ $60/unit

Result:
- Item A: $10 discount (2 units × $5)
- Item B: $10 discount (2 units × $5, remaining quota)
```

**Scenario 3: Percentage discount - single item**
```javascript
{
  type: "percentage",
  allocation: "once",
  value: 20,         // 20% off
  max_quantity: 3    // Apply to 3 items max
}

Cart:
- Item A: 5 units @ $100/unit
- Item B: 4 units @ $50/unit (lowest price)

Result: $30 discount on Item B (3 units × $50 × 20% = $30)
```

**Scenario 4: Percentage discount - distributed across items**
```javascript
{
  type: "percentage",
  allocation: "once",
  value: 15,         // 15% off
  max_quantity: 5
}

Cart:
- Item A: 2 units @ $40/unit (lowest price)
- Item B: 4 units @ $80/unit

Result:
- Item A: $12 discount (2 units × $40 × 15% = $12)
- Item B: $36 discount (3 units × $80 × 15% = $36, remaining quota)
Total: $48 discount
```

**Scenario 5: Percentage with max_quantity = 1**
```javascript
{
  type: "percentage",
  allocation: "once",
  value: 25,         // 25% off
  max_quantity: 1    // Only one item
}

Cart:
- Item A: 3 units @ $60/unit
- Item B: 2 units @ $30/unit (lowest price)

Result: $7.50 discount on Item B (1 unit × $30 × 25%)
```
2025-10-14 11:01:00 +00:00
Frane Polić
7dc3b0c5ff feat(core-flows,dashboard,js-sdk,promotion,medusa,types,utils): limit promotion usage per customer (#13451)
**What**
- implement promotion usage limits per customer/email
- fix registering spend usage over the limit
- fix type errors in promotion module tests

**How**
- introduce a new type of campaign budget that can be defined by an attribute such as customer id or email
- add `CampaignBudgetUsage` entity to keep track of the number of uses per attribute value
- update `registerUsage` and `computeActions` in the promotion module to work with the new type
- update `core-flows` to pass context needed for usage calculation to the promotion module

**Breaking**
- registering promotion usage now throws (and cart complete fails) if the budget limit is exceeded or if the cart completion would result in a breached limit

---

CLOSES CORE-1172
CLOSES CORE-1173
CLOSES CORE-1174
CLOSES CORE-1175


Co-authored-by: Adrien de Peretti <25098370+adrien2p@users.noreply.github.com>
2025-10-09 12:35:54 +00:00
Riqwan Thamir
5eab9e7399 feat(promotion,dashboard,types,utils,medusa): Add statuses to promotions (#10950)
what:

- adds a status column to promotion table
- introduce active promotion query
- scope revert, register and compute actions to active promotions
- admin to create and update promotion with statuses

RESOLVES CMRC-845
RESOLVES CMRC-846
RESOLVES CMRC-847
RESOLVES CMRC-848
RESOLVES CMRC-849
RESOLVES CMRC-850
2025-01-16 19:17:22 +00:00
Adrien de Peretti
bbccd6481d chore(): start moving some packages to the core directory (#7215) 2024-05-03 13:37:41 +02:00