Merge branch 'develop' of https://github.com/frappe/erpnext into currency-exchange-settings
This commit is contained in:
commit
93d784dde3
2
.github/workflows/docs-checker.yml
vendored
2
.github/workflows/docs-checker.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
|||||||
- name: 'Setup Environment'
|
- name: 'Setup Environment'
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
python-version: 3.6
|
python-version: 3.8
|
||||||
|
|
||||||
- name: 'Clone repo'
|
- name: 'Clone repo'
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
2
.github/workflows/patch.yml
vendored
2
.github/workflows/patch.yml
vendored
@ -34,7 +34,7 @@ jobs:
|
|||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
python-version: 3.7
|
python-version: 3.8
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
|
2
.github/workflows/server-tests-mariadb.yml
vendored
2
.github/workflows/server-tests-mariadb.yml
vendored
@ -46,7 +46,7 @@ jobs:
|
|||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
python-version: 3.7
|
python-version: 3.8
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
|
2
.github/workflows/server-tests-postgres.yml
vendored
2
.github/workflows/server-tests-postgres.yml
vendored
@ -46,7 +46,7 @@ jobs:
|
|||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
python-version: 3.7
|
python-version: 3.8
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
|
2
.github/workflows/ui-tests.yml
vendored
2
.github/workflows/ui-tests.yml
vendored
@ -36,7 +36,7 @@ jobs:
|
|||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
python-version: 3.7
|
python-version: 3.8
|
||||||
|
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
|
@ -651,7 +651,7 @@
|
|||||||
"hide_seconds": 1,
|
"hide_seconds": 1,
|
||||||
"label": "Ignore Pricing Rule",
|
"label": "Ignore Pricing Rule",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"permlevel": 1,
|
"permlevel": 0,
|
||||||
"print_hide": 1
|
"print_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2038,7 +2038,7 @@
|
|||||||
"link_fieldname": "consolidated_invoice"
|
"link_fieldname": "consolidated_invoice"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2021-10-21 20:19:38.667508",
|
"modified": "2021-12-23 20:19:38.667508",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Invoice",
|
"name": "Sales Invoice",
|
||||||
|
@ -547,10 +547,7 @@ def get_columns(filters):
|
|||||||
"fieldname": "balance",
|
"fieldname": "balance",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"width": 130
|
"width": 130
|
||||||
}
|
},
|
||||||
]
|
|
||||||
|
|
||||||
columns.extend([
|
|
||||||
{
|
{
|
||||||
"label": _("Voucher Type"),
|
"label": _("Voucher Type"),
|
||||||
"fieldname": "voucher_type",
|
"fieldname": "voucher_type",
|
||||||
@ -584,7 +581,7 @@ def get_columns(filters):
|
|||||||
"fieldname": "project",
|
"fieldname": "project",
|
||||||
"width": 100
|
"width": 100
|
||||||
}
|
}
|
||||||
])
|
]
|
||||||
|
|
||||||
if filters.get("include_dimensions"):
|
if filters.get("include_dimensions"):
|
||||||
for dim in get_accounting_dimensions(as_list = False):
|
for dim in get_accounting_dimensions(as_list = False):
|
||||||
|
48
erpnext/accounts/test/test_reports.py
Normal file
48
erpnext/accounts/test/test_reports.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import unittest
|
||||||
|
from typing import List, Tuple
|
||||||
|
|
||||||
|
from erpnext.tests.utils import ReportFilters, ReportName, execute_script_report
|
||||||
|
|
||||||
|
DEFAULT_FILTERS = {
|
||||||
|
"company": "_Test Company",
|
||||||
|
"from_date": "2010-01-01",
|
||||||
|
"to_date": "2030-01-01",
|
||||||
|
"period_start_date": "2010-01-01",
|
||||||
|
"period_end_date": "2030-01-01"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
REPORT_FILTER_TEST_CASES: List[Tuple[ReportName, ReportFilters]] = [
|
||||||
|
("General Ledger", {"group_by": "Group by Voucher (Consolidated)"} ),
|
||||||
|
("General Ledger", {"group_by": "Group by Voucher (Consolidated)", "include_dimensions": 1} ),
|
||||||
|
("Accounts Payable", {"range1": 30, "range2": 60, "range3": 90, "range4": 120}),
|
||||||
|
("Accounts Receivable", {"range1": 30, "range2": 60, "range3": 90, "range4": 120}),
|
||||||
|
("Consolidated Financial Statement", {"report": "Balance Sheet"} ),
|
||||||
|
("Consolidated Financial Statement", {"report": "Profit and Loss Statement"} ),
|
||||||
|
("Consolidated Financial Statement", {"report": "Cash Flow"} ),
|
||||||
|
("Gross Profit", {"group_by": "Invoice"}),
|
||||||
|
("Gross Profit", {"group_by": "Item Code"}),
|
||||||
|
("Gross Profit", {"group_by": "Item Group"}),
|
||||||
|
("Gross Profit", {"group_by": "Customer"}),
|
||||||
|
("Gross Profit", {"group_by": "Customer Group"}),
|
||||||
|
("Item-wise Sales Register", {}),
|
||||||
|
("Item-wise Purchase Register", {}),
|
||||||
|
("Sales Register", {}),
|
||||||
|
("Purchase Register", {}),
|
||||||
|
("Tax Detail", {"mode": "run", "report_name": "Tax Detail"},),
|
||||||
|
]
|
||||||
|
|
||||||
|
OPTIONAL_FILTERS = {}
|
||||||
|
|
||||||
|
|
||||||
|
class TestReports(unittest.TestCase):
|
||||||
|
def test_execute_all_accounts_reports(self):
|
||||||
|
"""Test that all script report in stock modules are executable with supported filters"""
|
||||||
|
for report, filter in REPORT_FILTER_TEST_CASES:
|
||||||
|
execute_script_report(
|
||||||
|
report_name=report,
|
||||||
|
module="Accounts",
|
||||||
|
filters=filter,
|
||||||
|
default_filters=DEFAULT_FILTERS,
|
||||||
|
optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None,
|
||||||
|
)
|
@ -279,6 +279,7 @@ erpnext.patches.v13_0.add_custom_field_for_south_africa #2
|
|||||||
erpnext.patches.v13_0.update_recipient_email_digest
|
erpnext.patches.v13_0.update_recipient_email_digest
|
||||||
erpnext.patches.v13_0.shopify_deprecation_warning
|
erpnext.patches.v13_0.shopify_deprecation_warning
|
||||||
erpnext.patches.v13_0.remove_bad_selling_defaults
|
erpnext.patches.v13_0.remove_bad_selling_defaults
|
||||||
|
erpnext.patches.v13_0.trim_whitespace_from_serial_nos
|
||||||
erpnext.patches.v13_0.migrate_stripe_api
|
erpnext.patches.v13_0.migrate_stripe_api
|
||||||
erpnext.patches.v13_0.reset_clearance_date_for_intracompany_payment_entries
|
erpnext.patches.v13_0.reset_clearance_date_for_intracompany_payment_entries
|
||||||
erpnext.patches.v13_0.einvoicing_deprecation_warning
|
erpnext.patches.v13_0.einvoicing_deprecation_warning
|
||||||
|
65
erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py
Normal file
65
erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
broken_sles = frappe.db.sql("""
|
||||||
|
select name, serial_no
|
||||||
|
from `tabStock Ledger Entry`
|
||||||
|
where
|
||||||
|
is_cancelled = 0
|
||||||
|
and (serial_no like %s or serial_no like %s or serial_no like %s or serial_no like %s)
|
||||||
|
""",
|
||||||
|
(
|
||||||
|
" %", # leading whitespace
|
||||||
|
"% ", # trailing whitespace
|
||||||
|
"%\n %", # leading whitespace on newline
|
||||||
|
"% \n%", # trailing whitespace on newline
|
||||||
|
),
|
||||||
|
as_dict=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
frappe.db.MAX_WRITES_PER_TRANSACTION += len(broken_sles)
|
||||||
|
|
||||||
|
if not broken_sles:
|
||||||
|
return
|
||||||
|
|
||||||
|
broken_serial_nos = set()
|
||||||
|
|
||||||
|
# patch SLEs
|
||||||
|
for sle in broken_sles:
|
||||||
|
serial_no_list = get_serial_nos(sle.serial_no)
|
||||||
|
correct_sr_no = "\n".join(serial_no_list)
|
||||||
|
|
||||||
|
if correct_sr_no == sle.serial_no:
|
||||||
|
continue
|
||||||
|
|
||||||
|
frappe.db.set_value("Stock Ledger Entry", sle.name, "serial_no", correct_sr_no, update_modified=False)
|
||||||
|
broken_serial_nos.update(serial_no_list)
|
||||||
|
|
||||||
|
if not broken_serial_nos:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Patch serial No documents if they don't have purchase info
|
||||||
|
# Purchase info is used for fetching incoming rate
|
||||||
|
broken_sr_no_records = frappe.get_list("Serial No",
|
||||||
|
filters={
|
||||||
|
"status":"Active",
|
||||||
|
"name": ("in", broken_serial_nos),
|
||||||
|
"purchase_document_type": ("is", "not set")
|
||||||
|
},
|
||||||
|
pluck="name",
|
||||||
|
)
|
||||||
|
|
||||||
|
frappe.db.MAX_WRITES_PER_TRANSACTION += len(broken_sr_no_records)
|
||||||
|
|
||||||
|
patch_savepoint = "serial_no_patch"
|
||||||
|
for serial_no in broken_sr_no_records:
|
||||||
|
try:
|
||||||
|
frappe.db.savepoint(patch_savepoint)
|
||||||
|
sn = frappe.get_doc("Serial No", serial_no)
|
||||||
|
sn.update_serial_no_reference()
|
||||||
|
sn.db_update()
|
||||||
|
except Exception:
|
||||||
|
frappe.db.rollback(save_point=patch_savepoint)
|
@ -125,17 +125,23 @@ def execute_script_report(
|
|||||||
if default_filters is None:
|
if default_filters is None:
|
||||||
default_filters = {}
|
default_filters = {}
|
||||||
|
|
||||||
|
test_filters = []
|
||||||
report_execute_fn = frappe.get_attr(get_report_module_dotted_path(module, report_name) + ".execute")
|
report_execute_fn = frappe.get_attr(get_report_module_dotted_path(module, report_name) + ".execute")
|
||||||
report_filters = frappe._dict(default_filters).copy().update(filters)
|
report_filters = frappe._dict(default_filters).copy().update(filters)
|
||||||
|
|
||||||
report_data = report_execute_fn(report_filters)
|
test_filters.append(report_filters)
|
||||||
|
|
||||||
if optional_filters:
|
if optional_filters:
|
||||||
for key, value in optional_filters.items():
|
for key, value in optional_filters.items():
|
||||||
filter_with_optional_param = report_filters.copy().update({key: value})
|
test_filters.append(report_filters.copy().update({key: value}))
|
||||||
report_execute_fn(filter_with_optional_param)
|
|
||||||
|
for test_filter in test_filters:
|
||||||
|
try:
|
||||||
|
report_execute_fn(test_filter)
|
||||||
|
except Exception:
|
||||||
|
print(f"Report failed to execute with filters: {test_filter}")
|
||||||
|
raise
|
||||||
|
|
||||||
return report_data
|
|
||||||
|
|
||||||
|
|
||||||
def timeout(seconds=30, error_message="Test timed out."):
|
def timeout(seconds=30, error_message="Test timed out."):
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# frappe # https://github.com/frappe/frappe is installed during bench-init
|
# frappe # https://github.com/frappe/frappe is installed during bench-init
|
||||||
gocardless-pro~=1.22.0
|
gocardless-pro~=1.22.0
|
||||||
googlemaps # used in ERPNext, but dependency is defined in Frappe
|
googlemaps
|
||||||
pandas~=1.1.5
|
pandas~=1.1.5
|
||||||
plaid-python~=7.2.1
|
plaid-python~=7.2.1
|
||||||
pycountry~=20.7.3
|
pycountry~=20.7.3
|
||||||
|
Loading…
Reference in New Issue
Block a user