コード例 #1
0
ファイル: like.py プロジェクト: vrms/frappe
def add_comment(doctype, name):
    doc = frappe.get_doc(doctype, name)

    if doctype == "Comment":
        link = get_link_to_form(
            doc.comment_doctype, doc.comment_docname, "{0} {1}".format(_(doc.comment_doctype), doc.comment_docname)
        )
        doc.add_comment(
            "Like",
            _("Comment: {0} in {1}").format("<b>" + doc.comment + "</b>", link),
            reference_doctype=doc.comment_doctype,
            reference_name=doc.comment_docname,
        )

    elif doctype == "Communication":
        link = get_link_to_form(
            doc.reference_doctype, doc.reference_name, "{0} {1}".format(_(doc.reference_doctype), doc.reference_name)
        )

        doc.add_comment(
            "Like",
            _("Communication: {0} in {1}").format("<b>" + doc.subject + "</b>", link),
            reference_doctype=doc.reference_doctype,
            reference_name=doc.reference_name,
        )

    else:
        doc.add_comment("Like", _("Liked"))
コード例 #2
0
ファイル: leave_application.py プロジェクト: ArchitW/erpnext
		def _get_message(url=False):
			name = self.name
			employee_name = cstr(employee.employee_name)
			if url:
				name = get_link_to_form(self.doctype, self.name)
				employee_name = get_link_to_form("Employee", self.employee, label=employee_name)

			return (_("New Leave Application") + ": %s - " + _("Employee") + ": %s") % (name, employee_name)
コード例 #3
0
		def _get_message(url=False):
			name = self.name
			employee_name = cstr(employee.employee_name)
			if url:
				name = get_link_to_form(self.doctype, self.name)
				employee_name = get_link_to_form("Employee", self.employee, label=employee_name)
			message = (_("Leave Application") + ": %s") % (name)+"<br>"
			message += (_("Employee") + ": %s") % (employee_name)+"<br>"
			message += (_("Leave Type") + ": %s") % (self.leave_type)+"<br>"
			message += (_("From Date") + ": %s") % (self.from_date)+"<br>"
			message += (_("To Date") + ": %s") % (self.to_date)
			return message
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_link_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)
コード例 #5
0
def notify_mentions(doc):
	if doc.communication_type != "Comment":
		return

	if doc.reference_doctype and doc.reference_name and doc.content and doc.comment_type=="Comment":
		mentions = extract_mentions(doc.content)

		if not mentions:
			return

		sender_fullname = get_fullname(frappe.session.user)
		parent_doc_label = "{0} {1}".format(_(doc.reference_doctype), doc.reference_name)
		subject = _("{0} mentioned you in a comment in {1}").format(sender_fullname, parent_doc_label)
		message = frappe.get_template("templates/emails/mentioned_in_comment.html").render({
			"sender_fullname": sender_fullname,
			"comment": doc,
			"link": get_link_to_form(doc.reference_doctype, doc.reference_name, label=parent_doc_label)
		})

		recipients = [frappe.db.get_value("User", {"enabled": 1, "username": username, "user_type": "System User"})
			for username in mentions]

		frappe.sendmail(
			recipients=recipients,
			sender=frappe.session.user,
			subject=subject,
			message=message,
			bulk=True
		)
コード例 #6
0
ファイル: leave_application.py プロジェクト: ArchitW/erpnext
		def _get_message(url=False):
			if url:
				name = get_link_to_form(self.doctype, self.name)
			else:
				name = self.name

			return (_("Leave Application") + ": %s - %s") % (name, _(status))
コード例 #7
0
def daily():
    users = frappe.db.sql("""select email, name from tabUser
        where name in (select parent from tabUserRole
        where role='Accounts Manager')""", as_dict=1)
    today = nowdate()
    end = add_days(today, 3)
    sales_invoices = frappe.db.sql("""select name from `tabSales Invoice`
        where (date(due_date) between date(%(start)s) and date(%(end)s))
        and outstanding_amount > 0
        and docstatus=1""", {
        "start": today,
        "end": end,
    }, as_dict=1)
    if sales_invoices:
        subject = "Outstanding sales invoices due %s" % today
        message = "<p>Please review and follow up with the customers on the outstanding sales invoices below:</p><ul>"
        from frappe.utils import get_link_to_form
        for si in sales_invoices:
            message += "<li>" + get_link_to_form("Sales Invoice", si.name, si.name) + "</li>"
        message += "</ul><p><b>Note:</b> The list above contains the invoices that are either overdue or have its due date within the next 3 business days</p>"

        frappe.sendmail(recipients=[u.email for u in users], subject=subject, message=message, reply_to=EMAIL_SENDER, bulk=True)
        formatted_si = ", ".join(si.name for si in sales_invoices)
        for u in [u.name for u in users]:
            todo_doc = frappe.get_doc({
                "doctype": "ToDo",
                "owner": u,
                "description": subject + ": " + formatted_si,
                "priority": "Medium",
                "status": "Open",
                "role": "Accounts Manager",
                "date": nowdate(),
                "assigned_by": frappe.session.user,
            })
            todo_doc.insert(ignore_permissions=True)
コード例 #8
0
		def _get_message(url=False):
			if url:
				name = get_link_to_form(self.doctype, self.name)
			else:
				name = self.name

			message = "Leave Application: {name}".format(name=name)+"<br>"
			message += "Leave Type: {leave_type}".format(leave_type=self.leave_type)+"<br>"
			message += "From Date: {from_date}".format(from_date=self.from_date)+"<br>"
			message += "To Date: {to_date}".format(to_date=self.to_date)+"<br>"
			message += "Status: {status}".format(status=_(status))
			return message
コード例 #9
0
ファイル: share.py プロジェクト: ESS-LLP/frappe
def notify_assignment(shared_by, doc_type, doc_name, description=None, notify=0):

	if not (shared_by and doc_type and doc_name): return

	from frappe.utils import get_link_to_form
	document = get_link_to_form(doc_type, doc_name, label="%s: %s" % (doc_type, doc_name))

	arg = {
		'contact': shared_by,
		'txt': _("A new document {0} has been shared by with you {1}.").format(document,
				shared_by),
		'notify': notify
	}
コード例 #10
0
ファイル: like.py プロジェクト: ESS-LLP/frappe
def add_comment(doctype, name):
	doc = frappe.get_doc(doctype, name)

	if doctype=="Communication" and doc.reference_doctype and doc.reference_name:
		link = get_link_to_form(doc.reference_doctype, doc.reference_name,
			"{0} {1}".format(_(doc.reference_doctype), doc.reference_name))

		doc.add_comment("Like", _("{0}: {1} in {2}").format(_(doc.communication_type),
			"<b>" + doc.subject + "</b>", link),
			link_doctype=doc.reference_doctype, link_name=doc.reference_name)

	else:
		doc.add_comment("Like", _("Liked"))
