From ac9a4fe03c40409af44f2f101d75968991a5f579 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Tue, 11 Jun 2019 14:25:44 +0530 Subject: [PATCH 01/30] feat: add tax and charges in expense claim --- .../hr/doctype/expense_claim/expense_claim.js | 62 +++++++++++ .../doctype/expense_claim/expense_claim.json | 22 +++- .../hr/doctype/expense_claim/expense_claim.py | 33 +++++- .../expense_taxes_and_charges/__init__.py | 0 .../expense_taxes_and_charges.json | 103 ++++++++++++++++++ .../expense_taxes_and_charges.py | 10 ++ 6 files changed, 227 insertions(+), 3 deletions(-) create mode 100644 erpnext/hr/doctype/expense_taxes_and_charges/__init__.py create mode 100644 erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json create mode 100644 erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.py diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js index 7c6abc7f94..0ff70cb680 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.js +++ b/erpnext/hr/doctype/expense_claim/expense_claim.js @@ -157,6 +157,14 @@ frappe.ui.form.on("Expense Claim", { } }; }); + // frm.set_query("taxes", "account_head", function(doc) { + // return { + // filters: [ + // ['docstatus', '=', 1], + // ['company', '=', doc.company] + // ] + // }; + // }); }, onload: function(frm) { @@ -259,6 +267,18 @@ frappe.ui.form.on("Expense Claim", { frm.events.get_advances(frm); }, + get_taxes: function(frm) { + if(frm.doc.taxes) { + frappe.call({ + method: "calculate_taxes", + doc: frm.doc, + callback: (r) => { + refresh_field("taxes"); + } + }); + } + }, + get_advances: function(frm) { frappe.model.clear_table(frm.doc, "advances"); if (frm.doc.employee) { @@ -298,6 +318,7 @@ frappe.ui.form.on("Expense Claim Detail", { sanctioned_amount: function(frm, cdt, cdn) { var doc = frm.doc; cur_frm.cscript.calculate_total(doc,cdt,cdn); + frm.trigger("get_taxes"); } }); @@ -332,6 +353,47 @@ frappe.ui.form.on("Expense Claim Advance", { } }); +frappe.ui.form.on("Expense Taxes and Charges", { + account_head: function(frm, cdt, cdn) { + var child = locals[cdt][cdn]; + if(child.account_head && !child.description && !child.rate) { + // set description from account head + child.description = child.account_head.split(' - ').slice(0, -1).join(' - '); + + // set the tax rate from account head + frappe.db.get_value("Account", child.account_head, "tax_rate").then((r) => { + if(r.message) { + frappe.model.set_value(cdt, cdn, 'rate', r.message.tax_rate); + } + }); + refresh_field("taxes"); + } + }, + + calculate_total: function(frm, cdt, cdn) { + var child = locals[cdt][cdn]; + child.total = flt(frm.doc.total_sanctioned_amount) + flt(child.tax_amount); + + refresh_field("taxes"); + }, + + rate: function(frm, cdt, cdn) { + var child = locals[cdt][cdn]; + if(!child.amount) { + child.tax_amount = flt(frm.doc.total_sanctioned_amount) * (flt(child.rate)/100); + refresh_field("taxes"); + } + frm.trigger("calculate_total", cdt, cdn) + }, + + tax_amount: function(frm, cdt, cdn) { + var child = locals[cdt][cdn]; + child.rate = flt(child.tax_amount/frm.doc.total_sanctioned_amount) * 100; + frm.trigger("calculate_total", cdt, cdn) + refresh_field("taxes"); + } +}); + cur_frm.fields_dict['task'].get_query = function(doc) { return { filters:{ diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.json b/erpnext/hr/doctype/expense_claim/expense_claim.json index 6e04644036..007e646815 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.json +++ b/erpnext/hr/doctype/expense_claim/expense_claim.json @@ -4,6 +4,7 @@ "creation": "2013-01-10 16:34:14", "doctype": "DocType", "document_type": "Setup", + "engine": "InnoDB", "field_order": [ "naming_series", "employee", @@ -18,6 +19,9 @@ "expense_details", "expenses", "sb1", + "taxes", + "net_total", + "section_break_16", "posting_date", "vehicle_log", "task", @@ -315,12 +319,28 @@ { "fieldname": "dimension_col_break", "fieldtype": "Column Break" + }, + { + "fieldname": "taxes", + "fieldtype": "Table", + "label": "Expense Taxes and Charges", + "options": "Expense Taxes and Charges" + }, + { + "fieldname": "section_break_16", + "fieldtype": "Section Break" + }, + { + "fieldname": "net_total", + "fieldtype": "Currency", + "label": "Net Total", + "read_only": 1 } ], "icon": "fa fa-money", "idx": 1, "is_submittable": 1, - "modified": "2019-05-25 22:53:31.682151", + "modified": "2019-06-11 13:21:42.386420", "modified_by": "Administrator", "module": "HR", "name": "Expense Claim", diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py index d6b0eca70e..c5b6ebe56b 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.py +++ b/erpnext/hr/doctype/expense_claim/expense_claim.py @@ -12,6 +12,7 @@ from erpnext.accounts.general_ledger import make_gl_entries from erpnext.accounts.doctype.sales_invoice.sales_invoice import get_bank_cash_account from erpnext.controllers.accounts_controller import AccountsController from frappe.utils.csvutils import getlink +from erpnext.accounts.utils import get_account_currency class InvalidExpenseApproverError(frappe.ValidationError): pass class ExpenseApproverIdentityError(frappe.ValidationError): pass @@ -29,6 +30,7 @@ class ExpenseClaim(AccountsController): self.set_expense_account(validate=True) self.set_payable_account() self.set_cost_center() + self.calculate_taxes() self.set_status() if self.task and not self.project: self.project = frappe.db.get_value("Task", self.task, "project") @@ -93,7 +95,7 @@ class ExpenseClaim(AccountsController): elif self.project: frappe.get_doc("Project", self.project).update_project() - def make_gl_entries(self, cancel = False): + def make_gl_entries(self, cancel=False): if flt(self.total_sanctioned_amount) > 0: gl_entries = self.get_gl_entries() make_gl_entries(gl_entries, cancel) @@ -102,7 +104,7 @@ class ExpenseClaim(AccountsController): gl_entry = [] self.validate_account_details() - payable_amount = flt(self.total_sanctioned_amount) - flt(self.total_advance_amount) + payable_amount = flt(self.net_total) - flt(self.total_advance_amount) # payable entry if payable_amount: @@ -170,8 +172,26 @@ class ExpenseClaim(AccountsController): }) ) + gl_entry = self.make_tax_gl_entries(gl_entry) + return gl_entry + def make_tax_gl_entries(self, gl_entries): + # tax table gl entries + for tax in self.get("taxes"): + account_currency = get_account_currency(tax.account_head) + gl_entries.append( + self.get_gl_dict({ + "account": tax.account_head, + "debit": tax.tax_amount, + "against": self.employee, + "cost_center": self.cost_center, + "against_voucher_type": self.doctype, + "against_voucher": self.name + }, account_currency) + ) + return gl_entries + def validate_account_details(self): if not self.cost_center: frappe.throw(_("Cost center is required to book an expense claim")) @@ -193,6 +213,15 @@ class ExpenseClaim(AccountsController): self.total_claimed_amount += flt(d.claim_amount) self.total_sanctioned_amount += flt(d.sanctioned_amount) + def calculate_taxes(self): + for tax in self.taxes: + if tax.rate: + tax.tax_amount = flt(self.total_sanctioned_amount) * flt(tax.rate/100) + if tax.tax_amount: + tax.rate = flt(tax.tax_amount)/flt(self.total_sanctioned_amount) * 100 + tax.total = flt(tax.tax_amount) + flt(self.total_sanctioned_amount) + self.net_total += tax.total + def update_task(self): task = frappe.get_doc("Task", self.task) task.update_total_expense_claim() diff --git a/erpnext/hr/doctype/expense_taxes_and_charges/__init__.py b/erpnext/hr/doctype/expense_taxes_and_charges/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json b/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json new file mode 100644 index 0000000000..8caf0a975a --- /dev/null +++ b/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json @@ -0,0 +1,103 @@ +{ + "autoname": "hash", + "creation": "2019-06-03 11:42:33.123976", + "doctype": "DocType", + "document_type": "Setup", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "account_head", + "cost_center", + "col_break1", + "rate", + "description", + "section_break_6", + "tax_amount", + "column_break_8", + "total" + ], + "fields": [ + { + "fieldname": "col_break1", + "fieldtype": "Column Break" + }, + { + "columns": 2, + "fieldname": "account_head", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Account Head", + "oldfieldname": "account_head", + "oldfieldtype": "Link", + "options": "Account", + "reqd": 1 + }, + { + "default": ":Company", + "fieldname": "cost_center", + "fieldtype": "Link", + "label": "Cost Center", + "oldfieldname": "cost_center", + "oldfieldtype": "Link", + "options": "Cost Center" + }, + { + "fieldname": "description", + "fieldtype": "Small Text", + "label": "Description", + "oldfieldname": "description", + "oldfieldtype": "Small Text", + "print_width": "300px", + "reqd": 1, + "width": "300px" + }, + { + "columns": 2, + "fieldname": "rate", + "fieldtype": "Float", + "in_list_view": 1, + "label": "Rate", + "oldfieldname": "rate", + "oldfieldtype": "Currency" + }, + { + "columns": 2, + "fieldname": "tax_amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Amount", + "oldfieldname": "tax_amount", + "oldfieldtype": "Currency", + "options": "currency" + }, + { + "columns": 2, + "fieldname": "total", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Total", + "oldfieldname": "total", + "oldfieldtype": "Currency", + "options": "currency", + "read_only": 1 + }, + { + "fieldname": "section_break_6", + "fieldtype": "Section Break" + }, + { + "fieldname": "column_break_8", + "fieldtype": "Column Break" + } + ], + "istable": 1, + "modified": "2019-06-11 14:19:34.780611", + "modified_by": "Administrator", + "module": "HR", + "name": "Expense Taxes and Charges", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "ASC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.py b/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.py new file mode 100644 index 0000000000..4103bef1ff --- /dev/null +++ b/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +# import frappe +from frappe.model.document import Document + +class ExpenseTaxesandCharges(Document): + pass From 444313bdfcd2b1b06e2590c8db9d9c5cf827cb0d Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 12 Jun 2019 12:52:02 +0530 Subject: [PATCH 02/30] feat: change the claim amount in expenses to amount --- erpnext/demo/user/hr.py | 4 ++-- .../hr/doctype/expense_claim/expense_claim.js | 6 +++--- .../doctype/expense_claim/expense_claim.json | 21 ++++++++++++------- .../hr/doctype/expense_claim/expense_claim.py | 9 ++++---- .../expense_claim/test_expense_claim.js | 2 +- .../expense_claim/test_expense_claim.py | 6 +++--- .../expense_claim_detail.json | 6 +++--- erpnext/hr/doctype/vehicle_log/vehicle_log.py | 8 +++---- 8 files changed, 34 insertions(+), 28 deletions(-) diff --git a/erpnext/demo/user/hr.py b/erpnext/demo/user/hr.py index 79f3c19287..0211bc8a90 100644 --- a/erpnext/demo/user/hr.py +++ b/erpnext/demo/user/hr.py @@ -97,7 +97,7 @@ def get_expenses(): "expense_date": frappe.flags.current_date, "expense_type": expense_type.name, "default_account": expense_type.default_account or "Miscellaneous Expenses - WPL", - "claim_amount": claim_amount, + "amount": claim_amount, "sanctioned_amount": claim_amount }) @@ -107,7 +107,7 @@ def update_sanctioned_amount(expense_claim): for expense in expense_claim.expenses: sanctioned_amount = random.randint(1,20)*10 - if sanctioned_amount < expense.claim_amount: + if sanctioned_amount < expense.amount: expense.sanctioned_amount = sanctioned_amount def get_timesheet_based_salary_slip_employee(): diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js index 0ff70cb680..6425b95d7e 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.js +++ b/erpnext/hr/doctype/expense_claim/expense_claim.js @@ -109,7 +109,7 @@ cur_frm.cscript.calculate_total = function(doc){ doc.total_claimed_amount = 0; doc.total_sanctioned_amount = 0; $.each((doc.expenses || []), function(i, d) { - doc.total_claimed_amount += d.claim_amount; + doc.total_claimed_amount += d.amount; doc.total_sanctioned_amount += d.sanctioned_amount; }); @@ -308,10 +308,10 @@ frappe.ui.form.on("Expense Claim", { }); frappe.ui.form.on("Expense Claim Detail", { - claim_amount: function(frm, cdt, cdn) { + amount: function(frm, cdt, cdn) { var child = locals[cdt][cdn]; var doc = frm.doc; - frappe.model.set_value(cdt, cdn, 'sanctioned_amount', child.claim_amount); + frappe.model.set_value(cdt, cdn, 'sanctioned_amount', child.amount); cur_frm.cscript.calculate_total(doc,cdt,cdn); }, diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.json b/erpnext/hr/doctype/expense_claim/expense_claim.json index 007e646815..409bdc8615 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.json +++ b/erpnext/hr/doctype/expense_claim/expense_claim.json @@ -13,20 +13,21 @@ "column_break_5", "expense_approver", "approval_status", - "total_claimed_amount", - "total_sanctioned_amount", "is_paid", "expense_details", "expenses", "sb1", "taxes", - "net_total", + "transactions_section", + "total_tax_amount", + "total_amount_reimbursed", + "total_sanctioned_amount", + "total_claimed_amount", "section_break_16", "posting_date", "vehicle_log", "task", "cb1", - "total_amount_reimbursed", "remark", "title", "email_id", @@ -331,16 +332,22 @@ "fieldtype": "Section Break" }, { - "fieldname": "net_total", + "fieldname": "transactions_section", + "fieldtype": "Section Break", + "label": "Transactions" + }, + { + "fieldname": "total_tax_amount", "fieldtype": "Currency", - "label": "Net Total", + "label": "Total Tax Amount", + "options": "Company:company:default_currency", "read_only": 1 } ], "icon": "fa fa-money", "idx": 1, "is_submittable": 1, - "modified": "2019-06-11 13:21:42.386420", + "modified": "2019-06-12 12:32:13.775009", "modified_by": "Administrator", "module": "HR", "name": "Expense Claim", diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py index c5b6ebe56b..07e711939c 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.py +++ b/erpnext/hr/doctype/expense_claim/expense_claim.py @@ -172,11 +172,11 @@ class ExpenseClaim(AccountsController): }) ) - gl_entry = self.make_tax_gl_entries(gl_entry) + self.add_tax_gl_entries(gl_entry) return gl_entry - def make_tax_gl_entries(self, gl_entries): + def add_tax_gl_entries(self, gl_entries): # tax table gl entries for tax in self.get("taxes"): account_currency = get_account_currency(tax.account_head) @@ -190,7 +190,6 @@ class ExpenseClaim(AccountsController): "against_voucher": self.name }, account_currency) ) - return gl_entries def validate_account_details(self): if not self.cost_center: @@ -210,7 +209,7 @@ class ExpenseClaim(AccountsController): if self.approval_status == 'Rejected': d.sanctioned_amount = 0.0 - self.total_claimed_amount += flt(d.claim_amount) + self.total_claimed_amount += flt(d.amount) self.total_sanctioned_amount += flt(d.sanctioned_amount) def calculate_taxes(self): @@ -253,7 +252,7 @@ class ExpenseClaim(AccountsController): def validate_sanctioned_amount(self): for d in self.get('expenses'): - if flt(d.sanctioned_amount) > flt(d.claim_amount): + if flt(d.sanctioned_amount) > flt(d.amount): frappe.throw(_("Sanctioned Amount cannot be greater than Claim Amount in Row {0}.").format(d.idx)) def set_expense_account(self, validate=False): diff --git a/erpnext/hr/doctype/expense_claim/test_expense_claim.js b/erpnext/hr/doctype/expense_claim/test_expense_claim.js index 070474e10f..d0c43d3be4 100644 --- a/erpnext/hr/doctype/expense_claim/test_expense_claim.js +++ b/erpnext/hr/doctype/expense_claim/test_expense_claim.js @@ -17,7 +17,7 @@ QUnit.test("Test: Expense Claim [HR]", function (assert) { d.expense_date = '2017-08-01', d.expense_type = 'Test Expense Type 1', d.description = 'This is just to test Expense Claim', - d.claim_amount = 2000, + d.amount = 2000, d.sanctioned_amount=2000, refresh_field('expenses'); }, diff --git a/erpnext/hr/doctype/expense_claim/test_expense_claim.py b/erpnext/hr/doctype/expense_claim/test_expense_claim.py index 075bc63345..6fc2a83ebd 100644 --- a/erpnext/hr/doctype/expense_claim/test_expense_claim.py +++ b/erpnext/hr/doctype/expense_claim/test_expense_claim.py @@ -89,7 +89,7 @@ class TestExpenseClaim(unittest.TestCase): "payable_account": payable_account, "approval_status": "Rejected", "expenses": - [{ "expense_type": "Travel", "default_account": "Travel Expenses - WP", "claim_amount": 300, "sanctioned_amount": 200 }] + [{ "expense_type": "Travel", "default_account": "Travel Expenses - WP", "amount": 300, "sanctioned_amount": 200 }] }) expense_claim.submit() @@ -102,7 +102,7 @@ class TestExpenseClaim(unittest.TestCase): def get_payable_account(company): return frappe.get_cached_value('Company', company, 'default_payable_account') -def make_expense_claim(payable_account,claim_amount, sanctioned_amount, company, account, project=None, task_name=None): +def make_expense_claim(payable_account,amount, sanctioned_amount, company, account, project=None, task_name=None): expense_claim = frappe.get_doc({ "doctype": "Expense Claim", "employee": "_T-Employee-00001", @@ -110,7 +110,7 @@ def make_expense_claim(payable_account,claim_amount, sanctioned_amount, company, "approval_status": "Approved", "company": company, "expenses": - [{ "expense_type": "Travel", "default_account": account, "claim_amount": claim_amount, "sanctioned_amount": sanctioned_amount }] + [{ "expense_type": "Travel", "default_account": account, "amount": amount, "sanctioned_amount": sanctioned_amount }] }) if project: expense_claim.project = project diff --git a/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.json b/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.json index d4e70575e9..b23fb6af0f 100644 --- a/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.json +++ b/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.json @@ -253,7 +253,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "claim_amount", + "fieldname": "amount", "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, @@ -262,7 +262,7 @@ "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 0, - "label": "Claim Amount", + "label": "Amount", "length": 0, "no_copy": 0, "oldfieldname": "claim_amount", @@ -360,7 +360,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2019-02-24 08:41:36.122565", + "modified": "2019-06-10 08:41:36.122565", "modified_by": "Administrator", "module": "HR", "name": "Expense Claim Detail", diff --git a/erpnext/hr/doctype/vehicle_log/vehicle_log.py b/erpnext/hr/doctype/vehicle_log/vehicle_log.py index ceea4933f3..df633611be 100644 --- a/erpnext/hr/doctype/vehicle_log/vehicle_log.py +++ b/erpnext/hr/doctype/vehicle_log/vehicle_log.py @@ -18,11 +18,11 @@ class VehicleLog(Document): if (service_detail.service_item or service_detail.type or service_detail.frequency or service_detail.expense_amount): if not (service_detail.service_item and service_detail.type and service_detail.frequency and service_detail.expense_amount): frappe.throw(_("Service Item,Type,frequency and expense amount are required")) - + def on_submit(self): frappe.db.sql("update `tabVehicle` set last_odometer=%s where license_plate=%s", (self.odometer, self.license_plate)) - + @frappe.whitelist() def get_make_model(license_plate): vehicle=frappe.get_doc("Vehicle",license_plate) @@ -41,7 +41,7 @@ def make_expense_claim(docname): for serdetail in vehicle_log.service_detail: total_exp_amt = total_exp_amt + serdetail.expense_amount return total_exp_amt - + vehicle_log = frappe.get_doc("Vehicle Log", docname) exp_claim = frappe.new_doc("Expense Claim") exp_claim.employee=vehicle_log.employee @@ -52,6 +52,6 @@ def make_expense_claim(docname): exp_claim.append("expenses",{ "expense_date":vehicle_log.date, "description":_("Vehicle Expenses"), - "claim_amount":total_claim_amt + "amount":total_claim_amt }) return exp_claim.as_dict() From ddea50fa223ce8caf9407ee280251bd87f914012 Mon Sep 17 00:00:00 2001 From: Rohan Bansal Date: Tue, 11 Jun 2019 14:44:45 +0530 Subject: [PATCH 03/30] fix(stock): Remove hardcoded validation for Item --- erpnext/stock/doctype/item/item.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 48693359fe..1a88473b1b 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -67,8 +67,6 @@ class Item(WebsiteGenerator): from frappe.model.naming import set_name_by_naming_series set_name_by_naming_series(self) self.item_code = self.name - elif not self.item_code: - msgprint(_("Item Code is mandatory because Item is not automatically numbered"), raise_exception=1) self.item_code = strip(self.item_code) self.name = self.item_code From a1d354e14752ef1ee2faee52f9239fd7b9b3ef81 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 12 Jun 2019 18:18:38 +0530 Subject: [PATCH 04/30] feat: add grand total field --- .../hr/doctype/expense_claim/expense_claim.js | 46 +++++++++++-------- .../doctype/expense_claim/expense_claim.json | 29 ++++++++---- .../hr/doctype/expense_claim/expense_claim.py | 32 ++++++------- 3 files changed, 64 insertions(+), 43 deletions(-) diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js index 6425b95d7e..4a61963d49 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.js +++ b/erpnext/hr/doctype/expense_claim/expense_claim.js @@ -112,9 +112,6 @@ cur_frm.cscript.calculate_total = function(doc){ doc.total_claimed_amount += d.amount; doc.total_sanctioned_amount += d.sanctioned_amount; }); - - refresh_field("total_claimed_amount"); - refresh_field('total_sanctioned_amount'); }; cur_frm.cscript.calculate_total_amount = function(doc,cdt,cdn){ @@ -157,14 +154,14 @@ frappe.ui.form.on("Expense Claim", { } }; }); - // frm.set_query("taxes", "account_head", function(doc) { - // return { - // filters: [ - // ['docstatus', '=', 1], - // ['company', '=', doc.company] - // ] - // }; - // }); + frm.set_query("account_head", "taxes", function(doc) { + return { + filters: [ + ['company', '=', doc.company], + ['account_type', 'in', ["Tax", "Chargeable", "Income Account", "Expenses Included In Valuation"]] + ] + }; + }); }, onload: function(frm) { @@ -205,6 +202,12 @@ frappe.ui.form.on("Expense Claim", { } }, + calculate_grand_total: function(frm) { + var grand_total = flt(frm.doc.total_sanctioned_amount) + flt(frm.doc.total_taxes_and_charges) - flt(frm.doc.total_advance_amount); + frm.set_value("grand_total", grand_total); + frm.refresh_fields(); + }, + make_payment_entry: function(frm) { var method = "erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry"; if(frm.doc.__onload && frm.doc.__onload.make_payment_via_journal_entry) { @@ -319,6 +322,7 @@ frappe.ui.form.on("Expense Claim Detail", { var doc = frm.doc; cur_frm.cscript.calculate_total(doc,cdt,cdn); frm.trigger("get_taxes"); + frm.trigger("calculate_grand_total"); } }); @@ -345,6 +349,7 @@ frappe.ui.form.on("Expense Claim Advance", { child.advance_paid = r.message[0].paid_amount; child.unclaimed_amount = flt(r.message[0].paid_amount) - flt(r.message[0].claimed_amount); child.allocated_amount = flt(r.message[0].paid_amount) - flt(r.message[0].claimed_amount); + frm.trigger('calculate_grand_total'); refresh_field("advances"); } } @@ -370,27 +375,30 @@ frappe.ui.form.on("Expense Taxes and Charges", { } }, - calculate_total: function(frm, cdt, cdn) { + calculate_total_tax: function(frm, cdt, cdn) { var child = locals[cdt][cdn]; child.total = flt(frm.doc.total_sanctioned_amount) + flt(child.tax_amount); + frm.trigger("calculate_tax_amount", cdt, cdn); + }, - refresh_field("taxes"); + calculate_tax_amount: function(frm) { + frm.doc.total_taxes_and_charges = 0; + (frm.doc.taxes || []).forEach(function(d) { + frm.doc.total_taxes_and_charges += d.tax_amount; + }); + frm.trigger("calculate_grand_total") }, rate: function(frm, cdt, cdn) { var child = locals[cdt][cdn]; if(!child.amount) { child.tax_amount = flt(frm.doc.total_sanctioned_amount) * (flt(child.rate)/100); - refresh_field("taxes"); } - frm.trigger("calculate_total", cdt, cdn) + frm.trigger("calculate_total_tax", cdt, cdn) }, tax_amount: function(frm, cdt, cdn) { - var child = locals[cdt][cdn]; - child.rate = flt(child.tax_amount/frm.doc.total_sanctioned_amount) * 100; - frm.trigger("calculate_total", cdt, cdn) - refresh_field("taxes"); + frm.trigger("calculate_total_tax", cdt, cdn) } }); diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.json b/erpnext/hr/doctype/expense_claim/expense_claim.json index 409bdc8615..7b0d4943fc 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.json +++ b/erpnext/hr/doctype/expense_claim/expense_claim.json @@ -19,10 +19,13 @@ "sb1", "taxes", "transactions_section", - "total_tax_amount", - "total_amount_reimbursed", "total_sanctioned_amount", "total_claimed_amount", + "total_advance_amount", + "column_break_17", + "total_amount_reimbursed", + "total_taxes_and_charges", + "grand_total", "section_break_16", "posting_date", "vehicle_log", @@ -44,8 +47,7 @@ "status", "amended_from", "advance_payments", - "advances", - "total_advance_amount" + "advances" ], "fields": [ { @@ -122,7 +124,6 @@ { "fieldname": "total_sanctioned_amount", "fieldtype": "Currency", - "in_list_view": 1, "label": "Total Sanctioned Amount", "no_copy": 1, "oldfieldname": "total_sanctioned_amount", @@ -337,9 +338,21 @@ "label": "Transactions" }, { - "fieldname": "total_tax_amount", + "fieldname": "grand_total", "fieldtype": "Currency", - "label": "Total Tax Amount", + "in_list_view": 1, + "label": "Grand Total", + "options": "Company:company:default_currency", + "read_only": 1 + }, + { + "fieldname": "column_break_17", + "fieldtype": "Column Break" + }, + { + "fieldname": "total_taxes_and_charges", + "fieldtype": "Currency", + "label": "Total Taxes and Charges", "options": "Company:company:default_currency", "read_only": 1 } @@ -347,7 +360,7 @@ "icon": "fa fa-money", "idx": 1, "is_submittable": 1, - "modified": "2019-06-12 12:32:13.775009", + "modified": "2019-06-12 15:35:09.092603", "modified_by": "Administrator", "module": "HR", "name": "Expense Claim", diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py index 07e711939c..7f660a45b5 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.py +++ b/erpnext/hr/doctype/expense_claim/expense_claim.py @@ -104,15 +104,13 @@ class ExpenseClaim(AccountsController): gl_entry = [] self.validate_account_details() - payable_amount = flt(self.net_total) - flt(self.total_advance_amount) - # payable entry - if payable_amount: + if self.grand_total: gl_entry.append( self.get_gl_dict({ "account": self.payable_account, - "credit": payable_amount, - "credit_in_account_currency": payable_amount, + "credit": self.grand_total, + "credit_in_account_currency": self.grand_total, "against": ",".join([d.default_account for d in self.expenses]), "party_type": "Employee", "party": self.employee, @@ -146,15 +144,16 @@ class ExpenseClaim(AccountsController): "against_voucher": self.name }) ) + self.add_tax_gl_entries(gl_entry) - if self.is_paid and payable_amount: + if self.is_paid and self.grand_total: # payment entry payment_account = get_bank_cash_account(self.mode_of_payment, self.company).get("account") gl_entry.append( self.get_gl_dict({ "account": payment_account, - "credit": payable_amount, - "credit_in_account_currency": payable_amount, + "credit": self.grand_total, + "credit_in_account_currency": self.grand_total, "against": self.employee }) ) @@ -165,15 +164,13 @@ class ExpenseClaim(AccountsController): "party_type": "Employee", "party": self.employee, "against": payment_account, - "debit": payable_amount, - "debit_in_account_currency": payable_amount, + "debit": self.grand_total, + "debit_in_account_currency": self.grand_total, "against_voucher": self.name, "against_voucher_type": self.doctype, }) ) - self.add_tax_gl_entries(gl_entry) - return gl_entry def add_tax_gl_entries(self, gl_entries): @@ -184,11 +181,12 @@ class ExpenseClaim(AccountsController): self.get_gl_dict({ "account": tax.account_head, "debit": tax.tax_amount, + "debit_in_account_currency": tax.tax_amount, "against": self.employee, "cost_center": self.cost_center, "against_voucher_type": self.doctype, "against_voucher": self.name - }, account_currency) + }) ) def validate_account_details(self): @@ -213,13 +211,15 @@ class ExpenseClaim(AccountsController): self.total_sanctioned_amount += flt(d.sanctioned_amount) def calculate_taxes(self): + self.total_taxes_and_charges = 0 for tax in self.taxes: if tax.rate: tax.tax_amount = flt(self.total_sanctioned_amount) * flt(tax.rate/100) - if tax.tax_amount: - tax.rate = flt(tax.tax_amount)/flt(self.total_sanctioned_amount) * 100 + tax.total = flt(tax.tax_amount) + flt(self.total_sanctioned_amount) - self.net_total += tax.total + self.total_taxes_and_charges += flt(tax.tax_amount) + + self.grand_total = flt(self.total_sanctioned_amount) + flt(self.total_taxes_and_charges) - flt(self.total_advance_amount) def update_task(self): task = frappe.get_doc("Task", self.task) From 0a3ed374cddf38728ee5d4735d470041d707daaf Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 12 Jun 2019 20:03:22 +0530 Subject: [PATCH 05/30] test: validate tax based expense claim gl entries --- .../doctype/expense_claim/expense_claim.json | 8 ++-- .../hr/doctype/expense_claim/expense_claim.py | 1 - .../expense_claim/test_expense_claim.py | 41 +++++++++++++++---- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.json b/erpnext/hr/doctype/expense_claim/expense_claim.json index 7b0d4943fc..db85037795 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.json +++ b/erpnext/hr/doctype/expense_claim/expense_claim.json @@ -20,12 +20,12 @@ "taxes", "transactions_section", "total_sanctioned_amount", - "total_claimed_amount", + "total_taxes_and_charges", "total_advance_amount", "column_break_17", - "total_amount_reimbursed", - "total_taxes_and_charges", "grand_total", + "total_claimed_amount", + "total_amount_reimbursed", "section_break_16", "posting_date", "vehicle_log", @@ -360,7 +360,7 @@ "icon": "fa fa-money", "idx": 1, "is_submittable": 1, - "modified": "2019-06-12 15:35:09.092603", + "modified": "2019-06-12 20:00:25.734108", "modified_by": "Administrator", "module": "HR", "name": "Expense Claim", diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py index 7f660a45b5..caeb2dd946 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.py +++ b/erpnext/hr/doctype/expense_claim/expense_claim.py @@ -176,7 +176,6 @@ class ExpenseClaim(AccountsController): def add_tax_gl_entries(self, gl_entries): # tax table gl entries for tax in self.get("taxes"): - account_currency = get_account_currency(tax.account_head) gl_entries.append( self.get_gl_dict({ "account": tax.account_head, diff --git a/erpnext/hr/doctype/expense_claim/test_expense_claim.py b/erpnext/hr/doctype/expense_claim/test_expense_claim.py index 6fc2a83ebd..a42209f6ad 100644 --- a/erpnext/hr/doctype/expense_claim/test_expense_claim.py +++ b/erpnext/hr/doctype/expense_claim/test_expense_claim.py @@ -6,6 +6,7 @@ import frappe import unittest from frappe.utils import random_string, nowdate from erpnext.hr.doctype.expense_claim.expense_claim import make_bank_entry +from erpnext.accounts.doctype.account.test_account import create_account test_records = frappe.get_test_records('Expense Claim') test_dependencies = ['Employee'] @@ -26,7 +27,7 @@ class TestExpenseClaim(unittest.TestCase): task_name = frappe.db.get_value("Task", {"project": "_Test Project 1"}) payable_account = get_payable_account("Wind Power LLC") - make_expense_claim(payable_account, 300, 200, "Wind Power LLC","Travel Expenses - WP", "_Test Project 1", task_name) + make_expense_claim(payable_account, 300, 200, "Wind Power LLC", "Travel Expenses - WP", "_Test Project 1", task_name) self.assertEqual(frappe.db.get_value("Task", task_name, "total_expense_claim"), 200) self.assertEqual(frappe.db.get_value("Project", "_Test Project 1", "total_expense_claim"), 200) @@ -62,7 +63,8 @@ class TestExpenseClaim(unittest.TestCase): def test_expense_claim_gl_entry(self): payable_account = get_payable_account("Wind Power LLC") - expense_claim = make_expense_claim(payable_account, 300, 200, "Wind Power LLC", "Travel Expenses - WP") + taxes = generate_taxes() + expense_claim = make_expense_claim(payable_account, 300, 200, "Wind Power LLC", "Travel Expenses - WP", do_not_submit=True, taxes=taxes) expense_claim.submit() gl_entries = frappe.db.sql("""select account, debit, credit @@ -72,7 +74,8 @@ class TestExpenseClaim(unittest.TestCase): self.assertTrue(gl_entries) expected_values = dict((d[0], d) for d in [ - [payable_account, 0.0, 200.0], + ['CGST - WP',10.0, 0.0], + [payable_account, 0.0, 210.0], ["Travel Expenses - WP", 200.0, 0.0] ]) @@ -100,22 +103,44 @@ class TestExpenseClaim(unittest.TestCase): self.assertEquals(len(gl_entry), 0) def get_payable_account(company): - return frappe.get_cached_value('Company', company, 'default_payable_account') + return frappe.get_cached_value('Company', company, 'default_payable_account') -def make_expense_claim(payable_account,amount, sanctioned_amount, company, account, project=None, task_name=None): - expense_claim = frappe.get_doc({ +def generate_taxes(): + parent_account = frappe.db.get_value('Account', + {'company': "Wind Power LLC", 'is_group':1, 'account_type': 'Tax'}, + 'name') + account = create_account(company="Wind Power LLC", account_name="CGST", account_type="Tax", parent_account=parent_account) + return {'taxes':[{ + "account_head": account, + "rate": 0, + "description": "CGST", + "tax_amount": 10, + "total": 210 + }]} + +def make_expense_claim(payable_account, amount, sanctioned_amount, company, account, project=None, task_name=None, do_not_submit=False, taxes=None): + expense_claim = { "doctype": "Expense Claim", "employee": "_T-Employee-00001", "payable_account": payable_account, "approval_status": "Approved", "company": company, "expenses": - [{ "expense_type": "Travel", "default_account": account, "amount": amount, "sanctioned_amount": sanctioned_amount }] - }) + [{"expense_type": "Travel", + "default_account": account, + "amount": amount, + "sanctioned_amount": sanctioned_amount}]} + if taxes: + expense_claim.update(taxes) + + expense_claim = frappe.get_doc(expense_claim) + if project: expense_claim.project = project if task_name: expense_claim.task = task_name + if do_not_submit: + return expense_claim expense_claim.submit() return expense_claim From f8bf57c95641034f6b91c7dff56fede81acb94d0 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Thu, 13 Jun 2019 18:09:23 +0530 Subject: [PATCH 06/30] fix: remove transaction section head --- erpnext/hr/doctype/expense_claim/expense_claim.js | 6 +++--- erpnext/hr/doctype/expense_claim/expense_claim.json | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js index 4a61963d49..9e78ca12c4 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.js +++ b/erpnext/hr/doctype/expense_claim/expense_claim.js @@ -275,7 +275,7 @@ frappe.ui.form.on("Expense Claim", { frappe.call({ method: "calculate_taxes", doc: frm.doc, - callback: (r) => { + callback: () => { refresh_field("taxes"); } }); @@ -386,7 +386,7 @@ frappe.ui.form.on("Expense Taxes and Charges", { (frm.doc.taxes || []).forEach(function(d) { frm.doc.total_taxes_and_charges += d.tax_amount; }); - frm.trigger("calculate_grand_total") + frm.trigger("calculate_grand_total"); }, rate: function(frm, cdt, cdn) { @@ -398,7 +398,7 @@ frappe.ui.form.on("Expense Taxes and Charges", { }, tax_amount: function(frm, cdt, cdn) { - frm.trigger("calculate_total_tax", cdt, cdn) + frm.trigger("calculate_total_tax", cdt, cdn); } }); diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.json b/erpnext/hr/doctype/expense_claim/expense_claim.json index db85037795..f0bc268e5d 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.json +++ b/erpnext/hr/doctype/expense_claim/expense_claim.json @@ -334,8 +334,7 @@ }, { "fieldname": "transactions_section", - "fieldtype": "Section Break", - "label": "Transactions" + "fieldtype": "Section Break" }, { "fieldname": "grand_total", @@ -360,7 +359,7 @@ "icon": "fa fa-money", "idx": 1, "is_submittable": 1, - "modified": "2019-06-12 20:00:25.734108", + "modified": "2019-06-13 18:05:52.530462", "modified_by": "Administrator", "module": "HR", "name": "Expense Claim", From 6726dea88bdd59a17825d9947ec303de0a0a34a4 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Fri, 14 Jun 2019 11:17:17 +0530 Subject: [PATCH 07/30] style: change formatting --- erpnext/hr/doctype/expense_claim/expense_claim.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js index 9e78ca12c4..deb6e1dc08 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.js +++ b/erpnext/hr/doctype/expense_claim/expense_claim.js @@ -394,7 +394,7 @@ frappe.ui.form.on("Expense Taxes and Charges", { if(!child.amount) { child.tax_amount = flt(frm.doc.total_sanctioned_amount) * (flt(child.rate)/100); } - frm.trigger("calculate_total_tax", cdt, cdn) + frm.trigger("calculate_total_tax", cdt, cdn); }, tax_amount: function(frm, cdt, cdn) { From 0ef1df72adb463de7ca40c00612cde6ef938d446 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 19 Jun 2019 17:50:33 +0530 Subject: [PATCH 08/30] refactor: fetch rate directly from the account head --- erpnext/hr/doctype/expense_claim/expense_claim.js | 9 +-------- .../expense_taxes_and_charges.json | 3 ++- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js index deb6e1dc08..40bec6d4d7 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.js +++ b/erpnext/hr/doctype/expense_claim/expense_claim.js @@ -361,16 +361,9 @@ frappe.ui.form.on("Expense Claim Advance", { frappe.ui.form.on("Expense Taxes and Charges", { account_head: function(frm, cdt, cdn) { var child = locals[cdt][cdn]; - if(child.account_head && !child.description && !child.rate) { + if(child.account_head && !child.description) { // set description from account head child.description = child.account_head.split(' - ').slice(0, -1).join(' - '); - - // set the tax rate from account head - frappe.db.get_value("Account", child.account_head, "tax_rate").then((r) => { - if(r.message) { - frappe.model.set_value(cdt, cdn, 'rate', r.message.tax_rate); - } - }); refresh_field("taxes"); } }, diff --git a/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json b/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json index 8caf0a975a..be51c43920 100644 --- a/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json +++ b/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json @@ -53,6 +53,7 @@ }, { "columns": 2, + "fetch_from": "account_head.tax_rate", "fieldname": "rate", "fieldtype": "Float", "in_list_view": 1, @@ -91,7 +92,7 @@ } ], "istable": 1, - "modified": "2019-06-11 14:19:34.780611", + "modified": "2019-06-19 17:47:40.236436", "modified_by": "Administrator", "module": "HR", "name": "Expense Taxes and Charges", From 4a1c7ddb094549517dee41a403072b0a869525fd Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Wed, 19 Jun 2019 19:15:37 +0530 Subject: [PATCH 09/30] fix: App logo URL --- erpnext/hooks.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index da0972bf5c..9502006265 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -10,6 +10,7 @@ app_color = "#e74c3c" app_email = "info@erpnext.com" app_license = "GNU General Public License (v3)" source_link = "https://github.com/frappe/erpnext" +app_logo_url = '/assets/erpnext/images/erp-icon.svg' develop_version = '12.x.x-develop' From 357592f55efb920b7ffbca0b8ea39a3b17e0366b Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Wed, 19 Jun 2019 19:17:50 +0530 Subject: [PATCH 10/30] fix: Remove logo replace logic --- erpnext/public/js/conf.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/erpnext/public/js/conf.js b/erpnext/public/js/conf.js index 477781bc80..047922f366 100644 --- a/erpnext/public/js/conf.js +++ b/erpnext/public/js/conf.js @@ -11,9 +11,6 @@ $(document).bind('toolbar_setup', function() { href="https://discuss.erpnext.com">Feedback

