Add simple payroll structure
This commit is contained in:
parent
d9d17c7521
commit
992048501a
1
addons/mcs_simple_payroll/__init__.py
Normal file
1
addons/mcs_simple_payroll/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from . import hooks
|
||||
15
addons/mcs_simple_payroll/__manifest__.py
Normal file
15
addons/mcs_simple_payroll/__manifest__.py
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "Metatroncube Simple Payroll",
|
||||
"version": "17.0.1.0.0",
|
||||
"category": "Payroll",
|
||||
"summary": "Simple monthly payroll without statutory tax, PF, or ESI deductions",
|
||||
"author": "Metatroncube Software Solutions",
|
||||
"license": "LGPL-3",
|
||||
"depends": ["payroll"],
|
||||
"data": [
|
||||
"views/hr_payslip_views.xml",
|
||||
],
|
||||
"post_init_hook": "post_init_hook",
|
||||
"installable": True,
|
||||
"application": False,
|
||||
}
|
||||
117
addons/mcs_simple_payroll/hooks.py
Normal file
117
addons/mcs_simple_payroll/hooks.py
Normal file
@ -0,0 +1,117 @@
|
||||
from odoo import api, SUPERUSER_ID
|
||||
|
||||
|
||||
def post_init_hook(env_or_cr, registry=None):
|
||||
if registry is not None:
|
||||
env = api.Environment(env_or_cr, SUPERUSER_ID, {})
|
||||
else:
|
||||
env = env_or_cr
|
||||
SimplePayrollSetup(env).run()
|
||||
|
||||
|
||||
class SimplePayrollSetup:
|
||||
def __init__(self, env):
|
||||
self.env = env
|
||||
self.Category = env["hr.salary.rule.category"]
|
||||
self.Rule = env["hr.salary.rule"]
|
||||
self.Structure = env["hr.payroll.structure"]
|
||||
self.Contract = env["hr.contract"]
|
||||
self.Company = env["res.company"]
|
||||
|
||||
def run(self):
|
||||
categories = self._ensure_categories()
|
||||
for company in self.Company.search([]):
|
||||
structure = self._ensure_structure(company, categories)
|
||||
self._assign_open_contracts(company, structure)
|
||||
|
||||
def _ensure_categories(self):
|
||||
specs = [
|
||||
("BASIC", "Basic"),
|
||||
("GROSS", "Gross"),
|
||||
("NET", "Net"),
|
||||
]
|
||||
result = {}
|
||||
for code, name in specs:
|
||||
category = self.Category.search([("code", "=", code)], limit=1)
|
||||
if not category:
|
||||
category = self.Category.create({"code": code, "name": name})
|
||||
result[code] = category
|
||||
return result
|
||||
|
||||
def _ensure_rule(self, company, code, name, sequence, category, python_code):
|
||||
rule = self.Rule.search(
|
||||
[
|
||||
("code", "=", code),
|
||||
("company_id", "=", company.id),
|
||||
("name", "=", name),
|
||||
],
|
||||
limit=1,
|
||||
)
|
||||
values = {
|
||||
"name": name,
|
||||
"code": code,
|
||||
"sequence": sequence,
|
||||
"category_id": category.id,
|
||||
"company_id": company.id,
|
||||
"condition_select": "none",
|
||||
"amount_select": "code",
|
||||
"amount_python_compute": python_code.strip(),
|
||||
"appears_on_payslip": True,
|
||||
"active": True,
|
||||
}
|
||||
if rule:
|
||||
rule.write(values)
|
||||
else:
|
||||
rule = self.Rule.create(values)
|
||||
return rule
|
||||
|
||||
def _ensure_structure(self, company, categories):
|
||||
basic = self._ensure_rule(
|
||||
company,
|
||||
"MCS_BASIC",
|
||||
"Basic Salary",
|
||||
10,
|
||||
categories["BASIC"],
|
||||
"result = contract.wage",
|
||||
)
|
||||
gross = self._ensure_rule(
|
||||
company,
|
||||
"MCS_GROSS",
|
||||
"Gross Salary",
|
||||
100,
|
||||
categories["GROSS"],
|
||||
"result = categories.BASIC",
|
||||
)
|
||||
net = self._ensure_rule(
|
||||
company,
|
||||
"MCS_NET",
|
||||
"Net Salary",
|
||||
200,
|
||||
categories["NET"],
|
||||
"result = categories.GROSS",
|
||||
)
|
||||
structure = self.Structure.search(
|
||||
[("code", "=", "MCS_SIMPLE_MONTHLY"), ("company_id", "=", company.id)],
|
||||
limit=1,
|
||||
)
|
||||
values = {
|
||||
"name": "MCS Simple Monthly Payroll",
|
||||
"code": "MCS_SIMPLE_MONTHLY",
|
||||
"company_id": company.id,
|
||||
"rule_ids": [(6, 0, [basic.id, gross.id, net.id])],
|
||||
}
|
||||
if structure:
|
||||
structure.write(values)
|
||||
else:
|
||||
structure = self.Structure.create(values)
|
||||
return structure
|
||||
|
||||
def _assign_open_contracts(self, company, structure):
|
||||
contracts = self.Contract.search(
|
||||
[
|
||||
("company_id", "=", company.id),
|
||||
("state", "=", "open"),
|
||||
("employee_id.active", "=", True),
|
||||
]
|
||||
)
|
||||
contracts.write({"struct_id": structure.id, "schedule_pay": "monthly"})
|
||||
55
addons/mcs_simple_payroll/views/hr_payslip_views.xml
Normal file
55
addons/mcs_simple_payroll/views/hr_payslip_views.xml
Normal file
@ -0,0 +1,55 @@
|
||||
<odoo>
|
||||
<template id="report_payslip_simple" inherit_id="payroll.report_payslip">
|
||||
<xpath expr="//div[hasclass('page')]" position="replace">
|
||||
<div class="page">
|
||||
<h2>Salary Payslip</h2>
|
||||
<table class="table table-sm table-bordered">
|
||||
<tr>
|
||||
<td><strong>Employee</strong></td>
|
||||
<td><span t-field="o.employee_id"/></td>
|
||||
<td><strong>Job Title</strong></td>
|
||||
<td><span t-field="o.employee_id.job_title"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Email</strong></td>
|
||||
<td><span t-field="o.employee_id.work_email"/></td>
|
||||
<td><strong>Payslip Ref</strong></td>
|
||||
<td><span t-field="o.number"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Period From</strong></td>
|
||||
<td><span t-field="o.date_from"/></td>
|
||||
<td><strong>Period To</strong></td>
|
||||
<td><span t-field="o.date_to"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Structure</strong></td>
|
||||
<td><span t-field="o.struct_id"/></td>
|
||||
<td><strong>Bank Account</strong></td>
|
||||
<td><span t-field="o.employee_id.bank_account_id"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table class="table table-sm table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Description</th>
|
||||
<th class="text-end">Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr t-foreach="o.line_ids.filtered(lambda l: l.appears_on_payslip and l.amount != 0)" t-as="line">
|
||||
<td><span t-field="line.name"/></td>
|
||||
<td class="text-end">
|
||||
<span t-esc="line.total" t-options='{"widget": "monetary", "display_currency": o.company_id.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p>This payslip is generated for internal salary processing only. No statutory tax, PF, or ESI deductions are applied in the simple payroll structure.</p>
|
||||
<p class="text-end"><strong>Authorized signature</strong></p>
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
</odoo>
|
||||
Loading…
x
Reference in New Issue
Block a user