コード例 #11
0
ファイル: auto_email_report.py プロジェクト: ESS-LLP/frappe
	def get_html_table(self, columns=None, data=None):

		date_time = global_date_format(now()) + ' ' + format_time(now())
		report_doctype = frappe.db.get_value('Report', self.report, 'ref_doctype')

		return frappe.render_template('frappe/templates/emails/auto_email_report.html', {
			'title': self.name,
			'description': self.description,
			'date_time': date_time,
			'columns': columns,
			'data': data,
			'report_url': get_url_to_report(self.report, self.report_type, report_doctype),
			'report_name': self.report,
			'edit_report_settings': get_link_to_form('Auto Email Report', self.name)
		})
コード例 #12
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_link_to_form
	assignment = get_link_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.chat import chat
	chat.post(**arg)
コード例 #13
0
	def validate_duplicate(self):
		data = frappe.db.sql(""" select name from `tabStudent Leave Application`
			where
				((%(from_date)s > from_date and %(from_date)s < to_date) or
				(%(to_date)s > from_date and %(to_date)s < to_date) or
				(%(from_date)s <= from_date and %(to_date)s >= to_date)) and
				name != %(name)s and student = %(student)s and docstatus < 2
		""", {
			'from_date': self.from_date,
			'to_date': self.to_date,
			'student': self.student,
			'name': self.name
		}, as_dict=1)

		if data:
			link = get_link_to_form("Student Leave Application", data[0].name)
			frappe.throw(_("Leave application {0} already exists against the student {1}")
				.format(link, self.student))
コード例 #14
0
ファイル: comment.py プロジェクト: ESS-LLP/frappe
def notify_mentions(doc):
	if doc.communication_type != "Comment":
		return

	if doc.reference_doctype and doc.reference_name and doc.content and doc.comment_type=="Comment":
		mentions = extract_mentions(doc.content)

		if not mentions:
			return

		sender_fullname = get_fullname(frappe.session.user)
		title_field = frappe.get_meta(doc.reference_doctype).get_title_field()
		title = doc.reference_name if title_field == "name" else \
			frappe.db.get_value(doc.reference_doctype, doc.reference_name, title_field)

		if title != doc.reference_name:
			parent_doc_label = "{0}: {1} (#{2})".format(_(doc.reference_doctype),
				title, doc.reference_name)
		else:
			parent_doc_label = "{0}: {1}".format(_(doc.reference_doctype),
				doc.reference_name)

		subject = _("{0} mentioned you in a comment").format(sender_fullname)

		recipients = [frappe.db.get_value("User", {"enabled": 1, "name": name, "user_type": "System User"}, "email")
			for name in mentions]
		link = get_link_to_form(doc.reference_doctype, doc.reference_name, label=parent_doc_label)

		frappe.sendmail(
			recipients=recipients,
			sender=frappe.session.user,
			subject=subject,
			template="mentioned_in_comment",
			args={
				"body_content": _("{0} mentioned you in a comment in {1}").format(sender_fullname, link),
				"comment": doc,
				"link": link
			},
			header=[_('New Mention'), 'orange']
		)
コード例 #15
0
    def validate_dates(self):
        if frappe.db.get_single_value("HR Settings",
                                      "restrict_backdated_leave_application"):
            if self.from_date and getdate(self.from_date) < getdate():
                allowed_role = frappe.db.get_single_value(
                    "HR Settings",
                    "role_allowed_to_create_backdated_leave_application")
                user = frappe.get_doc("User", frappe.session.user)
                user_roles = [d.role for d in user.roles]
                if not allowed_role:
                    frappe.throw(
                        _("Backdated Leave Application is restricted. Please set the {} in {}"
                          ).
                        format(
                            frappe.bold(
                                "Role Allowed to Create Backdated Leave Application"
                            ), get_link_to_form("HR Settings", "HR Settings")))

                if (allowed_role and allowed_role not in user_roles):
                    frappe.throw(
                        _("Only users with the {0} role can create backdated leave applications"
                          ).format(allowed_role))

        if self.from_date and self.to_date and (getdate(self.to_date) <
                                                getdate(self.from_date)):
            frappe.throw(_("To date cannot be before from date"))

        if self.half_day and self.half_day_date \
         and (getdate(self.half_day_date) < getdate(self.from_date)
         or getdate(self.half_day_date) > getdate(self.to_date)):

            frappe.throw(
                _("Half Day Date should be between From Date and To Date"))

        if not is_lwp(self.leave_type):
            self.validate_dates_across_allocation()
            self.validate_back_dated_application()
コード例 #16
0
    def notify_mentions(self):
        if self.comment_doctype and self.comment_docname and self.comment and self.comment_type == "Comment":
            mentions = extract_mentions(self.comment)

            if not mentions:
                return

            sender_fullname = get_fullname(frappe.session.user)
            parent_doc_label = "{0} {1}".format(_(self.comment_doctype),
                                                self.comment_docname)
            subject = _("{0} mentioned you in a comment in {1}").format(
                sender_fullname, parent_doc_label)
            message = frappe.get_template(
                "templates/emails/mentioned_in_comment.html").render({
                    "sender_fullname":
                    sender_fullname,
                    "comment":
                    self,
                    "link":
                    get_link_to_form(self.comment_doctype,
                                     self.comment_docname,
                                     label=parent_doc_label)
                })

            recipients = [
                frappe.db.get_value("User", {
                    "enabled": 1,
                    "username": username,
                    "user_type": "System User"
                }) for username in mentions
            ]

            frappe.sendmail(recipients=recipients,
                            sender=frappe.session.user,
                            subject=subject,
                            message=message,
                            bulk=True)
コード例 #17
0
    def validate_doc(self):
        if (self.enabled and self.document_type == "Issue"
                and not frappe.db.get_single_value(
                    "Support Settings", "track_service_level_agreement")):
            frappe.throw(
                _("{0} is not enabled in {1}").format(
                    frappe.bold("Track Service Level Agreement"),
                    get_link_to_form("Support Settings", "Support Settings"),
                ))

        if self.default_service_level_agreement and frappe.db.exists(
                "Service Level Agreement",
            {
                "document_type": self.document_type,
                "default_service_level_agreement": "1",
                "name": ["!=", self.name],
            },
        ):
            frappe.throw(
                _("Default Service Level Agreement for {0} already exists.").
                format(self.document_type))

        if self.start_date and self.end_date:
            self.validate_from_to_dates(self.start_date, self.end_date)

        if (self.entity_type and self.entity and frappe.db.exists(
                "Service Level Agreement",
            {
                "entity_type": self.entity_type,
                "entity": self.entity,
                "name": ["!=", self.name]
            },
        )):
            frappe.throw(
                _("Service Level Agreement for {0} {1} already exists."
                  ).format(frappe.bold(self.entity_type),
                           frappe.bold(self.entity)))
