Example #1
0
def check_doctype_restriction():
    restricted_docs = []
    employee = get_employee_code()
    max_priority = frappe.db.sql(
        "select max(priority) as max_priority from `tabEmployee Doctype Restriction`"
    )
    docs = frappe.db.get_values('Employee Doctype Restriction', {
        'employee': employee,
        'status': 'Open',
        'priority': max_priority[0][0]
    },
                                'document_type',
                                as_dict=True)
    for doc in docs:
        url = get_url_to_list(doc.document_type)
        if doc.document_type == "Employee":
            url = get_url_to_form(doc.document_type, employee)
        elif doc.document_type == "Employee Verification":
            # get name of the doc
            _emp_ver_name = frappe.db.get_value("Employee Verification",
                                                {"employee": employee})
            if _emp_ver_name:
                url = get_url_to_form(doc.document_type, _emp_ver_name)
        restricted_docs.append({"doc": doc.document_type, "url": url})
    return restricted_docs
		def _get_message(url=False):
			name = self.name
			employee_name = cstr(employee.employee_name)
			if url:
				name = get_url_to_form(self.doctype, self.name)
				employee_name = get_url_to_form("Employee", self.employee, label=employee_name)

			return (_("New Leave Application") + ": %s - " + _("Employee") + ": %s") % (name, employee_name)
Example #3
0
		def _get_message(url=False):
			name = self.name
			employee_name = cstr(employee.employee_name)
			if url:
				name = get_url_to_form(self.doctype, self.name)
				employee_name = get_url_to_form("Employee", self.employee, label=employee_name)

			return (_("New Leave Application") + ": %s - " + _("Employee") + ": %s") % (name, employee_name)
Example #4
0
def send_slack_message(webhook_url, message, reference_doctype, reference_name):
	slack_url = frappe.db.get_value("Slack Webhook URL", webhook_url, "webhook_url")
	doc_url = get_url_to_form(reference_doctype, reference_name)
	attachments = [
		{
			"fallback": _("See the document at {0}").format(doc_url),
			"actions": [
				{
				"type": "button",
				"text": _("Go to the document"),
				"url": doc_url,
				"style": "primary"
				}
			]
		}
	]
	data = {"text": message, "attachments": attachments}
	r = requests.post(slack_url, data=json.dumps(data))


	if r.ok == True:
		return 'success'

	elif r.ok == False:
		frappe.log_error(r.error, _('Slack Webhook Error'))
		return 'error'
Example #5
0
	def trigger_payments(self):
		"""Payment Workflow Utility
			1. Get all members due for payment
			1. Trigger Payment
			1. Update Membership
			1. Log success and failed payments
		"""
		if not self.enabled:
			frappe.throw("Please Enable E Mandate Payments in Membership Settings")
		members = self.get_members_due_for_payment()

		if not members:
			return

		for member in members:
			try:
				payment = self.trigger_payment_for_member(member)
				membership = self.update_membership_details(member, payment)
				self.successful_transaction.append(membership)
			except Exception as e:
				title = "E Mandate Payment Error for {0}".format(member.name)
				log = frappe.log_error(e, title)
				self.failed_transaction.append([member.name,get_url_to_form("Error Log", log.name), e])

		send_update_email(self.successful_transaction, self.failed_transaction)
Example #6
0
		def _get_message(url=False):
			if url:
				name = get_url_to_form(self.doctype, self.name)
			else:
				name = self.name

			return (_("Leave Application") + ": %s - %s") % (name, _(status))
def send_to_telegram(telegram_user,
                     message,
                     reference_doctype=None,
                     reference_name=None,
                     attachment=None):

    space = "\n" * 2
    telegram_chat_id = frappe.db.get_value('Telegram User Settings',
                                           telegram_user, 'telegram_chat_id')
    telegram_settings = frappe.db.get_value('Telegram User Settings',
                                            telegram_user, 'telegram_settings')
    telegram_token = frappe.db.get_value('Telegram Settings',
                                         telegram_settings, 'telegram_token')
    bot = telegram.Bot(token=telegram_token)

    if reference_doctype and reference_name:
        doc_url = get_url_to_form(reference_doctype, reference_name)
        telegram_doc_link = _("See the document at {0}").format(doc_url)
        if message:
            message = space + str(message) + space + str(telegram_doc_link)
            if type(attachment) is str:
                attachment = int(attachment)
            else:
                if attachment:
                    attachment = 1
            if attachment == 1:
                attachment_url = get_url_for_telegram(reference_doctype,
                                                      reference_name)
                message = message + space + attachment_url
            bot.send_message(chat_id=telegram_chat_id, text=message)

    else:
        message = space + str(message) + space
        bot.send_message(chat_id=telegram_chat_id, text=message)
Example #8
0
 def assign_to_role(role, reviewer=False):
     emails = get_emails_from_role(role)
     print "####### role = {} emails = {}".format(role, emails)
     name = ""
     for email in emails:
         if email == "*****@*****.**":
             continue
         print "email = {}".format(email)
         print "role[-2] = {}".format(role[:-2])
         if (reviewer):
             name = role
         else:
             name = role[:-2]
         add({
             "assign_to":
             email,
             "doctype":
             "Task",
             "name":
             doc.project + " - " + name,
             "description":
             "New Task : " + doc.project + " - " + name + "<br><br>" +
             "<a href='" + get_url_to_form("Task", doc.project + " - " +
                                           name) +
             "' target='_self'>&nbsp; Click Hear To open Task</a>"
         })
Example #9
0
    def get_purchase_orders_items_overdue_list(self):
        fields_po = "distinct `tabPurchase Order Item`.parent as po"
        fields_poi = "`tabPurchase Order Item`.parent, `tabPurchase Order Item`.schedule_date, item_code," \
                     "received_qty, qty - received_qty as missing_qty, rate, amount"

        sql_po = """select {fields} from `tabPurchase Order Item`
			left join `tabPurchase Order` on `tabPurchase Order`.name = `tabPurchase Order Item`.parent
			where status<>'Closed' and `tabPurchase Order Item`.docstatus=1 and curdate() > `tabPurchase Order Item`.schedule_date
			and received_qty < qty order by `tabPurchase Order Item`.parent DESC,
			`tabPurchase Order Item`.schedule_date DESC""".format(fields=fields_po)

        sql_poi = """select {fields} from `tabPurchase Order Item`
			left join `tabPurchase Order` on `tabPurchase Order`.name = `tabPurchase Order Item`.parent
			where status<>'Closed' and `tabPurchase Order Item`.docstatus=1 and curdate() > `tabPurchase Order Item`.schedule_date
			and received_qty < qty order by `tabPurchase Order Item`.idx""".format(
            fields=fields_poi)
        purchase_order_list = frappe.db.sql(sql_po, as_dict=True)
        purchase_order_items_overdue_list = frappe.db.sql(sql_poi,
                                                          as_dict=True)

        for t in purchase_order_items_overdue_list:
            t.link = get_url_to_form("Purchase Order", t.parent)
            t.rate = fmt_money(t.rate, 2, t.currency)
            t.amount = fmt_money(t.amount, 2, t.currency)
        return purchase_order_list, purchase_order_items_overdue_list
