mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-25 21:05:19 +00:00
refactor(job_card): move mapping functions to mapper.py
This commit is contained in:
@@ -8,7 +8,6 @@ from typing import Any
|
||||
import frappe
|
||||
from frappe import _, bold
|
||||
from frappe.model.document import Document
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
from frappe.query_builder import Criterion
|
||||
from frappe.query_builder.functions import IfNull, Max, Min, Sum
|
||||
from frappe.utils import (
|
||||
@@ -37,6 +36,8 @@ from erpnext.subcontracting.doctype.subcontracting_bom.subcontracting_bom import
|
||||
get_subcontracting_boms_for_finished_goods,
|
||||
)
|
||||
|
||||
from .mapper import make_corrective_job_card, make_material_request, make_stock_entry, make_subcontracting_po
|
||||
|
||||
|
||||
class OverlapError(frappe.ValidationError):
|
||||
pass
|
||||
@@ -1547,49 +1548,6 @@ class JobCard(Document):
|
||||
return ste.stock_entry.as_dict()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_subcontracting_po(source_name: str, target_doc: Document | str | None = None):
|
||||
def set_missing_values(source, target):
|
||||
_item_details = get_subcontracting_boms_for_finished_goods(source.finished_good)
|
||||
|
||||
pending_qty = source.for_quantity - source.manufactured_qty
|
||||
service_item_qty = flt(_item_details.service_item_qty) or 1.0
|
||||
fg_item_qty = flt(_item_details.finished_good_qty) or 1.0
|
||||
|
||||
target.is_subcontracted = 1
|
||||
target.supplier_warehouse = source.wip_warehouse
|
||||
target.append(
|
||||
"items",
|
||||
{
|
||||
"item_code": _item_details.service_item,
|
||||
"fg_item": source.finished_good,
|
||||
"uom": _item_details.service_item_uom,
|
||||
"stock_uom": _item_details.service_item_uom,
|
||||
"conversion_factor": _item_details.conversion_factor or 1,
|
||||
"item_name": _item_details.service_item,
|
||||
"qty": pending_qty * service_item_qty / fg_item_qty,
|
||||
"fg_item_qty": pending_qty,
|
||||
"job_card": source.name,
|
||||
"bom": source.semi_fg_bom,
|
||||
"warehouse": source.target_warehouse,
|
||||
},
|
||||
)
|
||||
|
||||
doclist = get_mapped_doc(
|
||||
"Job Card",
|
||||
source_name,
|
||||
{
|
||||
"Job Card": {
|
||||
"doctype": "Purchase Order",
|
||||
},
|
||||
},
|
||||
target_doc,
|
||||
set_missing_values,
|
||||
)
|
||||
|
||||
return doclist
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_time_log(kwargs: str | dict):
|
||||
if isinstance(kwargs, str):
|
||||
@@ -1633,105 +1591,6 @@ def get_operations(doctype: str, txt: str, searchfield: str, start: int, page_le
|
||||
)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_material_request(source_name: str, target_doc: Document | str | None = None):
|
||||
def update_item(obj, target, source_parent):
|
||||
target.warehouse = source_parent.wip_warehouse
|
||||
|
||||
def set_missing_values(source, target):
|
||||
target.material_request_type = "Material Transfer"
|
||||
|
||||
doclist = get_mapped_doc(
|
||||
"Job Card",
|
||||
source_name,
|
||||
{
|
||||
"Job Card": {
|
||||
"doctype": "Material Request",
|
||||
"field_map": {
|
||||
"name": "job_card",
|
||||
},
|
||||
},
|
||||
"Job Card Item": {
|
||||
"doctype": "Material Request Item",
|
||||
"field_map": {"required_qty": "qty", "uom": "stock_uom", "name": "job_card_item"},
|
||||
"postprocess": update_item,
|
||||
},
|
||||
},
|
||||
target_doc,
|
||||
set_missing_values,
|
||||
)
|
||||
|
||||
return doclist
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_stock_entry(source_name: str, target_doc: Document | str | None = None):
|
||||
def update_item(source, target, source_parent):
|
||||
target.t_warehouse = source_parent.wip_warehouse
|
||||
|
||||
if not target.conversion_factor:
|
||||
target.conversion_factor = 1
|
||||
|
||||
pending_rm_qty = flt(source.required_qty) - flt(source.transferred_qty)
|
||||
if pending_rm_qty > 0:
|
||||
target.qty = pending_rm_qty
|
||||
|
||||
def set_missing_values(source, target):
|
||||
if source.finished_good and not source.target_warehouse:
|
||||
frappe.throw(_("Please set the Target Warehouse in the Job Card"))
|
||||
|
||||
if not source.skip_material_transfer or source.backflush_from_wip_warehouse:
|
||||
if not source.wip_warehouse:
|
||||
frappe.throw(_("Please set the WIP Warehouse in the Job Card"))
|
||||
|
||||
target.purpose = "Material Transfer for Manufacture"
|
||||
target.from_bom = 1
|
||||
|
||||
if source.semi_fg_bom:
|
||||
target.bom_no = source.semi_fg_bom
|
||||
|
||||
# avoid negative 'For Quantity'
|
||||
pending_fg_qty = flt(source.get("for_quantity", 0)) - flt(source.get("transferred_qty", 0))
|
||||
target.fg_completed_qty = pending_fg_qty if pending_fg_qty > 0 else 0
|
||||
|
||||
target.set_missing_values()
|
||||
target.set_stock_entry_type()
|
||||
|
||||
wo_allows_alternate_item = frappe.db.get_value(
|
||||
"Work Order", target.work_order, "allow_alternative_item"
|
||||
)
|
||||
for item in target.items:
|
||||
item.allow_alternative_item = int(
|
||||
wo_allows_alternate_item
|
||||
and frappe.get_cached_value("Item", item.item_code, "allow_alternative_item")
|
||||
)
|
||||
|
||||
doclist = get_mapped_doc(
|
||||
"Job Card",
|
||||
source_name,
|
||||
{
|
||||
"Job Card": {
|
||||
"doctype": "Stock Entry",
|
||||
"field_map": {"name": "job_card", "for_quantity": "fg_completed_qty"},
|
||||
},
|
||||
"Job Card Item": {
|
||||
"doctype": "Stock Entry Detail",
|
||||
"field_map": {
|
||||
"source_warehouse": "s_warehouse",
|
||||
"required_qty": "qty",
|
||||
"name": "job_card_item",
|
||||
},
|
||||
"postprocess": update_item,
|
||||
"condition": lambda doc: doc.required_qty > 0,
|
||||
},
|
||||
},
|
||||
target_doc,
|
||||
set_missing_values,
|
||||
)
|
||||
|
||||
return doclist
|
||||
|
||||
|
||||
def time_diff_in_minutes(string_ed_date, string_st_date):
|
||||
return time_diff(string_ed_date, string_st_date).total_seconds() / 60
|
||||
|
||||
@@ -1782,40 +1641,3 @@ def get_job_details(start: Any, end: Any, filters: str | dict | None = None):
|
||||
events.append(job_card_data)
|
||||
|
||||
return events
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_corrective_job_card(
|
||||
source_name: str,
|
||||
operation: str | None = None,
|
||||
for_operation: str | None = None,
|
||||
target_doc: Document | str | None = None,
|
||||
):
|
||||
def set_missing_values(source, target):
|
||||
target.is_corrective_job_card = 1
|
||||
target.operation = operation
|
||||
target.for_operation = for_operation
|
||||
|
||||
target.set("time_logs", [])
|
||||
target.set("employee", [])
|
||||
target.set("items", [])
|
||||
target.set("sub_operations", [])
|
||||
target.set_sub_operations()
|
||||
target.get_required_items()
|
||||
|
||||
doclist = get_mapped_doc(
|
||||
"Job Card",
|
||||
source_name,
|
||||
{
|
||||
"Job Card": {
|
||||
"doctype": "Job Card",
|
||||
"field_map": {
|
||||
"name": "for_job_card",
|
||||
},
|
||||
}
|
||||
},
|
||||
target_doc,
|
||||
set_missing_values,
|
||||
)
|
||||
|
||||
return doclist
|
||||
|
||||
191
erpnext/manufacturing/doctype/job_card/mapper.py
Normal file
191
erpnext/manufacturing/doctype/job_card/mapper.py
Normal file
@@ -0,0 +1,191 @@
|
||||
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
from frappe.utils import flt
|
||||
|
||||
from erpnext.subcontracting.doctype.subcontracting_bom.subcontracting_bom import (
|
||||
get_subcontracting_boms_for_finished_goods,
|
||||
)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_subcontracting_po(source_name: str, target_doc: Document | str | None = None):
|
||||
def set_missing_values(source, target):
|
||||
_item_details = get_subcontracting_boms_for_finished_goods(source.finished_good)
|
||||
|
||||
pending_qty = source.for_quantity - source.manufactured_qty
|
||||
service_item_qty = flt(_item_details.service_item_qty) or 1.0
|
||||
fg_item_qty = flt(_item_details.finished_good_qty) or 1.0
|
||||
|
||||
target.is_subcontracted = 1
|
||||
target.supplier_warehouse = source.wip_warehouse
|
||||
target.append(
|
||||
"items",
|
||||
{
|
||||
"item_code": _item_details.service_item,
|
||||
"fg_item": source.finished_good,
|
||||
"uom": _item_details.service_item_uom,
|
||||
"stock_uom": _item_details.service_item_uom,
|
||||
"conversion_factor": _item_details.conversion_factor or 1,
|
||||
"item_name": _item_details.service_item,
|
||||
"qty": pending_qty * service_item_qty / fg_item_qty,
|
||||
"fg_item_qty": pending_qty,
|
||||
"job_card": source.name,
|
||||
"bom": source.semi_fg_bom,
|
||||
"warehouse": source.target_warehouse,
|
||||
},
|
||||
)
|
||||
|
||||
doclist = get_mapped_doc(
|
||||
"Job Card",
|
||||
source_name,
|
||||
{
|
||||
"Job Card": {
|
||||
"doctype": "Purchase Order",
|
||||
},
|
||||
},
|
||||
target_doc,
|
||||
set_missing_values,
|
||||
)
|
||||
|
||||
return doclist
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_material_request(source_name: str, target_doc: Document | str | None = None):
|
||||
def update_item(obj, target, source_parent):
|
||||
target.warehouse = source_parent.wip_warehouse
|
||||
|
||||
def set_missing_values(source, target):
|
||||
target.material_request_type = "Material Transfer"
|
||||
|
||||
doclist = get_mapped_doc(
|
||||
"Job Card",
|
||||
source_name,
|
||||
{
|
||||
"Job Card": {
|
||||
"doctype": "Material Request",
|
||||
"field_map": {
|
||||
"name": "job_card",
|
||||
},
|
||||
},
|
||||
"Job Card Item": {
|
||||
"doctype": "Material Request Item",
|
||||
"field_map": {"required_qty": "qty", "uom": "stock_uom", "name": "job_card_item"},
|
||||
"postprocess": update_item,
|
||||
},
|
||||
},
|
||||
target_doc,
|
||||
set_missing_values,
|
||||
)
|
||||
|
||||
return doclist
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_stock_entry(source_name: str, target_doc: Document | str | None = None):
|
||||
def update_item(source, target, source_parent):
|
||||
target.t_warehouse = source_parent.wip_warehouse
|
||||
|
||||
if not target.conversion_factor:
|
||||
target.conversion_factor = 1
|
||||
|
||||
pending_rm_qty = flt(source.required_qty) - flt(source.transferred_qty)
|
||||
if pending_rm_qty > 0:
|
||||
target.qty = pending_rm_qty
|
||||
|
||||
def set_missing_values(source, target):
|
||||
if source.finished_good and not source.target_warehouse:
|
||||
frappe.throw(_("Please set the Target Warehouse in the Job Card"))
|
||||
|
||||
if not source.skip_material_transfer or source.backflush_from_wip_warehouse:
|
||||
if not source.wip_warehouse:
|
||||
frappe.throw(_("Please set the WIP Warehouse in the Job Card"))
|
||||
|
||||
target.purpose = "Material Transfer for Manufacture"
|
||||
target.from_bom = 1
|
||||
|
||||
if source.semi_fg_bom:
|
||||
target.bom_no = source.semi_fg_bom
|
||||
|
||||
# avoid negative 'For Quantity'
|
||||
pending_fg_qty = flt(source.get("for_quantity", 0)) - flt(source.get("transferred_qty", 0))
|
||||
target.fg_completed_qty = pending_fg_qty if pending_fg_qty > 0 else 0
|
||||
|
||||
target.set_missing_values()
|
||||
target.set_stock_entry_type()
|
||||
|
||||
wo_allows_alternate_item = frappe.db.get_value(
|
||||
"Work Order", target.work_order, "allow_alternative_item"
|
||||
)
|
||||
for item in target.items:
|
||||
item.allow_alternative_item = int(
|
||||
wo_allows_alternate_item
|
||||
and frappe.get_cached_value("Item", item.item_code, "allow_alternative_item")
|
||||
)
|
||||
|
||||
doclist = get_mapped_doc(
|
||||
"Job Card",
|
||||
source_name,
|
||||
{
|
||||
"Job Card": {
|
||||
"doctype": "Stock Entry",
|
||||
"field_map": {"name": "job_card", "for_quantity": "fg_completed_qty"},
|
||||
},
|
||||
"Job Card Item": {
|
||||
"doctype": "Stock Entry Detail",
|
||||
"field_map": {
|
||||
"source_warehouse": "s_warehouse",
|
||||
"required_qty": "qty",
|
||||
"name": "job_card_item",
|
||||
},
|
||||
"postprocess": update_item,
|
||||
"condition": lambda doc: doc.required_qty > 0,
|
||||
},
|
||||
},
|
||||
target_doc,
|
||||
set_missing_values,
|
||||
)
|
||||
|
||||
return doclist
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_corrective_job_card(
|
||||
source_name: str,
|
||||
operation: str | None = None,
|
||||
for_operation: str | None = None,
|
||||
target_doc: Document | str | None = None,
|
||||
):
|
||||
def set_missing_values(source, target):
|
||||
target.is_corrective_job_card = 1
|
||||
target.operation = operation
|
||||
target.for_operation = for_operation
|
||||
|
||||
target.set("time_logs", [])
|
||||
target.set("employee", [])
|
||||
target.set("items", [])
|
||||
target.set("sub_operations", [])
|
||||
target.set_sub_operations()
|
||||
target.get_required_items()
|
||||
|
||||
doclist = get_mapped_doc(
|
||||
"Job Card",
|
||||
source_name,
|
||||
{
|
||||
"Job Card": {
|
||||
"doctype": "Job Card",
|
||||
"field_map": {
|
||||
"name": "for_job_card",
|
||||
},
|
||||
}
|
||||
},
|
||||
target_doc,
|
||||
set_missing_values,
|
||||
)
|
||||
|
||||
return doclist
|
||||
Reference in New Issue
Block a user