~inddiana/sisb/sisb_caja_chica_cierre_comparar_plus_reposiciones

« back to all changes in this revision

Viewing changes to sisb_horas_extras/model/horas_extras.py

  • Committer: Aryrosa Fuentes
  • Date: 2017-10-20 14:03:01 UTC
  • mfrom: (975.2.9 sisb_061017)
  • Revision ID: afuentes@industriasdiana.gob.ve-20171020140301-8ra8dk3pfi1z841q

[MOD] Ajustes en las limitaciones para la asignación de sobretiempos.
[MOD] Corregida la manera en que se creaba el select del tipo de proceso.
[IMP] Agregado módulo para la carga de permisos.
[IMP] Agregado módulo para la carga automática de conceptos variables que
tengan que ver con los turnos.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/env python
2
2
# -*- coding: utf-8 -*-
3
3
 
4
 
from osv import fields, osv  
 
4
from osv import fields, osv
5
5
from tools.translate import _
6
6
import datetime
7
 
from datetime import  timedelta
 
7
from datetime import timedelta
8
8
from functools import wraps
9
 
            
 
9
 
 
10
 
10
11
class horas_extras_planificacion_tipos(osv.osv):
11
 
        
 
12
 
12
13
    _name = 'horas.extras.planificacion.tipos'
13
14
    _description = 'tipos de planificacion de sobretiempo'
14
15
    _rec_name = 'descripcion'
15
16
    _columns = {
16
 
    'name': fields.char('Motivo', size=60),
17
 
    'descripcion': fields.char('Descripcion', size=60),
18
 
    'parent_id': fields.many2one('horas.extras.planificacion.tipos', 'Padre Tipos', select=True),
19
 
    'child_ids': fields.one2many('horas.extras.planificacion.tipos', 'parent_id', 'tipos hijos'),
 
17
        'name': fields.char('Motivo', size=60),
 
18
        'descripcion': fields.char('Descripcion', size=60),
 
19
        'parent_id': fields.many2one('horas.extras.planificacion.tipos', 'Padre Tipos', select=True),
 
20
        'child_ids': fields.one2many('horas.extras.planificacion.tipos', 'parent_id', 'tipos hijos'),
20
21
    }
21
 
    
22
 
    _sql_constraints = [('unique_code','unique(name)', _('El parametro motivo debe ser unico'))]
23
 
     
24
 
horas_extras_planificacion_tipos()    
25
 
 
 
22
 
 
23
    _sql_constraints = [('unique_code', 'unique(name)', _('El parametro motivo debe ser unico'))]
 
24
 
 
25
 
 
26
horas_extras_planificacion_tipos()
26
27
 
27
28
 
28
29
class horas_extras_planificacion(osv.osv):
29
 
    
 
30
 
30
31
    _name = 'horas.extras.planificacion'
31
32
    _description = 'horas extras'
32
 
    _order='fecha desc'
 
33
    _order = 'fecha desc'
33
34
    _rec_name = 'referencia'
34
 
    
35
35
 
36
36
    def search_manager_department(self, cr, uid, emp_id):
37
37
        obj_employee = self.pool.get('hr.employee')
42
42
        for emp in department_brw:
43
43
            subordinado = [i.id for i in emp.member_ids]
44
44
        return subordinado
45
 
    
 
45
 
46
46
    def search_childs_department(self, cr, uid, emp_id):
47
47
        emp_ids = []
48
48
        sql = """
49
 
        select id from hr_employee 
 
49
        select id from hr_employee
50
50
            where department_id in (select id from (select distinct slh.id as child_id from hr_department slp
51
51
            left outer join hr_department slh on slh.parent_id between slp.id and slh.parent_id
52
52
            where slh.parent_id =%s) as hijos join hr_department as hrd ON hrd.id = hijos.child_id or hrd.parent_id = hijos.child_id
53
 
            or id = %s order by id asc) or (department_id = %s); 
 
53
            or id = %s order by id asc) or (department_id = %s);
54
54
        """
55
 
        
 
55
 
56
56
        obj_employee = self.pool.get('hr.employee')
57
57
        employee_brw = obj_employee.browse(cr, uid, emp_id)
58
58
        department_id = [i.department_id.id for i in employee_brw if i.job_id.type_job_id.autoriza_sobretiempo]
59
59
        if department_id:
60
 
           sql = sql%(department_id[0], department_id[0], department_id[0])
61
 
           cr.execute(sql)
62
 
           emp_ids = cr.fetchall()
63
 
           emp_ids = list(set([i for t in emp_ids for i in t]))
 
60
            sql = sql % (department_id[0], department_id[0], department_id[0])
 
61
            cr.execute(sql)
 
62
            emp_ids = cr.fetchall()
 
63
            emp_ids = list(set([i for t in emp_ids for i in t]))
64
64
        return emp_ids
65
 
    
 
65
 
66
66
    def validar_departamentos(self, cr, uid):
67
67
        departamento_id = self._get_department(cr, uid)
68
68
        ids = []
70
70
            sql = """
71
71
            select id from (select distinct slh.id as child_id from hr_department slp
72
72
            left outer join hr_department slh on slh.parent_id between slp.id and slh.parent_id
73
 
            where slh.parent_id =%s) as hijos join hr_department as hrd ON hrd.id = hijos.child_id 
 
73
            where slh.parent_id =%s) as hijos join hr_department as hrd ON hrd.id = hijos.child_id
74
74
            or hrd.parent_id = hijos.child_id
75
 
            """ %departamento_id   
 
