refactor: ship Custom Fields and Property Setters as module customizations

Move the Sales Invoice withholding fields and both Property Setters from
fixtures to default_thai_company/custom/{sales_invoice,payment_entry}.json
with sync_on_migrate. sync_customizations updates Custom Fields in place
instead of the delete/re-insert that fixtures do on every migrate.
This commit is contained in:
2026-09-12 13:13:49 +00:00
parent ed4062590a
commit abeb2af0c8
6 changed files with 266 additions and 114 deletions
@@ -0,0 +1,32 @@
{
"custom_fields": [],
"custom_perms": [],
"doctype": "Payment Entry",
"links": [],
"property_setters": [
{
"_assign": null,
"_comments": null,
"_liked_by": null,
"_user_tags": null,
"creation": "2026-09-11 17:18:28.670630",
"default_value": null,
"doc_type": "Payment Entry",
"docstatus": 0,
"doctype_or_field": "DocField",
"field_name": "apply_tax_withholding_amount",
"idx": 0,
"is_system_generated": 0,
"modified": "2026-09-11 12:00:00",
"modified_by": "Administrator",
"module": null,
"name": "Payment Entry-apply_tax_withholding_amount-depends_on",
"owner": "Administrator",
"property": "depends_on",
"property_type": "Data",
"row_name": null,
"value": "eval:doc.party_type == 'Supplier' || (doc.party_type == 'Customer' && doc.payment_type == 'Receive')"
}
],
"sync_on_migrate": 1
}
@@ -0,0 +1,225 @@
{
"custom_fields": [
{
"_assign": null,
"_comments": null,
"_liked_by": null,
"_user_tags": null,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
"collapsible_depends_on": null,
"columns": 0,
"creation": "2026-09-11 17:18:48.182536",
"default": null,
"depends_on": "eval:doc.tax_withholding_category",
"description": null,
"docstatus": 0,
"dt": "Sales Invoice",
"fetch_from": null,
"fetch_if_empty": 0,
"fieldname": "amount_after_withholding",
"fieldtype": "Currency",
"hidden": 0,
"hide_border": 0,
"hide_days": 0,
"hide_seconds": 0,
"idx": 80,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_preview": 0,
"in_standard_filter": 0,
"insert_after": "withholding_tax_amount",
"is_system_generated": 0,
"is_virtual": 0,
"label": "Net Payable After Withholding Tax",
"length": 0,
"link_filters": null,
"mandatory_depends_on": null,
"modified": "2026-09-11 17:18:48.182536",
"modified_by": "Administrator",
"module": null,
"name": "Sales Invoice-amount_after_withholding",
"no_copy": 1,
"non_negative": 0,
"options": "currency",
"owner": "Administrator",
"permlevel": 0,
"placeholder": null,
"precision": null,
"print_hide": 0,
"print_hide_if_no_value": 1,
"print_width": null,
"read_only": 1,
"read_only_depends_on": null,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"show_dashboard": 0,
"sort_options": 0,
"translatable": 0,
"unique": 0,
"width": null
},
{
"_assign": null,
"_comments": null,
"_liked_by": null,
"_user_tags": null,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"collapsible_depends_on": null,
"columns": 0,
"creation": "2026-09-11 17:18:44.710456",
"default": null,
"depends_on": null,
"description": null,
"docstatus": 0,
"dt": "Sales Invoice",
"fetch_from": "customer.tax_withholding_category",
"fetch_if_empty": 1,
"fieldname": "tax_withholding_category",
"fieldtype": "Link",
"hidden": 0,
"hide_border": 0,
"hide_days": 0,
"hide_seconds": 0,
"idx": 57,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_preview": 0,
"in_standard_filter": 0,
"insert_after": "taxes_and_charges",
"is_system_generated": 0,
"is_virtual": 0,
"label": "Tax Withholding Category",
"length": 0,
"link_filters": null,
"mandatory_depends_on": null,
"modified": "2026-09-11 18:00:00",
"modified_by": "Administrator",
"module": null,
"name": "Sales Invoice-tax_withholding_category",
"no_copy": 0,
"non_negative": 0,
"options": "Tax Withholding Category",
"owner": "Administrator",
"permlevel": 0,
"placeholder": null,
"precision": null,
"print_hide": 1,
"print_hide_if_no_value": 0,
"print_width": null,
"read_only": 0,
"read_only_depends_on": null,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"show_dashboard": 0,
"sort_options": 0,
"translatable": 0,
"unique": 0,
"width": null
},
{
"_assign": null,
"_comments": null,
"_liked_by": null,
"_user_tags": null,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"collapsible_depends_on": null,
"columns": 0,
"creation": "2026-09-11 17:18:47.244523",
"default": null,
"depends_on": "eval:doc.tax_withholding_category",
"description": null,
"docstatus": 0,
"dt": "Sales Invoice",
"fetch_from": null,
"fetch_if_empty": 0,
"fieldname": "withholding_tax_amount",
"fieldtype": "Currency",
"hidden": 0,
"hide_border": 0,
"hide_days": 0,
"hide_seconds": 0,
"idx": 79,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_preview": 0,
"in_standard_filter": 0,
"insert_after": "rounded_total",
"is_system_generated": 0,
"is_virtual": 0,
"label": "Withholding Tax",
"length": 0,
"link_filters": null,
"mandatory_depends_on": null,
"modified": "2026-09-11 18:00:00",
"modified_by": "Administrator",
"module": null,
"name": "Sales Invoice-withholding_tax_amount",
"no_copy": 1,
"non_negative": 0,
"options": "currency",
"owner": "Administrator",
"permlevel": 0,
"placeholder": null,
"precision": null,
"print_hide": 0,
"print_hide_if_no_value": 1,
"print_width": null,
"read_only": 1,
"read_only_depends_on": null,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"show_dashboard": 0,
"sort_options": 0,
"translatable": 0,
"unique": 0,
"width": null
}
],
"custom_perms": [],
"doctype": "Sales Invoice",
"links": [],
"property_setters": [
{
"_assign": null,
"_comments": null,
"_liked_by": null,
"_user_tags": null,
"creation": "2026-09-11 17:18:28.581896",
"default_value": null,
"doc_type": "Sales Invoice",
"docstatus": 0,
"doctype_or_field": "DocType",
"field_name": null,
"idx": 0,
"is_system_generated": 1,
"modified": "2026-09-10 13:55:13.996942",
"modified_by": "Administrator",
"module": null,
"name": "Sales Invoice-main-default_print_format",
"owner": "Administrator",
"property": "default_print_format",
"property_type": "Data",
"row_name": null,
"value": "Default Standard Sales Invoice"
}
],
"sync_on_migrate": 1
}
@@ -1,50 +0,0 @@
[
{
"docstatus": 0,
"doctype": "Custom Field",
"dt": "Sales Invoice",
"fetch_from": "customer.tax_withholding_category",
"fetch_if_empty": 1,
"fieldname": "tax_withholding_category",
"fieldtype": "Link",
"insert_after": "taxes_and_charges",
"label": "Tax Withholding Category",
"modified": "2026-09-11 18:00:00.000000",
"name": "Sales Invoice-tax_withholding_category",
"options": "Tax Withholding Category",
"print_hide": 1
},
{
"depends_on": "eval:doc.tax_withholding_category",
"docstatus": 0,
"doctype": "Custom Field",
"dt": "Sales Invoice",
"fieldname": "withholding_tax_amount",
"fieldtype": "Currency",
"insert_after": "rounded_total",
"label": "Withholding Tax",
"modified": "2026-09-11 18:00:00.000000",
"name": "Sales Invoice-withholding_tax_amount",
"no_copy": 1,
"options": "currency",
"print_hide_if_no_value": 1,
"read_only": 1
},
{
"bold": 1,
"depends_on": "eval:doc.tax_withholding_category",
"docstatus": 0,
"doctype": "Custom Field",
"dt": "Sales Invoice",
"fieldname": "amount_after_withholding",
"fieldtype": "Currency",
"insert_after": "withholding_tax_amount",
"label": "Net Payable After Withholding Tax",
"modified": "2026-09-11 18:00:00.000000",
"name": "Sales Invoice-amount_after_withholding",
"no_copy": 1,
"options": "currency",
"print_hide_if_no_value": 1,
"read_only": 1
}
]
@@ -1,34 +0,0 @@
[
{
"default_value": null,
"doc_type": "Sales Invoice",
"docstatus": 0,
"doctype": "Property Setter",
"doctype_or_field": "DocType",
"field_name": null,
"is_system_generated": 1,
"modified": "2026-09-10 13:55:13.996942",
"module": null,
"name": "Sales Invoice-main-default_print_format",
"property": "default_print_format",
"property_type": "Data",
"row_name": null,
"value": "Default Standard Sales Invoice"
},
{
"default_value": null,
"doc_type": "Payment Entry",
"docstatus": 0,
"doctype": "Property Setter",
"doctype_or_field": "DocField",
"field_name": "apply_tax_withholding_amount",
"is_system_generated": 0,
"modified": "2026-09-11 12:00:00.000000",
"module": null,
"name": "Payment Entry-apply_tax_withholding_amount-depends_on",
"property": "depends_on",
"property_type": "Data",
"row_name": null,
"value": "eval:doc.party_type == 'Supplier' || (doc.party_type == 'Customer' && doc.payment_type == 'Receive')"
}
]
+2 -27
View File
@@ -84,38 +84,13 @@ jinja = {
# Fixtures # Fixtures
# -------- # --------
# Custom Fields and Property Setters live in default_thai_company/custom/*.json
# (synced in place on install and migrate); fixtures are for whole documents.
fixtures = [ fixtures = [
{"doctype": "Letter Head", "filters": [["name", "in", ["Default Letter Head"]]]}, {"doctype": "Letter Head", "filters": [["name", "in", ["Default Letter Head"]]]},
{"doctype": "Address Template", "filters": [["name", "in", ["Thailand"]]]}, {"doctype": "Address Template", "filters": [["name", "in", ["Thailand"]]]},
{"doctype": "Print Format", "filters": [["name", "in", ["Default Standard Sales Invoice"]]]}, {"doctype": "Print Format", "filters": [["name", "in", ["Default Standard Sales Invoice"]]]},
{
"doctype": "Property Setter",
"filters": [
[
"name",
"in",
[
"Sales Invoice-main-default_print_format",
"Payment Entry-apply_tax_withholding_amount-depends_on",
],
]
],
},
{"doctype": "Tax Withholding Category", "filters": [["name", "like", "WHT %"]]}, {"doctype": "Tax Withholding Category", "filters": [["name", "like", "WHT %"]]},
{
"doctype": "Custom Field",
"filters": [
[
"name",
"in",
[
"Sales Invoice-tax_withholding_category",
"Sales Invoice-withholding_tax_amount",
"Sales Invoice-amount_after_withholding",
],
]
],
},
] ]
# Installation # Installation
@@ -1,5 +1,8 @@
import json
import frappe import frappe
from frappe.modules.import_file import import_file_by_path from frappe.modules.import_file import import_file_by_path
from frappe.modules.utils import sync_customizations_for_doctype
from frappe.tests.utils import FrappeTestCase from frappe.tests.utils import FrappeTestCase
from frappe.utils import nowdate from frappe.utils import nowdate
@@ -10,7 +13,7 @@ ABBR = "_TWC"
CUSTOMER = "_Test WHT Customer" CUSTOMER = "_Test WHT Customer"
ITEM = "_Test WHT Service" ITEM = "_Test WHT Service"
FIXTURE = frappe.get_app_path("default_thai_company", "fixtures", "tax_withholding_category.json") FIXTURE = frappe.get_app_path("default_thai_company", "fixtures", "tax_withholding_category.json")
CUSTOM_FIELDS = frappe.get_app_path("default_thai_company", "fixtures", "custom_field.json") CUSTOM_DIR = frappe.get_app_path("default_thai_company", "default_thai_company", "custom")
class TestTaxWithholding(FrappeTestCase): class TestTaxWithholding(FrappeTestCase):
@@ -20,8 +23,9 @@ class TestTaxWithholding(FrappeTestCase):
# Fixture categories must exist before the company is created so the # Fixture categories must exist before the company is created so the
# Company hook has something to link; force=True re-imports. # Company hook has something to link; force=True re-imports.
import_file_by_path(FIXTURE, force=True, data_import=True) import_file_by_path(FIXTURE, force=True, data_import=True)
import_file_by_path(CUSTOM_FIELDS, force=True, data_import=True) for fname in ("sales_invoice.json", "payment_entry.json"):
frappe.clear_cache(doctype="Sales Invoice") with open(f"{CUSTOM_DIR}/{fname}") as f:
sync_customizations_for_doctype(json.load(f), CUSTOM_DIR, fname)
frappe.get_doc( frappe.get_doc(
{ {