from odoo import models, fields, api from odoo.exceptions import UserError, ValidationError, Warning from psycopg2 import sql, DatabaseError from dateutil.relativedelta import relativedelta from datetime import datetime from werkzeug import utils class EventRegistration(models.Model): _inherit = 'event.registration' room_id = fields.Many2one( 'booking.room', String='Room', index=True, group_expand='_read_group_room_ids', track_visibility='onchange', ) booking_event=fields.Boolean(related='event_id.booking_event') event_end=fields.Boolean(related='event_id.stage_id.pipe_end') medical_concern=fields.Selection( [('have medical concern','I have a medical concern to report'), ('have no medical concern','I have no medical concern to report'), ('no answer','I don\'t want to answer')], string='Medical concern', ) medical_information=fields.Char('Medical informations') medical_contact_name=fields.Char('Name and Firstname of the contact') medical_contact_phone=fields.Char('Phone of the contact') questionnaire_ids=fields.One2many( 'event.registration_questionnaire', 'event_registration_id', String='Questionnaire', readonly=True ) option_ids=fields.One2many( 'event.registration_option', 'event_registration_id', String='Options', readonly=True ) donation_ids=fields.One2many( 'donation.donation', 'event_registration_id', String='Donations', readonly=True ) down_payment=fields.Boolean('down payment',default=False) firstname=fields.Char('Firstname') age=fields.Integer('Age') gender=fields.Selection([('male','Male'),('femelle','Femelle')],string='gender') mobile=fields.Char('Mobile') kanban_color=fields.Char('kanban color',compute='_compute_kanban_color') order_id=fields.Many2one('sale.order') order_state=fields.Selection(related='order_id.state') down_payment_order_id=fields.Many2one('sale.order') down_payment_order_state=fields.Selection(related='down_payment_order_id.state') balance_order_id=fields.Many2one('sale.order') balance_order_state=fields.Selection(related='balance_order_id.state') payment_status=fields.Char(string='payment status',compute='_compute_payment_status') def _compute_payment_status(self): for rec in self: rec.payment_status='undefined' if rec.order_id: if rec.order_state in ('draft','sent'):rec.payment_status='not paid' if rec.order_state=='sale':rec.payment_status='paid' if rec.order_state in ('done','cancel'):rec.payment_status=rec.order_state else: if rec.down_payment_order_id and balance_order_state: if rec.down_payment_order_state in ('draft','sent'):rec.payment_status='down payment not paid' if rec.down_payment_order_state=='sale' and rec.balance_payment_order_state=='sale' :rec.payment_status='paid' if rec.down_payment_order_state=='sale' and rec.balance_payment_order_state!='sale':rec.payment_status='down payment paid' def _compute_kanban_color(self): for rec in self: rec.kanban_color='' if rec.gender=='male':rec.kanban_color="d0e0e3" if rec.gender=='femelle':rec.kanban_color="eebbcc" @api.model def _read_group_room_ids(self, stages, domain, order): return self.env['booking.room'].search([]) @api.model_create_multi def create(self, vals_list): registrations = super(EventRegistration, self).create(vals_list) if registrations._check_auto_confirmation(): registrations.sudo().action_confirm() #ajout du questionnaire pour la personne inscrite questions=self.env['event.question'].search([('event_id','=',int(registrations.event_id))]) if questions: for question in questions: vals={} vals['sequence']=question.sequence vals['question']=question.question vals['event_registration_id']=registrations.id res=self.env['event.registration_questionnaire'].create(vals) #ajout des options pour la personne inscrite options=self.env['booking.option'].search([('event_id','=',int(registrations.event_id))]) if options: for option in options: vals={} vals['booking_option_id']=int(option.booking_option_id) vals['booking_option_price']=option.booking_option_price vals['event_registration_id']=int(registrations.id) res=self.env['event.registration_option'].create(vals) return registrations def action_event_registration_order(self): return True def create_donation(self,event_registration_id,partner_id,product_id,price_unit): vals={} vals['partner_id']=int(partner_id) #raise Warning(vals['partner_id']) vals['donation_date']=datetime.now() vals['tax_receipt_option']='annual' #mode de paiement CB par defaut electronic_method=self.env['account.payment.method'].search([('code','=','electronic')],limit=1) if electronic_method: cb_mode=self.env['account.payment.mode'].search([('payment_method_id','=',int(electronic_method.id))],limit=1) if cb_mode: vals['payment_mode_id']=cb_mode.id else: raise Warning('please configure credit card mode') #tant que le devis n'est pas validé (paiment effectué), le don est en brouillon vals['state']='draft' vals['payment_ref']='internet' donation_draft=self.env['donation.donation'].sudo().create(vals) #ajout du don au niveau de l'inscription reg=self.env['event.registration'].search([('id','=',int(event_registration_id))]) if reg: reg.write({'donation_ids':[(4,int(donation_draft.id))]}) vals={} #create line donation vals['donation_id']=donation_draft.id product=self.env['product.product'].search([('id','=',int(product_id))]) vals['product_id']=int(product_id) vals['display_name']=product.name vals['quantity']=1 vals['unit_price']=price_unit vals['tax_receipt_ok']=product.tax_receipt_ok donation_line=self.env['donation.line'].sudo().create(vals) donation_draft.state='done' def action_event_registration_generate_order(self,id_registration=None): #suppression des devis existants if self.order_id: self.env['sale.order'].search([('id','=',int(self.order_id))]).unlink() self.order_id=False if self.down_payment_order_id: self.env['sale.order'].search([('id','=',int(self.down_payment_order_id))]).unlink() self.down_payment_order_id=False if self.balance_order_id: self.env['sale.order'].search([('id','=',int(self.balance_order_id))]).unlink() self.balance_order_id=False #suppression des dons existants self.env['donation.donation'].search([('id','in',self.donation_ids)]).unlink() self.donation_ids=False if id_registration:reg=self.env['event.registration'].search([('id','=',int(id_registration))]) else : reg=self event=self.env['event.event'].search([('id','=',int(reg.event_id))]) selected_registrant_options=self.env['event.registration_option'].search([ ('event_registration_id','=',int(reg.id))]) #controles avant traitement : un produit doit être associé à l'événement if not event.booking_product_id: raise Warning('product missing for event booking') #Prix à appliquer au produit en fonction du statut de l'inscrit status=reg.partner_id.member_status product_price=event.booking_price if status=='not member':product_price=event.booking_price if status=='member':product_price=event.booking_member_price if status=='super member':product_price=event.booking_super_member_price #Prix à appliquer au produit si paiement de l'adhésion membership_option=False membership_product=self.env['event.membership_product'].search([]) if membership_product: if selected_registrant_options: for opt in selected_registrant_options: if opt.booking_option_id==membership_product.id: membership_option=True if status!="super member": product_price=event.booking_member_price #calcul du montant total à régler #création du devis sans accompte if not reg.down_payment: #création du devis vals={} vals['partner_id']=int(reg.partner_id) order=self.env['sale.order'].create(vals) #création des lignes de devis vals={} vals['order_id']=order.id #ajout du produit vals['product_id']=int(event.booking_product_id) vals['product_uom_qty']=1 vals['price_unit']=product_price vals['name']=event.booking_product_id.name order_line=self.env['sale.order.line'].create(vals) #ajout des options vals={} if selected_registrant_options: for option in selected_registrant_options: vals['order_id']=order.id vals['product_id']=int(option.booking_option_id.id) vals['product_uom_qty']=1 prd=self.env['product.product'].search([('id','=',int(option.booking_option_id.id))]) vals['name']=prd.name #prix à appliquer aux options en fonction du statut ou de la présence de l'option d'adhesion event_option=self.env['booking.option'].search(['&',('event_id','=',int(reg.event_id)),('booking_option_id','=',int(option.booking_option_id.id))]) if event_option: if status=="super member":vals['price_unit']=event_option.booking_option_super_member_price if status=="member":vals['price_unit']=event_option.booking_option_member_price if status=="not member" and membership_option: vals['price_unit']=event_option.booking_option_member_price if status=="not member" and not membership_option: vals['price_unit']=event_option.booking_option_price order_line=self.env['sale.order.line'].create(vals) #si l'option est un produit de don on créé un don pour la personne #if prd.donation: self.create_donation(reg.id,reg.partner_id,vals['product_id'],vals['price_unit']) order.message_subscribe(partner_ids=order.partner_id.ids) order.state='sent' reg.order_id=order.id return order.id #2 devis si paiement avec acompte else: #création du 1er devis d'acompte vals={} vals['partner_id']=int(reg.partner_id) order=self.env['sale.order'].create(vals) #création des lignes de devis vals={} vals['order_id']=order.id #ajout du produit vals['product_id']=int(event.booking_product_id) vals['product_uom_qty']=1 vals['price_unit']=event.booking_down_payment vals['name']='Acompte '+event.booking_product_id.name order_line=self.env['sale.order.line'].create(vals) order.message_subscribe(partner_ids=order.partner_id.ids) order.state='sent' reg.down_payment_order_id=order.id #création du 2ème devis de solde + paiement des options vals={} vals['partner_id']=int(reg.partner_id) order2=self.env['sale.order'].create(vals) #création des lignes de devis vals={} vals['order_id']=order2.id #ajout du produit vals['product_id']=int(event.booking_product_id) vals['product_uom_qty']=1 vals['price_unit']=product_price-event.booking_down_payment vals['name']='solde '+event.booking_product_id.name order_line=self.env['sale.order.line'].create(vals) #ajout des options vals={} if selected_registrant_options: for option in selected_registrant_options: vals['order_id']=order2.id vals['product_id']=int(option.booking_option_id.id) vals['product_uom_qty']=1 prd=self.env['product.product'].search([('id','=',int(option.booking_option_id.id))]) vals['name']=prd.name #prix à appliquer aux options en fonction du statut ou de la présence de l'option d'adhesion event_option=self.env['booking.option'].search(['&',('event_id','=',int(reg.event_id)),('booking_option_id','=',int(option.booking_option_id.id))]) if event_option: if status=="super member":vals['price_unit']=event_option.booking_option_super_member_price if status=="member":vals['price_unit']=event_option.booking_option_member_price if status=="not member" and membership_option: vals['price_unit']=event_option.booking_option_member_price if status=="not member" and not membership_option: vals['price_unit']=event_option.booking_option_price order_line=self.env['sale.order.line'].create(vals) order2.message_subscribe(partner_ids=order2.partner_id.ids) order2.state='sent' reg.balance_order_id=order2.id return order.id class EventRegistration_questionnaire(models.Model): _name = 'event.registration_questionnaire' _description = 'event registration questionnaire' sequence = fields.Integer(string="sequence", default=10) question=fields.Text(string='question',readonly=True) answer=fields.Text(string='answer') event_registration_id=fields.Many2one( 'event.registration', String='Event registration', index=True, readonly=True, track_visibility='onchange', ondelete='cascade' ) class EventRegistration_option(models.Model): _name = 'event.registration_option' _description = 'event registration option' booking_option_id=fields.Many2one('product.product',string='booking options',domain="[('booking_option_product','=','True')]") booking_option_price=fields.Monetary('Price',currency_field='currency_id',readonly=True) event_registration_id=fields.Many2one( 'event.registration', String='Event registration', index=True, readonly=True, track_visibility='onchange', ) @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, states={'done': [('readonly', True)]}, track_visibility='onchange', ondelete='restrict', default=_default_currency )