# Company leave policies — September 6, 2026 NEW: Leave Configuration → Company Leaves now includes a compact policy form and version history for the selected company and brand. Existing global type management remains available under it for the system-admin role (`ADMIN`) and SuperAdmins, regardless of username. Leave module/action permissions and brand access still apply. Configuration and entitlement dialogs use Tailwind styling with focus management; errors stay inside the active dialog. Credit reversal opens separately from balance history to prevent stacked forms. ## Behavior - [MODIFIED 2026-09-06] Authorized shared-type managers can use **Add custom leave type** beneath the policy form's type selector. Saving the separate type form selects its returned ID and preserves the policy draft; cancelling returns to the unchanged draft. The type is saved independently of the policy and remains shared across companies. Deploy the frontend and updated create endpoint together; no SQL migration is required for this form change. - Policy read/save uses authenticated admin access, selected-brand authorization, `leave_type` module permission and `can_add` for each new version. Client-portal users cannot configure policies. Scope comes from trusted brand context, not request-body company/brand IDs. - Configure an existing type, annual limit (0–999.99 days), completed service months (0–600), and effective date. Zero days closes new requests under that version. Zero service months imposes no hire-date requirement. - New versions start today (Asia/Manila) or later, strictly after the latest version. Versions cannot be edited or deleted through the API. They apply until the next effective date. No statutory defaults are seeded. - Pending submissions and approvals, including direct HR entries and material edits, check the applicable policy. Approved requests without material changes retain their recorded version. A material type/date/duration edit reevaluates the applicable version. Policy checks are recorded transactionally. - Usage includes pending requests plus the greater of stored usage and active approved usage; a request's own previous contribution is excluded on edit. This preserves disputed historical usage conservatively. It does not certify the old balances or manufacture credits. Deferred reconciliation remains open. - Annual allowance is a request ceiling, not an accrual/entitlement credit. The existing Balance page continues to show legacy balance credits. Changing a policy does not rewrite those credits, prior deductions, or paid/unpaid treatment. - Configured leave must stay within a calendar year and one effective interval. HR must split cross-boundary requests. Existing pinned applications retain their version if later policy publication introduces a boundary within them. - Unconfigured types/dates keep the existing behavior. A request spanning the first configured effective date must be split. Rejections and cancellations remain available without meeting service/allowance checks. - Employee then brand locks serialize policy checks with usage and publication. Transactions use READ COMMITTED so a waiter sees committed usage after locking. Legacy direct database writes bypass PHP policy validation; integrations must use the guarded endpoints. Existing SQL remains the only balance writer. ## Database rollout NEW - September 6, 2026: Employee entitlements and manual credit grants now have a separate migration and journal. See `leave-entitlements-ledger.md`. After that migration, the Leave Balance page shows entitlement history and requests must satisfy both available credits and these policy limits. Saving a policy still does not automatically grant employee credits. 1. Back up and test a clone. Confirm the integrity migration is complete. 2. Select the intended database explicitly in phpMyAdmin. Run `backend/migrations/2026_09_06_company_leave_policies.sql` once. It adds three tables, with dated purpose/preservation comments, and can be rerun without dropping data. No employee, balance, or historical leave rows are changed. 3. Deploy the backend and rebuilt frontend together. The policy panel reports setup pending before migration. Partial policy-table setup blocks policy checks instead of silently bypassing them. 4. In Company Leaves, verify the displayed company/brand and publish a policy for an appropriate future date. Test with verified employee history first. This change has not been applied to the live database by the agent. The supplied employee-reference and balance discrepancies remain deferred at the user's request. Statutory/general-rules tabs remain previews. Accrual, ledger opening balances, working-day allocation, paid-treatment overrides, and configurable approval stages are separate future work. ## Validation `backend/tests/leave/policies.php` passed the 29 original integrity checks and 19 policy integration checks in the protected disposable instance. Four guard cases exercise allowed admin publication and denial for missing permissions, client users, and a foreign brand. PHP syntax, targeted frontend lint and a production build are also checked. This does not establish live login/browser validation. The disposable database was shut down and its temporary files removed afterward.