75
            """ % departamento_id
76
76
            ids.append(departamento_id)
77
77
            cr.execute(sql)
78
78
            ids_fech = cr.fetchall()
79
79
            if ids:
80
80
                ids = ids + [id[0] for id in ids_fech]
81
 
                
 
81
 
82
82
        return ids
83
 
    
 
83
 
84
84
    def _get_trabajadores_nomina(self, cr, uid, group_name, param_nomina=None, context=None):
85
 
                if not param_nomina:
86
 
                   parameter_obj = self.pool.get('hr.parameters')
87
 
                   parameters_id = parameter_obj.search(cr, uid, [('type', '=', 'cargar_sobretiempos_nomina')])
88
 
                   if not parameters_id:
89
 
                          return False 
90
 
                   parameters_brw = parameter_obj.browse(cr, uid, parameters_id)[0]
91
 
                   param_nomina = parameters_brw.check_cargar_sobretiempos_nomina
92
 
                if param_nomina:
93
 
                        grupo = self._get_grupo_id(cr, uid, group_name)
94
 
                        if grupo:
95
 
                           grupos_usuario = self._get_grupos_usuario(cr, uid, context)
96
 
                           if grupo in grupos_usuario:
97
 
                                  return True
98
 
                return False   
99
 
                
 
85
        if not param_nomina:
 
86
            parameter_obj = self.pool.get('hr.parameters')
 
87
            parameters_id = parameter_obj.search(cr, uid, [('type', '=', 'cargar_sobretiempos_nomina')])
 
88
            if not parameters_id:
 
89
                return False
 
90
            parameters_brw = parameter_obj.browse(cr, uid, parameters_id)[0]
 
91
            param_nomina = parameters_brw.check_cargar_sobretiempos_nomina
 
92
        if param_nomina:
 
93
            grupo = self._get_grupo_id(cr, uid, group_name)
 
94
            if grupo:
 
95
                grupos_usuario = self._get_grupos_usuario(cr, uid, context)
 
96
                if grupo in grupos_usuario:
 
97
                    return True
 
98
        return False
 
99
 
100
100
    def _get_subordinados_ids(self, cr, uid, ids, field_name, arg, context):
101
101
        res = {}
102
102
        obj_employee = self.pool.get('hr.employee')
103
103
        obj_department = self.pool.get('hr.department')
104
104
        load_nom = self._get_trabajadores_nomina(cr, uid, 'group_sisb_horas_extras_th', param_nomina=None, context=None)
105
 
        params = [] if uid ==1 or load_nom  else [('user_id', '=', uid)]
 
105
        params = [] if uid == 1 or load_nom else [('user_id', '=', uid)]
106
106
        emp_id = obj_employee.search(cr, uid, params)
107
107
        subordinado = emp_id
108
 
        if  uid !=1 and not load_nom:
 
108
        if uid != 1 and not load_nom:
109
109
            busqueda_recursiva_emp = self.search_childs_department
110
110
            subordinado = subordinado + busqueda_recursiva_emp(cr, uid, emp_id)
111
111
        subordinado = list(set(subordinado))
112
112
        if emp_id:
113
 
           if emp_id[0] in subordinado:
114
 
              subordinado.remove(emp_id[0])
 
113
            if emp_id[0] in subordinado:
 
114
                subordinado.remove(emp_id[0])
115
115
        subordinado = str(subordinado)
116
116
        for i in ids:
117
117
            res[i] = subordinado
118
 
        return res 
119
 
        
 
118
        return res
 
119
 
120
120
    def _get_back_draft(self, cr, uid, ids, field_name, arg, context):
121
121
        res = {}
122
122
        brw = self.browse(cr, uid, ids)
123
123
        grupo = self._get_grupo_id(cr, uid, 'group_sisb_horas_extras_volver_borrador')
124
124
        grupos_usuario = self._get_grupos_usuario(cr, uid, context)
125
 
                           
 
125
 
126
126
        for i in brw:
127
 
            if (uid == 1 and i.state in ['confirmed','cancel', 'processing']) or (grupo in grupos_usuario and i.state in ['confirmed','cancel', 'processing']) or i.state == 'confirmed' :
128
 
               res[i.id] = True
 
127
            if (uid == 1 and i.state in ['confirmed', 'processing']) or (grupo in grupos_usuario and i.state in ['confirmed', 'processing']) or i.state == 'confirmed':
 
128
                res[i.id] = True
129
129
            else:
130
 
                res[i.id] = False 
131
 
        return res 
132
 
        
 
130
                res[i.id] = False
 
131
        return res
 
132
 
133
133
    def _get_department(self, cr, uid):
134
 
        res = False  
135
 
        if uid == 1: return res
 
134
        res = False
 
135
        if uid == 1:
 
136
            return res
136
137
        obj_employee = self.pool.get('hr.employee')
137
138
        params = [('user_id', '=', uid)]
138
139
        emp_id = obj_employee.search(cr, uid, params)
139
140
        emp_brw = obj_employee.browse(cr, uid, emp_id)
140
141
        if emp_brw:
141
 
           res =  emp_brw[0].department_id.id
 
142
            res = emp_brw[0].department_id.id
142
143
        else:
143
 
           raise osv.except_osv(_('Error'), _('El usuario conectado debe poseer un perfil asociado en Talento Humano'))
144
 
        return res 
145
 
    
 
144
            raise osv.except_osv(_('Error'), _('El usuario conectado debe poseer un perfil asociado en Talento Humano'))
 
145
        return res
 
146
 
146
147
    def _get_grupos_usuario(self, cr, uid, context=None):
147
148
        return [group.id for group in self.pool.get('res.users').browse(cr, uid, uid, context=None).groups_id]
148
 
    
 
149
 
149
150
    def _get_grupo_id(self, cr, uid, group_name, context=None):
150
151
        """Devuelve el id del grupo 'group_name'. Devuelve False en caso de no existir """
151
152
        model_data_obj = self.pool.get('ir.model.data')
152
 
        grupo_search =  model_data_obj.search(cr, 1, [('name','=',group_name),('model','=','res.groups')], context=None)
 
153
        grupo_search = model_data_obj.search(cr, 1, [('name', '=', group_name), ('model', '=', 'res.groups')], context=None)
153
154
        grupo = model_data_obj.read(cr, 1, grupo_search, ['res_id'], context)[0]['res_id']
154
155
        if grupo:
155
156
            return grupo
156
157
        return False
157
 
    
 
158
 
158
159
    _columns = {
159
 
    'name': fields.char('name', size=64),
160
 
    'user_id': fields.many2one('res.users',  'Usuario', readonly=True),
161
 
    'department_id':fields.many2one('hr.department',  'Departamento', readonly=True),
162
 
    'observacion': fields.text('Observacion'),
163
 
    'fecha': fields.date('Fecha', required=True, readonly=True),
164
 
    'referencia': fields.char('Referencia', size=64, required=True, readonly=True),
165
 
    'permitidos': fields.function(_get_subordinados_ids, string='Permitidos', method=True, type='text', store=False, ),
166
 
    'permitir_back_draf': fields.function(_get_back_draft, string='Volver a borrador', method=True, type='boolean', store=False),
167
 
    'state': fields.selection([('draft','Borrador'), ('confirmed','Confirmado'),('approved','Aprobado'), 
168
 
                                                            ('processing','Procesado'), ('exception','Excepcion'), ('load','Cargado'), 
169
 
                                                            ('done','Listo'), ('cancel','Cancelado')],'Estado', readonly=True),
170
 
    }       
171
 
    
172
 
    _defaults = { 
173
 
     'fecha': lambda *a : datetime.datetime.now().strftime("%Y-%m-%d"),
174
 
     'state': lambda *a : 'draft',
175
 
     'referencia': lambda *a: 'ST-#',
176
 
     'user_id': lambda self, cr, uid, context=None: uid,
177
 
     'department_id': lambda self, cr, uid, context=None: self._get_department(cr, uid)
178
 
    }
179
 
    
180
 
horas_extras_planificacion()    
181
 
    
182
 
            
 
160
        'name': fields.char('name', size=64),
 
161
        'user_id': fields.many2one('res.users', 'Usuario', readonly=True),
 
162
        'department_id': fields.many2one('hr.department', 'Departamento', readonly=True),
 
163
        'observacion': fields.text('Observacion'),
 
164
        'fecha': fields.date('Fecha', required=True, readonly=True),
 
165
        'referencia': fields.char('Referencia', size=64, required=True, readonly=True),
 
166
        'permitidos': fields.function(_get_subordinados_ids, string='Permitidos', method=True, type='text', store=False, ),
 
167
        'permitir_back_draf': fields.function(_get_back_draft, string='Volver a borrador', method=True, type='boolean', store=False),
 
168
        'state': fields.selection([('draft', 'Borrador'), ('confirmed', 'Confirmado'), ('approved', 'Aprobado'),
 
169
                                   ('processing', 'Procesado'), ('exception', 'Excepcion'), ('load', 'Cargado'),
 
170
                                   ('done', 'Listo'), ('cancel', 'Cancelado')], 'Estado', readonly=True),
 
171
    }
 
172
 
 
173
    _defaults = {
 
174
        'fecha': lambda *a: datetime.datetime.now().strftime("%Y-%m-%d"),
 
175
        'state': lambda *a: 'draft',
 
176
        'referencia': lambda *a: 'ST-#',
 
177
        'user_id': lambda self, cr, uid, context=None: uid,
 
178
        'department_id': lambda self, cr, uid, context=None: self._get_department(cr, uid)
 
179
    }
 
180
 
 
181
 
 
182
horas_extras_planificacion()
 
183
 
 
184
 
183
185
class horas_extras_planificacion_lineas(osv.osv):
184
 
    
 
186
 
185
187
    _name = 'horas.extras.planificacion.lineas'
186
188
    _description = 'Horas extras lineas'
187
 
    _order='id desc'
188
 
        
 
189
    _order = 'id desc'
 
190
 
189
191
    def _calc_turno(self, cr, uid, ids, field_name, args, context=None):
190
192
        res = {}
191
193
        brw = self.browse(cr, uid, ids, context=context)
193
195
        hsw_obj = self.pool.get('hr.shift.week')
194
196
        for i in brw:
195
197
            hsw_id = hsw_obj.search(cr, uid, [('employee_id', '=', i.empleado_id.id), ('period_id.date_start', '<=', i.fecha_desde), ('period_id.date_end', '>=', i.fecha_desde)], context=context)
196
 
            res[i.id] = hsw_obj.read(cr, uid, hsw_id, context=context)[0][days[datetime.datetime.strptime(i.fecha_desde, '%Y-%m-%d').weekday()]+'_hours_day_id'][1] if hsw_id else None
 
198
            res[i.id] = hsw_obj.read(cr, uid, hsw_id, context=context)[0][days[datetime.datetime.strptime(i.fecha_desde, '%Y-%m-%d').weekday()] + '_hours_day_id'][1] if hsw_id else None
197
199
        return res
198
 
    
 
200
 
199
201
    _columns = {
200
 
          'name': fields.char('Lineas de horas extras', size=64),
201
 
          'empleado_id': fields.many2one('hr.employee',  'Trabajador', required=True),
202
 
          'department_id':fields.related('empleado_id', 'department_id',  relation='hr.department', string="Departamento", 
203
 
            type='many2one', store=True, readonly=True, select=False),
204
 
          'fecha_desde': fields.date('Fecha desde', required=True),
205
 
          'fecha_hasta': fields.date('Fecha hasta', required=True),
206
 
          'hora_desde': fields.time('Hora desde', required=True),
207
 
          'hora_hasta': fields.time('Hora hasta', required=True),
208
 
          'serv_comida': fields.boolean('Servicio de comida'),
209
 
          'horas_extras_planificacion_id': fields.many2one('horas.extras.planificacion', 'Referencia', readonly=True),
210
 
          'motivo_id': fields.many2one('horas.extras.planificacion.tipos', 'Motivo', required=True),
211
 
          'excepciones': fields.boolean('excepciones'),
212
 
          'turno_id': fields.function(_calc_turno, method=True, string='Turno calculado', type='meny2one', relation='hr.hour.per.day'),
213
 
          'state': fields.selection([('draft','Borrador'), ('confirmed','Confirmado'),('approved','Aprobado'), 
214
 
                                                                         ('processing','Procesado'), ('exception','Excepcion'), ('load','Cargado'), ('done','Listo'), 
215
 
                                                                         ('cancel','Cancelado')],'Estado', readonly=True),
 
202
        'name': fields.char('Lineas de horas extras', size=64),
 
203
        'empleado_id': fields.many2one('hr.employee', 'Trabajador', required=True),
 
204
        'department_id': fields.related('empleado_id', 'department_id', relation='hr.department', string="Departamento",
 
205
                                        type='many2one', store=True, readonly=True, select=False),
 
206
        'fecha_desde': fields.date('Fecha desde', required=True),
 
207
        'fecha_hasta': fields.date('Fecha hasta', required=True),
 
208
        'hora_desde': fields.time('Hora desde', required=True),
 
209
        'hora_hasta': fields.time('Hora hasta', required=True),
 
210
        'horas_extras_planificacion_id': fields.many2one('horas.extras.planificacion', 'Referencia', readonly=True),
 
211
        'motivo_id': fields.many2one('horas.extras.planificacion.tipos', 'Motivo', required=True),
 
212
        'excepciones': fields.boolean('excepciones'),
 
213
        'turno_id': fields.function(_calc_turno, method=True, string='Turno calculado', type='meny2one', relation='hr.hour.per.day'),
 
214
        'state': fields.selection([('draft', 'Borrador'), ('confirmed', 'Confirmado'), ('approved', 'Aprobado'),
 
215
                                   ('processing', 'Procesado'), ('exception', 'Excepcion'), ('exceed', 'Excedido'), ('load', 'Cargado'), ('done', 'Listo'),
 
216
                                   ('cancel', 'Cancelado')], 'Estado', readonly=True),
 
217
        'exceed': fields.boolean("Excedido")
216
218
    }
217
 
    _defaults = { 
218
 
     'state': lambda *a : 'draft',
219
 
     'excepciones': lambda *a: False,
220
 
     'serv_comida': lambda *a: False,
 
219
    _defaults = {
 
220
        'state': lambda *a: 'draft',
 
221
        'excepciones': lambda *a: False,
 
222
        'exceed': False
221
223
    }
222
224
 
223
225
    def _check_hour(self, cr, uid, ids, conetxt=None):
224
226
        convert_datetime = self.convert_datetime
225
227
        hel_brw = self.browse(cr, uid, ids)
226
228
        for i in hel_brw:
227
 
                        fecha_desde = "%s %s"%(i.fecha_desde, i.hora_desde)
228
 
                        fecha_hasta = "%s %s"%(i.fecha_hasta, i.hora_hasta)
229
 
                        if fecha_desde and fecha_hasta:
230
 
                           hora_inicio =convert_datetime(fecha_desde, tipo='object')
231
 
                           hora_fin = convert_datetime(fecha_hasta, tipo='object')
232
 
                           if hora_fin <= hora_inicio:
233
 
                                  return False
234
 
        return True   
235
 
          
 
229
            fecha_desde = "%s %s" % (i.fecha_desde, i.hora_desde)
 
230
            fecha_hasta = "%s %s" % (i.fecha_hasta, i.hora_hasta)
 
231
            if fecha_desde and fecha_hasta:
 
232
                hora_inicio = convert_datetime(fecha_desde, tipo='object')
 
233
                hora_fin = convert_datetime(fecha_hasta, tipo='object')
 
234
                if hora_fin <= hora_inicio:
 
235
                    return False
 
236
        return True
 
237
 
236
238
    def _check_24(self, cr, uid, ids, conetxt=None):
237
239
        hel_brw = self.browse(cr, uid, ids)
238
240
        convert_datetime = self.convert_datetime
239
241
        for i in hel_brw:
240
 
                        fecha_desde = "%s %s"%(i.fecha_desde, i.hora_desde)
241
 
                        fecha_hasta = "%s %s"%(i.fecha_hasta, i.hora_hasta)
242
 
                        if fecha_desde and fecha_hasta:
243
 
                           hora_inicio = convert_datetime(fecha_desde, tipo='object')
244
 
                           hora_fin = convert_datetime(fecha_hasta, tipo='object')
245
 
                           total_horas = abs(hora_fin - hora_inicio)
246
 
                           days = total_horas.days * 24
247
 
                           hours = total_horas.seconds / 3600.0 
248
 
                           total = days + hours
249
 
                           if total > 24.0:
250
 
                                  return False
251
 
        return True     
252
 
        
 
242
            fecha_desde = "%s %s" % (i.fecha_desde, i.hora_desde)
 
243
            fecha_hasta = "%s %s" % (i.fecha_hasta, i.hora_hasta)
 
244
            if fecha_desde and fecha_hasta:
 
245
                hora_inicio = convert_datetime(fecha_desde, tipo='object')
 
246
                hora_fin = convert_datetime(fecha_hasta, tipo='object')
 
247
                total_horas = abs(hora_fin - hora_inicio)
 
248
                days = total_horas.days * 24
 
249
                hours = total_horas.seconds / 3600.0
 
250
                total = days + hours
 
251
                if total > 24.0:
 
252
                    return False
 
253
        return True
 
254
 
253
255
    def _check_last_hour(self, cr, uid, ids, context=None):
254
256
        hel_brw = self.browse(cr, uid, ids)
255
257
        convert_datetime = self.convert_datetime
256
258
        now = datetime.datetime.now()
257
259
        last = now - timedelta(days=1)
258
260
        for i in hel_brw:
259
 
                        fecha_desde = "%s %s"%(i.fecha_desde, i.hora_desde)
260
 
                        fecha_hasta = "%s %s"%(i.fecha_hasta, i.hora_hasta)
261
 
                        if fecha_desde and fecha_hasta:
262
 
                           hora_inicio = convert_datetime(fecha_desde, tipo='object')
263
 
                           hora_fin = convert_datetime(fecha_hasta, tipo='object')
264
 
                           if hora_inicio > last and hora_fin > now:
265
 
                                   return False
266
 
        return True     
267
 
    
268
 
    _constraints = [(_check_hour,'La Hora final del sobretiempo no puede ser menor o igual a la hora de inicio', ['hora_hasta']), 
269
 
                                        (_check_24,'Las lineas de sobretiempos no puede ser mayor de 24 horas', ['hora_hasta']),
270
 
                                        (_check_last_hour,'Las lineas de sobretiempos no puede ser mayor a la fecha actual', ['hora_hasta']),]
271
 
   
272
 
    
 
261
            fecha_desde = "%s %s" % (i.fecha_desde, i.hora_desde)
 
262
            fecha_hasta = "%s %s" % (i.fecha_hasta, i.hora_hasta)
 
263
            if fecha_desde and fecha_hasta:
 
264
                hora_inicio = convert_datetime(fecha_desde, tipo='object')
 
265
                hora_fin = convert_datetime(fecha_hasta, tipo='object')
 
266
                if hora_inicio > last and hora_fin > now:
 
267
                    return False
 
268
        return True
 
269
 
 
270
    _constraints = [(_check_hour, 'La Hora final del sobretiempo no puede ser menor o igual a la hora de inicio', ['hora_hasta']),
 
271
                    (_check_24, 'Las lineas de sobretiempos no puede ser mayor de 24 horas', ['hora_hasta']),
 
272
                    (_check_last_hour, 'Las lineas de sobretiempos no puede ser mayor a la fecha actual', ['hora_hasta']), ]
 
273
 
273
274
    def onchange_fecha(self, cr, uid, ids, fecha_desde):
274
275
        result = {}
275
276
        if not ids:
276
 
                   result = {'value': {'fecha_hasta':fecha_desde}}
 
277
            result = {'value': {'fecha_hasta': fecha_desde}}
277
278
        return result
278
 
        
 
279
 
279
280
    def onchange_hora(self, cr, uid, ids, hora_desde):
280
281
        result = {}
281
282
        if not ids:
282
 
                        result = {'value': {'hora_hasta':hora_desde}}
 
283
            result = {'value': {'hora_hasta': hora_desde}}
283
284
        return result
284
 
    
 
285
 
285
286
    def convert_datetime(self, value_date, tipo='object', format_inp=None):
286
 
                if not format_inp:
287
 
                   format_inp = "%Y-%m-%d %H:%M:%S"
288
 
                value_date = datetime.datetime.strptime(value_date, format_inp)
289
 
                d = {'date':value_date.strftime("%Y-%m-%d"),
290
 
                        'time':value_date.strftime("%H:%M:%S"), 
291
 
                        'object': value_date}
292
 
                return d[tipo]
293
 
        
294
 
    def _validate_hour_lines(self,cr, uid, ids, emp_id, fecha_desde, fecha_hasta, hora_desde, hora_hasta):
295
 
        date_desde = "%s %s"%(fecha_desde, hora_desde) 
296
 
        date_hasta = "%s %s"%(fecha_hasta, hora_hasta) 
 
287
        if not format_inp:
 
288
            format_inp = "%Y-%m-%d %H:%M:%S"
 
289
        value_date = datetime.datetime.strptime(value_date, format_inp)
 
290
        d = {'date': value_date.strftime("%Y-%m-%d"),
 
291
             'time': value_date.strftime("%H:%M:%S"),
 
292
             'object': value_date}
 
293
        return d[tipo]
 
294
 
 
295
    def _validate_hour_lines(self, cr, uid, ids, emp_id, fecha_desde, fecha_hasta, hora_desde, hora_hasta):
 
296
        date_desde = "%s %s" % (fecha_desde, hora_desde)
 
297
        date_hasta = "%s %s" % (fecha_hasta, hora_hasta)
297
298
        sql = """
