20 Commits

Author SHA1 Message Date
f00e849ab9 feat: Se agrega traducción
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/pr/woodpecker Pipeline failed
2023-11-02 13:31:03 -05:00
30a37af5de fix: Se añade depends al botón de cerrar tareas
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/pr/woodpecker Pipeline failed
2023-11-02 13:17:19 -05:00
2ee22b1c0c fix: Si se agrega o modifica un método de contacto luego de que se haya generado la tarea, esta no se actualiza
Some checks failed
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline failed
2023-10-28 21:41:09 -05:00
f4566b7db4 chore(ContactMethod): refactor - se centraliza lógica de actualización de colaboradores
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-10-28 20:20:32 -05:00
a1d1e019ec fix: al crear segunda tarea al mismo seguimiento se pierden los contact_methods de la anterior
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-10-20 17:50:44 -05:00
3be97677a7 Merge branch '6.8' of https://gitea.onecluster.org/OneTeam/trytondo-sale_opportunity_management into pantallaDeTareasNoMuestraContactMethod_#74 2023-10-20 16:31:17 -05:00
d1ad40203b Merge pull request 'fix: al crear mecanismo de contacto desde prospecto no se actualiza correctamente en seguimiento de prospecto' (#77) from NoSeActualizaContactMethodEnProspectTrace_#76 into 6.8
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Se replica error en las pruebas y se soluciona con un on_change
2023-10-20 16:19:03 -05:00
9c368809f9 fix: al crear mecanismo de contacto desde prospecto no se actualiza correctamente en seguimiento de prospecto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
2023-10-20 15:27:51 -05:00
5873d35f12 feat(Pantalla Tareas pendientes): Se agregan vistas de método de contacto, #74
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-10-19 19:58:46 -05:00
85d5f714ef feat: Se implementa en las pruebas metodos de contacto dentro de PendingTask
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-10-19 19:52:40 -05:00
e40991de02 feat: Se agregan dominios de vista de prospectos
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-22 10:39:10 -05:00
b8ba775733 chore(Tipificación del cliente): Se hacen traducciones
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-21 19:28:19 -05:00
336a266578 chore: Se hace visible rating en vista de arbol de prospectos
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-21 19:13:29 -05:00
22fb3736a7 chore(Agendación de tarea): Se agregan traducciones faltantes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-21 19:08:24 -05:00
5cc7ef011d feat: Se agrega tipificación del cliente, closed #70
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-19 17:10:13 -05:00
72ae0cfa22 feat: Se hace posible agregar y modificar métodos de contactos desde seguimiento de prospectos, closed #72
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-19 15:56:21 -05:00
0b7d15f35b feat(Programación de tareas): Se agregan traducciones, #71
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-19 12:19:49 -05:00
8a0aa29368 feat: Se agregan estados a la vista de tareas pendientes, #71
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-19 11:57:29 -05:00
f71e6f4671 feat: Se implementa en las pruebas cierre de tarea pendientes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-19 11:47:31 -05:00
cf874db55f chore(Task): se extrae clase a otro archivo, #71 2023-09-19 11:24:49 -05:00
14 changed files with 280 additions and 41 deletions

View File

@@ -14,8 +14,8 @@ def register():
Pool.register(
user.User,
pending_call.PendingCall,
pending_call.PendingTask,
call.Call,
call.PendingTask,
department.Department,
city.City,
prospect.ContactMethod,
@@ -28,6 +28,7 @@ def register():
prospect_trace.MakeCallAskTask,
prospect.ReassignProspectByOperatorStart,
prospect.ReassignProspectByProspectStart,
call.PendingTask_ContactMethod,
module='sale_opportunity_management', type_='model')
Pool.register(
prospect_trace.ScheduleCall,

58
call.py
View File

@@ -1,7 +1,6 @@
from trytond.model import ModelSQL, ModelView, fields
from trytond.pyson import Eval
from datetime import date
from .selections.interest import Interest
from .selections.call_types import CallTypes
from .selections.call_results import CallResults
@@ -47,3 +46,58 @@ class Call(ModelSQL, ModelView):
@classmethod
def default_date(cls):
return date.today()
class PendingTask(ModelSQL, ModelView):
'Tarea a realizar a un seguimiento de prospecto'
__name__ = "sale.pending_task"
description = fields.Text(
'Description', required=True,
states={
'readonly': Eval('state') == 'done'
})
state = fields.Selection(
[('pending', 'Pending'),
('done', 'Done')],
'State')
prospect_trace = fields.Many2One(
'sale.prospect_trace', 'Prospect trace',
required=True, readonly=True)
contacts = fields.Many2Many(
'sale.pendingtask_contactmethod',
'pending_task_id', 'contact_method_id',
'Contact Methods')
@classmethod
def __setup__(cls):
super(PendingTask, cls).__setup__()
cls._buttons.update({
'close_task': {
'invisible': Eval('state') == 'done',
'depends': ['state'],
}
})
@classmethod
@ModelView.button
def close_task(cls, tasks):
for task in tasks:
task.state = 'done'
task.save()
@classmethod
def default_state(cls):
return 'pending'
class PendingTask_ContactMethod(ModelSQL):
'Relacion muchos a muchos entre tareas pendientes y mecanismos de contacto'
__name__ = "sale.pendingtask_contactmethod"
pending_task_id = fields.Many2One('sale.pending_task', 'Pending task id')
contact_method_id = fields.Many2One(
'prospect.contact_method', 'Contact method id')

View File

@@ -99,11 +99,37 @@ this repository contains the full copyright notices and license terms. -->
<field name="view" ref="pending_task_view_form"/>
<field name="act_window" ref="act_pending_task_tree"/>
</record>
<record model="ir.action.act_window.domain" id="act_task_domain_pending">
<field name="name">Pending</field>
<field name="sequence" eval="10"/>
<field name="domain" eval="[('state', '=', 'pending')]" pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_pending_task_tree"/>
</record>
<record model="ir.action.act_window.domain" id="act_task_domain_done">
<field name="name">Done</field>
<field name="sequence" eval="20"/>
<field name="domain" eval="[('state', '=', 'done')]" pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_pending_task_tree"/>
</record>
<record model="ir.action.act_window.domain" id="act_task_domain_all">
<field name="name">All</field>
<field name="sequence" eval="9999"/>
<field name="domain"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_pending_task_tree"/>
</record>
<menuitem
parent="menu_calls"
sequence="60"
id="menu_pending_tasks"
action="act_pending_task_tree"
icon="tryton-graph"/>
<record model="ir.model.button" id="close_task_button">
<field name="name">close_task</field>
<field name="string">Close task</field>
<field name="model" search="[('model', '=', 'sale.pending_task')]"/>
</record>
</data>
</tryton>

View File

@@ -2,10 +2,6 @@
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:res.user,user_admin:"
msgid "Is Admin"
msgstr "Es Administrador"
msgctxt "model:res.group,name:group_prospect"
msgid "Prospects"
msgstr "Prospectos"
@@ -30,6 +26,10 @@ msgctxt "model:res.group,name:group_prospect_trace_admin"
msgid "Traces Administrator"
msgstr "Administración de Seguimientos"
msgctxt "field:res.user,user_admin:"
msgid "Is Admin"
msgstr "Es Administrador"
msgctxt "field:sale.prospect_trace,prospect:"
msgid "Prospect"
msgstr "Prospecto"
@@ -76,7 +76,11 @@ msgstr "Unidad de negocio"
msgctxt "view:sale.prospect:"
msgid "Contact methods"
msgstr "Metodos de contacto"
msgstr "Métodos de contacto"
msgctxt "view:sale.prospect:"
msgid "About prospect"
msgstr "Tipificación del prospecto"
msgctxt "field:sale.prospect,contact_methods:"
msgid "Contact methods"
@@ -102,6 +106,14 @@ msgctxt "field:sale.prospect,prospect_trace:"
msgid "Prospect trace"
msgstr "Seguimiento de prospecto"
msgctxt "field:sale.prospect,rating:"
msgid "Rating (1-5)"
msgstr "Calificación (1-5)"
msgctxt "field:sale.prospect,comments:"
msgid "Comments"
msgstr "Comentarios"
msgctxt "field:sale.call,date:"
msgid "Date"
msgstr "Fecha"
@@ -226,6 +238,25 @@ msgctxt "field:sale.prospect_trace.make_call.ask,datetime:"
msgid "Date time"
msgstr "Fecha y hora"
msgctxt "field:sale.pending_task,description:"
msgid "Description"
msgstr "Descripción"
msgctxt "field:sale.pending_task,prospect_trace:"
msgid "Prospect trace"
msgstr "Seguimiento de prospecto"
msgctxt "field:sale.pending_task,contacts:"
msgid "Contact Methods"
msgstr "Métodos de Contacto"
msgctxt "field:sale.prospect_trace.make_call.start,schedule_task:"
msgid "Schedule task?"
msgstr "¿Agendar tarea?"
msgctxt "field:sale.prospect_trace.make_call.ask_task,task_description:"
msgid "Task description"
msgstr "Descripción de la tarea"
msgctxt "selection:sale.prospect,business_unit:"
msgid "Brigade"
@@ -259,6 +290,10 @@ msgctxt "selection:prospect.contact_method,contact_type:"
msgid "Mail"
msgstr "Correo electrónico"
msgctxt "selection:sale.prospect,rating:"
msgid "None"
msgstr "Sin calificación"
msgctxt "selection:sale.prospect.assign.start,business_unit:"
msgid "Brigade"
msgstr "Brigada"
@@ -387,6 +422,11 @@ msgctxt "selection:sale.call,call_business_unit:"
msgid "Equipment"
msgstr "Equipos"
msgctxt "selection:sale.prospect_trace.make_call.start,schedule_task:"
msgid "Yes"
msgstr "Si"
msgctxt "model:ir.ui.menu,name:menu_calls"
msgid "Calls"
msgstr "Llamadas"
@@ -419,6 +459,10 @@ msgctxt "model:ir.ui.menu,name:menu_reassign_by_prospect_wizard"
msgid "Reassign by prospect"
msgstr "Reasignar por prospecto"
msgctxt "model:ir.ui.menu,name:menu_pending_tasks"
msgid "Pending tasks"
msgstr "Tareas pendientes"
msgctxt "model:ir.model.button,string:schedule_call_wizard_button"
msgid "Schedule call"
@@ -436,6 +480,10 @@ msgctxt "model:ir.model.button,string:reopen_trace_button"
msgid "Reopen trace"
msgstr "Reabrir seguimiento"
msgctxt "model:ir.model.button,string:close_task_button"
msgid "Close task"
msgstr "Cerrar tarea"
msgctxt "wizard_button:sale.prospect_trace.make_call,start,end:"
msgid "Cancel"
@@ -451,7 +499,7 @@ msgstr "Cancelar"
msgctxt "wizard_button:sale.prospect_trace.make_call,ask,schedule_call:"
msgid "Schedule call"
msgstr "Agendar"
msgstr "Agendar llamada"
msgctxt "wizard_button:sale.prospect_trace.schedule,start,end:"
msgid "Cancel"
@@ -459,7 +507,15 @@ msgstr "Cancelar"
msgctxt "wizard_button:sale.prospect_trace.schedule,start,schedule:"
msgid "Schedule"
msgstr "Agendar"
msgstr "Agendar llamada"
msgctxt "wizard_button:sale.prospect_trace.make_call,ask_task,end:"
msgid "Cancel"
msgstr "Cancelar"
msgctxt "wizard_button:sale.prospect_trace.make_call,ask_task,schedule_task:"
msgid "Schedule task"
msgstr "Agendar tarea"
msgctxt "wizard_button:sale.prospect.assign,start,end:"
msgid "Cancel"
@@ -513,6 +569,19 @@ msgctxt "model:ir.action.act_window.domain,name:act_prospect_domain_assigned"
msgid "Assigned"
msgstr "Asignado"
msgctxt "model:ir.action.act_window.domain,name:act_task_domain_pending"
msgid "Pending"
msgstr "Pendiente"
msgctxt "model:ir.action.act_window.domain,name:act_task_domain_done"
msgid "Done"
msgstr "Completado"
msgctxt "model:ir.action.act_window.domain,name:act_task_domain_all"
msgid "All"
msgstr "Todo"
msgctxt "model:ir.action,name:schedule_call_wizard"
msgid "Schedule call"
msgstr "Agendar llamada"

View File

@@ -12,18 +12,3 @@ class PendingCall(ModelSQL, ModelView):
def get_rec_name(self, name):
if self.date:
return str(self.date)
class PendingTask(ModelSQL, ModelView):
'Tarea pendiente a un seguimiento de prospecto'
__name__ = "sale.pending_task"
description = fields.Text('Description', required=True)
done = fields.Boolean('Done')
prospect_trace = fields.Many2One(
'sale.prospect_trace', 'Prospect trace',
required=True, readonly=True)
@classmethod
def default_done(cls):
return False

View File

@@ -1,12 +1,12 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# 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, DeactivableMixin
from trytond.pyson import Eval, If
from trytond.pool import Pool
class Prospect(ModelSQL, ModelView):
class Prospect(ModelSQL, ModelView, DeactivableMixin):
'Prospecto'
__name__ = 'sale.prospect'
_rec_name = 'name'
@@ -38,10 +38,24 @@ class Prospect(ModelSQL, ModelView):
prospect_trace = fields.Many2One('sale.prospect_trace', 'Prospect trace')
rating = fields.Selection(
[(None, None),
('1', '1'),
('2', '2'),
('3', '3'),
('4', '4'),
('5', '5')], 'Rating (1-5)')
comments = fields.Text('Comments')
@classmethod
def default_state(cls):
return 'unassigned'
@fields.depends('prospect_trace', 'contact_methods')
def on_change_contact_methods(self):
for contact in self.contact_methods:
contact.update_collaborators(changed_from='prospect')
@fields.depends('city', 'department')
def on_change_city(self):
if self.city:
@@ -66,10 +80,24 @@ class ContactMethod(ModelSQL, ModelView):
prospect_trace = fields.Many2One(
'sale.prospect_trace', 'Prospect Trace', required=False)
tasks = fields.Many2Many(
'sale.pendingtask_contactmethod',
'contact_method_id', 'pending_task_id',
'Tasks')
@classmethod
def default_contact_type(cls):
return 'mobile'
def update_collaborators(self, changed_from):
if (changed_from == 'prospect'):
self.prospect_trace = self.prospect.prospect_trace
if (self.prospect_trace):
self.tasks = self.prospect.prospect_trace.tasks
if (changed_from == 'prospect_trace'):
self.prospect = self.prospect_trace.prospect
self.tasks = self.prospect_trace.tasks
def get_rec_name(self, name):
fields = [self.name, self.job, self.value]
contact_rec_name = ''

View File

@@ -21,6 +21,9 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.action.act_window" id="act_prospect_tree">
<field name="name">Prospects</field>
<field name="domain"
eval="[If(Eval('context', {}).get('user_admin', None), (), ('assigned_operator', '=', Eval('_user')))]"
pyson="1"/>
<field name="res_model">sale.prospect</field>
</record>
<record model="ir.ui.view" id="prospect_view_tree">

View File

@@ -24,8 +24,8 @@ class ProspectTrace(ModelSQL, ModelView):
'Business unit', states=_states
)
prospect_contacts = fields.One2Many(
'prospect.contact_method', 'prospect_trace', 'Prospect contacts',
states=_states)
'prospect.contact_method', 'prospect_trace',
'Prospect contacts', required=True)
prospect_city = fields.Many2One('sale.city', 'City',
states=_states)
@@ -36,6 +36,9 @@ class ProspectTrace(ModelSQL, ModelView):
'sale.call', 'prospect_trace', 'Calls', states=_states)
pending_call = fields.Many2One(
'sale.pending_call', 'Pending call', states=_states)
tasks = fields.One2Many(
'sale.pending_task', 'prospect_trace',
'Pending Tasks', states=_states)
current_interest = fields.Selection(
Interest.get_interest_levels(), 'Current interest',
@@ -49,6 +52,11 @@ class ProspectTrace(ModelSQL, ModelView):
], 'State',
states=_states)
@fields.depends('prospect_contacts', 'prospect')
def on_change_prospect_contacts(self):
for contact in self.prospect_contacts:
contact.update_collaborators(changed_from='prospect_trace')
@classmethod
def __setup__(cls):
super(ProspectTrace, cls).__setup__()
@@ -258,6 +266,7 @@ class MakeCall(Wizard):
task = Task()
task.description = description
task.prospect_trace = prospect_trace
task.contacts = prospect_trace.prospect_contacts
task.save()
@classmethod

