v2 with some rules
This commit is contained in:
parent
38c9006e82
commit
b5bf565e2b
4
gn_payroll/__init__.py
Normal file
4
gn_payroll/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import models
|
||||
26
gn_payroll/__manifest__.py
Normal file
26
gn_payroll/__manifest__.py
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "France - Paye",
|
||||
"version": "16.0.0.0.2",
|
||||
"category": "Payroll",
|
||||
"summary": "Configuration de la paie",
|
||||
"author": "Le Garage Numérique",
|
||||
"maintainers": ["makayabou"],
|
||||
"website": "https://odoo.legaragenumerique.fr",
|
||||
"depends": [
|
||||
"payroll",
|
||||
"hr_contract"
|
||||
],
|
||||
"data": [
|
||||
"data/gn_payroll_cc.xml",
|
||||
"data/gn_payroll_contract.xml",
|
||||
"data/gn_payroll_salary.xml",
|
||||
"data/gn_payroll_sickness.xml",
|
||||
"data/gn_payroll_time.xml",
|
||||
"data/gn_payroll_universal.xml",
|
||||
"data/gn_payroll_structure.xml",
|
||||
"data/init_flag.xml",
|
||||
"views/gn_payroll_company.xml",
|
||||
"security/ir.model.access.csv"
|
||||
],
|
||||
"license": "LGPL-3",
|
||||
}
|
||||
7
gn_payroll/data/gn_payroll_cc.xml
Normal file
7
gn_payroll/data/gn_payroll_cc.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="gn_payroll.cc_1418" model="gn_payroll.cc">
|
||||
<field name="name">Convention Eclat</field>
|
||||
<field name="idcc">1418</field>
|
||||
</record>
|
||||
</odoo>
|
||||
24
gn_payroll/data/gn_payroll_contract.xml
Normal file
24
gn_payroll/data/gn_payroll_contract.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="gn_payroll_contract_cae" model="hr.contract.type">
|
||||
<field name="name">PEC - CAE</field>
|
||||
</record>
|
||||
<record id="gn_payroll_contract_apprentissage" model="hr.contract.type">
|
||||
<field name="name">Contrat d'apprentissage</field>
|
||||
</record>
|
||||
<record id="gn_payroll_contract_cdd" model="hr.contract.type">
|
||||
<field name="name">CDD</field>
|
||||
</record>
|
||||
<record id="gn_payroll_contract_cdi" model="hr.contract.type">
|
||||
<field name="name">CDI</field>
|
||||
</record>
|
||||
<record id="gn_payroll_contract_service_civique" model="hr.contract.type">
|
||||
<field name="name">Service civique</field>
|
||||
</record>
|
||||
<record id="gn_payroll_contract_admin" model="hr.contract.type">
|
||||
<field name="name">Administrateur bénévole</field>
|
||||
</record>
|
||||
<record id="gn_payroll_contract_internship" model="hr.contract.type">
|
||||
<field name="name">Stage</field>
|
||||
</record>
|
||||
</odoo>
|
||||
58
gn_payroll/data/gn_payroll_salary.xml
Normal file
58
gn_payroll/data/gn_payroll_salary.xml
Normal file
@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="REMUNERATION" model="hr.salary.rule.category">
|
||||
<field name="name">Rémunération</field>
|
||||
<field name="code">REMUNERATION</field>
|
||||
</record>
|
||||
<record id="BRUT" model="hr.salary.rule">
|
||||
<field name="name">Salaire Brut</field>
|
||||
<field name="code">BRUT</field>
|
||||
<field name="sequence" eval="200" />
|
||||
<field name="category_id" ref="gn_payroll.REMUNERATION" />
|
||||
<field name="condition_select">none</field>
|
||||
<field name="amount_select">code</field>
|
||||
<field name="amount_python_compute">
|
||||
if inputs.BRUT and inputs.BRUT.amount > 0:
|
||||
result = inputs.BRUT.amount + categories.ALW + categories.INDEMNCOT
|
||||
elif inputs.BRUT and inputs.BRUT.amount == -1 :
|
||||
result = 0
|
||||
else:
|
||||
hours_month = 0
|
||||
dic_days = {0: 0, 1:0, 2: 0, 3: 0, 4:0}
|
||||
for x in contract.resource_calendar_id.attendance_ids:
|
||||
dic_days[int(x.dayofweek)] += (x.hour_to - x.hour_from)
|
||||
|
||||
# Calculating hours workable for the month
|
||||
for x in range(1, int(JOURSMOIS) + 1):
|
||||
day = payslip.date_from.replace(day = x).weekday()
|
||||
if day in dic_days:
|
||||
hours_month += dic_days[day]
|
||||
|
||||
hours_std = sum([(x.hour_to - x.hour_from) for x in contract.resource_calendar_id.attendance_ids]) * 52 /12
|
||||
|
||||
result = round( HOURS * contract.wage / hours_month , 2) + categories.ALW + categories.INDEMNCOT
|
||||
|
||||
#result = round( HOURS * contract.wage / hours_std , 2) + categories.ALW + categories.INDEMNCOT
|
||||
</field>
|
||||
</record>
|
||||
<record id="BRUTSC" model="hr.salary.rule">
|
||||
<field name="name">Indemnité de subsistance pour volontaire en service civique (Brut)</field>
|
||||
<field name="code">BRUTSC</field>
|
||||
<field name="sequence" eval="200" />
|
||||
<field name="category_id" ref="gn_payroll.REMUNERATION" />
|
||||
<field name="condition_select">none</field>
|
||||
<field name="amount_select">code</field>
|
||||
<field name="amount_python_compute">
|
||||
if inputs.BRUT and inputs.BRUT.amount > 0:
|
||||
result = inputs.BRUT.amount
|
||||
else:
|
||||
hours_std = sum([( x.hour_to - x.hour_from ) for x in contract.resource_calendar_id.attendance_ids]) * 52 / 12
|
||||
result = round( HOURS * TXSERVICECIVIQUE / hours_std , 2)
|
||||
</field>
|
||||
</record>
|
||||
<record id="BRUT_INPUT" model="hr.rule.input">
|
||||
<field name="name">Montant du Salaire Brut (corriger le montant calculé si nécessaire)</field>
|
||||
<field name="code">BRUT_INPUT</field>
|
||||
<field name="input_id" ref="gn_payroll.BRUT"/>
|
||||
</record>
|
||||
</odoo>
|
||||
156
gn_payroll/data/gn_payroll_sickness.xml
Normal file
156
gn_payroll/data/gn_payroll_sickness.xml
Normal file
@ -0,0 +1,156 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="SICKNESS" model="hr.salary.rule.category">
|
||||
<field name="name">Gestion des arrêts maladie</field>
|
||||
<field name="code">SICKNESS</field>
|
||||
</record>
|
||||
<record id ="CALENDAR_SICKNESS_DAYS" model="hr.salary.rule">
|
||||
<field name="name">Arrêt maladie (Jours Calendaires)</field>
|
||||
<field name="code">CALENDAR_SICKNESS_DAYS</field>
|
||||
<field name="active">true</field>
|
||||
<field name="appears_on_payslip">false</field>
|
||||
<field name="sequence" eval="100" />
|
||||
<field name="category_id" ref="gn_payroll.SICKNESS" />
|
||||
<field name="condition_select">python</field>
|
||||
<field name="condition_python">
|
||||
if (inputs.SICKNESS_FIRST_DAY and inputs.SICKNESS_FIRST_DAY.amount > 0) or (inputs.SICKNESS_LAST_DAY and inputs.SICKNESS_LAST_DAY.amount > 0):
|
||||
result = True
|
||||
</field>
|
||||
<field name="amount_select">code</field>
|
||||
<field name="amount_python_compute">
|
||||
first_day = payroll.date_from.day
|
||||
if inputs.SICKNESS_FIRST_DAY and \
|
||||
inputs.SICKNESS_FIRST_DAY.amount and \
|
||||
inputs.SICKNESS_FIRST_DAY.amount > 0:
|
||||
if (inputs.SICKNESS_FIRST_DAY.amount > payroll.date_to.day) or \
|
||||
(payroll.date_from.day > inputs.SICKNESS_FIRST_DAY.amount):
|
||||
raise UserError("La date de début de l'arrêt maladie ne peut pas être en dehors des dates de la fiche de paye.")
|
||||
else:
|
||||
first_day = inputs.SICKNESS_FIRST_DAY.amount
|
||||
|
||||
last_day = payroll.date_to.day
|
||||
if inputs.SICKNESS_LAST_DAY and \
|
||||
inputs.SICKNESS_LAST_DAY.amount and \
|
||||
inputs.SICKNESS_LAST_DAY.amount > 0:
|
||||
if (inputs.SICKNESS_LAST_DAY.amount > payroll.date_to.day) or \
|
||||
(payroll.date_from.day > inputs.SICKNESS_LAST_DAY.amount):
|
||||
raise UserError("La date de fin de l'arrêt maladie ne peut pas être en dehors des dates de la fiche de paye.")
|
||||
else:
|
||||
last_day = inputs.SICKNESS_LAST_DAY.amount
|
||||
|
||||
calendar_days = []
|
||||
for day in range(first_day, last_day, 1):
|
||||
calendar_days.append(first_day)
|
||||
result = calendar_days
|
||||
</field>
|
||||
</record>
|
||||
<record id="SICKNESS_FIRST_DAY" model="hr.rule.input">
|
||||
<field name="name">Arrêt maladie (Jour du mois de début de l'arrêt maladie)</field>
|
||||
<field name="code">SICKNESS_FIRST_DAY_INPUT</field>
|
||||
<field name="input_id" ref="gn_payroll.CALENDAR_SICKNESS_DAYS" />
|
||||
</record>
|
||||
<record id="SICKNESS_LAST_DAY" model="hr.rule.input">
|
||||
<field name="name">Arrêt maladie (Jour du mois de fin de l'arrêt maladie)</field>
|
||||
<field name="code">SICKNESS_LAST_DAY_INPUT</field>
|
||||
<field name="input_id" ref="gn_payroll.CALENDAR_SICKNESS_DAYS" />
|
||||
</record>
|
||||
<record id="NON_WORKED_SICKNESS_DAYS_INPUT" model="hr.rule.input">
|
||||
<field name="name">Arrêt maladie (Jours non-travaillés)</field>
|
||||
<field name="code">NON_WORKED_SICKNESS_DAYS_INPUT</field>
|
||||
<field name="input_id" ref="gn_payroll.CALENDAR_SICKNESS_DAYS" />
|
||||
</record>
|
||||
<record id="CALENDAR_SICKNESS_DAYS_INPUT" model="hr.rule.input">
|
||||
<field name="name">Arrêt maladie (Jours calendaires)</field>
|
||||
<field name="code">CALENDAR_SICKNESS_DAYS_INPUT</field>
|
||||
<field name="input_id" ref="gn_payroll.CALENDAR_SICKNESS_DAYS" />
|
||||
</record>
|
||||
<record id ="NON_WORKED_SICKNESS_DAYS" model="hr.salary.rule">
|
||||
<field name="name">Arrêt maladie (Jours non-travaillés)</field>
|
||||
<field name="code">NON_WORKED_SICKNESS_DAYS</field>
|
||||
<field name="active">true</field>
|
||||
<field name="appears_on_payslip">false</field>
|
||||
<field name="sequence" eval="101" />
|
||||
<field name="category_id" ref="gn_payroll.SICKNESS" />
|
||||
<field name="condition_select">python</field>
|
||||
<field name="condition_python">
|
||||
if rules.CALENDAR_SICKNESS_DAYS:
|
||||
result = True
|
||||
</field>
|
||||
<field name="amount_select">code</field>
|
||||
<field name="amount_python_compute">
|
||||
non_worked_days = []
|
||||
for sick_day in CALENDAR_SICKNESS_DAYS:
|
||||
is_day_worked = payslip.date_from.replace(day = sick_day).weekday()
|
||||
for planned_day in contract.resource_calendar_id.attendance_ids:
|
||||
if is_day_worked == int(x.dayofweek):
|
||||
non_worked_days.append(sick_day)
|
||||
break
|
||||
result = non_worked_days
|
||||
</field>
|
||||
</record>
|
||||
<record id ="WAITING_SICKNESS_DAYS" model="hr.salary.rule">
|
||||
<field name="name">Arrêt maladie (Jours de Carence)</field>
|
||||
<field name="code">WAITING_SICKNESS_DAYS</field>
|
||||
<field name="active">true</field>
|
||||
<field name="appears_on_payslip">false</field>
|
||||
<field name="sequence" eval="101" />
|
||||
<field name="category_id" ref="gn_payroll.SICKNESS" />
|
||||
<field name="condition_select">python</field>
|
||||
<field name="condition_python">
|
||||
if rules.CALENDAR_SICKNESS_DAYS:
|
||||
result = True
|
||||
</field>
|
||||
<field name="amount_select">code</field>
|
||||
<field name="amount_python_compute">
|
||||
from operator import itemgetter
|
||||
if payslip.company_id.cc.idcc == 1518:
|
||||
sickness_start_day = payslip.date_from.replace(day=CALENDAR_SICKNESS_DAYS[0])
|
||||
# Let's check if contract (or 1st contract if consecutive contracts) is older than 6 months:
|
||||
first_contract_day = payslip.contract_id.date_start
|
||||
employee_contracts = [contract for contract in payslip.employee_id.contract_ids if \
|
||||
(contract.id != payslip.contract_id.id and payslip.date_from >= contract.date_start) else None]
|
||||
sorted_employee_contracts = sorted(employee_contracts, key=itemgetter('date_start'), reverse=True)
|
||||
|
||||
for contract in sorted_employee_contracts:
|
||||
if contract.date_end == first_contract_day - 1:
|
||||
first_contract_day = contract.date_start
|
||||
else:
|
||||
break
|
||||
|
||||
if 90 >= sickness_start_day - first_contract_day:
|
||||
result = 3
|
||||
else:
|
||||
result = 0
|
||||
</field>
|
||||
</record>
|
||||
<record id="WAITING_SICKNESS_DAYS_INPUT" model="hr.rule.input">
|
||||
<field name="name">Arrêt maladie (Jours de Carence)</field>
|
||||
<field name="code">WAITING_SICKNESS_DAYS_INPUT</field>
|
||||
<field name="input_id" ref="gn_payroll.WAITING_SICKNESS_DAYS" />
|
||||
</record>
|
||||
<record id ="IJSS_SICKNESS" model="hr.salary.rule">
|
||||
<field name="name">Arrêt maladie (Montant IJSS Brut)</field>
|
||||
<field name="code">IJSS_SICKNESS</field>
|
||||
<field name="active">true</field>
|
||||
<field name="appears_on_payslip">false</field>
|
||||
<field name="sequence" eval="101" />
|
||||
<field name="category_id" ref="gn_payroll.SICKNESS" />
|
||||
<field name="condition_select">python</field>
|
||||
<field name="condition_python">
|
||||
if rules.CALENDAR_SICKNESS_DAYS:
|
||||
result = True
|
||||
</field>
|
||||
<field name="amount_select">code</field>
|
||||
<field name="amount_python_compute">
|
||||
daily_wage = contract.wage * 3 / 91.25
|
||||
daily_ijss = daily_wage / 2
|
||||
number_of_compensated_days = len(CALENDAR_SICKNESS_DAYS) - WAITING_SICKNESS_DAYS
|
||||
result = daily_ijss * number_of_compensated_days
|
||||
</field>
|
||||
</record>
|
||||
<record id="IJSS_SICKNESS_INPUT" model="hr.rule.input">
|
||||
<field name="name">Arrêt maladie (Montant IJSS)</field>
|
||||
<field name="code">IJSS_SICKNESS_INPUT</field>
|
||||
<field name="input_id" ref="gn_payroll.IJSS_SICKNESS" />
|
||||
</record>
|
||||
</odoo>
|
||||
35
gn_payroll/data/gn_payroll_structure.xml
Normal file
35
gn_payroll/data/gn_payroll_structure.xml
Normal file
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="gn_payroll_structure_common" model="hr.payroll.structure">
|
||||
<field name="name">Structure Salariale par Défaut</field>
|
||||
<field name="company_id" eval="1"/>
|
||||
<field name="rule_ids" eval="[
|
||||
(6, 0, [
|
||||
ref('CALENDAR_SICKNESS_DAYS'),
|
||||
ref('NON_WORKED_SICKNESS_DAYS'),
|
||||
ref('NON_WORKED_SICKNESS_DAYS'),
|
||||
ref('WAITING_SICKNESS_DAYS'),
|
||||
ref('IJSS_SICKNESS'),
|
||||
ref('HOURS'),
|
||||
ref('BRUT'),
|
||||
ref('JOURSMOIS'),
|
||||
ref('SMICH'),
|
||||
ref('PMSS'),
|
||||
ref('WAGE'),
|
||||
ref('TXREMBTRANS')
|
||||
])
|
||||
]"/>
|
||||
</record>
|
||||
<record id="gn_payroll_structure_cadre" model="hr.payroll.structure">
|
||||
<field name="name">Cadre</field>
|
||||
</record>
|
||||
<record id="gn_payroll_structure_service_civique" model="hr.payroll.structure">
|
||||
<field name="name">Service civique</field>
|
||||
</record>
|
||||
<record id="gn_payroll_structure_intern" model="hr.payroll.structure">
|
||||
<field name="name">Stage</field>
|
||||
</record>
|
||||
<record id="gn_payroll_structure_administrator" model="hr.payroll.structure">
|
||||
<field name="name">Administrateur</field>
|
||||
</record>
|
||||
</odoo>
|
||||
85
gn_payroll/data/gn_payroll_time.xml
Normal file
85
gn_payroll/data/gn_payroll_time.xml
Normal file
@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="TIME" model="hr.salary.rule.category">
|
||||
<field name="name">Calcul des heures</field>
|
||||
<field name="code">TIME</field>
|
||||
</record>
|
||||
<record id="HOURS" model="hr.salary.rule">
|
||||
<field name="name">Heures rémunérées</field>
|
||||
<field name="code">HOURS</field>
|
||||
<field name="sequence" eval="100" />
|
||||
<field name="category_id" ref="gn_payroll.TIME" />
|
||||
<field name="condition_select">none</field>
|
||||
<field name="amount_select">code</field>
|
||||
<field name="amount_python_compute">
|
||||
day = 0
|
||||
hours = 0
|
||||
hours_month = 0
|
||||
hours_std = sum([(x.hour_to - x.hour_from) for x in contract.resource_calendar_id.attendance_ids]) * 52 /12
|
||||
|
||||
# calculation for Service civique
|
||||
if contract.struct_id.code == "VOLSERVCIV":
|
||||
if payslip.date_from.day > 1:
|
||||
result = hours_std * (31 - payslip.date_from.day) / 30
|
||||
elif JOURSMOIS > payslip.date_to.day:
|
||||
result = hours_std * payslip.date_to.day / 30
|
||||
else:
|
||||
result = hours_std
|
||||
|
||||
# other calculations
|
||||
else:
|
||||
dic_days = {0: 0, 1:0, 2: 0, 3: 0, 4:0}
|
||||
for x in contract.resource_calendar_id.attendance_ids:
|
||||
dic_days[int(x.dayofweek)] += (x.hour_to - x.hour_from)
|
||||
|
||||
# Calculating missed hours when payslip doesn't start / end at the beginning/ end of the month
|
||||
|
||||
if payslip.date_from.day > 1:
|
||||
for x in range(payslip.date_from.day, 1, -1):
|
||||
day = payslip.date_from.replace(day = x).weekday()
|
||||
if day in dic_days:
|
||||
hours += dic_days[day]
|
||||
|
||||
if JOURSMOIS > payslip.date_to.day:
|
||||
for x in range(payslip.date_to.day + 1, int(JOURSMOIS)):
|
||||
day = payslip.date_to.replace(day = x).weekday()
|
||||
if day in dic_days:
|
||||
hours += dic_days[day]
|
||||
|
||||
hours_missed = hours
|
||||
|
||||
# Calculating missed hours when absence or sickday
|
||||
|
||||
maladie = inputs.MALADIE.amount if inputs.MALADIE and inputs.MALADIE.amount > 0.0 else 0
|
||||
absences = inputs.ABSENCE.amount if inputs.ABSENCE and inputs.ABSENCE.amount > 0.0 else 0
|
||||
calendaires = inputs.CALENDAIRE.amount if inputs.CALENDAIRE and inputs.CALENDAIRE.amount > 0.0 else 0
|
||||
|
||||
if ( maladie != 0 or absences != 0):
|
||||
if calendaires + absences == JOURSMOIS:
|
||||
hours_std = 0
|
||||
|
||||
else:
|
||||
days_off = absences + maladie
|
||||
hours_off = days_off * contract.resource_calendar_id.hours_per_day
|
||||
hours_missed += hours_off
|
||||
|
||||
# Final calculations
|
||||
|
||||
if worked_days.WORK100 and worked_days.WORK100.number_of_hours:
|
||||
hours_done = worked_days.WORK100.number_of_hours
|
||||
else:
|
||||
hours_done = hours_std
|
||||
|
||||
####result = hours_done - hours_missed
|
||||
#result = hours_done * hours_std / (hours_missed + hours_done)
|
||||
#result = hours_std * (hours_done - hours_missed) / hours_done
|
||||
result = hours_done - hours_missed
|
||||
####result = hours_std - hours_missed
|
||||
</field>
|
||||
</record>
|
||||
<record id="ABSENCE" model="hr.rule.input">
|
||||
<field name="name">Absences non rémunérées ( hors arrêt maladie)</field>
|
||||
<field name="code">ABSENCE</field>
|
||||
<field name="input_id" ref="gn_payroll.HOURS" />
|
||||
</record>
|
||||
</odoo>
|
||||
164
gn_payroll/data/gn_payroll_universal.xml
Normal file
164
gn_payroll/data/gn_payroll_universal.xml
Normal file
@ -0,0 +1,164 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="UNIVERSAL" model="hr.salary.rule.category">
|
||||
<field name="name">Universel</field>
|
||||
<field name="code">UNIVERSAL</field>
|
||||
</record>
|
||||
<record id="JOURSMOIS" model="hr.salary.rule">
|
||||
<field name="name">Jours dans le mois</field>
|
||||
<field name="code">JOURSMOIS</field>
|
||||
<field name="sequence" eval="2" />
|
||||
<field name="category_id" ref="gn_payroll.UNIVERSAL" />
|
||||
<field name="condition_select">none</field>
|
||||
<field name="amount_select">code</field>
|
||||
<field name="amount_python_compute">
|
||||
if payslip.date_from.month in [1, 3, 5, 7, 8, 10, 12]:
|
||||
result = 31
|
||||
elif payslip.date_from.month == 2:
|
||||
if payslip.date_from.year % 4 == 0:
|
||||
result = 29
|
||||
else:
|
||||
result = 28
|
||||
else:
|
||||
result = 30
|
||||
</field>
|
||||
</record>
|
||||
<record id="SMICH" model="hr.salary.rule">
|
||||
<field name="name">Smic Horaire</field>
|
||||
<field name="code">SMICH</field>
|
||||
<field name="sequence" eval="2" />
|
||||
<field name="category_id" ref="gn_payroll.UNIVERSAL" />
|
||||
<field name="condition_select">none</field>
|
||||
<field name="amount_select">code</field>
|
||||
<field name="amount_python_compute">
|
||||
rate_table = [
|
||||
("2014-01-01", 9.53),
|
||||
("2015-01-01", 9.61),
|
||||
("2016-01-01", 9.67),
|
||||
("2017-01-01", 9.76),
|
||||
("2018-01-01", 9.88),
|
||||
("2019-01-01", 10.03),
|
||||
("2020-01-01", 10.15),
|
||||
("2021-01-01", 10.25),
|
||||
("2021-10-01", 10.48),
|
||||
("2022-01-01", 10.57),
|
||||
("2022-05-01", 10.85),
|
||||
("2022-08-01", 11.07),
|
||||
("2023-01-01", 11.27),
|
||||
("2023-05-01", 11.52)
|
||||
]
|
||||
def parse_date(date_str):
|
||||
year, month, day = map(int, date_str.split('-'))
|
||||
return year, month, day
|
||||
|
||||
# Manually compare dates
|
||||
smic = rate_table[0][1]
|
||||
for rate_date_str, rate in rate_table:
|
||||
rate_year, rate_month, rate_day = parse_date(rate_date_str)
|
||||
payslip_year, payslip_month, payslip_day = parse_date(payslip.date_from.strftime('%Y-%m-%d'))
|
||||
|
||||
if (payslip_year, payslip_month, payslip_day) >= (rate_year, rate_month, rate_day):
|
||||
smic = rate
|
||||
else:
|
||||
break
|
||||
|
||||
result = smic
|
||||
</field>
|
||||
</record>
|
||||
<record id="PMSS" model="hr.salary.rule">
|
||||
<field name="name">Plafond Mensuel de Sécurité Sociale</field>
|
||||
<field name="code">PMSS</field>
|
||||
<field name="sequence" eval="2" />
|
||||
<field name="category_id" ref="gn_payroll.UNIVERSAL" />
|
||||
<field name="condition_select">none</field>
|
||||
<field name="amount_select">code</field>
|
||||
<field name="amount_python_compute">
|
||||
rate_table = [
|
||||
("2014-01-01", 3129),
|
||||
("2015-01-01", 3170),
|
||||
("2016-01-01", 3218),
|
||||
("2017-01-01", 3269),
|
||||
("2018-01-01", 3311),
|
||||
("2019-01-01", 3377),
|
||||
("2020-01-01", 3428),
|
||||
("2023-01-01", 3666)
|
||||
]
|
||||
def parse_date(date_str):
|
||||
year, month, day = map(int, date_str.split('-'))
|
||||
return year, month, day
|
||||
|
||||
# Manually compare dates
|
||||
pmss = rate_table[0][1]
|
||||
for rate_date_str, rate in rate_table:
|
||||
rate_year, rate_month, rate_day = parse_date(rate_date_str)
|
||||
payslip_year, payslip_month, payslip_day = parse_date(payslip.date_from.strftime('%Y-%m-%d'))
|
||||
|
||||
if (payslip_year, payslip_month, payslip_day) >= (rate_year, rate_month, rate_day):
|
||||
pmss = rate
|
||||
else:
|
||||
break
|
||||
|
||||
result = pmss
|
||||
</field>
|
||||
</record>
|
||||
<record id="TXSERVICECIVIQUE" model="hr.salary.rule">
|
||||
<field name="name">Indemnité de Service civique</field>
|
||||
<field name="code">TXSERVICECIVIQUE</field>
|
||||
<field name="sequence" eval="2" />
|
||||
<field name="category_id" ref="gn_payroll.UNIVERSAL" />
|
||||
<field name="condition_select">none</field>
|
||||
<field name="amount_select">code</field>
|
||||
<field name="amount_python_compute">
|
||||
rate_table = [
|
||||
("2015-01-01", 106.31),
|
||||
("2016-07-01", 106.94),
|
||||
("2017-02-01", 107.58),
|
||||
("2022-07-01", 111.35),
|
||||
("2023-07-01", 113.02)
|
||||
]
|
||||
def parse_date(date_str):
|
||||
year, month, day = map(int, date_str.split('-'))
|
||||
return year, month, day
|
||||
|
||||
# Manually compare dates
|
||||
indem_service_civique = rate_table[0][1]
|
||||
for rate_date_str, rate in rate_table:
|
||||
rate_year, rate_month, rate_day = parse_date(rate_date_str)
|
||||
payslip_year, payslip_month, payslip_day = parse_date(payslip.date_from.strftime('%Y-%m-%d'))
|
||||
|
||||
if (payslip_year, payslip_month, payslip_day) >= (rate_year, rate_month, rate_day):
|
||||
indem_service_civique = rate
|
||||
else:
|
||||
break
|
||||
|
||||
result = indem_service_civique
|
||||
</field>
|
||||
</record>
|
||||
<record id="WAGE" model="hr.salary.rule">
|
||||
<field name="name">Salaire contractuel</field>
|
||||
<field name="code">WAGE</field>
|
||||
<field name="sequence" eval="2" />
|
||||
<field name="category_id" ref="gn_payroll.UNIVERSAL" />
|
||||
<field name="condition_select">none</field>
|
||||
<field name="amount_select">code</field>
|
||||
<field name="amount_python_compute">
|
||||
result = contract.wage
|
||||
</field>
|
||||
</record>
|
||||
<record id="TXREMBTRANS" model="hr.salary.rule">
|
||||
<field name="name">Taux de Remboursement des Transports</field>
|
||||
<field name="code">TXREMBTRANS</field>
|
||||
<field name="sequence" eval="2" />
|
||||
<field name="category_id" ref="gn_payroll.UNIVERSAL" />
|
||||
<field name="condition_select">none</field>
|
||||
<field name="amount_select">code</field>
|
||||
<field name="amount_python_compute">
|
||||
if 2023 > payslip.date_from.year:
|
||||
result = 35
|
||||
elif payslip.date_from.year == 2023:
|
||||
result = 42.05
|
||||
elif payslip.date_from.year == 2024:
|
||||
result = 42.05
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
6
gn_payroll/data/init_flag.xml
Normal file
6
gn_payroll/data/init_flag.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<odoo>
|
||||
<function model="ir.config_parameter" name="set_param">
|
||||
<value eval="'gn_payroll.first_installation'" />
|
||||
<value eval="'True'" />
|
||||
</function>
|
||||
</odoo>
|
||||
7
gn_payroll/models/__init__.py
Normal file
7
gn_payroll/models/__init__.py
Normal file
@ -0,0 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import gn_payroll_cc
|
||||
from . import gn_payroll_company
|
||||
from . import gn_payroll_employee
|
||||
#from . import gn_payroll_contract_structure_type
|
||||
17
gn_payroll/models/gn_payroll_cc.py
Normal file
17
gn_payroll/models/gn_payroll_cc.py
Normal file
@ -0,0 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class ConventionCollective(models.Model):
|
||||
_name = "gn_payroll.cc"
|
||||
_description = "Convention Collective"
|
||||
_order = 'idcc, name'
|
||||
|
||||
def copy(self, default=None):
|
||||
raise UserError(_('Duplicating a company is not allowed. Please create a new company instead.'))
|
||||
|
||||
name = fields.Char(string='Nom complet de la Convention Collective', required=True, store=True, readonly=False)
|
||||
active = fields.Boolean(default=True)
|
||||
idcc = fields.Integer(string="IDCC", help='Used to order Conventions Collectives in the switcher', default=10)
|
||||
11
gn_payroll/models/gn_payroll_company.py
Normal file
11
gn_payroll/models/gn_payroll_company.py
Normal file
@ -0,0 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
cc = fields.Many2one('gn_payroll.cc', "Convention Collective appliquée")
|
||||
|
||||
14
gn_payroll/models/gn_payroll_contract_structure_type.py
Normal file
14
gn_payroll/models/gn_payroll_contract_structure_type.py
Normal file
@ -0,0 +1,14 @@
|
||||
from odoo import models, api
|
||||
|
||||
class HrPayrollStructureType(models.Model):
|
||||
_name = 'hr.payroll.structure.type'
|
||||
|
||||
@api.model
|
||||
def init(self):
|
||||
super(HrPayrollStructureType, self).init()
|
||||
first_install = self.env['ir.config_parameter'].sudo().get_param('gn_payroll.first_installation')
|
||||
if first_install:
|
||||
# Delete pre-existing records
|
||||
self.env['hr.payroll.structure.type'].search([]).unlink()
|
||||
# Reset the flag
|
||||
self.env['ir.config_parameter'].sudo().set_param('gn_payroll.first_installation', 'False')
|
||||
12
gn_payroll/models/gn_payroll_employee.py
Normal file
12
gn_payroll/models/gn_payroll_employee.py
Normal file
@ -0,0 +1,12 @@
|
||||
from odoo import models, fields
|
||||
|
||||
class GnPayrollHrEmployee(models.Model):
|
||||
_inherit = 'hr.employee'
|
||||
employee_type = fields.Selection([
|
||||
('employee', 'Employé'),
|
||||
('student', 'Étudiant'),
|
||||
('trainee', 'Stagiaire'),
|
||||
('volunteer', 'Volontaire'),
|
||||
('benevolent', 'Bénévole'),
|
||||
], string='Employee Type', default='employee', required=True,
|
||||
help="The employee type. Although the primary purpose may seem to categorize employees, this field has also an impact in the Contract History. Only Employee type is supposed to be under contract and will have a Contract History.")
|
||||
3
gn_payroll/security/ir.model.access.csv
Normal file
3
gn_payroll/security/ir.model.access.csv
Normal file
@ -0,0 +1,3 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_gn_payroll_cc_user,gn_payroll_cc_user,model_gn_payroll_cc,base.group_user,1,0,0,0
|
||||
acces_gn_payroll_cc_admin,gn_payroll_cc_admin,model_gn_payroll_cc,hr_contract.group_hr_contract_manager,1,1,0,0
|
||||
|
16
gn_payroll/views/gn_payroll_company.xml
Normal file
16
gn_payroll/views/gn_payroll_company.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="res_company_form_gn_payroll" model="ir.ui.view">
|
||||
<field name="name">res.company.form.gnpayroll.fr</field>
|
||||
<field name="model">res.company</field>
|
||||
<field name="priority">30</field>
|
||||
<field name="inherit_id" ref="account.view_company_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<data>
|
||||
<xpath expr="//field[@name='company_registry']" position="after">
|
||||
<field name="cc" attrs="{'invisible': [('country_code', '!=', 'FR')]}"/>
|
||||
</xpath>
|
||||
</data>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
Loading…
x
Reference in New Issue
Block a user