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) 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') start_day_individual_booking=fields.Date('Start day individual booking') end_day_individual_booking=fields.Date('End day individual booking') 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 _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'): rec.state='open' else: rec.state='draft' # @api.onchange('payment_status') # def _onchange_payment_status(self): # if self.payment_status=='paid' :self.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' 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 vals['name']=event.booking_product_id.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 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 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: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,vals['product_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)]) invoice.invoice_user_id=user.id invoice.user_id=user.id 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 vals['price_unit']=event.booking_down_payment vals['name']='Acompte '+event.booking_product_id.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 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 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 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 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 vals_d['account_id']=int(account_debit.id) vals_d['quantity']=1 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: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,vals['product_id'],vals['price_unit'],invoice.id) reg.balance_invoice_id=invoice.id 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 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 )