Compare commits
126 Commits
0be22b3298
...
7.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4fe42e15a | ||
| d1ad40203b | |||
| 9c368809f9 | |||
| e40991de02 | |||
| b8ba775733 | |||
| 336a266578 | |||
| 22fb3736a7 | |||
| 5cc7ef011d | |||
| 72ae0cfa22 | |||
| 0b7d15f35b | |||
| 8a0aa29368 | |||
| f71e6f4671 | |||
| cf874db55f | |||
| e97e8fa99d | |||
| 5a2c5217a6 | |||
| d50cca2924 | |||
| c1be04d009 | |||
| 214c6fc089 | |||
| a7bf0f2a38 | |||
| 243f1123a8 | |||
| faa8f35384 | |||
| 78fcd0231d | |||
| 3ac393dd01 | |||
| abf0c05894 | |||
| a73cd43582 | |||
| 0ccb733dab | |||
| 649f610bb0 | |||
| c32b4ce31c | |||
| 97bbcaed92 | |||
| a1716141b0 | |||
| 0c09498340 | |||
| 8e60272f91 | |||
| 4ec1d2e2cd | |||
| b36160c228 | |||
| 0460324ddf | |||
| 33ac57175c | |||
| 732b9dbfb8 | |||
| 01b5119f0b | |||
| eed86133f4 | |||
| dd3cd79a1f | |||
| 766f3fbc0b | |||
| 2bd62e1b14 | |||
| 94321866eb | |||
| f9bf0d3384 | |||
| 1bcc6e5294 | |||
| c9de0ab42e | |||
| d925fcf913 | |||
| 033f1aad43 | |||
| fd24a757fb | |||
| 3d77cf9a98 | |||
| 9efb29f1a1 | |||
| 8c1ed18530 | |||
| 1a469a5106 | |||
| fc70d7cb74 | |||
| ceb9f07aab | |||
| bdcf78ad56 | |||
| 79dd0454d6 | |||
| a8c6ecaa79 | |||
| 18413d9005 | |||
| e0c47961bc | |||
| 22478c9e68 | |||
| 8ec3e4b983 | |||
| 543a52303c | |||
| 70aa3f96d4 | |||
| 27d4ce8a77 | |||
| 2eb52e9dce | |||
| ed07f5fcbc | |||
| 3d77056e6f | |||
| e260c70a11 | |||
| 416804983b | |||
| 0364110866 | |||
| 27dcca74bc | |||
| 082d070643 | |||
| 1a1b262720 | |||
| 9067aa1446 | |||
| 7c39fcc429 | |||
| 1ece8ae959 | |||
| 05ae82839b | |||
| 31fb4211e4 | |||
| 8fa5d20ea6 | |||
| 4ffb654814 | |||
| a33d43cb57 | |||
| 3bb8ddbb2c | |||
| 11a541a3eb | |||
| 06a7402f0c | |||
| f3f7493d6c | |||
| 16508c5961 | |||
| 4449b57f60 | |||
| 9f8e0b96af | |||
| 229fa9044a | |||
| a8da18e2b6 | |||
| 8d1d5d1553 | |||
| 36f074a519 | |||
| d330ac341a | |||
| 1187dd6ecc | |||
| fd667a518b | |||
| b34a1e19af | |||
| 56550df81a | |||
| f0a5e30b38 | |||
| a63dd54089 | |||
| 3fc2db8543 | |||
| 05ff4b8f8d | |||
| 881f34d582 | |||
| d7095e05bb | |||
| c0db903ac8 | |||
| 93c2f10040 | |||
| 590e604604 | |||
| 2c68c3bb53 | |||
| 3c4e8f5a26 | |||
| 51d58de12a | |||
| 1bb4af8f16 | |||
| c3ad43d144 | |||
| bc4833b3cf | |||
| 1f52dcba26 | |||
| 582c8adbd3 | |||
| ca2d115e22 | |||
| 6d77af53ef | |||
| 8ab3a97b3c | |||
| 0d1602fe1d | |||
| 9b2c40d821 | |||
| d7d5c95b29 | |||
| 1d38d797c5 | |||
| 452b97cdf9 | |||
| 87da50560a | |||
| f7e8e40d4c | |||
| b479e83d8c |
@@ -1 +1,2 @@
|
|||||||
trytond: while true; do trytond -d ${DB_NAME} --dev -v -c $SCRIPT_DIR/trytond.cfg; done
|
trytond: while true; do trytond -d ${DB_NAME} --dev -v -c $SCRIPT_DIR/trytond.cfg; done
|
||||||
|
monitor: python3 $SCRIPT_DIR/dev.py
|
||||||
16
.dev/dev.py
@@ -2,9 +2,12 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
|
import time
|
||||||
|
|
||||||
import inotify.adapters
|
import inotify.adapters
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO, stream=sys.stderr)
|
||||||
|
|
||||||
SRC = os.environ['SRC']
|
SRC = os.environ['SRC']
|
||||||
MODULE_NAME = os.environ['MODULE_NAME']
|
MODULE_NAME = os.environ['MODULE_NAME']
|
||||||
DB_NAME = os.environ['DB_NAME']
|
DB_NAME = os.environ['DB_NAME']
|
||||||
@@ -18,12 +21,17 @@ def _main():
|
|||||||
for event in i.event_gen(yield_nones=False):
|
for event in i.event_gen(yield_nones=False):
|
||||||
(_, type_names, path, filename) = event
|
(_, type_names, path, filename) = event
|
||||||
(_, ext) = os.path.splitext(filename)
|
(_, ext) = os.path.splitext(filename)
|
||||||
|
if 'IN_CLOSE_WRITE' not in type_names:
|
||||||
|
continue
|
||||||
|
|
||||||
if ext in ['.py', '.xml', '.cfg']:
|
if ext in ['.py', '.xml', '.cfg']:
|
||||||
if os.system("trytond-admin -d {} -u {}".format(DB_NAME, MODULE_NAME)) != 0:
|
for _ in range(0, 10):
|
||||||
print("fallo trytond-admin", file=sys.stderr)
|
if os.system("trytond-admin -d {} -u {}".format(DB_NAME, MODULE_NAME)) != 0:
|
||||||
|
time.sleep(2)
|
||||||
logging.info("ACTUALIZADO TRYTOND POR CAMBIO DE ARCHIVO %s", filename)
|
logging.error("fallo trytond-admin")
|
||||||
|
else:
|
||||||
|
logging.info("ACTUALIZADO TRYTOND POR CAMBIO DE ARCHIVO %s", filename)
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
[web]
|
[web]
|
||||||
listen = 0.0.0.0:8000
|
listen = 0.0.0.0:8000
|
||||||
|
root=/var/lib/trytond/www
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# variables que puedo usar? https://woodpecker-ci.org/docs/0.15/usage/environment#built-in-environment-variables
|
# variables que puedo usar? https://woodpecker-ci.org/docs/0.15/usage/environment#built-in-environment-variables
|
||||||
|
|
||||||
pipeline:
|
steps:
|
||||||
style:
|
style:
|
||||||
image: python:3.9
|
image: python:3.9
|
||||||
commands:
|
commands:
|
||||||
@@ -20,7 +20,7 @@ pipeline:
|
|||||||
- python3 -m unittest
|
- python3 -m unittest
|
||||||
|
|
||||||
notify-success:
|
notify-success:
|
||||||
image: plugins/matrix
|
image: gitea.onecluster.org/alnus/plugins/matrix:latest
|
||||||
settings:
|
settings:
|
||||||
home_server: https://matrix.org
|
home_server: https://matrix.org
|
||||||
roomid: "!oxZmsJwfvciTuLYIwg:matrix.org"
|
roomid: "!oxZmsJwfvciTuLYIwg:matrix.org"
|
||||||
|
|||||||
@@ -18,12 +18,14 @@
|
|||||||
1. iniciar entorno `rake init`
|
1. iniciar entorno `rake init`
|
||||||
2. iterar con `rake tdd`
|
2. iterar con `rake tdd`
|
||||||
3. detener el entorno `rake down`
|
3. detener el entorno `rake down`
|
||||||
|
4. limpiar cache `git clean -xdf`
|
||||||
|
|
||||||
### entorno vivo de desarrollo
|
### entorno vivo de desarrollo
|
||||||
|
|
||||||
1. iniciar entorno `rake live:up`
|
1. iniciar entorno `rake live:up`
|
||||||
2. conectar cliente tryton a `localhost:8000` usuario: `admin` y clave: `admin`
|
2. conectar cliente tryton a `localhost:8000` usuario: `admin` y clave: `admin`
|
||||||
1. si desea ver la salida de trytond usar `rake live:tail`
|
1. o bien usar cliente web via `http://localhost:8000`
|
||||||
|
2. si desea ver la salida de trytond usar `rake live:tail`
|
||||||
3. detener entorno `rake live:down`
|
3. detener entorno `rake live:down`
|
||||||
|
|
||||||
### consideraciones
|
### consideraciones
|
||||||
|
|||||||
12
Dockerfile
@@ -1,4 +1,16 @@
|
|||||||
|
# TOMADO DE: https://hg.tryton.org/tryton-docker/file/tip/6.6/Dockerfile
|
||||||
|
FROM node as builder-node
|
||||||
|
|
||||||
|
ENV SERIES 6.8
|
||||||
|
RUN npm install -g bower
|
||||||
|
RUN curl https://downloads.tryton.org/${SERIES}/tryton-sao-last.tgz | tar zxf - -C /
|
||||||
|
RUN cd /package && bower install --allow-root
|
||||||
|
|
||||||
FROM python:3.9-bullseye
|
FROM python:3.9-bullseye
|
||||||
|
|
||||||
# trytond DB_CACHE requiere commandos `pg_dump` y `pg_restore`
|
# trytond DB_CACHE requiere commandos `pg_dump` y `pg_restore`
|
||||||
RUN apt-get update && apt-get install -y postgresql-client
|
RUN apt-get update && apt-get install -y postgresql-client
|
||||||
|
|
||||||
|
# TOMADO DE: https://hg.tryton.org/tryton-docker/file/tip/6.6/Dockerfile
|
||||||
|
COPY --from=builder-node /package /var/lib/trytond/www
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
doc/index.rst
|
./tests/scenario_sale_opportunity_management.rst
|
||||||
4
Rakefile
@@ -12,8 +12,8 @@ end
|
|||||||
desc 'poblar entorno'
|
desc 'poblar entorno'
|
||||||
task :init => [:up] do
|
task :init => [:up] do
|
||||||
pecker = YAML.load_file(WOODPECKER_YML)
|
pecker = YAML.load_file(WOODPECKER_YML)
|
||||||
['tests', 'style'].each do |pipeline|
|
['tests', 'style'].each do |steps|
|
||||||
pecker.dig('pipeline', pipeline, 'commands').grep(/install/).each do |cmd|
|
pecker.dig('steps', steps, 'commands').grep(/install/).each do |cmd|
|
||||||
compose('exec', 'app.dev', cmd)
|
compose('exec', 'app.dev', cmd)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
16
__init__.py
@@ -3,6 +3,7 @@ from . import prospect
|
|||||||
from . import prospect_trace
|
from . import prospect_trace
|
||||||
from . import call
|
from . import call
|
||||||
from . import pending_call
|
from . import pending_call
|
||||||
|
from . import user
|
||||||
from .locations import city
|
from .locations import city
|
||||||
from .locations import department
|
from .locations import department
|
||||||
|
|
||||||
@@ -11,16 +12,29 @@ __all__ = ['register']
|
|||||||
|
|
||||||
def register():
|
def register():
|
||||||
Pool.register(
|
Pool.register(
|
||||||
|
user.User,
|
||||||
pending_call.PendingCall,
|
pending_call.PendingCall,
|
||||||
call.Call,
|
call.Call,
|
||||||
|
call.PendingTask,
|
||||||
department.Department,
|
department.Department,
|
||||||
city.City,
|
city.City,
|
||||||
prospect.ContactMethod,
|
prospect.ContactMethod,
|
||||||
prospect.Prospect,
|
prospect.Prospect,
|
||||||
prospect_trace.ProspectTrace,
|
prospect_trace.ProspectTrace,
|
||||||
|
prospect.AssignOperatorStart,
|
||||||
|
prospect_trace.ScheduleCallStart,
|
||||||
|
prospect_trace.MakeCallStart,
|
||||||
|
prospect_trace.MakeCallAsk,
|
||||||
|
prospect_trace.MakeCallAskTask,
|
||||||
|
prospect.ReassignProspectByOperatorStart,
|
||||||
|
prospect.ReassignProspectByProspectStart,
|
||||||
module='sale_opportunity_management', type_='model')
|
module='sale_opportunity_management', type_='model')
|
||||||
Pool.register(
|
Pool.register(
|
||||||
|
prospect_trace.ScheduleCall,
|
||||||
|
prospect.AssignOperator,
|
||||||
|
prospect_trace.MakeCall,
|
||||||
|
prospect.ReassignProspectByOperator,
|
||||||
|
prospect.ReasignProspectByProspect,
|
||||||
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')
|
||||||
|
|||||||
80
call.py
@@ -1,7 +1,6 @@
|
|||||||
from trytond.model import ModelSQL, ModelView, fields
|
from trytond.model import ModelSQL, ModelView, fields
|
||||||
|
from trytond.pyson import Eval
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
|
||||||
|
|
||||||
from .selections.interest import Interest
|
from .selections.interest import Interest
|
||||||
from .selections.call_types import CallTypes
|
from .selections.call_types import CallTypes
|
||||||
from .selections.call_results import CallResults
|
from .selections.call_results import CallResults
|
||||||
@@ -9,28 +8,81 @@ from .selections.call_results import CallResults
|
|||||||
|
|
||||||
class Call(ModelSQL, ModelView):
|
class Call(ModelSQL, ModelView):
|
||||||
'Llamada'
|
'Llamada'
|
||||||
|
|
||||||
__name__ = 'sale.call'
|
__name__ = 'sale.call'
|
||||||
|
_order_name = 'date'
|
||||||
|
_states = {'readonly': True}
|
||||||
|
|
||||||
date = fields.Date('Date')
|
date = fields.Date('Date', states=_states)
|
||||||
description = fields.Text('Description', strip=True)
|
description = fields.Text('Description', strip=True)
|
||||||
|
|
||||||
prospect_trace = fields.Many2One('sale.prospect_trace', 'Prospect trace')
|
prospect_trace = fields.Many2One(
|
||||||
|
'sale.prospect_trace', 'Prospect trace', required=True, states=_states)
|
||||||
|
|
||||||
interest = fields.Selection(
|
interest = fields.Selection(
|
||||||
Interest.get_interest_levels(), 'Interest', required=True)
|
Interest.get_interest_levels(), 'Interest', required=True)
|
||||||
call_type = fields.Selection(CallTypes.get_call_types(), 'Call type')
|
|
||||||
|
call_type = fields.Selection(
|
||||||
|
CallTypes.get_call_types(), 'Call type', states=_states)
|
||||||
call_result = fields.Selection(
|
call_result = fields.Selection(
|
||||||
CallResults.get_call_results(), 'Call result')
|
CallResults.get_call_results(),
|
||||||
|
'Call result', states=_states)
|
||||||
|
call_business_unit = fields.Selection(
|
||||||
|
[('brigade', 'Brigade'),
|
||||||
|
('optics', 'Optics'),
|
||||||
|
('equipment', 'Equipment')],
|
||||||
|
'Business unit', states=_states
|
||||||
|
)
|
||||||
|
operator_who_called = fields.Many2One(
|
||||||
|
'res.user', "Operator who called", states=_states)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def __setup__(cls):
|
||||||
|
super(Call, cls).__setup__()
|
||||||
|
|
||||||
|
cls._order = [
|
||||||
|
('date', 'DESC NULLS FIRST')
|
||||||
|
]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def default_date(cls):
|
def default_date(cls):
|
||||||
return date.today()
|
return date.today()
|
||||||
|
|
||||||
@fields.depends('interest', 'call_result')
|
|
||||||
def on_change_interest(self):
|
class PendingTask(ModelSQL, ModelView):
|
||||||
if self.interest:
|
'Tarea a realizar a un seguimiento de prospecto'
|
||||||
if self.interest == '0':
|
__name__ = "sale.pending_task"
|
||||||
self.call_result = 'missed_call'
|
|
||||||
else:
|
description = fields.Text(
|
||||||
self.call_result = 'answered_call'
|
'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'
|
||||||
|
|||||||
102
call.xml
@@ -3,11 +3,26 @@
|
|||||||
this repository contains the full copyright notices and license terms. -->
|
this repository contains the full copyright notices and license terms. -->
|
||||||
<tryton>
|
<tryton>
|
||||||
<data>
|
<data>
|
||||||
|
<record model="res.group" id="group_call">
|
||||||
|
<field name="name">Calls</field>
|
||||||
|
</record>
|
||||||
|
<record model="res.group" id="group_call_admin">
|
||||||
|
<field name="name">Calls Administrator</field>
|
||||||
|
<field name="parent" ref="group_call"/>
|
||||||
|
</record>
|
||||||
|
<record model="res.user-res.group" id="user_admin_group_call">
|
||||||
|
<field name="user" ref="res.user_admin"/>
|
||||||
|
<field name="group" ref="group_call"/>
|
||||||
|
</record>
|
||||||
|
<record model="res.user-res.group" id="user_admin_group_call_admin">
|
||||||
|
<field name="user" ref="res.user_admin"/>
|
||||||
|
<field name="group" ref="group_call_admin"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
<record model="ir.action.act_window" id="act_call_tree">
|
<record model="ir.action.act_window" id="act_call_tree">
|
||||||
<field name="name">Calls</field>
|
<field name="name">Calls</field>
|
||||||
<field name="res_model">sale.call</field>
|
<field name="res_model">sale.call</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="call_view_tree">
|
<record model="ir.ui.view" id="call_view_tree">
|
||||||
<field name="model">sale.call</field>
|
<field name="model">sale.call</field>
|
||||||
<field name="type">tree</field>
|
<field name="type">tree</field>
|
||||||
@@ -18,7 +33,6 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<field name="type">form</field>
|
<field name="type">form</field>
|
||||||
<field name="name">call_form</field>
|
<field name="name">call_form</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.action.act_window.view" id="act_call_tree_view1">
|
<record model="ir.action.act_window.view" id="act_call_tree_view1">
|
||||||
<field name="sequence" eval="10"/>
|
<field name="sequence" eval="10"/>
|
||||||
<field name="view" ref="call_view_tree"/>
|
<field name="view" ref="call_view_tree"/>
|
||||||
@@ -29,15 +43,93 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<field name="view" ref="call_view_form"/>
|
<field name="view" ref="call_view_form"/>
|
||||||
<field name="act_window" ref="act_call_tree"/>
|
<field name="act_window" ref="act_call_tree"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<menuitem
|
<menuitem
|
||||||
name="Calls"
|
name="Calls"
|
||||||
sequence="10"
|
sequence="10"
|
||||||
id="menu_calls"/>
|
id="menu_calls"
|
||||||
|
icon="tryton-phone"/>
|
||||||
<menuitem
|
<menuitem
|
||||||
parent="menu_calls"
|
parent="menu_calls"
|
||||||
sequence="30"
|
sequence="30"
|
||||||
id="menu_calls_tree"
|
id="menu_calls_tree"
|
||||||
action="act_call_tree"/>
|
action="act_call_tree"
|
||||||
|
icon="tryton-graph"/>
|
||||||
|
|
||||||
|
<record model="ir.ui.menu-res.group" id="menu_call_group_call">
|
||||||
|
<field name="menu" ref="menu_calls_tree"/>
|
||||||
|
<field name="group" ref="group_call"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.model.access" id="access_calls">
|
||||||
|
<field name="model" search="[('model', '=', 'sale.call')]"/>
|
||||||
|
<field name="perm_read" eval="False"/>
|
||||||
|
<field name="perm_write" eval="False"/>
|
||||||
|
<field name="perm_create" eval="False"/>
|
||||||
|
<field name="perm_delete" eval="False"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.model.access" id="access_calls_calls">
|
||||||
|
<field name="model" search="[('model', '=', 'sale.call')]"/>
|
||||||
|
<field name="group" ref="group_call"/>
|
||||||
|
<field name="perm_read" eval="True"/>
|
||||||
|
<field name="perm_write" eval="True"/>
|
||||||
|
<field name="perm_create" eval="True"/>
|
||||||
|
<field name="perm_delete" eval="True"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.action.act_window" id="act_pending_task_tree">
|
||||||
|
<field name="name">Pending tasks</field>
|
||||||
|
<field name="res_model">sale.pending_task</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.view" id="pending_task_view_tree">
|
||||||
|
<field name="model">sale.pending_task</field>
|
||||||
|
<field name="type">tree</field>
|
||||||
|
<field name="name">pending_task_tree</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.view" id="pending_task_view_form">
|
||||||
|
<field name="model">sale.pending_task</field>
|
||||||
|
<field name="type">form</field>
|
||||||
|
<field name="name">pending_task_form</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.action.act_window.view" id="act_pending_task_tree_view1">
|
||||||
|
<field name="sequence" eval="30"/>
|
||||||
|
<field name="view" ref="pending_task_view_tree"/>
|
||||||
|
<field name="act_window" ref="act_pending_task_tree"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.action.act_window.view" id="act_pending_task_form_view1">
|
||||||
|
<field name="sequence" eval="40"/>
|
||||||
|
<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>
|
</data>
|
||||||
</tryton>
|
</tryton>
|
||||||
35
icons.xml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?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.ui.icon" id="party_icon">
|
||||||
|
<field name="name">tryton-party</field>
|
||||||
|
<field name="path">icons/tryton-party.svg</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.icon" id="person_icon">
|
||||||
|
<field name="name">tryton-person</field>
|
||||||
|
<field name="path">icons/tryton-person.svg</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.icon" id="unnasigned_icon">
|
||||||
|
<field name="name">tryton-person-negative</field>
|
||||||
|
<field name="path">icons/tryton-person-negative.svg</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.icon" id="asigned_icon">
|
||||||
|
<field name="name">tryton-person-positive</field>
|
||||||
|
<field name="path">icons/tryton-person-positive.svg</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.icon" id="tel_icon">
|
||||||
|
<field name="name">tryton-tel</field>
|
||||||
|
<field name="path">icons/tryton-tel.svg</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.icon" id="target_icon">
|
||||||
|
<field name="name">tryton-target</field>
|
||||||
|
<field name="path">icons/tryton-target.svg</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.icon" id="call_icon">
|
||||||
|
<field name="name">tryton-phone</field>
|
||||||
|
<field name="path">icons/tryton-phone.svg</field>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</tryton>
|
||||||
4
icons/tryton-party.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/>
|
||||||
|
<path d="M0 0h24v24H0z" fill="none"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 258 B |
7
icons/tryton-person-negative.svg
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#000000">
|
||||||
|
|
||||||
|
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||||
|
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
7
icons/tryton-person-positive.svg
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#000000">
|
||||||
|
|
||||||
|
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||||
|
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
7
icons/tryton-person.svg
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#000000">
|
||||||
|
|
||||||
|
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||||
|
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
12
icons/tryton-phone.svg
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
|
||||||
|
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||||
|
|
||||||
|
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
|
||||||
|
<g id="SVGRepo_iconCarrier"> <path d="M15.5562 14.5477L15.1007 15.0272C15.1007 15.0272 14.0181 16.167 11.0631 13.0559C8.10812 9.94484 9.1907 8.80507 9.1907 8.80507L9.47752 8.50311C10.1841 7.75924 10.2507 6.56497 9.63424 5.6931L8.37326 3.90961C7.61028 2.8305 6.13596 2.68795 5.26145 3.60864L3.69185 5.26114C3.25823 5.71766 2.96765 6.30945 3.00289 6.96594C3.09304 8.64546 3.81071 12.259 7.81536 16.4752C12.0621 20.9462 16.0468 21.1239 17.6763 20.9631C18.1917 20.9122 18.6399 20.6343 19.0011 20.254L20.4217 18.7584C21.3806 17.7489 21.1102 16.0182 19.8833 15.312L17.9728 14.2123C17.1672 13.7486 16.1858 13.8848 15.5562 14.5477Z" fill="#267F82"/> <path d="M13.2595 1.87983C13.3257 1.47094 13.7122 1.19357 14.1211 1.25976C14.1464 1.26461 14.2279 1.27983 14.2705 1.28933C14.3559 1.30834 14.4749 1.33759 14.6233 1.38082C14.9201 1.46726 15.3347 1.60967 15.8323 1.8378C16.8286 2.29456 18.1544 3.09356 19.5302 4.46936C20.906 5.84516 21.705 7.17097 22.1617 8.16725C22.3899 8.66487 22.5323 9.07947 22.6187 9.37625C22.6619 9.52466 22.6912 9.64369 22.7102 9.72901C22.7197 9.77168 22.7267 9.80594 22.7315 9.83125L22.7373 9.86245C22.8034 10.2713 22.5286 10.6739 22.1197 10.7401C21.712 10.8061 21.3279 10.53 21.2601 10.1231C21.258 10.1121 21.2522 10.0828 21.2461 10.0551C21.2337 9.9997 21.2124 9.91188 21.1786 9.79572C21.1109 9.56339 20.9934 9.21806 20.7982 8.79238C20.4084 7.94207 19.7074 6.76789 18.4695 5.53002C17.2317 4.29216 16.0575 3.59117 15.2072 3.20134C14.7815 3.00618 14.4362 2.88865 14.2038 2.82097C14.0877 2.78714 13.9417 2.75363 13.8863 2.7413C13.4793 2.67347 13.1935 2.28755 13.2595 1.87983Z" fill="#267F82"/> <path fill-rule="evenodd" clip-rule="evenodd" d="M13.4857 5.3293C13.5995 4.93102 14.0146 4.7004 14.4129 4.81419L14.2069 5.53534C14.4129 4.81419 14.4129 4.81419 14.4129 4.81419L14.4144 4.81461L14.4159 4.81505L14.4192 4.81602L14.427 4.81834L14.4468 4.8245C14.4618 4.82932 14.4807 4.8356 14.5031 4.84357C14.548 4.85951 14.6074 4.88217 14.6802 4.91337C14.8259 4.97581 15.0249 5.07223 15.2695 5.21694C15.7589 5.50662 16.4271 5.9878 17.2121 6.77277C17.9971 7.55775 18.4782 8.22593 18.7679 8.7154C18.9126 8.95991 19.009 9.15897 19.0715 9.30466C19.1027 9.37746 19.1254 9.43682 19.1413 9.48173C19.1493 9.50418 19.1555 9.52301 19.1604 9.53809L19.1665 9.55788L19.1688 9.56563L19.1698 9.56896L19.1702 9.5705C19.1702 9.5705 19.1707 9.57194 18.4495 9.77798L19.1707 9.57194C19.2845 9.97021 19.0538 10.3853 18.6556 10.4991C18.2607 10.6119 17.8492 10.3862 17.7313 9.99413L17.7276 9.98335C17.7223 9.96832 17.7113 9.93874 17.6928 9.89554C17.6558 9.8092 17.5887 9.66797 17.4771 9.47938C17.2541 9.10264 16.8514 8.53339 16.1514 7.83343C15.4515 7.13348 14.8822 6.73078 14.5055 6.50781C14.3169 6.39619 14.1757 6.32909 14.0893 6.29209C14.0461 6.27358 14.0165 6.26254 14.0015 6.25721L13.9907 6.25352C13.5987 6.13564 13.3729 5.72419 13.4857 5.3293Z" fill="#267F82"/> </g>
|
||||||
|
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.2 KiB |
7
icons/tryton-target.svg
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||||
|
<svg fill="#267F82" width="800px" height="800px" viewBox="0 0 256 256" id="Flat" xmlns="http://www.w3.org/2000/svg" stroke="#267F82">
|
||||||
|
|
||||||
|
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||||
|
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
18
icons/tryton-tel.svg
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="#267F82">
|
||||||
|
|
||||||
|
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||||
|
|
||||||
|
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
|
||||||
|
<g id="SVGRepo_iconCarrier">
|
||||||
|
|
||||||
|
<path d="M50.19 20.6a3.33 3.33 0 0 0-4.62.8l-1.9 2.71a3.31 3.31 0 0 0 .8 4.61c5.41 3.81 1.59 9.22-.31 11.93S38.44 48.76 33 45a3.31 3.31 0 0 0-4.61.8l-1.91 2.7a3.31 3.31 0 0 0 .8 4.61C34.07 57.83 40 58 49.57 44.46s7.43-19.09.62-23.86z"/>
|
||||||
|
|
||||||
|
<rect x="8" y="8" width="6" height="6"/>
|
||||||
|
|
||||||
|
<rect x="20" y="8" width="6" height="6"/>
|
||||||
|
|
||||||
|
<rect x="32" y="8" width="6" height="6"/>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
600
locale/es.po
Normal file
@@ -0,0 +1,600 @@
|
|||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||||
|
|
||||||
|
msgctxt "model:res.group,name:group_prospect"
|
||||||
|
msgid "Prospects"
|
||||||
|
msgstr "Prospectos"
|
||||||
|
|
||||||
|
msgctxt "model:res.group,name:group_prospect_admin"
|
||||||
|
msgid "Prospect Administrator"
|
||||||
|
msgstr "Administración de Prospectos"
|
||||||
|
|
||||||
|
msgctxt "model:res.group,name:group_call"
|
||||||
|
msgid "Calls"
|
||||||
|
msgstr "Llamadas"
|
||||||
|
|
||||||
|
msgctxt "model:res.group,name:group_call_admin"
|
||||||
|
msgid "Calls Administrator"
|
||||||
|
msgstr "Administrador de Llamadas"
|
||||||
|
|
||||||
|
msgctxt "model:res.group,name:group_prospect_trace"
|
||||||
|
msgid "Prospect Traces"
|
||||||
|
msgstr "Seguimiento de Prospectos"
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect_trace,prospect_business_unit:"
|
||||||
|
msgid "Business unit"
|
||||||
|
msgstr "Unidad de negocio"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect_trace,prospect_contacts:"
|
||||||
|
msgid "Prospect contacts"
|
||||||
|
msgstr "Métodos de contacto"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect_trace,prospect_city:"
|
||||||
|
msgid "City"
|
||||||
|
msgstr "Ciudad"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect_trace,prospect_assigned_operator:"
|
||||||
|
msgid "Assigned operator"
|
||||||
|
msgstr "Operario asignado"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect_trace,calls:"
|
||||||
|
msgid "Calls"
|
||||||
|
msgstr "Llamadas"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect_trace,pending_call:"
|
||||||
|
msgid "Pending call"
|
||||||
|
msgstr "LLamada pendiente"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect_trace,current_interest:"
|
||||||
|
msgid "Current interest"
|
||||||
|
msgstr "Interés actual"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect_trace,state:"
|
||||||
|
msgid "State"
|
||||||
|
msgstr "Estado"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect,name:"
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Nombre"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect,business_unit:"
|
||||||
|
msgid "Business unit"
|
||||||
|
msgstr "Unidad de negocio"
|
||||||
|
|
||||||
|
msgctxt "view:sale.prospect:"
|
||||||
|
msgid "Contact methods"
|
||||||
|
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"
|
||||||
|
msgstr "Métodos de contacto"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect,department:"
|
||||||
|
msgid "Department"
|
||||||
|
msgstr "Departamento"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect,city:"
|
||||||
|
msgid "City"
|
||||||
|
msgstr "Ciudad"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect,assigned_operator:"
|
||||||
|
msgid "Assigned operator"
|
||||||
|
msgstr "Operario asignado"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect,state:"
|
||||||
|
msgid "State"
|
||||||
|
msgstr "Estado"
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
msgctxt "field:sale.call,description:"
|
||||||
|
msgid "Description"
|
||||||
|
msgstr "Descripción"
|
||||||
|
|
||||||
|
msgctxt "field:sale.call,prospect_trace:"
|
||||||
|
msgid "Prospect trace"
|
||||||
|
msgstr "Seguimiento de prospecto"
|
||||||
|
|
||||||
|
msgctxt "field:sale.call,interest:"
|
||||||
|
msgid "Interest"
|
||||||
|
msgstr "Interés"
|
||||||
|
|
||||||
|
msgctxt "field:sale.call,call_type:"
|
||||||
|
msgid "Call type"
|
||||||
|
msgstr "Tipo"
|
||||||
|
|
||||||
|
msgctxt "field:sale.call,call_result:"
|
||||||
|
msgid "Call result"
|
||||||
|
msgstr "Resultado"
|
||||||
|
|
||||||
|
msgctxt "field:sale.call,call_business_unit:"
|
||||||
|
msgid "Business unit"
|
||||||
|
msgstr "Unidad de negocio"
|
||||||
|
|
||||||
|
msgctxt "field:sale.call,operator_who_called:"
|
||||||
|
msgid "Operator who called"
|
||||||
|
msgstr "Llamado por"
|
||||||
|
|
||||||
|
msgctxt "field:sale.pending_call,date:"
|
||||||
|
msgid "Date"
|
||||||
|
msgstr "Fecha"
|
||||||
|
|
||||||
|
msgctxt "field:prospect.contact_method,contact_type:"
|
||||||
|
msgid "Contact type"
|
||||||
|
msgstr "Tipo de contacto"
|
||||||
|
|
||||||
|
msgctxt "field:prospect.contact_method,value:"
|
||||||
|
msgid "Value"
|
||||||
|
msgstr "Valor"
|
||||||
|
|
||||||
|
msgctxt "field:prospect.contact_method,name:"
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Nombre"
|
||||||
|
|
||||||
|
msgctxt "field:prospect.contact_method,job:"
|
||||||
|
msgid "Job"
|
||||||
|
msgstr "Cargo"
|
||||||
|
|
||||||
|
msgctxt "field:prospect.contact_method,prospect:"
|
||||||
|
msgid "Prospect"
|
||||||
|
msgstr "Prospecto"
|
||||||
|
|
||||||
|
msgctxt "field:prospect.contact_method,prospect_trace:"
|
||||||
|
msgid "Prospect Trace"
|
||||||
|
msgstr "Seguimiento de prospecto"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect.assign.start,prospects_chunk:"
|
||||||
|
msgid "Prospects chunk"
|
||||||
|
msgstr "Cantidad de prospectos"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect.assign.start,operator:"
|
||||||
|
msgid "Operator"
|
||||||
|
msgstr "Operador"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect.assign.start,prospects:"
|
||||||
|
msgid "Prospects"
|
||||||
|
msgstr "Prospectos"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect.assign.start,business_unit:"
|
||||||
|
msgid "Business unit"
|
||||||
|
msgstr "Unidad de negocio"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect.reassign_by_operator.start,current_operator:"
|
||||||
|
msgid "Current operator"
|
||||||
|
msgstr "Operador actual"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect.reassign_by_operator.start,new_operator:"
|
||||||
|
msgid "New operator"
|
||||||
|
msgstr "Nuevo operador"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect.reassign_by_operator.start,prospects:"
|
||||||
|
msgid "Prospects"
|
||||||
|
msgstr "Prospectos"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect.reassign_by_prospect.start,prospect:"
|
||||||
|
msgid "Prospect"
|
||||||
|
msgstr "Prospecto"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect.reassign_by_prospect.start,new_operator:"
|
||||||
|
msgid "New operator"
|
||||||
|
msgstr "Nuevo operador"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect_trace.schedule.start,currency_date:"
|
||||||
|
msgid "Currency Date"
|
||||||
|
msgstr "Fecha actual"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect_trace.schedule.start,date_time:"
|
||||||
|
msgid "Date time"
|
||||||
|
msgstr "Fecha y hora"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect_trace.make_call.start,description:"
|
||||||
|
msgid "Description"
|
||||||
|
msgstr "Descripción"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect_trace.make_call.start,interest:"
|
||||||
|
msgid "Interest"
|
||||||
|
msgstr "Interés"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect_trace.make_call.start,schedule_call:"
|
||||||
|
msgid "Schedule call?"
|
||||||
|
msgstr "¿Agendar llamada?"
|
||||||
|
|
||||||
|
msgctxt "field:sale.prospect_trace.make_call.ask,currency_date:"
|
||||||
|
msgid "Currency Date"
|
||||||
|
msgstr "Fecha actual"
|
||||||
|
|
||||||
|
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"
|
||||||
|
msgstr "Brigada"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect,business_unit:"
|
||||||
|
msgid "Optics"
|
||||||
|
msgstr "Óptica"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect,business_unit:"
|
||||||
|
msgid "Equipment"
|
||||||
|
msgstr "Equipos"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect,state:"
|
||||||
|
msgid "Unsassigned"
|
||||||
|
msgstr "Sin asignar"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect,state:"
|
||||||
|
msgid "Assigned"
|
||||||
|
msgstr "Asignado"
|
||||||
|
|
||||||
|
msgctxt "selection:prospect.contact_method,contact_type:"
|
||||||
|
msgid "Phone"
|
||||||
|
msgstr "Teléfono fijo"
|
||||||
|
|
||||||
|
msgctxt "selection:prospect.contact_method,contact_type:"
|
||||||
|
msgid "Mobile"
|
||||||
|
msgstr "Celular"
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect.assign.start,business_unit:"
|
||||||
|
msgid "Optics"
|
||||||
|
msgstr "Óptica"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect.assign.start,business_unit:"
|
||||||
|
msgid "Equipment"
|
||||||
|
msgstr "Equipos"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect_trace,prospect_business_unit:"
|
||||||
|
msgid "Brigade"
|
||||||
|
msgstr "Brigada"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect_trace,prospect_business_unit:"
|
||||||
|
msgid "Optics"
|
||||||
|
msgstr "Óptica"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect_trace,prospect_business_unit:"
|
||||||
|
msgid "Equipment"
|
||||||
|
msgstr "Equipos"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect_trace,current_interest:"
|
||||||
|
msgid "0 - Not answered"
|
||||||
|
msgstr "0 - No contestó"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect_trace,current_interest:"
|
||||||
|
msgid "1 - Complete disinterest"
|
||||||
|
msgstr "1 - Completo desinterés"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect_trace,current_interest:"
|
||||||
|
msgid "2 - Middle interest"
|
||||||
|
msgstr "2 - Interés intermedio"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect_trace,current_interest:"
|
||||||
|
msgid "3 - High interest"
|
||||||
|
msgstr "3 - Interés alto"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect_trace,current_interest:"
|
||||||
|
msgid "4 - Closed sale"
|
||||||
|
msgstr "4 - Venta cerrada"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect_trace,state:"
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Abierto"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect_trace,state:"
|
||||||
|
msgid "With pending calls"
|
||||||
|
msgstr "Con llamada pendiente"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect_trace,state:"
|
||||||
|
msgid "Closed"
|
||||||
|
msgstr "Cerrado"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect_trace.make_call.start,schedule_call:"
|
||||||
|
msgid "Yes"
|
||||||
|
msgstr "Si"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect_trace.make_call.start,interest:"
|
||||||
|
msgid "0 - Not answered"
|
||||||
|
msgstr "0 - No contestó"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect_trace.make_call.start,interest:"
|
||||||
|
msgid "1 - Complete disinterest"
|
||||||
|
msgstr "1 - Completo desinterés"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect_trace.make_call.start,interest:"
|
||||||
|
msgid "2 - Middle interest"
|
||||||
|
msgstr "2 - Interés intermedio"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect_trace.make_call.start,interest:"
|
||||||
|
msgid "3 - High interest"
|
||||||
|
msgstr "3 - Interés alto"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.prospect_trace.make_call.start,interest:"
|
||||||
|
msgid "4 - Closed sale"
|
||||||
|
msgstr "4 - Venta cerrada"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.call,interest:"
|
||||||
|
msgid "0 - Not answered"
|
||||||
|
msgstr "0 - No contestó"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.call,interest:"
|
||||||
|
msgid "1 - Complete disinterest"
|
||||||
|
msgstr "1 - Completo desinterés"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.call,interest:"
|
||||||
|
msgid "2 - Middle interest"
|
||||||
|
msgstr "2 - Interés intermedio"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.call,interest:"
|
||||||
|
msgid "3 - High interest"
|
||||||
|
msgstr "3 - Interés alto"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.call,interest:"
|
||||||
|
msgid "4 - Closed sale"
|
||||||
|
msgstr "4 - Venta cerrada"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.call,call_type:"
|
||||||
|
msgid "First call"
|
||||||
|
msgstr "Primera llamada"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.call,call_type:"
|
||||||
|
msgid "Follow up call"
|
||||||
|
msgstr "LLamada de seguimiento"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.call,call_result:"
|
||||||
|
msgid "Missed call"
|
||||||
|
msgstr "Llamada perdida"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.call,call_result:"
|
||||||
|
msgid "Answered call"
|
||||||
|
msgstr "LLamada contestada"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.call,call_business_unit:"
|
||||||
|
msgid "Brigade"
|
||||||
|
msgstr "Brigada"
|
||||||
|
|
||||||
|
msgctxt "selection:sale.call,call_business_unit:"
|
||||||
|
msgid "Optics"
|
||||||
|
msgstr "Óptica"
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
msgctxt "model:ir.ui.menu,name:menu_calls_tree"
|
||||||
|
msgid "Calls"
|
||||||
|
msgstr "Llamadas"
|
||||||
|
|
||||||
|
msgctxt "model:ir.ui.menu,name:menu_prospect_trace_tree"
|
||||||
|
msgid "Prospect Traces"
|
||||||
|
msgstr "Seguimiento de Prospectos"
|
||||||
|
|
||||||
|
msgctxt "model:ir.ui.menu,name:menu_prospects_tree"
|
||||||
|
msgid "Prospects"
|
||||||
|
msgstr "Prospectos"
|
||||||
|
|
||||||
|
msgctxt "model:ir.ui.menu,name:menu_prospects_assigned_wizard"
|
||||||
|
msgid "Assign Operator"
|
||||||
|
msgstr "Asignar Operador"
|
||||||
|
|
||||||
|
msgctxt "model:ir.ui.menu,name:menu_reassign"
|
||||||
|
msgid "Reassign"
|
||||||
|
msgstr "Reasignar"
|
||||||
|
|
||||||
|
msgctxt "model:ir.ui.menu,name:menu_reassign_by_operator_wizard"
|
||||||
|
msgid "Reassign by operator"
|
||||||
|
msgstr "Reasignar por operador"
|
||||||
|
|
||||||
|
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"
|
||||||
|
msgstr "Agendar llamada"
|
||||||
|
|
||||||
|
msgctxt "model:ir.model.button,string:make_call_wizard_button"
|
||||||
|
msgid "Make call"
|
||||||
|
msgstr "Hacer llamada"
|
||||||
|
|
||||||
|
msgctxt "model:ir.model.button,string:close_trace_button"
|
||||||
|
msgid "Close trace"
|
||||||
|
msgstr "Cerrar seguimiento"
|
||||||
|
|
||||||
|
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"
|
||||||
|
msgstr "Cancelar"
|
||||||
|
|
||||||
|
msgctxt "wizard_button:sale.prospect_trace.make_call,start,make_call:"
|
||||||
|
msgid "Make call"
|
||||||
|
msgstr "Hacer llamada"
|
||||||
|
|
||||||
|
msgctxt "wizard_button:sale.prospect_trace.make_call,ask,end:"
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr "Cancelar"
|
||||||
|
|
||||||
|
msgctxt "wizard_button:sale.prospect_trace.make_call,ask,schedule_call:"
|
||||||
|
msgid "Schedule call"
|
||||||
|
msgstr "Agendar llamada"
|
||||||
|
|
||||||
|
msgctxt "wizard_button:sale.prospect_trace.schedule,start,end:"
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr "Cancelar"
|
||||||
|
|
||||||
|
msgctxt "wizard_button:sale.prospect_trace.schedule,start,schedule:"
|
||||||
|
msgid "Schedule"
|
||||||
|
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"
|
||||||
|
msgstr "Cancelar"
|
||||||
|
|
||||||
|
msgctxt "wizard_button:sale.prospect.assign,start,assign:"
|
||||||
|
msgid "Assign"
|
||||||
|
msgstr "Asignar"
|
||||||
|
|
||||||
|
msgctxt "wizard_button:sale.prospect.reassign_by_operator,start,end:"
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr "Cancelar"
|
||||||
|
|
||||||
|
msgctxt "wizard_button:sale.prospect.reassign_by_operator,start,reassign_by_operator:"
|
||||||
|
msgid "Reassign"
|
||||||
|
msgstr "Reasignar"
|
||||||
|
|
||||||
|
msgctxt "wizard_button:sale.prospect.reassign_by_prospect,start,end:"
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr "Cancelar"
|
||||||
|
|
||||||
|
msgctxt "wizard_button:sale.prospect.reassign_by_prospect,start,reassign_by_prospect:"
|
||||||
|
msgid "Reassign"
|
||||||
|
msgstr "Reasignar"
|
||||||
|
|
||||||
|
msgctxt "model:ir.action.act_window.domain,name:act_prospect_trace_domain_open"
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Abierto"
|
||||||
|
|
||||||
|
msgctxt "model:ir.action.act_window.domain,name:act_prospect_trace_domain_with_pending_calls"
|
||||||
|
msgid "With pending calls"
|
||||||
|
msgstr "Con llamada pendiente"
|
||||||
|
|
||||||
|
msgctxt "model:ir.action.act_window.domain,name:act_prospect_trace_domain_with_pending_calls"
|
||||||
|
msgid "With pending calls"
|
||||||
|
msgstr "Con llamada pendiente"
|
||||||
|
|
||||||
|
msgctxt "model:ir.action.act_window.domain,name:act_prospect_trace_domain_closed"
|
||||||
|
msgid "Closed"
|
||||||
|
msgstr "Cerrado"
|
||||||
|
|
||||||
|
msgctxt "model:ir.action.act_window.domain,name:act_prospect_trace_domain_all"
|
||||||
|
msgid "All"
|
||||||
|
msgstr "Todo"
|
||||||
|
|
||||||
|
msgctxt "model:ir.action.act_window.domain,name:act_prospect_domain_unassigned"
|
||||||
|
msgid "Unassigned"
|
||||||
|
msgstr "Sin asignar"
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
msgctxt "model:ir.action,name:make_call_wizard"
|
||||||
|
msgid "Make call"
|
||||||
|
msgstr "Hacer llamada"
|
||||||
|
|
||||||
|
msgctxt "model:ir.action,name:assign_operator_wizard"
|
||||||
|
msgid "Assign Operator"
|
||||||
|
msgstr "Asignar operador"
|
||||||
|
|
||||||
|
msgctxt "model:ir.action,name:reassign_by_operator_wizard"
|
||||||
|
msgid "Reassign by operator"
|
||||||
|
msgstr "Reasignar por operador"
|
||||||
|
|
||||||
|
msgctxt "model:ir.action,name:reassign_by_prospect_wizard"
|
||||||
|
msgid "Reassign by prospect"
|
||||||
|
msgstr "Reasignar por prospecto"
|
||||||
|
|
||||||
@@ -7,5 +7,8 @@ class PendingCall(ModelSQL, ModelView):
|
|||||||
'Llamada pendiente a un prospecto'
|
'Llamada pendiente a un prospecto'
|
||||||
__name__ = "sale.pending_call"
|
__name__ = "sale.pending_call"
|
||||||
|
|
||||||
date = fields.Date('Date', required=True)
|
date = fields.DateTime('Date', required=True)
|
||||||
prospect_trace = fields.Many2One('sale.prospect_trace', 'Prospect trace')
|
|
||||||
|
def get_rec_name(self, name):
|
||||||
|
if self.date:
|
||||||
|
return str(self.date)
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
<?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.act_window" id="act_pending_call_tree">
|
|
||||||
<field name="name">Pending calls</field>
|
|
||||||
<field name="res_model">sale.pending_call</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record model="ir.ui.view" id="pending_call_view_tree">
|
|
||||||
<field name="model">sale.pending_call</field>
|
|
||||||
<field name="type">tree</field>
|
|
||||||
<field name="name">pending_call_tree</field>
|
|
||||||
</record>
|
|
||||||
<record model="ir.ui.view" id="pending_call_view_form">
|
|
||||||
<field name="model">sale.pending_call</field>
|
|
||||||
<field name="type">form</field>
|
|
||||||
<field name="name">pending_call_form</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record model="ir.action.act_window.view" id="act_pending_call_tree_view1">
|
|
||||||
<field name="sequence" eval="10"/>
|
|
||||||
<field name="view" ref="pending_call_view_tree"/>
|
|
||||||
<field name="act_window" ref="act_pending_call_tree"/>
|
|
||||||
</record>
|
|
||||||
<record model="ir.action.act_window.view" id="act_pending_call_form_view1">
|
|
||||||
<field name="sequence" eval="20"/>
|
|
||||||
<field name="view" ref="pending_call_view_form"/>
|
|
||||||
<field name="act_window" ref="act_pending_call_tree"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!-- <menuitem
|
|
||||||
name="Calls"
|
|
||||||
sequence="10"
|
|
||||||
id="menu_calls"/> -->
|
|
||||||
<menuitem
|
|
||||||
parent="menu_calls"
|
|
||||||
sequence="40"
|
|
||||||
id="menu_pending_calls_tree"
|
|
||||||
action="act_pending_call_tree"/>
|
|
||||||
</data>
|
|
||||||
</tryton>
|
|
||||||
214
prospect.py
@@ -1,16 +1,25 @@
|
|||||||
# 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.model import ModelSQL, ModelView, fields
|
from trytond.wizard import Wizard, StateView, Button, StateTransition
|
||||||
|
from trytond.model import ModelSQL, ModelView, fields, DeactivableMixin
|
||||||
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, DeactivableMixin):
|
||||||
'Prospecto'
|
'Prospecto'
|
||||||
__name__ = 'sale.prospect'
|
__name__ = 'sale.prospect'
|
||||||
_rec_name = 'name'
|
_rec_name = 'name'
|
||||||
|
|
||||||
name = fields.Char('Name', required=True)
|
name = fields.Char('Name', required=True)
|
||||||
|
|
||||||
|
business_unit = fields.Selection(
|
||||||
|
[('brigade', 'Brigade'),
|
||||||
|
('optics', 'Optics'),
|
||||||
|
('equipment', 'Equipment')],
|
||||||
|
'Business unit', required=True
|
||||||
|
)
|
||||||
|
|
||||||
contact_methods = fields.One2Many(
|
contact_methods = fields.One2Many(
|
||||||
'prospect.contact_method',
|
'prospect.contact_method',
|
||||||
'prospect', 'Contact methods', required=True)
|
'prospect', 'Contact methods', required=True)
|
||||||
@@ -20,6 +29,33 @@ class Prospect(ModelSQL, ModelView):
|
|||||||
domain=[If(Eval('department'),
|
domain=[If(Eval('department'),
|
||||||
('parent', '=', Eval('department')))])
|
('parent', '=', Eval('department')))])
|
||||||
|
|
||||||
|
assigned_operator = fields.Many2One(
|
||||||
|
'res.user', "Assigned operator", readonly=True)
|
||||||
|
|
||||||
|
state = fields.Selection([
|
||||||
|
('unassigned', 'Unsassigned'),
|
||||||
|
('assigned', 'Assigned')], "State", readonly=True)
|
||||||
|
|
||||||
|
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.prospect_trace = self.prospect_trace
|
||||||
|
|
||||||
@fields.depends('city', 'department')
|
@fields.depends('city', 'department')
|
||||||
def on_change_city(self):
|
def on_change_city(self):
|
||||||
if self.city:
|
if self.city:
|
||||||
@@ -38,9 +74,11 @@ class ContactMethod(ModelSQL, ModelView):
|
|||||||
|
|
||||||
value = fields.Char('Value', required=True)
|
value = fields.Char('Value', required=True)
|
||||||
name = fields.Char('Name')
|
name = fields.Char('Name')
|
||||||
job = fields.Char('job')
|
job = fields.Char('Job')
|
||||||
|
|
||||||
prospect = fields.Many2One('sale.prospect', 'Prospect', required=True)
|
prospect = fields.Many2One('sale.prospect', 'Prospect', required=True)
|
||||||
|
prospect_trace = fields.Many2One(
|
||||||
|
'sale.prospect_trace', 'Prospect Trace', required=False)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def default_contact_type(cls):
|
def default_contact_type(cls):
|
||||||
@@ -55,3 +93,173 @@ 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', required=True,
|
||||||
|
states={
|
||||||
|
'readonly': ~Eval('business_unit', False)})
|
||||||
|
|
||||||
|
operator = fields.Many2One('res.user', 'Operator', required=True)
|
||||||
|
prospects = fields.One2Many(
|
||||||
|
'sale.prospect', None, 'Prospects', readonly=True)
|
||||||
|
|
||||||
|
business_unit = fields.Selection(
|
||||||
|
[('brigade', 'Brigade'),
|
||||||
|
('optics', 'Optics'),
|
||||||
|
('equipment', 'Equipment')],
|
||||||
|
'Business unit',
|
||||||
|
states={
|
||||||
|
'readonly': Eval('prospects_chunk', False)}
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def default_prospects_chunk(cls):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
@fields.depends('prospects_chunk', 'prospects', 'business_unit')
|
||||||
|
def on_change_prospects_chunk(self):
|
||||||
|
pool = Pool()
|
||||||
|
Prospect = pool.get('sale.prospect')
|
||||||
|
|
||||||
|
if self.prospects_chunk >= 1:
|
||||||
|
self.prospects = []
|
||||||
|
self.prospects = Prospect.search(
|
||||||
|
[('state', '=', 'unassigned'),
|
||||||
|
('business_unit', '=', self.business_unit)],
|
||||||
|
limit=self.prospects_chunk)
|
||||||
|
|
||||||
|
|
||||||
|
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()
|
||||||
|
ProspectTrace = pool.get('sale.prospect_trace')
|
||||||
|
|
||||||
|
for prospect in self.start.prospects:
|
||||||
|
prospect.assigned_operator = self.start.operator
|
||||||
|
prospect.state = 'assigned'
|
||||||
|
prospect.save()
|
||||||
|
|
||||||
|
prospect_trace = ProspectTrace(
|
||||||
|
prospect=prospect,
|
||||||
|
prospect_city=prospect.city,
|
||||||
|
prospect_business_unit=prospect.business_unit,
|
||||||
|
prospect_assigned_operator=prospect.assigned_operator,
|
||||||
|
prospect_contacts=prospect.contact_methods
|
||||||
|
)
|
||||||
|
prospect_trace.save()
|
||||||
|
|
||||||
|
prospect.prospect_trace = prospect_trace
|
||||||
|
prospect.save()
|
||||||
|
|
||||||
|
return 'end'
|
||||||
|
|
||||||
|
|
||||||
|
class ReassignProspectByOperatorStart(ModelView):
|
||||||
|
'Inicio de reasignación de prospecto por operario'
|
||||||
|
__name__ = 'sale.prospect.reassign_by_operator.start'
|
||||||
|
|
||||||
|
current_operator = fields.Many2One(
|
||||||
|
'res.user', "Current operator", required=True)
|
||||||
|
new_operator = fields.Many2One(
|
||||||
|
'res.user', "New operator", required=True)
|
||||||
|
prospects = fields.One2Many(
|
||||||
|
'sale.prospect', None, 'Prospects', readonly=True)
|
||||||
|
|
||||||
|
@fields.depends('current_operator', 'prospects')
|
||||||
|
def on_change_current_operator(self):
|
||||||
|
pool = Pool()
|
||||||
|
Prospect = pool.get('sale.prospect')
|
||||||
|
|
||||||
|
self.prospects = []
|
||||||
|
self.prospects = Prospect.search(
|
||||||
|
[('state', '=', 'assigned'),
|
||||||
|
('assigned_operator', '=', self.current_operator)])
|
||||||
|
|
||||||
|
|
||||||
|
class ReassignProspectByOperator(Wizard):
|
||||||
|
'Reasignar todos los prospectos de un operario, a otro operario'
|
||||||
|
__name__ = 'sale.prospect.reassign_by_operator'
|
||||||
|
|
||||||
|
start = StateView(
|
||||||
|
'sale.prospect.reassign_by_operator.start',
|
||||||
|
'sale_opportunity_management.reassign_by_operator_start_view_form',
|
||||||
|
[Button("Cancel", 'end', 'tryton-cancel'),
|
||||||
|
Button("Reassign", 'reassign_by_operator', 'tryton-ok', default=True)
|
||||||
|
])
|
||||||
|
|
||||||
|
reassign_by_operator = StateTransition()
|
||||||
|
|
||||||
|
def transition_reassign_by_operator(self):
|
||||||
|
pool = Pool()
|
||||||
|
ProspectTrace = pool.get('sale.prospect_trace')
|
||||||
|
|
||||||
|
for prospect in self.start.prospects:
|
||||||
|
prospect.assigned_operator = self.start.new_operator
|
||||||
|
|
||||||
|
if prospect.prospect_trace:
|
||||||
|
prospect_trace, = ProspectTrace.search(
|
||||||
|
[('prospect', '=', prospect)])
|
||||||
|
prospect_trace.prospect_assigned_operator =\
|
||||||
|
self.start.new_operator
|
||||||
|
prospect_trace.save()
|
||||||
|
|
||||||
|
prospect.save()
|
||||||
|
|
||||||
|
return 'end'
|
||||||
|
|
||||||
|
|
||||||
|
class ReassignProspectByProspectStart(ModelView):
|
||||||
|
'Inicio de reasignación de un prospecto en específico'
|
||||||
|
__name__ = 'sale.prospect.reassign_by_prospect.start'
|
||||||
|
|
||||||
|
prospect = fields.Many2One(
|
||||||
|
'sale.prospect', 'Prospect', required=True,
|
||||||
|
domain=[('assigned_operator', '!=', None)])
|
||||||
|
|
||||||
|
new_operator = fields.Many2One('res.user', "New operator", required=True)
|
||||||
|
|
||||||
|
|
||||||
|
class ReasignProspectByProspect(Wizard):
|
||||||
|
'Reasignar un prospecto en específico a un nuevo operario'
|
||||||
|
__name__ = 'sale.prospect.reassign_by_prospect'
|
||||||
|
|
||||||
|
start = StateView(
|
||||||
|
'sale.prospect.reassign_by_prospect.start',
|
||||||
|
'sale_opportunity_management.reassign_by_prospect_start_view_form',
|
||||||
|
[Button("Cancel", 'end', 'tryton-cancel'),
|
||||||
|
Button("Reassign", 'reassign_by_prospect', 'tryton-ok', default=True)
|
||||||
|
])
|
||||||
|
|
||||||
|
reassign_by_prospect = StateTransition()
|
||||||
|
|
||||||
|
def transition_reassign_by_prospect(self):
|
||||||
|
pool = Pool()
|
||||||
|
ProspectTrace = pool.get('sale.prospect_trace')
|
||||||
|
|
||||||
|
self.start.prospect.assigned_operator = self.start.new_operator
|
||||||
|
|
||||||
|
if self.start.prospect.prospect_trace:
|
||||||
|
prospect_trace, = ProspectTrace.search(
|
||||||
|
[('prospect', '=', self.start.prospect)])
|
||||||
|
prospect_trace.prospect_assigned_operator =\
|
||||||
|
self.start.new_operator
|
||||||
|
prospect_trace.save()
|
||||||
|
|
||||||
|
self.start.prospect.save()
|
||||||
|
return 'end'
|
||||||
|
|||||||
134
prospect.xml
@@ -3,11 +3,29 @@
|
|||||||
this repository contains the full copyright notices and license terms. -->
|
this repository contains the full copyright notices and license terms. -->
|
||||||
<tryton>
|
<tryton>
|
||||||
<data>
|
<data>
|
||||||
<record model="ir.action.act_window" id="act_prospect_tree">
|
<record model="res.group" id="group_prospect">
|
||||||
<field name="name">Prospects</field>
|
<field name="name">Prospects</field>
|
||||||
<field name="res_model">sale.prospect</field>
|
</record>
|
||||||
|
<record model="res.group" id="group_prospect_admin">
|
||||||
|
<field name="name">Prospect Administrator</field>
|
||||||
|
<field name="parent" ref="group_prospect"/>
|
||||||
|
</record>
|
||||||
|
<record model="res.user-res.group" id="user_admin_group_prospect">
|
||||||
|
<field name="user" ref="res.user_admin"/>
|
||||||
|
<field name="group" ref="group_prospect"/>
|
||||||
|
</record>
|
||||||
|
<record model="res.user-res.group" id="user_admin_group_prospect_admin">
|
||||||
|
<field name="user" ref="res.user_admin"/>
|
||||||
|
<field name="group" ref="group_prospect_admin"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<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">
|
<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 +36,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,19 +46,36 @@ 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>
|
||||||
|
<record model="ir.action.act_window.domain" id="act_prospect_domain_unassigned">
|
||||||
|
<field name="name">Unassigned</field>
|
||||||
|
<field name="sequence" eval="10"/>
|
||||||
|
<field name="domain" eval="[('state', '=', 'unassigned')]" pyson="1"/>
|
||||||
|
<field name="count" eval="True"/>
|
||||||
|
<field name="act_window" ref="act_prospect_tree"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.action.act_window.domain" id="act_prospect_domain_assigned">
|
||||||
|
<field name="name">Assigned</field>
|
||||||
|
<field name="sequence" eval="10"/>
|
||||||
|
<field name="domain" eval="[('state', '=', 'assigned')]" pyson="1"/>
|
||||||
|
<field name="count" eval="True"/>
|
||||||
|
<field name="act_window" ref="act_prospect_tree"/>
|
||||||
|
</record>
|
||||||
<menuitem
|
<menuitem
|
||||||
parent="menu_calls"
|
parent="menu_calls"
|
||||||
sequence="10"
|
sequence="10"
|
||||||
id="menu_prospects_tree"
|
id="menu_prospects_tree"
|
||||||
|
icon="tryton-party"
|
||||||
action="act_prospect_tree"/>
|
action="act_prospect_tree"/>
|
||||||
|
|
||||||
|
<record model="ir.ui.menu-res.group" id="menu_prospects_group_prospect">
|
||||||
|
<field name="menu" ref="menu_prospects_tree"/>
|
||||||
|
<field name="group" ref="group_prospect"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
<record model="ir.action.act_window" id="act_contact_method_tree">
|
<record model="ir.action.act_window" id="act_contact_method_tree">
|
||||||
<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>
|
||||||
@@ -52,7 +86,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"/>
|
||||||
@@ -63,5 +96,90 @@ 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>
|
||||||
</data>
|
|
||||||
|
<record model="ir.action.wizard" id="assign_operator_wizard">
|
||||||
|
<field name="name">Assign Operator</field>
|
||||||
|
<field name="wiz_name">sale.prospect.assign</field>
|
||||||
|
</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>
|
||||||
|
<record model="ir.action.keyword" id="assign_operator_wizard_keyword">
|
||||||
|
<field name="keyword">form_action</field>
|
||||||
|
<field name="model">sale.prospect, -1</field>
|
||||||
|
<field name="action" ref="assign_operator_wizard"/>
|
||||||
|
</record>
|
||||||
|
<menuitem
|
||||||
|
parent="menu_prospects_tree"
|
||||||
|
sequence="40"
|
||||||
|
id="menu_prospects_assigned_wizard"
|
||||||
|
action="assign_operator_wizard"/>
|
||||||
|
|
||||||
|
<record model="ir.ui.menu-res.group" id="menu_prospect_assigned_group_prospect">
|
||||||
|
<field name="menu" ref="menu_prospects_assigned_wizard"/>
|
||||||
|
<field name="group" ref="group_prospect_admin"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.action.wizard" id="reassign_by_operator_wizard">
|
||||||
|
<field name="name">Reassign by operator</field>
|
||||||
|
<field name="wiz_name">sale.prospect.reassign_by_operator</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.view" id="reassign_by_operator_start_view_form">
|
||||||
|
<field name="model">sale.prospect.reassign_by_operator.start</field>
|
||||||
|
<field name="type">form</field>
|
||||||
|
<field name="name">reassign_by_operator_form</field>
|
||||||
|
</record>
|
||||||
|
<menuitem
|
||||||
|
name="Reassign"
|
||||||
|
parent="menu_prospects_tree"
|
||||||
|
sequence="50"
|
||||||
|
id="menu_reassign"
|
||||||
|
icon='tryton-refresh'/>
|
||||||
|
|
||||||
|
<record model="ir.ui.menu-res.group" id="menu_prospect_reassigned_group_prospect">
|
||||||
|
<field name="menu" ref="menu_reassign"/>
|
||||||
|
<field name="group" ref="group_prospect_admin"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<menuitem
|
||||||
|
parent="menu_reassign"
|
||||||
|
sequence="10"
|
||||||
|
id="menu_reassign_by_operator_wizard"
|
||||||
|
action="reassign_by_operator_wizard"/>
|
||||||
|
|
||||||
|
<record model="ir.action.wizard" id="reassign_by_prospect_wizard">
|
||||||
|
<field name="name">Reassign by prospect</field>
|
||||||
|
<field name="wiz_name">sale.prospect.reassign_by_prospect</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.view" id="reassign_by_prospect_start_view_form">
|
||||||
|
<field name="model">sale.prospect.reassign_by_prospect.start</field>
|
||||||
|
<field name="type">form</field>
|
||||||
|
<field name="name">reassign_by_prospect_form</field>
|
||||||
|
</record>
|
||||||
|
<menuitem
|
||||||
|
parent="menu_reassign"
|
||||||
|
sequence="20"
|
||||||
|
id="menu_reassign_by_prospect_wizard"
|
||||||
|
action="reassign_by_prospect_wizard"/>
|
||||||
|
|
||||||
|
<record model="ir.model.access" id="access_sale">
|
||||||
|
<field name="model" search="[('model', '=', 'sale.prospect')]"/>
|
||||||
|
<field name="perm_read" eval="False"/>
|
||||||
|
<field name="perm_write" eval="False"/>
|
||||||
|
<field name="perm_create" eval="False"/>
|
||||||
|
<field name="perm_delete" eval="False"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.model.access" id="access_sale_prospect">
|
||||||
|
<field name="model" search="[('model', '=', 'sale.prospect')]"/>
|
||||||
|
<field name="group" ref="group_prospect"/>
|
||||||
|
<field name="perm_read" eval="True"/>
|
||||||
|
<field name="perm_write" eval="True"/>
|
||||||
|
<field name="perm_create" eval="True"/>
|
||||||
|
<field name="perm_delete" eval="True"/>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
|
||||||
</tryton>
|
</tryton>
|
||||||
@@ -1,92 +1,278 @@
|
|||||||
# 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.model import ModelSQL, ModelView, fields, DeactivableMixin
|
from trytond.wizard import Wizard, StateView, Button, StateTransition
|
||||||
|
from trytond.model import ModelSQL, ModelView, fields
|
||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
|
from trytond.pyson import Eval
|
||||||
from .selections.call_types import CallTypes
|
from .selections.call_types import CallTypes
|
||||||
from .selections.interest import Interest
|
from .selections.interest import Interest
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
class ProspectTrace(DeactivableMixin, ModelSQL, ModelView):
|
class ProspectTrace(ModelSQL, ModelView):
|
||||||
'Seguimiento de un prospecto'
|
'Seguimiento de un prospecto'
|
||||||
__name__ = 'sale.prospect_trace'
|
__name__ = 'sale.prospect_trace'
|
||||||
|
|
||||||
prospect = fields.Many2One('sale.prospect', 'Prospect', required=True)
|
_states = {'readonly': True}
|
||||||
prospect_contact = fields.Many2One(
|
|
||||||
'prospect.contact_method', 'Contact method')
|
|
||||||
prospect_city = fields.Many2One('sale.city', 'City')
|
|
||||||
|
|
||||||
calls = fields.One2Many('sale.call', 'prospect_trace', 'Calls')
|
prospect = fields.Many2One(
|
||||||
pending_calls = fields.One2Many(
|
'sale.prospect', 'Prospect', required=True, states=_states)
|
||||||
'sale.pending_call', 'prospect_trace', 'Pending calls')
|
prospect_business_unit = fields.Selection(
|
||||||
|
[('brigade', 'Brigade'),
|
||||||
|
('optics', 'Optics'),
|
||||||
|
('equipment', 'Equipment')],
|
||||||
|
'Business unit', states=_states
|
||||||
|
)
|
||||||
|
prospect_contacts = fields.One2Many(
|
||||||
|
'prospect.contact_method', 'prospect_trace',
|
||||||
|
'Prospect contacts', required=True)
|
||||||
|
prospect_city = fields.Many2One('sale.city', 'City',
|
||||||
|
states=_states)
|
||||||
|
|
||||||
|
prospect_assigned_operator = fields.Many2One(
|
||||||
|
'res.user', "Assigned operator", states=_states)
|
||||||
|
|
||||||
|
calls = fields.One2Many(
|
||||||
|
'sale.call', 'prospect_trace', 'Calls', states=_states)
|
||||||
|
pending_call = fields.Many2One(
|
||||||
|
'sale.pending_call', 'Pending call', states=_states)
|
||||||
|
|
||||||
current_interest = fields.Selection(
|
current_interest = fields.Selection(
|
||||||
Interest.get_interest_levels(), 'Current interest')
|
Interest.get_interest_levels(), 'Current interest',
|
||||||
|
states=_states)
|
||||||
|
|
||||||
state = fields.Selection([
|
state = fields.Selection([
|
||||||
('unassigned', 'Unassigned'),
|
('unassigned', 'Unassigned'),
|
||||||
('open', 'Open'),
|
('open', 'Open'),
|
||||||
('with_pending_calls', 'With pending calls'),
|
('with_pending_calls', 'With pending calls'),
|
||||||
('closed', 'Closed')
|
('closed', 'Closed')
|
||||||
], 'State')
|
], '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__()
|
||||||
|
cls._buttons.update({
|
||||||
|
'wizard_schedule': {
|
||||||
|
'invisible': Eval('state') == 'with_pending_calls',
|
||||||
|
},
|
||||||
|
'wizard_make_call': {},
|
||||||
|
'close_trace': {
|
||||||
|
'invisible': Eval('state') == 'closed',
|
||||||
|
'depends': ['state']
|
||||||
|
},
|
||||||
|
'reopen_trace': {
|
||||||
|
'invisible': (Eval('state') == 'open')
|
||||||
|
| (Eval('state') == 'with_pending_calls'),
|
||||||
|
|
||||||
|
'depends': ['state']
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def default_state(cls):
|
def default_state(cls):
|
||||||
return 'open'
|
return 'open'
|
||||||
|
|
||||||
@fields.depends('calls', 'pending_calls', 'current_interest')
|
@classmethod
|
||||||
def on_change_calls(self):
|
@ModelView.button_action(
|
||||||
if not self.calls:
|
'sale_opportunity_management.schedule_call_wizard')
|
||||||
return
|
def wizard_schedule(cls, prospect_traces):
|
||||||
|
pass
|
||||||
|
|
||||||
last_call = self.calls[-1]
|
@classmethod
|
||||||
self.current_interest = last_call.interest
|
@ModelView.button_action(
|
||||||
|
'sale_opportunity_management.make_call_wizard')
|
||||||
|
def wizard_make_call(cls, prospect_traces):
|
||||||
|
pass
|
||||||
|
|
||||||
already_exist_a_call = len(self.calls) > 1
|
@classmethod
|
||||||
if already_exist_a_call:
|
@ModelView.button
|
||||||
followup_call_type = CallTypes.get_call_types()[1][0]
|
def close_trace(cls, prospect_traces):
|
||||||
last_call.call_type = followup_call_type
|
for prospect_trace in prospect_traces:
|
||||||
else:
|
prospect_trace.state = 'closed'
|
||||||
first_call_type = CallTypes.get_call_types()[0][0]
|
prospect_trace.save()
|
||||||
last_call.call_type = first_call_type
|
|
||||||
|
|
||||||
there_is_a_pending_call = len(self.pending_calls) >= 1
|
@classmethod
|
||||||
if there_is_a_pending_call:
|
@ModelView.button
|
||||||
self.pending_calls = None
|
def reopen_trace(cls, prospect_traces):
|
||||||
self.state = 'open'
|
for prospect_trace in prospect_traces:
|
||||||
|
prospect_trace.state = 'open'
|
||||||
@fields.depends('pending_calls', 'state')
|
prospect_trace.save()
|
||||||
def on_change_pending_calls(self):
|
|
||||||
if len(self.pending_calls) >= 1:
|
|
||||||
self.state = 'with_pending_calls'
|
|
||||||
|
|
||||||
@fields.depends('prospect')
|
|
||||||
def on_change_prospect(self):
|
|
||||||
if not self.prospect:
|
|
||||||
return
|
|
||||||
|
|
||||||
self.prospect_city = self.prospect.city
|
|
||||||
mobile_contact = self._get_prospect_mobile_contact()
|
|
||||||
|
|
||||||
if mobile_contact:
|
|
||||||
self.prospect_contact = mobile_contact
|
|
||||||
|
|
||||||
def get_rec_name(self, name):
|
def get_rec_name(self, name):
|
||||||
if self.prospect:
|
if self.prospect:
|
||||||
return '[' + str(self.id) + '] ' + self.prospect.name
|
return '[' + str(self.id) + '] ' + self.prospect.name
|
||||||
|
|
||||||
def _get_current_interest(self, name):
|
|
||||||
if self.calls:
|
|
||||||
return self.calls[-1].interest
|
|
||||||
|
|
||||||
def _get_prospect_mobile_contact(self):
|
class ScheduleCallStart(ModelView):
|
||||||
|
'Inicio agendar llamada a seguimiento de prospecto'
|
||||||
|
__name__ = 'sale.prospect_trace.schedule.start'
|
||||||
|
|
||||||
|
currency_date = fields.DateTime('Currency Date', readonly=True)
|
||||||
|
date_time = fields.DateTime('Date time', domain=[
|
||||||
|
('date_time', '>=', Eval('currency_date'))])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def default_currency_date(cls):
|
||||||
|
date = datetime.now()
|
||||||
|
|
||||||
|
return date
|
||||||
|
|
||||||
|
|
||||||
|
class ScheduleCall(Wizard):
|
||||||
|
'Agendar llamada a seguimiento de prospecto'
|
||||||
|
__name__ = 'sale.prospect_trace.schedule'
|
||||||
|
|
||||||
|
start = StateView(
|
||||||
|
'sale.prospect_trace.schedule.start',
|
||||||
|
'sale_opportunity_management.schedule_start_view_form', [
|
||||||
|
Button("Cancel", 'end', 'tryton-cancel'),
|
||||||
|
Button("Schedule", 'schedule', 'tryton-ok', default=True)])
|
||||||
|
|
||||||
|
schedule = StateTransition()
|
||||||
|
|
||||||
|
def transition_schedule(self):
|
||||||
|
MakeCall.create_schedule_call(self.start.date_time, self.record)
|
||||||
|
return 'end'
|
||||||
|
|
||||||
|
|
||||||
|
class MakeCallStart(ModelView):
|
||||||
|
'Inicio de creación de llamada a seguimiento de prospecto'
|
||||||
|
__name__ = 'sale.prospect_trace.make_call.start'
|
||||||
|
|
||||||
|
description = fields.Text('Description')
|
||||||
|
interest = fields.Selection(
|
||||||
|
Interest.get_interest_levels(), 'Interest', required=True)
|
||||||
|
schedule_call = fields.Selection(
|
||||||
|
[('yes', 'Yes'),
|
||||||
|
('no', 'No')], 'Schedule call?', required=True)
|
||||||
|
|
||||||
|
schedule_task = fields.Selection(
|
||||||
|
[('yes', 'Yes'),
|
||||||
|
('no', 'No')], 'Schedule task?', required=True)
|
||||||
|
|
||||||
|
|
||||||
|
class MakeCallAsk(ModelView):
|
||||||
|
'Posible agendación de llamada luego de hacer llamada actual'
|
||||||
|
__name__ = 'sale.prospect_trace.make_call.ask'
|
||||||
|
|
||||||
|
currency_date = fields.DateTime('Currency Date', readonly=True)
|
||||||
|
datetime = fields.DateTime('Date time', domain=[
|
||||||
|
('datetime', '>=', Eval('currency_date'))])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def default_currency_date(cls):
|
||||||
|
date = datetime.now()
|
||||||
|
|
||||||
|
return date
|
||||||
|
|
||||||
|
|
||||||
|
class MakeCallAskTask(ModelView):
|
||||||
|
'Posible agendación de tarea luego de hacer llamada actual'
|
||||||
|
__name__ = 'sale.prospect_trace.make_call.ask_task'
|
||||||
|
|
||||||
|
task_description = fields.Text('Task description')
|
||||||
|
|
||||||
|
|
||||||
|
class MakeCall(Wizard):
|
||||||
|
'Crear llamada a un seguimiento de prospecto'
|
||||||
|
__name__ = 'sale.prospect_trace.make_call'
|
||||||
|
|
||||||
|
start = StateView(
|
||||||
|
'sale.prospect_trace.make_call.start',
|
||||||
|
'sale_opportunity_management.make_call_start_view_form', [
|
||||||
|
Button("Cancel", 'end', 'tryton-cancel'),
|
||||||
|
Button("Make call", 'make_call', 'tryton-ok', default=True)])
|
||||||
|
make_call = StateTransition()
|
||||||
|
|
||||||
|
ask = StateView(
|
||||||
|
'sale.prospect_trace.make_call.ask',
|
||||||
|
'sale_opportunity_management.make_call_ask_view_form', [
|
||||||
|
Button("Cancel", 'end', 'tryton-cancel'),
|
||||||
|
Button(
|
||||||
|
"Schedule call", 'schedule_call', 'tryton-ok', default=True)])
|
||||||
|
schedule_call = StateTransition()
|
||||||
|
|
||||||
|
ask_task = StateView(
|
||||||
|
'sale.prospect_trace.make_call.ask_task',
|
||||||
|
'sale_opportunity_management.make_call_ask_task_view_form', [
|
||||||
|
Button("Cancel", 'end', 'tryton-cancel'),
|
||||||
|
Button("Schedule task", 'schedule_task', 'tryton-ok', default=True)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
schedule_task = StateTransition()
|
||||||
|
|
||||||
|
def transition_make_call(self):
|
||||||
|
prospect_trace = self.record
|
||||||
|
|
||||||
pool = Pool()
|
pool = Pool()
|
||||||
ContactMethod = pool.get('prospect.contact_method')
|
Call = pool.get('sale.call')
|
||||||
|
call = Call()
|
||||||
|
call.description = self.start.description
|
||||||
|
call.interest = self.start.interest
|
||||||
|
call.prospect_trace = self.record
|
||||||
|
call.call_business_unit = self.record.prospect_business_unit
|
||||||
|
call.operator_who_called = self.record.prospect_assigned_operator
|
||||||
|
|
||||||
contact_mobile = ContactMethod.search(
|
if call.interest == '0':
|
||||||
[('prospect', '=', self.prospect.id),
|
call.call_result = 'missed_call'
|
||||||
('contact_type', '=', 'mobile')],
|
else:
|
||||||
limit=1)
|
call.call_result = 'answered_call'
|
||||||
|
already_exist_a_call = len(prospect_trace.calls) >= 1
|
||||||
|
if already_exist_a_call:
|
||||||
|
followup_call_type = CallTypes.get_call_types()[1][0]
|
||||||
|
call.call_type = followup_call_type
|
||||||
|
else:
|
||||||
|
first_call_type = CallTypes.get_call_types()[0][0]
|
||||||
|
call.call_type = first_call_type
|
||||||
|
call.save()
|
||||||
|
|
||||||
if contact_mobile:
|
prospect_trace.current_interest = call.interest
|
||||||
return contact_mobile[0]
|
if prospect_trace.pending_call:
|
||||||
|
prospect_trace.pending_call = None
|
||||||
|
prospect_trace.state = 'open'
|
||||||
|
prospect_trace.calls += (call,)
|
||||||
|
prospect_trace.save()
|
||||||
|
|
||||||
|
if self.start.schedule_call == 'yes':
|
||||||
|
return 'ask'
|
||||||
|
if self.start.schedule_task == 'yes':
|
||||||
|
return 'ask_task'
|
||||||
|
return 'end'
|
||||||
|
|
||||||
|
def transition_schedule_task(self):
|
||||||
|
self.create_schedule_task(self.ask_task.task_description, self.record)
|
||||||
|
return 'end'
|
||||||
|
|
||||||
|
def transition_schedule_call(self):
|
||||||
|
self.create_schedule_call(self.ask.datetime, self.record)
|
||||||
|
|
||||||
|
if (self.start.schedule_call and self.start.schedule_task) == 'yes':
|
||||||
|
return 'ask_task'
|
||||||
|
return 'end'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_schedule_task(cls, description, prospect_trace):
|
||||||
|
pool = Pool()
|
||||||
|
Task = pool.get('sale.pending_task')
|
||||||
|
task = Task()
|
||||||
|
task.description = description
|
||||||
|
task.prospect_trace = prospect_trace
|
||||||
|
task.save()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_schedule_call(cls, datetime, prospect_trace):
|
||||||
|
pool = Pool()
|
||||||
|
PendingCall = pool.get('sale.pending_call')
|
||||||
|
pending_call = PendingCall()
|
||||||
|
pending_call.date = datetime
|
||||||
|
pending_call.save()
|
||||||
|
|
||||||
|
prospect_trace.pending_call = pending_call
|
||||||
|
prospect_trace.state = 'with_pending_calls'
|
||||||
|
prospect_trace.save()
|
||||||
|
|||||||
@@ -3,6 +3,22 @@
|
|||||||
this repository contains the full copyright notices and license terms. -->
|
this repository contains the full copyright notices and license terms. -->
|
||||||
<tryton>
|
<tryton>
|
||||||
<data>
|
<data>
|
||||||
|
<record model="res.group" id="group_prospect_trace">
|
||||||
|
<field name="name">Prospect Traces</field>
|
||||||
|
</record>
|
||||||
|
<record model="res.group" id="group_prospect_trace_admin">
|
||||||
|
<field name="name">Traces Administrator</field>
|
||||||
|
<field name="parent" ref="group_prospect_trace"/>
|
||||||
|
</record>
|
||||||
|
<record model="res.user-res.group" id="user_admin_group_prospect_trace">
|
||||||
|
<field name="user" ref="res.user_admin"/>
|
||||||
|
<field name="group" ref="group_prospect_trace"/>
|
||||||
|
</record>
|
||||||
|
<record model="res.user-res.group" id="user_admin_group_prospect_traces_admin">
|
||||||
|
<field name="user" ref="res.user_admin"/>
|
||||||
|
<field name="group" ref="group_prospect_trace_admin"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="prospect_trace_view_tree">
|
<record model="ir.ui.view" id="prospect_trace_view_tree">
|
||||||
<field name="model">sale.prospect_trace</field>
|
<field name="model">sale.prospect_trace</field>
|
||||||
<field name="type">tree</field>
|
<field name="type">tree</field>
|
||||||
@@ -15,6 +31,9 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
</record>
|
</record>
|
||||||
<record model="ir.action.act_window" id="act_prospect_trace_tree">
|
<record model="ir.action.act_window" id="act_prospect_trace_tree">
|
||||||
<field name="name">Prospect Traces</field>
|
<field name="name">Prospect Traces</field>
|
||||||
|
<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>
|
<field name="res_model">sale.prospect_trace</field>
|
||||||
</record>
|
</record>
|
||||||
<record model="ir.action.act_window.view" id="act_prospect_trace_tree_view1">
|
<record model="ir.action.act_window.view" id="act_prospect_trace_tree_view1">
|
||||||
@@ -36,11 +55,18 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
</record>
|
</record>
|
||||||
<record model="ir.action.act_window.domain" id="act_prospect_trace_domain_with_pending_calls">
|
<record model="ir.action.act_window.domain" id="act_prospect_trace_domain_with_pending_calls">
|
||||||
<field name="name">With pending calls</field>
|
<field name="name">With pending calls</field>
|
||||||
<field name="sequence" eval="10"/>
|
<field name="sequence" eval="20"/>
|
||||||
<field name="domain" eval="[('state', '=', 'with_pending_calls')]" pyson="1"/>
|
<field name="domain" eval="[('state', '=', 'with_pending_calls')]" pyson="1"/>
|
||||||
<field name="count" eval="True"/>
|
<field name="count" eval="True"/>
|
||||||
<field name="act_window" ref="act_prospect_trace_tree"/>
|
<field name="act_window" ref="act_prospect_trace_tree"/>
|
||||||
</record>
|
</record>
|
||||||
|
<record model="ir.action.act_window.domain" id="act_prospect_trace_domain_closed">
|
||||||
|
<field name="name">Closed</field>
|
||||||
|
<field name="sequence" eval="30"/>
|
||||||
|
<field name="domain" eval="[('state', '=', 'closed')]" pyson="1"/>
|
||||||
|
<field name="count" eval="True"/>
|
||||||
|
<field name="act_window" ref="act_prospect_trace_tree"/>
|
||||||
|
</record>
|
||||||
<record model="ir.action.act_window.domain" id="act_prospect_trace_domain_all">
|
<record model="ir.action.act_window.domain" id="act_prospect_trace_domain_all">
|
||||||
<field name="name">All</field>
|
<field name="name">All</field>
|
||||||
<field name="sequence" eval="9999"/>
|
<field name="sequence" eval="9999"/>
|
||||||
@@ -48,11 +74,85 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<field name="count" eval="True"/>
|
<field name="count" eval="True"/>
|
||||||
<field name="act_window" ref="act_prospect_trace_tree"/>
|
<field name="act_window" ref="act_prospect_trace_tree"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<menuitem
|
<menuitem
|
||||||
parent="menu_calls"
|
parent="menu_calls"
|
||||||
sequence="20"
|
sequence="20"
|
||||||
id="menu_prospect_trace_tree"
|
id="menu_prospect_trace_tree"
|
||||||
|
icon="tryton-target"
|
||||||
action="act_prospect_trace_tree"/>
|
action="act_prospect_trace_tree"/>
|
||||||
|
|
||||||
|
<record model="ir.ui.menu-res.group" id="menu_prospect_trace_group_prospect_trace">
|
||||||
|
<field name="menu" ref="menu_prospect_trace_tree"/>
|
||||||
|
<field name="group" ref="group_prospect_trace"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.model.access" id="access_prospect_trace">
|
||||||
|
<field name="model" search="[('model', '=', 'sale.prospect_trace')]"/>
|
||||||
|
<field name="perm_read" eval="False"/>
|
||||||
|
<field name="perm_write" eval="False"/>
|
||||||
|
<field name="perm_create" eval="False"/>
|
||||||
|
<field name="perm_delete" eval="False"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.model.access" id="access_prospect_trace_trace">
|
||||||
|
<field name="model" search="[('model', '=', 'sale.prospect_trace')]"/>
|
||||||
|
<field name="group" ref="group_prospect_trace"/>
|
||||||
|
<field name="perm_read" eval="True"/>
|
||||||
|
<field name="perm_write" eval="True"/>
|
||||||
|
<field name="perm_create" eval="True"/>
|
||||||
|
<field name="perm_delete" eval="True"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.action.wizard" id="schedule_call_wizard">
|
||||||
|
<field name="name">Schedule call</field>
|
||||||
|
<field name="wiz_name">sale.prospect_trace.schedule</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.view" id="schedule_start_view_form">
|
||||||
|
<field name="model">sale.prospect_trace.schedule.start</field>
|
||||||
|
<field name="type">form</field>
|
||||||
|
<field name="name">schedule_start_form</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.model.button" id="schedule_call_wizard_button">
|
||||||
|
<field name="name">wizard_schedule</field>
|
||||||
|
<field name="string">Schedule call</field>
|
||||||
|
<field name="model" search="[('model', '=', 'sale.prospect_trace')]"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.action.wizard" id="make_call_wizard">
|
||||||
|
<field name="name">Make call</field>
|
||||||
|
<field name="wiz_name">sale.prospect_trace.make_call</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.view" id="make_call_start_view_form">
|
||||||
|
<field name="model">sale.prospect_trace.make_call.start</field>
|
||||||
|
<field name="type">form</field>
|
||||||
|
<field name="name">make_call_start_form</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.view" id="make_call_ask_view_form">
|
||||||
|
<field name="model">sale.prospect_trace.make_call.ask</field>
|
||||||
|
<field name="type">form</field>
|
||||||
|
<field name="name">make_call_ask_form</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.view" id="make_call_ask_task_view_form">
|
||||||
|
<field name="model">sale.prospect_trace.make_call.ask_task</field>
|
||||||
|
<field name="type">form</field>
|
||||||
|
<field name="name">make_call_ask_task_form</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.model.button" id="make_call_wizard_button">
|
||||||
|
<field name="name">wizard_make_call</field>
|
||||||
|
<field name="string">Make call</field>
|
||||||
|
<field name="model" search="[('model', '=', 'sale.prospect_trace')]"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.model.button" id="close_trace_button">
|
||||||
|
<field name="name">close_trace</field>
|
||||||
|
<field name="string">Close trace</field>
|
||||||
|
<field name="model" search="[('model', '=', 'sale.prospect_trace')]"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.model.button" id="reopen_trace_button">
|
||||||
|
<field name="name">reopen_trace</field>
|
||||||
|
<field name="string">Reopen trace</field>
|
||||||
|
<field name="model" search="[('model', '=', 'sale.prospect_trace')]"/>
|
||||||
|
</record>
|
||||||
</data>
|
</data>
|
||||||
</tryton>
|
</tryton>
|
||||||
@@ -6,7 +6,8 @@ class Interest():
|
|||||||
('0', '0 - Not answered'),
|
('0', '0 - Not answered'),
|
||||||
('1', '1 - Complete disinterest'),
|
('1', '1 - Complete disinterest'),
|
||||||
('2', '2 - Middle interest'),
|
('2', '2 - Middle interest'),
|
||||||
('3', '3 - High interest')
|
('3', '3 - High interest'),
|
||||||
|
('4', '4 - Closed sale')
|
||||||
]
|
]
|
||||||
|
|
||||||
return interest_levels
|
return interest_levels
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Imports::
|
|||||||
|
|
||||||
>>> from proteus import Model, Wizard
|
>>> from proteus import Model, Wizard
|
||||||
>>> from trytond.tests.tools import activate_modules
|
>>> from trytond.tests.tools import activate_modules
|
||||||
>>> from datetime import date, timedelta
|
>>> from datetime import date, timedelta, datetime
|
||||||
>>> import xml.etree.ElementTree as ET
|
>>> import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
Activate modules::
|
Activate modules::
|
||||||
@@ -42,57 +42,97 @@ 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'
|
|
||||||
>>> contact_method = prospect.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 = prospect.contact_methods.new(contact_type='mail', value='peralto@guchitos.org', name='Peralto', job='Administrador')
|
|
||||||
|
|
||||||
.. >>> Department = Model.get('sale.department')
|
|
||||||
.. >>> cundinamarca, = Department.find([('code', '=', 'CO-25')])
|
|
||||||
.. >>> prospect.department = cundinamarca
|
|
||||||
|
|
||||||
|
>>> prospect1.name = 'guchito S.A.S'
|
||||||
|
>>> contact_method = prospect1.contact_methods.new(value='31223425234', name='Roberto', job='Gerente R.H')
|
||||||
|
>>> contact_method = prospect1.contact_methods.new(contact_type='mobile', value='12345678910', name='Pancracia', job='Asistente administrativo')
|
||||||
|
>>> 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.business_unit = 'brigade'
|
||||||
|
>>> 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'
|
||||||
|
>>> prospect1.business_unit
|
||||||
|
'brigade'
|
||||||
|
>>> prospect1.state
|
||||||
|
'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.business_unit = 'brigade'
|
||||||
|
>>> prospect2.save()
|
||||||
|
|
||||||
|
Crear tercer prospecto::
|
||||||
|
>>> prospect3 = Prospect()
|
||||||
|
|
||||||
|
>>> prospect3.name = 'Vision S.A.S'
|
||||||
|
>>> contact_method = prospect3.contact_methods.new(value='3122324287', name='Alfredo', job='Administrador')
|
||||||
|
>>> 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
|
Asignación de prospectos a operarios
|
||||||
------------------------------------
|
------------------------------------
|
||||||
**Como administrador, quiero poder asignar diferentes seguimientos de prospectos a diferentes operarios, para dividir el trabajo de una manera efectiva y que cada operario tenga sus propias llamadas y que no se mezcle con las de los demás**
|
**Como administrador, quiero poder asignar diferentes seguimientos de prospectos a diferentes operarios, para dividir el trabajo de una manera efectiva y que cada operario tenga sus propias llamadas y que no se mezcle con las de los demás**
|
||||||
|
|
||||||
TODO
|
Asignar prospectos a un operario::
|
||||||
|
>>> User = Model.get('res.user')
|
||||||
|
>>> user, = User.find([('name', '=', 'Administrator')])
|
||||||
|
|
||||||
|
>>> assign = Wizard('sale.prospect.assign', [prospect1, prospect2, prospect3])
|
||||||
|
>>> assign.form.business_unit = 'brigade'
|
||||||
|
>>> assign.form.prospects_chunk = 3
|
||||||
|
>>> assign.form.operator = user
|
||||||
|
>>> assign.form.prospects
|
||||||
|
[proteus.Model.get('sale.prospect')(1), proteus.Model.get('sale.prospect')(2)]
|
||||||
|
>>> assign.execute('assign')
|
||||||
|
|
||||||
|
>>> prospect1.assigned_operator.name
|
||||||
|
'Administrator'
|
||||||
|
>>> prospect1.state
|
||||||
|
'assigned'
|
||||||
|
>>> prospect2.assigned_operator.name
|
||||||
|
'Administrator'
|
||||||
|
>>> prospect2.state
|
||||||
|
'assigned'
|
||||||
|
|
||||||
|
|
||||||
-----------------------
|
-----------------------
|
||||||
Seguimiento de llamadas
|
Seguimiento de llamadas
|
||||||
-----------------------
|
-----------------------
|
||||||
**Como operador quiero poder crear un seguimiento de prospecto para luego hacer una llamada**
|
**Como operador quiero poder crear un seguimiento de prospecto para luego hacer una llamada**
|
||||||
|
|
||||||
**Como operador quiero registrar una llamada para luego generar reportes**
|
**Como operador quiero registrar una llamada para luego generar reportes**
|
||||||
|
|
||||||
**Como operador quiero programar una llamada para luego obtener un reporte de trabajo pendiente**
|
**Como operador quiero programar una llamada para luego obtener un reporte de trabajo pendiente**
|
||||||
|
|
||||||
["Crear Campo para registro de la fecha de la llamada"]
|
["Crear Campo para registro de la fecha de la llamada"]
|
||||||
@@ -141,38 +181,64 @@ Seguimiento de prospecto 2
|
|||||||
* Seguimiento de prospecto al que pertence
|
* Seguimiento de prospecto al que pertence
|
||||||
|
|
||||||
|
|
||||||
Crear seguimiento de prospecto::
|
Verificar creación de seguimiento de prospecto::
|
||||||
>>> ProspectTrace = Model.get('sale.prospect_trace')
|
>>> ProspectTrace = Model.get('sale.prospect_trace')
|
||||||
>>> prospect_trace = ProspectTrace()
|
>>> prospect_trace, = ProspectTrace.find([('prospect', '=', prospect1)])
|
||||||
|
|
||||||
>>> prospect_trace.prospect = prospect
|
|
||||||
>>> prospect_trace.save()
|
|
||||||
|
|
||||||
>>> prospect_trace.prospect.name
|
>>> prospect_trace.prospect.name
|
||||||
'guchito S.A.S'
|
'guchito S.A.S'
|
||||||
|
>>> prospect_trace.prospect_business_unit
|
||||||
|
'brigade'
|
||||||
>>> prospect_trace.prospect_city.name
|
>>> prospect_trace.prospect_city.name
|
||||||
'Medellín'
|
'Medellín'
|
||||||
>>> prospect_trace.prospect_contact.value
|
>>> prospect_trace.prospect_assigned_operator.name
|
||||||
'31223425234'
|
'Administrator'
|
||||||
>>> prospect_trace.prospect_contact.contact_type
|
>>> prospect_trace.prospect_contacts
|
||||||
'mobile'
|
[proteus.Model.get('prospect.contact_method')(1), proteus.Model.get('prospect.contact_method')(2), proteus.Model.get('prospect.contact_method')(3)]
|
||||||
>>> prospect_trace.prospect_contact.job
|
|
||||||
'Gerente R.H'
|
|
||||||
|
|
||||||
Crear llamadas a un seguimiento de prospecto desde el seguimiento de prospecto::
|
Agregar un método de contacto desde el seguimiento de prospecto::
|
||||||
>>> call1 = prospect_trace.calls.new(description='First call', interest='0')
|
>>> contact_method_ = prospect_trace.prospect_contacts.new(value='31231231212', name='Carlos', job='Supervisor')
|
||||||
>>> call2 = prospect_trace.calls.new(description='Second call', interest='1')
|
>>> contact_method_.prospect
|
||||||
>>> call3 = prospect_trace.calls.new(description='Third call', interest='3')
|
proteus.Model.get('sale.prospect')(1)
|
||||||
>>> prospect_trace.save()
|
|
||||||
|
|
||||||
Verificar estado final del seguimiento del prospecto y sus llamadas
|
|
||||||
|
Crear llamadas a un seguimiento de prospecto::
|
||||||
|
>>> make_call = Wizard('sale.prospect_trace.make_call', [prospect_trace])
|
||||||
|
>>> make_call.form.description = 'First call to the prospect'
|
||||||
|
>>> make_call.form.interest = '0'
|
||||||
|
>>> make_call.form.schedule_call = 'no'
|
||||||
|
>>> make_call.execute('make_call')
|
||||||
|
>>> make_call.state
|
||||||
|
'end'
|
||||||
|
|
||||||
|
>>> make_call = Wizard('sale.prospect_trace.make_call', [prospect_trace])
|
||||||
|
>>> make_call.form.description = 'Second call to the prospect'
|
||||||
|
>>> make_call.form.interest = '1'
|
||||||
|
>>> make_call.form.schedule_call = 'no'
|
||||||
|
>>> make_call.execute('make_call')
|
||||||
|
>>> make_call.state
|
||||||
|
'end'
|
||||||
|
|
||||||
|
>>> make_call = Wizard('sale.prospect_trace.make_call', [prospect_trace])
|
||||||
|
>>> make_call.form.description = 'Third call to the prospect'
|
||||||
|
>>> make_call.form.interest = '3'
|
||||||
|
>>> make_call.form.schedule_call = 'yes'
|
||||||
|
>>> make_call.execute('make_call')
|
||||||
|
>>> make_call.form.datetime = datetime(2023, 8, 14, 15, 30, 30)
|
||||||
|
>>> make_call.execute('schedule_call')
|
||||||
|
|
||||||
|
|
||||||
|
Verificar estado final del seguimiento del prospecto y sus llamadas::
|
||||||
>>> prospect_trace.calls[0].call_result
|
>>> prospect_trace.calls[0].call_result
|
||||||
'missed_call'
|
'missed_call'
|
||||||
>>> prospect_trace.calls[0].call_type
|
>>> prospect_trace.calls[0].call_type
|
||||||
'first_call'
|
'first_call'
|
||||||
>>> prospect_trace.calls[0].date == date.today()
|
>>> prospect_trace.calls[0].date == date.today()
|
||||||
True
|
True
|
||||||
|
>>> prospect_trace.calls[0].call_business_unit
|
||||||
|
'brigade'
|
||||||
|
>>> prospect_trace.calls[0].operator_who_called.name
|
||||||
|
'Administrator'
|
||||||
>>> prospect_trace.calls[1].call_result
|
>>> prospect_trace.calls[1].call_result
|
||||||
'answered_call'
|
'answered_call'
|
||||||
>>> prospect_trace.calls[1].call_type
|
>>> prospect_trace.calls[1].call_type
|
||||||
@@ -180,46 +246,143 @@ Verificar estado final del seguimiento del prospecto y sus llamadas
|
|||||||
|
|
||||||
>>> prospect_trace.calls
|
>>> prospect_trace.calls
|
||||||
[proteus.Model.get('sale.call')(1), proteus.Model.get('sale.call')(2), proteus.Model.get('sale.call')(3)]
|
[proteus.Model.get('sale.call')(1), proteus.Model.get('sale.call')(2), proteus.Model.get('sale.call')(3)]
|
||||||
|
>>> prospect_trace.pending_call.date
|
||||||
|
datetime.datetime(2023, 8, 14, 15, 30, 30)
|
||||||
>>> prospect_trace.current_interest
|
>>> prospect_trace.current_interest
|
||||||
'3'
|
'3'
|
||||||
>>> prospect_trace.state
|
>>> prospect_trace.state
|
||||||
'open'
|
'with_pending_calls'
|
||||||
|
|
||||||
Programar una próxima llamada pendiente al seguimiento de prospecto::
|
Programar una próxima llamada pendiente al seguimiento de prospecto::
|
||||||
>>> pending_call4 = prospect_trace.pending_calls.new(date = date.today() + timedelta(days=7))
|
>>> schedule = Wizard('sale.prospect_trace.schedule', [prospect_trace])
|
||||||
>>> prospect_trace.save()
|
>>> schedule.form.date_time = datetime(2023, 8, 14, 15, 30, 30)
|
||||||
|
>>> schedule.execute('schedule')
|
||||||
>>> prospect_trace.pending_calls
|
|
||||||
[proteus.Model.get('sale.pending_call')(1)]
|
|
||||||
|
|
||||||
|
>>> prospect_trace.pending_call.date
|
||||||
|
datetime.datetime(2023, 8, 14, 15, 30, 30)
|
||||||
>>> prospect_trace.state
|
>>> prospect_trace.state
|
||||||
'with_pending_calls'
|
'with_pending_calls'
|
||||||
|
|
||||||
Crear una llamada agendada previamente:
|
Crear una llamada agendada previamente::
|
||||||
>>> call4 = prospect_trace.calls.new(description='fourth call', interest='3')
|
>>> make_call = Wizard('sale.prospect_trace.make_call', [prospect_trace])
|
||||||
|
>>> make_call.form.description = 'Fourth call to the prospect'
|
||||||
|
>>> make_call.form.interest = '2'
|
||||||
|
>>> make_call.execute('make_call')
|
||||||
|
|
||||||
|
>>> prospect_trace.pending_call
|
||||||
|
|
||||||
>>> prospect_trace.pending_calls
|
|
||||||
[]
|
|
||||||
>>> prospect_trace.state
|
>>> prospect_trace.state
|
||||||
'open'
|
'open'
|
||||||
|
|
||||||
Cuando se asigna prospecto sin método de contacto mobile, el contacto en el seguimiento es vacío::
|
Hacer llamada y programar tarea::
|
||||||
>>> prospect2 = Prospect()
|
>>> make_call = Wizard('sale.prospect_trace.make_call', [prospect_trace])
|
||||||
>>> prospect2.name = 'Sin celulares S.A.S'
|
>>> make_call.form.description = 'Prospect told me to send him an email'
|
||||||
>>> contact_method = prospect2.contact_methods.new(contact_type='mail', value='felpucio@sincelulares.org', name='felpucio', job='Supervisor')
|
>>> make_call.form.interest = '3'
|
||||||
>>> prospect2.save()
|
>>> make_call.form.schedule_call = 'yes'
|
||||||
|
>>> make_call.form.schedule_task = 'yes'
|
||||||
|
>>> make_call.execute('make_call')
|
||||||
|
>>> make_call.form.datetime = datetime(2023, 8, 14, 15, 30, 30)
|
||||||
|
>>> make_call.execute('schedule_call')
|
||||||
|
>>> make_call.form.task_description = 'I have to send a mail to prospect offering him this services...'
|
||||||
|
>>> make_call.execute('schedule_task')
|
||||||
|
|
||||||
>>> prospect_trace2 = ProspectTrace()
|
>>> Task = Model.get('sale.pending_task')
|
||||||
>>> prospect_trace2.prospect = prospect2
|
>>> task, = Task.find([('description', '=', 'I have to send a mail to prospect offering him this services...')])
|
||||||
|
>>> task
|
||||||
|
proteus.Model.get('sale.pending_task')(1)
|
||||||
|
|
||||||
>>> prospect_trace2.save()
|
>>> 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'
|
||||||
|
>>> make_call.form.interest = '4'
|
||||||
|
>>> make_call.execute('make_call')
|
||||||
|
>>> prospect_trace.click('close_trace')
|
||||||
|
|
||||||
|
>>> prospect_trace.state
|
||||||
|
'closed'
|
||||||
|
|
||||||
|
Reabrir seguimiento a prospecto una vez cerrado::
|
||||||
|
>>> prospect_trace.click('reopen_trace')
|
||||||
|
>>> prospect_trace.state
|
||||||
|
'open'
|
||||||
|
|
||||||
|
Reasignar prospectos por operador::
|
||||||
|
>>> operator2 = User();
|
||||||
|
>>> operator2.name = 'Operatus'
|
||||||
|
>>> operator2.login = 'login'
|
||||||
|
>>> operator2.save()
|
||||||
|
|
||||||
|
>>> reassign_by_operator = Wizard('sale.prospect.reassign_by_operator', [])
|
||||||
|
>>> reassign_by_operator.form.current_operator = user
|
||||||
|
>>> reassign_by_operator.form.prospects
|
||||||
|
[proteus.Model.get('sale.prospect')(1), proteus.Model.get('sale.prospect')(2)]
|
||||||
|
>>> reassign_by_operator.form.new_operator = operator2
|
||||||
|
>>> reassign_by_operator.execute('reassign_by_operator')
|
||||||
|
|
||||||
|
>>> prospect1.reload()
|
||||||
|
>>> prospect1.assigned_operator.name
|
||||||
|
'Operatus'
|
||||||
|
|
||||||
|
>>> prospect2.reload()
|
||||||
|
>>> prospect2.assigned_operator.name
|
||||||
|
'Operatus'
|
||||||
|
|
||||||
|
>>> prospect_trace.reload()
|
||||||
|
>>> prospect_trace.prospect_assigned_operator.name
|
||||||
|
'Operatus'
|
||||||
|
|
||||||
|
.. Las llamadas deben conservar el operador que las hizo
|
||||||
|
>>> prospect_trace.calls[0].operator_who_called.name
|
||||||
|
'Administrator'
|
||||||
|
|
||||||
|
Reasignar prospectos por prospecto::
|
||||||
|
>>> reassign_by_prospect = Wizard('sale.prospect.reassign_by_prospect', [])
|
||||||
|
>>> 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
|
||||||
|
'Administrator'
|
||||||
|
>>> prospect_trace.reload()
|
||||||
|
>>> prospect_trace.prospect_assigned_operator.name
|
||||||
|
'Administrator'
|
||||||
|
>>> prospect_trace.calls[0].operator_who_called.name
|
||||||
|
'Administrator'
|
||||||
|
|
||||||
|
Crear un usuario de rol administrador::
|
||||||
|
>>> User = Model.get('res.user')
|
||||||
|
>>> admin = User(name="Administrator", login="administrator", user_admin=True)
|
||||||
|
>>> 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
|
Reportes
|
||||||
--------
|
--------
|
||||||
["Crear un reporte en el que evidencie por operario y consolidado"]
|
["Crear un reporte en el que evidencie por operario y consolidado"]
|
||||||
|
|
||||||
["Cantidad de llamadas realizadas en un período de tiempo"]
|
["Cantidad de llamadas realizadas en un período de tiempo"]
|
||||||
|
|
||||||
["Crear un reporte para verificar cantidad de llamadas por realizar"]
|
["Crear un reporte para verificar cantidad de llamadas por realizar"]
|
||||||
|
|
||||||
["Crear reporte para identificación de clientes potenciales (Cliente que en la llamada fueron marcados con un nivel alto)"]
|
["Crear reporte para identificación de clientes potenciales (Cliente que en la llamada fueron marcados con un nivel alto)"]
|
||||||
|
|
||||||
|
|
||||||
@@ -229,7 +392,7 @@ Reportes
|
|||||||
* Observaciones
|
* Observaciones
|
||||||
* Operario
|
* Operario
|
||||||
|
|
||||||
* Reporte de seguimientos a prospectos (Análisis de prospectos):
|
* Reporte de seguimiento a prospecto (Análisis de prospecto):
|
||||||
* Interés durante distintas etapas del seguimiento
|
* Interés durante distintas etapas del seguimiento
|
||||||
|
|
||||||
|
|
||||||
@@ -243,3 +406,4 @@ Reportes
|
|||||||
* Reporte de prospectos potenciales
|
* Reporte de prospectos potenciales
|
||||||
* llamadas con un nivel de interés alto
|
* llamadas con un nivel de interés alto
|
||||||
* Seguimiento de prospecto al que pertenecen las llamadas
|
* Seguimiento de prospecto al que pertenecen las llamadas
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,12 @@ class RequiredValuesTestCase(ModuleTestCase):
|
|||||||
Prospect = pool.get('sale.prospect')
|
Prospect = pool.get('sale.prospect')
|
||||||
self.assertTrue(Prospect.name.required)
|
self.assertTrue(Prospect.name.required)
|
||||||
|
|
||||||
|
@with_transaction()
|
||||||
|
def test_bussiness_unit_en_Prospect_es_obligatorio(self):
|
||||||
|
pool = Pool()
|
||||||
|
Prospect = pool.get('sale.prospect')
|
||||||
|
self.assertTrue(Prospect.business_unit.required)
|
||||||
|
|
||||||
@with_transaction()
|
@with_transaction()
|
||||||
def test_value_en_ContactMethod_es_obligatorio(self):
|
def test_value_en_ContactMethod_es_obligatorio(self):
|
||||||
pool = Pool()
|
pool = Pool()
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
[tryton]
|
[tryton]
|
||||||
version=6.8.0
|
version=7.0.0
|
||||||
depends:
|
depends:
|
||||||
ir
|
ir
|
||||||
res
|
res
|
||||||
xml:
|
xml:
|
||||||
|
icons.xml
|
||||||
|
user.xml
|
||||||
call.xml
|
call.xml
|
||||||
prospect_trace.xml
|
prospect_trace.xml
|
||||||
prospect.xml
|
prospect.xml
|
||||||
pending_call.xml
|
|
||||||
./locations/departments.xml
|
./locations/departments.xml
|
||||||
./locations/cities.xml
|
./locations/cities.xml
|
||||||
17
user.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
# 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 fields
|
||||||
|
from trytond.pool import PoolMeta
|
||||||
|
|
||||||
|
|
||||||
|
class User(metaclass=PoolMeta):
|
||||||
|
"User"
|
||||||
|
__name__ = 'res.user'
|
||||||
|
|
||||||
|
user_admin = fields.Boolean('Is Admin')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def __setup__(cls):
|
||||||
|
super(User, cls).__setup__()
|
||||||
|
cls._context_fields.insert(0, 'user_admin')
|
||||||
12
user.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?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.ui.view" id="user_view_form" >
|
||||||
|
<field name="name">user_form</field>
|
||||||
|
<field name="inherit" ref="res.user_view_form"/>
|
||||||
|
<field name="model">res.user</field>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</tryton>
|
||||||
19
view/assign_start_form.xml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?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 col="6">
|
||||||
|
<label name="operator"/>
|
||||||
|
<field name="operator"/>
|
||||||
|
<label name="business_unit"/>
|
||||||
|
<field name="business_unit"/>
|
||||||
|
<label name="prospects_chunk"/>
|
||||||
|
<field name="prospects_chunk"/>
|
||||||
|
|
||||||
|
<notebook colspan="6">
|
||||||
|
<page string="Prospects" id="prospects_to_assign" col="6">
|
||||||
|
<group col="2" id="prospects">
|
||||||
|
<field name="prospects"/>
|
||||||
|
</group>
|
||||||
|
</page>
|
||||||
|
</notebook>
|
||||||
|
</form>
|
||||||
@@ -18,4 +18,6 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
|
|
||||||
<label name="call_result"/>
|
<label name="call_result"/>
|
||||||
<field name="call_result"/>
|
<field name="call_result"/>
|
||||||
|
<label name="call_business_unit"/>
|
||||||
|
<field name="call_business_unit"/>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -8,4 +8,6 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<field name="call_result" expand="1"/>
|
<field name="call_result" expand="1"/>
|
||||||
<field name="prospect_trace" expand="1"/>
|
<field name="prospect_trace" expand="1"/>
|
||||||
<field name="description" expand="1"/>
|
<field name="description" expand="1"/>
|
||||||
|
<field name="call_business_unit" expand="1"/>
|
||||||
|
<field name="operator_who_called" expand="1"/>
|
||||||
</tree>
|
</tree>
|
||||||
@@ -4,7 +4,6 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<tree editable="1">
|
<tree editable="1">
|
||||||
<field name="contact_type" expand="1"/>
|
<field name="contact_type" expand="1"/>
|
||||||
<field name="value" expand="1"/>
|
<field name="value" expand="1"/>
|
||||||
<field name="prospect" expand="1"/>
|
|
||||||
<field name="name" expand="1"/>
|
<field name="name" expand="1"/>
|
||||||
<field name="job" expand="1"/>
|
<field name="job" expand="1"/>
|
||||||
</tree>
|
</tree>
|
||||||
|
|||||||
7
view/make_call_ask_form.xml
Normal 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. -->
|
||||||
|
<form>
|
||||||
|
<label name="datetime"/>
|
||||||
|
<field name="datetime"/>
|
||||||
|
</form>
|
||||||
7
view/make_call_ask_task_form.xml
Normal 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. -->
|
||||||
|
<form>
|
||||||
|
<label name="task_description"/>
|
||||||
|
<field name="task_description"/>
|
||||||
|
</form>
|
||||||
18
view/make_call_start_form.xml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?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>
|
||||||
|
<group col="6" id="description">
|
||||||
|
<label name="description"/>
|
||||||
|
<field name="description"/>
|
||||||
|
</group>
|
||||||
|
<newline/>
|
||||||
|
<group col="6" id="call_data">
|
||||||
|
<label name="interest"/>
|
||||||
|
<field name="interest" colspan="1"/>
|
||||||
|
<label name="schedule_call"/>
|
||||||
|
<field name="schedule_call" colspan="1"/>
|
||||||
|
<label name="schedule_task"/>
|
||||||
|
<field name="schedule_task" colspan="1"/>
|
||||||
|
</group>
|
||||||
|
</form>
|
||||||
12
view/pending_task_form.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?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>
|
||||||
|
<group col="6" id="content">
|
||||||
|
<label name="prospect_trace"/>
|
||||||
|
<field name="prospect_trace"/>
|
||||||
|
<newline/>
|
||||||
|
<label name="description"/>
|
||||||
|
<field name="description"/>
|
||||||
|
</group>
|
||||||
|
</form>
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
<!-- 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. -->
|
||||||
<tree>
|
<tree>
|
||||||
<field name="date" expand="1"/>
|
|
||||||
<field name="prospect_trace" expand="1"/>
|
<field name="prospect_trace" expand="1"/>
|
||||||
|
<field name="description" expand="1"/>
|
||||||
|
<button name="close_task"/>
|
||||||
</tree>
|
</tree>
|
||||||
@@ -6,6 +6,9 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<label name="name"/>
|
<label name="name"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
|
|
||||||
|
<label name="business_unit"/>
|
||||||
|
<field name="business_unit"/>
|
||||||
|
|
||||||
<newline/>
|
<newline/>
|
||||||
<label name="department"/>
|
<label name="department"/>
|
||||||
<field name="department"/>
|
<field name="department"/>
|
||||||
@@ -19,6 +22,24 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<page string="Contact methods" id="contact_methods">
|
<page string="Contact methods" id="contact_methods">
|
||||||
<field name="contact_methods" colspan="2"/>
|
<field name="contact_methods" colspan="2"/>
|
||||||
</page>
|
</page>
|
||||||
|
<page string="About prospect" id="contact_methods">
|
||||||
|
<label name="rating"/>
|
||||||
|
<field name="rating"/>
|
||||||
|
<newline/>
|
||||||
|
<label name="comments"/>
|
||||||
|
<field name="comments"/>
|
||||||
|
</page>
|
||||||
</notebook>
|
</notebook>
|
||||||
|
<newline/>
|
||||||
|
|
||||||
|
<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>
|
</form>
|
||||||
@@ -5,8 +5,8 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<group col="6" colspan="5" id="header" yalign="0">
|
<group col="6" colspan="5" id="header" yalign="0">
|
||||||
<label name="prospect"/>
|
<label name="prospect"/>
|
||||||
<field name="prospect"/>
|
<field name="prospect"/>
|
||||||
<label name="prospect_contact"/>
|
<label name="prospect_business_unit"/>
|
||||||
<field name="prospect_contact"/>
|
<field name="prospect_business_unit"/>
|
||||||
<label name="prospect_city"/>
|
<label name="prospect_city"/>
|
||||||
<field name="prospect_city"/>
|
<field name="prospect_city"/>
|
||||||
</group>
|
</group>
|
||||||
@@ -14,18 +14,25 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<group col="6" colspan="5" id="trace_data" yalign="0">
|
<group col="6" colspan="5" id="trace_data" yalign="0">
|
||||||
<label name="current_interest"/>
|
<label name="current_interest"/>
|
||||||
<field name="current_interest"/>
|
<field name="current_interest"/>
|
||||||
<label name="active"/>
|
|
||||||
<field name="active" xexpand="0" width="25"/>
|
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
|
<field name="calls" colspan="6"/>
|
||||||
|
<newline/>
|
||||||
|
<group col="-1" colspan="6" id="buttons">
|
||||||
|
<button name="wizard_make_call" icon="tryton-tel"/>
|
||||||
|
<button name="wizard_schedule" icon="tryton-calendar"/>
|
||||||
|
</group>
|
||||||
<newline/>
|
<newline/>
|
||||||
<notebook colspan="6">
|
|
||||||
<page string="Calls - Oldest to Newest" id="calls">
|
|
||||||
<field name="calls" colspan="2"/>
|
|
||||||
</page>
|
|
||||||
</notebook>
|
|
||||||
|
|
||||||
<field name="pending_calls" colspan="6"/>
|
<field name="prospect_contacts" colspan="6"/>
|
||||||
|
|
||||||
|
<label name="pending_call"/>
|
||||||
|
<field name="pending_call"/>
|
||||||
<label name="state"/>
|
<label name="state"/>
|
||||||
<field name="state"/>
|
<field name="state"/>
|
||||||
|
|
||||||
|
<group col="-1" colspan="6" id="footer_buttons">
|
||||||
|
<button name="close_trace" icon="tryton-archive"/>
|
||||||
|
<button name="reopen_trace" icon="tryton-unarchive"/>
|
||||||
|
</group>
|
||||||
</form>
|
</form>
|
||||||
@@ -3,9 +3,10 @@
|
|||||||
this repository contains the full copyright notices and license terms. -->
|
this repository contains the full copyright notices and license terms. -->
|
||||||
<tree>
|
<tree>
|
||||||
<field name="prospect" expand="1"/>
|
<field name="prospect" expand="1"/>
|
||||||
<field name="prospect_contact" expand="1"/>
|
<field name="prospect_business_unit" expand="1"/>
|
||||||
<field name="prospect_city" expand="1"/>
|
<field name="prospect_city" expand="1"/>
|
||||||
<field name="current_interest" expand="1"/>
|
<field name="current_interest" expand="1"/>
|
||||||
<field name="calls" expand="1"/>
|
<field name="calls" expand="1"/>
|
||||||
<field name="pending_calls" expand="1"/>
|
<field name="pending_call" expand="1"/>
|
||||||
|
<field name="prospect_assigned_operator" expand="1"/>
|
||||||
</tree>
|
</tree>
|
||||||
@@ -3,7 +3,9 @@
|
|||||||
this repository contains the full copyright notices and license terms. -->
|
this repository contains the full copyright notices and license terms. -->
|
||||||
<tree>
|
<tree>
|
||||||
<field name="name" expand="1"/>
|
<field name="name" expand="1"/>
|
||||||
|
<field name="business_unit" expand="1"/>
|
||||||
<field name="department" expand="1"/>
|
<field name="department" expand="1"/>
|
||||||
<field name="city" expand="1"/>
|
<field name="city" expand="1"/>
|
||||||
<field name="contact_methods" expand="1"/>
|
<field name="assigned_operator" expand="1"/>
|
||||||
|
<field name="rating" expand="1"/>
|
||||||
</tree>
|
</tree>
|
||||||
10
view/reassign_by_operator_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="current_operator"/>
|
||||||
|
<field name="current_operator"/>
|
||||||
|
<label name="new_operator"/>
|
||||||
|
<field name="new_operator"/>
|
||||||
|
<field name="prospects" colspan="6"/>
|
||||||
|
</form>
|
||||||
@@ -2,9 +2,8 @@
|
|||||||
<!-- 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. -->
|
||||||
<form>
|
<form>
|
||||||
<label name="date"/>
|
<label name="prospect"/>
|
||||||
<field name="date"/>
|
<field name="prospect"/>
|
||||||
|
<label name="new_operator"/>
|
||||||
<label name="prospect_trace"/>
|
<field name="new_operator"/>
|
||||||
<field name="prospect_trace"/>
|
|
||||||
</form>
|
</form>
|
||||||
7
view/schedule_start_form.xml
Normal 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. -->
|
||||||
|
<form>
|
||||||
|
<label name="date_time"/>
|
||||||
|
<field name="date_time"/>
|
||||||
|
</form>
|
||||||
9
view/user_form.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?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. -->
|
||||||
|
<data>
|
||||||
|
<xpath expr="//field[@name='name']" position="after">
|
||||||
|
<label name="user_admin"/>
|
||||||
|
<field name="user_admin"/>
|
||||||
|
</xpath>
|
||||||
|
</data>
|
||||||