Example #10
0
    def get_access_token(self, oauth_token, oauth_verifier):
        auth = tweepy.OAuthHandler(
            self.consumer_key, self.get_password(fieldname="consumer_secret"))
        auth.request_token = {
            "oauth_token": oauth_token,
            "oauth_token_secret": oauth_verifier
        }

        try:
            auth.get_access_token(oauth_verifier)
            self.access_token = auth.access_token
            self.access_token_secret = auth.access_token_secret
            api = self.get_api()
            user = api.me()
            profile_pic = (user._json["profile_image_url"]).replace(
                "_normal", "")

            frappe.db.set_value(
                self.doctype,
                self.name,
                {
                    "access_token": auth.access_token,
                    "access_token_secret": auth.access_token_secret,
                    "account_name": user._json["screen_name"],
                    "profile_pic": profile_pic,
                    "session_status": "Active",
                },
            )

            frappe.local.response["type"] = "redirect"
            frappe.local.response["location"] = get_url_to_form(
                "Twitter Settings", "Twitter Settings")
        except TweepError as e:
            frappe.msgprint(_("Error! Failed to get access token."))
            frappe.throw(_("Invalid Consumer Key or Consumer Secret Key"))
Example #11
0
def send_slack_message(webhook_url, message, reference_doctype,
                       reference_name):
    data = {"text": message, "attachments": []}

    slack_url, show_link = frappe.db.get_value(
        "Slack Webhook URL", webhook_url,
        ["webhook_url", "show_document_link"])

    if show_link:
        doc_url = get_url_to_form(reference_doctype, reference_name)
        link_to_doc = {
            "fallback":
            _("See the document at {0}").format(doc_url),
            "actions": [{
                "type": "button",
                "text": _("Go to the document"),
                "url": doc_url,
                "style": "primary",
            }],
        }
        data["attachments"].append(link_to_doc)

    r = requests.post(slack_url, data=json.dumps(data))

    if not r.ok:
        message = error_messages.get(r.status_code, r.status_code)
        frappe.log_error(message, _("Slack Webhook Error"))
        return "error"

    return "success"
Example #12
0
def send_notification_email(doc):

	if doc.type == 'Energy Point' and doc.email_content is None:
		return

	from frappe.utils import get_url_to_form, strip_html

	doc_link = get_url_to_form(doc.document_type, doc.document_name)
	header = get_email_header(doc)
	email_subject = strip_html(doc.subject)

	frappe.sendmail(
		recipients = doc.for_user,
		subject = email_subject,
		template = "new_notification",
		args = {
			'body_content': doc.subject,
			'description': doc.email_content,
			'document_type': doc.document_type,
			'document_name': doc.document_name,
			'doc_link': doc_link
		},
		header = [header, 'orange'],
		now=frappe.flags.in_test
	)
Example #13
0
def _make_customer(source_name, ignore_permissions=False):
    quotation = frappe.db.get_value("Quotation", source_name,
                                    ["lead", "order_type"])
    if quotation and quotation[0]:
        lead_name = quotation[0]
        customer_name = frappe.db.get_value("Customer",
                                            {"lead_name": lead_name})
        if not customer_name:
            from erpnext.selling.doctype.lead.lead import _make_customer
            customer_doclist = _make_customer(
                lead_name, ignore_permissions=ignore_permissions)
            customer = frappe.bean(customer_doclist)
            customer.ignore_permissions = ignore_permissions
            if quotation[1] == "Shopping Cart":
                customer.doc.customer_group = frappe.db.get_value(
                    "Shopping Cart Settings", None, "default_customer_group")

            try:
                customer.insert()
                return customer
            except NameError:
                if frappe.defaults.get_global_default(
                        'cust_master_name') == "Customer Name":
                    customer.run_method("autoname")
                    customer.doc.name += "-" + lead_name
                    customer.insert()
                    return customer
                else:
                    raise
            except frappe.MandatoryError:
                from frappe.utils import get_url_to_form
                frappe.throw(_("Before proceeding, please create Customer from Lead") + \
                 (" - %s" % get_url_to_form("Lead", lead_name)))
Example #14
0
def notify_assignment(assigned_by,
                      owner,
                      doc_type,
                      doc_name,
                      action='CLOSE',
                      description=None,
                      notify=0):
    """
		Notify assignee that there is a change in assignment
	"""
    if not (assigned_by and owner and doc_type and doc_name): return

    # self assignment / closing - no message
    if assigned_by == owner:
        return

    from frappe.boot import get_fullnames
    user_info = get_fullnames()

    # Search for email address in description -- i.e. assignee
    from frappe.utils import get_url_to_form
    assignment = get_url_to_form(doc_type,
                                 doc_name,
                                 label="%s: %s" % (doc_type, doc_name))

    if action == 'CLOSE':
        if owner == frappe.session.get('user'):
            arg = {
                'contact':
                assigned_by,
                'txt':
                _("The task %s, that you assigned to %s, has been closed.") %
                (assignment, user_info.get(owner, {}).get('fullname'))
            }
        else:
            arg = {
                'contact':
                assigned_by,
                'txt':
                _("The task %s, that you assigned to %s, has been closed by %s."
                  ) %
                (assignment, user_info.get(owner, {}).get('fullname'),
                 user_info.get(frappe.session.get('user'), {}).get('fullname'))
            }
    else:
        arg = {
            'contact':
            owner,
            'txt':
            _("A new task, %s, has been assigned to you by %s. %s") %
            (assignment, user_info.get(frappe.session.get('user'),
                                       {}).get('fullname'), description and
             ("<p>" + _("Description") + ": " + description + "</p>") or ""),
            'notify':
            notify
        }

    arg["parenttype"] = "Assignment"
    from frappe.desk.page.messages import messages
    messages.post(**arg)
		def _get_message(url=False):
			if url:
				name = get_url_to_form(self.doctype, self.name)
			else:
				name = self.name

			return (_("Leave Application") + ": %s - %s") % (name, _(status))
