diff --git a/src/endpoints/subscription-invoices.js b/src/endpoints/subscription-invoices.js new file mode 100644 index 0000000..045fe99 --- /dev/null +++ b/src/endpoints/subscription-invoices.js @@ -0,0 +1,59 @@ +import RequestFactory from '../factories/request' +import { buildURL } from '../utils/helpers' + +class SubscriptionInvoicesEndpoint { + constructor(endpoint) { + const config = { ...endpoint } + this.request = new RequestFactory(config) + + this.endpoint = 'subscriptions/invoices' + } + + All() { + const { filter, limit, offset } = this + + return this.request.send( + buildURL(this.endpoint, { + filter, + limit, + offset + }), + 'GET' + ) + } + + Get(id) { + return this.request.send(`${this.endpoint}/${id}`, 'GET') + } + + GetPayments(invoiceId) { + return this.request.send(`${this.endpoint}/${invoiceId}/payments`, 'GET') + } + + GetPayment(invoiceId, paymentId) { + return this.request.send( + `${this.endpoint}/${invoiceId}/payments/${paymentId}`, + 'GET' + ) + } + + Filter(filter) { + this.filter = filter + + return this + } + + Limit(value) { + this.limit = value + + return this + } + + Offset(value) { + this.offset = value + + return this + } +} + +export default SubscriptionInvoicesEndpoint diff --git a/src/index.d.ts b/src/index.d.ts index e37ba6b..37f4b8d 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -67,6 +67,7 @@ import { SubscriptionSchedulesEndpoint } from './types/subscription-schedules' import { CustomApisEndpoint } from './types/custom-apis' import { SubscriptionDunningRulesEndpoint } from './types/subscription-dunning-rules' import { SubscriptionProrationPoliciesEndpoint } from './types/subscription-proration-policies' +import { SubscriptionInvoicesEndpoint } from './types/subscription-invoices' export * from './types/config' export * from './types/storage' @@ -144,6 +145,7 @@ export * from './types/subscription-schedules' export * from './types/custom-apis' export * from './types/subscription-dunning-rules' export * from './types/subscription-proration-policies' +export * from './types/subscription-invoices' // UMD export as namespace elasticpath @@ -205,13 +207,14 @@ export class ElasticPath { SubscriptionOfferings: SubscriptionOfferingsEndpoint OneTimePasswordTokenRequest: OneTimePasswordTokenRequestEndpoint Subscriptions: SubscriptionsEndpoint - RulePromotions : RulePromotionsEndpoint - SubscriptionSubscribers : SubscriptionSubscribersEndpoint - SubscriptionJobs : SubscriptionJobsEndpoint + RulePromotions: RulePromotionsEndpoint + SubscriptionSubscribers: SubscriptionSubscribersEndpoint + SubscriptionJobs: SubscriptionJobsEndpoint SubscriptionSchedules: SubscriptionSchedulesEndpoint CustomApis: CustomApisEndpoint SubscriptionDunningRules: SubscriptionDunningRulesEndpoint SubscriptionProrationPolicies: SubscriptionProrationPoliciesEndpoint + SubscriptionInvoices: SubscriptionInvoicesEndpoint Cart(id?: string): CartEndpoint // This optional cart id is super worrying when using the SDK in a node server :/ constructor(config: Config) diff --git a/src/index.js b/src/index.js index 76ed62c..4bb33c2 100644 --- a/src/index.js +++ b/src/index.js @@ -54,10 +54,11 @@ import SubscriptionOfferingsEndpoint from './endpoints/subscription-offerings' import SubscriptionsEndpoint from './endpoints/subscriptions' import RulePromotionsEndpoint from './endpoints/rule-promotions' import SubscriptionSubscribersEndpoint from './endpoints/subscription-subscribers' -import SubscriptionJobsEndpoint from './endpoints/subscription-jobs' +import SubscriptionJobsEndpoint from './endpoints/subscription-jobs' import SubscriptionSchedulesEndpoint from './endpoints/subscription-schedules' import SubscriptionDunningRulesEndpoint from './endpoints/subscription-dunning-rules' import SubscriptionProrationPoliciesEndpoint from './endpoints/subscription-proration-policies' +import SubscriptionInvoicesEndpoint from './endpoints/subscription-invoices' import { cartIdentifier, @@ -144,7 +145,9 @@ export default class ElasticPath { this.SubscriptionSchedules = new SubscriptionSchedulesEndpoint(config) this.CustomApis = new CustomApisEndpoint(config) this.SubscriptionDunningRules = new SubscriptionDunningRulesEndpoint(config) - this.SubscriptionProrationPolicies = new SubscriptionProrationPoliciesEndpoint(config) + this.SubscriptionProrationPolicies = + new SubscriptionProrationPoliciesEndpoint(config) + this.SubscriptionInvoices = new SubscriptionInvoicesEndpoint(config) } // Expose `Cart` class on ElasticPath class diff --git a/src/types/subscription-invoices.d.ts b/src/types/subscription-invoices.d.ts new file mode 100644 index 0000000..71a33d2 --- /dev/null +++ b/src/types/subscription-invoices.d.ts @@ -0,0 +1,178 @@ +/** + * Subscription Invoices + * Description: Invoices represent the amount a customer owes for a subscription. + * Elastic Path Subscriptions generates an invoice for every period in a subscription billing cycle. + * DOCS: https://elasticpath.dev/docs/api/subscriptions/invoices + */ +import { + Identifiable, + CrudQueryableResource, + Resource, + ResourceList, + ResourcePage +} from './core' +import { ItemTaxObject } from './cart' +import { Price } from './price' + +interface SubscriptionInvoiceItemPrice extends Omit { + includes_tax?: boolean +} + +interface SubscriptionInvoiceItem { + description: string + price: SubscriptionInvoiceItemPrice + product_id?: string + from_time_period?: string + until_time_period?: string +} + +/** + * Core Subscription Invoice Base Interface + * For custom flows, extend this interface + * DOCS: https://elasticpath.dev/docs/api/subscriptions/get-invoice#responses + */ + +export interface SubscriptionInvoiceBase { + type: 'subscription_invoice' + attributes: { + billing_period: { + start: string + end: string + } + invoice_items: SubscriptionInvoiceItem[] + tax_items?: ItemTaxObject[] + outstanding: boolean + number?: number + tax_required: boolean + payment_retries_limit_reached: boolean + updated_at?: string + created_at?: string + } +} + +interface ProrationEvent { + proration_policy_id: string + billing_cost_before_proration: number + refunded_amount_for_unused_plan: number + new_plan_cost: number + prorated_at: string +} + +export interface SubscriptionInvoice + extends Identifiable, + SubscriptionInvoiceBase { + meta: { + owner: 'store' | 'organization' + subscription_id?: string + subscriber_id?: string + price?: SubscriptionInvoiceItemPrice + timestamps: { + updated_at: string + created_at: string + taxes_added_at?: string + } + prorated_at: ProrationEvent[] + } +} + +/** + * Core Subscription Invoice Payments Base Interface + * DOCS: https://elasticpath.dev/docs/api/subscriptions/get-invoice-payment#responses + */ + +export interface SubscriptionInvoicePaymentBase { + type: 'subscription_invoice_payment' + attributes: { + success: boolean + gateway: string + external_payment_id?: string + failure_detail?: { + reason?: string + } + amount: SubscriptionInvoiceItemPrice + } +} + +export interface SubscriptionInvoicePayment + extends Identifiable, + SubscriptionInvoicePaymentBase { + meta: { + owner: 'store' | 'organization' + subscription_id: string + invoice_id: string + job_id: string + timestamps: { + updated_at: string + created_at: string + payment_taken_at?: string + } + } +} + +/** + * Subscription Invoice Filtering + * DOCS: https://elasticpath.dev/docs/api/subscriptions/list-invoices#filtering + */ +export interface SubscriptionInvoiceFilter { + eq?: { + subscriber_id?: string + subscription_id?: string + outstanding?: string + tax_required?: string + } +} + +/** + * Subscription Invoice Endpoints + * DOCS: https://elasticpath.dev/docs/api/subscriptions/list-invoices + */ +export interface SubscriptionInvoicesEndpoint { + endpoint: 'invoices' + + /** + * List Invoices + * DOCS: https://elasticpath.dev/docs/api/subscriptions/list-invoices + * @constructor + */ + All(): Promise> + + /** + * Get Invoice + * DOCS: https://elasticpath.dev/docs/api/subscriptions/get-invoice + * @param id - The ID of the invoice. + * @constructor + */ + Get(id: string): Promise> + + /** + * List Invoice Payments + * DOCS: https://elasticpath.dev/docs/api/subscriptions/list-invoice-payments + * @param invoiceId - The ID of the invoice to get the payments for. + * @constructor + */ + GetPayments( + invoiceId: string + ): Promise> + + /** + * Get Invoice Payment + * DOCS: https://elasticpath.dev/docs/api/subscriptions/get-invoice-payment + * @param invoiceId - The ID of the invoice to get the payment for. + * @param paymentId - The ID of the payment. + * @constructor + */ + GetPayment( + invoiceId: string, + paymentId: string + ): Promise> + + /** + * Subscription Invoice Filtering + * DOCS: https://elasticpath.dev/docs/api/subscriptions/list-invoices#filtering + */ + Filter(filter: SubscriptionInvoiceFilter): SubscriptionInvoicesEndpoint + + Limit(value: number): SubscriptionInvoicesEndpoint + + Offset(value: number): SubscriptionInvoicesEndpoint +} diff --git a/src/types/subscriptions.d.ts b/src/types/subscriptions.d.ts index 9e3c09c..6f92366 100644 --- a/src/types/subscriptions.d.ts +++ b/src/types/subscriptions.d.ts @@ -9,7 +9,11 @@ import { Resource, ResourcePage } from './core' -import { SubscriptionOfferingPlan, SubscriptionOfferingProduct } from './subscription-offerings' +import { + SubscriptionOfferingPlan, + SubscriptionOfferingProduct +} from './subscription-offerings' +import { SubscriptionInvoice } from './subscription-invoices' /** * Core Subscription Base Interface @@ -17,13 +21,13 @@ import { SubscriptionOfferingPlan, SubscriptionOfferingProduct } from './subscri * DOCS: TODO: add docs when ready */ export interface SubscriptionBase { - type: "subscription" + type: 'subscription' attributes: { external_ref?: string account_id: string offering: { id: string - type: "subscription_offering" + type: 'subscription_offering' attributes: { external_ref?: string name: string @@ -44,10 +48,10 @@ export interface SubscriptionBase { } export interface SubscriptionCreate { - account_id: string, - offering_id: string, - plan_id: string, - currency: string, + account_id: string + offering_id: string + plan_id: string + currency: string meta?: { owner?: string } @@ -60,43 +64,12 @@ export interface SubscriptionUpdate extends Identifiable { } } -export interface SubscriptionInvoice extends Identifiable { - type: "subscription-invoice", - attributes: { - billing_period: { - start: string, - end: string - }, - invoice_items: { - description: string, - price: { - currency: string, - amount: number, - includes_tax: boolean - } - }[], - outstanding: boolean, - updated_at: string, - created_at: string - }, - meta: { - owner: string, - subscription_id: string, - price: { - currency: string, - amount: number, - includes_tax: boolean - } - } -} - export interface SubscriptionFilter { eq?: { account_id?: string } } - export interface Subscription extends Identifiable, SubscriptionBase { relationships: { subscriber: { @@ -122,7 +95,7 @@ export interface Subscription extends Identifiable, SubscriptionBase { export type SubscriptionsInclude = 'plans' -export type SubscriptionsStateAction = 'cancel'| 'pause'| 'resume' +export type SubscriptionsStateAction = 'cancel' | 'pause' | 'resume' export interface SubscriptionsIncluded { plans: SubscriptionOfferingPlan[] @@ -133,23 +106,30 @@ export interface SubscriptionsIncluded { * DOCS: TODO: add docs when ready */ export interface SubscriptionsEndpoint - extends Omit, "All" | "Attributes" | "Link" > { + extends Omit< + CrudQueryableResource< + Subscription, + SubscriptionCreate, + SubscriptionUpdate, + SubscriptionFilter, + never, + SubscriptionsInclude + >, + 'All' | 'Attributes' | 'Link' + > { endpoint: 'subscriptions' - All(token?: string): Promise> + All( + token?: string + ): Promise> GetInvoices(id: string): Promise> - GetAttachedProducts(id: string) : Promise> + GetAttachedProducts( + id: string + ): Promise> - GetAttachedPlans(id: string) : Promise> + GetAttachedPlans(id: string): Promise> - CreateState(id: string, action: SubscriptionsStateAction) : Promise + CreateState(id: string, action: SubscriptionsStateAction): Promise }