From 623ed576632bb9f6556ed49061e55475ecdf56af Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 17 Jul 2015 16:28:10 +0530 Subject: [PATCH] Removed Sales/Purchase Return option from Stock Entry --- erpnext/stock/doctype/serial_no/serial_no.py | 9 +- .../stock/doctype/stock_entry/stock_entry.js | 199 +------ .../doctype/stock_entry/stock_entry.json | 8 +- .../stock/doctype/stock_entry/stock_entry.py | 372 +------------ .../doctype/stock_entry/test_stock_entry.py | 512 +++++++++--------- 5 files changed, 286 insertions(+), 814 deletions(-) diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index bac544194a..452182198c 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -81,20 +81,19 @@ class SerialNo(StockController): def set_status(self, last_sle): if last_sle: if last_sle.voucher_type == "Stock Entry": - document_type = frappe.db.get_value("Stock Entry", last_sle.voucher_no, - "purpose") + document_type = frappe.db.get_value("Stock Entry", last_sle.voucher_no, "purpose") else: document_type = last_sle.voucher_type if last_sle.actual_qty > 0: - if document_type == "Sales Return": + if document_type in ("Delivery Note", "Sales Invoice", "Sales Return"): self.status = "Sales Returned" else: self.status = "Available" else: - if document_type == "Purchase Return": + if document_type in ("Purchase Receipt", "Purchase Invoice", "Purchase Return"): self.status = "Purchase Returned" - elif last_sle.voucher_type in ("Delivery Note", "Sales Invoice"): + elif document_type in ("Delivery Note", "Sales Invoice"): self.status = "Delivered" else: self.status = "Not Available" diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index 6958ea03ca..8526117223 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -7,20 +7,7 @@ frappe.provide("erpnext.stock"); erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ setup: function() { var me = this; - - this.frm.fields_dict.delivery_note_no.get_query = function() { - return { query: "erpnext.stock.doctype.stock_entry.stock_entry.query_sales_return_doc" }; - }; - - this.frm.fields_dict.sales_invoice_no.get_query = - this.frm.fields_dict.delivery_note_no.get_query; - - this.frm.fields_dict.purchase_receipt_no.get_query = function() { - return { - filters:{ 'docstatus': 1 } - }; - }; - + this.frm.fields_dict.bom_no.get_query = function() { return { filters:{ 'docstatus': 1 } @@ -28,20 +15,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ }; this.frm.fields_dict.items.grid.get_field('item_code').get_query = function() { - if(in_list(["Sales Return", "Purchase Return"], me.frm.doc.purpose) && - me.get_doctype_docname()) { - return { - query: "erpnext.stock.doctype.stock_entry.stock_entry.query_return_item", - filters: { - purpose: me.frm.doc.purpose, - delivery_note_no: me.frm.doc.delivery_note_no, - sales_invoice_no: me.frm.doc.sales_invoice_no, - purchase_receipt_no: me.frm.doc.purchase_receipt_no - } - }; - } else { - return erpnext.queries.item({is_stock_item: "Yes"}); - } + return erpnext.queries.item({is_stock_item: "Yes"}); }; this.frm.set_query("purchase_order", function() { @@ -84,19 +58,6 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ this.toggle_enable_bom(); this.show_stock_ledger(); this.show_general_ledger(); - - if(this.frm.doc.docstatus === 1 && frappe.boot.user.can_create.indexOf("Journal Entry")!==-1 - && this.frm.doc.__onload.credit_debit_note_exists == 0 ) { - if(this.frm.doc.purpose === "Sales Return") { - this.frm.add_custom_button(__("Make Credit Note"), - function() { me.make_return_jv(); }, frappe.boot.doctype_icons["Journal Entry"]); - this.add_excise_button(); - } else if(this.frm.doc.purpose === "Purchase Return") { - this.frm.add_custom_button(__("Make Debit Note"), - function() { me.make_return_jv(); }, frappe.boot.doctype_icons["Journal Entry"]); - this.add_excise_button(); - } - } }, on_submit: function() { @@ -111,15 +72,10 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ var me = this; if(cint(frappe.defaults.get_default("auto_accounting_for_stock")) && this.frm.doc.company) { - var account_for = "stock_adjustment_account"; - - if (this.frm.doc.purpose == "Purchase Return") - account_for = "stock_received_but_not_billed"; - return this.frm.call({ method: "erpnext.accounts.utils.get_company_default", args: { - "fieldname": account_for, + "fieldname": "stock_adjustment_account", "company": this.frm.doc.company }, callback: function(r) { @@ -192,35 +148,6 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ this.frm.toggle_enable("bom_no", !in_list(["Manufacture", "Material Transfer for Manufacture"], this.frm.doc.purpose)); }, - get_doctype_docname: function() { - if(this.frm.doc.purpose === "Sales Return") { - if(this.frm.doc.delivery_note_no && this.frm.doc.sales_invoice_no) { - // both specified - msgprint(__("You can not enter both Delivery Note No and Sales Invoice No. Please enter any one.")); - - } else if(!(this.frm.doc.delivery_note_no || this.frm.doc.sales_invoice_no)) { - // none specified - msgprint(__("Please enter Delivery Note No or Sales Invoice No to proceed")); - - } else if(this.frm.doc.delivery_note_no) { - return {doctype: "Delivery Note", docname: this.frm.doc.delivery_note_no}; - - } else if(this.frm.doc.sales_invoice_no) { - return {doctype: "Sales Invoice", docname: this.frm.doc.sales_invoice_no}; - - } - } else if(this.frm.doc.purpose === "Purchase Return") { - if(this.frm.doc.purchase_receipt_no) { - return {doctype: "Purchase Receipt", docname: this.frm.doc.purchase_receipt_no}; - - } else { - // not specified - msgprint(__("Please enter Purchase Receipt No to proceed")); - - } - } - }, - add_excise_button: function() { if(frappe.boot.sysdefaults.country === "India") this.frm.add_custom_button(__("Make Excise Invoice"), function() { @@ -231,37 +158,16 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ }, frappe.boot.doctype_icons["Journal Entry"], "btn-default"); }, - make_return_jv: function() { - if(this.get_doctype_docname()) { - return this.frm.call({ - method: "make_return_jv", - args: { - stock_entry: this.frm.doc.name - }, - callback: function(r) { - if(!r.exc) { - var doclist = frappe.model.sync(r.message); - frappe.set_route("Form", doclist[0].doctype, doclist[0].name); - - } - } - }); - } - }, - items_add: function(doc, cdt, cdn) { var row = frappe.get_doc(cdt, cdn); - this.frm.script_manager.copy_from_first_row("items", row, - ["expense_account", "cost_center"]); + this.frm.script_manager.copy_from_first_row("items", row, ["expense_account", "cost_center"]); if(!row.s_warehouse) row.s_warehouse = this.frm.doc.from_warehouse; if(!row.t_warehouse) row.t_warehouse = this.frm.doc.to_warehouse; }, - source_mandatory: ["Material Issue", "Material Transfer", "Purchase Return", "Subcontract", - "Material Transfer for Manufacture"], - target_mandatory: ["Material Receipt", "Material Transfer", "Sales Return", "Subcontract", - "Material Transfer for Manufacture"], + source_mandatory: ["Material Issue", "Material Transfer", "Subcontract", "Material Transfer for Manufacture"], + target_mandatory: ["Material Receipt", "Material Transfer", "Subcontract", "Material Transfer for Manufacture"], from_warehouse: function(doc) { var me = this; @@ -295,92 +201,21 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ items_on_form_rendered: function(doc, grid_row) { erpnext.setup_serial_no(); - }, - - customer: function() { - this.get_party_details({ - party: this.frm.doc.customer, - party_type:"Customer", - doctype: this.frm.doc.doctype - }); - }, - - supplier: function() { - this.get_party_details({ - party: this.frm.doc.supplier, - party_type:"Supplier", - doctype: this.frm.doc.doctype - }); - }, - - get_party_details: function(args) { - var me = this; - frappe.call({ - method: "erpnext.accounts.party.get_party_details", - args: args, - callback: function(r) { - if(r.message) { - me.frm.set_value({ - "customer_name": r.message["customer_name"], - "customer_address": r.message["address_display"] - }); - } - } - }); - }, - - delivery_note_no: function() { - this.get_party_details_from_against_voucher({ - ref_dt: "Delivery Note", - ref_dn: this.frm.doc.delivery_note_no - }) - }, - - sales_invoice_no: function() { - this.get_party_details_from_against_voucher({ - ref_dt: "Sales Invoice", - ref_dn: this.frm.doc.sales_invoice_no - }) - }, - - purchase_receipt_no: function() { - this.get_party_details_from_against_voucher({ - ref_dt: "Purchase Receipt", - ref_dn: this.frm.doc.purchase_receipt_no - }) - }, - - get_party_details_from_against_voucher: function(args) { - return this.frm.call({ - method: "erpnext.stock.doctype.stock_entry.stock_entry.get_party_details", - args: args, - }) } - }); cur_frm.script_manager.make(erpnext.stock.StockEntry); cur_frm.cscript.toggle_related_fields = function(doc) { - disable_from_warehouse = inList(["Material Receipt", "Sales Return"], doc.purpose); - disable_to_warehouse = inList(["Material Issue", "Purchase Return"], doc.purpose); + cur_frm.toggle_enable("from_warehouse", doc.purpose!='Material Receipt'); + cur_frm.toggle_enable("to_warehouse", doc.purpose!='Material Issue'); - cur_frm.toggle_enable("from_warehouse", !disable_from_warehouse); - cur_frm.toggle_enable("to_warehouse", !disable_to_warehouse); - - cur_frm.fields_dict["items"].grid.set_column_disp("s_warehouse", !disable_from_warehouse); - cur_frm.fields_dict["items"].grid.set_column_disp("t_warehouse", !disable_to_warehouse); + cur_frm.fields_dict["items"].grid.set_column_disp("s_warehouse", doc.purpose!='Material Receipt'); + cur_frm.fields_dict["items"].grid.set_column_disp("t_warehouse", doc.purpose!='Material Issue'); cur_frm.cscript.toggle_enable_bom(); - if(doc.purpose == 'Purchase Return') { - doc.customer = doc.customer_name = doc.customer_address = - doc.delivery_note_no = doc.sales_invoice_no = null; - doc.bom_no = doc.production_order = doc.fg_completed_qty = null; - } else if(doc.purpose == 'Sales Return') { - doc.supplier=doc.supplier_name = doc.supplier_address = doc.purchase_receipt_no=null; - doc.bom_no = doc.production_order = doc.fg_completed_qty = null; - } else if (doc.purpose == 'Subcontract') { + if (doc.purpose == 'Subcontract') { doc.customer = doc.customer_name = doc.customer_address = doc.delivery_note_no = doc.sales_invoice_no = null; } else { @@ -388,7 +223,7 @@ cur_frm.cscript.toggle_related_fields = function(doc) { doc.delivery_note_no = doc.sales_invoice_no = doc.supplier = doc.supplier_name = doc.supplier_address = doc.purchase_receipt_no = null; } - if(in_list(["Material Receipt", "Sales Return", "Purchase Return"], doc.purpose)) { + if(doc.purpose == "Material Receipt") { cur_frm.set_value("from_bom", 0); } } @@ -505,8 +340,6 @@ cur_frm.cscript.uom = function(doc, cdt, cdn) { } cur_frm.cscript.validate = function(doc, cdt, cdn) { - if($.inArray(cur_frm.doc.purpose, ["Purchase Return", "Sales Return"])!==-1) - validated = cur_frm.cscript.get_doctype_docname() ? true : false; cur_frm.cscript.validate_items(doc); } @@ -526,14 +359,6 @@ cur_frm.cscript.cost_center = function(doc, cdt, cdn) { erpnext.utils.copy_value_in_all_row(doc, cdt, cdn, "items", "cost_center"); } -cur_frm.fields_dict.customer.get_query = function(doc, cdt, cdn) { - return { query: "erpnext.controllers.queries.customer_query" } -} - -cur_frm.fields_dict.supplier.get_query = function(doc, cdt, cdn) { - return { query: "erpnext.controllers.queries.supplier_query" } -} - cur_frm.cscript.company = function(doc, cdt, cdn) { if(doc.company) { erpnext.get_fiscal_year(doc.company, doc.posting_date, function() { diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.json b/erpnext/stock/doctype/stock_entry/stock_entry.json index 06dec5808b..ca84db9e31 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.json +++ b/erpnext/stock/doctype/stock_entry/stock_entry.json @@ -54,7 +54,7 @@ "no_copy": 0, "oldfieldname": "purpose", "oldfieldtype": "Select", - "options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nManufacture\nRepack\nSubcontract\nSales Return\nPurchase Return", + "options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nManufacture\nRepack\nSubcontract", "permlevel": 0, "print_hide": 0, "read_only": 0, @@ -678,7 +678,7 @@ "is_submittable": 1, "issingle": 0, "max_attachments": 0, - "modified": "2015-07-13 05:28:26.085266", + "modified": "2015-07-17 15:41:00.980883", "modified_by": "Administrator", "module": "Stock", "name": "Stock Entry", @@ -695,7 +695,7 @@ "print": 1, "read": 1, "report": 1, - "role": "Stock User", + "role": "Material User", "share": 1, "submit": 1, "write": 1 @@ -741,7 +741,7 @@ "print": 1, "read": 1, "report": 1, - "role": "Stock Manager", + "role": "Material Manager", "share": 1, "submit": 1, "write": 1 diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index fb1ec3d17b..78e1038292 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -4,10 +4,8 @@ from __future__ import unicode_literals import frappe import frappe.defaults - -from frappe.utils import cstr, cint, flt, comma_or, get_datetime, getdate - from frappe import _ +from frappe.utils import cstr, cint, flt, comma_or, get_datetime, getdate from erpnext.stock.utils import get_incoming_rate from erpnext.stock.stock_ledger import get_previous_sle, NegativeStockError from erpnext.controllers.queries import get_match_cond @@ -16,7 +14,6 @@ from erpnext.manufacturing.doctype.bom.bom import validate_bom_no from erpnext.accounts.utils import validate_fiscal_year class NotUpdateStockError(frappe.ValidationError): pass -class StockOverReturnError(frappe.ValidationError): pass class IncorrectValuationRateError(frappe.ValidationError): pass class DuplicateEntryForProductionOrderError(frappe.ValidationError): pass class OperationsNotCompleteError(frappe.ValidationError): pass @@ -37,13 +34,6 @@ class StockEntry(StockController): item.update(get_available_qty(item.item_code, item.s_warehouse)) - count = frappe.db.exists({ - "doctype": "Journal Entry", - "stock_entry":self.name, - "docstatus":1 - }) - self.get("__onload").credit_debit_note_exists = 1 if count else 0 - def validate(self): self.pro_doc = None if self.production_order: @@ -84,16 +74,13 @@ class StockEntry(StockController): def validate_purpose(self): valid_purposes = ["Material Issue", "Material Receipt", "Material Transfer", "Material Transfer for Manufacture", - "Manufacture", "Repack", "Subcontract", "Sales Return", "Purchase Return"] + "Manufacture", "Repack", "Subcontract"] if self.purpose not in valid_purposes: frappe.throw(_("Purpose must be one of {0}").format(comma_or(valid_purposes))) - if self.purpose in ("Manufacture", "Repack", "Sales Return") and not self.difference_account: + if self.purpose in ("Manufacture", "Repack") and not self.difference_account: self.difference_account = frappe.db.get_value("Company", self.company, "default_expense_account") - if self.purpose in ("Purchase Return") and not self.difference_account: - frappe.throw(_("Difference Account mandatory for purpose '{0}'").format(self.purpose)) - def set_transfer_qty(self): for item in self.get("items"): if not flt(item.qty): @@ -122,7 +109,7 @@ class StockEntry(StockController): if not item.transfer_qty: item.transfer_qty = item.qty * item.conversion_factor - if (self.purpose in ("Material Transfer", "Sales Return", "Purchase Return", "Material Transfer for Manufacture") + if (self.purpose in ("Material Transfer", "Material Transfer for Manufacture") and not item.serial_no and item.item_code in serialized_items): frappe.throw(_("Row #{0}: Please specify Serial No for Item {1}").format(item.idx, item.item_code), @@ -131,8 +118,8 @@ class StockEntry(StockController): def validate_warehouse(self): """perform various (sometimes conditional) validations on warehouse""" - source_mandatory = ["Material Issue", "Material Transfer", "Purchase Return", "Subcontract", "Material Transfer for Manufacture"] - target_mandatory = ["Material Receipt", "Material Transfer", "Sales Return", "Subcontract", "Material Transfer for Manufacture"] + source_mandatory = ["Material Issue", "Material Transfer", "Subcontract", "Material Transfer for Manufacture"] + target_mandatory = ["Material Receipt", "Material Transfer", "Subcontract", "Material Transfer for Manufacture"] validate_for_manufacture_repack = any([d.bom_no for d in self.get("items")]) @@ -291,8 +278,8 @@ class StockEntry(StockController): # get incoming rate if not d.bom_no: - if not flt(d.incoming_rate) or d.s_warehouse or self.purpose == "Sales Return" or force: - incoming_rate = flt(self.get_incoming_rate(args), self.precision("incoming_rate", d)) + if not flt(d.incoming_rate) or d.s_warehouse or force: + incoming_rate = flt(get_incoming_rate(args), self.precision("incoming_rate", d)) if incoming_rate > 0: d.incoming_rate = incoming_rate @@ -336,27 +323,6 @@ class StockEntry(StockController): return operation_cost_per_unit + (flt(self.additional_operating_cost) / flt(qty)) - def get_incoming_rate(self, args): - incoming_rate = 0 - if self.purpose == "Sales Return": - incoming_rate = self.get_incoming_rate_for_sales_return(args) - else: - incoming_rate = get_incoming_rate(args) - - return incoming_rate - - def get_incoming_rate_for_sales_return(self, args): - incoming_rate = 0.0 - if (self.delivery_note_no or self.sales_invoice_no) and args.get("item_code"): - incoming_rate = frappe.db.sql("""select abs(ifnull(stock_value_difference, 0) / actual_qty) - from `tabStock Ledger Entry` - where voucher_type = %s and voucher_no = %s and item_code = %s limit 1""", - ((self.delivery_note_no and "Delivery Note" or "Sales Invoice"), - self.delivery_note_no or self.sales_invoice_no, args.item_code)) - incoming_rate = incoming_rate[0][0] if incoming_rate else 0.0 - - return incoming_rate - def validate_purchase_order(self): """Throw exception if more raw material is transferred against Purchase Order than in the raw materials supplied table""" @@ -403,55 +369,6 @@ class StockEntry(StockController): frappe.throw(_("Finished Item {0} must be entered for Manufacture type entry") .format(production_item)) - def validate_return_reference_doc(self): - """validate item with reference doc""" - ref = get_return_doc_and_details(self) - - if ref.doc: - # validate docstatus - if ref.doc.docstatus != 1: - frappe.throw(_("{0} {1} must be submitted").format(ref.doc.doctype, ref.doc.name), - frappe.InvalidStatusError) - - # update stock check - if ref.doc.doctype == "Sales Invoice" and cint(ref.doc.update_stock) != 1: - frappe.throw(_("'Update Stock' for Sales Invoice {0} must be set").format(ref.doc.name), NotUpdateStockError) - - # posting date check - ref_posting_datetime = "%s %s" % (ref.doc.posting_date, ref.doc.posting_time or "00:00:00") - - if get_datetime(ref_posting_datetime) < get_datetime(ref_posting_datetime): - from frappe.utils.dateutils import datetime_in_user_format - frappe.throw(_("Posting timestamp must be after {0}") - .format(datetime_in_user_format(ref_posting_datetime))) - - stock_items = get_stock_items_for_return(ref.doc, ref.parentfields) - already_returned_item_qty = self.get_already_returned_item_qty(ref.fieldname) - - for item in self.get("items"): - # validate if item exists in the ref doc and that it is a stock item - if item.item_code not in stock_items: - frappe.throw(_("Item {0} does not exist in {1} {2}").format(item.item_code, ref.doc.doctype, ref.doc.name), - frappe.DoesNotExistError) - - # validate quantity <= ref item's qty - qty already returned - if self.purpose == "Purchase Return": - ref_item_qty = sum([flt(d.qty)*flt(d.conversion_factor) for d in ref.doc.get({"item_code": item.item_code})]) - elif self.purpose == "Sales Return": - ref_item_qty = sum([flt(d.qty) for d in ref.doc.get({"item_code": item.item_code})]) - returnable_qty = ref_item_qty - flt(already_returned_item_qty.get(item.item_code)) - if not returnable_qty: - frappe.throw(_("Item {0} has already been returned").format(item.item_code), StockOverReturnError) - elif item.transfer_qty > returnable_qty: - frappe.throw(_("Cannot return more than {0} for Item {1}").format(returnable_qty, item.item_code), - StockOverReturnError) - - def get_already_returned_item_qty(self, ref_fieldname): - return dict(frappe.db.sql("""select item_code, sum(transfer_qty) as qty - from `tabStock Entry Detail` where parent in ( - select name from `tabStock Entry` where `%s`=%s and docstatus=1) - group by item_code""" % (ref_fieldname, "%s"), (self.get(ref_fieldname),))) - def update_stock_ledger(self): sl_entries = [] for d in self.get('items'): @@ -514,6 +431,7 @@ class StockEntry(StockController): (args.get('item_code')), as_dict = 1) if not item: frappe.throw(_("Item {0} is not active or end of life has been reached").format(args.get("item_code"))) + item = item[0] ret = { @@ -561,7 +479,7 @@ class StockEntry(StockController): ret = { "actual_qty" : get_previous_sle(args).get("qty_after_transaction") or 0, - "incoming_rate" : self.get_incoming_rate(args) + "incoming_rate" : get_incoming_rate(args) } return ret @@ -738,15 +656,6 @@ class StockEntry(StockController): if getdate(self.posting_date) > getdate(expiry_date): frappe.throw(_("Batch {0} of Item {1} has expired.").format(item.batch_no, item.item_code)) -@frappe.whitelist() -def get_party_details(ref_dt, ref_dn): - if ref_dt in ["Delivery Note", "Sales Invoice"]: - res = frappe.db.get_value(ref_dt, ref_dn, - ["customer", "customer_name", "address_display as customer_address"], as_dict=1) - else: - res = frappe.db.get_value(ref_dt, ref_dn, - ["supplier", "supplier_name", "address_display as supplier_address"], as_dict=1) - return res or {} @frappe.whitelist() def get_production_order_details(production_order): @@ -756,264 +665,3 @@ def get_production_order_details(production_order): from `tabProduction Order` where name = %s""", production_order, as_dict=1) return res and res[0] or {} - -def query_sales_return_doc(doctype, txt, searchfield, start, page_len, filters): - conditions = "" - if doctype == "Sales Invoice": - conditions = "and update_stock=1" - - return frappe.db.sql("""select name, customer, customer_name - from `tab%s` where docstatus = 1 - and (`%s` like %%(txt)s - or `customer` like %%(txt)s) %s %s - order by name, customer, customer_name - limit %s""" % (doctype, searchfield, conditions, - get_match_cond(doctype), "%(start)s, %(page_len)s"), - {"txt": "%%%s%%" % txt, "start": start, "page_len": page_len}, - as_list=True) - -def query_purchase_return_doc(doctype, txt, searchfield, start, page_len, filters): - return frappe.db.sql("""select name, supplier, supplier_name - from `tab%s` where docstatus = 1 - and (`%s` like %%(txt)s - or `supplier` like %%(txt)s) %s - order by name, supplier, supplier_name - limit %s""" % (doctype, searchfield, get_match_cond(doctype), - "%(start)s, %(page_len)s"), {"txt": "%%%s%%" % txt, "start": - start, "page_len": page_len}, as_list=True) - -def query_return_item(doctype, txt, searchfield, start, page_len, filters): - txt = txt.replace("%", "") - - ref = get_return_doc_and_details(filters) - - stock_items = get_stock_items_for_return(ref.doc, ref.parentfields) - - result = [] - for item in ref.doc.get_all_children(): - if getattr(item, "item_code", None) in stock_items: - item.item_name = cstr(item.item_name) - item.description = cstr(item.description) - if (txt in item.item_code) or (txt in item.item_name) or (txt in item.description): - val = [ - item.item_code, - (len(item.item_name) > 40) and (item.item_name[:40] + "...") or item.item_name, - (len(item.description) > 40) and (item.description[:40] + "...") or \ - item.description - ] - if val not in result: - result.append(val) - - return result[start:start+page_len] - -def get_stock_items_for_return(ref_doc, parentfields): - """return item codes filtered from doc, which are stock items""" - if isinstance(parentfields, basestring): - parentfields = [parentfields] - - all_items = list(set([d.item_code for d in - ref_doc.get_all_children() if d.get("item_code")])) - stock_items = frappe.db.sql_list("""select name from `tabItem` - where is_stock_item='Yes' and name in (%s)""" % (", ".join(["%s"] * len(all_items))), - tuple(all_items)) - - return stock_items - -def get_return_doc_and_details(args): - ref = frappe._dict() - - # get ref_doc - if args.get("purpose") in return_map: - for fieldname, val in return_map[args.get("purpose")].items(): - if args.get(fieldname): - ref.fieldname = fieldname - ref.doc = frappe.get_doc(val[0], args.get(fieldname)) - ref.parentfields = val[1] - break - - return ref - -return_map = { - "Sales Return": { - # [Ref DocType, [Item tables' parentfields]] - "delivery_note_no": ["Delivery Note", ["items", "packed_items"]], - "sales_invoice_no": ["Sales Invoice", ["items", "packed_items"]] - }, - "Purchase Return": { - "purchase_receipt_no": ["Purchase Receipt", ["items"]] - } -} - -@frappe.whitelist() -def make_return_jv(stock_entry): - se = frappe.get_doc("Stock Entry", stock_entry) - if not se.purpose in ["Sales Return", "Purchase Return"]: - return - - ref = get_return_doc_and_details(se) - - if ref.doc.doctype == "Delivery Note": - result = make_return_jv_from_delivery_note(se, ref) - elif ref.doc.doctype == "Sales Invoice": - result = make_return_jv_from_sales_invoice(se, ref) - elif ref.doc.doctype == "Purchase Receipt": - result = make_return_jv_from_purchase_receipt(se, ref) - - # create jv doc and fetch balance for each unique row item - jv = frappe.new_doc("Journal Entry") - jv.update({ - "posting_date": se.posting_date, - "voucher_type": se.purpose == "Sales Return" and "Credit Note" or "Debit Note", - "fiscal_year": se.fiscal_year, - "company": se.company, - "stock_entry": se.name - }) - - from erpnext.accounts.utils import get_balance_on - for r in result: - jv.append("accounts", { - "account": r.get("account"), - "party_type": r.get("party_type"), - "party": r.get("party"), - "balance": get_balance_on(r.get("account"), se.posting_date) if r.get("account") else 0 - }) - - return jv - -def make_return_jv_from_sales_invoice(se, ref): - # customer account entry - parent = { - "account": ref.doc.debit_to, - "party_type": "Customer", - "party": ref.doc.customer - } - - # income account entries - children = [] - for se_item in se.get("items"): - # find item in ref.doc - ref_item = ref.doc.get({"item_code": se_item.item_code})[0] - - account = get_sales_account_from_item(ref.doc, ref_item) - - if account not in children: - children.append(account) - - return [parent] + [{"account": account} for account in children] - -def get_sales_account_from_item(doc, ref_item): - account = None - if not getattr(ref_item, "income_account", None): - if ref_item.parent_item: - parent_item = doc.get("items", {"item_code": ref_item.parent_item})[0] - account = parent_item.income_account - else: - account = ref_item.income_account - - return account - -def make_return_jv_from_delivery_note(se, ref): - invoices_against_delivery = get_invoice_list("Sales Invoice Item", "delivery_note", - ref.doc.name) - - if not invoices_against_delivery: - sales_orders_against_delivery = [d.against_sales_order for d in ref.doc.get_all_children() if getattr(d, "against_sales_order", None)] - - if sales_orders_against_delivery: - invoices_against_delivery = get_invoice_list("Sales Invoice Item", "sales_order", - sales_orders_against_delivery) - - if not invoices_against_delivery: - return [] - - packing_item_parent_map = dict([[d.item_code, d.parent_item] for d in ref.doc.get(ref.parentfields[1])]) - - parent = {} - children = [] - - for se_item in se.get("items"): - for sales_invoice in invoices_against_delivery: - si = frappe.get_doc("Sales Invoice", sales_invoice) - - if se_item.item_code in packing_item_parent_map: - ref_item = si.get({"item_code": packing_item_parent_map[se_item.item_code]}) - else: - ref_item = si.get({"item_code": se_item.item_code}) - - if not ref_item: - continue - - ref_item = ref_item[0] - - account = get_sales_account_from_item(si, ref_item) - - if account not in children: - children.append(account) - - if not parent: - parent = { - "account": si.debit_to, - "party_type": "Customer", - "party": si.customer - } - - break - - result = [parent] + [{"account": account} for account in children] - - return result - -def get_invoice_list(doctype, link_field, value): - if isinstance(value, basestring): - value = [value] - - return frappe.db.sql_list("""select distinct parent from `tab%s` - where docstatus = 1 and `%s` in (%s)""" % (doctype, link_field, - ", ".join(["%s"]*len(value))), tuple(value)) - -def make_return_jv_from_purchase_receipt(se, ref): - invoice_against_receipt = get_invoice_list("Purchase Invoice Item", "purchase_receipt", - ref.doc.name) - - if not invoice_against_receipt: - purchase_orders_against_receipt = [d.prevdoc_docname for d in - ref.doc.get("items", {"prevdoc_doctype": "Purchase Order"}) - if getattr(d, "prevdoc_docname", None)] - - if purchase_orders_against_receipt: - invoice_against_receipt = get_invoice_list("Purchase Invoice Item", "purchase_order", - purchase_orders_against_receipt) - - if not invoice_against_receipt: - return [] - - parent = {} - children = [] - - for se_item in se.get("items"): - for purchase_invoice in invoice_against_receipt: - pi = frappe.get_doc("Purchase Invoice", purchase_invoice) - ref_item = pi.get({"item_code": se_item.item_code}) - - if not ref_item: - continue - - ref_item = ref_item[0] - - account = ref_item.expense_account - - if account not in children: - children.append(account) - - if not parent: - parent = { - "account": pi.credit_to, - "party_type": "Supplier", - "party": pi.supplier - } - - break - - result = [parent] + [{"account": account} for account in children] - - return result diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index 70d6413ce1..5406bdccfb 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -303,262 +303,262 @@ class TestStockEntry(unittest.TestCase): self.assertEquals(expected_gl_entries[i][1], gle[1]) self.assertEquals(expected_gl_entries[i][2], gle[2]) - def _test_sales_invoice_return(self, item_code, delivered_qty, returned_qty): - from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice - - si = create_sales_invoice(item_code=item_code, qty=delivered_qty) - - se = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=returned_qty, - purpose="Sales Return", sales_invoice_no=si.name, do_not_save=True) - self.assertRaises(NotUpdateStockError, se.insert) - - make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=200, incoming_rate=100) - - # check currency available qty in bin - actual_qty_0 = get_qty_after_transaction() - - # insert a pos invoice with update stock - si = create_sales_invoice(update_stock=1, item_code=item_code, qty=5) - - # check available bin qty after invoice submission - actual_qty_1 = get_qty_after_transaction() - - self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1) - - # check if item is validated - se = make_stock_entry(item_code="_Test Item Home Desktop 200", target="_Test Warehouse - _TC", - qty=returned_qty, purpose="Sales Return", sales_invoice_no=si.name, do_not_save=True) - - self.assertRaises(frappe.DoesNotExistError, se.insert) - - # try again - se = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", - qty=returned_qty, purpose="Sales Return", sales_invoice_no=si.name) - - # check if available qty is increased - actual_qty_2 = get_qty_after_transaction() - - self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2) - - return se - - def test_sales_invoice_return_of_non_packing_item(self): - self._test_sales_invoice_return("_Test Item", 5, 2) - - def test_sales_invoice_return_of_packing_item(self): - self._test_sales_invoice_return("_Test Product Bundle Item", 25, 20) - - def _test_delivery_note_return(self, item_code, delivered_qty, returned_qty): - from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note - - from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice - - make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, incoming_rate=100) - - actual_qty_0 = get_qty_after_transaction() - # make a delivery note based on this invoice - dn = create_delivery_note(item_code="_Test Item", - warehouse="_Test Warehouse - _TC", qty=delivered_qty) - - actual_qty_1 = get_qty_after_transaction() - - self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1) - - si = make_sales_invoice(dn.name) - si.insert() - si.submit() - - # insert and submit stock entry for sales return - se = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", - qty=returned_qty, purpose="Sales Return", delivery_note_no=dn.name) - - actual_qty_2 = get_qty_after_transaction() - self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2) - - return se - - def test_delivery_note_return_of_non_packing_item(self): - self._test_delivery_note_return("_Test Item", 5, 2) - - def test_delivery_note_return_of_packing_item(self): - self._test_delivery_note_return("_Test Product Bundle Item", 25, 20) - - def _test_sales_return_jv(self, se): - jv = make_return_jv(se.name) - - self.assertEqual(len(jv.get("accounts")), 2) - self.assertEqual(jv.get("voucher_type"), "Credit Note") - self.assertEqual(jv.get("posting_date"), getdate(se.posting_date)) - self.assertEqual(jv.get("accounts")[0].get("account"), "Debtors - _TC") - self.assertEqual(jv.get("accounts")[0].get("party_type"), "Customer") - self.assertEqual(jv.get("accounts")[0].get("party"), "_Test Customer") - self.assertEqual(jv.get("accounts")[1].get("account"), "Sales - _TC") - - def test_make_return_jv_for_sales_invoice_non_packing_item(self): - se = self._test_sales_invoice_return("_Test Item", 5, 2) - self._test_sales_return_jv(se) - - def test_make_return_jv_for_sales_invoice_packing_item(self): - se = self._test_sales_invoice_return("_Test Product Bundle Item", 25, 20) - self._test_sales_return_jv(se) - - def test_make_return_jv_for_delivery_note_non_packing_item(self): - se = self._test_delivery_note_return("_Test Item", 5, 2) - self._test_sales_return_jv(se) - - se = self._test_delivery_note_return_against_sales_order("_Test Item", 5, 2) - self._test_sales_return_jv(se) - - def test_make_return_jv_for_delivery_note_packing_item(self): - se = self._test_delivery_note_return("_Test Product Bundle Item", 25, 20) - self._test_sales_return_jv(se) - - se = self._test_delivery_note_return_against_sales_order("_Test Product Bundle Item", 25, 20) - self._test_sales_return_jv(se) - - def _test_delivery_note_return_against_sales_order(self, item_code, delivered_qty, returned_qty): - from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice - - actual_qty_0 = get_qty_after_transaction() - - so = make_sales_order(qty=50) - - dn = create_dn_against_so(so.name, delivered_qty) - - actual_qty_1 = get_qty_after_transaction() - self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1) - - si = make_sales_invoice(so.name) - si.insert() - si.submit() - - # insert and submit stock entry for sales return - se = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", - qty=returned_qty, purpose="Sales Return", delivery_note_no=dn.name) - - actual_qty_2 = get_qty_after_transaction() - self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2) - - return se - - def test_purchase_receipt_return(self): - actual_qty_0 = get_qty_after_transaction() - - # submit purchase receipt - pr = make_purchase_receipt(item_code="_Test Item", warehouse="_Test Warehouse - _TC", qty=5) - - actual_qty_1 = get_qty_after_transaction() - - self.assertEquals(actual_qty_0 + 5, actual_qty_1) - - pi_doc = make_purchase_invoice(pr.name) - - pi = frappe.get_doc(pi_doc) - pi.posting_date = pr.posting_date - pi.credit_to = "_Test Payable - _TC" - for d in pi.get("items"): - d.expense_account = "_Test Account Cost for Goods Sold - _TC" - d.cost_center = "_Test Cost Center - _TC" - - for d in pi.get("taxes"): - d.cost_center = "_Test Cost Center - _TC" - - pi.insert() - pi.submit() - - # submit purchase return - se = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", - qty=5, purpose="Purchase Return", purchase_receipt_no=pr.name) - - actual_qty_2 = get_qty_after_transaction() - - self.assertEquals(actual_qty_1 - 5, actual_qty_2) - - return se, pr.name - - def test_over_stock_return(self): - from erpnext.stock.doctype.stock_entry.stock_entry import StockOverReturnError - - # out of 10, 5 gets returned - prev_se, pr_docname = self.test_purchase_receipt_return() - - se = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", - qty=6, purpose="Purchase Return", purchase_receipt_no=pr_docname, do_not_save=True) - - self.assertRaises(StockOverReturnError, se.insert) - - def _test_purchase_return_jv(self, se): - jv = make_return_jv(se.name) - - self.assertEqual(len(jv.get("accounts")), 2) - self.assertEqual(jv.get("voucher_type"), "Debit Note") - self.assertEqual(jv.get("posting_date"), getdate(se.posting_date)) - self.assertEqual(jv.get("accounts")[0].get("account"), "_Test Payable - _TC") - self.assertEqual(jv.get("accounts")[0].get("party"), "_Test Supplier") - self.assertEqual(jv.get("accounts")[1].get("account"), "_Test Account Cost for Goods Sold - _TC") - - def test_make_return_jv_for_purchase_receipt(self): - se, pr_name = self.test_purchase_receipt_return() - self._test_purchase_return_jv(se) - - se, pr_name = self._test_purchase_return_return_against_purchase_order() - self._test_purchase_return_jv(se) - - def _test_purchase_return_return_against_purchase_order(self): - - actual_qty_0 = get_qty_after_transaction() - - from erpnext.buying.doctype.purchase_order.test_purchase_order \ - import test_records as purchase_order_test_records - - from erpnext.buying.doctype.purchase_order.purchase_order import \ - make_purchase_receipt, make_purchase_invoice - - # submit purchase receipt - po = frappe.copy_doc(purchase_order_test_records[0]) - po.transaction_date = nowdate() - po.is_subcontracted = None - po.get("items")[0].item_code = "_Test Item" - po.get("items")[0].rate = 50 - po.insert() - po.submit() - - pr_doc = make_purchase_receipt(po.name) - - pr = frappe.get_doc(pr_doc) - pr.posting_date = po.transaction_date - pr.insert() - pr.submit() - - actual_qty_1 = get_qty_after_transaction() - - self.assertEquals(actual_qty_0 + 10, actual_qty_1) - - pi_doc = make_purchase_invoice(po.name) - - pi = frappe.get_doc(pi_doc) - pi.posting_date = pr.posting_date - pi.credit_to = "_Test Payable - _TC" - for d in pi.get("items"): - d.expense_account = "_Test Account Cost for Goods Sold - _TC" - d.cost_center = "_Test Cost Center - _TC" - for d in pi.get("taxes"): - d.cost_center = "_Test Cost Center - _TC" - - pi.run_method("calculate_taxes_and_totals") - pi.bill_no = "NA" - pi.insert() - pi.submit() - - # submit purchase return - se = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", - qty=5, purpose="Purchase Return", purchase_receipt_no=pr.name) - - actual_qty_2 = get_qty_after_transaction() - - self.assertEquals(actual_qty_1 - 5, actual_qty_2) - - return se, pr.name + # def _test_sales_invoice_return(self, item_code, delivered_qty, returned_qty): + # from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice + # + # si = create_sales_invoice(item_code=item_code, qty=delivered_qty) + # + # se = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=returned_qty, + # purpose="Sales Return", sales_invoice_no=si.name, do_not_save=True) + # self.assertRaises(NotUpdateStockError, se.insert) + # + # make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=200, incoming_rate=100) + # + # # check currency available qty in bin + # actual_qty_0 = get_qty_after_transaction() + # + # # insert a pos invoice with update stock + # si = create_sales_invoice(update_stock=1, item_code=item_code, qty=5) + # + # # check available bin qty after invoice submission + # actual_qty_1 = get_qty_after_transaction() + # + # self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1) + # + # # check if item is validated + # se = make_stock_entry(item_code="_Test Item Home Desktop 200", target="_Test Warehouse - _TC", + # qty=returned_qty, purpose="Sales Return", sales_invoice_no=si.name, do_not_save=True) + # + # self.assertRaises(frappe.DoesNotExistError, se.insert) + # + # # try again + # se = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", + # qty=returned_qty, purpose="Sales Return", sales_invoice_no=si.name) + # + # # check if available qty is increased + # actual_qty_2 = get_qty_after_transaction() + # + # self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2) + # + # return se + # + # def test_sales_invoice_return_of_non_packing_item(self): + # self._test_sales_invoice_return("_Test Item", 5, 2) + # + # def test_sales_invoice_return_of_packing_item(self): + # self._test_sales_invoice_return("_Test Product Bundle Item", 25, 20) + # + # def _test_delivery_note_return(self, item_code, delivered_qty, returned_qty): + # from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note + # + # from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice + # + # make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, incoming_rate=100) + # + # actual_qty_0 = get_qty_after_transaction() + # # make a delivery note based on this invoice + # dn = create_delivery_note(item_code="_Test Item", + # warehouse="_Test Warehouse - _TC", qty=delivered_qty) + # + # actual_qty_1 = get_qty_after_transaction() + # + # self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1) + # + # si = make_sales_invoice(dn.name) + # si.insert() + # si.submit() + # + # # insert and submit stock entry for sales return + # se = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", + # qty=returned_qty, purpose="Sales Return", delivery_note_no=dn.name) + # + # actual_qty_2 = get_qty_after_transaction() + # self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2) + # + # return se + # + # def test_delivery_note_return_of_non_packing_item(self): + # self._test_delivery_note_return("_Test Item", 5, 2) + # + # def test_delivery_note_return_of_packing_item(self): + # self._test_delivery_note_return("_Test Product Bundle Item", 25, 20) + # + # def _test_sales_return_jv(self, se): + # jv = make_return_jv(se.name) + # + # self.assertEqual(len(jv.get("accounts")), 2) + # self.assertEqual(jv.get("voucher_type"), "Credit Note") + # self.assertEqual(jv.get("posting_date"), getdate(se.posting_date)) + # self.assertEqual(jv.get("accounts")[0].get("account"), "Debtors - _TC") + # self.assertEqual(jv.get("accounts")[0].get("party_type"), "Customer") + # self.assertEqual(jv.get("accounts")[0].get("party"), "_Test Customer") + # self.assertEqual(jv.get("accounts")[1].get("account"), "Sales - _TC") + # + # def test_make_return_jv_for_sales_invoice_non_packing_item(self): + # se = self._test_sales_invoice_return("_Test Item", 5, 2) + # self._test_sales_return_jv(se) + # + # def test_make_return_jv_for_sales_invoice_packing_item(self): + # se = self._test_sales_invoice_return("_Test Product Bundle Item", 25, 20) + # self._test_sales_return_jv(se) + # + # def test_make_return_jv_for_delivery_note_non_packing_item(self): + # se = self._test_delivery_note_return("_Test Item", 5, 2) + # self._test_sales_return_jv(se) + # + # se = self._test_delivery_note_return_against_sales_order("_Test Item", 5, 2) + # self._test_sales_return_jv(se) + # + # def test_make_return_jv_for_delivery_note_packing_item(self): + # se = self._test_delivery_note_return("_Test Product Bundle Item", 25, 20) + # self._test_sales_return_jv(se) + # + # se = self._test_delivery_note_return_against_sales_order("_Test Product Bundle Item", 25, 20) + # self._test_sales_return_jv(se) + # + # def _test_delivery_note_return_against_sales_order(self, item_code, delivered_qty, returned_qty): + # from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice + # + # actual_qty_0 = get_qty_after_transaction() + # + # so = make_sales_order(qty=50) + # + # dn = create_dn_against_so(so.name, delivered_qty) + # + # actual_qty_1 = get_qty_after_transaction() + # self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1) + # + # si = make_sales_invoice(so.name) + # si.insert() + # si.submit() + # + # # insert and submit stock entry for sales return + # se = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", + # qty=returned_qty, purpose="Sales Return", delivery_note_no=dn.name) + # + # actual_qty_2 = get_qty_after_transaction() + # self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2) + # + # return se + # + # def test_purchase_receipt_return(self): + # actual_qty_0 = get_qty_after_transaction() + # + # # submit purchase receipt + # pr = make_purchase_receipt(item_code="_Test Item", warehouse="_Test Warehouse - _TC", qty=5) + # + # actual_qty_1 = get_qty_after_transaction() + # + # self.assertEquals(actual_qty_0 + 5, actual_qty_1) + # + # pi_doc = make_purchase_invoice(pr.name) + # + # pi = frappe.get_doc(pi_doc) + # pi.posting_date = pr.posting_date + # pi.credit_to = "_Test Payable - _TC" + # for d in pi.get("items"): + # d.expense_account = "_Test Account Cost for Goods Sold - _TC" + # d.cost_center = "_Test Cost Center - _TC" + # + # for d in pi.get("taxes"): + # d.cost_center = "_Test Cost Center - _TC" + # + # pi.insert() + # pi.submit() + # + # # submit purchase return + # se = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", + # qty=5, purpose="Purchase Return", purchase_receipt_no=pr.name) + # + # actual_qty_2 = get_qty_after_transaction() + # + # self.assertEquals(actual_qty_1 - 5, actual_qty_2) + # + # return se, pr.name + # + # def test_over_stock_return(self): + # from erpnext.stock.doctype.stock_entry.stock_entry import StockOverReturnError + # + # # out of 10, 5 gets returned + # prev_se, pr_docname = self.test_purchase_receipt_return() + # + # se = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", + # qty=6, purpose="Purchase Return", purchase_receipt_no=pr_docname, do_not_save=True) + # + # self.assertRaises(StockOverReturnError, se.insert) + # + # def _test_purchase_return_jv(self, se): + # jv = make_return_jv(se.name) + # + # self.assertEqual(len(jv.get("accounts")), 2) + # self.assertEqual(jv.get("voucher_type"), "Debit Note") + # self.assertEqual(jv.get("posting_date"), getdate(se.posting_date)) + # self.assertEqual(jv.get("accounts")[0].get("account"), "_Test Payable - _TC") + # self.assertEqual(jv.get("accounts")[0].get("party"), "_Test Supplier") + # self.assertEqual(jv.get("accounts")[1].get("account"), "_Test Account Cost for Goods Sold - _TC") + # + # def test_make_return_jv_for_purchase_receipt(self): + # se, pr_name = self.test_purchase_receipt_return() + # self._test_purchase_return_jv(se) + # + # se, pr_name = self._test_purchase_return_return_against_purchase_order() + # self._test_purchase_return_jv(se) + # + # def _test_purchase_return_return_against_purchase_order(self): + # + # actual_qty_0 = get_qty_after_transaction() + # + # from erpnext.buying.doctype.purchase_order.test_purchase_order \ + # import test_records as purchase_order_test_records + # + # from erpnext.buying.doctype.purchase_order.purchase_order import \ + # make_purchase_receipt, make_purchase_invoice + # + # # submit purchase receipt + # po = frappe.copy_doc(purchase_order_test_records[0]) + # po.transaction_date = nowdate() + # po.is_subcontracted = None + # po.get("items")[0].item_code = "_Test Item" + # po.get("items")[0].rate = 50 + # po.insert() + # po.submit() + # + # pr_doc = make_purchase_receipt(po.name) + # + # pr = frappe.get_doc(pr_doc) + # pr.posting_date = po.transaction_date + # pr.insert() + # pr.submit() + # + # actual_qty_1 = get_qty_after_transaction() + # + # self.assertEquals(actual_qty_0 + 10, actual_qty_1) + # + # pi_doc = make_purchase_invoice(po.name) + # + # pi = frappe.get_doc(pi_doc) + # pi.posting_date = pr.posting_date + # pi.credit_to = "_Test Payable - _TC" + # for d in pi.get("items"): + # d.expense_account = "_Test Account Cost for Goods Sold - _TC" + # d.cost_center = "_Test Cost Center - _TC" + # for d in pi.get("taxes"): + # d.cost_center = "_Test Cost Center - _TC" + # + # pi.run_method("calculate_taxes_and_totals") + # pi.bill_no = "NA" + # pi.insert() + # pi.submit() + # + # # submit purchase return + # se = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", + # qty=5, purpose="Purchase Return", purchase_receipt_no=pr.name) + # + # actual_qty_2 = get_qty_after_transaction() + # + # self.assertEquals(actual_qty_1 - 5, actual_qty_2) + # + # return se, pr.name def test_serial_no_not_reqd(self): se = frappe.copy_doc(test_records[0])