blob: f97cd5e9dd0910224b5a4ce20386f2b4b286d97a [file] [log] [blame]
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +05301# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
2# License: GNU General Public License v3. See license.txt
3
Chillar Anand915b3432021-09-02 16:44:59 +05304
mbauskarc482aed2017-05-02 12:53:12 +05305import json
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +05306
Chillar Anand915b3432021-09-02 16:44:59 +05307import frappe
8from frappe import _
9from frappe.utils import cint, cstr, flt
10
11from erpnext.stock.doctype.item.item import get_last_purchase_details, validate_end_of_life
12
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053013
14def update_last_purchase_rate(doc, is_submit):
15 """updates last_purchase_rate in item table for each item"""
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053016 import frappe.utils
Ankush Menat494bd9e2022-03-28 18:52:46 +053017
18 this_purchase_date = frappe.utils.getdate(doc.get("posting_date") or doc.get("transaction_date"))
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053019
20 for d in doc.get("items"):
21 # get last purchase details
22 last_purchase_details = get_last_purchase_details(d.item_code, doc.name)
23
24 # compare last purchase date and this transaction's date
25 last_purchase_rate = None
Ankush Menat494bd9e2022-03-28 18:52:46 +053026 if last_purchase_details and (
27 doc.get("docstatus") == 2 or last_purchase_details.purchase_date > this_purchase_date
28 ):
29 last_purchase_rate = last_purchase_details["base_net_rate"]
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053030 elif is_submit == 1:
31 # even if this transaction is the latest one, it should be submitted
32 # for it to be considered for latest purchase rate
33 if flt(d.conversion_factor):
Saqib290253f2019-11-22 12:12:29 +053034 last_purchase_rate = flt(d.base_net_rate) / flt(d.conversion_factor)
Deepesh Garg8b0302b2019-08-05 10:14:19 +053035 # Check if item code is present
36 # Conversion factor should not be mandatory for non itemized items
37 elif d.item_code:
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053038 frappe.throw(_("UOM Conversion factor is required in row {0}").format(d.idx))
39
40 # update last purchsae rate
Ankush Menat494bd9e2022-03-28 18:52:46 +053041 frappe.db.set_value("Item", d.item_code, "last_purchase_rate", flt(last_purchase_rate))
Mohammad Hasnain Mohsin Rajan00981202021-01-14 19:23:18 +053042
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053043
44def validate_for_items(doc):
45 items = []
46 for d in doc.get("items"):
47 if not d.qty:
48 if doc.doctype == "Purchase Receipt" and d.rejected_qty:
49 continue
50 frappe.throw(_("Please enter quantity for Item {0}").format(d.item_code))
51
52 # update with latest quantities
Ankush Menat494bd9e2022-03-28 18:52:46 +053053 bin = frappe.db.sql(
54 """select projected_qty from `tabBin` where
55 item_code = %s and warehouse = %s""",
56 (d.item_code, d.warehouse),
57 as_dict=1,
58 )
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053059
Ankush Menat494bd9e2022-03-28 18:52:46 +053060 f_lst = {
61 "projected_qty": bin and flt(bin[0]["projected_qty"]) or 0,
62 "ordered_qty": 0,
63 "received_qty": 0,
64 }
65 if d.doctype in ("Purchase Receipt Item", "Purchase Invoice Item"):
66 f_lst.pop("received_qty")
67 for x in f_lst:
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053068 if d.meta.get_field(x):
69 d.set(x, f_lst[x])
70
Ankush Menat494bd9e2022-03-28 18:52:46 +053071 item = frappe.db.sql(
72 """select is_stock_item,
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053073 is_sub_contracted_item, end_of_life, disabled from `tabItem` where name=%s""",
Ankush Menat494bd9e2022-03-28 18:52:46 +053074 d.item_code,
75 as_dict=1,
76 )[0]
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053077
78 validate_end_of_life(d.item_code, item.end_of_life, item.disabled)
79
80 # validate stock item
Ankush Menat494bd9e2022-03-28 18:52:46 +053081 if item.is_stock_item == 1 and d.qty and not d.warehouse and not d.get("delivered_by_supplier"):
82 frappe.throw(
83 _("Warehouse is mandatory for stock Item {0} in row {1}").format(d.item_code, d.idx)
84 )
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053085
86 items.append(cstr(d.item_code))
87
Ankush Menat494bd9e2022-03-28 18:52:46 +053088 if (
89 items
90 and len(items) != len(set(items))
91 and not cint(frappe.db.get_single_value("Buying Settings", "allow_multiple_items") or 0)
92 ):
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053093 frappe.throw(_("Same item cannot be entered multiple times."))
94
Ankush Menat494bd9e2022-03-28 18:52:46 +053095
Mangesh-Khairnara1afd782019-03-11 17:15:05 +053096def check_on_hold_or_closed_status(doctype, docname):
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053097 status = frappe.db.get_value(doctype, docname, "status")
98
Mangesh-Khairnara1afd782019-03-11 17:15:05 +053099 if status in ("Closed", "On Hold"):
Ankush Menat494bd9e2022-03-28 18:52:46 +0530100 frappe.throw(
101 _("{0} {1} status is {2}").format(doctype, docname, status), frappe.InvalidStatusError
102 )
103
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +0530104
mbauskarc482aed2017-05-02 12:53:12 +0530105@frappe.whitelist()
106def get_linked_material_requests(items):
107 items = json.loads(items)
108 mr_list = []
109 for item in items:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530110 material_request = frappe.db.sql(
111 """SELECT distinct mr.name AS mr_name,
Deepesh Garg8b0302b2019-08-05 10:14:19 +0530112 (mr_item.qty - mr_item.ordered_qty) AS qty,
mbauskarc482aed2017-05-02 12:53:12 +0530113 mr_item.item_code AS item_code,
Deepesh Garg8b0302b2019-08-05 10:14:19 +0530114 mr_item.name AS mr_item
mbauskarc482aed2017-05-02 12:53:12 +0530115 FROM `tabMaterial Request` mr, `tabMaterial Request Item` mr_item
116 WHERE mr.name = mr_item.parent
Deepesh Garg8b0302b2019-08-05 10:14:19 +0530117 AND mr_item.item_code = %(item)s
mbauskarc482aed2017-05-02 12:53:12 +0530118 AND mr.material_request_type = 'Purchase'
119 AND mr.per_ordered < 99.99
120 AND mr.docstatus = 1
121 AND mr.status != 'Stopped'
Ankush Menat494bd9e2022-03-28 18:52:46 +0530122 ORDER BY mr_item.item_code ASC""",
123 {"item": item},
124 as_dict=1,
125 )
mbauskarc482aed2017-05-02 12:53:12 +0530126 if material_request:
127 mr_list.append(material_request)
Deepesh Garg8b0302b2019-08-05 10:14:19 +0530128
mbauskarc482aed2017-05-02 12:53:12 +0530129 return mr_list