def validate_condition(self): temp_doc = dataent.new_doc(self.document_type) if self.condition: try: dataent.safe_eval(self.condition, None, get_context(temp_doc)) except Exception: dataent.throw(_("The Condition '{0}' is invalid").format(self.condition))
def eval_condition_and_formula(self, d, data): try: condition = d.condition.strip() if d.condition else None if condition: if not dataent.safe_eval(condition, self.whitelisted_globals, data): return None amount = d.amount if d.amount_based_on_formula: formula = d.formula.strip() if d.formula else None if formula: amount = flt( dataent.safe_eval(formula, self.whitelisted_globals, data), d.precision("amount")) if amount: data[d.abbr] = amount return amount except NameError as err: dataent.throw(_("Name error: {0}".format(err))) except SyntaxError as err: dataent.throw( _("Syntax error in formula or condition: {0}".format(err))) except Exception as e: dataent.throw(_("Error in formula or condition: {0}".format(e))) raise
def test_fifo(self): dataent.db.set_value("Stock Settings", None, "allow_negative_stock", 1) item_code = "_Test Item 2" warehouse = "_Test Warehouse - _TC" create_stock_reconciliation(item_code="_Test Item 2", warehouse="_Test Warehouse - _TC", qty=0, rate=100) make_stock_entry(item_code=item_code, target=warehouse, qty=1, basic_rate=10) sle = get_sle(item_code=item_code, warehouse=warehouse)[0] self.assertEqual([[1, 10]], dataent.safe_eval(sle.stock_queue)) # negative qty make_stock_entry(item_code=item_code, source=warehouse, qty=2, basic_rate=10) sle = get_sle(item_code=item_code, warehouse=warehouse)[0] self.assertEqual([[-1, 10]], dataent.safe_eval(sle.stock_queue)) # further negative make_stock_entry(item_code=item_code, source=warehouse, qty=1) sle = get_sle(item_code=item_code, warehouse=warehouse)[0] self.assertEqual([[-2, 10]], dataent.safe_eval(sle.stock_queue)) # move stock to positive make_stock_entry(item_code=item_code, target=warehouse, qty=3, basic_rate=20) sle = get_sle(item_code=item_code, warehouse=warehouse)[0] self.assertEqual([[1, 20]], dataent.safe_eval(sle.stock_queue)) # incoming entry with diff rate make_stock_entry(item_code=item_code, target=warehouse, qty=1, basic_rate=30) sle = get_sle(item_code=item_code, warehouse=warehouse)[0] self.assertEqual([[1, 20], [1, 30]], dataent.safe_eval(sle.stock_queue)) dataent.db.set_default("allow_negative_stock", 0)
def set_breadcrumbs(self, context): """Build breadcrumbs template """ if self.breadcrumbs: context.parents = dataent.safe_eval(self.breadcrumbs, {"_": _}) if not "no_breadcrumbs" in context: if "<!-- no-breadcrumbs -->" in context.main_section: context.no_breadcrumbs = 1
def calculate_weighted_score(self, weighing_function): try: weighed_score = dataent.safe_eval(self.get_eval_statement(weighing_function), None, {'max':max, 'min': min}) except Exception: dataent.throw(_("Could not solve weighted score function. Make sure the formula is valid."),dataent.ValidationError) weighed_score = 0 return weighed_score
def calculate_criteria(self): for crit in self.criteria: try: crit.score = min(crit.max_score, max( 0 ,dataent.safe_eval(self.get_eval_statement(crit.formula), None, {'max':max, 'min': min}))) except Exception: dataent.throw(_("Could not solve criteria score function for {0}. Make sure the formula is valid.".format(crit.criteria_name)),dataent.ValidationError) crit.score = 0
def get_transitions(doc, workflow = None): '''Return list of possible transitions for the given doc''' doc = dataent.get_doc(dataent.parse_json(doc)) if doc.is_new(): return [] dataent.has_permission(doc, 'read', throw=True) roles = dataent.get_roles() if not workflow: workflow = get_workflow(doc.doctype) current_state = doc.get(workflow.workflow_state_field) if not current_state: dataent.throw(_('Workflow State not set'), WorkflowStateError) transitions = [] for transition in workflow.transitions: if transition.state == current_state and transition.allowed in roles: if transition.condition: # if condition, evaluate # access to dataent.db.get_value and dataent.db.get_list success = dataent.safe_eval(transition.condition, dict(dataent = dataent._dict( db = dataent._dict(get_value = dataent.db.get_value, get_list=dataent.db.get_list), session = dataent.session )), dict(doc = doc)) if not success: continue transitions.append(transition.as_dict()) return transitions
def get_value_from_fieldname(field_map, fieldname_field, doc): field_name = get_source_value(field_map, fieldname_field) if field_name.startswith('eval:'): value = dataent.safe_eval(field_name[5:], dict(dataent=dataent)) elif field_name[0] in ('"', "'"): value = field_name[1:-1] else: value = get_source_value(doc, field_name) return value
def eval_tax_slab_condition(self, condition, data): try: condition = condition.strip() if condition: return dataent.safe_eval(condition, self.whitelisted_globals, data) except NameError as err: dataent.throw(_("Name error: {0}".format(err))) except SyntaxError as err: dataent.throw(_("Syntax error in condition: {0}".format(err))) except Exception as e: dataent.throw(_("Error in formula or condition: {0}".format(e))) raise
def get_documents_for_today(self): '''get list of documents that will be triggered today''' docs = [] diff_days = self.days_in_advance if self.event=="Days After": diff_days = -diff_days for name in dataent.db.sql_list("""select name from `tab{0}` where DATE(`{1}`) = ADDDATE(DATE(%s), INTERVAL %s DAY)""".format(self.document_type, self.date_changed), (nowdate(), diff_days or 0)): doc = dataent.get_doc(self.document_type, name) if self.condition and not dataent.safe_eval(self.condition, None, get_context(doc)): continue docs.append(doc) return docs
def set_status(self, update=False, status=None, update_modified=True): if self.is_new(): if self.get('amended_from'): self.status = 'Draft' return if self.doctype in status_map: _status = self.status if status and update: self.db_set("status", status) sl = status_map[self.doctype][:] sl.reverse() for s in sl: if not s[1]: self.status = s[0] break elif s[1].startswith("eval:"): if dataent.safe_eval( s[1][5:], None, { "self": self.as_dict(), "getdate": getdate, "nowdate": nowdate, "get_value": dataent.db.get_value }): self.status = s[0] break elif getattr(self, s[1])(): self.status = s[0] break if self.status != _status and self.status not in ( "Cancelled", "Partially Ordered", "Ordered", "Issued", "Transferred"): self.add_comment("Label", _(self.status)) if update: self.db_set('status', self.status, update_modified=update_modified)
def get_list_of_recipients(self, doc, context): recipients = [] cc = [] bcc = [] for recipient in self.recipients: if recipient.condition: if not dataent.safe_eval(recipient.condition, None, context): continue if recipient.email_by_document_field: email_ids_value = doc.get(recipient.email_by_document_field) if validate_email_add(email_ids_value): email_ids = email_ids_value.replace(",", "\n") recipients = recipients + email_ids.split("\n") # else: # print "invalid email" if recipient.cc and "{" in recipient.cc: recipient.cc = dataent.render_template(recipient.cc, context) if recipient.cc: recipient.cc = recipient.cc.replace(",", "\n") cc = cc + recipient.cc.split("\n") if recipient.bcc and "{" in recipient.bcc: recipient.bcc = dataent.render_template(recipient.bcc, context) if recipient.bcc: recipient.bcc = recipient.bcc.replace(",", "\n") bcc = bcc + recipient.bcc.split("\n") #For sending emails to specified role if recipient.email_by_role: emails = get_emails_from_role(recipient.email_by_role) for email in emails: recipients = recipients + email.split("\n") if not recipients and not cc and not bcc: return None, None, None return list(set(recipients)), list(set(cc)), list(set(bcc))
def evaluate_alert(doc, alert, event): from jinja2 import TemplateError try: if isinstance(alert, string_types): alert = dataent.get_doc("Notification", alert) context = get_context(doc) if alert.condition: if not dataent.safe_eval(alert.condition, None, context): return if event=="Value Change" and not doc.is_new(): try: db_value = dataent.db.get_value(doc.doctype, doc.name, alert.value_changed) except pymysql.InternalError as e: if e.args[0]== ER.BAD_FIELD_ERROR: alert.db_set('enabled', 0) dataent.log_error('Notification {0} has been disabled due to missing field'.format(alert.name)) return db_value = parse_val(db_value) if (doc.get(alert.value_changed) == db_value) or \ (not db_value and not doc.get(alert.value_changed)): return # value not changed if event != "Value Change" and not doc.is_new(): # reload the doc for the latest values & comments, # except for validate type event. doc = dataent.get_doc(doc.doctype, doc.name) alert.send(doc) except TemplateError: dataent.throw(_("Error while evaluating Notification {0}. Please fix your template.").format(alert)) except Exception as e: dataent.log_error(message=dataent.get_traceback(), title=str(e)) dataent.throw(_("Error in Notification"))
def get_feedback_request_details(reference_doctype, reference_name, trigger="Manual", request=None): if not dataent.db.get_value(reference_doctype, reference_name): # reference document is either deleted or renamed return elif not trigger and not request and not dataent.db.get_value( "Feedback Trigger", {"document_type": reference_doctype}): return elif not trigger and request: trigger = dataent.db.get_value("Feedback Request", request, "feedback_trigger") else: trigger = dataent.db.get_value("Feedback Trigger", {"document_type": reference_doctype}) if not trigger: return feedback_trigger = dataent.get_doc("Feedback Trigger", trigger) doc = dataent.get_doc(reference_doctype, reference_name) context = get_context(doc) recipients = doc.get(feedback_trigger.email_fieldname, None) if feedback_trigger.check_communication: communications = dataent.get_all("Communication", filters={ "reference_doctype": reference_doctype, "reference_name": reference_name, "communication_type": "Communication", "sent_or_received": "Sent" }, fields=["name"]) if len(communications) < 1: dataent.msgprint( _("At least one reply is mandatory before requesting feedback") ) return None if recipients and (not feedback_trigger.condition or \ dataent.safe_eval(feedback_trigger.condition, None, context)): subject = feedback_trigger.subject context.update({"feedback_trigger": feedback_trigger}) if "{" in subject: subject = dataent.render_template(feedback_trigger.subject, context) feedback_request_message = dataent.render_template( feedback_trigger.message, context) return { "subject": subject, "recipients": recipients, "reference_name": doc.name, "reference_doctype": doc.doctype, "message": feedback_request_message, } else: dataent.msgprint(_("Feedback conditions do not match")) return None
def get_filters(self): if self.condition: return dataent.safe_eval(self.condition, dict(dataent=dataent))
def get_context(self, context): '''Build context to render the `web_form.html` template''' self.set_web_form_module() context._login_required = False if self.login_required and dataent.session.user == "Guest": context._login_required = True doc, delimeter = make_route_string(dataent.form_dict) context.doc = doc context.delimeter = delimeter # check permissions if dataent.session.user == "Guest" and dataent.form_dict.name: dataent.throw( _("You need to be logged in to access this {0}.").format( self.doc_type), dataent.PermissionError) if dataent.form_dict.name and not has_web_form_permission( self.doc_type, dataent.form_dict.name): dataent.throw( _("You don't have the permissions to access this document"), dataent.PermissionError) self.reset_field_parent() if self.is_standard: self.use_meta_fields() if not context._login_required: if self.allow_edit: if self.allow_multiple: if not dataent.form_dict.name and not dataent.form_dict.new: self.build_as_list(context) else: if dataent.session.user != 'Guest' and not dataent.form_dict.name: dataent.form_dict.name = dataent.db.get_value( self.doc_type, {"owner": dataent.session.user}, "name") if not dataent.form_dict.name: # only a single doc allowed and no existing doc, hence new dataent.form_dict.new = 1 # always render new form if login is not required or doesn't allow editing existing ones if not self.login_required or not self.allow_edit: dataent.form_dict.new = 1 self.load_document(context) context.parents = self.get_parents(context) if self.breadcrumbs: context.parents = dataent.safe_eval(self.breadcrumbs, {"_": _}) context.has_header = ((dataent.form_dict.name or dataent.form_dict.new) and (dataent.session.user != "Guest" or not self.login_required)) if context.success_message: context.success_message = dataent.db.escape( context.success_message.replace("\n", "<br>")) self.add_custom_context_and_script(context) if not context.max_attachment_size: context.max_attachment_size = get_max_file_size() / 1024 / 1024 context.show_in_grid = self.show_in_grid