washday-sdk 1.6.63 → 1.6.64

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.
@@ -69,3 +69,23 @@ export const getCFDIAddonStatus = function (data) {
69
69
  }
70
70
  });
71
71
  };
72
+ export const getAvailableSubscriptionPlans = function () {
73
+ return __awaiter(this, arguments, void 0, function* (data = {}) {
74
+ try {
75
+ const config = {
76
+ headers: { Authorization: `Bearer ${this.apiToken}` }
77
+ };
78
+ const params = new URLSearchParams();
79
+ if (data.companyId) {
80
+ params.set("companyId", data.companyId);
81
+ }
82
+ const query = params.toString();
83
+ const response = yield this.axiosInstance.get(`${GET_SET_BILLING}/subscription/available-plans${query ? `?${query}` : ""}`, config);
84
+ return response;
85
+ }
86
+ catch (error) {
87
+ console.error('Error fetching getAvailableSubscriptionPlans:', error);
88
+ throw error;
89
+ }
90
+ });
91
+ };
@@ -99,3 +99,33 @@ export const disableCFDIAddon = function (data) {
99
99
  }
100
100
  });
101
101
  };
102
+ export const previewSubscriptionPlanChange = function (data) {
103
+ return __awaiter(this, void 0, void 0, function* () {
104
+ try {
105
+ const config = {
106
+ headers: { Authorization: `Bearer ${this.apiToken}` }
107
+ };
108
+ const response = yield this.axiosInstance.post(`${GET_SET_BILLING}/subscription/change-plan/preview`, data, config);
109
+ return response;
110
+ }
111
+ catch (error) {
112
+ console.error('Error fetching previewSubscriptionPlanChange:', error);
113
+ throw error;
114
+ }
115
+ });
116
+ };
117
+ export const changeSubscriptionPlan = function (data) {
118
+ return __awaiter(this, void 0, void 0, function* () {
119
+ try {
120
+ const config = {
121
+ headers: { Authorization: `Bearer ${this.apiToken}` }
122
+ };
123
+ const response = yield this.axiosInstance.post(`${GET_SET_BILLING}/subscription/change-plan`, data, config);
124
+ return response;
125
+ }
126
+ catch (error) {
127
+ console.error('Error fetching changeSubscriptionPlan:', error);
128
+ throw error;
129
+ }
130
+ });
131
+ };
package/dist/api/index.js CHANGED
@@ -2,8 +2,8 @@ import { deleteCashierBoxById, deleteCashierBoxMovementById } from "./cashierbox
2
2
  import { getCashierBoxMovementsHistory, getCashierboxesById, getCashierboxesByStoreId } from "./cashierbox/get";
3
3
  import { addCashierBoxMovement, createCashierBox } from "./cashierbox/post";
4
4
  import { updateCashierBoxById, updateCashierBoxMovementById } from "./cashierbox/put";
5
- import { getCFDIAddonStatus, getCompanyById, getCompanyOrdersMetrics, getGarmentAttributeCatalogs } from "./companies/get";
6
- import { disableBillingOverage, disableCFDIAddon, enableBillingOverage, enableCFDIAddon, updateCFDIOrgLogo, updateCompanyTaxInfoCertificates } from "./companies/post";
5
+ import { getAvailableSubscriptionPlans, getCFDIAddonStatus, getCompanyById, getCompanyOrdersMetrics, getGarmentAttributeCatalogs } from "./companies/get";
6
+ import { changeSubscriptionPlan, disableBillingOverage, disableCFDIAddon, enableBillingOverage, enableCFDIAddon, previewSubscriptionPlanChange, updateCFDIOrgLogo, updateCompanyTaxInfoCertificates } from "./companies/post";
7
7
  import { updateCompanyById, updateCompanyLogoById, updateCompanySubscriptionBillingInfoById, updateCompanyTaxInfoById, updateGarmentAttributeCatalogsById } from "./companies/put";
8
8
  import { getCountries } from "./countries/get";
9
9
  import * as configEndpoints from "./config";
