Skip to content

Document Reporting Gap Mining

This mining pass covers the legacy reservation document center, receipt handoff, daily report flows, service records, print/export generation, template registry risks, download access, A4/HTML/PDF requirements, and OSS replacement candidates.

  • Reservation documents and customer-facing downloads.
  • Customer receipts and payment receipt handoff.
  • Customer daily surveys, caregiver daily reports, sub-caregiver reports, and service records.
  • Admin print/export generation, bundled downloads, and scheduled document delivery.
  • Template identifier drift, static PDF/XLSX templates, A4 layout needs, and render engine replacement choices.

Legacy behavior:

  • The customer reservation page builds a short-lived document download token, renders a document list, and opens a tokenized download URL through the customer API. Evidence: source-refs/sanmopia_web/application/controllers/MyReservation.php:352-372, source-refs/sanmopia_web/application/views/mypage/reservation_document.php:38-139, source-refs/sanmopia_web/application/models/User_model.php:461-489, source-refs/sanmopia_web/application/controllers/api/ReservationDocument.php:1-55.
  • The customer document view hardcodes service-type document sets, numeric document IDs, end-date/status visibility, and ?token= URL construction in the view. Evidence: source-refs/sanmopia_web/application/views/mypage/reservation_document.php:38-139.
  • The customer API validates token ownership and delegates PDF generation to an admin-side document interface. Evidence: source-refs/sanmopia_web/application/models/Reservation_model.php:2769-2820, source-refs/sanmopia-admin/application/controllers/SanmoInterface.php:37-51.
  • The customer document list excludes receipt, service record, customer daily survey, and caregiver daily report artifacts. Those are available only through other screens or admin export flows. Evidence: source-refs/sanmopia_web/application/views/mypage/reservation_document.php:38-139, source-refs/sanmopia-admin/application/controllers/DataRoom.php:311-420.
  • The customer receipt screen opens a card gateway receipt URL from payment context instead of serving a stored receipt artifact. Evidence: source-refs/sanmopia_web/application/controllers/MyReservation.php:329-350, source-refs/sanmopia_web/application/views/mypage/reservation_receipt.php:49-128.
  • The customer receipt view decodes payment context, exposes gateway order and transaction identifiers, and builds the KCP provider URL client-side. Evidence: source-refs/sanmopia_web/application/views/mypage/reservation_receipt.php:37-128.
  • Receipt notification behavior was removed from the payment model while document notification behavior remained. Evidence: source-refs/sanmopia_web/application/models/Payment_model.php:131-138.
  • Scheduled service-start and end-notice delivery generates attachments, sends mail, records delivery status, and deletes temporary files. Evidence: source-refs/sanmopia-admin/application/controllers/cli/ReservationDocument.php:1-130, source-refs/sanmopia-admin/application/controllers/cli/ReservationDocument.php:175-227, source-refs/sanmopia-admin/application/controllers/cli/ReservationDocument.php:330-365.

