Hola a tod@s, en este pequeño tutorial quiero mostrar, una nomina en odoo que desarrolle para llevar un registro a los empleados, y de esa manera tengan una copia de su liquidación de sueldo, este desarrollo no es, tan complejo o tan completo como lo puedes encontrar dentro de odoo (https://apps.odoo.com/apps) (https://odoo-community.org/shop), pero sirve para el propósito de mi cliente y si alguien lo quiere utilizar aqui les dejo el código, obviamente siéntanse libre de mejorarlo.
bueno supongo que si estas viendo esto, es porque ya sabes algo de odoo y te manejas en algo con el código y su estructura, dejo una imagen de como se ve el from, aclaro que esta hecho para Chile.
Nomina en Odoo

Ahora ingresare el código del .py que concierne a la nomina, como comente ustedes son libres de modificar los nombres y si lo pueden mejorar lo puedan compartir.
Nomina.py
# -*- coding: utf-8 -*-
from datetime import date
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
from odoo.osv import expression
class NominaCert(models.Model):
_name = 'cert.nomina'
_inherit = ['mail.thread', 'mail.activity.mixin']
_description = 'Nomina Empleados'
name = fields.Many2one('res.users', string='Empleados', required=True,)
rut = fields.Char(string='Rut', related="name.identification_id")
poste = fields.Char(related='name.job_title', string='Puesto de Trabajo')
date = fields.Date('Fecha', default=fields.Date.today())
sale = fields.Integer(string='Sueldo dias Trabajados', compute='_sale', help='Son los Dias que Trabajo el Empleado')
bonus = fields.Integer(string='Bonificación Imponible')
extra = fields.Integer(string='Horas Extras')
gratuity = fields.Integer(string='Gratificación Legal', compute='_gratuity')
afp = fields.Integer(string='AFP', compute='_afp', store=True)
afp_id = fields.Float(string='Fondo AFP %', related='contract_id.afp_id')
fonasa = fields.Integer(string='Fonasa / Isapre', compute='_fonasa', store=True)
fonasa_id = fields.Float(string='Fonasa %', related='contract_id.fonasa_id')
sure = fields.Integer(string='Seguro de Cesantia', compute='_sure')
sure_id = fields.Float(string='Seguro %', related='contract_id.sure_id')
tax = fields.Integer(string='Impuesto Unico')
family = fields.Integer(string='Cargas Familiares')
car = fields.Integer(string='Asignación Locomoción')
lunch = fields.Integer(string='Asignación de Colación')
taxi = fields.Integer(string='Haberes Imponibles', compute='_taxi')
tax_id = fields.Integer(string='Haberes No Imponibles', compute='_tax_id')
discount = fields.Integer(string='Descuentos', compute='_discount')
pay = fields.Integer(string='Liquido a Pagar', compute='_pay', store=True)
month = fields.Selection([('E', 'Enero'), ('F', 'Febrero'), ('M', 'Marzo'), ('A', 'Abril'), ('Z', 'Mayo'),
('J', 'Junio'), ('X', 'Julio'), ('B', 'Agosto'), ('S', 'Septiembre'), ('O', 'Octubre'),
('N', 'Noviembre'), ('D', 'Diciembre')], default=' ')
contract_id = fields.Many2one('hr.contract', string='Contracto', required=True)
days = fields.Integer(string='Dias Trabajados', required=True)
sale_id = fields.Integer(string='Sueldo Base', related='contract_id.sale', store=True)
@api.depends('days','sale_id')
def _sale(self):
for r in self:
her = r.days
jer = r.sale_id /30
ger = jer * her
if her <= 30:
r.sale = ger
else:
r.sale = 0
@api.depends('sale','bonus','extra')
def _gratuity(self):
for r in self:
gratuity = 0.25*(r.sale+r.bonus+r.extra)
if gratuity <= 158333:
r.gratuity = gratuity
else:
r.gratuity = 158333
@api.depends('sale','bonus','extra','gratuity')
def _taxi(self):
for r in self:
r.taxi = r.sale+r.bonus+r.extra+r.gratuity
@api.depends('family','car','lunch')
def _tax_id(self):
for r in self:
r.tax_id = r.family+r.car+r.lunch
@api.depends('taxi','sure_id')
def _sure(self):
for r in self:
r.sure = r.sure_id*r.taxi/100
@api.depends('taxi','fonasa_id')
def _fonasa(self):
for r in self:
r.fonasa = r.fonasa_id*r.taxi/100
@api.depends('taxi','afp_id')
def _afp(self):
for r in self:
r.afp = r.afp_id*r.taxi/100
@api.depends('afp','fonasa','sure','tax')
def _discount(self):
for r in self:
r.discount = r.afp+r.fonasa+r.sure+r.tax
@api.depends('taxi','tax_id','discount')
def _pay(self):
for r in self:
r.pay = r.taxi+r.tax_id-r.discount
Ahora les comparto el código del archivo XML, donde creo el form, el tree y el pivot el cual se usa para sacar valores para el pago de los impuestos.
Views_nomina.xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
//from para el modulo de nomina de los empleados//
<record id="view_cert_nomina_form" model="ir.ui.view">
<field name="name">nomina.form</field>
<field name="model">cert.nomina</field>
<field name="arch" type="xml">
<form string="Nomina">
<sheet>
<separator string="CREAR LIQUIDACIÓN"/>
<div class="oe_title">
<h1>
<field name="name" placeholder="Empleado..." />
</h1>
</div>
<group col="4">
<field name="rut"/>
<field name="poste"/>
<field name="date"/>
<field name="contract_id"/>
<field name="month" required="1"/>
<field name="sale_id"/>
</group>
<group col="4">
<field name="days"/>
<field name="afp_id" invisible="True"/>
<field name="sale"/>
<field name="afp"/>
<field name="bonus"/>
<field name="fonasa"/>
<field name="extra"/>
<field name="sure"/>
<field name="gratuity"/>
<field name="fonasa_id" invisible="True"/>
<field name="sure_id" invisible="True"/>
</group>
<group col="4">
<field name="family"/>
<field name="tax"/>
<field name="car"/>
<field name="lunch"/>
</group>
<group col="4">
<field name="taxi"/>
<field name="discount"/>
<field name="tax_id"/>
<field name="pay" sum="Total"/>
</group>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids"/>
<field name="activity_ids"/>
<field name="message_ids"/>
</div>
</form>
</field>
</record>
<record id="view_cert_nomina_tree" model="ir.ui.view">
<field name="name">nomina.tree</field>
<field name="model">cert.nomina</field>
<field name="arch" type="xml">
<tree string="Nomina">
<field name="name"/>
<field name="rut"/>
<field name="poste" optional="hide"/>
<field name="month"/>
<field name="days"/>
<field name="sale"/>
<field name="afp"/>
<field name="fonasa" optional="hide"/>
<field name="sure" optional="hide"/>
<field name="gratuity" optional="hide"/>
<field name="taxi" optional="hide"/>
<field name="discount"/>
<field name="pay"/>
</tree>
</field>
</record>
<record id="view_cert_nomina_pivot" model="ir.ui.view">
<field name="model">cert.nomina</field>
<field name="arch" type="xml">
<pivot>
<field name="name" type="row"/>
<field name="month" interval="year" type="col"/>
<field name="afp" type="measure"/>
<field name="fonasa" type="measure"/>
<field name="pay" type="measure"/>
</pivot>
</field>
</record>
</data>
</odoo>
Por ultimo les dejare el codigo del template, para imprimir la liquidacion de sueldo al empleado.
Templates_nomina.xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<report id="reporte_nomina_cert"
string="Imp Liquidación"
model="cert.nomina"
report_type="qweb-pdf"
name="shool_startel.nomina_reporte_nomina_cert"
print_report_name="'Liquidación - %s' % (object.name)"
/>
<template id="nomina_reporte_nomina_cert">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="o">
<t t-call="web.external_layout">
<div class="page">
<head>
<style>
.demo {
border: 1px sólido #354259;
border-collapse:colapso;
padding:0px;
border-radius: 10px;
font-size: 12px;
}
.demo th {
border: 1px sólido #354259;
padding:5px;
text-align:centrar;
background:#839AA8;
}
.demo td {
border: 1px sólido #354259;
padding:5px;
}
</style>
</head>
<div>
<h4>
<center>Escuela de Conductores </center>
<center>76.000.000-0</center>
<center>Andres Bello 100 - Valdivia</center>
</h4>
<h4>
<center>Liquidaciones de Remuneraciones Mes
<span t-field="o.month"/>
</center>
</h4>
<br/>
<h5>
Nombre :
<span t-field="o.name"/>
<br/>
Rut :
<span t-field="o.rut"/>
<br/>
Cargo :
<span t-field="o.poste"/>
<br/>
Dias Trabajados :
<span t-field="o.days"/>
</h5>
</div>
<br/>
<div class="row" align="center">
<table width="100%" style="border: 2px solid black" class="demo">
<thead>
<tr>
<th>Haberes</th>
<th></th>
<th>Descuentos</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>Sueldo Base</td>
<td style="text-align: right">
<span t-field="o.sale"/>
</td>
<td>AFP</td>
<td style="text-align: right">
<span t-field="o.afp"/>
</td>
</tr>
<tr>
<td>Bonificación Imponible</td>
<td style="text-align: right">
<span t-field="o.bonus"/>
</td>
<td>Fonasa</td>
<td style="text-align: right">
<span t-field="o.fonasa"/>
</td>
</tr>
<tr>
<td>Horas Extras</td>
<td style="text-align: right">
<span t-field="o.extra"/>
</td>
<td>Seguro de Cesantia</td>
<td style="text-align: right">
<span t-field="o.sure"/>
</td>
</tr>
<tr>
<td>Gratificación Legal</td>
<td style="text-align: right">
<span t-field="o.gratuity"/>
</td>
<td>Impuesto Unico</td>
<td style="text-align: right">
<span t-field="o.tax"/>
</td>
</tr>
<tr>
<td>Cargas Familiares</td>
<td style="text-align: right">
<span t-field="o.family"/>
</td>
<td></td>
<td style="text-align: right">0</td>
</tr>
<tr>
<td>Asignación de Locomoción</td>
<td style="text-align: right">
<span t-field="o.car"/>
</td>
<td></td>
<td style="text-align: right">0</td>
</tr>
<tr>
<td>Asignación de Colación</td>
<td style="text-align: right">
<span t-field="o.lunch"/>
</td>
<td></td>
<td style="text-align: right">0</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Haberes Imponibles</td>
<td style="text-align: right">
<span t-field="o.taxi"/>
</td>
<td>Descuentos</td>
<td style="text-align: right">
<span t-field="o.discount"/>
</td>
</tr>
<tr>
<td>Haberes No Imponibles</td>
<td style="text-align: right">
<span t-field="o.tax_id"/>
</td>
<td style="background: #839AA8">Liquido a Pagar</td>
<td style="background: #839AA8; text-align: right">
<span t-field="o.pay"/>
</td>
</tr>
</tbody>
</table>
</div>
<div>
<p>
Certifico Haber recibido de C la remuneracion integra a pagar indicada
en esta liquidacion no teneniendo cobro alguno que hacer por dichos conceptos.
</p>
</div>
<br/>
<br/>
<br/>
<div>
<h5>
<center>FIRMA DEL TRABAJADOR</center>
</h5>
</div>
</div>
<div class="footer">
<p>
<center>www.serco.com - Telefono:(45)11111868 - Mail: serco@serco.com</center>
</p>
</div>
</t>
</t>
</t>
</template>
</data>
</odoo>
Dejo una imagen del template como se veria al imprimir.

Obviamente todo lo que comparto es porque yo lo he realizado y esta funcionando, mas adelante seguire compartiendo mas cosas en las cuales estoy trabajando, no soy un esperto en odoo, ni en programacion, me dedico a la conectividad y seguridad de la información.