feat: serial and batch bundle for Packing Items
This commit is contained in:
parent
9c097e85f8
commit
674bd3e2e5
@ -38,7 +38,9 @@ class SellingController(StockController):
|
|||||||
self.validate_for_duplicate_items()
|
self.validate_for_duplicate_items()
|
||||||
self.validate_target_warehouse()
|
self.validate_target_warehouse()
|
||||||
self.validate_auto_repeat_subscription_dates()
|
self.validate_auto_repeat_subscription_dates()
|
||||||
self.set_serial_and_batch_bundle()
|
for table_field in ["items", "packed_items"]:
|
||||||
|
if self.get(table_field):
|
||||||
|
self.set_serial_and_batch_bundle(table_field)
|
||||||
|
|
||||||
def set_missing_values(self, for_validate=False):
|
def set_missing_values(self, for_validate=False):
|
||||||
|
|
||||||
@ -426,8 +428,7 @@ class SellingController(StockController):
|
|||||||
"posting_date": self.get("posting_date") or self.get("transaction_date"),
|
"posting_date": self.get("posting_date") or self.get("transaction_date"),
|
||||||
"posting_time": self.get("posting_time") or nowtime(),
|
"posting_time": self.get("posting_time") or nowtime(),
|
||||||
"qty": qty if cint(self.get("is_return")) else (-1 * qty),
|
"qty": qty if cint(self.get("is_return")) else (-1 * qty),
|
||||||
"serial_no": d.get("serial_no"),
|
"serial_and_batch_bundle": d.serial_and_batch_bundle,
|
||||||
"batch_no": d.get("batch_no"),
|
|
||||||
"company": self.company,
|
"company": self.company,
|
||||||
"voucher_type": self.doctype,
|
"voucher_type": self.doctype,
|
||||||
"voucher_no": self.name,
|
"voucher_no": self.name,
|
||||||
|
@ -719,7 +719,7 @@ class StockController(AccountsController):
|
|||||||
table_name = "items"
|
table_name = "items"
|
||||||
|
|
||||||
for row in self.get(table_name):
|
for row in self.get(table_name):
|
||||||
if row.serial_and_batch_bundle:
|
if row.get("serial_and_batch_bundle"):
|
||||||
frappe.get_doc(
|
frappe.get_doc(
|
||||||
"Serial and Batch Bundle", row.serial_and_batch_bundle
|
"Serial and Batch Bundle", row.serial_and_batch_bundle
|
||||||
).set_serial_and_batch_values(self, row)
|
).set_serial_and_batch_values(self, row)
|
||||||
|
@ -51,7 +51,9 @@ class SubcontractingController(StockController):
|
|||||||
if self.doctype in ["Subcontracting Order", "Subcontracting Receipt"]:
|
if self.doctype in ["Subcontracting Order", "Subcontracting Receipt"]:
|
||||||
self.validate_items()
|
self.validate_items()
|
||||||
self.create_raw_materials_supplied()
|
self.create_raw_materials_supplied()
|
||||||
self.set_serial_and_batch_bundle("supplied_items")
|
for table_field in ["items", "supplied_items"]:
|
||||||
|
if self.get(table_field):
|
||||||
|
self.set_total_in_words(table_field)
|
||||||
else:
|
else:
|
||||||
super(SubcontractingController, self).validate()
|
super(SubcontractingController, self).validate()
|
||||||
|
|
||||||
|
@ -431,6 +431,7 @@ erpnext.selling.SellingController = class SellingController extends erpnext.Tran
|
|||||||
item.has_serial_no = r.message.has_serial_no;
|
item.has_serial_no = r.message.has_serial_no;
|
||||||
item.has_batch_no = r.message.has_batch_no;
|
item.has_batch_no = r.message.has_batch_no;
|
||||||
item.type_of_transaction = item.qty > 0 ? "Outward":"Inward";
|
item.type_of_transaction = item.qty > 0 ? "Outward":"Inward";
|
||||||
|
item.outward = item.qty > 0 ? 1 : 0;
|
||||||
|
|
||||||
item.title = item.has_serial_no ?
|
item.title = item.has_serial_no ?
|
||||||
__("Select Serial No") : __("Select Batch No");
|
__("Select Serial No") : __("Select Batch No");
|
||||||
@ -446,6 +447,8 @@ erpnext.selling.SellingController = class SellingController extends erpnext.Tran
|
|||||||
me.frm.refresh_fields();
|
me.frm.refresh_fields();
|
||||||
frappe.model.set_value(cdt, cdn,
|
frappe.model.set_value(cdt, cdn,
|
||||||
"serial_and_batch_bundle", r.name);
|
"serial_and_batch_bundle", r.name);
|
||||||
|
|
||||||
|
me.frm.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -5,7 +5,7 @@ import collections
|
|||||||
from typing import Dict, List
|
from typing import Dict, List
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _, bold
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.query_builder.functions import Sum
|
from frappe.query_builder.functions import Sum
|
||||||
from frappe.utils import cint, flt, today
|
from frappe.utils import cint, flt, today
|
||||||
@ -301,6 +301,15 @@ class SerialandBatchBundle(Document):
|
|||||||
for batch in batches:
|
for batch in batches:
|
||||||
frappe.db.set_value("Batch", batch.name, {"reference_name": None, "reference_doctype": None})
|
frappe.db.set_value("Batch", batch.name, {"reference_name": None, "reference_doctype": None})
|
||||||
|
|
||||||
|
def on_cancel(self):
|
||||||
|
self.validate_voucher_no_docstatus()
|
||||||
|
|
||||||
|
def validate_voucher_no_docstatus(self):
|
||||||
|
if frappe.db.get_value(self.voucher_type, self.voucher_no, "docstatus") == 1:
|
||||||
|
msg = f"""The {self.voucher_type} {bold(self.voucher_no)}
|
||||||
|
is in submitted state, please cancel it first"""
|
||||||
|
frappe.throw(_(msg))
|
||||||
|
|
||||||
def on_trash(self):
|
def on_trash(self):
|
||||||
self.delink_refernce_from_voucher()
|
self.delink_refernce_from_voucher()
|
||||||
self.delink_reference_from_batch()
|
self.delink_reference_from_batch()
|
||||||
|
@ -1220,11 +1220,18 @@ class StockEntry(StockController):
|
|||||||
sle.recalculate_rate = 1
|
sle.recalculate_rate = 1
|
||||||
|
|
||||||
if d.serial_and_batch_bundle and self.docstatus == 1:
|
if d.serial_and_batch_bundle and self.docstatus == 1:
|
||||||
self.copy_serial_and_batch_bundle(sle, d)
|
d.serial_and_batch_bundle = self.copy_serial_and_batch_bundle(sle)
|
||||||
|
|
||||||
if d.serial_and_batch_bundle and self.docstatus == 2:
|
if d.serial_and_batch_bundle and self.docstatus == 2:
|
||||||
bundle_id = frappe.get_cached_value(
|
bundle_id = frappe.get_cached_value(
|
||||||
"Serial and Batch Bundle", {"voucher_detail_no": d.name, "is_cancelled": 0}, "name"
|
"Serial and Batch Bundle",
|
||||||
|
{
|
||||||
|
"voucher_detail_no": d.name,
|
||||||
|
"voucher_no": self.name,
|
||||||
|
"is_cancelled": 0,
|
||||||
|
"type_of_transaction": "Inward",
|
||||||
|
},
|
||||||
|
"name",
|
||||||
)
|
)
|
||||||
|
|
||||||
if d.serial_and_batch_bundle != bundle_id:
|
if d.serial_and_batch_bundle != bundle_id:
|
||||||
@ -1232,7 +1239,7 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
sl_entries.append(sle)
|
sl_entries.append(sle)
|
||||||
|
|
||||||
def copy_serial_and_batch_bundle(self, sle, child):
|
def copy_serial_and_batch_bundle(self, child):
|
||||||
allowed_types = [
|
allowed_types = [
|
||||||
"Material Transfer",
|
"Material Transfer",
|
||||||
"Send to Subcontractor",
|
"Send to Subcontractor",
|
||||||
@ -1260,7 +1267,7 @@ class StockEntry(StockController):
|
|||||||
bundle_doc.set_avg_rate()
|
bundle_doc.set_avg_rate()
|
||||||
bundle_doc.flags.ignore_permissions = True
|
bundle_doc.flags.ignore_permissions = True
|
||||||
bundle_doc.submit()
|
bundle_doc.submit()
|
||||||
sle.serial_and_batch_bundle = bundle_doc.name
|
return bundle_doc.name
|
||||||
|
|
||||||
def get_gl_entries(self, warehouse_account):
|
def get_gl_entries(self, warehouse_account):
|
||||||
gl_entries = super(StockEntry, self).get_gl_entries(warehouse_account)
|
gl_entries = super(StockEntry, self).get_gl_entries(warehouse_account)
|
||||||
|
@ -307,6 +307,9 @@ class SerialBatchBundle:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def post_process(self):
|
def post_process(self):
|
||||||
|
if not self.sle.serial_and_batch_bundle:
|
||||||
|
return
|
||||||
|
|
||||||
if self.item_details.has_serial_no == 1:
|
if self.item_details.has_serial_no == 1:
|
||||||
self.set_warehouse_and_status_in_serial_nos()
|
self.set_warehouse_and_status_in_serial_nos()
|
||||||
|
|
||||||
|
@ -259,8 +259,11 @@ def get_incoming_rate(args, raise_error_if_no_rate=True):
|
|||||||
"Item", args.get("item_code"), ["has_serial_no", "has_batch_no"], as_dict=1
|
"Item", args.get("item_code"), ["has_serial_no", "has_batch_no"], as_dict=1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if isinstance(args, dict):
|
||||||
|
args = frappe._dict(args)
|
||||||
|
|
||||||
if item_details.has_serial_no and args.get("serial_and_batch_bundle"):
|
if item_details.has_serial_no and args.get("serial_and_batch_bundle"):
|
||||||
args["actual_qty"] = args["qty"]
|
args.actual_qty = args.qty
|
||||||
sn_obj = SerialNoBundleValuation(
|
sn_obj = SerialNoBundleValuation(
|
||||||
sle=args,
|
sle=args,
|
||||||
warehouse=args.get("warehouse"),
|
warehouse=args.get("warehouse"),
|
||||||
@ -270,7 +273,7 @@ def get_incoming_rate(args, raise_error_if_no_rate=True):
|
|||||||
in_rate = sn_obj.get_incoming_rate()
|
in_rate = sn_obj.get_incoming_rate()
|
||||||
|
|
||||||
elif item_details.has_batch_no and args.get("serial_and_batch_bundle"):
|
elif item_details.has_batch_no and args.get("serial_and_batch_bundle"):
|
||||||
args["actual_qty"] = args["qty"]
|
args.actual_qty = args.qty
|
||||||
batch_obj = BatchNoBundleValuation(
|
batch_obj = BatchNoBundleValuation(
|
||||||
sle=args,
|
sle=args,
|
||||||
warehouse=args.get("warehouse"),
|
warehouse=args.get("warehouse"),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user