Gaps to migrate:

  • Add ReservationDocumentCatalog as the single policy source for customer-visible documents, admin-only exports, service-type eligibility, and required payment/service-state gates.
  • Add PrintableDocumentAccessGrant with actor, reservation, document kind, format, expiry, revocation, and audit state. A two-hour token alone is not enough for artifact access.
  • Add CustomerReceiptArtifact that can reference an external gateway receipt and optionally persist a rendered receipt fallback. The cash-receipt tax-evidence foundation now exists as CustomerReceiptTaxEvidenceArtifact (d247aba), visibility is backend-owned (e5a1571), printable access handoff exists (04690fa), receipt render data/render-plan binding exists (24c5f40), stored printable artifact binding exists (2c0ce95), legacy KCP cash-receipt backfill command exists (203e179), and the internal import-run HTTP binding exists (c48bbfc). Remaining work is source extractor/runbook execution that feeds the import endpoint from reviewed historical rows while following payment ledger state, not only a gateway URL assembled in a view.
  • Add VoucherSelfPayReceiptArtifact for legacy admin document id 7 / type7.xlsx. Source Spreadsheet_model::excelVoucherPaymentReceipt() fills branch, mother, consume-type split, service-day type, branch stamp, mother signature, reservation number fallback, service/government/self-pay amounts, and deposited date from voucher payment rows. Modern render source must freeze these facts as VoucherReceiptPaymentEvidenceSnapshot and VoucherReceiptRenderSource, not reload live spreadsheet rows.
  • DocumentDeliveryAttempt now has a backend slice for recipient/channel attempt status, retry scheduling, provider message/code/payload response audit, Supabase persistence, and API facade. Remaining delivery gaps are scheduled batch orchestration, bundle-version linkage, provider cleanup policy, and operator resend screens.
  • Customer document access and admin export access should both point at stored artifacts or signed object URLs, not a live cross-service render call.
  • Public document/read models must expose typed document/template keys and signed handoff references only. They must not expose source numeric document IDs, token query parameters, storage object paths, gateway order IDs, transaction IDs, or provider URL construction facts.
  • Service-use contract render worker consumption now exists in backend commit 3cdc86a: queued render_care_team_document_projection messages load a frozen sanmopia_service_use_contract_render_sources row, retry when the source is not ready, render through the printable document handler, and store a versioned artifact. The remaining gap is the producer side: persist CareTeamDocumentProjection/roster revision render sources and access grants before render, without reloading live RESERVATION_MANAGER_LOG_TB, MANAGER_TB, MANAGER_INFO, or SUB_MANAGER, and without transient XLSX/PDF temp files as the artifact record. Evidence: source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:167-376, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:3507-3664, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:4434-4598, source-refs/sanmopia-admin/application/controllers/cli/ReservationDocument.php:19-132, source-refs/sanmopia-admin/application/controllers/cli/ReservationDocument.php:624-688.
  • Backend commit e7972cc records ServiceUseContractEvidenceSnapshotPayload as ServiceUseContractRenderSource rows and adds render-source readiness: waiting_for_required_facts rows make workers retry instead of rendering incomplete artifacts, while ready_for_render rows must have no missing fact codes. Remaining producer-side data must freeze the inputs currently pulled from live reservation/payment/caregiver/asset rows: service-use template year from SERVICE_START_DT; service period/type; mother name, contact, registered/service addresses, masked birth date from voucher resident-number fragments; branch legal/contact fields plus stamp asset reference; mother signature asset reference; deposit/contract date from payment rows; current or previous primary caregiver name/phone from manager-change logs or MANAGER_TB; adjacent voucher/intake document provider count, primary/sub caregiver names, manager personality text, service balance/custom balance, and add-day facts. Evidence: source-refs/sanmopia-admin/application/models/Reservation_model.php:10-48, source-refs/sanmopia-admin/application/models/Reservation_model.php:160-276, source-refs/sanmopia-admin/application/models/Reservation_model.php:408-470, source-refs/sanmopia-admin/application/models/Reservation_model.php:938-963, source-refs/sanmopia-admin/application/models/Payment_model.php:3149-3179, source-refs/sanmopia-admin/application/models/Manager_model.php:2366-2372, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:167-376, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:3507-3664.
  • ServiceUseContractRenderSourceProducer must freeze payment and asset provenance separately from printable cell values. Source scheduled mail chooses service-use contract bundle membership from BEFORE_PAYMENT_DEPOSITED_DT and service type, while the contract footer date reads getPaymentInfoByReservationId() with no "before" argument, so the default source row is payment type 2. Branch stamp comes from mutable BRANCH_TB.STAMP_IMG_URL, can be uploaded/deleted through office-management actions, and is converted to JPEG during render. Mother signature is captured as browser base64 during payment request, overwrites RESERVATION_TB.SIGN_IMG_URL, deletes the previous file, then the renderer dereferences that mutable path. Modern producer targets: ServiceUseContractPaymentEvidenceSnapshot, BranchStampAssetSnapshot, MotherSignatureAssetSnapshot, and ServiceUseContractAssetReferenceSnapshot with storage object version, checksum, source revision, and readiness codes. Evidence: source-refs/sanmopia-admin/application/controllers/cli/ReservationDocument.php:37-108, source-refs/sanmopia-admin/application/controllers/cli/ReservationDocument.php:633-670, source-refs/sanmopia-admin/application/models/Payment_model.php:3149-3179, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:183-225, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:316-332, source-refs/sanmopia-admin/application/models/Branch_model.php:157-166, source-refs/sanmopia-admin/application/models/Branch_model.php:481-504, source-refs/sanmopia-admin/application/models/Branch_model.php:561-575, source-refs/sanmopia-admin/application/controllers/OfficeManagement.php:118-166, source-refs/sanmopia-admin/application/controllers/OfficeManagement.php:270-276, source-refs/sanmopia_web/static/js/reservation_payment.js:40-66, source-refs/sanmopia_web/application/controllers/api/Service.php:869-882, source-refs/sanmopia_web/application/models/Payment_model.php:12-42.
  • Backend commit 1ff144e adds ServiceUseContractEvidenceSnapshotFactReader, ProjectServiceUseContractRenderSourceCommand, and ProjectServiceUseContractRenderSourceHandler. Complete fact sets now project ready render-source rows; incomplete fact sets project waiting_for_required_facts rows with exact missing fact codes. Backend commit 9f16fc1 adds a concrete Supabase fact reader for available service-calendar plan, paid payment, care-team assignment decision, finalized charge snapshot, and finalized charge line facts. Backend commit c7ad654 wires care-team assignment invalidation to project a service-use contract render source before queuing render work, and the fact reader now records an enabled document definition as ContractTemplateEffectiveVersionDecision when its active window covers the service start date. Backend commit aa92fce adds branch-stamp/mother-signature asset readiness facts plus backend-owned document-center download readiness so UI cannot synthesize render request codes or bundle handoff members. Backend commit 92aed4f reads safe redacted resident identity evidence rows and completes identity_evidence only when the snapshot supplies birth date, evidence kind, and redaction profile without raw resident-number fields. Backend commit 544c27f adds the producer foundation that records voucher recipient identity evidence into backend-owned sanmopia_redacted_resident_identity_evidences rows with no raw resident-number storage. Contract commit 7cb680d exposes the document-center projection and makes printable render request codes snapshot-revision aware. Remaining gaps are runtime voucher-intake/API binding for the producer, immutable branch stamp/mother signature asset snapshots with grants/checksums, stored artifact/access grants, backfill, and live render E2E without mutable row reload.
  • Document-center projection exposure is now a typed backend/contract surface, not a browser catalog recipe. Backend aa92fce projects DocumentCenterProjection from the active document catalog plus latest stored artifact facts, including per-item eligibility, artifact metadata, download handoff descriptors, bundle members, missing definition keys, and bundle availability. Backend 695943a binds that projection to authenticated FastAPI route GET /document-center-projections/{reservationBookingId} with camelCase response aliases and Supabase Auth bearer-token enforcement. Contract 7cb680d exposes DocumentCenterCatalogItem, DocumentCenterStoredArtifact, DocumentCenterDownloadHandoffDescriptor, and DocumentCenterBundleDownload so frontend code should consume typed projection rows through Nanostores state and call the described handoff endpoints. Browser code must not compose numeric document ids, token query strings, render request codes, bundle members, missing-artifact status, or service-kind eligibility. Remaining runtime gaps are signed-storage handoff implementation, frontend Nanostores adapter/view-model consumption, and guard/reroute of old live numeric document-id render entrypoints. Evidence: backend-repo/src/sanmopia_modernization/application/document_reporting/features/document_center/project_document_center.py, backend-repo/src/sanmopia_modernization/interfaces/document_center_http.py, backend-repo/src/sanmopia_modernization/interfaces/document_center_http_test.py, contract-repo/packages/ts-client/src/types/document-reporting.ts:806-864.
  • Remaining producer gaps after c7ad654 have concrete legacy sources. Legacy template effective version was selected inside render from SERVICE_START_DT year (>= 2024 used the current type-1 spreadsheet, otherwise type1_old_20240122.xlsx); the modern producer now reads the enabled document definition and active window instead. Mother birth evidence is still rebuilt during render from raw voucher resident-number fragments USER_NUMBER1/USER_NUMBER2, not from a redacted identity evidence snapshot. Branch stamp and mother signature still flow as mutable file paths: branch stamp reads BRANCH_TB.STAMP_IMG_URL, converts that file to JPEG, and office-management upload/delete overwrites or deletes the previous file; mother signature posts browser base64 to the payment request endpoint, writes RESERVATION_TB.SIGN_IMG_URL, and deletes the previous file. Contract access/storage remains token/live-render based: customer UI gets a two-hour USER_TOKEN_TB token, builds a ?token= download URL, calls the admin makePdfDocument interface, decodes base64 PDF bytes, and streams them directly; scheduled mail writes converter output to temp files and deletes attachments after send. Modern producer targets: RedactedMotherIdentityEvidenceSnapshot, BranchStampAssetSnapshot, MotherSignatureAssetSnapshot, StoredPrintableDocumentArtifact, and PrintableDocumentAccessGrant. Evidence: source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:167-179, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:251-260, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:316-332, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:4284-4297, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:4434-4600, source-refs/sanmopia-admin/application/models/Reservation_model.php:938-963, source-refs/sanmopia-admin/application/models/Branch_model.php:157-166, source-refs/sanmopia-admin/application/models/Branch_model.php:481-518, source-refs/sanmopia-admin/application/models/Branch_model.php:561-586, source-refs/sanmopia-admin/application/controllers/OfficeManagement.php:118-166, source-refs/sanmopia-admin/application/controllers/OfficeManagement.php:270-276, source-refs/sanmopia_web/static/js/reservation_payment.js:40-66, source-refs/sanmopia_web/application/controllers/api/Service.php:869-882, source-refs/sanmopia_web/application/models/Payment_model.php:12-42, source-refs/sanmopia_web/application/controllers/MyReservation.php:352-372, source-refs/sanmopia_web/application/views/mypage/reservation_document.php:118-139, source-refs/sanmopia_web/application/models/User_model.php:461-489, source-refs/sanmopia_web/application/controllers/api/ReservationDocument.php:21-55, source-refs/sanmopia_web/application/models/Reservation_model.php:2769-2820, source-refs/sanmopia-admin/application/controllers/SanmoInterface.php:37-51, source-refs/sanmopia-admin/application/controllers/cli/ReservationDocument.php:104-132, source-refs/sanmopia-admin/application/controllers/cli/ReservationDocument.php:200-227, source-refs/sanmopia-admin/application/controllers/cli/ReservationDocument.php:330-365, source-refs/sanmopia-admin/application/controllers/cli/ReservationDocument.php:666-688.
  • Redacted mother identity evidence now has a backend producer foundation. Backend 42f7ed0 records redacted-identity readiness without reloading raw resident-number fragments, backend 92aed4f consumes safe sanmopia_redacted_resident_identity_evidences rows when they exist, and backend 544c27f adds RecordVoucherRecipientIdentityEvidenceHandler plus the Supabase store/migration for service-role-owned evidence rows. Source voucher intake shows raw resident-number fields in the customer form, stores them as USER_NUMBER1 and USER_NUMBER2 in RESERVATION_SERVICE_VOUCHER_TB, and admin reservation creation writes the same raw columns. One extension path explicitly unsets those fields before returning a cloned reservation, proving raw fragments are known sensitive but still available to renderers. The service-use contract renderer reconstructs birth date from the raw fragments at render time. Modern readiness now records identity_readiness from voucher recipient identity decision metadata, and the fact reader fills identity_evidence only from a redacted snapshot that supplies birth_date, evidence_kind, and redaction_profile_key; if the row is missing or incomplete, render source remains waiting_for_required_facts. Runtime follow-up: bind the producer into voucher intake/customer/admin command paths, backfill legacy voucher rows, and reject any render-source producer that reloads USER_NUMBER1, USER_NUMBER2, or resident_identity_digits. document_reporting should own only the frozen redacted snapshot and evidence reference; it must not parse voucher resident-number fragments or expose raw identity fields in render-source rows. Evidence: source-refs/sanmopia_web/application/views/service/step3_voucher.php:70-90, source-refs/sanmopia_web/application/models/Reservation_model.php:488-510, source-refs/sanmopia_web/application/models/Reservation_model.php:2448-2458, source-refs/sanmopia-admin/application/models/Reservation_model.php:5058-5066, source-refs/sanmopia-admin/application/models/Reservation_model.php:938-963, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:251-260, backend-repo/src/sanmopia_modernization/application/document_reporting/features/service_use_contract/service_use_contract_evidence_snapshot_projection.py, backend-repo/src/sanmopia_modernization/adapters/document_reporting/features/service_use_contract/supabase_service_use_contract_evidence_snapshot_fact_reader.py, backend-repo/src/sanmopia_modernization/application/member_management/features/redacted_resident_identity_evidence/record_voucher_recipient_identity_evidence.py, backend-repo/supabase/migrations/20260707150000_redacted_resident_identity_evidences.sql.
  • Branch stamp and mother signature need asset-snapshot producers, not path copying. Legacy upload helpers return relative paths and original names but no checksum, object version, grant id, or immutable artifact row. Admin branch stamp upload/delete updates BRANCH_TB.STAMP_IMG_URL and unlinks the previous file; customer payment signature upload writes a random PNG path into RESERVATION_TB.SIGN_IMG_URL and unlinks the previous signature. The service-use contract renderer reads those current paths and only checks file existence. Implementation recommendation: persist BranchStampAssetSnapshot and MotherSignatureAssetSnapshot with storage bucket/object key, object generation/version, sha256 checksum, byte size, media type, source row revision, actor/source command evidence, access grant reference, and missing/expired readiness codes; renderers should consume snapshots only. Evidence: source-refs/sanmopia-admin/application/libraries/Uploadlib.php:47-90, source-refs/sanmopia-admin/application/libraries/Uploadlib.php:123-170, source-refs/sanmopia_web/application/libraries/Uploadlib.php:40-76, source-refs/sanmopia_web/application/libraries/Uploadlib.php:110-124, source-refs/sanmopia-admin/application/models/Branch_model.php:481-518, source-refs/sanmopia-admin/application/models/Branch_model.php:561-586, source-refs/sanmopia_web/application/models/Payment_model.php:12-42, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:183-207, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:316-332.
  • Stored artifact/access grant needs a runtime seam that rejects live mutable render for service-use contracts. Admin data-room and customer document paths still call numeric document-id renderers; makePdfData() and makePdfDataToSendMail() reload mutable reservation/service/rental rows, write temp XLSX/PDF names from current mother name/reservation id, call the external converter, return base64 or temp path, and scheduled mail deletes attachments after send. Customer access is a two-hour token over USER_TOKEN_TB, not a grant over a persisted artifact. Implementation recommendation: service-use contract render requests should read only ServiceUseContractRenderSource, write StoredPrintableDocumentArtifact with artifact checksum/storage version/source-render-source revision, then issue PrintableDocumentAccessGrant for customer/admin/scheduled-mail surfaces; legacy live-render entrypoints should be guarded or routed to stored artifacts for document id 1. Evidence: source-refs/sanmopia-admin/application/controllers/DataRoom.php:80-96, source-refs/sanmopia-admin/application/controllers/DataRoom.php:311-376, source-refs/sanmopia-admin/application/controllers/ajax/DataRoom.php:66-86, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:3914-3940, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:4284-4423, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:4434-4600, source-refs/sanmopia_web/application/controllers/MyReservation.php:352-372, source-refs/sanmopia_web/application/views/mypage/reservation_document.php:118-139, source-refs/sanmopia_web/application/models/User_model.php:461-489, source-refs/sanmopia_web/application/controllers/api/ReservationDocument.php:21-55, source-refs/sanmopia_web/application/models/Reservation_model.php:2769-2820, source-refs/sanmopia-admin/application/controllers/SanmoInterface.php:37-51, source-refs/sanmopia-admin/application/controllers/cli/ReservationDocument.php:104-132, source-refs/sanmopia-admin/application/controllers/cli/ReservationDocument.php:200-227, source-refs/sanmopia-admin/application/controllers/cli/ReservationDocument.php:330-365, source-refs/sanmopia-admin/application/controllers/cli/ReservationDocument.php:666-688.
  • ServiceUseContractRenderSourceProducer also needs frozen charge and occurrence inputs before render. Legacy price attachment builds additionalServicePriceList, voucher special/live-in add price, rental/delivery totals, discount/coupon effects, user-fee rows, and leftPrice from mutable reservation, price-version, service-day, address, coupon, rental, and additional-service rows. Legacy spreadsheet renderers then read SERVICE_PRICE_LATEST, OWN_PRICE_LATEST, DISCOUNT_GOVERNMENT_PRICE_LATEST, SERVICE_PRICE, PRICE_TABLE['voucherSpecialPrice'], and PRICE_TABLE['additionalServicePriceList'], and adjacent down-payment sheets still recompute Saturday/holiday added-day counts, non-SAT/HOLI add-on multipliers over SERVICE_DAY + addDays, rental delivery hardcodes, voucher surcharge, and first SAT/HOLI display date. Modern producer targets: ChargeComponentRevisionSnapshot and ServiceOccurrenceSet with price version, component revision, occurrence-set revision, selected additional-day source rows, extension/holiday evidence, and readiness codes. Evidence: source-refs/sanmopia-admin/application/models/Reservation_model.php:644-923, source-refs/sanmopia-admin/application/models/Reservation_model.php:4013-4045, source-refs/sanmopia-admin/application/models/Reservation_model.php:4110-4137, source-refs/sanmopia-admin/application/models/Reservation_model.php:4748-4764, source-refs/sanmopia-admin/application/models/Reservation_model.php:4992-5014, source-refs/sanmopia-admin/application/models/Reservation_model.php:5200-5208, source-refs/sanmopia-admin/application/models/Reservation_model.php:5455-5496, source-refs/sanmopia-admin/application/models/Reservation_model.php:5644-5658, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:335-373, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:629-780, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:3570-3607.

