1
# -*- encoding: utf-8 -*-
2
##############################################################################
4
# OpenERP, Open Source Management Solution
5
# Copyright (C) 2009 Ting! (<http://www.ting.es>). All Rights Reserved
8
# This program is free software: you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation, either version 3 of the License, or
11
# (at your option) any later version.
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
# GNU General Public License for more details.
18
# You should have received a copy of the GNU General Public License
19
# along with this program. If not, see <http://www.gnu.org/licenses/>.
21
##############################################################################
24
from osv import fields
28
from tools.translate import _
30
class res_company(osv.osv):
32
_inherit = 'res.company'
34
'diario_destino': fields.many2one('account.journal', 'Diario de Destino', required=True),
35
'cuenta_ss_empresa': fields.many2one('account.account', 'Cuenta Seguridad Social a cargo de la empresa', required=True),
36
'cuenta_ss_acreedores': fields.many2one('account.account', 'Cuenta Organismos de la S.S acreedores', required=True),
37
'cuenta_hacienda_publica': fields.many2one('account.account', 'Cuenta H.P acreedor por retenciones practicadas', required=True),
38
'cuenta_pendientes_pago': fields.many2one('account.account', 'Cuenta Remuneraciones pendientes de pago', required=True),
39
'cuenta_bancos': fields.many2one('account.account', 'Cuenta Bancos e instituciones de crédito', required=True),
40
'cuenta_anticipos': fields.many2one('account.account', 'Cuenta anticipos de remuneraciones', required=True),
45
def get_configuration(cr, uid, ids, context=None):
46
pool = pooler.get_pool(cr.dbname)
47
obj_user = pool.get('res.users').browse(cr, uid, uid)
48
obj_company = pool.get('res.company').browse(cr, uid, obj_user.company_id.id)
50
if obj_company.cuenta_ss_empresa:#Como las cuentas son obligatorias si esta definida esta cuenta estarán todas definidas
51
res['diario_destino'] = obj_company.diario_destino.id
52
res['cuenta_ss_empresa'] = obj_company.cuenta_ss_empresa.id
53
res['cuenta_ss_acreedores'] = obj_company.cuenta_ss_acreedores.id
54
res['cuenta_hacienda_publica'] = obj_company.cuenta_hacienda_publica.id
55
res['cuenta_pendientes_pago'] = obj_company.cuenta_pendientes_pago.id
56
res['cuenta_bancos'] = obj_company.cuenta_bancos.id
57
res['cuenta_anticipos'] = obj_company.cuenta_anticipos.id
60
company_name = str(obj_user.company_id.name)
61
raise osv.except_osv(_('No hay una configuración de cuentas activa para la compañia ') + company_name, _('Debe configurar las cuentas!\nPor favor configure las cuentas en el menú de configuración de la compañia: ') + company_name)
63
class hr_employee(osv.osv):
65
_inherit = 'hr.employee'
67
'retribucion_bruta': fields.float('Retribución Bruta', digits=(16, 2)),
68
'ss_empresa': fields.float('S.S a Cargo de la empresa', digits=(16, 2)),
69
'ss_trabajador': fields.float('S.S a cargo del Trabajador', digits=(16, 2)),
70
'irpf': fields.float('Retención IRPF (%)', digits=(16, 2)),
71
'retribucion_bruta_extra': fields.float('Retribución Bruta', digits=(16, 2)),
72
'ss_empresa_extra': fields.float('S.S a Cargo de la empresa', digits=(16, 2)),
73
'ss_trabajador_extra': fields.float('S.S a cargo del Trabajador', digits=(16, 2)),
74
'irpf_extra': fields.float('Retención IRPF (%)', digits=(16, 2)),
75
'nominas_ids': fields.one2many('hr.nomina', 'employee_id', 'Nóminas del Empleado', readonly=True),
76
'anticipos_ids': fields.one2many('hr.anticipo', 'employee_id', 'Anticipos del Empleado', readonly=True),
77
'cuenta_id': fields.many2one('account.account', 'Cuenta', required=True, help="El empleado debe tener una cuenta para su nómina."),
80
'cuenta_id': lambda * a: 377 or None,
86
class hr_nomina(osv.osv):
88
_description = 'Nominas de Empleados'
90
'name': fields.char('Nómina', size=20),
91
'employee_id': fields.many2one('hr.employee', 'Empleado', required=True, select="1"),
92
'retribucion_bruta': fields.float('Retribución Bruta', digits=(16, 2)),
93
'ss_empresa': fields.float('S.S a Cargo de la empresa', digits=(16, 2)),
94
'ss_trabajador': fields.float('S.S a cargo del Trabajador', digits=(16, 2)),
95
'irpf': fields.float('Retención IRPF (%)', digits=(16, 2)),
96
'fecha_nomina': fields.date('Fecha de la Nómina', select="1"),
97
'state': fields.selection((('borrador', 'Borrador'),
98
('confirmada', 'Confirmada'),
100
('cancelada', 'Cancelada')), 'Estado Nómina', readonly=True, select="2"),
101
'numero': fields.char('Número de nomina', size=32, readonly=True, help="Número único de nómina, se asigna automáticamente cuando se crea la nómina", select="1"),
102
'extra': fields.boolean('Paga Extra'),
103
'asiento_nomina_confirmada': fields.many2one('account.move', 'Asiento Nómina confirmada', readonly=True),
104
'asiento_nomina_pagada': fields.many2one('account.move', 'Asiento Nómina pagada', readonly=True),
108
'state': lambda * a:'borrador',
111
def comprueba_mes(self, fecha_anticipo, fecha_nomina):
112
anticipo = time.strptime(fecha_anticipo, '%Y-%m-%d')
113
nomina = time.strptime(fecha_nomina, '%Y-%m-%d')
114
dateNomina = datetime.datetime(nomina[0], nomina[1], nomina[2])
115
dateAnterior = time.strptime((dateNomina - datetime.timedelta(nomina[2] + 1)).strftime('%Y-%m-%d'), '%Y-%m-%d')
117
if (anticipo[0] == dateAnterior[0]) and (dateAnterior[1] == anticipo[1]): #Si se solicito anticipo el mes pasado
122
def comprueba_anticipo(self, cr, uid, ids, fechaNomina, empleado_id):
123
anticipo_ids = self.pool.get('hr.anticipo').search(cr, uid, [('employee_id', '=', empleado_id)])
124
for anticipo in anticipo_ids:
125
obj_anticipo = self.pool.get('hr.anticipo').browse(cr, uid, anticipo)
126
if self.comprueba_mes(obj_anticipo.fecha_anticipo, fechaNomina) and obj_anticipo.state == 'pagado':
127
return obj_anticipo.cantidad
131
def confirmar_nomina(self, cr, uid, ids, *args):
132
cuentas = get_configuration(cr, uid, ids)
133
for nom in self.browse(cr, uid, ids):
134
if nom.state != 'borrador':
136
journal_id = cuentas['diario_destino']
137
numero = self.pool.get('ir.sequence').get(cr, uid, 'hr.nomina')
138
journal = self.pool.get('account.journal').browse(cr, uid, journal_id)
139
fechaNomina = nom.fecha_nomina
142
period_ids = self.pool.get('account.period').search(cr, uid, [('date_start', '<=', fechaNomina or time.strftime('%Y-%m-%d')), ('date_stop', '>=', fechaNomina or time.strftime('%Y-%m-%d'))])
144
periodo_id = period_ids[0]
146
raise osv.except_osv(_('No existe un periodo para esa fecha de nomina!'), _('No se pueden generar nóminas cuya fecha esté en un periodo que no existe, \nsi desea generarla por favor cree el periodo contable correspondiente.'))
148
referencia = numero + ' : ' + nom.employee_id.name + ' - ' + fechaNomina
150
referencia = "Paga Extra: " + nom.employee_id.name + ' - ' + fechaNomina
151
move = {'ref': referencia, 'journal_id': journal_id, 'date': fechaNomina, 'period_id': periodo_id}
153
move_id = self.pool.get('account.move').create(cr, uid, move)
155
obj_linea = self.pool.get('account.move.line')
157
cuenta_id = nom.employee_id.cuenta_id.id
158
#si no tiene cuenta lanzamos un error
160
raise osv.except_osv(_('No existe una cuenta configurada para el empleado!'), _('Por favor configure una cuenta en la ficha del empleado en la que generar los asientos de la nómina.'))
161
retencion_irpf = (nom.retribucion_bruta * nom.irpf) / 100
162
anticipo = self.comprueba_anticipo(cr, uid, ids, fechaNomina, nom.employee_id.id)
164
sueldo_neto = nom.retribucion_bruta - retencion_irpf - nom.ss_trabajador
165
if anticipo and nom.extra == False:
166
sueldo_neto -= anticipo
167
obj_linea.create(cr, uid, {'account_id': cuentas['cuenta_anticipos'], 'move_id': move_id, 'journal_id': journal_id, 'period_id': periodo_id, 'name': 'Anticipo', 'credit': anticipo, 'ref': referencia})
169
obj_linea.create(cr, uid, {'account_id': cuenta_id, 'move_id': move_id, 'journal_id': journal_id, 'period_id': periodo_id, 'name': 'Sueldo Bruto', 'debit': nom.retribucion_bruta , 'ref': referencia})
170
obj_linea.create(cr, uid, {'account_id': cuentas['cuenta_ss_empresa'], 'move_id': move_id, 'journal_id': journal_id, 'period_id': periodo_id, 'name': 'S.S. Empresa', 'debit': nom.ss_empresa, 'ref': referencia})
171
obj_linea.create(cr, uid, {'account_id': cuentas['cuenta_hacienda_publica'], 'move_id': move_id, 'journal_id': journal_id, 'period_id': periodo_id, 'name': 'IRPF', 'credit': retencion_irpf, 'ref': referencia})
172
obj_linea.create(cr, uid, {'account_id': cuentas['cuenta_ss_acreedores'], 'move_id': move_id, 'journal_id': journal_id, 'period_id': periodo_id, 'name': 'S.S. Acreedores ', 'credit': nom.ss_trabajador + nom.ss_empresa, 'ref': referencia})
173
obj_linea.create(cr, uid, {'account_id': cuentas['cuenta_pendientes_pago'], 'move_id': move_id, 'journal_id': journal_id, 'period_id': periodo_id, 'name': 'Sueldo Neto', 'credit': sueldo_neto, 'ref': referencia})
175
self.pool.get('account.move').write(cr, uid, [move_id], {'date': fechaNomina})
176
self.pool.get('account.move').post(cr, uid, [move_id])
177
self.write(cr, uid, ids, {'numero': numero})
178
self.write(cr, uid, ids, {'state': 'confirmada', 'asiento_nomina_confirmada': move_id})
180
def pagar_nomina(self, cr, uid, ids, *args):
181
cuentas = get_configuration(cr, uid, ids)
182
for nom in self.browse(cr, uid, ids):
183
if nom.state != 'confirmada':
185
journal_id = cuentas['diario_destino']
186
journal = self.pool.get('account.journal').browse(cr, uid, journal_id)
187
fechaNomina = nom.fecha_nomina
190
period_ids = self.pool.get('account.period').search(cr, uid, [('date_start', '<=', fechaNomina or time.strftime('%Y-%m-%d')), ('date_stop', '>=', fechaNomina or time.strftime('%Y-%m-%d'))])
192
periodo_id = period_ids[0]
194
referencia = nom.numero + ' : Pago ' + nom.employee_id.name + ' - ' + fechaNomina
196
referencia = "Pago de Paga Extra: " + nom.employee_id.name + ' - ' + fechaNomina
197
move = {'ref': referencia, 'journal_id': journal_id, 'date': fechaNomina, 'period_id': periodo_id}
199
move_id = self.pool.get('account.move').create(cr, uid, move)
201
retencion_irpf = (nom.retribucion_bruta * nom.irpf) / 100
202
sueldo_neto = nom.retribucion_bruta - retencion_irpf - nom.ss_trabajador
203
anticipo = self.comprueba_anticipo(cr, uid, ids, fechaNomina, nom.employee_id.id)
204
if anticipo and nom.extra == False:
205
sueldo_neto -= anticipo
207
self.pool.get('account.move.line').create(cr, uid, {'account_id': cuentas['cuenta_bancos'], 'move_id': move_id, 'journal_id': journal_id, 'period_id': periodo_id, 'name': 'Banco', 'credit': sueldo_neto, 'ref': referencia})
208
self.pool.get('account.move.line').create(cr, uid, {'account_id': cuentas['cuenta_pendientes_pago'], 'move_id': move_id, 'journal_id': journal_id, 'period_id': periodo_id, 'name': 'Renumeraciones pendientes', 'debit': sueldo_neto, 'ref': referencia})
210
self.write(cr, uid, ids, {'state': 'pagada', 'asiento_nomina_pagada':move_id})
211
self.pool.get('account.move').write(cr, uid, [move_id], {'date': fechaNomina})
212
self.pool.get('account.move').post(cr, uid, [move_id])
214
def cancelar_nomina(self, cr, uid, ids, *args):
215
for nom in self.browse(cr, uid, ids):
216
acc_obj = self.pool.get('account.move')
217
if nom.state == 'confirmada':
218
acc_obj.button_cancel(cr, uid, [nom.asiento_nomina_confirmada.id])
219
self.write(cr, uid, ids, {'state': 'cancelada'})
223
class hr_anticipo(osv.osv):
224
_name = 'hr.anticipo'
225
_description = 'Anticipos de Nominas'
227
'name': fields.char('Anticipo', size=30),
228
'employee_id': fields.many2one('hr.employee', 'Empleado', required=True, select="1", readonly=True),
229
'fecha_anticipo': fields.date('Fecha de Anticipo', select="1", readonly=True),
230
'cantidad': fields.float('Cantidad Anticipo', digits=(16, 2), readonly=True),
231
'state': fields.selection((('borrador', 'Borrador'),
232
('confirmado', 'Confirmado'),
233
('pagado', 'Pagado'),
234
('cancelado', 'Cancelado')), 'Estado de anticipo', readonly=True, select="1"),
235
'asiento_anticipo': fields.many2one('account.move', 'Asiento Anticipo', readonly=True),
239
'state': lambda * a:'borrador',
242
def confirmar_anticipo(self, cr, uid, ids, *args):
243
cuentas = get_configuration(cr, uid, ids)
244
for anticipo in self.browse(cr, uid, ids):
245
if anticipo.state != 'borrador':
247
journal_id = cuentas['diario_destino']
248
journal = self.pool.get('account.journal').browse(cr, uid, journal_id)
249
fecha_anticipo = anticipo.fecha_anticipo
251
period_ids = self.pool.get('account.period').search(cr, uid, [('date_start', '<=', fecha_anticipo or time.strftime('%Y-%m-%d')), ('date_stop', '>=', fecha_anticipo or time.strftime('%Y-%m-%d'))])
253
periodo_id = period_ids[0]
254
referencia = 'Anticipo: ' + anticipo.employee_id.name + ' - ' + fecha_anticipo
255
move_id = self.pool.get('account.move').create(cr, uid, {'ref': referencia, 'journal_id': journal_id, 'date': fecha_anticipo, 'period_id': periodo_id })
256
self.pool.get('account.move.line').create(cr, uid, {'account_id': cuentas['cuenta_anticipos'], 'move_id': move_id, 'journal_id': journal_id, 'period_id': periodo_id, 'name': 'Anticipo', 'debit': anticipo.cantidad, 'ref': referencia})
257
self.pool.get('account.move.line').create(cr, uid, {'account_id': cuentas['cuenta_bancos'], 'move_id': move_id, 'journal_id': journal_id, 'period_id': periodo_id, 'name': 'Bancos', 'credit': anticipo.cantidad, 'ref': referencia})
258
self.write(cr, uid, ids, {'state': 'confirmado', 'asiento_anticipo': move_id})
259
self.pool.get('account.move').write(cr, uid, [move_id], {'date': fecha_anticipo})
261
def pagar_anticipo(self, cr, uid, ids, *args):
262
for ant in self.browse(cr, uid, ids):
263
if ant.state != 'confirmado':
265
acc_obj = self.pool.get('account.move')
266
acc_obj.post(cr, uid, [ant.asiento_anticipo.id])
267
self.write(cr, uid, ids, {'state':'pagado'})
269
def cancelar_anticipo(self, cr, uid, ids, *args):
270
for ant in self.browse(cr, uid, ids):
271
acc_obj = self.pool.get('account.move')
272
if ant.state == 'confirmado':
273
self.write(cr, uid, ids, {'state':'cancelado'})