| 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 lead marked Lost needs a reason, and a reason of “Other” also needs notes. A Perch rule can check that a later edit, by you or an agent, keeps them. Other validation can still reject the update.
Add the workflow requirement
The rule below is written from that implementation. It does not report a new defect, and we have not run a full 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 only needs the source, not a running CRM. Testing the whole workflow does need Frappe and the project’s application test environment.
Behavior rule
Save this as perch.yaml in the root of the clone:
- 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
After you commit an edit, scan the file with the custom rules:
perch scan --paths crm/fcrm/doctype/crm_lead/crm_lead.py --filter type=lint
Rule controls
To test the rule itself, remove the branch that requires notes for “Other” in a throwaway copy and run the same check. Then restore the branch and compare the two results. A useful rule fails the broken copy and passes the original.
The current method looks up the type of each status instead of assuming every status named “Lost” is configured the same way. Keep that distinction in the rule and in your test data when you adapt it to your CRM.
Workflow tests
Run each row of the scenario table through the application’s save path. That also shows whether the framework calls the validation method at all and rolls back rejected updates, which a review of one method cannot tell you.
Approval workflows follow the same pattern. State the allowed transition, the required role, and the required data, and scope each Perch rule to the method that enforces one requirement. Use integration tests for transaction boundaries and external effects.