def execute():

    doctypes = [
        "salary_component",
        "Employee Tax Exemption Declaration",
        "Employee Tax Exemption Proof Submission",
        "Employee Tax Exemption Declaration Category",
        "Employee Tax Exemption Proof Submission Detail",
        "gratuity_rule",
        "gratuity_rule_slab",
        "gratuity_applicable_component",
    ]

    for doctype in doctypes:
        frappe.reload_doc("Payroll", "doctype", doctype, force=True)

    reports = [
        "Professional Tax Deductions", "Provident Fund Deductions",
        "E-Invoice Summary"
    ]
    for report in reports:
        frappe.reload_doc("Regional", "Report", report)
        frappe.reload_doc("Regional", "Report", report)

    if erpnext.get_region() == "India":
        create_custom_field(
            "Salary Component",
            dict(
                fieldname="component_type",
                label="Component Type",
                fieldtype="Select",
                insert_after="description",
                options=
                "\nProvident Fund\nAdditional Provident Fund\nProvident Fund Loan\nProfessional Tax",
                depends_on='eval:doc.type == "Deduction"',
            ),
        )

    if frappe.db.exists("Salary Component", "Income Tax"):
        frappe.db.set_value("Salary Component", "Income Tax",
                            "is_income_tax_component", 1)
    if frappe.db.exists("Salary Component", "TDS"):
        frappe.db.set_value("Salary Component", "TDS",
                            "is_income_tax_component", 1)

    components = frappe.db.sql(
        "select name from `tabSalary Component` where variable_based_on_taxable_salary = 1",
        as_dict=1)
    for component in components:
        frappe.db.set_value("Salary Component", component.name,
                            "is_income_tax_component", 1)

    if erpnext.get_region() == "India":
        if frappe.db.exists("Salary Component", "Provident Fund"):
            frappe.db.set_value("Salary Component", "Provident Fund",
                                "component_type", "Provident Fund")
        if frappe.db.exists("Salary Component", "Professional Tax"):
            frappe.db.set_value("Salary Component", "Professional Tax",
                                "component_type", "Professional Tax")
Esempio n. 2
0
def get_data(filters):

    data = []

    fields = ["employee", "branch", "bank_name", "bank_ac_no", "salary_mode"]
    if erpnext.get_region() == "India":
        fields += ["ifsc_code", "micr_code"]

    employee_details = frappe.get_list("Employee", fields=fields)
    employee_data_dict = {}

    for d in employee_details:
        employee_data_dict.setdefault(
            d.employee, {
                "bank_ac_no": d.bank_ac_no,
                "ifsc_code": d.ifsc_code or None,
                "micr_code": d.micr_code or None,
                "branch": d.branch,
                "salary_mode": d.salary_mode,
                "bank_name": d.bank_name
            })

    conditions = get_conditions(filters)

    entry = frappe.db.sql(""" select employee, employee_name, gross_pay
		from `tabSalary Slip`
		where docstatus = 1 %s """ % (conditions),
                          as_dict=1)

    for d in entry:

        employee = {
            "branch": employee_data_dict.get(d.employee).get("branch"),
            "employee_name": d.employee_name,
            "employee": d.employee,
            "gross_pay": d.gross_pay,
        }

        if employee_data_dict.get(d.employee).get("salary_mode") == "Bank":
            employee["bank"] = employee_data_dict.get(
                d.employee).get("bank_name")
            employee["account_no"] = employee_data_dict.get(
                d.employee).get("bank_ac_no")
            if erpnext.get_region() == "India":
                employee["ifsc"] = employee_data_dict.get(
                    d.employee).get("ifsc_code")
                employee["micr"] = employee_data_dict.get(
                    d.employee).get("micr_code")
        else:
            employee["account_no"] = employee_data_dict.get(
                d.employee).get("salary_mode")

        if filters.get("type") and employee_data_dict.get(
                d.employee).get("salary_mode") == filters.get("type"):
            data.append(employee)
        elif not filters.get("type"):
            data.append(employee)

    return data
