blob: 81d995ce8de1d45554221338e55bff6df25ef0ee [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
4from __future__ import unicode_literals
Chillar Anand915b3432021-09-02 16:44:59 +05305
mbauskarc482aed2017-05-02 12:53:12 +05306import json
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +05307
Chillar Anand915b3432021-09-02 16:44:59 +05308import frappe
9from frappe import _
10from frappe.utils import cint, cstr, flt
11
12from erpnext.stock.doctype.item.item import get_last_purchase_details, validate_end_of_life
13
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053014
15def update_last_purchase_rate(doc, is_submit):
16 """updates last_purchase_rate in item table for each item"""
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053017 import frappe.utils
18 this_purchase_date = frappe.utils.getdate(doc.get('posting_date') or doc.get('transaction_date'))
19
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
26 if last_purchase_details and \
Lokesh Waingankar28666172020-02-27 13:21:14 +053027 (doc.get('docstatus') == 2 or last_purchase_details.purchase_date > this_purchase_date):
Saqib290253f2019-11-22 12:12:29 +053028 last_purchase_rate = last_purchase_details['base_net_rate']
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053029 elif is_submit == 1:
30 # even if this transaction is the latest one, it should be submitted
31 # for it to be considered for latest purchase rate
32 if flt(d.conversion_factor):
Saqib290253f2019-11-22 12:12:29 +053033 last_purchase_rate = flt(d.base_net_rate) / flt(d.conversion_factor)
Deepesh Garg8b0302b2019-08-05 10:14:19 +053034 # Check if item code is present
35 # Conversion factor should not be mandatory for non itemized items
36 elif d.item_code:
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053037 frappe.throw(_("UOM Conversion factor is required in row {0}").format(d.idx))
38
39 # update last purchsae rate
Mohammad Hasnain Mohsin Rajan00981202021-01-14 19:23:18 +053040 frappe.db.set_value('Item', d.item_code, 'last_purchase_rate', flt(last_purchase_rate))
41
42
43
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053044
45def validate_for_items(doc):
46 items = []
47 for d in doc.get("items"):
48 if not d.qty:
49 if doc.doctype == "Purchase Receipt" and d.rejected_qty:
50 continue
51 frappe.throw(_("Please enter quantity for Item {0}").format(d.item_code))
52
53 # update with latest quantities
54 bin = frappe.db.sql("""select projected_qty from `tabBin` where
55 item_code = %s and warehouse = %s""", (d.item_code, d.warehouse), as_dict=1)
56
57 f_lst ={'projected_qty': bin and flt(bin[0]['projected_qty']) or 0, 'ordered_qty': 0, 'received_qty' : 0}
58 if d.doctype in ('Purchase Receipt Item', 'Purchase Invoice Item'):
59 f_lst.pop('received_qty')
60 for x in f_lst :
61 if d.meta.get_field(x):
62 d.set(x, f_lst[x])
63
64 item = frappe.db.sql("""select is_stock_item,
65 is_sub_contracted_item, end_of_life, disabled from `tabItem` where name=%s""",
66 d.item_code, as_dict=1)[0]
67
68 validate_end_of_life(d.item_code, item.end_of_life, item.disabled)
69
70 # validate stock item
Makarand Bauskarc4ec9372017-05-05 11:52:17 +053071 if item.is_stock_item==1 and d.qty and not d.warehouse and not d.get("delivered_by_supplier"):
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053072 frappe.throw(_("Warehouse is mandatory for stock Item {0} in row {1}").format(d.item_code, d.idx))
73
74 items.append(cstr(d.item_code))
75
76 if items and len(items) != len(set(items)) and \
77 not cint(frappe.db.get_single_value("Buying Settings", "allow_multiple_items") or 0):
78 frappe.throw(_("Same item cannot be entered multiple times."))
79
Mangesh-Khairnara1afd782019-03-11 17:15:05 +053080def check_on_hold_or_closed_status(doctype, docname):
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053081 status = frappe.db.get_value(doctype, docname, "status")
82
Mangesh-Khairnara1afd782019-03-11 17:15:05 +053083 if status in ("Closed", "On Hold"):
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +053084 frappe.throw(_("{0} {1} status is {2}").format(doctype, docname, status), frappe.InvalidStatusError)
85
mbauskarc482aed2017-05-02 12:53:12 +053086@frappe.whitelist()
87def get_linked_material_requests(items):
88 items = json.loads(items)
89 mr_list = []
90 for item in items:
Deepesh Garg8b0302b2019-08-05 10:14:19 +053091 material_request = frappe.db.sql("""SELECT distinct mr.name AS mr_name,
92 (mr_item.qty - mr_item.ordered_qty) AS qty,
mbauskarc482aed2017-05-02 12:53:12 +053093 mr_item.item_code AS item_code,
Deepesh Garg8b0302b2019-08-05 10:14:19 +053094 mr_item.name AS mr_item
mbauskarc482aed2017-05-02 12:53:12 +053095 FROM `tabMaterial Request` mr, `tabMaterial Request Item` mr_item
96 WHERE mr.name = mr_item.parent
Deepesh Garg8b0302b2019-08-05 10:14:19 +053097 AND mr_item.item_code = %(item)s
mbauskarc482aed2017-05-02 12:53:12 +053098 AND mr.material_request_type = 'Purchase'
99 AND mr.per_ordered < 99.99
100 AND mr.docstatus = 1
101 AND mr.status != 'Stopped'
102 ORDER BY mr_item.item_code ASC""",{"item": item}, as_dict=1)
103 if material_request:
104 mr_list.append(material_request)
Deepesh Garg8b0302b2019-08-05 10:14:19 +0530105
mbauskarc482aed2017-05-02 12:53:12 +0530106 return mr_list