Sales / Purchase Return redesigned via negative DN / SI / PR / PI

This commit is contained in:
Nabin Hait
2015-07-17 15:19:02 +05:30
parent ada485f096
commit 1d21842f68
24 changed files with 451 additions and 112 deletions

View File

@@ -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();

View File

@@ -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",

View File

@@ -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)

View File

@@ -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();

View File

@@ -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",

View File

@@ -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)