Legacy behavior:

  • Customer daily survey forms validate service date, ownership, service range, stop day, and first/middle/last question sets. Evidence: source-refs/sanmopia_web/application/controllers/MyReservation.php:193-258, source-refs/sanmopia_web/application/views/mypage/daily_report.php:1-197.
  • Sub-caregiver customer survey forms are separate but mirror the primary caregiver flow. Evidence: source-refs/sanmopia_web/application/controllers/MyReservation.php:261-326, source-refs/sanmopia_web/application/views/mypage/daily_sub_report.php:1-172.
  • Caregiver daily report forms validate caregiver ownership, notification state, first/progress/last question sets, and save structured answers plus essay text. Evidence: source-refs/sanmopia-manager/application/controllers/Report.php:1-108, source-refs/sanmopia-manager/application/models/Report_model.php:1-101, source-refs/sanmopia-manager/application/views/report/report.php:1-137, source-refs/sanmopia-manager/static/js/report/report.js:1-70.
  • Service record save accepts primary or sub caregiver ownership, validates respiratory symptom comments, mother temperature, and URL-supplied service date shape, then writes primary rows to MANAGER_SERVICE_TB and sub rows to MANAGER_SUB_SERVICE_TB. Duplicate suppression is per table by RESERVATION_ID_FK + SERVICE_DT, not caregiver/role/handoff; duplicates return success without insert or error. Evidence: source-refs/sanmopia-manager/application/controllers/Service.php:58-180, source-refs/sanmopia-manager/application/models/Service_model.php:10-135.
  • Service record route/date handling is inconsistent: routes expose /service/{notifyIndex} while controller requires notify id plus date; schedule passes /service/index/{notifyIndex}/{date}. Notify read creates attendance rows as a hidden side effect. Evidence: source-refs/sanmopia-manager/application/config/routes.php:56-57, source-refs/sanmopia-manager/application/views/notify/notify_main.php:51-57, source-refs/sanmopia-manager/application/views/home/main.php:253-258, source-refs/sanmopia-manager/application/views/schedule/schedule_info.php:227-230, source-refs/sanmopia-manager/application/models/Notify_model.php:380-437.
  • Scheduled notification creation and push dispatch are separate flows. Fcm.php first inserts REPORT_FIRST, REPORT_PROGRESS, REPORT_LAST, and SERVICE notify rows, then a separate push flow derives manager ids and sends FCM. Manual repair is CLI-only, takes one reservation id, inserts missing report/service notify rows up to today, and does not push. Evidence: source-refs/sanmopia-manager/application/controllers/cli/Fcm.php:24-41, source-refs/sanmopia-manager/application/controllers/cli/Fcm.php:90-104, source-refs/sanmopia-manager/application/controllers/cli/Fcm.php:237-287, source-refs/sanmopia-manager/application/models/Reservation_model.php:559-580.
  • Report obligation date filters differ by kind: first report uses SERVICE_START_DT == today, progress uses start before today and end after today, last uses SERVICE_END_DT == today, and service record uses start/end containing today. Current report/service queries include reservation statuses 0,3,4,5,6,11,12; status 13 is excluded, while older repair helpers still include it. Evidence: source-refs/sanmopia-manager/application/models/User_model.php:1603-1643, source-refs/sanmopia-manager/application/models/User_model.php:1858-1901, source-refs/sanmopia-manager/application/models/User_model.php:1941-1982, source-refs/sanmopia-manager/application/models/User_model.php:2070-2106, source-refs/sanmopia-manager/application/models/Notify_model.php:70-260.
  • Customer report-date readers infer stopped intervals from reservation change logs. The stop transition date is included as a report date and marked as the last report day, suspended in-between dates are filtered out, and the service end date remains eligible. Evidence: source-refs/sanmopia_web/application/models/Report_model.php:267-391 and source-refs/sanmopia_web/application/models/Report_model.php:394-518.
  • The FCM sender reads USER_TOKEN_TB where TYPE = 'fcm' and PUSH_FL = 1 for multi-recipient sends, but sendById can ignore PUSH_FL and sends only the first token. Provider calls return raw http_code/response values with no token id, durable attempt row, retry, dead-letter, or repair state. Evidence: source-refs/sanmopia-manager/application/models/Fcm_model.php:60-88, source-refs/sanmopia-manager/application/models/Fcm_model.php:91-124, source-refs/sanmopia-manager/application/models/Fcm_model.php:161-188, source-refs/sanmopia-manager/application/models/User_model.php:1514-1540.
  • Admin exports resolve customer survey and caregiver report data during export, then choose first/middle/last templates by service date and stop day. Stop day uses the last-day daily report template even when it is not SERVICE_END_DT. Evidence: source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:4017-4096, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:4040-4045, source-refs/sanmopia-admin/application/models/Reservation_model.php:3262-3272, source-refs/sanmopia-admin/application/models/Reservation_model.php:3323-3358.

