From 3b6dc141c617b44543ea411a64c6b4f51449ba82 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 19 Aug 2016 16:39:33 +0530 Subject: [PATCH 1/7] [fix] Repost only distinct purchase receipts and invoices --- erpnext/controllers/stock_controller.py | 6 +++--- .../doctype/landed_cost_voucher/landed_cost_voucher.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index fcdff21591..3f25e0222f 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -204,10 +204,10 @@ class StockController(AccountsController): from erpnext.stock.stock_ledger import make_sl_entries make_sl_entries(sl_entries, is_amended, allow_negative_stock, via_landed_cost_voucher) - def make_gl_entries_on_cancel(self): + def make_gl_entries_on_cancel(self, repost_future_gle=True): if frappe.db.sql("""select name from `tabGL Entry` where voucher_type=%s and voucher_no=%s""", (self.doctype, self.name)): - self.make_gl_entries() + self.make_gl_entries(repost_future_gle) def get_serialized_items(self): serialized_items = [] @@ -261,7 +261,7 @@ def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for future_stock_vouchers = get_future_stock_vouchers(posting_date, posting_time, for_warehouses, for_items) gle = get_voucherwise_gl_entries(future_stock_vouchers, posting_date) - + for voucher_type, voucher_no in future_stock_vouchers: existing_gle = gle.get((voucher_type, voucher_no), []) voucher_obj = frappe.get_doc(voucher_type, voucher_no) diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py index ac59e06ca8..cdf7263126 100644 --- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py +++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py @@ -84,7 +84,7 @@ class LandedCostVoucher(Document): self.update_landed_cost() def update_landed_cost(self): - for d in self.get("items"): + for d in self.get("purchase_receipts"): doc = frappe.get_doc(d.receipt_document_type, d.receipt_document) # set landed cost voucher amount in pr item @@ -103,7 +103,7 @@ class LandedCostVoucher(Document): # update stock & gl entries for cancelled state of PR doc.docstatus = 2 doc.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True) - doc.make_gl_entries_on_cancel() + doc.make_gl_entries_on_cancel(repost_future_gle=False) # update stock & gl entries for submit state of PR From 713e2b7b629be56f3f55b7beed1004aecc243f58 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Fri, 19 Aug 2016 15:11:36 +0530 Subject: [PATCH 2/7] [POS] Fixed issue of paid amount, write off account --- .../doctype/sales_invoice/sales_invoice.py | 4 +++- erpnext/accounts/page/pos/pos.js | 16 ++++++++++++--- erpnext/public/js/payment/payments.js | 20 +++++++++---------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 871a1512e0..35df29955d 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -381,8 +381,10 @@ class SalesInvoice(SellingController): if d.delivery_note: msgprint(_("Stock cannot be updated against Delivery Note {0}").format(d.delivery_note), raise_exception=1) - def validate_write_off_account(self): + if flt(self.write_off_amount) and not self.write_off_account: + self.write_off_account = frappe.db.get_value('Company', self.company, 'write_off_account') + if flt(self.write_off_amount) and not self.write_off_account: msgprint(_("Please enter Write Off Account"), raise_exception=1) diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js index 06606a97fe..5947bde878 100644 --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -509,7 +509,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ this.remove_zero_qty_item(); } - this.refresh(); + this.update_paid_amount_status(false) }, remove_zero_qty_item: function(){ @@ -591,7 +591,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ if (!caught) this.add_new_item_to_grid(); - this.refresh(); + this.update_paid_amount_status(false) }, add_new_item_to_grid: function() { @@ -616,6 +616,14 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ ? this.item_serial_no[this.child.item_code][0] : ''); }, + update_paid_amount_status: function(update_paid_amount){ + if(this.name){ + update_paid_amount = update_paid_amount ? false : true; + } + + this.refresh(update_paid_amount); + }, + refresh: function(update_paid_amount) { var me = this; this.refresh_fields(update_paid_amount); @@ -623,6 +631,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ this.update_rate(); this.set_primary_action(); }, + refresh_fields: function(update_paid_amount) { this.apply_pricing_rule(); this.discount_amount_applied = false; @@ -698,7 +707,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ if (this.frm.doc.docstatus==0) { this.page.set_primary_action(__("Pay"), function() { - me.validate() + me.validate(); + me.update_paid_amount_status(true); me.create_invoice(); me.make_payment(); }, "octicon octicon-credit-card"); diff --git a/erpnext/public/js/payment/payments.js b/erpnext/public/js/payment/payments.js index 06df425262..6133fcf245 100644 --- a/erpnext/public/js/payment/payments.js +++ b/erpnext/public/js/payment/payments.js @@ -177,19 +177,17 @@ erpnext.payments = erpnext.stock.StockController.extend({ write_off_amount: function(write_off_amount) { var me = this; - if(this.frm.doc.paid_amount > 0){ - this.frm.doc.write_off_amount = write_off_amount; - this.frm.doc.base_write_off_amount = flt(this.frm.doc.write_off_amount * this.frm.doc.conversion_rate, - precision("base_write_off_amount")); - this.calculate_outstanding_amount(false) - this.show_amounts() - } + this.frm.doc.write_off_amount = flt(write_off_amount, precision("write_off_amount")); + this.frm.doc.base_write_off_amount = flt(this.frm.doc.write_off_amount * this.frm.doc.conversion_rate, + precision("base_write_off_amount")); + this.calculate_outstanding_amount(false) + this.show_amounts() }, change_amount: function(change_amount) { var me = this; - this.frm.doc.change_amount = change_amount; + this.frm.doc.change_amount = flt(change_amount, precision("change_amount")); this.calculate_write_off_amount() this.show_amounts() }, @@ -197,7 +195,7 @@ erpnext.payments = erpnext.stock.StockController.extend({ update_paid_amount: function() { var me = this; if(in_list(['change_amount', 'write_off_amount'], this.idx)){ - value = flt(me.selected_mode.val(), 2) + value = me.selected_mode.val(); if(me.idx == 'change_amount'){ me.change_amount(value) } else{ @@ -226,9 +224,9 @@ erpnext.payments = erpnext.stock.StockController.extend({ show_amounts: function(){ var me = this; - $(this.$body).find(".write_off_amount").val(format_number(this.frm.doc.write_off_amount, 2)); + $(this.$body).find(".write_off_amount").val(flt(this.frm.doc.write_off_amount, precision("write_off_amount"))); $(this.$body).find('.paid_amount').text(format_currency(this.frm.doc.paid_amount, this.frm.doc.currency)); - $(this.$body).find('.change_amount').val(format_number(this.frm.doc.change_amount, 2)) + $(this.$body).find('.change_amount').val(flt(this.frm.doc.change_amount, precision("change_amount"))) $(this.$body).find('.outstanding_amount').text(format_currency(this.frm.doc.outstanding_amount, this.frm.doc.currency)) this.update_invoice(); } From 9239ed5c44a7a5d9cff8d8353ae3a5d4547fcc00 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 22 Aug 2016 12:59:28 +0530 Subject: [PATCH 3/7] Ignore validating mandatory fields on converting timelogs to timesheets --- erpnext/patches/v7_0/convert_timelog_to_timesheet.py | 10 +++++++++- erpnext/patches/v7_0/migrate_schools_to_erpnext.py | 5 +++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/erpnext/patches/v7_0/convert_timelog_to_timesheet.py b/erpnext/patches/v7_0/convert_timelog_to_timesheet.py index b802656f7f..d00980f6cf 100644 --- a/erpnext/patches/v7_0/convert_timelog_to_timesheet.py +++ b/erpnext/patches/v7_0/convert_timelog_to_timesheet.py @@ -16,7 +16,6 @@ def execute(): time_sheet = make_timesheet(data.production_order) args = get_timelog_data(data) add_timesheet_detail(time_sheet, args) - time_sheet.docstatus = data.docstatus time_sheet.note = data.note time_sheet.company = company @@ -25,6 +24,15 @@ def execute(): time_sheet.calculate_total_amounts() time_sheet.flags.ignore_validate = True time_sheet.save(ignore_permissions=True) + + # To ignore validate_mandatory_fields function + if data.docstatus == 1: + time_sheet.db_set("docstatus", 1) + for d in time_sheet.get("time_logs"): + d.db_set("docstatus", 1) + time_sheet.update_production_order(time_sheet.name) + time_sheet.update_task_and_project() + def get_timelog_data(data): return { diff --git a/erpnext/patches/v7_0/migrate_schools_to_erpnext.py b/erpnext/patches/v7_0/migrate_schools_to_erpnext.py index f64f400feb..2aa6f04376 100644 --- a/erpnext/patches/v7_0/migrate_schools_to_erpnext.py +++ b/erpnext/patches/v7_0/migrate_schools_to_erpnext.py @@ -9,12 +9,13 @@ def execute(): frappe.reload_doc('website', 'doctype', 'portal_menu_item') frappe.reload_doc('buying', 'doctype', 'request_for_quotation') - if 'schools' in frappe.get_installed_apps(): + if frappe.db.exists("Module Def", "Academics") \ + and frappe.db.get_value("Module Def", "Academics", "app_name") == "schools": frappe.db.sql("""delete from `tabDesktop Icon`""") if not frappe.db.exists('Module Def', 'Schools') and frappe.db.exists('Module Def', 'Academics'): frappe.rename_doc("Module Def", "Academics", "Schools") - + remove_from_installed_apps("schools") def reload_doctypes_for_schools_icons(): From 20b01873ab3a62bd3891d6cba40de55d8957a355 Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Mon, 22 Aug 2016 13:12:44 +0530 Subject: [PATCH 4/7] Made operation mandatory and removed mandatory from operation desc in Production Order Operation, set operation name as desc in operation master if desc is blank --- erpnext/manufacturing/doctype/operation/operation.py | 10 +++------- .../production_order_operation.json | 6 +++--- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/erpnext/manufacturing/doctype/operation/operation.py b/erpnext/manufacturing/doctype/operation/operation.py index 2c75feebd4..69e83292ff 100644 --- a/erpnext/manufacturing/doctype/operation/operation.py +++ b/erpnext/manufacturing/doctype/operation/operation.py @@ -2,13 +2,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document class Operation(Document): - def calculate_op_cost(self): - if self.hour_rate and self.time_in_mins: - self.operating_cost = flt(self.hour_rate) * flt(self.time_in_mins) / 60.0 - else : - self.operating_cost = 0 - + def validate(self): + if not self.description: + self.description = self.name diff --git a/erpnext/manufacturing/doctype/production_order_operation/production_order_operation.json b/erpnext/manufacturing/doctype/production_order_operation/production_order_operation.json index 3493ccf43e..00bf934d83 100644 --- a/erpnext/manufacturing/doctype/production_order_operation/production_order_operation.json +++ b/erpnext/manufacturing/doctype/production_order_operation/production_order_operation.json @@ -58,7 +58,7 @@ "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, - "reqd": 0, + "reqd": 1, "search_index": 0, "set_only_once": 0, "unique": 0 @@ -85,7 +85,7 @@ "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, - "reqd": 1, + "reqd": 0, "search_index": 0, "set_only_once": 0, "unique": 0 @@ -539,7 +539,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-07-11 03:28:04.235889", + "modified": "2016-08-22 03:41:42.356833", "modified_by": "Administrator", "module": "Manufacturing", "name": "Production Order Operation", From 01b555edc73273a08591e027f1fee9db28612839 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 22 Aug 2016 15:50:21 +0530 Subject: [PATCH 5/7] Change logs for v7 --- erpnext/change_log/v7/v7_0_0.md | 58 +++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 erpnext/change_log/v7/v7_0_0.md diff --git a/erpnext/change_log/v7/v7_0_0.md b/erpnext/change_log/v7/v7_0_0.md new file mode 100644 index 0000000000..144d74dd5e --- /dev/null +++ b/erpnext/change_log/v7/v7_0_0.md @@ -0,0 +1,58 @@ +#### New POS +- Offline +- Multiple Payment Modes +- Standard documents cannot be edited in POS view + +#### Payment Entry +- Dedicated form for managing Payments +- Designed for normal users who do not have accounting background + +#### Request for Quotation +- Updated workflow: Material Request -> **Request for Quotation** -> Supplier Quotation -> Purchase Order + +#### Fixed Asset Management +- Manage fixed asset records and their depreciation + +#### Improved Navigation +- Heatmaps +- Centralized navigation from Masters like Item, Customer, Supplier, Employee etc. + +#### Timesheets +- New grid +- Multiple time logs in one timesheets +- Linked to Payroll and Billing + +#### Graphs in Reports +- Added graphs in some important reports like Balance Sheet, Accounts Receivable etc. + +#### Sub-warehouse +- Tree view for Warehouse + +#### New Portal Design +- New Homepage Design +- Sidebar in Portal View +- New Cart View + +#### Collaborative Project Management +- Web View +- Customers/Suppliers can add/edit issues and view timesheets + +#### Budget +- Dedicated budget form +- Budget can be assigned against Cost Center Group + +#### Check Printing Format +- Ability to customize Cheque Printing Format for any bank + +#### Schools application is now part of ERPNext + +#### Minor + +- Selling Price calculation based on Margin defined in the Pricing Rule +- Document flow-chart on Sales / Purchase Transactions +- Domain specific desktop views +- Add opening Stock and Rate while creating a new Item +- Book payments and update stock directly from Purchase Invoice +- List view for Products on Website +- Features Setup is deprecated, settings moved to individual module setup views +- Added Safety Stock to Item Master From ea6d7e9b09bcfb8d3cd5f4b528d8e32b3da3f3a5 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 22 Aug 2016 19:49:17 +0530 Subject: [PATCH 6/7] [Fix] decimal button not working --- erpnext/controllers/taxes_and_totals.py | 3 ++- erpnext/public/js/payment/payments.js | 16 ++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 125f4fedb6..da803cf75e 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -471,7 +471,8 @@ class calculate_taxes_and_totals(object): def calculate_write_off_amount(self): if flt(self.doc.change_amount) > 0: - self.doc.write_off_amount = self.doc.grand_total - self.doc.paid_amount + self.doc.change_amount + self.doc.write_off_amount = flt(self.doc.grand_total - self.doc.paid_amount + self.doc.change_amount, + self.doc.precision("write_off_amount")) self.doc.base_write_off_amount = flt(self.doc.write_off_amount * self.doc.conversion_rate, self.doc.precision("base_write_off_amount")) diff --git a/erpnext/public/js/payment/payments.js b/erpnext/public/js/payment/payments.js index 6133fcf245..23db61fcb4 100644 --- a/erpnext/public/js/payment/payments.js +++ b/erpnext/public/js/payment/payments.js @@ -112,15 +112,15 @@ erpnext.payments = erpnext.stock.StockController.extend({ $(this.$body).find('.form-control').click(function(){ me.idx = $(this).attr("idx"); me.set_outstanding_amount(); - me.update_paid_amount(); + me.update_paid_amount(true); }) $(this.$body).find('.write_off_amount').change(function(){ - me.write_off_amount(flt($(this).val())); + me.write_off_amount(flt($(this).val()), precision("write_off_amount")); }) $(this.$body).find('.change_amount').change(function(){ - me.change_amount(flt($(this).val())); + me.change_amount(flt($(this).val()), precision("change_amount")); }) }, @@ -139,7 +139,7 @@ erpnext.payments = erpnext.stock.StockController.extend({ me.payment_val += $(this).text(); me.selected_mode.val(format_number(me.payment_val, 2)) me.idx = me.selected_mode.attr("idx") - me.selected_mode.change() + me.update_paid_amount() }) $(this.$body).find('.delete-btn').click(function(){ @@ -192,14 +192,14 @@ erpnext.payments = erpnext.stock.StockController.extend({ this.show_amounts() }, - update_paid_amount: function() { + update_paid_amount: function(update_write_off) { var me = this; if(in_list(['change_amount', 'write_off_amount'], this.idx)){ value = me.selected_mode.val(); if(me.idx == 'change_amount'){ me.change_amount(value) } else{ - if(value == 0) { + if(value == 0 && update_write_off) { value = me.frm.doc.outstanding_amount; } me.write_off_amount(value) @@ -224,9 +224,9 @@ erpnext.payments = erpnext.stock.StockController.extend({ show_amounts: function(){ var me = this; - $(this.$body).find(".write_off_amount").val(flt(this.frm.doc.write_off_amount, precision("write_off_amount"))); + $(this.$body).find(".write_off_amount").val(format_number(this.frm.doc.write_off_amount, precision("write_off_amount"))); $(this.$body).find('.paid_amount').text(format_currency(this.frm.doc.paid_amount, this.frm.doc.currency)); - $(this.$body).find('.change_amount').val(flt(this.frm.doc.change_amount, precision("change_amount"))) + $(this.$body).find('.change_amount').val(format_number(this.frm.doc.change_amount, precision("change_amount"))) $(this.$body).find('.outstanding_amount').text(format_currency(this.frm.doc.outstanding_amount, this.frm.doc.currency)) this.update_invoice(); } From db05ac2414d5c03a74b237830b0f0b310fe6eb50 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 23 Aug 2016 12:40:56 +0600 Subject: [PATCH 7/7] bumped to version 7.0.32 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 7c5133aff8..6b59a1891b 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import frappe -__version__ = '7.0.31' +__version__ = '7.0.32' def get_default_company(user=None): '''Get default company for user'''