refactor: backport old subcontracting code

This commit is contained in:
s-aga-r
2022-06-18 15:46:59 +05:30
parent ca24b5287e
commit 6d89b2fa28
41 changed files with 1047 additions and 459 deletions

View File

@@ -24,7 +24,8 @@ frappe.ui.form.on('Subcontracting Order', {
return {
filters: {
docstatus: 1,
is_subcontracted: 1
is_subcontracted: 1,
is_old_subcontracting_flow: 0
}
};
});
@@ -115,10 +116,14 @@ frappe.ui.form.on('Subcontracting Order', {
if (sco_rm_details && sco_rm_details.length) {
frm.add_custom_button(__('Return of Components'), () => {
frm.call({
method: 'erpnext.subcontracting.doctype.subcontracting_order.subcontracting_order.get_materials_from_supplier',
method: 'erpnext.controllers.subcontracting_controller.get_materials_from_supplier',
freeze: true,
freeze_message: __('Creating Stock Entry'),
args: { subcontracting_order: frm.doc.name, sco_rm_details: sco_rm_details },
args: {
subcontract_order: frm.doc.name,
rm_details: sco_rm_details,
order_doctype: cur_frm.doc.doctype
},
callback: function (r) {
if (r && r.message) {
const doc = frappe.model.sync(r.message);
@@ -306,10 +311,11 @@ erpnext.buying.SubcontractingOrderController = class SubcontractingOrderControll
make_rm_stock_entry(rm_items) {
frappe.call({
method: 'erpnext.subcontracting.doctype.subcontracting_order.subcontracting_order.make_rm_stock_entry',
method: 'erpnext.controllers.subcontracting_controller.make_rm_stock_entry',
args: {
subcontracting_order: cur_frm.doc.name,
rm_items: rm_items
subcontract_order: cur_frm.doc.name,
rm_items: rm_items,
order_doctype: cur_frm.doc.doctype
},
callback: (r) => {
var doclist = frappe.model.sync(r.message);

View File

@@ -1,8 +1,6 @@
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
import json
import frappe
from frappe import _
from frappe.model.mapper import get_mapped_doc
@@ -42,6 +40,9 @@ class SubcontractingOrder(SubcontractingController):
if not po.is_subcontracted:
frappe.throw(_("Please select a valid Purchase Order that is configured for Subcontracting."))
if po.is_old_subcontracting_flow:
frappe.throw(_("Please select a valid Purchase Order that has Service Items."))
if po.docstatus != 1:
msg = f"Please submit Purchase Order {po.name} before proceeding."
frappe.throw(_(msg))
@@ -227,143 +228,6 @@ def get_mapped_subcontracting_receipt(source_name, target_doc=None):
return target_doc
def get_item_details(items):
item = frappe.qb.DocType("Item")
item_list = (
frappe.qb.from_(item)
.select(item.item_code, item.description, item.allow_alternative_item)
.where(item.name.isin(items))
.run(as_dict=True)
)
item_details = {}
for item in item_list:
item_details[item.item_code] = item
return item_details
@frappe.whitelist()
def make_rm_stock_entry(subcontracting_order, rm_items):
rm_items_list = rm_items
if isinstance(rm_items, str):
rm_items_list = json.loads(rm_items)
elif not rm_items:
frappe.throw(_("No Items available for transfer"))
if rm_items_list:
fg_items = list(set(item["item_code"] for item in rm_items_list))
else:
frappe.throw(_("No Items selected for transfer"))
if subcontracting_order:
subcontracting_order = frappe.get_doc("Subcontracting Order", subcontracting_order)
if fg_items:
items = tuple(set(item["rm_item_code"] for item in rm_items_list))
item_wh = get_item_details(items)
stock_entry = frappe.new_doc("Stock Entry")
stock_entry.purpose = "Send to Subcontractor"
stock_entry.subcontracting_order = subcontracting_order.name
stock_entry.supplier = subcontracting_order.supplier
stock_entry.supplier_name = subcontracting_order.supplier_name
stock_entry.supplier_address = subcontracting_order.supplier_address
stock_entry.address_display = subcontracting_order.address_display
stock_entry.company = subcontracting_order.company
stock_entry.to_warehouse = subcontracting_order.supplier_warehouse
stock_entry.set_stock_entry_type()
for item_code in fg_items:
for rm_item_data in rm_items_list:
if rm_item_data["item_code"] == item_code:
rm_item_code = rm_item_data["rm_item_code"]
items_dict = {
rm_item_code: {
"sco_rm_detail": rm_item_data.get("name"),
"item_name": rm_item_data["item_name"],
"description": item_wh.get(rm_item_code, {}).get("description", ""),
"qty": rm_item_data["qty"],
"from_warehouse": rm_item_data["warehouse"],
"stock_uom": rm_item_data["stock_uom"],
"serial_no": rm_item_data.get("serial_no"),
"batch_no": rm_item_data.get("batch_no"),
"main_item_code": rm_item_data["item_code"],
"allow_alternative_item": item_wh.get(rm_item_code, {}).get("allow_alternative_item"),
}
}
stock_entry.add_to_stock_entry_detail(items_dict)
return stock_entry.as_dict()
else:
frappe.throw(_("No Items selected for transfer"))
return subcontracting_order.name
def add_items_in_ste(ste_doc, row, qty, sco_rm_details, batch_no=None):
item = ste_doc.append("items", row.item_details)
sco_rm_detail = list(set(row.sco_rm_details).intersection(sco_rm_details))
item.update(
{
"qty": qty,
"batch_no": batch_no,
"basic_rate": row.item_details["rate"],
"sco_rm_detail": sco_rm_detail[0] if sco_rm_detail else "",
"s_warehouse": row.item_details["t_warehouse"],
"t_warehouse": row.item_details["s_warehouse"],
"item_code": row.item_details["rm_item_code"],
"subcontracted_item": row.item_details["main_item_code"],
"serial_no": "\n".join(row.serial_no) if row.serial_no else "",
}
)
def make_return_stock_entry_for_subcontract(available_materials, sco_doc, sco_rm_details):
ste_doc = frappe.new_doc("Stock Entry")
ste_doc.purpose = "Material Transfer"
ste_doc.subcontracting_order = sco_doc.name
ste_doc.company = sco_doc.company
ste_doc.is_return = 1
for key, value in available_materials.items():
if not value.qty:
continue
if value.batch_no:
for batch_no, qty in value.batch_no.items():
if qty > 0:
add_items_in_ste(ste_doc, value, value.qty, sco_rm_details, batch_no)
else:
add_items_in_ste(ste_doc, value, value.qty, sco_rm_details)
ste_doc.set_stock_entry_type()
ste_doc.calculate_rate_and_amount()
return ste_doc
@frappe.whitelist()
def get_materials_from_supplier(subcontracting_order, sco_rm_details):
if isinstance(sco_rm_details, str):
sco_rm_details = json.loads(sco_rm_details)
doc = frappe.get_cached_doc("Subcontracting Order", subcontracting_order)
doc.initialized_fields()
doc.subcontracting_orders = [doc.name]
doc.get_available_materials()
if not doc.available_materials:
frappe.throw(
_("Materials are already received against the Subcontracting Order {0}").format(
subcontracting_order
)
)
return make_return_stock_entry_for_subcontract(doc.available_materials, doc, sco_rm_details)
@frappe.whitelist()
def update_subcontracting_order_status(sco):
if isinstance(sco, str):

View File

@@ -7,6 +7,7 @@ import frappe
from frappe.tests.utils import FrappeTestCase
from erpnext.buying.doctype.purchase_order.purchase_order import get_mapped_subcontracting_order
from erpnext.controllers.subcontracting_controller import make_rm_stock_entry
from erpnext.controllers.tests.test_subcontracting_controller import (
get_rm_items,
get_subcontracting_order,
@@ -22,7 +23,6 @@ from erpnext.controllers.tests.test_subcontracting_controller import (
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
from erpnext.subcontracting.doctype.subcontracting_order.subcontracting_order import (
make_rm_stock_entry,
make_subcontracting_receipt,
)

View File

@@ -3,7 +3,7 @@
import frappe
from frappe import _
from frappe.utils import cint, flt, getdate, nowdate
from frappe.utils import cint, getdate, nowdate
from erpnext.controllers.subcontracting_controller import SubcontractingController
@@ -78,7 +78,7 @@ class SubcontractingReceipt(SubcontractingController):
self.update_status_updater_args()
self.update_prevdoc_status()
self.set_subcontracting_order_status()
self.set_consumed_qty_in_sco()
self.set_consumed_qty_in_subcontract_order()
self.update_stock_ledger()
from erpnext.stock.doctype.serial_no.serial_no import update_serial_nos_after_submit
@@ -97,7 +97,7 @@ class SubcontractingReceipt(SubcontractingController):
self.make_gl_entries_on_cancel()
self.repost_future_sle_and_gle()
self.delete_auto_created_batches()
self.set_consumed_qty_in_sco()
self.set_consumed_qty_in_subcontract_order()
self.set_subcontracting_order_status()
self.update_status()
@@ -162,17 +162,6 @@ class SubcontractingReceipt(SubcontractingController):
if not item.expense_account:
item.expense_account = expense_account
@frappe.whitelist()
def get_current_stock(self):
for item in self.get("supplied_items"):
if self.supplier_warehouse:
actual_qty = frappe.db.get_value(
"Bin",
{"item_code": item.rm_item_code, "warehouse": self.supplier_warehouse},
"actual_qty",
)
item.current_stock = flt(actual_qty) or 0
def update_status(self, status=None, update_modified=False):
if self.docstatus >= 1 and not status:
if self.docstatus == 1:

View File

@@ -119,7 +119,7 @@ class TestSubcontractingReceipt(FrappeTestCase):
receive more than the required qty in the SCO.
Expected Result: Error Raised for Over Receipt against SCO.
"""
from erpnext.subcontracting.doctype.subcontracting_order.subcontracting_order import (
from erpnext.controllers.subcontracting_controller import (
make_rm_stock_entry as make_subcontract_transfer_entry,
)
from erpnext.subcontracting.doctype.subcontracting_order.subcontracting_order import (
@@ -188,8 +188,8 @@ class TestSubcontractingReceipt(FrappeTestCase):
self.assertRaises(frappe.ValidationError, scr2.submit)
def test_subcontracted_scr_for_multi_transfer_batches(self):
from erpnext.controllers.subcontracting_controller import make_rm_stock_entry
from erpnext.subcontracting.doctype.subcontracting_order.subcontracting_order import (
make_rm_stock_entry,
make_subcontracting_receipt,
)