Example #16
0
    def get_todo_list(self, user_id):
        todo_list = frappe.db.sql("""select *
			from `tabToDo` where (owner=%s or assigned_by=%s) and status="Open"
			order by field(priority, 'High', 'Medium', 'Low') asc, date asc""",
                                  (user_id, user_id),
                                  as_dict=True)

        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 execute():
	wrong_records = []
	for dt in ("Quotation", "Sales Order", "Delivery Note", "Sales Invoice", 
		"Purchase Order", "Purchase Receipt", "Purchase Invoice"):
			records = frappe.db.sql_list("""select name from `tab{0}` 
				where apply_discount_on = 'Net Total' and ifnull(discount_amount, 0) != 0
				and modified >= '2015-02-17' and docstatus=1""".format(dt))
		
			if records:
				records = [get_url_to_form(dt, d) for d in records]
				wrong_records.append([dt, records])
				
	if wrong_records:
		content = """Dear System Manager,

Due to an error related to Discount Amount on Net Total, tax calculation might be wrong in the following records. We did not fix the tax amount automatically because it can corrupt the entries, so we request you to check these records and amend if you found the calculation wrong.

Please check following Entries:

%s


Regards,

Administrator""" % "\n".join([(d[0] + ": " + ", ".join(d[1])) for d in wrong_records])
		try:
			sendmail_to_system_managers("[Important] [ERPNext] Tax calculation might be wrong, please check.", content)
		except:
			pass
		
		print "="*50
		print content
		print "="*50
Example #18
0
    def get_todo_list(self, user_id):
        todo_list = frappe.db.sql(
            """select *
			from `tabToDo` where (owner=%s or assigned_by=%s)
			order by field(priority, 'High', 'Medium', 'Low') asc, date asc""",
            (user_id, user_id),
            as_dict=True,
        )

        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>"
Example #19
0
def background_enqueue_run(report_name, filters=None, user=None):
    """run reports in background"""
    if not user:
        user = frappe.session.user
    report = get_report_doc(report_name)
    track_instance = \
     frappe.get_doc({
      "doctype": "Prepared Report",
      "report_name": report_name,
      # This looks like an insanity but, without this it'd be very hard to find Prepared Reports matching given condition
      # We're ensuring that spacing is consistent. e.g. JS seems to put no spaces after ":", Python on the other hand does.
      "filters": json.dumps(json.loads(filters)),
      "ref_report_doctype": report_name,
      "report_type": report.report_type,
      "query": report.query,
      "module": report.module,
     })
    track_instance.insert(ignore_permissions=True)
    frappe.db.commit()
    track_instance.enqueue_report()

    return {
        "name": track_instance.name,
        "redirect_url": get_url_to_form("Prepared Report", track_instance.name)
    }
Example #20
0
def approve_attendance(doc, method):
    user = frappe.session.user
    if not doc.attendance_approver:
        frappe.throw(_("Please set Attendance Approver on Employee form"))
    if doc.attendance_approver and user != doc.attendance_approver:
        frappe.throw(
            _("Only '{0}' can approve this Attendance.").format(
                doc.attendance_approver))
    else:
        frappe.db.set_value(doc.doctype, doc.name, "approval_status",
                            "Approved")
        att_details = {
            "approver": doc.attendance_approver,
            "date": doc.att_date,
            "path": get_url_to_form(doc.doctype, doc.name),
            "status": "approved"
        }
        template = "templates/emails/attendance_notification.html"

        subject = "Attendance approved for date {0}.".format(doc.att_date)
        recipients = frappe.db.get_value("Employee", doc.employee, "user_id")
        message = frappe.get_template(template).render(
            {"att_details": att_details})
        frappe.sendmail(recipients=recipients,
                        subject=subject,
                        message=message)
Example #21
0
	def stock_entry_received(self):
		se = frappe.new_doc("Stock Entry")
		se.posting_date = self.received_date
		se.purpose = "Repack"
		se.naming_series = "STE-"
		se.company = self.company
		se.volume = self.volume
		se.volume_rate = self.volume_rate
		se.volume_cost = self.volume_cost
		
		abbr = frappe.db.get_value("Company",self.company,'abbr')

		if self.get('bom_no'):
			se.from_bom = 1
			se.bom_no = self.bom_no
			se.fg_completed_qty = flt(self.finished_product_qty)
			se.based_on = self.based_on
	
		for row in self.items:
			se.append("items",{
				'item_code': row.item_code,
				's_warehouse': 'Jobwork - ' + abbr,
				'qty': row.received_qty,
				'batch_no': row.batch_no,
				'basic_rate': row.rate,
				'lot_no': row.lot_no,
				'packaging_material': row.packaging_material,
				'packing_size': row.packing_size,
				'batch_yield': row.batch_yield,
				'concentration': row.concentration
			})

		se.append("items",{
			'item_code': self.finished_product,
			't_warehouse': self.finished_product_warehouse,
			'qty': self.finished_product_qty,
			'packaging_material': self.packaging_material,
			'packing_size': self.packing_size,
			'lot_no': self.lot_no,
			'concentration': self.concentration,
			'batch_yield': self.batch_yield,
		})

		for row in self.additional_costs:
			se.append('additional_costs', {
				'description': row.description,
				'amount': row.amount,
			})

		try:
			se.save()
			se.submit()
			self.db_set('received_stock_entry' , se.name)
			self.db_set('valuation_rate' , se.items[-1].valuation_rate)
			url = get_url_to_form("Stock Entry", se.name)
			frappe.msgprint("New Stock Entry - <a href='{url}'>{doc}</a> created of Repack for Finished Product".format(url=url, doc=frappe.bold(se.name)))
		except:
			frappe.db.rollback()
			frappe.throw(_("Error creating Stock Entry"), title="Error")
Example #22
0
	def cancel_received(self):
		if self.received_stock_entry:
			se = frappe.get_doc("Stock Entry",self.received_stock_entry)
			se.cancel()
			frappe.db.commit()
			self.db_set('received_stock_entry','')
			url = get_url_to_form("Stock Entry", se.name)
			frappe.msgprint("Cancelled Stock Entry - <a href='{url}'>{doc}</a>".format(url=url, doc=frappe.bold(se.name)))
Example #23
0
def callback(oauth_token=None, oauth_verifier=None):
    if oauth_token and oauth_verifier:
        twitter_settings = frappe.get_single("Twitter Settings")
        twitter_settings.get_access_token(oauth_token, oauth_verifier)
        frappe.db.commit()
    else:
        frappe.local.response["type"] = "redirect"
        frappe.local.response["location"] = get_url_to_form(
            "Twitter Settings", "Twitter Settings")
