# -*- coding: utf-8 -*- from openerp import models, fields, api, exceptions, _ import datetime import pytz from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT from openerp.exceptions import except_orm, Warning, RedirectWarning __INSERT_DATA__ = False CONFIRMED_ACTUAL = 'confirmed_actual' CONFIRMED_PREVIOUS = 'confirmed_previous' AUTHORIZED_ACTUAL = 'authorized_actual' AUTHORIZED_PREVIOUS = 'authorized_previous' DRAFT = 'draft' def gt_eq_zero(num): return num >= 0 def control_dates(my_period, its_period): my_start_date = datetime.datetime.strptime(my_period.start_date, DEFAULT_SERVER_DATETIME_FORMAT) my_end_date = datetime.datetime.strptime(my_period.end_date, DEFAULT_SERVER_DATETIME_FORMAT) its_start_date = datetime.datetime.strptime(its_period.start_date, DEFAULT_SERVER_DATETIME_FORMAT) its_end_date = datetime.datetime.strptime(its_period.end_date, DEFAULT_SERVER_DATETIME_FORMAT) """Controls: 1st line: the is no old period start hour in middle of the new period 2nd line: the is no old period end hour in middle of the new period 3st line: the new period end hour is not in middle of any old period """ return (gt_eq_zero((my_start_date - its_start_date).days) != gt_eq_zero((my_end_date - its_start_date).days)) \ or (gt_eq_zero((my_start_date - its_end_date).days) != gt_eq_zero((my_end_date - its_end_date).days)) \ or (gt_eq_zero((its_start_date - my_end_date).days) != gt_eq_zero((its_end_date - my_end_date).days)) class RoutePeriodPoint(models.Model): _name = 'route.period.point' _inherit = ['mail.thread'] _track = { 'state': { 'rafalim_route_calendar.mt_route_confirmed': lambda self, cr, uid, obj, ctx=None: obj.state in [CONFIRMED_ACTUAL,CONFIRMED_PREVIOUS], 'rafalim_route_calendar.mt_route_authorized': lambda self, cr, uid, obj, ctx=None: obj.state in [AUTHORIZED_ACTUAL,AUTHORIZED_PREVIOUS], }, } @api.multi def _get_repositor(self): user_id = self.env.user.id res = self.env['res.repositor'].search([('user_id', '=', user_id)]) is_route_admin = self.env.user.has_group('rafalim_route_calendar.group_routing_admin') if not res and not is_route_admin: raise except_orm(_("Repositor error!"), _("You cannot load routing information "\ "because you are not a Repositor nor Route Admin")) if is_route_admin: return False return res.id name = fields.Char(size=64, string='Name', compute='_get_name', readonly=True) repositor_id = fields.Many2one('res.repositor',default=_get_repositor,string='Repositor')#, required=True) start_date = fields.Datetime(required=True, string='Start Date', states={AUTHORIZED_PREVIOUS: [('readonly', True)],AUTHORIZED_ACTUAL: [('readonly', True)]}) end_date = fields.Datetime(required=True, string='End Date', states={AUTHORIZED_PREVIOUS: [('readonly', True)],AUTHORIZED_ACTUAL: [('readonly', True)]}) duration = fields.Float(digits=(2,2),compute='_get_duration', string='Duration', help='Duration in hours',store=True, readonly=True) partner_id = fields.Many2one('res.partner', string='Client', required=True, states={AUTHORIZED_PREVIOUS: [('readonly', True)],AUTHORIZED_ACTUAL: [('readonly', True)]}) region_id = fields.Many2one('geographic.zone', string='Region', compute='_get_region', store=True) commercial_zone_id = fields.Many2one('commercial.zone', string='Commercial zone', compute='_get_commercial_zone', store=True) state = fields.Selection([ (DRAFT, "Draft"), (CONFIRMED_PREVIOUS, "Confirmed"), (AUTHORIZED_PREVIOUS, "Authorized"), (CONFIRMED_ACTUAL, "Confirmed"), (AUTHORIZED_ACTUAL, "Authorized"), ], default=DRAFT, string='State', readonly=True) # TODO: Cambiar el compute por el valor segun el context de la action, ya que ahora lo # tenemos por separado cuando cargan efectivo y anticipado route_type = fields.Selection([ ('previous', "Previous"), ('actual', "Actual"), ], string='Route Type', compute='_get_route_type', store=True, readonly=True) commentary = fields.Text(string='Commentaries', states={AUTHORIZED_PREVIOUS: [('readonly', True)],AUTHORIZED_ACTUAL: [('readonly', True)]}) period_id = fields.Many2one('route.period', compute='_get_period',store=True, string='Supervisor period', states={AUTHORIZED_PREVIOUS: [('readonly', True)],AUTHORIZED_ACTUAL: [('readonly', True)]}) calendar_week_id = fields.Many2one('calendar.year.week', string='Week', compute='_get_week', store=True, states={AUTHORIZED_PREVIOUS: [('readonly', True)],AUTHORIZED_ACTUAL: [('readonly', True)]}) @api.onchange('repositor_id') def change_repositor(self): domain=[('requires_reposition', '=', True), ('id', 'in', sum(map(lambda zone: zone.customers.mapped('id'),self.repositor_id.zone_ids),[]))] return {'domain': {'partner_id': domain}} @api.depends('partner_id') def _get_region(self): for point in self: point.region_id = point.partner_id.sub_region_id.geographic_zone_id @api.depends('partner_id') def _get_commercial_zone(self): for point in self: point.commercial_zone_id = point.partner_id.commercial_zone_id @api.multi @api.depends('start_date', 'end_date', 'repositor_id') def _get_period(self): #Checks if the period exits, if not create it and assign it """ import ipdb ipdb.set_trace() #""" # TODO: Chequear pr que en cierto momento vienen varios period.points. Ver el compute, # o tratar de evitarlo for point in self: calendar_week_id = self.env['calendar.year.week']._check_date(point.start_date) #calendar_week_id = self.env['calendar.year.week'].search(['&',('first_day','<=',self.start_date),('last_day','>=',self.start_date)]) repositor_id = point.repositor_id #self.env['res.repositor'].search([('user_id','=',self.env.user.id)]) if len(repositor_id.supervisor_id) > 0: period_id = self.env['route.period']._check_period(calendar_week_id,repositor_id) #period_id = self.env['route.period'].search(['&', ('calendar_week_id','=',calendar_week_id.id),('repositor_id','=',repositor_id.id)]) #point.period_id = period_id point.update({"period_id": period_id.id}) #self.repositor_id = period_id.repositor_id else: raise exceptions.ValidationError(_("You have none supervisor, please contact a system admin")) @api.depends('start_date') def _get_route_type(self): for route_period_point in self: """ import pdb pdb.set_trace() #""" today = datetime.datetime.strptime(fields.Date.context_today(self), DEFAULT_SERVER_DATE_FORMAT) today = datetime.datetime(year=today.year, month=today.month, day=today.day, hour=5) to_next_monday_delta = datetime.timedelta(days=-today.weekday()+7) next_monday = today + to_next_monday_delta sdate = route_period_point.start_date compare_date = fields.Datetime.context_timestamp(self,datetime.datetime.strptime(sdate, DEFAULT_SERVER_DATETIME_FORMAT)) sdate = compare_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT) snext_monday = next_monday.strftime(DEFAULT_SERVER_DATETIME_FORMAT) if (snext_monday < sdate): #gt_eq_zero((next_monday - compare_date).days)): #and gt_eq_zero((compare_date - last_monday).days)): route_period_point.route_type = 'previous' else: route_period_point.route_type = 'actual' @api.depends('period_id') def _get_week(self): for route_period_point in self: route_period_point.calendar_week_id = route_period_point.period_id.calendar_week_id @api.multi def action_confirm(self): if self.route_type == 'actual': if self.state != AUTHORIZED_ACTUAL: state = AUTHORIZED_ACTUAL else: state = CONFIRMED_ACTUAL else: state = CONFIRMED_PREVIOUS self.message_post(body='Confirmado: \n * Inicio: %s \n * Fin: %s \n * Sucursal: %s \n * Semana: %s' %(self.start_date,self.end_date,self.partner_id.name,self.calendar_week_id.name)) self.write({'state': state}) return True @api.multi def action_delete(self): self.unlink() @api.multi def action_authorize(self): if self.state != DRAFT: if self.route_type == 'actual': state = AUTHORIZED_ACTUAL else: state = AUTHORIZED_PREVIOUS self.write({'state': state}) self.message_post(body='Autorizado.') @api.depends('period_id') @api.constrains('start_date', 'end_date') def _check_date(self): today = datetime.datetime.strptime(fields.Date.context_today(self), DEFAULT_SERVER_DATE_FORMAT) today = datetime.datetime(year=today.year, month=today.month, day=today.day, hour=5) to_monday_delta = datetime.timedelta(days=-today.weekday()) week_delta = datetime.timedelta(days=7) last_monday = today + to_monday_delta next_monday = last_monday + week_delta group_id_supervisor = self.env.ref('supervisors_and_pools.group_salesman_supervisor') for route_period_point in self: start_date = fields.Datetime.context_timestamp(self,datetime.datetime.strptime(route_period_point.start_date, DEFAULT_SERVER_DATETIME_FORMAT)) end_date = fields.Datetime.context_timestamp(self,datetime.datetime.strptime(route_period_point.end_date, DEFAULT_SERVER_DATETIME_FORMAT)) if not __INSERT_DATA__: if group_id_supervisor not in self.env.user.groups_id: if route_period_point.state != DRAFT: raise exceptions.ValidationError(_("It is not an editable period")) if start_date.weekday() == 6: raise exceptions.ValidationError(_("Can't assign a job on Sunday")) """ import pdb pdb.set_trace() #""" control_line_ids = route_period_point.period_id.period_point_ids if not (start_date.day == end_date.day and start_date.month == end_date.month and start_date.year == end_date.year): raise exceptions.ValidationError(_("Period must have the same start and end date")) start_date = datetime.datetime(year=start_date.year, month=start_date.month, day=start_date.day, hour=start_date.hour,minute=start_date.minute) #Controls if its the correct time to commit the period if route_period_point.route_type == 'previous': next_monday_diff = start_date - next_monday if next_monday_diff.days < 0 or next_monday_diff.days > 6: raise exceptions.ValidationError(_("Should be the previous week to add a previous period")) elif route_period_point.route_type == 'actual': last_monday_diff = start_date - last_monday next_monday_diff = start_date - next_monday if last_monday_diff.days < 0 or next_monday_diff.days > 0: raise exceptions.ValidationError(_("Should be the same week to add an actual period")) #Controls collisiding hours for control_line in control_line_ids: #control_line = self.browse(control_line_id.id) if control_line.id != route_period_point.id and control_line.route_type == route_period_point.route_type and control_dates(route_period_point,control_line): raise exceptions.ValidationError(_("Can not have collisiding periods")) @api.model def process_comfirm_calendar_scheduler(self): state_to_upgrade = DRAFT #Contains all ids for the model route.period.point scheduler_line_ids = self.env['route.period.point'].search([('state','=',state_to_upgrade)]) #Loops over every record in the model route.point.period for scheduler_line in scheduler_line_ids : state = scheduler_line.state #Comment section How to work if its not call at 5am """ start_date = fields.Datetime.context_timestamp(self,datetime.datetime.strptime(scheduler_line.start_date, DEFAULT_SERVER_DATETIME_FORMAT)) start_date = datetime.datetime(year=start_date.year, month=start_date.month, day=start_date.day, hour=start_date.hour,minute=start_date.minute) today = datetime.datetime.strptime(fields.Date.context_today(self), DEFAULT_SERVER_DATE_FORMAT) today = datetime.datetime(year=today.year, month=today.month, day=today.day, hour=5) """ #Uncomment section start_date = datetime.datetime.strptime(scheduler_line.start_date, DEFAULT_SERVER_DATETIME_FORMAT) today = datetime.datetime.now() if scheduler_line.route_type == 'previous': if (start_date - today).days <= 7: if state == DRAFT: to_state = CONFIRMED_PREVIOUS scheduler_line.write({'state': to_state, 'lastModified': today}) if scheduler_line.route_type == 'actual': if (start_date - today).days <= 0: if state == DRAFT: to_state = CONFIRMED_ACTUAL scheduler_line.write({'state': to_state, 'lastModified': today}) @api.depends('partner_id', 'route_type', 'state') def _get_name(self): for route_period_point in self: route_period_point.name = "%s - %s - %s" % (route_period_point.partner_id.name, route_period_point.route_type, route_period_point.state) @api.multi def unlink(self): if not self.state == DRAFT: raise Warning(_('You cannot delete a route period point which is not draft.')) return models.Model.unlink(self) # @api.multi # def write(self, vals): # for route_period_point in self: # arr = self.env['crm.case.section'].search([('user_id','=',self.env.user.id)]) # # if len(arr) == 0: # if not self.state == 'draft' and not self.state == 'to_correct' : # raise Warning(_('You cannot edit a route period point which is not draft.')) # elif len(vals) > 1: # if vals.get('state') != None: # raise Warning(_('You cannot edit a route period point')) # if self.state == 'draft': # raise Warning(_('You cannot authorize a draft route period point')) # return models.Model.write(self,vals) @api.depends('start_date','end_date') def _get_duration(self): for route_period_point in self: start_date = datetime.datetime.strptime(route_period_point.start_date, DEFAULT_SERVER_DATETIME_FORMAT) end_date = datetime.datetime.strptime(route_period_point.end_date, DEFAULT_SERVER_DATETIME_FORMAT) duration = end_date - start_date route_period_point.duration = duration.seconds/3600.0 #@api.multi #def fields_get(self): def fields_get(self, cr, uid, fields=None, context=None, write_access=True, attributes=None): res = super(RoutePeriodPoint, self).fields_get(cr, uid, fields, context, write_access, attributes) #res = super(RoutePeriodPoint, self).fields_get() #import ipdb #ipdb.set_trace() user_id = self.pool.get('res.users').browse(cr,uid,[uid],context=context) is_route_admin = user_id.has_group('rafalim_route_calendar.group_routing_admin') is_route_repositor = user_id.has_group('rafalim_route_calendar.group_repositor') is_route_supervisor = user_id.has_group('supervisors_and_pools.group_salesman_supervisor') fieldss = ['start_date','end_date','partner_id','commentary'] ## REPEAT CODE > UNREADABLE CODE for field in fieldss: if field in res: res[field].setdefault('states', {}) res[field]['states'][DRAFT] = [('readonly', False)] res[field]['states'][AUTHORIZED_ACTUAL] = [('readonly', True)] res[field]['states'][AUTHORIZED_PREVIOUS] = [('readonly', True)] if is_route_admin: res[field]['states'][CONFIRMED_PREVIOUS] = [('readonly', False)] res[field]['states'][CONFIRMED_ACTUAL] = [('readonly', False)] elif is_route_supervisor: res[field]['states'][CONFIRMED_PREVIOUS] = [('readonly', False)] res[field]['states'][CONFIRMED_ACTUAL] = [('readonly', True)] else: res[field]['states'][CONFIRMED_PREVIOUS] = [('readonly', True)] res[field]['states'][CONFIRMED_ACTUAL] = [('readonly', True)] if 'repositor_id' in res: res['repositor_id'].setdefault('states', {}) res['repositor_id']['states'][CONFIRMED_PREVIOUS] = [('readonly', True)] res['repositor_id']['states'][CONFIRMED_ACTUAL] = [('readonly', True)] res['repositor_id']['states'][AUTHORIZED_ACTUAL] = [('readonly', True)] res['repositor_id']['states'][AUTHORIZED_PREVIOUS] = [('readonly', True)] if is_route_admin: res['repositor_id']['states'][DRAFT] = [('readonly', False)] else: res['repositor_id']['states'][DRAFT] = [('readonly', True)] return res """Add domain for user_id and member_ids fields on the supervisor's form base_url = self.env['ir.config_parameter'].get_param('web.base.url') action = self.env.ref('kilbel_hr_attendance_timetable.hr_holidays_selected_action') final_url = base_url + '/web#min=1&limit=80&view_type=list&model=hr.holidays&action=' + str(action.id) message_body = _('The holidays to pay attention are in %s') % (final_url) value = self.env["ir.config_parameter"].get_param("hr_holidays_renovate_partners", default='[]').replace('[','').replace(']','') value_list = value.encode('ascii').split(',') hr_holidays_renovate_partner_m2m_list = map(lambda x: (4,int(x),0), filter(lambda y: y != '', value_list)) thread_pool = self.env['mail.thread'] mess_id = thread_pool.message_post( message_type="notification", subtype="mt_comment", subject = "Message subject", body= message_body, ) mess_id.write({"partner_ids" : hr_holidays_renovate_partner_m2m_list, "needaction_partner_ids": hr_holidays_renovate_partner_m2m_list}) """ @api.onchange('start_date','end_date','partner_id','commentary','state') def control_supervisor_changes(self): is_route_supervisor = self.env.user.has_group('supervisors_and_pools.group_salesman_supervisor') for route_period_point in self: if is_route_supervisor: #send message base_url = self.env['ir.config_parameter'].get_param('web.base.url') action = self.env.ref('rafalim_route_calendar.see_points') final_url = base_url + '/web#id='+ str(self._origin.id) +'&view_type=form&model=see_points&action=' + str(action.id) """Add domain for user_id and member_ids fields on the supervisor's form.""" message_body = _('There are changes by your supervisor in the route period point at %s, the change are:') % (final_url) if self._origin.start_date != self.start_date: message_body = message_body + '\n' +_('Start date %s -> %s') % (self._origin.start_date,self.start_date) if self._origin.end_date != self.end_date: message_body = message_body + '\n' +_('End date %s -> %s') % (self._origin.end_date,self.end_date) if self._origin.partner_id != self.partner_id: message_body = message_body + '\n' +_('Partner %s -> %s') % (self._origin.partner_id.name,self.partner_id.name) if self._origin.commentary != self.commentary: message_body = message_body + '\n' +_('Commentary %s -> %s') % (self._origin.commentary,self.commentary) if self._origin.state != self.state: message_body = message_body + '\n' +_('State %s -> %s') % (self._origin.state,self.state) thread_pool = self.env['mail.thread'] mess_id = self.repositor_id.user_id.message_post( message_type="notification", subtype="mt_comment", subject = "Changes at route period point", body= message_body ) """ @api.multi @api.model def read_group(self): def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False, lazy=True): res = super(your_class, self).read_group(cr, uid, domain, fields, groupby, offset, limit=limit, context=context, orderby=orderby, lazy=lazy) if 'duration' in fields: for line in res: if '__domain' in line: lines = self.search(cr, uid, line['__domain'], context=context) pending_value = 0.0 for current_account in self.browse(cr, uid, lines, context=context): pending_value += current_account.amount_pending line['amount_pending'] = pending_value if 'amount_payed' in fields: for line in res: if '__domain' in line: lines = self.search(cr, uid, line['__domain'], context=context) payed_value = 0.0 for current_account in self.browse(cr, uid, lines, context=context): payed_value += current_account.amount_payed line['amount_payed'] = payed_value return res """