Gaps to migrate:

  • Add CaregiverReportObligation generated from the service calendar and assignment history. Reminder jobs should be idempotent commands over obligations, not one-off notification scans.
  • CareDeliveryNotificationWorkQueueProjection now exposes obligation key, reservation id, service date, caregiver id, obligation kind, due time, attempt state, retry state, oldest attempt age, attempt count, retry due time, last provider code/status, suppression reason, repair action set, and backend-owned action set. Remaining proof: Supabase persistence, queue worker binding, Novu/FCM adapter audit events, and operator API. The browser should render this projection and submit commands with expectedRevision and an idempotency key; it must not derive recipients, due dates, retry/backoff, token filtering, or missing-report math.
  • Add DailyCareReportSubmission keyed by reservation, service date, care team member, role, question set, and submission status. Primary and sub-caregiver variants should be role-scoped records, not duplicated flows.
  • Add CustomerDailySurveySubmission with first/middle/last/stop-day question set versioning and explicit edit/lock rules.
  • Stop-day acceptance: CustomerDailySurveySubmission and DailyCareReportSubmission must consume durable suspension intervals, mark the effective stop date as the last-day question set/template for mother and caregiver lanes, exclude dates between stop and resume, keep the actual service end date eligible, and avoid read-time inference from raw RESERVATION_CHANGE_LOG JSON.
  • CaregiverServiceRecordSubmission now owns primary/assistant identity, handoff order, service-date access window, respiratory/temperature facts, meal/feeding/recovery fields, explicit duplicate replay, correction revision, route date, sequential write action, and attendance outbox key. Remaining proof: Supabase persistence, API route wiring, baby bootstrap facts, frozen export snapshots, and document IDs 6/20 for primary/sub service records.
  • Admin exports should read frozen submission snapshots and artifact metadata. They should not recalculate question-set classification or row grouping during download.
