Workflow Register
Last updated: 2026-10-01.
This register tracks implemented workflows that mutate business data.
| Workflow | Business event | Records that may change | Current rule document | Technical references |
|---|---|---|---|---|
| Contact created MSP seat automation | A CRM Contact is created; its Company has one active Service with MSP seats enabled. | Contact Lead_Status; Account-owned MSP Seat creation. |
MSP contact lifecycle | app/automations/contact_created.py, zoho_crm/deluge/standalone.on_create_contact_automations.dg |
| Contact edited MSP seat automation | A CRM Contact is edited; the same explicit MSP entitlement checks apply. | MSP Seat Billing_Status / Billing_End; Contact Lead_Status / update_source; MSP Seat creation when missing. |
MSP contact lifecycle | app/automations/contact_edited.py, zoho_crm/deluge/standalone.on_edit_contact_automations.dg |
| Generate or refresh one MSP invoice | A user clicks the Service-level MSP button; only Legacy MSP-owned lines qualify. | CRM Invoice; Xero draft invoice; CRM invoice Xero reference fields. | MSP invoicing | docs/systems/engineering/invoice-integration.md, msp_imports/msp_invoices/service.py |
| Generate or refresh monthly MSP invoices | A user clicks the Services list MSP button; only Legacy MSP-owned lines qualify. | CRM Invoices; Xero draft invoices; CRM invoice Xero reference fields. | MSP invoicing | docs/systems/engineering/invoice-integration.md, msp_imports/msp_invoices/service.py |
| Mirror or link one posted project invoice | An operator reviews the preview and reruns the project-invoice mirror with --apply. |
CRM Invoice only; the source Xero invoice is read but never changed. | Project Invoice Reconciliation | xero_sync/project_invoice_mirror.py, tests/test_project_invoice_mirror.py |
| Reconcile one MSP invoice line | A Service Line is created or edited. | No fields currently change; the retained date reconciliation returns skipped. | MSP invoicing | docs/notes/2026-05-29_msp_invoice_line_crm_implementation_plan.md, msp_imports/msp_invoices/reconcile.py |
| Project from deal | A Deal workflow requests a project; only new-client MSP, Tech Project and Tech Retainer qualify (plus legacy aliases). | Zoho Project; Deal project link fields; project tasklists/tasks; Delivery Models. | Deals, projects, and delivery models | app/automations/projects_from_deal/project_bootstrap.py |
| Reserved deal setup | A Deal reaches Reserved for MSP - New Client or Tech Project (plus legacy aliases). |
Zoho Project tasklists; tasklist completion; Delivery Models; Deal Closing_Date. |
Deals, projects, and delivery models | app/automations/projects_from_deal/reserved_pending.py |
| Delivery Model alert evaluation | Delivery Model progress is evaluated, optionally with CRM updates and alert emails. | Delivery Model completion fields; Delivery Model mail action. | Deals, projects, and delivery models | app/delivery_models/alerts.py, app/automations/delivery_model_completion_calculations.py |
| Delivery Model state sync | Delivery Model progress is evaluated and optionally written without sending alert emails. | Delivery Model completion fields and Cumulated_Amount. |
Deals, projects, and delivery models | app/automations/delivery_model_completion.py |
| Migrate recurring MSP budgets to MSP Plans | An operator runs the reviewed Delivery Model migration with --apply. |
MSP Plan fallback revenue, expected support hours, timesheet scope pair, and budget source. | MSP budget migration | msp_imports/migrate_delivery_models_to_msp_plans.py, tests/test_migrate_delivery_models_to_msp_plans.py |
| Set current MSP Plan agreement | An operator applies a reviewed agreement batch for selected Plans. | Four optional current-agreement fields on Managed Services Plans; reviewed Plan agreement Deal/start/acceptance/renewal values only. Billing inputs and other business records are preserved. | Current Agreement | msp_imports/plan_agreements.py, tests/test_msp_plan_agreements.py |
| Configure MSP Commercial Service review | An operator applies a candidate batch sourced from existing MSP Plans and invoices. | Five optional Commercial Service context fields; selected service summaries/agreement references and captured-line coverage/review fields. Operational inputs and financial values are preserved. | Commercial Service Review | commercial_services/msp_review.py, tests/commercial_services/test_msp_review.py |
| Link actual invoice lines to configured MSP charges | An operator applies explicit line-to-charge mappings with the captured batch hash. | Optional configured MSP Invoice Line lookup and selected Service Invoice Line lookup values only; historical financial values and operational inputs are preserved. | Invoice charge reconciliation | commercial_services/invoice_charge_links.py, tests/commercial_services/test_invoice_charge_links.py |
| Migrate native MSP invoice history | An operator applies an explicit native-item batch with its reviewed hash. | Native item service/charge/coverage/source IDs; optional reviewed CRM-to-Xero financial and header reconciliation. Original snapshots and IDs are preserved; no Xero or billing configuration writes. | Native invoice history | commercial_services/native_invoice_migration.py, tests/commercial_services/test_native_invoice_migration.py |
| Retire verified MSP custom captures | An operator has validated native replacements and deployed dependent readers. | Exact archived Service Invoice Lines move to recycle bin with workflows disabled after dependency/freshness checks. No native invoice, configuration or module deletion; old writers reject duplicate migrated captures. | Native invoice history | commercial_services/native_invoice_retirement.py, tests/commercial_services/test_native_invoice_retirement.py |
| Install project Consulting labour tier | Operator runs the service-line costing installer with --apply. |
Optional Expected_Labour_Tier picklist on MSP Invoice Lines, used only by project Consulting; no record values or invoices changed. |
Confirming services and refreshing reports | commercial_services/service_line_costing.py, tests/commercial_services/test_service_line_costing.py |
| Archived timelog backfill cache reset | A reporting operator resets the archived timelog report cache. | Generated cached report files only; no CRM/Projects/Xero business records. | Reporting assumptions | docs/notes/2026-05-06_archived_timelog_backfill.md |
| Reviewed July-onward commercial invoice reconciliation | Operator reviews configured invoice/service/product identities and runs the reconciliation batch with --apply. |
CRM Invoice writes with triggers disabled; native CRM inventory bookkeeping can follow. No new Deals, direct Company/Product/Projects writes or Xero writes. Reporting-only identities stay in report configuration. | Project Invoice Reconciliation | app/commercial_margin/reconcile.py, tests/test_contribution_report.py |
| Product costing category backfill | Operator applies a captured catalogue migration preview. | Products Costing_Category picklist and record values only; existing classifications retained, prices and invoice links unchanged. |
Product Costing Categories | commercial_services/product_costing_migration.py, tests/commercial_services/test_product_costing_migration.py |
| Link retained records to Commercial Services | Operator applies the reviewed cleanup inventory. | Optional Commercial Service lookups on native Invoices and shared MSP Invoice Lines; conditional lookup-only backfill with workflows suppressed and complete readback. Plan is optional on the shared line layout; existing MSP billing still requires Plan. | Shared service records | commercial_services/cleanup.py, tests/test_commercial_cleanup.py |
| Install line labour budget fields | Operator runs the line labour field installer during reviewed CRM setup. | Optional Labour Budget Type and Expected Labour Hours fields on shared Service Lines; no record values or invoices changed by the installer. | Product-led lines | commercial_services/service_line_labour.py, tests/commercial_services/test_service_line_labour.py |
| Save commercial service forecast | An authenticated operator uses the retained management-input endpoint; the dashboard no longer exposes this form. | Private management file: agreed value, opening delivery costs, dated remaining-work estimates and explicit allowance expiry policy for supporting reserves; these do not change the configured headline forecast. No CRM, Projects, Xero or invoice records change. | Delivery reserve and service forecast | app/commercial_margin/forecast_inputs.py, app/commercial_margin/delivery_reserve.py, tests/test_forecast_inputs.py |
| Create external consultant Product and switch selected lines | Operator applies a captured preview for explicit Commercial Service IDs. | New External Consulting Product, optional External Hourly Cost field, and selected Service Line Product/rate values. Sales fields preserved; no invoice or Xero writes. | External consultant product and migration | commercial_services/external_consulting.py, tests/commercial_services/test_external_consulting.py |
| Classify Plan-linked recurring Commercial Services as MSP | Operator applies a captured Service Role migration preview. | Commercial Services Service_Role only; additive MSP picklist option if absent. Exact Recurring agreement + existing Managed Service Plan link selection, all review states; conditional writes and verified readback. |
Service Role migration | commercial_services/service_role_migration.py, tests/commercial_services/test_service_role_migration.py |
| Configure universal CRM structure | An operator installs the reviewed additive schema and defaults. | Optional Service, Service Line and Product fields; preserved picklists/layout defaults and reviewed labels/requirements. | CRM structure cutover | commercial_services/universal_schema.py, universal_defaults.py, universal_layouts.py |
| Map existing billing and MSP entitlement | An operator applies explicit selected-record decisions with the reviewed batch hash. | Only MSP_Seats_Enabled and Billing_Authority; conditional writes and saved readback, with workflow triggers disabled. |
Compatibility controls | commercial_services/universal_controls.py, tests/commercial_services/test_universal_controls.py |
| Move MSP Seats to Accounts | Apply a reviewed ownership batch with its exact hash. | Seat Account lookup only; IDs, legacy Service evidence, Contact and billing inputs preserved. | Account seat migration | commercial_services/account_seats.py |
| Prepare and update a Deal offer | Staff prepare an offer using the six-category mapping; category changes require review before the same Qwilr page is updated. | Private offer drafts and one linked Qwilr draft per Deal; no CRM or invoice writes. | Deal offers | app/blueprints/offers.py, tests/test_offers.py |
Not Process Rules
Some endpoints are intentionally excluded from the process-rule register:
- Read-only report exports.
- Health checks and internal debug pages.
- Thin technical proxy endpoints that forward a specific Projects update without applying Peppermint business rules.
- Compatibility endpoints that currently do not mutate records, including
POST /zoho/msp-invoices/reconcile-plan-lines. - One-off scripts unless they become repeatable business processes.
Commercial contribution reporting now begins on 1 July 2026, defaults to complete calendar months and costs recorded time using private salary-only or contractor rates matched by Projects user ID and work date. Unmatched rates retain the explicit $80 fallback. Salary/monthly-hours gaps are diagnostics, not extra expenses or evidence of idle time. Shared infrastructure and central operations stay at business level. Actual Xero P&L expenses replace service cost estimates in the business result; they are not added twice. See Current model and calculation rules.
Exploratory service capture and original-baseline migrations are retired. Their module-creation and record-write paths reject writes to the four selected modules. Historical ownership and private before-images are retained; the live report does not read the exploratory terms or budgets. See Shared service records.