@@ -288,6 +288,9 @@ const WashdayClient = function WashdayClient(apiToken, env = 'PROD', clientId, c
288
288
  enableCFDIAddon: enableCFDIAddon,
289
289
  disableCFDIAddon: disableCFDIAddon,
290
290
  getCFDIAddonStatus: getCFDIAddonStatus,
291
+ getAvailableSubscriptionPlans: getAvailableSubscriptionPlans,
292
+ previewSubscriptionPlanChange: previewSubscriptionPlanChange,
293
+ changeSubscriptionPlan: changeSubscriptionPlan,
291
294
  });
292
295
  this.stripe = bindMethods(this, {
293
296
  createCreateSuscriptionCheckoutSession: createCreateSuscriptionCheckoutSession,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "washday-sdk",
3
- "version": "1.6.63",
3
+ "version": "1.6.64",
4
4
  "description": "Washday utilities functions and API",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -1,5 +1,8 @@
1
1
  import { WashdayClientInstance } from "../../interfaces/Api";
2
- import { GetCFDIAddonStatusRequest } from "../../interfaces/Company";
2
+ import {
3
+ GetAvailableSubscriptionPlansRequest,
4
+ GetCFDIAddonStatusRequest,
5
+ } from "../../interfaces/Company";
3
6
 
4
7
  const GET_SET_COMPANIES = 'api/company';
5
8
  const GET_SET_BILLING = 'api/billing';
@@ -58,3 +61,27 @@ export const getCFDIAddonStatus = async function (
58
61
  throw error;
59
62
  }
60
63
  };
64
+
65
+ export const getAvailableSubscriptionPlans = async function (
66
+ this: WashdayClientInstance,
67
+ data: GetAvailableSubscriptionPlansRequest = {},
68
+ ): Promise<any> {
69
+ try {
70
+ const config = {
71
+ headers: { Authorization: `Bearer ${this.apiToken}` }
72
+ };
73
+ const params = new URLSearchParams();
74
+ if (data.companyId) {
75
+ params.set("companyId", data.companyId);
76
+ }
77
+ const query = params.toString();
78
+ const response = await this.axiosInstance.get(
79
+ `${GET_SET_BILLING}/subscription/available-plans${query ? `?${query}` : ""}`,
80
+ config,
81
+ );
82
+ return response;
83
+ } catch (error) {
84
+ console.error('Error fetching getAvailableSubscriptionPlans:', error);
85
+ throw error;
86
+ }
87
+ };
@@ -1,5 +1,9 @@
1
1
  import { WashdayClientInstance } from "../../interfaces/Api";
2
- import { CFDIAddonToggleRequest } from "../../interfaces/Company";
2
+ import {
3
+ ApplySubscriptionPlanChangeRequest,
4
+ CFDIAddonToggleRequest,
5
+ PreviewSubscriptionPlanChangeRequest,
6
+ } from "../../interfaces/Company";
3
7
  import axiosInstance from "../axiosInstance";
4
8
  const GET_SET_COMPANIES = 'api/company';
5
9
  const GET_SET_BILLING = 'api/billing';
@@ -91,3 +95,35 @@ export const disableCFDIAddon = async function (
91
95
  throw error;
92
96
  }
93
97
  }
98
+
99
+ export const previewSubscriptionPlanChange = async function (
100
+ this: WashdayClientInstance,
101
+ data: PreviewSubscriptionPlanChangeRequest
102
+ ): Promise<any> {
103
+ try {
104
+ const config = {
105
+ headers: { Authorization: `Bearer ${this.apiToken}` }
106
+ };
107
+ const response = await this.axiosInstance.post(`${GET_SET_BILLING}/subscription/change-plan/preview`, data, config);
108
+ return response;
109
+ } catch (error) {
110
+ console.error('Error fetching previewSubscriptionPlanChange:', error);
111
+ throw error;
112
+ }
113
+ }
114
+
115
+ export const changeSubscriptionPlan = async function (
116
+ this: WashdayClientInstance,
117
+ data: ApplySubscriptionPlanChangeRequest
118
+ ): Promise<any> {
119
+ try {
120
+ const config = {
121
+ headers: { Authorization: `Bearer ${this.apiToken}` }
122
+ };
123
+ const response = await this.axiosInstance.post(`${GET_SET_BILLING}/subscription/change-plan`, data, config);
124
+ return response;
125
+ } catch (error) {
126
+ console.error('Error fetching changeSubscriptionPlan:', error);
127
+ throw error;
128
+ }
129
+ }
package/src/api/index.ts CHANGED
@@ -3,8 +3,8 @@ import { deleteCashierBoxById, deleteCashierBoxMovementById } from "./cashierbox
3
3
  import { getCashierBoxMovementsHistory, getCashierboxesById, getCashierboxesByStoreId } from "./cashierbox/get";
