def savedocs(doc, action): """save / submit / update doclist""" try: doc = dataent.get_doc(json.loads(doc)) set_local_name(doc) # action doc.docstatus = { "Save": 0, "Submit": 1, "Update": 1, "Cancel": 2 }[action] if doc.docstatus == 1: doc.submit() else: try: doc.save() except dataent.NameError as e: doctype, name, original_exception = e if isinstance( e, tuple) else (doc.doctype or "", doc.name or "", None) dataent.msgprint( dataent._("{0} {1} already exists").format(doctype, name)) raise # update recent documents run_onload(doc) dataent.get_user().update_recent(doc.doctype, doc.name) send_updated_docs(doc) except Exception: dataent.errprint(dataent.utils.get_traceback()) raise
def add_webhook(doc, session): """Use Mandrill API to add the webhook""" r = session.post( get_api_url("/webhooks/add.json"), data=json.dumps({ "key": doc.password, "url": get_webhook_post_url(), "description": _("Dataent Mandrill Integration"), "events": [ # subscribe to these events # NOTE: 'deferral' event wasn't allowed at the time of making this "send", "hard_bounce", "soft_bounce", "open", "click", "spam", "unsub", "reject" ] })) if r.status_code != 200: # something went wrong dataent.msgprint(_("Could not activate Mandrill Integration")) dataent.errprint(r.text) return # store its value in Email Account mandrill_webhook_key = r.json()["auth_key"] doc.db_set("mandrill_webhook_key", mandrill_webhook_key)
def take_backups_s3(): try: backup_to_s3() send_email(True, "S3 Backup Settings") except Exception: error_message = dataent.get_traceback() dataent.errprint(error_message) send_email(False, "S3 Backup Settings", error_message)
def report_error(status_code): '''Build error. Show traceback in developer mode''' if (cint(dataent.db.get_system_setting('allow_error_traceback')) and (status_code != 404 or dataent.conf.logging) and not dataent.local.flags.disable_traceback): dataent.errprint(dataent.utils.get_traceback()) response = build_response("json") response.status_code = status_code return response
def webhook_exists(doc, session): """Use Mandrill API to find a list of existing webhooks""" r = session.post(get_api_url("/webhooks/list.json"), data={"key": doc.password}) if r.status_code != 200: # something went wrong dataent.msgprint(_("Could not connect to Mandrill Integration")) dataent.errprint(r.text) return webhooks = r.json() return False if len(webhooks) == 0 else True
def cancel(doctype=None, name=None, workflow_state_fieldname=None, workflow_state=None): """cancel a doclist""" try: doc = dataent.get_doc(doctype, name) if workflow_state_fieldname and workflow_state: doc.set(workflow_state_fieldname, workflow_state) doc.cancel() send_updated_docs(doc) except Exception: dataent.errprint(dataent.utils.get_traceback()) dataent.msgprint(dataent._("Did not cancel")) raise
def validate_link(): """validate link when updated by user""" import dataent import dataent.utils value, options, fetch = dataent.form_dict.get( 'value'), dataent.form_dict.get('options'), dataent.form_dict.get( 'fetch') # no options, don't validate if not options or options == 'null' or options == 'undefined': dataent.response['message'] = 'Ok' return valid_value = dataent.db.sql( "select name from `tab%s` where name=%s" % (dataent.db.escape(options), '%s'), (value, )) if valid_value: valid_value = valid_value[0][0] # get fetch values if fetch: # escape with "`" fetch = ", ".join(("`{0}`".format(dataent.db.escape(f.strip())) for f in fetch.split(","))) fetch_value = None try: fetch_value = dataent.db.sql( "select %s from `tab%s` where name=%s" % (fetch, dataent.db.escape(options), '%s'), (value, ))[0] except Exception as e: error_message = str(e).split("Unknown column '") fieldname = None if len( error_message) <= 1 else error_message[1].split("'")[0] dataent.msgprint( _("Wrong fieldname <b>{0}</b> in add_fetch configuration of custom script" ).format(fieldname)) dataent.errprint(dataent.get_traceback()) if fetch_value: dataent.response['fetch_values'] = [ dataent.utils.parse_val(c) for c in fetch_value ] dataent.response['valid_value'] = valid_value dataent.response['message'] = 'Ok'
def upload(): if not dataent.has_permission("Attendance", "create"): raise dataent.PermissionError from dataent.utils.csvutils import read_csv_content_from_uploaded_file from dataent.modules import scrub rows = read_csv_content_from_uploaded_file() rows = list(filter(lambda x: x and any(x), rows)) if not rows: msg = [_("Please select a csv file")] return {"messages": msg, "error": msg} columns = [scrub(f) for f in rows[4]] columns[0] = "name" columns[3] = "attendance_date" ret = [] error = False from dataent.utils.csvutils import check_record, import_doc for i, row in enumerate(rows[5:]): if not row: continue row_idx = i + 5 d = dataent._dict(zip(columns, row)) d["doctype"] = "Attendance" if d.name: d["docstatus"] = dataent.db.get_value("Attendance", d.name, "docstatus") try: check_record(d) ret.append(import_doc(d, "Attendance", 1, row_idx, submit=True)) except AttributeError: pass except Exception as e: error = True ret.append('Error for row (#%d) %s : %s' % (row_idx, len(row) > 1 and row[1] or "", cstr(e))) dataent.errprint(dataent.get_traceback()) if error: dataent.db.rollback() else: dataent.db.commit() return {"messages": ret, "error": error}
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 explain_query(self, query, values=None): """Print `EXPLAIN` in error log.""" try: dataent.errprint("--- query explain ---") if values is None: self._cursor.execute("explain " + query) else: self._cursor.execute("explain " + query, values) import json dataent.errprint(json.dumps(self.fetch_as_dict(), indent=1)) dataent.errprint("--- query explain end ---") except: dataent.errprint("error in query explain")
def take_backup_to_dropbox(retry_count=0, upload_db_backup=True): did_not_upload, error_log = [], [] try: if cint(dataent.db.get_value("Dropbox Settings", None, "enabled")): did_not_upload, error_log = backup_to_dropbox(upload_db_backup) if did_not_upload: raise Exception send_email(True, "Dropbox") except JobTimeoutException: if retry_count < 2: args = { "retry_count": retry_count + 1, "upload_db_backup": False #considering till worker timeout db backup is uploaded } enqueue("dataent.integrations.doctype.dropbox_settings.dropbox_settings.take_backup_to_dropbox", queue='long', timeout=1500, **args) except Exception: file_and_error = [" - ".join(f) for f in zip(did_not_upload, error_log)] error_message = ("\n".join(file_and_error) + "\n" + dataent.get_traceback()) dataent.errprint(error_message) send_email(False, "Dropbox", error_message)
def uploadfile(): ret = None try: if dataent.form_dict.get('from_form'): try: ret = dataent.utils.file_manager.upload() except dataent.DuplicateEntryError: # ignore pass ret = None dataent.db.rollback() else: if dataent.form_dict.get('method'): method = dataent.get_attr(dataent.form_dict.method) is_whitelisted(method) ret = method() except Exception: dataent.errprint(dataent.utils.get_traceback()) dataent.response['http_status_code'] = 500 ret = None return ret
def update_controller_context(context, controller): module = dataent.get_module(controller) if module: # get config fields for prop in ("base_template_path", "template", "no_cache", "no_sitemap", "condition_field"): if hasattr(module, prop): context[prop] = getattr(module, prop) if hasattr(module, "get_context"): try: ret = module.get_context(context) if ret: context.update(ret) except (dataent.PermissionError, dataent.DoesNotExistError, dataent.Redirect): raise except: if not dataent.flags.in_migrate: dataent.errprint(dataent.utils.get_traceback()) if hasattr(module, "get_children"): context.children = module.get_children(context)
def check_matching_amount(bank_account, company, transaction): payments = [] amount = transaction.credit if transaction.credit > 0 else transaction.debit payment_type = "Receive" if transaction.credit > 0 else "Pay" account_from_to = "paid_to" if transaction.credit > 0 else "paid_from" currency_field = "paid_to_account_currency as currency" if transaction.credit > 0 else "paid_from_account_currency as currency" payment_entries = dataent.get_all( "Payment Entry", fields=[ "'Payment Entry' as doctype", "name", "paid_amount", "payment_type", "reference_no", "reference_date", "party", "party_type", "posting_date", "{0}".format(currency_field) ], filters=[["paid_amount", "like", "{0}%".format(amount)], ["docstatus", "=", "1"], ["payment_type", "=", [payment_type, "Internal Transfer"]], ["ifnull(clearance_date, '')", "=", ""], [ "{0}".format(account_from_to), "=", "{0}".format(bank_account) ]]) if transaction.credit > 0: journal_entries = dataent.db.sql(""" SELECT 'Journal Entry' as doctype, je.name, je.posting_date, je.cheque_no as reference_no, je.pay_to_recd_from as party, je.cheque_date as reference_date, jea.debit_in_account_currency as paid_amount FROM `tabJournal Entry Account` as jea JOIN `tabJournal Entry` as je ON jea.parent = je.name WHERE (je.clearance_date is null or je.clearance_date='0000-00-00') AND jea.account = %s AND jea.debit_in_account_currency like %s AND je.docstatus = 1 """, (bank_account, amount), as_dict=True) else: journal_entries = dataent.db.sql(""" SELECT 'Journal Entry' as doctype, je.name, je.posting_date, je.cheque_no as reference_no, jea.account_currency as currency, je.pay_to_recd_from as party, je.cheque_date as reference_date, jea.credit_in_account_currency as paid_amount FROM `tabJournal Entry Account` as jea JOIN `tabJournal Entry` as je ON jea.parent = je.name WHERE (je.clearance_date is null or je.clearance_date='0000-00-00') AND jea.account = %(bank_account)s AND jea.credit_in_account_currency like %(txt)s AND je.docstatus = 1 """, { 'bank_account': bank_account, 'txt': '%%%s%%' % amount }, as_dict=True) dataent.errprint(journal_entries) if transaction.credit > 0: sales_invoices = dataent.db.sql(""" SELECT 'Sales Invoice' as doctype, si.name, si.customer as party, si.posting_date, sip.amount as paid_amount FROM `tabSales Invoice Payment` as sip JOIN `tabSales Invoice` as si ON sip.parent = si.name WHERE (sip.clearance_date is null or sip.clearance_date='0000-00-00') AND sip.account = %s AND sip.amount like %s AND si.docstatus = 1 """, (bank_account, amount), as_dict=True) else: sales_invoices = [] if transaction.debit > 0: purchase_invoices = dataent.get_all( "Purchase Invoice", fields=[ "'Purchase Invoice' as doctype", "name", "paid_amount", "supplier as party", "posting_date", "currency" ], filters=[["paid_amount", "like", "{0}%".format(amount)], ["docstatus", "=", "1"], ["is_paid", "=", "1"], ["ifnull(clearance_date, '')", "=", ""], ["cash_bank_account", "=", "{0}".format(bank_account)]]) mode_of_payments = [ x["parent"] for x in dataent.db.get_list( "Mode of Payment Account", filters={"default_account": bank_account}, fields=["parent"]) ] company_currency = get_company_currency(company) expense_claims = dataent.get_all( "Expense Claim", fields=[ "'Expense Claim' as doctype", "name", "total_sanctioned_amount as paid_amount", "employee as party", "posting_date", "'{0}' as currency".format(company_currency) ], filters=[[ "total_sanctioned_amount", "like", "{0}%".format(amount) ], ["docstatus", "=", "1"], ["is_paid", "=", "1"], ["ifnull(clearance_date, '')", "=", ""], [ "mode_of_payment", "in", "{0}".format(tuple(mode_of_payments)) ]]) else: purchase_invoices = expense_claims = [] for data in [ payment_entries, journal_entries, sales_invoices, purchase_invoices, expense_claims ]: if data: payments.extend(data) return payments
def sql(self, query, values=(), as_dict=0, as_list=0, formatted=0, debug=0, ignore_ddl=0, as_utf8=0, auto_commit=0, update=None, explain=False): """Execute a SQL query and fetch all rows. :param query: SQL query. :param values: List / dict of values to be escaped and substituted in the query. :param as_dict: Return as a dictionary. :param as_list: Always return as a list. :param formatted: Format values like date etc. :param debug: Print query and `EXPLAIN` in debug log. :param ignore_ddl: Catch exception if table, column missing. :param as_utf8: Encode values as UTF 8. :param auto_commit: Commit after executing the query. :param update: Update this dict to all rows (if returned `as_dict`). Examples: # return customer names as dicts dataent.db.sql("select name from tabCustomer", as_dict=True) # return names beginning with a dataent.db.sql("select name from tabCustomer where name like %s", "a%") # values as dict dataent.db.sql("select name from tabCustomer where name like %(name)s and owner=%(owner)s", {"name": "a%", "owner":"*****@*****.**"}) """ if not self._conn: self.connect() # in transaction validations self.check_transaction_status(query) # autocommit if auto_commit: self.commit() # execute try: if debug: time_start = time() if values != (): if isinstance(values, dict): values = dict(values) # MySQL-python==1.2.5 hack! if not isinstance(values, (dict, tuple, list)): values = (values, ) if debug and query.strip().lower().startswith('select'): try: if explain: self.explain_query(query, values) dataent.errprint(query % values) except TypeError: dataent.errprint([query, values]) if (dataent.conf.get("logging") or False) == 2: dataent.log("<<<< query") dataent.log(query) dataent.log("with values:") dataent.log(values) dataent.log(">>>>") self._cursor.execute(query, values) if dataent.flags.in_migrate: self.log_touched_tables(query, values) else: if debug: if explain: self.explain_query(query) dataent.errprint(query) if (dataent.conf.get("logging") or False) == 2: dataent.log("<<<< query") dataent.log(query) dataent.log(">>>>") self._cursor.execute(query) if dataent.flags.in_migrate: self.log_touched_tables(query) if debug: time_end = time() dataent.errprint(("Execution time: {0} sec").format( round(time_end - time_start, 2))) except Exception as e: if ignore_ddl and e.args[0] in (ER.BAD_FIELD_ERROR, ER.NO_SUCH_TABLE, ER.CANT_DROP_FIELD_OR_KEY): pass # NOTE: causes deadlock # elif e.args[0]==2006: # # mysql has gone away # self.connect() # return self.sql(query=query, values=values, # as_dict=as_dict, as_list=as_list, formatted=formatted, # debug=debug, ignore_ddl=ignore_ddl, as_utf8=as_utf8, # auto_commit=auto_commit, update=update) else: raise if auto_commit: self.commit() # scrub output if required if as_dict: ret = self.fetch_as_dict(formatted, as_utf8) if update: for r in ret: r.update(update) return ret elif as_list: return self.convert_to_lists(self._cursor.fetchall(), formatted, as_utf8) elif as_utf8: return self.convert_to_lists(self._cursor.fetchall(), formatted, as_utf8) else: return self._cursor.fetchall()