From 524ebbcbb9071c2b41b5ae072ee3102af2850cc3 Mon Sep 17 00:00:00 2001 From: jof2jc Date: Mon, 8 Feb 2016 23:44:55 +0700 Subject: [PATCH] Added Make Receipt (Update Stock) and IsCash option on Purchase Invoice --- .../purchase_invoice/purchase_invoice.js | 135 ++++++++++- .../purchase_invoice/purchase_invoice.json | 207 ++++++++++++++-- .../purchase_invoice/purchase_invoice.py | 167 ++++++++++++- .../purchase_invoice_item.json | 220 ++++++++++++++++++ .../controllers/sales_and_purchase_return.py | 1 + erpnext/controllers/stock_controller.py | 2 +- .../public/js/controllers/taxes_and_totals.js | 4 +- 7 files changed, 715 insertions(+), 21 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index 32ad6d2820..7ac5400a64 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -4,6 +4,7 @@ frappe.provide("erpnext.accounts"); {% include 'buying/doctype/purchase_common/purchase_common.js' %}; + erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ onload: function() { this._super(); @@ -14,6 +15,8 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ this.frm.set_df_property("credit_to", "print_hide", 0); } } + + cur_frm.cscript.hide_fields(this.frm.doc); }, refresh: function(doc) { @@ -28,9 +31,16 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ this.frm.add_custom_button(__('Payment'), this.make_bank_entry, __("Make")); cur_frm.page.set_inner_btn_group_as_primary(__("Make")); } - if(doc.outstanding_amount >= 0 || Math.abs(flt(doc.outstanding_amount)) < flt(doc.grand_total)) { - cur_frm.add_custom_button(__('Debit Note'), this.make_debit_note, __("Make")); + + if (!doc.make_receipt) { + if(doc.outstanding_amount >= 0 || Math.abs(flt(doc.outstanding_amount)) < flt(doc.grand_total)) { + cur_frm.add_custom_button(__('Debit Note'), this.make_debit_note, __("Make")); + } } + else { + cur_frm.add_custom_button(__('Return'), this.make_debit_note, __("Make")); + } + } if(doc.docstatus===0) { @@ -62,6 +72,52 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ }, __("Get items from")); } } + if(doc.docstatus==1 && doc.make_receipt==1) { + this.show_stock_ledger(); + } + + }, + + received_qty: function(doc, cdt, cdn) { + var item = frappe.get_doc(cdt, cdn); + frappe.model.round_floats_in(item, ["qty", "received_qty"]); + + item.qty = (item.qty < item.received_qty) ? item.qty : item.received_qty; + this.qty(doc, cdt, cdn); + }, + + qty: function(doc, cdt, cdn) { + var item = frappe.get_doc(cdt, cdn); + frappe.model.round_floats_in(item, ["qty", "received_qty"]); + + if(!(item.received_qty || item.rejected_qty) && item.qty) { + item.received_qty = item.qty; + } + + if(item.qty > item.received_qty) { + msgprint(__("Error: {0} > {1}", [__(frappe.meta.get_label(item.doctype, "qty", item.name)), + __(frappe.meta.get_label(item.doctype, "received_qty", item.name))])) + item.qty = item.rejected_qty = 0.0; + } else { + item.rejected_qty = flt(item.received_qty - item.qty, precision("rejected_qty", item)); + } + + this._super(doc, cdt, cdn); + }, + + rejected_qty: function(doc, cdt, cdn) { + var item = frappe.get_doc(cdt, cdn); + frappe.model.round_floats_in(item, ["received_qty", "rejected_qty"]); + + if(item.rejected_qty > item.received_qty) { + msgprint(__("Error: {0} > {1}", [__(frappe.meta.get_label(item.doctype, "rejected_qty", item.name)), + __(frappe.meta.get_label(item.doctype, "received_qty", item.name))])); + item.qty = item.rejected_qty = 0.0; + } else { + item.qty = flt(item.received_qty - item.rejected_qty, precision("qty", item)); + } + + this.qty(doc, cdt, cdn); }, supplier: function() { @@ -100,12 +156,30 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ } }, + is_cash: function() { + cur_frm.cscript.hide_fields(this.frm.doc); + if(cint(this.frm.doc.is_cash)) { + if(!this.frm.doc.company) { + this.frm.set_value("is_cash", 0); + msgprint(__("Please specify Company to proceed")); + } + } + this.calculate_outstanding_amount(); + this.frm.refresh_fields(); + }, + write_off_amount: function() { this.set_in_company_currency(this.frm.doc, ["write_off_amount"]); this.calculate_outstanding_amount(); this.frm.refresh_fields(); }, + paid_amount: function() { + this.set_in_company_currency(this.frm.doc, ["paid_amount"]); + this.write_off_outstanding_amount(); + this.frm.refresh_fields(); + }, + allocated_amount: function() { this.calculate_total_advance(); this.frm.refresh_fields(); @@ -137,6 +211,63 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ cur_frm.script_manager.make(erpnext.accounts.PurchaseInvoice); +// Hide Fields +// ------------ +cur_frm.cscript.hide_fields = function(doc) { + par_flds = ['due_date', 'is_opening', 'advances_section', 'from_date', 'to_date']; + + if(cint(doc.is_cash) == 1) { + hide_field(par_flds); + } else { + for (i in par_flds) { + var docfield = frappe.meta.docfield_map[doc.doctype][par_flds[i]]; + if(!docfield.hidden) unhide_field(par_flds[i]); + } + + } + + item_flds_stock = ['sc_wh', 'received_qty', 'rejected_qty']; + + //item_flds_stock = ['serial_no', 'batch_no', 'actual_qty', 'expense_account', 'warehouse', 'expense_account', 'warehouse'] + cur_frm.fields_dict['items'].grid.set_column_disp(item_flds_stock, + (cint(doc.make_receipt)==1 ? true : false)); + + cur_frm.refresh_fields(); +} + +cur_frm.cscript.make_receipt = function(doc, dt, dn) { + cur_frm.cscript.hide_fields(doc, dt, dn); +} + +cur_frm.cscript.mode_of_payment = function(doc) { + if(doc.is_cash) { + return cur_frm.call({ + method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.get_bank_cash_account", + args: { + "mode_of_payment": doc.mode_of_payment, + "company": doc.company + }, + callback: function(r, rt) { + if(r.message) { + cur_frm.set_value("cash_bank_account", r.message["account"]); + } + + } + }); + } +} + +cur_frm.fields_dict.cash_bank_account.get_query = function(doc) { + return { + filters: [ + ["Account", "account_type", "in", ["Cash", "Bank"]], + ["Account", "root_type", "=", "Asset"], + ["Account", "is_group", "=",0], + ["Account", "company", "=", doc.company] + ] + } +} + cur_frm.cscript.make_bank_entry = function() { return frappe.call({ method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_payment_entry_against_invoice", diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index bba4a4aeb9..df47ba7656 100755 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -803,6 +803,31 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "default": "0", + "fieldname": "make_receipt", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Make Receipt (Update Stock)", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -1663,6 +1688,156 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 1, + "collapsible_depends_on": "paid_amount", + "depends_on": "eval:doc.is_cash===1", + "fieldname": "sc_br_payments", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Payments", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "mode_of_payment", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Mode of Payment", + "length": 0, + "no_copy": 0, + "oldfieldname": "mode_of_payment", + "oldfieldtype": "Select", + "options": "Mode of Payment", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "cash_bank_account", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Cash/Bank Account", + "length": 0, + "no_copy": 0, + "options": "Account", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "col_br_payments", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "paid_amount", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Paid Amount", + "length": 0, + "no_copy": 0, + "options": "currency", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "base_paid_amount", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Paid Amount (Company Currency)", + "length": 0, + "no_copy": 0, + "options": "Company:company:default_currency", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -2700,18 +2875,19 @@ "permissions": [ { "amend": 1, - "apply_user_permissions": 0, + "apply_user_permissions": 1, "cancel": 1, "create": 1, "delete": 0, - "email": 1, - "export": 0, + "email": 0, + "export": 1, "if_owner": 0, "import": 0, "permlevel": 0, "print": 1, "read": 1, - "report": 1, + "report": 0, + "restrict": 0, "role": "Accounts User", "set_user_permissions": 0, "share": 1, @@ -2720,18 +2896,19 @@ }, { "amend": 0, - "apply_user_permissions": 0, + "apply_user_permissions": 1, "cancel": 0, "create": 0, "delete": 0, - "email": 1, + "email": 0, "export": 0, "if_owner": 0, "import": 0, "permlevel": 0, - "print": 1, + "print": 0, "read": 1, - "report": 1, + "report": 0, + "restrict": 0, "role": "Purchase User", "set_user_permissions": 0, "share": 0, @@ -2743,15 +2920,16 @@ "apply_user_permissions": 0, "cancel": 1, "create": 1, - "delete": 1, - "email": 1, - "export": 0, + "delete": 0, + "email": 0, + "export": 1, "if_owner": 0, "import": 0, "permlevel": 0, "print": 1, "read": 1, "report": 1, + "restrict": 0, "role": "Accounts Manager", "set_user_permissions": 0, "share": 1, @@ -2760,7 +2938,7 @@ }, { "amend": 0, - "apply_user_permissions": 0, + "apply_user_permissions": 1, "cancel": 0, "create": 0, "delete": 0, @@ -2772,6 +2950,7 @@ "print": 1, "read": 1, "report": 1, + "restrict": 0, "role": "Auditor", "set_user_permissions": 0, "share": 0, @@ -2792,11 +2971,11 @@ "print": 0, "read": 1, "report": 0, - "role": "Accounts Manager", + "role": "All", "set_user_permissions": 0, "share": 0, "submit": 0, - "write": 1 + "write": 0 } ], "read_only": 0, diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 427e04098d..ba80bcfbb6 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import frappe -from frappe.utils import cint, formatdate, flt, getdate +from frappe.utils import cstr, cint, formatdate, flt, getdate from frappe import msgprint, _, throw from erpnext.setup.utils import get_company_currency import frappe.defaults @@ -13,6 +13,7 @@ from erpnext.accounts.party import get_party_account, get_due_date from erpnext.accounts.utils import get_account_currency, get_fiscal_year from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_billed_amount_based_on_po + form_grid_templates = { "items": "templates/form_grid/item_grid.html" } @@ -45,6 +46,23 @@ class PurchaseInvoice(BuyingController): self.validate_supplier_invoice() self.validate_advance_jv("Purchase Order") + # validate cash purchase + if (self.is_cash == 1): + self.validate_cash() + + # validate stock items + if (self.make_receipt == 1): + self.validate_purchase_return() + self.validate_rejected_warehouse() + self.validate_accepted_rejected_qty() + + # sub-contracting + # self.validate_for_subcontracting() + # self.create_raw_materials_supplied("supplied_items") + # self.set_landed_cost_voucher_amount() + # self.update_valuation_rate("items") + + self.check_active_purchase_items() self.check_conversion_rate() self.validate_credit_to_acc() self.clear_unallocated_advances("Purchase Invoice Advance", "advances") @@ -58,6 +76,45 @@ class PurchaseInvoice(BuyingController): self.validate_fixed_asset_account() self.create_remarks() + def validate_cash(self): + if not self.cash_bank_account and flt(self.paid_amount): + frappe.throw(_("Cash or Bank Account is mandatory for making payment entry")) + + if flt(self.paid_amount) + flt(self.write_off_amount) \ + - flt(self.base_grand_total) > 1/(10**(self.precision("base_grand_total") + 1)): + frappe.throw(_("""Paid amount + Write Off Amount can not be greater than Grand Total""")) + + def validate_purchase_return(self): + for d in self.get("items"): + if self.is_return and flt(d.rejected_qty) != 0: + frappe.throw(_("Row #{0}: Rejected Qty can not be entered in Purchase Return").format(d.idx)) + + # validate rate with ref PR + + def validate_rejected_warehouse(self): + for d in self.get("items"): + if flt(d.rejected_qty) and not d.rejected_warehouse: + d.rejected_warehouse = self.rejected_warehouse + if not d.rejected_warehouse: + frappe.throw(_("Row #{0}: Rejected Warehouse is mandatory against rejected Item {1}").format(d.idx, d.item_code)) + + # validate accepted and rejected qty + def validate_accepted_rejected_qty(self): + for d in self.get("items"): + if not flt(d.received_qty) and flt(d.qty): + d.received_qty = flt(d.qty) - flt(d.rejected_qty) + + elif not flt(d.qty) and flt(d.rejected_qty): + d.qty = flt(d.received_qty) - flt(d.rejected_qty) + + elif not flt(d.rejected_qty): + d.rejected_qty = flt(d.received_qty) - flt(d.qty) + + # Check Received Qty = Accepted Qty + Rejected Qty + if ((flt(d.qty) + flt(d.rejected_qty)) != flt(d.received_qty)): + frappe.throw(_("Accepted + Rejected Qty must be equal to Received quantity for Item {0}").format(d.item_code)) + + def create_remarks(self): if not self.remarks: if self.bill_no and self.bill_date: @@ -228,6 +285,75 @@ class PurchaseInvoice(BuyingController): from erpnext.accounts.utils import reconcile_against_document reconcile_against_document(lst) + def update_status_updater_args(self): + if cint(self.make_receipt): + self.status_updater.extend([{ + 'source_dt': 'Purchase Invoice Item', + 'target_dt': 'Purchase Order Item', + 'join_field': 'po_detail', + 'target_field': 'received_qty', + 'target_parent_dt': 'Purchase Order', + 'target_parent_field': 'per_received', + 'target_ref_field': 'qty', + 'source_field': 'qty', + 'percent_join_field':'purchase_order', + # 'percent_join_field': 'prevdoc_docname', + 'overflow_type': 'receipt', + 'extra_cond': """ and exists(select name from `tabPurchase Invoice` + where name=`tabPurchase Invoice Item`.parent and make_receipt = 1)""" + }, + { + 'source_dt': 'Purchase Invoice Item', + 'target_dt': 'Purchase Order Item', + 'join_field': 'po_detail', + 'target_field': 'returned_qty', + 'target_parent_dt': 'Purchase Order', + # 'target_parent_field': 'per_received', + # 'target_ref_field': 'qty', + 'source_field': '-1 * qty', + # 'percent_join_field': 'prevdoc_docname', + # 'overflow_type': 'receipt', + 'extra_cond': """ and exists (select name from `tabPurchase Invoice` where name=`tabPurchase Invoice Item`.parent and is_return=1)""" + } + ]) + + def update_stock_ledger(self, allow_negative_stock=False, via_landed_cost_voucher=False): + sl_entries = [] + stock_items = self.get_stock_items() + + for d in self.get('items'): + if d.item_code in stock_items and d.warehouse: + pr_qty = flt(d.qty) * flt(d.conversion_factor) + + if pr_qty: + val_rate_db_precision = 6 if cint(self.precision("valuation_rate", d)) <= 6 else 9 + rate = flt(d.valuation_rate, val_rate_db_precision) + sle = self.get_sl_entries(d, { + "actual_qty": flt(pr_qty), + "serial_no": cstr(d.serial_no).strip() + }) + if self.is_return: + sle.update({ + "outgoing_rate": rate + }) + else: + sle.update({ + "incoming_rate": rate + }) + sl_entries.append(sle) + + if flt(d.rejected_qty) > 0: + sl_entries.append(self.get_sl_entries(d, { + "warehouse": d.rejected_warehouse, + "actual_qty": flt(d.rejected_qty) * flt(d.conversion_factor), + "serial_no": cstr(d.rejected_serial_no).strip(), + "incoming_rate": 0.0 + })) + + # self.bk_flush_supp_wh(sl_entries) + self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock, + via_landed_cost_voucher=via_landed_cost_voucher) + def on_submit(self): self.check_prev_docstatus() self.validate_asset() @@ -235,8 +361,18 @@ class PurchaseInvoice(BuyingController): frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype, self.company, self.base_grand_total) + # make purchase receipt + if (self.make_receipt == 1): + # from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_stock_ledger + self.update_stock_ledger() + self.make_gl_entries() + from erpnext.stock.doctype.serial_no.serial_no import update_serial_nos_after_submit + update_serial_nos_after_submit(self, "items") + self.update_status_updater_args() + self.update_prevdoc_status() + # this sequence because outstanding may get -negative - self.make_gl_entries() + self.make_gl_entries1() if not self.is_return: self.update_against_document_in_jv() self.update_prevdoc_status() @@ -281,6 +417,33 @@ class PurchaseInvoice(BuyingController): gl_entries = [] + # Make Cash GL Entries + if cint(self.is_cash) and self.cash_bank_account and self.paid_amount: + bank_account_currency = get_account_currency(self.cash_bank_account) + # CASH, make payment entries + gl_entries.append( + self.get_gl_dict({ + "account": self.credit_to, + "party_type": "Supplier", + "party": self.supplier, + "against": self.cash_bank_account, + "debit": self.base_paid_amount, + "debit_in_account_currency": self.base_paid_amount \ + if self.party_account_currency==self.company_currency else self.paid_amount, + "against_voucher": self.return_against if cint(self.is_return) else self.name, + "against_voucher_type": self.doctype, + }, self.party_account_currency) + ) + gl_entries.append( + self.get_gl_dict({ + "account": self.cash_bank_account, + "against": self.supplier, + "credit": self.base_paid_amount, + "credit_in_account_currency": self.base_paid_amount \ + if bank_account_currency==self.company_currency else self.paid_amount + }, bank_account_currency) + ) + # parent's gl entry if self.grand_total: # Didnot use base_grand_total to book rounding loss gle diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json index 784c7478d8..cc9e1d3f56 100755 --- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json +++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json @@ -213,6 +213,30 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "received_qty", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Received Qty", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "2", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 1, @@ -239,6 +263,30 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "rejected_qty", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Rejected Qty", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "2", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -763,6 +811,178 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "sc_wh", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Warehouse", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "default": "", + "fieldname": "warehouse", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Accepted Warehouse", + "length": 0, + "no_copy": 0, + "options": "Warehouse", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "rejected_warehouse", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Rejected Warehouse", + "length": 0, + "no_copy": 0, + "options": "Warehouse", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "batch_no", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Batch No", + "length": 0, + "no_copy": 0, + "options": "Batch", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "col_br_wh", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "serial_no", + "fieldtype": "Text", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Serial No", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "rejected_serial_no", + "fieldtype": "Text", + "hidden": 1, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Rejected Serial No", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index ac8a5dfd70..91877068e7 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -152,6 +152,7 @@ def make_return_doc(doctype, source_name, target_doc=None): target_doc.prevdoc_docname = source_doc.prevdoc_docname target_doc.prevdoc_detail_docname = source_doc.prevdoc_detail_docname elif doctype == "Purchase Invoice": + target_doc.received_qty = -1* source_doc.qty target_doc.purchase_order = source_doc.purchase_order target_doc.purchase_receipt = source_doc.purchase_receipt target_doc.po_detail = source_doc.po_detail diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index a832ab771f..bd1f258a8d 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -169,7 +169,7 @@ class StockController(AccountsController): else: is_expense_account = frappe.db.get_value("Account", item.get("expense_account"), "report_type")=="Profit and Loss" - if self.doctype not in ("Purchase Receipt", "Stock Reconciliation", "Stock Entry") and not is_expense_account: + if self.doctype not in ("Purchase Receipt", "Purchase Invoice", "Stock Reconciliation", "Stock Entry") and not is_expense_account: frappe.throw(_("Expense / Difference account ({0}) must be a 'Profit or Loss' account") .format(item.get("expense_account"))) if is_expense_account and not item.get("cost_center"): diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index a2ee1b75b9..b93857d3b2 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -516,10 +516,10 @@ erpnext.taxes_and_totals = erpnext.stock.StockController.extend({ ); } - if(this.frm.doc.doctype == "Sales Invoice") { + if(this.frm.doc.doctype == "Sales Invoice" || this.frm.doc.doctype == "Purchase Invoice") { frappe.model.round_floats_in(this.frm.doc, ["paid_amount"]); - if(this.frm.doc.is_pos) { + if(this.frm.doc.is_pos || this.frm.doc.is_cash) { if(!this.frm.doc.paid_amount || update_paid_amount===undefined || update_paid_amount) { this.frm.doc.paid_amount = flt(total_amount_to_pay); }