# -*- coding: utf-8 -*- # Copyright 2017 Fabien Bourgeois # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . """ GOLEM activities related models """ import collections from datetime import datetime, timedelta from dateutil import parser #from dateutil import rrule from dateutil.rrule import WEEKLY, rrule from dateutil.relativedelta import relativedelta from odoo import models, fields, api, _ from datetime import timedelta from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT #from dateutil import rrule #from dateutil.rrule import rrule #from dateutil.rrule import rrule class GolemActivityType(models.Model): """ GOLEM Activity Type """ _name = 'golem.activity.type' _description = 'GOLEM Activity Type' _sql_constraints = [('golem_activity_type_name_uniq', 'UNIQUE (name)', _('This activity type name has already been used.'))] name = fields.Char('Activity type', required=True, translate=True) is_recurrent = fields.Boolean('Is recurrent?') class GolemActivity(models.Model): """ GOLEM Activity """ _name = 'golem.activity' _description = 'GOLEM Activity' _inherit = 'mail.thread' _inherits = {'product.template': 'product_id'} _rec_name = 'full_name' product_id = fields.Many2one('product.template', required=True, ondelete='cascade') image = fields.Binary(help='This field holds the image used as image for ' 'the activity.') full_name = fields.Char('Name', compute='_compute_full_name', store=True, index=True) is_fullseason = fields.Boolean('Is full season?', compute='_compute_is_full_season') @api.onchange('is_fullseason') def onchange_fullseason(self): """ Sets dates as season ones if needed """ for activity in self: if activity.is_fullseason: if activity.season_id.date_start: activity.date_start = activity.season_id.date_start if activity.season_id.date_end: activity.date_stop = activity.season_id.date_end @api.depends('date_start', 'date_stop') def _compute_is_full_season(self): """ Display date for is full season """ for activity in self: if activity.date_start == activity.season_id.date_start and \ activity.date_stop == activity.season_id.date_end: activity.is_fullseason = True @api.depends('name', 'default_code') def _compute_full_name(self): """ Provide a better displayed name """ for activity in self: full_name = unicode(activity.name) if activity.default_code: full_name = u'[{}] {}'.format(activity.default_code, full_name) activity.full_name = full_name @api.model def _default_season(self): """ Get default season """ domain = [('is_default', '=', True)] return self.env['golem.season'].search(domain) season_id = fields.Many2one('golem.season', string='Season', copy=False, required=True, default=_default_season, ondelete='restrict') is_current = fields.Boolean('Current season?', store=True, default=False, compute='compute_is_current') @api.depends('season_id') def compute_is_current(self): """ Checks if activity is active for current season """ default_season = self._default_season() for activity in self: activity.is_current = (default_season == activity.season_id) animator_id = fields.Many2one('res.partner', string='Animator', domain=[('is_company', '=', False)]) categ_id = fields.Many2one('product.category', help='Select category for the current activity') type_id = fields.Many2one('golem.activity.type', required=True, index=True, string='Type') is_recurrent = fields.Boolean(related='type_id.is_recurrent') date_start = fields.Date('Start date', copy=False) date_stop = fields.Date('End date', copy=False) @api.onchange('date_start') def _onchange_date_start(self): """ Sets end date to start date if no start date """ for activity in self: if not activity.date_stop: activity.date_stop = activity.date_start @api.constrains('date_start', 'date_stop') def _check_period(self): """ Checks if end date if after start date """ for activity in self: season = activity.season_id if activity.date_start and activity.date_stop and \ activity.date_start > activity.date_stop: raise models.ValidationError(_('Start of the period cannot be ' 'after end of the period.')) if season.date_start and season.date_start > activity.date_start: msg = _(u'Activity start date can not be set before ' 'linked season start.') raise models.ValidationError(msg) if season.date_end and season.date_end < activity.date_stop: msg = _(u'Activity end date can not be set after ' 'linked season end.') raise models.ValidationError(msg) @api.onchange('season_id') def _onchange_season_dates(self): """ Sets defaults dates according to season """ for activity in self: if activity.season_id: if not activity.date_start: activity.date_start = activity.season_id.date_start if not activity.date_stop: activity.date_stop = activity.season_id.date_end weekday = fields.Selection([(0, _('Monday')), (1, _('Tuesday')), (2, _('Wednesday')), (3, _('Thursday')), (4, _('Friday')), (5, _('Saturday')), (6, _('Sunday'))], copy=False) hour_start = fields.Float('Start time', copy=False) hour_stop = fields.Float('Stop time', copy=False) @api.onchange('hour_start') def _onchange_hour_start(self): """ Sets end hour to start hour if no start hour """ for activity in self: if activity.hour_start and not activity.hour_stop: activity.hour_stop = activity.hour_start + 1 @api.constrains('hour_start', 'hour_stop') def _check_hour_period(self): """ Check if end hour if after start hour """ for activity in self: if activity.hour_start > activity.hour_stop: raise models.ValidationError(_('Start of the period cannot be ' 'after end of the period.')) ########################################### ########################################## @api.multi def read(self, fields=None, load='_classic_read'): print '_________read call _______________' print 'load' print load print self.ids fields2 = fields and fields[:] or None select = map(lambda x: (x, self.calendar_id2real_id(x)), self.ids) print '_____________________<<' print select print '>>_____________________' real_events = self.browse([real_id for calendar_id, real_id in select]) #print real_events #print " calendar_id n:1 : "+ str(calendar_id) #verify that attribute of real id is working after next statement real_data = super(GolemActivity, real_events).read(fields=fields2, load=load) real_data = dict((d['id'], d) for d in real_data) print real_data result = [] #print " calendar_id n:3 : "+ str(calendar_id) for calendar_id, real_id in select: #print "cal" #print calendar_id res = real_data[real_id].copy() date_start = str(calendar_id).split('_') if len(date_start) == 2: dt = datetime.strptime(date_start[1],DEFAULT_SERVER_DATETIME_FORMAT).date()# "%y-%m-%d %H:%M:%S") res['date_start'] = str(dt) res['date_stop'] = str(dt) #print " calendar_id n:4 : "+ str(calendar_id) res['id'] = calendar_id #res['date_start'] = date_start[1] result.append(res) #print 'resuuuuuuuuuuuuuult' #print result return result """print res print '_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_' print calendar_id print '_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_' print real_id""" #ls = self.calendar_id2real_id(calendar_id, with_date=res and res.get('duration', 0) > 0 and res.get('duration') or 1) """for calendar_id, real_id in select: print calendar_id print real_id""" #for id in self.ids: # print self.env['golem.activity'].browse(id) #return super(GolemActivity, self).read(self, fields=None, load='_classic_read') @api.multi def get_metadata(self): real = self.browse(set({x: self.calendar_id2real_id(x) for x in self.ids}.values())) return super(GolemActivity, real).get_metadata() @api.multi def calendar_id2real_id(self, calendar_id=None): if calendar_id and isinstance(calendar_id, (basestring)): res = filter(None, calendar_id.split('_')) if len(res) == 2: real_id = res[0] return int(real_id) return calendar_id and int(calendar_id) or calendar_id @api.multi def real_id2calendar_id(self, record_id): """ convert Real Id to Calendar ID """ activity = self.env['golem.activity'].browse(record_id) date_start = fields.Date.from_string(activity.date_start) date_stop = fields.Date.from_string(activity.date_stop) weekday = 0#date_start.weekday() if activity.weekday: weekday = activity.weekday #print '_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-' #print weekday list_date = list(rrule(freq=WEEKLY, dtstart=date_start, until=date_stop, byweekday=weekday)) calendar_ids = [] for date in list_date: calendar_ids.append('%s_%s' % (record_id, date)) #print '_______________________________________________' #print calendar_ids return calendar_ids @api.multi def get_recurrent_ids(self): result = [] for activity in self: #print '___________________tktk______' #if not meeting.recurrency or not meeting.rrule: if activity.is_recurrent: result += activity.real_id2calendar_id(activity.id) else: result.append(activity.id) return result @api.model def search(self, args, offset=0, limit=0, order=None, count=False): activities = super(GolemActivity, self).search(args, offset=0, limit=0, order=None, count=False) activities = self.browse(activities.get_recurrent_ids()) #print "àààààààààààààààààààààààààààààààààààààààà" #print activities.mapped('id') return activities class ProductTemplate(models.Model): """ GOLEM Activity Product adaptations """ _inherit = 'product.template' type = fields.Selection(default='service') default_code = fields.Char(copy=True) categ_id = fields.Many2one(copy=True)