コード例 #18
0
ファイル: utils.py プロジェクト: Dharmraj-48/erpnext
def get_product_discount_rule(pricing_rule, item_details, doc=None):
    free_item = (pricing_rule.free_item if not pricing_rule.same_item
                 or pricing_rule.apply_on == 'Transaction' else
                 item_details.item_code)

    if not free_item:
        frappe.throw(
            _("Free item not set in the pricing rule {0}").format(
                get_link_to_form("Pricing Rule", pricing_rule.name)))

    item_details.free_item_data = {
        'item_code': free_item,
        'qty': pricing_rule.free_qty or 1,
        'rate': pricing_rule.free_item_rate or 0,
        'price_list_rate': pricing_rule.free_item_rate or 0,
        'is_free_item': 1
    }

    item_data = frappe.get_cached_value(
        'Item',
        free_item, ['item_name', 'description', 'stock_uom'],
        as_dict=1)

    item_details.free_item_data.update(item_data)
    item_details.free_item_data[
        'uom'] = pricing_rule.free_item_uom or item_data.stock_uom
    item_details.free_item_data['conversion_factor'] = get_conversion_factor(
        free_item,
        item_details.free_item_data['uom']).get("conversion_factor", 1)

    if item_details.get("parenttype") == 'Purchase Order':
        item_details.free_item_data[
            'schedule_date'] = doc.schedule_date if doc else today()

    if item_details.get("parenttype") == 'Sales Order':
        item_details.free_item_data[
            'delivery_date'] = doc.delivery_date if doc else today()
コード例 #19
0
    def validate_doc(self):
        if not frappe.db.get_single_value(
                "Support Settings",
                "track_service_level_agreement") and self.enable:
            frappe.throw(
                _("{0} is not enabled in {1}").format(
                    frappe.bold("Track Service Level Agreement"),
                    get_link_to_form("Support Settings", "Support Settings")))

        if self.default_service_level_agreement:
            if frappe.db.exists("Service Level Agreement", {
                    "default_service_level_agreement": "1",
                    "name": ["!=", self.name]
            }):
                frappe.throw(
                    _("A Default Service Level Agreement already exists."))
        else:
            if self.start_date and self.end_date:
                if getdate(self.start_date) >= getdate(self.end_date):
                    frappe.throw(
                        _("Start Date of Agreement can't be greater than or equal to End Date."
                          ))

                if getdate(self.end_date) < getdate(frappe.utils.getdate()):
                    frappe.throw(
                        _("End Date of Agreement can't be less than today."))

        if self.entity_type and self.entity:
            if frappe.db.exists(
                    "Service Level Agreement", {
                        "entity_type": self.entity_type,
                        "entity": self.entity,
                        "name": ["!=", self.name]
                    }):
                frappe.throw(
                    _("Service Level Agreement with Entity Type {0} and Entity {1} already exists."
                      ).format(self.entity_type, self.entity))
コード例 #20
0
ファイル: exit_interview.py プロジェクト: ankush/erpnext
def send_exit_questionnaire(interviews):
    interviews = get_interviews(interviews)
    validate_questionnaire_settings()

    email_success = []
    email_failure = []

    for exit_interview in interviews:
        interview = frappe.get_doc("Exit Interview",
                                   exit_interview.get("name"))
        if interview.get("questionnaire_email_sent"):
            continue

        employee = frappe.get_doc("Employee", interview.employee)
        email = get_employee_email(employee)

        context = interview.as_dict()
        context.update(employee.as_dict())
        template_name = frappe.db.get_single_value(
            "HR Settings", "exit_questionnaire_notification_template")
        template = frappe.get_doc("Email Template", template_name)

        if email:
            frappe.sendmail(
                recipients=email,
                subject=template.subject,
                message=frappe.render_template(template.response, context),
                reference_doctype=interview.doctype,
                reference_name=interview.name,
            )
            interview.db_set("questionnaire_email_sent", True)
            interview.notify_update()
            email_success.append(email)
        else:
            email_failure.append(get_link_to_form("Employee", employee.name))

    show_email_summary(email_success, email_failure)
コード例 #21
0
	def validate_duplication(self):
		"""Check if the Attendance Record is Unique"""
		attendance_record = None
		if self.course_schedule:
			attendance_record = frappe.db.exists('Student Attendance', {
				'student': self.student,
				'course_schedule': self.course_schedule,
				'docstatus': ('!=', 2),
				'name': ('!=', self.name)
			})
		else:
			attendance_record = frappe.db.exists('Student Attendance', {
				'student': self.student,
				'student_group': self.student_group,
				'date': self.date,
				'docstatus': ('!=', 2),
				'name': ('!=', self.name),
				'course_schedule': ''
			})

		if attendance_record:
			record = get_link_to_form('Student Attendance', attendance_record)
			frappe.throw(_('Student Attendance record {0} already exists against the Student {1}')
				.format(record, frappe.bold(self.student)), title=_('Duplicate Entry'))
コード例 #22
0
ファイル: product_bundle.py プロジェクト: erpnext-tm/erpnext
    def on_trash(self):
        linked_doctypes = [
            "Delivery Note",
            "Sales Invoice",
            "POS Invoice",
            "Purchase Receipt",
            "Purchase Invoice",
            "Stock Entry",
            "Stock Reconciliation",
            "Sales Order",
            "Purchase Order",
            "Material Request",
        ]

        invoice_links = []
        for doctype in linked_doctypes:
            item_doctype = doctype + " Item"

            if doctype == "Stock Entry":
                item_doctype = doctype + " Detail"

            invoices = frappe.db.get_all(item_doctype, {
                "item_code": self.new_item_code,
                "docstatus": 1
            }, ["parent"])

            for invoice in invoices:
                invoice_links.append(
                    get_link_to_form(doctype, invoice["parent"]))

        if len(invoice_links):
            frappe.throw(
                "This Product Bundle is linked with {0}. You will have to cancel these documents in order to delete this Product Bundle"
                .format(", ".join(invoice_links)),
                title=_("Not Allowed"),
            )
コード例 #23
0
ファイル: pos_profile.py プロジェクト: MorezMartin/erpnext
    def validate_payment_methods(self):
        if not self.payments:
            frappe.throw(
                _("Payment methods are mandatory. Please add at least one payment method."
                  ))

        default_mode = [d.default for d in self.payments if d.default]
        if not default_mode:
            frappe.throw(_("Please select a default mode of payment"))

        if len(default_mode) > 1:
            frappe.throw(
                _("You can only select one mode of payment as default"))

        invalid_modes = []
        for d in self.payments:
            account = frappe.db.get_value("Mode of Payment Account", {
                "parent": d.mode_of_payment,
                "company": self.company
            }, "default_account")

            if not account:
                invalid_modes.append(
                    get_link_to_form("Mode of Payment", d.mode_of_payment))

        if invalid_modes:
            if invalid_modes == 1:
                msg = _(
                    "Please set default Cash or Bank account in Mode of Payment {}"
                )
            else:
                msg = _(
                    "Please set default Cash or Bank account in Mode of Payments {}"
                )
            frappe.throw(msg.format(", ".join(invalid_modes)),
                         title=_("Missing Account"))
