feat(regional): a central place for regional address templates (#19862)
* feat: a central place for regional address templates * set up address templates during install * why don't the tests run? * fix: remove unused variables, fix cwd * fix: .get() dicts contents * fix: choose the right default * fix: fieldname is template, not html * fix: import unittest * fix: remove unnecessary code * fix: ensure country exists * fix: ensure country exists * feat: test updating an existing template * fix(regional): DuplicateEntryError in test_update_address_template * refactor and set 'is_default' * fix codacy * fix: patch gst_fixes * fix: patch update_address_template_for_india Co-authored-by: Nabin Hait <nabinhait@gmail.com>
This commit is contained in:
parent
0672b6b2e8
commit
9aae0c27c2
@ -3,10 +3,10 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from erpnext.regional.india.setup import update_address_template
|
from erpnext.regional.address_template.setup import set_up_address_templates
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
if frappe.db.get_value('Company', {'country': 'India'}, 'name'):
|
if frappe.db.get_value('Company', {'country': 'India'}, 'name'):
|
||||||
address_template = frappe.db.get_value('Address Template', 'India', 'template')
|
address_template = frappe.db.get_value('Address Template', 'India', 'template')
|
||||||
if not address_template or "gstin" not in address_template:
|
if not address_template or "gstin" not in address_template:
|
||||||
update_address_template()
|
set_up_address_templates(default_country='India')
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.custom.doctype.custom_field.custom_field import create_custom_field
|
from frappe.custom.doctype.custom_field.custom_field import create_custom_field
|
||||||
from erpnext.regional.india.setup import update_address_template
|
from erpnext.regional.address_template.setup import set_up_address_templates
|
||||||
|
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
company = frappe.get_all('Company', filters = {'country': 'India'})
|
company = frappe.get_all('Company', filters = {'country': 'India'})
|
||||||
@ -10,9 +11,10 @@ def execute():
|
|||||||
|
|
||||||
update_existing_custom_fields()
|
update_existing_custom_fields()
|
||||||
add_custom_fields()
|
add_custom_fields()
|
||||||
update_address_template()
|
set_up_address_templates(default_country='India')
|
||||||
frappe.reload_doc("regional", "print_format", "gst_tax_invoice")
|
frappe.reload_doc("regional", "print_format", "gst_tax_invoice")
|
||||||
|
|
||||||
|
|
||||||
def update_existing_custom_fields():
|
def update_existing_custom_fields():
|
||||||
frappe.db.sql("""update `tabCustom Field` set label = 'HSN/SAC'
|
frappe.db.sql("""update `tabCustom Field` set label = 'HSN/SAC'
|
||||||
where fieldname='gst_hsn_code' and label='GST HSN Code'
|
where fieldname='gst_hsn_code' and label='GST HSN Code'
|
||||||
@ -34,6 +36,7 @@ def update_existing_custom_fields():
|
|||||||
where fieldname='gst_hsn_code' and dt in ('Sales Invoice Item', 'Purchase Invoice Item')
|
where fieldname='gst_hsn_code' and dt in ('Sales Invoice Item', 'Purchase Invoice Item')
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
||||||
def add_custom_fields():
|
def add_custom_fields():
|
||||||
hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC',
|
hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC',
|
||||||
fieldtype='Data', options='item_code.gst_hsn_code', insert_after='description')
|
fieldtype='Data', options='item_code.gst_hsn_code', insert_after='description')
|
||||||
|
18
erpnext/regional/address_template/README.md
Normal file
18
erpnext/regional/address_template/README.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
To add an **Address Template** for your country, place a new file in this directory:
|
||||||
|
|
||||||
|
* File name: `your_country.html` (lower case with underscores)
|
||||||
|
* File content: a [Jinja Template](http://jinja.pocoo.org/docs/templates/).
|
||||||
|
|
||||||
|
All the fields of **Address** (including Custom Fields, if any) will be available to the template. Example:
|
||||||
|
|
||||||
|
```jinja
|
||||||
|
{{ address_line1 }}<br>
|
||||||
|
{% if address_line2 %}{{ address_line2 }}<br>{% endif -%}
|
||||||
|
{{ city }}<br>
|
||||||
|
{% if state %}{{ state }}<br>{% endif -%}
|
||||||
|
{% if pincode %} PIN: {{ pincode }}<br>{% endif -%}
|
||||||
|
{{ country }}<br>
|
||||||
|
{% if phone %}Phone: {{ phone }}<br>{% endif -%}
|
||||||
|
{% if fax %}Fax: {{ fax }}<br>{% endif -%}
|
||||||
|
{% if email_id %}Email: {{ email_id }}<br>{% endif -%}
|
||||||
|
```
|
0
erpnext/regional/address_template/__init__.py
Normal file
0
erpnext/regional/address_template/__init__.py
Normal file
53
erpnext/regional/address_template/setup.py
Normal file
53
erpnext/regional/address_template/setup.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
"""Import Address Templates from ./templates directory."""
|
||||||
|
import os
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def set_up_address_templates(default_country=None):
|
||||||
|
for country, html in get_address_templates():
|
||||||
|
is_default = 1 if country == default_country else 0
|
||||||
|
update_address_template(country, html, is_default)
|
||||||
|
|
||||||
|
def get_address_templates():
|
||||||
|
"""
|
||||||
|
Return country and path for all HTML files in this directory.
|
||||||
|
|
||||||
|
Returns a list of dicts.
|
||||||
|
"""
|
||||||
|
def country(file_name):
|
||||||
|
"""Convert 'united_states.html' to 'United States'."""
|
||||||
|
suffix_pos = file_name.find(".html")
|
||||||
|
country_snake_case = file_name[:suffix_pos]
|
||||||
|
country_title_case = " ".join(country_snake_case.split("_")).title()
|
||||||
|
return country_title_case
|
||||||
|
|
||||||
|
def get_file_content(file_name):
|
||||||
|
"""Convert 'united_states.html' to '/path/to/united_states.html'."""
|
||||||
|
full_path = os.path.join(template_dir, file_name)
|
||||||
|
with open(full_path, "r") as f:
|
||||||
|
content = f.read()
|
||||||
|
return content
|
||||||
|
|
||||||
|
dir_name = os.path.dirname(__file__)
|
||||||
|
template_dir = os.path.join(dir_name, "templates")
|
||||||
|
file_names = os.listdir(template_dir)
|
||||||
|
html_files = [file for file in file_names if file.endswith(".html")]
|
||||||
|
|
||||||
|
return [(country(file_name), get_file_content(file_name)) for file_name in html_files]
|
||||||
|
|
||||||
|
|
||||||
|
def update_address_template(country, html, is_default=0):
|
||||||
|
"""Update existing Address Template or create a new one."""
|
||||||
|
if not frappe.db.exists("Country", country):
|
||||||
|
frappe.log_error("Country {} for regional Address Template does not exist.".format(country))
|
||||||
|
return
|
||||||
|
|
||||||
|
if frappe.db.exists("Address Template", country):
|
||||||
|
frappe.db.set_value("Address Template", country, "template", html)
|
||||||
|
frappe.db.set_value("Address Template", country, "is_default", is_default)
|
||||||
|
else:
|
||||||
|
frappe.get_doc(dict(
|
||||||
|
doctype="Address Template",
|
||||||
|
country=country,
|
||||||
|
is_default=is_default,
|
||||||
|
template=html
|
||||||
|
)).insert()
|
@ -0,0 +1,45 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
from unittest import TestCase
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from erpnext.regional.address_template.setup import get_address_templates
|
||||||
|
from erpnext.regional.address_template.setup import update_address_template
|
||||||
|
|
||||||
|
def ensure_country(country):
|
||||||
|
if frappe.db.exists("Country", country):
|
||||||
|
return frappe.get_doc("Country", country)
|
||||||
|
else:
|
||||||
|
c = frappe.get_doc({
|
||||||
|
"doctype": "Country",
|
||||||
|
"country_name": country
|
||||||
|
})
|
||||||
|
c.insert()
|
||||||
|
return c
|
||||||
|
|
||||||
|
class TestRegionalAddressTemplate(TestCase):
|
||||||
|
def test_get_address_templates(self):
|
||||||
|
"""Get the countries and paths from the templates directory."""
|
||||||
|
templates = get_address_templates()
|
||||||
|
self.assertIsInstance(templates, list)
|
||||||
|
self.assertIsInstance(templates[0], tuple)
|
||||||
|
|
||||||
|
def test_create_address_template(self):
|
||||||
|
"""Create a new Address Template."""
|
||||||
|
country = ensure_country("Germany")
|
||||||
|
update_address_template(country.name, "TEST")
|
||||||
|
doc = frappe.get_doc("Address Template", country.name)
|
||||||
|
self.assertEqual(doc.template, "TEST")
|
||||||
|
|
||||||
|
def test_update_address_template(self):
|
||||||
|
"""Update an existing Address Template."""
|
||||||
|
country = ensure_country("Germany")
|
||||||
|
if not frappe.db.exists("Address Template", country.name):
|
||||||
|
template = frappe.get_doc({
|
||||||
|
"doctype": "Address Template",
|
||||||
|
"country": country.name,
|
||||||
|
"template": "EXISTING"
|
||||||
|
}).insert()
|
||||||
|
|
||||||
|
update_address_template(country.name, "NEW")
|
||||||
|
doc = frappe.get_doc("Address Template", country.name)
|
||||||
|
self.assertEqual(doc.template, "NEW")
|
@ -3,29 +3,4 @@ import frappe
|
|||||||
|
|
||||||
|
|
||||||
def setup(company=None, patch=True):
|
def setup(company=None, patch=True):
|
||||||
if not patch:
|
pass
|
||||||
update_address_template()
|
|
||||||
|
|
||||||
|
|
||||||
def update_address_template():
|
|
||||||
"""
|
|
||||||
Read address template from file. Update existing Address Template or create a
|
|
||||||
new one.
|
|
||||||
"""
|
|
||||||
dir_name = os.path.dirname(__file__)
|
|
||||||
template_path = os.path.join(dir_name, 'address_template.html')
|
|
||||||
|
|
||||||
with open(template_path, 'r') as template_file:
|
|
||||||
template_html = template_file.read()
|
|
||||||
|
|
||||||
address_template = frappe.db.get_value('Address Template', 'Germany')
|
|
||||||
|
|
||||||
if address_template:
|
|
||||||
frappe.db.set_value('Address Template', 'Germany', 'template', template_html)
|
|
||||||
else:
|
|
||||||
# make new html template for Germany
|
|
||||||
frappe.get_doc(dict(
|
|
||||||
doctype='Address Template',
|
|
||||||
country='Germany',
|
|
||||||
template=template_html
|
|
||||||
)).insert()
|
|
||||||
|
@ -13,7 +13,6 @@ from frappe.utils import today
|
|||||||
def setup(company=None, patch=True):
|
def setup(company=None, patch=True):
|
||||||
setup_company_independent_fixtures()
|
setup_company_independent_fixtures()
|
||||||
if not patch:
|
if not patch:
|
||||||
update_address_template()
|
|
||||||
make_fixtures(company)
|
make_fixtures(company)
|
||||||
|
|
||||||
# TODO: for all countries
|
# TODO: for all countries
|
||||||
@ -24,21 +23,6 @@ def setup_company_independent_fixtures():
|
|||||||
frappe.enqueue('erpnext.regional.india.setup.add_hsn_sac_codes', now=frappe.flags.in_test)
|
frappe.enqueue('erpnext.regional.india.setup.add_hsn_sac_codes', now=frappe.flags.in_test)
|
||||||
add_print_formats()
|
add_print_formats()
|
||||||
|
|
||||||
def update_address_template():
|
|
||||||
with open(os.path.join(os.path.dirname(__file__), 'address_template.html'), 'r') as f:
|
|
||||||
html = f.read()
|
|
||||||
|
|
||||||
address_template = frappe.db.get_value('Address Template', 'India')
|
|
||||||
if address_template:
|
|
||||||
frappe.db.set_value('Address Template', 'India', 'template', html)
|
|
||||||
else:
|
|
||||||
# make new html template for India
|
|
||||||
frappe.get_doc(dict(
|
|
||||||
doctype='Address Template',
|
|
||||||
country='India',
|
|
||||||
template=html
|
|
||||||
)).insert()
|
|
||||||
|
|
||||||
def add_hsn_sac_codes():
|
def add_hsn_sac_codes():
|
||||||
# HSN codes
|
# HSN codes
|
||||||
with open(os.path.join(os.path.dirname(__file__), 'hsn_code_data.json'), 'r') as f:
|
with open(os.path.join(os.path.dirname(__file__), 'hsn_code_data.json'), 'r') as f:
|
||||||
|
@ -5,12 +5,9 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
|
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
|
||||||
|
|
||||||
|
|
||||||
def setup(company=None, patch=True):
|
def setup(company=None, patch=True):
|
||||||
make_custom_fields()
|
make_custom_fields()
|
||||||
add_print_formats()
|
add_print_formats()
|
||||||
update_address_template()
|
|
||||||
|
|
||||||
|
|
||||||
def make_custom_fields():
|
def make_custom_fields():
|
||||||
custom_fields = {
|
custom_fields = {
|
||||||
@ -21,22 +18,7 @@ def make_custom_fields():
|
|||||||
}
|
}
|
||||||
create_custom_fields(custom_fields)
|
create_custom_fields(custom_fields)
|
||||||
|
|
||||||
|
|
||||||
def add_print_formats():
|
def add_print_formats():
|
||||||
frappe.reload_doc("regional", "print_format", "irs_1099_form")
|
frappe.reload_doc("regional", "print_format", "irs_1099_form")
|
||||||
frappe.db.sql(""" update `tabPrint Format` set disabled = 0 where
|
frappe.db.sql(""" update `tabPrint Format` set disabled = 0 where
|
||||||
name in('IRS 1099 Form') """)
|
name in('IRS 1099 Form') """)
|
||||||
|
|
||||||
|
|
||||||
def update_address_template():
|
|
||||||
html = """{{ address_line1 }}<br>
|
|
||||||
{% if address_line2 %}{{ address_line2 }}<br>{% endif -%}
|
|
||||||
{{ city }}, {% if state %}{{ state }}{% endif -%}{% if pincode %} {{ pincode }}<br>{% endif -%}
|
|
||||||
{% if country != "United States" %}{{ country|upper }}{% endif -%}
|
|
||||||
"""
|
|
||||||
|
|
||||||
address_template = frappe.db.get_value('Address Template', 'United States')
|
|
||||||
if address_template:
|
|
||||||
frappe.db.set_value('Address Template', 'United States', 'template', html)
|
|
||||||
else:
|
|
||||||
frappe.get_doc(dict(doctype='Address Template', country='United States', template=html)).insert()
|
|
||||||
|
@ -8,9 +8,11 @@ import frappe, os, json
|
|||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.desk.page.setup_wizard.setup_wizard import make_records
|
from frappe.desk.page.setup_wizard.setup_wizard import make_records
|
||||||
from frappe.utils import cstr, getdate
|
from frappe.utils import cstr, getdate
|
||||||
from erpnext.accounts.doctype.account.account import RootNotEditable
|
|
||||||
from frappe.desk.doctype.global_search_settings.global_search_settings import update_global_search_doctypes
|
from frappe.desk.doctype.global_search_settings.global_search_settings import update_global_search_doctypes
|
||||||
|
|
||||||
|
from erpnext.accounts.doctype.account.account import RootNotEditable
|
||||||
|
from erpnext.regional.address_template.setup import set_up_address_templates
|
||||||
|
|
||||||
default_lead_sources = ["Existing Customer", "Reference", "Advertisement",
|
default_lead_sources = ["Existing Customer", "Reference", "Advertisement",
|
||||||
"Cold Calling", "Exhibition", "Supplier Reference", "Mass Mailing",
|
"Cold Calling", "Exhibition", "Supplier Reference", "Mass Mailing",
|
||||||
"Customer's Vendor", "Campaign", "Walk In"]
|
"Customer's Vendor", "Campaign", "Walk In"]
|
||||||
@ -30,7 +32,7 @@ def install(country=None):
|
|||||||
{ 'doctype': 'Domain', 'domain': 'Agriculture'},
|
{ 'doctype': 'Domain', 'domain': 'Agriculture'},
|
||||||
{ 'doctype': 'Domain', 'domain': 'Non Profit'},
|
{ 'doctype': 'Domain', 'domain': 'Non Profit'},
|
||||||
|
|
||||||
# address template
|
# ensure at least an empty Address Template exists for this Country
|
||||||
{'doctype':"Address Template", "country": country},
|
{'doctype':"Address Template", "country": country},
|
||||||
|
|
||||||
# item group
|
# item group
|
||||||
@ -269,12 +271,11 @@ def install(country=None):
|
|||||||
|
|
||||||
# Records for the Supplier Scorecard
|
# Records for the Supplier Scorecard
|
||||||
from erpnext.buying.doctype.supplier_scorecard.supplier_scorecard import make_default_records
|
from erpnext.buying.doctype.supplier_scorecard.supplier_scorecard import make_default_records
|
||||||
|
|
||||||
make_default_records()
|
make_default_records()
|
||||||
|
|
||||||
make_records(records)
|
make_records(records)
|
||||||
|
set_up_address_templates(default_country=country)
|
||||||
set_more_defaults()
|
set_more_defaults()
|
||||||
|
|
||||||
update_global_search_doctypes()
|
update_global_search_doctypes()
|
||||||
|
|
||||||
# path = frappe.get_app_path('erpnext', 'regional', frappe.scrub(country))
|
# path = frappe.get_app_path('erpnext', 'regional', frappe.scrub(country))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user