PriorityStatusModern ubiquitous nameHidden source evidenceFeature gap
P0PartialDailyReportPrintableSeriesManifestsource-refs/sanmopia-admin/application/controllers/ajax/DataRoom.php:108-123, source-refs/sanmopia-admin/application/models/Reservation_model.php:3323-3358, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:4017-4057, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:1966-2010, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:2859-2903Admin export lists customer daily-report reservations by joining live report tables, then export builds one printable series from REPORT_TB service dates and a separate sub-caregiver series from REPORT_SUB_MANAGER_TB. Template choice is recomputed at export time from first/middle/last/stop-day rules and fixed spreadsheet slots. Modern print/export needs a frozen manifest per reservation, service date, care-team member role, report lane, question-set version, template version, and artifact build request before download.
P1PendingCaregiverDailyReportPrintableSeriesManifestsource-refs/sanmopia-admin/application/models/Spreadsheet_model.php:4058-4096, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:1449-1548, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:1530-1572, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:1700-1730Caregiver daily-report print export discovers first/middle/last pages by question ids (1-1, 2-1, 3-1) and CREATED_DT, mutates $reservation->MIDDLE_DATE for middle pages, then maps answer codes directly to fixed cells. Modern export should publish a role-scoped caregiver report print-series manifest with service occurrence key, submitted-at timestamp, question/answer snapshot, essay answer, template section key, and deterministic page ordering.
P0PendingContractPrintPricingSnapshotsource-refs/sanmopia-admin/application/models/Spreadsheet_model.php:644-660, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:663-700, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:705-724, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:728-780The contract/deposit print renderer recalculates additional-service totals, treats Saturday/holiday add-ons differently from per-service-day add-ons, hardcodes rental delivery/add-on amounts, and writes government support, customer share, voucher service price, special add price, child/adult add-ons, and rental fee totals directly into spreadsheet cells. Modern print/export needs a frozen pricing snapshot from accepted quote and payment ledger facts before render; template code should not own add-on multiplication, hardcoded rental fees, or amount classification.
P0PartialVoucherReceiptPrintableSettlementSnapshotsource-refs/sanmopia-admin/application/models/Spreadsheet_model.php:1057-1077, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:1104-1132, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:1221-1237, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:1243-1290The voucher receipt renderer queries branch/caregiver data, re-derives short/standard/extended service-day classification from positional SERVICE_DAY_LIST, falls back from gateway transaction number to reservation number, recomputes service price as government support plus customer share, and reads deposited date from payment rows while filling receipt cells. Existing backend receipt/catalog foundations must be bound to printable artifact generation so renderer input is a ledger-backed settlement snapshot with receipt date, service-day classification, amount components, and identifier policy already frozen.
P1PendingVoucherServiceEndNoticeSnapshotsource-refs/sanmopia-admin/application/models/Spreadsheet_model.php:1396-1446The voucher service-end notice renderer derives birthday from resident-number fragments, formats service period text, maps SERVICE_TYPE_DETAIL string literals to public service labels, and injects branch name/phone at render time. Modern notice generation needs a backend-owned service-end notice snapshot with privacy-safe birth date, service-period facts, service package label, branch contact snapshot, and template version before scheduled delivery or admin export.

