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',store=True)
    individual_booking_event=fields.Boolean(related='event_id.individual_booking_event',store=True)
    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
       
    )
    @api.model
    def _default_currency(self):
        company = self.env['res.company']._company_default_get(
            'event.registration')
        return company.currency_id
    currency_id = fields.Many2one(
        'res.currency',
        string='Currency',
        required=True,
        track_visibility='onchange',
        ondelete='restrict',
        default=_default_currency
    )

    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')
    city=fields.Char('City')
    image_right_clearance=fields.Boolean('image right clearance')
    train_arrival_time=fields.Float(string="train arrival time")
    train_arrival_date=fields.Date(string="train arrival date")
    image_permission=fields.Boolean("Image permission")
    kanban_color=fields.Char('kanban color',compute='_compute_kanban_color')
    
    invoice_state=fields.Selection(related='invoice_id.payment_state')
   
    down_payment_invoice_state=fields.Selection(related='down_payment_invoice_id.payment_state')
  
    balance_invoice_state=fields.Selection(related='balance_invoice_id.payment_state')

    invoice_id=fields.Many2one('account.move', readonly=True, ondelete="cascade")
    #invoice_state=fields.Selection(related='invoice_id.state')
    down_payment_invoice_id=fields.Many2one('account.move', ondelete="cascade")
    #down_payment_invoice_state=fields.Selection(related='down_payment_order_id.state')
    balance_invoice_id=fields.Many2one('account.move' ,ondelete="cascade")
    #balance_invoice_state=fields.Selection(related='balance_order_id.state')

    end_of_stay_invoice_id=fields.Many2one('account.move' ,string='end of stay invoice',ondelete="cascade")


    payment_status=fields.Selection(string='payment status',selection=[('paid','Paid'),('not paid','Not paid'),('down payment not paid','down payment not paid'),('down payment paid','down payment paid')],compute='_compute_payment_status',translate=True)
    to_be_paid_amount=fields.Monetary('to be paid amount',compute='_compute_to_be_paid_amount',currency_field='currency_id')
    payment_adjustement=fields.Monetary('payment adjustement',currency_field='currency_id')
    individual_room=fields.Boolean('Individual room',compute='compute_individual_room')
    
    #individual booking fields
    start_day_individual_booking=fields.Date('Start day')
    end_day_individual_booking=fields.Date('End day')
    days_duration=fields.Integer('Duration in days')
    price_individual_booking=fields.Monetary('price individual booking',currency_field='currency_id')
    
    exported_state=fields.Char('accounting exported state')

    def compute_individual_room(self):
        for rec in self:
            prd=self.env['product.product'].search([('individual_room','=',True)])
            rec.individual_room=False
            for opt in rec.option_ids:
                if prd.id==opt.booking_option_id.id : rec.individual_room=True

    def _compute_to_be_paid_amount(self):
        for rec in self:
            rec.to_be_paid_amount=0
            if rec.invoice_id :	rec.to_be_paid_amount=rec.invoice_id.amount_residual
            else:
                if rec.down_payment_invoice_id and rec.balance_invoice_id:
                    rec.to_be_paid_amount=rec.down_payment_invoice_id.amount_residual+rec.balance_invoice_id.amount_residual

    def action_cancel(self):
        self.write({'state': 'cancel'})
        #annulation de la facture liée à l'événement
        if self.invoice_id: self.invoice_id.state='cancel'
        #annulation des factures de retraites
        if self.down_payment_invoice_id: self.down_payment_invoice_id.state='cancel'
        if self.balance_invoice_id: self.balance_invoice_id.state='cancel'

    def unlink(self):
        if self.state!='cancel':raise UserError(_('This action is not allowed, please cancel the registration'))
        if self.state=='cancel':raise UserError(_('This action is not allowed,the registration is already canceled'))
    def _compute_payment_status(self):
        for rec in self:
            rec.payment_status='not paid'
            if rec.invoice_id:
                if rec.invoice_state not in ('paid'):rec.payment_status='not paid'
                if rec.invoice_state=='paid':rec.payment_status='paid'
                

            else:
                if rec.down_payment_invoice_id and rec.balance_invoice_id:
                    if rec.down_payment_invoice_state!='paid':rec.payment_status='down payment not paid'
                    if rec.down_payment_invoice_state=='paid' and rec.balance_invoice_state=='paid' :rec.payment_status='paid'
                    if rec.down_payment_invoice_state=='paid' and rec.balance_invoice_state!='paid':rec.payment_status='down payment paid'
            
            if rec.payment_status in('paid','down payment paid') and rec.state!='cancel':
                rec.state='open'
            
          
    def _compute_kanban_color(self):
        for rec in self:
            rec.kanban_color=''
            if rec.gender=='male':rec.kanban_color="50aaf3"
            if rec.gender=='femelle':rec.kanban_color="ffffff"
    @api.model
    def _read_group_room_ids(self, stages, domain, order):
        return self.env['booking.room'].search([])

    @api.model
    def create(self, vals_list):
        
        reg = super(EventRegistration, self).create(vals_list)
                
        

        return reg
    
    def action_event_registration_order(self):
        return True
    
    def create_donation(self,event_registration_id,partner_id,product_id,price_unit,invoice_id):
            vals={}
            vals['partner_id']=int(partner_id)
            vals['invoice_id']=int(invoice_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='draft'

    
    

    def remove_invoice(self):
        
        invoice=self.env['account.move'].sudo().search([('id','=',int(self.invoice_id))])
        if invoice:
            if invoice.payment_state!='paid':
                invoice.state='draft'
                invoice.posted_before=False
                invoice_id=self.invoice_id
                self.invoice_id=False

                #suppression des  lignes de paiements liés à la facture
                move_line=self.env['account.move.line'].sudo().search([('move_id','=',int(invoice_id))])
                if move_line:
                    for m in move_line:
                        self.env['account.payment.line'].sudo().search([('move_line_id','=',int(m.id))]).unlink()

                 #suppression des paiements liés à la facture
                self.env['account.payment'].sudo().search([('move_id','=',int(invoice_id))]).unlink()

                #suppression des écritures comptables lié à la facture
                self.env['account.move.line'].sudo().search([('move_id','=',int(invoice_id))]).unlink()
                #suppression de la facture
                
                self.env['account.move'].sudo().search([('id','=',int(invoice_id))]).unlink()
        
        if self.down_payment_invoice_id:
            invoice=self.env['account.move'].sudo().search([('id','=',int(self.down_payment_invoice_id))])
            if invoice:
                if invoice.payment_state!='paid':
                    invoice.state='draft'
                    invoice.posted_before=False
                    invoice_id=self.down_payment_invoice_id
                    self.down_payment_invoice_id=False
                    #suppression des  lignes de paiements liés à la facture
                    move_line=self.env['account.move.line'].sudo().search([('move_id','=',int(invoice_id))])
                    if move_line:
                        for m in move_line:
                            self.env['account.payment.line'].sudo().search([('move_line_id','=',int(m.id))]).unlink()

                    #suppression des paiements liés à la facture
                    self.env['account.payment'].sudo().search([('move_id','=',int(invoice_id))]).unlink()

                    #suppression des écritures comptables lié à la facture
                    self.env['account.move.line'].sudo().search([('move_id','=',int(invoice_id))]).unlink()
                    #suppression de la facture
                    
                    self.env['account.move'].sudo().search([('id','=',int(invoice_id))]).unlink()
        if self.balance_invoice_id:
            invoice=self.env['account.move'].sudo().search([('id','=',int(self.balance_invoice_id))])
            if invoice:
                    if invoice.payment_state!='paid':
                        invoice.state='draft'
                        invoice.posted_before=False
                        invoice_id=self.balance_invoice_id
                        self.balance_invoice_id=False
                        #suppression des  lignes de paiements liés à la facture
                        move_line=self.env['account.move.line'].sudo().search([('move_id','=',int(invoice_id))])
                        if move_line:
                            for m in move_line:
                                self.env['account.payment.line'].sudo().search([('move_line_id','=',int(m.id))]).unlink()

                        #suppression des paiements liés à la facture
                        self.env['account.payment'].sudo().search([('move_id','=',int(invoice_id))]).unlink()

                        #suppression des écritures comptables lié à la facture
                        self.env['account.move.line'].sudo().search([('move_id','=',int(invoice_id))]).unlink()
                        #suppression de la facture
                        
                        self.env['account.move'].sudo().search([('id','=',int(invoice_id))]).unlink()
                    
     
        return True

    def remove_donation(self):
        #suppression des dons existants lié à l'inscription et aux options
        donation=self.env['donation.donation'].sudo().search([('id','in',self.donation_ids.ids)])
        for d in donation:
            d.state='draft'
        self.env['donation.donation'].sudo().search([('id','in',self.donation_ids.ids)]).unlink()
        self.donation_ids=False
        return True

    def action_event_registration_generate_end_of_stay_invoice(self):
        return self.action_event_registration_generate_invoice(None,True,True)

    def action_event_registration_generate_invoice(self,id_registration=None,backoffice=True,end_of_stay_invoice=False):
        
        
        if not end_of_stay_invoice:
            #suppression des factures existantes
            #si les factures sont payés on les supprime pas
            self.remove_invoice()
            #suppression des dons existants lié aux options de l'inscription
            self.remove_donation()
        else:
            end_invoice=self.env['account.move'].sudo().search([('id','=',int(self.end_of_stay_invoice_id))])
            if end_invoice:
                if end_invoice.payment_state!='paid':
                    invoice_id=self.end_of_stay_invoice_id
                    self.end_of_stay_invoice_id=False
                    self.env['account.move'].sudo().search([('id','=',int(invoice_id))]).unlink()



        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
        if reg.partner_id.email==reg.email:
            status=reg.partner_id.member_status
        #le participant n'est pas la personne qui s'est connecté
        
        else:
            participant=self.env['res.partner'].sudo().search([('email','=',reg.email)],limit=1)
            if participant:
                status=participant.member_status
            else:
                status='not member'

        if event.individual_booking_event:
            product_price=reg.price_individual_booking
            membership_option=False
        else:

            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([])
            membership_product=self.env['product.product'].sudo().search([('membership_product','=',True)],limit=1)
            
            if membership_product:
                if selected_registrant_options:
                        for opt in selected_registrant_options:
                            #raise Warning("opt.booking_option_id="+str(opt.booking_option_id.id)+" membership_product.id="+str(membership_product.id))
                            if opt.booking_option_id.id==membership_product.id:
                                membership_option=True
                                
                                if status!="super member":
                                    product_price=event.booking_member_price
                                    
            if self.payment_adjustement!=0:
                product_price=product_price+self.payment_adjustement
            
        #calcul du montant total à régler
        if end_of_stay_invoice:product_price=0

        #création du devis sans acompte
        
        if (not reg.down_payment and reg.invoice_state!='paid') or (end_of_stay_invoice):
            if not selected_registrant_options and end_of_stay_invoice :
                return False


            #création de la facture
            vals={}
            
            vals['partner_id']=int(reg.partner_id)
            vals['invoice_date']=datetime.now()
            
            #mode de paiement CB par defaut si frontoffice
            if not backoffice:
                electronic_method=self.env['account.payment.method'].sudo().search([('code','=','electronic')],limit=1)
                if electronic_method:
                        cb_mode=self.env['account.payment.mode'].sudo().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')
            else:
                check_mode=self.env['account.payment.mode'].sudo().search([('name','=','chèque')])
                if check_mode:
                    vals['payment_mode_id']=check_mode.id
                else:
                     raise Warning('please configure check mode')

           
            vals['move_type']='out_invoice'
            vals['state']='draft'
            
            
            invoice=self.env['account.move'].sudo().create(vals)
            
            invoice.state='posted'
            invoice.name='REC'+str(invoice.id)
            invoice.payment_reference=invoice.name
            
            vals={}
            account_credit=self.env['account.account'].sudo().search([('code','=','707100')])
            account_debit=self.env['account.account'].sudo().search([('code','=','411100')])
            
            vals['move_id']=invoice.id
            vals['product_id']=int(event.booking_product_id)
            vals['quantity']=1
            vals['price_unit']=product_price
            if event.individual_booking_event:
                vals['name']=event.booking_product_id.name+' du '+str(reg.start_day_individual_booking)+' au '+str(reg.end_day_individual_booking)+ ' - '+str(reg.days_duration)+' jours'
            else:
                vals['name']=event.booking_product_id.name+ ' du '+ str(event.date_begin)+' au '+str(event.date_end)
            
            vals['account_id']=int(account_credit.id)

            invoice_line=self.env['account.move.line'].with_context(check_move_validity=False).sudo().create(vals)

            
            # #debit_line 
            vals_d={}        
            vals_d['move_id']=invoice.id
            vals_d['debit']=product_price
            vals_d['credit']=0
            vals_d['date']=datetime.now()
            vals_d['partner_id']=int(reg.partner_id)
            vals_d['product_id']=int(event.booking_product_id)
            vals_d['name']=event.booking_product_id.name + ' du '+ str(event.date_begin)+' au '+str(event.date_end)
            vals_d['account_id']=int(account_debit.id)
            vals_d['quantity']=1
            vals_d['price_unit']=product_price
            vals_d['exclude_from_invoice_tab']=True

            
            #statut payment=paid         
            invoice_line=self.env['account.move.line'].with_context(check_move_validity=False).sudo().create(vals_d)
            #statut payment=not_paid
            l=self.env['account.move.line'].sudo().search([('move_id','=',invoice.id),('balance','<',0)])
            l.partner_id=int(reg.partner_id)


            #ajout des options
            
            if selected_registrant_options:
                for option in selected_registrant_options:
                    
                    prd=self.env['product.product'].sudo().search([('id','=',int(option.booking_option_id.id))])
                    
                    #prix à appliquer aux options en fonction du statut ou de la présence de l'option d'adhesion
                    event_option=self.env['booking.option'].sudo().search(['&',('event_id','=',int(reg.event_id)),('booking_option_id','=',int(option.booking_option_id.id))],limit=1)
                    price_unit=0
                    if event_option:
                        if status=="super member":price_unit=event_option.booking_option_super_member_price
                        if status=="member":price_unit=event_option.booking_option_member_price
                        if status=="not member" and membership_option and event_option.booking_option_id.membership_product:price_unit=event_option.booking_option_price
                        if status=="not member" and membership_option and not event_option.booking_option_id.membership_product:price_unit=event_option.booking_option_member_price
                        if status=="not member" and  not membership_option:price_unit=event_option.booking_option_price
                    if backoffice:
                        if option.booking_option_id.booking_option_product_backoffice:
                            price_unit=option.booking_option_price

                    vals={}
                    vals['move_id']=invoice.id
                    #ajout du produit
                    vals['product_id']=int(option.booking_option_id.id)
                    vals['quantity']=1
                    vals['price_unit']=price_unit                   
                    vals['name']=prd.name             
                    vals['account_id']=int(account_credit.id)
                    
                    invoice_line=self.env['account.move.line'].with_context(check_move_validity=False).sudo().create(vals)
                   

                    #debit_line 
                    vals_d={}        
                    vals_d['move_id']=invoice.id
                    if price_unit>=0:
                        vals_d['debit']=price_unit
                        vals_d['credit']=0  
                    if price_unit<0:
                        vals_d['debit']=0
                        vals_d['credit']=-price_unit
                    
                    vals_d['date']=datetime.now()
                    vals_d['partner_id']=int(reg.partner_id)
                    vals_d['product_id']=int(option.booking_option_id.id)
                    vals_d['name']=prd.name
                    vals_d['account_id']=int(account_debit.id)
                    vals_d['quantity']=1
                    vals_d['price_unit']=price_unit
                    vals_d['exclude_from_invoice_tab']=True
                    
                    invoice_line=self.env['account.move.line'].with_context(check_move_validity=True).sudo().create([vals_d])
                    l=self.env['account.move.line'].sudo().search([('move_id','=',invoice.id),('balance','<',0)])
                    l.partner_id=int(reg.partner_id)
                    
                    
                    #si l'option est un produit de don on créé un don pour la personne
                    if prd.donation: self.sudo().create_donation(reg.id,reg.partner_id,prd.id,vals['price_unit'],invoice.id)

            
            if not end_of_stay_invoice:
                reg.invoice_id=invoice.id
            else:
                reg.end_of_stay_invoice_id=invoice.id

            user=self.env['res.users'].search([('email','ilike',reg.partner_id.email)],limit=1)
            invoice.invoice_user_id=user.id
            invoice.user_id=user.id
            # if event.individual_booking_event:
            #     mail_template = self.env['mail.template'].search([('name','=','individual_booking_confirmation')])
            #     mail_template.email_to = self.partner_id.email
            #     if mail_template:
            #         mail_template.with_context({'down_payment_invoice_id':self.down_payment_invoice_id}).send_mail(self.id,False)
                    #mail_template.send_mail(self.id,False)
            return invoice
            
        
        #2 factures si paiement avec acompte
        else:
            if reg.down_payment_invoice_state!='paid' and reg.down_payment and not end_of_stay_invoice:
                #création de la 1ère facture d'acompte
                vals={}
                
                vals['partner_id']=int(reg.partner_id)
                vals['invoice_date']=datetime.now()

                #mode de paiement CB par defaut
                if not backoffice:
                    electronic_method=self.env['account.payment.method'].sudo().search([('code','=','electronic')],limit=1)
                    if electronic_method:
                            cb_mode=self.env['account.payment.mode'].sudo().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')
                else:
                    check_mode=self.env['account.payment.mode'].sudo().search([('name','=','chèque')])
                    if check_mode:
                        vals['payment_mode_id']=check_mode.id
                    else:
                        raise Warning('please configure check mode')

                vals['move_type']='out_invoice'
                vals['state']='draft'
                #vals['currency_id']=self.currency_id.id
                invoice=self.env['account.move'].sudo().create(vals)
                invoice.state='posted'
                invoice.name='REC'+str(invoice.id)
                invoice.payment_reference=invoice.name
                user=self.env['res.users'].search([('email','ilike',reg.partner_id.email)],limit=1)
                invoice.invoice_user_id=user.id
                invoice.user_id=user.id
                
                vals={}
                account_credit=self.env['account.account'].sudo().search([('code','=','707100')])
                account_debit=self.env['account.account'].sudo().search([('code','=','411100')])
                
                vals['move_id']=invoice.id
                vals['product_id']=int(event.booking_product_id)
                vals['quantity']=1
                
                if event.individual_booking_event:
                    if product_price<event.booking_down_payment:
                         vals['price_unit']=product_price

                    else:
                        vals['price_unit']=event.booking_down_payment

                    vals['name']='Acompte '+event.booking_product_id.name+' du '+str(reg.start_day_individual_booking)+' au '+str(reg.end_day_individual_booking)+ '- '+str(reg.days_duration)+' jour(s)'
                else:
                    vals['price_unit']=event.booking_down_payment
                    vals['name']='Acompte '+event.booking_product_id.name+ ' du '+ str(event.date_begin)+' au '+str(event.date_end)

                
                
                vals['account_id']=int(account_credit.id)

                invoice_line=self.env['account.move.line'].with_context(check_move_validity=False).sudo().create(vals)

                
                # #debit_line 
                vals_d={}        
                vals_d['move_id']=invoice.id
                if event.individual_booking_event:
                    if product_price<event.booking_down_payment:
                        vals_d['debit']=product_price
                    else:
                        vals_d['debit']=event.booking_down_payment
                else:
                    vals_d['debit']=event.booking_down_payment
                vals_d['credit']=0
                vals_d['date']=datetime.now()
                vals_d['partner_id']=int(reg.partner_id)
                vals_d['product_id']=int(event.booking_product_id)
                vals_d['name']='Acompte '+event.booking_product_id.name
                vals_d['account_id']=int(account_debit.id)
                vals_d['quantity']=1
                if event.individual_booking_event:
                    if product_price<event.booking_down_payment:
                        vals_d['price_unit']=product_price
                    else:
                        vals_d['price_unit']=event.booking_down_payment
   
                else:
                    vals_d['price_unit']=event.booking_down_payment
                vals_d['exclude_from_invoice_tab']=True

                            
                invoice_line=self.env['account.move.line'].with_context(check_move_validity=False).sudo().create(vals_d)
                l=self.env['account.move.line'].sudo().search([('move_id','=',invoice.id),('balance','<',0)])
                l.partner_id=int(reg.partner_id)

                reg.down_payment_invoice_id=invoice.id 
            
            if reg.balance_invoice_state!='paid' and reg.down_payment and not end_of_stay_invoice:
                #création 2ème facture  de solde + paiement des options
                vals={}
                
                vals['partner_id']=int(reg.partner_id)
                vals['invoice_date']=datetime.now()


                vals['move_type']='out_invoice'
                vals['state']='draft'
                #vals['currency_id']=self.currency_id.id
                invoice=self.env['account.move'].sudo().create(vals)
                
                invoice.state='posted'
                invoice.name='REC'+str(invoice.id)
                invoice.payment_reference=invoice.name
                user=self.env['res.users'].search([('email','ilike',reg.partner_id.email)],limit=1)
                invoice.invoice_user_id=user.id
                invoice.user_id=user.id

                vals={}
                        
                vals['move_id']=invoice.id
                vals['product_id']=int(event.booking_product_id)
                vals['quantity']=1
                if event.individual_booking_event:
                    if product_price<event.booking_down_payment:
                        vals['price_unit']=0
                    else:
                        vals['price_unit']=product_price-event.booking_down_payment

                else:
                    vals['price_unit']=product_price-event.booking_down_payment
                vals['name']='solde '+event.booking_product_id.name
                
                vals['account_id']=int(account_credit.id)

                #mode de paiement CB par defaut
                if not backoffice:
                    electronic_method=self.env['account.payment.method'].sudo().search([('code','=','electronic')],limit=1)
                    if electronic_method:
                            cb_mode=self.env['account.payment.mode'].sudo().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')
                else:
                    check_mode=self.env['account.payment.mode'].sudo().search([('name','=','chèque')])
                    if check_mode:
                        vals['payment_mode_id']=check_mode.id
                    else:
                        raise Warning('please configure check mode')

                invoice_line=self.env['account.move.line'].with_context(check_move_validity=False).sudo().create(vals)
                
                
                # #debit_line 
                vals_d={}        
                vals_d['move_id']=invoice.id
                if event.individual_booking_event:
                    if product_price<event.booking_down_payment:
                        vals_d['debit']=0
                    else:
                        vals_d['debit']=product_price-event.booking_down_payment
                else:                            
                    vals_d['debit']=product_price-event.booking_down_payment
                vals_d['credit']=0
                vals_d['date']=datetime.now()
                vals_d['partner_id']=int(reg.partner_id)
                vals_d['product_id']=int(event.booking_product_id)
                vals_d['name']='solde '+event.booking_product_id.name+ ' du '+ str(event.date_begin)+' au '+str(event.date_end)
                vals_d['account_id']=int(account_debit.id)
                vals_d['quantity']=1
                if event.individual_booking_event:
                    if product_price<event.booking_down_payment:
                        vals['price_unit']=0
                    else:
                        vals['price_unit']=product_price-event.booking_down_payment
                else:
                    vals_d['price_unit']=product_price-event.booking_down_payment
                vals_d['exclude_from_invoice_tab']=True

                           
                invoice_line=self.env['account.move.line'].with_context(check_move_validity=False).sudo().create(vals_d)
                
                l=self.env['account.move.line'].sudo().search([('move_id','=',invoice.id),('balance','<',0)])
                l.partner_id=int(reg.partner_id)
                
                
                #ajout des options
                if selected_registrant_options:
                    for option in selected_registrant_options:
                        
                        prd=self.env['product.product'].sudo().search([('id','=',int(option.booking_option_id.id))])
                        
                        #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))])
                        price_unit=0
                        if event_option:
                            if status=="super member":price_unit=event_option.booking_option_super_member_price
                            if status=="member":price_unit=event_option.booking_option_member_price
                            if status=="not member" and membership_option and event_option.booking_option_id.membership_product:price_unit=event_option.booking_option_price
                            if status=="not member" and membership_option and not event_option.booking_option_id.membership_product:price_unit=event_option.booking_option_member_price
                            if status=="not member" and  not membership_option:price_unit=event_option.booking_option_price

                        
                        if backoffice:
                            if option.booking_option_id.booking_option_product_backoffice:
                                price_unit=option.booking_option_price
                        

                        vals={}
                        vals['move_id']=invoice.id
                        #ajout du produit
                        vals['product_id']=int(event.booking_product_id)
                        vals['quantity']=1
                        vals['price_unit']=price_unit                   
                        vals['name']=prd.name                    
                        vals['account_id']=int(account_credit.id)
                        invoice_line=self.env['account.move.line'].with_context(check_move_validity=False).sudo().create(vals)
                    

                        #debit_line 
                        vals_d={}        
                        vals_d['move_id']=invoice.id
                        if price_unit>=0:
                            vals_d['debit']=price_unit
                            vals_d['credit']=0
                        if price_unit<0:
                            vals_d['debit']=0
                            vals_d['credit']=-price_unit
                        vals_d['date']=datetime.now()
                        vals_d['partner_id']=int(reg.partner_id)
                        vals_d['product_id']=int(option.booking_option_id.id)
                        vals_d['name']=prd.name
                        vals_d['account_id']=int(account_debit.id)
                        vals_d['quantity']=1
                        vals_d['price_unit']=price_unit
                        vals_d['exclude_from_invoice_tab']=True
                        
                        invoice_line=self.env['account.move.line'].with_context(check_move_validity=True).sudo().create([vals_d])
                        
                        l=self.env['account.move.line'].search([('move_id','=',invoice.id),('balance','<',0)])
                        l.partner_id=int(reg.partner_id)
                        
                        
                        #si l'option est un produit de don on créé un don pour la personne
                        if prd.donation: self.sudo().create_donation(reg.id,reg.partner_id,prd.id,vals['price_unit'],invoice.id)
                
                reg.balance_invoice_id=invoice.id
                if event.individual_booking_event:
                    mail_template = self.env['mail.template'].search([('name','=','individual_booking_confirmation')])
                    mail_template.email_to = self.partner_id.email
                    if mail_template:
                        mail_template.with_context({'down_payment_invoice_id':int(self.down_payment_invoice_id)}).send_mail(self.id,False)
                        #mail_template.send_mail(self.id,False)
            return reg.down_payment_invoice_id       
    
    def info_objet(self,model_id,objet_id):
        field_list=request.env[model_id].sudo().fields_get()
        result=[]
        for key in field_list:
             result.append((key,key))
        result.sort()
        return result

    def create_payment(self,invoice_id,code_payment_method):
        invoice=self.env['account.move'].search([('id','=',int(invoice_id))])
        payment_method=self.env['account.payment.method'].search([('code','=',code_payment_method),('payment_type','=','inbound')])

        bank=self.env['account.journal'].search([('type','=','bank')])

        if not  payment_method : raise Warning ('please set up the '+code_payment_method+ ' method')
        if not  bank : raise Warning ('please set up the bank journal !')
        Payment = self.env['account.payment'].with_context(default_invoice_ids=[(4, invoice_id, False)])
        payment = Payment.create({
            'date': datetime.now(),
            'payment_method_id': payment_method.id,
            'payment_type': 'inbound',
            'partner_type': 'customer',
            'partner_id': invoice.partner_id.id,
            'amount': invoice.amount_residual,
            'journal_id': int(bank.id),
            'company_id': self.env.company,
            'currency_id': int(self.currency_id)
            #'payment_difference_handling': 'reconcile',
            #'writeoff_account_id': self.diff_income_account.id,
        })
        payment.state='posted'
        invoice.payment_id=payment.id
        invoice.payment_order_ok=True
        
    def invoice_without_registration(self,account_description):
        
        move=self.env['account.move'].search([])
        result=''
        for mv in move:
            description=''
            for line in mv.line_ids:
                    if line.product_id.name==account_description:
                        #recherche de l'inscription
                        reg=self.env['event.registration'].search([('invoice_id','=',int(mv.id))])
                        if not reg: result=result+mv.name+':'+mv.partner_id.name+'\nr'
                    break

        raise UserError(result)
        

        



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="[('id','in',selectable_option_ids)]")
        booking_option_id=fields.Many2one('product.product',string='booking options', domain="['|',('booking_option_product_backoffice','=','True'),('booking_option_product','=','True')]")
        booking_option_price=fields.Monetary('Price',currency_field='currency_id')
        booking_option_backoffice=fields.Boolean(related='booking_option_id.booking_option_product_backoffice',store=True)
        selectable_option_ids = fields.Many2many('product.product', compute='_compute_selectable_option')
        event_registration_id=fields.Many2one(
            'event.registration',
            String='Event registration',
            index=True,
            readonly=True,
            track_visibility='onchange',
            
        )
        def _compute_selectable_option(self):
            selectable_options=self.env['booking.option'].search([('event_id','=',int(self.event_registration_id.event_id))])
            if selectable_options:
                self.selectable_option_ids=selectable_options.booking_option_id.ids
                

        @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
        )