Example #1
0
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
Example #2
0
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)
Example #3
0
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)
Example #4
0
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
Example #5
0
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
Example #6
0
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
Example #7
0
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'
Example #8
0
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}
Example #9
0
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)
Example #10
0
 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")
Example #11
0
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)
Example #12
0
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
Example #13
0
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)
Example #14
0
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
Example #15
0
    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()