Legacy behavior:

  • A numeric document registry maps reservation document kinds, daily report kinds, service record kinds, receipts, bundled downloads, and notices. Evidence: source-refs/sanmopia-admin/application/config/constants.php:217-257.
  • Spreadsheet generation uses a positional template array with static XLSX/PDF files and inconsistent file naming. Evidence: source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:1-39, source-refs/sanmopia-admin/static/dist/excel/type8.xlsx, source-refs/sanmopia-admin/static/dist/excel/type8.pdf, source-refs/sanmopia-admin/static/dist/excel/type15.pdf.
  • The static template directory includes current and old XLSX/PDF variants for document, receipt, daily report, and notice output. Evidence: source-refs/sanmopia-admin/static/dist/excel/type6_old.xlsx, source-refs/sanmopia-admin/static/dist/excel/type7_old.xlsx, source-refs/sanmopia-admin/static/dist/excel/type10_3_old_20240125.xlsx, source-refs/sanmopia-admin/static/dist/excel/type21.xlsx.
  • Admin download generation fills spreadsheets, copies static PDFs for some kinds, creates ZIP bundles, writes temporary files, deletes temporary files, and exits the request. Evidence: source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:3914-4199.
  • Customer PDF generation supports only a subset of document kinds and returns base64 PDF data. Evidence: source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:4284-4598.
  • XLSX-to-PDF conversion was moved from a local office conversion path to a network conversion service with an authorization header. Evidence: source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:4368-4408, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:4524-4579.
  • Admin bundle selection builds different integrated bundles by service type, then posts selected reservations to a hidden iframe download. Evidence: source-refs/sanmopia-admin/application/controllers/DataRoom.php:311-420, source-refs/sanmopia-admin/static/js/data_room/form_reservation_list.js:1-149, source-refs/sanmopia-admin/static/js/data_room/form_reservation_list.js:219-247.

