Commit Graph

84 Commits

Author SHA1 Message Date
kevin-asprec
5276f3bbf4 docs(05): capture phase context
Phase 05: Visibility and Client Portal
- Implementation decisions documented
- Phase boundary established

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 17:01:38 +08:00
kevin-asprec
517454b329 docs(04): complete Inventory, Expenses, and Financial Reports phase
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 15:57:57 +08:00
kevin-asprec
0316bb211f fix(04-05): add missing financial-report-service.ts to git
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 15:13:26 +08:00
kevin-asprec
df3e36b7a2 docs(04-04): complete Expense Reports and Audit Trail plan
Tasks completed: 2/2
- ExpenseReportService and AuditTrailService with API routes
- 9 passing integration tests

SUMMARY: .planning/phases/04-inventory-expenses-and-financial-reports/04-04-SUMMARY.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 15:11:49 +08:00
kevin-asprec
787b22e6a1 test(04-04): expense report and audit trail tests -- 9 passing
- Expense by category: correct totals, excludes DRAFT/VOIDED
- Expense by vendor: correct totals, No Vendor bucket
- Expense summary: combined view with grand total
- Date range filtering works
- JE audit trail: createdBy, source, referenceType for expense JE
- Audit trail for entity: original + void reversal entries
- Cross-source audit: Payment JE referenceType correctly returned

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 14:52:44 +08:00
kevin-asprec
6bc24a3fb4 feat(04-04): ExpenseReportService, AuditTrailService, and API routes
- ExpenseReportService: getExpensesByCategory, getExpensesByVendor, getExpenseSummary
- AuditTrailService: getJournalEntryAudit, getAuditTrailForEntity (ACCT-08)
- GET /api/reports/expenses -- expense summary by category
- GET /api/reports/expenses/by-vendor -- expense summary by vendor
- GET /api/accounting/journal-entries/[id]/audit -- JE audit trail

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 14:44:13 +08:00
kevin-asprec
e3a177f194 docs(04-02): complete asset management plan — Phase 4 complete
Tasks completed: 2/2
- AssetService with assign, return, dispose, history
- 11 integration tests all passing

SUMMARY: .planning/phases/04-inventory-expenses-and-financial-reports/04-02-SUMMARY.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 14:34:09 +08:00
kevin-asprec
0f733627bd test(04-02): asset service tests — 11 cases covering full lifecycle
- Assign to subscriber/technician creates correct ISSUED movements
- Return from subscriber/technician creates RETURNED with condition
- Rejects reassignment without return, rejects batch items
- Admin disposal creates write-off JE (DR 5030, CR 1200)
- Non-admin disposal rejected, field disposal rejected
- History returns chronological timeline with resolved names
- Full lifecycle: RECEIVED->ISSUED->RETURNED->ISSUED->RETURNED->DISPOSED

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 13:59:51 +08:00
kevin-asprec
eb29d6e3be feat(04-02): AssetService with assign, return, dispose, and history APIs
- AssetService: assignToSubscriber, assignToTechnician, returnAsset, disposeAsset, getAssetHistory
- getCurrentLocation helper derives location from latest movement
- Disposal validates ADMIN role and creates write-off JE (DR 5030, CR 1200)
- API routes: POST assign, POST return, POST dispose, GET history
- Location history resolves subscriber/technician/warehouse names

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 13:20:10 +08:00
kevin-asprec
6dd1fe827c docs(04-05): complete financial reports plan
Tasks completed: 2/2
- Financial report API routes (trial balance, income statement, balance sheet, drill-down)
- Comprehensive tests (16 passing — all 3 reports verified)

