def upload(select_doctype=None, rows=None): from webnotes.utils.datautils import read_csv_content_from_uploaded_file from webnotes.modules import scrub from webnotes.model.rename_doc import rename_doc if not select_doctype: select_doctype = webnotes.form_dict.select_doctype if not rows: rows = read_csv_content_from_uploaded_file() if not rows: webnotes.msgprint(_("Please select a valid csv file with data.")) raise Exception if len(rows) > 500: webnotes.msgprint(_("Max 500 rows only.")) raise Exception rename_log = [] for row in rows: if len(row) > 2: try: if rename_doc(select_doctype, row[0], row[1]): rename_log.append(_("Successful: ") + row[0] + " -> " + row[1]) webnotes.conn.commit() else: rename_log.append(_("Ignored: ") + row[0] + " -> " + row[1]) except Exception, e: rename_log.append("<span style='color: RED'>" + \ _("Failed: ") + row[0] + " -> " + row[1] + "</span>") rename_log.append("<span style='margin-left: 20px;'>" + repr(e) + "</span>")
def validate_item(self, item_code, row_num): from stock.utils import validate_end_of_life, validate_is_stock_item, \ validate_cancelled_item # using try except to catch all validation msgs and display together try: item = webnotes.doc("Item", item_code) # end of life and stock item validate_end_of_life(item_code, item.end_of_life, verbose=0) validate_is_stock_item(item_code, item.is_stock_item, verbose=0) # item should not be serialized if item.has_serial_no == "Yes": raise webnotes.ValidationError, (_("Serialized Item: '") + item_code + _("""' can not be managed using Stock Reconciliation.\ You can add/delete Serial No directly, \ to modify stock of this item.""")) # docstatus should be < 2 validate_cancelled_item(item_code, item.docstatus, verbose=0) except Exception, e: self.validation_messages.append(_("Row # ") + ("%d: " % (row_num+2)) + cstr(e))
def validate_value(self, fieldname, condition, val2, doc=None, raise_exception=None): """check that value of fieldname should be 'condition' val2 else throw exception""" if not doc: doc = self.doc df = self.meta.get_field(fieldname, parent=doc.doctype) val1 = doc.fields.get(fieldname) if df.fieldtype in ("Currency", "Float"): val1 = flt(val1, self.precision(df.fieldname, doc.parentfield or None)) val2 = flt(val2, self.precision(df.fieldname, doc.parentfield or None)) elif df.fieldtype in ("Int", "Check"): val1 = cint(val1) val2 = cint(val2) if not webnotes.compare(val1, condition, val2): msg = _("Error") + ": " if doc.parentfield: msg += _("Row") + (" # %d: " % doc.idx) msg += _(self.meta.get_label(fieldname, parent=doc.doctype)) \ + " " + error_condition_map.get(condition, "") + " " + cstr(val2) # raise passed exception or True msgprint(msg, raise_exception=raise_exception or True)
def validate_expense_against_budget(args): args = webnotes._dict(args) if webnotes.conn.get_value("Account", {"name": args.account, "is_pl_account": "Yes", "debit_or_credit": "Debit"}): budget = webnotes.conn.sql(""" select bd.budget_allocated, cc.distribution_id from `tabCost Center` cc, `tabBudget Detail` bd where cc.name=bd.parent and cc.name=%s and account=%s and bd.fiscal_year=%s """, (args.cost_center, args.account, args.fiscal_year), as_dict=True) if budget and budget[0].budget_allocated: yearly_action, monthly_action = webnotes.conn.get_value("Company", args.company, ["yearly_bgt_flag", "monthly_bgt_flag"]) action_for = action = "" if monthly_action in ["Stop", "Warn"]: budget_amount = get_allocated_budget(budget[0].distribution_id, args.posting_date, args.fiscal_year, budget[0].budget_allocated) args["month_end_date"] = webnotes.conn.sql("select LAST_DAY(%s)", args.posting_date)[0][0] action_for, action = "Monthly", monthly_action elif yearly_action in ["Stop", "Warn"]: budget_amount = budget[0].budget_allocated action_for, action = "Monthly", yearly_action if action_for: actual_expense = get_actual_expense(args) if actual_expense > budget_amount: webnotes.msgprint(action_for + _(" budget ") + cstr(budget_amount) + _(" for account ") + args.account + _(" against cost center ") + args.cost_center + _(" will exceed by ") + cstr(actual_expense - budget_amount) + _(" after this transaction.") , raise_exception=BudgetError if action=="Stop" else False)
def update_outstanding_amt(account, against_voucher_type, against_voucher, on_cancel=False): # get final outstanding amt bal = flt(webnotes.conn.sql("""select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0)) from `tabGL Entry` where against_voucher_type=%s and against_voucher=%s and account = %s""", (against_voucher_type, against_voucher, account))[0][0] or 0.0) if against_voucher_type == 'Purchase Invoice': bal = -bal elif against_voucher_type == "Journal Voucher": against_voucher_amount = flt(webnotes.conn.sql(""" select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0)) from `tabGL Entry` where voucher_type = 'Journal Voucher' and voucher_no = %s and account = %s and ifnull(against_voucher, '') = ''""", (against_voucher, account))[0][0]) bal = against_voucher_amount + bal if against_voucher_amount < 0: bal = -bal # Validation : Outstanding can not be negative if bal < 0 and not on_cancel: webnotes.throw(_("Outstanding for Voucher ") + against_voucher + _(" will become ") + fmt_money(bal) + _(". Outstanding cannot be less than zero. \ Please match exact outstanding.")) # Update outstanding amt on against voucher if against_voucher_type in ["Sales Invoice", "Purchase Invoice"]: webnotes.conn.sql("update `tab%s` set outstanding_amount=%s where name='%s'" % (against_voucher_type, bal, against_voucher))
def update_last_purchase_rate(self, obj, is_submit): """updates last_purchase_rate in item table for each item""" import webnotes.utils this_purchase_date = webnotes.utils.getdate(obj.doc.fields.get('posting_date') or obj.doc.fields.get('transaction_date')) for d in getlist(obj.doclist,obj.fname): # get last purchase details last_purchase_details = get_last_purchase_details(d.item_code, obj.doc.name) # compare last purchase date and this transaction's date last_purchase_rate = None if last_purchase_details and \ (last_purchase_details.purchase_date > this_purchase_date): last_purchase_rate = last_purchase_details['purchase_rate'] elif is_submit == 1: # even if this transaction is the latest one, it should be submitted # for it to be considered for latest purchase rate if flt(d.conversion_factor): last_purchase_rate = flt(d.purchase_rate) / flt(d.conversion_factor) else: msgprint(_("Row ") + cstr(d.idx) + ": " + _("UOM Conversion Factor is mandatory"), raise_exception=1) # update last purchsae rate if last_purchase_rate: webnotes.conn.sql("update `tabItem` set last_purchase_rate = %s where name = %s", (flt(last_purchase_rate),d.item_code))
def validate_max_discount(self): for d in self.doclist.get({"parentfield": self.fname}): discount = flt(webnotes.conn.get_value("Item", d.item_code, "max_discount")) if discount and flt(d.adj_rate) > discount: webnotes.throw(_("You cannot give more than ") + cstr(discount) + "% " + _("discount on Item Code") + ": " + cstr(d.item_code))
def validate_production_order_against_so(self): # already ordered qty ordered_qty_against_so = webnotes.conn.sql("""select sum(qty) from `tabProduction Order` where production_item = %s and sales_order = %s and docstatus < 2 and name != %s""", (self.doc.production_item, self.doc.sales_order, self.doc.name))[0][0] total_qty = flt(ordered_qty_against_so) + flt(self.doc.qty) # get qty from Sales Order Item table so_item_qty = webnotes.conn.sql("""select sum(qty) from `tabSales Order Item` where parent = %s and item_code = %s""", (self.doc.sales_order, self.doc.production_item))[0][0] # get qty from Packing Item table dnpi_qty = webnotes.conn.sql("""select sum(qty) from `tabPacked Item` where parent = %s and parenttype = 'Sales Order' and item_code = %s""", (self.doc.sales_order, self.doc.production_item))[0][0] # total qty in SO so_qty = flt(so_item_qty) + flt(dnpi_qty) if total_qty > so_qty: webnotes.throw(_("Total production order qty for item") + ": " + cstr(self.doc.production_item) + _(" against sales order") + ": " + cstr(self.doc.sales_order) + _(" will be ") + cstr(total_qty) + ", " + _("which is greater than sales order qty ") + "(" + cstr(so_qty) + ")" + _("Please reduce qty."), exc=OverProductionError)
def validate_duplicate_record(self): res = sql("""select name from `tabAttendance` where employee = %s and att_date = %s and name != %s and docstatus = 1""", (self.doc.employee, self.doc.att_date, self.doc.name)) if res: msgprint(_("Attendance for the employee: ") + self.doc.employee + _(" already marked"), raise_exception=1)
def update_dob_event(self): if self.doc.status == "Active" and self.doc.date_of_birth \ and not cint(webnotes.conn.get_value("HR Settings", None, "stop_birthday_reminders")): birthday_event = webnotes.conn.sql("""select name from `tabEvent` where repeat_on='Every Year' and ref_type='Employee' and ref_name=%s""", self.doc.name) starts_on = self.doc.date_of_birth + " 00:00:00" ends_on = self.doc.date_of_birth + " 00:15:00" if birthday_event: event = webnotes.bean("Event", birthday_event[0][0]) event.doc.starts_on = starts_on event.doc.ends_on = ends_on event.save() else: webnotes.bean({ "doctype": "Event", "subject": _("Birthday") + ": " + self.doc.employee_name, "description": _("Happy Birthday!") + " " + self.doc.employee_name, "starts_on": starts_on, "ends_on": ends_on, "event_type": "Public", "all_day": 1, "send_reminder": 1, "repeat_this_event": 1, "repeat_on": "Every Year", "ref_type": "Employee", "ref_name": self.doc.name }).insert() else: webnotes.conn.sql("""delete from `tabEvent` where repeat_on='Every Year' and ref_type='Employee' and ref_name=%s""", self.doc.name)
def validate_order_type(self): valid_types = ["Sales", "Maintenance", "Shopping Cart"] if not self.doc.order_type: self.doc.order_type = "Sales" elif self.doc.order_type not in valid_types: msgprint(_(self.meta.get_label("order_type")) + " " + _("must be one of") + ": " + comma_or(valid_types), raise_exception=True)
def validate_uom_is_integer(doclist, uom_field, qty_fields): if isinstance(qty_fields, basestring): qty_fields = [qty_fields] integer_uoms = filter( lambda uom: webnotes.conn.get_value("UOM", uom, "must_be_whole_number") or None, doclist.get_distinct_values(uom_field), ) if not integer_uoms: return for d in doclist: if d.fields.get(uom_field) in integer_uoms: for f in qty_fields: if d.fields.get(f): if cint(d.fields[f]) != d.fields[f]: webnotes.msgprint( _("For UOM") + " '" + d.fields[uom_field] + "': " + _("Quantity cannot be a fraction.") + " " + _("In Row") + ": " + str(d.idx), raise_exception=UOMMustBeIntegerError, )
def run(report_name, filters=None): report = webnotes.doc("Report", report_name) if filters and isinstance(filters, basestring): filters = json.loads(filters) if not webnotes.has_permission(report.ref_doctype, "report"): webnotes.msgprint(_("Must have report permission to access this report."), raise_exception=True) if report.report_type=="Query Report": if not report.query: webnotes.msgprint(_("Must specify a Query to run"), raise_exception=True) if not report.query.lower().startswith("select"): webnotes.msgprint(_("Query must be a SELECT"), raise_exception=True) result = [list(t) for t in webnotes.conn.sql(report.query, filters)] columns = [c[0] for c in webnotes.conn.get_description()] else: method_name = scrub(webnotes.conn.get_value("DocType", report.ref_doctype, "module")) \ + ".report." + scrub(report.name) + "." + scrub(report.name) + ".execute" columns, result = webnotes.get_method(method_name)(filters or {}) result = get_filtered_data(report.ref_doctype, columns, result) if cint(report.add_total_row) and result: result = add_total_row(result, columns) return { "result": result, "columns": columns }
def update_completed_qty(controller, caller_method): if controller.doc.doctype == "Stock Entry": material_request_map = {} for d in controller.doclist.get({"parentfield": "mtn_details"}): if d.material_request: if d.material_request not in material_request_map: material_request_map[d.material_request] = [] material_request_map[d.material_request].append(d.material_request_item) for mr_name, mr_items in material_request_map.items(): mr_obj = webnotes.get_obj("Material Request", mr_name, with_children=1) mr_doctype = webnotes.get_doctype("Material Request") if mr_obj.doc.status in ["Stopped", "Cancelled"]: msgprint( _("Material Request") + ": %s, " % mr_obj.doc.name + _(mr_doctype.get_label("status")) + " = %s. " % _(mr_obj.doc.status) + _("Cannot continue."), raise_exception=webnotes.InvalidStatusError, ) _update_requested_qty(controller, mr_obj, mr_items) # update ordered percentage and qty mr_obj.update_completed_qty(mr_items)
def _get_message(url=False): if url: name = get_url_to_form(self.doc.doctype, self.doc.name) else: name = self.doc.name return (_("Leave Application") + ": %s - %s") % (name, _(status))
def validate(self): if self.doc.buying_or_selling not in ["Buying", "Selling"]: msgprint(_(self.meta.get_label("buying_or_selling")) + " " + _("must be one of") + " " + comma_or(["Buying", "Selling"]), raise_exception=True) # at least one territory self.validate_table_has_rows("valid_for_territories")
def place_order(): quotation = _get_cart_quotation() quotation.doc.company = webnotes.conn.get_value("Shopping Cart Settings", None, "company") controller = quotation.make_controller() for fieldname in ["customer_address", "shipping_address_name"]: if not quotation.doc.fields.get(fieldname): msgprint(_("Please select a") + " " + _(controller.meta.get_label(fieldname)), raise_exception=True) quotation.ignore_permissions = True quotation.submit() if quotation.doc.lead: # company used to create customer accounts webnotes.defaults.set_user_default("company", quotation.doc.company) from selling.doctype.quotation.quotation import _make_sales_order sales_order = webnotes.bean(_make_sales_order(quotation.doc.name, ignore_permissions=True)) for item in sales_order.doclist.get({"parentfield": "sales_order_details"}): item.reserved_warehouse = webnotes.conn.get_value("Item", item.item_code, "website_warehouse") or None sales_order.ignore_permissions = True sales_order.insert() sales_order.submit() webnotes._response.set_cookie("cart_count", "") return sales_order.doc.name
def check_if_latest(self, method="save"): from webnotes.model.meta import is_single conflict = False if not cint(self.doc.fields.get('__islocal')): if is_single(self.doc.doctype): modified = webnotes.conn.get_value(self.doc.doctype, self.doc.name, "modified") if isinstance(modified, list): modified = modified[0] if cstr(modified) and cstr(modified) != cstr(self.doc.modified): conflict = True else: tmp = webnotes.conn.sql("""select modified, docstatus from `tab%s` where name="%s" for update""" % (self.doc.doctype, self.doc.name), as_dict=True) if not tmp: webnotes.msgprint("""This record does not exist. Please refresh.""", raise_exception=1) modified = cstr(tmp[0].modified) if modified and modified != cstr(self.doc.modified): conflict = True self.check_docstatus_transition(tmp[0].docstatus, method) if conflict: webnotes.msgprint(_("Error: Document has been modified after you have opened it") \ + (" (%s, %s). " % (modified, self.doc.modified)) \ + _("Please refresh to get the latest document."), raise_exception=TimestampMismatchError)
def validate_warehouse(self): if not self.doc.fields.get("__islocal"): item_code, warehouse = webnotes.conn.get_value("Serial No", self.doc.name, ["item_code", "warehouse"]) if item_code != self.doc.item_code: webnotes.throw(_("Item Code cannot be changed for Serial No."), SerialNoCannotCannotChangeError) if not self.via_stock_ledger and warehouse != self.doc.warehouse: webnotes.throw(_("Warehouse cannot be changed for Serial No."), SerialNoCannotCannotChangeError)
def run(report_name): report = webnotes.doc("Report", report_name) if not webnotes.has_permission(report.ref_doctype, "report"): webnotes.msgprint(_("Must have report permission to access this report."), raise_exception=True) if report.report_type=="Query Report": if not report.query: webnotes.msgprint(_("Must specify a Query to run"), raise_exception=True) if not report.query.lower().startswith("select"): webnotes.msgprint(_("Query must be a SELECT"), raise_exception=True) result = [list(t) for t in webnotes.conn.sql(report.query)] columns = [c[0] for c in webnotes.conn.get_description()] else: from webnotes.modules import scrub method_name = scrub(webnotes.conn.get_value("DocType", report.ref_doctype, "module")) \ + ".report." + scrub(report.name) + "." + scrub(report.name) + ".execute" columns, result = webnotes.get_method(method_name)() return { "result": result, "columns": columns }
def sign_up(email, full_name): profile = webnotes.conn.get("Profile", {"email": email}) if profile: if profile.disabled: return _("Registered but disabled.") else: return _("Already Registered") else: if ( webnotes.conn.sql( """select count(*) from tabProfile where TIMEDIFF(%s, modified) > '1:00:00' """, now(), )[0][0] > 200 ): raise Exception, "Too Many New Profiles" from webnotes.utils import random_string profile = webnotes.bean( { "doctype": "Profile", "email": email, "first_name": full_name, "enabled": 1, "new_password": random_string(10), "user_type": "Website User", } ) profile.ignore_permissions = True profile.insert() return _("Registration Details Emailed.")
def validate_filters(filters, account_details): if account_details and account_details.group_or_ledger == "Ledger" \ and filters.get("group_by") == "Group by Account": webnotes.throw(_("Can not filter based on Account, if grouped by Account")) if filters.get("voucher_no") and filters.get("group_by") == "Group by Voucher": webnotes.throw(_("Can not filter based on Voucher No, if grouped by Voucher"))
def validate_conversion_factor(self): check_list = [] for d in getlist(self.doclist, "uom_conversion_details"): if cstr(d.uom) in check_list: msgprint( _("UOM %s has been entered more than once in Conversion Factor Table." % cstr(d.uom)), raise_exception=1, ) else: check_list.append(cstr(d.uom)) if d.uom and cstr(d.uom) == cstr(self.doc.stock_uom) and flt(d.conversion_factor) != 1: msgprint( _( """Conversion Factor of UOM: %s should be equal to 1. As UOM: %s is Stock UOM of Item: %s.""" % (d.uom, d.uom, self.doc.name) ), raise_exception=1, ) elif d.uom and cstr(d.uom) != self.doc.stock_uom and flt(d.conversion_factor) == 1: msgprint( _( """Conversion Factor of UOM: %s should not be equal to 1. As UOM: %s is not Stock UOM of Item: %s""" % (d.uom, d.uom, self.doc.name) ), raise_exception=1, )
def on_trash(self): parent = self.doc.fields[self.nsm_parent_field] if not parent: msgprint(_("Root ") + self.doc.doctype + _(" cannot be deleted."), raise_exception=1) parent = "" update_nsm(self)
def validate_data(self): if not self.doc.reconciliation_json: return data = json.loads(self.doc.reconciliation_json) # strip out extra columns (if any) data = [row[:4] for row in data] if self.head_row not in data: msgprint(_("""Wrong Template: Unable to find head row."""), raise_exception=1) # remove the help part and save the json if data.index(self.head_row) != 0: data = data[data.index(self.head_row):] self.doc.reconciliation_json = json.dumps(data) def _get_msg(row_num, msg): return _("Row # ") + ("%d: " % (row_num+2)) + _(msg) self.validation_messages = [] item_warehouse_combinations = [] # validate no of rows rows = data[data.index(self.head_row)+1:] if len(rows) > 100: msgprint(_("""Sorry! We can only allow upto 100 rows for Stock Reconciliation."""), raise_exception=True) for row_num, row in enumerate(rows): # find duplicates if [row[0], row[1]] in item_warehouse_combinations: self.validation_messages.append(_get_msg(row_num, "Duplicate entry")) else: item_warehouse_combinations.append([row[0], row[1]]) self.validate_item(row[0], row_num) # note: warehouse will be validated through link validation # if both not specified if row[2] == "" : self.validation_messages.append(_get_msg(row_num, "Please specify Quantity ")) # do not allow negative quantity if flt(row[2]) < 0: self.validation_messages.append(_get_msg(row_num, "Negative Quantity is not allowed")) # do not allow negative valuation #if flt(row[3]) < 0: # self.validation_messages.append(_get_msg(row_num, # "Negative Valuation Rate is not allowed")) # throw all validation messages if self.validation_messages: for msg in self.validation_messages: msgprint(msg) raise webnotes.ValidationError
def update_outstanding_amt(self): # get final outstanding amt bal = flt(sql("""select sum(debit) - sum(credit) from `tabGL Entry` where against_voucher=%s and against_voucher_type=%s and ifnull(is_cancelled,'No') = 'No'""", (self.doc.against_voucher, self.doc.against_voucher_type))[0][0] or 0.0) if self.doc.against_voucher_type == 'Purchase Invoice': bal = -bal elif self.doc.against_voucher_type == "Journal Voucher": against_voucher_amount = flt(webnotes.conn.sql("""select sum(debit) - sum(credit) from `tabGL Entry` where voucher_type = 'Journal Voucher' and voucher_no = %s and account = %s""", (self.doc.against_voucher, self.doc.account))[0][0]) bal = against_voucher_amount + bal if against_voucher_amount < 0: bal = -bal # Validation : Outstanding can not be negative if bal < 0 and self.doc.is_cancelled == 'No': msgprint(_("Outstanding for Voucher ") + self.doc.against_voucher + _(" will become ") + fmt_money(bal) + _(". Outstanding cannot be less than zero. \ Please match exact outstanding."), raise_exception=1) # Update outstanding amt on against voucher if self.doc.against_voucher_type in ["Sales Invoice", "Purchase Invoice"]: sql("update `tab%s` set outstanding_amount=%s where name='%s'"% (self.doc.against_voucher_type, bal, self.doc.against_voucher))
def validate_account_head(self): debit_or_credit, is_pl_account = webnotes.conn.get_value("Account", self.doc.closing_account_head, ["debit_or_credit", "is_pl_account"]) if debit_or_credit != 'Credit' or is_pl_account != 'No': webnotes.throw(_("Account") + ": " + self.doc.closing_account_head + _("must be a Liability account"))
def validate_item(self, item_code, row_num): from stock.utils import validate_end_of_life, validate_is_stock_item, \ validate_cancelled_item # using try except to catch all validation msgs and display together try: item = webnotes.doc("Item", item_code) if not item: raise webnotes.ValidationError, (_("Item: {0} not found in the system").format(item_code)) # end of life and stock item validate_end_of_life(item_code, item.end_of_life, verbose=0) validate_is_stock_item(item_code, item.is_stock_item, verbose=0) # item should not be serialized if item.has_serial_no == "Yes": raise webnotes.ValidationError, (_("Serialized item: {0} can not be managed \ using Stock Reconciliation, use Stock Entry instead").format(item_code)) # item managed batch-wise not allowed if item.has_batch_no == "Yes": raise webnotes.ValidationError, (_("Item: {0} managed batch-wise, can not be \ reconciled using Stock Reconciliation, instead use Stock Entry").format(item_code)) # docstatus should be < 2 validate_cancelled_item(item_code, item.docstatus, verbose=0) except Exception, e: self.validation_messages.append(_("Row # ") + ("%d: " % (row_num)) + cstr(e))
def check_value(self, ref_dt, ref_dn, ref_item_dn, val, item_code): ref_val = webnotes.conn.get_value(ref_dt + " Item", ref_item_dn, "export_rate") if flt(ref_val, 2) != flt(val, 2): msgprint( _("Rate is not matching with ") + ref_dt + ": " + ref_dn + _(" for item: ") + item_code, raise_exception=True, )
def validate_exchange_rates_exist(self): """check if exchange rates exist for all Price List currencies (to company's currency)""" company_currency = webnotes.conn.get_value("Company", self.doc.company, "default_currency") if not company_currency: msgprint(_("Please specify currency in Company") + ": " + self.doc.company, raise_exception=ShoppingCartSetupError) price_list_currency_map = webnotes.conn.get_values("Price List", [d.price_list for d in self.doclist.get({"parentfield": "price_lists"})], "currency") expected_to_exist = [currency + "-" + company_currency for currency in price_list_currency_map.values() if currency != company_currency] if expected_to_exist: exists = webnotes.conn.sql_list("""select name from `tabCurrency Exchange` where name in (%s)""" % (", ".join(["%s"]*len(expected_to_exist)),), tuple(expected_to_exist)) missing = list(set(expected_to_exist).difference(exists)) if missing: msgprint(_("Missing Currency Exchange Rates for" + ": " + comma_and(missing)), raise_exception=ShoppingCartSetupError)
def get_fiscal_years(date=None, fiscal_year=None, label="Date", verbose=1): # if year start date is 2012-04-01, year end date should be 2013-03-31 (hence subdate) cond = "" if fiscal_year: cond = "name = '%s'" % fiscal_year else: cond = "'%s' >= year_start_date and '%s' <= year_end_date" % \ (date, date) fy = webnotes.conn.sql("""select name, year_start_date, year_end_date from `tabFiscal Year` where %s order by year_start_date desc""" % cond) if not fy: error_msg = """%s %s not in any Fiscal Year""" % (label, formatdate(date)) error_msg = """{msg}: {date}""".format(msg=_("Fiscal Year does not exist for date"), date=formatdate(date)) if verbose: webnotes.msgprint(error_msg) raise FiscalYearError, error_msg return fy
def get_rm_rate(self, arg): """ Get raw material rate as per selected method, if bom exists takes bom cost """ rate = 0 if arg['bom_no']: rate = self.get_bom_unitcost(arg['bom_no']) elif arg and (arg['is_purchase_item'] == 'Yes' or arg['is_sub_contracted_item'] == 'Yes'): if self.doc.rm_cost_as_per == 'Valuation Rate': rate = self.get_valuation_rate(arg) elif self.doc.rm_cost_as_per == 'Last Purchase Rate': rate = arg['last_purchase_rate'] elif self.doc.rm_cost_as_per == "Price List": if not self.doc.buying_price_list: webnotes.throw(_("Please select Price List")) rate = webnotes.conn.get_value("Item Price", {"price_list": self.doc.buying_price_list, "parent": arg["item_code"]}, "ref_rate") or 0 elif self.doc.rm_cost_as_per == 'Standard Rate': rate = arg['standard_rate'] return rate
def validate_notification_email_id(self): if self.doc.notification_email_address: email_list = filter(None, [ cstr(email).strip() for email in self.doc.notification_email_address.replace( "\n", "").split(",") ]) from webnotes.utils import validate_email_add for email in email_list: if not validate_email_add(email): msgprint(self.meta.get_label("notification_email_address") \ + " - " + _("Invalid Email Address") + ": \"%s\"" % email, raise_exception=1) else: msgprint( "Notification Email Addresses not specified for recurring invoice", raise_exception=1)
def cant_change(self): if not self.doc.fields.get("__islocal"): vals = webnotes.conn.get_value( "Item", self.doc.name, ["has_serial_no", "is_stock_item", "valuation_method"], as_dict=True) if vals and ((self.doc.is_stock_item == "No" and vals.is_stock_item == "Yes") or vals.has_serial_no != self.doc.has_serial_no or cstr(vals.valuation_method) != cstr( self.doc.valuation_method)): if self.check_if_sle_exists() == "exists": webnotes.msgprint( _("As there are existing stock transactions for this \ item, you can not change the values of 'Has Serial No', \ 'Is Stock Item' and 'Valuation Method'"), raise_exception=1)
def get_conditions(filters): if not (filters.get("month") and filters.get("fiscal_year")): msgprint(_("Please select month and year"), raise_exception=1) filters["month"] = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ].index(filters["month"]) + 1 from calendar import monthrange filters["total_days_in_month"] = monthrange( cint(filters["fiscal_year"].split("-")[-1]), filters["month"])[1] conditions = " and month(att_date) = %(month)s and fiscal_year = %(fiscal_year)s" if filters.get("company"): conditions += " and company = %(company)s" if filters.get("employee"): conditions += " and employee = %(employee)s" return conditions, filters
def validate_warehouse_account(self): if not cint( webnotes.defaults.get_global_default( "auto_accounting_for_stock")): return if self.doc.account_type == "Warehouse": old_warehouse = cstr( webnotes.conn.get_value("Account", self.doc.name, "master_name")) if old_warehouse != cstr(self.doc.master_name): if old_warehouse: self.validate_warehouse(old_warehouse) if self.doc.master_name: self.validate_warehouse(self.doc.master_name) else: webnotes.throw( _("Master Name is mandatory if account type is Warehouse" ))
def set_stock_value_difference(self): """stock_value_difference is the increment in the stock value""" from stock.utils import get_buying_amount item_list = [d.item_code for d in self.entries] warehouse_list = [d.warehouse for d in self.entries] if not (item_list and warehouse_list): webnotes.throw(_("Invalid Item or Warehouse Data")) stock_ledger_entries = self.get_stock_ledger_entries( item_list, warehouse_list) self.doc.stock_value_difference = 0.0 for d in self.entries: self.doc.stock_value_difference -= get_buying_amount( self.doc.doctype, self.doc.name, d.voucher_detail_no, stock_ledger_entries.get((d.item_code, d.warehouse), [])) webnotes.conn.set(self.doc, "stock_value_difference", self.doc.stock_value_difference)
def validate_all_link_fields(self): accounts = { "Account": [ self.doc.cash_bank_account, self.doc.income_account, self.doc.expense_account ], "Cost Center": [self.doc.cost_center], "Warehouse": [self.doc.warehouse] } for link_dt, dn_list in accounts.items(): for link_dn in dn_list: if link_dn and not webnotes.conn.exists({ "doctype": link_dt, "company": self.doc.company, "name": link_dn }): webnotes.throw(link_dn + _(" does not belong to ") + self.doc.company)
def add_block_dates(events, start, end, employee, company): # block days from hr.doctype.leave_block_list.leave_block_list import get_applicable_block_dates cnt = 0 block_dates = get_applicable_block_dates(start, end, employee, company, all_lists=True) for block_date in block_dates: events.append({ "doctype": "Leave Block List Date", "from_date": block_date.block_date, "title": _("Leave Blocked") + ": " + block_date.reason, "name": "_" + str(cnt), }) cnt += 1
def validate(self): if not self.doc.stock_uom: msgprint(_("Please enter Default Unit of Measure"), raise_exception=1) self.check_warehouse_is_set_for_stock_item() self.check_stock_uom_with_bin() self.validate_conversion_factor() self.add_default_uom_in_conversion_factor_table() self.valiadte_item_type() self.check_for_active_boms() self.validate_price_lists() self.fill_customer_code() self.check_item_tax() self.validate_barcode() self.cant_change() self.validate_item_type_for_reorder() if self.doc.name: self.old_page_name = webnotes.conn.get_value('Item', self.doc.name, 'page_name')
def update_birthday_reminders(self): original_stop_birthday_reminders = cint( webnotes.conn.get_value("HR Settings", None, "stop_birthday_reminders")) # reset birthday reminders if cint(self.doc.stop_birthday_reminders ) != original_stop_birthday_reminders: webnotes.conn.sql( """delete from `tabEvent` where repeat_on='Every Year' and ref_type='Employee'""" ) if not self.doc.stop_birthday_reminders: for employee in webnotes.conn.sql_list( """select name from `tabEmployee` where status='Active' and ifnull(date_of_birth, '')!=''"""): webnotes.get_obj("Employee", employee).update_dob_event() webnotes.msgprint(webnotes._("Updated Birthday Reminders"))
def get_gl_entries(self, warehouse_account=None, default_expense_account=None, default_cost_center=None): from accounts.general_ledger import process_gl_map if not warehouse_account: warehouse_account = self.get_warehouse_account() stock_ledger = self.get_stock_ledger_details() voucher_details = self.get_voucher_details(stock_ledger, default_expense_account, default_cost_center) gl_list = [] warehouse_with_no_account = [] for detail in voucher_details: sle_list = stock_ledger.get(detail.name) if sle_list: for sle in sle_list: if warehouse_account.get(sle.warehouse): # from warehouse account gl_list.append(self.get_gl_dict({ "account": warehouse_account[sle.warehouse], "against": detail.expense_account, "cost_center": detail.cost_center, "remarks": self.doc.remarks or "Accounting Entry for Stock", "debit": sle.stock_value_difference })) # to target warehouse / expense account gl_list.append(self.get_gl_dict({ "account": detail.expense_account, "against": warehouse_account[sle.warehouse], "cost_center": detail.cost_center, "remarks": self.doc.remarks or "Accounting Entry for Stock", "credit": sle.stock_value_difference })) elif sle.warehouse not in warehouse_with_no_account: warehouse_with_no_account.append(sle.warehouse) if warehouse_with_no_account: msgprint(_("No accounting entries for following warehouses") + ": \n" + "\n".join(warehouse_with_no_account)) return process_gl_map(gl_list)
def get_conditions(filters): conditions = "" supplier_accounts = [] if filters.get("account"): supplier_accounts = [filters["account"]] else: cond = filters.get("company") and (" and company = '%s'" % filters["company"]) or "" supplier_accounts = webnotes.conn.sql_list("""select name from `tabAccount` where ifnull(master_type, '') = 'Supplier' and docstatus < 2 %s""" % cond) if supplier_accounts: conditions += " and jvd.account in (%s)" % (", ".join(['%s']*len(supplier_accounts))) else: msgprint(_("No Supplier Accounts found. Supplier Accounts are identified based on \ 'Master Type' value in account record."), raise_exception=1) if filters.get("from_date"): conditions += " and jv.posting_date >= '%s'" % filters["from_date"] if filters.get("to_date"): conditions += " and jv.posting_date <= '%s'" % filters["to_date"] return conditions, supplier_accounts
def get_columns(filters): for fieldname in ["fiscal_year", "period", "target_on"]: if not filters.get(fieldname): label = (" ".join(fieldname.split("_"))).title() msgprint(_("Please specify") + ": " + label, raise_exception=True) columns = ["Territory:Link/Territory:120", "Item Group:Link/Item Group:120"] group_months = False if filters["period"] == "Monthly" else True for from_date, to_date in get_period_date_ranges(filters["period"], filters["fiscal_year"]): for label in ["Target (%s)", "Achieved (%s)", "Variance (%s)"]: if group_months: label = label % (from_date.strftime("%b") + " - " + to_date.strftime("%b")) else: label = label % from_date.strftime("%b") columns.append(label+":Float:120") return columns + ["Total Target:Float:120", "Total Achieved:Float:120", "Total Variance:Float:120"]
def prepare_conditions(self): conditions = [""] values = {} if self.filters.company: conditions.append("company=%(company)s") values["company"] = self.filters.company if self.filters.account: conditions.append("account=%(account)s") values["account"] = self.filters.account else: account_map = self.get_account_map() if not account_map: webnotes.throw(_("No Customer Accounts found.")) else: accounts_list = ['"{}"'.format(ac) for ac in account_map] conditions.append("account in ({})".format(", ".join(accounts_list))) return " and ".join(conditions), values
def validate(self): for key in [ "item_naming_by", "item_group", "stock_uom", "allow_negative_stock" ]: webnotes.conn.set_default(key, self.doc.fields.get(key, "")) from setup.doctype.naming_series.naming_series import set_by_naming_series set_by_naming_series("Item", "item_code", self.doc.get("item_naming_by") == "Naming Series", hide_name_field=True) stock_frozen_limit = 356 submitted_stock_frozen = self.doc.stock_frozen_upto_days if submitted_stock_frozen > stock_frozen_limit: self.doc.stock_frozen_upto_days = stock_frozen_limit webnotes.msgprint( _("`Freeze Stocks Older Than` should be smaller than %d days.") % stock_frozen_limit)
def savedocs(): """save / submit / update doclist""" try: wrapper = webnotes.bean() wrapper.from_compressed(webnotes.form_dict.docs, webnotes.form_dict.docname) # action action = webnotes.form_dict.action if action == 'Update': action = 'update_after_submit' getattr(wrapper, action.lower())() # update recent documents webnotes.user.update_recent(wrapper.doc.doctype, wrapper.doc.name) send_updated_docs(wrapper) except Exception, e: webnotes.msgprint(webnotes._('Did not save')) webnotes.errprint(webnotes.utils.getTraceback()) raise e
def on_trash(self): if self.doc.file_name and webnotes.conn.sql( """select count(*) from `tabFile Data` where file_name=%s""", self.doc.file_name)[0][0] == 1: path = webnotes.utils.get_path("public", "files", self.doc.file_name) if os.path.exists(path): os.remove(path) if self.doc.attached_to_name: # check persmission try: if not webnotes.has_permission(self.doc.attached_to_doctype, "write", self.doc.attached_to_name): webnotes.msgprint( webnotes._("No permission to write / remove."), raise_exception=True) except webnotes.DoesNotExistError: pass
def before_rename(self, olddn, newdn, merge=False): if merge: # Validate properties before merging field_list = [ "stock_uom", "is_stock_item", "has_serial_no", "has_batch_no" ] new_properties = [ cstr(d) for d in webnotes.conn.get_value("Item", newdn, field_list) ] if new_properties != [ cstr(self.doc.fields[fld]) for fld in field_list ]: webnotes.throw( _("To merge, following properties must be same for both items" ) + ": \n" + ", ".join([self.meta.get_label(fld) for fld in field_list])) webnotes.conn.sql("delete from `tabBin` where item_code=%s", olddn)
def upload(): # get record details dt = webnotes.form_dict.doctype dn = webnotes.form_dict.docname at_id = webnotes.form_dict.at_id file_url = webnotes.form_dict.file_url filename = webnotes.form_dict.filename if not filename and not file_url: webnotes.msgprint(_("Please select a file or url"), raise_exception=True) # save if filename: fid, fname = save_uploaded(dt, dn) elif file_url: fid, fname = save_url(file_url, dt, dn) if fid: return fid
def get_todo_list(self, user_id): from core.page.todo.todo import get todo_list = get() html = "" if todo_list: for i, todo in enumerate([todo for todo in todo_list if not todo.checked]): if i>= 10: break if not todo.description and todo.reference_type: todo.description = "%s: %s - %s %s" % \ (todo.reference_type, get_url_to_form(todo.reference_type, todo.reference_name), _("assigned by"), get_fullname(todo.assigned_by)) html += "<li style='line-height: 200%%'>%s [%s]</li>" % (todo.description, todo.priority) if html: return 1, "<h4>To Do (max 10):</h4><ul>" + html + "</ul><hr>" else: return 0, "<p>To Do</p>"
def check_negative_balance(self, adv_adj): if not adv_adj: account = webnotes.conn.get_value( "Account", self.doc.account, ["allow_negative_balance", "debit_or_credit"], as_dict=True) if not account["allow_negative_balance"]: balance = webnotes.conn.sql( """select sum(debit) - sum(credit) from `tabGL Entry` where account = %s and ifnull(is_cancelled, 'No') = 'No'""", self.doc.account) balance = account["debit_or_credit"] == "Debit" and \ balance[0][0] or -1*balance[0][0] if flt(balance) < 0: msgprint( _("Negative balance is not allowed for account ") + self.doc.account, raise_exception=1)
def get_calendar_events(self, user_id): from core.doctype.event.event import get_events events = get_events(self.future_from_date.strftime("%Y-%m-%d"), self.future_to_date.strftime("%Y-%m-%d")) html = "" if events: for i, e in enumerate(events): if i>=10: break if e.all_day: html += """<li style='line-height: 200%%'>%s [%s (%s)]</li>""" % \ (e.subject, datetime_in_user_format(e.starts_on), _("All Day")) else: html += "<li style='line-height: 200%%'>%s [%s - %s]</li>" % \ (e.subject, datetime_in_user_format(e.starts_on), datetime_in_user_format(e.ends_on)) if html: return 1, "<h4>Upcoming Calendar Events (max 10):</h4><ul>" + html + "</ul><hr>" else: return 0, "<p>Calendar Events</p>"
def remove_against_link_from_jv(ref_type, ref_no, against_field): linked_jv = webnotes.conn.sql_list("""select parent from `tabJournal Voucher Detail` where `%s`=%s and docstatus < 2""" % (against_field, "%s"), (ref_no)) if linked_jv: webnotes.conn.sql("""update `tabJournal Voucher Detail` set `%s`=null, modified=%s, modified_by=%s where `%s`=%s and docstatus < 2""" % (against_field, "%s", "%s", against_field, "%s"), (now(), webnotes.session.user, ref_no)) webnotes.conn.sql("""update `tabGL Entry` set against_voucher_type=null, against_voucher=null, modified=%s, modified_by=%s where against_voucher_type=%s and against_voucher=%s and voucher_no != ifnull(against_voucher, '')""", (now(), webnotes.session.user, ref_type, ref_no)) webnotes.msgprint("{msg} {linked_jv}".format(msg = _("""Following linked Journal Vouchers \ made against this transaction has been unlinked. You can link them again with other \ transactions via Payment Reconciliation Tool."""), linked_jv="\n".join(linked_jv)))
def validate_account_details(self, adv_adj): """Account must be ledger, active and not freezed""" ret = webnotes.conn.sql("""select group_or_ledger, docstatus, company from tabAccount where name=%s""", self.doc.account, as_dict=1)[0] if ret.group_or_ledger=='Group': webnotes.throw(_("Account") + ": " + self.doc.account + _(" is not a ledger")) if ret.docstatus==2: webnotes.throw(_("Account") + ": " + self.doc.account + _(" is not active")) if ret.company != self.doc.company: webnotes.throw(_("Account") + ": " + self.doc.account + _(" does not belong to the company") + ": " + self.doc.company)
def on_trash(self): if self.doc.attached_to_name: # check persmission try: if not webnotes.has_permission(self.doc.attached_to_doctype, "write", self.doc.attached_to_name): webnotes.msgprint( webnotes._("No permission to write / remove."), raise_exception=True) except webnotes.DoesNotExistError: pass # if file not attached to any other record, delete it if self.doc.file_name and webnotes.conn.sql( """select count(*) from `tabFile Data` where file_name=%s and name!=%s""", (self.doc.file_name, self.doc.name)): path = webnotes.utils.get_site_path(conf.files_path, self.doc.file_name) if os.path.exists(path): os.remove(path)
def check_duplicate_entry_for_production_order(self): other_ste = [t[0] for t in webnotes.conn.get_values("Stock Entry", { "production_order": self.doc.production_order, "purpose": self.doc.purpose, "docstatus": ["!=", 2], "name": ["!=", self.doc.name] }, "name")] if other_ste: production_item, qty = webnotes.conn.get_value("Production Order", self.doc.production_order, ["production_item", "qty"]) args = other_ste + [production_item] fg_qty_already_entered = webnotes.conn.sql("""select sum(actual_qty) from `tabStock Entry Detail` where parent in (%s) and item_code = %s and ifnull(s_warehouse,'')='' """ % (", ".join(["%s" * len(other_ste)]), "%s"), args)[0][0] if fg_qty_already_entered >= qty: webnotes.throw(_("Stock Entries already created for Production Order ") + self.doc.production_order + ":" + ", ".join(other_ste), DuplicateEntryForProductionOrderError)
def save(self, check_links=1): perm_to_check = "write" if self.doc.fields.get("__islocal"): perm_to_check = "create" if not self.doc.owner: self.doc.owner = webnotes.session.user if self.ignore_permissions or webnotes.has_permission(self.doc.doctype, perm_to_check, self.doc): self.to_docstatus = 0 self.prepare_for_save("save") if not self.ignore_validate: self.run_method('validate') if not self.ignore_mandatory: self.check_mandatory() self.save_main() self.save_children() self.run_method('on_update') else: self.no_permission_to(_(perm_to_check.title())) return self
def upload(): # get record details dt = webnotes.form_dict.doctype dn = webnotes.form_dict.docname file_url = webnotes.form_dict.file_url filename = webnotes.form_dict.filename if not filename and not file_url: webnotes.msgprint(_("Please select a file or url"), raise_exception=True) # save if filename: filedata = save_uploaded(dt, dn) elif file_url: filedata = save_url(file_url, dt, dn) return { "fid": filedata.name, "filename": filedata.file_name or filedata.file_url }
def make_serial_no(self, serial_no): sr = webnotes.new_bean("Serial No") sr.doc.serial_no = serial_no sr.doc.item_code = self.doc.item sr.make_controller().via_stock_ledger = True sr.insert() sr.doc.warehouse = 'Finished Goods - P' sr.doc.status = "Available" sr.doc.purchase_document_type = 'Packing Items' sr.doc.purchase_document_no = self.doc.name sr.doc.purchase_date = self.doc.creation sr.save() qr = "select warranty_period from tabItem where name='" + self.doc.item + "'" res = webnotes.conn.sql(qr) if res: exdt = add_months(cstr(nowdate()), cint(res[0][0])) qr1 = "update `tabSerial No` set warranty_expiry_date='" + cstr( exdt) + "' where name='" + sr.doc.name + "'" webnotes.conn.sql(qr1) webnotes.msgprint(_("Serial No created") + ": " + sr.doc.name) return sr.doc.name