Exemplo n.º 1
0
def reply_to_support_issue(client_issue_id,
                           subject,
                           description,
                           raised_by,
                           recipients,
                           frappe_issue_id,
                           attachments=None):

    comm = frappe.get_doc({
        "doctype": "Communication",
        "subject": subject,
        "content": description,
        "recipients": recipients,
        "sent_or_received": "Sent",
        "reference_doctype": "ERPNext Support Issue",
        "communication_medium": "Email",
        "sender": raised_by,
        "reference_name": client_issue_id,
        "has_attachment": 1 if attachments else 0
    }).insert(ignore_permissions=True)

    if isinstance(attachments, string_types):
        attachments = json.loads(attachments)

    if attachments:
        add_attachments("Communication", comm.name, attachments)
        add_attachments("ERPNext Support Issue", client_issue_id, attachments)

    frappe.db.commit()

    file_attachments = []

    if attachments:
        for a in attachments:
            filename, content = get_file(a)
            file_attachments.append({
                "filename":
                filename,
                "content":
                base64.b64encode(content).decode("ascii")
            })

    file_attachments = json.dumps(file_attachments)

    params = {
        "subject": subject,
        "recipients": recipients,
        "description": description,
        "raised_by": raised_by,
        "frappe_issue_id": frappe_issue_id,
        "attachments": file_attachments
    }

    last_sync_on = json.loads(
        call_remote_method("create_reply_from_customer", params))
    frappe.db.set_value("ERPNext Support Issue", client_issue_id,
                        "last_sync_on",
                        get_datetime(last_sync_on.get("last_sync_on")))