' - $('.navbar-home').html(''); - $('[data-link="docs"]').attr("href", "https://erpnext.com/docs") $('[data-link="issues"]').attr("href", "https://github.com/frappe/erpnext/issues") From 8619fc7413e2cc98d7e9b768f671e54f7fcc9625 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Thu, 20 Jun 2019 12:02:47 +0530 Subject: [PATCH 11/30] fix: fetch rate only if field is empty --- .../expense_taxes_and_charges/expense_taxes_and_charges.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json b/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json index be51c43920..9bf69daf65 100644 --- a/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json +++ b/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json @@ -54,6 +54,7 @@ { "columns": 2, "fetch_from": "account_head.tax_rate", + "fetch_if_empty": 1, "fieldname": "rate", "fieldtype": "Float", "in_list_view": 1, @@ -92,7 +93,7 @@ } ], "istable": 1, - "modified": "2019-06-19 17:47:40.236436", + "modified": "2019-06-20 12:01:33.919555", "modified_by": "Administrator", "module": "HR", "name": "Expense Taxes and Charges", From 7483cb49fe939636882e608ec53db9b2a341ef7b Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Thu, 20 Jun 2019 15:25:06 +0530 Subject: [PATCH 12/30] Revert "fix: GSTR-1 Report fixes" This reverts commit 7592e0b588ad72d3e79cd101e94102ab1c1829f0. --- erpnext/regional/report/gstr_1/gstr_1.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py index 9d8fa2ae53..7f323a2ab0 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.py +++ b/erpnext/regional/report/gstr_1/gstr_1.py @@ -60,11 +60,8 @@ class Gstr1Report(object): else: for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): invoice_details = self.invoices.get(inv) - for key, items in items_based_on_rate.items(): - rate = key[0] - account = key[1] - - row, taxable_value = self.get_row_data_for_invoice(inv, invoice_details, rate, account, items) + for rate, items in items_based_on_rate.items(): + row, taxable_value = self.get_row_data_for_invoice(inv, invoice_details, rate, items) if self.filters.get("type_of_business") == "CDNR": row.append("Y" if invoice_details.posting_date <= date(2017, 7, 1) else "N") @@ -103,7 +100,7 @@ class Gstr1Report(object): for key, value in iteritems(b2cs_output): self.data.append(value) - def get_row_data_for_invoice(self, invoice, invoice_details, tax_rate, account, items): + def get_row_data_for_invoice(self, invoice, invoice_details, tax_rate, items): row = [] for fieldname in self.invoice_fields: if self.filters.get("type_of_business") == "CDNR" and fieldname == "invoice_value": @@ -120,10 +117,8 @@ class Gstr1Report(object): taxable_value = 0 for item_code, net_amount in self.invoice_items.get(invoice).items(): if item_code in items: - if self.item_tax_rate.get(invoice) and self.item_tax_rate.get(invoice, {}).get(item_code): - item_tax_rate = self.item_tax_rate.get(invoice, {}).get(item_code) - if account in item_tax_rate and tax_rate == item_tax_rate.get(account): - taxable_value += abs(net_amount) + if self.item_tax_rate.get(invoice) and tax_rate == self.item_tax_rate.get(invoice, {}).get(item_code): + taxable_value += abs(net_amount) elif not self.item_tax_rate.get(invoice): taxable_value += abs(net_amount) @@ -215,7 +210,8 @@ class Gstr1Report(object): item_tax_rate = json.loads(d.item_tax_rate) if item_tax_rate: - self.item_tax_rate.setdefault(d.parent, {}).setdefault(d.item_code, item_tax_rate) + for account, rate in item_tax_rate.items(): + self.item_tax_rate.setdefault(d.parent, {}).setdefault(d.item_code, rate) def get_items_based_on_tax_rate(self): self.tax_details = frappe.db.sql(""" @@ -255,7 +251,7 @@ class Gstr1Report(object): tax_rate *= 2 rate_based_dict = self.items_based_on_tax_rate\ - .setdefault(parent, {}).setdefault((tax_rate, account), []) + .setdefault(parent, {}).setdefault(tax_rate, []) if item_code not in rate_based_dict: rate_based_dict.append(item_code) except ValueError: From a8e49b8afdb1bce536e926165b4b3dc1ec345ae5 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Thu, 20 Jun 2019 15:26:04 +0530 Subject: [PATCH 13/30] Revert "fix: GSTR-2 Report fixes" This reverts commit a55413cb0d3828c20ad53e54ad7abe3ca2492668. --- erpnext/regional/report/gstr_1/gstr_1.py | 5 +---- erpnext/regional/report/gstr_2/gstr_2.py | 7 ++----- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py index 7f323a2ab0..5aa2441ee6 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.py +++ b/erpnext/regional/report/gstr_1/gstr_1.py @@ -204,10 +204,7 @@ class Gstr1Report(object): sum(i.get('base_net_amount', 0) for i in items if i.item_code == d.item_code and i.parent == d.parent)) - item_tax_rate = {} - - if d.item_tax_rate: - item_tax_rate = json.loads(d.item_tax_rate) + item_tax_rate = json.loads(d.item_tax_rate) if item_tax_rate: for account, rate in item_tax_rate.items(): diff --git a/erpnext/regional/report/gstr_2/gstr_2.py b/erpnext/regional/report/gstr_2/gstr_2.py index d9cab63fef..a362269007 100644 --- a/erpnext/regional/report/gstr_2/gstr_2.py +++ b/erpnext/regional/report/gstr_2/gstr_2.py @@ -43,11 +43,8 @@ class Gstr2Report(Gstr1Report): self.get_igst_invoices() for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): invoice_details = self.invoices.get(inv) - for key, items in items_based_on_rate.items(): - rate = key[0] - account = key[1] - - row, taxable_value = self.get_row_data_for_invoice(inv, invoice_details, rate, account, items) + for rate, items in items_based_on_rate.items(): + row, taxable_value = self.get_row_data_for_invoice(inv, invoice_details, rate, items) tax_amount = taxable_value * rate / 100 if inv in self.igst_invoices: row += [tax_amount, 0, 0] From 5ff830b6f43b238453bc91f5a29216c277fc007e Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Thu, 20 Jun 2019 15:50:02 +0530 Subject: [PATCH 14/30] fix: GSTR report fixes --- erpnext/regional/report/gstr_1/gstr_1.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py index 5aa2441ee6..accbff760a 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.py +++ b/erpnext/regional/report/gstr_1/gstr_1.py @@ -117,7 +117,7 @@ class Gstr1Report(object): taxable_value = 0 for item_code, net_amount in self.invoice_items.get(invoice).items(): if item_code in items: - if self.item_tax_rate.get(invoice) and tax_rate == self.item_tax_rate.get(invoice, {}).get(item_code): + if self.item_tax_rate.get(invoice) and tax_rate in self.item_tax_rate.get(invoice, {}).get(item_code): taxable_value += abs(net_amount) elif not self.item_tax_rate.get(invoice): taxable_value += abs(net_amount) @@ -208,7 +208,8 @@ class Gstr1Report(object): if item_tax_rate: for account, rate in item_tax_rate.items(): - self.item_tax_rate.setdefault(d.parent, {}).setdefault(d.item_code, rate) + tax_rate_dict = self.item_tax_rate.setdefault(d.parent, {}).setdefault(d.item_code, []) + tax_rate_dict.append(rate) def get_items_based_on_tax_rate(self): self.tax_details = frappe.db.sql(""" From 50f4fc48a583851bd1e8314246258f8ba5173098 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Thu, 20 Jun 2019 15:53:14 +0530 Subject: [PATCH 15/30] fix: GSTR report fixes --- erpnext/regional/report/gstr_1/gstr_1.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py index accbff760a..815a4e4b82 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.py +++ b/erpnext/regional/report/gstr_1/gstr_1.py @@ -204,7 +204,10 @@ class Gstr1Report(object): sum(i.get('base_net_amount', 0) for i in items if i.item_code == d.item_code and i.parent == d.parent)) - item_tax_rate = json.loads(d.item_tax_rate) + item_tax_rate = {} + + if d.item_tax_rate: + item_tax_rate = json.loads(d.item_tax_rate) if item_tax_rate: for account, rate in item_tax_rate.items(): From 6ef38ebf34434c1748b0d6182ed9fe88f8b436bb Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Thu, 20 Jun 2019 15:55:09 +0530 Subject: [PATCH 16/30] fix: GSTR report fixes --- erpnext/regional/report/gstr_1/gstr_1.py | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py index 815a4e4b82..3a8149d1cf 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.py +++ b/erpnext/regional/report/gstr_1/gstr_1.py @@ -209,7 +209,6 @@ class Gstr1Report(object): if d.item_tax_rate: item_tax_rate = json.loads(d.item_tax_rate) - if item_tax_rate: for account, rate in item_tax_rate.items(): tax_rate_dict = self.item_tax_rate.setdefault(d.parent, {}).setdefault(d.item_code, []) tax_rate_dict.append(rate) From da629810ad129fbde879de8190b6bdb3511ec20e Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 20 Jun 2019 17:20:19 +0530 Subject: [PATCH 17/30] fix: Get accounting dimensions only if user has access --- erpnext/public/js/utils.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index f44fb0c1a6..86fa70d8ad 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -65,6 +65,9 @@ $.extend(erpnext, { }, get_dimension_filters: async function() { + if (!frappe.boot.user.can_read.includes('Accounting Dimension')) { + return + } let dimensions = await frappe.db.get_list('Accounting Dimension', { fields: ['label', 'fieldname', 'document_type'], filters: { From b663966c6821beafa2c77db24c245538f814aed7 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 20 Jun 2019 18:00:19 +0530 Subject: [PATCH 18/30] fix: Use can_read API --- erpnext/public/js/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 86fa70d8ad..dcc15fb5b3 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -65,7 +65,7 @@ $.extend(erpnext, { }, get_dimension_filters: async function() { - if (!frappe.boot.user.can_read.includes('Accounting Dimension')) { + if (!frappe.model.can_read('Accounting Dimension')) { return } let dimensions = await frappe.db.get_list('Accounting Dimension', { From 01f56b867e13c837347fe26b3d2056a235e34d23 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 20 Jun 2019 18:07:58 +0530 Subject: [PATCH 19/30] fix: Return empty array to avoid failure --- erpnext/public/js/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index dcc15fb5b3..f4bb64a64d 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -66,7 +66,7 @@ $.extend(erpnext, { get_dimension_filters: async function() { if (!frappe.model.can_read('Accounting Dimension')) { - return + return []; } let dimensions = await frappe.db.get_list('Accounting Dimension', { fields: ['label', 'fieldname', 'document_type'], From 23deb6f79be27430a964a52eb203bb8892129225 Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Thu, 20 Jun 2019 19:11:58 +0530 Subject: [PATCH 20/30] fix: Default cost center fix for delivery note item (#17990) --- erpnext/selling/doctype/sales_order/sales_order.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index fb7a335302..b87ad031f5 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -581,8 +581,8 @@ def make_delivery_note(source_name, target_doc=None): if item: target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center") \ - or item.get("selling_cost_center") \ - or item_group.get("selling_cost_center") + or item.get("buying_cost_center") \ + or item_group.get("buying_cost_center") target_doc = get_mapped_doc("Sales Order", source_name, { "Sales Order": { From d2061b44dde0b451700892cf3b9efa89537bcfc5 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 20 Jun 2019 19:13:54 +0530 Subject: [PATCH 21/30] fix: could not find company all (#17978) --- .../employee_attendance_tool.js | 5 ++--- .../employee_attendance_tool.py | 11 +++++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.js b/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.js index 376d0c0a5a..22ba5ad473 100644 --- a/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.js +++ b/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.js @@ -2,9 +2,8 @@ frappe.ui.form.on("Employee Attendance Tool", { refresh: function(frm) { frm.disable_save(); }, - + onload: function(frm) { - frm.doc.department = frm.doc.branch = frm.doc.company = "All"; frm.set_value("date", frappe.datetime.get_today()); erpnext.employee_attendance_tool.load_employees(frm); }, @@ -24,7 +23,7 @@ frappe.ui.form.on("Employee Attendance Tool", { company: function(frm) { erpnext.employee_attendance_tool.load_employees(frm); } - + }); diff --git a/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.py b/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.py index ea5f4bdeca..32fcee1abe 100644 --- a/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.py +++ b/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.py @@ -17,12 +17,11 @@ def get_employees(date, department = None, branch = None, company = None): attendance_not_marked = [] attendance_marked = [] filters = {"status": "Active", "date_of_joining": ["<=", date]} - if department != "All": - filters["department"] = department - if branch != "All": - filters["branch"] = branch - if company != "All": - filters["company"] = company + + for field, value in {'department': department, + 'branch': branch, 'company': company}.items(): + if value: + filters[field] = value employee_list = frappe.get_list("Employee", fields=["employee", "employee_name"], filters=filters, order_by="employee_name") marked_employee = {} From 3fa112d8a7338d30112be476ea18b6734bc4c0eb Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Wed, 1 May 2019 11:16:25 +0530 Subject: [PATCH 22/30] feat(travis): Python 3.6 tests --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 869fe959c0..f2ba2c4326 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ dist: trusty python: - "2.7" + - "3.6" services: - mysql From f397acc9362d7820798dae4286c8e839fa16f0f8 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Wed, 1 May 2019 11:31:08 +0530 Subject: [PATCH 23/30] fix(travis): Refactor .travis.yml --- .travis.yml | 24 +++++++++--------------- travis/run-tests.sh | 12 ++++++++++++ 2 files changed, 21 insertions(+), 15 deletions(-) create mode 100644 travis/run-tests.sh diff --git a/.travis.yml b/.travis.yml index f2ba2c4326..26a4caa0fb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,10 @@ python: - "2.7" - "3.6" +env: + - TEST_TYPE=Server Side Test + - TEST_TYPE=Patch Test + services: - mysql @@ -40,18 +44,8 @@ before_script: - bench start & - sleep 10 -jobs: - include: - - stage: test - script: - - set -e - - bench run-tests --app erpnext --coverage - after_script: - - coveralls -b apps/erpnext -d ../../sites/.coverage - env: Server Side Test - - # stage - script: - - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz - - bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis - - bench migrate - env: Patch Testing +script: + - $TRAVIS_BUILD_DIR/travis/run-tests.sh + +after_script: + - coveralls -b apps/erpnext -d ../../sites/.coverage diff --git a/travis/run-tests.sh b/travis/run-tests.sh new file mode 100644 index 0000000000..7cfd64833b --- /dev/null +++ b/travis/run-tests.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e + +if [[ $TEST_TYPE == 'Server Side Test' ]]; then + bench run-tests --app erpnext --coverage + +elif [[ $TEST_TYPE == 'Patch Test' ]]; then + wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz + bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis + bench migrate +fi From 63ddff867a0ad62648488ea99f7f1027abb965ec Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Wed, 1 May 2019 12:06:24 +0530 Subject: [PATCH 24/30] chore: Temporarily disable flake rule F821 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 26a4caa0fb..2e3a1e7782 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ install: # fix mongodb travis error - sudo rm /etc/apt/sources.list.d/mongodb*.list - pip install flake8==3.3.0 - - flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics + - flake8 . --count --select=E901,E999,F822,F823 --show-source --statistics - sudo rm /etc/apt/sources.list.d/docker.list - sudo apt-get install hhvm && rm -rf /home/travis/.kiex/ - sudo apt-get purge -y mysql-common mysql-server mysql-client From bb5ca5a01fe89fcb36a73306c2dedabcee2bf334 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Wed, 1 May 2019 17:35:37 +0530 Subject: [PATCH 25/30] fix(py3): Convert filter to list --- erpnext/accounts/doctype/pricing_rule/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py index 8a8e3291aa..5795b8f808 100644 --- a/erpnext/accounts/doctype/pricing_rule/utils.py +++ b/erpnext/accounts/doctype/pricing_rule/utils.py @@ -232,7 +232,7 @@ def filter_pricing_rules(args, pricing_rules, doc=None): if len(pricing_rules) > 1: rate_or_discount = list(set([d.rate_or_discount for d in pricing_rules])) if len(rate_or_discount) == 1 and rate_or_discount[0] == "Discount Percentage": - pricing_rules = filter(lambda x: x.for_price_list==args.price_list, pricing_rules) \ + pricing_rules = list(filter(lambda x: x.for_price_list==args.price_list, pricing_rules)) \ or pricing_rules if len(pricing_rules) > 1 and not args.for_shopping_cart: From c052ce61f77a1660bc9322877f05ecdfd3632841 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Wed, 1 May 2019 17:41:36 +0530 Subject: [PATCH 26/30] fix: Set file permissions 755 on travis/run-tests.sh --- travis/run-tests.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 travis/run-tests.sh diff --git a/travis/run-tests.sh b/travis/run-tests.sh old mode 100644 new mode 100755 From 44da737c1bdc50ecf623957bae2c2dda7185052a Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Wed, 1 May 2019 18:08:44 +0530 Subject: [PATCH 27/30] fix: Minor --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2e3a1e7782..612a9e416c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,8 @@ python: - "3.6" env: - - TEST_TYPE=Server Side Test - - TEST_TYPE=Patch Test + - TEST_TYPE="Server Side Test" + - TEST_TYPE="Patch Test" services: - mysql From 700711c28d2206efc939d6172c939b864cd81841 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Wed, 1 May 2019 18:25:53 +0530 Subject: [PATCH 28/30] fix: Run script with bash --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 612a9e416c..3ce1439d95 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,7 +45,7 @@ before_script: - sleep 10 script: - - $TRAVIS_BUILD_DIR/travis/run-tests.sh + - bash $TRAVIS_BUILD_DIR/travis/run-tests.sh after_script: - coveralls -b apps/erpnext -d ../../sites/.coverage From 51eecd0c4276631ca267223c3fb84ef4b5a253b1 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 20 Jun 2019 14:07:32 +0530 Subject: [PATCH 29/30] chore: Enable Flake 821 rule --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3ce1439d95..a8a0d82614 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ install: # fix mongodb travis error - sudo rm /etc/apt/sources.list.d/mongodb*.list - pip install flake8==3.3.0 - - flake8 . --count --select=E901,E999,F822,F823 --show-source --statistics + - flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics - sudo rm /etc/apt/sources.list.d/docker.list - sudo apt-get install hhvm && rm -rf /home/travis/.kiex/ - sudo apt-get purge -y mysql-common mysql-server mysql-client From c980143764cac7bf1ffb809c6491a396d1e91615 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 2 May 2019 21:10:13 +0530 Subject: [PATCH 30/30] fix(test): Explicitly search for Material Request Item with Item Code --- .../doctype/production_plan/test_production_plan.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py index 42fce5ad49..e9ef70c49b 100644 --- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py @@ -152,7 +152,7 @@ class TestProductionPlan(unittest.TestCase): make_bom(item = item, raw_materials = raw_materials) production_plan = create_production_plan(item_code = 'Production Item CUST') production_plan.make_material_request() - material_request = frappe.get_value('Material Request Item', {'production_plan': production_plan.name}, 'parent') + material_request = frappe.db.get_value('Material Request Item', {'production_plan': production_plan.name, 'item_code': 'CUST-0987'}, 'parent') mr = frappe.get_doc('Material Request', material_request) self.assertTrue(mr.material_request_type, 'Customer Provided') self.assertTrue(mr.customer, '_Test Customer')