SUMMARY: .planning/phases/04-inventory-expenses-and-financial-reports/04-05-SUMMARY.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 13:00:04 +08:00
kevin-asprec
1dd423ca43 test(04-05): comprehensive financial report tests — 16 passing, all 3 reports verified
- Trial Balance: debits = credits (isBalanced), per-account balances, asOfDate filter
- Income Statement: revenue/expense sections, net income = 600, header exclusion, date range
- Balance Sheet: A = L + E (isBalanced), cash = 600, net income in equity, date filter
- Drill-down: running balance, entry metadata (entryNumber, referenceType)
- Edge cases: empty tenant balanced, leaf-only accounts across all reports

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 12:35:50 +08:00
kevin-asprec
5366e8c1ad feat(04-05): financial report API routes — trial balance, income statement, balance sheet, drill-down
- GET /api/reports/trial-balance with optional asOfDate filter
- GET /api/reports/income-statement with required startDate/endDate
- GET /api/reports/balance-sheet with required asOfDate
- GET /api/reports/accounts/[id]/entries drill-down with optional date range
- All routes use withPermission("read", "Report") for ADMIN access
- FinancialReportService already existed with all 4 methods

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 12:31:33 +08:00
kevin-asprec
cc8314f854 docs(04-03): complete expense tracking plan
Tasks completed: 2/2
- Task 1: Schema + COA additions + expense category seeding
- Task 2: VendorService, ExpenseService, API routes, migration, 15 tests

SUMMARY: .planning/phases/04-inventory-expenses-and-financial-reports/04-03-SUMMARY.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 10:53:50 +08:00
kevin-asprec
b7bbc50b2b feat(04-03): VendorService, ExpenseService, API routes, migration, and 15 passing tests
- VendorService: CRUD with unique name validation per tenant
- ExpenseService: create, approve, post, void with full JE integration
- Auto-generated EXP-NNNN expense numbers per tenant
- JE posting: DR category expense account, CR cash (1010) or bank (1020)
- Optional approval workflow: requireApproval flag controls DRAFT-only vs immediate post
- Void reverses JE via JournalEntryService.reverseEntry
- Custom category creation with COA account validation
- System categories protected from deletion
- API routes: expenses CRUD, approve, categories CRUD, vendors CRUD
- Migration: add_expense_vendor_models applied via db push + resolve
- 15 integration tests covering all expense lifecycle scenarios

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 10:52:07 +08:00
kevin-asprec
fe4d22f440 feat(04-03): Vendor, ExpenseCategory, Expense schema + category seeding + COA additions
- Add ExpenseStatus and ExpensePaymentMethod enums
- Add Vendor model (@@unique([tenantId, name]))
- Add ExpenseCategory model with accountCode linking to COA
- Add Expense model with approval workflow and JE reference
- Add User relations: createdExpenses, approvedExpenses
- Add COA accounts 5080 Fuel/Transportation, 5085 Rent Expense (31 total)
- Seed 9 default expense categories in createTenant transaction
- Add Vendor subject to CASL types, Expense/Vendor permissions for OFFICE_STAFF

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 10:38:03 +08:00
kevin-asprec
daf5bddf0b docs(04-01): complete inventory event-ledger plan
Tasks completed: 2/2
- Task 1: Schema — InventoryItem, StockMovement models and enums
- Task 2: InventoryService, API routes, migration, and tests (13 passing)

