import { Amount } from '../../commonStateTypes/amount'; import { ID } from '../../commonStateTypes/common'; import { ScheduleDaysOfMonth } from '../../commonStateTypes/timePeriod'; import { ZeniDate } from '../../zeniDayJS'; import { ZeniUrl as Url } from '../../zeniUrl'; import { TransactionID } from '../transaction/stateTypes/transactionID'; import { JEOneTimeAccrualKey, JEScheduleKey, JEScheduleTransactionKey, JournalEntryErrorCodeType, OneTimeAccrualAutomationTierType, OneTimeAccrualOriginType, OneTimeAccrualReversalPolicyType, OneTimeAccrualReversalTriggerType, OneTimeAccrualStatusCodeType, ScheduleJournalEntryStatusCodeType, ScheduleStatusCodeType, ScheduleTypes } from './jeSchedulesTypes'; export interface ScheduleStatus { code: ScheduleStatusCodeType; label: string; } export interface ScheduleJournalStatusCode { code: ScheduleJournalEntryStatusCodeType; label: string; } export interface JEScheduleFieldRecommendation { confidence: number; /** @deprecated prefer cot */ reasoning: string; cot?: string[]; } /** * The agent's summary of the whole recommendation, as opposed to one field of it. * * `confidence` is mapped but not yet produced: the schedule's own `confidence_score` column arrives * null on every agent-written schedule, and agent-je's ScheduleSummary currently carries narrative * only. Whichever of the two the backend starts populating, the UI picks it up without a change * here -- and until one of them does, the popover shows no confidence rather than a made-up one. */ export interface JEScheduleSummary { confidence?: number; cot?: string[]; reasoning?: string; reasoningLong?: string; } export interface JEScheduleAISummaries { creditAccount?: JEScheduleFieldRecommendation; creditClass?: JEScheduleFieldRecommendation; debitAccount?: JEScheduleFieldRecommendation; debitClass?: JEScheduleFieldRecommendation; endDate?: JEScheduleFieldRecommendation; period?: JEScheduleFieldRecommendation; postingDate?: JEScheduleFieldRecommendation; postingStartDate?: JEScheduleFieldRecommendation; scheduleSummary?: JEScheduleSummary; scheduleType?: JEScheduleFieldRecommendation; startingMonth?: JEScheduleFieldRecommendation; } export interface JEScheduleRecommendations { creditAccountConfidence?: number; creditClassConfidence?: number; debitAccountConfidence?: number; debitClassConfidence?: number; endDate?: string; jeCreditAccountId?: string; jeCreditAccountingClassId?: string; jeDebitAccountId?: string; jeDebitAccountingClassId?: string; jeScheduleType?: string; jeScheduleTypeConfidence?: number; period?: number; periodConfidence?: number; postingDate?: string; postingDateConfidence?: number; similarTransactions?: unknown[]; startDate?: string; startingMonth?: string; startingMonthConfidence?: number; } export interface JEScheduleOtherAttributes { assetId?: string; startingBalance?: Amount; } export interface ScheduledJournalEntryState { error: JournalEntryErrorCodeType[]; expectedPostDate: ZeniDate; memo: string; scheduledJournalEntryID: ID; status: ScheduleJournalStatusCode; actualPostDate?: ZeniDate; actualReversalPostDate?: ZeniDate; amount?: Amount; createTime?: ZeniDate; currencyCode?: string; currencySymbol?: string; isPlatformGenerated?: boolean; jeScheduleId?: ID; recommendedTransactionID?: TransactionID; reversalThirdPartyID?: ID; reversalTransactionDetails?: TransactionID; reversalTransactionID?: ID; runningBalance?: Amount; syncToken?: string; thirdPartyID?: ID; transactionID?: ID; updateTime?: ZeniDate; } export interface JEScheduledTransactionState { baseTransaction: JEScheduleTransactionKey; currencyCode: string; currencySymbol: string; jeCredit: { accountId?: ID; accountingClassId?: ID; }; jeDebit: { accountId?: ID; accountingClassId?: ID; }; otherAttributes: JEScheduleOtherAttributes; scheduledJournalEntry: ScheduledJournalEntryState[]; status: ScheduleStatus; vendorId: ID; aiSummaries?: JEScheduleAISummaries; balanceAsOfToday?: number; confidenceScore?: number; createdByUserID?: ID; createTime?: ZeniDate; dayOfPostingDate?: ScheduleDaysOfMonth; endDate?: ZeniDate; jeScheduleId?: ID; jeScheduleType?: ScheduleTypes; lastDayOfMonth?: boolean; period?: number; postedCount?: number; recommendations?: JEScheduleRecommendations; recurringAmount?: Amount; startDate?: ZeniDate; updatedAt?: ZeniDate; updatedByUserID?: ID; } export interface JEAccruedScheduledTransactionState extends Omit { createTime: ZeniDate; jeScheduleId: ID; memo: string; recurringAmount: Amount; } /** * What a human can change on a draft accrual before posting it. * * Deliberately not the whole accrual: posting date is derived server-side from the service month, * and vendor / service month are identity -- agent-je rejects a promote whose body disagrees with * the stored draft on either. */ export interface OneTimeAccrualEdits { expectedReversalDate?: ZeniDate; jeCreditAccountId?: ID; /** * Carried beside the id, not derived from it later: the accrual document stores the name too, so * an id sent without its name leaves the row displaying the account the user just moved away * from. */ jeCreditAccountName?: string; jeDebitAccountId?: ID; jeDebitAccountingClassId?: ID; jeDebitAccountingClassName?: string; jeDebitAccountName?: string; memo?: string; /** * The Auto Reversal toggle, modelled as the same boolean the New form and the create payload use * rather than a policy string: `reverse_next_month` alone decides the policy server-side, and * sending both would be two sources of truth for one control. */ reverseNextMonth?: boolean; } export interface JEOneTimeAccrualCreator { userId: ID; email?: string; firstName?: string; lastName?: string; photo?: Url; } /** * One month of a vendor's billed history, taken from profile_snapshot. Kept as an ordered array * rather than the payload's map because the months are not contiguous — a vendor that skipped a * month has no entry — so consumers must not derive the sequence themselves. */ export interface JEOneTimeAccrualMonthlyTotal { amount: Amount; month: string; } export interface JEOneTimeAccrualBillingPattern { avgAmount?: Amount; billingLagDays?: number; consistencyScore?: number; frequency?: string; lastBillAmount?: Amount; lastBillDate?: ZeniDate; monthsOfHistory?: number; typicalBillDay?: number; } /** * The vendor profile the AI used to decide this accrual. Absent on human-created accruals, so every * card built from it has to be omitted rather than rendered empty. */ export interface JEOneTimeAccrualProfileSnapshot { monthlyTotals: JEOneTimeAccrualMonthlyTotal[]; billingPattern?: JEOneTimeAccrualBillingPattern; } /** What the AI originally suggested, frozen at draft time. */ export interface JEOneTimeAccrualAiSuggestion { estimatedAmount?: Amount; jeCreditAccountName?: string; jeDebitAccountName?: string; memo?: string; } export interface JEOneTimeAccrualState { accrualId: ID; accrualStatus: OneTimeAccrualStatusCodeType; estimatedAmount: Amount; /** * Ignoring an accrual sets this flag and leaves the status on `draft`, so the status alone cannot * tell an ignored row from an actionable one. */ isIgnored: boolean; memo: string; origin: OneTimeAccrualOriginType; reversalPolicy: OneTimeAccrualReversalPolicyType; serviceMonth: string; vendorId: ID; vendorName: string; actualPostDate?: ZeniDate; actualReversalPostDate?: ZeniDate; aiSuggestion?: JEOneTimeAccrualAiSuggestion; automationTier?: OneTimeAccrualAutomationTierType; createdBy?: JEOneTimeAccrualCreator; expectedReversalDate?: ZeniDate; jeCreditAccountId?: ID; jeCreditAccountingClassId?: ID; jeCreditAccountingClassName?: string; jeCreditAccountName?: string; jeDebitAccountId?: ID; jeDebitAccountingClassId?: ID; jeDebitAccountingClassName?: string; jeDebitAccountName?: string; postingDate?: ZeniDate; profileSnapshot?: JEOneTimeAccrualProfileSnapshot; reversalTransactionId?: ID; reversalTrigger?: OneTimeAccrualReversalTriggerType; transactionId?: ID; transactionIntegrationId?: ID; } export interface JESchedulesState { oneTimeAccrualsByKey: Record; schedulesByAccruedJEScheduleKey: Record; schedulesByTransactionKey: Record; }