| Lead update | Required result |
|---|---|
| Lost, no reason | Reject |
| Lost, reason “Other,” no notes | Reject |
| Lost, reason “Other,” notes supplied | Accept these fields |
| Open, no reason | Do not require a lost reason |
Frappe CRM’s lead validator enforces these conditions. A Perch rule can check whether a later edit preserves them. Other validation can still reject the update.
Add the workflow requirement
The rule below is based on that implementation; this example does not claim a new defect or a completed scan of Frappe CRM.
Source checkout
git clone --filter=blob:none https://github.com/frappe/crm.git crm-example
cd crm-example
git checkout 08f8fb5227494835a65024717fe41126cdac8358
Perch can read the source without a running CRM instance. Testing the complete workflow requires Frappe and the project’s application test environment.
Behavior rule
Save this in the clone’s root perch.yaml:
- name: lost-lead-requires-reason
where: crm/fcrm/doctype/crm_lead/crm_lead.py
each: method
ensure: >-
If this method validates a lead's lost reason, it rejects
a status of type Lost when lost_reason is empty. When
lost_reason is Other, it also rejects empty lost_notes.
It does not require a lost reason for an Open status.
Silently filling in a reason or checking only the reason
while accepting missing Other notes breaks this rule.
Methods unrelated to lost-reason validation satisfy it.
perch check crm/fcrm/doctype/crm_lead/crm_lead.py::CRMLead.validate_lost_reason \
--rules lost-lead-requires-reason
For a committed edit, scan the file with the custom rules:
perch scan --paths crm/fcrm/doctype/crm_lead/crm_lead.py --filter type=lint
Rule controls
In a disposable local copy, remove the branch requiring notes for “Other” and run the same check. Restore the branch and compare the result. This tests whether the question distinguishes the specific regression from the original implementation.
The current method looks up the status’s type rather than assuming every status named “Lost” has identical configuration. Keep that distinction in the rule and test data when adapting it to your CRM.
Workflow tests
Run the scenario table through the application’s save path. This also checks that the framework invokes the validation method and rolls back rejected updates. A method-level review alone cannot establish either behavior.
The same pattern works for approval workflows: state the allowed transition, required role, and required data, then keep each Perch rule scoped to the method that enforces one requirement. Use integration tests for transaction boundaries and external effects.