Esempio n. 3
0
def get_data(filters):

	data = []

	if erpnext.get_region() == "India":
		employee_pan_dict = frappe._dict(
			frappe.db.sql(""" select employee, pan_number from `tabEmployee`""")
		)

	component_types = frappe.db.sql(
		""" select name from `tabSalary Component`
		where is_income_tax_component = 1 """
	)

	component_types = [comp_type[0] for comp_type in component_types]

	if not len(component_types):
		return []

	conditions = get_conditions(filters)

	entry = frappe.db.sql(
		""" select sal.employee, sal.employee_name, sal.posting_date, ded.salary_component, ded.amount,sal.gross_pay
		from `tabSalary Slip` sal, `tabSalary Detail` ded
		where sal.name = ded.parent
		and ded.parentfield = 'deductions'
		and ded.parenttype = 'Salary Slip'
		and sal.docstatus = 1 %s
		and ded.salary_component in (%s)
	"""
		% (conditions, ", ".join(["%s"] * len(component_types))),
		tuple(component_types),
		as_dict=1,
	)

	for d in entry:

		employee = {
			"employee": d.employee,
			"employee_name": d.employee_name,
			"it_comp": d.salary_component,
			"posting_date": d.posting_date,
			# "pan_number": employee_pan_dict.get(d.employee),
			"it_amount": d.amount,
			"gross_pay": d.gross_pay,
		}

		if erpnext.get_region() == "India":
			employee["pan_number"] = employee_pan_dict.get(d.employee)

		data.append(employee)

	return data
Esempio n. 4
0
def get_columns(filters):
    columns = [
        {
            "label": _("Branch"),
            "options": "Branch",
            "fieldname": "branch",
            "fieldtype": "Link",
            "width": 200,
        },
        {
            "label": _("Employee Name"),
            "options": "Employee",
            "fieldname": "employee_name",
            "fieldtype": "Link",
            "width": 160,
        },
        {
            "label": _("Employee"),
            "options": "Employee",
            "fieldname": "employee",
            "fieldtype": "Link",
            "width": 140,
        },
        {
            "label": _("Gross Pay"),
            "fieldname": "gross_pay",
            "fieldtype": "Currency",
            "options": "currency",
            "width": 140,
        },
        {
            "label": _("Bank"),
            "fieldname": "bank",
            "fieldtype": "Data",
            "width": 140
        },
        {
            "label": _("Account No"),
            "fieldname": "account_no",
            "fieldtype": "Data",
            "width": 140
        },
    ]
    if erpnext.get_region() == "India":
        columns += [
            {
                "label": _("IFSC"),
                "fieldname": "ifsc",
                "fieldtype": "Data",
                "width": 140
            },
            {
                "label": _("MICR"),
                "fieldname": "micr",
                "fieldtype": "Data",
                "width": 140
            },
        ]

    return columns
Esempio n. 5
0
def create_qr_code(doc, method):
    """Create QR Code after inserting Sales Inv
	"""

    region = get_region(doc.company)
    if region not in ['Saudi Arabia']:
        return

    # if QR Code field not present, do nothing
    if not hasattr(doc, 'qr_code'):
        return

    # Don't create QR Code if it already exists
    qr_code = doc.get("qr_code")
    if qr_code and frappe.db.exists({"doctype": "File", "file_url": qr_code}):
        return

    meta = frappe.get_meta('Sales Invoice')

    for field in meta.get_image_fields():
        if field.fieldname == 'qr_code':
            # Creating public url to print format
            default_print_format = frappe.db.get_value(
                'Property Setter',
                dict(property='default_print_format', doc_type=doc.doctype),
                "value")

            # System Language
            language = frappe.get_system_settings('language')

            # creating qr code for the url
            url = f"{ frappe.utils.get_url() }/{ doc.doctype }/{ doc.name }?format={ default_print_format or 'Standard' }&_lang={ language }&key={ doc.get_signature() }"
            qr_image = io.BytesIO()
            url = qr_create(url, error='L')
            url.png(qr_image, scale=2, quiet_zone=1)

            # making file
            filename = f"QR-CODE-{doc.name}.png".replace(os.path.sep, "__")
            _file = frappe.get_doc({
                "doctype": "File",
                "file_name": filename,
                "is_private": 0,
                "content": qr_image.getvalue(),
                "attached_to_doctype": doc.get("doctype"),
                "attached_to_name": doc.get("name"),
                "attached_to_field": "qr_code"
            })

            _file.save()

            # assigning to document
            doc.db_set('qr_code', _file.file_url)
            doc.notify_update()

            break
