mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-01 03:09:09 +00:00
Sales / Purchase Return redesigned via negative DN / SI / PR / PI
This commit is contained in:
@@ -24,7 +24,9 @@ erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend(
|
||||
cur_frm.add_custom_button(__('Make Installation Note'), this.make_installation_note);
|
||||
|
||||
if (doc.docstatus==1) {
|
||||
|
||||
cur_frm.add_custom_button(__('Make Sales Return'), this.make_sales_return,
|
||||
frappe.boot.doctype_icons["Delivery Note"]);
|
||||
|
||||
this.show_stock_ledger();
|
||||
this.show_general_ledger();
|
||||
}
|
||||
@@ -73,6 +75,13 @@ erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend(
|
||||
frm: cur_frm
|
||||
});
|
||||
},
|
||||
|
||||
make_sales_return: function() {
|
||||
frappe.model.open_mapped_doc({
|
||||
method: "erpnext.stock.doctype.delivery_note.delivery_note.make_sales_return",
|
||||
frm: cur_frm
|
||||
})
|
||||
},
|
||||
|
||||
tc_name: function() {
|
||||
this.get_terms();
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "naming_series",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "DN-",
|
||||
"options": "DN-\nDN-RET-",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
@@ -205,6 +205,28 @@
|
||||
"read_only": 1,
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"fieldname": "is_return",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Return",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "is_return",
|
||||
"fieldname": "return_against",
|
||||
"fieldtype": "Link",
|
||||
"label": "Return Against Delivery Note",
|
||||
"no_copy": 1,
|
||||
"options": "Delivery Note",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "cusrrency_and_price_list",
|
||||
"fieldtype": "Section Break",
|
||||
@@ -1070,7 +1092,7 @@
|
||||
"idx": 1,
|
||||
"in_create": 0,
|
||||
"is_submittable": 1,
|
||||
"modified": "2015-07-13 05:28:29.814096",
|
||||
"modified": "2015-07-17 13:29:28.019506",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Delivery Note",
|
||||
|
||||
@@ -84,7 +84,7 @@ class DeliveryNote(SellingController):
|
||||
|
||||
def so_required(self):
|
||||
"""check in manage account if sales order required or not"""
|
||||
if frappe.db.get_value("Selling Settings", None, 'so_required') == 'Yes':
|
||||
if not self.is_return and frappe.db.get_value("Selling Settings", None, 'so_required') == 'Yes':
|
||||
for d in self.get('items'):
|
||||
if not d.against_sales_order:
|
||||
frappe.throw(_("Sales Order required for Item {0}").format(d.item_code))
|
||||
@@ -175,17 +175,15 @@ class DeliveryNote(SellingController):
|
||||
# Check for Approving Authority
|
||||
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype, self.company, self.base_grand_total, self)
|
||||
|
||||
# update delivered qty in sales order
|
||||
self.update_prevdoc_status()
|
||||
if not self.is_return:
|
||||
# update delivered qty in sales order
|
||||
self.update_prevdoc_status()
|
||||
|
||||
self.check_credit_limit()
|
||||
self.check_credit_limit()
|
||||
|
||||
# create stock ledger entry
|
||||
self.update_stock_ledger()
|
||||
|
||||
self.make_gl_entries()
|
||||
|
||||
# set DN status
|
||||
frappe.db.set(self, 'status', 'Submitted')
|
||||
|
||||
|
||||
@@ -193,7 +191,8 @@ class DeliveryNote(SellingController):
|
||||
self.check_stop_sales_order("against_sales_order")
|
||||
self.check_next_docstatus()
|
||||
|
||||
self.update_prevdoc_status()
|
||||
if not self.is_return:
|
||||
self.update_prevdoc_status()
|
||||
|
||||
self.update_stock_ledger()
|
||||
|
||||
@@ -251,9 +250,14 @@ class DeliveryNote(SellingController):
|
||||
if frappe.db.get_value("Item", d.item_code, "is_stock_item") == "Yes" \
|
||||
and d.warehouse and flt(d['qty']):
|
||||
self.update_reserved_qty(d)
|
||||
|
||||
|
||||
incoming_rate = 0
|
||||
if cint(self.is_return) and self.return_against and self.docstatus==1:
|
||||
incoming_rate = self.get_incoming_rate_for_sales_return(d.item_code, self.return_against)
|
||||
|
||||
sl_entries.append(self.get_sl_entries(d, {
|
||||
"actual_qty": -1*flt(d['qty']),
|
||||
incoming_rate: incoming_rate
|
||||
}))
|
||||
|
||||
self.make_sl_entries(sl_entries)
|
||||
@@ -387,3 +391,9 @@ def make_packing_slip(source_name, target_doc=None):
|
||||
}, target_doc)
|
||||
|
||||
return doclist
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_sales_return(source_name, target_doc=None):
|
||||
from erpnext.utilities.transaction_base import make_return_doc
|
||||
return make_return_doc("Delivery Note", source_name, target_doc)
|
||||
@@ -34,6 +34,9 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend
|
||||
cur_frm.add_custom_button(__('Make Purchase Invoice'), this.make_purchase_invoice,
|
||||
frappe.boot.doctype_icons["Purchase Invoice"]);
|
||||
}
|
||||
|
||||
cur_frm.add_custom_button(__('Make Purchase Return'), this.make_purchase_return,
|
||||
frappe.boot.doctype_icons["Purchase Receipt"]);
|
||||
|
||||
this.show_stock_ledger();
|
||||
this.show_general_ledger();
|
||||
@@ -105,6 +108,13 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend
|
||||
frm: cur_frm
|
||||
})
|
||||
},
|
||||
|
||||
make_purchase_return: function() {
|
||||
frappe.model.open_mapped_doc({
|
||||
method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_purchase_return",
|
||||
frm: cur_frm
|
||||
})
|
||||
},
|
||||
|
||||
tc_name: function() {
|
||||
this.get_terms();
|
||||
|
||||
@@ -21,13 +21,14 @@
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"default": "",
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"label": "Series",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "naming_series",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "PREC-",
|
||||
"options": "PREC-\nPREC-RET-",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"reqd": 1
|
||||
@@ -130,6 +131,28 @@
|
||||
"search_index": 0,
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"fieldname": "is_return",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Return",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "is_return",
|
||||
"fieldname": "return_against",
|
||||
"fieldtype": "Link",
|
||||
"label": "Return Against Purchase Receipt",
|
||||
"no_copy": 1,
|
||||
"options": "Purchase Receipt",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "currency_and_price_list",
|
||||
"fieldtype": "Section Break",
|
||||
@@ -854,7 +877,7 @@
|
||||
"icon": "icon-truck",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2015-07-13 05:28:27.389559",
|
||||
"modified": "2015-07-17 13:29:10.298448",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Purchase Receipt",
|
||||
|
||||
@@ -44,6 +44,7 @@ class PurchaseReceipt(BuyingController):
|
||||
self.set_status()
|
||||
self.po_required()
|
||||
self.validate_with_previous_doc()
|
||||
self.validate_purchase_return()
|
||||
self.validate_rejected_warehouse()
|
||||
self.validate_accepted_rejected_qty()
|
||||
self.validate_inspection()
|
||||
@@ -60,12 +61,21 @@ class PurchaseReceipt(BuyingController):
|
||||
self.set_landed_cost_voucher_amount()
|
||||
self.update_valuation_rate("items")
|
||||
|
||||
|
||||
def set_landed_cost_voucher_amount(self):
|
||||
for d in self.get("items"):
|
||||
lc_voucher_amount = frappe.db.sql("""select sum(ifnull(applicable_charges, 0))
|
||||
from `tabLanded Cost Item`
|
||||
where docstatus = 1 and purchase_receipt_item = %s""", d.name)
|
||||
d.landed_cost_voucher_amount = lc_voucher_amount[0][0] if lc_voucher_amount else 0.0
|
||||
|
||||
def validate_purchase_return(self):
|
||||
for d in self.get("items"):
|
||||
print flt(d.rejected_qty)
|
||||
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"):
|
||||
@@ -108,7 +118,7 @@ class PurchaseReceipt(BuyingController):
|
||||
self.validate_rate_with_reference_doc([["Purchase Order", "prevdoc_docname", "prevdoc_detail_docname"]])
|
||||
|
||||
def po_required(self):
|
||||
if frappe.db.get_value("Buying Settings", None, "po_required") == 'Yes':
|
||||
if not self.is_return and frappe.db.get_value("Buying Settings", None, "po_required") == 'Yes':
|
||||
for d in self.get('items'):
|
||||
if not d.prevdoc_docname:
|
||||
frappe.throw(_("Purchase Order number required for Item {0}").format(d.item_code))
|
||||
@@ -123,11 +133,20 @@ class PurchaseReceipt(BuyingController):
|
||||
|
||||
if pr_qty:
|
||||
val_rate_db_precision = 6 if cint(self.precision("valuation_rate", d)) <= 6 else 9
|
||||
sl_entries.append(self.get_sl_entries(d, {
|
||||
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(),
|
||||
"incoming_rate": flt(d.valuation_rate, val_rate_db_precision)
|
||||
}))
|
||||
"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, {
|
||||
@@ -176,7 +195,6 @@ class PurchaseReceipt(BuyingController):
|
||||
"item_code": d.rm_item_code,
|
||||
"warehouse": self.supplier_warehouse,
|
||||
"actual_qty": -1*flt(d.consumed_qty),
|
||||
"incoming_rate": 0
|
||||
}))
|
||||
|
||||
def validate_inspection(self):
|
||||
@@ -207,17 +225,16 @@ class PurchaseReceipt(BuyingController):
|
||||
# Set status as Submitted
|
||||
frappe.db.set(self, 'status', 'Submitted')
|
||||
|
||||
self.update_prevdoc_status()
|
||||
|
||||
self.update_ordered_qty()
|
||||
if not self.is_return:
|
||||
self.update_prevdoc_status()
|
||||
self.update_ordered_qty()
|
||||
purchase_controller.update_last_purchase_rate(self, 1)
|
||||
|
||||
self.update_stock_ledger()
|
||||
|
||||
from erpnext.stock.doctype.serial_no.serial_no import update_serial_nos_after_submit
|
||||
update_serial_nos_after_submit(self, "items")
|
||||
|
||||
purchase_controller.update_last_purchase_rate(self, 1)
|
||||
|
||||
self.make_gl_entries()
|
||||
|
||||
def check_next_docstatus(self):
|
||||
@@ -244,12 +261,13 @@ class PurchaseReceipt(BuyingController):
|
||||
|
||||
self.update_stock_ledger()
|
||||
|
||||
self.update_prevdoc_status()
|
||||
if not self.is_return:
|
||||
self.update_prevdoc_status()
|
||||
|
||||
# Must be called after updating received qty in PO
|
||||
self.update_ordered_qty()
|
||||
# Must be called after updating received qty in PO
|
||||
self.update_ordered_qty()
|
||||
|
||||
pc_obj.update_last_purchase_rate(self, 0)
|
||||
pc_obj.update_last_purchase_rate(self, 0)
|
||||
|
||||
self.make_gl_entries_on_cancel()
|
||||
|
||||
@@ -417,7 +435,7 @@ def make_purchase_invoice(source_name, target_doc=None):
|
||||
"doctype": "Purchase Invoice",
|
||||
"validation": {
|
||||
"docstatus": ["=", 1],
|
||||
}
|
||||
},
|
||||
},
|
||||
"Purchase Receipt Item": {
|
||||
"doctype": "Purchase Invoice Item",
|
||||
@@ -449,3 +467,8 @@ def get_invoiced_qty_map(purchase_receipt):
|
||||
invoiced_qty_map[pr_detail] += qty
|
||||
|
||||
return invoiced_qty_map
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_purchase_return(source_name, target_doc=None):
|
||||
from erpnext.utilities.transaction_base import make_return_doc
|
||||
return make_return_doc("Purchase Receipt", source_name, target_doc)
|
||||
Reference in New Issue
Block a user