diff --git a/erpnext/__init__.py b/erpnext/__init__.py index ce16a6e7db..fa3fcc2cce 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -4,7 +4,7 @@ import inspect import frappe from erpnext.hooks import regional_overrides -__version__ = '9.0.3' +__version__ = '9.0.4' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index c7258a4945..6d05a0ba8f 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -520,6 +520,24 @@ frappe.ui.form.on('Sales Invoice', { }; }); }, + //When multiple companies are set up. in case company name is changed set default company address + company:function(frm){ + if (frm.doc.company) + { + frappe.call({ + method:"frappe.contacts.doctype.address.address.get_default_address", + args:{ doctype:'Company',name:frm.doc.company}, + callback: function(r){ + if (r.message){ + frm.set_value("company_address",r.message) + } + else { + frm.set_value("company_address","") + } + } + }) + } + }, project: function(frm){ frm.call({ diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index a1b737dffb..b86561b837 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -324,11 +324,15 @@ def set_taxes(party, party_type, posting_date, company, customer_group=None, sup from erpnext.accounts.doctype.tax_rule.tax_rule import get_tax_template, get_party_details args = { party_type.lower(): party, - "customer_group": customer_group, - "supplier_type": supplier_type, "company": company } + if customer_group: + args['customer_group'] = customer_group + + if supplier_type: + args['supplier_type'] = supplier_type + if billing_address or shipping_address: args.update(get_party_details(party, party_type, {"billing_address": billing_address, \ "shipping_address": shipping_address })) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index a51246bcb8..8134e7e701 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -1,3 +1,4 @@ + // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors // License: GNU General Public License v3. See license.txt @@ -24,6 +25,18 @@ frappe.ui.form.on("Purchase Order", { }, }); +frappe.ui.form.on("Purchase Order Item", { + item_code: function(frm) { + frappe.call({ + method: "get_last_purchase_rate", + doc: frm.doc, + callback: function(r, rt) { + frm.trigger('calculate_taxes_and_totals'); + } + }) + } +}); + erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend({ refresh: function(doc, cdt, cdn) { var me = this; @@ -214,17 +227,6 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend( delivered_by_supplier: function(){ cur_frm.cscript.update_status('Deliver', 'Delivered') - }, - - get_last_purchase_rate: function() { - frappe.call({ - "method": "get_last_purchase_rate", - "doc": cur_frm.doc, - callback: function(r, rt) { - cur_frm.dirty(); - cur_frm.cscript.calculate_taxes_and_totals(); - } - }) } }); diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index 0c19d2b41a..4ed4d7cc1c 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.json +++ b/erpnext/buying/doctype/purchase_order/purchase_order.json @@ -1206,37 +1206,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.docstatus===0 && (doc.items && doc.items.length)", - "fieldname": "get_last_purchase_rate", - "fieldtype": "Button", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Get last purchase rate", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -3550,8 +3519,8 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-09-26 04:41:49.329626", - "modified_by": "Administrator", + "modified": "2017-09-22 16:11:49.856808", + "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order", "owner": "Administrator", diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 56f3059f2e..e2f5a9dca8 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -116,14 +116,13 @@ class PurchaseOrder(BuyingController): d.discount_percentage = last_purchase_details['discount_percentage'] d.base_rate = last_purchase_details['base_rate'] * (flt(d.conversion_factor) or 1.0) d.price_list_rate = d.base_price_list_rate / conversion_rate - d.rate = d.base_rate / conversion_rate + d.last_purchase_rate = d.base_rate / conversion_rate else: - msgprint(_("Last purchase rate not found")) item_last_purchase_rate = frappe.db.get_value("Item", d.item_code, "last_purchase_rate") if item_last_purchase_rate: d.base_price_list_rate = d.base_rate = d.price_list_rate \ - = d.rate = item_last_purchase_rate + = d.last_purchase_rate = item_last_purchase_rate # Check for Closed status def check_for_closed_status(self): diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_last_purchase_rate.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_last_purchase_rate.js new file mode 100644 index 0000000000..d19f017425 --- /dev/null +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_last_purchase_rate.js @@ -0,0 +1,99 @@ +QUnit.module('Buying'); + +QUnit.test("test: purchase order with last purchase rate", function(assert) { + assert.expect(5); + let done = assert.async(); + + frappe.run_serially([ + () => { + return frappe.tests.make('Purchase Order', [ + {supplier: 'Test Supplier'}, + {is_subcontracted: 'No'}, + {currency: 'INR'}, + {items: [ + [ + {"item_code": 'Test Product 4'}, + {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, + {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, + {"qty": 1}, + {"rate": 800}, + {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} + ], + [ + {"item_code": 'Test Product 1'}, + {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, + {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, + {"qty": 1}, + {"rate": 400}, + {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} + ] + ]} + ]); + }, + + () => { + // Get item details + assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 4', "Item 1 name correct"); + assert.ok(cur_frm.doc.items[1].item_name == 'Test Product 1', "Item 2 name correct"); + }, + + () => frappe.timeout(1), + + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(3), + + () => frappe.tests.click_button('Close'), + () => frappe.timeout(1), + + () => { + return frappe.tests.make('Purchase Order', [ + {supplier: 'Test Supplier'}, + {is_subcontracted: 'No'}, + {currency: 'INR'}, + {items: [ + [ + {"item_code": 'Test Product 4'}, + {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, + {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, + {"qty": 1}, + {"rate": 600}, + {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} + ], + [ + {"item_code": 'Test Product 1'}, + {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, + {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, + {"qty": 1}, + {"rate": 200}, + {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} + ] + ]} + ]); + }, + + () => frappe.timeout(2), + + // Get the last purchase rate of items + () => { + assert.ok(cur_frm.doc.items[0].last_purchase_rate == 800, "Last purchase rate of item 1 correct"); + }, + () => { + assert.ok(cur_frm.doc.items[1].last_purchase_rate == 400, "Last purchase rate of item 2 correct"); + }, + + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(3), + + () => frappe.tests.click_button('Close'), + + () => frappe.timeout(1), + + () => { + assert.ok(cur_frm.doc.status == 'To Receive and Bill', "Submitted successfully"); + }, + + () => done() + ]); +}); \ No newline at end of file diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json index 2dd7b6c0ed..1ddce628a2 100755 --- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json +++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json @@ -655,6 +655,37 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "last_purchase_rate", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Last Purchase Rate", + "length": 0, + "no_copy": 0, + "options": "currency", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -1714,7 +1745,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-08-02 22:15:47.411235", + "modified": "2017-09-22 16:47:08.783546", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order Item", diff --git a/erpnext/config/desktop.py b/erpnext/config/desktop.py index ef1ff103fa..8fb66b1b70 100644 --- a/erpnext/config/desktop.py +++ b/erpnext/config/desktop.py @@ -268,5 +268,13 @@ def get_data(): "icon": "octicon octicon-plus", "type": "module", "label": _("Healthcare") - } + }, + { + "module_name": "Data Import Tool", + "color": "#7f8c8d", + "icon": "octicon octicon-circuit-board", + "type": "page", + "link": "data-import-tool", + "label": _("Data Import Tool") + }, ] diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py index e5564404ec..513b97f53a 100644 --- a/erpnext/controllers/item_variant.py +++ b/erpnext/controllers/item_variant.py @@ -207,7 +207,7 @@ def copy_attributes_to_variant(item, variant): if variant.attributes: variant.description += "\n" for d in variant.attributes: - variant.description += "
" + d.attribute + ": " + cstr(d.attribute_value) + "
" + variant.description += "An error occured while creating recurring {{ type }} {{ name }} for {{ party }}.
-This could be because of some invalid Email Addresses in the {{ type }}.
-To stop sending repetitive error notifications from the system, we have checked "Disabled" field in the subscription {{ subscription}} for the {{ type }} {{ name }}.
-Please correct the {{ type }} and unchcked "Disabled" in the {{ subscription }} for making recurring again.
+{{_("An error occured while creating recurring")}} {{ type }} {{ name }} {{_("for")}} {{ party }}.
+{{_("This could be because of some invalid Email Addresses in the")}} {{ type }}.
+{{_("To stop sending repetitive error notifications from the system, we have checked "Disabled" field in the subscription")}} {{ subscription}} {{_("for the")}} {{ type }} {{ name }}.
+{{_("Please correct the")}} {{ type }} {{_('and unchcked "Disabled" in the')}} {{ subscription }} {{_("for making recurring again.")}}
It is necessary to take this action today itself for the above mentioned recurring {{ type }} -to be generated. If delayed, you will have to manually change the "Repeat on Day of Month" field -of this {{ type }} for generating the recurring {{ type }} in the subscription {{ subscription }}.
-[This email is autogenerated]
+{{_("It is necessary to take this action today itself for the above mentioned recurring")}} {{ type }} +{{_('to be generated. If delayed, you will have to manually change the "Repeat on Day of Month" field +of this')}} {{ type }} {{_("for generating the recurring")}} {{ type }} {{_("in the subscription")}} {{ subscription }}.
+[{{_("This email is autogenerated")}}]
diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index 909216b92e..199d886deb 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -128,3 +128,4 @@ erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_issue_with erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_repack.js erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_serialize_item.js erpnext/accounts/doctype/payment_entry/tests/test_payment_against_invoice.js +erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_last_purchase_rate.js \ No newline at end of file