Esempio n. 6
0
def get_columns(filters):
	columns = [
		{
			"label": _("Employee"),
			"options": "Employee",
			"fieldname": "employee",
			"fieldtype": "Link",
			"width": 200
		},
		{
			"label": _("Employee Name"),
			"options": "Employee",
			"fieldname": "employee_name",
			"fieldtype": "Link",
			"width": 160
		}]

	if erpnext.get_region() == "India":
		columns.append({
			"label": _("PAN Number"),
			"fieldname": "pan_number",
			"fieldtype": "Data",
			"width": 140
		})

	columns += [{
			"label": _("Income Tax Component"),
			"fieldname": "it_comp",
			"fieldtype": "Data",
			"width": 170
		},
		{
			"label": _("Income Tax Amount"),
			"fieldname": "it_amount",
			"fieldtype": "Currency",
			"options": "currency",
			"width": 140
		},
		{
			"label": _("Gross Pay"),
			"fieldname": "gross_pay",
			"fieldtype": "Currency",
			"options": "currency",
			"width": 140
		},
		{
			"label": _("Posting Date"),
			"fieldname": "posting_date",
			"fieldtype": "Date",
			"width": 140
		}
	]

	return columns
Esempio n. 7
0
def delete_qr_code_file(doc, method=None):
    region = get_region(doc.company)
    if region not in ["Saudi Arabia"]:
        return

    if hasattr(doc, "ksa_einv_qr"):
        if doc.get("ksa_einv_qr"):
            file_doc = frappe.get_list("File",
                                       {"file_url": doc.get("ksa_einv_qr")})
            if len(file_doc):
                frappe.delete_doc("File", file_doc[0].name)
Esempio n. 8
0
def execute():

    doctypes = [
        'salary_component', 'Employee Tax Exemption Declaration',
        'Employee Tax Exemption Proof Submission',
        'Employee Tax Exemption Declaration Category',
        'Employee Tax Exemption Proof Submission Detail'
    ]

    for doctype in doctypes:
        frappe.reload_doc('Payroll', 'doctype', doctype)

    reports = ['Professional Tax Deductions', 'Provident Fund Deductions']
    for report in reports:
        frappe.reload_doc('Regional', 'Report', report)
        frappe.reload_doc('Regional', 'Report', report)

    if erpnext.get_region() == "India":
        setup(patch=True)

    if frappe.db.exists("Salary Component", "Income Tax"):
        frappe.db.set_value("Salary Component", "Income Tax",
                            "is_income_tax_component", 1)
    if frappe.db.exists("Salary Component", "TDS"):
        frappe.db.set_value("Salary Component", "TDS",
                            "is_income_tax_component", 1)

    components = frappe.db.sql(
        "select name from `tabSalary Component` where variable_based_on_taxable_salary = 1",
        as_dict=1)
    for component in components:
        frappe.db.set_value("Salary Component", component.name,
                            "is_income_tax_component", 1)

    if erpnext.get_region() == "India":
        if frappe.db.exists("Salary Component", "Provident Fund"):
            frappe.db.set_value("Salary Component", "Provident Fund",
                                "component_type", "Provident Fund")
        if frappe.db.exists("Salary Component", "Professional Tax"):
            frappe.db.set_value("Salary Component", "Professional Tax",
                                "component_type", "Professional Tax")