Gaps to migrate:

  • Add PrintableTemplateRegistry keyed by document kind, template version, locale, paper format, render format, storage object key, and supported service types. Reject registry entries when declared format and stored file extension disagree.
  • Add PrintableRenderRequest for one artifact at a time, with reservation snapshot hash, template version, renderer, requested format, output object key, status, error reason, and retry count.
  • Backend printable policy now models a versioned template registry decision with document kind, template version/revision, A4 page policy, render format, renderer, supported service kinds, repeat-section flow policy, snapshot revision, readiness, and missing reasons. Storage references remain domain-internal and are excluded from public read models.
  • Add PrintableDocumentBundle that references artifact IDs instead of building ZIP files from live render side effects. Bundle policy should report missing artifacts and ineligible document kinds.
  • Move from positional template IDs to versioned document kinds. Migration must include a manifest from every legacy numeric value to a modern document kind and template version.
  • Keep the numeric/template-file mapping in migration docs and import scripts only. The modern backend catalog should store stable document definition keys, template versions, renderer/page policy, service-kind eligibility, and internal template storage references without source-audit fields.
  • Stop using request-time temporary files as the artifact system of record. Persist HTML/PDF output, checksum, byte size, content type, and generated-at time.

Legacy behavior:

  • Customer and caregiver report forms are mobile HTML screens, not print-specific A4 layouts. Evidence: source-refs/sanmopia_web/static/css/mypage.css:1-130, source-refs/sanmopia_web/application/views/mypage/daily_report.php:1-197, source-refs/sanmopia-manager/application/views/report/report.php:1-137.
  • Printable output relies on fixed spreadsheet coordinates, static PDFs, ZIP assembly, and network conversion. Evidence: source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:3914-4199, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:4284-4598.
  • Modern docs and tests already point toward HTML/PDF render requests, A4 repeat sections, stored templates, and stored artifacts. Evidence: apps/docs/src/content/docs/migration-source-map/sanmopia-feature-backlog.md:502-542, apps/docs/src/content/docs/frontend/document-output-ux.mdx:15-50, backend-repo/src/sanmopia_modernization/adapters/document_reporting/features/printable_document/html_print_renderer.py:7-155, backend-repo/src/sanmopia_modernization/adapters/document_reporting/features/printable_document/html_print_renderer_test.py:22-129, backend-repo/src/sanmopia_modernization/adapters/document_reporting/features/printable_document/supabase_printable_template_test.py:94-139, contract-repo/packages/ts-client/src/types/document-reporting_test.ts:250-333, frontend-repo/src/features/document-center/document-center-view-model.ts:33-840.