Exemplo n.º 2
0
def create_invoice(object):
    config = frappe.get_doc("MudEx Settings", "MudEx Settings")
    # find customer: either from Object or default
    o = frappe.get_doc("Object", object)
    customer = config.default_customer_for_mud
    for c in o.checklist:
        if c.activity == config.mud_activity:
            if c.invoice_to:
                customer = c.invoice_to
    # find taxes from customer record
    tax_templates = frappe.get_all('Party Account',
                                   filters={
                                       'parent': customer,
                                       'company': config.company
                                   },
                                   fields=['default_sales_taxes_and_charges'])
    if tax_templates and len(tax_templates) > 0:
        tax_template = tax_templates[0]['default_sales_taxes_and_charges']
    else:
        tax_template = None
    # set default cost center from company
    cost_center = frappe.get_value("Company", config.company, "cost_center")
    # get project link
    if frappe.db.exists("Project", object):
        project = object
    else:
        project = None
    # create new invoice
    new_sinv = frappe.get_doc({
        'doctype':
        'Sales Invoice',
        'company':
        config.company,
        'customer':
        customer,
        'object':
        object,
        'taxes_and_charges':
        tax_template,
        'tax_id':
        frappe.get_value("Customer", customer, "tax_id"),
        'cost_center':
        cost_center,
        # 'project': project,               # do not link to project, as project customer is end customer (will create a validation error)
        'naming_series':
        'RE-MX-.YY.#####',
        'title':
        'Rechnung'
    })
    # apply taxes
    if tax_template:
        tax_details = frappe.get_doc("Sales Taxes and Charges Template",
                                     tax_template)
        for t in tax_details.taxes:
            new_sinv.append(
                'taxes', {
                    'charge_type': t.charge_type,
                    'account_head': t.account_head,
                    'description': t.description,
                    'rate': t.rate
                })
    # get deliveries and add as positions
    invoiceable_deliveries = get_deliveries(object)
    if invoiceable_deliveries and len(invoiceable_deliveries) > 0:
        # fetch mud type - item data
        mud_type_items = frappe.get_all("Truck Load Type",
                                        fields=['title', 'item'])
        mud_type_map = {}
        for m in mud_type_items:
            mud_type_map[m['title']] = m['item']
        # append invoice positions
        for i in invoiceable_deliveries:
            d = i[
                'date']  # datetime.strptime(str(i['date'])[:19], "%Y-%m-%d %H:%M:%S")
            new_sinv.append(
                'items', {
                    'item_code':
                    mud_type_map[i['load_type']],
                    'qty':
                    i['weight'] / 1000,
                    'description':
                    "{date}: {truck}".format(
                        date=d.strftime("%d.%m.%Y, %H:%M"), truck=i['truck']),
                    'truck_delivery':
                    i['delivery'],
                    'truck_delivery_detail':
                    i['detail'],
                    'cost_center':
                    cost_center
                })
        # insert the new sales invoice
        new_sinv.insert()
        # submit directly internal/default customer
        if customer == config.default_customer_for_mud:
            new_sinv.submit()
            # create mathing purchase invoice
            pinv_company = new_sinv.customer_name
            pinv_supplier = frappe.get_all(
                "Supplier",
                filters={'supplier_name': config.company},
                fields=['name'])[0]['name']
            pinv_cost_center = frappe.get_value("Company", pinv_company,
                                                "cost_center")
            # find taxes from customer record
            pinv_tax_templates = frappe.get_all(
                'Party Account',
                filters={
                    'parent': pinv_supplier,
                    'company': pinv_company
                },
                fields=['default_purchase_taxes_and_charges'])
            if pinv_tax_templates and len(pinv_tax_templates) > 0:
                pinv_tax_template = pinv_tax_templates[0][
                    'default_purchase_taxes_and_charges']
            else:
                pinv_tax_template = None
            # create new purchase invoice
            new_pinv = frappe.get_doc({
                'doctype': 'Purchase Invoice',
                'company': pinv_company,
                'supplier': pinv_supplier,
                'bill_no': new_sinv.name,
                'bill_date': new_sinv.posting_date,
                'due_date': new_sinv.due_date,
                'object': new_sinv.object,
                'project': new_sinv.project,
                'cost_center': pinv_cost_center,
                'taxes_and_charges': pinv_tax_template,
                'disable_rounded_total': 1
            })
            # add item positions
            for i in new_sinv.items:
                new_pinv.append(
                    'items', {
                        'item_code': i.item_code,
                        'qty': i.qty,
                        'description': i.description,
                        'rate': i.rate,
                        'cost_center': pinv_cost_center
                    })
            # apply taxes
            if pinv_tax_template:
                pinv_tax_details = frappe.get_doc(
                    "Purchase Taxes and Charges Template", pinv_tax_template)
                for t in pinv_tax_details.taxes:
                    new_pinv.append(
                        'taxes', {
                            'charge_type': t.charge_type,
                            'account_head': t.account_head,
                            'description': t.description,
                            'rate': t.rate
                        })
            # insert
            new_pinv.insert()
            new_pinv.submit()
            # create pdf attachments
            try:
                # use execute instead of attach_pdf to make it sync for the subsequent doc
                execute("Sales Invoice",
                        new_sinv.name,
                        lang="de",
                        title=new_sinv.title,
                        print_format=config.sales_invoice_print_format)
                frappe.db.commit()
                attached_file = frappe.get_all("File",
                                               filters={
                                                   'attached_to_name':
                                                   new_sinv.name,
                                                   'attached_to_doctype':
                                                   "Sales Invoice"
                                               },
                                               fields=['name'])
                add_attachments("Purchase Invoice", new_pinv.name,
                                [attached_file[0]['name']])
            except Exception as err:
                frappe.log_error(
                    "Unable to attach pdf: {0}".format(err),
                    "Truck delivery document creation {0}".format(object))
        return new_sinv.name
    else:
        frappe.throw(_("Nothing to invoice"))