Esempio n. 9
0
def delete_qr_code_file(doc, method):
    """Delete QR Code on deleted sales invoice"""

    region = get_region(doc.company)
    if region not in ['Saudi Arabia']:
        return

    if hasattr(doc, 'qr_code'):
        if doc.get('qr_code'):
            file_doc = frappe.get_list('File',
                                       {'file_url': doc.get('qr_code')})
            if len(file_doc):
                frappe.delete_doc('File', file_doc[0].name)
Esempio n. 10
0
def create_transaction_log(doc, method):
    region = get_region()
    if region not in ["France"]:
        return
    else:
        data = str(doc.as_dict())

        frappe.get_doc({
            "doctype": "Transaction Log",
            "reference_doctype": doc.doctype,
            "document_name": doc.name,
            "data": data
        }).insert(ignore_permissions=True)
Esempio n. 11
0
def create_transaction_log(doc, method):
	region = get_region()
	if region not in ["France"]:
		return
	else:
		data = str(doc.as_dict())

		frappe.get_doc({
			"doctype": "Transaction Log",
			"reference_doctype": doc.doctype,
			"document_name": doc.name,
			"data": data
		}).insert(ignore_permissions=True)
Esempio n. 12
0
def set_sales_tax(doc, method):
	if not TAXJAR_CALCULATE_TAX:
		return

	if get_region(doc.company) != 'United States':
		return

	if not doc.items:
		return

	if check_sales_tax_exemption(doc):
		return

	tax_dict = get_tax_data(doc)

	if not tax_dict:
		# Remove existing tax rows if address is changed from a taxable state/country
		setattr(doc, "taxes", [tax for tax in doc.taxes if tax.account_head != TAX_ACCOUNT_HEAD])
		return

	# check if delivering within a nexus
	check_for_nexus(doc, tax_dict)

	tax_data = validate_tax_request(tax_dict)
	if tax_data is not None:
		if not tax_data.amount_to_collect:
			setattr(doc, "taxes", [tax for tax in doc.taxes if tax.account_head != TAX_ACCOUNT_HEAD])
		elif tax_data.amount_to_collect > 0:
			# Loop through tax rows for existing Sales Tax entry
			# If none are found, add a row with the tax amount
			for tax in doc.taxes:
				if tax.account_head == TAX_ACCOUNT_HEAD:
					tax.tax_amount = tax_data.amount_to_collect

					doc.run_method("calculate_taxes_and_totals")
					break
			else:
				doc.append("taxes", {
					"charge_type": "Actual",
					"description": "Sales Tax",
					"account_head": TAX_ACCOUNT_HEAD,
					"tax_amount": tax_data.amount_to_collect
				})
			# Assigning values to tax_collectable and taxable_amount fields in sales item table
			for item in tax_data.breakdown.line_items:
				doc.get('items')[cint(item.id)-1].tax_collectable = item.tax_collectable
				doc.get('items')[cint(item.id)-1].taxable_amount = item.taxable_amount

			doc.run_method("calculate_taxes_and_totals")
Esempio n. 13
0
def create_transaction_log(doc, method):
    """
    Appends the transaction to a chain of hashed logs for legal resons.
    Called on submit of Sales Invoice and Payment Entry.
    """
    region = get_region()
    if region not in ["France", "Germany"]:
        return

    data = str(doc.as_dict())

    frappe.get_doc({
        "doctype": "Transaction Log",
        "reference_doctype": doc.doctype,
        "document_name": doc.name,
        "data": data
    }).insert(ignore_permissions=True)
Esempio n. 14
0
def check_deletion_permission(doc, method):
    region = get_region(doc.company)
    if region in ["Nepal", "France"] and doc.docstatus != 0:
        frappe.throw(
            _("Deletion is not permitted for country {0}").format(region))
Esempio n. 15
0
def check_deletion_permission(doc, method):
	region = get_region()
	if region in ["Nepal", "France"] and doc.docstatus != 0:
		frappe.throw(_("Deletion is not permitted for country {0}".format(region)))
