diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 71e9c420c0..1e02415beb 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -35,6 +35,25 @@ class PurchaseInvoice(BuyingController): 'percent_join_field': 'purchase_order', 'overflow_type': 'billing' }] + + self.prev_link_mapper = { + "Purchase Order": { + "fieldname": "purchase_order", + "doctype": "Purchase Invoice Item", + "filters": [ + ["Purchase Invoice Item", "parent", "=", self.name], + ["Purchase Invoice Item", "purchase_order", "!=", ""] + ] + }, + "Purchase Receipt": { + "fieldname": "purchase_receipt", + "doctype": "Purchase Invoice Item", + "filters": [ + ["Purchase Invoice Item", "parent", "=", self.item], + ["Purchase Invoice Item", "purchase_receipt", "!=", ""] + ] + } + } def validate(self): if not self.is_opening: diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 8f7c3411e5..2f1ecf1e43 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -38,6 +38,25 @@ class SalesInvoice(SellingController): 'keyword': 'Billed', 'overflow_type': 'billing' }] + + self.prev_link_mapper = { + "Sales Order": { + "fieldname": "sales_order", + "doctype": "Sales Invoice Item", + "filters": [ + ["Sales Invoice Item", "parent", "=", self.name], + ["Sales Invoice Item", "sales_order", "!=", ""] + ] + }, + "Delivery Note": { + "fieldname": "delivery_note", + "doctype": "Sales Invoice Item", + "filters": [ + ["Sales Invoice Item", "parent", "=", self.name], + ["Sales Invoice Item", "delivery_note", "!=", ""] + ] + } + } def set_indicator(self): """Set indicator for portal""" diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 61842363c3..d4b2221095 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -32,6 +32,17 @@ class PurchaseOrder(BuyingController): 'percent_join_field': 'prevdoc_docname', 'overflow_type': 'order' }] + + self.prev_link_mapper = { + "Supplier Quotation": { + "fieldname": "supplier_quotation", + "doctype": "Purchase Order Item", + "filters": [ + ["Purchase Order Item", "parent", "=", self.name], + ["Purchase Order Item", "supplier_quotation", "!=", ""] + ] + } + } def validate(self): super(PurchaseOrder, self).validate() diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 2e0a272ae5..8103756cfd 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -21,6 +21,20 @@ form_grid_templates = { class WarehouseRequired(frappe.ValidationError): pass class SalesOrder(SellingController): + def __init__(self, arg1, arg2=None): + super(SalesOrder, self).__init__(arg1, arg2) + + self.prev_link_mapper = { + "Quotation": { + "fieldname": "prevdoc_docname", + "doctype": "Sales Order Item", + "filters": [ + ["Sales Order Item", "parent", "=", self.name], + ["Sales Order Item", "prevdoc_docname", "!=", ""] + ] + } + } + def validate(self): super(SalesOrder, self).validate() @@ -306,7 +320,7 @@ class SalesOrder(SellingController): mcount = month_map[reference_doc.recurring_type] self.set("delivery_date", get_next_date(reference_doc.delivery_date, mcount, cint(reference_doc.repeat_on_day_of_month))) - + def get_list_context(context=None): from erpnext.controllers.website_list_for_contact import get_list_context list_context = get_list_context(context) diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 6c6a3b3c97..d8defc0d4d 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -60,7 +60,19 @@ class DeliveryNote(SellingController): 'source_field': '-1 * qty', 'extra_cond': """ and exists (select name from `tabDelivery Note` where name=`tabDelivery Note Item`.parent and is_return=1)""" }] + + self.prev_link_mapper = { + "Sales Order": { + "fieldname": "against_sales_order", + "doctype": "Delivery Note Item", + "filters": [ + ["Delivery Note Item", "parent", "=", self.name], + ["Delivery Note Item", "against_sales_order", "!=", ""] + ] + } + } + def before_print(self): def toggle_print_hide(meta, fieldname): df = meta.get_field(fieldname) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 70cef3603a..6c72d6bf99 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -45,6 +45,17 @@ class PurchaseReceipt(BuyingController): # 'overflow_type': 'receipt', 'extra_cond': """ and exists (select name from `tabPurchase Receipt` where name=`tabPurchase Receipt Item`.parent and is_return=1)""" }] + + self.prev_link_mapper = { + "Purchase Order": { + "fieldname": "prevdoc_docname", + "doctype": "Purchase Receipt Item", + "filters": [ + ["Purchase Receipt Item", "parent", "=", self.name], + ["Purchase Receipt Item", "prevdoc_docname", "!=", ""] + ] + } + } def validate(self): super(PurchaseReceipt, self).validate() diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py index d088f599ad..3cc79ef713 100644 --- a/erpnext/utilities/transaction_base.py +++ b/erpnext/utilities/transaction_base.py @@ -107,6 +107,24 @@ class TransactionBase(StatusUpdater): frappe.throw(_("Row #{0}: Rate must be same as {1}: {2} ({3} / {4}) ") .format(d.idx, ref_dt, d.get(ref_dn_field), d.rate, ref_rate)) + def get_link_filters(self, for_doctype): + if hasattr(self, "prev_link_mapper") and self.prev_link_mapper.get(for_doctype): + fieldname = self.prev_link_mapper[for_doctype]["fieldname"] + + values = filter(None, tuple([item.as_dict()[fieldname] for item in self.items])) + + if values: + ret = { + for_doctype : { + "filters": [[for_doctype, "name", "in", values]] + } + } + else: + ret = None + else: + ret = None + + return ret def delete_events(ref_type, ref_name): frappe.delete_doc("Event", frappe.db.sql_list("""select name from `tabEvent`