SUMMARY: .planning/phases/04-inventory-expenses-and-financial-reports/04-01-SUMMARY.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 10:33:18 +08:00
kevin-asprec
a742f701e7 feat(04-01): InventoryService, API routes, migration, and 13 passing tests
- InventoryService: registerItem, recordMovement, getStockLevels, getItemMovements, listItems
- RECEIVED movements auto-post JE (DR 1200 Equipment Inventory, CR 2010 AP)
- Stock levels derived from movement aggregation (no mutable quantity column)
- All 5 movement types validated with type-specific rules
- API routes: POST/GET items, GET item detail, POST/GET movements, GET stock-levels
- CASL: OFFICE_STAFF gets manage Inventory permission
- Migration applied: add_inventory_models (4 enums, 2 tables)
- 13 tests: registration, all movement types, stock derivation, JE posting, history

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 10:31:44 +08:00
kevin-asprec
3712600c4e feat(04-01): InventoryItem and StockMovement schema with enums
- Add ItemTrackingType (SERIALIZED/BATCH), ItemCondition, MovementType, LocationType enums
- Add InventoryItem model with dual tracking (serialized by serial number, batch by quantity)
- Add StockMovement model as immutable movement ledger (no updatedAt)
- Add recordedMovements relation on User model
- Indexes on tenantId, itemType, trackingType, inventoryItemId, movementType

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 10:17:28 +08:00
kevin-asprec
b5f2f3946b docs(04): create phase plan — Inventory, Expenses, and Financial Reports
Phase 04: 5 plans in 2 waves
- Wave 1: 04-01 (inventory event-ledger), 04-03 (expense tracking), 04-05 (financial reports) — parallel
- Wave 2: 04-02 (asset management), 04-04 (expense reports + audit trail) — sequential
- Ready for execution

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 10:00:55 +08:00
kevin-asprec
d8bf8d52ac docs(04): capture phase context
Phase 04: Inventory, Expenses, and Financial Reports
- Implementation decisions documented
- Phase boundary established

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 09:50:43 +08:00
kevin-asprec
2fa5cdb9b5 docs(03): complete Operational Modules phase
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 08:44:53 +08:00
kevin-asprec
f49bbf32b5 docs(03-05): complete technician management plan — Phase 3 complete
Tasks completed: 2/2
- Task 1: TechnicianProfile/JobTypeRate schema, migration, tenant scoping
- Task 2: Technician service, compensation service, 6 APIs, 27 integration tests

SUMMARY: .planning/phases/03-operational-modules/03-05-SUMMARY.md
2026-03-05 08:19:11 +08:00
kevin-asprec
fba2ba4bf9 feat(03-05): technician service, compensation service, APIs, and 27 passing tests
- technician-service.ts: createTechnicianProfile, updateTechnicianProfile, getTechnicianProfile, getTechnicianProfileByUserId, listTechnicians
- compensation-service.ts: getCompensationSummary (all 3 models), getTechnicianCompensationDetail (job-by-job)
- 6 API routes: GET/POST /api/technicians, GET/PUT /api/technicians/[id], GET /api/technicians/[id]/compensation, GET/POST /api/job-type-rates, PUT /api/job-type-rates/[id], GET /api/reports/compensation
- Added TechnicianProfile and JobTypeRate to CASL AppSubjects; OFFICE_STAFF read access
- 27 integration tests: all 3 models, missing rate defaults to 0, only COMPLETED count, date range filter, summary+detail reports, cross-tenant isolation — all green
2026-03-05 08:17:03 +08:00
kevin-asprec
230b0ec683 feat(03-05): TechnicianProfile/JobTypeRate schema, migration, tenant scoping
- Added CompensationModel enum (PER_JOB, SALARY, HYBRID)
- Added TechnicianProfile model with userId FK, skills[], zoneId?, compensationModel, monthlySalary?, isActive, @@unique([tenantId,userId])
- Added JobTypeRate model with jobType, rate, isActive, @@unique([tenantId,jobType])
- Added reverse relations: User.technicianProfiles[], Zone.technicianProfiles[]
- Applied migration: 20260305000851_add_technician_profiles
- Added technicianProfile and jobTypeRate to TENANT_SCOPED_MODELS with full 12-operation extension blocks
2026-03-05 08:10:46 +08:00
kevin-asprec
bdd0fda7d2 docs(03-04): complete Job Orders plan
Tasks completed: 2/2
- Task 1: JobOrder schema, migration, and tenant scoping
- Task 2: Job order service, API routes, and integration tests