Example #24
0
def callback(code=None, error=None, error_description=None):
	if not error:
		linkedin_settings = frappe.get_doc("LinkedIn Settings")
		linkedin_settings.get_access_token(code)
		linkedin_settings.get_member_profile()
		frappe.db.commit()
	else:
		frappe.local.response["type"] = "redirect"
		frappe.local.response["location"] = get_url_to_form("LinkedIn Settings","LinkedIn Settings")
Example #25
0
def opportunity_send_mail(self, method):
    if self.service == 'TGT':
        link = get_url_to_form("Opportunity", self.name)
        subject = 'Reg.Opportunity- %s' % self.name
        content = """Dear Mam<br>Kindly find the new Opportunity.
        Click on <a href='%s'>View</a> to open the opportunity.<br>Thanks & Regards,<br>ERP
        """ % link
        frappe.sendmail(recipients=['*****@*****.**'],
                        subject=subject,
                        message=content)
Example #26
0
def get_project_details():
    '''Get all projects details'''

    project_data = []
    projects = frappe.db.get_all(
        "Project", fields=["name", "priority", "percent_complete", "_assign"])

    for project in projects:
        project_users = []

        total_tasks = frappe.db.count("Task",
                                      filters={"project": project.name})
        closed_tasks = frappe.db.count("Task",
                                       filters={
                                           "project": project.name,
                                           "status": "Completed"
                                       })
        assigned_users = json.loads(project._assign) if project._assign else []

        for assignee in assigned_users:
            full_name = frappe.db.get_value("User", assignee, "full_name")
            assignee_tasks = frappe.get_list(
                "Task",
                filters={"_assign": ["like", "%{}%".format(assignee)]},
                fields=["name", "status"])

            user_data = {
                "name": assignee,
                "label": full_name,
                "avatar": get_gravatar_url(assignee),
                "tasks": []
            }

            for task in assignee_tasks:
                user_data["tasks"].append({
                    "url":
                    get_url_to_form("Task", task.name),
                    "status":
                    task.status
                })

            project_users.append(user_data)

        project_data.append({
            "name": project.name,
            "totalTasks": total_tasks,
            "closedTasks": closed_tasks,
            "percentCompleted": project.percent_complete,
            "priority": project.priority,
            "assigned": project_users
        })

    return project_data
Example #27
0
	def get_calendar_events(self):
		"""Get calendar events for given user"""
		from frappe.desk.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")) or []

		for i, e in enumerate(events):
			e.starts_on_label = format_time(e.starts_on)
			e.ends_on_label = format_time(e.ends_on) if e.ends_on else None
			e.date = formatdate(e.starts)
			e.link = get_url_to_form("Event", e.name)

		return events
Example #28
0
	def get_project_list(self, user_id=None):
		"""Get project list"""
		if not user_id:
			user_id = frappe.session.user

		project_list = frappe.db.sql("""select *
			from `tabProject` where status='Open' and project_type='External'
			order by modified asc limit 10""", as_dict=True)

		for t in project_list:
			t.link = get_url_to_form("Issue", t.name)

		return project_list
Example #29
0
	def get_project_list(self, user_id=None):
		"""Get project list"""
		if not user_id:
			user_id = frappe.session.user

		project_list = frappe.db.sql("""select *
			from `tabProject` where status='Open' and project_type='External'
			order by modified asc limit 10""", as_dict=True)

		for t in project_list:
			t.link = get_url_to_form("Issue", t.name)

		return project_list
Example #30
0
 def validate(self):
     if frappe.db.exists("Supplier Items", {
             'supplier': self.supplier,
             'item_code': self.item_code
     }):
         name = frappe.db.get_value("Supplier Items", {
             'supplier': self.supplier,
             'item_code': self.item_code
         })
         url = get_url_to_form("Supplier Items", name)
         frappe.throw(
             _("Record already exist. <br><b><a href='{url}'>{name}</a></b>."
               .format(url=url, name=name)))
Example #31
0
    def get_calendar_events(self):
        """Get calendar events for given user"""
        from frappe.desk.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")) or []

        for i, e in enumerate(events):
            e.starts_on_label = format_time(e.starts_on)
            e.ends_on_label = format_time(e.ends_on) if e.ends_on else None
            e.date = formatdate(e.starts)
            e.link = get_url_to_form("Event", e.name)

        return events
Example #32
0
	def get_todo_list(self, user_id=None):
		"""Get to-do list"""
		if not user_id:
			user_id = frappe.session.user

		todo_list = frappe.db.sql("""select *
			from `tabToDo` where (owner=%s or assigned_by=%s) and status="Open"
			order by field(priority, 'High', 'Medium', 'Low') asc, date asc limit 20""",
			(user_id, user_id), as_dict=True)

		for t in todo_list:
			t.link = get_url_to_form("ToDo", t.name)

		return todo_list
Example #33
0
	def get_todo_list(self, user_id=None):
		"""Get to-do list"""
		if not user_id:
			user_id = frappe.session.user

		todo_list = frappe.db.sql("""select *
			from `tabToDo` where (owner=%s or assigned_by=%s) and status="Open"
			order by field(priority, 'High', 'Medium', 'Low') asc, date asc limit 20""",
			(user_id, user_id), as_dict=True)

		for t in todo_list:
			t.link = get_url_to_form("ToDo", t.name)

		return todo_list
Example #34
0
    def get_member_profile(self):
        response = requests.get(url="https://api.linkedin.com/v2/me",
                                headers=self.get_headers())
        response = frappe.parse_json(response.content.decode())

        frappe.db.set_value(
            self.doctype, self.name, {
                "person_urn": response["id"],
                "account_name": response["vanityName"],
                "session_status": "Active"
            })
        frappe.local.response["type"] = "redirect"
        frappe.local.response["location"] = get_url_to_form(
            "LinkedIn Settings", "LinkedIn Settings")