4
4
  import { addCashierBoxMovement, createCashierBox } from "./cashierbox/post";
5
5
  import { updateCashierBoxById, updateCashierBoxMovementById } from "./cashierbox/put";
6
- import { getCFDIAddonStatus, getCompanyById, getCompanyOrdersMetrics, getGarmentAttributeCatalogs } from "./companies/get";
7
- import { disableBillingOverage, disableCFDIAddon, enableBillingOverage, enableCFDIAddon, updateCFDIOrgLogo, updateCompanyTaxInfoCertificates } from "./companies/post";
6
+ import { getAvailableSubscriptionPlans, getCFDIAddonStatus, getCompanyById, getCompanyOrdersMetrics, getGarmentAttributeCatalogs } from "./companies/get";
7
+ import { changeSubscriptionPlan, disableBillingOverage, disableCFDIAddon, enableBillingOverage, enableCFDIAddon, previewSubscriptionPlanChange, updateCFDIOrgLogo, updateCompanyTaxInfoCertificates } from "./companies/post";
8
8
  import { updateCompanyById, updateCompanyLogoById, updateCompanySubscriptionBillingInfoById, updateCompanyTaxInfoById, updateGarmentAttributeCatalogsById } from "./companies/put";
9
9
  import { getCountries } from "./countries/get";
10
10
  import * as configEndpoints from "./config";
@@ -295,6 +295,9 @@ const WashdayClient: WashdayClientConstructor = function WashdayClient(this: Was
295
295
  enableCFDIAddon: enableCFDIAddon,
296
296
  disableCFDIAddon: disableCFDIAddon,
297
297
  getCFDIAddonStatus: getCFDIAddonStatus,
298
+ getAvailableSubscriptionPlans: getAvailableSubscriptionPlans,
299
+ previewSubscriptionPlanChange: previewSubscriptionPlanChange,
300
+ changeSubscriptionPlan: changeSubscriptionPlan,
298
301
  });
