def compare_expense_with_budget(args, budget_amount, action_for, action, budget_against, amount=0): actual_expense = amount or get_actual_expense(args) if actual_expense > budget_amount: diff = actual_expense - budget_amount currency = dataent.get_cached_value('Company', args.company, 'default_currency') msg = _( "{0} Budget for Account {1} against {2} {3} is {4}. It will exceed by {5}" ).format(_(action_for), dataent.bold(args.account), args.budget_against_field, dataent.bold(budget_against), dataent.bold(fmt_money(budget_amount, currency=currency)), dataent.bold(fmt_money(diff, currency=currency))) if (dataent.flags.exception_approver_role and dataent.flags.exception_approver_role in dataent.get_roles( dataent.session.user)): action = "Warn" if action == "Stop": dataent.throw(msg, BudgetError) else: dataent.msgprint(msg, indicator='orange')
def return_success_page(doc): dataent.respond_as_web_page(_("Success"), _("{0}: {1} is set to state {2}".format( doc.get('doctype'), dataent.bold(doc.get('name')), dataent.bold( get_doc_workflow_state(doc)))), indicator_color='green')
def return_link_expired_page(doc, doc_workflow_state): dataent.respond_as_web_page( _("Link Expired"), _("Document {0} has been set to state {1} by {2}".format( dataent.bold(doc.get('name')), dataent.bold(doc_workflow_state), dataent.bold( dataent.get_value('User', doc.get("modified_by"), 'full_name')))), indicator_color='blue')
def make_invoices(self): names = [] mandatory_error_msg = _( "Row {0}: {1} is required to create the Opening {2} Invoices") if not self.company: dataent.throw(_("Please select the Company")) for row in self.invoices: if not row.qty: row.qty = 1.0 # always mandatory fields for the invoices if not row.temporary_opening_account: row.temporary_opening_account = get_temporary_opening_account( self.company) row.party_type = "Customer" if self.invoice_type == "Sales" else "Supplier" # Allow to create invoice even if no party present in customer or supplier. if not dataent.db.exists(row.party_type, row.party): if self.create_missing_party: self.add_party(row.party_type, row.party) else: dataent.throw( _("{0} {1} does not exist.").format( dataent.bold(row.party_type), dataent.bold(row.party))) if not row.item_name: row.item_name = _("Opening Invoice Item") if not row.posting_date: row.posting_date = nowdate() if not row.due_date: row.due_date = nowdate() for d in ("Party", "Outstanding Amount", "Temporary Opening Account"): if not row.get(scrub(d)): dataent.throw( mandatory_error_msg.format(row.idx, _(d), self.invoice_type)) args = self.get_invoice_dict(row=row) if not args: continue doc = dataent.get_doc(args).insert() doc.submit() names.append(doc.name) if len(self.invoices) > 5: dataent.publish_realtime( "progress", dict(progress=[row.idx, len(self.invoices)], title=_('Creating {0}').format(doc.doctype)), user=dataent.session.user) return names
def validate_report_format(self): """ check if user has select correct report format """ valid_report_formats = ["HTML", "XLSX", "CSV"] if self.format not in valid_report_formats: dataent.throw( _("%s is not a valid report format. Report format should \ one of the following %s" % (dataent.bold(self.format), dataent.bold(", ".join(valid_report_formats)))))
def validate_inspection(self): '''Checks if quality inspection is set for Items that require inspection. On submit, throw an exception''' inspection_required_fieldname = None if self.doctype in ["Purchase Receipt", "Purchase Invoice"]: inspection_required_fieldname = "inspection_required_before_purchase" elif self.doctype in ["Delivery Note", "Sales Invoice"]: inspection_required_fieldname = "inspection_required_before_delivery" if ((not inspection_required_fieldname and self.doctype != "Stock Entry") or (self.doctype == "Stock Entry" and not self.inspection_required) or (self.doctype in ["Sales Invoice", "Purchase Invoice"] and not self.update_stock)): return for d in self.get('items'): qa_required = False if (inspection_required_fieldname and not d.quality_inspection and dataent.db.get_value( "Item", d.item_code, inspection_required_fieldname)): qa_required = True elif self.doctype == "Stock Entry" and not d.quality_inspection and d.t_warehouse: qa_required = True if self.docstatus == 1 and d.quality_inspection: qa_doc = dataent.get_doc("Quality Inspection", d.quality_inspection) if qa_doc.docstatus == 0: link = dataent.utils.get_link_to_form( 'Quality Inspection', d.quality_inspection) dataent.throw( _("Quality Inspection: {0} is not submitted for the item: {1} in row {2}" ).format(link, d.item_code, d.idx), QualityInspectionNotSubmittedError) qa_failed = any( [r.status == "Rejected" for r in qa_doc.readings]) if qa_failed: dataent.throw( _("Row {0}: Quality Inspection rejected for item {1}" ).format(d.idx, d.item_code), QualityInspectionRejectedError) elif qa_required: action = dataent.get_doc( 'Stock Settings' ).action_if_quality_inspection_is_not_submitted if self.docstatus == 1 and action == 'Stop': dataent.throw( _("Quality Inspection required for Item {0} to submit" ).format(dataent.bold(d.item_code)), exc=QualityInspectionRequiredError) else: dataent.msgprint( _("Create Quality Inspection for Item {0}").format( dataent.bold(d.item_code)))
def limits_crossed_error(self, args, item): '''Raise exception for limits crossed''' dataent.throw(_( 'This document is over limit by {0} {1} for item {4}. Are you making another {3} against the same {2}?' ).format( dataent.bold(_(item["target_ref_field"].title())), dataent.bold(item["reduce_by"]), dataent.bold(_(args.get('target_dt'))), dataent.bold(_(self.doctype)), dataent.bold(item.get('item_code')) ) + '<br><br>' + _( 'To allow over-billing or over-ordering, update "Allowance" in Stock Settings or the Item.' ), title=_('Limit Crossed'))
def validate_for_subcontracting(self): if not self.is_subcontracted and self.sub_contracted_items: dataent.throw(_("Please enter 'Is Subcontracted' as Yes or No")) if self.is_subcontracted == "Yes": if self.doctype in ["Purchase Receipt", "Purchase Invoice" ] and not self.supplier_warehouse: dataent.throw( _("Supplier Warehouse mandatory for sub-contracted Purchase Receipt" )) for item in self.get("items"): if item in self.sub_contracted_items and not item.bom: dataent.throw( _("Please select BOM in BOM field for Item {0}"). format(item.item_code)) if self.doctype == "Purchase Order": for supplied_item in self.get("supplied_items"): if not supplied_item.reserve_warehouse: dataent.throw( _("Reserved Warehouse is mandatory for Item {0} in Raw Materials supplied" ).format(dataent.bold( supplied_item.rm_item_code))) else: for item in self.get("items"): if item.bom: item.bom = None
def validate_with_parent_plan(self, staffing_plan_detail): if not dataent.get_cached_value('Company', self.company, "parent_company"): return # No parent, nothing to validate # Get staffing plan applicable for the company (Parent Company) parent_plan_details = get_active_staffing_plan_details(self.company, staffing_plan_detail.designation, self.from_date, self.to_date) if not parent_plan_details: return #no staffing plan for any parent Company in hierarchy # Fetch parent company which owns the staffing plan. NOTE: Parent could be higher up in the hierarchy parent_company = dataent.db.get_value("Staffing Plan", parent_plan_details[0].name, "company") # Parent plan available, validate with parent, siblings as well as children of staffing plan Company if cint(staffing_plan_detail.vacancies) > cint(parent_plan_details[0].vacancies) or \ flt(staffing_plan_detail.total_estimated_cost) > flt(parent_plan_details[0].total_estimated_cost): dataent.throw(_("You can only plan for upto {0} vacancies and budget {1} \ for {2} as per staffing plan {3} for parent company {4}." .format(cint(parent_plan_details[0].vacancies), parent_plan_details[0].total_estimated_cost, dataent.bold(staffing_plan_detail.designation), parent_plan_details[0].name, parent_company)), ParentCompanyError) #Get vacanices already planned for all companies down the hierarchy of Parent Company lft, rgt = dataent.get_cached_value('Company', parent_company, ["lft", "rgt"]) all_sibling_details = dataent.db.sql("""select sum(spd.vacancies) as vacancies, sum(spd.total_estimated_cost) as total_estimated_cost from `tabStaffing Plan Detail` spd join `tabStaffing Plan` sp on spd.parent=sp.name where spd.designation=%s and sp.docstatus=1 and sp.to_date >= %s and sp.from_date <=%s and sp.company in (select name from tabCompany where lft > %s and rgt < %s) """, (staffing_plan_detail.designation, self.from_date, self.to_date, lft, rgt), as_dict = 1)[0] if (cint(parent_plan_details[0].vacancies) < \ (cint(staffing_plan_detail.vacancies) + cint(all_sibling_details.vacancies))) or \ (flt(parent_plan_details[0].total_estimated_cost) < \ (flt(staffing_plan_detail.total_estimated_cost) + flt(all_sibling_details.total_estimated_cost))): dataent.throw(_("{0} vacancies and {1} budget for {2} already planned for subsidiary companies of {3}. \ You can only plan for upto {4} vacancies and and budget {5} as per staffing plan {6} for parent company {3}." .format(cint(all_sibling_details.vacancies), all_sibling_details.total_estimated_cost, dataent.bold(staffing_plan_detail.designation), parent_company, cint(parent_plan_details[0].vacancies), parent_plan_details[0].total_estimated_cost, parent_plan_details[0].name)))
def append_table(self, table_name): self.tables.append(table_name) doctype = table_name[4:-1] if (not self.flags.ignore_permissions) and ( not dataent.has_permission(doctype)): dataent.flags.error_message = _( 'Insufficient Permission for {0}').format( dataent.bold(doctype)) raise dataent.PermissionError(doctype)
def validate_assessment_criteria(self): assessment_criteria_list = dataent.db.sql_list(''' select apc.assessment_criteria from `tabAssessment Plan` ap , `tabAssessment Plan Criteria` apc where ap.name = apc.parent and ap.course=%s and ap.student_group=%s and ap.assessment_group=%s and ap.name != %s and ap.docstatus=1''', (self.course, self.student_group, self.assessment_group, self.name)) for d in self.assessment_criteria: if d.assessment_criteria in assessment_criteria_list: dataent.throw(_("You have already assessed for the assessment criteria {}.") .format(dataent.bold(d.assessment_criteria)))
def validate_column_name(n): special_characters = re.findall("[\W]", n, re.UNICODE) if special_characters: special_characters = ", ".join('"{0}"'.format(c) for c in special_characters) dataent.throw( _("Fieldname {0} cannot have special characters like {1}").format( dataent.bold(cstr(n)), special_characters), InvalidColumnName) return n
def validate_workflow(doc): '''Validate Workflow State and Transition for the current user. - Check if user is allowed to edit in current state - Check if user is allowed to transition to the next state (if changed) ''' workflow = get_workflow(doc.doctype) current_state = None if getattr(doc, '_doc_before_save', None): current_state = doc._doc_before_save.get(workflow.workflow_state_field) next_state = doc.get(workflow.workflow_state_field) if not next_state: next_state = workflow.states[0].state doc.set(workflow.workflow_state_field, next_state) if not current_state: current_state = workflow.states[0].state state_row = [d for d in workflow.states if d.state == current_state] if not state_row: dataent.throw(_('{0} is not a valid Workflow State. Please update your Workflow and try again.'.format(dataent.bold(current_state)))) state_row = state_row[0] # if transitioning, check if user is allowed to transition if current_state != next_state: bold_current = dataent.bold(current_state) bold_next = dataent.bold(next_state) if not doc._doc_before_save: # transitioning directly to a state other than the first # e.g from data import dataent.throw(_('Workflow State transition not allowed from {0} to {1}').format(bold_current, bold_next), WorkflowPermissionError) transitions = get_transitions(doc._doc_before_save) transition = [d for d in transitions if d.next_state == next_state] if not transition: dataent.throw(_('Workflow State transition not allowed from {0} to {1}').format(bold_current, bold_next), WorkflowPermissionError)
def setup_user_email_inbox(email_account, awaiting_password, email_id, enable_outgoing): """ setup email inbox for user """ def add_user_email(user): user = dataent.get_doc("User", user) row = user.append("user_emails", {}) row.email_id = email_id row.email_account = email_account row.awaiting_password = awaiting_password or 0 row.enable_outgoing = enable_outgoing or 0 user.save(ignore_permissions=True) udpate_user_email_settings = False if not all([email_account, email_id]): return user_names = dataent.db.get_values("User", {"email": email_id}, as_dict=True) if not user_names: return for user in user_names: user_name = user.get("name") # check if inbox is alreay configured user_inbox = dataent.db.get_value("User Email", { "email_account": email_account, "parent": user_name }, ["name"]) or None if not user_inbox: add_user_email(user_name) else: # update awaiting password for email account udpate_user_email_settings = True if udpate_user_email_settings: dataent.db.sql( """UPDATE `tabUser Email` SET awaiting_password = %(awaiting_password)s, enable_outgoing = %(enable_outgoing)s WHERE email_account = %(email_account)s""", { "email_account": email_account, "enable_outgoing": enable_outgoing, "awaiting_password": awaiting_password or 0 }) else: users = " and ".join( [dataent.bold(user.get("name")) for user in user_names]) dataent.msgprint(_("Enabled email inbox for user {0}").format(users)) ask_pass_update()
def get_msg(df): if df.fieldtype == "Table": return "{}: {}: {}".format(_("Error"), _("Data missing in table"), _(df.label)) elif self.parentfield: return "{}: {} {} #{}: {}: {}".format( _("Error"), dataent.bold(_(self.doctype)), _("Row"), self.idx, _("Value missing for"), _(df.label)) else: return _("Error: Value missing for {0}: {1}").format( _(df.parent), _(df.label))
def make_default(name): """Set print format as default""" dataent.has_permission("Print Format", "write") print_format = dataent.get_doc("Print Format", name) if (dataent.conf.get('developer_mode') or 0) == 1: # developer mode, set it default in doctype doctype = dataent.get_doc("DocType", print_format.doc_type) doctype.default_print_format = name doctype.save() else: # customization dataent.make_property_setter({ 'doctype_or_field': "DocType", 'doctype': print_format.doc_type, 'property': "default_print_format", 'value': name, }) dataent.msgprint( dataent._("{0} is now default print format for {1} doctype").format( dataent.bold(name), dataent.bold(print_format.doc_type)))
def validate(self): """Validate Email Address and check POP3/IMAP and SMTP connections is enabled.""" if self.email_id: validate_email_add(self.email_id, True) if self.login_id_is_different: if not self.login_id: dataent.throw(_("Login Id is required")) else: self.login_id = None duplicate_email_account = dataent.get_all("Email Account", filters={ "email_id": self.email_id, "name": ("!=", self.name) }) if duplicate_email_account: dataent.throw(_("Email ID must be unique, Email Account already exists \ for {0}".format(dataent.bold(self.email_id)))) if dataent.local.flags.in_patch or dataent.local.flags.in_test: return #if self.enable_incoming and not self.append_to: # dataent.throw(_("Append To is mandatory for incoming mails")) if (not self.awaiting_password and not dataent.local.flags.in_install and not dataent.local.flags.in_patch): if self.password or self.smtp_server in ('127.0.0.1', 'localhost'): if self.enable_incoming: self.get_incoming_server() self.no_failed = 0 if self.enable_outgoing: self.check_smtp() else: if self.enable_incoming or (self.enable_outgoing and not self.no_smtp_authentication): dataent.throw(_("Password is required or select Awaiting Password")) if self.notify_if_unreplied: if not self.send_notification_to: dataent.throw(_("{0} is mandatory").format(self.meta.get_label("send_notification_to"))) for e in self.get_unreplied_notification_emails(): validate_email_add(e, True) if self.enable_incoming and self.append_to: valid_doctypes = [d[0] for d in get_append_to()] if self.append_to not in valid_doctypes: dataent.throw(_("Append To can be one of {0}").format(comma_or(valid_doctypes)))
def set_component_amounts_based_on_payment_days(self): joining_date, relieving_date = dataent.get_cached_value( "Employee", self.employee, ["date_of_joining", "relieving_date"]) if not relieving_date: relieving_date = getdate(self.end_date) if not joining_date: dataent.throw( _("Please set the Date Of Joining for employee {0}").format( dataent.bold(self.employee_name))) for component_type in ("earnings", "deductions"): for d in self.get(component_type): d.amount = self.get_amount_based_on_payment_days( d, joining_date, relieving_date)[0]
def get_taxable_earnings(self, based_on_payment_days=0): joining_date, relieving_date = dataent.get_cached_value( "Employee", self.employee, ["date_of_joining", "relieving_date"]) if not relieving_date: relieving_date = getdate(self.end_date) if not joining_date: dataent.throw( _("Please set the Date Of Joining for employee {0}").format( dataent.bold(self.employee_name))) taxable_earnings = 0 additional_income = 0 additional_income_with_full_tax = 0 flexi_benefits = 0 for earning in self.earnings: if based_on_payment_days: amount, additional_amount = self.get_amount_based_on_payment_days( earning, joining_date, relieving_date) else: amount, additional_amount = earning.amount, earning.additional_amount if earning.is_tax_applicable: if additional_amount: taxable_earnings += (amount - additional_amount) additional_income += additional_amount if earning.deduct_full_tax_on_selected_payroll_date: additional_income_with_full_tax += additional_amount continue if earning.is_flexible_benefit: flexi_benefits += amount else: taxable_earnings += amount return dataent._dict({ "taxable_earnings": taxable_earnings, "additional_income": additional_income, "additional_income_with_full_tax": additional_income_with_full_tax, "flexi_benefits": flexi_benefits })
def validate_with_subsidiary_plans(self, staffing_plan_detail): #Valdate this plan with all child company plan children_details = dataent.db.sql("""select sum(spd.vacancies) as vacancies, sum(spd.total_estimated_cost) as total_estimated_cost from `tabStaffing Plan Detail` spd join `tabStaffing Plan` sp on spd.parent=sp.name where spd.designation=%s and sp.docstatus=1 and sp.to_date >= %s and sp.from_date <=%s and sp.company in (select name from tabCompany where parent_company = %s) """, (staffing_plan_detail.designation, self.from_date, self.to_date, self.company), as_dict = 1)[0] if children_details and \ cint(staffing_plan_detail.vacancies) < cint(children_details.vacancies) or \ flt(staffing_plan_detail.total_estimated_cost) < flt(children_details.total_estimated_cost): dataent.throw(_("Subsidiary companies have already planned for {1} vacancies at a budget of {2}. \ Staffing Plan for {0} should allocate more vacancies and budget for {3} than planned for its subsidiary companies" .format(self.company, cint(children_details.vacancies), children_details.total_estimated_cost, dataent.bold(staffing_plan_detail.designation))), SubsidiaryCompanyError)
def getdoc(doctype, name, user=None): """ Loads a doclist for a given document. This method is called directly from the client. Requries "doctype", "name" as form variables. Will also call the "onload" method on the document. """ if not (doctype and name): raise Exception('doctype and name required!') if not name: name = doctype if not dataent.db.exists(doctype, name): return [] try: doc = dataent.get_doc(doctype, name) run_onload(doc) if not doc.has_permission("read"): dataent.flags.error_message = _( 'Insufficient Permission for {0}').format( dataent.bold(doctype + ' ' + name)) raise dataent.PermissionError(("read", doctype, name)) doc.apply_fieldlevel_read_permissions() # add file list doc.add_viewed() get_docinfo(doc) except Exception: dataent.errprint(dataent.utils.get_traceback()) raise if doc and not name.startswith('_'): dataent.get_user().update_recent(doctype, name) doc.add_seen() dataent.response.docs.append(doc)
def get_item_dict(): default_uom = dataent.db.get_single_value("Stock Settings", "stock_uom") or _("Nos") cost_center = dataent.get_cached_value('Company', self.company, "cost_center") if not cost_center: dataent.throw( _("Please set the Default Cost Center in {0} company."). format(dataent.bold(self.company))) rate = flt(row.outstanding_amount) / flt(row.qty) return dataent._dict({ "uom": default_uom, "rate": rate or 0.0, "qty": row.qty, "conversion_factor": 1.0, "item_name": row.item_name or "Opening Invoice Item", "description": row.item_name or "Opening Invoice Item", income_expense_account_field: row.temporary_opening_account, "cost_center": cost_center })
def rename_doc(doctype, old, new, force=False, merge=False, ignore_permissions=False, ignore_if_exists=False): """ Renames a doc(dt, old) to doc(dt, new) and updates all linked fields of type "Link" """ if not dataent.db.exists(doctype, old): return if ignore_if_exists and dataent.db.exists(doctype, new): return if old==new: dataent.msgprint(_('Please select a new name to rename')) return force = cint(force) merge = cint(merge) meta = dataent.get_meta(doctype) # call before_rename old_doc = dataent.get_doc(doctype, old) out = old_doc.run_method("before_rename", old, new, merge) or {} new = (out.get("new") or new) if isinstance(out, dict) else (out or new) if doctype != "DocType": new = validate_rename(doctype, new, meta, merge, force, ignore_permissions) if not merge: rename_parent_and_child(doctype, old, new, meta) # update link fields' values link_fields = get_link_fields(doctype) update_link_field_values(link_fields, old, new, doctype) rename_dynamic_links(doctype, old, new) # save the user settings in the db update_user_settings(old, new, link_fields) if doctype=='DocType': rename_doctype(doctype, old, new, force) update_attachments(doctype, old, new) rename_versions(doctype, old, new) # call after_rename new_doc = dataent.get_doc(doctype, new) # copy any flags if required new_doc._local = getattr(old_doc, "_local", None) new_doc.run_method("after_rename", old, new, merge) if not merge: rename_password(doctype, old, new) # update user_permissions dataent.db.sql("""update tabDefaultValue set defvalue=%s where parenttype='User Permission' and defkey=%s and defvalue=%s""", (new, doctype, old)) if merge: new_doc.add_comment('Edit', _("merged {0} into {1}").format(dataent.bold(old), dataent.bold(new))) else: new_doc.add_comment('Edit', _("renamed from {0} to {1}").format(dataent.bold(old), dataent.bold(new))) if merge: dataent.delete_doc(doctype, old) dataent.clear_cache() dataent.enqueue('dataent.utils.global_search.rebuild_for_doctype', doctype=doctype) return new
def validate_student_belongs_to_group(student, student_group): groups = dataent.db.get_all('Student Group Student', ['parent'], dict(student = student, active=1)) if not student_group in [d.parent for d in groups]: dataent.throw(_('Student {0} does not belong to group {1}').format(dataent.bold(student), dataent.bold(student_group)), StudentNotInGroupError)
def execute(self, query=None, fields=None, filters=None, or_filters=None, docstatus=None, group_by=None, order_by=None, limit_start=False, limit_page_length=None, as_list=False, with_childnames=False, debug=False, ignore_permissions=False, user=None, with_comment_count=False, join='left join', distinct=False, start=None, page_length=None, limit=None, ignore_ifnull=False, save_user_settings=False, save_user_settings_fields=False, update=None, add_total_row=None, user_settings=None, reference_doctype=None): if not ignore_permissions and not dataent.has_permission( self.doctype, "read", user=user): dataent.flags.error_message = _( 'Insufficient Permission for {0}').format( dataent.bold(self.doctype)) raise dataent.PermissionError(self.doctype) # filters and fields swappable # its hard to remember what comes first if (isinstance(fields, dict) or (isinstance(fields, list) and fields and isinstance(fields[0], list))): # if fields is given as dict/list of list, its probably filters filters, fields = fields, filters elif fields and isinstance(filters, list) \ and len(filters) > 1 and isinstance(filters[0], string_types): # if `filters` is a list of strings, its probably fields filters, fields = fields, filters if fields: self.fields = fields else: self.fields = ["`tab{0}`.`name`".format(self.doctype)] if start: limit_start = start if page_length: limit_page_length = page_length if limit: limit_page_length = limit self.filters = filters or [] self.or_filters = or_filters or [] self.docstatus = docstatus or [] self.group_by = group_by self.order_by = order_by self.limit_start = 0 if (limit_start is False) else cint(limit_start) self.limit_page_length = cint( limit_page_length) if limit_page_length else None self.with_childnames = with_childnames self.debug = debug self.join = join self.distinct = distinct self.as_list = as_list self.ignore_ifnull = ignore_ifnull self.flags.ignore_permissions = ignore_permissions self.user = user or dataent.session.user self.update = update self.user_settings_fields = copy.deepcopy(self.fields) # for contextual user permission check # to determine which user permission is applicable on link field of specific doctype self.reference_doctype = reference_doctype or self.doctype if user_settings: self.user_settings = json.loads(user_settings) if query: result = self.run_custom_query(query) else: result = self.build_and_run() if with_comment_count and not as_list and self.doctype: self.add_comment_count(result) if save_user_settings: self.save_user_settings_fields = save_user_settings_fields self.update_user_settings() return result
def logout_feed(user, reason): if user and user != "Guest": subject = _("{0} logged out: {1}").format(get_fullname(user), dataent.bold(reason)) add_authentication_log(subject, user, operation="Logout")
def get_batch_no(item_code, warehouse, qty=1, throw=False): """ Get batch number using First Expiring First Out method. :param item_code: `item_code` of Item Document :param warehouse: name of Warehouse to check :param qty: quantity of Items :return: String represent batch number of batch with sufficient quantity else an empty String """ batch_no = None batches = get_batches(item_code, warehouse, qty, throw) for batch in batches: if cint(qty) <= cint(batch.qty): batch_no = batch.batch_id break if not batch_no: dataent.msgprint(_('Please select a Batch for Item {0}. Unable to find a single batch that fulfills this requirement').format(dataent.bold(item_code))) if throw: raise UnableToSelectBatchError return batch_no
def validate(self): """Check if change in varchar length isn't truncating the columns""" if self.is_new(): return self.get_columns_from_db() columns = [ dataent._dict({ "fieldname": f, "fieldtype": "Data" }) for f in standard_varchar_columns ] columns += self.columns.values() for col in columns: if len(col.fieldname) >= 64: dataent.throw( _("Fieldname is limited to 64 characters ({0})").format( dataent.bold(col.fieldname))) if col.fieldtype in type_map and type_map[ col.fieldtype][0] == "varchar": # validate length range new_length = cint(col.length) or cint(varchar_len) if not (1 <= new_length <= 1000): dataent.throw( _("Length of {0} should be between 1 and 1000").format( col.fieldname)) current_col = self.current_columns.get(col.fieldname, {}) if not current_col: continue current_type = self.current_columns[col.fieldname]["type"] current_length = re.findall('varchar\(([\d]+)\)', current_type) if not current_length: # case when the field is no longer a varchar continue current_length = current_length[0] if cint(current_length) != cint(new_length): try: # check for truncation max_length = dataent.db.sql("""select max(char_length(`{fieldname}`)) from `tab{doctype}`"""\ .format(fieldname=col.fieldname, doctype=self.doctype)) except pymysql.InternalError as e: if e.args[0] == ER.BAD_FIELD_ERROR: # Unknown column 'column_name' in 'field list' continue else: raise if max_length and max_length[0][ 0] and max_length[0][0] > new_length: if col.fieldname in self.columns: self.columns[col.fieldname].length = current_length dataent.msgprint(_("Reverting length to {0} for '{1}' in '{2}'; Setting the length as {3} will cause truncation of data.")\ .format(current_length, col.fieldname, self.doctype, new_length))