feat: Se crea asistente para asignación de prospectos a operarios
This commit is contained in:
parent
1f52dcba26
commit
bc4833b3cf
@ -18,9 +18,10 @@ def register():
|
|||||||
prospect.ContactMethod,
|
prospect.ContactMethod,
|
||||||
prospect.Prospect,
|
prospect.Prospect,
|
||||||
prospect_trace.ProspectTrace,
|
prospect_trace.ProspectTrace,
|
||||||
|
prospect.AssignOperatorStart,
|
||||||
module='sale_opportunity_management', type_='model')
|
module='sale_opportunity_management', type_='model')
|
||||||
Pool.register(
|
Pool.register(
|
||||||
|
prospect.AssignOperator,
|
||||||
module='sale_opportunity_management', type_='wizard')
|
module='sale_opportunity_management', type_='wizard')
|
||||||
Pool.register(
|
Pool.register(
|
||||||
module='sale_opportunity_management', type_='report')
|
module='sale_opportunity_management', type_='report')
|
||||||
|
39
prospect.py
39
prospect.py
@ -1,7 +1,9 @@
|
|||||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
# this repository contains the full copyright notices and license terms.
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
from trytond.wizard import Wizard, StateView, Button, StateTransition
|
||||||
from trytond.model import ModelSQL, ModelView, fields
|
from trytond.model import ModelSQL, ModelView, fields
|
||||||
from trytond.pyson import Eval, If
|
from trytond.pyson import Eval, If
|
||||||
|
from trytond.pool import Pool
|
||||||
|
|
||||||
|
|
||||||
class Prospect(ModelSQL, ModelView):
|
class Prospect(ModelSQL, ModelView):
|
||||||
@ -41,6 +43,7 @@ class Prospect(ModelSQL, ModelView):
|
|||||||
self.state = 'assigned'
|
self.state = 'assigned'
|
||||||
else:
|
else:
|
||||||
self.state = 'unassigned'
|
self.state = 'unassigned'
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ContactMethod(ModelSQL, ModelView):
|
class ContactMethod(ModelSQL, ModelView):
|
||||||
@ -72,3 +75,39 @@ class ContactMethod(ModelSQL, ModelView):
|
|||||||
contact_rec_name += ' [' + str(field) + '] '
|
contact_rec_name += ' [' + str(field) + '] '
|
||||||
|
|
||||||
return contact_rec_name
|
return contact_rec_name
|
||||||
|
|
||||||
|
|
||||||
|
class AssignOperatorStart(ModelView):
|
||||||
|
'Inicio de asignación de operador'
|
||||||
|
__name__ = 'sale.prospect.assign.start'
|
||||||
|
|
||||||
|
prospects_chunk = fields.Integer('Prospects chunk')
|
||||||
|
operator = fields.Many2One('res.user', 'Operator')
|
||||||
|
|
||||||
|
|
||||||
|
class AssignOperator(Wizard):
|
||||||
|
'Asignar operador a prospecto'
|
||||||
|
__name__ = 'sale.prospect.assign'
|
||||||
|
|
||||||
|
start = StateView(
|
||||||
|
'sale.prospect.assign.start',
|
||||||
|
'sale_opportunity_management.assign_start_view_form', [
|
||||||
|
Button("Cancel", 'end', 'tryton-cancel'),
|
||||||
|
Button("Assign", 'assign', 'tryton-ok', default=True)])
|
||||||
|
|
||||||
|
assign = StateTransition()
|
||||||
|
|
||||||
|
def transition_assign(self):
|
||||||
|
pool = Pool()
|
||||||
|
Prospect = pool.get('sale.prospect')
|
||||||
|
|
||||||
|
prospects = Prospect.search(
|
||||||
|
[('state', '=', 'unassigned')],
|
||||||
|
limit=self.start.prospects_chunk)
|
||||||
|
|
||||||
|
for prospect in prospects:
|
||||||
|
prospect.assigned_operator = self.start.operator
|
||||||
|
prospect.state = 'assigned'
|
||||||
|
prospect.save()
|
||||||
|
|
||||||
|
return 'end'
|
||||||
|
17
prospect.xml
17
prospect.xml
@ -7,7 +7,6 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<field name="name">Prospects</field>
|
<field name="name">Prospects</field>
|
||||||
<field name="res_model">sale.prospect</field>
|
<field name="res_model">sale.prospect</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="prospect_view_tree">
|
<record model="ir.ui.view" id="prospect_view_tree">
|
||||||
<field name="model">sale.prospect</field>
|
<field name="model">sale.prospect</field>
|
||||||
<field name="type">tree</field>
|
<field name="type">tree</field>
|
||||||
@ -18,7 +17,6 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<field name="type">form</field>
|
<field name="type">form</field>
|
||||||
<field name="name">prospect_form</field>
|
<field name="name">prospect_form</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.action.act_window.view" id="act_prospect_tree_view1">
|
<record model="ir.action.act_window.view" id="act_prospect_tree_view1">
|
||||||
<field name="sequence" eval="10"/>
|
<field name="sequence" eval="10"/>
|
||||||
<field name="view" ref="prospect_view_tree"/>
|
<field name="view" ref="prospect_view_tree"/>
|
||||||
@ -29,7 +27,6 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<field name="view" ref="prospect_view_form"/>
|
<field name="view" ref="prospect_view_form"/>
|
||||||
<field name="act_window" ref="act_prospect_tree"/>
|
<field name="act_window" ref="act_prospect_tree"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<menuitem
|
<menuitem
|
||||||
parent="menu_calls"
|
parent="menu_calls"
|
||||||
sequence="10"
|
sequence="10"
|
||||||
@ -41,7 +38,6 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<field name="res_model">sale.prospect</field>
|
<field name="res_model">sale.prospect</field>
|
||||||
<field name="domain" eval="[('state', '=', 'unassigned')]" pyson="1"/>
|
<field name="domain" eval="[('state', '=', 'unassigned')]" pyson="1"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="prospect_unassigned_view_tree">
|
<record model="ir.ui.view" id="prospect_unassigned_view_tree">
|
||||||
<field name="model">sale.prospect</field>
|
<field name="model">sale.prospect</field>
|
||||||
<field name="type">tree</field>
|
<field name="type">tree</field>
|
||||||
@ -52,7 +48,6 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<field name="type">form</field>
|
<field name="type">form</field>
|
||||||
<field name="name">prospect_form</field>
|
<field name="name">prospect_form</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.action.act_window.view" id="act_prospect_unassigned_tree_view1">
|
<record model="ir.action.act_window.view" id="act_prospect_unassigned_tree_view1">
|
||||||
<field name="sequence" eval="10"/>
|
<field name="sequence" eval="10"/>
|
||||||
<field name="view" ref="prospect_unassigned_view_tree"/>
|
<field name="view" ref="prospect_unassigned_view_tree"/>
|
||||||
@ -63,7 +58,6 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<field name="view" ref="prospect_view_form"/>
|
<field name="view" ref="prospect_view_form"/>
|
||||||
<field name="act_window" ref="act_prospect_unassigned_tree"/>
|
<field name="act_window" ref="act_prospect_unassigned_tree"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<menuitem
|
<menuitem
|
||||||
parent="menu_prospects_tree"
|
parent="menu_prospects_tree"
|
||||||
sequence="10"
|
sequence="10"
|
||||||
@ -75,7 +69,6 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<field name="res_model">sale.prospect</field>
|
<field name="res_model">sale.prospect</field>
|
||||||
<field name="domain" eval="[('state', '=', 'assigned')]" pyson="1"/>
|
<field name="domain" eval="[('state', '=', 'assigned')]" pyson="1"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="prospect_assigned_view_tree">
|
<record model="ir.ui.view" id="prospect_assigned_view_tree">
|
||||||
<field name="model">sale.prospect</field>
|
<field name="model">sale.prospect</field>
|
||||||
<field name="type">tree</field>
|
<field name="type">tree</field>
|
||||||
@ -86,7 +79,6 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<field name="type">form</field>
|
<field name="type">form</field>
|
||||||
<field name="name">prospect_form</field>
|
<field name="name">prospect_form</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.action.act_window.view" id="act_prospect_assigned_tree_view1">
|
<record model="ir.action.act_window.view" id="act_prospect_assigned_tree_view1">
|
||||||
<field name="sequence" eval="10"/>
|
<field name="sequence" eval="10"/>
|
||||||
<field name="view" ref="prospect_assigned_view_tree"/>
|
<field name="view" ref="prospect_assigned_view_tree"/>
|
||||||
@ -97,7 +89,6 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<field name="view" ref="prospect_view_form"/>
|
<field name="view" ref="prospect_view_form"/>
|
||||||
<field name="act_window" ref="act_prospect_assigned_tree"/>
|
<field name="act_window" ref="act_prospect_assigned_tree"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<menuitem
|
<menuitem
|
||||||
parent="menu_prospects_tree"
|
parent="menu_prospects_tree"
|
||||||
sequence="10"
|
sequence="10"
|
||||||
@ -108,7 +99,6 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<field name="name">Contact method</field>
|
<field name="name">Contact method</field>
|
||||||
<field name="res_model">prospect.contact_method</field>
|
<field name="res_model">prospect.contact_method</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="contact_method_view_tree">
|
<record model="ir.ui.view" id="contact_method_view_tree">
|
||||||
<field name="model">prospect.contact_method</field>
|
<field name="model">prospect.contact_method</field>
|
||||||
<field name="type">tree</field>
|
<field name="type">tree</field>
|
||||||
@ -119,7 +109,6 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<field name="type">form</field>
|
<field name="type">form</field>
|
||||||
<field name="name">contact_method_form</field>
|
<field name="name">contact_method_form</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.action.act_window.view" id="act_contact_method_tree_view1">
|
<record model="ir.action.act_window.view" id="act_contact_method_tree_view1">
|
||||||
<field name="sequence" eval="10"/>
|
<field name="sequence" eval="10"/>
|
||||||
<field name="view" ref="contact_method_view_tree"/>
|
<field name="view" ref="contact_method_view_tree"/>
|
||||||
@ -130,5 +119,11 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<field name="view" ref="contact_method_view_form"/>
|
<field name="view" ref="contact_method_view_form"/>
|
||||||
<field name="act_window" ref="act_contact_method_tree"/>
|
<field name="act_window" ref="act_contact_method_tree"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.ui.view" id="assign_start_view_form">
|
||||||
|
<field name="model">sale.prospect.assign.start</field>
|
||||||
|
<field name="type">form</field>
|
||||||
|
<field name="name">assign_start_form</field>
|
||||||
|
</record>
|
||||||
</data>
|
</data>
|
||||||
</tryton>
|
</tryton>
|
||||||
|
@ -42,50 +42,71 @@ El administrador deberá poder registrar los contactos de diferentes prospectos,
|
|||||||
|
|
||||||
Crear prospecto::
|
Crear prospecto::
|
||||||
>>> Prospect = Model.get('sale.prospect')
|
>>> Prospect = Model.get('sale.prospect')
|
||||||
>>> prospect = Prospect()
|
>>> prospect1 = Prospect()
|
||||||
|
|
||||||
>>> prospect.name = 'guchito S.A.S'
|
>>> prospect1.name = 'guchito S.A.S'
|
||||||
>>> contact_method = prospect.contact_methods.new(value='31223425234', name='Roberto', job='Gerente R.H')
|
>>> contact_method = prospect1.contact_methods.new(value='31223425234', name='Roberto', job='Gerente R.H')
|
||||||
>>> contact_method = prospect.contact_methods.new(contact_type='mobile', value='12345678910', name='Pancracia', job='Asistente administrativo')
|
>>> contact_method = prospect1.contact_methods.new(contact_type='mobile', value='12345678910', name='Pancracia', job='Asistente administrativo')
|
||||||
>>> contact_method = prospect.contact_methods.new(contact_type='mail', value='peralto@guchitos.org', name='Peralto', job='Administrador')
|
>>> contact_method = prospect1.contact_methods.new(contact_type='mail', value='peralto@guchitos.org', name='Peralto', job='Administrador')
|
||||||
|
|
||||||
>>> City = Model.get('sale.city')
|
>>> City = Model.get('sale.city')
|
||||||
>>> medellin, = City.find([('code', '=', 'CO-05001')])
|
>>> medellin, = City.find([('code', '=', 'CO-05001')])
|
||||||
>>> prospect.city = medellin
|
>>> prospect1.city = medellin
|
||||||
>>> prospect.save()
|
>>> prospect1.save()
|
||||||
|
|
||||||
Verificar estado final de creación de prospecto::
|
Verificar estado final de creación de prospecto::
|
||||||
>>> prospect.contact_methods
|
>>> prospect1.contact_methods
|
||||||
[proteus.Model.get('prospect.contact_method')(1), proteus.Model.get('prospect.contact_method')(2), proteus.Model.get('prospect.contact_method')(3)]
|
[proteus.Model.get('prospect.contact_method')(1), proteus.Model.get('prospect.contact_method')(2), proteus.Model.get('prospect.contact_method')(3)]
|
||||||
>>> prospect.contact_methods[0].contact_type
|
>>> prospect1.contact_methods[0].contact_type
|
||||||
'mobile'
|
'mobile'
|
||||||
>>> prospect.contact_methods[0].job
|
>>> prospect1.contact_methods[0].job
|
||||||
'Gerente R.H'
|
'Gerente R.H'
|
||||||
>>> prospect.contact_methods[2].name
|
>>> prospect1.contact_methods[2].name
|
||||||
'Peralto'
|
'Peralto'
|
||||||
>>> prospect.contact_methods[2].value
|
>>> prospect1.contact_methods[2].value
|
||||||
'peralto@guchitos.org'
|
'peralto@guchitos.org'
|
||||||
|
|
||||||
>>> prospect.city.code
|
>>> prospect1.city.code
|
||||||
'CO-05001'
|
'CO-05001'
|
||||||
>>> prospect.department.code
|
>>> prospect1.department.code
|
||||||
'CO-05'
|
'CO-05'
|
||||||
>>> prospect.state
|
>>> prospect1.state
|
||||||
'unassigned'
|
'unassigned'
|
||||||
|
|
||||||
|
Crear segundo prospecto::
|
||||||
|
>>> prospect2 = Prospect()
|
||||||
|
|
||||||
|
>>> prospect2.name = 'Modernitus S.A.S'
|
||||||
|
>>> contact_method = prospect2.contact_methods.new(value='3122390987', name='Pepe', job='Jefe de ventas')
|
||||||
|
|
||||||
|
>>> City = Model.get('sale.city')
|
||||||
|
>>> bogota, = City.find([('code', '=', 'CO-11001')])
|
||||||
|
>>> prospect2.city = bogota
|
||||||
|
>>> prospect2.save()
|
||||||
|
|
||||||
Asignar operario a un prospecto::
|
Asignar operario a un prospecto::
|
||||||
>>> User = Model.get('res.user')
|
>>> User = Model.get('res.user')
|
||||||
>>> user, = User.find([('name', '=', 'Administrator')])
|
>>> user, = User.find([('name', '=', 'Administrator')])
|
||||||
>>> prospect.assigned_operator = user
|
|
||||||
|
|
||||||
>>> prospect.assigned_operator.name
|
.. >>> prospect1.assigned_operator = user
|
||||||
|
|
||||||
|
>>> assign = Wizard('sale.prospect.assign', [prospect1, prospect2])
|
||||||
|
>>> assign.form.prospects_chunk = 2
|
||||||
|
>>> assign.form.operator = user
|
||||||
|
>>> assign.execute('assign')
|
||||||
|
|
||||||
|
>>> prospect1.assigned_operator.name
|
||||||
'Administrator'
|
'Administrator'
|
||||||
>>> prospect.state
|
>>> prospect1.state
|
||||||
|
'assigned'
|
||||||
|
>>> prospect2.assigned_operator.name
|
||||||
|
'Administrator'
|
||||||
|
>>> prospect2.state
|
||||||
'assigned'
|
'assigned'
|
||||||
|
|
||||||
Remover operario asignado de un prospecto::
|
Remover operario asignado de un prospecto::
|
||||||
>>> prospect.assigned_operator = None
|
>>> prospect1.assigned_operator = None
|
||||||
>>> prospect.state
|
>>> prospect1.state
|
||||||
'unassigned'
|
'unassigned'
|
||||||
|
|
||||||
|
|
||||||
@ -155,7 +176,7 @@ Crear seguimiento de prospecto::
|
|||||||
>>> ProspectTrace = Model.get('sale.prospect_trace')
|
>>> ProspectTrace = Model.get('sale.prospect_trace')
|
||||||
>>> prospect_trace = ProspectTrace()
|
>>> prospect_trace = ProspectTrace()
|
||||||
|
|
||||||
>>> prospect_trace.prospect = prospect
|
>>> prospect_trace.prospect = prospect1
|
||||||
>>> prospect_trace.save()
|
>>> prospect_trace.save()
|
||||||
|
|
||||||
>>> prospect_trace.prospect.name
|
>>> prospect_trace.prospect.name
|
||||||
@ -215,10 +236,10 @@ Crear una llamada agendada previamente:
|
|||||||
'open'
|
'open'
|
||||||
|
|
||||||
Cuando se asigna prospecto sin método de contacto mobile, el contacto en el seguimiento es vacío::
|
Cuando se asigna prospecto sin método de contacto mobile, el contacto en el seguimiento es vacío::
|
||||||
>>> prospect2 = Prospect()
|
>>> prospect3 = Prospect()
|
||||||
>>> prospect2.name = 'Sin celulares S.A.S'
|
>>> prospect3.name = 'Sin celulares S.A.S'
|
||||||
>>> contact_method = prospect2.contact_methods.new(contact_type='mail', value='felpucio@sincelulares.org', name='felpucio', job='Supervisor')
|
>>> contact_method = prospect3.contact_methods.new(contact_type='mail', value='felpucio@sincelulares.org', name='felpucio', job='Supervisor')
|
||||||
>>> prospect2.save()
|
>>> prospect3.save()
|
||||||
|
|
||||||
>>> prospect_trace2 = ProspectTrace()
|
>>> prospect_trace2 = ProspectTrace()
|
||||||
>>> prospect_trace2.prospect = prospect2
|
>>> prospect_trace2.prospect = prospect2
|
||||||
|
10
view/assign_start_form.xml
Normal file
10
view/assign_start_form.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
this repository contains the full copyright notices and license terms. -->
|
||||||
|
<form>
|
||||||
|
<label name="prospects_chunk"/>
|
||||||
|
<field name="prospects_chunk"/>
|
||||||
|
<newline/>
|
||||||
|
<label name="operator"/>
|
||||||
|
<field name="operator"/>
|
||||||
|
</form>
|
Loading…
Reference in New Issue
Block a user