Example #35
0
def notify_assignment(assigned_by, owner, doc_type, doc_name, action='CLOSE',
	description=None, notify=0):
	"""
		Notify assignee that there is a change in assignment
	"""
	if not (assigned_by and owner and doc_type and doc_name): return

	# self assignment / closing - no message
	if assigned_by==owner:
		return

	from frappe.boot import get_fullnames
	user_info = get_fullnames()

	# Search for email address in description -- i.e. assignee
	from frappe.utils import get_url_to_form
	assignment = get_url_to_form(doc_type, doc_name, label="%s: %s" % (doc_type, doc_name))

	if action=='CLOSE':
		if owner == frappe.session.get('user'):
			arg = {
				'contact': assigned_by,
				'txt': "The task %s, that you assigned to %s, has been \
					closed." % (assignment,
						user_info.get(owner, {}).get('fullname'))
			}
		else:
			arg = {
				'contact': assigned_by,
				'txt': "The task %s, that you assigned to %s, \
					has been closed	by %s." % (assignment,
					user_info.get(owner, {}).get('fullname'),
					user_info.get(frappe.session.get('user'),
						{}).get('fullname'))
			}
	else:
		arg = {
			'contact': owner,
			'txt': "A new task, %s, has been assigned to you by %s. %s" \
				% (assignment,
				user_info.get(frappe.session.get('user'), {}).get('fullname'),
				description and ("<p>Description: " + description + "</p>") or ""),
			'notify': notify
		}

	arg["parenttype"] = "Assignment"
	from frappe.core.page.messages import messages
	import json
	messages.post(json.dumps(arg))
Example #36
0
	def get_calendar_events(self):
		"""Get calendar events for given user"""
		from frappe.desk.doctype.event.event import get_events
		from_date, to_date = get_future_date_for_calendaer_event(self.frequency)

		events = get_events(from_date, to_date)

		event_count = 0
		for i, e in enumerate(events):
			e.starts_on_label = format_time(e.starts_on)
			e.ends_on_label = format_time(e.ends_on) if e.ends_on else None
			e.date = formatdate(e.starts)
			e.link = get_url_to_form("Event", e.name)
			event_count += 1

		return events, event_count
def send_mail_to_approver(doctype,doc_name,att_date,employee_name,attendance_approver):
	attendance_doc = frappe.get_doc("Attendance",doc_name)
	attendance_doc.send_mail_to_approver = 1
	attendance_doc.save(ignore_permissions=True)
	att_details = {"employee": employee_name, "date": att_date,
				"path": get_url_to_form(doctype, doc_name), "status": "pending"}
	template = "templates/emails/attendance_notification.html"

	subject = "Pending Attendance Approval of {0} for date {1}.".format(employee_name,att_date)
	recipients = frappe.db.get_value("User",attendance_approver, "email")
	message = frappe.get_template(template).render({"att_details": att_details})
	try:
		frappe.sendmail(recipients=recipients, subject=subject,message= message)
		return "Success"
	except:
		msgprint(_("sendmail Error"), raise_exception=1)
Example #38
0
def send_mail_to_approver(doctype,doc_name,att_date,employee_name,attendance_approver):
	attendance_doc = frappe.get_doc("Attendance",doc_name)
	attendance_doc.send_mail_to_approver = 1
	attendance_doc.save(ignore_permissions=True)
	att_details = {"employee": employee_name, "date": att_date,
				"path": get_url_to_form(doctype, doc_name), "status": "pending"}
	template = "templates/emails/attendance_notification.html"

	subject = "Pending Attendance Approval of {0} for date {1}.".format(employee_name,att_date)
	recipients = frappe.db.get_value("User",attendance_approver, "email")
	message = frappe.get_template(template).render({"att_details": att_details})
	try:
		frappe.sendmail(recipients=recipients, subject=subject,message= message)
		return "Success"
	except:
		msgprint(_("sendmail Error"), raise_exception=1)
Example #39
0
    def create_stock_entry(self):
        se = frappe.new_doc("Stock Entry")
        se.naming_series = "STE-.fiscal.-"
        se.stock_entry_type = "Material Receipt"
        se.purpose = "Material Receipt"
        se.posting_date = self.posting_date
        se.posting_time = self.posting_time
        se.company = self.company
        se.set_posting_time = self.set_posting_time
        se.to_warehouse = self.warehouse
        se.fiscal = self.fiscal

        for row in self.items:
            se.append(
                "items", {
                    'item_code': row.item_code,
                    't_warehouse': row.t_warehouse,
                    'qty': row.qty,
                    'basic_rate': row.basic_rate,
                    'uom': row.uom,
                    'conversion_factor': row.conversion_factor,
                })

        for row in self.additional_costs:
            se.append(
                'additional_costs', {
                    'posting_date': row.posting_date,
                    'expense_account': row.expense_account,
                    'credit_account': row.credit_account,
                    'description': row.description,
                    'amount': row.amount,
                })

        try:
            se.save()
            se.submit()
        except:
            frappe.db.rollback()
            frappe.throw(_("Error creating Stock Entry"), title="Error")
        else:
            self.update_batch_no(se)
            self.db_set('stock_entry', se.name)
            url = get_url_to_form("Stock Entry", se.name)
            frappe.msgprint(
                "Stock Entry - <a href='{url}'>{doc}</a> created of Material Receipt."
                .format(url=url, doc=frappe.bold(se.name)))
            frappe.db.commit()
Example #40
0
	def get_issue_list(self, user_id=None):
		"""Get issue list"""
		if not user_id:
			user_id = frappe.session.user
		
		meta = frappe.get_meta("Issue")
		role_permissions = frappe.permissions.get_role_permissions(meta, user_id)
		if not role_permissions.get("read"):
			return None

		issue_list = frappe.db.sql("""select *
			from `tabIssue` where status in ("Replied","Open")
			order by modified asc limit 10""", as_dict=True)

		for t in issue_list:
			t.link = get_url_to_form("Issue", t.name)

		return issue_list
Example #41
0
	def get_issue_list(self, user_id=None):
		"""Get issue list"""
		if not user_id:
			user_id = frappe.session.user

		meta = frappe.get_meta("Issue")
		role_permissions = frappe.permissions.get_role_permissions(meta, user_id)
		if not role_permissions.get("read"):
			return None

		issue_list = frappe.db.sql("""select *
			from `tabIssue` where status in ("Replied","Open")
			order by modified asc limit 10""", as_dict=True)

		for t in issue_list:
			t.link = get_url_to_form("Issue", t.name)

		return issue_list
