Added Make Receipt (Update Stock) and IsCash option on Purchase Invoice
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 32ad6d2..7ac5400 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 @@
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 @@
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 @@
}, __("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 @@
}
},
+ 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 @@
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 bba4a4a..df47ba7 100755
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -807,6 +807,31 @@
"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,
+ "collapsible": 0,
"fieldname": "items",
"fieldtype": "Table",
"hidden": 0,
@@ -1667,6 +1692,156 @@
"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,
+ "collapsible": 1,
"collapsible_depends_on": "write_off_amount",
"depends_on": "grand_total",
"fieldname": "write_off",
@@ -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 427e040..ba80bcf 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.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 @@
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 @@
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 @@
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 @@
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 @@
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 784c747..cc9e1d3 100755
--- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
+++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
@@ -215,6 +215,30 @@
},
{
"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,
"collapsible": 0,
"fieldname": "qty",
@@ -243,6 +267,30 @@
"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,
+ "collapsible": 0,
"fieldname": "col_break2",
"fieldtype": "Column Break",
"hidden": 0,
@@ -767,6 +815,178 @@
"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,
+ "collapsible": 0,
"fieldname": "accounting",
"fieldtype": "Section Break",
"hidden": 0,
diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py
index ac8a5df..9187706 100644
--- a/erpnext/controllers/sales_and_purchase_return.py
+++ b/erpnext/controllers/sales_and_purchase_return.py
@@ -152,6 +152,7 @@
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 a832ab7..bd1f258 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -169,7 +169,7 @@
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 a2ee1b7..b93857d 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -516,10 +516,10 @@
);
}
- 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);
}