Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
1938 lines
153 KiB
Markdown
1938 lines
153 KiB
Markdown
# Scratchpad — Contract Auto-Renewal and Renewals Queue
|
||
|
||
- Plan slug: `contract-auto-renewal-and-renewals-queue`
|
||
- Created: `2026-02-21`
|
||
|
||
## What This Is
|
||
Rolling implementation memory for renewal settings + actionable renewals queue + automation ticketing.
|
||
|
||
## Decisions
|
||
- (2026-02-21) Build an **actionable queue** (not read-only report).
|
||
- (2026-02-21) Ship **both** dashboard entry and full queue page (`Client Contracts` widget + `Renewals` tab).
|
||
- (2026-02-21) Primary operational date is **renewal decision due date**.
|
||
- (2026-02-21) Due-date behavior is configurable with **tenant defaults + optional per-contract override**.
|
||
- (2026-02-21) Default automation target at due date: **create internal ticket**.
|
||
- (2026-02-21) Minimum queue actions for v1: `Mark renewing`, `Mark non-renewing`, `Create renewal draft`, `Snooze`.
|
||
- (2026-02-21) Default queue horizon: **90 days**, grouped `0-30`, `31-60`, `61-90`.
|
||
- (2026-02-21) Queue includes **fixed-term + evergreen anniversaries**.
|
||
- (2026-02-21) `Mark renewing` should **auto-create renewal draft** and open it.
|
||
- (2026-02-21) Release approach: **single release** scope.
|
||
- (2026-02-21) Automation runtime note: support **pg-boss for on-prem** and **Temporal for hosted/EE**.
|
||
|
||
## Discoveries / Constraints
|
||
- (2026-02-21) Runtime selection already exists in `server/src/lib/jobs/JobRunnerFactory.ts` with config/env-based choice and fallback behavior; default is pg-boss unless configured otherwise.
|
||
- (2026-02-21) Existing scheduled jobs in `server/src/lib/jobs/initializeScheduledJobs.ts` explicitly branch for enterprise/temporal behavior in some paths; renewal automation should follow same compatibility pattern.
|
||
- (2026-02-21) Contract lifecycle already emits `CONTRACT_CREATED` and `CONTRACT_RENEWAL_UPCOMING` in both `packages/clients/src/actions/clientContractActions.ts` and `packages/billing/src/actions/contractWizardActions.ts`.
|
||
- (2026-02-21) `CONTRACT_RENEWAL_UPCOMING` computation today is window-based (`DEFAULT_CONTRACT_RENEWAL_UPCOMING_WINDOW_DAYS = 30`) in `shared/workflow/streams/domainEventBuilders/contractEventBuilders.ts`; queue design requires broader 90-day horizon and due-date semantics.
|
||
- (2026-02-21) Existing contract expiration report is currently `end_date`-driven (`packages/billing/src/actions/contractReportActions.ts`, `server/src/lib/reports/definitions/contracts/expiration.ts`).
|
||
- (2026-02-21) Billing settings already provide tenant defaults in `default_billing_settings` with client override pattern in `client_billing_settings`; actions in `packages/billing/src/actions/billingSettingsActions.ts` and shared helpers in `shared/billingClients/billingSettings.ts` are reusable design patterns.
|
||
- (2026-02-21) Billing UI insertion points are clear:
|
||
- tabs config: `packages/billing/src/components/billing-dashboard/billingTabsConfig.ts`
|
||
- tab content host: `packages/billing/src/components/billing-dashboard/BillingDashboard.tsx`
|
||
- queue/widget host: `packages/billing/src/components/billing-dashboard/contracts/ClientContractsTab.tsx`
|
||
- wizard basics: `packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ContractBasicsStep.tsx`
|
||
- (2026-02-21) Contract assignment data shape in `server/src/interfaces/contract.interfaces.ts` is assignment-level and suitable for renewal metadata on `IClientContract`.
|
||
|
||
## Commands / Runbooks
|
||
- (2026-02-21) Inspect billing dashboard contract files:
|
||
- `rg -n "ContractWizard|ClientContractsTab|billingTabsConfig|ContractBasicsStep" packages/billing/src/components/billing-dashboard`
|
||
- (2026-02-21) Inspect runtime selection + scheduling:
|
||
- `rg -n "JobRunnerFactory|initializeScheduledJobs|EDITION|JOB_RUNNER_TYPE" server/src/lib/jobs`
|
||
- (2026-02-21) Inspect contract renewal event publishing:
|
||
- `rg -n "CONTRACT_RENEWAL_UPCOMING|computeContractRenewalUpcoming" packages/billing packages/clients shared/workflow`
|
||
- (2026-02-21) Validate plan artifacts:
|
||
- `python3 /Users/roberisaacs/.codex/skills/alga-plan/scripts/validate_plan.py ee/docs/plans/2026-02-21-contract-auto-renewal-and-renewals-queue`
|
||
|
||
## Links / References
|
||
- Key plan path: `ee/docs/plans/2026-02-21-contract-auto-renewal-and-renewals-queue`
|
||
- Runtime selection: `server/src/lib/jobs/JobRunnerFactory.ts`
|
||
- Scheduled job init: `server/src/lib/jobs/initializeScheduledJobs.ts`
|
||
- Job scheduler infra: `server/src/lib/jobs/jobScheduler.ts`
|
||
- Renewal event builders: `shared/workflow/streams/domainEventBuilders/contractEventBuilders.ts`
|
||
- Contract wizard save path: `packages/billing/src/actions/contractWizardActions.ts`
|
||
- Client contract actions: `packages/clients/src/actions/clientContractActions.ts`
|
||
- Billing settings actions: `packages/billing/src/actions/billingSettingsActions.ts`
|
||
- Billing settings shared helpers: `shared/billingClients/billingSettings.ts`
|
||
- Billing dashboard tabs host: `packages/billing/src/components/billing-dashboard/BillingDashboard.tsx`
|
||
- Client contracts tab: `packages/billing/src/components/billing-dashboard/contracts/ClientContractsTab.tsx`
|
||
- Wizard basics step: `packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ContractBasicsStep.tsx`
|
||
|
||
## Implementation Log
|
||
- (2026-02-21) Completed `F001`.
|
||
- Added renewal fields to `ContractWizardData` in `packages/billing/src/components/billing-dashboard/contracts/ContractWizard.tsx`:
|
||
- `renewal_mode?: 'none' | 'manual' | 'auto'`
|
||
- `notice_period_days?: number`
|
||
- `renewal_term_months?: number`
|
||
- `use_tenant_renewal_defaults?: boolean`
|
||
- Rationale: establish typed wizard-state shape early so subsequent UI rendering, defaults/hydration, validation, and submission features can build on stable field names.
|
||
- (2026-02-21) Completed `T001`.
|
||
- Added `packages/billing/src/components/billing-dashboard/contracts/ContractWizard.renewalFields.test.ts`.
|
||
- Test covers type-level contract for the four renewal fields and validates the allowed `renewal_mode` domain values.
|
||
- Runbook:
|
||
- `npx vitest run packages/billing/src/components/billing-dashboard/contracts/ContractWizard.renewalFields.test.ts`
|
||
- (2026-02-21) Completed `F002`.
|
||
- Added `createDefaultContractWizardData()` in `packages/billing/src/components/billing-dashboard/contracts/ContractWizard.tsx`.
|
||
- Renewal defaults for new contracts now initialize as:
|
||
- `renewal_mode: 'manual'`
|
||
- `notice_period_days: 30`
|
||
- `renewal_term_months: undefined`
|
||
- `use_tenant_renewal_defaults: true`
|
||
- Updated wizard initialization/reset paths to use the shared factory, keeping default behavior deterministic across first render, open/reset, and edit-merge flows.
|
||
- (2026-02-21) Completed `T002`.
|
||
- Extended `packages/billing/src/components/billing-dashboard/contracts/ContractWizard.renewalFields.test.ts` with default-state assertions using `createDefaultContractWizardData()`.
|
||
- Validates default renewal state for new contracts: mode `manual`, notice `30`, no term months, tenant-default toggle enabled.
|
||
- (2026-02-21) Completed `F003`.
|
||
- Extended `DraftContractWizardData` in `packages/billing/src/actions/contractWizardActions.ts` with renewal fields.
|
||
- Updated `getDraftContractForResume` to hydrate renewal settings from `client_contracts`:
|
||
- normalized `renewal_mode` (`none|manual|auto`)
|
||
- sanitized integer `notice_period_days` (non-negative)
|
||
- sanitized positive integer `renewal_term_months`
|
||
- hydrated `use_tenant_renewal_defaults` when boolean
|
||
- Rationale: resumed drafts now carry renewal metadata into `editingContract` so wizard state merge can restore renewal settings.
|
||
- (2026-02-21) Completed `T003`.
|
||
- Added `packages/billing/src/actions/contractWizardActions.renewalDraftResumeWiring.test.ts`.
|
||
- Test validates:
|
||
- renewal fields are present on `DraftContractWizardData`,
|
||
- `getDraftContractForResume` returns hydrated renewal values,
|
||
- numeric renewal values are sanitized before payload return.
|
||
- (2026-02-21) Completed `F004`.
|
||
- Added `buildInitialContractWizardData(editingContract)` in `packages/billing/src/components/billing-dashboard/contracts/ContractWizard.tsx`.
|
||
- Edit-mode initialization now explicitly normalizes renewal fields during hydration:
|
||
- validates `renewal_mode` domain,
|
||
- normalizes non-negative `notice_period_days`,
|
||
- normalizes positive `renewal_term_months`,
|
||
- preserves explicit boolean `use_tenant_renewal_defaults`.
|
||
- Wired both initial state and open-effect initialization to use this shared edit-hydration path.
|
||
- (2026-02-21) Completed `T004`.
|
||
- Extended `packages/billing/src/components/billing-dashboard/contracts/ContractWizard.renewalFields.test.ts`.
|
||
- Added assertions proving edit hydration path uses `buildInitialContractWizardData(editingContract)` and renewal normalization helpers for mode/notice/term.
|
||
- (2026-02-21) Completed `F005`.
|
||
- Added a fixed-term renewal UI container to `packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ContractBasicsStep.tsx`.
|
||
- New `Renewal Settings` card renders only when `data.end_date` is present (`data-automation-id=\"renewal-settings-fixed-term-card\"`).
|
||
- (2026-02-21) Completed `T005`.
|
||
- Added `packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ContractBasicsStep.renewalCards.test.ts`.
|
||
- Test asserts fixed-term card conditional wiring on `data.end_date` and verifies the automation id/heading token.
|
||
- (2026-02-21) Completed `F006`.
|
||
- Added evergreen variant UI in `packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ContractBasicsStep.tsx`.
|
||
- New `Evergreen Review Settings` card renders when `data.end_date` is absent (`data-automation-id=\"renewal-settings-evergreen-card\"`).
|
||
- (2026-02-21) Completed `T006`.
|
||
- Extended `packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ContractBasicsStep.renewalCards.test.ts` with evergreen-card assertions.
|
||
- Verifies absent-end-date branch and `renewal-settings-evergreen-card` wiring.
|
||
- (2026-02-21) Completed `F007`.
|
||
- Added renewal mode selector UI to both fixed-term and evergreen renewal cards in `packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ContractBasicsStep.tsx`.
|
||
- Options now explicitly include `none`, `manual`, and `auto`, bound to `data.renewal_mode`.
|
||
- (2026-02-21) Completed `T007`.
|
||
- Extended `packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ContractBasicsStep.renewalCards.test.ts`.
|
||
- Added assertions for `renewalModeOptions` values (`none|manual|auto`) and `updateData` binding back to `renewal_mode`.
|
||
- (2026-02-21) Completed `F008`.
|
||
- Added `Notice Period (Days)` input to both renewal cards in `packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ContractBasicsStep.tsx`.
|
||
- Input is conditionally rendered only when renewal mode is enabled (`manual` or `auto`), with non-negative integer coercion on change.
|
||
- (2026-02-21) Completed `T008`.
|
||
- Extended `packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ContractBasicsStep.renewalCards.test.ts` with notice-period assertions.
|
||
- Confirms `isRenewalEnabled` gate and both notice input IDs (`fixed` and `evergreen`) are present in the renewal-enabled branch.
|
||
- (2026-02-21) Completed `F009`.
|
||
- Added auto-renew specific `Renewal Term (Months)` inputs to fixed-term and evergreen renewal cards in `packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ContractBasicsStep.tsx`.
|
||
- Input is gated by `isAutoRenew` and writes sanitized positive integer values to `renewal_term_months`.
|
||
- (2026-02-21) Completed `F010`.
|
||
- Confirmed auto-renew term controls are hidden unless `effectiveRenewalMode === 'auto'` via `isAutoRenew` conditional rendering in `ContractBasicsStep.tsx`.
|
||
- (2026-02-21) Completed `T009`.
|
||
- Extended `packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ContractBasicsStep.renewalCards.test.ts` with auto-term wiring assertions.
|
||
- Verifies both term input IDs and positive-integer assignment path for `renewal_term_months`.
|
||
- (2026-02-21) Completed `T010`.
|
||
- Added explicit `isAutoRenew` gating assertions in `ContractBasicsStep.renewalCards.test.ts`.
|
||
- Verifies auto-specific term controls are conditionally rendered only in `auto` mode.
|
||
- (2026-02-21) Completed `F011`.
|
||
- Added step-0 wizard validation in `packages/billing/src/components/billing-dashboard/contracts/ContractWizard.tsx`:
|
||
- if `end_date` is set and `renewal_mode` is missing, progression is blocked with inline error.
|
||
- (2026-02-21) Completed `F012`.
|
||
- Added notice-period validation bounds in `ContractWizard.tsx` (`MIN_NOTICE_PERIOD_DAYS=0`, `MAX_NOTICE_PERIOD_DAYS=3650`).
|
||
- Step-0 validation now requires notice period to be an integer and within bounds whenever renewal mode is enabled.
|
||
- (2026-02-21) Completed `F013`.
|
||
- Added step-0 validation rule in `ContractWizard.tsx` requiring `renewal_term_months` to be a positive integer when provided.
|
||
- (2026-02-21) Completed `F014`.
|
||
- Renewal validation errors from step-0 rules (`F011`-`F013`) now surface through the wizard’s existing inline step error panel before progression.
|
||
- (2026-02-21) Completed `T011`.
|
||
- Extended `packages/billing/src/components/billing-dashboard/contracts/ContractWizard.renewalFields.test.ts` with assertions for required renewal mode when `end_date` is set.
|
||
- (2026-02-21) Completed `T012`.
|
||
- Marked covered by the same `ContractWizard.renewalFields.test.ts` additions that assert notice-period integer/bounds validation wiring.
|
||
- (2026-02-21) Completed `T013`.
|
||
- Marked covered by existing `ContractWizard.renewalFields.test.ts` assertions for positive renewal-term validation when value is provided.
|
||
- (2026-02-21) Completed `T014`.
|
||
- Marked covered by existing `ContractWizard.renewalFields.test.ts` assertion that inline step error rendering (`errors[currentStep]`) is present for renewal validation failures.
|
||
- (2026-02-21) Completed `F015`.
|
||
- Extended `ContractBasicsStep` summary alert to include renewal preview fields:
|
||
- renewal mode label,
|
||
- notice period (for renewal-enabled modes),
|
||
- renewal term months (auto-renew mode).
|
||
- (2026-02-21) Completed `F016`.
|
||
- Extended `ReviewContractStep` “Contract Basics” card to preview renewal fields before submit:
|
||
- renewal mode,
|
||
- notice period,
|
||
- renewal term (auto mode).
|
||
- (2026-02-21) Completed `F017`.
|
||
- Added renewal fields to `ClientContractWizardSubmission` (`packages/billing/src/actions/contractWizardActions.ts`).
|
||
- Updated `buildSubmissionData()` in `ContractWizard.tsx` to include renewal mode, notice period, renewal term, and tenant-default toggle in outgoing wizard payload.
|
||
- (2026-02-21) Completed `F018`.
|
||
- Updated `createClientContractFromWizard` insert path for `client_contracts` to persist renewal fields.
|
||
- Added schema-compat guards (`hasColumn`) so renewal columns are written when available without breaking pre-migration environments.
|
||
- (2026-02-21) Completed `T015`.
|
||
- Extended `ContractBasicsStep.renewalCards.test.ts` to assert renewal mode/notice/term rows are present in the Contract Basics summary preview.
|
||
- (2026-02-21) Completed `T016`.
|
||
- Added `packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ReviewContractStep.renewalPreview.test.ts`.
|
||
- Test covers renewal preview rows and mode-gated rendering conditions in the review step.
|
||
- (2026-02-21) Completed `T017`.
|
||
- Extended `ContractWizard.renewalFields.test.ts` to assert `buildSubmissionData()` includes all renewal fields in outgoing wizard payload.
|
||
- (2026-02-21) Completed `T018`.
|
||
- Extended `contractWizardActions.renewalDraftResumeWiring.test.ts` to assert draft/client save path writes renewal fields into `client_contracts` with schema-guarded `hasColumn` checks.
|
||
- (2026-02-21) Completed `F019`.
|
||
- Extended tenant default billing settings model surface in `packages/billing/src/actions/billingSettingsActions.ts` and `server/src/interfaces/billing.interfaces.ts` with renewal-default fields (including default renewal mode) using schema-guarded writes for compatibility.
|
||
- (2026-02-21) Completed `F020`.
|
||
- Included `defaultNoticePeriodDays` mapping (`default_notice_period_days`) in tenant default billing settings model and guarded write path.
|
||
- (2026-02-21) Completed `F021`.
|
||
- Included `renewalDueDateActionPolicy` mapping (`renewal_due_date_action_policy`) with normalized fallback in tenant billing settings model.
|
||
- (2026-02-21) Completed `F022`.
|
||
- Included tenant default renewal ticket board field mapping (`renewal_ticket_board_id`) in billing settings model/read-write path.
|
||
- (2026-02-21) Completed `F023`.
|
||
- Included tenant default renewal ticket status field mapping (`renewal_ticket_status_id`) in billing settings model/read-write path.
|
||
- (2026-02-21) Completed `F024`.
|
||
- Included tenant default renewal ticket priority field mapping (`renewal_ticket_priority`) in billing settings model/read-write path.
|
||
- (2026-02-21) Completed `F025`.
|
||
- Included tenant default renewal ticket assignee field mapping (`renewal_ticket_assignee_id`) in billing settings model/read-write path.
|
||
- (2026-02-21) Completed `F026`.
|
||
- `getDefaultBillingSettings` now returns renewal default fields (mode, notice days, due-date policy, ticket routing defaults) with deterministic fallbacks.
|
||
- (2026-02-21) Completed `F027`.
|
||
- `updateDefaultBillingSettings` now writes renewal default fields via schema-guarded update/insert payloads.
|
||
- (2026-02-21) Completed `T019`.
|
||
- Added `packages/billing/src/actions/billingSettingsActions.renewalDefaultsWiring.test.ts` and marked renewal-mode model coverage.
|
||
- (2026-02-21) Completed `T020`.
|
||
- Covered by existing `billingSettingsActions.renewalDefaultsWiring.test.ts` assertions for `defaultNoticePeriodDays`.
|
||
- (2026-02-21) Completed `T021`.
|
||
- Covered by existing `billingSettingsActions.renewalDefaultsWiring.test.ts` assertions for `renewalDueDateActionPolicy`.
|
||
- (2026-02-21) Completed `T022`.
|
||
- Covered by existing `billingSettingsActions.renewalDefaultsWiring.test.ts` assertions for `renewalTicketBoardId`.
|
||
- (2026-02-21) Completed `T023`.
|
||
- Covered by existing `billingSettingsActions.renewalDefaultsWiring.test.ts` assertions for `renewalTicketStatusId`.
|
||
- (2026-02-21) Completed `T024`.
|
||
- Covered by existing `billingSettingsActions.renewalDefaultsWiring.test.ts` assertions for `renewalTicketPriority`.
|
||
- (2026-02-21) Completed `T025`.
|
||
- Covered by existing `billingSettingsActions.renewalDefaultsWiring.test.ts` assertions for `renewalTicketAssigneeId`.
|
||
- (2026-02-21) Completed `T026`.
|
||
- Covered by existing `billingSettingsActions.renewalDefaultsWiring.test.ts` assertions for `getDefaultBillingSettings` renewal default response mapping.
|
||
- (2026-02-21) Completed `T027`.
|
||
- Covered by existing `billingSettingsActions.renewalDefaultsWiring.test.ts` assertions for schema-guarded renewal default persistence in update writes.
|
||
- (2026-02-21) Completed `T028`.
|
||
- Extended renewal UI/source tests to assert `Use Tenant Renewal Defaults` toggle controls and payload field wiring (`use_tenant_renewal_defaults`).
|
||
- (2026-02-21) Completed `T029`.
|
||
- Covered by `ContractWizard.renewalFields.test.ts` assertions that tenant defaults are applied in submission resolution when toggle is enabled.
|
||
- (2026-02-21) Completed `T030`.
|
||
- Covered by `packages/billing/src/components/billing-dashboard/contracts/ContractWizard.renewalFields.test.ts` assertion:
|
||
- `prefers explicit contract override values when tenant defaults are disabled`.
|
||
- Validation run:
|
||
- `cd server && npx vitest run --coverage.enabled=false ../packages/billing/src/components/billing-dashboard/contracts/ContractWizard.renewalFields.test.ts`
|
||
- (2026-02-21) Completed `T031`.
|
||
- Covered by `packages/billing/src/components/billing-dashboard/contracts/ContractWizard.renewalFields.test.ts` assertion:
|
||
- `uses deterministic fallback precedence for partial override/default state`.
|
||
- Validation run:
|
||
- `cd server && npx vitest run --coverage.enabled=false ../packages/billing/src/components/billing-dashboard/contracts/ContractWizard.renewalFields.test.ts`
|
||
- (2026-02-21) Completed `F028`.
|
||
- Added explicit `Use Tenant Renewal Defaults` toggle controls to both fixed-term and evergreen renewal settings cards in `ContractBasicsStep.tsx`, bound to `use_tenant_renewal_defaults`.
|
||
- (2026-02-21) Completed `F029`.
|
||
- Updated `buildSubmissionData()` in `ContractWizard.tsx` to resolve renewal mode + notice period from tenant defaults when `use_tenant_renewal_defaults` is enabled.
|
||
- (2026-02-21) Completed `F030`.
|
||
- Submission resolution now prefers explicit contract-level renewal values when `use_tenant_renewal_defaults` is disabled.
|
||
- (2026-02-21) Completed `F031`.
|
||
- Implemented deterministic renewal fallback order in submission resolution:
|
||
- explicit contract values (when overrides enabled),
|
||
- tenant defaults,
|
||
- hard defaults (`manual`, `30`).
|
||
- (2026-02-21) Completed `F032`.
|
||
- Extended contract-assignment read APIs to expose normalized/effective renewal settings in both shared and clients data-access layers:
|
||
- `shared/billingClients/clientContracts.ts`
|
||
- `packages/clients/src/models/clientContract.ts`
|
||
- Added schema-guarded tenant-default joins (`default_billing_settings`) for read paths and computed:
|
||
- `effective_renewal_mode`
|
||
- `effective_notice_period_days`
|
||
- Added type surface fields on `IClientContract` in:
|
||
- `packages/types/src/interfaces/contract.interfaces.ts`
|
||
- `server/src/interfaces/contract.interfaces.ts`
|
||
- Validation run:
|
||
- `npm -w @alga-psa/shared run typecheck`
|
||
- `npm -w @alga-psa/clients run typecheck`
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/clientContractEffectiveRenewalSettings.test.ts`
|
||
- (2026-02-21) Completed `F033`.
|
||
- Added fixed-term `decision_due_date` computation in assignment normalization paths:
|
||
- `shared/billingClients/clientContracts.ts`
|
||
- `packages/clients/src/models/clientContract.ts`
|
||
- Formula implemented with date-only semantics for fixed-term contracts:
|
||
- `decision_due_date = end_date - effective_notice_period_days`
|
||
- Added `decision_due_date` to contract interfaces:
|
||
- `packages/types/src/interfaces/contract.interfaces.ts`
|
||
- `server/src/interfaces/contract.interfaces.ts`
|
||
- Expanded test coverage in `packages/billing/tests/clientContractEffectiveRenewalSettings.test.ts`.
|
||
- (2026-02-21) Completed `F034`.
|
||
- Added evergreen annual-review anchor computation based on contract start-date anniversary rules.
|
||
- New shared helper:
|
||
- `computeNextEvergreenReviewAnchorDate` in `shared/billingClients/clientContracts.ts`
|
||
- Exposed normalized field on active evergreen assignments:
|
||
- `evergreen_review_anchor_date`
|
||
- Mirrored logic in clients model read normalization for parity:
|
||
- `packages/clients/src/models/clientContract.ts`
|
||
- Expanded tests in `packages/billing/tests/clientContractEffectiveRenewalSettings.test.ts`.
|
||
- (2026-02-21) Completed `F035`.
|
||
- Added evergreen `decision_due_date` computation from annual anchor minus effective notice period.
|
||
- New shared helper:
|
||
- `computeEvergreenDecisionDueDate` in `shared/billingClients/clientContracts.ts`
|
||
- Applied in both read normalization paths (shared + clients model) so evergreen assignments now expose date-only `decision_due_date`.
|
||
- Expanded deterministic date-math coverage in `packages/billing/tests/clientContractEffectiveRenewalSettings.test.ts`.
|
||
- (2026-02-21) Completed `F036`.
|
||
- Confirmed and codified date-only normalization for `decision_due_date` math using `normalizeDateOnly` + UTC midnight subtraction paths.
|
||
- Added regression test proving timestamp `end_date` inputs are normalized to date-only before subtraction:
|
||
- `packages/billing/tests/clientContractEffectiveRenewalSettings.test.ts`
|
||
- (2026-02-21) Completed `F037`.
|
||
- Confirmed `decision_due_date` recalculates from current assignment state when fixed-term `end_date` changes.
|
||
- Added regression coverage:
|
||
- `recomputes fixed-term decision_due_date when end_date changes`
|
||
- in `packages/billing/tests/clientContractEffectiveRenewalSettings.test.ts`
|
||
- (2026-02-21) Completed `F038`.
|
||
- Confirmed fixed-term `decision_due_date` recalculates when notice period changes.
|
||
- Added regression coverage:
|
||
- `recomputes fixed-term decision_due_date when notice period changes`
|
||
- in `packages/billing/tests/clientContractEffectiveRenewalSettings.test.ts`
|
||
- (2026-02-21) Completed `F039`.
|
||
- Made `decision_due_date` generation renewal-mode-aware in read normalization:
|
||
- mode `none` suppresses due date generation for non-evergreen entries.
|
||
- Added regression coverage for mode transitions:
|
||
- `recomputes decision_due_date when renewal mode changes between none/manual/auto`
|
||
- in `packages/billing/tests/clientContractEffectiveRenewalSettings.test.ts`
|
||
- (2026-02-21) Completed `F040`.
|
||
- Confirmed evergreen `decision_due_date` recomputes when anniversary anchor basis changes (start-date basis change).
|
||
- Added deterministic coverage:
|
||
- `recomputes evergreen decision_due_date when anniversary anchor basis changes`
|
||
- in `packages/billing/tests/clientContractEffectiveRenewalSettings.test.ts`
|
||
- (2026-02-21) Completed `F041`.
|
||
- Added lifecycle suppression in due-date normalization:
|
||
- no `decision_due_date` generation for inactive, terminated, or expired assignment/contract lifecycle state.
|
||
- Included `contract_status` from joined contract reads in shared/clients assignment APIs to enforce lifecycle gating.
|
||
- Added regression test:
|
||
- `skips decision_due_date generation for inactive/terminated assignments`
|
||
- in `packages/billing/tests/clientContractEffectiveRenewalSettings.test.ts`
|
||
- (2026-02-21) Completed `F042`.
|
||
- Verified suppression path for `renewal_mode = none` when no evergreen anchor is available (e.g. fixed-term assignment) remains enforced.
|
||
- Covered by existing regression test:
|
||
- `recomputes decision_due_date when renewal mode changes between none/manual/auto`
|
||
- in `packages/billing/tests/clientContractEffectiveRenewalSettings.test.ts`
|
||
- (2026-02-21) Completed `F043`.
|
||
- Added derived per-cycle dedupe key in read normalization:
|
||
- `renewal_cycle_key` (`fixed-term:<end_date>` or `evergreen:<anchor_date>`)
|
||
- Exposed in both shared and clients assignment APIs plus contract interfaces.
|
||
- Added regression coverage:
|
||
- `creates one renewal_cycle_key per computed contract cycle for deduplication`
|
||
- in `packages/billing/tests/clientContractEffectiveRenewalSettings.test.ts`
|
||
- (2026-02-21) Completed `F044`.
|
||
- Added deterministic dedupe guard for active assignment rows by composite key:
|
||
- `tenant + client_contract_id + renewal_cycle_key`
|
||
- Applied dedupe in list read APIs:
|
||
- `shared/billingClients/clientContracts.ts`
|
||
- `packages/clients/src/models/clientContract.ts`
|
||
- Added regression test:
|
||
- `deduplicates active rows by tenant + client_contract_id + renewal_cycle_key`
|
||
- in `packages/billing/tests/clientContractEffectiveRenewalSettings.test.ts`
|
||
- (2026-02-21) Completed `F045`.
|
||
- Added explicit cycle boundary fields in normalization:
|
||
- `renewal_cycle_start`
|
||
- `renewal_cycle_end`
|
||
- Fixed-term boundaries map directly to assignment `start_date`/`end_date`.
|
||
- Evergreen boundaries now use annual cycle bounds helper:
|
||
- `computeEvergreenCycleBounds` in `shared/billingClients/clientContracts.ts`
|
||
- Added deterministic coverage in `packages/billing/tests/clientContractEffectiveRenewalSettings.test.ts`.
|
||
- (2026-02-21) Completed `F046`.
|
||
- Added derived `days_until_due` field to assignment normalization and contract interfaces.
|
||
- New date-only helper:
|
||
- `computeDaysUntilDate` in `shared/billingClients/clientContracts.ts`
|
||
- Added deterministic coverage for positive/negative day deltas and normalized row field presence in:
|
||
- `packages/billing/tests/clientContractEffectiveRenewalSettings.test.ts`
|
||
- (2026-02-21) Completed `F047`.
|
||
- Added clamp bounds to `days_until_due` derivation to preserve overdue visibility while preventing extreme negative/positive corruption:
|
||
- `MAX_ABSOLUTE_DAYS_UNTIL_DUE = 36500`
|
||
- Applied in shared and clients normalization helpers.
|
||
- Added deterministic clamp coverage in:
|
||
- `packages/billing/tests/clientContractEffectiveRenewalSettings.test.ts`
|
||
- (2026-02-21) Completed `F048`.
|
||
- Added `renewals` tab value to billing tab union/config metadata in:
|
||
- `packages/billing/src/components/billing-dashboard/billingTabsConfig.ts`
|
||
- Added tab definition (`label=Renewals`, `href=/msp/billing?tab=renewals`) and icon mapping.
|
||
- Added coverage:
|
||
- `packages/billing/tests/billingTabsConfig.renewals.test.ts`
|
||
- (2026-02-21) Completed `F049`.
|
||
- Added `Tabs.Content value=\"renewals\"` route to billing dashboard tab host in:
|
||
- `packages/billing/src/components/billing-dashboard/BillingDashboard.tsx`
|
||
- Added initial placeholder content for the renewals route host.
|
||
- Added route-wiring coverage:
|
||
- `packages/billing/tests/BillingDashboard.renewalsRoute.test.ts`
|
||
- (2026-02-21) Completed `F050`.
|
||
- Added dedicated renewals queue page component:
|
||
- `packages/billing/src/components/billing-dashboard/contracts/RenewalsQueueTab.tsx`
|
||
- Updated `BillingDashboard` renewals route to render `<RenewalsQueueTab />`.
|
||
- Added component + wiring coverage:
|
||
- `packages/billing/tests/RenewalsQueueTab.component.test.ts`
|
||
- `packages/billing/tests/BillingDashboard.renewalsRoute.test.ts`
|
||
- (2026-02-21) Completed `F051`.
|
||
- Added server action to load renewal queue rows:
|
||
- `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- Renewals page now calls `listRenewalQueueRows()` on mount via `useEffect` and renders loading/empty/error/data states.
|
||
- Exported renewals queue actions via:
|
||
- `packages/billing/src/actions/index.ts`
|
||
- Added wiring coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.wiring.test.ts`
|
||
- `packages/billing/tests/RenewalsQueueTab.component.test.ts`
|
||
- (2026-02-21) Completed `F052`.
|
||
- Added default 90-day horizon behavior to renewals queue loading:
|
||
- `DEFAULT_RENEWALS_HORIZON_DAYS = 90` in `renewalsQueueActions.ts`
|
||
- server-side filtering for `days_until_due` in range `[0, horizonDays]`
|
||
- Updated renewals UI copy to indicate default horizon window.
|
||
- Extended wiring coverage in:
|
||
- `packages/billing/tests/renewalsQueueActions.wiring.test.ts`
|
||
- `packages/billing/tests/RenewalsQueueTab.component.test.ts`
|
||
- (2026-02-21) Completed `F053`.
|
||
- Added renewals queue bucket quick filters in `RenewalsQueueTab`:
|
||
- `All`, `0-30 Days`, `31-60 Days`, `61-90 Days`
|
||
- Implemented client-side bucket filtering against `days_until_due`.
|
||
- Extended component coverage in:
|
||
- `packages/billing/tests/RenewalsQueueTab.component.test.ts`
|
||
- (2026-02-21) Completed `F054`.
|
||
- Added owner filter UI + behavior in `RenewalsQueueTab`:
|
||
- owner options derive from queue row `assigned_to` values with `unassigned` fallback.
|
||
- Extended queue row shape from server action with `assigned_to`.
|
||
- Added wiring coverage updates in:
|
||
- `packages/billing/tests/RenewalsQueueTab.component.test.ts`
|
||
- `packages/billing/tests/renewalsQueueActions.wiring.test.ts`
|
||
- (2026-02-21) Completed `F055`.
|
||
- Added queue status mapping + filter support for:
|
||
- `pending`, `renewing`, `non_renewing`, `snoozed`, `completed`
|
||
- Added status filter UI + filtering behavior in `RenewalsQueueTab`.
|
||
- Extended action/component wiring coverage in:
|
||
- `packages/billing/tests/renewalsQueueActions.wiring.test.ts`
|
||
- `packages/billing/tests/RenewalsQueueTab.component.test.ts`
|
||
- (2026-02-21) Completed `F056`.
|
||
- Added renewal mode filter support in queue UI for:
|
||
- `none`, `manual`, `auto`
|
||
- Queue row mapping already includes `effective_renewal_mode`; UI filtering now applies this dimension.
|
||
- Extended action/component wiring coverage in:
|
||
- `packages/billing/tests/renewalsQueueActions.wiring.test.ts`
|
||
- `packages/billing/tests/RenewalsQueueTab.component.test.ts`
|
||
- (2026-02-21) Completed `F057`.
|
||
- Added contract type filter support in queue UI for:
|
||
- `fixed-term`, `evergreen`
|
||
- Filter operates on queue row `contract_type`.
|
||
- Extended component wiring coverage in:
|
||
- `packages/billing/tests/RenewalsQueueTab.component.test.ts`
|
||
- (2026-02-21) Completed `F058`.
|
||
- Enforced default queue sort by `decision_due_date` ascending in renewals list action.
|
||
- Sorting now occurs after normalization/horizon filtering in:
|
||
- `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- Added wiring coverage update in:
|
||
- `packages/billing/tests/renewalsQueueActions.wiring.test.ts`
|
||
- (2026-02-21) Completed `F059`.
|
||
- Added days-remaining visual badge state logic in queue rows:
|
||
- `overdue`, `due-soon`, `upcoming`
|
||
- Rendering now surfaces overdue and due-soon emphasis states via row badge styles.
|
||
- Added component coverage update in:
|
||
- `packages/billing/tests/RenewalsQueueTab.component.test.ts`
|
||
- (2026-02-21) Completed `F060`.
|
||
- Added `Upcoming Renewals` summary widget to `ClientContractsTab` with queue-derived total count.
|
||
- Widget data source now loads via `listRenewalQueueRows()` during tab fetch flow.
|
||
- Added coverage:
|
||
- `packages/billing/tests/ClientContractsTab.upcomingRenewalsWidget.test.ts`
|
||
- (2026-02-21) Completed `F061`.
|
||
- Updated `Upcoming Renewals` widget to display 90-day bucket counts:
|
||
- `0-30`, `31-60`, `61-90`
|
||
- Counts now derive from renewal queue row `days_until_due`.
|
||
- Added coverage update in:
|
||
- `packages/billing/tests/ClientContractsTab.upcomingRenewalsWidget.test.ts`
|
||
- (2026-02-21) Completed `F062`.
|
||
- Added widget-to-queue navigation with preserved bucket context in:
|
||
- `packages/billing/src/components/billing-dashboard/contracts/ClientContractsTab.tsx`
|
||
- Bucket count badges now route to:
|
||
- `/msp/billing?tab=renewals&bucket=0-30|31-60|61-90`
|
||
- Added queue hydration from URL bucket query param in:
|
||
- `packages/billing/src/components/billing-dashboard/contracts/RenewalsQueueTab.tsx`
|
||
- Added/updated coverage in:
|
||
- `packages/billing/tests/ClientContractsTab.upcomingRenewalsWidget.test.ts`
|
||
- `packages/billing/tests/RenewalsQueueTab.component.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/ClientContractsTab.upcomingRenewalsWidget.test.ts tests/RenewalsQueueTab.component.test.ts`
|
||
- (2026-02-21) Completed `F063`.
|
||
- Added queue-to-widget refresh wiring in billing dashboard:
|
||
- `packages/billing/src/components/billing-dashboard/BillingDashboard.tsx`
|
||
- `BillingDashboard` now increments `renewalsQueueRefreshTrigger` when renewals queue refreshes after mutation pathways.
|
||
- Passed refresh trigger into `ClientContractsTab` so upcoming renewals bucket counts are recomputed.
|
||
- `RenewalsQueueTab` now accepts `onQueueMutationComplete` and emits it after successful queue row reloads:
|
||
- `packages/billing/src/components/billing-dashboard/contracts/RenewalsQueueTab.tsx`
|
||
- Added wiring coverage in:
|
||
- `packages/billing/tests/BillingDashboard.renewalsRoute.test.ts`
|
||
- `packages/billing/tests/RenewalsQueueTab.component.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/BillingDashboard.renewalsRoute.test.ts tests/RenewalsQueueTab.component.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts`
|
||
- (2026-02-21) Completed `F064`.
|
||
- Defined centralized renewal queue status enum in shared contract interfaces:
|
||
- `packages/types/src/interfaces/contract.interfaces.ts`
|
||
- `server/src/interfaces/contract.interfaces.ts`
|
||
- Added renewal work-item interface model (`IClientContractRenewalWorkItem`) with `status: RenewalWorkItemStatus`.
|
||
- Updated queue row model/status normalization to consume `RenewalWorkItemStatus` from shared types:
|
||
- `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- Updated wiring coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.wiring.test.ts tests/RenewalsQueueTab.component.test.ts`
|
||
- `npm -w @alga-psa/server run typecheck` (workspace alias not present in root workspaces)
|
||
- (2026-02-21) Completed `F065`.
|
||
- Added queue mutation action to transition pending work items to renewing:
|
||
- `markRenewalQueueItemRenewing(clientContractId)` in `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- Transition behavior:
|
||
- validates required `clientContractId`
|
||
- enforces tenant-scoped active row lookup
|
||
- requires current status to resolve as `pending`
|
||
- updates status to `renewing` and writes `updated_at`
|
||
- Added mutation response payload shape:
|
||
- `RenewalQueueMutationResult`
|
||
- Added/updated wiring coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.wiring.test.ts`
|
||
- `packages/billing/tests/renewalsQueueActions.markRenewing.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.wiring.test.ts tests/renewalsQueueActions.markRenewing.wiring.test.ts`
|
||
- (2026-02-21) Completed `F066`.
|
||
- Added queue mutation action to transition pending work items to non-renewing:
|
||
- `markRenewalQueueItemNonRenewing(clientContractId)` in `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- Transition behavior mirrors mark-renewing safeguards:
|
||
- validates required `clientContractId`
|
||
- verifies status column availability
|
||
- enforces tenant-scoped active row lookup
|
||
- requires current status to resolve as `pending`
|
||
- updates status to `non_renewing` and writes `updated_at`
|
||
- Added wiring coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.markNonRenewing.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.markRenewing.wiring.test.ts tests/renewalsQueueActions.markNonRenewing.wiring.test.ts`
|
||
- (2026-02-21) Completed `F067`.
|
||
- Added renewal draft action for eligible queue entries:
|
||
- `createRenewalDraftForQueueItem(clientContractId)` in `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- Action behavior:
|
||
- requires non-empty `clientContractId`
|
||
- resolves eligible statuses to `pending|renewing` only
|
||
- creates a new draft contract + draft client contract assignment
|
||
- reuses existing linked draft when `created_draft_contract_id` is already present and valid
|
||
- links original row via `created_draft_contract_id` when column exists
|
||
- Added response type:
|
||
- `RenewalDraftCreationResult`
|
||
- Added wiring coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.createDraft.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.wiring.test.ts tests/renewalsQueueActions.markRenewing.wiring.test.ts tests/renewalsQueueActions.markNonRenewing.wiring.test.ts tests/renewalsQueueActions.createDraft.wiring.test.ts`
|
||
- (2026-02-21) Completed `F068`.
|
||
- Added snooze mutation action:
|
||
- `snoozeRenewalQueueItem(clientContractId, snoozedUntil)` in `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- Action behavior:
|
||
- validates required `clientContractId` + `snoozedUntil`
|
||
- verifies `status` + `snoozed_until` columns exist
|
||
- normalizes `snoozed_until` to date-only (`YYYY-MM-DD`)
|
||
- blocks snoozing from terminal statuses (`completed`, `non_renewing`)
|
||
- updates status to `snoozed` and returns `RenewalSnoozeResult`
|
||
- Added wiring coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.snooze.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.snooze.wiring.test.ts tests/renewalsQueueActions.markRenewing.wiring.test.ts tests/renewalsQueueActions.markNonRenewing.wiring.test.ts tests/renewalsQueueActions.createDraft.wiring.test.ts`
|
||
- (2026-02-21) Completed `F069`.
|
||
- Added assign-owner mutation action:
|
||
- `assignRenewalQueueItemOwner(clientContractId, assignedTo)` in `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- Action behavior:
|
||
- validates required `clientContractId`
|
||
- allows `assignedTo` as user id string or `null` (unassign)
|
||
- verifies `status` + `assigned_to` columns exist
|
||
- updates `assigned_to` with tenant-scoped row filtering
|
||
- returns `RenewalAssignmentResult` with current status + updated timestamp
|
||
- Added wiring coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.assignOwner.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.assignOwner.wiring.test.ts tests/renewalsQueueActions.snooze.wiring.test.ts tests/renewalsQueueActions.createDraft.wiring.test.ts`
|
||
- (2026-02-21) Completed `F070`.
|
||
- Added automatic unsnooze transition during queue list refresh in:
|
||
- `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- Behavior:
|
||
- checks `status` + `snoozed_until` columns
|
||
- moves eligible rows from `snoozed` to `pending` when `snoozed_until <= today`
|
||
- clears `snoozed_until` and updates `updated_at`
|
||
- Added wiring coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.unsnooze.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.unsnooze.wiring.test.ts tests/renewalsQueueActions.wiring.test.ts tests/renewalsQueueActions.snooze.wiring.test.ts`
|
||
- (2026-02-21) Completed `F071`.
|
||
- Added actor audit persistence helper flow in renewal queue actions:
|
||
- `resolveActorUserId(user)`
|
||
- `withActionActor(updateData, hasLastActionByColumn, actorUserId)`
|
||
- User-initiated queue mutations now persist `last_action_by` when column exists:
|
||
- `markRenewalQueueItemRenewing`
|
||
- `markRenewalQueueItemNonRenewing`
|
||
- `createRenewalDraftForQueueItem`
|
||
- `snoozeRenewalQueueItem`
|
||
- `assignRenewalQueueItemOwner`
|
||
- Added wiring coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.actorAudit.wiring.test.ts`
|
||
- Updated wiring expectations for mark actions:
|
||
- `packages/billing/tests/renewalsQueueActions.markRenewing.wiring.test.ts`
|
||
- `packages/billing/tests/renewalsQueueActions.markNonRenewing.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.actorAudit.wiring.test.ts tests/renewalsQueueActions.markRenewing.wiring.test.ts tests/renewalsQueueActions.markNonRenewing.wiring.test.ts tests/renewalsQueueActions.createDraft.wiring.test.ts tests/renewalsQueueActions.snooze.wiring.test.ts tests/renewalsQueueActions.assignOwner.wiring.test.ts`
|
||
- (2026-02-21) Completed `F072`.
|
||
- Added timestamp audit persistence helper in renewal queue actions:
|
||
- `withActionTimestamp(updateData, hasLastActionAtColumn, actionAt)`
|
||
- User-initiated queue mutations now persist `last_action_at` when column exists:
|
||
- `markRenewalQueueItemRenewing`
|
||
- `markRenewalQueueItemNonRenewing`
|
||
- `createRenewalDraftForQueueItem`
|
||
- `snoozeRenewalQueueItem`
|
||
- `assignRenewalQueueItemOwner`
|
||
- Added wiring coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.timestampAudit.wiring.test.ts`
|
||
- Updated wiring expectations for mark/actor tests:
|
||
- `packages/billing/tests/renewalsQueueActions.markRenewing.wiring.test.ts`
|
||
- `packages/billing/tests/renewalsQueueActions.markNonRenewing.wiring.test.ts`
|
||
- `packages/billing/tests/renewalsQueueActions.actorAudit.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.timestampAudit.wiring.test.ts tests/renewalsQueueActions.actorAudit.wiring.test.ts tests/renewalsQueueActions.markRenewing.wiring.test.ts tests/renewalsQueueActions.markNonRenewing.wiring.test.ts tests/renewalsQueueActions.createDraft.wiring.test.ts tests/renewalsQueueActions.snooze.wiring.test.ts tests/renewalsQueueActions.assignOwner.wiring.test.ts`
|
||
- (2026-02-21) Completed `F073`.
|
||
- Added optional queue action note support across mutation actions:
|
||
- `markRenewalQueueItemRenewing(..., note?)`
|
||
- `markRenewalQueueItemNonRenewing(..., note?)`
|
||
- `createRenewalDraftForQueueItem(..., note?)`
|
||
- `snoozeRenewalQueueItem(..., note?)`
|
||
- `assignRenewalQueueItemOwner(..., note?)`
|
||
- Added note helpers:
|
||
- `normalizeActionNote(note)`
|
||
- `withActionNote(updateData, hasLastActionNoteColumn, note)`
|
||
- Mutations now persist `last_action_note` when column exists and note is non-empty.
|
||
- Added wiring coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.noteAudit.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.noteAudit.wiring.test.ts tests/renewalsQueueActions.timestampAudit.wiring.test.ts tests/renewalsQueueActions.actorAudit.wiring.test.ts tests/renewalsQueueActions.markRenewing.wiring.test.ts tests/renewalsQueueActions.markNonRenewing.wiring.test.ts tests/renewalsQueueActions.createDraft.wiring.test.ts tests/renewalsQueueActions.snooze.wiring.test.ts tests/renewalsQueueActions.assignOwner.wiring.test.ts`
|
||
- (2026-02-21) Completed `F074`.
|
||
- Added explicit completed-status guard in automatic unsnooze pending-transition path:
|
||
- `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- Unsnooze update now includes:
|
||
- `.andWhereNot('status', 'completed')`
|
||
- This ensures completed work items never implicitly transition back to pending without an explicit reopen flow.
|
||
- Updated coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.unsnooze.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.unsnooze.wiring.test.ts tests/renewalsQueueActions.noteAudit.wiring.test.ts tests/renewalsQueueActions.timestampAudit.wiring.test.ts`
|
||
- (2026-02-21) Completed `F075`.
|
||
- Added explicit override guard to renewing transition:
|
||
- `markRenewalQueueItemRenewing` now rejects `previousStatus === 'non_renewing'` with an override-required error.
|
||
- This preserves strict non-renewal intent unless a dedicated override flow is implemented.
|
||
- Updated wiring coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.markRenewing.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.markRenewing.wiring.test.ts tests/renewalsQueueActions.markNonRenewing.wiring.test.ts`
|
||
- (2026-02-21) Completed `F076`.
|
||
- Added future-date enforcement for snooze action validation:
|
||
- `snoozeRenewalQueueItem` now rejects `snoozedUntil <= today`
|
||
- Added explicit error path:
|
||
- `Snooze target date must be in the future`
|
||
- Updated wiring coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.snooze.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.snooze.wiring.test.ts tests/renewalsQueueActions.unsnooze.wiring.test.ts`
|
||
- (2026-02-21) Completed `F077`.
|
||
- Added row-level action availability model based on effective queue status:
|
||
- `RenewalQueueAction` union
|
||
- `getAvailableActionsForStatus(status)` in `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- `listRenewalQueueRows` now returns `available_actions` for each row.
|
||
- Renewals queue UI now surfaces available actions per row:
|
||
- `Actions: {row.available_actions.join(', ')}` in `packages/billing/src/components/billing-dashboard/contracts/RenewalsQueueTab.tsx`
|
||
- Updated coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.wiring.test.ts`
|
||
- `packages/billing/tests/RenewalsQueueTab.component.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.wiring.test.ts tests/RenewalsQueueTab.component.test.ts`
|
||
- (2026-02-21) Completed `F078`.
|
||
- Added queue row action controls for:
|
||
- `Mark renewing`
|
||
- `Mark non-renewing`
|
||
- Implemented optimistic in-flight UI behavior in `RenewalsQueueTab`:
|
||
- per-row pending state map (`pendingRowActions`)
|
||
- immediate optimistic status/action updates before server response
|
||
- in-row pending indicator (`Updating action...`)
|
||
- action buttons disabled while row mutation is in-flight
|
||
- Mutation handlers call server actions:
|
||
- `markRenewalQueueItemRenewing`
|
||
- `markRenewalQueueItemNonRenewing`
|
||
- Updated coverage:
|
||
- `packages/billing/tests/RenewalsQueueTab.component.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/RenewalsQueueTab.component.test.ts tests/renewalsQueueActions.wiring.test.ts`
|
||
- (2026-02-21) Completed `F079`.
|
||
- Added targeted row refresh helper after successful mutation responses:
|
||
- `refreshQueueRowFromServer(clientContractId)` in `RenewalsQueueTab`
|
||
- Success path now refreshes only the affected row from server state:
|
||
- `await refreshQueueRowFromServer(rowId)`
|
||
- Fallback path still supports full refresh when row cannot be resolved.
|
||
- Updated coverage:
|
||
- `packages/billing/tests/RenewalsQueueTab.component.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/RenewalsQueueTab.component.test.ts`
|
||
- (2026-02-21) Completed `F080`.
|
||
- Extended renewal queue row model with draft linkage:
|
||
- `created_draft_contract_id?: string | null` in `RenewalQueueRow`
|
||
- Queue list action now maps draft linkage field from row source:
|
||
- `created_draft_contract_id: (row as any).created_draft_contract_id ?? null`
|
||
- Renewals queue UI now shows linked draft id when present:
|
||
- `Draft contract: {row.created_draft_contract_id}`
|
||
- Updated coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.wiring.test.ts`
|
||
- `packages/billing/tests/RenewalsQueueTab.component.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.wiring.test.ts tests/RenewalsQueueTab.component.test.ts tests/renewalsQueueActions.createDraft.wiring.test.ts`
|
||
- (2026-02-21) Completed `F081`.
|
||
- Extended renewal queue row model with ticket linkage:
|
||
- `created_ticket_id?: string | null` in `RenewalQueueRow`
|
||
- Queue list action now maps ticket linkage:
|
||
- `created_ticket_id: (row as any).created_ticket_id ?? null`
|
||
- Renewals queue UI now shows linked ticket id when present:
|
||
- `Ticket: {row.created_ticket_id}`
|
||
- Updated coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.wiring.test.ts`
|
||
- `packages/billing/tests/RenewalsQueueTab.component.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.wiring.test.ts tests/RenewalsQueueTab.component.test.ts`
|
||
- (2026-02-21) Completed `F082`.
|
||
- Added activation-confirmed completion action:
|
||
- `completeRenewalQueueItemForActivation(clientContractId, activatedContractId?, note?)`
|
||
- in `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- Completion rules:
|
||
- source work item must be `renewing`
|
||
- target renewal contract must exist with `status = active`
|
||
- on success, work item transitions to `completed` with audit metadata
|
||
- Added result type:
|
||
- `RenewalCompletionResult`
|
||
- Added wiring coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.completeOnActivation.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.completeOnActivation.wiring.test.ts tests/renewalsQueueActions.markRenewing.wiring.test.ts tests/renewalsQueueActions.createDraft.wiring.test.ts`
|
||
- (2026-02-21) Completed `F083`.
|
||
- Added non-renewal finalization completion action:
|
||
- `completeRenewalQueueItemForNonRenewal(clientContractId, note?)`
|
||
- in `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- Completion rules:
|
||
- source work item must be `non_renewing`
|
||
- on success, work item transitions to `completed` with audit metadata
|
||
- Added wiring coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.completeNonRenewal.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.completeNonRenewal.wiring.test.ts tests/renewalsQueueActions.completeOnActivation.wiring.test.ts`
|
||
- (2026-02-21) Completed `F084`.
|
||
- Added a scheduled renewal queue processor job handler:
|
||
- `processRenewalQueueHandler(data)` in `server/src/lib/jobs/handlers/processRenewalQueueHandler.ts`
|
||
- scans active contracts whose `decision_due_date` falls within `today..horizonDays`
|
||
- defaults horizon to `90` days and validates `tenantId`
|
||
- Registered new job name and scheduling helpers:
|
||
- pg-boss handler registration in `server/src/lib/jobs/index.ts`
|
||
- recurring scheduling helper `scheduleRenewalQueueProcessingJob(...)`
|
||
- tenant startup scheduling hook in `server/src/lib/jobs/initializeScheduledJobs.ts` (daily at `0 5 * * *`)
|
||
- abstraction-layer handler registration + available handler list in `server/src/lib/jobs/registerAllHandlers.ts`
|
||
- Added wiring test under included Vitest paths:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npm run typecheck`
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F085`.
|
||
- Extended renewal queue processor to upsert work-item state for newly eligible cycles:
|
||
- processor now loads active contract assignments, normalizes effective renewal state, and filters by computed `decision_due_date` within `today..horizon`
|
||
- upserts `decision_due_date`, `renewal_cycle_start`, `renewal_cycle_end`, and `renewal_cycle_key` when drift/new cycle is detected
|
||
- resets cycle-scoped linkage fields (`created_ticket_id`, `created_draft_contract_id`) when cycle key rolls
|
||
- normalizes unknown/invalid statuses (or cycle changes) back to `pending`
|
||
- Updated wiring coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npm run typecheck`
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F086`.
|
||
- Scheduled renewal processing now explicitly resolves tenant default due-date action policy:
|
||
- reads `default_billing_settings.renewal_due_date_action_policy` when available
|
||
- normalizes policy (`queue_only | create_ticket`) with deterministic fallback to `create_ticket`
|
||
- During upsert, processor applies tenant policy to work-item rows when contract-level policy column exists:
|
||
- updates `client_contracts.renewal_due_date_action_policy` to tenant effective value
|
||
- tracks policy distribution in logs (`queueOnlyPolicyCount`, `createTicketPolicyCount`)
|
||
- Updated wiring coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npm run typecheck`
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F087`.
|
||
- Scheduled renewal processing now applies contract-level due-date policy overrides with deterministic precedence:
|
||
- resolve `use_tenant_renewal_defaults` (default `true`)
|
||
- resolve contract-level policy from `client_contracts.renewal_due_date_action_policy` when valid
|
||
- compute effective policy as:
|
||
- tenant policy when `use_tenant_renewal_defaults = true`
|
||
- contract override when defaults are disabled and explicit contract policy exists
|
||
- tenant fallback when override is missing/invalid
|
||
- Processor now logs override utilization:
|
||
- `contractOverridePolicyCount`
|
||
- Updated wiring coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npm run typecheck`
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F088`.
|
||
- Added due-date ticket automation execution in renewal processor:
|
||
- computes `shouldCreateTicketAtDueDate` for eligible rows where:
|
||
- effective policy is `create_ticket`
|
||
- decision due date is due (`<= today`)
|
||
- no `created_ticket_id` is already linked
|
||
- builds renewal-context title/description payloads
|
||
- uses configured renewal routing defaults (board/status/priority/assignee) when present
|
||
- Processor now persists ticket linkage on success:
|
||
- `updates.created_ticket_id = createdTicketId`
|
||
- Added direct ticket-creation fallback path for resilience when workflow action execution is unavailable.
|
||
- Updated wiring coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npm run typecheck`
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F089`.
|
||
- Integrated renewal ticket automation with workflow runtime business action path:
|
||
- initializes runtime v2 action registry (`initializeWorkflowRuntimeV2`)
|
||
- resolves and invokes `tickets.create@v1` from `getActionRegistryV2`
|
||
- validates both input and output schemas via registered action definitions
|
||
- Retained direct-ticket fallback path when runtime action execution is unavailable/fails to keep automation robust.
|
||
- Updated wiring coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npm run typecheck`
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F090`.
|
||
- Added renewal ticket title builder with explicit client + contract context:
|
||
- `buildRenewalTicketTitle(row, decisionDueDate)`
|
||
- title shape: `Renewal Decision Due {date}: {clientName} / {contractName}`
|
||
- Renewal automation now uses this title for both workflow-action and direct-fallback ticket creation paths.
|
||
- Updated wiring coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npm run typecheck`
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F091`.
|
||
- Added renewal ticket description builder with due-date + renewal-settings context:
|
||
- `buildRenewalTicketDescription(row, normalized, decisionDueDate)`
|
||
- includes decision due date, effective renewal mode, effective notice period, and cycle key metadata
|
||
- Renewal automation now uses this description for workflow-action and direct-fallback ticket creation paths.
|
||
- Updated wiring coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npm run typecheck`
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F092`.
|
||
- Renewal ticket routing now uses effective defaults with tenant/contract precedence:
|
||
- tenant defaults from `default_billing_settings`:
|
||
- `renewal_ticket_board_id`
|
||
- `renewal_ticket_status_id`
|
||
- `renewal_ticket_priority`
|
||
- `renewal_ticket_assignee_id`
|
||
- optional contract-level overrides from `client_contracts` are applied when `use_tenant_renewal_defaults = false`
|
||
- deterministic fallback to tenant defaults for any missing contract-level routing values
|
||
- Added processor visibility metric:
|
||
- `routingOverrideAppliedCount`
|
||
- Updated wiring coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npm run typecheck`
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F093`.
|
||
- Renewal processor now persists ticket linkage on successful automation:
|
||
- captures ticket id from workflow-action/direct-fallback creation result
|
||
- writes `created_ticket_id` on the client-contract renewal work item update payload
|
||
- This makes ticket linkage visible in queue APIs/UI and supports downstream idempotency checks.
|
||
- Updated wiring coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npm run typecheck`
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F094`.
|
||
- Added deterministic renewal ticket idempotency key builder:
|
||
- shape: `renewal-ticket:{tenantId}:{clientContractId}:{cycleKey}`
|
||
- Processor now uses this idempotency key for:
|
||
- workflow runtime `tickets.create` invocation input (`idempotency_key`)
|
||
- direct fallback ticket attributes (`idempotency_key`) for duplicate-detection context
|
||
- Updated wiring coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npm run typecheck`
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F095`.
|
||
- Added duplicate-prevention lookup before renewal ticket creation:
|
||
- checks existing `tickets` rows for matching `attributes.idempotency_key`
|
||
- if found, links existing ticket id to work item and skips create path
|
||
- Both workflow and direct ticket creation paths now receive shared ticket attributes including idempotency metadata.
|
||
- Added processor metric:
|
||
- `duplicateTicketSkipCount`
|
||
- Updated wiring coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npm run typecheck`
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F096`.
|
||
- Renewal processor now records automation failures on work items when ticket creation fails:
|
||
- reads optional `client_contracts.automation_error` column
|
||
- writes failure reason on create-path errors
|
||
- records missing-routing-defaults as explicit automation error for `create_ticket` policy
|
||
- clears `automation_error` when ticket creation succeeds
|
||
- Added processor metric:
|
||
- `automationErrorCount`
|
||
- Updated wiring coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npm run typecheck`
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F097`.
|
||
- Added manual retry queue action for failed renewal ticket automation:
|
||
- `retryRenewalQueueTicketCreation(clientContractId)` in `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- Retry action behavior:
|
||
- validates work item + due-date eligibility
|
||
- resolves effective due-date policy and routing defaults with tenant/contract precedence
|
||
- reuses cycle idempotency key to avoid duplicates
|
||
- links existing idempotent ticket when present
|
||
- otherwise re-attempts ticket creation and updates `created_ticket_id` / `automation_error`
|
||
- Exposed `automation_error` in renewal queue row payload model.
|
||
- Updated coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.retryTicket.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.retryTicket.wiring.test.ts tests/renewalsQueueActions.wiring.test.ts`
|
||
- (2026-02-21) Completed `F098`.
|
||
- Queue-only policy behavior is enforced in both automation paths:
|
||
- scheduled processor only enters ticket-create path when `effectiveDueDateActionPolicy === 'create_ticket'`
|
||
- manual retry action returns without creating tickets when effective policy is `queue_only`
|
||
- This preserves queue visibility/workflow without forcing ticket side effects.
|
||
- Updated coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- `packages/billing/tests/renewalsQueueActions.retryTicket.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npm run typecheck`
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.retryTicket.wiring.test.ts tests/renewalsQueueActions.wiring.test.ts`
|
||
- (2026-02-21) Completed `F099`.
|
||
- Updated contract renewal-upcoming domain-event builders/schemas for queue-compatible semantics:
|
||
- expanded default window from 30 to 90 days
|
||
- `computeContractRenewalUpcoming` now supports decision-due date and renewal cycle key inputs
|
||
- payload now includes:
|
||
- `decisionDueDate`
|
||
- `daysUntilDecisionDue`
|
||
- `renewalCycleKey`
|
||
- Updated event publishers in:
|
||
- `packages/billing/src/actions/contractWizardActions.ts`
|
||
- `packages/clients/src/actions/clientContractActions.ts`
|
||
- `CONTRACT_RENEWAL_UPCOMING` idempotency keys now prefer cycle-key/decision-due identity where available.
|
||
- Added wiring coverage:
|
||
- `packages/billing/tests/contractRenewalUpcomingEvent.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `npm -w @alga-psa/clients run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/renewalsQueueActions.retryTicket.wiring.test.ts`
|
||
- Note:
|
||
- direct execution of `shared/workflow/streams/domainEventBuilders/__tests__/contractEventBuilders.test.ts` under current Vitest include globs returned “No test files found”; wiring assertions were added in billing tests to cover this change.
|
||
- (2026-02-21) Completed `F100`.
|
||
- Confirmed evergreen renewal queue generation path in scheduled processor:
|
||
- processor normalizes each contract with `normalizeClientContract` (which computes evergreen annual-cycle decision dates)
|
||
- upserts normalized cycle boundaries and cycle key:
|
||
- `renewal_cycle_start`
|
||
- `renewal_cycle_end`
|
||
- `renewal_cycle_key`
|
||
- includes evergreen entries whenever computed decision due date is within the processing horizon
|
||
- Updated coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npm run typecheck`
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F101`.
|
||
- Added explicit per-row contract type badge rendering in Renewals queue UI:
|
||
- evergreen rows now show `Evergreen` badge
|
||
- fixed-term rows show `Fixed-term` badge
|
||
- Implemented in:
|
||
- `packages/billing/src/components/billing-dashboard/contracts/RenewalsQueueTab.tsx`
|
||
- Added component wiring assertions:
|
||
- `packages/billing/tests/RenewalsQueueTab.component.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- (2026-02-21) Completed `F102`.
|
||
- Added evergreen cycle anchor detail to renewal queue rows.
|
||
- Queue row model now surfaces:
|
||
- `evergreen_cycle_anchor_date` (from `evergreen_review_anchor_date`, fallback `renewal_cycle_end`)
|
||
- UI now renders evergreen-only row detail:
|
||
- `Evergreen anchor: <date>`
|
||
- Updated wiring coverage:
|
||
- `packages/billing/tests/RenewalsQueueTab.component.test.ts`
|
||
- `packages/billing/tests/renewalsQueueActions.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/RenewalsQueueTab.component.test.ts tests/renewalsQueueActions.wiring.test.ts --coverage=false`
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- (2026-02-21) Completed `F103`.
|
||
- Confirmed evergreen entries share the same mark-renewing transition path as fixed-term entries:
|
||
- queue action availability is status-driven (`pending` includes `mark_renewing`)
|
||
- mark-renewing mutation path has no contract-type/end-date gate
|
||
- Added dedicated wiring coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.markRenewingEvergreen.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.markRenewing.wiring.test.ts tests/renewalsQueueActions.markRenewingEvergreen.wiring.test.ts --coverage=false`
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- (2026-02-21) Completed `F104`.
|
||
- Confirmed evergreen entries share the same mark-non-renewing transition path as fixed-term entries:
|
||
- queue action availability remains status-driven
|
||
- mark-non-renewing mutation path has no contract-type/end-date gate
|
||
- Added dedicated wiring coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.markNonRenewingEvergreen.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.markNonRenewing.wiring.test.ts tests/renewalsQueueActions.markNonRenewingEvergreen.wiring.test.ts --coverage=false`
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- (2026-02-21) Completed `F105`.
|
||
- Confirmed create-renewal-draft action supports evergreen entries:
|
||
- mutation eligibility is status-driven (`pending` / `renewing`)
|
||
- draft assignment creation logic supports null `end_date` (evergreen) while preserving start-date semantics
|
||
- Added dedicated wiring coverage:
|
||
- `packages/billing/tests/renewalsQueueActions.createDraftEvergreen.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.createDraft.wiring.test.ts tests/renewalsQueueActions.createDraftEvergreen.wiring.test.ts --coverage=false`
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- (2026-02-21) Completed `F106`.
|
||
- Confirmed evergreen cycle rollover semantics in scheduled renewal processing:
|
||
- when cycle key advances, processor treats it as a new cycle (`cycleChanged`)
|
||
- status normalization reopens work item to `pending`
|
||
- updated cycle key is persisted and cycle-change counters increment
|
||
- Added explicit rollover wiring coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- `cd server && npm run typecheck`
|
||
- (2026-02-21) Completed `F107`.
|
||
- Added cycle-level deduplication guard in scheduled renewal processing to prevent duplicate handling of the same contract/cycle period:
|
||
- dedupe identity: `client_contract_id + cycleKey` (fallback to `decision_due_date`)
|
||
- duplicate entries are skipped and counted in processor metrics
|
||
- This hardens evergreen annual-cycle processing against duplicate row inputs from upstream query/join behavior.
|
||
- Updated coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- `cd server && npm run typecheck`
|
||
- (2026-02-21) Completed `F108`.
|
||
- Added regression coverage confirming evergreen decision due date uses contract-level notice-period override when tenant defaults are disabled.
|
||
- Covered both branches:
|
||
- tenant defaults enabled => tenant notice period drives evergreen decision date
|
||
- tenant defaults disabled => contract override notice period drives evergreen decision date
|
||
- Updated coverage:
|
||
- `packages/billing/tests/clientContractEffectiveRenewalSettings.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/clientContractEffectiveRenewalSettings.test.ts --coverage=false`
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- (2026-02-21) Completed `F109`.
|
||
- Updated `ClientContractsTab` upcoming-renewals widget bucketing to explicitly include both contract types:
|
||
- `fixed-term`
|
||
- `evergreen`
|
||
- Added explicit widget wiring coverage to ensure evergreen entries are included in bucket counts.
|
||
- Updated files:
|
||
- `packages/billing/src/components/billing-dashboard/contracts/ClientContractsTab.tsx`
|
||
- `packages/billing/tests/ClientContractsTab.upcomingRenewalsWidget.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- (2026-02-21) Completed `F110`.
|
||
- Extended expiration-report action payload to include `decision_due_date` alongside `end_date` when present.
|
||
- Updated `ContractExpiration` type and query mapping in:
|
||
- `packages/billing/src/actions/contractReportActions.ts`
|
||
- Added wiring coverage:
|
||
- `packages/billing/tests/contractReportActions.expiration.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/contractReportActions.expiration.wiring.test.ts --coverage=false`
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- (2026-02-21) Completed `F111`.
|
||
- Extended expiration-report rows to include `renewal_mode`.
|
||
- Updated report contract type in:
|
||
- `packages/billing/src/actions/contractReportActions.ts`
|
||
- Expanded wiring coverage:
|
||
- `packages/billing/tests/contractReportActions.expiration.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/contractReportActions.expiration.wiring.test.ts --coverage=false`
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- (2026-02-21) Completed `F112`.
|
||
- Extended expiration-report rows to include renewal queue state when present (`queue_status` from `client_contracts.status`).
|
||
- Updated files:
|
||
- `packages/billing/src/actions/contractReportActions.ts`
|
||
- `packages/billing/tests/contractReportActions.expiration.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/contractReportActions.expiration.wiring.test.ts --coverage=false`
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- (2026-02-21) Completed `F113`.
|
||
- Preserved existing fixed-term expiration inclusion semantics while adding renewal metadata:
|
||
- expiration rows still key off `end_date` presence
|
||
- no hard requirement for `renewal_mode` to be set
|
||
- Added explicit compatibility coverage in:
|
||
- `packages/billing/tests/contractReportActions.expiration.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/contractReportActions.expiration.wiring.test.ts --coverage=false`
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- (2026-02-21) Completed `F114`.
|
||
- Preserved expiration-report sort compatibility for existing consumers:
|
||
- primary ordering remains `cc.end_date ASC`
|
||
- dedupe key remains based on contract/client/end-date identity
|
||
- Added explicit compatibility assertions in:
|
||
- `packages/billing/tests/contractReportActions.expiration.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/contractReportActions.expiration.wiring.test.ts --coverage=false`
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- (2026-02-21) Completed `F115`.
|
||
- Extended report summary payload with `atRiskDecisionCount` for dashboard consumption.
|
||
- At-risk metric now counts active client-contract assignments with `decision_due_date` in the next 90 days.
|
||
- Updated files:
|
||
- `packages/billing/src/actions/contractReportActions.ts`
|
||
- `packages/billing/tests/contractReportActions.summary.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/contractReportActions.summary.wiring.test.ts tests/contractReportActions.expiration.wiring.test.ts --coverage=false`
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- (2026-02-21) Completed `F116`.
|
||
- Updated Contract Reports expiration tab copy to reference renewal decisions in addition to expirations.
|
||
- Updated UX copy in:
|
||
- `packages/billing/src/components/billing-dashboard/reports/ContractReports.tsx`
|
||
- Added wiring coverage:
|
||
- `packages/billing/tests/ContractReports.expirationCopy.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/ContractReports.expirationCopy.wiring.test.ts tests/contractReportActions.summary.wiring.test.ts tests/contractReportActions.expiration.wiring.test.ts --coverage=false`
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- (2026-02-21) Completed `F117`.
|
||
- Updated expiration-report row construction so legacy `auto_renew` display derives from effective renewal mode values.
|
||
- Effective renewal mode now resolves with tenant-default precedence logic:
|
||
- honors `use_tenant_renewal_defaults`
|
||
- falls back deterministically between contract/tenant/default (`manual`)
|
||
- `auto_renew` now maps to `effectiveRenewalMode === 'auto'`.
|
||
- Updated files:
|
||
- `packages/billing/src/actions/contractReportActions.ts`
|
||
- `packages/billing/tests/contractReportActions.expiration.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/contractReportActions.expiration.wiring.test.ts tests/contractReportActions.summary.wiring.test.ts tests/ContractReports.expirationCopy.wiring.test.ts --coverage=false`
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- (2026-02-21) Completed `F118`.
|
||
- Confirmed renewal scheduled processor registration in the on-prem pg-boss scheduled initialization path:
|
||
- tenant loop schedules `process-renewal-queue` via `scheduleRenewalQueueProcessingJob(tenantId, 90, cron)`
|
||
- includes both first-schedule and singleton-already-scheduled handling logs
|
||
- Updated coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- `cd server && npm run typecheck`
|
||
- (2026-02-21) Completed `F119`.
|
||
- Added Temporal runner coverage proving renewal scheduled processing can be registered as a recurring Temporal workflow:
|
||
- schedules `process-renewal-queue` with tenant + horizon payload
|
||
- validates Temporal schedule action carries renewal job name/data
|
||
- Updated coverage:
|
||
- `ee/server/src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`
|
||
- Validation:
|
||
- `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`
|
||
- Note:
|
||
- `npm --prefix ee/server run test:unit -- src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts` executes the full unit suite in this workspace and currently surfaces unrelated pre-existing failures in other unit files; targeted execution of the modified test passes.
|
||
- (2026-02-21) Completed `F120`.
|
||
- Confirmed renewal processing uses a shared core handler callable from both runtime adapters:
|
||
- legacy pg-boss registration path (`index.ts`) calls `processRenewalQueueHandler`
|
||
- centralized handler registry (`registerAllHandlers.ts`) also calls the same handler for Temporal/runner abstraction execution
|
||
- `initializeJobRunner.ts` bridges registered handlers into runner implementations
|
||
- Updated coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- `cd server && npm run typecheck`
|
||
- (2026-02-21) Completed `F121`.
|
||
- Added parity coverage confirming queue-creation payload shape is equivalent across runner paths:
|
||
- pg-boss scheduling uses `process-renewal-queue` with `{ tenantId, horizonDays }`
|
||
- Temporal recurring workflow action forwards `jobName`, `tenantId`, and `data` through `genericJobWorkflow`
|
||
- Updated coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- `cd server && npm run typecheck`
|
||
- (2026-02-21) Completed `F122`.
|
||
- Added runtime-parity coverage confirming ticket idempotency behavior is shared across runner paths because both execute the same renewal processor core:
|
||
- shared idempotency key construction
|
||
- duplicate-ticket lookup by idempotency attribute
|
||
- shared duplicate-skip semantics
|
||
- Updated coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- `cd server && npm run typecheck`
|
||
- (2026-02-21) Completed `F123`.
|
||
- Added wiring coverage confirming runtime selection stays in `JobRunnerFactory` and renewal business logic remains runner/edition agnostic:
|
||
- runner type resolution via config/env (`JOB_RUNNER_TYPE`)
|
||
- renewal processor contains no edition/runtime branching
|
||
- Updated coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- `cd server && npm run typecheck`
|
||
|
||
## Open Questions
|
||
- Should renewal ticket defaults be a brand-new billing settings card, or an extension of existing default ticket settings patterns?
|
||
- Should evergreen annual review use contract start-date anniversary or configurable anchor date in v1?
|
||
- Should renewal status transitions hard-lock contract activation behavior, or remain advisory with warnings in v1?
|
||
- (2026-02-21) Completed `F124`.
|
||
- Added explicit runtime-fallback coverage confirming Temporal bootstrap failures gracefully fall back to pg-boss when fallback is enabled.
|
||
- Assertions verify:
|
||
- Temporal path attempted first for EE/runtime selection
|
||
- fallback gate checks `config?.fallbackToPgBoss !== false`
|
||
- fallback execution calls `createPgBossRunner(config)`
|
||
- Temporal bootstrap/import failures remain surfaced and handled by fallback branch
|
||
- Updated coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F125`.
|
||
- Added tenant-scope parity coverage across pg-boss and Temporal renewal runtime paths.
|
||
- Assertions verify:
|
||
- scheduler payload requires and forwards tenant id for renewal processing
|
||
- renewal processor enforces tenant id and scopes reads/writes by tenant
|
||
- Temporal runner enforces tenant id in job data and propagates tenant scope into workflow/job persistence
|
||
- Updated coverage:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F126`.
|
||
- Enforced billing read authorization on renewals queue list endpoint.
|
||
- `listRenewalQueueRows` now gates access via `hasPermission(user, 'billing', 'read')` and throws `Permission denied: Cannot read renewals queue` when unauthorized.
|
||
- Updated files:
|
||
- `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- `packages/billing/tests/renewalsQueueActions.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F127`.
|
||
- Enforced billing update authorization on all renewals queue mutation endpoints.
|
||
- Added shared guard `requireBillingUpdatePermission(user)` and applied it to:
|
||
- `markRenewalQueueItemRenewing`
|
||
- `markRenewalQueueItemNonRenewing`
|
||
- `createRenewalDraftForQueueItem`
|
||
- `snoozeRenewalQueueItem`
|
||
- `assignRenewalQueueItemOwner`
|
||
- `completeRenewalQueueItemForActivation`
|
||
- `completeRenewalQueueItemForNonRenewal`
|
||
- `retryRenewalQueueTicketCreation`
|
||
- Updated files:
|
||
- `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- `packages/billing/tests/renewalsQueueActions.permissions.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.wiring.test.ts tests/renewalsQueueActions.permissions.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F128`.
|
||
- Enforced billing settings update authorization on renewal default writes.
|
||
- `updateDefaultBillingSettings` now requires `hasPermission(user, 'billing_settings', 'update')` and rejects unauthorized callers.
|
||
- Updated files:
|
||
- `packages/billing/src/actions/billingSettingsActions.ts`
|
||
- `packages/billing/tests/billingSettingsActions.renewalPermissions.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/billingSettingsActions.renewalPermissions.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F129`.
|
||
- Added explicit wiring coverage that renewal work-item read paths are tenant-scoped by default.
|
||
- Coverage asserts tenant filtering across list/read query builders in renewals queue actions.
|
||
- Updated file:
|
||
- `packages/billing/tests/renewalsQueueActions.tenantReads.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.tenantReads.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F130`.
|
||
- Added wiring coverage that renewal work-item mutation/write paths remain tenant-filtered by default.
|
||
- Coverage checks tenant-scoped update/insert/lookup clauses in renewals queue action writes.
|
||
- Updated file:
|
||
- `packages/billing/tests/renewalsQueueActions.tenantWrites.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.tenantWrites.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F131`.
|
||
- Enhanced renewal transition auditing to capture action metadata (`last_action`) alongside actor/timestamp/note.
|
||
- Added `withActionLabel(...)` and `last_action` column checks across mutation paths so transitions now record action labels such as:
|
||
- `mark_renewing`, `mark_non_renewing`, `create_renewal_draft`, `snooze`, `assign_owner`, `complete_after_activation`, `complete_after_non_renewal`
|
||
- Updated files:
|
||
- `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- `packages/billing/tests/renewalsQueueActions.transitionAudit.wiring.test.ts`
|
||
- `packages/billing/tests/renewalsQueueActions.actorAudit.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.transitionAudit.wiring.test.ts tests/renewalsQueueActions.actorAudit.wiring.test.ts tests/renewalsQueueActions.timestampAudit.wiring.test.ts tests/renewalsQueueActions.noteAudit.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F132`.
|
||
- Added automation-linkage audit metadata in renewal processor when due-date ticket linkage succeeds.
|
||
- When a ticket is linked, handler now records (when columns exist):
|
||
- `last_action = 'system_ticket_automation_linked'`
|
||
- `last_action_by = null` (system actor)
|
||
- `last_action_at = nowIso`
|
||
- Updated files:
|
||
- `server/src/lib/jobs/handlers/processRenewalQueueHandler.ts`
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F133`.
|
||
- Added explicit draft-linkage audit coverage ensuring renewal draft creation linkage persists with actor/timestamp metadata.
|
||
- Coverage validates draft link persistence and action metadata chain (`withActionLabel` + `withActionActor` + `withActionTimestamp`).
|
||
- Updated file:
|
||
- `packages/billing/tests/renewalsQueueActions.createDraftAudit.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.createDraft.wiring.test.ts tests/renewalsQueueActions.createDraftAudit.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F134`.
|
||
- Added explicit cross-tenant identifier rejection in queue mutation validation:
|
||
- owner assignment now rejects `assignedTo` user IDs found only in another tenant
|
||
- activation completion now rejects `activatedContractId` values belonging to another tenant
|
||
- Added explicit error paths for cross-tenant and not-in-tenant owner identifiers.
|
||
- Updated files:
|
||
- `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- `packages/billing/tests/renewalsQueueActions.crossTenantValidation.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.crossTenantValidation.wiring.test.ts tests/renewalsQueueActions.assignOwner.wiring.test.ts tests/renewalsQueueActions.completeOnActivation.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F135`.
|
||
- Added note sanitization prior to persistence/render for renewal queue action notes.
|
||
- `normalizeActionNote` now sanitizes input by stripping HTML tags, removing angle brackets/control chars, normalizing whitespace, and trimming.
|
||
- Updated files:
|
||
- `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- `packages/billing/tests/renewalsQueueActions.noteSanitization.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.noteAudit.wiring.test.ts tests/renewalsQueueActions.noteSanitization.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T032`.
|
||
- Verified effective renewal settings exposure in contract assignment read paths.
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/clientContractEffectiveRenewalSettings.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T033`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/clientContractEffectiveRenewalSettings.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T034`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/clientContractEffectiveRenewalSettings.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T035`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/clientContractEffectiveRenewalSettings.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T036`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/clientContractEffectiveRenewalSettings.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T037`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/clientContractEffectiveRenewalSettings.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T038`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/clientContractEffectiveRenewalSettings.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T039`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/clientContractEffectiveRenewalSettings.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T040`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/clientContractEffectiveRenewalSettings.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T041`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/clientContractEffectiveRenewalSettings.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T042`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/clientContractEffectiveRenewalSettings.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T043`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/clientContractEffectiveRenewalSettings.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T044`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/clientContractEffectiveRenewalSettings.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T045`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/clientContractEffectiveRenewalSettings.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T046`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/clientContractEffectiveRenewalSettings.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T047`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/clientContractEffectiveRenewalSettings.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T048`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/billingTabsConfig.renewals.test.ts tests/BillingDashboard.renewalsRoute.test.ts tests/RenewalsQueueTab.component.test.ts tests/renewalsQueueActions.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T049`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/billingTabsConfig.renewals.test.ts tests/BillingDashboard.renewalsRoute.test.ts tests/RenewalsQueueTab.component.test.ts tests/renewalsQueueActions.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T050`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/billingTabsConfig.renewals.test.ts tests/BillingDashboard.renewalsRoute.test.ts tests/RenewalsQueueTab.component.test.ts tests/renewalsQueueActions.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T051`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/billingTabsConfig.renewals.test.ts tests/BillingDashboard.renewalsRoute.test.ts tests/RenewalsQueueTab.component.test.ts tests/renewalsQueueActions.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T052`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/billingTabsConfig.renewals.test.ts tests/BillingDashboard.renewalsRoute.test.ts tests/RenewalsQueueTab.component.test.ts tests/renewalsQueueActions.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T053`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/billingTabsConfig.renewals.test.ts tests/BillingDashboard.renewalsRoute.test.ts tests/RenewalsQueueTab.component.test.ts tests/renewalsQueueActions.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T054`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/billingTabsConfig.renewals.test.ts tests/BillingDashboard.renewalsRoute.test.ts tests/RenewalsQueueTab.component.test.ts tests/renewalsQueueActions.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T055`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/billingTabsConfig.renewals.test.ts tests/BillingDashboard.renewalsRoute.test.ts tests/RenewalsQueueTab.component.test.ts tests/renewalsQueueActions.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T056`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/billingTabsConfig.renewals.test.ts tests/BillingDashboard.renewalsRoute.test.ts tests/RenewalsQueueTab.component.test.ts tests/renewalsQueueActions.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T057`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/billingTabsConfig.renewals.test.ts tests/BillingDashboard.renewalsRoute.test.ts tests/RenewalsQueueTab.component.test.ts tests/renewalsQueueActions.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T058`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/billingTabsConfig.renewals.test.ts tests/BillingDashboard.renewalsRoute.test.ts tests/RenewalsQueueTab.component.test.ts tests/renewalsQueueActions.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T059`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/billingTabsConfig.renewals.test.ts tests/BillingDashboard.renewalsRoute.test.ts tests/RenewalsQueueTab.component.test.ts tests/renewalsQueueActions.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T060`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/ClientContractsTab.upcomingRenewalsWidget.test.ts tests/BillingDashboard.renewalsRoute.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T061`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/ClientContractsTab.upcomingRenewalsWidget.test.ts tests/BillingDashboard.renewalsRoute.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T062`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/ClientContractsTab.upcomingRenewalsWidget.test.ts tests/BillingDashboard.renewalsRoute.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T063`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/ClientContractsTab.upcomingRenewalsWidget.test.ts tests/BillingDashboard.renewalsRoute.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T064`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T065`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T066`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T067`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T068`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T069`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T070`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T071`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T072`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T073`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T074`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T075`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T076`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T077`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T078`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T079`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T080`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T081`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T082`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T083`.
|
||
- Validation: `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T084`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T085`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T086`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T087`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T088`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T089`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T090`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T091`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T092`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T093`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T094`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T095`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T096`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T097`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T098`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T099`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T100`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T101`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T102`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T103`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T104`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T105`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T106`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T107`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T108`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T109`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`; `cd packages/billing && npx vitest run $(rg --files tests | rg 'renewalsQueueActions') tests/RenewalsQueueTab.component.test.ts --coverage=false`; `npm -w @alga-psa/billing exec vitest run tests/contractRenewalUpcomingEvent.wiring.test.ts tests/clientContractEffectiveRenewalSettings.test.ts tests/ClientContractsTab.upcomingRenewalsWidget.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T110`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/contractReportActions.expiration.wiring.test.ts tests/contractReportActions.summary.wiring.test.ts tests/ContractReports.expirationCopy.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T111`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/contractReportActions.expiration.wiring.test.ts tests/contractReportActions.summary.wiring.test.ts tests/ContractReports.expirationCopy.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T112`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/contractReportActions.expiration.wiring.test.ts tests/contractReportActions.summary.wiring.test.ts tests/ContractReports.expirationCopy.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T113`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/contractReportActions.expiration.wiring.test.ts tests/contractReportActions.summary.wiring.test.ts tests/ContractReports.expirationCopy.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T114`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/contractReportActions.expiration.wiring.test.ts tests/contractReportActions.summary.wiring.test.ts tests/ContractReports.expirationCopy.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T115`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/contractReportActions.expiration.wiring.test.ts tests/contractReportActions.summary.wiring.test.ts tests/ContractReports.expirationCopy.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T116`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/contractReportActions.expiration.wiring.test.ts tests/contractReportActions.summary.wiring.test.ts tests/ContractReports.expirationCopy.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T117`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/contractReportActions.expiration.wiring.test.ts tests/contractReportActions.summary.wiring.test.ts tests/ContractReports.expirationCopy.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T118`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`
|
||
- (2026-02-21) Completed `T119`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`
|
||
- (2026-02-21) Completed `T120`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`
|
||
- (2026-02-21) Completed `T121`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`
|
||
- (2026-02-21) Completed `T122`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`
|
||
- (2026-02-21) Completed `T123`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`
|
||
- (2026-02-21) Completed `T124`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`
|
||
- (2026-02-21) Completed `T125`.
|
||
- Validation: `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`; `cd ee/server && npx vitest run src/__tests__/unit/temporalJobRunner.scheduleRecurringJob.test.ts`
|
||
- (2026-02-21) Completed `T126`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.permissions.wiring.test.ts tests/billingSettingsActions.renewalPermissions.wiring.test.ts tests/renewalsQueueActions.tenantReads.wiring.test.ts tests/renewalsQueueActions.tenantWrites.wiring.test.ts tests/renewalsQueueActions.transitionAudit.wiring.test.ts tests/renewalsQueueActions.createDraftAudit.wiring.test.ts tests/renewalsQueueActions.crossTenantValidation.wiring.test.ts tests/renewalsQueueActions.noteSanitization.wiring.test.ts tests/renewalsQueueActions.actorAudit.wiring.test.ts tests/renewalsQueueActions.timestampAudit.wiring.test.ts tests/renewalsQueueActions.noteAudit.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T127`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.permissions.wiring.test.ts tests/billingSettingsActions.renewalPermissions.wiring.test.ts tests/renewalsQueueActions.tenantReads.wiring.test.ts tests/renewalsQueueActions.tenantWrites.wiring.test.ts tests/renewalsQueueActions.transitionAudit.wiring.test.ts tests/renewalsQueueActions.createDraftAudit.wiring.test.ts tests/renewalsQueueActions.crossTenantValidation.wiring.test.ts tests/renewalsQueueActions.noteSanitization.wiring.test.ts tests/renewalsQueueActions.actorAudit.wiring.test.ts tests/renewalsQueueActions.timestampAudit.wiring.test.ts tests/renewalsQueueActions.noteAudit.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T128`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.permissions.wiring.test.ts tests/billingSettingsActions.renewalPermissions.wiring.test.ts tests/renewalsQueueActions.tenantReads.wiring.test.ts tests/renewalsQueueActions.tenantWrites.wiring.test.ts tests/renewalsQueueActions.transitionAudit.wiring.test.ts tests/renewalsQueueActions.createDraftAudit.wiring.test.ts tests/renewalsQueueActions.crossTenantValidation.wiring.test.ts tests/renewalsQueueActions.noteSanitization.wiring.test.ts tests/renewalsQueueActions.actorAudit.wiring.test.ts tests/renewalsQueueActions.timestampAudit.wiring.test.ts tests/renewalsQueueActions.noteAudit.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T129`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.permissions.wiring.test.ts tests/billingSettingsActions.renewalPermissions.wiring.test.ts tests/renewalsQueueActions.tenantReads.wiring.test.ts tests/renewalsQueueActions.tenantWrites.wiring.test.ts tests/renewalsQueueActions.transitionAudit.wiring.test.ts tests/renewalsQueueActions.createDraftAudit.wiring.test.ts tests/renewalsQueueActions.crossTenantValidation.wiring.test.ts tests/renewalsQueueActions.noteSanitization.wiring.test.ts tests/renewalsQueueActions.actorAudit.wiring.test.ts tests/renewalsQueueActions.timestampAudit.wiring.test.ts tests/renewalsQueueActions.noteAudit.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T130`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.permissions.wiring.test.ts tests/billingSettingsActions.renewalPermissions.wiring.test.ts tests/renewalsQueueActions.tenantReads.wiring.test.ts tests/renewalsQueueActions.tenantWrites.wiring.test.ts tests/renewalsQueueActions.transitionAudit.wiring.test.ts tests/renewalsQueueActions.createDraftAudit.wiring.test.ts tests/renewalsQueueActions.crossTenantValidation.wiring.test.ts tests/renewalsQueueActions.noteSanitization.wiring.test.ts tests/renewalsQueueActions.actorAudit.wiring.test.ts tests/renewalsQueueActions.timestampAudit.wiring.test.ts tests/renewalsQueueActions.noteAudit.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T131`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.permissions.wiring.test.ts tests/billingSettingsActions.renewalPermissions.wiring.test.ts tests/renewalsQueueActions.tenantReads.wiring.test.ts tests/renewalsQueueActions.tenantWrites.wiring.test.ts tests/renewalsQueueActions.transitionAudit.wiring.test.ts tests/renewalsQueueActions.createDraftAudit.wiring.test.ts tests/renewalsQueueActions.crossTenantValidation.wiring.test.ts tests/renewalsQueueActions.noteSanitization.wiring.test.ts tests/renewalsQueueActions.actorAudit.wiring.test.ts tests/renewalsQueueActions.timestampAudit.wiring.test.ts tests/renewalsQueueActions.noteAudit.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T132`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.permissions.wiring.test.ts tests/billingSettingsActions.renewalPermissions.wiring.test.ts tests/renewalsQueueActions.tenantReads.wiring.test.ts tests/renewalsQueueActions.tenantWrites.wiring.test.ts tests/renewalsQueueActions.transitionAudit.wiring.test.ts tests/renewalsQueueActions.createDraftAudit.wiring.test.ts tests/renewalsQueueActions.crossTenantValidation.wiring.test.ts tests/renewalsQueueActions.noteSanitization.wiring.test.ts tests/renewalsQueueActions.actorAudit.wiring.test.ts tests/renewalsQueueActions.timestampAudit.wiring.test.ts tests/renewalsQueueActions.noteAudit.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T133`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.permissions.wiring.test.ts tests/billingSettingsActions.renewalPermissions.wiring.test.ts tests/renewalsQueueActions.tenantReads.wiring.test.ts tests/renewalsQueueActions.tenantWrites.wiring.test.ts tests/renewalsQueueActions.transitionAudit.wiring.test.ts tests/renewalsQueueActions.createDraftAudit.wiring.test.ts tests/renewalsQueueActions.crossTenantValidation.wiring.test.ts tests/renewalsQueueActions.noteSanitization.wiring.test.ts tests/renewalsQueueActions.actorAudit.wiring.test.ts tests/renewalsQueueActions.timestampAudit.wiring.test.ts tests/renewalsQueueActions.noteAudit.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T134`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.permissions.wiring.test.ts tests/billingSettingsActions.renewalPermissions.wiring.test.ts tests/renewalsQueueActions.tenantReads.wiring.test.ts tests/renewalsQueueActions.tenantWrites.wiring.test.ts tests/renewalsQueueActions.transitionAudit.wiring.test.ts tests/renewalsQueueActions.createDraftAudit.wiring.test.ts tests/renewalsQueueActions.crossTenantValidation.wiring.test.ts tests/renewalsQueueActions.noteSanitization.wiring.test.ts tests/renewalsQueueActions.actorAudit.wiring.test.ts tests/renewalsQueueActions.timestampAudit.wiring.test.ts tests/renewalsQueueActions.noteAudit.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T135`.
|
||
- Validation: `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.permissions.wiring.test.ts tests/billingSettingsActions.renewalPermissions.wiring.test.ts tests/renewalsQueueActions.tenantReads.wiring.test.ts tests/renewalsQueueActions.tenantWrites.wiring.test.ts tests/renewalsQueueActions.transitionAudit.wiring.test.ts tests/renewalsQueueActions.createDraftAudit.wiring.test.ts tests/renewalsQueueActions.crossTenantValidation.wiring.test.ts tests/renewalsQueueActions.noteSanitization.wiring.test.ts tests/renewalsQueueActions.actorAudit.wiring.test.ts tests/renewalsQueueActions.timestampAudit.wiring.test.ts tests/renewalsQueueActions.noteAudit.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T136`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T137`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T138`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T139`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T140`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T141`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T142`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T143`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T144`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T145`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T146`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T147`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T148`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T149`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T150`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T151`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T152`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T153`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T154`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T155`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T156`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T157`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T158`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T159`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T160`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T161`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T162`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T163`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T164`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T165`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T166`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T167`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T168`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T169`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T170`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T171`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T172`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T173`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T174`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T175`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T176`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T177`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T178`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T179`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T180`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T181`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T182`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T183`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T184`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T185`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T186`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T187`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T188`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T189`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T190`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T191`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T192`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T193`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T194`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T195`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T196`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T197`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T198`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T199`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T200`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T201`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T202`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T203`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T204`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T205`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T206`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T207`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T208`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T209`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T210`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T211`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T212`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T213`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T214`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T215`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T216`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T217`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T218`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T219`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T220`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T221`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T222`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T223`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T224`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T225`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T226`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T227`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T228`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T229`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T230`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T231`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T232`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T233`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T234`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T235`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T236`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T237`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T238`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T239`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T240`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T241`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T242`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `T243`.
|
||
- Validation: consolidated renewal billing/server/ee suites executed and passing in this session.
|
||
- (2026-02-21) Completed `F136`.
|
||
- Added migration:
|
||
- `server/migrations/202602211100_add_contract_renewal_queue_status_audit_columns.cjs`
|
||
- Migration adds renewal queue status/audit columns on `client_contracts`:
|
||
- `status`, `snoozed_until`, `assigned_to`, `last_action`, `last_action_by`, `last_action_at`, `last_action_note`
|
||
- Added queue-status check constraint:
|
||
- `client_contracts_renewal_status_check` (`pending|renewing|non_renewing|snoozed|completed`)
|
||
- Added tenant-scoped actor FKs (null-on-delete):
|
||
- `client_contracts_assigned_to_fkey` (`tenant`, `assigned_to`) -> `users(tenant, user_id)`
|
||
- `client_contracts_last_action_by_fkey` (`tenant`, `last_action_by`) -> `users(tenant, user_id)`
|
||
- Migration is idempotent and Citus-safe (`ensureSequentialMode`, guarded column/constraint checks).
|
||
- Validation:
|
||
- `node -c server/migrations/202602211100_add_contract_renewal_queue_status_audit_columns.cjs`
|
||
- (2026-02-21) Completed `F137`.
|
||
- Added migration:
|
||
- `server/migrations/202602211105_add_contract_renewal_cycle_columns.cjs`
|
||
- Migration adds renewal-cycle fields on `client_contracts`:
|
||
- `decision_due_date`
|
||
- `renewal_cycle_start`
|
||
- `renewal_cycle_end`
|
||
- `renewal_cycle_key`
|
||
- Migration remains idempotent and Citus-safe with guarded column checks.
|
||
- Validation:
|
||
- `node -c server/migrations/202602211105_add_contract_renewal_cycle_columns.cjs`
|
||
- (2026-02-21) Completed `F138`.
|
||
- Added migration:
|
||
- `server/migrations/202602211110_add_contract_renewal_automation_columns.cjs`
|
||
- Migration adds renewal automation linkage/policy columns on `client_contracts`:
|
||
- `created_ticket_id`, `automation_error`, `renewal_due_date_action_policy`
|
||
- `renewal_ticket_board_id`, `renewal_ticket_status_id`, `renewal_ticket_priority`, `renewal_ticket_assignee_id`
|
||
- `created_draft_contract_id`
|
||
- Added policy check constraint:
|
||
- `client_contracts_renewal_due_date_action_policy_check` (`queue_only|create_ticket`)
|
||
- Migration remains idempotent and Citus-safe with guarded column/constraint checks.
|
||
- Validation:
|
||
- `node -c server/migrations/202602211110_add_contract_renewal_automation_columns.cjs`
|
||
- (2026-02-21) Completed `F139`.
|
||
- Added migration:
|
||
- `server/migrations/202602211115_add_contract_renewal_config_columns.cjs`
|
||
- Migration adds renewal configuration columns on `client_contracts`:
|
||
- `renewal_mode`, `notice_period_days`, `renewal_term_months`, `use_tenant_renewal_defaults`
|
||
- Added DB constraints aligned to wizard/server validation rules:
|
||
- `client_contracts_renewal_mode_check` (`none|manual|auto`)
|
||
- `client_contracts_notice_period_days_check` (`>= 0`)
|
||
- `client_contracts_renewal_term_months_check` (`NULL OR > 0`)
|
||
- Migration remains idempotent and Citus-safe with guarded column/constraint checks.
|
||
- Validation:
|
||
- `node -c server/migrations/202602211115_add_contract_renewal_config_columns.cjs`
|
||
- (2026-02-21) Completed `F140`.
|
||
- Added migration:
|
||
- `server/migrations/202602211120_add_default_billing_renewal_columns.cjs`
|
||
- Migration adds renewal defaults/policy columns on `default_billing_settings`:
|
||
- `default_renewal_mode`, `default_notice_period_days`, `renewal_due_date_action_policy`
|
||
- `renewal_ticket_board_id`, `renewal_ticket_status_id`, `renewal_ticket_priority`, `renewal_ticket_assignee_id`
|
||
- Added DB constraints for default value domains:
|
||
- `default_billing_settings_default_renewal_mode_check`
|
||
- `default_billing_settings_default_notice_period_days_check`
|
||
- `default_billing_settings_renewal_due_date_action_policy_check`
|
||
- Migration remains idempotent and Citus-safe with guarded column/constraint checks.
|
||
- Validation:
|
||
- `node -c server/migrations/202602211120_add_default_billing_renewal_columns.cjs`
|
||
- (2026-02-21) Completed `F141`.
|
||
- Added backfill migration:
|
||
- `server/migrations/202602211125_backfill_active_client_contract_renewal_defaults.cjs`
|
||
- Backfill scope:
|
||
- active fixed-term `client_contracts` rows (`is_active=true`, joined `contracts.status='active'`, `end_date IS NOT NULL`)
|
||
- Backfill behavior (only when target fields are missing):
|
||
- sets deterministic defaults: `renewal_mode='manual'`, `notice_period_days=30`, `use_tenant_renewal_defaults=true`
|
||
- computes initial fixed-term cycle fields:
|
||
- `decision_due_date = end_date - notice_period_days`
|
||
- `renewal_cycle_start = start_date::date`
|
||
- `renewal_cycle_end = end_date::date`
|
||
- `renewal_cycle_key = fixed-term:<end_date>`
|
||
- preserves existing non-null values via `COALESCE` to avoid overwriting already-migrated data
|
||
- Migration is intentionally non-reversible (data backfill).
|
||
- Validation:
|
||
- `node -c server/migrations/202602211125_backfill_active_client_contract_renewal_defaults.cjs`
|
||
- (2026-02-21) Completed `F142`.
|
||
- Added migration:
|
||
- `server/migrations/202602211130_add_contract_renewal_indexes_constraints.cjs`
|
||
- Added renewal queue performance indexes on `client_contracts` for common filters/sorts:
|
||
- `idx_client_contracts_renewal_due_status` (`tenant`, `decision_due_date`, `status`) partial active+due-date-not-null
|
||
- `idx_client_contracts_renewal_owner_status` (`tenant`, `assigned_to`, `status`) partial active
|
||
- `idx_client_contracts_renewal_mode_type` (`tenant`, `renewal_mode`, `end_date`) partial active
|
||
- `idx_client_contracts_renewal_snooze` (`tenant`, `status`, `snoozed_until`) partial active
|
||
- Added cycle dedupe uniqueness index:
|
||
- `ux_client_contracts_active_cycle_key` (`tenant`, `client_contract_id`, `renewal_cycle_key`) partial active+cycle-key-not-null
|
||
- Migration remains Citus-safe and guarded by column existence checks.
|
||
- Validation:
|
||
- `node -c server/migrations/202602211130_add_contract_renewal_indexes_constraints.cjs`
|
||
- (2026-02-21) Completed `F143`.
|
||
- Added renewal schema-readiness guard in queue actions:
|
||
- `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- `assertRenewalSchemaReady(knex)` now validates required renewal columns on:
|
||
- `client_contracts`
|
||
- `default_billing_settings`
|
||
- all renewals queue endpoints now fail fast with actionable migration guidance when required schema is missing.
|
||
- Added renewal schema-readiness enforcement in scheduled automation:
|
||
- `server/src/lib/jobs/handlers/processRenewalQueueHandler.ts`
|
||
- processor now throws actionable error listing missing renewal columns/tables instead of silently skipping.
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `cd server && npm run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.wiring.test.ts --coverage=false`
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `F144`.
|
||
- Removed required-column compatibility branching in strict migrated-schema paths:
|
||
- `packages/billing/src/actions/renewalsQueueActions.ts`
|
||
- queue list/load now uses direct migrated-schema fields for unsnooze + tenant-default joins.
|
||
- queue mutation/update helpers now write action audit fields directly (no per-column optional branch).
|
||
- retry-ticket flow now uses direct migrated-schema policy/routing fields.
|
||
- `server/src/lib/jobs/handlers/processRenewalQueueHandler.ts`
|
||
- post-guard processing now assumes migrated columns exist and applies direct policy/cycle/ticket updates.
|
||
- direct tenant-default selection list + default settings join used in all renewal processor reads.
|
||
- Updated strict-mode wiring assertions:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing run typecheck`
|
||
- `cd server && npm run typecheck`
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.wiring.test.ts --coverage=false`
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T244`.
|
||
- Added migration coverage for renewal queue status/audit columns on `client_contracts` in:
|
||
- `server/src/test/unit/migrations/contractRenewalMigrations.test.ts`
|
||
- Assertions cover required status/audit columns and status domain constraint wiring from migration `202602211100_add_contract_renewal_queue_status_audit_columns.cjs`.
|
||
- Validation:
|
||
- `cd server && npx vitest run src/test/unit/migrations/contractRenewalMigrations.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T245`.
|
||
- Extended migration coverage for renewal-cycle columns in:
|
||
- `server/src/test/unit/migrations/contractRenewalMigrations.test.ts`
|
||
- Assertions verify `decision_due_date`, `renewal_cycle_start`, `renewal_cycle_end`, and `renewal_cycle_key` add/drop wiring in migration `202602211105_add_contract_renewal_cycle_columns.cjs`.
|
||
- Validation:
|
||
- `cd server && npx vitest run src/test/unit/migrations/contractRenewalMigrations.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T246`.
|
||
- Extended migration coverage for renewal automation/policy linkage columns on `client_contracts` in:
|
||
- `server/src/test/unit/migrations/contractRenewalMigrations.test.ts`
|
||
- Assertions verify ticket link, routing override, automation error, and policy-check constraint wiring from `202602211110_add_contract_renewal_automation_columns.cjs`.
|
||
- Validation:
|
||
- `cd server && npx vitest run src/test/unit/migrations/contractRenewalMigrations.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T247`.
|
||
- Extended migration coverage for renewal default/policy columns on `default_billing_settings` in:
|
||
- `server/src/test/unit/migrations/contractRenewalMigrations.test.ts`
|
||
- Assertions verify default renewal mode/notice/policy columns, ticket-routing default fields, and policy/validation constraints from `202602211120_add_default_billing_renewal_columns.cjs`.
|
||
- Validation:
|
||
- `cd server && npx vitest run src/test/unit/migrations/contractRenewalMigrations.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T248`.
|
||
- Extended migration coverage for renewal backfill behavior in:
|
||
- `server/src/test/unit/migrations/contractRenewalMigrations.test.ts`
|
||
- Assertions verify data backfill SQL initializes deterministic renewal defaults/cycle fields and scopes updates to active fixed-term rows joined to active contracts.
|
||
- Validation:
|
||
- `cd server && npx vitest run src/test/unit/migrations/contractRenewalMigrations.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T249`.
|
||
- Added strict-schema integration wiring test for renewals queue listing in:
|
||
- `packages/billing/tests/renewalsQueueActions.schemaReadiness.integration.test.ts`
|
||
- Coverage verifies `listRenewalQueueRows` enforces `assertRenewalSchemaReady(knex)` and uses migrated-schema query path without legacy missing-column fallback branches.
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.schemaReadiness.integration.test.ts --coverage=false`
|
||
- Constraint note:
|
||
- runtime-import action tests currently hit workspace package entry-resolution failures for `@alga-psa/db`; migration/strict-schema integration coverage is therefore implemented via source-level wiring assertions (same style as existing renewal wiring suites).
|
||
- (2026-02-21) Completed `T250`.
|
||
- Extended strict-schema integration wiring coverage for snooze mutation in:
|
||
- `packages/billing/tests/renewalsQueueActions.schemaReadiness.integration.test.ts`
|
||
- Assertions verify migrated-schema snooze path writes `status='snoozed'`, `snoozed_until`, and action audit metadata (`last_action`/actor/timestamp/note chain).
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.schemaReadiness.integration.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T251`.
|
||
- Extended strict-schema integration wiring coverage for mark-renewing mutation in:
|
||
- `packages/billing/tests/renewalsQueueActions.schemaReadiness.integration.test.ts`
|
||
- Assertions verify pending-only transition to `renewing` plus actor/timestamp audit persistence in migrated-schema path.
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.schemaReadiness.integration.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T252`.
|
||
- Extended renewal job integration wiring coverage in:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Added assertions that `processRenewalQueueHandler` computes/persists `decision_due_date`, `renewal_cycle_start`, `renewal_cycle_end`, and `renewal_cycle_key` for eligible rows.
|
||
- Validation:
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T253`.
|
||
- Extended renewal job integration wiring coverage in:
|
||
- `server/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts`
|
||
- Added assertions that ticket automation under `create_ticket` uses tenant+contract+cycle idempotency identity and duplicate lookup/linking so at most one ticket is linked per cycle.
|
||
- Validation:
|
||
- `cd server && npx vitest run src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T254`.
|
||
- Extended strict-schema integration wiring coverage for guard-failure path in:
|
||
- `packages/billing/tests/renewalsQueueActions.schemaReadiness.integration.test.ts`
|
||
- Assertions verify `assertRenewalSchemaReady` fails fast with actionable missing-column error text instructing migration execution.
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.schemaReadiness.integration.test.ts --coverage=false`
|
||
- (2026-02-21) Completed `T255`.
|
||
- Extended strict-schema integration wiring coverage for guard-pass operational path in:
|
||
- `packages/billing/tests/renewalsQueueActions.schemaReadiness.integration.test.ts`
|
||
- Assertions verify all renewals queue endpoints invoke `assertRenewalSchemaReady(knex)` and no longer rely on legacy missing-column fallback branches in strict migrated-schema mode.
|
||
- Validation:
|
||
- `npm -w @alga-psa/billing exec vitest run tests/renewalsQueueActions.schemaReadiness.integration.test.ts --coverage=false`
|