import {z} from 'zod' export type DocumentJSONPatchReplaceVoided = {op: 'replace', path: '/voided', value: boolean}; export type DocumentReconciliationStatus = 'OPEN' | 'MATCHED' | 'RECONCILED' | 'IGNORED'; export type DocumentJSONPatchReplaceReconciliationStatus = {op: 'replace', path: '/reconciliationStatus', value: DocumentReconciliationStatus}; export type CurrencyCode = string; export type AmountIntegerValueInput = {currency: CurrencyCode, value: number}; export type AmountStringValueInput = {currency: CurrencyCode, stringValue: string}; export type AmountInput = AmountIntegerValueInput | AmountStringValueInput; export type MultiCurrencyAmountInput = {baseAmount: AmountInput, instructedAmount: AmountInput}; export type DocumentJSONPatchReplaceRemainingAmount = {op: 'replace', path: '/remainingAmount', value: MultiCurrencyAmountInput}; export type DocumentJSONPatchRemoveRemainingAmount = {op: 'remove', path: '/remainingAmount'}; export type DocumentJSONPatchReplaceDescription = {op: 'replace', path: '/description', value: string}; export type DocumentJSONPatchReplaceReference = {op: 'replace', path: '/reference', value: string}; export type DocumentJSONPatchReplaceReferences = {op: 'replace', path: '/references', value: {[key: string]: string}}; export type Date = string; export type DocumentJSONPatchReplaceDate = {op: 'replace', path: '/date', value: Date}; export type DocumentJSONPatchReplaceIssueDate = {op: 'replace', path: '/issueDate', value: Date}; export type CounterpartyType = 'VENDOR' | 'CUSTOMER' | 'EMPLOYEE' | 'GL_ENTITY'; export type AccountingCounterparty = {name: string, type: CounterpartyType, erpId: string}; export type DocumentJSONPatchReplaceCounterparty = {op: 'replace', path: '/counterparty', value: AccountingCounterparty}; export type ResourceID = string; export type GLEntryAmountInput = {baseAmount: AmountInput, instructedAmount?: AmountInput | undefined}; export type GLEntryType = 'DEBIT' | 'CREDIT'; export type CreateGLEntryRequest = {vendorId: string, glAccountId: string, vendorBankAccountId?: ResourceID | undefined, glClassificationIds?: Array | undefined, amount: GLEntryAmountInput, type: GLEntryType}; export type DocumentJSONPatchReplaceGlEntries = {op: 'replace', path: '/glEntries', value: Array}; export type DocumentType = 'JOURNAL_ENTRY' | 'PAYMENT' | 'CREDIT_MEMO' | 'INVOICE' | 'PURCHASE_ORDER' | 'TRANSFER' | 'EXPENSE_REPORT'; export type CreateAppliedDocumentRequest = {amount: AmountInput, targetDocumentId?: string | undefined, targetDocumentType: DocumentType, targetDocumentExternalId: string, date?: Date | undefined}; export type DocumentJSONPatchReplaceAppliedDocuments = {op: 'replace', path: '/appliedDocuments', value: Array}; export type DocumentJSONPatchReplaceReconciliationMatchId = {op: 'replace', path: '/reconciliationMatchId', value: string}; export type DocumentJSONPatchRemoveReconciliationMatchId = {op: 'remove', path: '/reconciliationMatchId'}; export type DocumentJSONPatchReplaceAmount = {op: 'replace', path: '/amount', value: MultiCurrencyAmountInput}; export type CurrencyExchange = {exchangeRate: string, sourceCurrency: CurrencyCode, targetCurrency?: CurrencyCode | undefined, unitCurrency?: CurrencyCode | undefined}; export type DocumentJSONPatchReplaceCurrencyExchange = {op: 'replace', path: '/currencyExchange', value: CurrencyExchange}; export type DocumentJSONPatchRequest = Array; export type PatchApiAccountingV2betaDocumentsIdArgs = {id: string, 'If-Match'?: string | undefined, body: DocumentJSONPatchRequest}; export type PatchApiAccountingV2betaDocumentsIdOptions = {baseUrl?: string | undefined, basicAuth?: {username: string, password: string} | undefined, fetch?: typeof fetch | undefined}; export const resourceID = z.string().min(32).max(64); export const organizationID = z.string(); export const documentType = z.enum(["JOURNAL_ENTRY", "PAYMENT", "CREDIT_MEMO", "INVOICE", "PURCHASE_ORDER", "TRANSFER", "EXPENSE_REPORT"]); export const documentClassification = z.enum(["SOURCE", "INSTRUCTION"]); export const currencyCode = z.string().min(3).max(3); export const amount = z.object({currency: currencyCode, stringValue: z.string(), value: z.number().int()}); export const multiCurrencyAmount = z.object({baseAmount: amount, instructedAmount: amount}); export const date = z.string(); export const documentInvoiceDetails = z.object({settledDate: date.optional(), daysToDue: z.number().int().optional(), daysToSettled: z.number().int().optional(), settlementDaysPastDue: z.number().int().optional()}); export const counterpartyType = z.enum(["VENDOR", "CUSTOMER", "EMPLOYEE", "GL_ENTITY"]); export const accountingCounterparty = z.object({name: z.string(), type: counterpartyType, erpId: z.string()}); export const documentReconciliationStatus = z.enum(["OPEN", "MATCHED", "RECONCILED", "IGNORED"]); export const gLEntryAmount = z.object({baseAmount: amount, instructedAmount: amount.optional()}); export const gLEntryType = z.enum(["DEBIT", "CREDIT"]); export const gLEntry = z.object({id: resourceID, vendorId: z.string(), glAccountId: resourceID, vendorBankAccountId: resourceID.optional(), glClassificationIds: z.array(resourceID).optional(), amount: gLEntryAmount, type: gLEntryType}); export const appliedDocument = z.object({amount: amount, targetDocumentId: resourceID.optional(), targetDocumentType: documentType, targetDocumentExternalId: z.string(), date: date.optional()}); export const documentProvenanceResourceType = z.enum(["FILE", "API"]); export const contentType = z.enum(["application/vnd.iso20022.pain.001.001.03+xml", "application/vnd.iso20022.pain.001.001.03.ch.02+xml", "application/vnd.iso20022.pain.001.001.09+xml", "application/vnd.iso20022.pain.001.001.09.ch.03+xml", "application/vnd.iso20022.pain.002.001.03+xml", "application/vnd.iso20022.pain.002.001.10+xml", "application/vnd.iso20022.pain.008.001.02+xml", "application/vnd.iso20022.pain.008.001.02.ch.03+xml", "application/vnd.iso20022.pain.008.001.03+xml", "application/vnd.iso20022.pain.008.001.08+xml", "application/vnd.iso20022.camt.052.001.02+xml", "application/vnd.iso20022.camt.052.001.03+xml", "application/vnd.iso20022.camt.052.001.04+xml", "application/vnd.iso20022.camt.052.001.08+xml", "application/vnd.iso20022.camt.053.001.02+xml", "application/vnd.iso20022.camt.053.001.03+xml", "application/vnd.iso20022.camt.053.001.04+xml", "application/vnd.iso20022.camt.053.001.08+xml", "application/vnd.iso20022.camt.053.001.10+xml", "application/vnd.iso20022.camt.053.001.11+xml", "application/vnd.iso20022.camt.053.001.12+xml", "application/vnd.iso20022.camt.054.001.02+xml", "application/vnd.iso20022.pacs.002.001.10+xml", "application/vnd.iso20022.pacs.008.001.02+xml", "application/vnd.iso20022.pacs.008.001.08+xml", "application/vnd.swift.mt.101", "application/vnd.swift.mt.103", "application/vnd.swift.mt.900", "application/vnd.swift.mt.940", "application/vnd.swift.mt.942", "application/vnd.bai.bai2", "application/vnd.bgc.autogiro.payee", "application/vnd.bgc.autogiro.payments.rejected", "application/vnd.bgc.autogiro.payments.spec", "application/vnd.bgc.autogiro.mandate", "application/vnd.bgc.payins.bgmax", "application/vnd.nacha.ach", "application/vnd.atlar.testbank.mandate+json", "application/vnd.atlar.testbank.transaction+json", "application/vnd.atlar.connectivity.proprietary", "application/vnd.atlar.connectivity.proprietary+json", "application/vnd.atlar.connectivity.proprietary+xml", "application/vnd.atlar.connectivity.proprietary+csv", "application/vnd.atlar.connectivity.v2.investment-statement+json", "application/vnd.atlar.connectivity.v2.accounting-statement+json", "application/vnd.atlar.connectivity.v2.fx-rate-statement+json", "application/vnd.atlar.connectivity.v2.benchmark-rate-statement+json", "application/vnd.atlar.connectivity.v2.instrument-product-statement+json", "application/vnd.atlar.connectivity.v2.statement+json", "application/vnd.atlar.connectivity.v2.statement+csv", "application/vnd.deutsche.wealth-online+csv", "application/vnd.m2.m006.m001+xml", "application/vnd.m2.m006.m005+xml", "application/vnd.ebics.htd.v30+xml", "application/vnd.ebics.hac.v25+xml", "application/vnd.ebics.hac.v30+xml", "application/vnd.jpm.daily-feed+zip", "application/vnd.jpm.morgan-money.balance-report+csv", "application/vnd.jpm.morgan-money.transaction-report+csv", "application/vnd.jpm.soci.holdings+csv", "application/vnd.jpm.soci.transactions+csv", "application/vnd.jpm.soci.cash-balance+csv", "application/vnd.nordea.investments.abasec.pos+csv", "application/vnd.nordea.investments.abasec.tra+csv", "application/vnd.blackrock.cachematrix.balance+csv", "application/vnd.blackrock.cachematrix.transactions+csv", "application/vnd.adyen.balance-platform.statement-report+csv", "application/vnd.ms-excel", "application/x-ofx", "application/json", "application/zip", "application/pdf", "text/plain", "text/csv", "application/vnd.edi.820", "application/vnd.edi.824", "application/vnd.edi.997"]); export const documentProvenance = z.object({vendorId: z.string(), vendorTimestamp: z.string(), resource: z.discriminatedUnion("type", [z.object({type: documentProvenanceResourceType, name: z.string(), contentType: contentType, timestamp: z.string()}), z.object({type: documentProvenanceResourceType, url: z.string(), contentType: contentType, timestamp: z.string()})])}); export const currencyExchange = z.object({exchangeRate: z.string(), sourceCurrency: currencyCode, targetCurrency: currencyCode.optional(), unitCurrency: currencyCode.optional()}); export const resourceVersion = z.number().int().gte(1); export const eTag = z.string(); export const createdTimestamp = z.string(); export const updatedTimestamp = z.string(); export const document = z.object({id: resourceID, organizationId: organizationID, glEntityId: z.string(), type: documentType, classification: documentClassification, amount: multiCurrencyAmount, remainingAmount: multiCurrencyAmount.optional(), date: date, issueDate: date, invoiceDetails: documentInvoiceDetails.optional(), description: z.string().min(1).max(255), reference: z.string().min(1).max(255).optional(), references: z.record(z.string(), z.string()), counterparty: accountingCounterparty.optional(), voided: z.boolean(), reconciliationStatus: documentReconciliationStatus, reconciliationMatchId: resourceID.optional(), outgoingDocumentId: resourceID.optional(), glEntries: z.array(gLEntry), appliedDocuments: z.array(appliedDocument).optional(), provenance: documentProvenance, vendorCreated: z.string(), vendorResourceUrl: z.string().optional(), currencyExchange: currencyExchange.optional(), version: resourceVersion, etag: eTag, created: createdTimestamp, updated: updatedTimestamp}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Update document * * PATCH /accounting/v2beta/documents/{id} */ export const patchApiAccountingV2betaDocumentsId = async (args: PatchApiAccountingV2betaDocumentsIdArgs, options?: PatchApiAccountingV2betaDocumentsIdOptions) => { const {baseUrl = "https://api.atlar.com", fetch: fetchFn = fetch, basicAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json-patch+json") headers.set('accept', "application/json") if (args['If-Match'] != null) headers.set("If-Match", String(args['If-Match'])) if (basicAuth !== undefined) headers.set('authorization', `Basic ${btoa(`${basicAuth.username}:${basicAuth.password}`)}`) const url = `${baseUrl.replace(/\/+$/, '')}/accounting/v2beta/documents/${encodeURIComponent(String(args.id))}${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "PATCH", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(document, await res.json()) };