Document Details

Purpose

This catalog defines the business rules that shape validation, transformation, controls, and exception handling throughout the migration workflow.

View or Download

Document Preview

Business Rules

Evidence Labels

Rules marked Observed are enforced or documented in code, tests, or README. Rules marked Inferred describe likely business intent behind implementation behavior.

ID Rule Enforcement point Exceptions or notes Evidence quality
BR-001 Source Odin report must be an .xlsx workbook. inspect_inputs in src/odin_lunchtab/managed.py Other extensions are rejected. Observed
BR-002 Lunchtab users export must be a .csv file. inspect_inputs in src/odin_lunchtab/managed.py Other extensions are rejected. Observed
BR-003 Odin rows require account type, ID number, deposits, spendings, balance, and student name. extract_odin_report in src/odin_lunchtab/workflow.py Missing fields become malformed exceptions. Observed
BR-004 Odin student names must use Surname, FirstName format. split_student_name in src/odin_lunchtab/workflow.py Invalid names become malformed exceptions. Observed
BR-005 Monetary values must parse to finite decimals. _money_text, _decimal, and _decimal_or_none in workflow modules Invalid values block or are excluded depending on workflow stage. Observed
BR-006 Lunchtab users export must include FirstName, PreferredName, Surname, LoginBarcode, DefaultFamilyCode, and DefaultFamilyBalanceAmount. REQUIRED_LUNCHTAB_HEADERS in src/odin_lunchtab/managed.py Profile-specific target fields can add required headers. Observed
BR-007 OdinBalanceAmount is inserted immediately after DefaultFamilyBalanceAmount in the transfer CSV. run_workflow in src/odin_lunchtab/workflow.py The original Lunchtab rows are preserved with the added balance column. Observed
BR-008 A duplicate Odin account identity is not auto-matched. match_balances_detailed in src/odin_lunchtab/workflow.py Reason is duplicate Odin ID Number. Observed
BR-009 A crosswalk match must resolve to exactly one Lunchtab target and pass name validation. match_balances_detailed in src/odin_lunchtab/workflow.py Stale, duplicate, or name-failed crosswalks become exceptions. Observed
BR-010 Identifier matches must pass surname and first/preferred-name validation. names_compatible in src/odin_lunchtab/workflow.py Surnames normalize exactly; first names can match by compatible prefix. Observed
BR-011 Matching profiles can target LoginBarcode, ExternalId, or EmailUsername only. APPROVED_TARGET_FIELDS in src/odin_lunchtab/profiles.py Unsupported targets are rejected. Observed
BR-012 Email username matching uses the complete local part before a single @, and optional domains must be exact and valid. parse_email_address, valid_email_domain, and _email_candidate_allowed Malformed or disallowed emails do not produce candidates. Observed
BR-013 A matching profile cannot contain duplicate enabled rule names or duplicate crosswalk source identities. MatchingProfile.validate in src/odin_lunchtab/profiles.py Validation raises an error. Observed
BR-014 The Legacy Default profile is read-only and cannot be modified or deleted. save_profile and delete_profile in src/odin_lunchtab/profiles.py It preserves exact ID-to-LoginBarcode matching plus name fallback. Observed
BR-015 Multiple matching rules resolving to different Lunchtab users are quarantined. match_balances_detailed in src/odin_lunchtab/workflow.py Reason is matching rules resolved to different Lunchtab users. Observed
BR-016 Multiple Odin records matching one Lunchtab user are quarantined. match_balances_detailed in src/odin_lunchtab/workflow.py Prevents multiple balance writes to one user row. Observed
BR-017 no Lunchtab match records are excluded from the focused manual-review exception file. run_workflow in src/odin_lunchtab/workflow.py They remain in the full exceptions report. Observed
BR-018 Reconciliation audit control must satisfy valid source dollars equals matched dollars plus valid exception dollars. write_reconciliation_audit_control in src/odin_lunchtab/audit_control.py A failure raises an error in run_workflow. Observed
BR-019 Managed runs publish only after output files and manifest are created. run_managed_workflow, run_initial_balances_workflow, and run_manual_reconciliation_workflow Staging folders are removed on failure. Observed
BR-020 Manual reconciliation edited transfer must have the same headers and row count as the original transfer. audit_manual_reconciliation in src/odin_lunchtab/manual_reconciliation.py Structural mismatch is rejected. Observed
BR-021 Filling a previously blank OdinBalanceAmount is treated as a manual resolution. audit_manual_reconciliation Severity is REVIEW. Observed
BR-022 Invalid manual balance amounts block downstream use. audit_manual_reconciliation Summary status becomes BLOCKED. Observed
BR-023 Changing automated balances, family codes, identity fields, or other fields requires review. audit_manual_reconciliation Summary status becomes REVIEW unless invalid amounts block. Observed
BR-024 InitialBalances export must contain exactly FamilyName,FamilyCode,Amount in order. inspect_initial_balances_inputs in src/odin_lunchtab/initial_balances.py Noncanonical headers are rejected. Observed
BR-025 InitialBalances transfer aggregates populated Odin balances by case-sensitive DefaultFamilyCode. _analyze_initial_balances in src/odin_lunchtab/initial_balances.py Multiple source rows can update one family. Observed
BR-026 Blank target InitialBalances amounts are treated as zero. _decimal(..., blank_as_zero=True) Only when parsing target amount. Observed
BR-027 InitialBalances import file is omitted when blocking exceptions exist. process_initial_balances in src/odin_lunchtab/initial_balances.py Audit and exception artifacts are still produced. Observed
BR-028 InitialBalances control totals must pass before publication. process_initial_balances and write_initial_balances_audit_control Failure raises an integrity error. Observed
BR-029 CSV reads support UTF-8, Windows-1252, and BOM-marked UTF-16, and reject binary-looking or corrupted text. _decode_csv_bytes and _validate_csv_text in src/odin_lunchtab/workflow.py Generated CSVs use UTF-8 with BOM. Observed
BR-030 Source files are not modified by the application. README and workflow behavior Outputs are written to separate result folders. Observed
BR-031 Logs and manifests should avoid student-level row data and absolute source paths. README and manifest structures in managed.py and initial_balances.py File hashes and names are stored for provenance. Observed
BR-032 Staff should use generated imports only after reviewing summaries and resolving blocking exceptions. README and run summary next-action text Operational approval outside the app remains a human activity. Inferred

Related case study