from odoo import models, fields, api from odoo.exceptions import UserError, ValidationError from psycopg2 import sql, DatabaseError from werkzeug import utils import json import logging import xlwt from io import BytesIO import base64 import csv _logger = logging.getLogger(__name__) MASS_MAILING_BUSINESS_MODELS = [ 'crm.lead', 'event.registration', 'hr.applicant', 'res.partner', 'event.track', 'sale.order', 'mailing.list', 'mailing.contact' ] class opendons_operation(models.Model): _name = 'opendons.operation' _description = 'opération marketing : mailing, emailing evenements' _inherit = ['mail.thread'] code=fields.Char(string='Code',required=True, translate=True,track_visibility='always') name=fields.Char(string='Name',required=True, translate=True,track_visibility='always') partner_count = fields.Integer(string="count",readonly=True) #begin_date=fields.Date(string='Date begin',required=True, translate=True,track_visibility='always') #end_date=fields.Date(string='Date end',required=True, translate=True,track_visibility='always') chanel=fields.Selection([ ('mail', 'Mailing'), ('email', 'E-mailing'), ('event', 'Event')], string='Chanel',required=True, translate=True,track_visibility='always') user_id = fields.Many2one('res.users', string='Author', default=lambda self: self.env.uid) cost = fields.Monetary( string='Cost', currency_field='currency_id') @api.model def _default_currency(self): company = self.env['res.company']._company_default_get( 'opendons.operation') return company.currency_id currency_id = fields.Many2one( 'res.currency', string='Currency', required=True, track_visibility='onchange', ondelete='restrict', default=_default_currency ) _sql_constraints = [ ('name_uniq', 'unique (name)', "Name already exists !"), ('code_uniq', 'unique (code)', "Code already exists !"), ] number_of_sending = fields.Integer( compute='_compute_number_of_sending', string="# of sending", readonly=True ) segment_ids = fields.One2many( 'opendons.segment', 'operation_id', string='Segments', readonly=True ) segment_count = fields.Integer( string="# of segment", readonly=True ) state = fields.Selection([ ('draft', 'Draft'), ('done', 'Done'), ('cancel', 'Cancelled')], string='State', readonly=True, copy=False, default='draft', index=True, track_visibility='onchange' ) csv_export = fields.Binary('csv export', filters='.csv', readonly=True) document_fname=fields.Char() # def _compute_segment_count(self): # # The current user may not have access rights for donations # for operation in self: # try: # operation.segment_count = len(operation.segment_ids) # except Exception: # operation.segment_count = 0 def validate(self): for operation in self: vals = {'state': 'done'} operation.write(vals) return def done2cancel(self): '''from Done state to Cancel state''' for operation in self: operation.state = 'cancel' def cancel2draft(self): '''from Cancel state to Draft state''' for operation in self: operation.state = 'draft' def csv_export_operation(self): with open('export.csv', mode='w') as file: writer = csv.writer(file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL) # create a row contains heading of each column writer.writerow(['name', 'email']) # fetch products and write respective data. partners = self.env['res.partner'].sudo().search([]) for p in partners: name=p.name email=p.email writer.writerow([name,email]) with open('export.csv', 'r', encoding="utf-8") as f2: # file encode and store in a variable ‘data’ data = str.encode(f2.read(), 'utf-8') self.csv_export=base64.encodestring(data) self.document_fname='operation'+str(self.id)+'.csv' return def export_partners(self): partners = self.env['res.partner'].sudo().search([]) stream = BytesIO() book = xlwt.Workbook(encoding='utf-8') sheet = book.add_sheet(u'{}'.format(u'My Sheet')) row = 1 cell = 0 for p in partners: sheet.write(row, cell, p.name) row += 1 book.save(stream) self.excel_report = base64.encodestring(stream.getvalue()) self.document_fname='operation'+seld.id+'.csv' return class opendons_segment(models.Model): _name = 'opendons.segment' _description = 'operation marketing segment : a segment is a part of contacts selected for an operation ' _inherit = ['mail.thread'] sequence = fields.Integer(string="sequence", default=10) code=fields.Char(string='Code',required=True, translate=True,track_visibility='always') name=fields.Char(string='Name',required=True, translate=True,track_visibility='always') exclusion=fields.Boolean(String='segment d\'exclusion',default=False) logical_operator = fields.Selection([('union','union'),('inter','intersection')],'Type',default='union') cost = fields.Monetary( string='Cost', currency_field='currency_id') partner_count = fields.Integer(string="count",readonly=True) @api.model def _default_currency(self): company = self.env['res.company']._company_default_get( 'opendons.segment') return company.currency_id currency_id = fields.Many2one( 'res.currency', string='Currency', required=True, track_visibility='onchange', ondelete='restrict', default=_default_currency ) operation_id = fields.Many2one( 'opendons.operation', String='Operation', index=True, readonly=True, track_visibility='onchange', ondelete='restrict' ) ensemble_ids = fields.One2many( 'opendons.ensemble', 'segment_id', string='Ensemble', required=True, track_visibility='onchange') ensemble_count = fields.Integer( compute='_compute_ensemble_count', string="# of ensemble", readonly=True ) def _compute_ensemble_count(self): # The current user may not have access rights for donations for segment in self: try: segment.ensemble_count = len(segment.ensemble_ids) except Exception: segment.ensemble_count = 0 @api.model def create(self,vals): res=super(opendons_segment, self).create(vals) #segment=self.env['opendons.segment'].search([('id','=',int(res.id))]) operation=self.env['opendons.operation'].search([('id','=',int(res.operation_id))]) #_logger.error('segment.id='+str(res.operation_id)) operation.write({'segment_count':len(operation.segment_ids)}) return res class opendons_ensemble(models.Model): _name = 'opendons.ensemble' _description = 'operation marketing ensemble : an ensemble is a part of contacts selected for an segment ' _inherit = ['mail.thread'] name=fields.Char(string='Name',required=True, translate=True,track_visibility='always') logical_operator = fields.Selection([('union','union'),('inter','intersection')],'Type',default='union') mailing_domain = fields.Char( string='partners selection', readonly=True, store=True) partner_count = fields.Integer(string="count",readonly=True) sequence = fields.Integer(string="sequence", default=10) segment_id = fields.Many2one( 'opendons.segment','Segment', index=True, readonly=True, track_visibility='onchange', ondelete='restrict') request_ids = fields.One2many( 'opendons.request', 'ensemble_id', string='Request', required=True, track_visibility='onchange') request_count = fields.Integer( compute='_compute_request_count', string="# of request", readonly=True ) csv_export = fields.Binary('csv export', filters='.csv', readonly=True) document_fname=fields.Char() def csv_export_ensemble(self): with open('export.csv', mode='w') as file: writer = csv.writer(file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL) # create a row contains heading of each column writer.writerow(['name', 'email']) # fetch products and write respective data. partners = self.env['res.partner'].sudo().search([]) for p in partners: name=p.name email=p.email writer.writerow([name,email]) with open('export.csv', 'r', encoding="utf-8") as f2: # file encode and store in a variable ‘data’ data = str.encode(f2.read(), 'utf-8') self.csv_export=base64.encodestring(data) self.document_fname='contacts.csv' return def _compute_request_count(self): # The current user may not have access rights for donations for ensemble in self: try: ensemble.request_count = len(ensemble.request_ids) except Exception: ensemble.request_count = 0 @api.model def create(self,vals): res=super(opendons_ensemble, self).create(vals) segment=self.env['opendons.segment'].search([('id','=',int(res.segment_id))]) #_logger.error('segment.id='+str(res.operation_id)) segment.write({'ensemble_count':len(segment.ensemble_ids)}) return res def write(self,vals): res=super(opendons_ensemble, self).write(vals) mailing_domain=False for val in vals: if val=='logical_operator': mailing_domain=self.env['opendons.request'].update_ensemble_domaine(self) if mailing_domain: vals['mailing_domain']=mailing_domain res=super(opendons_ensemble, self).write(vals) class opendons_request(models.Model): _name = 'opendons.request' _description = 'operation marketing request : a request is a part of contacts selected for an ensemble ' _inherit = ['mail.thread'] sequence = fields.Integer(string="sequence", default=10) name=fields.Char(string='Name',required=True, translate=True,track_visibility='always') partner_count = fields.Integer(string="count",readonly=True) partner_ids = fields.Many2many('res.partner', 'partner_request_rel', 'partner_id', 'request_id', string='partners') ensemble_id = fields.Many2one( 'opendons.ensemble','Ensemble', index=True, readonly=True, track_visibility='onchange', ondelete='restrict') mailing_domain = fields.Char( string='Domain', readonly=False, store=True) def count_partners_ensemble(self,ensemble): #on boucle sur toutes les requêtes de l'ensemble pour compter les contacts result=0 for req in ensemble.request_ids: result+=req.partner_count return result def update_ensemble_domaine(self,ensemble): #on boucle sur toutes les requêtes de l'ensemble logical_operator=ensemble.logical_operator if logical_operator=='union': str_operator='"|",' if logical_operator=='inter': str_operator='"&",' mailing_domain='' if len(ensemble.request_ids)>1: i=1 for req in ensemble.request_ids: if i==1: mailing_domain=req.mailing_domain[1:-1] if i>1 : mailing_domain=str_operator +mailing_domain+","+req.mailing_domain[1:-1] i+=1 mailing_domain="["+mailing_domain+"]" if len(ensemble.request_ids)==1: mailing_domain=req.mailing_domain return mailing_domain def count_partners_segment(self,segment): #on boucle sur toutes les requêtes de l'ensemble pour compter les contacts result=0 for ensemble in segment.ensemble_ids: result+=ensemble.partner_count return result def count_partners_operation(self,operation): #on boucle sur toutes les requêtes de l'ensemble pour compter les contacts result=0 for segment in operation.segment_ids: result+=segment.partner_count return result def count_partner_request(self,vals): if vals['mailing_domain']: partners=self.env['res.partner'].search(eval(vals['mailing_domain'])) else: partners=self.env['res.partner'] result=len(partners) return result def refresh_partners_count(self): for r in self: r.partner_count=self.env['res.partner'].search_count(eval(r.mailing_domain)) return True @api.model def create(self,vals): partners=self.count_partner_request(vals) res=super(opendons_request, self).create(vals) #mise à jour du nombre de requête pour l'ensemble,le segment et l'opération liée ensemble=self.env['opendons.ensemble'].search([('id','=',int(res.ensemble_id))]) #partner_count=self.count_partners_ensemble(ensemble) #mise à jour du domaine pour l'ensemble ensemble_domaine=self.update_ensemble_domaine(ensemble) ensemble.write( {'request_count':len(ensemble.request_ids), 'mailing_domain':ensemble_domaine }) # segment=self.env['opendons.segment'].search([('id','=',int(ensemble.segment_id))]) # partner_count=self.count_partners_segment(segment) # segment.write({ # 'partner_count':partner_count # }) # operation=self.env['opendons.operation'].search([('id','=',int(segment.operation_id))]) # partner_count=self.count_partners_operation(operation) # operation.write({ # 'partner_count':partner_count # }) return res def write(self,vals): mailing_domain_update=False for val in vals: if val=='mailing_domain': mailing_domain_update=True partners_count=self.count_partner_request(vals) #partner_count=len(partners) #partner_ids=[(6, 0,partners.ids)] if mailing_domain_update==True : vals['partner_count']=partners_count res=super(opendons_request, self).write(vals) if mailing_domain_update==True: # #mise à jour du nombre de requête pour l'ensemble lié ensemble=self.env['opendons.ensemble'].search([('id','=',int(self.ensemble_id))]) ensemble_domaine=self.update_ensemble_domaine(ensemble) # partner_count=self.count_partners_ensemble(ensemble) ensemble.write({ 'request_count':len(ensemble.request_ids), 'mailing_domain':ensemble_domaine }) # segment=self.env['opendons.segment'].search([('id','=',int(ensemble.segment_id))]) # partner_count=self.count_partners_segment(segment) # segment.write({ # 'partner_count':partner_count # }) # operation=self.env['opendons.operation'].search([('id','=',int(segment.operation_id))]) # partner_count=self.count_partners_operation(operation) # operation.write({ # 'partner_count':partner_count # }) return res