From b44ef0b249b3d4181cda9034ad0d40a90966d629 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 16 Jan 2018 19:21:02 +0530 Subject: [PATCH 1/9] Delete employee records on deletion of company --- erpnext/setup/doctype/company/company.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index 81b94bd91f..cbb747e509 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -287,7 +287,9 @@ class Company(Document): frappe.db.sql("delete from tabBOM where company=%s", self.name) for dt in ("BOM Operation", "BOM Item", "BOM Scrap Item", "BOM Explosion Item"): frappe.db.sql("delete from `tab%s` where parent in (%s)""" - % (dt, ', '.join(['%s']*len(boms))), tuple(boms), debug=1) + % (dt, ', '.join(['%s']*len(boms))), tuple(boms)) + + frappe.db.sql("delete from tabEmployee where company=%s", self.name) @frappe.whitelist() def enqueue_replace_abbr(company, old, new): From 2bfa1803e9877abe54fd99e944e0613ad75143d6 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 17 Jan 2018 14:39:05 +0530 Subject: [PATCH 2/9] GL Entry on asset sale (#12514) * GL Entry on asset sale * Asset sale test case fixed --- .../doctype/sales_invoice/sales_invoice.py | 26 +++++++++---------- erpnext/assets/doctype/asset/asset.py | 22 +++++++++------- erpnext/assets/doctype/asset/depreciation.py | 20 +++++++------- erpnext/assets/doctype/asset/test_asset.py | 3 +-- erpnext/public/js/controllers/transaction.js | 2 +- erpnext/selling/doctype/customer/customer.py | 3 ++- 6 files changed, 40 insertions(+), 36 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index c457f9ad51..477e37d45e 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -675,28 +675,28 @@ class SalesInvoice(SellingController): # income account gl entries for item in self.get("items"): if flt(item.base_net_amount): - account_currency = get_account_currency(item.income_account) - gl_entries.append( - self.get_gl_dict({ - "account": item.income_account, - "against": self.customer, - "credit": item.base_net_amount, - "credit_in_account_currency": item.base_net_amount \ - if account_currency==self.company_currency else item.net_amount, - "cost_center": item.cost_center - }, account_currency) - ) - if item.is_fixed_asset: asset = frappe.get_doc("Asset", item.asset) - fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(asset, is_sale=True) + fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(asset, item.base_net_amount) for gle in fixed_asset_gl_entries: gle["against"] = self.customer gl_entries.append(self.get_gl_dict(gle)) asset.db_set("disposal_date", self.posting_date) asset.set_status("Sold" if self.docstatus==1 else None) + else: + account_currency = get_account_currency(item.income_account) + gl_entries.append( + self.get_gl_dict({ + "account": item.income_account, + "against": self.customer, + "credit": item.base_net_amount, + "credit_in_account_currency": item.base_net_amount \ + if account_currency==self.company_currency else item.net_amount, + "cost_center": item.cost_center + }, account_currency) + ) # expense account gl entries if cint(self.update_stock) and \ diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 857aadef61..8bba0b6936 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -51,9 +51,6 @@ class Asset(Document): if not self.get(field): self.set(field, value) - self.value_after_depreciation = (flt(self.gross_purchase_amount) - - flt(self.opening_accumulated_depreciation)) - def validate_asset_values(self): if flt(self.expected_value_after_useful_life) >= flt(self.gross_purchase_amount): frappe.throw(_("Expected Value After Useful Life must be less than Gross Purchase Amount")) @@ -61,7 +58,10 @@ class Asset(Document): if not flt(self.gross_purchase_amount): frappe.throw(_("Gross Purchase Amount is mandatory"), frappe.MandatoryError) - if not self.is_existing_asset and self.calculate_depreciation: + if not self.calculate_depreciation: + return + + if not self.is_existing_asset: self.opening_accumulated_depreciation = 0 self.number_of_depreciations_booked = 0 if not self.next_depreciation_date: @@ -81,6 +81,9 @@ class Asset(Document): if cint(self.number_of_depreciations_booked) > cint(self.total_number_of_depreciations): frappe.throw(_("Number of Depreciations Booked cannot be greater than Total Number of Depreciations")) + self.value_after_depreciation = (flt(self.gross_purchase_amount) - + flt(self.opening_accumulated_depreciation)) + if self.next_depreciation_date and getdate(self.next_depreciation_date) < getdate(nowdate()): frappe.msgprint(_("Next Depreciation Date is entered as past date"), title=_('Warning'), indicator='red') @@ -106,12 +109,13 @@ class Asset(Document): n * cint(self.frequency_of_depreciation)) depreciation_amount = self.get_depreciation_amount(value_after_depreciation) - value_after_depreciation -= flt(depreciation_amount) + if depreciation_amount: + value_after_depreciation -= flt(depreciation_amount) - self.append("schedules", { - "schedule_date": schedule_date, - "depreciation_amount": depreciation_amount - }) + self.append("schedules", { + "schedule_date": schedule_date, + "depreciation_amount": depreciation_amount + }) def set_accumulated_depreciation(self): accumulated_depreciation = flt(self.opening_accumulated_depreciation) diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index c72cb968da..92a251e4fa 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -151,13 +151,11 @@ def restore_asset(asset_name): asset.set_status() @frappe.whitelist() -def get_gl_entries_on_asset_disposal(asset, is_sale=False): +def get_gl_entries_on_asset_disposal(asset, selling_amount=0): fixed_asset_account, accumulated_depr_account, depr_expense_account = get_depreciation_accounts(asset) - accumulated_depr_amount = flt(asset.gross_purchase_amount) - flt(asset.value_after_depreciation) + disposal_account, depreciation_cost_center = get_disposal_account_and_cost_center(asset.company) - expense_account, cost_center = get_disposal_account_and_cost_center(asset.company) - if is_sale: - expense_account = depr_expense_account + accumulated_depr_amount = flt(asset.gross_purchase_amount) - flt(asset.value_after_depreciation) gl_entries = [ { @@ -172,12 +170,14 @@ def get_gl_entries_on_asset_disposal(asset, is_sale=False): } ] - if flt(asset.value_after_depreciation): + profit_amount = flt(selling_amount) - flt(asset.value_after_depreciation) + if profit_amount: + debit_or_credit = "debit" if profit_amount < 0 else "credit" gl_entries.append({ - "account": expense_account, - "cost_center": cost_center, - "debit": flt(asset.value_after_depreciation), - "debit_in_account_currency": flt(asset.value_after_depreciation) + "account": disposal_account, + "cost_center": depreciation_cost_center, + debit_or_credit: abs(profit_amount), + debit_or_credit + "_in_account_currency": abs(profit_amount) }) return gl_entries diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 107ffec038..76c46cff7a 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -234,9 +234,8 @@ class TestAsset(unittest.TestCase): expected_gle = ( ("_Test Accumulated Depreciations - _TC", 30000.0, 0.0), - ("_Test Depreciations - _TC", 70000.0, 0.0), ("_Test Fixed Asset - _TC", 0.0, 100000.0), - ("_Test Gain/Loss on Asset Disposal - _TC", 0.0, 25000.0), + ("_Test Gain/Loss on Asset Disposal - _TC", 45000.0, 0.0), ("Debtors - _TC", 25000.0, 0.0) ) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index e198c7eecf..c37a61739e 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -549,7 +549,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ final_message = final_message + message1; } - if (this.frm.doc.payment_schedule.length) { + if ((this.frm.doc.payment_schedule || []).length) { message2 = "Payment Schedule Table"; if (message1.length !== 0) message2 = " and " + message2; final_message = final_message + message2; diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 6c9e4501f8..eaa82b3713 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -146,7 +146,8 @@ class Customer(TransactionBase): frappe.throw(_("A Customer Group exists with same name please change the Customer name or rename the Customer Group"), frappe.NameError) def validate_credit_limit_on_change(self): - if self.get("__islocal") or self.credit_limit == frappe.db.get_value("Customer", self.name, "credit_limit"): + if self.get("__islocal") or not self.credit_limit \ + or self.credit_limit == frappe.db.get_value("Customer", self.name, "credit_limit"): return for company in frappe.get_all("Company"): From 052b51ab20c4d3303f556aab34718c40d14a4758 Mon Sep 17 00:00:00 2001 From: Vishal Dhayagude Date: Wed, 17 Jan 2018 14:39:54 +0530 Subject: [PATCH 3/9] [fix] Fetch UOM conversion and stock_uom from BOM into material request (#12513) * [fix]Fetch UOM conversion and stock_uom from BOM into material Request * Update material_request.js --- erpnext/stock/doctype/material_request/material_request.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js index 9eb2313bb2..ed0597cd98 100644 --- a/erpnext/stock/doctype/material_request/material_request.js +++ b/erpnext/stock/doctype/material_request/material_request.js @@ -170,6 +170,8 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten d.description = item.description; d.warehouse = values.warehouse; d.uom = item.stock_uom; + d.stock_uom = item.stock_uom; + d.conversion_factor = 1; d.qty = item.qty; }); } @@ -282,4 +284,4 @@ function set_schedule_date(frm) { if(frm.doc.schedule_date){ erpnext.utils.copy_value_in_all_row(frm.doc, frm.doc.doctype, frm.doc.name, "items", "schedule_date"); } -} \ No newline at end of file +} From 4d4ce3e5cf3a50e0448f0492879c5dd207d1e242 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Wed, 17 Jan 2018 14:40:27 +0530 Subject: [PATCH 4/9] Rename enquiry_type to opportunity_type in MultiSelect dialog (#12517) --- erpnext/selling/doctype/quotation/quotation.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js index 1863fb2a5e..84176426be 100644 --- a/erpnext/selling/doctype/quotation/quotation.js +++ b/erpnext/selling/doctype/quotation/quotation.js @@ -82,8 +82,8 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({ get_query_filters: { status: ["not in", ["Lost", "Closed"]], company: me.frm.doc.company, - // cannot set enquiry_type as setter, as the fieldname is order_type - enquiry_type: me.frm.doc.order_type, + // cannot set opportunity_type as setter, as the fieldname is order_type + opportunity_type: me.frm.doc.order_type, } }) }, __("Get items from"), "btn-default"); From 60febc5465d5170c05cb32b5d045e0e59e604027 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Wed, 17 Jan 2018 14:40:59 +0530 Subject: [PATCH 5/9] [Fix] Gross profit validation issue (#12516) --- .../report/gross_profit/gross_profit.py | 19 +++++++++---------- erpnext/stock/utils.py | 3 +-- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 2bd5cc5577..fe3bb8cd4c 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -6,7 +6,6 @@ import frappe from frappe import _, scrub from erpnext.stock.utils import get_incoming_rate from erpnext.controllers.queries import get_match_cond -from erpnext.stock.stock_ledger import get_valuation_rate from frappe.utils import flt @@ -248,6 +247,7 @@ class GrossProfitGenerator(object): return 0.0 def get_average_buying_rate(self, row, item_code): + args = row if not item_code in self.average_buying_rate: if item_code in self.non_stock_items: self.average_buying_rate[item_code] = flt(frappe.db.sql(""" @@ -255,14 +255,14 @@ class GrossProfitGenerator(object): from `tabPurchase Invoice Item` where item_code = %s and docstatus=1""", item_code)[0][0]) else: - row.voucher_type = row.parenttype - row.voucher_no = row.parent - average_buying_rate = get_incoming_rate(row) - if not average_buying_rate: - average_buying_rate = get_valuation_rate(item_code, row.warehouse, - row.parenttype, row.parent, allow_zero_rate=row.allow_zero_valuation, - currency=self.filters.currency, company=self.filters.company) + args.update({ + 'voucher_type': row.parenttype, + 'voucher_no': row.parent, + 'allow_zero_valuation': True, + 'company': self.filters.company + }) + average_buying_rate = get_incoming_rate(args) self.average_buying_rate[item_code] = flt(average_buying_rate) return self.average_buying_rate[item_code] @@ -311,8 +311,7 @@ class GrossProfitGenerator(object): `tabSales Invoice Item`.brand, `tabSales Invoice Item`.dn_detail, `tabSales Invoice Item`.delivery_note, `tabSales Invoice Item`.stock_qty as qty, `tabSales Invoice Item`.base_net_rate, `tabSales Invoice Item`.base_net_amount, - `tabSales Invoice Item`.name as "item_row", `tabSales Invoice`.is_return, - `tabSales Invoice Item`.allow_zero_valuation_rate as "allow_zero_valuation" + `tabSales Invoice Item`.name as "item_row", `tabSales Invoice`.is_return {sales_person_cols} from `tabSales Invoice` inner join `tabSales Invoice Item` diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py index ae71f355b6..9b2fcb7088 100644 --- a/erpnext/stock/utils.py +++ b/erpnext/stock/utils.py @@ -144,10 +144,9 @@ def get_incoming_rate(args): if not in_rate: voucher_no = args.get('voucher_no') or args.get('name') - in_rate = get_valuation_rate(args.get('item_code'), args.get('warehouse'), args.get('voucher_type'), voucher_no, args.get('allow_zero_valuation'), - currency=erpnext.get_company_currency(args.get('company'))) + currency=erpnext.get_company_currency(args.get('company')), company=args.get('company')) return in_rate From 230805b016a90a8dde618d8e84a096b09f18cb04 Mon Sep 17 00:00:00 2001 From: Umair Sayed Date: Wed, 17 Jan 2018 14:41:38 +0530 Subject: [PATCH 6/9] Update total.html (#12511) --- erpnext/templates/print_formats/includes/total.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/templates/print_formats/includes/total.html b/erpnext/templates/print_formats/includes/total.html index df3f49e024..c13bf92760 100644 --- a/erpnext/templates/print_formats/includes/total.html +++ b/erpnext/templates/print_formats/includes/total.html @@ -1,7 +1,7 @@
{% if doc.flags.show_inclusive_tax_in_print %}
-
+
{{ doc.get_formatted("net_total", doc) }}
@@ -12,4 +12,4 @@ {{ doc.get_formatted("total", doc) }} {% endif %} - \ No newline at end of file + From 91fd29a9636c46d0a069be2e8d6665dd632c5b45 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 17 Jan 2018 16:14:31 +0530 Subject: [PATCH 7/9] Remove enqueuing update_total_sales method, sometimes it does not include current invoice (#12522) --- .../accounts/doctype/sales_invoice/sales_invoice.py | 11 ++--------- erpnext/setup/doctype/company/company.py | 2 -- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 477e37d45e..f6d43c7f70 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -142,7 +142,7 @@ class SalesInvoice(SellingController): self.update_time_sheet(self.name) - self.update_current_month_sales() + update_company_current_month_sales(self.company) self.update_project() def validate_pos_paid_amount(self): @@ -181,16 +181,9 @@ class SalesInvoice(SellingController): self.make_gl_entries_on_cancel() frappe.db.set(self, 'status', 'Cancelled') - self.update_current_month_sales() + update_company_current_month_sales(self.company) self.update_project() - def update_current_month_sales(self): - if frappe.flags.in_test: - update_company_current_month_sales(self.company) - else: - frappe.enqueue('erpnext.setup.doctype.company.company.update_company_current_month_sales', - company=self.company) - def update_status_updater_args(self): if cint(self.update_stock): self.status_updater.extend([{ diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index cbb747e509..ac7c830675 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -358,7 +358,6 @@ def update_company_current_month_sales(company): monthly_total = results[0]['total'] if len(results) > 0 else 0 frappe.db.set_value("Company", company, "total_monthly_sales", monthly_total) - frappe.db.commit() def update_company_monthly_sales(company): '''Cache past year monthly sales of every company based on sales invoices''' @@ -369,7 +368,6 @@ def update_company_monthly_sales(company): "posting_date", filter_str, "sum") frappe.db.set_value("Company", company, "sales_monthly_history", json.dumps(month_to_value_dict)) - frappe.db.commit() def cache_companies_monthly_sales_history(): companies = [d['name'] for d in frappe.get_list("Company")] From da941af6873da165f50a59fcaaae377fbe3bb6df Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Wed, 17 Jan 2018 16:23:04 +0530 Subject: [PATCH 8/9] Set due date in purchase invoice based on suppler invoice date (#12395) --- erpnext/controllers/accounts_controller.py | 2 +- erpnext/public/js/controllers/transaction.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 81d2786c10..8de1a1219c 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -666,7 +666,7 @@ class AccountsController(TransactionBase): self.remove(item) def set_payment_schedule(self): - posting_date = self.get("posting_date") or self.get("transaction_date") + posting_date = self.get("bill_date") or self.get("posting_date") or self.get("transaction_date") date = self.get("due_date") due_date = date or posting_date grand_total = self.get("rounded_total") or self.grand_total diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index c37a61739e..9ee82d2118 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1261,11 +1261,14 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ payment_terms_template: function() { var me = this; if(this.frm.doc.payment_terms_template) { + var posting_date = this.frm.doc.bill_date || + this.frm.doc.posting_date || this.frm.doc.transaction_date; + frappe.call({ method: "erpnext.controllers.accounts_controller.get_payment_terms", args: { terms_template: this.frm.doc.payment_terms_template, - posting_date: this.frm.doc.posting_date || this.frm.doc.transaction_date, + posting_date: posting_date, grand_total: this.frm.doc.rounded_total || this.frm.doc.grand_total }, callback: function(r) { From f76fb5068529d09ec8a02adb16ba72ca146b8933 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 17 Jan 2018 19:21:20 +0600 Subject: [PATCH 9/9] bumped to version 10.0.10 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index d8122088b6..bd400c0870 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '10.0.9' +__version__ = '10.0.10' def get_default_company(user=None): '''Get default company for user'''