コード例 #24
0
	def validate_for_duplicate_items(self):
		check_list, chk_dupl_itm = [], []
		if cint(frappe.db.get_single_value("Selling Settings", "allow_multiple_items")):
			return
		if self.doctype == "Sales Invoice" and self.is_consolidated:
			return
		if self.doctype == "POS Invoice":
			return

		for d in self.get('items'):
			if self.doctype == "Sales Invoice":
				stock_items = [d.item_code, d.description, d.warehouse, d.sales_order or d.delivery_note, d.batch_no or '']
				non_stock_items = [d.item_code, d.description, d.sales_order or d.delivery_note]
			elif self.doctype == "Delivery Note":
				stock_items = [d.item_code, d.description, d.warehouse, d.against_sales_order or d.against_sales_invoice, d.batch_no or '']
				non_stock_items = [d.item_code, d.description, d.against_sales_order or d.against_sales_invoice]
			elif self.doctype in ["Sales Order", "Quotation"]:
				stock_items = [d.item_code, d.description, d.warehouse, '']
				non_stock_items = [d.item_code, d.description]

			if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1:
				duplicate_items_msg = _("Item {0} entered multiple times.").format(frappe.bold(d.item_code))
				duplicate_items_msg += "<br><br>"
				duplicate_items_msg += _("Please enable {} in {} to allow same item in multiple rows").format(
					frappe.bold("Allow Item to Be Added Multiple Times in a Transaction"),
					get_link_to_form("Selling Settings", "Selling Settings")
				)
				if stock_items in check_list:
					frappe.throw(duplicate_items_msg)
				else:
					check_list.append(stock_items)
			else:
				if non_stock_items in chk_dupl_itm:
					frappe.throw(duplicate_items_msg)
				else:
					chk_dupl_itm.append(non_stock_items)
コード例 #25
0
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_link_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)
コード例 #26
0
	def create_separate_ledger_entries(self, alloc_on_from_date, alloc_on_to_date, submit, lwp):
		"""Creates separate ledger entries for application period falling into separate allocations"""
		# for creating separate ledger entries existing allocation periods should be consecutive
		if (
			submit
			and alloc_on_from_date
			and alloc_on_to_date
			and add_days(alloc_on_from_date.to_date, 1) != alloc_on_to_date.from_date
		):
			frappe.throw(
				_(
					"Leave Application period cannot be across two non-consecutive leave allocations {0} and {1}."
				).format(
					get_link_to_form("Leave Allocation", alloc_on_from_date.name),
					get_link_to_form("Leave Allocation", alloc_on_to_date),
				)
			)

		raise_exception = False if frappe.flags.in_patch else True

		if alloc_on_from_date:
			first_alloc_end = alloc_on_from_date.to_date
			second_alloc_start = add_days(alloc_on_from_date.to_date, 1)
		else:
			first_alloc_end = add_days(alloc_on_to_date.from_date, -1)
			second_alloc_start = alloc_on_to_date.from_date

		leaves_in_first_alloc = get_number_of_leave_days(
			self.employee,
			self.leave_type,
			self.from_date,
			first_alloc_end,
			self.half_day,
			self.half_day_date,
		)
		leaves_in_second_alloc = get_number_of_leave_days(
			self.employee,
			self.leave_type,
			second_alloc_start,
			self.to_date,
			self.half_day,
			self.half_day_date,
		)

		args = dict(
			is_lwp=lwp,
			holiday_list=get_holiday_list_for_employee(self.employee, raise_exception=raise_exception)
			or "",
		)

		if leaves_in_first_alloc:
			args.update(
				dict(from_date=self.from_date, to_date=first_alloc_end, leaves=leaves_in_first_alloc * -1)
			)
			create_leave_ledger_entry(self, args, submit)

		if leaves_in_second_alloc:
			args.update(
				dict(from_date=second_alloc_start, to_date=self.to_date, leaves=leaves_in_second_alloc * -1)
			)
			create_leave_ledger_entry(self, args, submit)
コード例 #27
0
def validate_active_employee(employee):
    if frappe.db.get_value("Employee", employee, "status") == "Inactive":
        frappe.throw(
            _("Transactions cannot be created for an Inactive Employee {0}."
              ).format(get_link_to_form("Employee", employee)),
            InactiveEmployeeStatusError)
コード例 #28
0
ファイル: utils.py プロジェクト: HauptschuIe/erpnext
def validate_disabled_warehouse(warehouse):
    if frappe.db.get_value("Warehouse", warehouse, "disabled"):
        frappe.throw(
            _("Disabled Warehouse {0} cannot be used for this transaction.").
            format(get_link_to_form('Warehouse', warehouse)))
コード例 #29
0
		def _validate_invoice_discounting_status(inv_disc, id_status, expected_status, row_id):
			id_link = get_link_to_form("Invoice Discounting", inv_disc)
			if id_status != expected_status:
				frappe.throw(_("Row #{0}: Status must be {1} for Invoice Discounting {2}").format(d.idx, expected_status, id_link))
コード例 #30
0
def send_mail(deferred_process):
	title = _("Error while processing deferred accounting for {0}").format(deferred_process)
	link = get_link_to_form('Process Deferred Accounting', deferred_process)
	content = _("Deferred accounting failed for some invoices:") + "\n"
	content += _("Please check Process Deferred Accounting {0} and submit manually after resolving errors.").format(link)
	sendmail_to_system_managers(title, content)
コード例 #31
0
ファイル: subcontracting.py プロジェクト: MorezMartin/erpnext
	def __validate_batch_no(self, row, key):
		if row.get('batch_no') and row.get('batch_no') not in self.__transferred_items.get(key).get('batch_no'):
			link = get_link_to_form('Purchase Order', row.purchase_order)
			msg = f'The Batch No {frappe.bold(row.get("batch_no"))} has not supplied against the Purchase Order {link}'
			frappe.throw(_(msg), title=_("Incorrect Batch Consumed"))
コード例 #32
0
 def validate_duplicate(self):
     year = frappe.db.sql("""select name from `tabAcademic Year` where school=%s and academic_year_name=%s and docstatus<2 and name!=%s""", (self.school, self.academic_year_name, self.name))
     if year:
         frappe.throw(_("An academic year with this name {0} and this school {1} already exist.").format(self.academic_year_name, get_link_to_form("School", self.school)), title=_("Duplicate Entry"))
コード例 #33
0
def check_if_child_exists(name):
    child_tasks = frappe.get_all("Task", filters={"parent_task": name})
    child_tasks = [get_link_to_form("Task", task.name) for task in child_tasks]
    return child_tasks