View File

@@ -31,7 +31,7 @@ this repository contains the full copyright notices and license terms. -->
</record>
<record model="ir.action.act_window" id="act_prospect_trace_tree">
<field name="name">Prospect Traces</field>
<field name="domain"
<field name="domain"
eval="[If(Eval('context', {}).get('user_admin', None), (), ('prospect_assigned_operator', '=', Eval('_user')))]"
pyson="1"/>
<field name="res_model">sale.prospect_trace</field>

View File

@@ -95,6 +95,10 @@ Crear tercer prospecto::
>>> prospect3.business_unit = 'optics'
>>> prospect3.save()
Asignar tipificación a un prospecto
>>> prospect3.rating = '1'
>>> prospect3.comments = 'Calificación al cliente'
------------------------------------
Asignación de prospectos a operarios
------------------------------------
@@ -192,6 +196,11 @@ Verificar creación de seguimiento de prospecto::
>>> prospect_trace.prospect_contacts
[proteus.Model.get('prospect.contact_method')(1), proteus.Model.get('prospect.contact_method')(2), proteus.Model.get('prospect.contact_method')(3)]
Agregar un método de contacto desde el seguimiento de prospecto::
>>> contact_method_ = prospect_trace.prospect_contacts.new(value='31231231212', name='Carlos', job='Supervisor')
>>> contact_method_.prospect
proteus.Model.get('sale.prospect')(1)
Crear llamadas a un seguimiento de prospecto::
>>> make_call = Wizard('sale.prospect_trace.make_call', [prospect_trace])
@@ -265,7 +274,7 @@ Crear una llamada agendada previamente::
>>> prospect_trace.state
'open'
Hacer llamada y programar tarea
Hacer llamada y programar tarea::
>>> make_call = Wizard('sale.prospect_trace.make_call', [prospect_trace])
>>> make_call.form.description = 'Prospect told me to send him an email'
>>> make_call.form.interest = '3'
@@ -278,9 +287,42 @@ Hacer llamada y programar tarea
>>> make_call.execute('schedule_task')
>>> Task = Model.get('sale.pending_task')
>>> task, = Task.find([('description', '=', 'I have to send a mail to prospect offering him this services...')])
>>> task
>>> task1, = Task.find([('description', '=', 'I have to send a mail to prospect offering him this services...')])
>>> task1
proteus.Model.get('sale.pending_task')(1)
>>> task1.state
'pending'
>>> task1.click('close_task')
>>> task1.state
'done'
>>> task1.contacts[0].value
'12345678910'
Programar segunda tarea al mismo seguimiento::
>>> make_call = Wizard('sale.prospect_trace.make_call', [prospect_trace])
>>> make_call.form.description = 'Prospect told me to send him an SMS'
>>> make_call.form.interest = '3'
>>> make_call.form.schedule_call = 'no'
>>> make_call.form.schedule_task = 'yes'
>>> make_call.execute('make_call')
>>> make_call.form.task_description = 'I have to send a SMS to prospect offering him this services...'
>>> make_call.execute('schedule_task')
>>> task1.save()
>>> Task = Model.get('sale.pending_task')
>>> task2, = Task.find([('description', '=', 'I have to send a SMS to prospect offering him this services...')])
>>> task2
proteus.Model.get('sale.pending_task')(2)
>>> task2.state
'pending'
>>> task2.contacts[0].value
'12345678910'
>>> task1.contacts[0].value
'12345678910'
Hacer llamada y cerrar venta (Seguimiento de prospecto)::
>>> make_call = Wizard('sale.prospect_trace.make_call', [prospect_trace])
@@ -331,7 +373,6 @@ Reasignar prospectos por prospecto::
>>> reassign_by_prospect.form.prospect = prospect1
>>> reassign_by_prospect.form.new_operator = user
>>> reassign_by_prospect.execute('reassign_by_prospect')
>>> prospect1.reload()
>>> prospect1.assigned_operator.name
@@ -348,9 +389,15 @@ Crear un usuario de rol administrador::
>>> admin.save()
>>> admin.user_admin == True
True
Agregar un nuevo método de contacto desde prospecto
>>> contact_method = prospect1.contact_methods.new(value='0000000000', name='Nuevo', job='Puesto increíble')
>>> prospect1.save()
>>> prospect1.contact_methods[-1].value
'0000000000'
>>> prospect_trace.prospect_contacts[-1].value
'0000000000'
--------
Reportes