Example #42
0
def notify_assignment(assigned_by, owner, doc_type, doc_name, action='CLOSE',
	description=None, notify=0):
	"""
		Notify assignee that there is a change in assignment
	"""
	if not (assigned_by and owner and doc_type and doc_name): return

	# self assignment / closing - no message
	if assigned_by==owner:
		return

	from frappe.boot import get_fullnames
	user_info = get_fullnames()

	# Search for email address in description -- i.e. assignee
	from frappe.utils import get_url_to_form
	assignment = get_url_to_form(doc_type, doc_name, label="%s: %s" % (doc_type, doc_name))
	owner_name = user_info.get(owner, {}).get('fullname')
	user_name = user_info.get(frappe.session.get('user'), {}).get('fullname')
	if action=='CLOSE':
		if owner == frappe.session.get('user'):
			arg = {
				'contact': assigned_by,
				'txt': _("The task {0}, that you assigned to {1}, has been closed.").format(assignment,
						owner_name)
			}
		else:
			arg = {
				'contact': assigned_by,
				'txt': _("The task {0}, that you assigned to {1}, has been closed by {2}.").format(assignment,
					owner_name, user_name)
			}
	else:
		description_html = "<p>{0}</p>".format(description)
		arg = {
			'contact': owner,
			'txt': _("A new task, {0}, has been assigned to you by {1}. {2}").format(assignment,
				user_name, description_html),
			'notify': notify
		}

	arg["parenttype"] = "Assignment"
	from frappe.desk.page.messages import messages
	messages.post(**arg)
Example #43
0
	def get_purchase_orders_items_overdue_list(self):
		fields_po = "distinct `tabPurchase Order Item`.parent as po"
		fields_poi = "`tabPurchase Order Item`.parent, `tabPurchase Order Item`.schedule_date, item_code," \
		             "received_qty, qty - received_qty as missing_qty, rate, amount"

		sql_po = """select {fields} from `tabPurchase Order Item` 
			left join `tabPurchase Order` on `tabPurchase Order`.name = `tabPurchase Order Item`.parent
			where status<>'Closed' and `tabPurchase Order Item`.docstatus=1 and curdate() > `tabPurchase Order Item`.schedule_date
			and received_qty < qty order by `tabPurchase Order Item`.parent DESC,
			`tabPurchase Order Item`.schedule_date DESC""".format(fields=fields_po)

		sql_poi = """select {fields} from `tabPurchase Order Item` 
			left join `tabPurchase Order` on `tabPurchase Order`.name = `tabPurchase Order Item`.parent
			where status<>'Closed' and `tabPurchase Order Item`.docstatus=1 and curdate() > `tabPurchase Order Item`.schedule_date
			and received_qty < qty order by `tabPurchase Order Item`.idx""".format(fields=fields_poi)
		purchase_order_list = frappe.db.sql(sql_po, as_dict=True)
		purchase_order_items_overdue_list = frappe.db.sql(sql_poi, as_dict=True)

		for t in purchase_order_items_overdue_list:
			t.link = get_url_to_form("Purchase Order", t.parent)
			t.rate = fmt_money(t.rate, 2, t.currency)
			t.amount = fmt_money(t.amount, 2, t.currency)
		return purchase_order_list, purchase_order_items_overdue_list
Example #44
0
def background_enqueue_run(report_name, filters=None, user=None):
	"""run reports in background"""
	if not user:
		user = frappe.session.user
	report = get_report_doc(report_name)
	track_instance = \
		frappe.get_doc({
			"doctype": "Prepared Report",
			"report_name": report_name,
			# This looks like an insanity but, without this it'd be very hard to find Prepared Reports matching given condition
			# We're ensuring that spacing is consistent. e.g. JS seems to put no spaces after ":", Python on the other hand does.
			"filters": json.dumps(json.loads(filters)),
			"ref_report_doctype": report_name,
			"report_type": report.report_type,
			"query": report.query,
			"module": report.module,
		})
	track_instance.insert(ignore_permissions=True)
	frappe.db.commit()
	return {
		"name": track_instance.name,
		"redirect_url": get_url_to_form("Prepared Report", track_instance.name)
	}