298
299
             select id from
299
 
                (select id, fecha_desde + hora_desde as date_desde, fecha_hasta + hora_hasta as date_hasta  
300
 
                from horas_extras_planificacion_lineas 
 
300
                (select id, fecha_desde + hora_desde as date_desde, fecha_hasta + hora_hasta as date_hasta
 
301
                from horas_extras_planificacion_lineas
301
302
                where empleado_id = %s) as hxl
302
 
            where (('%s' BETWEEN  hxl.date_desde and hxl.date_hasta) 
303
 
            or ('%s' BETWEEN  hxl.date_desde and hxl.date_hasta))  
304
 
            and hxl.id != %s    
305
 
            """%(emp_id,date_desde,date_hasta, ids)
 
303
            where (('%s' BETWEEN  hxl.date_desde and hxl.date_hasta)
 
304
            or ('%s' BETWEEN  hxl.date_desde and hxl.date_hasta))
 
305
            and hxl.id != %s
 
306
            """ % (emp_id, date_desde, date_hasta, ids)
306
307
        cr.execute(sql)
307
308
        validar = cr.fetchall()
308
309
        validar = [t for i in validar for t in i]
310
311
            brw = self.browse(cr, uid, validar)[0]
311
312
            msg = """
312
313
                 Las horas del trabajador %s coinciden con un registro anterior
313
 
                 """%brw.empleado_id.name 
 
314
                 """ % brw.empleado_id.name
314
315
            raise osv.except_osv(_('Error'), _(msg))
315
 
        return True 
316
 
    
317
 
    def _check_nomina(self, cr, uid, ids, emp_id,  conetxt=None):
 
316
        return True
 
317
 
 
318
    def _check_nomina(self, cr, uid, ids, emp_id, conetxt=None):
318
319
        hel_obj = self.pool.get('horas.extras.planificacion.lineas')
319
320
        emp_obj = self.pool.get('hr.employee')
320
321
        emp_brw = emp_obj.browse(cr, uid, emp_id)
322
323
        nomina_emp = emp_brw.hr_payroll_id.id
323
324
        for i in hel_brw:
324
325
            if nomina_emp != i.empleado_id.hr_payroll_id.id:
325
 
                return False                    
326
 
        return True 
327
 
 
328
 
    def create(self, cr, uid, vals, context=None):
329
 
        emp_id = vals['empleado_id']
330
 
        horas_extras_planificacion_id = vals['horas_extras_planificacion_id']
 
326
                return False
 
327
        return True
 
328
 
 
329
    def diff_hours(self, hour_start, hour_end):
 
330
        hd = datetime.datetime.strptime(hour_start, '%H:%M:%S')
 
331
        hh = datetime.datetime.strptime(hour_end, '%H:%M:%S')
 
332
        return (hh - hd).seconds / float(3600)
 
333
 
 
334
    def validate_lines(self, cr, uid, vals, cid=0, context=None):
 
335
        emp_id = vals['empleado_id'] if type(vals['empleado_id']) == int else vals.empleado_id.id
 
336
        horas_extras_planificacion_id = vals['horas_extras_planificacion_id'] if type(vals['horas_extras_planificacion_id']) == int else vals.horas_extras_planificacion_id.id
331
337
        fecha_desde = vals['fecha_desde']
332
338
        fecha_hasta = vals['fecha_hasta']
333
339
        hora_desde = vals['hora_desde']
334
 
        hora_hasta = vals['hora_hasta']        
335
 
        lines_ids = self.pool.get('horas.extras.planificacion.lineas').search(cr, uid, [('horas_extras_planificacion_id','=',vals['horas_extras_planificacion_id'])])   
 
340
        hora_hasta = vals['hora_hasta']
 
341
        dept_obj = self.pool.get('hr.employee').browse(cr, uid, emp_id, context=context).department_id
 
342
        # Validando que no exceda de las horas diarias permitidas por el departamento
 
343
        week_lines = self.search(cr, uid, ['&', '&', '&', '|', ('state', 'not in', ['draft', 'cancel']), ('horas_extras_planificacion_id', '=', horas_extras_planificacion_id), ('fecha_desde', '=', fecha_desde), ('empleado_id', '=', emp_id), ('id', '!=', cid)], context=context)
 
344
        sum_hours = sum(self.diff_hours(l.hora_desde, l.hora_hasta) for l in self.browse(cr, uid, week_lines, context=context))
 
345
        if sum_hours + self.diff_hours(hora_desde, hora_hasta) > dept_obj.hours_per_day:
 
346
            return False
 
347
        # Validando que no pase de las horas semanales permitidas por el departamento
 
348
        day = datetime.datetime.strptime(fecha_desde, '%Y-%m-%d')
 
349
        weekstart = day - timedelta(days=day.weekday())
 
350
        weekend = day + timedelta(days=6 - day.weekday())
 
351
        week_lines = self.search(cr, uid, ['&', '&', '&', '&', '|', ('state', 'not in', ['draft', 'cancel']), ('horas_extras_planificacion_id', '=', horas_extras_planificacion_id), ('fecha_desde', '>=', weekstart.strftime('%Y-%m-%d')), ('fecha_desde', '<=', weekend.strftime('%Y-%m-%d')), ('empleado_id', '=', emp_id), ('id', '!=', cid)], context=context)
 
352
        sum_hours = sum(self.diff_hours(l.hora_desde, l.hora_hasta) for l in self.browse(cr, uid, week_lines, context=context))
 
353
        if sum_hours + self.diff_hours(hora_desde, hora_hasta) > dept_obj.hours_per_week:
 
354
            return False
 
355
        # Validando que no exceda de las horas mensuales para todos los trabajadores del departamento
 
356
        monthstart = day - timedelta(days=day.day - 1)
 
357
        next_month = day.replace(day=28) + timedelta(days=4)
 
358
        monthend = next_month - timedelta(days=next_month.day)
 
359
        while dept_obj:  # Iterando por cada departamento, desde el actual hasta sus padres
 
360
            depts_ids = pending_ids = dept_obj.child_ids
 
361
            while pending_ids:  # Haciendo la búsqueda hacia sus hijos
 
362
                pending_ids = reduce(lambda x, y: x + y, [c.child_ids for c in pending_ids], [])
 
363
                depts_ids += pending_ids
 
364
            depts_ids = [i.id for i in depts_ids] + [dept_obj.id]
 
365
            week_lines = self.search(cr, uid, ['&', '&', '&', '&', '|', ('state', 'not in', ['draft', 'cancel']), ('horas_extras_planificacion_id', '=', horas_extras_planificacion_id), ('fecha_desde', '>=', monthstart.strftime('%Y-%m-%d')), ('fecha_desde', '<=', monthend.strftime('%Y-%m-%d')), ('empleado_id.department_id', 'in', depts_ids), ('id', '!=', cid)], context=context)
 
366
            sum_hours = sum(self.diff_hours(l.hora_desde, l.hora_hasta) for l in self.browse(cr, uid, week_lines, context=context))
 
367
            if sum_hours + self.diff_hours(hora_desde, hora_hasta) > dept_obj.hours_per_dept:
 
368
                return False
 
369
            else:
 
370
                dept_obj = dept_obj.parent_id
 
371
        return True
 
372
 
 
373
    def create(self, cr, uid, vals, context=None):
 
374
        lines_ids = self.search(cr, uid, [('horas_extras_planificacion_id', '=', vals['horas_extras_planificacion_id'])])
336
375
        if lines_ids:
337
376
            check_nomina = self._check_nomina(cr, uid, lines_ids, vals['empleado_id'])
338
377
            if not check_nomina:
339
 
               raise osv.except_osv(_('Error'), _('Los trabajadores deben pertenecer a una misma nomina por hoja'))
340
 
        return super(horas_extras_planificacion_lineas, self).create(cr, uid, vals, context=None)    
 
378
                raise osv.except_osv(_('Error'), _('Los trabajadores deben pertenecer a una misma nomina por hoja'))
 
379
        return super(horas_extras_planificacion_lineas, self).create(cr, uid, vals, context=context)
 
380
 
 
381
    def write(self, cr, uid, ids, vals, context=None):
 
382
        ids = [ids] if type(ids) != list else ids
 
383
        for record in self.browse(cr, uid, ids, context=context):
 
384
            lines_ids = self.search(cr, uid, [('horas_extras_planificacion_id', '=', record.horas_extras_planificacion_id.id)])
 
385
            if lines_ids:
 
386
                check_nomina = self._check_nomina(cr, uid, lines_ids, record.empleado_id.id)
 
387
                if not check_nomina:
 
388
                    raise osv.except_osv(_('Error'), _('Los trabajadores deben pertenecer a una misma nomina por hoja'))
 
389
            super(horas_extras_planificacion_lineas, self).write(cr, uid, record.id, vals, context=context)
 
390
        return True
341
391
 
342
392
    def copy(self, cr, uid, id, default=None, context=None):
343
393
        raise osv.except_osv(_('Accion no permitida!'), _('No se pueden duplicar las lineas de sobretiempos'))
348
398
        if not isinstance(ids, list):
349
399
            ids = [ids]
350
400
        brw = self.browse(cr, uid, ids)
351
 
        load_nom = self.pool.get('horas.extras.planificacion')._get_trabajadores_nomina(cr, uid, 'group_sisb_horas_extras_th', param_nomina=False) 
 
401
        load_nom = self.pool.get('horas.extras.planificacion')._get_trabajadores_nomina(cr, uid, 'group_sisb_horas_extras_th', param_nomina=False)
352
402
        if uid != 1 and not load_nom:
353
 
            if not reduce(lambda x,y: x and y, map(lambda x: x.horas_extras_planificacion_id.user_id.id == uid, brw)):
354
 
               raise osv.except_osv(_('Error'), _('No cuenta con los permisos para borrar lineas a este documento'))
 
403
            if not reduce(lambda x, y: x and y, map(lambda x: x.horas_extras_planificacion_id.user_id.id == uid, brw)):
 
404
                raise osv.except_osv(_('Error'), _('No cuenta con los permisos para borrar lineas a este documento'))
355
405
        return super(horas_extras_planificacion_lineas, self).unlink(cr, uid, ids, context=context)
356
406
 
 
407
 
357
408
horas_extras_planificacion_lineas()
358
409
 
 
410
 
359
411
class horas_extras_planificacion_calculos(osv.osv):
360
 
    
 
412
 
361
413
    _name = 'horas.extras.planificacion.calculos'
362
414
    _description = 'Historico de horas extras'
363
415
    _columns = {
364
 
    'trabajador_id': fields.many2one('hr.employee', 'Trabajador', readonly=True),
365
 
    'horas_extras_planificacion_id': fields.many2one('horas.extras.planificacion', 'Planificacion de horas extras lineas', readonly=True),
366
 
    'value': fields.float('Cantidad', readonly=True),
367
 
    'concept_id': fields.many2one('hr.concept', 'Concepto', readonly=True), 
 
416
        'trabajador_id': fields.many2one('hr.employee', 'Trabajador', readonly=True),
 
417
        'horas_extras_planificacion_id': fields.many2one('horas.extras.planificacion', 'Planificacion de horas extras lineas', readonly=True),
 
418
        'value': fields.float('Cantidad', readonly=True),
 
419
        'concept_id': fields.many2one('hr.concept', 'Concepto', readonly=True),
368
420
    }
369
 
    
 
421
 
 
422
 
370
423
horas_extras_planificacion_calculos()
371
424
 
 
425
 
372
426
class horas_extras_planificacion(osv.osv):
373
427
    _inherit = 'horas.extras.planificacion'
374
 
    
 
428
 
375
429
    def _nota_nomina_editable(self, cr, uid, ids, name, args, context=None):
376
430
        res = {}
377
 
        grupo = self._get_grupo_id(cr, uid,'group_hr_user')
 
431
        grupo = self._get_grupo_id(cr, uid, 'group_hr_user')
378
432
        if grupo:
379
433
            grupos_usuario = self._get_grupos_usuario(cr, uid, context)
380
434
            horas_extras_brw = self.browse(cr, uid, ids[0])
383
437
                    res[line.horas_extras_planificacion_id.id] = True
384
438
                else:
385
439
                    res[line.horas_extras_planificacion_id.id] = False
386
 
            
 
440
 
387
441
        return res
388
 
        
 
442
 
389
443
    _columns = {
390
 
         'planificacion_lineas_ids': fields.one2many('horas.extras.planificacion.lineas', 'horas_extras_planificacion_id', 'Lineas de sobretiempos'),
391
 
         'calculos_ids': fields.one2many('horas.extras.planificacion.calculos', 'horas_extras_planificacion_id', 'Calculos de sobretiempos'),            
392
 
         'variable_concept_id': fields.many2one('hr.variable.concepts', 'Concepto variable', readonly=True),    
393
 
         'nota_nomina': fields.text('Nota de nomina'),
394
 
                 'nota_nomina_editable': fields.function(_nota_nomina_editable, method=True, string='¿Es editable?', type='boolean'),                    
 
444
        'planificacion_lineas_ids': fields.one2many('horas.extras.planificacion.lineas', 'horas_extras_planificacion_id', 'Lineas de sobretiempos'),
 
445
        'calculos_ids': fields.one2many('horas.extras.planificacion.calculos', 'horas_extras_planificacion_id', 'Calculos de sobretiempos'),
 
446
        'variable_concept_id': fields.many2one('hr.variable.concepts', 'Concepto variable', readonly=True),
 
447
        'nota_nomina': fields.text('Nota de nomina'),
 
448
        'nota_nomina_editable': fields.function(_nota_nomina_editable, method=True, string='¿Es editable?', type='boolean'),
395
449
    }
396
450
 
 
451
    def check_lines(self, cr, uid, ids, context=None):
 
452
        validar = self.pool.get('horas.extras.planificacion.lineas').validate_lines
 
453
        for record in self.browse(cr, uid, ids, context=context):
 
454
            for line in record.planificacion_lineas_ids:
 
455
                self.write(cr, uid, record.id, {'planificacion_lineas_ids': [(1, line.id, {'exceed': not validar(cr, uid, line, cid=line.id, context=context)})]}, context=context)
 
456
        return True
 
457
 
397
458
    def validate_doc(func):
398
459
        @wraps(func)
399
 
        def wraper(*args,**kargs):
 
460
        def wraper(*args, **kargs):
400
461
            proccess_name = 'confirmar' if func.__name__ == 'confirmed' else 'aprobar' if func.__name__ == 'approved' else 'cargar'
401
462
            self, cr, uid, ids, context = args
402
463
            today = datetime.datetime.now().strftime('%Y-%m-%d')
408
469
                    if not period:
409
470
                        raise osv.except_osv(_('Error'), _('No existe periodo creado en Talento Humano para el dia actual'))
410
471
                    if line.fecha_hasta >= period.date_start:
411
 
                        raise osv.except_osv(_('Error'), _('No se puede %s sobretiempo al empleado %s en el periodo actual de la nomina')%(proccess_name, line.empleado_id.name))
 
472
                        raise osv.except_osv(_('Error'), _('No se puede %s sobretiempo al empleado %s en el periodo actual de la nomina') % (proccess_name, line.empleado_id.name))
412
473
                    if datetime.datetime.strptime(period.date_start, '%Y-%m-%d') - timedelta(days=allowed_days) > datetime.datetime.strptime(line.fecha_desde, '%Y-%m-%d'):
413
 
                        raise osv.except_osv(_('Error'), _('No se puede %s sobretiempo al empleado %s porque ha excedido el periodo permitido por nomina')%(proccess_name, line.empleado_id.name))
414
 
            func(*args,**kargs)
 
474
                        raise osv.except_osv(_('Error'), _('No se puede %s sobretiempo al empleado %s fuera de los periodos configurados por nomina') % (proccess_name, line.empleado_id.name))
 
475
            return func(*args, **kargs)
415
476
        return wraper
416
 
  
 
477
 
417
478
    @validate_doc
418
 
    def confirmed(self, cr, uid, ids, context = None):
 
479
    def confirmed(self, cr, uid, ids, context=None):
 
480
        validar = self.pool.get('horas.extras.planificacion.lineas').validate_lines
419
481
        #  Validando que no vaya a saltar el flujo
420
482
        if not isinstance(ids, list):
421
483
            ids = [ids]
422
 
        for record in self.browse(cr,uid,ids):
423
 
            if record.state != 'draft': return False
424
 
        #Fin de la validacion
425
 
        lines_obj =  self.pool.get('horas.extras.planificacion.lineas')
426
 
        lines_id = lines_obj.search(cr, uid, [('horas_extras_planificacion_id','=',ids)])
 
484
        for record in self.browse(cr, uid, ids):
 
485
            if record.state != 'draft':
 
486
                return False
 
487
        # Fin de la validacion
 
488
        group_id = self.pool.get('ir.model.data').search(cr, uid, [('name', '=', 'group_sisb_horas_extras_autoriza_exceso')])
 
489
        group_id = self.pool.get('ir.model.data').browse(cr, uid, group_id[0]).res_id
 
490
        autoriza = True if group_id in map(int, self.pool.get('res.users').browse(cr, uid, uid).groups_id) else False
 
491
 
 
492
        lines_obj = self.pool.get('horas.extras.planificacion.lineas')
 
493
        lines_id = lines_obj.search(cr, uid, [('horas_extras_planificacion_id', '=', ids)])
427
494
        line_brw = lines_obj.browse(cr, uid, lines_id)
428
495
        if not line_brw:
429
 
           raise osv.except_osv(_('Error'), _('No hay lineas cargadas'))
 
496
            raise osv.except_osv(_('Error'), _('No hay lineas cargadas'))
430
497
        for i in line_brw:
431
498
            emp_id = i.empleado_id.id
432
 
            fecha_desde=i.fecha_desde
433
 
            fecha_hasta=i.fecha_hasta
434
 
            hora_desde=i.hora_desde
435
 
            hora_hasta=i.hora_hasta
 
499
            fecha_desde = i.fecha_desde
 
500
            fecha_hasta = i.fecha_hasta
 
501
            hora_desde = i.hora_desde
 
502
            hora_hasta = i.hora_hasta
436
503
            lines_obj._validate_hour_lines(cr, uid, i.id, emp_id, fecha_desde, fecha_hasta, hora_desde, hora_hasta)
 
504
            if not validar(cr, uid, i, cid=i.id, context=context):
 
505
                if autoriza:
 
506
                    lines_obj.log(cr, uid, i.id, 'Se autorizo sobretiempo con exceso a %s (%s) desde %s %s hasta %s %s' % (i.empleado_id.name, i.empleado_id.cod_number, i.fecha_desde, i.hora_desde, i.fecha_hasta, i.hora_hasta))
 
507
                else:
 
508
                    raise osv.except_osv(_('Error'), _('No se puede confirmar sobretiempo al empleado %s porque ha excedido las horas permitidas') % i.empleado_id.name)
437
509
        vals = {'state': 'confirmed'}
438
510
        if self.browse(cr, uid, ids[0]).referencia == 'ST-#':
439
511
            vals.update({'referencia': self.pool.get('ir.sequence').get(cr, uid, 'sobretiempos_tseq')})
440
512
        self.write(cr, uid, ids, vals)
441
 
        self.write_state_lines(cr, uid, ids,'confirmed')
 
513
        self.write_state_lines(cr, uid, ids, 'confirmed')
 
514
        lines_obj.write(cr, uid, lines_id, {'exceed': False}, context=context)
442
515
        return True
443
 
    
444
 
    def write_state_lines(self, cr ,uid, ids, state, lines=None, field=None):
 
516
 
 
517
    def write_state_lines(self, cr, uid, ids, state, lines=None, field=None):
445
518
        horas_extras_lines_obj = self.pool.get('horas.extras.planificacion.lineas')
446
519
        brw = self.browse(cr, uid, ids)[0]
447
520
        if not lines:
448
 
           lines = [obj.id for obj in brw.planificacion_lineas_ids]
 
521
            lines = [obj.id for obj in brw.planificacion_lineas_ids]
449
522
        if not field:
450
523
            field = 'state'
451
 
        write_id = horas_extras_lines_obj.write(cr, uid, lines, {field:state})
 
524
        write_id = horas_extras_lines_obj.write(cr, uid, lines, {field: state})
452
525
        return write_id
453
 
                
454
 
    def back_draft(self, cr, uid, ids, context = None):
 
526
 
 
527
    def back_draft(self, cr, uid, ids, context=None):
455
528
        #  Validando que no vaya a saltar el flujo
456
529
        if not isinstance(ids, list):
457
530
            ids = [ids]
458
 
        for record in self.browse(cr,uid,ids):
459
 
            if record.state not in ['confirmed', 'processing']: return False
460
 
        #Fin de la validacion
 
531
        for record in self.browse(cr, uid, ids):
 
532
            if record.state not in ['confirmed', 'processing']:
 
533
                return False
 
534
        # Fin de la validacion
461
535
        self.write(cr, uid, ids, {'state': 'draft'})
462
 
        self.write_state_lines(cr, uid, ids,'draft')
 
536
        self.write_state_lines(cr, uid, ids, 'draft')
463
537
        horas_extras_calc_obj = self.pool.get('horas.extras.planificacion.calculos')
464
 
        calc_ids = horas_extras_calc_obj.search(cr, uid, [('horas_extras_planificacion_id','in',ids)])
 
538
        calc_ids = horas_extras_calc_obj.search(cr, uid, [('horas_extras_planificacion_id', 'in', ids)])
465
539
        if calc_ids:
466
 
           horas_extras_calc_obj.unlink(cr, uid, calc_ids)
 
540
            horas_extras_calc_obj.unlink(cr, uid, calc_ids)
467
541
        return True
468
542
 
469
 
    def cancel(self, cr, uid, ids, context = None):
 
543
    def cancel(self, cr, uid, ids, context=None):
470
544
        for i in self.browse(cr, uid, ids):
471
 
                        if not i.nota_nomina:
472
 
                           raise osv.except_osv(_('Error'), _('Debe colocar una observacion para poder cancelar la hoja de sobretiempo'))
 
545
            if not i.nota_nomina:
 
546
                raise osv.except_osv(_('Error'), _('Debe colocar una observacion para poder cancelar la hoja de sobretiempo'))
473
547
        self.write(cr, uid, ids, {'state': 'cancel'})
474
 
        self.write_state_lines(cr, uid, ids,'cancel')
 
548
        self.write_state_lines(cr, uid, ids, 'cancel')
475
549
        return True
476
 
        
 
550
 
477
551
    @validate_doc
478
 
    def approved(self, cr, uid, ids, context = None):
 
552
    def approved(self, cr, uid, ids, context=None):
479
553
        #  Validando que no vaya a saltar el flujo
480
554
        if not isinstance(ids, list):
481
555
            ids = [ids]
482
 
        for record in self.browse(cr,uid,ids):
483
 
            if record.state != 'confirmed': return False
484
 
        #Fin de la validacion
 
556
        for record in self.browse(cr, uid, ids):
 
557
            if record.state != 'confirmed':
 
558
                return False
 
559
        # Fin de la validacion
485
560
        self.write(cr, uid, ids, {'state': 'approved'})
486
 
        self.write_state_lines(cr, uid, ids,'approved')
 
561
        self.write_state_lines(cr, uid, ids, 'approved')
487
562
        return True
488
 
        
 
563
 
489
564
    def chequear_turno(self, cr, uid, ids, date_start, date_end, emp_id):
490
 
                shitf_week_obj = self.pool.get('horas.extras.wizard.concept.variable')
491
 
                shitf_week = shitf_week_obj.get_shitf_week(cr, uid, ids, date_start, date_end, emp_id)
492
 
                return shitf_week
493
 
        
 
565
        shitf_week_obj = self.pool.get('horas.extras.wizard.concept.variable')
 
566
        shitf_week = shitf_week_obj.get_shitf_week(cr, uid, ids, date_start, date_end, emp_id)
 
567
        return shitf_week
 
568
 
494
569
    def calcular_cantidad_conceptos(self, cr, uid, ids, date_start, date_end, emp_id, line_id, shift_id=None):
495
570
        horas_extras_obj = self.pool.get('horas.extras.wizard.concept.variable')
496
571
        value = horas_extras_obj.calcular_sobretiempo(cr, uid, ids, date_start, date_end, emp_id, ids, shift_id=shift_id)
497
572
        return value
498
573
 
499
 
    def processing(self, cr, uid, ids, context = None):
 
574
    def processing(self, cr, uid, ids, context=None):
500
575
        #  Validando que no vaya a saltar el flujo
501
576
        if not isinstance(ids, list):
502
577
            ids = [ids]
503
 
        for record in self.browse(cr,uid,ids):
504
 
            if record.state != 'approved': return False
505
 
        #Fin de la validacion
 
578
        for record in self.browse(cr, uid, ids):
 
579
            if record.state != 'approved':
 
580
                return False
 
581
        # Fin de la validacion
506
582
        self.write(cr, uid, ids, {'state': 'processing'})
507
 
        dict_emp_values = {}  
508
 
        for i in self.browse(cr, uid, ids, context):
509
 
            for line in i.planificacion_lineas_ids:
510
 
                dict_emp_values[line.empleado_id.id] = {}  
511
 
        
512
 
        for i in self.browse(cr, uid, ids, context):
513
 
            for line in i.planificacion_lineas_ids:
514
 
                fecha_desde = "%s %s"%(line.fecha_desde, line.hora_desde)
515
 
                fecha_hasta = "%s %s"%(line.fecha_hasta, line.hora_hasta)
 
583
        dict_emp_values = {}
 
584
        for i in self.browse(cr, uid, ids, context):
 
585
            for line in i.planificacion_lineas_ids:
 
586
                dict_emp_values[line.empleado_id.id] = {}
 
587
 
 
588
        for i in self.browse(cr, uid, ids, context):
 
589
            for line in i.planificacion_lineas_ids:
 
590
                fecha_desde = "%s %s" % (line.fecha_desde, line.hora_desde)
 
591
                fecha_hasta = "%s %s" % (line.fecha_hasta, line.hora_hasta)
516
592
                if not self.chequear_turno(cr, uid, ids, fecha_desde, fecha_hasta, line.empleado_id.id):
517
 
                   self.write_state_lines(cr, uid, ids, 'exception', lines=line.id)
518
 
                   self.write_state_lines(cr, uid, ids, True, lines=line.id, field='excepciones')
 
593
                    self.write_state_lines(cr, uid, ids, 'exception', lines=line.id)
 
594
                    self.write_state_lines(cr, uid, ids, True, lines=line.id, field='excepciones')
519
595
                else:
520
 
                    self.write_state_lines(cr, uid, ids,'processing', lines=line.id)
 
596
                    self.write_state_lines(cr, uid, ids, 'processing', lines=line.id)
521
597
                    valor = self.calcular_cantidad_conceptos(cr, uid, ids, fecha_desde, fecha_hasta, line.empleado_id.id, line.id, None)
522
 
                    for concepto in valor: 
523
 
                        if not concepto in dict_emp_values[line.empleado_id.id]:
524
 
                           dict_emp_values[line.empleado_id.id][concepto] = valor[concepto]
 
598
                    for concepto in valor:
 
599
                        if concepto not in dict_emp_values[line.empleado_id.id]:
 
600
                            dict_emp_values[line.empleado_id.id][concepto] = valor[concepto]
525
601
                        else:
526
602
                            dict_emp_values[line.empleado_id.id][concepto] += valor[concepto]
527
 
        
 
603
 
528
604
        horas_extras_calc_obj = self.pool.get('horas.extras.planificacion.calculos')
529
 
        
 
605
 
530
606
        for emp in dict_emp_values:
531
 
            vals = {'trabajador_id':emp, 'horas_extras_planificacion_id':ids[0]}
 
607
            vals = {'trabajador_id': emp, 'horas_extras_planificacion_id': ids[0]}
532
608
            for c in dict_emp_values[emp]:
533
 
                vals['concept_id'] = c 
 
609
                vals['concept_id'] = c
534
610
                vals['value'] = dict_emp_values[emp][c]
535
 
                horas_extras_calc_obj.create(cr, uid, vals) 
 
611
                horas_extras_calc_obj.create(cr, uid, vals)
536
612
        return True
537
 
    
 
613
 
538
614
    def unlink(self, cr, uid, ids, context=None):
539
615
        if not isinstance(ids, list):
540
616
            ids = [ids]
541
617
        brw = self.browse(cr, uid, ids)
542
618
        if brw[0].planificacion_lineas_ids:
543
 
           raise osv.except_osv(_('Accion no permitida!'), _('Solo se pueden eliminar hojas vacias'))
 
619
            raise osv.except_osv(_('Accion no permitida!'), _('Solo se pueden eliminar hojas vacias'))
544
620
        if brw[0].referencia != 'ST-#':
545
 
           raise osv.except_osv(_('Accion no permitida!'), _('No se pueden borrar hojas con numero de referencia asignado'))
 
621
            raise osv.except_osv(_('Accion no permitida!'), _('No se pueden borrar hojas con numero de referencia asignado'))
546
622
        return super(horas_extras_planificacion, self).unlink(cr, uid, ids, context)
547
 
    
 
623
 
548
624
    def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
549
625
        if not context:
550
 
            context={}
551
 
        load_nom =  self._get_trabajadores_nomina(cr, uid, 'group_sisb_horas_extras_th', param_nomina=False) 
552
 
        hr_user =  self._get_trabajadores_nomina(cr, uid, 'group_hr_user', param_nomina=True)
553
 
        if (uid <> 1 and not load_nom and not hr_user):
 
626
            context = {}
 
627
        load_nom = self._get_trabajadores_nomina(cr, uid, 'group_sisb_horas_extras_th', param_nomina=False)
 
628
        hr_user = self._get_trabajadores_nomina(cr, uid, 'group_hr_user', param_nomina=True)
 
629
        if (uid != 1 and not load_nom and not hr_user):
554
630
            lista = self.validar_departamentos(cr, uid)
555
631
            dic = 'department_id', 'in', lista
556
632
            args.append(dic)
557
633
        return super(horas_extras_planificacion, self).search(cr, uid, args, offset, limit, order, context, count)
558
 
    
 
634
 
559
635
    def write(self, cr, uid, ids, values, context=None):
560
636
        if context is None:
561
637
            context = {}
563
639
            ids = [ids]
564
640
        brw = self.browse(cr, uid, ids)
565
641
        user_id = brw[0].user_id
566
 
        load_nom = self._get_trabajadores_nomina(cr, uid, 'group_sisb_horas_extras_th', param_nomina=False) 
 
642
        load_nom = self._get_trabajadores_nomina(cr, uid, 'group_sisb_horas_extras_th', param_nomina=False)
567
643
        if uid != 1 and not load_nom and brw[0].state == 'draft' and 'state' not in values:
568
644
            if uid != user_id.id:
569
 
               raise osv.except_osv(_('Error'), _('Solo el usuario %s puede editar esta hoja' %user_id.name))
570
 
        return super(horas_extras_planificacion, self).write(cr, uid, ids, values, context)     
571
 
    
 
645
                raise osv.except_osv(_('Error'), _('Solo el usuario %s puede editar esta hoja' % user_id.name))
 
646
        return super(horas_extras_planificacion, self).write(cr, uid, ids, values, context=context)
 
647
 
572
648
    def copy(self, cr, uid, id, default=None, context=None):
573
649
        raise osv.except_osv(_('Accion no permitida!'), _('No se pueden duplicar las hojas de sobretiempos'))
574
650
        return False
575
 
    
576
 
horas_extras_planificacion()     
 
651
 
 
652
 
 
653
horas_extras_planificacion()
 
654
 
577
655
 
578
656
class horas_extras_planificacion_lineas_excepciones(osv.osv):
579
 
    
 
657
 
580
658
    _name = 'horas.extras.planificacion.lineas.excepciones'
581
659
    _description = 'Lineas con excepcioneses'
582
660
    _columns = {
583
 
    'horas_extras_planificacion_lineas_id': fields.many2one('horas.extras.planificacion.lineas', 'Planificacion de horas extras lineas', readonly=True),
584
 
    'value': fields.float("Calculo de hora extras", required=True),
585
 
    'concept_id': fields.many2one('hr.concept', 'Concepto', required=True), 
 
661
        'horas_extras_planificacion_lineas_id': fields.many2one('horas.extras.planificacion.lineas', 'Planificacion de horas extras lineas', readonly=True),
 
662
        'value': fields.float("Calculo de hora extras", required=True),
 
663
        'concept_id': fields.many2one('hr.concept', 'Concepto', required=True),
586
664
    }
 
665
 
 
666
 
587
667
horas_extras_planificacion_lineas_excepciones()
588
668
 
589
669
# Herencia sobre hr_payroll (nominas) para agregar campos de dias permitidos para sobretiempo
 
670
 
 
671
 
590
672
class hr_payroll(osv.osv):
591
673
    _inherit = 'hr.payroll'
592
674
    _columns = {
595
677
    _defaults = {
596
678
        'periodos_sobretiempo': lambda *a: 1
597
679
    }
 
680
 
 
681
 
598
682
hr_payroll()
 
683
 
 
684
 
 
685
class horas_extras_historial_parametros(osv.osv):
 
686
    _name = 'horas.extras.historial.parametros'
 
687
    _description = 'Historial de cambios en sobretiempos por departamento'
 
688
    _columns = {
 
689
        'user_id': fields.many2one('res.users', 'Usuario'),
 
690
        'date': fields.datetime('Fecha'),
 
691
        'department_id': fields.many2one('hr.department', 'Departamento'),
 
692
        'prev_hours_per_dept': fields.integer('Departamento - previo'),
 
693
        'prev_hours_per_week': fields.integer('Semanal - previo'),
 
694
        'prev_hours_per_day': fields.integer('Diario - previo'),
 
695
        'hours_per_dept': fields.integer('Departamento - nuevo'),
 
696
        'hours_per_week': fields.integer('Semanal - nuevo'),
 
697
        'hours_per_day': fields.integer('Diario - nuevo')
 
698
    }
 
699
    _order = 'date desc'
 
700
 
 
701
 
 
702
horas_extras_historial_parametros()