* feat: new DocType `Service Item and Finished Good Map`
* fix(ux): filters for Service Item and Finished Good
* fix: validations for Service Item and Finished Good
* feat: set FG Item on Service Item selection in PO
* refactor: one-to-many mapping between service item and finished goods
* feat: auto set Service Item for finished good in PO created from PP
* feat: auto set Service Item on Finished Good selection in PO
* test: add test case for service item and finished goods map
* feat: `BOM` field in `Finished Good Detail`
* feat: new DocType `Subcontracting BOM`
* fix: filters and validations for Subcontracting BOM
* feat: auto select Service Item in PO created from PP
* test: add test case for PO service item auto pick
* feat: pick BOM from Subcontracting BOM in SCO
* feat: auto pick `Service Item` on FG select
* refactor: remove DocType `Service Item and Finished Goods Map` and `Finished Good Detail`
* feat: fetch FG for Service Item
* chore: `linter`
* refactor: update `Auto Name` expression for Subcontracting BOM
* feat: Multi-level BOM Creator
* fix: renamed BOM Configurator to BOM Creator
* fix: added Cost in the tree
* fix: finished good cost
* fix: valuation rate in tree ui
* chore: conflicts and removed unnecessary files
* test: test cases for BOM Creator
* fix: added shortcut for the BOM Creator
* fix: added validation for Final Product
ifnull isn't really required when doing `!= 'anything'` because if it's null then value will be falsy.
ifnull is only required when checking `= ''` if you treat `null = ''`
Actuall better fix would be make things explcitly non-nullable, then we won't ever have to add this on such fields.
ref: https://github.com/frappe/frappe/pull/21822
I just applied semgrep autofix. Untested completed, review before merging.
```yaml
- id: frappe-set-value-semantics
patterns:
- pattern-either:
- pattern: frappe.db.set_value($DOCTYPE, None, $...AFTER)
- pattern: frappe.db.set_value($DOCTYPE, $DOCTYPE, $...AFTER)
fix: frappe.db.set_single_value($DOCTYPE, $...AFTER)
message: |
If $DOCTYPE is a single doctype then using `frappe.db.set_value` is discouraged for setting values in DB. Use db.set_single_value for single doctype instead.
languages: [python]
severity: ERROR
```