コード例 #34
0
def set_po_item_rate(doc):
	if doc.items:
		for item in doc.items:
			if item.purchase_order_item:
				rate = frappe.db.get_value('Purchase Order Item', item.purchase_order_item, 'rate')
				if item.maintain_fix_rate == 1 and rate != item.rate:
					frappe.throw('Not allowed to change the rate for <b>Row {0}</b> as <b>Maintain Fix Rate</b> is checked on the purchase order {1}'.format(item.idx, get_link_to_form('Purchase Order', item.purchase_order)))
コード例 #35
0
ファイル: project_activities.py プロジェクト: farouk-muha/pav
def check_if_child_exists(name):
	child_tasks = frappe.get_all("Project Activities", filters={"parent_project_activities": name})
	child_tasks = [get_link_to_form("Project Activities", project_activities.name) for project_activities in child_tasks]
	return child_tasks
コード例 #36
0
def calculate_annual_eligible_hra_exemption(doc):
    basic_component, hra_component = frappe.db.get_value(
        "Company", doc.company, ["basic_component", "hra_component"])

    if not (basic_component and hra_component):
        frappe.throw(
            _("Please set Basic and HRA component in Company {0}").format(
                get_link_to_form("Company", doc.company)))

    annual_exemption = monthly_exemption = hra_amount = basic_amount = 0

    if hra_component and basic_component:
        assignments = get_salary_assignments(doc.employee, doc.payroll_period)

        if not assignments and doc.docstatus == 1:
            frappe.throw(
                _("Salary Structure must be submitted before submission of {0}"
                  ).format(doc.doctype))

        assignment_dates = [assignment.from_date for assignment in assignments]

        for idx, assignment in enumerate(assignments):
            if has_hra_component(assignment.salary_structure, hra_component):
                basic_salary_amt, hra_salary_amt = get_component_amt_from_salary_slip(
                    doc.employee,
                    assignment.salary_structure,
                    basic_component,
                    hra_component,
                    assignment.from_date,
                )
                to_date = get_end_date_for_assignment(assignment_dates, idx,
                                                      doc.payroll_period)

                frequency = frappe.get_value("Salary Structure",
                                             assignment.salary_structure,
                                             "payroll_frequency")
                basic_amount += get_component_pay(frequency, basic_salary_amt,
                                                  assignment.from_date,
                                                  to_date)
                hra_amount += get_component_pay(frequency, hra_salary_amt,
                                                assignment.from_date, to_date)

        if hra_amount:
            if doc.monthly_house_rent:
                annual_exemption = calculate_hra_exemption(
                    assignment.salary_structure,
                    basic_amount,
                    hra_amount,
                    doc.monthly_house_rent,
                    doc.rented_in_metro_city,
                )
                if annual_exemption > 0:
                    monthly_exemption = annual_exemption / 12
                else:
                    annual_exemption = 0

    return frappe._dict({
        "hra_amount": hra_amount,
        "annual_exemption": annual_exemption,
        "monthly_exemption": monthly_exemption,
    })
コード例 #37
0
ファイル: job_card.py プロジェクト: perkasajob/QuantumErp
 def validate_job_card(self):
     if not self.time_logs:
         frappe.throw(
             _("Time logs are required for {0} {1}").format(
                 frappe.bold("Job Card"),
                 get_link_to_form("Job Card", self.name)))
コード例 #38
0
	def throw_overlap_error(self, d):
		form_link = get_link_to_form("Leave Application", d.name)
		msg = _("Employee {0} has already applied for {1} between {2} and {3} : {4}").format(
			self.employee, d["leave_type"], formatdate(d["from_date"]), formatdate(d["to_date"]), form_link
		)
		frappe.throw(msg, OverlapError)
コード例 #39
0
    def create_calendar_events(self):
        if self.at_start:
            start_at = frappe.get_doc("School Event", self.at_start)
            if getdate(start_at.starts_on) != getdate(self.term_start_date):
                start_at.db_set("starts_on", self.term_start_date)
                start_at.db_set("ends_on", self.term_start_date)
                frappe.msgprint(_("Date for the start of the term {0} has been updated on the School Event Calendar {1}").format(self.term_start_date, get_link_to_form("School Event", start_at.name)))

        if self.at_end:
            end_at = frappe.get_doc("School Event", self.at_end)
            if getdate(end_at.ends_on) != getdate(self.term_end_date):
                end_at.db_set("starts_on", self.term_end_date)
                end_at.db_set("ends_on", self.term_end_date)
                frappe.msgprint(_("Date for the end of the term {0} has been updated on the School Event Calendar {1}").format(self.term_end_date, get_link_to_form("School Event", end_at.name)))

        if not self.at_start:
            start_term = frappe.get_doc({
                "doctype": "School Event",
        	    "owner": frappe.session.user,
                "subject": "Start of the " + cstr(self.name) + " Academic Term",
                "starts_on": getdate(self.term_start_date),
                "ends_on": getdate(self.term_start_date),
                "school": self.school,
        	    "event_category": "Other",
        	    "event_type": "Public",
                "all_day": "1",
        	    "color": "#7575ff",
                "reference_type": "Academic Term",
                "reference_name": self.name
        	})
            start_term.insert()
            self.db_set("at_start", start_term.name)
            frappe.msgprint(_("Date for the start of the term {0} has been created on the School Event Calendar {1}").format(self.term_start_date, get_link_to_form("School Event", start_term.name)))

        if not self.at_end:
            end_term = frappe.get_doc({
                "doctype": "School Event",
                "owner": frappe.session.user,
        	    "subject": "End of the " + cstr(self.name) + " Academic Term",
        	    "starts_on": getdate(self.term_end_date),
        	    "ends_on": getdate(self.term_end_date),
                "school": self.school,
                "event_category": "Other",
                "event_type": "Public",
                "all_day": "1",
        	    "color": "#7575ff",
                "reference_type": "Academic Term",
                "reference_name": self.name
        	})
            end_term.insert()
            self.db_set("at_end", end_term.name)
            frappe.msgprint(_("Date for the end of the term {0} has been created on the School Event Calendar {1}").format(self.term_end_date, get_link_to_form("School Event", end_term.name)))