Replacement candidates:

  • Use Jinja2 plus WeasyPrint as the server-side PDF baseline for deterministic A4 artifacts and testable HTML templates.
  • Use Paged.js for browser preview and standard A4 print behavior in the document center.
  • Use Vivliostyle for long report series with repeat sections that must flow across pages.
  • Keep browser print CSS and print-js as a fallback path only, not the canonical renderer.
  • Use object storage for source templates, rendered HTML, rendered PDF, and bundle artifacts.
  • Keep office-based conversion only as a transitional compatibility bridge for imported spreadsheet templates. It should not be the target renderer for new templates.
  • Unify customer-visible documents, admin export-only documents, receipts, service records, daily surveys, and caregiver reports under a single document catalog.
  • Replace token-only live PDF generation with access grants over persisted artifacts and signed object URLs.
  • Convert receipt display from gateway-only view behavior into a receipt artifact/access model tied to payment ledger state.
  • Replace positional template IDs and mixed XLSX/PDF static files with a versioned template registry and migration manifest.
  • Replace live ZIP generation with bundle artifacts that reference rendered artifact IDs and expose missing/ineligible item diagnostics.
  • Model daily report obligations, submissions, and service records as role-scoped service-date records, including sub-caregiver variants.
  • Standardize A4 HTML/PDF rendering with repeat-section support and stored artifacts before migrating fixed spreadsheet templates.