SUMMARY: .planning/phases/03-operational-modules/03-04-SUMMARY.md
2026-03-05 08:05:50 +08:00
kevin-asprec
86284f1f5b feat(03-04): job order service, API routes, and 17 passing integration tests
- Added checkTicketAutoResolve/checkTicketRevertToOpen to ticket-service.ts
- Created job-order-service.ts: createJobOrder, updateJobOrderStatus, updateJobOrder,
  getJobOrder, listJobOrders, getMyJobOrders with VALID_JO_TRANSITIONS guard map
- PENDING->IN_PROGRESS->COMPLETED(outcomeNotes required)/CANCELLED lifecycle enforced
- OPEN ticket auto-transitions to ASSIGNED on first job order creation
- Auto-resolves ticket when all non-cancelled jobs COMPLETED
- Reverts ticket to OPEN when all jobs CANCELLED
- Created POST /api/tickets/[id]/job-orders, GET/PUT /api/job-orders/[id],
  POST /api/job-orders/[id]/status, GET /api/job-orders (with TECHNICIAN filter)
- 17 integration tests: lifecycle, auto-resolve, revert-to-open, partial completion,
  technician self-service, cross-tenant isolation — all green
2026-03-05 08:04:21 +08:00
kevin-asprec
d59f1d55ea feat(03-04): JobOrder schema, migration, and tenant scoping
- Added JobOrderStatus enum (PENDING, IN_PROGRESS, COMPLETED, CANCELLED)
- Added JobOrder model with ticket FK, assignedTo/createdBy user FKs
- Added orderNumber (JO-NNNN), scheduledDate, timestamps, outcomeNotes
- Added jobOrders reverse relation on Ticket model
- Added assignedJobOrders/createdJobOrders reverse relations on User model
- Applied migration: 20260304235859_add_job_orders
- Added jobOrder to TENANT_SCOPED_MODELS with full 12-operation extension block
2026-03-05 07:59:56 +08:00
kevin-asprec
0373810d9e docs(03-02): complete Collector Collection and Remittance plan
Tasks completed: 2/2
- Task 1: Collection/Remittance schema, 1030 COA, migration, tenant scoping
- Task 2: Collector service, remittance service, report service, APIs, 26 tests

SUMMARY: .planning/phases/03-operational-modules/03-02-SUMMARY.md
2026-03-05 07:56:20 +08:00
kevin-asprec
a72aaa987d feat(03-02): Collector service, remittance service, report service, APIs, and tests
- collector-service.ts: recordCollection (FIFO, zone enforcement, DR 1030/CR 1100 JE),
  voidCollection (reversing JE), getCollectionHistory
- remittance-service.ts: createRemittance, verifyRemittance (DR 1010/CR 1030, variance
  non-blocking), listRemittances
- collection-report-service.ts: getDailyCollectionSummary, getCollectorCollectionDetail
- 6 API routes: POST/GET /collections, GET /collections/[id],
  POST /collections/[id]/void, POST/GET /remittances,
  POST /remittances/[id]/verify, GET /reports/collections
- 26 integration tests: 13 collector (FIFO, zone enforcement, JE verification, void,
  cross-tenant) + 13 remittance (variance, JE accounts, double-verify rejection)
- All 26 tests pass
2026-03-05 07:54:39 +08:00
kevin-asprec
0967fc23fd feat(03-02): Collection/Remittance schema, 1030 COA account, migration, tenant scoping
- Added 1030 Cash in Transit to ISP_CHART_OF_ACCOUNTS (between 1020 and 1100)
- Added CollectionStatus (COMPLETED/VOIDED) and RemittanceStatus (PENDING/VERIFIED) enums
- Added Collection model with FIFO allocations, zone-scoped collector, JE link, void fields
- Added CollectionAllocation model linking collections to invoices
- Added Remittance model with two-party verification, variance field, JE link
- Added reverse relations on User (collections, remittances) and Subscriber (collections)
- Applied migration: add-collections-remittances
- Extended TENANT_SCOPED_MODELS with collection, collectionAllocation, remittance
- Added full 12-operation extension blocks for all three new models
2026-03-05 07:46:21 +08:00
kevin-asprec
570218320c docs(03-03): complete Ticketing System plan
Tasks completed: 2/2
- Task 1: Ticket schema, categories, migration, and tenant scoping
- Task 2: Ticket service, category service, API routes, and 28 integration tests

