diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index efab5801e8b..291aff3f5ad 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -112,8 +112,8 @@ class GLEntry(Document): from tabAccount where name=%s""", self.account, as_dict=1)[0] if ret.is_group==1: - frappe.throw(_("{0} {1}: Account {2} cannot be a Group") - .format(self.voucher_type, self.voucher_no, self.account)) + frappe.throw(_('''{0} {1}: Account {2} is a Group Account and group accounts cannot be used in + transactions''').format(self.voucher_type, self.voucher_no, self.account)) if ret.docstatus==2: frappe.throw(_("{0} {1}: Account {2} is inactive") diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 22df5be1b9d..d2245d6a6d6 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -451,8 +451,6 @@ class PaymentEntry(AccountsController): frappe.throw(_("Reference No and Reference Date is mandatory for Bank transaction")) def set_remarks(self): - if self.remarks: return - if self.payment_type=="Internal Transfer": remarks = [_("Amount {0} {1} transferred from {2} to {3}") .format(self.paid_from_account_currency, self.paid_amount, self.paid_from, self.paid_to)] diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index cf4e158bbaa..aa1d5b526c8 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -1020,6 +1020,40 @@ class PurchaseInvoice(BuyingController): # calculate totals again after applying TDS self.calculate_taxes_and_totals() + + def set_status(self, update=False, status=None, update_modified=True): + if self.is_new(): + if self.get('amended_from'): + self.status = 'Draft' + return + + precision = self.precision("outstanding_amount") + outstanding_amount = flt(self.outstanding_amount, precision) + due_date = getdate(self.due_date) + nowdate = getdate() + + if not status: + if self.docstatus == 2: + status = "Cancelled" + elif self.docstatus == 1: + if outstanding_amount > 0 and due_date < nowdate: + self.status = "Overdue" + elif outstanding_amount > 0 and due_date >= nowdate: + self.status = "Unpaid" + #Check if outstanding amount is 0 due to debit note issued against invoice + elif outstanding_amount <= 0 and self.is_return == 0 and frappe.db.get_value('Purchase Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}): + self.status = "Debit Note Issued" + elif self.is_return == 1: + self.status = "Return" + elif outstanding_amount<=0: + self.status = "Paid" + else: + self.status = "Submitted" + else: + self.status = "Draft" + + if update: + self.db_set('status', self.status, update_modified = update_modified) def get_list_context(context=None): from erpnext.controllers.website_list_for_contact import get_list_context diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index e41ad428469..61700050614 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -86,6 +86,8 @@ class TestPurchaseInvoice(unittest.TestCase): pe.submit() pi_doc = frappe.get_doc('Purchase Invoice', pi_doc.name) + pi_doc.load_from_db() + self.assertTrue(pi_doc.status, "Paid") self.assertRaises(frappe.LinkExistsError, pi_doc.cancel) unlink_payment_on_cancel_of_invoice() @@ -203,7 +205,9 @@ class TestPurchaseInvoice(unittest.TestCase): pi.insert() pi.submit() + pi.load_from_db() + self.assertTrue(pi.status, "Unpaid") self.check_gle_for_pi(pi.name) def check_gle_for_pi(self, pi): @@ -234,6 +238,9 @@ class TestPurchaseInvoice(unittest.TestCase): pi = frappe.copy_doc(test_records[0]) pi.insert() + pi.load_from_db() + + self.assertTrue(pi.status, "Draft") pi.naming_series = 'TEST-' self.assertRaises(frappe.CannotChangeConstantError, pi.save) @@ -248,6 +255,8 @@ class TestPurchaseInvoice(unittest.TestCase): pi.get("taxes").pop(1) pi.insert() pi.submit() + pi.load_from_db() + self.assertTrue(pi.status, "Unpaid") gl_entries = frappe.db.sql("""select account, debit, credit from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s @@ -599,6 +608,11 @@ class TestPurchaseInvoice(unittest.TestCase): # return entry pi1 = make_purchase_invoice(is_return=1, return_against=pi.name, qty=-2, rate=50, update_stock=1) + pi.load_from_db() + self.assertTrue(pi.status, "Debit Note Issued") + pi1.load_from_db() + self.assertTrue(pi1.status, "Return") + actual_qty_2 = get_qty_after_transaction() self.assertEqual(actual_qty_1 - 2, actual_qty_2) @@ -771,6 +785,8 @@ class TestPurchaseInvoice(unittest.TestCase): from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import get_outstanding_amount pi = make_purchase_invoice(item_code = "_Test Item", qty = (5 * -1), rate=500, is_return = 1) + pi.load_from_db() + self.assertTrue(pi.status, "Return") outstanding_amount = get_outstanding_amount(pi.doctype, pi.name, "Creditors - _TC", pi.supplier, "Supplier") diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js index 16061c61ba0..1b8b40459f6 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js @@ -18,6 +18,10 @@ erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.ext refresh: function() { var me = this; this._super(); + + if (this.frm.doc.__islocal && !this.frm.doc.valid_till) { + this.frm.set_value('valid_till', frappe.datetime.add_months(this.frm.doc.transaction_date, 1)); + } if (this.frm.doc.docstatus === 1) { cur_frm.add_custom_button(__("Purchase Order"), this.make_purchase_order, __('Create')); diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json index 82fc6285bcf..3bc441af6d1 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json @@ -13,9 +13,10 @@ "supplier", "supplier_name", "column_break1", - "transaction_date", - "amended_from", "company", + "transaction_date", + "valid_till", + "amended_from", "address_section", "supplier_address", "contact_person", @@ -791,13 +792,18 @@ "options": "Opportunity", "print_hide": 1, "read_only": 1 + }, + { + "fieldname": "valid_till", + "fieldtype": "Date", + "label": "Valid Till" } ], "icon": "fa fa-shopping-cart", "idx": 29, "is_submittable": 1, "links": [], - "modified": "2019-12-30 19:17:28.208693", + "modified": "2020-04-15 11:44:52.958022", "modified_by": "Administrator", "module": "Buying", "name": "Supplier Quotation", diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py index 5b4356a7471..baf245735a4 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe from frappe import _ -from frappe.utils import flt, nowdate, add_days +from frappe.utils import flt, nowdate, add_days, getdate from frappe.model.mapper import get_mapped_doc from erpnext.controllers.buying_controller import BuyingController @@ -28,6 +28,7 @@ class SupplierQuotation(BuyingController): validate_for_items(self) self.validate_with_previous_doc() self.validate_uom_is_integer("uom", "qty") + self.validate_valid_till() def on_submit(self): frappe.db.set(self, "status", "Submitted") @@ -52,6 +53,11 @@ class SupplierQuotation(BuyingController): "is_child_table": True } }) + + def validate_valid_till(self): + if self.valid_till and getdate(self.valid_till) < getdate(self.transaction_date): + frappe.throw(_("Valid till Date cannot be before Transaction Date")) + def update_rfq_supplier_status(self, include_me): rfq_list = set([]) for item in self.items: @@ -158,3 +164,11 @@ def make_quotation(source_name, target_doc=None): }, target_doc) return doclist + +def set_expired_status(): + frappe.db.sql(""" + UPDATE + `tabSupplier Quotation` SET `status` = 'Expired' + WHERE + `status` not in ('Cancelled', 'Stopped') AND `valid_till` < %s + """, (nowdate())) \ No newline at end of file diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation_list.js b/erpnext/buying/doctype/supplier_quotation/supplier_quotation_list.js index 95554397bb7..9f4fecea86b 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation_list.js +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation_list.js @@ -5,6 +5,8 @@ frappe.listview_settings['Supplier Quotation'] = { return [__("Ordered"), "green", "status,=,Ordered"]; } else if(doc.status==="Rejected") { return [__("Lost"), "darkgrey", "status,=,Lost"]; + } else if(doc.status==="Expired") { + return [__("Expired"), "darkgrey", "status,=,Expired"]; } } }; diff --git a/erpnext/buying/report/quoted_item_comparison/quoted_item_comparison.js b/erpnext/buying/report/quoted_item_comparison/quoted_item_comparison.js index 3d05612c9ed..a76ffeec2ec 100644 --- a/erpnext/buying/report/quoted_item_comparison/quoted_item_comparison.js +++ b/erpnext/buying/report/quoted_item_comparison/quoted_item_comparison.js @@ -5,20 +5,18 @@ frappe.query_reports["Quoted Item Comparison"] = { filters: [ { fieldtype: "Link", - label: __("Supplier Quotation"), - options: "Supplier Quotation", - fieldname: "supplier_quotation", - default: "", - get_query: () => { - return { filters: { "docstatus": ["<", 2] } } - } + label: __("Company"), + options: "Company", + fieldname: "company", + default: frappe.defaults.get_user_default("Company"), + "reqd": 1 }, { reqd: 1, default: "", options: "Item", label: __("Item"), - fieldname: "item", + fieldname: "item_code", fieldtype: "Link", get_query: () => { let quote = frappe.query_report.get_filter_value('supplier_quotation'); @@ -37,8 +35,37 @@ frappe.query_reports["Quoted Item Comparison"] = { } } } + }, + { + fieldname: "supplier", + label: __("Supplier"), + fieldtype: "MultiSelectList", + get_data: function(txt) { + return frappe.db.get_link_options('Supplier', txt); + } + }, + { + fieldtype: "Link", + label: __("Supplier Quotation"), + options: "Supplier Quotation", + fieldname: "supplier_quotation", + default: "", + get_query: () => { + return { filters: { "docstatus": ["<", 2] } } + } + }, + { + fieldtype: "Link", + label: __("Request for Quotation"), + options: "Request for Quotation", + fieldname: "request_for_quotation", + default: "", + get_query: () => { + return { filters: { "docstatus": ["<", 2] } } + } } ], + onload: (report) => { // Create a button for setting the default supplier report.page.add_inner_button(__("Select Default Supplier"), () => { @@ -102,6 +129,4 @@ frappe.query_reports["Quoted Item Comparison"] = { }); dialog.show(); } -} - - +} \ No newline at end of file diff --git a/erpnext/buying/report/quoted_item_comparison/quoted_item_comparison.py b/erpnext/buying/report/quoted_item_comparison/quoted_item_comparison.py index 5aff6bacaea..a33867a525e 100644 --- a/erpnext/buying/report/quoted_item_comparison/quoted_item_comparison.py +++ b/erpnext/buying/report/quoted_item_comparison/quoted_item_comparison.py @@ -2,103 +2,180 @@ # For license information, please see license.txt from __future__ import unicode_literals -from erpnext.setup.utils import get_exchange_rate -from frappe.utils import flt, cint import frappe +from frappe.utils import flt, cint +from frappe import _ +from collections import defaultdict +from erpnext.setup.utils import get_exchange_rate def execute(filters=None): - qty_list = get_quantity_list(filters.item) - data = get_quote_list(filters.item, qty_list) - columns = get_columns(qty_list) - return columns, data - -def get_quote_list(item, qty_list): - out = [] - if not item: + if not filters: + return [], [] + + conditions = get_conditions(filters) + supplier_quotation_data = get_data(filters, conditions) + columns = get_columns() + + data, chart_data = prepare_data(supplier_quotation_data) + + return columns, data, None, chart_data + +def get_conditions(filters): + conditions = "" + if filters.get("supplier_quotation"): + conditions += " AND sqi.parent = %(supplier_quotation)s" + + if filters.get("request_for_quotation"): + conditions += " AND sqi.request_for_quotation = %(request_for_quotation)s" + + if filters.get("supplier"): + conditions += " AND sq.supplier in %(supplier)s" + return conditions + +def get_data(filters, conditions): + if not filters.get("item_code"): return [] - suppliers = [] - price_data = [] - company_currency = frappe.db.get_default("currency") - float_precision = cint(frappe.db.get_default("float_precision")) or 2 - # Get the list of suppliers - for root in frappe.db.sql("""select parent, qty, rate from `tabSupplier Quotation Item` - where item_code=%s and docstatus < 2""", item, as_dict=1): - for splr in frappe.db.sql("""select supplier from `tabSupplier Quotation` - where name =%s and docstatus < 2""", root.parent, as_dict=1): - ip = frappe._dict({ - "supplier": splr.supplier, - "qty": root.qty, - "parent": root.parent, - "rate": root.rate - }) - price_data.append(ip) - suppliers.append(splr.supplier) + supplier_quotation_data = frappe.db.sql("""SELECT + sqi.parent, sqi.qty, sqi.rate, sqi.uom, sqi.request_for_quotation, + sq.supplier + FROM + `tabSupplier Quotation Item` sqi, + `tabSupplier Quotation` sq + WHERE + sqi.item_code = %(item_code)s + AND sqi.parent = sq.name + AND sqi.docstatus < 2 + AND sq.company = %(company)s + AND sq.status != 'Expired' + {0}""".format(conditions), filters, as_dict=1) + + return supplier_quotation_data + +def prepare_data(supplier_quotation_data): + out, suppliers, qty_list = [], [], [] + supplier_wise_map = defaultdict(list) + supplier_qty_price_map = {} + + company_currency = frappe.db.get_default("currency") + float_precision = cint(frappe.db.get_default("float_precision")) or 2 + + for data in supplier_quotation_data: + supplier = data.get("supplier") + supplier_currency = frappe.db.get_value("Supplier", data.get("supplier"), "default_currency") - #Add a row for each supplier - for root in set(suppliers): - supplier_currency = frappe.db.get_value("Supplier", root, "default_currency") if supplier_currency: exchange_rate = get_exchange_rate(supplier_currency, company_currency) else: exchange_rate = 1 - row = frappe._dict({ - "supplier_name": root - }) - for col in qty_list: - # Get the quantity for this row - for item_price in price_data: - if str(item_price.qty) == col.key and item_price.supplier == root: - row[col.key] = flt(item_price.rate * exchange_rate, float_precision) - row[col.key + "QUOTE"] = item_price.parent - break - else: - row[col.key] = "" - row[col.key + "QUOTE"] = "" - out.append(row) - - return out - -def get_quantity_list(item): - out = [] - - if item: - qty_list = frappe.db.sql("""select distinct qty from `tabSupplier Quotation Item` - where ifnull(item_code,'')=%s and docstatus < 2 order by qty""", item, as_dict=1) + row = { + "quotation": data.get("parent"), + "qty": data.get("qty"), + "price": flt(data.get("rate") * exchange_rate, float_precision), + "uom": data.get("uom"), + "request_for_quotation": data.get("request_for_quotation"), + } - for qt in qty_list: - col = frappe._dict({ - "key": str(qt.qty), - "label": "Qty: " + str(int(qt.qty)) - }) - out.append(col) + # map for report view of form {'supplier1':[{},{},...]} + supplier_wise_map[supplier].append(row) - return out - -def get_columns(qty_list): + # map for chart preparation of the form {'supplier1': {'qty': 'price'}} + if not supplier in supplier_qty_price_map: + supplier_qty_price_map[supplier] = {} + supplier_qty_price_map[supplier][row["qty"]] = row["price"] + + suppliers.append(supplier) + qty_list.append(data.get("qty")) + + suppliers = list(set(suppliers)) + qty_list = list(set(qty_list)) + + # final data format for report view + for supplier in suppliers: + supplier_wise_map[supplier][0].update({"supplier_name": supplier}) + for entry in supplier_wise_map[supplier]: + out.append(entry) + + chart_data = prepare_chart_data(suppliers, qty_list, supplier_qty_price_map) + + return out, chart_data + +def prepare_chart_data(suppliers, qty_list, supplier_qty_price_map): + data_points_map = {} + qty_list.sort() + + # create qty wise values map of the form {'qty1':[value1, value2]} + for supplier in suppliers: + entry = supplier_qty_price_map[supplier] + for qty in qty_list: + if not qty in data_points_map: + data_points_map[qty] = [] + if qty in entry: + data_points_map[qty].append(entry[qty]) + else: + data_points_map[qty].append(None) + + dataset = [] + for qty in qty_list: + datapoints = { + "name": _("Price for Qty ") + str(qty), + "values": data_points_map[qty] + } + dataset.append(datapoints) + + chart_data = { + "data": { + "labels": suppliers, + "datasets": dataset + }, + "type": "bar" + } + + return chart_data + +def get_columns(): columns = [{ "fieldname": "supplier_name", - "label": "Supplier", + "label": _("Supplier"), "fieldtype": "Link", "options": "Supplier", "width": 200 - }] - - for qty in qty_list: - columns.append({ - "fieldname": qty.key, - "label": qty.label, - "fieldtype": "Currency", - "options": "currency", - "width": 80 - }) - columns.append({ - "fieldname": qty.key + "QUOTE", - "label": "Quotation", - "fieldtype": "Link", - "options": "Supplier Quotation", - "width": 90 - }) + }, + { + "fieldname": "quotation", + "label": _("Supplier Quotation"), + "fieldtype": "Link", + "options": "Supplier Quotation", + "width": 200 + }, + { + "fieldname": "qty", + "label": _("Quantity"), + "fieldtype": "Float", + "width": 80 + }, + { + "fieldname": "price", + "label": _("Price"), + "fieldtype": "Currency", + "options": "Company:company:default_currency", + "width": 110 + }, + { + "fieldname": "uom", + "label": _("UOM"), + "fieldtype": "Link", + "options": "UOM", + "width": 90 + }, + { + "fieldname": "request_for_quotation", + "label": _("Request for Quotation"), + "fieldtype": "Link", + "options": "Request for Quotation", + "width": 200 + } + ] return columns \ No newline at end of file diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index de76e45cd11..b465a106f0e 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -69,17 +69,6 @@ status_map = { ["Cancelled", "eval:self.docstatus==2"], ["Closed", "eval:self.status=='Closed'"], ], - "Purchase Invoice": [ - ["Draft", None], - ["Submitted", "eval:self.docstatus==1"], - ["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1"], - ["Return", "eval:self.is_return==1 and self.docstatus==1"], - ["Debit Note Issued", - "eval:self.outstanding_amount <= 0 and self.docstatus==1 and self.is_return==0 and get_value('Purchase Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1})"], - ["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"], - ["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"], - ["Cancelled", "eval:self.docstatus==2"], - ], "Material Request": [ ["Draft", None], ["Stopped", "eval:self.status == 'Stopped'"], diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 6b198e744cc..ab161aa9f51 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -308,7 +308,8 @@ scheduler_events = { "erpnext.crm.doctype.email_campaign.email_campaign.send_email_to_leads_or_contacts", "erpnext.crm.doctype.email_campaign.email_campaign.set_email_campaign_status", "erpnext.selling.doctype.quotation.quotation.set_expired_status", - "erpnext.healthcare.doctype.patient_appointment.patient_appointment.update_appointment_status" + "erpnext.healthcare.doctype.patient_appointment.patient_appointment.update_appointment_status", + "erpnext.buying.doctype.supplier_quotation.supplier_quotation.set_expired_status" ], "daily_long": [ "erpnext.setup.doctype.email_digest.email_digest.send", diff --git a/erpnext/hr/doctype/employee_other_income/employee_other_income.json b/erpnext/hr/doctype/employee_other_income/employee_other_income.json index 2dd6c10988d..8abfe1e93a8 100644 --- a/erpnext/hr/doctype/employee_other_income/employee_other_income.json +++ b/erpnext/hr/doctype/employee_other_income/employee_other_income.json @@ -76,25 +76,15 @@ ], "is_submittable": 1, "links": [], - "modified": "2020-03-19 18:06:45.361830", + "modified": "2020-05-14 17:17:38.883126", "modified_by": "Administrator", "module": "HR", "name": "Employee Other Income", "owner": "Administrator", "permissions": [ { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "share": 1, - "write": 1 - }, - { + "amend": 1, + "cancel": 1, "create": 1, "delete": 1, "email": 1, @@ -104,9 +94,12 @@ "report": 1, "role": "HR Manager", "share": 1, + "submit": 1, "write": 1 }, { + "amend": 1, + "cancel": 1, "create": 1, "delete": 1, "email": 1, @@ -116,9 +109,12 @@ "report": 1, "role": "HR User", "share": 1, + "submit": 1, "write": 1 }, { + "amend": 1, + "cancel": 1, "create": 1, "delete": 1, "email": 1, @@ -128,6 +124,7 @@ "report": 1, "role": "Employee", "share": 1, + "submit": 1, "write": 1 } ], diff --git a/erpnext/patches.txt b/erpnext/patches.txt index e7df4722723..ebbcccc7109 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -683,3 +683,4 @@ erpnext.patches.v13_0.patch_to_fix_reverse_linking_in_additional_salary_encashme execute:frappe.delete_doc_if_exists("Page", "appointment-analytic") execute:frappe.rename_doc("Desk Page", "Getting Started", "Home", force=True) erpnext.patches.v12_0.unset_customer_supplier_based_on_type_of_item_price +erpnext.patches.v12_0.set_valid_till_date_in_supplier_quotation diff --git a/erpnext/patches/v12_0/set_valid_till_date_in_supplier_quotation.py b/erpnext/patches/v12_0/set_valid_till_date_in_supplier_quotation.py new file mode 100644 index 00000000000..4a6e2288564 --- /dev/null +++ b/erpnext/patches/v12_0/set_valid_till_date_in_supplier_quotation.py @@ -0,0 +1,8 @@ +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.reload_doc("buying", "doctype", "supplier_quotation") + frappe.db.sql("""UPDATE `tabSupplier Quotation` + SET valid_till = DATE_ADD(transaction_date , INTERVAL 1 MONTH) + WHERE docstatus < 2""") diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index 33098587c2a..732780a0a33 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -251,8 +251,7 @@ def get_tax_template_for_sez(party_details, master_doctype, company, party_type) def calculate_annual_eligible_hra_exemption(doc): - basic_component = frappe.get_cached_value('Company', doc.company, "basic_component") - hra_component = frappe.get_cached_value('Company', doc.company, "hra_component") + basic_component, hra_component = frappe.db.get_value('Company', doc.company, ["basic_component", "hra_component"]) if not (basic_component and hra_component): frappe.throw(_("Please mention Basic and HRA component in Company")) annual_exemption, monthly_exemption, hra_amount = 0, 0, 0 diff --git a/erpnext/shopping_cart/product_info.py b/erpnext/shopping_cart/product_info.py index a7da09cb808..21ee335125b 100644 --- a/erpnext/shopping_cart/product_info.py +++ b/erpnext/shopping_cart/product_info.py @@ -10,14 +10,16 @@ from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings from erpnext.utilities.product import get_price, get_qty_in_stock, get_non_stock_item_status @frappe.whitelist(allow_guest=True) -def get_product_info_for_website(item_code): +def get_product_info_for_website(item_code, skip_quotation_creation=False): """get product price / stock info for website""" cart_settings = get_shopping_cart_settings() if not cart_settings.enabled: return frappe._dict() - cart_quotation = _get_cart_quotation() + cart_quotation = frappe._dict() + if not skip_quotation_creation: + cart_quotation = _get_cart_quotation() price = get_price( item_code, @@ -51,7 +53,7 @@ def get_product_info_for_website(item_code): def set_product_info_for_website(item): """set product price uom for website""" - product_info = get_product_info_for_website(item.item_code) + product_info = get_product_info_for_website(item.item_code, skip_quotation_creation=True) if product_info: item.update(product_info) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 4cc50bba9ea..7a1c1279eae 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -467,7 +467,7 @@ class Item(WebsiteGenerator): def set_shopping_cart_data(self, context): from erpnext.shopping_cart.product_info import get_product_info_for_website - context.shopping_cart = get_product_info_for_website(self.name) + context.shopping_cart = get_product_info_for_website(self.name, skip_quotation_creation=True) def add_default_uom_in_conversion_factor_table(self): uom_conv_list = [d.uom for d in self.get("uoms")]