View File

@@ -8,5 +8,8 @@ this repository contains the full copyright notices and license terms. -->
<newline/>
<label name="description"/>
<field name="description"/>
<newline/>
<label name="contacts"/>
<field name="contacts"/>
</group>
</form>

View File

@@ -4,4 +4,6 @@ this repository contains the full copyright notices and license terms. -->
<tree>
<field name="prospect_trace" expand="1"/>
<field name="description" expand="1"/>
<field name="contacts" expand="1"/>
<button name="close_task"/>
</tree>

View File

@@ -22,13 +22,24 @@ this repository contains the full copyright notices and license terms. -->
<page string="Contact methods" id="contact_methods">
<field name="contact_methods" colspan="2"/>
</page>
<page string="About prospect" id="contact_methods">
<label name="rating"/>
<field name="rating"/>
<newline/>
<label name="comments"/>
<field name="comments"/>
</page>
</notebook>
<newline/>
<group col="4" id="stated">
<label name="assigned_operator"/>
<field name="assigned_operator"/>
<label name="state"/>
<field name="state"/>
<group col="6" colspan="5" id="footer" yalign="0">
<label name="assigned_operator"/>
<field name="assigned_operator"/>
<label name="state"/>
<field name="state"/>
<group col="-1" colspan="1" id="checkboxes">
<label name="active"/>
<field name="active" xexpand="0" width="25"/>
</group>
</group>
</form>

View File

@@ -7,4 +7,5 @@ this repository contains the full copyright notices and license terms. -->
<field name="department" expand="1"/>
<field name="city" expand="1"/>
<field name="assigned_operator" expand="1"/>
<field name="rating" expand="1"/>
</tree>