from __future__ import print_function
|
|
from odoo import models, fields, api,_
|
|
from odoo.exceptions import UserError, ValidationError,Warning
|
|
from psycopg2 import sql, DatabaseError
|
|
from pytz import timezone
|
|
from odoo.addons.http_routing.models.ir_http import slugify
|
|
|
|
from werkzeug import utils
|
|
|
|
|
|
import os.path
|
|
from google.oauth2 import service_account
|
|
from googleapiclient.discovery import build
|
|
from datetime import date,datetime, timedelta
|
|
import json
|
|
import babel
|
|
import babel.dates
|
|
|
|
import time
|
|
import sib_api_v3_sdk
|
|
from sib_api_v3_sdk.rest import ApiException
|
|
from pprint import pprint
|
|
|
|
|
|
# IF YOU MODIFY THE SCOPE DELETE THE TOKEN.TXT FILE
|
|
SCOPES = ['https://www.googleapis.com/auth/calendar']
|
|
GOOGLE_ACCOUNT_FILE = '/usr/lib/python3/dist-packages/odoo/kalachakra_module/kalachakra/models/creds.json' # You should make it an environment variable
|
|
|
|
|
|
SUBJECT = 'kalachakra-srv@kalachakra-351613.iam.gserviceaccount.com'
|
|
|
|
|
|
class EventTagCategory(models.Model):
|
|
_inherit = "event.tag.category"
|
|
_description = 'Event tag category'
|
|
|
|
calendar_id=fields.Char('google calendar id')
|
|
hidden=fields.Boolean('hidden tag')
|
|
|
|
class KalachakraEvent(models.Model):
|
|
_inherit = "event.event"
|
|
_description = 'Event'
|
|
|
|
calendar_id=fields.Char('calendar id')
|
|
calendar_event_id=fields.Char('event id')
|
|
free_participation=fields.Boolean('Free participation')
|
|
participation_product_id=fields.Many2one('product.product',string='participation product')
|
|
participation_standard_price=fields.Monetary('Standard Price',currency_field='currency_id')
|
|
participation_member_price=fields.Monetary('Member price',currency_field='currency_id')
|
|
participation_super_member_price=fields.Monetary('Super member price',currency_field='currency_id')
|
|
subscription_product_id=fields.Many2one('product.product',string='subscription product')
|
|
subscription_standard_price=fields.Monetary('Standard Price',currency_field='currency_id')
|
|
subscription_member_price=fields.Monetary('Member price',currency_field='currency_id')
|
|
subscription_super_member_price=fields.Monetary('Super member price',currency_field='currency_id')
|
|
|
|
recurring_event=fields.Boolean('Recurring event')
|
|
recurring_event_newsletter_id=fields.Many2one('mailing.list',string='Recurring event Newsletter')
|
|
online_event=fields.Boolean('Online event')
|
|
onthespot_event=fields.Boolean('On the spot event', default=True)
|
|
online_only=fields.Boolean('Online only')
|
|
online_link=fields.Char('link')
|
|
online_id=fields.Char('id')
|
|
online_password=fields.Char('password',default='123456')
|
|
duration=fields.Integer('duration', compute="_compute_duration")
|
|
frequency=fields.Selection(string='Frequency',selection=[('daily', 'Daily'), ('weekly', 'Weekly')])
|
|
weekly_day=fields.Selection(string='Weekly day',selection=[('monday', 'Monday'),('tuesday', 'Tuesday'),('wednesday', 'Wednesday'),('thursday', 'Thursday'),('friday', 'Friday'),('saturday', 'Saturday'),('sunday', 'Sunday') ])
|
|
end_generation_date=fields.Datetime('End generation date')
|
|
generated_events=fields.Boolean('generated_ events', compute='_compute_generated_events')
|
|
#for event generated from a parent event
|
|
parent_event_id=fields.Many2one('event.event',string='parent event', readonly=True)
|
|
find_out_more_link=fields.Char('Find out more link')
|
|
city=fields.Char('city', related="address_id.city")
|
|
no_online_payment=fields.Boolean('no online payment')
|
|
|
|
@api.depends('seats_unconfirmed', 'seats_reserved', 'seats_used')
|
|
def _compute_seats_expected(self):
|
|
for event in self:
|
|
i=0
|
|
for reg_id in event.registration_ids:
|
|
reg=self.env['event.registration'].search([('id','=',int(reg_id))])
|
|
if reg.state in ('draft','open','done'):i=i+1
|
|
event.seats_expected=i
|
|
|
|
|
|
def bulk_change_date_events(self,name,date_start_str,hour):
|
|
|
|
date_format_str = '%d/%m/%Y %H:%M:%S'
|
|
date_start=datetime.strptime(date_start_str, date_format_str)
|
|
events=self.env['event.event'].search([('name','=', name),('date_begin','>',date_start)])
|
|
|
|
|
|
if events:
|
|
for ev in events:
|
|
ev.date_begin=ev.date_begin+timedelta(hours=1)
|
|
ev.date_end=ev.date_end+timedelta(hours=1)
|
|
|
|
def write(self,vals):
|
|
res = super(KalachakraEvent, self).write(vals)
|
|
#mise à jour du calendrier google si
|
|
#modification date de début ou date de fin
|
|
#modification du nom de l'événement
|
|
if self.calendar_event_id:
|
|
|
|
if vals.get('date_begin') or vals.get('date_end') or vals.get('name'):
|
|
|
|
self.update_event_google_agenda()
|
|
#s'il existe des événements liés à celui-ci, mise à jour de ceux-ci
|
|
#uniquement sur les champs suivants : nom, liste de diffusion, lien zoom, type de participation, lien en savoir plus
|
|
|
|
child_events=self.env['event.event'].search([('parent_event_id','=', int(self.id))])
|
|
if child_events:
|
|
|
|
for child_event in child_events:
|
|
|
|
child_event.name=self.name
|
|
child_event.event_type_id=self.event_type_id
|
|
child_event.recurring_event_newsletter_id=self.recurring_event_newsletter_id
|
|
child_event.find_out_more_link=self.find_out_more_link
|
|
|
|
child_event.auto_confirm=self.auto_confirm
|
|
child_event.seats_limited=self.seats_limited
|
|
child_event.seats_max=self.seats_max
|
|
|
|
child_event.user_id=self.user_id
|
|
child_event.address_id=self.address_id
|
|
|
|
child_event.online_only=self.online_only
|
|
child_event.no_online_payment=self.no_online_payment
|
|
child_event.online_event=self.online_event
|
|
child_event.online_link=self.online_link
|
|
child_event.online_id=self.online_id
|
|
child_event.online_password=self.online_password
|
|
|
|
child_event.event_logo=self.event_logo
|
|
child_event.cover_properties=self.cover_properties
|
|
child_event.tag_ids=self.tag_ids
|
|
child_event.description=self.description
|
|
#child_event.is_published=self.is_published
|
|
child_event.participation_product_id=self.participation_product_id
|
|
child_event.participation_standard_price=self.participation_standard_price
|
|
child_event.participation_member_price=self.participation_member_price
|
|
child_event.participation_super_member_price=self.participation_super_member_price
|
|
|
|
#child_event.event_mail_ids=self.event_mail_ids
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _compute_generated_events(self):
|
|
for rec in self:
|
|
rec.generated_events=False
|
|
evt=rec.env['event.event'].search([('parent_event_id','=', rec.id)])
|
|
if evt:rec.generated_events=True
|
|
|
|
def remove_generated_events(self):
|
|
evt=self.env['event.event'].search([('parent_event_id','=', self.id)])
|
|
if evt:
|
|
for e in evt:
|
|
if e.calendar_id and e.calendar_event_id:
|
|
e.remove_event_from_google_agenda()
|
|
# reg=self.env['event.registration'].search([('event_id','=', int(e.id))])
|
|
# if reg:
|
|
# return str(e.date_begin)
|
|
e.unlink()
|
|
|
|
def remove_generated_calendar_events(self):
|
|
evt=self.env['event.event'].search([('parent_event_id','=', self.id)])
|
|
if evt:
|
|
for e in evt:
|
|
if e.calendar_id and e.calendar_event_id:
|
|
e.remove_event_from_google_agenda()
|
|
|
|
def generate_calendar_events(self):
|
|
self.remove_generated_calendar_events()
|
|
evt=self.env['event.event'].search([('parent_event_id','=', self.id)])
|
|
if evt:
|
|
for e in evt:
|
|
e.add_event_to_google_agenda()
|
|
|
|
|
|
def generate_events(self):
|
|
for rec in self:
|
|
if rec.duration>1 :raise Warning('action cancelled: the duration f the event is more than 1 days !')
|
|
|
|
if rec.end_generation_date<datetime.now() :raise Warning('action cancelled: the end generation date must be in the future !')
|
|
delta=rec.end_generation_date-rec.date_begin
|
|
if delta.days>200:raise Warning('action cancelled: the duration f the event is more than 6 months !')
|
|
|
|
if rec.frequency=='daily':d=1
|
|
|
|
if rec.frequency=='weekly':d=7
|
|
|
|
start_date_event=rec.date_begin+timedelta(days=d)
|
|
end_date_event=rec.date_end+timedelta(days=d)
|
|
|
|
while start_date_event<=rec.end_generation_date:
|
|
|
|
if not start_date_event.weekday() in (5,6):
|
|
#avant de dupliquer l'événement on regarde si celui-ci n'a pas déjà été crée !
|
|
evt=self.env['event.event'].search([('date_begin','=',start_date_event),('parent_event_id','=', int(self.id))])
|
|
if evt: raise Warning('action cancelled: event already generated with this date :'+ str(start_date_event))
|
|
|
|
dup=self._create_event(rec,start_date_event,end_date_event)
|
|
|
|
dup.add_event_to_google_agenda()
|
|
|
|
end_date_event=end_date_event+timedelta(days=d)
|
|
start_date_event=start_date_event+timedelta(days=d)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _create_event(self,rec,start_date_event,end_date_event):
|
|
vals={}
|
|
vals['name']=rec.name
|
|
vals['date_begin']=start_date_event
|
|
vals['date_end']=end_date_event
|
|
vals['description']=rec.description
|
|
vals['tag_ids']=rec.tag_ids
|
|
vals['event_mail_ids']=rec.event_mail_ids
|
|
vals['event_logo']=rec.event_logo
|
|
vals['is_published']=True
|
|
vals['free_participation']=rec.free_participation
|
|
vals['participation_product_id']=int(rec.participation_product_id)
|
|
vals['participation_standard_price']=rec.participation_standard_price
|
|
vals['participation_member_price']=rec.participation_member_price
|
|
vals['participation_super_member_price']=rec.participation_super_member_price
|
|
vals['subscription_product_id']=int(rec.subscription_product_id)
|
|
# vals['subscription_standard_price']=rec.subscription_standard_price
|
|
# vals['subscription_member_price']=rec.subscription_member_price
|
|
# vals['subscription_super_member_price']=rec.subscription_super_member_price
|
|
vals['recurring_event']=rec.recurring_event
|
|
vals['recurring_event_newsletter_id']=int(rec.recurring_event_newsletter_id)
|
|
vals['online_event']=rec.online_event
|
|
vals['online_link']=rec.online_link
|
|
vals['online_id']=rec.online_id
|
|
vals['no_online_payment']=rec.no_online_payment
|
|
vals['online_password']=rec.online_password
|
|
vals['parent_event_id']=int(rec.id)
|
|
vals['cover_properties']=rec.cover_properties
|
|
|
|
|
|
ev=self.env['event.event'].create(vals)
|
|
|
|
|
|
|
|
return ev
|
|
|
|
def _compute_duration(self):
|
|
for rec in self:
|
|
if rec.date_end and rec.date_begin:
|
|
b_date = date(rec.date_begin.year, rec.date_begin.month, rec.date_begin.day)
|
|
e_date = date(rec.date_end.year, rec.date_end.month, rec.date_end.day)
|
|
duration = e_date-b_date
|
|
|
|
rec.duration = duration.days+1
|
|
|
|
else:
|
|
rec.duration=0
|
|
|
|
|
|
|
|
booking_event = fields.Boolean(string="Booking event", tracking=True)
|
|
question_ids=fields.One2many(
|
|
'event.question',
|
|
'event_id',
|
|
string='Questions'
|
|
|
|
)
|
|
booking_option_ids=fields.One2many('booking.option','event_id','booking options')
|
|
booking_price=fields.Monetary('Price',currency_field='currency_id')
|
|
booking_member_price=fields.Monetary('Member price',currency_field='currency_id')
|
|
booking_super_member_price=fields.Monetary('Super member price',currency_field='currency_id')
|
|
booking_down_payment=fields.Monetary('Down payment',default=50,currency_field='currency_id')
|
|
booking_product_id=fields.Many2one('product.product',string='booking product',domain="[('booking_product','=','True')]")
|
|
|
|
@api.onchange('booking_event')
|
|
def onchange_bookin_event(self):
|
|
if self.booking_event:
|
|
|
|
booking_option=self.env['product.product'].search([('booking_option_product','=',True)])
|
|
if booking_option:
|
|
|
|
#on supprime les options existantes:
|
|
self.booking_option_ids=False
|
|
|
|
#on rappatrie les options
|
|
for option in booking_option:
|
|
id_prd=int(option.id)
|
|
prd=self.env['product.product'].sudo().search([('id','=',id_prd)])
|
|
vals={}
|
|
#calcul du prix en fonction du sejour,nuité, ou jour
|
|
|
|
price=option.list_price
|
|
if prd.price_per=='day':
|
|
price=option.list_price*self.duration
|
|
if prd.price_per=='night':
|
|
price=option.list_price*(self.duration-1)
|
|
|
|
vals['event_id']=self._origin.id
|
|
vals['booking_option_id']=option.id
|
|
vals['booking_option_price']=price
|
|
vals['booking_option_member_price']=price
|
|
vals['booking_option_super_member_price']=price
|
|
vals['currency_id']=option.currency_id
|
|
self.booking_option_ids = [(0, 0, vals)]
|
|
|
|
#suppression des 2 templates de mail
|
|
# self.event_mail_ids=False
|
|
# self.env['event.mail'].sudo().search([('event_id','=',self._origin.id)]).unlink()
|
|
|
|
# template_mail_reg=self.env['mail.template'].sudo().search([('name','=','Retraite : Inscription')])
|
|
# #création du mail d'enregistrement
|
|
# if template_mail_reg:
|
|
# vals={}
|
|
# vals['display_name']=template_mail_reg.name
|
|
# vals['event_id']=self._origin.id
|
|
# vals['template_id']=template_mail_reg.id
|
|
# vals['interval_nbr']=0
|
|
# vals['interval_unit']='now'
|
|
# vals['interval_type']='after_sub'
|
|
# mail=self.env['event.mail'].sudo().create(vals)
|
|
|
|
# self.event_mail_ids=[(4, mail.id)]
|
|
|
|
# template_mail_remind=self.env['mail.template'].sudo().search([('name','=','Retraite : Rappel')])
|
|
# #création du mail avant événement
|
|
# if template_mail_remind:
|
|
# vals={}
|
|
# vals['display_name']=template_mail_remind.name
|
|
# vals['event_id']=self._origin.id
|
|
# vals['template_id']=int(template_mail_remind.id)
|
|
# vals['interval_nbr']=5
|
|
# vals['interval_unit']='days'
|
|
# vals['interval_type']='before_event'
|
|
# mail=self.env['event.mail'].sudo().create(vals)
|
|
# self.event_mail_ids=[(4, mail.id)]
|
|
|
|
|
|
# #événement
|
|
# else:
|
|
|
|
# #suppression des 2 templates de mail
|
|
# self.event_mail_ids=False
|
|
# self.env['event.mail'].sudo().search([('event_id','=',self._origin.id)]).unlink()
|
|
|
|
# template_mail_reg=self.env['mail.template'].sudo().search([('name','=','Evénement : Inscription')])
|
|
# #création du mail d'enregistrement
|
|
# if template_mail_reg:
|
|
# vals={}
|
|
# vals['display_name']=template_mail_reg.name
|
|
# vals['event_id']=self._origin.id
|
|
# vals['template_id']=template_mail_reg.id
|
|
# vals['interval_nbr']=0
|
|
# vals['interval_unit']='now'
|
|
# vals['interval_type']='after_sub'
|
|
# mail=self.env['event.mail'].sudo().create(vals)
|
|
|
|
# self.event_mail_ids=[(4, mail.id)]
|
|
|
|
# template_mail_remind=self.env['mail.template'].sudo().search([('name','=','Evénement : Rappel')])
|
|
# #création du mail avant événement
|
|
# if template_mail_remind:
|
|
# vals={}
|
|
# vals['display_name']=template_mail_remind.name
|
|
# vals['event_id']=self._origin.id
|
|
# vals['template_id']=int(template_mail_remind.id)
|
|
# vals['interval_nbr']=5
|
|
# vals['interval_unit']='days'
|
|
# vals['interval_type']='before_event'
|
|
# mail=self.env['event.mail'].sudo().create(vals)
|
|
# self.event_mail_ids=[(4, mail.id)]
|
|
|
|
|
|
|
|
|
|
|
|
@api.model
|
|
def _default_currency(self):
|
|
company = self.env['res.company']._company_default_get(
|
|
'event.event')
|
|
return company.currency_id
|
|
|
|
currency_id = fields.Many2one(
|
|
'res.currency',
|
|
string='Currency',
|
|
required=True,
|
|
track_visibility='onchange',
|
|
ondelete='restrict',
|
|
default=_default_currency
|
|
)
|
|
media_session_ids=fields.One2many(
|
|
'event.media.session',
|
|
'event_id',
|
|
string='Media sessions'
|
|
|
|
)
|
|
|
|
|
|
def add_event_to_google_agenda(self):
|
|
|
|
|
|
credentials = service_account.Credentials.from_service_account_file(GOOGLE_ACCOUNT_FILE, scopes=SCOPES)
|
|
delegated_credentials = credentials.with_subject(SUBJECT)
|
|
service = build('calendar', 'v3', credentials=delegated_credentials)
|
|
|
|
start=self.date_begin.astimezone(timezone('Europe/Paris'))
|
|
end=self.date_end.astimezone(timezone('Europe/Paris'))
|
|
|
|
start=start.isoformat()
|
|
end=end.isoformat()
|
|
diff_date=self.date_end-self.date_begin
|
|
if diff_date.days>0:
|
|
date_param=self.date_begin.strftime('%Y-%m-%d')+'-'+self.date_end.strftime('%Y-%m-%d')+'-'+str(self.id)
|
|
else:
|
|
date_param=self.date_begin.strftime('%Y-%m-%d')+'-'+str(self.id)
|
|
|
|
name_event_slug=slugify(self.name,max_length=1024, path=True)
|
|
name_param=name_event_slug.replace(' ','-')
|
|
name_param=name_param.replace('\'','-')
|
|
description='<a href="'+self.env['ir.config_parameter'].sudo().get_param('web.base.url')+'/event/'+name_param+'-'+date_param+'/register">cliquer ici pour s\'inscrire</a>'
|
|
#str(self.date_begin.year())+'-'+str(self.date_begin.month())+'-'+self.date_begin.day()
|
|
|
|
body={"summary": self.name,
|
|
"description": description,
|
|
"start": {"dateTime": start, "timeZone": 'Europe/Paris'},
|
|
"end": {"dateTime": end, "timeZone": 'Europe/Paris'},
|
|
}
|
|
|
|
#recherche de l'id calendar lié à l'étiquette de l'événément
|
|
|
|
calendar_find=False
|
|
for tag in self.tag_ids:
|
|
if tag.category_id.calendar_id:
|
|
|
|
calendar_find=True
|
|
event = service.events().insert(calendarId=tag.category_id.calendar_id, body=body).execute()
|
|
self.calendar_event_id=event['id']
|
|
self.calendar_id=tag.category_id.calendar_id
|
|
|
|
if not calendar_find: raise Warning('operation cancelled: no calendar id find, please selected a label wih category with a calendar_id')
|
|
|
|
|
|
def remove_event_from_google_agenda(self):
|
|
credentials = service_account.Credentials.from_service_account_file(GOOGLE_ACCOUNT_FILE, scopes=SCOPES)
|
|
delegated_credentials = credentials.with_subject(SUBJECT)
|
|
service = build('calendar', 'v3', credentials=delegated_credentials)
|
|
|
|
|
|
event = service.events().get(calendarId=self.calendar_id, eventId=self.calendar_event_id).execute()
|
|
#raise Warning(json.dumps(event, indent = 4) )
|
|
if event['status'] != "cancelled" :
|
|
service.events().delete(calendarId=self.calendar_id, eventId=self.calendar_event_id).execute()
|
|
|
|
self.calendar_event_id=False
|
|
self.calendar_id=False
|
|
|
|
def update_event_google_agenda(self):
|
|
credentials = service_account.Credentials.from_service_account_file(GOOGLE_ACCOUNT_FILE, scopes=SCOPES)
|
|
delegated_credentials = credentials.with_subject(SUBJECT)
|
|
service = build('calendar', 'v3', credentials=delegated_credentials)
|
|
|
|
start=self.date_begin.astimezone(timezone('Europe/Paris'))
|
|
end=self.date_end.astimezone(timezone('Europe/Paris'))
|
|
|
|
start=start.isoformat()
|
|
end=end.isoformat()
|
|
diff_date=self.date_end-self.date_begin
|
|
if diff_date.days>0:
|
|
date_param=self.date_begin.strftime('%Y-%m-%d')+'-'+self.date_end.strftime('%Y-%m-%d')+'-'+str(self.id)
|
|
else:
|
|
date_param=self.date_begin.strftime('%Y-%m-%d')+'-'+str(self.id)
|
|
|
|
name_param=self.name.replace(' ','-')
|
|
name_param=name_param.replace('\'','-')
|
|
description='<a href="'+self.env['ir.config_parameter'].sudo().get_param('web.base.url')+'/event/'+name_param+'-'+date_param+'/register">cliquer ici pour s\'inscrire</a>'
|
|
#str(self.date_begin.year())+'-'+str(self.date_begin.month())+'-'+self.date_begin.day()
|
|
|
|
body={"summary": self.name,
|
|
"description": description,
|
|
"start": {"dateTime": start, "timeZone": 'Europe/Paris'},
|
|
"end": {"dateTime": end, "timeZone": 'Europe/Paris'},
|
|
}
|
|
#event = service.events().get(calendarId=self.calendar_id, eventId=self.calendar_event_id).execute()
|
|
updated_event = service.events().update(calendarId=self.calendar_id, eventId=self.calendar_event_id, body=body).execute()
|
|
|
|
class EventTag(models.Model):
|
|
_inherit = "event.tag"
|
|
_description = 'Event tag'
|
|
|
|
hidden=fields.Boolean('hidden tag')
|