UNPKG

quickbooks-api

Version:

A modular TypeScript SDK for seamless integration with Intuit QuickBooks APIs. Provides robust authentication handling and future-ready foundation for accounting, payments, and commerce operations.

387 lines (329 loc) 9.45 kB
// Import the Types import { ApiClient } from '../../packages/api/api-client'; import { DeliveryMethod, EmailAddress, ModificationMetadata, QuickbooksError, ReferenceType, TelephoneNumber, WebsiteAddress, } from '../types'; /** * Customer * * @description * The Customer Object * * @see {@link https://developer.intuit.com/app/developer/qbo/docs/api/accounting/all-entities/customer} */ export class Customer { /** * @description The API client used to make requests to the API to manage the Customer object */ private apiClient: ApiClient; // Setup the Readonly Properties /** * @description Unique identifier for this object * @readonly @systemDefined * @filterable * @sortable * @requiredForUpdate */ public readonly Id: string; /** * @description Version number for update tracking * @readonly @systemDefined * @requiredForUpdate */ public readonly SyncToken: string; /** * @description Currency reference for all customer amounts * @readonly */ public readonly CurrencyRef?: ReferenceType; /** * @description System-defined metadata. Read-only */ public readonly MetaData?: ModificationMetadata; /** * @description Fully qualified hierarchical name * @readonly * @systemDefined * @filterable * @sortable * @remarks Format: Customer:Job:Sub-job (max 5 levels) * @example "ParentCustomer:ChildJob:SubJob" */ public readonly FullyQualifiedName: string; /** * @description Hierarchy level position * @readonly * @systemDefined * @remarks 0 = top level, increments with depth (max 5 levels) */ public readonly Level: number; // Setup the Optional Properties /** * @description Primary email address * @filterable * @maxLength 500 */ public PrimaryEmailAddr?: EmailAddress; /** * @description Resale number or additional customer info * @maxLength 16 */ public ResaleNum?: string; /** * @description Default tax code reference (requires Taxable=true) * @remarks Ignored if Taxable=false. System-managed when automated tax enabled */ public DefaultTaxCodeRef?: ReferenceType; /** * @description Preferred delivery method */ public PreferredDeliveryMethod?: DeliveryMethod; /** * @description Reference to sales terms associated with this customer * @remarks Query SalesTerm list to determine appropriate reference */ public SalesTermRef?: ReferenceType; /** * @description Customer type classification reference * @remarks From predefined customer type list */ public CustomerTypeRef?: ReferenceType; /** * @description Fax number * @maxLength 30 */ public Fax?: TelephoneNumber; /** * @description Indicates if customer is billed with parent * @remarks Only valid for Job/Sub-Customer, requires ParentRef */ public BillWithParent?: boolean; /** * @description Mobile phone number * @maxLength 30 */ public Mobile?: TelephoneNumber; /** * @description Indicates if this is a Job/Sub-customer * @remarks Requires ParentRef if true */ public Job?: boolean; /** * @description Cumulative open balance including sub-jobs * @readonly * @sortable */ public BalanceWithJobs?: number; /** * @description Primary phone number * @maxLength 30 */ public PrimaryPhone?: TelephoneNumber; /** * @description Date of opening balance * @remarks Write-on-create field */ public OpenBalanceDate?: string; /** * @description Indicates if transactions are taxable * @remarks Defaults true if DefaultTaxCodeRef defined */ public Taxable?: boolean; /** * @description Alternate phone number * @maxLength 30 */ public AlternatePhone?: TelephoneNumber; /** * @description Reference to parent customer * @remarks Required for sub-customers/jobs */ public ParentRef?: ReferenceType; /** * @description Free-form notes about customer * @maxLength 2000 */ public Notes?: string; /** * @description Website address * @maxLength 1000 */ public WebAddr?: WebsiteAddress; /** * @description Customer active status * @filterable * @sortable * @remarks Inactive customers with balances get CreditMemo */ public Active?: boolean; /** * @description Associated company name * @maxLength 100 * @filterable * @sortable */ public CompanyName?: string; /** * @description Open balance amount * @filterable * @sortable * @remarks Write-on-create field */ public Balance?: number; /** * @description Default shipping address * @remarks Address components handled differently in transactions */ public ShipAddr?: string; /** * @description Preferred payment method reference * @remarks Query PaymentMethod list for valid references */ public PaymentMethodRef?: ReferenceType; /** * @description Name printed on checks * @maxLength 110 * @filterable * @sortable * @remarks Defaults to DisplayName if not provided */ public PrintOnCheckName?: string; /** * @description Default billing address * @remarks Address components handled differently in transactions */ public BillAddr?: string; /** * @description Display name (conditionally required) * @maxLength 500 * @filterable * @sortable * @remarks Must be unique across all entities. Generated from name components if not provided */ public DisplayName: string; /** * @description Title (conditionally required) * @maxLength 16 * @remarks Part of name component group (with GivenName/MiddleName/FamilyName/Suffix) */ public Title: string; /** * @description Given name (conditionally required). Maximum 100 characters * @filterable, sortable * @remarks Part of name component group */ public GivenName: string; /** * @description Middle name (conditionally required). Maximum 100 characters * @filterable, sortable * @remarks Part of name component group */ public MiddleName: string; /** * @description Name suffix (conditionally required). Maximum 16 characters * @remarks Part of name component group */ public Suffix: string; /** * @description Family name (conditionally required). Maximum 100 characters * @filterable, sortable * @remarks Part of name component group */ public FamilyName: string; /** * @description Constructor for Customer * @param apiClient - The API client * @param customerCreationData - The data for the customer */ constructor(apiClient: ApiClient, customerCreationData: CustomerCreationData) { // Set the API Client this.apiClient = apiClient; // Initialize the System Defined Properties this.Id = null!; this.SyncToken = null!; this.FullyQualifiedName = null!; this.Level = null!; // Build the Required Properties this.DisplayName = customerCreationData?.DisplayName ?? null!; this.Title = customerCreationData?.Title ?? null!; this.GivenName = customerCreationData?.GivenName ?? null!; this.MiddleName = customerCreationData?.MiddleName ?? null!; this.Suffix = customerCreationData?.Suffix ?? null!; this.FamilyName = customerCreationData?.FamilyName ?? null!; } /** * @description Set the API Client * @param apiClient - The API client */ public setApiClient(apiClient: ApiClient) { this.apiClient = apiClient; } /** * @description Reload the Customer Data * @throws {QuickbooksError} If the Customer was not found */ public async reload() { // Get the Customer by ID const customer = await this.apiClient.customers.getCustomerById(this.Id); // Check if the Customer was not Found if (!customer) throw new QuickbooksError('Customer not found', await ApiClient.getIntuitErrorDetails(null)); // Assign the Properties Object.assign(this, customer); } /** * @description Custom JSON serialization to exclude private properties */ private toJSON() { // Setup the Excluded Properties const excludedProperties = ['apiClient']; // Setup the JSON Object const jsonData = { ...Object.fromEntries(Object.entries(this).filter(([key]) => !excludedProperties.includes(key))) }; // Return the JSON Object return jsonData; } /** * @description Updates or creates (if the Id is not set) the Customer */ public async save() { // Get the Customer URL const url = await this.apiClient.customers.getUrl(); // Setup the Request Data const requestData: RequestInit = { method: 'POST', body: JSON.stringify({ ...this.toJSON(), sparse: true }), }; // Update the Customer const { responseData } = await this.apiClient.runRequest(url.href, requestData); // Extract the Customer from the response (QuickBooks returns { Customer: {...} } or wrapped format) const customerData = responseData?.Customer?.[0] || responseData?.Customer || responseData; // Assign the Properties Object.assign(this, customerData); } /** * @description Deletes (deactivates) the Customer by setting Active=false * @throws {QuickbooksError} If the Customer ID is not set or the delete fails */ public async delete() { // Check if the Customer has an ID if (!this.Id) throw new QuickbooksError('Customer must be saved before deleting', await ApiClient.getIntuitErrorDetails(null)); // Set Active to false for soft delete this.Active = false; // Save the Customer with Active=false await this.save(); } } // Setup the Creation Data export type CustomerCreationData = { DisplayName: string; Title: string; GivenName: string; MiddleName: string; Suffix: string; FamilyName: string; };