import {z} from 'zod' export type GetApiFinanceV1FoliosIdArgs = {id: string, expand?: Array<'folios'> | undefined}; export type GetApiFinanceV1FoliosIdOptions = {baseUrl: string, oauth2?: string | undefined, fetch?: typeof fetch | undefined}; export const nonStrictAddressModel = z.object({addressLine1: z.string().nullable().optional(), addressLine2: z.string().nullable().optional(), postalCode: z.string().nullable().optional(), city: z.string().nullable().optional(), regionCode: z.string().nullable().optional(), countryCode: z.string().nullable().optional()}); export const invoiceNetworkIdentityModel = z.object({network: z.literal("Peppol"), id: z.string().min(1)}); export const companyInfoModel = z.object({name: z.string().min(1), taxId: z.string().nullable().optional(), additionalTaxId: z.string().nullable().optional(), additionalTaxId2: z.string().nullable().optional(), invoiceNetworkIdentity: invoiceNetworkIdentityModel.optional()}); export const folioDebitorModel = z.object({type: z.enum(["Booker", "PrimaryGuest", "Company", "AdditionalGuest", "Property"]).nullable().optional(), title: z.enum(["Mr", "Ms", "Dr", "Prof", "Mrs", "Other"]).nullable().optional(), firstName: z.string().nullable().optional(), name: z.string().nullable().optional(), address: nonStrictAddressModel.optional(), company: companyInfoModel.optional(), personalTaxId: z.string().nullable().optional(), reference: z.string().max(400).nullable().optional(), email: z.string().nullable().optional(), phone: z.string().nullable().optional()}); export const embeddedReservationModel = z.object({id: z.string(), bookingId: z.string()}); export const embeddedCompanyModel = z.object({id: z.string(), code: z.string().nullable().optional(), name: z.string().nullable().optional(), canCheckOutOnAr: z.boolean().nullable().optional()}); export const embeddedPropertyModel = z.object({id: z.string(), code: z.string().nullable().optional(), name: z.string().nullable().optional(), description: z.string().nullable().optional()}); export const embeddedFolioModel = z.object({id: z.string(), debitor: z.string().nullable().optional()}); export const amountModel = z.object({grossAmount: z.number(), netAmount: z.number(), vatType: z.enum(["Null", "VeryReduced", "Reduced", "Normal", "Without", "Special", "Special1", "Special2", "ReducedCovid19", "NormalCovid19", "Mixed"]), vatPercent: z.number(), currency: z.string()}); export const chargeModel = z.object({id: z.string(), serviceType: z.enum(["Other", "Accommodation", "FoodAndBeverages", "CancellationFees", "NoShow", "CityTax", "SecondCityTax", "LocalTax", "ConsumptionTax"]), name: z.string().min(1), translatedNames: z.record(z.string(), z.string().nullable()).nullable().optional(), isPosted: z.boolean(), serviceDate: z.string(), created: z.string(), movedFrom: embeddedFolioModel.optional(), movedTo: embeddedFolioModel.optional(), movedReason: z.string().nullable().optional(), routedFrom: embeddedFolioModel.optional(), routedTo: embeddedFolioModel.optional(), amount: amountModel, receipt: z.string().nullable().optional(), groupId: z.string().nullable().optional(), subAccountId: z.string().nullable().optional(), quantity: z.number().int(), type: z.enum(["Direct", "TimeSlice", "IncludedService", "ExtraService", "CityTax", "NoShowFee", "CancellationFee", "ServiceFee", "Tax", "SecondCityTax", "GuestLevy"])}); export const monetaryValueModel = z.object({amount: z.number(), currency: z.string()}); export const transitoryChargeModel = z.object({id: z.string(), name: z.string().min(1), amount: monetaryValueModel, serviceType: z.enum(["Other", "Accommodation", "FoodAndBeverages", "CancellationFees", "NoShow", "CityTax", "SecondCityTax", "LocalTax", "ConsumptionTax"]).nullable().optional(), serviceDate: z.string(), created: z.string(), receipt: z.string().nullable().optional(), movedFrom: embeddedFolioModel.optional(), movedTo: embeddedFolioModel.optional(), movedReason: z.string().nullable().optional(), quantity: z.number().int()}); export const externalReference = z.object({merchantReference: z.string().min(1), pspReference: z.string().min(1)}); export const paymentModel = z.object({id: z.string(), method: z.enum(["Cash", "BankTransfer", "CreditCard", "Invoice", "Amex", "VisaCredit", "VisaDebit", "MasterCard", "MasterCardDebit", "Maestro", "GiroCard", "DiscoverCard", "Diners", "Jcb", "BookingCom", "VPay", "PayPal", "Postcard", "Reka", "Twint", "Lunchcheck", "Voucher", "ChinaUnionPay", "Other", "Cheque", "Airbnb", "HolidayCheck", "PspCash", "PspDebit", "PspBanking", "PspOpenInvoice", "PspWallet", "Representation", "IDeal"]), amount: monetaryValueModel, externalReference: externalReference.optional(), receipt: z.string().nullable().optional(), paymentDate: z.string().optional(), movedFrom: embeddedFolioModel.optional(), movedTo: embeddedFolioModel.optional(), movedReason: z.string().nullable().optional(), sourcePaymentId: z.string().nullable().optional(), depositEntryId: z.string().nullable().optional(), businessDate: z.string()}); export const pendingPaymentModel = z.object({id: z.string(), amount: monetaryValueModel, terminalId: z.string().nullable().optional()}); export const allowanceModel = z.object({id: z.string(), amount: amountModel, reason: z.string().min(1), serviceType: z.enum(["Other", "Accommodation", "FoodAndBeverages", "CancellationFees", "NoShow", "CityTax", "SecondCityTax", "LocalTax", "ConsumptionTax"]), serviceDate: z.string(), created: z.string(), movedFrom: embeddedFolioModel.optional(), movedTo: embeddedFolioModel.optional(), movedReason: z.string().nullable().optional(), sourceChargeId: z.string().nullable().optional(), subAccountId: z.string().nullable().optional()}); export const embeddedInvoiceModel = z.object({id: z.string()}); export const folioModel = z.object({id: z.string(), created: z.string(), updated: z.string(), type: z.enum(["House", "Guest", "External", "Booking"]).optional(), debitor: folioDebitorModel.optional(), closingDate: z.string().nullable().optional(), reservation: embeddedReservationModel.optional(), bookingId: z.string().nullable().optional(), company: embeddedCompanyModel.optional(), property: embeddedPropertyModel, charges: z.array(chargeModel).nullable().optional(), transitoryCharges: z.array(transitoryChargeModel).nullable().optional(), payments: z.array(paymentModel).nullable().optional(), pendingPayments: z.array(pendingPaymentModel).nullable().optional(), allowances: z.array(allowanceModel).nullable().optional(), balance: monetaryValueModel, checkedOutOnAccountsReceivable: z.boolean().optional(), isMainFolio: z.boolean().optional(), isEmpty: z.boolean().optional(), relatedFolios: z.array(embeddedFolioModel).nullable().optional(), relatedInvoices: z.array(embeddedInvoiceModel).nullable().optional(), folioWarnings: z.array(z.enum(["IncompleteBillingAddress", "IncompleteBillingDetails", "DepositNotInvoiced"])).nullable().optional(), allowedActions: z.array(z.enum(["AddCharge", "AddDepositItem", "AddAllowance", "AddCancellationFee", "AddNoShowFee", "AddPayment", "AddRefund", "CheckoutOnAr", "Close", "PostOpenCharges", "CorrectFolio", "ChangeAddress", "ChangeAddressWithSimpleDebitor", "Delete", "Reopen", "CreateInvoice", "CreateAdvanceInvoice", "CancelLastInvoice", "CreateInvoiceWithSimpleDebitor", "CreatePrepaymentNotice", "CreateProFormaInvoice", "CreateDepositReceipt", "PreviewInvoice", "CreateDepositInvoice"])).nullable().optional(), allowedPayment: z.number().optional(), maximumAllowance: z.number().optional(), status: z.enum(["Open", "Closed", "ClosedWithInvoice"])}); 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 }; /** * Returns one folio. * * GET /finance/v1/folios/{id} */ export const getApiFinanceV1FoliosId = async (args: GetApiFinanceV1FoliosIdArgs, options: GetApiFinanceV1FoliosIdOptions) => { const {baseUrl, fetch: fetchFn = fetch, oauth2} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") for (const item of args.expand ?? []) query.append("expand", String(item)) if (oauth2 !== undefined) headers.set('authorization', `Bearer ${oauth2}`) const url = `${baseUrl.replace(/\/+$/, '')}/finance/v1/folios/${encodeURIComponent(String(args.id))}${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(folioModel, await res.json()) };