コード例 #40
0
def validate_serial_no(sle, item_det):
	serial_nos = get_serial_nos(sle.serial_no) if sle.serial_no else []
	validate_material_transfer_entry(sle)

	if item_det.has_serial_no==0:
		if serial_nos:
			frappe.throw(_("Item {0} is not setup for Serial Nos. Column must be blank").format(sle.item_code),
				SerialNoNotRequiredError)
	elif not sle.is_cancelled:
		if serial_nos:
			if cint(sle.actual_qty) != flt(sle.actual_qty):
				frappe.throw(_("Serial No {0} quantity {1} cannot be a fraction").format(sle.item_code, sle.actual_qty))

			if len(serial_nos) and len(serial_nos) != abs(cint(sle.actual_qty)):
				frappe.throw(_("{0} Serial Numbers required for Item {1}. You have provided {2}.").format(abs(sle.actual_qty), sle.item_code, len(serial_nos)),
					SerialNoQtyError)

			if len(serial_nos) != len(set(serial_nos)):
				frappe.throw(_("Duplicate Serial No entered for Item {0}").format(sle.item_code), SerialNoDuplicateError)

			for serial_no in serial_nos:
				if frappe.db.exists("Serial No", serial_no):
					sr = frappe.db.get_value("Serial No", serial_no, ["name", "item_code", "batch_no", "sales_order",
						"delivery_document_no", "delivery_document_type", "warehouse", "purchase_document_type",
						"purchase_document_no", "company"], as_dict=1)

					if sr.item_code!=sle.item_code:
						if not allow_serial_nos_with_different_item(serial_no, sle):
							frappe.throw(_("Serial No {0} does not belong to Item {1}").format(serial_no,
								sle.item_code), SerialNoItemError)

					if cint(sle.actual_qty) > 0 and has_serial_no_exists(sr, sle):
						doc_name = frappe.bold(get_link_to_form(sr.purchase_document_type, sr.purchase_document_no))
						frappe.throw(_("Serial No {0} has already been received in the {1} #{2}")
							.format(frappe.bold(serial_no), sr.purchase_document_type, doc_name), SerialNoDuplicateError)

					if (sr.delivery_document_no and sle.voucher_type not in ['Stock Entry', 'Stock Reconciliation']
						and sle.voucher_type == sr.delivery_document_type):
						return_against = frappe.db.get_value(sle.voucher_type, sle.voucher_no, 'return_against')
						if return_against and return_against != sr.delivery_document_no:
							frappe.throw(_("Serial no {0} has been already returned").format(sr.name))

					if cint(sle.actual_qty) < 0:
						if sr.warehouse!=sle.warehouse:
							frappe.throw(_("Serial No {0} does not belong to Warehouse {1}").format(serial_no,
								sle.warehouse), SerialNoWarehouseError)

						if sle.voucher_type in ("Delivery Note", "Sales Invoice"):

							if sr.batch_no and sr.batch_no != sle.batch_no:
								frappe.throw(_("Serial No {0} does not belong to Batch {1}").format(serial_no,
									sle.batch_no), SerialNoBatchError)

							if not sle.is_cancelled and not sr.warehouse:
								frappe.throw(_("Serial No {0} does not belong to any Warehouse")
									.format(serial_no), SerialNoWarehouseError)

							# if Sales Order reference in Serial No validate the Delivery Note or Invoice is against the same
							if sr.sales_order:
								if sle.voucher_type == "Sales Invoice":
									if not frappe.db.exists("Sales Invoice Item", {"parent": sle.voucher_no,
										"item_code": sle.item_code, "sales_order": sr.sales_order}):
										frappe.throw(
											_("Cannot deliver Serial No {0} of item {1} as it is reserved to fullfill Sales Order {2}")
											.format(sr.name, sle.item_code, sr.sales_order)
										)
								elif sle.voucher_type == "Delivery Note":
									if not frappe.db.exists("Delivery Note Item", {"parent": sle.voucher_no,
										"item_code": sle.item_code, "against_sales_order": sr.sales_order}):
										invoice = frappe.db.get_value("Delivery Note Item", {"parent": sle.voucher_no,
											"item_code": sle.item_code}, "against_sales_invoice")
										if not invoice or frappe.db.exists("Sales Invoice Item",
											{"parent": invoice, "item_code": sle.item_code,
											"sales_order": sr.sales_order}):
											frappe.throw(
												_("Cannot deliver Serial No {0} of item {1} as it is reserved to fullfill Sales Order {2}")
												.format(sr.name, sle.item_code, sr.sales_order)
											)
							# if Sales Order reference in Delivery Note or Invoice validate SO reservations for item
							if sle.voucher_type == "Sales Invoice":
								sales_order = frappe.db.get_value("Sales Invoice Item", {"parent": sle.voucher_no,
									"item_code": sle.item_code}, "sales_order")
								if sales_order and get_reserved_qty_for_so(sales_order, sle.item_code):
									validate_so_serial_no(sr, sales_order)
							elif sle.voucher_type == "Delivery Note":
								sales_order = frappe.get_value("Delivery Note Item", {"parent": sle.voucher_no,
									"item_code": sle.item_code}, "against_sales_order")
								if sales_order and get_reserved_qty_for_so(sales_order, sle.item_code):
									validate_so_serial_no(sr, sales_order)
								else:
									sales_invoice = frappe.get_value("Delivery Note Item", {"parent": sle.voucher_no,
										"item_code": sle.item_code}, "against_sales_invoice")
									if sales_invoice:
										sales_order = frappe.db.get_value("Sales Invoice Item", {
											"parent": sales_invoice, "item_code": sle.item_code}, "sales_order")
										if sales_order and get_reserved_qty_for_so(sales_order, sle.item_code):
											validate_so_serial_no(sr, sales_order)
				elif cint(sle.actual_qty) < 0:
					# transfer out
					frappe.throw(_("Serial No {0} not in stock").format(serial_no), SerialNoNotExistsError)
		elif cint(sle.actual_qty) < 0 or not item_det.serial_no_series:
			frappe.throw(_("Serial Nos Required for Serialized Item {0}").format(sle.item_code),
				SerialNoRequiredError)
	elif serial_nos:
		for serial_no in serial_nos:
			sr = frappe.db.get_value("Serial No", serial_no, ["name", "warehouse"], as_dict=1)
			if sr and cint(sle.actual_qty) < 0 and sr.warehouse != sle.warehouse:
				frappe.throw(_("Cannot cancel {0} {1} because Serial No {2} does not belong to the warehouse {3}")
					.format(sle.voucher_type, sle.voucher_no, serial_no, sle.warehouse))
コード例 #41
0
ファイル: task.py プロジェクト: ci2014/erpnext
def check_if_child_exists(name):
	child_tasks = frappe.get_all("Task", filters={"parent_task": name})
	child_tasks = [get_link_to_form("Task", task.name) for task in child_tasks]
	return child_tasks
コード例 #42
0
ファイル: job_card.py プロジェクト: ravik0007/erpnext
	def validate_operation_id(self):
		if (self.get("operation_id") and self.get("operation_row_number") and self.operation and self.work_order and
			frappe.get_cached_value("Work Order Operation", self.operation_row_number, "name") != self.operation_id):
			work_order = frappe.bold(get_link_to_form("Work Order", self.work_order))
			frappe.throw(_("Operation {0} does not belong to the work order {1}")
				.format(frappe.bold(self.operation), work_order), OperationMismatchError)
