mirror of
https://github.com/frappe/erpnext.git
synced 2026-03-12 06:48:31 +00:00
Merge pull request #23645 from rohitwaghchaure/receive-at-warehouse-not-validate-for-extra-transfer-qty
fix: extra material received against send to warehouse entry
This commit is contained in:
@@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
||||
import frappe, erpnext
|
||||
import frappe.defaults
|
||||
from frappe import _
|
||||
from frappe.utils import cstr, cint, flt, comma_or, getdate, nowdate, formatdate, format_time
|
||||
from frappe.utils import cstr, cint, flt, comma_or, getdate, nowdate, formatdate, format_time, get_link_to_form
|
||||
from erpnext.stock.utils import get_incoming_rate
|
||||
from erpnext.stock.stock_ledger import get_previous_sle, NegativeStockError, get_valuation_rate
|
||||
from erpnext.stock.get_item_details import get_bin_details, get_default_cost_center, get_conversion_factor, get_reserved_qty_for_so
|
||||
@@ -27,6 +27,7 @@ class IncorrectValuationRateError(frappe.ValidationError): pass
|
||||
class DuplicateEntryForWorkOrderError(frappe.ValidationError): pass
|
||||
class OperationsNotCompleteError(frappe.ValidationError): pass
|
||||
class MaxSampleAlreadyRetainedError(frappe.ValidationError): pass
|
||||
class ExtraMaterialReceived(frappe.ValidationError): pass
|
||||
|
||||
from erpnext.controllers.stock_controller import StockController
|
||||
|
||||
@@ -35,6 +36,11 @@ form_grid_templates = {
|
||||
}
|
||||
|
||||
class StockEntry(StockController):
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""To initialize the status updater."""
|
||||
super(StockEntry, self).__init__(*args, **kwargs)
|
||||
self.status_updater = []
|
||||
|
||||
def get_feed(self):
|
||||
return self.stock_entry_type
|
||||
|
||||
@@ -51,7 +57,6 @@ class StockEntry(StockController):
|
||||
self.validate_purpose()
|
||||
self.validate_item()
|
||||
self.validate_customer_provided_item()
|
||||
self.validate_qty()
|
||||
self.set_transfer_qty()
|
||||
self.validate_uom_is_integer("uom", "qty")
|
||||
self.validate_uom_is_integer("stock_uom", "transfer_qty")
|
||||
@@ -122,6 +127,22 @@ class StockEntry(StockController):
|
||||
self.from_bom = 1
|
||||
self.bom_no = data.bom_no
|
||||
|
||||
def limits_crossed_error(self, args, item, qty_or_amount):
|
||||
"""To override the method limits_crossed_error which is defined in the status_updater."""
|
||||
"""Raise the exception for extra material transfer against the send to warehouse."""
|
||||
|
||||
send_to_ste = frappe.bold(get_link_to_form("Stock Entry", self.outgoing_stock_entry))
|
||||
message = _("For more details please check the send to warehouse document {0}.").format(send_to_ste)
|
||||
|
||||
frappe.throw(_('For the item {0}, the received quantity {1} is more than the sent quantity {2}. {3}{4}')
|
||||
.format(
|
||||
frappe.bold(item.get('item_code')),
|
||||
frappe.bold((item[args["target_field"]])),
|
||||
frappe.bold(item[args["target_ref_field"]]),
|
||||
'<br>',
|
||||
message
|
||||
), ExtraMaterialReceived, title = _('Extra Materials Transferred'))
|
||||
|
||||
def validate_work_order_status(self):
|
||||
pro_doc = frappe.get_doc("Work Order", self.work_order)
|
||||
if pro_doc.status == 'Completed':
|
||||
@@ -205,33 +226,6 @@ class StockEntry(StockController):
|
||||
frappe.throw(_("Row #{0}: Please specify Serial No for Item {1}").format(item.idx, item.item_code),
|
||||
frappe.MandatoryError)
|
||||
|
||||
def validate_qty(self):
|
||||
manufacture_purpose = ["Manufacture", "Material Consumption for Manufacture"]
|
||||
|
||||
if self.purpose in manufacture_purpose and self.work_order:
|
||||
if not frappe.get_value('Work Order', self.work_order, 'skip_transfer'):
|
||||
item_code = []
|
||||
for item in self.items:
|
||||
if cstr(item.t_warehouse) == '':
|
||||
req_items = frappe.get_all('Work Order Item',
|
||||
filters={'parent': self.work_order, 'item_code': item.item_code}, fields=["item_code"])
|
||||
|
||||
transferred_materials = frappe.db.sql("""
|
||||
select
|
||||
sum(qty) as qty
|
||||
from `tabStock Entry` se,`tabStock Entry Detail` sed
|
||||
where
|
||||
se.name = sed.parent and se.docstatus=1 and
|
||||
(se.purpose='Material Transfer for Manufacture' or se.purpose='Manufacture')
|
||||
and sed.item_code=%s and se.work_order= %s and ifnull(sed.t_warehouse, '') != ''
|
||||
""", (item.item_code, self.work_order), as_dict=1)
|
||||
|
||||
stock_qty = flt(item.qty)
|
||||
trans_qty = flt(transferred_materials[0].qty)
|
||||
if req_items:
|
||||
if stock_qty > trans_qty:
|
||||
item_code.append(item.item_code)
|
||||
|
||||
def validate_fg_completed_qty(self):
|
||||
if self.purpose == "Manufacture" and self.work_order:
|
||||
production_item = frappe.get_value('Work Order', self.work_order, 'production_item')
|
||||
@@ -1297,37 +1291,7 @@ class StockEntry(StockController):
|
||||
|
||||
def update_transferred_qty(self):
|
||||
if self.purpose == 'Receive at Warehouse':
|
||||
stock_entries = {}
|
||||
stock_entries_child_list = []
|
||||
for d in self.items:
|
||||
if not (d.against_stock_entry and d.ste_detail):
|
||||
continue
|
||||
|
||||
stock_entries_child_list.append(d.ste_detail)
|
||||
transferred_qty = frappe.get_all("Stock Entry Detail", fields = ["sum(qty) as qty"],
|
||||
filters = { 'against_stock_entry': d.against_stock_entry,
|
||||
'ste_detail': d.ste_detail,'docstatus': 1})
|
||||
|
||||
stock_entries[(d.against_stock_entry, d.ste_detail)] = (transferred_qty[0].qty
|
||||
if transferred_qty and transferred_qty[0] else 0.0) or 0.0
|
||||
|
||||
if not stock_entries: return None
|
||||
|
||||
cond = ''
|
||||
for data, transferred_qty in stock_entries.items():
|
||||
cond += """ WHEN (parent = %s and name = %s) THEN %s
|
||||
""" %(frappe.db.escape(data[0]), frappe.db.escape(data[1]), transferred_qty)
|
||||
|
||||
if cond and stock_entries_child_list:
|
||||
frappe.db.sql(""" UPDATE `tabStock Entry Detail`
|
||||
SET
|
||||
transferred_qty = CASE {cond} END
|
||||
WHERE
|
||||
name in ({ste_details}) """.format(cond=cond,
|
||||
ste_details = ','.join(['%s'] * len(stock_entries_child_list))),
|
||||
tuple(stock_entries_child_list))
|
||||
|
||||
args = {
|
||||
self.status_updater.append({
|
||||
'source_dt': 'Stock Entry Detail',
|
||||
'target_field': 'transferred_qty',
|
||||
'target_ref_field': 'qty',
|
||||
@@ -1336,10 +1300,11 @@ class StockEntry(StockController):
|
||||
'target_parent_dt': 'Stock Entry',
|
||||
'target_parent_field': 'per_transferred',
|
||||
'source_field': 'qty',
|
||||
'percent_join_field': 'against_stock_entry'
|
||||
}
|
||||
'percent_join_field': 'against_stock_entry',
|
||||
'no_allowance': 1
|
||||
})
|
||||
|
||||
self._update_percent_field_in_targets(args, update_modified=True)
|
||||
self.update_prevdoc_status()
|
||||
|
||||
def update_quality_inspection(self):
|
||||
if self.inspection_required:
|
||||
|
||||
@@ -14,7 +14,8 @@ from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import
|
||||
from erpnext.stock.doctype.item.test_item import set_item_variant_settings, make_item_variant, create_item
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||
from erpnext.accounts.doctype.account.test_account import get_inventory_account
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry import move_sample_to_retention_warehouse, make_stock_in_entry
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry import (move_sample_to_retention_warehouse,
|
||||
make_stock_in_entry, ExtraMaterialReceived)
|
||||
from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import OpeningEntryAccountError
|
||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||
from six import iteritems
|
||||
@@ -871,6 +872,30 @@ class TestStockEntry(unittest.TestCase):
|
||||
doc = frappe.get_doc('Stock Entry', outward_entry.name)
|
||||
self.assertEqual(doc.per_transferred, 100)
|
||||
|
||||
def test_raise_extra_transfer_materials(self):
|
||||
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
|
||||
warehouse = "_Test Warehouse FG 1 - _TC"
|
||||
|
||||
if not frappe.db.exists('Warehouse', warehouse):
|
||||
create_warehouse("_Test Warehouse FG 1")
|
||||
|
||||
outward_entry = make_stock_entry(item_code="_Test Item",
|
||||
purpose="Send to Warehouse",
|
||||
source="_Test Warehouse - _TC",
|
||||
target="_Test Warehouse 1 - _TC", qty=50, basic_rate=100)
|
||||
|
||||
inward_entry1 = make_stock_in_entry(outward_entry.name)
|
||||
inward_entry1.items[0].t_warehouse = warehouse
|
||||
inward_entry1.items[0].qty = 25
|
||||
inward_entry1.submit()
|
||||
|
||||
inward_entry2 = make_stock_in_entry(outward_entry.name)
|
||||
inward_entry2.items[0].t_warehouse = warehouse
|
||||
inward_entry2.items[0].qty = 35
|
||||
|
||||
self.assertRaises(ExtraMaterialReceived, inward_entry2.submit)
|
||||
print(inward_entry2.name)
|
||||
|
||||
def test_gle_for_opening_stock_entry(self):
|
||||
mr = make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company="_Test Company with perpetual inventory",qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1", is_opening="Yes", do_not_save=True)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user