Esempio n. 16
0
def create_qr_code(doc, method=None):
    region = get_region(doc.company)
    if region not in ["Saudi Arabia"]:
        return

    # if QR Code field not present, create it. Invoices without QR are invalid as per law.
    if not hasattr(doc, "ksa_einv_qr"):
        create_custom_fields({
            doc.doctype: [
                dict(
                    fieldname="ksa_einv_qr",
                    label="KSA E-Invoicing QR",
                    fieldtype="Attach Image",
                    read_only=1,
                    no_copy=1,
                    hidden=1,
                )
            ]
        })

    # Don't create QR Code if it already exists
    qr_code = doc.get("ksa_einv_qr")
    if qr_code and frappe.db.exists({"doctype": "File", "file_url": qr_code}):
        return

    meta = frappe.get_meta(doc.doctype)

    if "ksa_einv_qr" in [d.fieldname for d in meta.get_image_fields()]:
        """TLV conversion for
		1. Seller's Name
		2. VAT Number
		3. Time Stamp
		4. Invoice Amount
		5. VAT Amount
		"""
        tlv_array = []
        # Sellers Name

        seller_name = frappe.db.get_value("Company", doc.company,
                                          "company_name_in_arabic")

        if not seller_name:
            frappe.throw(
                _("Arabic name missing for {} in the company document").format(
                    doc.company))

        tag = bytes([1]).hex()
        length = bytes([len(seller_name.encode("utf-8"))]).hex()
        value = seller_name.encode("utf-8").hex()
        tlv_array.append("".join([tag, length, value]))

        # VAT Number
        tax_id = frappe.db.get_value("Company", doc.company, "tax_id")
        if not tax_id:
            frappe.throw(
                _("Tax ID missing for {} in the company document").format(
                    doc.company))

        tag = bytes([2]).hex()
        length = bytes([len(tax_id)]).hex()
        value = tax_id.encode("utf-8").hex()
        tlv_array.append("".join([tag, length, value]))

        # Time Stamp
        posting_date = getdate(doc.posting_date)
        time = get_time(doc.posting_time)
        seconds = time.hour * 60 * 60 + time.minute * 60 + time.second
        time_stamp = add_to_date(posting_date, seconds=seconds)
        time_stamp = time_stamp.strftime("%Y-%m-%dT%H:%M:%SZ")

        tag = bytes([3]).hex()
        length = bytes([len(time_stamp)]).hex()
        value = time_stamp.encode("utf-8").hex()
        tlv_array.append("".join([tag, length, value]))

        # Invoice Amount
        invoice_amount = str(doc.grand_total)
        tag = bytes([4]).hex()
        length = bytes([len(invoice_amount)]).hex()
        value = invoice_amount.encode("utf-8").hex()
        tlv_array.append("".join([tag, length, value]))

        # VAT Amount
        vat_amount = str(get_vat_amount(doc))

        tag = bytes([5]).hex()
        length = bytes([len(vat_amount)]).hex()
        value = vat_amount.encode("utf-8").hex()
        tlv_array.append("".join([tag, length, value]))

        # Joining bytes into one
        tlv_buff = "".join(tlv_array)

        # base64 conversion for QR Code
        base64_string = b64encode(bytes.fromhex(tlv_buff)).decode()

        qr_image = io.BytesIO()
        url = qr_create(base64_string, error="L")
        url.png(qr_image, scale=2, quiet_zone=1)

        name = frappe.generate_hash(doc.name, 5)

        # making file
        filename = f"QRCode-{name}.png".replace(os.path.sep, "__")
        _file = frappe.get_doc({
            "doctype": "File",
            "file_name": filename,
            "is_private": 0,
            "content": qr_image.getvalue(),
            "attached_to_doctype": doc.get("doctype"),
            "attached_to_name": doc.get("name"),
            "attached_to_field": "ksa_einv_qr",
        })

        _file.save()

        # assigning to document
        doc.db_set("ksa_einv_qr", _file.file_url)
        doc.notify_update()
Esempio n. 17
0
def check_deletion_permission(doc, method):
    region = get_region()
    if region in ["Nepal", "France"]:
        frappe.throw(
            _("Deletion is not permitted for country {0}".format(region)))