Exemplo n.º 3
0
def make(doctype=None, name=None, content=None, subject=None, sent_or_received = "Sent",
	sender=None, sender_full_name=None, recipients=None, communication_medium="Email", send_email=False,
	print_html=None, print_format=None, attachments='[]', send_me_a_copy=False, cc=None, bcc=None,
	flags=None, read_receipt=None, print_letterhead=True):
	"""Make a new communication.

	:param doctype: Reference DocType.
	:param name: Reference Document name.
	:param content: Communication body.
	:param subject: Communication subject.
	:param sent_or_received: Sent or Received (default **Sent**).
	:param sender: Communcation sender (default current user).
	:param recipients: Communication recipients as list.
	:param communication_medium: Medium of communication (default **Email**).
	:param send_mail: Send via email (default **False**).
	:param print_html: HTML Print format to be sent as attachment.
	:param print_format: Print Format name of parent document to be sent as attachment.
	:param attachments: List of attachments as list of files or JSON string.
	:param send_me_a_copy: Send a copy to the sender (default **False**).
	"""

	is_error_report = (doctype=="User" and name==frappe.session.user and subject=="Error Report")
	send_me_a_copy = cint(send_me_a_copy)

	if doctype and name and not is_error_report and not frappe.has_permission(doctype, "email", name) and not (flags or {}).get('ignore_doctype_permissions'):
		raise frappe.PermissionError("You are not allowed to send emails related to: {doctype} {name}".format(
			doctype=doctype, name=name))

	if not sender:
		sender = get_formatted_email(frappe.session.user)

	comm = frappe.get_doc({
		"doctype":"Communication",
		"subject": subject,
		"content": content,
		"sender": sender,
		"sender_full_name":sender_full_name,
		"recipients": recipients,
		"cc": cc or None,
		"bcc": bcc or None,
		"communication_medium": communication_medium,
		"sent_or_received": sent_or_received,
		"reference_doctype": doctype,
		"reference_name": name,
		"message_id":get_message_id().strip(" <>"),
		"read_receipt":read_receipt,
		"has_attachment": 1 if attachments else 0
	})
	comm.insert(ignore_permissions=True)

	if not doctype:
		# if no reference given, then send it against the communication
		comm.db_set(dict(reference_doctype='Communication', reference_name=comm.name))

	if isinstance(attachments, string_types):
		attachments = json.loads(attachments)

	# if not committed, delayed task doesn't find the communication
	if attachments:
		add_attachments("Communication", comm.name, attachments)

	frappe.db.commit()

	if cint(send_email):
		frappe.flags.print_letterhead = cint(print_letterhead)
		comm.send(print_html, print_format, attachments, send_me_a_copy=send_me_a_copy)

	return {
		"name": comm.name,
		"emails_not_sent_to": ", ".join(comm.emails_not_sent_to) if hasattr(comm, "emails_not_sent_to") else None
	}