Example #45
0
def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False, no_email=True, overwrite=None,
	update_only = None, ignore_links=False, pre_process=None, via_console=False, from_data_import="No",
	skip_errors = True, data_import_doc=None, validate_template=False, user=None):
	"""upload data"""

	# for translations
	if user:
		frappe.cache().hdel("lang", user)
		frappe.set_user_lang(user)

	if data_import_doc and isinstance(data_import_doc, string_types):
		data_import_doc = frappe.get_doc("Data Import", data_import_doc)
	if data_import_doc and from_data_import == "Yes":
		no_email = data_import_doc.no_email
		ignore_encoding_errors = data_import_doc.ignore_encoding_errors
		update_only = data_import_doc.only_update
		submit_after_import = data_import_doc.submit_after_import
		overwrite = data_import_doc.overwrite
		skip_errors = data_import_doc.skip_errors
	else:
		# extra input params
		params = json.loads(frappe.form_dict.get("params") or '{}')
		if params.get("submit_after_import"):
			submit_after_import = True
		if params.get("ignore_encoding_errors"):
			ignore_encoding_errors = True
		if not params.get("no_email"):
			no_email = False
		if params.get('update_only'):
			update_only = True
		if params.get('from_data_import'):
			from_data_import = params.get('from_data_import')
		if not params.get('skip_errors'):
			skip_errors = params.get('skip_errors')

	frappe.flags.in_import = True
	frappe.flags.mute_emails = no_email

	def get_data_keys_definition():
		return get_data_keys()

	def bad_template():
		frappe.throw(_("Please do not change the rows above {0}").format(get_data_keys_definition().data_separator))

	def check_data_length():
		if not data:
			frappe.throw(_("No data found in the file. Please reattach the new file with data."))

	def get_start_row():
		for i, row in enumerate(rows):
			if row and row[0]==get_data_keys_definition().data_separator:
				return i+1
		bad_template()

	def get_header_row(key):
		return get_header_row_and_idx(key)[0]

	def get_header_row_and_idx(key):
		for i, row in enumerate(header):
			if row and row[0]==key:
				return row, i
		return [], -1

	def filter_empty_columns(columns):
		empty_cols = list(filter(lambda x: x in ("", None), columns))

		if empty_cols:
			if columns[-1*len(empty_cols):] == empty_cols:
				# filter empty columns if they exist at the end
				columns = columns[:-1*len(empty_cols)]
			else:
				frappe.msgprint(_("Please make sure that there are no empty columns in the file."),
					raise_exception=1)

		return columns

	def make_column_map():
		doctype_row, row_idx = get_header_row_and_idx(get_data_keys_definition().doctype)
		if row_idx == -1: # old style
			return

		dt = None
		for i, d in enumerate(doctype_row[1:]):
			if d not in ("~", "-"):
				if d and doctype_row[i] in (None, '' ,'~', '-', _("DocType") + ":"):
					dt, parentfield = d, None
					# xls format truncates the row, so it may not have more columns
					if len(doctype_row) > i+2:
						parentfield = doctype_row[i+2]
					doctypes.append((dt, parentfield))
					column_idx_to_fieldname[(dt, parentfield)] = {}
					column_idx_to_fieldtype[(dt, parentfield)] = {}
				if dt:
					column_idx_to_fieldname[(dt, parentfield)][i+1] = rows[row_idx + 2][i+1]
					column_idx_to_fieldtype[(dt, parentfield)][i+1] = rows[row_idx + 4][i+1]

	def get_doc(start_idx):
		if doctypes:
			doc = {}
			attachments = []
			last_error_row_idx = None
			for idx in range(start_idx, len(rows)):
				last_error_row_idx = idx	# pylint: disable=W0612
				if (not doc) or main_doc_empty(rows[idx]):
					for dt, parentfield in doctypes:
						d = {}
						for column_idx in column_idx_to_fieldname[(dt, parentfield)]:
							try:
								fieldname = column_idx_to_fieldname[(dt, parentfield)][column_idx]
								fieldtype = column_idx_to_fieldtype[(dt, parentfield)][column_idx]

								if not fieldname or not rows[idx][column_idx]:
									continue

								d[fieldname] = rows[idx][column_idx]
								if fieldtype in ("Int", "Check"):
									d[fieldname] = cint(d[fieldname])
								elif fieldtype in ("Float", "Currency", "Percent"):
									d[fieldname] = flt(d[fieldname])
								elif fieldtype == "Date":
									if d[fieldname] and isinstance(d[fieldname], string_types):
										d[fieldname] = getdate(parse_date(d[fieldname]))
								elif fieldtype == "Datetime":
									if d[fieldname]:
										if " " in d[fieldname]:
											_date, _time = d[fieldname].split()
										else:
											_date, _time = d[fieldname], '00:00:00'
										_date = parse_date(d[fieldname])
										d[fieldname] = get_datetime(_date + " " + _time)
									else:
										d[fieldname] = None

								elif fieldtype in ("Image", "Attach Image", "Attach"):
									# added file to attachments list
									attachments.append(d[fieldname])

								elif fieldtype in ("Link", "Dynamic Link", "Data") and d[fieldname]:
									# as fields can be saved in the number format(long type) in data import template
									d[fieldname] = cstr(d[fieldname])

							except IndexError:
								pass

						# scrub quotes from name and modified
						if d.get("name") and d["name"].startswith('"'):
							d["name"] = d["name"][1:-1]

						if sum([0 if not val else 1 for val in d.values()]):
							d['doctype'] = dt
							if dt == doctype:
								doc.update(d)
							else:
								if not overwrite and doc.get("name"):
									d['parent'] = doc["name"]
								d['parenttype'] = doctype
								d['parentfield'] = parentfield
								doc.setdefault(d['parentfield'], []).append(d)
				else:
					break

			return doc, attachments, last_error_row_idx
		else:
			doc = frappe._dict(zip(columns, rows[start_idx][1:]))
			doc['doctype'] = doctype
			return doc, [], None

	# used in testing whether a row is empty or parent row or child row
	# checked only 3 first columns since first two columns can be blank for example the case of
	# importing the item variant where item code and item name will be blank.
	def main_doc_empty(row):
		if row:
			for i in range(3,0,-1):
				if len(row) > i and row[i]:
					return False
		return True

	def validate_naming(doc):
		autoname = frappe.get_meta(doctype).autoname
		if autoname:
			if autoname[0:5] == 'field':
				autoname = autoname[6:]
			elif autoname == 'naming_series:':
				autoname = 'naming_series'
			else:
				return True

			if (autoname not in doc) or (not doc[autoname]):
				from frappe.model.base_document import get_controller
				if not hasattr(get_controller(doctype), "autoname"):
					frappe.throw(_("{0} is a mandatory field".format(autoname)))
		return True

	users = frappe.db.sql_list("select name from tabUser")
	def prepare_for_insert(doc):
		# don't block data import if user is not set
		# migrating from another system
		if not doc.owner in users:
			doc.owner = frappe.session.user
		if not doc.modified_by in users:
			doc.modified_by = frappe.session.user

	def is_valid_url(url):
		is_valid = False
		if url.startswith("/files") or url.startswith("/private/files"):
			url = get_url(url)

		try:
			r = requests.get(url)
			is_valid = True if r.status_code == 200 else False
		except Exception:
			pass

		return is_valid

	def attach_file_to_doc(doctype, docname, file_url):
		# check if attachment is already available
		# check if the attachement link is relative or not
		if not file_url:
			return
		if not is_valid_url(file_url):
			return

		files = frappe.db.sql("""Select name from `tabFile` where attached_to_doctype='{doctype}' and
			attached_to_name='{docname}' and (file_url='{file_url}' or thumbnail_url='{file_url}')""".format(
				doctype=doctype,
				docname=docname,
				file_url=file_url
			))

		if files:
			# file is already attached
			return

		save_url(file_url, None, doctype, docname, "Home/Attachments", 0)

	# header
	filename, file_extension = ['','']
	if not rows:
		from frappe.utils.file_manager import get_file # get_file_doc
		fname, fcontent = get_file(data_import_doc.import_file)
		filename, file_extension = os.path.splitext(fname)

		if file_extension == '.xlsx' and from_data_import == 'Yes':
			from frappe.utils.xlsxutils import read_xlsx_file_from_attached_file
			rows = read_xlsx_file_from_attached_file(file_id=data_import_doc.import_file)

		elif file_extension == '.csv':
			from frappe.utils.csvutils import read_csv_content
			rows = read_csv_content(fcontent, ignore_encoding_errors)

		else:
			frappe.throw(_("Unsupported File Format"))

	start_row = get_start_row()
	header = rows[:start_row]
	data = rows[start_row:]
	try:
		doctype = get_header_row(get_data_keys_definition().main_table)[1]
		columns = filter_empty_columns(get_header_row(get_data_keys_definition().columns)[1:])
	except:
		frappe.throw(_("Cannot change header content"))
	doctypes = []
	column_idx_to_fieldname = {}
	column_idx_to_fieldtype = {}

	if skip_errors:
		data_rows_with_error = header

	if submit_after_import and not cint(frappe.db.get_value("DocType",
			doctype, "is_submittable")):
		submit_after_import = False

	parenttype = get_header_row(get_data_keys_definition().parent_table)

	if len(parenttype) > 1:
		parenttype = parenttype[1]

	# check permissions
	if not frappe.permissions.can_import(parenttype or doctype):
		frappe.flags.mute_emails = False
		return {"messages": [_("Not allowed to Import") + ": " + _(doctype)], "error": True}

	# Throw expception in case of the empty data file
	check_data_length()
	make_column_map()
	total = len(data)

	if validate_template:
		if total:
			data_import_doc.total_rows = total
		return True

	if overwrite==None:
		overwrite = params.get('overwrite')

	# delete child rows (if parenttype)
	parentfield = None
	if parenttype:
		parentfield = get_parent_field(doctype, parenttype)

		if overwrite:
			delete_child_rows(data, doctype)

	import_log = []
	def log(**kwargs):
		if via_console:
			print((kwargs.get("title") + kwargs.get("message")).encode('utf-8'))
		else:
			import_log.append(kwargs)

	def as_link(doctype, name):
		if via_console:
			return "{0}: {1}".format(doctype, name)
		else:
			return getlink(doctype, name)

	# publish realtime task update
	def publish_progress(achieved, reload=False):
		if data_import_doc:
			frappe.publish_realtime("data_import_progress", {"progress": str(int(100.0*achieved/total)),
				"data_import": data_import_doc.name, "reload": reload}, user=frappe.session.user)


	error_flag = rollback_flag = False

	batch_size = frappe.conf.data_import_batch_size or 1000

	for batch_start in range(0, total, batch_size):
		batch = data[batch_start:batch_start + batch_size]

		for i, row in enumerate(batch):
			# bypass empty rows
			if main_doc_empty(row):
				continue

			row_idx = i + start_row
			doc = None

			publish_progress(i)

			try:
				doc, attachments, last_error_row_idx = get_doc(row_idx)
				validate_naming(doc)
				if pre_process:
					pre_process(doc)

				original = None
				if parentfield:
					parent = frappe.get_doc(parenttype, doc["parent"])
					doc = parent.append(parentfield, doc)
					parent.save()
				else:
					if overwrite and doc.get("name") and frappe.db.exists(doctype, doc["name"]):
						original = frappe.get_doc(doctype, doc["name"])
						original_name = original.name
						original.update(doc)
						# preserve original name for case sensitivity
						original.name = original_name
						original.flags.ignore_links = ignore_links
						original.save()
						doc = original
					else:
						if not update_only:
							doc = frappe.get_doc(doc)
							prepare_for_insert(doc)
							doc.flags.ignore_links = ignore_links
							doc.insert()
					if attachments:
						# check file url and create a File document
						for file_url in attachments:
							attach_file_to_doc(doc.doctype, doc.name, file_url)
					if submit_after_import:
						doc.submit()

				# log errors
				if parentfield:
					log(**{"row": doc.idx, "title": 'Inserted row for "%s"' % (as_link(parenttype, doc.parent)),
						"link": get_url_to_form(parenttype, doc.parent), "message": 'Document successfully saved', "indicator": "green"})
				elif submit_after_import:
					log(**{"row": row_idx + 1, "title":'Submitted row for "%s"' % (as_link(doc.doctype, doc.name)),
						"message": "Document successfully submitted", "link": get_url_to_form(doc.doctype, doc.name), "indicator": "blue"})
				elif original:
					log(**{"row": row_idx + 1,"title":'Updated row for "%s"' % (as_link(doc.doctype, doc.name)),
						"message": "Document successfully updated", "link": get_url_to_form(doc.doctype, doc.name), "indicator": "green"})
				elif not update_only:
					log(**{"row": row_idx + 1, "title":'Inserted row for "%s"' % (as_link(doc.doctype, doc.name)),
						"message": "Document successfully saved", "link": get_url_to_form(doc.doctype, doc.name), "indicator": "green"})
				else:
					log(**{"row": row_idx + 1, "title":'Ignored row for %s' % (row[1]), "link": None,
						"message": "Document updation ignored", "indicator": "orange"})

			except Exception as e:
				error_flag = True

				# build error message
				if frappe.local.message_log:
					err_msg = "\n".join(['<p class="border-bottom small">{}</p>'.format(json.loads(msg).get('message')) for msg in frappe.local.message_log])
				else:
					err_msg = '<p class="border-bottom small">{}</p>'.format(cstr(e))

				error_trace = frappe.get_traceback()
				if error_trace:
					error_log_doc = frappe.log_error(error_trace)
					error_link = get_url_to_form("Error Log", error_log_doc.name)
				else:
					error_link = None

				log(**{
					"row": row_idx + 1,
					"title": 'Error for row %s' % (len(row)>1 and frappe.safe_decode(row[1]) or ""),
					"message": err_msg,
					"indicator": "red",
					"link":error_link
				})

				# data with error to create a new file
				# include the errored data in the last row as last_error_row_idx will not be updated for the last row
				if skip_errors:
					if last_error_row_idx == len(rows)-1:
						last_error_row_idx = len(rows)
					data_rows_with_error += rows[row_idx:last_error_row_idx]
				else:
					rollback_flag = True
			finally:
				frappe.local.message_log = []

		start_row += batch_size
		if rollback_flag:
			frappe.db.rollback()
		else:
			frappe.db.commit()

	frappe.flags.mute_emails = False
	frappe.flags.in_import = False

	log_message = {"messages": import_log, "error": error_flag}
	if data_import_doc:
		data_import_doc.log_details = json.dumps(log_message)

		import_status = None
		if error_flag and data_import_doc.skip_errors and len(data) != len(data_rows_with_error):
			import_status = "Partially Successful"
			# write the file with the faulty row
			from frappe.utils.file_manager import save_file
			file_name = 'error_' + filename + file_extension
			if file_extension == '.xlsx':
				from frappe.utils.xlsxutils import make_xlsx
				xlsx_file = make_xlsx(data_rows_with_error, "Data Import Template")
				file_data = xlsx_file.getvalue()
			else:
				from frappe.utils.csvutils import to_csv
				file_data = to_csv(data_rows_with_error)
			error_data_file = save_file(file_name, file_data, "Data Import",
				data_import_doc.name,  "Home/Attachments")
			data_import_doc.error_file = error_data_file.file_url

		elif error_flag:
			import_status = "Failed"
		else:
			import_status = "Successful"

		data_import_doc.import_status = import_status
		data_import_doc.save()
		if data_import_doc.import_status in ["Successful", "Partially Successful"]:
			data_import_doc.submit()
			publish_progress(100, True)
		else:
			publish_progress(0, True)
		frappe.db.commit()
	else:
		return log_message