SUMMARY: .planning/phases/03-operational-modules/03-03-SUMMARY.md
2026-03-05 07:41:39 +08:00
kevin-asprec
74d26d92f0 feat(03-03): Ticket service, category service, API routes, and 28 integration tests
- ticket-category-service.ts: createCategory, updateCategory, listCategories
- ticket-service.ts: createTicket (TKT-NNNN numbering), updateTicket, getTicket, listTickets, transitionTicketStatus (guard map), resolveTicket (idempotent)
- 5 ticket API routes: GET/POST /api/tickets, GET/PUT /api/tickets/[id], POST /api/tickets/[id]/status
- 2 category API routes: GET/POST /api/ticket-categories, PUT /api/ticket-categories/[id]
- 28 integration tests: lifecycle, transitions, deactivated category rejection, idempotent resolve, cross-tenant isolation
2026-03-05 07:40:10 +08:00
kevin-asprec
b0562a0a12 feat(03-03): Ticket schema, categories, migration, and tenant scoping
- Added TicketStatus, TicketPriority, TicketSource enums to schema
- Added TicketCategory model (tenant-scoped, unique per tenant by name)
- Added Ticket model with lifecycle fields (status, priority, source, resolvedAt, closedAt)
- Added reverse relations: Subscriber.tickets, User.createdTickets, TicketCategory.tickets
- Applied migration 20260304233528_add_tickets
- Added ticket and ticketCategory to TENANT_SCOPED_MODELS with full extension blocks
- Seeded 6 default ISP ticket categories in createTenant transaction
2026-03-05 07:36:45 +08:00
kevin-asprec
2321bf2ada docs(03-01): complete zone management plan
Tasks completed: 2/2
- Task 1: Zone schema, migration, and tenant scoping
- Task 2: Zone service, API routes, and integration tests

SUMMARY: .planning/phases/03-operational-modules/03-01-SUMMARY.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 07:32:21 +08:00
kevin-asprec
214df6cd92 feat(03-01): Zone service, API routes, and 25 integration tests
- zone-service.ts: createZone, updateZone, listZones, getZone,
  assignSubscriberToZone, removeSubscriberFromZone, assignCollectorToZone,
  removeCollectorFromZone, getCollectorZones, getCollectorSubscribers
- API routes: GET/POST /api/zones, GET/PUT /api/zones/[id],
  POST/DELETE /api/zones/[id]/subscribers, GET /api/collectors/[id]/subscribers
- 25 integration tests: zone CRUD, subscriber assignment, collector scoping,
  no-zone-assignment security boundary, cross-tenant isolation
