From aef2c241f9fcc4469f5e84fb632d34099ccaf6ce Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 22 Nov 2023 16:07:00 +0530 Subject: [PATCH 01/24] feat: add field `Action on Purchase Order Submission` --- .../buying_settings/buying_settings.json | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json index 3297aad23a4..e166a7db036 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.json +++ b/erpnext/buying/doctype/buying_settings/buying_settings.json @@ -28,7 +28,9 @@ "subcontract", "backflush_raw_materials_of_subcontract_based_on", "column_break_11", - "over_transfer_allowance" + "over_transfer_allowance", + "section_break_xcug", + "purchase_order_submit_action" ], "fields": [ { @@ -168,12 +170,14 @@ "label": "Blanket Order Allowance (%)" }, { - "default": "Each Transaction", - "description": "How often should Project be updated of Total Purchase Cost ?", - "fieldname": "project_update_frequency", + "fieldname": "section_break_xcug", + "fieldtype": "Section Break" + }, + { + "fieldname": "purchase_order_submit_action", "fieldtype": "Select", - "label": "Update frequency of Project", - "options": "Each Transaction\nManual" + "label": "Purchase Order Submit Action", + "options": "\nCreate Subcontracting Order\nCreate and Submit Subcontracting Order" } ], "icon": "fa fa-cog", @@ -181,7 +185,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-11-24 10:55:51.287327", + "modified": "2023-11-22 16:05:33.262940", "modified_by": "Administrator", "module": "Buying", "name": "Buying Settings", -- GitLab From 547944554f3466f58cf2fbe90d304c1b9f239d62 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 22 Nov 2023 17:06:19 +0530 Subject: [PATCH 02/24] feat: auto create SCO on PO submission --- .../buying_settings/buying_settings.json | 8 +++--- .../doctype/purchase_order/purchase_order.py | 26 +++++++++++++++++-- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json index e166a7db036..2a9cfba7f56 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.json +++ b/erpnext/buying/doctype/buying_settings/buying_settings.json @@ -30,7 +30,7 @@ "column_break_11", "over_transfer_allowance", "section_break_xcug", - "purchase_order_submit_action" + "action_on_purchase_order_submission" ], "fields": [ { @@ -174,9 +174,9 @@ "fieldtype": "Section Break" }, { - "fieldname": "purchase_order_submit_action", + "fieldname": "action_on_purchase_order_submission", "fieldtype": "Select", - "label": "Purchase Order Submit Action", + "label": "Action on Purchase Order Submission", "options": "\nCreate Subcontracting Order\nCreate and Submit Subcontracting Order" } ], @@ -185,7 +185,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-11-22 16:05:33.262940", + "modified": "2023-11-22 17:42:28.978582", "modified_by": "Administrator", "module": "Buying", "name": "Buying Settings", diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 0438591c66e..424ee916c5a 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -358,6 +358,8 @@ class PurchaseOrder(BuyingController): update_linked_doc(self.doctype, self.name, self.inter_company_order_reference) + self.auto_create_subcontracting_order() + def on_cancel(self): self.ignore_linked_doctypes = ("GL Entry", "Payment Ledger Entry") super(PurchaseOrder, self).on_cancel() @@ -486,6 +488,16 @@ class PurchaseOrder(BuyingController): return result + def auto_create_subcontracting_order(self): + if self.is_subcontracted and not self.is_old_subcontracting_flow: + if action := frappe.db.get_single_value( + "Buying Settings", "action_on_purchase_order_submission" + ): + if action == "Create Subcontracting Order": + make_subcontracting_order(self.name, save=True) + elif action == "Create and Submit Subcontracting Order": + make_subcontracting_order(self.name, submit=True) + def item_last_purchase_rate(name, conversion_rate, item_code, conversion_factor=1.0): """get last purchase rate for an item""" @@ -703,8 +715,18 @@ def make_inter_company_sales_order(source_name, target_doc=None): @frappe.whitelist() -def make_subcontracting_order(source_name, target_doc=None): - return get_mapped_subcontracting_order(source_name, target_doc) +def make_subcontracting_order(source_name, target_doc=None, save=False, submit=False): + target_doc = get_mapped_subcontracting_order(source_name, target_doc) + + if (save or submit) and frappe.has_permission(target_doc.doctype, "create"): + target_doc.save() + if submit and frappe.has_permission(target_doc.doctype, "submit", target_doc): + try: + target_doc.submit() + except Exception as e: + target_doc.add_comment("Comment", _("Submit Action Failed") + "

" + str(e)) + + return target_doc def get_mapped_subcontracting_order(source_name, target_doc=None): -- GitLab From c9ac8ef6c9e06af6e211b44bee32c92f1cf0a7d1 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 22 Nov 2023 17:47:49 +0530 Subject: [PATCH 03/24] feat: add field `Action on Subcontracting Receipt Submission` --- .../doctype/buying_settings/buying_settings.json | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json index 2a9cfba7f56..9d5cf23cc6e 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.json +++ b/erpnext/buying/doctype/buying_settings/buying_settings.json @@ -30,7 +30,9 @@ "column_break_11", "over_transfer_allowance", "section_break_xcug", - "action_on_purchase_order_submission" + "action_on_purchase_order_submission", + "column_break_izrr", + "action_on_subcontracting_receipt_submission" ], "fields": [ { @@ -178,6 +180,16 @@ "fieldtype": "Select", "label": "Action on Purchase Order Submission", "options": "\nCreate Subcontracting Order\nCreate and Submit Subcontracting Order" + }, + { + "fieldname": "column_break_izrr", + "fieldtype": "Column Break" + }, + { + "fieldname": "action_on_subcontracting_receipt_submission", + "fieldtype": "Select", + "label": "Action on Subcontracting Receipt Submission", + "options": "\nCreate Purchase Receipt\nCreate and Submit Purchase Receipt" } ], "icon": "fa fa-cog", @@ -185,7 +197,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-11-22 17:42:28.978582", + "modified": "2023-11-22 17:46:26.474708", "modified_by": "Administrator", "module": "Buying", "name": "Buying Settings", -- GitLab From 219e52d87562bd9609b78d3c8555bcc3ee7daf4a Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 23 Nov 2023 11:40:46 +0530 Subject: [PATCH 04/24] chore: notify user on SCO creation --- .../doctype/purchase_order/purchase_order.py | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 424ee916c5a..224a585e444 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -8,7 +8,7 @@ import frappe from frappe import _, msgprint from frappe.desk.notifications import clear_doctype_notifications from frappe.model.mapper import get_mapped_doc -from frappe.utils import cint, cstr, flt +from frappe.utils import cint, cstr, flt, get_link_to_form from erpnext.accounts.doctype.sales_invoice.sales_invoice import ( unlink_inter_company_doc, @@ -494,9 +494,9 @@ class PurchaseOrder(BuyingController): "Buying Settings", "action_on_purchase_order_submission" ): if action == "Create Subcontracting Order": - make_subcontracting_order(self.name, save=True) + make_subcontracting_order(self.name, save=True, notify=True) elif action == "Create and Submit Subcontracting Order": - make_subcontracting_order(self.name, submit=True) + make_subcontracting_order(self.name, submit=True, notify=True) def item_last_purchase_rate(name, conversion_rate, item_code, conversion_factor=1.0): @@ -715,17 +715,29 @@ def make_inter_company_sales_order(source_name, target_doc=None): @frappe.whitelist() -def make_subcontracting_order(source_name, target_doc=None, save=False, submit=False): +def make_subcontracting_order( + source_name, target_doc=None, save=False, submit=False, notify=False +): target_doc = get_mapped_subcontracting_order(source_name, target_doc) if (save or submit) and frappe.has_permission(target_doc.doctype, "create"): target_doc.save() + if submit and frappe.has_permission(target_doc.doctype, "submit", target_doc): try: target_doc.submit() except Exception as e: target_doc.add_comment("Comment", _("Submit Action Failed") + "

" + str(e)) + if notify: + frappe.msgprint( + _("Subcontracting Order {0} created.").format( + get_link_to_form(target_doc.doctype, target_doc.name) + ), + indicator="green", + alert=True, + ) + return target_doc -- GitLab From db75125e606356b7fa28fc8dbb264ab421c199ff Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 23 Nov 2023 13:39:49 +0530 Subject: [PATCH 05/24] feat: add field `Purchase Order Item` in SCO Service Item --- .../subcontracting_order_service_item.json | 270 +++++++++--------- 1 file changed, 140 insertions(+), 130 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.json b/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.json index f213313ef6b..2ca41da71e2 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.json +++ b/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.json @@ -1,131 +1,141 @@ { - "actions": [], - "autoname": "hash", - "creation": "2022-04-01 19:23:05.728354", - "doctype": "DocType", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "item_code", - "column_break_2", - "item_name", - "section_break_4", - "qty", - "column_break_6", - "rate", - "column_break_8", - "amount", - "section_break_10", - "fg_item", - "column_break_12", - "fg_item_qty" - ], - "fields": [ - { - "bold": 1, - "columns": 2, - "fieldname": "item_code", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Item Code", - "options": "Item", - "reqd": 1, - "search_index": 1 - }, - { - "fetch_from": "item_code.item_name", - "fieldname": "item_name", - "fieldtype": "Data", - "in_global_search": 1, - "in_list_view": 1, - "label": "Item Name", - "print_hide": 1, - "reqd": 1 - }, - { - "bold": 1, - "columns": 1, - "fieldname": "qty", - "fieldtype": "Float", - "in_list_view": 1, - "label": "Quantity", - "print_width": "60px", - "reqd": 1, - "width": "60px" - }, - { - "bold": 1, - "columns": 2, - "fetch_from": "item_code.standard_rate", - "fetch_if_empty": 1, - "fieldname": "rate", - "fieldtype": "Currency", - "in_list_view": 1, - "label": "Rate", - "options": "currency", - "reqd": 1 - }, - { - "columns": 2, - "fieldname": "amount", - "fieldtype": "Currency", - "in_list_view": 1, - "label": "Amount", - "options": "currency", - "read_only": 1, - "reqd": 1 - }, - { - "fieldname": "fg_item", - "fieldtype": "Link", - "label": "Finished Good Item", - "options": "Item", - "reqd": 1 - }, - { - "default": "1", - "fieldname": "fg_item_qty", - "fieldtype": "Float", - "label": "Finished Good Item Quantity", - "reqd": 1 - }, - { - "fieldname": "column_break_2", - "fieldtype": "Column Break" - }, - { - "fieldname": "section_break_4", - "fieldtype": "Section Break" - }, - { - "fieldname": "column_break_6", - "fieldtype": "Column Break" - }, - { - "fieldname": "column_break_8", - "fieldtype": "Column Break" - }, - { - "fieldname": "section_break_10", - "fieldtype": "Section Break" - }, - { - "fieldname": "column_break_12", - "fieldtype": "Column Break" - } - ], - "istable": 1, - "links": [], - "modified": "2022-04-07 11:43:43.094867", - "modified_by": "Administrator", - "module": "Subcontracting", - "name": "Subcontracting Order Service Item", - "naming_rule": "Random", - "owner": "Administrator", - "permissions": [], - "quick_entry": 1, - "search_fields": "item_name", - "sort_field": "modified", - "sort_order": "DESC", - "states": [] -} \ No newline at end of file + "actions": [], + "autoname": "hash", + "creation": "2022-04-01 19:23:05.728354", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "item_code", + "column_break_2", + "item_name", + "section_break_4", + "qty", + "column_break_6", + "rate", + "column_break_8", + "amount", + "section_break_10", + "fg_item", + "column_break_12", + "fg_item_qty", + "purchase_order_item" + ], + "fields": [ + { + "bold": 1, + "columns": 2, + "fieldname": "item_code", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Item Code", + "options": "Item", + "reqd": 1, + "search_index": 1 + }, + { + "fetch_from": "item_code.item_name", + "fieldname": "item_name", + "fieldtype": "Data", + "in_global_search": 1, + "in_list_view": 1, + "label": "Item Name", + "print_hide": 1, + "reqd": 1 + }, + { + "bold": 1, + "columns": 1, + "fieldname": "qty", + "fieldtype": "Float", + "in_list_view": 1, + "label": "Quantity", + "print_width": "60px", + "reqd": 1, + "width": "60px" + }, + { + "bold": 1, + "columns": 2, + "fetch_from": "item_code.standard_rate", + "fetch_if_empty": 1, + "fieldname": "rate", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Rate", + "options": "currency", + "reqd": 1 + }, + { + "columns": 2, + "fieldname": "amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Amount", + "options": "currency", + "read_only": 1, + "reqd": 1 + }, + { + "fieldname": "fg_item", + "fieldtype": "Link", + "label": "Finished Good Item", + "options": "Item", + "reqd": 1 + }, + { + "default": "1", + "fieldname": "fg_item_qty", + "fieldtype": "Float", + "label": "Finished Good Item Quantity", + "reqd": 1 + }, + { + "fieldname": "column_break_2", + "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_4", + "fieldtype": "Section Break" + }, + { + "fieldname": "column_break_6", + "fieldtype": "Column Break" + }, + { + "fieldname": "column_break_8", + "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_10", + "fieldtype": "Section Break" + }, + { + "fieldname": "column_break_12", + "fieldtype": "Column Break" + }, + { + "fieldname": "purchase_order_item", + "fieldtype": "Data", + "hidden": 1, + "label": "Purchase Order Item", + "no_copy": 1, + "read_only": 1, + "search_index": 1 + } + ], + "istable": 1, + "links": [], + "modified": "2023-11-23 17:05:04.561948", + "modified_by": "Administrator", + "module": "Subcontracting", + "name": "Subcontracting Order Service Item", + "naming_rule": "Random", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "search_fields": "item_name", + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} -- GitLab From 85ec9d19c76c5365ac305dafe9705db189c0b97b Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 23 Nov 2023 13:40:41 +0530 Subject: [PATCH 06/24] fix: hold PO item ref in SCO Service Item --- erpnext/buying/doctype/purchase_order/purchase_order.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 224a585e444..074af8e06f1 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -764,7 +764,9 @@ def get_mapped_subcontracting_order(source_name, target_doc=None): }, "Purchase Order Item": { "doctype": "Subcontracting Order Service Item", - "field_map": {}, + "field_map": { + "name": "purchase_order_item", + }, "field_no_map": [], }, }, -- GitLab From 93291331935fa0c071e858a6b6691a9c4bf11fc6 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 23 Nov 2023 16:59:42 +0530 Subject: [PATCH 07/24] feat: add field `Purchase Order Item` in SCO Item --- .../subcontracting_order/subcontracting_order.py | 13 +++++-------- .../subcontracting_order_item.json | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py index 70ca1c31f5c..fa840bc09e4 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py @@ -148,8 +148,6 @@ class SubcontractingOrder(SubcontractingController): stock_bin.update_reserved_qty_for_sub_contracting() def populate_items_table(self): - items = [] - for si in self.service_items: if si.fg_item: item = frappe.get_doc("Item", si.fg_item) @@ -159,7 +157,8 @@ class SubcontractingOrder(SubcontractingController): ) or item.default_bom ) - items.append( + self.append( + "items", { "item_code": item.item_code, "item_name": item.item_name, @@ -168,6 +167,7 @@ class SubcontractingOrder(SubcontractingController): "qty": si.fg_item_qty, "stock_uom": item.stock_uom, "bom": bom, + "purchase_order_item": si.purchase_order_item, }, ) else: @@ -176,11 +176,8 @@ class SubcontractingOrder(SubcontractingController): si.item_name or si.item_code ) ) - else: - for item in items: - self.append("items", item) - else: - self.set_missing_values() + + self.set_missing_values() def update_status(self, status=None, update_modified=True): if self.docstatus >= 1 and not status: diff --git a/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json b/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json index a5d2176575f..d1f21ba7c96 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json +++ b/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json @@ -45,7 +45,8 @@ "dimension_col_break", "project", "section_break_34", - "page_break" + "page_break", + "purchase_order_item" ], "fields": [ { @@ -332,13 +333,22 @@ "fieldtype": "Link", "label": "Project", "options": "Project" + }, + { + "fieldname": "purchase_order_item", + "fieldtype": "Data", + "hidden": 1, + "label": "Purchase Order Item", + "no_copy": 1, + "read_only": 1, + "search_index": 1 } ], "idx": 1, "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2023-11-14 18:38:37.640677", + "modified": "2023-11-23 16:56:22.182698", "modified_by": "Administrator", "module": "Subcontracting", "name": "Subcontracting Order Item", -- GitLab From 97f5980b1e9d783116251c6efb72f613e2295834 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 23 Nov 2023 17:48:34 +0530 Subject: [PATCH 08/24] fix: maintain PO and PO Item ref in SCR Item --- .../subcontracting_order.py | 8 +++--- .../subcontracting_receipt_item.json | 25 +++++++++++++++++-- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py index fa840bc09e4..2b0d71adbfb 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py @@ -219,9 +219,11 @@ def make_subcontracting_receipt(source_name, target_doc=None): def get_mapped_subcontracting_receipt(source_name, target_doc=None): - def update_item(obj, target, source_parent): - target.qty = flt(obj.qty) - flt(obj.received_qty) - target.amount = (flt(obj.qty) - flt(obj.received_qty)) * flt(obj.rate) + def update_item(source, target, source_parent): + target.purchase_order = source_parent.purchase_order + target.purchase_order_item = source.purchase_order_item + target.qty = flt(source.qty) - flt(source.received_qty) + target.amount = (flt(source.qty) - flt(source.received_qty)) * flt(source.rate) target_doc = get_mapped_doc( "Subcontracting Order", diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json b/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json index b9da2d54d18..cb00fc788e7 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json +++ b/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json @@ -63,7 +63,9 @@ "dimension_col_break", "project", "section_break_80", - "page_break" + "page_break", + "purchase_order", + "purchase_order_item" ], "fields": [ { @@ -517,12 +519,31 @@ "label": "Reference Name", "no_copy": 1, "read_only": 1 + }, + { + "fieldname": "purchase_order_item", + "fieldtype": "Data", + "hidden": 1, + "label": "Purchase Order Item", + "no_copy": 1, + "read_only": 1, + "search_index": 1 + }, + { + "fieldname": "purchase_order", + "fieldtype": "Link", + "hidden": 1, + "label": "Purchase Order", + "no_copy": 1, + "options": "Purchase Order", + "read_only": 1, + "search_index": 1 } ], "idx": 1, "istable": 1, "links": [], - "modified": "2023-11-14 18:38:26.459669", + "modified": "2023-11-23 17:38:55.134685", "modified_by": "Administrator", "module": "Subcontracting", "name": "Subcontracting Receipt Item", -- GitLab From e2e3ecff2dd0cbeaa0014d2e3d83c01ce08ce4f3 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 23 Nov 2023 22:16:27 +0530 Subject: [PATCH 09/24] feat: auto create PR on SCR submission --- .../subcontracting_receipt.py | 91 ++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index ae64cc632aa..6b8c97e8ec2 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -3,7 +3,8 @@ import frappe from frappe import _ -from frappe.utils import cint, flt, getdate, nowdate +from frappe.model.mapper import get_mapped_doc +from frappe.utils import cint, flt, get_link_to_form, getdate, nowdate import erpnext from erpnext.accounts.utils import get_account_currency @@ -80,6 +81,7 @@ class SubcontractingReceipt(SubcontractingController): self.make_gl_entries() self.repost_future_sle_and_gle() self.update_status() + self.auto_create_purchase_receipt() def on_update(self): for table_field in ["items", "supplied_items"]: @@ -528,9 +530,96 @@ class SubcontractingReceipt(SubcontractingController): + "\n".join(warehouse_with_no_account) ) + def auto_create_purchase_receipt(self): + if action := frappe.db.get_single_value( + "Buying Settings", "action_on_subcontracting_receipt_submission" + ): + if action == "Create Purchase Receipt": + make_purchase_receipt(self, save=True, notify=True) + elif action == "Create and Submit Purchase Receipt": + make_purchase_receipt(self, submit=True, notify=True) + @frappe.whitelist() def make_subcontract_return(source_name, target_doc=None): from erpnext.controllers.sales_and_purchase_return import make_return_doc return make_return_doc("Subcontracting Receipt", source_name, target_doc) + + +def make_purchase_receipt(subcontracting_receipt, save=False, submit=False, notify=False): + if isinstance(subcontracting_receipt, str): + subcontracting_receipt = frappe.get_doc("Subcontracting Receipt", subcontracting_receipt) + + if not subcontracting_receipt.is_return: + purchase_receipt = frappe.new_doc("Purchase Receipt") + purchase_receipt.is_subcontracted = 1 + purchase_receipt.is_old_subcontracting_flow = 0 + + purchase_receipt = get_mapped_doc( + "Subcontracting Receipt", + subcontracting_receipt.name, + { + "Subcontracting Receipt": { + "doctype": "Purchase Receipt", + "field_map": { + "posting_date": "posting_date", + "posting_time": "posting_time", + "supplier_warehouse": "supplier_warehouse", + }, + "field_no_map": ["total_qty", "total"], + }, + }, + purchase_receipt, + ignore_child_tables=True, + ) + + po_items_details = {} + for item in subcontracting_receipt.items: + if item.purchase_order and item.purchase_order_item: + if item.purchase_order not in po_items_details: + po_doc = frappe.get_doc("Purchase Order", item.purchase_order) + po_items_details[item.purchase_order] = {po_item.name: po_item for po_item in po_doc.items} + + if po_item := po_items_details[item.purchase_order].get(item.purchase_order_item): + conversion_factor = flt(po_item.qty) / flt(po_item.fg_item_qty) + item_row = { + "item_code": po_item.item_code, + "item_name": po_item.item_name, + "qty": item.qty * conversion_factor, + "rejected_qty": item.rejected_qty * conversion_factor, + "uom": po_item.uom, + "rate": po_item.rate, + "warehouse": item.warehouse, + "rejected_warehouse": item.rejected_warehouse, + "purchase_order": item.purchase_order, + "purchase_order_item": item.purchase_order_item, + } + purchase_receipt.append("items", item_row) + + if not purchase_receipt.items: + frappe.throw( + _("Purchase Order Item reference is missing in Subcontracting Receipt {0}").format( + subcontracting_receipt.name + ) + ) + + if (save or submit) and frappe.has_permission(purchase_receipt.doctype, "create"): + purchase_receipt.save() + + if submit and frappe.has_permission(purchase_receipt.doctype, "submit", purchase_receipt): + try: + purchase_receipt.submit() + except Exception as e: + purchase_receipt.add_comment("Comment", _("Submit Action Failed") + "

" + str(e)) + + if notify: + frappe.msgprint( + _("Purchase Receipt {0} created.").format( + get_link_to_form(purchase_receipt.doctype, purchase_receipt.name) + ), + indicator="green", + alert=True, + ) + + return purchase_receipt -- GitLab From 7598fcc4a6fd8b9cfcb7fe5d517148501f7e4d72 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Fri, 24 Nov 2023 12:09:09 +0530 Subject: [PATCH 10/24] feat: add `Purchase Order` link in SCR connections --- .../subcontracting_receipt_dashboard.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py index deb8342b833..f6e1356ed9a 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py @@ -9,11 +9,15 @@ def get_data(): }, "internal_links": { "Subcontracting Order": ["items", "subcontracting_order"], + "Purchase Order": ["items", "purchase_order"], "Project": ["items", "project"], "Quality Inspection": ["items", "quality_inspection"], }, "transactions": [ - {"label": _("Reference"), "items": ["Subcontracting Order", "Quality Inspection", "Project"]}, + { + "label": _("Reference"), + "items": ["Subcontracting Order", "Purchase Order", "Quality Inspection", "Project"], + }, {"label": _("Returns"), "items": ["Subcontracting Receipt"]}, ], } -- GitLab From 7f10910afafc740aa6b5fc62b618de717c563913 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Fri, 24 Nov 2023 12:14:38 +0530 Subject: [PATCH 11/24] feat: add `Subcontracting Receipt` link in PO connections --- .../doctype/purchase_order/purchase_order_dashboard.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py b/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py index 05b5a8e7b8c..36fe079fc98 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py @@ -22,7 +22,10 @@ def get_data(): "label": _("Reference"), "items": ["Material Request", "Supplier Quotation", "Project", "Auto Repeat"], }, - {"label": _("Sub-contracting"), "items": ["Subcontracting Order", "Stock Entry"]}, + { + "label": _("Sub-contracting"), + "items": ["Subcontracting Order", "Subcontracting Receipt", "Stock Entry"], + }, {"label": _("Internal"), "items": ["Sales Order"]}, ], } -- GitLab From e86deb85e3660868a4f0cb65a4e9d1f62f6d2407 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Fri, 24 Nov 2023 12:17:05 +0530 Subject: [PATCH 12/24] fix: dont show `View` button on cancelled SCR --- .../doctype/subcontracting_receipt/subcontracting_receipt.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js index fd6bc7d7825..e3788bc0298 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js @@ -24,7 +24,7 @@ frappe.ui.form.on('Subcontracting Receipt', { }, refresh: (frm) => { - if (frm.doc.docstatus > 0) { + if (frm.doc.docstatus === 1) { frm.add_custom_button(__('Stock Ledger'), () => { frappe.route_options = { voucher_no: frm.doc.name, -- GitLab From 9e15d7577fbde7f52e6f9b61a1a64ac3537fdb48 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 28 Nov 2023 13:02:27 +0530 Subject: [PATCH 13/24] fix: use checkbox instead of select field --- .../buying_settings/buying_settings.json | 28 ++++++++++--------- .../doctype/purchase_order/purchase_order.py | 9 ++---- .../subcontracting_receipt.py | 9 ++---- 3 files changed, 19 insertions(+), 27 deletions(-) diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json index 9d5cf23cc6e..4750f74c0e8 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.json +++ b/erpnext/buying/doctype/buying_settings/buying_settings.json @@ -30,9 +30,9 @@ "column_break_11", "over_transfer_allowance", "section_break_xcug", - "action_on_purchase_order_submission", + "auto_create_subcontracting_order", "column_break_izrr", - "action_on_subcontracting_receipt_submission" + "auto_create_purchase_receipt" ], "fields": [ { @@ -175,21 +175,23 @@ "fieldname": "section_break_xcug", "fieldtype": "Section Break" }, - { - "fieldname": "action_on_purchase_order_submission", - "fieldtype": "Select", - "label": "Action on Purchase Order Submission", - "options": "\nCreate Subcontracting Order\nCreate and Submit Subcontracting Order" - }, { "fieldname": "column_break_izrr", "fieldtype": "Column Break" }, { - "fieldname": "action_on_subcontracting_receipt_submission", - "fieldtype": "Select", - "label": "Action on Subcontracting Receipt Submission", - "options": "\nCreate Purchase Receipt\nCreate and Submit Purchase Receipt" + "default": "0", + "description": "Subcontracting Order (Draft) will be auto-created on submission of Purchase Order.", + "fieldname": "auto_create_subcontracting_order", + "fieldtype": "Check", + "label": "Auto Create Subcontracting Order" + }, + { + "default": "0", + "description": "Purchase Receipt (Draft) will be auto-created on submission of Subcontracting Receipt.", + "fieldname": "auto_create_purchase_receipt", + "fieldtype": "Check", + "label": "Auto Create Purchase Receipt" } ], "icon": "fa fa-cog", @@ -197,7 +199,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-11-22 17:46:26.474708", + "modified": "2023-11-28 13:01:18.403492", "modified_by": "Administrator", "module": "Buying", "name": "Buying Settings", diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 074af8e06f1..519b3cdec55 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -490,13 +490,8 @@ class PurchaseOrder(BuyingController): def auto_create_subcontracting_order(self): if self.is_subcontracted and not self.is_old_subcontracting_flow: - if action := frappe.db.get_single_value( - "Buying Settings", "action_on_purchase_order_submission" - ): - if action == "Create Subcontracting Order": - make_subcontracting_order(self.name, save=True, notify=True) - elif action == "Create and Submit Subcontracting Order": - make_subcontracting_order(self.name, submit=True, notify=True) + if frappe.db.get_single_value("Buying Settings", "auto_create_subcontracting_order"): + make_subcontracting_order(self.name, save=True, notify=True) def item_last_purchase_rate(name, conversion_rate, item_code, conversion_factor=1.0): diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 6b8c97e8ec2..021f96fe913 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -531,13 +531,8 @@ class SubcontractingReceipt(SubcontractingController): ) def auto_create_purchase_receipt(self): - if action := frappe.db.get_single_value( - "Buying Settings", "action_on_subcontracting_receipt_submission" - ): - if action == "Create Purchase Receipt": - make_purchase_receipt(self, save=True, notify=True) - elif action == "Create and Submit Purchase Receipt": - make_purchase_receipt(self, submit=True, notify=True) + if frappe.db.get_single_value("Buying Settings", "auto_create_purchase_receipt"): + make_purchase_receipt(self, save=True, notify=True) @frappe.whitelist() -- GitLab From d6b801db1cdf5e2729824281ccc220759d312cb1 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 28 Nov 2023 13:17:24 +0530 Subject: [PATCH 14/24] feat: Subcontracting Receipt ref in Purchase Receipt --- .../doctype/purchase_receipt/purchase_receipt.js | 8 ++++++++ .../doctype/purchase_receipt/purchase_receipt.json | 11 ++++++++++- .../subcontracting_receipt/subcontracting_receipt.py | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js index e1fedf702a0..a306f43d888 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js @@ -52,6 +52,14 @@ frappe.ui.form.on("Purchase Receipt", { } }); + frm.set_query("subcontracting_receipt", function() { + return { + filters: { + 'docstatus': 1, + 'supplier': frm.doc.supplier, + } + } + }); }, onload: function(frm) { erpnext.queries.setup_queries(frm, "Warehouse", function() { diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json index db198e4beb2..c745d187bf4 100755 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json @@ -16,6 +16,7 @@ "supplier", "supplier_name", "supplier_delivery_note", + "subcontracting_receipt", "column_break1", "posting_date", "posting_time", @@ -1236,13 +1237,21 @@ "fieldname": "named_place", "fieldtype": "Data", "label": "Named Place" + }, + { + "depends_on": "eval: (doc.is_subcontracted && !doc.is_old_subcontracting_flow)", + "fieldname": "subcontracting_receipt", + "fieldtype": "Link", + "label": "Subcontracting Receipt", + "options": "Subcontracting Receipt", + "search_index": 1 } ], "icon": "fa fa-truck", "idx": 261, "is_submittable": 1, "links": [], - "modified": "2023-10-01 21:00:44.556816", + "modified": "2023-11-28 13:14:15.243474", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt", diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 021f96fe913..3f6e2733b84 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -560,6 +560,7 @@ def make_purchase_receipt(subcontracting_receipt, save=False, submit=False, noti "field_map": { "posting_date": "posting_date", "posting_time": "posting_time", + "name": "subcontracting_receipt", "supplier_warehouse": "supplier_warehouse", }, "field_no_map": ["total_qty", "total"], -- GitLab From 4a80d6c42f0ab10b139cfa37cf04187218220188 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 28 Nov 2023 13:39:15 +0530 Subject: [PATCH 15/24] feat: SCR Item ref in PR Item --- .../purchase_receipt_item.json | 16 ++++++++++++++-- .../subcontracting_receipt.py | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json index a5c24958b72..f938fb18b2c 100644 --- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json +++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json @@ -127,7 +127,8 @@ "section_break_80", "page_break", "sales_order", - "sales_order_item" + "sales_order_item", + "subcontracting_receipt_item" ], "fields": [ { @@ -1087,12 +1088,23 @@ "print_hide": 1, "read_only": 1, "search_index": 1 + }, + { + "fieldname": "subcontracting_receipt_item", + "fieldtype": "Data", + "hidden": 1, + "label": "Subcontracting Receipt Item", + "no_copy": 1, + "print_hide": 1, + "read_only": 1, + "report_hide": 1, + "search_index": 1 } ], "idx": 1, "istable": 1, "links": [], - "modified": "2023-11-14 18:38:15.251994", + "modified": "2023-11-28 13:37:29.245204", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt Item", diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 3f6e2733b84..b83e58afde1 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -590,6 +590,7 @@ def make_purchase_receipt(subcontracting_receipt, save=False, submit=False, noti "rejected_warehouse": item.rejected_warehouse, "purchase_order": item.purchase_order, "purchase_order_item": item.purchase_order_item, + "subcontracting_receipt_item": item.name, } purchase_receipt.append("items", item_row) -- GitLab From 241c43759438a1d3a63821f93e58748e04022bd1 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 28 Nov 2023 16:28:54 +0530 Subject: [PATCH 16/24] feat: provision to create PR from SCR --- .../purchase_receipt/purchase_receipt.js | 14 ++++++ .../subcontracting_receipt.js | 47 +++++++++++-------- .../subcontracting_receipt.py | 46 +++++++++--------- .../subcontracting_receipt_dashboard.py | 2 +- 4 files changed, 68 insertions(+), 41 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js index a306f43d888..c869a6f1b59 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js @@ -133,6 +133,20 @@ frappe.ui.form.on("Purchase Receipt", { erpnext.accounts.dimensions.update_dimension(frm, frm.doctype); }, + subcontracting_receipt: (frm) => { + if (frm.doc.is_subcontracted === 1 && frm.doc.is_old_subcontracting_flow === 0 && frm.doc.subcontracting_receipt) { + frm.set_value('items', null); + + erpnext.utils.map_current_doc({ + method: 'erpnext.subcontracting.doctype.subcontracting_receipt.subcontracting_receipt.make_purchase_receipt', + source_name: frm.doc.subcontracting_receipt, + target_doc: frm, + freeze: true, + freeze_message: __('Mapping Purchase Receipt ...'), + }); + } + }, + toggle_display_account_head: function(frm) { var enabled = erpnext.is_perpetual_inventory_enabled(frm.doc.company) frm.fields_dict["items"].grid.set_column_disp(["cost_center"], enabled); diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js index e3788bc0298..6a69479f2b0 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js @@ -26,27 +26,36 @@ frappe.ui.form.on('Subcontracting Receipt', { refresh: (frm) => { if (frm.doc.docstatus === 1) { frm.add_custom_button(__('Stock Ledger'), () => { - frappe.route_options = { - voucher_no: frm.doc.name, - from_date: frm.doc.posting_date, - to_date: moment(frm.doc.modified).format('YYYY-MM-DD'), - company: frm.doc.company, - show_cancelled_entries: frm.doc.docstatus === 2 - } - frappe.set_route('query-report', 'Stock Ledger'); - }, __('View')); + frappe.route_options = { + voucher_no: frm.doc.name, + from_date: frm.doc.posting_date, + to_date: moment(frm.doc.modified).format('YYYY-MM-DD'), + company: frm.doc.company, + show_cancelled_entries: frm.doc.docstatus === 2 + } + frappe.set_route('query-report', 'Stock Ledger'); + }, __('View')); frm.add_custom_button(__('Accounting Ledger'), () => { - frappe.route_options = { - voucher_no: frm.doc.name, - from_date: frm.doc.posting_date, - to_date: moment(frm.doc.modified).format('YYYY-MM-DD'), - company: frm.doc.company, - group_by: 'Group by Voucher (Consolidated)', - show_cancelled_entries: frm.doc.docstatus === 2 - } - frappe.set_route('query-report', 'General Ledger'); - }, __('View')); + frappe.route_options = { + voucher_no: frm.doc.name, + from_date: frm.doc.posting_date, + to_date: moment(frm.doc.modified).format('YYYY-MM-DD'), + company: frm.doc.company, + group_by: 'Group by Voucher (Consolidated)', + show_cancelled_entries: frm.doc.docstatus === 2 + } + frappe.set_route('query-report', 'General Ledger'); + }, __('View')); + + frm.add_custom_button(__('Purchase Receipt'), () => { + frappe.model.open_mapped_doc({ + method: 'erpnext.subcontracting.doctype.subcontracting_receipt.subcontracting_receipt.make_purchase_receipt', + frm: frm, + freeze: true, + freeze_message: __('Creating Purchase Receipt ...') + }); + }, __('Create')); } if (!frm.doc.is_return && frm.doc.docstatus === 1 && frm.doc.per_returned < 100) { diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index b83e58afde1..53b79b1cdeb 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -542,18 +542,20 @@ def make_subcontract_return(source_name, target_doc=None): return make_return_doc("Subcontracting Receipt", source_name, target_doc) -def make_purchase_receipt(subcontracting_receipt, save=False, submit=False, notify=False): - if isinstance(subcontracting_receipt, str): - subcontracting_receipt = frappe.get_doc("Subcontracting Receipt", subcontracting_receipt) +@frappe.whitelist() +def make_purchase_receipt(source_name, target_doc=None, save=False, submit=False, notify=False): + if isinstance(source_name, str): + source_name = frappe.get_doc("Subcontracting Receipt", source_name) - if not subcontracting_receipt.is_return: - purchase_receipt = frappe.new_doc("Purchase Receipt") - purchase_receipt.is_subcontracted = 1 - purchase_receipt.is_old_subcontracting_flow = 0 + if not source_name.is_return: + if not target_doc: + target_doc = frappe.new_doc("Purchase Receipt") + target_doc.is_subcontracted = 1 + target_doc.is_old_subcontracting_flow = 0 - purchase_receipt = get_mapped_doc( + target_doc = get_mapped_doc( "Subcontracting Receipt", - subcontracting_receipt.name, + source_name.name, { "Subcontracting Receipt": { "doctype": "Purchase Receipt", @@ -566,12 +568,12 @@ def make_purchase_receipt(subcontracting_receipt, save=False, submit=False, noti "field_no_map": ["total_qty", "total"], }, }, - purchase_receipt, + target_doc, ignore_child_tables=True, ) po_items_details = {} - for item in subcontracting_receipt.items: + for item in source_name.items: if item.purchase_order and item.purchase_order_item: if item.purchase_order not in po_items_details: po_doc = frappe.get_doc("Purchase Order", item.purchase_order) @@ -592,31 +594,33 @@ def make_purchase_receipt(subcontracting_receipt, save=False, submit=False, noti "purchase_order_item": item.purchase_order_item, "subcontracting_receipt_item": item.name, } - purchase_receipt.append("items", item_row) + target_doc.append("items", item_row) - if not purchase_receipt.items: + if not target_doc.items: frappe.throw( _("Purchase Order Item reference is missing in Subcontracting Receipt {0}").format( - subcontracting_receipt.name + source_name.name ) ) - if (save or submit) and frappe.has_permission(purchase_receipt.doctype, "create"): - purchase_receipt.save() + target_doc.set_missing_values() + + if (save or submit) and frappe.has_permission(target_doc.doctype, "create"): + target_doc.save() - if submit and frappe.has_permission(purchase_receipt.doctype, "submit", purchase_receipt): + if submit and frappe.has_permission(target_doc.doctype, "submit", target_doc): try: - purchase_receipt.submit() + target_doc.submit() except Exception as e: - purchase_receipt.add_comment("Comment", _("Submit Action Failed") + "

" + str(e)) + target_doc.add_comment("Comment", _("Submit Action Failed") + "

" + str(e)) if notify: frappe.msgprint( _("Purchase Receipt {0} created.").format( - get_link_to_form(purchase_receipt.doctype, purchase_receipt.name) + get_link_to_form(target_doc.doctype, target_doc.name) ), indicator="green", alert=True, ) - return purchase_receipt + return target_doc diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py index f6e1356ed9a..4d15938e4b5 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py @@ -3,7 +3,7 @@ from frappe import _ def get_data(): return { - "fieldname": "subcontracting_receipt_no", + "fieldname": "subcontracting_receipt", "non_standard_fieldnames": { "Subcontracting Receipt": "return_against", }, -- GitLab From 3e3a736a67c5d73388f91e758f1204a0d94720ea Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 29 Nov 2023 12:46:31 +0530 Subject: [PATCH 17/24] chore: PR ref in SCR connections --- .../subcontracting_receipt/subcontracting_receipt.js | 4 ++++ .../subcontracting_receipt_dashboard.py | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js index 6a69479f2b0..08ead65d5ff 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js @@ -11,6 +11,10 @@ frappe.ui.form.on('Subcontracting Receipt', { frm.get_field('supplied_items').grid.cannot_add_rows = true; frm.get_field('supplied_items').grid.only_sortable(); frm.trigger('set_queries'); + + frm.custom_make_buttons = { + 'Purchase Receipt': 'Purchase Receipt', + } }, on_submit(frm) { diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py index 4d15938e4b5..6b67a1621a7 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py @@ -16,7 +16,13 @@ def get_data(): "transactions": [ { "label": _("Reference"), - "items": ["Subcontracting Order", "Purchase Order", "Quality Inspection", "Project"], + "items": [ + "Purchase Order", + "Purchase Receipt", + "Subcontracting Order", + "Quality Inspection", + "Project", + ], }, {"label": _("Returns"), "items": ["Subcontracting Receipt"]}, ], -- GitLab From 0dea8a290c7ca17d523712048e6b6a2099c68416 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 29 Nov 2023 13:07:39 +0530 Subject: [PATCH 18/24] fix: map warehouses in return SCR --- erpnext/controllers/sales_and_purchase_return.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index 9abe3c2bc84..8f79ae09efc 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -391,7 +391,10 @@ def make_return_doc( if doc.get("discount_amount"): doc.discount_amount = -1 * source.discount_amount - if doctype != "Subcontracting Receipt": + if doctype == "Subcontracting Receipt": + doc.set_warehouse = source.set_warehouse + doc.supplier_warehouse = source.supplier_warehouse + else: doc.run_method("calculate_taxes_and_totals") def update_item(source_doc, target_doc, source_parent): -- GitLab From 6f54d9c83b7dbc577462f2c19062d9c51792e92c Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 29 Nov 2023 13:21:24 +0530 Subject: [PATCH 19/24] fix(ux): hide `Create Purchase Receipt` button for Subcontract Return --- .../subcontracting_receipt.js | 68 ++++++++++--------- .../subcontracting_receipt.py | 12 ++-- 2 files changed, 42 insertions(+), 38 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js index 08ead65d5ff..575c4eda731 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js @@ -52,49 +52,51 @@ frappe.ui.form.on('Subcontracting Receipt', { frappe.set_route('query-report', 'General Ledger'); }, __('View')); - frm.add_custom_button(__('Purchase Receipt'), () => { - frappe.model.open_mapped_doc({ - method: 'erpnext.subcontracting.doctype.subcontracting_receipt.subcontracting_receipt.make_purchase_receipt', - frm: frm, - freeze: true, - freeze_message: __('Creating Purchase Receipt ...') - }); - }, __('Create')); + if (frm.doc.is_return === 0) { + frm.add_custom_button(__('Purchase Receipt'), () => { + frappe.model.open_mapped_doc({ + method: 'erpnext.subcontracting.doctype.subcontracting_receipt.subcontracting_receipt.make_purchase_receipt', + frm: frm, + freeze: true, + freeze_message: __('Creating Purchase Receipt ...') + }); + }, __('Create')); + } } if (!frm.doc.is_return && frm.doc.docstatus === 1 && frm.doc.per_returned < 100) { frm.add_custom_button(__('Subcontract Return'), () => { - frappe.model.open_mapped_doc({ - method: 'erpnext.subcontracting.doctype.subcontracting_receipt.subcontracting_receipt.make_subcontract_return', - frm: frm - }); - }, __('Create')); + frappe.model.open_mapped_doc({ + method: 'erpnext.subcontracting.doctype.subcontracting_receipt.subcontracting_receipt.make_subcontract_return', + frm: frm + }); + }, __('Create')); frm.page.set_inner_btn_group_as_primary(__('Create')); } if (frm.doc.docstatus === 0) { frm.add_custom_button(__('Subcontracting Order'), () => { - if (!frm.doc.supplier) { - frappe.throw({ - title: __('Mandatory'), - message: __('Please Select a Supplier') - }); - } - - erpnext.utils.map_current_doc({ - method: 'erpnext.subcontracting.doctype.subcontracting_order.subcontracting_order.make_subcontracting_receipt', - source_doctype: 'Subcontracting Order', - target: frm, - setters: { - supplier: frm.doc.supplier, - }, - get_query_filters: { - docstatus: 1, - per_received: ['<', 100], - company: frm.doc.company - } + if (!frm.doc.supplier) { + frappe.throw({ + title: __('Mandatory'), + message: __('Please Select a Supplier') }); - }, __('Get items from')); + } + + erpnext.utils.map_current_doc({ + method: 'erpnext.subcontracting.doctype.subcontracting_order.subcontracting_order.make_subcontracting_receipt', + source_doctype: 'Subcontracting Order', + target: frm, + setters: { + supplier: frm.doc.supplier, + }, + get_query_filters: { + docstatus: 1, + per_received: ['<', 100], + company: frm.doc.company + } + }); + }, __('Get Items From')); frm.fields_dict.supplied_items.grid.update_docfield_property('consumed_qty', 'read_only', frm.doc.__onload && frm.doc.__onload.backflush_based_on === 'BOM'); } diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 53b79b1cdeb..fbea01eae6e 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -545,9 +545,11 @@ def make_subcontract_return(source_name, target_doc=None): @frappe.whitelist() def make_purchase_receipt(source_name, target_doc=None, save=False, submit=False, notify=False): if isinstance(source_name, str): - source_name = frappe.get_doc("Subcontracting Receipt", source_name) + source_doc = frappe.get_doc("Subcontracting Receipt", source_name) + else: + source_doc = source_name - if not source_name.is_return: + if not source_doc.is_return: if not target_doc: target_doc = frappe.new_doc("Purchase Receipt") target_doc.is_subcontracted = 1 @@ -555,7 +557,7 @@ def make_purchase_receipt(source_name, target_doc=None, save=False, submit=False target_doc = get_mapped_doc( "Subcontracting Receipt", - source_name.name, + source_doc.name, { "Subcontracting Receipt": { "doctype": "Purchase Receipt", @@ -573,7 +575,7 @@ def make_purchase_receipt(source_name, target_doc=None, save=False, submit=False ) po_items_details = {} - for item in source_name.items: + for item in source_doc.items: if item.purchase_order and item.purchase_order_item: if item.purchase_order not in po_items_details: po_doc = frappe.get_doc("Purchase Order", item.purchase_order) @@ -599,7 +601,7 @@ def make_purchase_receipt(source_name, target_doc=None, save=False, submit=False if not target_doc.items: frappe.throw( _("Purchase Order Item reference is missing in Subcontracting Receipt {0}").format( - source_name.name + source_doc.name ) ) -- GitLab From 894f689485cfc69fa33ba9eaa6f50b17305ee099 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 29 Nov 2023 13:39:02 +0530 Subject: [PATCH 20/24] chore: `linter` --- .../subcontracting_order/subcontracting_order.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py index 2b0d71adbfb..6a658460da9 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py @@ -148,6 +148,8 @@ class SubcontractingOrder(SubcontractingController): stock_bin.update_reserved_qty_for_sub_contracting() def populate_items_table(self): + items = [] + for si in self.service_items: if si.fg_item: item = frappe.get_doc("Item", si.fg_item) @@ -157,8 +159,8 @@ class SubcontractingOrder(SubcontractingController): ) or item.default_bom ) - self.append( - "items", + + items.append( { "item_code": item.item_code, "item_name": item.item_name, @@ -168,7 +170,7 @@ class SubcontractingOrder(SubcontractingController): "stock_uom": item.stock_uom, "bom": bom, "purchase_order_item": si.purchase_order_item, - }, + } ) else: frappe.throw( @@ -177,6 +179,10 @@ class SubcontractingOrder(SubcontractingController): ) ) + if items: + for item in items: + self.append("items", item) + self.set_missing_values() def update_status(self, status=None, update_modified=True): -- GitLab From 93fb89c9f02dac3a007cfc157a87eb36f559d317 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 29 Nov 2023 13:58:21 +0530 Subject: [PATCH 21/24] test: auto create SCO on PO submit --- .../purchase_order/test_purchase_order.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index 1add731fe0c..d4589d307f1 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -983,6 +983,38 @@ class TestPurchaseOrder(FrappeTestCase): self.assertEqual(po.items[0].qty, 30) self.assertEqual(po.items[0].fg_item_qty, 30) + @change_settings("Buying Settings", {"auto_create_subcontracting_order": 1}) + def test_auto_create_subcontracting_order(self): + from erpnext.controllers.tests.test_subcontracting_controller import ( + make_bom_for_subcontracted_items, + make_raw_materials, + make_service_items, + make_subcontracted_items, + ) + + make_subcontracted_items() + make_raw_materials() + make_service_items() + make_bom_for_subcontracted_items() + + service_items = [ + { + "warehouse": "_Test Warehouse - _TC", + "item_code": "Subcontracted Service Item 7", + "qty": 10, + "rate": 100, + "fg_item": "Subcontracted Item SA7", + "fg_item_qty": 10, + }, + ] + po = create_purchase_order( + rm_items=service_items, + is_subcontracted=1, + supplier_warehouse="_Test Warehouse 1 - _TC", + ) + + self.assertTrue(frappe.db.get_value("Subcontracting Order", {"purchase_order": po.name})) + def prepare_data_for_internal_transfer(): from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier -- GitLab From 0ca7e63443efc51935ece0f1d70c54de443715ac Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 29 Nov 2023 14:10:48 +0530 Subject: [PATCH 22/24] test: auto create PR on SCR submit --- .../subcontracting_receipt.py | 4 +-- .../test_subcontracting_receipt.py | 29 ++++++++++++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index fbea01eae6e..825c2a5d678 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -586,8 +586,8 @@ def make_purchase_receipt(source_name, target_doc=None, save=False, submit=False item_row = { "item_code": po_item.item_code, "item_name": po_item.item_name, - "qty": item.qty * conversion_factor, - "rejected_qty": item.rejected_qty * conversion_factor, + "qty": flt(item.qty) * conversion_factor, + "rejected_qty": flt(item.rejected_qty) * conversion_factor, "uom": po_item.uom, "rate": po_item.rate, "warehouse": item.warehouse, diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py index 43ac8d6ace1..769a63d9c82 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py @@ -5,7 +5,7 @@ import copy import frappe -from frappe.tests.utils import FrappeTestCase +from frappe.tests.utils import FrappeTestCase, change_settings from frappe.utils import add_days, cint, cstr, flt, nowtime, today import erpnext @@ -952,6 +952,33 @@ class TestSubcontractingReceipt(FrappeTestCase): scr.submit() + @change_settings("Buying Settings", {"auto_create_purchase_receipt": 1}) + def test_auto_create_purchase_receipt(self): + fg_item = "Subcontracted Item SA1" + service_items = [ + { + "warehouse": "_Test Warehouse - _TC", + "item_code": "Subcontracted Service Item 1", + "qty": 5, + "rate": 100, + "fg_item": fg_item, + "fg_item_qty": 5, + }, + ] + sco = get_subcontracting_order(service_items=service_items) + rm_items = get_rm_items(sco.supplied_items) + itemwise_details = make_stock_in_entry(rm_items=rm_items) + make_stock_transfer_entry( + sco_no=sco.name, + rm_items=rm_items, + itemwise_details=copy.deepcopy(itemwise_details), + ) + scr = make_subcontracting_receipt(sco.name) + scr.save() + scr.submit() + + self.assertTrue(frappe.db.get_value("Purchase Receipt", {"subcontracting_receipt": scr.name})) + def make_return_subcontracting_receipt(**args): args = frappe._dict(args) -- GitLab From f4c1a63b0b3ade22ea0c28af0dd217da9203fee2 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 29 Nov 2023 17:35:21 +0530 Subject: [PATCH 23/24] fix(test): `test_auto_create_purchase_receipt` --- .../doctype/subcontracting_receipt/subcontracting_receipt.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 825c2a5d678..6df91297009 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -574,6 +574,8 @@ def make_purchase_receipt(source_name, target_doc=None, save=False, submit=False ignore_child_tables=True, ) + target_doc.currency = frappe.get_cached_value("Company", target_doc.company, "default_currency") + po_items_details = {} for item in source_doc.items: if item.purchase_order and item.purchase_order_item: @@ -586,6 +588,7 @@ def make_purchase_receipt(source_name, target_doc=None, save=False, submit=False item_row = { "item_code": po_item.item_code, "item_name": po_item.item_name, + "conversion_factor": conversion_factor, "qty": flt(item.qty) * conversion_factor, "rejected_qty": flt(item.rejected_qty) * conversion_factor, "uom": po_item.uom, -- GitLab From f29300bf71807e143481a3a85e9c8a625d0cb1a4 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 29 Nov 2023 17:57:11 +0530 Subject: [PATCH 24/24] Merge pull request #38290 from s-aga-r/FIX-36704 feat: auto create PR on SCR submission --- .../buying/doctype/buying_settings/buying_settings.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json index 4750f74c0e8..ea64b78fa36 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.json +++ b/erpnext/buying/doctype/buying_settings/buying_settings.json @@ -192,6 +192,14 @@ "fieldname": "auto_create_purchase_receipt", "fieldtype": "Check", "label": "Auto Create Purchase Receipt" + }, + { + "default": "Each Transaction", + "description": "How often should Project be updated of Total Purchase Cost ?", + "fieldname": "project_update_frequency", + "fieldtype": "Select", + "label": "Update frequency of Project", + "options": "Each Transaction\nManual" } ], "icon": "fa fa-cog", -- GitLab