コード例 #43
0
ファイル: document.py プロジェクト: MostafaBalata/frappe
	def workflow_manager(self):
		from frappe.model.workflow import get_workflow_name
		if not getattr(self, "__islocal", None) and frappe.db.exists(self.doctype, self.name):
			self.previous_doc = frappe.db.get_value(self.doctype, self.name, "*", as_dict=True)
		else:
			self.previous_doc = None
		self._current_action = self._action
		if get_workflow_name(self.doctype) is not None:
			if not self.is_new():
#				frappe.msgprint("1")
				transactions = frappe.db.sql("""
				SELECT state,next_state, thecondition ,idx ,`action` , allowed FROM `tabWorkflow Transition` WHERE `parent` = '{workflow_name}' and `action` = 'Approve'  order by `idx` asc
				""".format(workflow_name = get_workflow_name(self.doctype)))
				frappe.clear_cache(doctype=self.doctype)

				transactions = list(transactions)
				print "****************************\n"
				print "History"
				print self.get('workflow_history')
				print "****************************\n"

				print "****************************\n"
				print "Transactions"
				print transactions
				print "****************************\n"

				same_states = []

				transactions_index = 0
				for i in range(0,len(transactions)):

					if self.workflow_state == transactions[i][0]:
						same_states.append(i)
					transactions_index +=1

				print "****************************\n"
				print "Same States"
				print same_states , self.workflow_state
				print "****************************\n"

				if self._action == "submit" or self._action == "update_after_submit":
					current_transaction = transactions[len(transactions)-1]
				elif self._action == "cancel":
					child = self.append('workflow_history', {})
					child.user = frappe.session.user
					child.action = self._action
					if self.previous_doc and 'workflow_state' in self.previous_doc:
						child.previous_state = self.previous_doc['workflow_state']
					child.new_state = self.workflow_state
					return
				elif len(same_states) == 0:
					#Check if last status
					frappe.throw(_("Its not Allowed"))
				else:
#					frappe.msgprint("2")
					current_transaction = None
#					for i in range(0,len(same_states)):
					if len(same_states):
						i = 0
#						frappe.msgprint("3")
						length = len(self.get('workflow_history'))-1 if len(self.get('workflow_history')) > 0 else 0
						print self.get('workflow_history')
						prev_transaction = transactions[ same_states[i] - 1]
						print length
						last_elem = self.get('workflow_history')[length] #if length >= 0 else None
						print last_elem
						print "****************************\n"
						print "Last Transaction and last history"
						print prev_transaction[0] , last_elem.name
						print "****************************\n"

						#Action
						if last_elem is None or last_elem.new_state is None:
							current_transaction = transactions[0]
						#Update
						elif str(prev_transaction[0]) == str(last_elem.new_state):
							current_transaction = prev_transaction
						#Update
						elif last_elem.new_state == self.workflow_state:
							current_transaction = transactions[same_states[i]]
							self._current_action = "update"

				if current_transaction is None:
					frappe.throw("There's no workflow state, Refresh the page")

				condition = str(current_transaction[2]).split(":")
				if len(condition) == 1:
					check_func = condition[0]
					if not self.run_method(check_func):
						frappe.throw(_("You are not permitted."))

				if current_transaction[5] not in frappe.get_roles(frappe.session.user):
					frappe.throw(_("You are not Allowed ."))

#				print current_transaction[2]
				if current_transaction[2] is not None and self._current_action != "update":
					if len(condition) == 2:
						try:
							fcall = self.run_method(condition[0])
							if fcall:
								self.run_method("before_submit")
								self.db_set("workflow_state", condition[1])
								self.db_set("docstatus", "1") # submitted
								self.run_method("on_submit")
						except AttributeError as e:
							frappe.throw("Check workflow transaction condition :"+ str(e))
			else:
				pass

#			frappe.msgprint("before add to history")
			child = self.append('workflow_history', {})
			child.user = frappe.session.user
			child.action = self._current_action
			if self.previous_doc and 'workflow_state' in self.previous_doc:
				child.previous_state = self.previous_doc['workflow_state']
			child.new_state = self.workflow_state

			from frappe.utils import get_link_to_form , get_url , get_fullname

			#frappe.get_doc("Workflow Transition" , "" , "allowed")
			owner_employee = frappe.get_doc('Employee',{'name' : self.employee } )
			#if self.workflow_state =  or
			owner_user = frappe.db.get_value("User", owner_employee.user_id, "email")


			frappe.sendmail(
				recipients=(owner_user),
				sender= frappe.db.get_value("User", frappe.session.user, "email"),
				subject = "New Message from " + get_fullname(frappe.session.user),
				message = frappe.get_template("templates/emails/new_message.html").render({
					"from": get_fullname(frappe.session.user),
					"message": "Hello This is me",
					"link": get_link_to_form(self.doctype , self.name)
			}))
コード例 #44
0
def verify_and_initiate_transaction(doc, entered_password=None, otp=None):
    if isinstance(doc, string_types):
        doc = frappe._dict(json.loads(doc))
    obp_doc_name = doc['name']
    retry_count = doc['retry_count'] + 1
    frappe.db.set_value(doc['doctype'], doc['name'], 'retry_count',
                        retry_count)
    if doc['doctype'] == 'Bulk Outward Bank Payment':
        row = doc['outward_bank_payment_details'][0]
        data = {
            'party_type': row['party_type'],
            'party': row['party'],
            'amount': row['amount'],
            'remarks': doc['remarks'],
            'transaction_type': doc['transaction_type'],
            'company_bank_account': doc['company_bank_account'],
            'reconcile_action': doc['reconcile_action'],
            'bobp': doc['name']
        }
        obp_doc_name = frappe.db.exists('Outward Bank Payment', data)
        if not obp_doc_name:
            data['doctype'] = 'Outward Bank Payment'
            obp_doc = frappe.get_doc(data)
            obp_doc.save(ignore_permissions=True)
            obp_doc.submit()
            status = frappe.db.get_value('Outward Bank Payment', obp_doc.name,
                                         'workflow_state')
            frappe.db.set_value(
                'Outward Bank Payment Details', {
                    'parent': doc['name'],
                    'party_type': row['party_type'],
                    'party': row['party'],
                    'amount': row['amount']
                }, 'outward_bank_payment',
                get_link_to_form('Outward Bank Payment', obp_doc.name))
            frappe.db.set_value(
                'Outward Bank Payment Details', {
                    'parent': doc['name'],
                    'party_type': row['party_type'],
                    'party': row['party'],
                    'amount': row['amount'],
                    'outward_bank_payment': obp_doc.name
                }, 'status', status)
            obp_doc_name = obp_doc.name

    if entered_password and otp:
        integration_doc_name = frappe.get_value(
            'Bank API Integration',
            {'bank_account': doc['company_bank_account']}, 'name')
        defined_password = frappe.utils.password.get_decrypted_password(
            'Bank API Integration',
            integration_doc_name,
            fieldname='transaction_password')
        if not entered_password == defined_password:
            frappe.throw(_("Invalid Password"))
        initiate_transaction_with_otp(obp_doc_name, otp)

    if entered_password and not otp:
        integration_doc_name = frappe.get_value(
            'Bank API Integration',
            {'bank_account': doc['company_bank_account']}, 'name')
        defined_password = frappe.utils.password.get_decrypted_password(
            'Bank API Integration',
            integration_doc_name,
            fieldname='transaction_password')
        if not entered_password == defined_password:
            frappe.throw(_("Invalid Password"))
        initiate_transaction_without_otp(obp_doc_name)

    if otp and not entered_password:
        initiate_transaction_with_otp(obp_doc_name, otp)

    retry_count = frappe.db.get_value(doc['doctype'], doc['name'],
                                      'retry_count')
    workflow_state = frappe.db.get_value('Outward Bank Payment', obp_doc_name,
                                         'workflow_state')
    if workflow_state == 'Approved' and retry_count == 3:
        frappe.db.set_value(doc.doctype, doc.name, 'workflow_state',
                            'Verification Failed')

    if workflow_state in ['Initiated', 'Initiation Pending']:
        if doc['doctype'] == 'Bulk Outward Bank Payment':
            bobp = frappe.get_doc('Bulk Outward Bank Payment', doc['name'])
            bobp.bulk_create_obp_records()