299
302
  this.stripe = bindMethods(this, {
300
303
  createCreateSuscriptionCheckoutSession: createCreateSuscriptionCheckoutSession,
@@ -2,8 +2,8 @@ import { deleteCashierBoxById, deleteCashierBoxMovementById } from "../api/cashi
2
2
  import { getCashierBoxMovementsHistory, getCashierboxesById, getCashierboxesByStoreId } from "../api/cashierbox/get";
3
3
  import { addCashierBoxMovement, createCashierBox } from "../api/cashierbox/post";
4
4
  import { updateCashierBoxById, updateCashierBoxMovementById } from "../api/cashierbox/put";
5
- import { getCFDIAddonStatus, getCompanyById, getCompanyOrdersMetrics, getGarmentAttributeCatalogs } from "../api/companies/get";
6
- import { disableBillingOverage, disableCFDIAddon, enableBillingOverage, enableCFDIAddon, updateCFDIOrgLogo, updateCompanyTaxInfoCertificates } from "../api/companies/post";
5
+ import { getAvailableSubscriptionPlans, getCFDIAddonStatus, getCompanyById, getCompanyOrdersMetrics, getGarmentAttributeCatalogs } from "../api/companies/get";
6
+ import { changeSubscriptionPlan, disableBillingOverage, disableCFDIAddon, enableBillingOverage, enableCFDIAddon, previewSubscriptionPlanChange, updateCFDIOrgLogo, updateCompanyTaxInfoCertificates } from "../api/companies/post";
7
7
  import { updateCompanyById, updateCompanyLogoById, updateCompanySubscriptionBillingInfoById, updateCompanyTaxInfoById, updateGarmentAttributeCatalogsById } from "../api/companies/put";
8
8
  import { getCountries } from "../api/countries/get";
9
9
  import * as configEndpoints from "../api/config";
@@ -280,6 +280,9 @@ export interface WashdayClientInstance {
280
280
  enableCFDIAddon: typeof enableCFDIAddon;
281
281
  disableCFDIAddon: typeof disableCFDIAddon;
282
282
  getCFDIAddonStatus: typeof getCFDIAddonStatus;
283
+ getAvailableSubscriptionPlans: typeof getAvailableSubscriptionPlans;
284
+ previewSubscriptionPlanChange: typeof previewSubscriptionPlanChange;
285
+ changeSubscriptionPlan: typeof changeSubscriptionPlan;
283
286
  };
284
287
  stripe: {
285
288
  createCreateSuscriptionCheckoutSession: typeof createCreateSuscriptionCheckoutSession;
@@ -54,7 +54,98 @@ export interface GetCFDIAddonStatusRequest {
54
54
  companyId: string;
55
55
  }
56
56
 
57
+ export type SubscriptionPlanChangePlan = "basic" | "standard" | "premium";
58
+ export type SubscriptionPlanChangeDirection = "upgrade" | "downgrade" | "same_plan";
59
+ export type SubscriptionPlanChangeBehavior =
60
+ | "immediate_prorated_charge"
61
+ | "contact_support"
62
+ | "no_change";
63
+ export type SubscriptionPlanChangeAddon = "cfdi" | "orders_overage";
64
+
65
+ export interface GetAvailableSubscriptionPlansRequest {
66
+ companyId?: string;
67
+ }
68
+
69
+ export interface AvailableSubscriptionPlan {
70
+ plan: SubscriptionPlanChangePlan;
71
+ priceId: string;
72
+ amount: number;
73
+ currency: string;
74
+ interval: string | null;
75
+ displayPrice: string;
76
+ }
77
+
78
+ export interface AvailableSubscriptionPlansResponse {
79
+ currentPlan: SubscriptionPlanChangePlan;
80
+ currentPlanPriceId: string;
81
+ country: string;
82
+ currency: string;
83
+ plans: AvailableSubscriptionPlan[];
84
+ }
85
+
86
+ export interface PreviewSubscriptionPlanChangeRequest {
87
+ companyId?: string;
88
+ targetPlan: SubscriptionPlanChangePlan;
89
+ }
90
+
91
+ export interface PlanChangePreviewLine {
92
+ description: string;
93
+ amount: number;
94
+ currency: string;
95
+ amountFormatted?: string;
96
+ proration?: boolean;
97
+ priceId?: string;
98
+ type?: "credit" | "charge" | "tax" | "addon" | "plan";
99
+ }
100
+
101
+ export interface PlanChangePreviewResponse {
102
+ status: "preview_ready" | "downgrade_not_supported" | "no_change";
103
+ currentPlan: SubscriptionPlanChangePlan;
104
+ targetPlan: SubscriptionPlanChangePlan;
105
+ direction: SubscriptionPlanChangeDirection;
106
+ behavior: SubscriptionPlanChangeBehavior;
107
+ prorationDate?: number;
108
+ currency: string;
109
+ amountDueNow: number;
110
+ amountDueNowFormatted?: string;
111
+ subtotal?: number;
112
+ tax?: number | null;
113
+ total?: number;
114
+ currentPeriodEnd?: string;
115
+ nextBillingDate?: string;
116
+ currentPlanPriceId?: string;
117
+ targetPlanPriceId: string;
118
+ preservedAddons: SubscriptionPlanChangeAddon[];
119
+ lines: PlanChangePreviewLine[];
120
+ message: string;
121
+ }
122
+
123
+ export interface ApplySubscriptionPlanChangeRequest {
124
+ companyId?: string;
125
+ targetPlan: SubscriptionPlanChangePlan;
126
+ expectedCurrentPlanPriceId: string;
127
+ expectedTargetPlanPriceId: string;
128
+ expectedProrationDate: number;
129
+ previewIdempotencyKey?: string;
130
+ idempotencyKey?: string;
131
+ }
132
+
133
+ export interface ApplySubscriptionPlanChangeResponse {
134
+ status: "applied" | "requires_payment_action" | "payment_failed" | "pending_update" | "no_change";
135
+ currentPlan: SubscriptionPlanChangePlan;
136
+ targetPlan: SubscriptionPlanChangePlan;
137
+ subscriptionId: string;
138
+ invoiceId?: string;
139
+ hostedInvoiceUrl?: string;
140
+ paymentIntentClientSecret?: string;
141
+ amountDueNow?: number;
142
+ currency?: string;
143
+ currentPeriodEnd?: string;
144
+ message: string;
145
+ }
146
+
57
147
  export interface IStripeSettings {
148
+ planPriceId?: string | null;
58
149
  stripeCFDISubID: string | null;
59
150
  stripeCFDISubItemID: string | null;
60
151
  cfdiBillingMode?: CFDIBillingMode;
@@ -0,0 +1,92 @@
1
+ import { getAvailableSubscriptionPlans } from "../src/api/companies/get";
2
+ import {
3
+ changeSubscriptionPlan,
4
+ previewSubscriptionPlanChange,
5
+ } from "../src/api/companies/post";
6
+ import type {
7
+ ApplySubscriptionPlanChangeRequest,
8
+ PlanChangePreviewResponse,
9
+ } from "../src/interfaces/Company";
10
+
11
+ describe("subscription plan change company endpoints", () => {
12
+ it("fetches available plans through the billing endpoint", async () => {
13
+ const get = jest.fn().mockResolvedValue({ data: { data: { plans: [] } } });
14
+ const client = {
15
+ apiToken: "token-1",
16
+ axiosInstance: { get },
17
+ } as any;
18
+
19
+ await getAvailableSubscriptionPlans.call(client, { companyId: "company-1" });
20
+
21
+ expect(get).toHaveBeenCalledWith(
22
+ "api/billing/subscription/available-plans?companyId=company-1",
23
+ { headers: { Authorization: "Bearer token-1" } },
24
+ );
25
+ });
26
+
27
+ it("fetches available plans without sending an undefined companyId", async () => {
28
+ const get = jest.fn().mockResolvedValue({ data: { data: { plans: [] } } });
29
+ const client = {
30
+ apiToken: "token-1",
31
+ axiosInstance: { get },
32
+ } as any;
33
+
34
+ await getAvailableSubscriptionPlans.call(client, {});
35
+
36
+ expect(get).toHaveBeenCalledWith(
37
+ "api/billing/subscription/available-plans",
38
+ { headers: { Authorization: "Bearer token-1" } },
39
+ );
40
+ });
41
+
42
+ it("previews a subscription plan change through the billing endpoint", async () => {
43
+ const post = jest.fn().mockResolvedValue({
44
+ data: {
45
+ data: {
46
+ status: "preview_ready",
47
+ prorationDate: 1770000000,
48
+ } satisfies Partial<PlanChangePreviewResponse>,
49
+ },
50
+ });
51
+ const client = {
52
+ apiToken: "token-1",
53
+ axiosInstance: { post },
54
+ } as any;
55
+
56
+ await previewSubscriptionPlanChange.call(client, {
57
+ companyId: "company-1",
58
+ targetPlan: "premium",
59
+ });
60
+
61
+ expect(post).toHaveBeenCalledWith(
62
+ "api/billing/subscription/change-plan/preview",
63
+ { companyId: "company-1", targetPlan: "premium" },
64
+ { headers: { Authorization: "Bearer token-1" } },
65
+ );
66
+ });
67
+
68
+ it("applies a subscription plan change with expected preview fields", async () => {
69
+ const post = jest.fn().mockResolvedValue({ data: { data: { status: "applied" } } });
70
+ const client = {
71
+ apiToken: "token-1",
72
+ axiosInstance: { post },
73
+ } as any;
74
+ const payload: ApplySubscriptionPlanChangeRequest = {
75
+ companyId: "company-1",
76
+ targetPlan: "premium",
77
+ expectedCurrentPlanPriceId: "price_standard",
78
+ expectedTargetPlanPriceId: "price_premium",
79
+ expectedProrationDate: 1770000000,
80
+ previewIdempotencyKey: "preview-1",
81
+ idempotencyKey: "apply-1",
82
+ };
83
+
84
+ await changeSubscriptionPlan.call(client, payload);
85
+
86
+ expect(post).toHaveBeenCalledWith(
87
+ "api/billing/subscription/change-plan",
88
+ payload,
89
+ { headers: { Authorization: "Bearer token-1" } },
90
+ );
91
+ });
92
+ });