Exemplo n.º 4
0
def make(doctype=None,
         name=None,
         content=None,
         subject=None,
         sent_or_received="Sent",
         sender=None,
         sender_full_name=None,
         recipients=None,
         communication_medium="Email",
         send_email=False,
         print_html=None,
         print_format=None,
         attachments='[]',
         send_me_a_copy=False,
         cc=None,
         bcc=None,
         flags=None,
         read_receipt=None,
         print_letterhead=True):
    """Make a new communication.

	:param doctype: Reference DocType.
	:param name: Reference Document name.
	:param content: Communication body.
	:param subject: Communication subject.
	:param sent_or_received: Sent or Received (default **Sent**).
	:param sender: Communcation sender (default current user).
	:param recipients: Communication recipients as list.
	:param communication_medium: Medium of communication (default **Email**).
	:param send_mail: Send via email (default **False**).
	:param print_html: HTML Print format to be sent as attachment.
	:param print_format: Print Format name of parent document to be sent as attachment.
	:param attachments: List of attachments as list of files or JSON string.
	:param send_me_a_copy: Send a copy to the sender (default **False**).
	"""

    is_error_report = (doctype == "User" and name == frappe.session.user
                       and subject == "Error Report")
    send_me_a_copy = cint(send_me_a_copy)

    if doctype and name and not is_error_report and not frappe.has_permission(
            doctype, "email",
            name) and not (flags or {}).get('ignore_doctype_permissions'):
        raise frappe.PermissionError(
            "You are not allowed to send emails related to: {doctype} {name}".
            format(doctype=doctype, name=name))

    if not sender:
        sender = get_formatted_email(frappe.session.user)

    comm = frappe.get_doc({
        "doctype": "Communication",
        "subject": subject,
        "content": content,
        "sender": sender,
        "sender_full_name": sender_full_name,
        "recipients": recipients,
        "cc": cc or None,
        "bcc": bcc or None,
        "communication_medium": communication_medium,
        "sent_or_received": sent_or_received,
        "reference_doctype": doctype,
        "reference_name": name,
        "message_id": get_message_id().strip(" <>"),
        "read_receipt": read_receipt,
        "has_attachment": 1 if attachments else 0
    })
    comm.insert(ignore_permissions=True)

    if not doctype:
        # if no reference given, then send it against the communication
        comm.db_set(
            dict(reference_doctype='Communication', reference_name=comm.name))

    if isinstance(attachments, string_types):
        attachments = json.loads(attachments)

    # if not committed, delayed task doesn't find the communication
    if attachments:
        add_attachments("Communication", comm.name, attachments)

    frappe.db.commit()

    if cint(send_email):
        frappe.flags.print_letterhead = cint(print_letterhead)
        comm.send(print_html,
                  print_format,
                  attachments,
                  send_me_a_copy=send_me_a_copy)

    return {
        "name":
        comm.name,
        "emails_not_sent_to":
        ", ".join(comm.emails_not_sent_to)
        if hasattr(comm, "emails_not_sent_to") else None
    }
Exemplo n.º 5
0
def create_erpnext_support_issue(subject,
                                 issue_type,
                                 issue_found_in,
                                 raised_by,
                                 description,
                                 attachments=None):

    erpnext_support_issue = frappe.get_doc({
        "doctype": "ERPNext Support Issue",
        "subject": subject,
        "issue_type": issue_type,
        "issue_found_in": issue_found_in,
        "raised_by": raised_by,
        "description": description,
    }).insert(ignore_permissions=True)

    comm = frappe.get_doc({
        "doctype": "Communication",
        "subject": subject,
        "content": description,
        "recipients": "*****@*****.**",
        "sent_or_received": "Sent",
        "reference_doctype": "ERPNext Support Issue",
        "communication_medium": "Email",
        "sender": raised_by,
        "reference_name": erpnext_support_issue.name,
        "has_attachment": 1 if attachments else 0
    }).insert(ignore_permissions=True)

    if isinstance(attachments, string_types):
        attachments = json.loads(attachments)

    if attachments:
        add_attachments("Communication", comm.name, attachments)
        add_attachments("ERPNext Support Issue", erpnext_support_issue.name,
                        attachments)

    frappe.db.commit()
    frappe.publish_realtime("erpnext_support_issue",
                            erpnext_support_issue.name)

    file_attachments = []

    if attachments:
        for a in attachments:
            filename, content = get_file(a)
            file_attachments.append({
                "filename":
                filename,
                "content":
                base64.b64encode(content).decode("ascii")
            })

    file_attachments = json.dumps(file_attachments)

    params = get_params(erpnext_support_issue, file_attachments)

    frappe_issue = call_remote_method("create_issue_from_customer", params)

    # If FrappeClient request fails, increment sync count
    if frappe_issue.get("failed"):
        erpnext_support_issue.db_set("sync_count",
                                     erpnext_support_issue.sync_count + 1)
        frappe.throw(
            "Could not sync Issue with Frappe Technologies. Retrying in sometime."
        )

    set_corresponding_frappe_values(erpnext_support_issue, frappe_issue)
    frappe.publish_realtime("refresh_erpnext_support_issue")

    return erpnext_support_issue.name