コード例 #45
0
    def check_nextdoc_docstatus(self):
        # Checks Delivery Note
        submit_dn = frappe.db.sql_list(
            """
			select t1.name
			from `tabDelivery Note` t1,`tabDelivery Note Item` t2
			where t1.name = t2.parent and t2.against_sales_order = %s and t1.docstatus = 1""",
            self.name)

        if submit_dn:
            submit_dn = [
                get_link_to_form("Delivery Note", dn) for dn in submit_dn
            ]
            frappe.throw(
                _("Delivery Notes {0} must be cancelled before cancelling this Sales Order"
                  ).format(", ".join(submit_dn)))

        # Checks Sales Invoice
        submit_rv = frappe.db.sql_list(
            """select t1.name
			from `tabSales Invoice` t1,`tabSales Invoice Item` t2
			where t1.name = t2.parent and t2.sales_order = %s and t1.docstatus = 1""",
            self.name)

        if submit_rv:
            submit_rv = [
                get_link_to_form("Sales Invoice", si) for si in submit_rv
            ]
            frappe.throw(
                _("Sales Invoice {0} must be cancelled before cancelling this Sales Order"
                  ).format(", ".join(submit_rv)))

        #check maintenance schedule
        submit_ms = frappe.db.sql_list(
            """
			select t1.name
			from `tabMaintenance Schedule` t1, `tabMaintenance Schedule Item` t2
			where t2.parent=t1.name and t2.sales_order = %s and t1.docstatus = 1""",
            self.name)

        if submit_ms:
            submit_ms = [
                get_link_to_form("Maintenance Schedule", ms)
                for ms in submit_ms
            ]
            frappe.throw(
                _("Maintenance Schedule {0} must be cancelled before cancelling this Sales Order"
                  ).format(", ".join(submit_ms)))

        # check maintenance visit
        submit_mv = frappe.db.sql_list(
            """
			select t1.name
			from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2
			where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1""",
            self.name)

        if submit_mv:
            submit_mv = [
                get_link_to_form("Maintenance Visit", mv) for mv in submit_mv
            ]
            frappe.throw(
                _("Maintenance Visit {0} must be cancelled before cancelling this Sales Order"
                  ).format(", ".join(submit_mv)))

        # check work order
        pro_order = frappe.db.sql_list(
            """
			select name
			from `tabWork Order`
			where sales_order = %s and docstatus = 1""", self.name)

        if pro_order:
            pro_order = [
                get_link_to_form("Work Order", po) for po in pro_order
            ]
            frappe.throw(
                _("Work Order {0} must be cancelled before cancelling this Sales Order"
                  ).format(", ".join(pro_order)))
コード例 #46
0
def update_transaction_status(obp_name=None, bobp_name=None):
    bulk_update = True
    if obp_name or bobp_name:
        bulk_update = False
    if obp_name:
        obp_list = [{'name': obp_name}]
    if bobp_name:
        obp_list = frappe.db.get_all(
            'Outward Bank Payment', {
                'workflow_state': [
                    'in',
                    ['Initiated', 'Initiation Pending', 'Transaction Pending']
                ],
                'bobp': ['=', bobp_name]
            })
    if bulk_update:
        obp_list = frappe.db.get_all(
            'Outward Bank Payment', {
                'workflow_state': [
                    'in',
                    ['Initiated', 'Initiation Pending', 'Transaction Pending']
                ]
            })

    failed_obp_list = []
    if not obp_list:
        frappe.throw(_("No transaction found in the initiated state."))
    for doc in obp_list:
        res = None
        workflow_state = None
        obp_doc = frappe.get_doc('Outward Bank Payment', doc['name'])
        prov, config = get_api_provider_class(obp_doc.company_bank_account)
        unique_id = frappe.db.get_value(
            'Bank API Integration',
            {'bank_account': obp_doc.company_bank_account}, 'unique_id')
        filters = {"UNIQUEID": obp_doc.name if not unique_id else unique_id}
        try:
            res = prov.get_transaction_status(filters)
            if res['status'] == 'SUCCESS' and 'utr_number' in res:
                workflow_state = 'Transaction Completed'
            elif res['status'] in ['FAILURE', 'DUPLICATE']:
                workflow_state = 'Transaction Failed'
            elif 'PENDING' in res['status']:
                workflow_state = 'Transaction Pending'
            else:
                workflow_state = 'Transaction Error'
        except:
            workflow_state = 'Transaction Error'
            res = frappe.get_traceback()

        log_name = log_request(obp_doc.name, 'Update Transaction Status',
                               filters, config, res)
        frappe.db.set_value('Outward Bank Payment', {'name': obp_doc.name},
                            'workflow_state', workflow_state)
        frappe.db.commit()
        if workflow_state in [
                'Transaction Pending', 'Transaction Error',
                'Transaction Failed'
        ] and not bulk_update:
            if not obp_doc.bobp:
                frappe.throw(
                    _(f'An error occurred while making request. Kindly check request log for more info {get_link_to_form("Bank API Request Log", log_name)}'
                      ))
            else:
                failed_obp_list.append(
                    get_link_to_form("Outward Bank Payment", doc['name']))
    if failed_obp_list and not bulk_update:
        failed_obp = ','.join(failed_obp_list)
        frappe.throw(
            _(f"Transaction status update failed for the below obp(s) {failed_obp}"
              ))
    if bobp_name and not bulk_update:
        frappe.msgprint(_("Transaction Status Updated"))