11 Commits

Author SHA1 Message Date
fa850b69ef No-estable: Inicio reporte por operario
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-30 19:15:45 -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
16 changed files with 254 additions and 37 deletions

View File

@@ -4,6 +4,7 @@ from . import prospect_trace
from . import call
from . import pending_call
from . import user
from . import print_report_by_operator
from .locations import city
from .locations import department
@@ -14,8 +15,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 +29,7 @@ def register():
prospect_trace.MakeCallAskTask,
prospect.ReassignProspectByOperatorStart,
prospect.ReassignProspectByProspectStart,
print_report_by_operator.PrintReportByOperatorStart,
module='sale_opportunity_management', type_='model')
Pool.register(
prospect_trace.ScheduleCall,
@@ -35,6 +37,7 @@ def register():
prospect_trace.MakeCall,
prospect.ReassignProspectByOperator,
prospect.ReasignProspectByProspect,
print_report_by_operator.PrintReportByOperator,
module='sale_opportunity_management', type_='wizard')
Pool.register(
module='sale_opportunity_management', type_='report')

43
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,43 @@ 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)
@classmethod
def __setup__(cls):
super(PendingTask, cls).__setup__()
cls._buttons.update({
'close_task': {
'invisible': Eval('state') == 'done'
}
})
@classmethod
@ModelView.button
def close_task(cls, tasks):
for task in tasks:
task.state = 'done'
task.save()
@classmethod
def default_state(cls):
return 'pending'

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,21 @@ 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.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 +286,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 +418,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 +455,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 +476,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 +495,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 +503,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 +565,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

@@ -0,0 +1,24 @@
# 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.model import ModelSQL, ModelView, fields
from trytond.wizard import Wizard, StateView, Button # , StateReport
from trytond.model import fields, ModelView
class PrintReportByOperatorStart(ModelView):
'Vista inicial de reporte por operario'
__name__ = 'sale.print_report_by_operator.start'
start_date = fields.Date('Start date')
end_date = fields.Date('End date')
class PrintReportByOperator(Wizard):
'Generar reporte por operario'
__name__ = 'sale.print_report_by_operator'
start = StateView(
'sale.print_report_by_operator.start',
'sale_opportunity_management.print_report_by_operator_start_view_form',
[Button("Cancel", "end", "tryton-cancel"),
Button("Print Report", "print_report", "tryton-ok", default=True)])

View File

@@ -0,0 +1,16 @@
<!-- <?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. -->
<tryton>
<data>
<record model="ir.action.wizard" id="print_report_by_operator_wizard">
<field name="name">Print report by operator</field>
<field name="wiz_name">sale.print_report_by_operator</field>
</record>
<record model="ir.ui.view" id="print_report_by_operator_start_view_form">
<field name="model">sale.print_report_by_operator.start</field>
<field name="type">form</field>
<field name="name">print_report_by_operator_start_form</field>
</record>
<data>
<tryton/> -->

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,6 +38,15 @@ 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'

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)
@@ -49,6 +49,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.prospect = self.prospect
@classmethod
def __setup__(cls):
super(ProspectTrace, cls).__setup__()

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'
@@ -282,6 +291,13 @@ Hacer llamada y programar tarea
>>> task
proteus.Model.get('sale.pending_task')(1)
>>> task.state
'pending'
>>> task.click('close_task')
>>> task.state
'done'
Hacer llamada y cerrar venta (Seguimiento de prospecto)::
>>> make_call = Wizard('sale.prospect_trace.make_call', [prospect_trace])
>>> make_call.form.description = 'Closed sale'
@@ -349,8 +365,14 @@ Crear un usuario de rol administrador::
>>> admin.user_admin == True
True
.. Generar reporte por operario y consolidado::
.. >>> PrintReportByOperator = Model.get('sale.print_report_by_operato`r', type='wizard')
.. >>> session_id, _, _ = PrintReportByOperator.create()
.. >>> print_report_by_operator = Wizard('sale.print_report_by_operator', [])
.. >>> print_report_by_operator.form.start_date = date.today()
.. >>> print_report_by_operator.form.end_date = date.today()
.. >>> print_report_by_operator.execute('print_report')
--------
Reportes

View File

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

View File

@@ -0,0 +1,7 @@
<?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. -->
<tree>
<field name="start_date" expand="1"/>
<field name="end_date" expand="1"/>
</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>