|
@ -9,6 +9,7 @@ import xlwt |
|
|
from io import BytesIO |
|
|
from io import BytesIO |
|
|
import base64 |
|
|
import base64 |
|
|
import csv |
|
|
import csv |
|
|
|
|
|
import os,secrets |
|
|
|
|
|
|
|
|
_logger = logging.getLogger(__name__) |
|
|
_logger = logging.getLogger(__name__) |
|
|
|
|
|
|
|
@ -33,7 +34,9 @@ class opendons_operation(models.Model): |
|
|
partner_count = fields.Integer(string="count",readonly=True) |
|
|
partner_count = fields.Integer(string="count",readonly=True) |
|
|
#begin_date=fields.Date(string='Date begin',required=True, translate=True,track_visibility='always') |
|
|
#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') |
|
|
#end_date=fields.Date(string='Date end',required=True, translate=True,track_visibility='always') |
|
|
|
|
|
|
|
|
|
|
|
partner_ids = fields.Many2many('res.partner', 'partner_operation_rel', 'partner_id', 'operation_id', string='partners') |
|
|
|
|
|
#contacts exclus de l'opération |
|
|
|
|
|
partner_excl_ids=fields.Many2many('res.partner', 'partner_excl_operation_rel', 'partner_id', 'operation_id', string='excluded partners') |
|
|
chanel=fields.Selection([ |
|
|
chanel=fields.Selection([ |
|
|
('mail', 'Mailing'), |
|
|
('mail', 'Mailing'), |
|
|
('email', 'E-mailing'), |
|
|
('email', 'E-mailing'), |
|
@ -93,9 +96,6 @@ class opendons_operation(models.Model): |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
csv_export = fields.Binary('csv export', filters='.csv', readonly=True) |
|
|
csv_export = fields.Binary('csv export', filters='.csv', readonly=True) |
|
|
document_fname=fields.Char() |
|
|
document_fname=fields.Char() |
|
|
|
|
|
|
|
@ -133,35 +133,162 @@ class opendons_operation(models.Model): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def csv_export_operation(self): |
|
|
def csv_export_operation(self): |
|
|
|
|
|
|
|
|
with open('export.csv', mode='w') as file: |
|
|
|
|
|
|
|
|
tmstp=secrets.token_hex(16) |
|
|
|
|
|
csv_filename='/tmp/export_'+tmstp+'.csv' |
|
|
|
|
|
with open(csv_filename, mode='w') as file: |
|
|
writer = csv.writer(file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL) |
|
|
writer = csv.writer(file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL) |
|
|
# ggcreate a row containds heading of each column |
|
|
|
|
|
|
|
|
|
|
|
writer.writerow(['name', 'email']) |
|
|
|
|
|
# fetch products and write respective data. |
|
|
|
|
|
partners = self.select_partner_operation() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for p in partners: |
|
|
|
|
|
name=p.name |
|
|
|
|
|
email=p.email |
|
|
|
|
|
writer.writerow([name,email]) |
|
|
|
|
|
|
|
|
writer.writerow(['id','key','name', 'email','operation','segment']) |
|
|
|
|
|
|
|
|
|
|
|
#sélections des contacts |
|
|
|
|
|
res=self.select_partner_operation() |
|
|
|
|
|
|
|
|
with open('export.csv', 'r', encoding="utf-8") as f2: |
|
|
|
|
|
|
|
|
segments=self.env['opendons.segment'].search(['&',('operation_id','=',self.id),('exclusion','=',False)]) |
|
|
|
|
|
|
|
|
|
|
|
#extraction des contacts sélectionnés sur chaque segment |
|
|
|
|
|
for seg in segments: |
|
|
|
|
|
if seg.partner_ids: |
|
|
|
|
|
for p in seg.partner_ids: |
|
|
|
|
|
#raise UserError(p) |
|
|
|
|
|
id=p.id |
|
|
|
|
|
key=p.key |
|
|
|
|
|
name=p.name |
|
|
|
|
|
email=p.email |
|
|
|
|
|
operation=int(self.id) |
|
|
|
|
|
segment=int(seg.id) |
|
|
|
|
|
writer.writerow([id,key,name,email,operation,segment]) |
|
|
|
|
|
|
|
|
|
|
|
with open(csv_filename, 'r', encoding="utf-8") as f2: |
|
|
# file encode and store in a variable ‘data’ |
|
|
# file encode and store in a variable ‘data’ |
|
|
data = str.encode(f2.read(), 'utf-8') |
|
|
data = str.encode(f2.read(), 'utf-8') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.csv_export=base64.encodestring(data) |
|
|
self.csv_export=base64.encodestring(data) |
|
|
self.document_fname='operation'+str(self.id)+'.csv' |
|
|
self.document_fname='operation'+str(self.id)+'.csv' |
|
|
|
|
|
|
|
|
|
|
|
os.unlink(csv_filename) |
|
|
return |
|
|
return |
|
|
#def select_partner_operation(self): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def select_partner_operation(self): |
|
|
|
|
|
|
|
|
|
|
|
# suppression selections précédemment calculées sur l'opération |
|
|
|
|
|
self.partner_ids=False |
|
|
|
|
|
self.partner_excl_ids=False |
|
|
|
|
|
|
|
|
|
|
|
#suppression des selections précédemment calculées sur sur les segments |
|
|
|
|
|
segments=self.env['opendons.segment'].search(['&',('operation_id','=',self.id),('exclusion','=',False)]) |
|
|
|
|
|
for seg in segments: |
|
|
|
|
|
seg.partner_ids=False |
|
|
|
|
|
|
|
|
|
|
|
segexcl=self.env['opendons.segment'].search(['&',('operation_id','=',self.id),('exclusion','=',True)]) |
|
|
|
|
|
segments=self.env['opendons.segment'].search(['&',('operation_id','=',self.id),('exclusion','=',False)],order='sequence asc') |
|
|
|
|
|
|
|
|
|
|
|
#[["id","not in",[1,3,7,8,10]]] |
|
|
|
|
|
#["&",["id","not in",[22]],["id","not in",[1,3,7,8,10]]] |
|
|
|
|
|
# partner_excl=self.env['res.partner'].search(eval(segexcl.mailing_domain)) |
|
|
|
|
|
# raise UserError(str(partner_excl)) |
|
|
|
|
|
# str_excl="[" |
|
|
|
|
|
# i=1 |
|
|
|
|
|
# for p in partner_excl: |
|
|
|
|
|
# if i==1: str_excl=str_excl+str(p.id) |
|
|
|
|
|
# if i>1 : str_excl=str_excl+','+str(p.id) |
|
|
|
|
|
# str_excl=str_excl+']' |
|
|
|
|
|
# excl_domain='["id","not in"',+str_excl +']' |
|
|
|
|
|
#List of Domain operators: ! (Not), | (Or), & (And) |
|
|
|
|
|
#List of Term operators: '=', '!=', '<=', '<', '>', '>=', '=?', '=like', '=ilike', 'like', 'not like', 'ilike', 'not ilike', 'in', 'not in', 'child_of' |
|
|
|
|
|
|
|
|
|
|
|
#excl_domain='[("operation_excl_ids","!=","'+self.id+"')]" |
|
|
|
|
|
i=1 |
|
|
|
|
|
|
|
|
|
|
|
for sg in segments: |
|
|
|
|
|
if i==1: |
|
|
|
|
|
|
|
|
|
|
|
mailing_domain='["&","!",'+segexcl.mailing_domain[1:-1]+','+ sg.mailing_domain[1:-1]+']' |
|
|
|
|
|
|
|
|
|
|
|
#["&","!",["id","=",1],["id","=",2]] |
|
|
|
|
|
#["&","!",[["id","=",1]],[["id","=",1]]] |
|
|
|
|
|
#raise UserError(str(mailing_domain)) |
|
|
|
|
|
#try: |
|
|
|
|
|
partners=self.env['res.partner'].search(eval(mailing_domain)) |
|
|
|
|
|
#except: |
|
|
|
|
|
# raise UserError(mailing_domain) |
|
|
|
|
|
|
|
|
|
|
|
#ajouts des contact à l'opération |
|
|
|
|
|
self.partner_ids=partners |
|
|
|
|
|
#ajouts des contacts au segment |
|
|
|
|
|
sg.partner_ids=partners |
|
|
|
|
|
#sg_1=sg |
|
|
|
|
|
else: |
|
|
|
|
|
#on doit exclure tous les contacts qui pourraient être dans les segments précédent |
|
|
|
|
|
sg_up=self.env['opendons.segment'].search(['&',('operation_id','=',self.id),('sequence','<',int(sg.sequence))]) |
|
|
|
|
|
if len(sg_up)>1: |
|
|
|
|
|
str_domain='"&",' |
|
|
|
|
|
j=1 |
|
|
|
|
|
for s in sg_up: |
|
|
|
|
|
if j==1: |
|
|
|
|
|
str_domain=str_domain + s.mailing_domain[1:-1] |
|
|
|
|
|
else: |
|
|
|
|
|
str_domain= '"&",' + str_domain & s.mailing_domain[1:-1] |
|
|
|
|
|
j=j+1 |
|
|
|
|
|
str_domain=str_domain+',' |
|
|
|
|
|
else: |
|
|
|
|
|
str_domain='' |
|
|
|
|
|
|
|
|
|
|
|
#mailing_domain='["&","!","&",'+segexcl.mailing_domain[1:-1]+','+ sg_1.mailing_domain[1:-1]+',' +sg.mailing_domain[1:-1]+']' |
|
|
|
|
|
mailing_domain='["&","!",'+str_domain+ segexcl.mailing_domain[1:-1]+',' +sg.mailing_domain[1:-1]+']' |
|
|
|
|
|
#raise UserError(str_domain) |
|
|
|
|
|
partners=self.env['res.partner'].search(eval(mailing_domain)) |
|
|
|
|
|
#ajouts des contact à l'opération |
|
|
|
|
|
self.partner_ids=partners |
|
|
|
|
|
#ajouts des contacts au segment |
|
|
|
|
|
sg.partner_ids=partners |
|
|
|
|
|
sg_1=sg |
|
|
|
|
|
|
|
|
|
|
|
i=i+1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return True |
|
|
|
|
|
|
|
|
|
|
|
def select_partner_operation_old(self): |
|
|
|
|
|
|
|
|
#le principe est de selectionner les contacts associés aux segments avec les règles suivantes : |
|
|
#le principe est de selectionner les contacts associés aux segments avec les règles suivantes : |
|
|
#RG1: si un contact est présent dans un segment d'exclusion, alos on le retire de la sélection |
|
|
|
|
|
#RG2: la priorité des segments est l'ordre de présentation dans la liste des segmments |
|
|
|
|
|
#RG3: au final, un contact sélectionné est rattaché à l'opération avec le segment d'appartenance |
|
|
|
|
|
|
|
|
#RG1: la priorité des segments est l'ordre de présentation dans la liste des segments |
|
|
|
|
|
#RG2: au final, un contact sélectionné est rattaché à l'opération avec le segment d'appartenance |
|
|
|
|
|
#RG1: si un contact est présent dans un segment d'exclusion, alors on le retire de la sélection operateur "!"" |
|
|
|
|
|
|
|
|
|
|
|
#suppression des contacts déjà présents pour l'opération |
|
|
|
|
|
self.env["opendons.operation_partner"].search([('operation_id','=',self.id)]).unlink() |
|
|
|
|
|
|
|
|
|
|
|
segments=self.env['opendons.segment'].search(['&',('operation_id','=',self.id),('exclusion','=','False')],order='sequence asc') |
|
|
|
|
|
i=1 |
|
|
|
|
|
for sg in segments: |
|
|
|
|
|
if i==1: |
|
|
|
|
|
partners=self.env['res.partner'].search(eval(sg.mailing_domain)) |
|
|
|
|
|
for p in partners: |
|
|
|
|
|
vals={} |
|
|
|
|
|
vals['operation_id']=self.id |
|
|
|
|
|
vals['segment_id']=sg.id |
|
|
|
|
|
vals['partner_id']=p.id |
|
|
|
|
|
|
|
|
|
|
|
res2=self.env['opendons.operation_partner'].create(vals) |
|
|
|
|
|
|
|
|
|
|
|
if i>1: |
|
|
|
|
|
partners=self.env['res.partner'].search(eval(sg.mailing_domain)) |
|
|
|
|
|
for p in partners: |
|
|
|
|
|
pp=self.env["opendons.operation_partner"].search_count( |
|
|
|
|
|
['&',('operation_id','=',int(self.id)), |
|
|
|
|
|
('partner_id','=',int(p.id))]) |
|
|
|
|
|
if pp==0: |
|
|
|
|
|
vals={} |
|
|
|
|
|
vals['operation_id']=self.id |
|
|
|
|
|
vals['segment_id']=sg.id |
|
|
|
|
|
vals['partner_id']=p.id |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
res2=self.env['opendons.operation_partner'].create(vals) |
|
|
|
|
|
i=i+1 |
|
|
|
|
|
|
|
|
|
|
|
return self.env["opendons.operation_partner"].search([('operation_id','=',self.id)]) |
|
|
|
|
|
|
|
|
@api.model |
|
|
@api.model |
|
|
def create(self,vals): |
|
|
def create(self,vals): |
|
@ -203,6 +330,29 @@ class opendons_operation(models.Model): |
|
|
self.document_fname='operation'+seld.id+'.csv' |
|
|
self.document_fname='operation'+seld.id+'.csv' |
|
|
return |
|
|
return |
|
|
|
|
|
|
|
|
|
|
|
class opendons_operation_partner(models.Model): |
|
|
|
|
|
_name = 'opendons.operation_partner' |
|
|
|
|
|
_description = 'opération marketing : lignes des contacts sélectionnés et exportés' |
|
|
|
|
|
|
|
|
|
|
|
operation_id = fields.Many2one( |
|
|
|
|
|
'opendons.operation', |
|
|
|
|
|
String='Operation', |
|
|
|
|
|
index=True, |
|
|
|
|
|
readonly=True) |
|
|
|
|
|
|
|
|
|
|
|
segment_id = fields.Many2one( |
|
|
|
|
|
'opendons.segment', |
|
|
|
|
|
String='Segemnt', |
|
|
|
|
|
index=True, |
|
|
|
|
|
readonly=True) |
|
|
|
|
|
|
|
|
|
|
|
partner_id = fields.Many2one( |
|
|
|
|
|
'res.partner', |
|
|
|
|
|
String='Partner', |
|
|
|
|
|
index=True, |
|
|
|
|
|
readonly=True) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class opendons_segment(models.Model): |
|
|
class opendons_segment(models.Model): |
|
|
_name = 'opendons.segment' |
|
|
_name = 'opendons.segment' |
|
@ -216,6 +366,7 @@ class opendons_segment(models.Model): |
|
|
cost = fields.Monetary( |
|
|
cost = fields.Monetary( |
|
|
string='Cost', |
|
|
string='Cost', |
|
|
currency_field='currency_id') |
|
|
currency_field='currency_id') |
|
|
|
|
|
partner_ids = fields.Many2many('res.partner', 'partner_segment_rel', 'partner_id', 'segment_id', string='partners') |
|
|
partner_count = fields.Integer(string="partners count", compute='_count_partner_segment',readonly=True) |
|
|
partner_count = fields.Integer(string="partners count", compute='_count_partner_segment',readonly=True) |
|
|
mailing_domain = fields.Char(string='partners selection', readonly=True) |
|
|
mailing_domain = fields.Char(string='partners selection', readonly=True) |
|
|
|
|
|
|
|
@ -241,7 +392,7 @@ class opendons_segment(models.Model): |
|
|
readonly=True, |
|
|
readonly=True, |
|
|
track_visibility='onchange', |
|
|
track_visibility='onchange', |
|
|
ondelete='cascade' |
|
|
ondelete='cascade' |
|
|
) |
|
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
ensemble_ids = fields.One2many( |
|
|
ensemble_ids = fields.One2many( |
|
|
'opendons.ensemble', |
|
|
'opendons.ensemble', |
|
@ -320,6 +471,8 @@ class opendons_ensemble(models.Model): |
|
|
logical_operator = fields.Selection([('union','union'),('inter','intersection')],'Type',default='union') |
|
|
logical_operator = fields.Selection([('union','union'),('inter','intersection')],'Type',default='union') |
|
|
mailing_domain = fields.Char(string='partners selection', readonly=True) |
|
|
mailing_domain = fields.Char(string='partners selection', readonly=True) |
|
|
partner_count = fields.Integer(string="partners count",compute='_count_partner_ensemble',readonly=True) |
|
|
partner_count = fields.Integer(string="partners count",compute='_count_partner_ensemble',readonly=True) |
|
|
|
|
|
#partner_ids = fields.Many2many('res.partner', 'partner_segment_rel', 'partner_id', 'segment_id', string='partners') |
|
|
|
|
|
|
|
|
sequence = fields.Integer(string="sequence", default=10) |
|
|
sequence = fields.Integer(string="sequence", default=10) |
|
|
segment_id = fields.Many2one( |
|
|
segment_id = fields.Many2one( |
|
|
'opendons.segment','Segment', |
|
|
'opendons.segment','Segment', |
|
|