import { ID } from '../../commonStateTypes/common'; import { ZeniAPIResponse } from '../../responsePayload'; import { CardPolicyStats, CardPolicyTemplate, CardPolicyTemplateEntityList, CardPolicyTemplateMode, CardPolicyTemplateSpendLimits, ExtractedCardPolicyRules, MccCategory } from './cardPolicyState'; export interface MccCategoryPayload { count: number; mcc_codes: string[]; name: string; } /** * Wire shape for `GET /cards/1.0/cards/mcc-codes`. Beyond the universe of * MCC categories used to populate the category search dropdown, the * endpoint also ships **suggested** allow / block merchants and categories * that the chip-pickers seed into their cloud body before the user starts * editing. * * Field spellings (`*_catagories`) preserve the BE wire format verbatim; * the camelCase mapper below corrects to `Categories`. */ export interface CardPolicyMccCategoriesPayload { categories: MccCategoryPayload[]; suggested_allow_catagories?: MccCategoryPayload[]; suggested_allow_merchants?: string[]; suggested_block_catagories?: MccCategoryPayload[]; suggested_block_merchants?: string[]; } export type CardPolicyMccCategoriesResponse = ZeniAPIResponse; export declare const toMccCategory: (payload: MccCategoryPayload) => MccCategory; /** * Vendor row returned by `/accounting/1.0/vendors`. The card-policy * vendor search dropdown only needs `vendor_id` + `vendor_name`; we * deliberately ignore the rest of the payload to keep this slice * independent of the heavy `vendor` entity store. */ export interface CardPolicyVendorSearchVendorPayload { vendor_id: string; vendor_name: string; } export interface CardPolicyVendorSearchData { vendors: CardPolicyVendorSearchVendorPayload[]; } export type CardPolicyVendorSearchResponse = ZeniAPIResponse; export interface CardPolicyVendorSearchOption { name: string; vendorId: string; } export declare const toCardPolicyVendorSearchOption: (payload: CardPolicyVendorSearchVendorPayload) => CardPolicyVendorSearchOption; interface CardPolicyTemplateEntityListPayload { category_codes: string[]; merchant_names: string[]; } interface CardPolicyTemplateSpendLimitsPayload { transaction: number | null; } /** * Per-template request shape. `POST /cards/1.0/policy-templates` now * accepts a bulk wrapper (`CreateCardPolicyTemplatesRequest`); this * interface describes a single entry inside the `templates` array. * * `PUT /cards/1.0/policy-templates/{id}` (update) still consumes this * shape directly — see `UpdateCardPolicyTemplateRequest` below. */ export interface CreateCardPolicyTemplateRequest { allowedEntity: CardPolicyTemplateEntityList; applyToCards: ID[]; blockedEntity: CardPolicyTemplateEntityList; description: string; mode: CardPolicyTemplateMode; name: string; /** * `null` indicates the require-receipt toggle is off (no threshold * configured). The BE accepts `null` and treats it as "no requirement"; * `0` means the user explicitly entered zero with the toggle on. */ requiredReceiptThreshold: number | null; spendLimits: CardPolicyTemplateSpendLimits; } export interface CreateCardPolicyTemplateRequestBody { allowed_entity: CardPolicyTemplateEntityListPayload; apply_to_cards: ID[]; blocked_entity: CardPolicyTemplateEntityListPayload; description: string; mode: string; name: string; required_receipt_threshold: number | null; spend_limits: CardPolicyTemplateSpendLimitsPayload; } /** * Bulk request for `POST /cards/1.0/policy-templates`. The single-policy * create flow wraps its one request in a length-1 `templates` array; * future multi-policy submit (AI CFO review step) sends N entries in a * single round-trip. * * `sourceChatSessionId` ties the submit back to an AI CFO chat session so * the BE can attribute the created templates to it. Manual create-page * callers omit it. */ export interface CreateCardPolicyTemplatesRequest { templates: CreateCardPolicyTemplateRequest[]; sourceChatSessionId?: string; } export interface CreateCardPolicyTemplatesRequestBody { templates: CreateCardPolicyTemplateRequestBody[]; source_chat_session_id?: string; } export interface CardPolicyTemplatePayload { allowed_entity: CardPolicyTemplateEntityListPayload; applied_cards: ID[]; blocked_entity: CardPolicyTemplateEntityListPayload; cards_count: number; category_restrictions: unknown[]; created_at: string; created_by: ID; description: string; mode: string; name: string; required_receipt_threshold: number | null; spend_limits: CardPolicyTemplateSpendLimitsPayload; status: string; template_id: ID; tenant_id: ID; updated_at: string; } /** * Per-template response envelope. Still returned by `PUT /policy-templates/{id}`, * `GET /policy-templates/{id}`, and (as the row payload) the list endpoint. * Also nested inside `CreateCardPolicyTemplatesResponseData.templates_created`. */ export interface CreateCardPolicyTemplateResponseData { cards_applied: number; template: CardPolicyTemplatePayload; } export type CreateCardPolicyTemplateResponse = ZeniAPIResponse; /** * Per-item error returned by the bulk POST when one or more templates in * the request fail validation / persistence. The exact field shape is * **TBD** with the BE — `message` is the only guaranteed field today; the * rest are best-effort placeholders that callers should not assume to be * present. * * TODO: lock down the shape (`index`, `name`, `code`) once the BE * documents it. See plan §"Open question to resolve with BE". */ export interface BulkCreateCardPolicyTemplateErrorPayload { message: string; code?: string; index?: number; name?: string; } /** * Wire shape returned by the bulk `POST /cards/1.0/policy-templates`. * Partial success is allowed — `templates_created` holds the successfully * created rows (each in the same envelope as the single endpoint), and * `errors` holds per-item failures for the rest. `status.message` follows * the "N of M templates created" convention. */ export interface CreateCardPolicyTemplatesResponseData { errors: BulkCreateCardPolicyTemplateErrorPayload[]; templates_created: CreateCardPolicyTemplateResponseData[]; } export type CreateCardPolicyTemplatesResponse = ZeniAPIResponse; /** * Camel-cased mirror of `BulkCreateCardPolicyTemplateErrorPayload` stored * on the create-card-policy view slice so the UI can render a partial-success * banner without re-touching the wire types. */ export interface BulkCreateCardPolicyTemplateError { message: string; code?: string; index?: number; name?: string; } export type UpdateCardPolicyTemplateRequest = CreateCardPolicyTemplateRequest; export type UpdateCardPolicyTemplateRequestBody = CreateCardPolicyTemplateRequestBody; export type UpdateCardPolicyTemplateResponseData = CreateCardPolicyTemplateResponseData; export type UpdateCardPolicyTemplateResponse = CreateCardPolicyTemplateResponse; export type CardPolicyDetailResponseData = CreateCardPolicyTemplateResponseData; export type CardPolicyDetailResponse = CreateCardPolicyTemplateResponse; /** * Aggregate counters returned alongside the templates list. Stored on * the entity slice (alongside `cardPolicyTemplateById`) so any list * surface can read it without re-fetching. */ export interface CardPolicyStatsPayload { active_policies: number; total_cards: number; total_templates: number; } /** * Each list row is wrapped in the same `{cards_applied, template}` * envelope the create endpoint returns. Only the `template` portion is * stored on the entity slice; `cards_applied` is a one-shot summary * carried over from create and not surfaced in the list state today. */ export interface CardPolicyListRowPayload { data: CreateCardPolicyTemplateResponseData; } export interface ListCardPolicyTemplatesResponseData { stats: CardPolicyStatsPayload; templates: CardPolicyListRowPayload[]; } export type ListCardPolicyTemplatesResponse = ZeniAPIResponse; export declare const toCardPolicyStats: (payload: CardPolicyStatsPayload) => CardPolicyStats; export declare const toCardPolicyTemplateList: (data: ListCardPolicyTemplatesResponseData) => CardPolicyTemplate[]; export declare const toCardPolicyTemplate: (payload: CardPolicyTemplatePayload) => CardPolicyTemplate; /** * Re-shape a single camelCase create request into the snake_case wire * body. Used by the bulk-create mapper to build each entry of the * `templates` array, and directly by the update epic (PUT) since the * update endpoint still consumes a single object. */ export declare const toCreateCardPolicyTemplateRequestBody: (request: CreateCardPolicyTemplateRequest) => CreateCardPolicyTemplateRequestBody; /** * Re-shape a bulk create request into the snake_case wire body for * `POST /cards/1.0/policy-templates`. Maps each entry through * `toCreateCardPolicyTemplateRequestBody` and only emits * `source_chat_session_id` when the camelCase counterpart is defined, * so manual-create callers don't ship a stray `undefined` over the wire. */ export declare const toCreateCardPolicyTemplatesRequestBody: (request: CreateCardPolicyTemplatesRequest) => CreateCardPolicyTemplatesRequestBody; /** * Map a single bulk-response error payload to its camelCased view shape. * Defensive against missing optional fields (see `BulkCreateCardPolicyTemplateErrorPayload` * docstring — the BE contract isn't fully locked yet). */ export declare const toBulkCreateCardPolicyTemplateError: (payload: BulkCreateCardPolicyTemplateErrorPayload) => BulkCreateCardPolicyTemplateError; export declare const toUpdateCardPolicyTemplateRequestBody: (request: CreateCardPolicyTemplateRequest) => CreateCardPolicyTemplateRequestBody; /** * Seed an edit-form draft (`CreateCardPolicyTemplateRequest`) from an * existing camelCased `CardPolicyTemplate`. Used by the detail-fetch * epic so the edit page can render with the saved values pre-populated. */ export declare const toCardPolicyEditFormDraft: (template: CardPolicyTemplate) => CreateCardPolicyTemplateRequest; /** * Wire shape returned by `POST /cards/1.0/policy-documents/extract`. * The backend OCRs / parses an uploaded policy document (PDF, image, etc.) * and returns a best-effort set of policy rules + a confidence score. * * Consumers (manual `CardPolicyCreatePage` + AI CFO `CardPolicyInteractiveForm`) * use `toExtractedCardPolicyRules` to map this onto the camelCase FE shape * and then feed the result through `applyExtractedPolicyRulesToFormValues` * (`@zeniai/web-components`) to seed the RHF form. */ export interface ExtractedCardPolicyRulesPayload { allowed_entity: CardPolicyTemplateEntityListPayload; blocked_entity: CardPolicyTemplateEntityListPayload; confidence_score: number; policy_name: string; required_receipt_threshold: number; transaction_limit: number; } export interface PolicyDocumentExtractResponseData { extracted_rules: ExtractedCardPolicyRulesPayload; message: string; } export type PolicyDocumentExtractResponse = ZeniAPIResponse; export declare const toExtractedCardPolicyRules: (payload: ExtractedCardPolicyRulesPayload) => ExtractedCardPolicyRules; /** * Wire shape returned by `POST /cards/1.0/ai-cfo/policy-recommendation-from-upload`. * Chained after `extractPolicyDocument` succeeds in the AI CFO `upload` * flow: the FE forwards the just-returned `extracted_rules` and the BE * synthesizes a wizard plan + upload source metadata. * * The response mirrors the same `mode`-discriminated envelope the * controller API ships for `auto` / `guided`, but always with `mode: * "upload"` and a populated `wizard_plan.step_5_review`. The FE merges * the returned `wizard_plan` + `source` into the in-flight AI CFO * answer's `CardPolicyInitialData` via * `updateAiCfoAnswerCardPolicyWizardPlan`. */ export interface CardPolicyRecommendationFromUploadResponseData { mode: 'upload'; source: import('../aiCfo/aiCfoPayload').CardPolicyUploadSourcePayload; tenant_id: string; wizard_plan: import('../aiCfo/aiCfoPayload').CardPolicyWizardPlanPayload; } export type CardPolicyRecommendationFromUploadResponse = ZeniAPIResponse; export {};