- Fix subscriber-service.ts: zone String? -> zoneId FK (deviation Rule 1)
- Fix subscriber API routes: zone -> zoneId (deviation Rule 1)
2026-03-05 07:30:34 +08:00
kevin-asprec
56f5d071c4 feat(03-01): Zone schema, migration, and tenant scoping
- Add Zone model (id, tenantId, name, description, isActive)
- Add ZoneAssignment model (collector-to-zone join table)
- Replace Subscriber.zone String? with Subscriber.zoneId FK to Zone
- Add Zone + ZoneAssignment to TENANT_SCOPED_MODELS with full operation blocks
- Add "Zone" to AppSubjects in types.ts
- Grant OFFICE_STAFF manage Zone, COLLECTOR read Zone in permissions.ts
- Migration 20260305000000_add_zones applied to DB
2026-03-05 07:24:58 +08:00
kevin-asprec
d54b517e2e docs(03): create phase plan
Phase 03: Operational Modules
- 5 plans in 3 waves
- Wave 1: 03-01 (zones), 03-03 (tickets) — parallel
- Wave 2: 03-02 (collector collections), 03-04 (job orders) — parallel
- Wave 3: 03-05 (technician compensation)
- Ready for execution

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 07:11:44 +08:00
kevin-asprec
9af86c54c3 docs(03): research phase domain
Phase 03: Operational Modules
- Standard stack identified (no new dependencies)
- Architecture patterns documented (10 patterns from codebase)
- Pitfalls catalogued (8 pitfalls from direct code inspection)
2026-03-05 06:20:41 +08:00
kevin-asprec
ef0150654b docs(03): create phase plan
Phase 03: Operational Modules
- 5 plans in 3 waves
- Wave 1: 03-01 (zones), 03-03 (tickets) — parallel
- Wave 2: 03-02 (collector collections), 03-04 (job orders) — parallel
- Wave 3: 03-05 (technician compensation) — sequential
- Ready for execution

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 06:05:55 +08:00
kevin-asprec
4b4f7bce3b docs(03): capture phase context
Phase 03: Operational Modules
- Implementation decisions documented
- Phase boundary established
2026-03-05 05:53:44 +08:00
kevin-asprec
e6e09bd0cb docs(02): complete Subscriber and Billing Core phase
Phase 2 verified: 5/5 plans executed, 265 tests passing.
16 requirements marked complete (SUB-01..05, BILL-01..06, ACCT-01..03, ACCT-07, ACCT-09).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 00:09:09 +08:00
kevin-asprec
a821733b28 fix(02-04): set invoice status to SENT on generation
Invoices were created with default DRAFT status, but PaymentService queries
for SENT/PARTIAL/OVERDUE. This broke the generate → pay flow. Now invoices
are immediately SENT with issuedAt timestamp on generation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 00:07:46 +08:00
kevin-asprec
816ac5360f docs(02-05): complete payment system plan — Phase 2 complete
Tasks completed: 2/2
- Task 1: Payment model with FIFO allocation and void
- Task 2: Payment APIs, outstanding report, and 29 passing tests

Phase 2 (Subscriber and Billing Core) complete — 265/265 tests passing
SUMMARY: .planning/phases/02-subscriber-and-billing-core/02-05-SUMMARY.md
2026-03-04 23:54:42 +08:00
kevin-asprec
bbfc9d6fb4 feat(02-05): Payment APIs, outstanding report, and 29 passing tests
- Implement OutstandingReportService.getOutstandingReport() with filtering/pagination
- Add POST/GET /api/payments (record and list payments)
- Add GET /api/payments/[id] (payment detail)
- Add POST /api/payments/[id]/void (void payment)
- Add GET /api/subscribers/[id]/payments (payment history)
- Add GET /api/subscribers/[id]/balance (outstanding balance)
- Add GET /api/reports/outstanding (outstanding report)
- Write 29 comprehensive tests covering full/partial/overpayment,
  FIFO allocation, JE balance, bank vs cash, idempotency, void,
  outstanding report filters, reconciliation, history, tenant isolation
- All 265 tests pass (full regression clean)
2026-03-04 23:52:57 +08:00
kevin-asprec
6b91e67bdc feat(02-05): Payment model with FIFO allocation and void
- Add PaymentMethod (CASH, BANK_TRANSFER) and PaymentStatus (COMPLETED, VOIDED) enums
- Add Payment model with idempotency key, journal entry link, void fields
- Add PaymentAllocation model for FIFO invoice allocation tracking
- Add Payment/PaymentAllocation relations to Subscriber, Invoice, User
- Update TENANT_SCOPED_MODELS with "payment" and "paymentAllocation"
- Add payment/paymentAllocation query extensions in withTenantContext()
- Implement recordPayment() with FIFO allocation, overpayment credit balance
- Implement voidPayment() with reversing journal entries
- Implement getSubscriberPaymentHistory() with pagination
- Run migration: 20260304154606_add_payment_model
2026-03-04 23:47:58 +08:00
kevin-asprec
df4a467a38 docs(02-04): complete billing engine plan
Tasks completed: 2/2
- Task 1: Invoice model + BillingService + InvoiceService + CreditService
- Task 2: Billing API routes + comprehensive tests (38 passing)

