feat(efectivo): the EFE cash receipt book, folio and posting in one step
Build and Push Images / Build jorgecuadros-web (push) Successful in 1m47s
Build and Push Images / Build jorgecuadros-api (push) Successful in 2m17s

The office still issues cash receipts from Access (EFE MENU -> EFE). This is
that form: cliente, fecha, monto + moneda, concepto, elaboró (the logged-in
user), fecha de depósito, and a folio that continues the legacy book.

- cash_receipts, folio unique. Next folio = one past the highest of the
  platform's receipts and the imported utilities EFECTIVO journal, so after
  the cutover import it lands on the office's next number (13935 on prod
  today). A typed folio the legacy book already used is refused.
- Issuing a receipt posts its credit in the same database transaction, as
  legacy posted to DATOS2: reference C<folio>, CASH DEPOSIT, pseudo check
  CASH<MMDD><P|D>. Dollars with a rate credit a pesos ledger (1,500 USD at
  16.80 -> 25,200 MXN, as C13830 did). Voiding that row voids the receipt.
- /efectivo: issue, search, record the deposit date; /efectivo/<folio>
  prints the receipt.
- Reporte de efectivo now lists platform receipts by receipt, not by check,
  so each is counted once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rmancinasandClaude Opus 5.5 committed 2026-10-12 19:24:43 -07:00
1 parent fd5df240bc
commit ca76f4d57a
14 files changed
+959 -3

No files matched your search

+35
View File
@@ -131,6 +131,7 @@ model Customer {
statementDocuments StatementDocument[]
statementSplits StatementDocumentSplit[]
cashReceipts CashReceipt[]
policyOcrDocuments PolicyOcrDocument[] @relation("PolicyOcrDocumentCustomer")
emailNotificationLogs EmailNotificationLog[]
@@ -884,6 +885,7 @@ model Transaction {
/// Set only on OCR-posted rows — the statement page this came from.
statementDocument StatementDocument?
statementSplit StatementDocumentSplit? @relation("StatementDocumentSplitTransaction")
cashReceipt CashReceipt?
policyOcrDocument PolicyOcrDocument? @relation("PolicyOcrDocumentTransaction")
@@unique([legacySourceDb, legacySourceTable, legacyId])
@@ -1005,6 +1007,7 @@ model User {
statementBatches StatementBatch[] @relation("StatementBatchUploader")
statementsReviewed StatementDocument[] @relation("StatementDocumentReviewer")
cashReceipts CashReceipt[] @relation("CashReceiptPreparer")
policyOcrBatches PolicyOcrBatch[] @relation("PolicyOcrBatchUploader")
policyOcrReviewed PolicyOcrDocument[] @relation("PolicyOcrDocumentReviewer")
@@ -1287,3 +1290,35 @@ model AppSetting {
@@map("app_settings")
}
/// The EFE cash receipt book (legacy EFE form / EFECTIVO table): the paper the
/// office hands a customer who pays in cash. A journal, not a ledger — the
/// money reaches the customer's balance through `transaction`, posted with it
/// as `C<folio>` exactly as legacy posted to DATOS2. Voiding that row voids
/// the receipt.
model CashReceipt {
id String @id @default(uuid())
/// Printed receipt number. Continues the legacy book's sequence.
folio Int @unique
customerId String
customer Customer @relation(fields: [customerId], references: [id])
receivedAt DateTime
amount Decimal @db.Decimal(12, 2)
currency Currency
/// Set when dollars are credited to a pesos ledger, as legacy did; the
/// posted row then carries amount × rate in MXN.
exchangeRate Decimal? @db.Decimal(10, 4)
concept String @db.Text
/// ELABORÓ — whoever was logged in.
preparedById String
preparedBy User @relation("CashReceiptPreparer", fields: [preparedById], references: [id])
/// FECHA DEPÓSITO — filled in when the cash reaches the bank.
depositedAt DateTime?
transactionId String @unique
transaction Transaction @relation(fields: [transactionId], references: [id])
createdAt DateTime @default(now())
@@index([customerId])
@@index([receivedAt])
@@map("cash_receipts")
}