import {z} from 'zod' export type OfferId = number; export type StoreCount = number; export type CouponDiscountCode = string; export type CouponOfferCode = unknown; export type BillingPeriodInMonth = number; export type OfferRequest = {offerId: OfferId, storeCount: StoreCount, couponDiscountCode?: CouponDiscountCode | undefined, couponOfferCode?: CouponOfferCode | undefined, billingPeriodInMonth: BillingPeriodInMonth}; export type CreateApiV2UserCustomerOffersArgs = {body: OfferRequest}; export type CreateApiV2UserCustomerOffersOptions = {baseUrl?: string | undefined, fetch?: typeof fetch | undefined}; export const previousFixPeriodInvoiceProrataInfo = z.object({computedProrataToBeDeducted: z.number().optional(), invoiceNumber: z.string().optional(), amountToBePaid: z.number().optional(), amountAfterTax: z.number().optional(), contractId: z.string().optional(), fixedPeriodEndDate: z.string().optional(), fixedPeriodStartDate: z.string().optional()}); export const billingPeriodInMonth = z.number().int().gte(1); export const contractBillingPeriodInfo = z.object({amountBillingPeriodDiscount: z.number().optional(), billingPeriodPercentDiscount: z.number().optional(), billingPeriodInMonth: billingPeriodInMonth.optional()}); export const contractClickInfo = z.object({additionalClickPrice: z.number().optional(), clickIncluded: z.number().int().optional(), initialOfferClickIncluded: z.number().int().optional()}); export const offerId = z.number().int().gte(1); export const paymentMethod = z.enum(["Transfer", "Debit", "Paypal", "Check", "CreditNote", "Loss", "OnlinePayment"]); export const clickIncludedAndAdditionalClickPrice = z.object({clickIncluded: z.number().int().optional(), additionalClickPrice: z.number().optional()}); export const fixedAndVariableClickModelInfo = z.object({clickIncludedAndAdditionalClickPrices: z.array(clickIncludedAndAdditionalClickPrice)}); export const clickIncludedAndVariablePrice = z.object({clickIncluded: z.number().int().optional(), variablePrice: z.number().optional()}); export const variableModelInfo = z.object({clickIncludedAndVariablePrices: z.array(clickIncludedAndVariablePrice), overflowClickCount: z.number().int(), overflowClickPrice: z.number()}); export const couponOfferCode = z.string(); export const contractCommitmentInfo = z.object({commitmentCalculatedFinishDate: z.string().optional(), newContractStartDate: z.string().optional(), commitmentPeriodInMonth: z.number().int().optional(), trialPeriodInMonth: z.number().int().optional(), trialPeriodFinishDate: z.string().optional(), paymentDelayInDays: z.number().int().optional(), offerId: offerId.optional(), offerName: z.string().optional(), currentContractId: z.string().optional(), commercialUserId: z.string().optional(), model: z.string().optional(), currentContractTerminationDate: z.string().optional(), requestedPaymentMethod: paymentMethod.optional(), currentCustomerPaymentMethod: paymentMethod.optional(), contractType: z.number().int().optional(), isModelMustBeTransmittedInNewContract: z.boolean().optional(), fixedAndVariableClickInfo: fixedAndVariableClickModelInfo.optional(), variableModelInfo: variableModelInfo.optional(), paymentMethodAuthorized: paymentMethod.optional(), couponOfferCode: couponOfferCode.optional(), commercialCreatorUserId: z.string().optional(), minBillingPeriodInMonths: z.number().int().optional(), isCustomerWantsToTerminateHisContract: z.boolean().optional()}); export const promotionalCodeValidity = z.enum(["None", "Valid", "Invalid", "ExpiredOrInactive"]); export const contractDiscountInfo = z.object({amountCodePromoDiscountPerMonth: z.number().optional(), discountDurationInMonth: z.number().int().optional(), percentDiscount: z.number().optional(), promotionalCodeValidity: promotionalCodeValidity.optional(), amountCodePromoDiscount: z.number().optional(), couponDiscountCode: z.string().optional(), couponDiscountId: z.number().int().optional(), isCouponDiscountLinkedToCouponOffer: z.boolean().optional(), customerHasActualDiscount: z.boolean().optional()}); export const beezUPCommonCurrencyCode = z.string(); export const contractMoneyInfo = z.object({amountExcludingTaxesAndExcludingCodePromoDiscountIncludingBillingPeriodDiscount: z.number().optional(), amountExcludingTaxesIncludingDiscounts: z.number().optional(), amountTaxesExcludingDiscountIncludingBillingPeriodDiscount: z.number().optional(), amountIncludingTaxesExcludingDiscountIncludingBillingPeriodDiscount: z.number().optional(), currencyCode: beezUPCommonCurrencyCode.optional(), vatPercent: z.number().optional(), amountExcludingTaxesIncludingDiscountsPerMonth: z.number().optional(), amountExcludingTaxesAndExcludingDiscounts: z.number().optional(), amountTaxesIncludingDiscounts: z.number().optional(), amountIncludingTaxesIncludingDiscounts: z.number().optional(), initialOfferFixedPrice: z.number().optional()}); export const storeCount = z.number().int().gte(1); export const contractStoreInfo = z.object({storeCount: storeCount.optional(), maxStoreCount: z.number().int().optional(), minStoreCount: z.number().int().optional(), ownedStoreCount: z.number().int().optional(), additionalStorePrice: z.number().optional(), storeIncluded: z.number().int().optional()}); export const bonusType = z.enum(["OnlinePaymentMethodBonus", "PreviousInvoiceProrataBonus", "PreviousContractBonus"]); export const bonusInfo = z.object({bonusType: bonusType, amount: z.number()}); export const contractBonusInfo = z.object({bonuses: z.array(bonusInfo)}); export const contractTerminationReasonType = z.number().int(); export const contractTerminationReason = z.string(); export const offerContent = z.object({previousFixPeriodInvoiceProrataInfo: previousFixPeriodInvoiceProrataInfo, contractBillingPeriodInfo: contractBillingPeriodInfo, contractClickInfo: contractClickInfo, contractCommitmentInfo: contractCommitmentInfo, contractDiscountInfo: contractDiscountInfo, contractMoneyInfo: contractMoneyInfo, contractStoreInfo: contractStoreInfo, contractBonusInfo: contractBonusInfo, contractTerminationReasonType: contractTerminationReasonType.optional(), contractTerminationReason: contractTerminationReason.optional(), notifyVatExemption: z.boolean()}); export const beezUPCommonSuccessSummary = z.object({successCode: z.string().optional(), successMessage: z.string().optional(), successArguments: z.record(z.string(), z.string()).optional(), propertyName: z.string().optional(), propertyValue: z.string().optional(), objectName: z.string().optional()}); export const beezUPCommonExceptionDetail = z.object({helpLink: z.string().optional(), message: z.string().optional(), stackTrace: z.string().optional(), type: z.string().optional()}); export const beezUPCommonErrorSummary = z.object({utcDate: z.string().optional(), errorGuid: z.string().optional(), errorCode: z.string().optional(), errorMessage: z.string().optional(), technicalErrorMessage: z.string().optional(), exceptionDetail: beezUPCommonExceptionDetail.optional(), errorArguments: z.record(z.string(), z.string()).optional(), propertyName: z.string().optional(), propertyValue: z.string().optional(), objectName: z.string().optional(), source: z.string().optional()}); export const beezUPCommonWarningSummary = z.object({technicalErrorMessage: z.string().optional(), warningMessage: z.string().optional(), warningCode: z.string().optional(), warningArguments: z.record(z.string(), z.string()).optional()}); export const beezUPCommonInfoSummary = z.object({informationCode: z.string().optional(), informationMessage: z.string().optional(), informationArguments: z.record(z.string(), z.string()).optional(), propertyName: z.string().optional(), propertyValue: z.string().optional(), objectName: z.string().optional()}); export const beezUPCommonInfoSummaries = z.object({successes: z.array(beezUPCommonSuccessSummary).optional(), errors: z.array(beezUPCommonErrorSummary).optional(), warnings: z.array(beezUPCommonWarningSummary).optional(), informations: z.array(beezUPCommonInfoSummary).optional()}); export const beezUPCommonDocUrl = z.string(); export const beezUPCommonHref = z.string(); export const beezUPCommonOperationId = z.string(); export const beezUPCommonHttpMethod = z.enum(["GET", "POST", "PATCH", "DELETE", "PUT", "HEAD"]); export const beezUPCommonParameterIn = z.enum(["path", "header", "query", "body"]); export const beezUPCommonParameterType = z.enum(["string", "integer", "number", "boolean", "object", "array", "date", "date-time"]); export const beezUPCommonLOVLink3 = z.object({href: z.string(), method: beezUPCommonHttpMethod.optional()}); export const beezUPCommonLinkParameterProperty3 = z.object({label: z.string().optional(), value: z.object({}).optional(), required: z.boolean().optional(), type: beezUPCommonParameterType, lovLink: beezUPCommonLOVLink3.optional(), lovRequired: z.boolean().optional(), description: z.string().optional(), schema: z.string().optional()}); export const beezUPCommonLinkParameter3 = z.object({label: z.string().optional(), value: z.object({}).optional(), required: z.boolean().optional(), in: beezUPCommonParameterIn, type: beezUPCommonParameterType.optional(), lovLink: beezUPCommonLOVLink3.optional(), lovRequired: z.boolean().optional(), description: z.string().optional(), schema: z.string().optional(), properties: z.record(z.string(), beezUPCommonLinkParameterProperty3).optional()}); export const linksCreateContractLink = z.object({label: z.string().optional(), docUrl: beezUPCommonDocUrl.optional(), description: z.string().optional(), href: beezUPCommonHref, operationId: beezUPCommonOperationId.optional(), method: beezUPCommonHttpMethod.optional(), parameters: z.record(z.string(), beezUPCommonLinkParameter3).optional(), urlTemplated: z.boolean().optional(), allRequiredParamsProvided: z.boolean().optional(), allOptionalParamsProvided: z.boolean().optional(), info: beezUPCommonInfoSummaries.optional()}); export const offerLinks = z.object({createContract: linksCreateContractLink.optional()}); export const offer = z.object({content: offerContent.optional(), info: beezUPCommonInfoSummaries.optional(), links: offerLinks.optional()}); 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 }; /** * Get offer pricing * * POST /v2/user/customer/offers */ export const createApiV2UserCustomerOffers = async (args: CreateApiV2UserCustomerOffersArgs, options?: CreateApiV2UserCustomerOffersOptions) => { const {baseUrl = "https://api.beezup.com", fetch: fetchFn = fetch} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") const url = `${baseUrl.replace(/\/+$/, '')}/v2/user/customer/offers${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", 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(offer, await res.json()) };