SUMMARY: .planning/phases/02-subscriber-and-billing-core/02-04-SUMMARY.md
2026-03-04 23:41:50 +08:00
kevin-asprec
902587683f feat(02-04): billing API routes and comprehensive tests (38 passing)
- Fix shouldBillToday() month-wrapping logic for PREPAID lead days
- POST /api/billing/generate — triggers monthly invoice generation cycle
- GET /api/invoices — paginated list with status/subscriber/date filters
- GET /api/invoices/[id] — invoice detail with lines and subscriber
- POST /api/invoices/[id]/void — void with JE reversal

Test coverage (38 tests):
- computeBillingPeriod pure function
- shouldBillToday: postpaid, prepaid, and month-wrapping edge case
- Invoice number sequencing per tenant/year
- Invoice generation: amounts, InvoiceLine, period dates
- Journal entries: DR AR (1100), CR Revenue (4010), balanced
- Idempotency: duplicate prevention via unique(subscriberId, periodStart)
- Credit auto-application: full, partial, zero credit, JE (DR 1150, CR 1100)
- Billing cycle: active-only, suspended/cancelled excluded, prepaid lead days
- Overdue detection: bulk update of DRAFT/SENT/PARTIAL past due date
- Void: JE reversal, already-voided guard, PAID guard
- getInvoice, listInvoices, status filtering
- Tenant isolation: Tenant B cannot see Tenant A invoices
2026-03-04 23:38:43 +08:00
kevin-asprec
7cb7a9099c feat(02-04): Invoice model, BillingService, InvoiceService, CreditService
- Add InvoiceStatus enum + Invoice + InvoiceLine models to schema
- Add Invoice relation to Subscriber model
- Add invoice/invoiceLine to TENANT_SCOPED_MODELS in prisma-tenant.ts
- Add invoice/invoiceLine tenant-scoped query extensions to withTenantContext()
- Run migration: 20260304152900_add_invoice_model
- Create invoice-service.ts: generateInvoiceNumber, getInvoice, listInvoices,
  updateInvoiceStatus, markOverdueInvoices, voidInvoice (with JE reversal)
- Create credit-service.ts: applyCredit() — DR Subscriber Credits (1150), CR AR (1100)
- Create billing-service.ts: generateInvoiceForSubscriber (idempotent, JE + auto-credit),
  generateMonthlyInvoices (postpaid + prepaid timing with lead days)
2026-03-04 23:32:14 +08:00
kevin-asprec
c60c22b080 docs(02-02): complete JournalEntryService plan
Tasks completed: 2/2
- Task 1: JournalEntry models + JournalEntryService
- Task 2: Journal entry API routes + comprehensive tests

SUMMARY: .planning/phases/02-subscriber-and-billing-core/02-02-SUMMARY.md
2026-03-04 23:25:42 +08:00
kevin-asprec
30ec936b68 feat(02-02): journal entry API routes + comprehensive test suite
- GET/POST /api/accounting/journal-entries (list + create manual entry)
- GET /api/accounting/journal-entries/[id] (single entry with lines)
- POST /api/accounting/journal-entries/[id]/approve (maker-checker approval)
- POST /api/accounting/journal-entries/[id]/reverse (create reversing entry)
- GET /api/accounting/accounts/[id]/balance (derived balance, never stored)
- All routes use closure pattern over withPermission HOF (same as periods/close)
- Add startDate parameter to getAccountBalance for date range queries
- 36 integration tests: balance enforcement, closed period, immutability,
  reversals, maker-checker, entry numbering, account balance derivation,
  trial balance self-verification
- Total test suite: 198 tests all passing
2026-03-04 23:23:11 +08:00