diff --git a/.changeset/tidy-comics-tall.md b/.changeset/tidy-comics-tall.md new file mode 100644 index 000000000..83c9e68bb --- /dev/null +++ b/.changeset/tidy-comics-tall.md @@ -0,0 +1,8 @@ +--- +'@voucherify/sdk': minor +--- + +Add support for 3 missing endpoints in loyalties api. Corrected a typo in one of loyalties api method. +- Added support for new endpoints: `GET /loyalties/{campaignId}/earning-rules/{earningRuleId}`, `POST /loyalties/{campaignId}/earning-rules/{earningRuleId}/enable` and `POST /loyalties/{campaignId}/earning-rules/{earningRuleId}/disable` [(examples available in readme.md)](..%2F..%2Fpackages%2Fsdk%2FREADME.md) +- New exported types/interfaces: `LoyaltiesGetEarningRuleResponseBody`, `LoyaltiesEnableEarningRulesResponseBody`, `LoyaltiesDisableEarningRulesResponseBody`, `EarningRuleEvent`, `EarningRuleBase`, `EarningRuleLoyaltyFixed`, `EarningRuleLoyaltyProportionalOrder`, `EarningRuleLoyaltyProportionalOrderAmount`, `EarningRuleLoyaltyProportionalOrderTotalAmount`, `EarningRuleLoyaltyProportionalOrderMetadata`, `EarningRuleLoyaltyProportionalOrderItems`, `EarningRuleLoyaltyProportionalOrderItemsQuantity`, `EarningRuleLoyaltyProportionalOrderItemsAmount`, `EarningRuleLoyaltyProportionalOrderItemsSubtotalAmount`, `EarningRuleLoyaltyProportionalCustomerMetadata`, `EarningRuleLoyaltyProportionalCustomEvent`, `EarningRuleLoyaltyProportional` +- Added optional parameter `calculation_type` to `LoyaltyProportional` diff --git a/packages/sdk/README.md b/packages/sdk/README.md index d593e0e77..30a1292b8 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -984,6 +984,9 @@ Methods are provided within `client.loyalties.*` namespace. - [Create Loyalty Program Earning Rules](#create-loyalty-program-earning-rules) - [Update Loyalty Program Earning Rule](#update-loyalty-program-earning-rule) - [Delete Loyalty Program Earning Rule](#delete-loyalty-program-earning-rule) +- [Get Loyalty Program Earning Rule](#get-loyalty-program-earning-rule) +- [Enable Loyalty Program Earning Rule](#enable-loyalty-program-earning-rule) +- [Disable Loyalty Program Earning Rule](#disable-loyalty-program-earning-rule) - [List Loyalty Program Earning Rules](#list-loyalty-program-earning-rules) - [Create Loyalty Program Member](#create-loyalty-program-member) - [Get Loyalty Program Member](#get-loyalty-program-member) @@ -1066,6 +1069,24 @@ client.loyalties.updateEarningRule(campaignId, earningRule) client.loyalties.deleteEarningRule(campaignId, earningRuleId) ``` +#### [Get Loyalty Program Earning Rule](https://docs.voucherify.io/reference/get-earning-rule) + +```javascript +client.loyalties.getEarningRule(campaignId, earningRuleId) +``` + +#### [Enable Loyalty Program Earning Rule](https://docs.voucherify.io/reference/enable-earning-rule) + +```javascript +client.loyalties.enableEarningRule(campaignId, earningRuleId) +``` + +#### [Disable Loyalty Program Earning Rule](https://docs.voucherify.io/reference/disable-earning-rule) + +```javascript +client.loyalties.disableEarningRule(campaignId, earningRuleId) +``` + #### [List Loyalty Program Earning Rules](https://docs.voucherify.io/reference/list-earning-rules) ```javascript diff --git a/packages/sdk/src/Loyalties.ts b/packages/sdk/src/Loyalties.ts index dd7a232af..5925544be 100644 --- a/packages/sdk/src/Loyalties.ts +++ b/packages/sdk/src/Loyalties.ts @@ -102,6 +102,32 @@ export class Loyalties { public deleteEarningRule(campaignId: string, earningRuleId: string) { return this.client.delete(`/loyalties/${encode(campaignId)}/earning-rules/${earningRuleId}`) } + /** + * @see https://docs.voucherify.io/reference/get-earning-rule + */ + public getEarningRule(campaignId: string, earningRuleId: string) { + return this.client.get( + `/loyalties/${encode(campaignId)}/earning-rules/${encode(earningRuleId)}`, + ) + } + /** + * @see https://docs.voucherify.io/reference/enable-earning-rule + */ + public enableEarningRule(campaignId: string, earningRuleId: string) { + return this.client.post( + `/loyalties/${encode(campaignId)}/earning-rules/${earningRuleId}/enable`, + {}, + ) + } + /** + * @see https://docs.voucherify.io/reference/disable-earning-rule + */ + public disableEarningRule(campaignId: string, earningRuleId: string) { + return this.client.post( + `/loyalties/${encode(campaignId)}/earning-rules/${earningRuleId}/disable`, + {}, + ) + } /** * @see https://docs.voucherify.io/reference/list-members */ diff --git a/packages/sdk/src/types/Loyalties.ts b/packages/sdk/src/types/Loyalties.ts index 9c2bb0f0a..346da9882 100644 --- a/packages/sdk/src/types/Loyalties.ts +++ b/packages/sdk/src/types/Loyalties.ts @@ -173,6 +173,15 @@ export interface LoyaltyFixed { export interface LoyaltyProportional { type: 'PROPORTIONAL' + calculation_type?: + | 'ORDER_AMOUNT' + | 'ORDER_TOTAL_AMOUNT' + | 'ORDER_METADATA' + | 'ORDER_ITEMS_QUANTITY' + | 'ORDER_ITEMS_AMOUNT' + | 'ORDER_ITEMS_SUBTOTAL_AMOUNT' + | 'CUSTOMER_METADATA' + | 'CUSTOM_EVENT_METADATA' order?: { amount: { every: number @@ -497,3 +506,166 @@ export interface LoyaltyPointsTransfer { code: string points: number } + +// 0 Level types + +export type LoyaltiesGetEarningRuleResponseBody = EarningRuleBase & { + validation_rule_id: string | null + updated_at: string | null + active: boolean +} + +export type LoyaltiesEnableEarningRulesResponseBody = EarningRuleBase & { + updated_at: string | null + active: true +} + +export type LoyaltiesDisableEarningRulesResponseBody = EarningRuleBase & { + updated_at: string | null + active: false +} + +// Domain types +export interface EarningRuleBase { + id: string + created_at: string + loyalty: EarningRuleFixed | EarningRuleProportional + event?: EarningRuleEvent + custom_event?: { + schema_id: string + } + segment?: { + id: string + } + source: { + banner?: string + object_id: string + object_type: 'campaign' + } + loyalty_tier?: { + id: string + } + object: 'earning_rule' + automation_id: string + start_date?: string + expiration_date?: string + validity_timeframe?: { + duration: string + interval: string + } + validity_day_of_week?: number[] + metadata: Record +} + +export type EarningRuleEvent = + | 'order.paid' + | 'customer.segment.entered' + | 'custom_event' + | 'customer.loyalty.tier.upgraded' + | 'customer.loyalty.tier.downgraded' + | 'customer.loyalty.tier.prolonged' + | 'customer.loyalty.tier.joined' + | 'customer.loyalty.tier.left' + +export interface EarningRuleFixed { + type: 'FIXED' + points: number +} + +export type EarningRuleProportionalOrder = + | EarningRuleProportionalOrderAmount + | EarningRuleProportionalOrderTotalAmount + | EarningRuleProportionalOrderMetadata + +export interface EarningRuleProportionalOrderAmount { + type: 'PROPORTIONAL' + calculation_type: 'ORDER_AMOUNT' + order: { + amount: { + every: number + points: number + } + } +} + +export interface EarningRuleProportionalOrderTotalAmount { + type: 'PROPORTIONAL' + calculation_type: 'ORDER_TOTAL_AMOUNT' + order: { + total_amount: { + every: number + points: number + } + } +} + +export interface EarningRuleProportionalOrderMetadata { + type: 'PROPORTIONAL' + calculation_type: 'ORDER_METADATA' + order: { + metadata: { + every: number + points: number + property: string + } + } +} + +export type EarningRuleProportional = + | EarningRuleProportionalOrder + | EarningRuleProportionalOrderItems + | EarningRuleProportionalCustomerMetadata + | EarningRuleProportionalCustomEvent + +export type EarningRuleProportionalOrderItems = + | EarningRuleProportionalOrderItemsQuantity + | EarningRuleProportionalOrderItemsAmount + | EarningRuleProportionalOrderItemsSubtotalAmount + +export interface EarningRuleProportionalOrderItemsQuantity { + type: 'PROPORTIONAL' + calculation_type: 'ORDER_ITEMS_QUANTITY' + order_items: { + quantity: { every: number; points: number; object: `products_collection` | `product` | `sku`; id: string } + } +} + +export interface EarningRuleProportionalOrderItemsAmount { + type: 'PROPORTIONAL' + calculation_type: 'ORDER_ITEMS_AMOUNT' + order_items: { + amount: { every: number; points: number; object: `products_collection` | `product` | `sku`; id: string } + } +} + +export interface EarningRuleProportionalOrderItemsSubtotalAmount { + type: 'PROPORTIONAL' + calculation_type: 'ORDER_ITEMS_SUBTOTAL_AMOUNT' + order_items: { + subtotal_amount: { every: number; points: number; object: `products_collection` | `product` | `sku`; id: string } + } +} + +export interface EarningRuleProportionalCustomerMetadata { + type: 'PROPORTIONAL' + calculation_type: 'CUSTOMER_METADATA' + customer: { + metadata: { + every: number + points: number + property: string + } + } +} + +export interface EarningRuleProportionalCustomEvent { + type: 'PROPORTIONAL' + calculation_type: 'CUSTOM_EVENT_METADATA' + custom_event: { + metadata: { + every: number + points: number + property: string + } + } +} diff --git a/packages/sdk/test/loyalties.spec.ts b/packages/sdk/test/loyalties.spec.ts new file mode 100644 index 000000000..3305ce3ab --- /dev/null +++ b/packages/sdk/test/loyalties.spec.ts @@ -0,0 +1,60 @@ +import { voucherifyClient as client } from './client' +import { generateRandomString } from './utils/generateRandomString' + +describe('Loyalties API', () => { + it('Create loyalty campaign, create earning rule and validate it', async () => { + const campaign = await client.loyalties.create({ + name: generateRandomString(), + vouchers_count: 10, + voucher: { + type: 'LOYALTY_CARD', + loyalty_card: { + points: 100, + }, + redemption: { + quantity: 100, + }, + code_config: { + pattern: 'TC2-PROMO-#######', + }, + }, + type: 'AUTO_UPDATE', + metadata: { + campaign: true, + }, + }) + const earningRules = await client.loyalties.createEarningRule(campaign.id, [ + { + event: 'order.paid', + loyalty: { + type: 'PROPORTIONAL', + calculation_type: 'ORDER_AMOUNT', + order: { + amount: { + every: 1000, + points: 3, + }, + }, + }, + }, + ]) + for (const earningRuleId of earningRules.map(earningRule => earningRule.id)) { + const earningRule = await client.loyalties.getEarningRule(campaign.id, earningRuleId) + if (earningRule.loyalty.type === 'PROPORTIONAL') { + if (earningRule.loyalty.calculation_type === 'ORDER_AMOUNT') { + expect(typeof earningRule.loyalty.order.amount.every).toBe('number') + expect(typeof earningRule.loyalty.order.amount.points).toBe('number') + } + if (earningRule.loyalty.calculation_type === 'ORDER_TOTAL_AMOUNT') { + expect(typeof earningRule.loyalty.order.total_amount.every).toBe('number') + expect(typeof earningRule.loyalty.order.total_amount.points).toBe('number') + } + if (earningRule.loyalty.calculation_type === 'ORDER_METADATA') { + expect(typeof earningRule.loyalty.order.metadata.every).toBe('number') + expect(typeof earningRule.loyalty.order.metadata.points).toBe('number') + expect(typeof earningRule.loyalty.order.metadata.property).toBe('string') + } + } + } + }) +})