265 Commits

Author SHA1 Message Date
Rodia
a4fe42e15a Update tryton.cfg 2023-12-04 23:51:05 -05:00
d1ad40203b Merge pull request 'fix: al crear mecanismo de contacto desde prospecto no se actualiza correctamente en seguimiento de prospecto' (#77) from NoSeActualizaContactMethodEnProspectTrace_#76 into 6.8
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Se replica error en las pruebas y se soluciona con un on_change
2023-10-20 16:19:03 -05:00
9c368809f9 fix: al crear mecanismo de contacto desde prospecto no se actualiza correctamente en seguimiento de prospecto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
2023-10-20 15:27:51 -05:00
e40991de02 feat: Se agregan dominios de vista de prospectos
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-22 10:39:10 -05:00
b8ba775733 chore(Tipificación del cliente): Se hacen traducciones
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-21 19:28:19 -05:00
336a266578 chore: Se hace visible rating en vista de arbol de prospectos
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-21 19:13:29 -05:00
22fb3736a7 chore(Agendación de tarea): Se agregan traducciones faltantes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-21 19:08:24 -05:00
5cc7ef011d feat: Se agrega tipificación del cliente, closed #70
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-19 17:10:13 -05:00
72ae0cfa22 feat: Se hace posible agregar y modificar métodos de contactos desde seguimiento de prospectos, closed #72
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-19 15:56:21 -05:00
0b7d15f35b feat(Programación de tareas): Se agregan traducciones, #71
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-19 12:19:49 -05:00
8a0aa29368 feat: Se agregan estados a la vista de tareas pendientes, #71
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-19 11:57:29 -05:00
f71e6f4671 feat: Se implementa en las pruebas cierre de tarea pendientes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-19 11:47:31 -05:00
cf874db55f chore(Task): se extrae clase a otro archivo, #71 2023-09-19 11:24:49 -05:00
e97e8fa99d chore: prueba error usuario gitea, #71
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-19 07:08:32 -05:00
5a2c5217a6 feat: Se agrega reporte de tareas pendientes, #71 2023-09-19 06:48:55 -05:00
d50cca2924 feat: Se implementa agendación de tarea en las vistas, #71
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-19 06:10:09 -05:00
c1be04d009 Merge branch '6.8' of https://gitea.onecluster.org/OneTeam/trytondo-sale_opportunity_management into 6.8
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-18 19:50:10 -05:00
214c6fc089 feat: Se implementa agendación de tarea en las pruebas, #71 2023-09-18 19:49:58 -05:00
a7bf0f2a38 Fix: Se añaden traducciones pendientes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-12 19:29:24 -05:00
243f1123a8 Fix: se añade traduccion es administrador en usuarios
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-12 19:17:11 -05:00
faa8f35384 Fix: se añade traduccion pagina metodos de contacto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-12 19:13:09 -05:00
78fcd0231d chore(Reasignación por prospecto): Solo se muestran los prospectos con un operario asignado, closed #68
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-10 14:07:13 -05:00
3ac393dd01 chore: Se corrige error en traducción
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-10 13:59:09 -05:00
abf0c05894 fix: Closed #65
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-09 18:14:16 -05:00
a73cd43582 prueba carpintero
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-05 18:22:37 -05:00
0ccb733dab chore: Se remueve código muerto
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-04 18:00:11 -05:00
649f610bb0 Fix: Se añade dominio en seguiemiento de prospectos por rol
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-04 17:42:24 -05:00
c32b4ce31c Fix: Se añade dominio en seguiemiento de prospectos por rol
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-04 17:39:20 -05:00
97bbcaed92 Fix: Se añade dominio en seguiemiento de prospectos por rol
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-04 17:33:37 -05:00
a1716141b0 Fix: Se añaden grupos de usuarios
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-04 13:43:20 -05:00
0c09498340 Fix: Se corrige errores de pruebas
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-04 09:53:01 -05:00
8e60272f91 Se añade grupos de usuarios
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-04 09:32:20 -05:00
4ec1d2e2cd feat: Se traducen encabezados de wizards, #63
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-02 11:26:22 -05:00
b36160c228 chore: Se remueve código muerto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-02 11:04:50 -05:00
0460324ddf Chore: Se remueve página innecesaria
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-02 11:04:27 -05:00
33ac57175c feat: Se traducen dominios, #63
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-02 11:01:49 -05:00
732b9dbfb8 feat: Se traducen botones de wizards, #63
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-02 10:44:25 -05:00
01b5119f0b chore: Se agrega icono de reporte de llamadas
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-02 10:19:12 -05:00
eed86133f4 feat: Se agregan traducciones a selections, #63
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-31 18:56:13 -05:00
dd3cd79a1f fix: Se remueve traducción invalida
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-31 18:18:06 -05:00
766f3fbc0b feat: Gpt agrega traducciones a campos de modelos faltantes, #63
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-31 17:45:24 -05:00
2bd62e1b14 feat: Se agregan traducciones a campos de prospect, #63
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-31 17:26:07 -05:00
94321866eb feat: Se agregan traducciones a campos de prospect trace, #63
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-31 17:21:42 -05:00
f9bf0d3384 feat: Se agregan traducciones a botones, #63
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-31 17:13:30 -05:00
1bcc6e5294 chore: Se cambia enlace simbólico de documentación
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-30 21:31:00 -05:00
c9de0ab42e chore: Se cambian iconos
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-30 21:25:50 -05:00
d925fcf913 fix(Botón reabrir seguimiento): Se arreglan las evaluaciones de 'invisible'
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-30 21:19:29 -05:00
033f1aad43 feat(Prospect_Trace): Se agrega reanudación de seguimiento a las vistas, #64
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-30 19:13:28 -05:00
fd24a757fb feat: Se implementa reanudación de seguimiento en las pruebas, #64
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-30 19:00:31 -05:00
3d77cf9a98 chore: Se remueve código muerto, #64
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-30 18:31:42 -05:00
9efb29f1a1 feat(Prospect_Trace): Se agrega estado 'cerrado' las vistas, #64
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-30 18:30:11 -05:00
8c1ed18530 feat: Se implementa cierre de seguimiento en las pruebas, #64
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-30 18:04:27 -05:00
1a469a5106 feat: Se agregan traducciones (es) de menús
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-29 21:01:38 -05:00
fc70d7cb74 Fix: Se elimina campo currency_date de la vista
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-29 19:50:56 -05:00
ceb9f07aab feat: se añade dominio a campo para agendar proxima llamada
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-29 19:46:12 -05:00
bdcf78ad56 chore: En registros de llamadas se renombra 'operario asignado' por 'operario que llamó'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-28 20:27:30 -05:00
79dd0454d6 chore(Calls): Se hace unidad de negocio de solo lectura
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-28 20:20:01 -05:00
a8c6ecaa79 feat: Se limita creación de llamadas desde otro lugar que no sea el asistente destinado a ello
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-28 20:18:28 -05:00
18413d9005 chore(Vista de prospectos): se cambia vista de menús por vista de pestañas, closed #62
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-28 20:13:16 -05:00
e0c47961bc chore: Se elimina código muerto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-28 20:03:31 -05:00
22478c9e68 chore: se elimina código muerto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-28 20:03:09 -05:00
8ec3e4b983 feat: Se inicia seguimiento automáticamente luego de asignar operario, closed #61
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-28 19:59:52 -05:00
543a52303c chore: Se remueve código duplicado
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-28 19:27:26 -05:00
70aa3f96d4 feat: Se agrega posible agendación de llamada en el flujo de crear una llamada, #58
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-27 20:52:42 -05:00
27d4ce8a77 feat: Se agregan vistas de reasignación de prospecto específico, #53
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-27 19:13:17 -05:00
2eb52e9dce feat: Se implementa reasignación de prospecto específico en las pruebas, #53
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-27 18:48:30 -05:00
ed07f5fcbc feat: Se hacen vistas a asistente de reasignación por operario, #53
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-27 11:39:33 -05:00
3d77056e6f feat: Se implementa en las pruebas asistene de reasignación por operario
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-27 11:13:43 -05:00
e260c70a11 Error: Solo se guarda nuevo operario en primer iteración
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-27 10:21:43 -05:00
416804983b chore: Se elimina código muerto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-27 09:49:55 -05:00
0364110866 chore(scenario): Se usa registro de prospect_trace obtenido por el click de iniciar seguimiento
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-27 08:22:00 -05:00
27dcca74bc feat: Se crea botón para iniciar seguimiento de prospecto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-26 20:38:40 -05:00
082d070643 chore: Se remueve menú innecesario
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-26 18:11:47 -05:00
1a1b262720 feat: Se hace posible filtrar llamadas por operario que realizó dicha llamada
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-26 17:59:08 -05:00
9067aa1446 chore: Se remueve código muerto y se da orden a las vistas, closed #54
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-26 17:35:59 -05:00
7c39fcc429 feat(ProspectTrace): Se agregan a la vista todos los contactos del prospecto 2023-08-26 16:36:32 -05:00
1ece8ae959 feat(ProspectTrace): Se agrega campo para todos los contactos del prospecto 2023-08-26 16:28:21 -05:00
05ae82839b feat: Se añade nuevo item en escala de interés, closed #57
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-24 15:18:21 -05:00
31fb4211e4 feat(AssignProspectsWizard): Se encuentran prospectos también por unidad de negocio, closed #55
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-24 15:01:39 -05:00
8fa5d20ea6 feat(Call): Se hace visible unidad de negocio, actualizandose junto con el seguimiento de prospecto, closed #56
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-24 14:11:05 -05:00
4ffb654814 feat(ProspectTrace): Se hace visible unidad de negocio, actualizandose al seleccionar prospecto, #56
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-24 13:16:21 -05:00
a33d43cb57 feat(Prospect): Se crea campo de unidad de negocio, #56
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-24 12:56:55 -05:00
3bb8ddbb2c chore: Se hace requerido prospect_trace en Call
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-22 19:03:07 -05:00
11a541a3eb chore: Se elimina código muerto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-22 18:55:50 -05:00
06a7402f0c chore: Se da formato a formulario de asistente de creación de llamadas, closed #50
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-22 18:18:33 -05:00
f3f7493d6c chore: Se crea dominio en mecanismo de contacto, closed #48
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-22 18:11:19 -05:00
16508c5961 chore: Se agregan iconos personalizados, closed #51
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-22 17:56:02 -05:00
4449b57f60 chore: Se agregan iconos personalizados a ventana principal y wizard de creación de llamada
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-22 17:17:22 -05:00
9f8e0b96af feat: Se hace visible operario asignado desde la vista de árbol, closed #49
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-22 16:25:04 -05:00
229fa9044a chore: Se ajustan detalles en la documentación
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-22 16:14:45 -05:00
a8da18e2b6 feat: Se crea asistente para creación de llamadas a seguimiento, closed #39
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-21 12:48:25 -05:00
8d1d5d1553 fix: Se genera error cuando prospects_chunks es negativo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-21 12:20:19 -05:00
36f074a519 Merge branch '6.8' of https://gitea.onecluster.org/OneTeam/trytondo-sale_opportunity_management into 6.8
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-21 11:59:46 -05:00
d330ac341a Se implementa wizard para crear llamadas a prospectos (en las pruebas), #39 2023-08-21 11:59:38 -05:00
1187dd6ecc Fix: Se da formato a la vista closed #46
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-21 10:18:43 -05:00
fd667a518b chore: Se hace que agendar llamada pendiente solo se pueda hacer desde el asistente
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-21 09:39:06 -05:00
b34a1e19af feat: Se crea asistente para agendar próxima llamada
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-21 09:27:48 -05:00
56550df81a Merge branch '6.8' of https://gitea.onecluster.org/OneTeam/trytondo-sale_opportunity_management into vistasWizardPendingCall 2023-08-21 09:08:53 -05:00
f0a5e30b38 feat(Wizard de asignación de prospectos): Se agrega campo para visualización de terceros encontrados según el chunk
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-21 09:05:48 -05:00
a63dd54089 Merge branch '6.8' of https://gitea.onecluster.org/OneTeam/trytondo-sale_opportunity_management into vistasWizardPendingCall
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-21 07:55:42 -05:00
3fc2db8543 chore: cambia pipeline por steps
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-20 23:04:46 +00:00
05ff4b8f8d Error registrando boton en ProspectTrace 2023-08-19 14:39:30 -05:00
881f34d582 feat: closed #44
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-19 13:01:00 -05:00
d7095e05bb chore: Se remueve código muerto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-19 12:56:12 -05:00
c0db903ac8 Merge branch '6.8' of https://gitea.onecluster.org/OneTeam/trytondo-sale_opportunity_management into 6.8
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-19 12:45:33 -05:00
93c2f10040 Se implementa wizard para crear llamada pendiente en las pruebas, #35 2023-08-19 12:41:29 -05:00
590e604604 chore: usando imagen personalizada para plugin/matrix
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-18 20:41:09 -05:00
2c68c3bb53 chore: compatibilidad versión 1.0 woodpecker
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-18 20:34:34 -05:00
3c4e8f5a26 Feat: Se añade Wizard assign_operator_wizard a la vista
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-18 19:24:47 -05:00
51d58de12a Feat: se actualiza CONTRIBUIR.md
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-17 11:20:31 -05:00
1bb4af8f16 feat: Se añade wizard de asignación de operarios a la vista
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-16 20:49:00 -05:00
c3ad43d144 Merge branch '6.8' of https://gitea.onecluster.org/OneTeam/trytondo-sale_opportunity_management into 6.8
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-15 22:33:09 -05:00
bc4833b3cf feat: Se crea asistente para asignación de prospectos a operarios 2023-08-15 22:33:02 -05:00
1f52dcba26 chore: Se remueve código muerto 2023-08-15 16:35:44 -05:00
582c8adbd3 chore: se habilita nuevamente actualizador de cambios
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-14 21:44:04 -05:00
ca2d115e22 chore: se adiciona cliente sao 6.8
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fixes #33
2023-08-14 21:15:53 -05:00
6d77af53ef feat: closed #36
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-14 20:32:49 -05:00
8ab3a97b3c feat: Se admite fecha y hora en llamada pendiente, closed #25
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-14 20:00:41 -05:00
0d1602fe1d chore: closed #21
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-14 19:48:46 -05:00
9b2c40d821 feat: Se hace visible agenda de llamadas en vista tree de prospect_trace, closed #31
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-13 21:05:57 -05:00
d7d5c95b29 chore: Se remueve código muerto luego de refactorizar
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-13 20:35:11 -05:00
1d38d797c5 fix: Un seguimiento a prospecto solo debe tener máximo una llamada agendada, closed #28
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-13 20:31:59 -05:00
452b97cdf9 feat: Se hace prospect_city de solo lectura
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-13 19:31:35 -05:00
87da50560a feat: Se añade vistas de estados
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-13 18:58:29 -05:00
f7e8e40d4c feat: Se implementa cambio de estado al remover operario
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-13 18:45:29 -05:00
b479e83d8c feat: Se añade estados al prospecto 2023-08-13 18:39:49 -05:00
0be22b3298 feat: se hace por defecto el tipo mobile en contact_type, closed #30
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-13 17:36:43 -05:00
29a20afbfa fix: Poder editar mecanismo de contacto desde el tree closed #29
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-13 17:27:57 -05:00
48a75b3399 fix: Se añade pending_calls a dependencias de on_change_calls
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-13 17:17:21 -05:00
24cc06d4c6 chore: Se alinean campos en vistas
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-12 22:42:53 -05:00
bb5ecf31b3 chore: Se da orden a vista de formulario de seguimiento de prospecto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-12 21:49:03 -05:00
a7972a898a chore: Se refactoriza on_change_calls para mejor legibilidad
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-12 20:52:39 -05:00
6fb2e1d537 chore: se invierte comprobación de nulo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-12 20:46:19 -05:00
cf51d4d989 feat: Al crear una nueva llamada se elimina la llamada pendiente
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-12 20:43:51 -05:00
2cc3864767 feat: Se añade posibilidad de cerrar (archivar) seguimiento a prospectos
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-12 20:37:57 -05:00
d099529aa6 chore: Se cambia título de prueba por uno más descriptivo 2023-08-12 20:36:21 -05:00
635bd59c51 fix: Error al quitar llamada pendiente se entra en estado de with_pending_calls
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-12 18:50:00 -05:00
92384ebf3c fix: Error en Prospect_Trace al asignar un Prospect sin metodo de contacto de tipo mobile, closed #26
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-12 18:21:46 -05:00
36d7788d8d feat: Se agregan estados a la vista: open, with_pending_calls, all
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-12 13:35:37 -05:00
51d81797d8 chore: Se asigna estado por defecto en vez de en on_change_prospect
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-12 13:32:52 -05:00
428767ab81 chore: Se crea reduce código duplicado creando campo _states_selection
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-12 12:54:43 -05:00
7e19fbdaec Se cambia comportamiento de campo Function por métodos on_changes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-12 12:51:02 -05:00
dead8398f3 chore: se remueve registro duplicado de prospect.Prospect
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-11 20:54:25 -05:00
8acc2fd61a chore: se adiciona rake live:sh
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-11 19:39:58 -05:00
cf207447e2 chore: se deshabilita refrescador live (problemas concurrencia) 2023-08-11 19:39:23 -05:00
54b9a61305 chore: correrion reinicio servicio en rake live:reset
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-11 17:44:38 -05:00
ee9b1dc1ff chore: se adiciona rake live:reset
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-11 17:43:43 -05:00
553bec420d chore: se remueve base de datos de tests
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-11 17:29:32 -05:00
b63f0ffd85 chore: Se usa if guard para romper flujo en caso de nulo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-11 17:22:49 -05:00
55b7aada89 chore: rake live:up ejecuta en conjunto rake tdd
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-10 09:41:29 -05:00
7b7286c50c chore: rake tdd usa sqlite
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
usamos `sqlite` para agilizar el ciclo del tdd
y dejamos al carpintero confirmar con `postgres`
2023-08-09 22:06:48 -05:00
74a035e432 chore: Se hace obligatorio date en PendingCall
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-09 20:38:26 -05:00
cd3ab0247d chore: se hacen obligatorios campos pertinentes en Prospect y ContactMethod
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-09 19:52:03 -05:00
e6cc5e524e chore: Se cambia formato de escritura de mecanismo de contacto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-09 19:39:21 -05:00
14fd3fa09f fix: #24
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-09 19:20:46 -05:00
0c78983db7 feat: se hacen visibles datos relevantes del contacto en prospect_trace
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-09 14:12:52 -05:00
4d4bdca848 feat: Se agrega tercero relacionado a las vistas de mecanismo de contacto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-09 13:59:25 -05:00
4f0ea40253 feat: se agrega prueba (Se debe poder asignar más de un método de contacto de tipo móvil a un mismo prospecto)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-09 13:45:03 -05:00
fe3ea6a42a feat: Se agrega tercero relacionado en mecanismo de contacto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-09 13:39:49 -05:00
a34e324006 chore: Se cambia ciclo for por método .search en la búsqueda del móvil del contacto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-08 18:22:08 -05:00
e72de25e3a chore: Se extrae lógica de buscar movil de prospecto en un método aparte
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-08 17:23:51 -05:00
9928194cf7 feat(prospect_trace): prospect_contact se llena automáticamente con contact_method 'mobile' de prospecto si este existe, #18
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-08 17:18:00 -05:00
21fc7a7bcd chore: Se hace obligatorio mecanismo de contacto en creación de prospecto, #19
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-08 16:25:46 -05:00
c8243835d7 chore: se hace obligatorio prospecto en prospect trace
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-08 16:22:02 -05:00
3ae02445e8 feat: #20
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-08 16:07:34 -05:00
ce71b0c932 feat: Se crean estados autollenados al seguimiento de prospecto (open, with_pending_calls)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-08 15:56:01 -05:00
e16e1c6d90 chore: Se hace prueba de agregar llamada pendiente desde el punto de vista del seguimiento
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-08 13:01:19 -05:00
54848199a7 feat: Al crear una nueva llamada de a un seguimiento, call_type se llena automáticamente
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-07 21:16:49 -05:00
c48b72fc6a chore: Se ajustan dimensiones en prospect_trace_tree.xml
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-07 19:38:41 -05:00
f6e6ac44a1 fix: Se crean llamadas desde el punto de vista desde el seguimiento de prospecto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-07 19:11:16 -05:00
a714f4740d chore: Se asignan atributos pendientes en las vistas
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-07 15:46:18 -05:00
c1df0de713 feat: Se crean vistas a agenda de llamadas pendientes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-07 13:29:38 -05:00
3e41315689 fix: Si no se han creado llamadas al prospecto se rompe la transacción en _get_current_interest
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-07 13:27:24 -05:00
2bcaad6087 feat: Se crea modelo pending_call y se asignan sus relaciones
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-07 12:43:44 -05:00
2d521686ee Merge branch '6.8' of https://gitea.onecluster.org/OneTeam/trytondo-sale_opportunity_management into 6.8
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-07 11:41:01 -05:00
c5c80d348a fix: Se asigna tipo de dato adecuado al campo prospect_city 2023-08-07 11:40:55 -05:00
13d25b7a84 chore: fixes #13
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-07 09:58:06 -05:00
a6b53dd021 feat: Se agregan campos a vistas de llamada, prospecto y seguimiento de prospecto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-06 22:49:36 -05:00
f7cc481673 Se remueve campo innecesario en seguimiento de prospecto (prospect_name)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-06 20:48:08 -05:00
46749c4234 Fix: se soluciona falta de argumentos en elementos de vista de prospect_form
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-06 20:14:03 -05:00
98ae18336e feat: Se agrega campo de departamento en vista de prospecto
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-06 20:01:28 -05:00
d71f9ce6b2 fix: En los escenarios la segunda llamada sobreescribía la primera
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-06 19:49:54 -05:00
a85e3adc1c Merge branch '6.8' of https://gitea.onecluster.org/OneTeam/trytondo-sale_opportunity_management into 6.8
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-06 14:27:59 -05:00
6ecb0da346 feat: Se agrega dominio de ciudad y departamento en creación de prospecto 2023-08-06 14:27:52 -05:00
a5375d8445 chore: rake tdd soporta fossil scm
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-06 11:54:02 -05:00
beb285485d feat: Se asignan ciudades a creación de prospecto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-05 18:12:50 -05:00
6b972da26b feat: Se configura creación de ciudades y departamentos
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-05 17:14:23 -05:00
9a7a95e00f chore: Se renombra carpeta util y archivo municipalities
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-05 16:41:13 -05:00
b3b897db63 chore: Se remueve campo dane_code 2023-08-05 16:27:46 -05:00
f0171303e8 fix: Se convierte la carpeta locations en un paquete de python
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-05 16:20:35 -05:00
72a5c3462d chore: se ordena formato en escenarios
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-05 14:07:56 -05:00
ed3435c139 feat: Se crean relaciones entre ciudades y departamentos
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-05 14:01:51 -05:00
aa7f2fc152 fix: Se arregla el escenario de métodos de contacto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-04 08:59:35 -05:00
2f35253682 feat: Add call results
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-04 07:11:38 -05:00
e6735a88d6 chore: Se agrega archivo generado por rake en .gitignore
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-03 18:37:53 -05:00
1a43a2636a fix: Se arregla error, no se encuentra util
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-03 17:59:38 -05:00
297572b5d2 chore: se translada regla de exclude a .flake8
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-03 16:19:35 -05:00
5113ad0289 chore: se formatean archivos estilo pep8
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-03 16:08:44 -05:00
dc649a80b5 feat: se fuerza flake8 en tdd 2023-08-03 16:05:45 -05:00
1453766396 chore: fixes #9
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-03 15:52:58 -05:00
ad9a99ecc0 chore: fixes #20
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-03 15:49:21 -05:00
56def869ee feat: Se crea diferenciación de tipos de llamadas
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-03 19:01:05 +00:00
9fd4567dbe fix: Se arregla error en importación de módulos 2023-08-03 18:53:59 +00:00
a79490ed0f chore: Se elimina código duplicado extrayendo niveles de interés en una clase aparte
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-03 18:18:13 +00:00
41036b1c59 feat: Se agrega seguimiento de nivel de interés y nivel de interés actual
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-03 17:55:43 +00:00
31ca58425a fix: Se unifica toda la documentación en un mismo elemento
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-03 01:32:37 +00:00
eb28f4cba0 fix: Se remueve duplicidad entre documentaciones
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-03 00:52:41 +00:00
22b5d6cb7f chore: se limpia cache de trytond
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fixes #18
2023-08-01 18:47:43 -05:00
2531747b64 chore: se adiciona cliente postgresql para DB_CACHE 2023-08-01 18:07:03 -05:00
17ddb2e868 chore: tdd usa instalacion de modulo 2023-08-01 18:06:43 -05:00
b49423c943 chore: se extra instalacion de modulo a script 2023-08-01 18:06:14 -05:00
41533230ed chore: se extrae image a Dockerfile 2023-08-01 17:45:29 -05:00
1bbf058a3d chore: se ajustan nombres de archivos segun documentacion 2023-08-01 17:42:50 -05:00
72cb6bd76d chore: se extrae servicio a archivo 2023-08-01 17:41:17 -05:00
9d36e53371 chore: se adicion rake sh
terminal bash del contenedor
2023-08-01 17:06:12 -05:00
a88bd73833 feat: Se completan relaciones para el esqueleto andante
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-30 22:08:16 +00:00
e48a8c2124 feat(vista contact_method): Se crea la vista de contact method 2023-07-30 22:08:16 +00:00
2f4c47cafb chore: se adiciona enlance a pipeline
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fixes #17
2023-07-30 12:39:18 -05:00
e589908e1c Merge pull request 'walking_skeleton/views' (#6) from walking_skeleton into 6.8
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Reviewed-on: #6
2023-07-29 21:14:39 -05:00
0fe8ede9fd Chore: Se cambian nombres de vistas
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
2023-07-30 02:12:57 +00:00
51dcc6ff5e fix: Se arregla secuancia de vistas
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-30 02:00:38 +00:00
60e0096c06 feat(vista de prospectos): Se crea vista de prospectos 2023-07-30 01:55:56 +00:00
4d8c520bb0 chore: remove dead code 2023-07-30 01:47:09 +00:00
8dc10a7865 chore: rename model 2023-07-30 01:44:46 +00:00
a40164d386 fix(call.xml): Se arregla orden de sequencia de items 2023-07-30 01:42:28 +00:00
63fa2b7ebb Chore: se actualiza .gitignore 2023-07-30 01:41:18 +00:00
b4b5da7e2d feat(Vista de seguimiento): Se crea vista de seguimiento a prospecto 2023-07-30 01:40:37 +00:00
9d33b48a5d chore: remove dead code 2023-07-30 01:08:24 +00:00
5bcfc87c37 Feat(Vista principal): Se crea vista principal 2023-07-30 00:55:44 +00:00
4c6db3959f Refactor: rename models 2023-07-28 22:50:24 +00:00
6985b5300f Se crean relaciones entre llamadas y seguimiento de prospecto
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-07-28 03:26:38 +00:00
d1def24dd6 Se crea modelo de llamada y se hace valida fecha por defecto = hoy 2023-07-28 03:00:30 +00:00
f9f929ae1e Se agrega seguimiento de prospecto y se hace relación con prospecto 2023-07-28 02:09:17 +00:00
76b4485c22 Se crea modelo inicial de prospecto 2023-07-28 01:09:31 +00:00
3d5c3e17e0 Se crea modelo inicial de prospecto 2023-07-28 00:30:32 +00:00
5e7a41fa3b Se hace prueba de creación de prospecto 2023-07-28 00:28:30 +00:00
b7455c809f chore(calls.rst): Se cambia concepto de cliente por prospecto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-28 00:19:02 +00:00
65a2eee45c chore(calls.rst): Se cambia concepto de cliente por prospecto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-28 00:18:38 +00:00
12a7415330 chore(calls.rst): Se completan reportes faltantes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-27 16:53:34 -05:00
5700dfa12c chore: se adiciona entorno vivo de desarrollo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-27 13:32:15 -05:00
927c7ce178 chore: renombrar docker-compose.dev.yml 2023-07-27 11:27:26 -05:00
ca87254df8 chore: ajuste CI
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-27 10:02:38 -05:00
2cfa23a741 chore: ajuste CI
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-27 09:56:02 -05:00
b8a83f493a chore: ajuste CI
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-27 09:52:03 -05:00
99dc55adb2 chore: ajuste CI
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-27 09:48:31 -05:00
5122bd8320 chore: se arregla formato de documentación
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-27 01:18:25 +00:00
af79826489 chore: Se agrega documentación inicial de lógica de negocio
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-27 01:07:38 +00:00
fb8a7849d7 chore: ajuste CI
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-26 19:18:15 -05:00
c27de9cb9a chore: ajuste CI
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-26 19:14:26 -05:00
4c7b21e53d chore: ajuste CI 2023-07-26 19:13:28 -05:00
8518e78dba chore: ajuste CI 2023-07-26 19:08:25 -05:00
16acff8dbf chore: ajuste CI
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-26 18:59:28 -05:00
cd0a4054da chore: prueba notificacion ci 2023-07-26 18:57:41 -05:00
6ec3469b48 chore: ajuste detalle CI. 2023-07-26 18:56:41 -05:00
a5862cdca9 chore: ajuste detalle CI
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-26 18:46:40 -05:00
a96cec816e chore: formateo html detalle ci
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-26 18:39:40 -05:00
5684dcff47 chore: se detalla notificacion en CI
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-26 18:32:14 -05:00
627a8238c0 chore: se actualiza CONTRIBUIR.md
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-25 18:06:05 -05:00
5406852ef6 chore: se actualiza CONTRIBUIR.md
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-07-25 17:17:38 -05:00
75a3993f7c doc: actualizacion CONTRIBUIR.md 2023-07-25 17:10:20 -05:00
4fac22984c chore: se adiciona mecanismo para iterar rapidamente en desarrollo
ver CONTRIBUIR.md para detalles
2023-07-25 17:04:45 -05:00
aeb13eeec3 Add 'CONTRIBUIR.md' 2023-07-25 16:36:30 -05:00
8318a16885 update variable user in woodpecker
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-17 20:15:18 -05:00
2bf058ae0e add setting and notify to woodpecker
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-07-17 20:09:48 -05:00
5dc7d29b91 update file woodpecker
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-17 19:34:17 -05:00
64 changed files with 8759 additions and 21 deletions

2
.dev/Procfile Normal file
View File

@@ -0,0 +1,2 @@
trytond: while true; do trytond -d ${DB_NAME} --dev -v -c $SCRIPT_DIR/trytond.cfg; done
monitor: python3 $SCRIPT_DIR/dev.py

38
.dev/dev.py Normal file
View File

@@ -0,0 +1,38 @@
# script para refrescar cambios de xml del modulo de tryton
import sys
import os
import logging
import time
import inotify.adapters
logging.basicConfig(level=logging.INFO, stream=sys.stderr)
SRC = os.environ['SRC']
MODULE_NAME = os.environ['MODULE_NAME']
DB_NAME = os.environ['DB_NAME']
def _main():
i = inotify.adapters.Inotify()
i.add_watch(SRC)
logging.info("MONITOREANDO ARCHIVOS EN %s", SRC)
for event in i.event_gen(yield_nones=False):
(_, type_names, path, filename) = event
(_, ext) = os.path.splitext(filename)
if 'IN_CLOSE_WRITE' not in type_names:
continue
if ext in ['.py', '.xml', '.cfg']:
for _ in range(0, 10):
if os.system("trytond-admin -d {} -u {}".format(DB_NAME, MODULE_NAME)) != 0:
time.sleep(2)
logging.error("fallo trytond-admin")
else:
logging.info("ACTUALIZADO TRYTOND POR CAMBIO DE ARCHIVO %s", filename)
break
if __name__ == '__main__':
_main()

27
.dev/install_module.sh Normal file
View File

@@ -0,0 +1,27 @@
# este script fuerza que los cambios se vean reflejados
# directamente en trytond.
#
# variables exportadas:
# - module_name
[ ! -d "$SRC" ] && die "no se ubica ruta en SRC"
# dependencias minimas
pip3 install psycopg2 proteus inotify honcho
# instalar dependencias de tryton desde paquete
python3 setup.py install
# usamos enlace al paquete
python3 setup.py develop
# instalar modulo
trytond_modules_path=`pip3 show trytond | grep Location | sed -nr 's/Location: +//gp'`/trytond/modules
module_name=`cat "$SRC/setup.py" | fgrep -A 1 [trytond.modules] | sed 1d | cut -d '=' -f 1 | tr -d ' \n'`
[ ! -d "$trytond_modules_path" ] && die "fallo al ubicar ruta de modulos de trytond"
# se limpia para evitar enlaces recursivos
module_trytond_path="$trytond_modules_path/$module_name"
rm -f "$module_trytond_path"
ln -sf "$SRC" "$module_trytond_path"

31
.dev/run.sh Executable file
View File

@@ -0,0 +1,31 @@
#!/bin/bash
# script para iniciar entorno vivo
SCRIPT_DIR=$(dirname `realpath $0`)
die() {
echo $1
exit 1
}
[ ! -d "$SRC" ] && die "no se ubica ruta en SRC"
[ -z "$DB_NAME" ] && die "se requiere variable DB_NAME"
set -e
# instalar modulo
source ${SCRIPT_DIR}/install_module.sh
# inicializar base de datos
# https://docs.tryton.org/projects/server/en/latest/tutorial/module/setup_database.html
yes admin | trytond-admin -d ${DB_NAME} --all
# ejecutar servidor
export SCRIPT_DIR
export MODULE_NAME=$module_name
export DB_NAME
export SRC
honcho -d ${SCRIPT_DIR} start

3
.dev/trytond.cfg Normal file
View File

@@ -0,0 +1,3 @@
[web]
listen = 0.0.0.0:8000
root=/var/lib/trytond/www

View File

@@ -1,2 +1,3 @@
[flake8] [flake8]
ignore=E123,E124,E126,E128,E741,W503 ignore=E123,E124,E126,E128,E741,W503
exclude=.git,__pycache__,docs/source/conf.py,old,build,dist,.dev

5
.gitignore vendored
View File

@@ -5,6 +5,8 @@ __pycache__/
*$py.class *$py.class
*.bk *.bk
/.vscode
# C extensions # C extensions
*.so *.so
@@ -215,3 +217,6 @@ tags
pyvenv.cfg pyvenv.cfg
.venv .venv
pip-selfcheck.json pip-selfcheck.json
.tdd_cache
app

View File

@@ -1,12 +1,13 @@
#clone: #
# git: # variables que puedo usar? https://woodpecker-ci.org/docs/0.15/usage/environment#built-in-environment-variables
# image: woodpeckerci/plugin-git
# # necesario para el entorno docker-compose steps:
# # de lo contrario los agentes no pueden acceder al servidor gitea local style:
# network_mode: host image: python:3.9
# privileged: true commands:
- pip3 install flake8
- flake8
pipeline:
tests: tests:
image: python:3.9 image: python:3.9
environment: environment:
@@ -14,11 +15,42 @@ pipeline:
- DB_NAME=trytontest - DB_NAME=trytontest
- TRYTOND_DATABASE_URI=postgresql://tryton:tryton@postgres:5432/ - TRYTOND_DATABASE_URI=postgresql://tryton:tryton@postgres:5432/
commands: commands:
- cd party_ciiu
- pip3 install psycopg2 proteus - pip3 install psycopg2 proteus
- python3 setup.py install - python3 setup.py install
- python3 -m unittest - python3 -m unittest
notify-success:
image: gitea.onecluster.org/alnus/plugins/matrix:latest
settings:
home_server: https://matrix.org
roomid: "!oxZmsJwfvciTuLYIwg:matrix.org"
username:
from_secret: matrix_user
password:
from_secret: matrix_password
template: >
PikPukPak..
<p>${CI_COMMIT_AUTHOR}: <a href="${CI_BUILD_LINK}">Task ${CI_BUILD_NUMBER}</a> <font color="green"><b>TODO BIEN EN ${CI_REPO}</b></font></p>
<pre><a href="${CI_COMMIT_LINK}">${CI_COMMIT_MESSAGE}</a></pre>
when:
status: [ success ]
notify-failure:
image: plugins/matrix
settings:
home_server: https://matrix.org
roomid: "!oxZmsJwfvciTuLYIwg:matrix.org"
username:
from_secret: matrix_user
password:
from_secret: matrix_password
template: >
PikPukPak..
<p>${CI_COMMIT_AUTHOR}: <a href="${CI_BUILD_LINK}">Task ${CI_BUILD_NUMBER}</a> <font color="red"><b>!!!TODO MAL EN ${CI_REPO} </b></font></p>
<pre><a href="${CI_COMMIT_LINK}">${CI_COMMIT_MESSAGE}</a></pre>
when:
status: [ failure ]
services: services:
postgres: postgres:
image: postgres:12 image: postgres:12

62
CONTRIBUIR.md Normal file
View File

@@ -0,0 +1,62 @@
# CONTRIBUIR
`Para ver estado del repositorio actual hacer uso de la vpn.`
[![Build Status](http://170.16.238.10:8000/api/badges/OneTeam/trytondo-sale_opportunity_management/status.svg)]
### requerimientos tecnicos
* python >= 3.9
* docker >= 20
* docker-compose >= 2
* pre-commit >= 2
* git >= 2.30
* rake >= 13
### procedimiento en pruebas
1. iniciar entorno `rake init`
2. iterar con `rake tdd`
3. detener el entorno `rake down`
4. limpiar cache `git clean -xdf`
### entorno vivo de desarrollo
1. iniciar entorno `rake live:up`
2. conectar cliente tryton a `localhost:8000` usuario: `admin` y clave: `admin`
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`
### consideraciones
* evito trabajo innecesario
* evito generalizar, primero hago pruebas y luego elimino duplicidad
* evito redundancia, si lo puedo automatizar lo automatizo
* evito usar `git add .`
* a todo momento hago expresivo lo escrito, renombro, muevo o elimino
* en todo momento debo poder ejecutar las pruebas
* en todo momento debo poder ejecutar el programa
* en todo momento especulo, me ilustro y aprendo
### consideraciones en pruebas
* los escenarios (*.rst) se escriben en espanol
* el identificador de clase y metodo en (*.py) se escribe en espanol
### convencion commit
ante cada commit el mensaje se clasifica en:
* **feat(\<COMPONENTE\>)** una nueva funcionalidad accesible al usuario o sistema
* **fix(\<COMPONENTE\>)** correcion de una funcionalidad ya entregada
* **chore(\<COMPONENTE\>)** otros cambios que no impactan directamente al usuario, ejemplo renombramiento de archivo,clases,metodos,variables,carpetas,scripts, documentacion, recursos digitales, etc..
`COMPONENTE` nombre del directorio
ejemplos:
`git commit -m 'feat(<COMPONENTE>): venta de equipos opticos`
`git commit -m 'fix(<COMPONENTE>): se adiciona boton faltante`
`git commit -m 'chore(<COMPONENTE>): cambio de color en columna Producto`

16
Dockerfile Normal file
View File

@@ -0,0 +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
# trytond DB_CACHE requiere commandos `pg_dump` y `pg_restore`
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

View File

@@ -1 +1 @@
doc/index.rst ./tests/scenario_sale_opportunity_management.rst

115
Rakefile Normal file
View File

@@ -0,0 +1,115 @@
require 'yaml'
require 'digest'
WOODPECKER_YML='.woodpecker.yml'
DOCKER_COMPOSE='compose.test.yml'
desc 'iniciar entorno'
task :up do
compose('up', '--build', '-d')
end
desc 'poblar entorno'
task :init => [:up] do
pecker = YAML.load_file(WOODPECKER_YML)
['tests', 'style'].each do |steps|
pecker.dig('steps', steps, 'commands').grep(/install/).each do |cmd|
compose('exec', 'app.dev', cmd)
end
end
compose('exec', 'app.dev', 'bash .dev/install_module.sh')
end
desc 'terminal'
task :sh do
compose('exec', 'app.dev', 'bash')
end
desc 'iterar'
task :tdd do
refresh_cache
compose('exec', 'app.dev', 'flake8')
compose('exec', 'app.dev', 'python3 -m unittest')
end
desc 'detener entorno'
task :down do
compose('down')
end
desc 'entorno vivo'
namespace :live do
desc 'iniciar entorno'
task :up do
compose('up', '--build', '-d', compose: 'compose.yml')
end
desc 'terminal'
task :sh do
compose('exec', 'live.dev', 'bash')
end
desc 'resetear entorno'
task :reset do
compose('down', '-v', compose: 'compose.yml')
Rake::Task['live:up'].invoke
end
desc 'monitorear salida'
task :tail do
compose('logs', '-f', 'live.dev', compose: 'compose.yml')
end
desc 'detener entorno'
task :down do
compose('down', compose: 'compose.yml')
end
end
def compose(*arg, compose: DOCKER_COMPOSE)
sh "docker-compose -f #{compose} #{arg.join(' ')}"
end
def refresh_cache
# cuando se realizan cambios sobre los modelos
# que afectan las tablas es necesario limpiar el cache
# de trytond
changes = []
has_git_dir = File.directory?(File.join(File.dirname(__FILE__), '.git'))
try_git = `which git`.then { $? }.success? && has_git_dir
try_fossil = system('fossil status', err: :close, out: :close)
if try_fossil
changes = %x{fossil diff}.split("\n").grep(/^[-+]/)
elsif try_git
changes = %x{git diff}.split("\n").grep(/^[-+]/)
else
warn <<WARN
no se detecta repositorio en control de versiones, debe manualmente
limpiar el cache si ahi cambios en el esquema de los modelos.
Eliminando en el contenedor los archivo /tmp/*.dump
WARN
end
refresh_trytond_cache(changes)
end
def refresh_trytond_cache(changes)
num = changes.grep(/fields/).length
hash = Digest::MD5.hexdigest(changes.flatten.join(''))
# touch
File.open('.tdd_cache', 'a+').close
File.open('.tdd_cache', 'r+') do |cache|
tdd_cache = cache.read()
if num > 0 && (tdd_cache != hash)
compose('exec', 'app.dev', 'bash -c "rm -f /tmp/*.dump"')
cache.seek(0); cache.write(hash)
end
end
end

View File

@@ -1,12 +1,40 @@
from trytond.pool import Pool from trytond.pool import Pool
from . import prospect
from . import prospect_trace
from . import call
from . import pending_call
from . import user
from .locations import city
from .locations import department
__all__ = ['register'] __all__ = ['register']
def register(): def register():
Pool.register( Pool.register(
user.User,
pending_call.PendingCall,
call.Call,
call.PendingTask,
department.Department,
city.City,
prospect.ContactMethod,
prospect.Prospect,
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')

88
call.py Normal file
View File

@@ -0,0 +1,88 @@
from trytond.model import ModelSQL, ModelView, fields
from trytond.pyson import Eval
from datetime import date
from .selections.interest import Interest
from .selections.call_types import CallTypes
from .selections.call_results import CallResults
class Call(ModelSQL, ModelView):
'Llamada'
__name__ = 'sale.call'
_order_name = 'date'
_states = {'readonly': True}
date = fields.Date('Date', states=_states)
description = fields.Text('Description', strip=True)
prospect_trace = fields.Many2One(
'sale.prospect_trace', 'Prospect trace', required=True, states=_states)
interest = fields.Selection(
Interest.get_interest_levels(), 'Interest', required=True)
call_type = fields.Selection(
CallTypes.get_call_types(), 'Call type', states=_states)
call_result = fields.Selection(
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
def default_date(cls):
return date.today()
class PendingTask(ModelSQL, ModelView):
'Tarea a realizar a un seguimiento de prospecto'
__name__ = "sale.pending_task"
description = fields.Text(
'Description', required=True,
states={
'readonly': Eval('state') == 'done'
})
state = fields.Selection(
[('pending', 'Pending'),
('done', 'Done')],
'State')
prospect_trace = fields.Many2One(
'sale.prospect_trace', 'Prospect trace',
required=True, readonly=True)
@classmethod
def __setup__(cls):
super(PendingTask, cls).__setup__()
cls._buttons.update({
'close_task': {
'invisible': Eval('state') == 'done'
}
})
@classmethod
@ModelView.button
def close_task(cls, tasks):
for task in tasks:
task.state = 'done'
task.save()
@classmethod
def default_state(cls):
return 'pending'

135
call.xml Normal file
View File

@@ -0,0 +1,135 @@
<?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="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">
<field name="name">Calls</field>
<field name="res_model">sale.call</field>
</record>
<record model="ir.ui.view" id="call_view_tree">
<field name="model">sale.call</field>
<field name="type">tree</field>
<field name="name">call_tree</field>
</record>
<record model="ir.ui.view" id="call_view_form">
<field name="model">sale.call</field>
<field name="type">form</field>
<field name="name">call_form</field>
</record>
<record model="ir.action.act_window.view" id="act_call_tree_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="call_view_tree"/>
<field name="act_window" ref="act_call_tree"/>
</record>
<record model="ir.action.act_window.view" id="act_call_form_view1">
<field name="sequence" eval="20"/>
<field name="view" ref="call_view_form"/>
<field name="act_window" ref="act_call_tree"/>
</record>
<menuitem
name="Calls"
sequence="10"
id="menu_calls"
icon="tryton-phone"/>
<menuitem
parent="menu_calls"
sequence="30"
id="menu_calls_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>
</tryton>

14
compose.test.yml Normal file
View File

@@ -0,0 +1,14 @@
version: '3.9'
services:
app.dev:
build:
context: .
environment:
SRC: /app
DB_CACHE: /tmp
DB_NAME: ":memory:"
TRYTOND_DATABASE_URI: sqlite://
command: sleep 10h
volumes:
- .:/app
working_dir: /app

23
compose.yml Normal file
View File

@@ -0,0 +1,23 @@
version: '3.9'
services:
db.dev:
image: postgres:12
environment:
- POSTGRES_USER=tryton
- POSTGRES_PASSWORD=tryton
- POSTGRES_DB=tryton
live.dev:
build:
context: .
depends_on:
- db.dev
command: bash .dev/run.sh
environment:
- DB_NAME=tryton
- SRC=/app
- TRYTOND_DATABASE_URI=postgresql://tryton:tryton@db.dev:5432/
volumes:
- .:/app
ports:
- "8000:8000"
working_dir: /app

35
icons.xml Normal file
View 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
View 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

View 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

View 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
View 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
View 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
View 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
View 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
View 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"

0
locations/__init__.py Normal file
View File

5576
locations/cities.xml Normal file

File diff suppressed because it is too large Load Diff

13
locations/city.py Normal file
View File

@@ -0,0 +1,13 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.model import ModelSQL, ModelView, fields
class City(ModelSQL, ModelView):
'Ciudad'
__name__ = 'sale.city'
_rec_name = 'name'
name = fields.Char('City')
code = fields.Char('Code')
parent = fields.Many2One('sale.department', 'Departamento')

11
locations/department.py Normal file
View File

@@ -0,0 +1,11 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.model import ModelSQL, ModelView, fields
class Department(ModelSQL, ModelView):
'Departamento'
__name__ = 'sale.department'
name = fields.Char('Department')
code = fields.Char('Code')

137
locations/departments.xml Normal file
View File

@@ -0,0 +1,137 @@
<?xml version="1.0"?>
<tryton>
<data>
<record model="sale.department" id="CO-91">
<field name="name">Amazonas</field>
<field name="code">CO-91</field>
</record>
<record model="sale.department" id="CO-05">
<field name="name">Antioquia</field>
<field name="code">CO-05</field>
</record>
<record model="sale.department" id="CO-81">
<field name="name">Arauca</field>
<field name="code">CO-81</field>
</record>
<record model="sale.department" id="CO-08">
<field name="name">Atlántico</field>
<field name="code">CO-08</field>
</record>
<record model="sale.department" id="CO-13">
<field name="name">Bolívar</field>
<field name="code">CO-13</field>
</record>
<record model="sale.department" id="CO-15">
<field name="name">Boyacá</field>
<field name="code">CO-15</field>
</record>
<record model="sale.department" id="CO-17">
<field name="name">Caldas</field>
<field name="code">CO-17</field>
</record>
<record model="sale.department" id="CO-18">
<field name="name">Caquetá</field>
<field name="code">CO-18</field>
</record>
<record model="sale.department" id="CO-85">
<field name="name">Casanare</field>
<field name="code">CO-85</field>
</record>
<record model="sale.department" id="CO-19">
<field name="name">Cauca</field>
<field name="code">CO-19</field>
</record>
<record model="sale.department" id="CO-20">
<field name="name">Cesar</field>
<field name="code">CO-20</field>
</record>
<record model="sale.department" id="CO-27">
<field name="name">Chocó</field>
<field name="code">CO-27</field>
</record>
<record model="sale.department" id="CO-23">
<field name="name">Córdoba</field>
<field name="code">CO-23</field>
</record>
<record model="sale.department" id="CO-25">
<field name="name">Cundinamarca</field>
<field name="code">CO-25</field>
</record>
<record model="sale.department" id="CO-11">
<field name="name">Bogotá</field>
<field name="code">CO-11</field>
</record>
<record model="sale.department" id="CO-94">
<field name="name">Guainía</field>
<field name="code">CO-94</field>
</record>
<record model="sale.department" id="CO-95">
<field name="name">Guaviare</field>
<field name="code">CO-95</field>
</record>
<record model="sale.department" id="CO-41">
<field name="name">Huila</field>
<field name="code">CO-41</field>
</record>
<record model="sale.department" id="CO-44">
<field name="name">La Guajira</field>
<field name="code">CO-44</field>
</record>
<record model="sale.department" id="CO-47">
<field name="name">Magdalena</field>
<field name="code">CO-47</field>
</record>
<record model="sale.department" id="CO-50">
<field name="name">Meta</field>
<field name="code">CO-50</field>
</record>
<record model="sale.department" id="CO-52">
<field name="name">Nariño</field>
<field name="code">CO-52</field>
</record>
<record model="sale.department" id="CO-54">
<field name="name">Norte de Santander</field>
<field name="code">CO-54</field>
</record>
<record model="sale.department" id="CO-86">
<field name="name">Putumayo</field>
<field name="code">CO-86</field>
</record>
<record model="sale.department" id="CO-63">
<field name="name">Quindío</field>
<field name="code">CO-63</field>
</record>
<record model="sale.department" id="CO-66">
<field name="name">Risaralda</field>
<field name="code">CO-66</field>
</record>
<record model="sale.department" id="CO-88">
<field name="name">San Andrés y Providencia</field>
<field name="code">CO-88</field>
</record>
<record model="sale.department" id="CO-68">
<field name="name">Santander</field>
<field name="code">CO-68</field>
</record>
<record model="sale.department" id="CO-70">
<field name="name">Sucre</field>
<field name="code">CO-70</field>
</record>
<record model="sale.department" id="CO-73">
<field name="name">Tolima</field>
<field name="code">CO-73</field>
</record>
<record model="sale.department" id="CO-76">
<field name="name">Valle del Cauca</field>
<field name="code">CO-76</field>
</record>
<record model="sale.department" id="CO-97">
<field name="name">Vaupés</field>
<field name="code">CO-97</field>
</record>
<record model="sale.department" id="CO-99">
<field name="name">Vichada</field>
<field name="code">CO-99</field>
</record>
</data>
</tryton>

14
pending_call.py Normal file
View File

@@ -0,0 +1,14 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.model import ModelSQL, ModelView, fields
class PendingCall(ModelSQL, ModelView):
'Llamada pendiente a un prospecto'
__name__ = "sale.pending_call"
date = fields.DateTime('Date', required=True)
def get_rec_name(self, name):
if self.date:
return str(self.date)

265
prospect.py Normal file
View File

@@ -0,0 +1,265 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.wizard import Wizard, StateView, Button, StateTransition
from trytond.model import ModelSQL, ModelView, fields, DeactivableMixin
from trytond.pyson import Eval, If
from trytond.pool import Pool
class Prospect(ModelSQL, ModelView, DeactivableMixin):
'Prospecto'
__name__ = 'sale.prospect'
_rec_name = 'name'
name = fields.Char('Name', required=True)
business_unit = fields.Selection(
[('brigade', 'Brigade'),
('optics', 'Optics'),
('equipment', 'Equipment')],
'Business unit', required=True
)
contact_methods = fields.One2Many(
'prospect.contact_method',
'prospect', 'Contact methods', required=True)
department = fields.Many2One('sale.department', 'Department')
city = fields.Many2One('sale.city', 'City',
domain=[If(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')
def on_change_city(self):
if self.city:
self.department = self.city.parent
class ContactMethod(ModelSQL, ModelView):
'Mecanismo de contacto'
__name__ = 'prospect.contact_method'
contact_type = fields.Selection([
('phone', 'Phone'),
('mobile', 'Mobile'),
('mail', 'Mail')
], 'Contact type', required=True)
value = fields.Char('Value', required=True)
name = fields.Char('Name')
job = fields.Char('Job')
prospect = fields.Many2One('sale.prospect', 'Prospect', required=True)
prospect_trace = fields.Many2One(
'sale.prospect_trace', 'Prospect Trace', required=False)
@classmethod
def default_contact_type(cls):
return 'mobile'
def get_rec_name(self, name):
fields = [self.name, self.job, self.value]
contact_rec_name = ''
for field in fields:
if field:
contact_rec_name += ' [' + str(field) + '] '
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'

185
prospect.xml Normal file
View File

@@ -0,0 +1,185 @@
<?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="res.group" id="group_prospect">
<field name="name">Prospects</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 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">
<field name="model">sale.prospect</field>
<field name="type">tree</field>
<field name="name">prospect_tree</field>
</record>
<record model="ir.ui.view" id="prospect_view_form">
<field name="model">sale.prospect</field>
<field name="type">form</field>
<field name="name">prospect_form</field>
</record>
<record model="ir.action.act_window.view" id="act_prospect_tree_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="prospect_view_tree"/>
<field name="act_window" ref="act_prospect_tree"/>
</record>
<record model="ir.action.act_window.view" id="act_prospect_form_view1">
<field name="sequence" eval="20"/>
<field name="view" ref="prospect_view_form"/>
<field name="act_window" ref="act_prospect_tree"/>
</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
parent="menu_calls"
sequence="10"
id="menu_prospects_tree"
icon="tryton-party"
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">
<field name="name">Contact method</field>
<field name="res_model">prospect.contact_method</field>
</record>
<record model="ir.ui.view" id="contact_method_view_tree">
<field name="model">prospect.contact_method</field>
<field name="type">tree</field>
<field name="name">contact_method_tree</field>
</record>
<record model="ir.ui.view" id="contact_method_view_form">
<field name="model">prospect.contact_method</field>
<field name="type">form</field>
<field name="name">contact_method_form</field>
</record>
<record model="ir.action.act_window.view" id="act_contact_method_tree_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="contact_method_view_tree"/>
<field name="act_window" ref="act_contact_method_tree"/>
</record>
<record model="ir.action.act_window.view" id="act_contact_method_form_view1">
<field name="sequence" eval="20"/>
<field name="view" ref="contact_method_view_form"/>
<field name="act_window" ref="act_contact_method_tree"/>
</record>
<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>

278
prospect_trace.py Normal file
View File

@@ -0,0 +1,278 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.wizard import Wizard, StateView, Button, StateTransition
from trytond.model import ModelSQL, ModelView, fields
from trytond.pool import Pool
from trytond.pyson import Eval
from .selections.call_types import CallTypes
from .selections.interest import Interest
from datetime import datetime
class ProspectTrace(ModelSQL, ModelView):
'Seguimiento de un prospecto'
__name__ = 'sale.prospect_trace'
_states = {'readonly': True}
prospect = fields.Many2One(
'sale.prospect', 'Prospect', required=True, states=_states)
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(
Interest.get_interest_levels(), 'Current interest',
states=_states)
state = fields.Selection([
('unassigned', 'Unassigned'),
('open', 'Open'),
('with_pending_calls', 'With pending calls'),
('closed', 'Closed')
], '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
def default_state(cls):
return 'open'
@classmethod
@ModelView.button_action(
'sale_opportunity_management.schedule_call_wizard')
def wizard_schedule(cls, prospect_traces):
pass
@classmethod
@ModelView.button_action(
'sale_opportunity_management.make_call_wizard')
def wizard_make_call(cls, prospect_traces):
pass
@classmethod
@ModelView.button
def close_trace(cls, prospect_traces):
for prospect_trace in prospect_traces:
prospect_trace.state = 'closed'
prospect_trace.save()
@classmethod
@ModelView.button
def reopen_trace(cls, prospect_traces):
for prospect_trace in prospect_traces:
prospect_trace.state = 'open'
prospect_trace.save()
def get_rec_name(self, name):
if self.prospect:
return '[' + str(self.id) + '] ' + self.prospect.name
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()
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
if call.interest == '0':
call.call_result = 'missed_call'
else:
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()
prospect_trace.current_interest = call.interest
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()

158
prospect_trace.xml Normal file
View File

@@ -0,0 +1,158 @@
<?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="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">
<field name="model">sale.prospect_trace</field>
<field name="type">tree</field>
<field name="name">prospect_trace_tree</field>
</record>
<record model="ir.ui.view" id="prospect_trace_view_form">
<field name="model">sale.prospect_trace</field>
<field name="type">form</field>
<field name="name">prospect_trace_form</field>
</record>
<record model="ir.action.act_window" id="act_prospect_trace_tree">
<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>
</record>
<record model="ir.action.act_window.view" id="act_prospect_trace_tree_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="prospect_trace_view_tree"/>
<field name="act_window" ref="act_prospect_trace_tree"/>
</record>
<record model="ir.action.act_window.view" id="act_prospect_trace_form_view1">
<field name="sequence" eval="20"/>
<field name="view" ref="prospect_trace_view_form"/>
<field name="act_window" ref="act_prospect_trace_tree"/>
</record>
<record model="ir.action.act_window.domain" id="act_prospect_trace_domain_open">
<field name="name">Open</field>
<field name="sequence" eval="10"/>
<field name="domain" eval="[('state', '=', 'open')]" 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_with_pending_calls">
<field name="name">With pending calls</field>
<field name="sequence" eval="20"/>
<field name="domain" eval="[('state', '=', 'with_pending_calls')]" 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_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">
<field name="name">All</field>
<field name="sequence" eval="9999"/>
<field name="domain"></field>
<field name="count" eval="True"/>
<field name="act_window" ref="act_prospect_trace_tree"/>
</record>
<menuitem
parent="menu_calls"
sequence="20"
id="menu_prospect_trace_tree"
icon="tryton-target"
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>
</tryton>

0
selections/__init__.py Normal file
View File

View File

@@ -0,0 +1,9 @@
class CallResults():
@staticmethod
def get_call_results():
call_results = [
('missed_call', 'Missed call'),
('answered_call', 'Answered call'),
]
return call_results

9
selections/call_types.py Normal file
View File

@@ -0,0 +1,9 @@
class CallTypes():
@staticmethod
def get_call_types():
call_types = [
('first_call', 'First call'),
('followup_call', 'Follow up call'),
]
return call_types

13
selections/interest.py Normal file
View File

@@ -0,0 +1,13 @@
class Interest():
@staticmethod
def get_interest_levels():
interest_levels = [
('', None),
('0', '0 - Not answered'),
('1', '1 - Complete disinterest'),
('2', '2 - Middle interest'),
('3', '3 - High interest'),
('4', '4 - Closed sale')
]
return interest_levels

View File

@@ -2,11 +2,408 @@
Sale Opportunity Management Scenario Sale Opportunity Management Scenario
==================================== ====================================
Imports:: 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, datetime
>>> import xml.etree.ElementTree as ET
Activate modules:: Activate modules::
>>> config = activate_modules('sale_opportunity_management') >>> config = activate_modules('sale_opportunity_management')
**Cada sección contiene:**
1. Encabezado, historia de usuario
2. Elementos textuales de propuesta final
3. Descripción detallada
4. Escenarios de pruebas
(Entre [""] estarán los elementos textuales que se acordaron con el cliente en la propuesta final)
----------------------
Registro de prospectos
----------------------
**Como administrador quiero registrar un prospecto para lugo poder hacerle un seguimiento**
["Crear un Formulario de registro rápido de prospecto, Nombres, Métodos de contacto,Direcciones"]
El administrador deberá poder registrar los contactos de diferentes prospectos, junto con su información básica:
* Razón social (Nombre de la empresa)
* Ciudad
* Metodos de contacto
* Tercero relacionado
* Nombre
* Cargo
Crear prospecto::
>>> Prospect = Model.get('sale.prospect')
>>> prospect1 = Prospect()
>>> 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')
>>> medellin, = City.find([('code', '=', 'CO-05001')])
>>> prospect1.city = medellin
>>> prospect1.business_unit = 'brigade'
>>> prospect1.save()
Verificar estado final de creación de prospecto::
>>> prospect1.contact_methods
[proteus.Model.get('prospect.contact_method')(1), proteus.Model.get('prospect.contact_method')(2), proteus.Model.get('prospect.contact_method')(3)]
>>> prospect1.contact_methods[0].contact_type
'mobile'
>>> prospect1.contact_methods[0].job
'Gerente R.H'
>>> prospect1.contact_methods[2].name
'Peralto'
>>> prospect1.contact_methods[2].value
'peralto@guchitos.org'
>>> prospect1.city.code
'CO-05001'
>>> prospect1.department.code
'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
------------------------------------
**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**
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
-----------------------
**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 programar una llamada para luego obtener un reporte de trabajo pendiente**
["Crear Campo para registro de la fecha de la llamada"]
["Crear campo de evento de la llamada con primera llamada, segunda llamada"]
["Crear Campo llamado potencial en el que se asigne un nivel de interés por parte del prospecto identificado en la llamada realizada"]
["Crear campo para asignar descripción ó notas importantes evidenciadas en la llamada"]
El seguimiento de llamadas consiste en realizar llamadas a diferentes contactos con el fin de realizar ofertas de servicios o productos, los cuales pertenecen principalmente a 3 unidades de negocio:
* Optica
* Brigada
* Equipos
Luego de realizar estas llamadas, el operador dejará registro sobre aspectos como el interés del prospecto, descripción u observaciones importantes, tipificación del prospecto...
Cada conjunto de **llamadas** a un prospecto, se llamará **seguimiento de prospecto**, por lo que este podrá tener varias llamadas, y una llamada solo podrá pertenecer a un seguimiento de prospecto. Ej:
Seguimiento de prospecto 1
* llamada 1
* llamada 2
Seguimiento de prospecto 2
* llamada 1
* llamada 2
* llamada 3
**Seguimiento de prospecto**:
* Razon social del prospecto (Tercero)
* Metodo de contacto del prospecto
* Unidad de negocio
* Estado (Abierto o cerrado)
* Llamadas
**LLamada**:
* Fecha
* Descripion o observaciones
* Nivel de interés (0-3)
* 0 - No contestó
* 1 - total desinterés
* 2 - Interés intermedio, brindar mas información
* 3 - Interés alto, generar venta
* Seguimiento de prospecto al que pertence
Verificar creación de seguimiento de prospecto::
>>> ProspectTrace = Model.get('sale.prospect_trace')
>>> prospect_trace, = ProspectTrace.find([('prospect', '=', prospect1)])
>>> prospect_trace.prospect.name
'guchito S.A.S'
>>> prospect_trace.prospect_business_unit
'brigade'
>>> prospect_trace.prospect_city.name
'Medellín'
>>> prospect_trace.prospect_assigned_operator.name
'Administrator'
>>> prospect_trace.prospect_contacts
[proteus.Model.get('prospect.contact_method')(1), proteus.Model.get('prospect.contact_method')(2), proteus.Model.get('prospect.contact_method')(3)]
Agregar un método de contacto desde el seguimiento de prospecto::
>>> contact_method_ = prospect_trace.prospect_contacts.new(value='31231231212', name='Carlos', job='Supervisor')
>>> contact_method_.prospect
proteus.Model.get('sale.prospect')(1)
Crear llamadas a un seguimiento de prospecto::
>>> make_call = Wizard('sale.prospect_trace.make_call', [prospect_trace])
>>> 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
'missed_call'
>>> prospect_trace.calls[0].call_type
'first_call'
>>> prospect_trace.calls[0].date == date.today()
True
>>> prospect_trace.calls[0].call_business_unit
'brigade'
>>> prospect_trace.calls[0].operator_who_called.name
'Administrator'
>>> prospect_trace.calls[1].call_result
'answered_call'
>>> prospect_trace.calls[1].call_type
'followup_call'
>>> prospect_trace.calls
[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
'3'
>>> prospect_trace.state
'with_pending_calls'
Programar una próxima llamada pendiente al seguimiento de prospecto::
>>> schedule = Wizard('sale.prospect_trace.schedule', [prospect_trace])
>>> schedule.form.date_time = datetime(2023, 8, 14, 15, 30, 30)
>>> schedule.execute('schedule')
>>> prospect_trace.pending_call.date
datetime.datetime(2023, 8, 14, 15, 30, 30)
>>> prospect_trace.state
'with_pending_calls'
Crear una llamada agendada previamente::
>>> 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.state
'open'
Hacer llamada y programar tarea::
>>> make_call = Wizard('sale.prospect_trace.make_call', [prospect_trace])
>>> make_call.form.description = 'Prospect told me to send him an email'
>>> make_call.form.interest = '3'
>>> 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')
>>> Task = Model.get('sale.pending_task')
>>> task, = Task.find([('description', '=', 'I have to send a mail to prospect offering him this services...')])
>>> task
proteus.Model.get('sale.pending_task')(1)
>>> task.state
'pending'
>>> task.click('close_task')
>>> task.state
'done'
Hacer llamada y cerrar venta (Seguimiento de prospecto)::
>>> make_call = Wizard('sale.prospect_trace.make_call', [prospect_trace])
>>> make_call.form.description = 'Closed sale'
>>> 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
--------
["Crear un reporte en el que evidencie por operario y consolidado"]
["Cantidad de llamadas realizadas en un período de tiempo"]
["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)"]
* Reporte de llamadas realizadas en un periodo de tiempo (Análisis de operarios):
* Nivel de interés
* Unidad de negocio
* Observaciones
* Operario
* Reporte de seguimiento a prospecto (Análisis de prospecto):
* Interés durante distintas etapas del seguimiento
* Reporte de Llamadas a realizar (Analisis de trabajo pendiente):
* Llamadas pendientes
* Seguimientos a prospectos abiertos
* Reporte de seguimientos sin asignar - asignados:
* Seguimientos a prospectos pendientes por asignar a operador
* Reporte de prospectos potenciales
* llamadas con un nivel de interés alto
* Seguimiento de prospecto al que pertenecen las llamadas

View File

@@ -1,10 +0,0 @@
from trytond.tests.test_tryton import ModuleTestCase
class SaleOpportunityManagementTestCase(ModuleTestCase):
"Test Sale Opportunity Management module"
module = 'sale_opportunity_management'
del ModuleTestCase

View File

@@ -0,0 +1,58 @@
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
from trytond.pool import Pool
class RequiredValuesTestCase(ModuleTestCase):
"Test Sale Opportunity Management module"
module = 'sale_opportunity_management'
@with_transaction()
def test_prospect_en_ProspectTrace_es_obligatorio(self):
pool = Pool()
ProspectTrace = pool.get('sale.prospect_trace')
self.assertTrue(ProspectTrace.prospect.required)
@with_transaction()
def test_contact_method_en_Prospect_es_obligatorio(self):
pool = Pool()
Prospect = pool.get('sale.prospect')
self.assertTrue(Prospect.contact_methods.required)
@with_transaction()
def test_name_en_Prospect_es_obligatorio(self):
pool = Pool()
Prospect = pool.get('sale.prospect')
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()
def test_value_en_ContactMethod_es_obligatorio(self):
pool = Pool()
ContactMethod = pool.get('prospect.contact_method')
self.assertTrue(ContactMethod.value.required)
@with_transaction()
def test_contact_type_en_ContactMethod_es_obligatorio(self):
pool = Pool()
ContactMethod = pool.get('prospect.contact_method')
self.assertTrue(ContactMethod.contact_type.required)
@with_transaction()
def test_prospect_en_ContactMethod_es_obligatorio(self):
pool = Pool()
ContactMethod = pool.get('prospect.contact_method')
self.assertTrue(ContactMethod.prospect.required)
@with_transaction()
def test_date_en_PendingCall_es_obligatorio(self):
pool = Pool()
PendingCall = pool.get('sale.pending_call')
self.assertTrue(PendingCall.date.required)
del ModuleTestCase

View File

@@ -1,5 +1,13 @@
[tryton] [tryton]
version=6.8.0 version=7.0.0
depends: depends:
ir ir
res
xml: xml:
icons.xml
user.xml
call.xml
prospect_trace.xml
prospect.xml
./locations/departments.xml
./locations/cities.xml

17
user.py Normal file
View 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
View 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>

View 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>

23
view/call_form.xml Normal file
View File

@@ -0,0 +1,23 @@
<?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="prospect_trace"/>
<field name="prospect_trace" colspan="5"/>
<label name="interest"/>
<field name="interest"/>
<label name="date"/>
<field name="date" xexpand="1"/>
<newline/>
<label name="description"/>
<field name="description" colspan="3"/>
<newline/>
<label name="call_type"/>
<field name="call_type"/>
<label name="call_result"/>
<field name="call_result"/>
<label name="call_business_unit"/>
<field name="call_business_unit"/>
</form>

13
view/call_tree.xml Normal file
View File

@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tree>
<field name="date" expand="1"/>
<field name="interest" expand="1"/>
<field name="call_type" expand="1"/>
<field name="call_result" expand="1"/>
<field name="prospect_trace" expand="1"/>
<field name="description" expand="1"/>
<field name="call_business_unit" expand="1"/>
<field name="operator_who_called" expand="1"/>
</tree>

View File

@@ -0,0 +1,14 @@
<?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="contact_type"/>
<field name="contact_type"/>
<label name="value"/>
<field name="value"/>
<label name="name"/>
<field name="name"/>
<label name="job"/>
<field name="job"/>
<field name="prospect" invisible="1"/>
</form>

View 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. -->
<tree editable="1">
<field name="contact_type" expand="1"/>
<field name="value" expand="1"/>
<field name="name" expand="1"/>
<field name="job" expand="1"/>
</tree>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form>
<label name="datetime"/>
<field name="datetime"/>
</form>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form>
<label name="task_description"/>
<field name="task_description"/>
</form>

View 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>

View 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>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tree>
<field name="prospect_trace" expand="1"/>
<field name="description" expand="1"/>
<button name="close_task"/>
</tree>

45
view/prospect_form.xml Normal file
View File

@@ -0,0 +1,45 @@
<?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">
<group col="4" id="prospect_data">
<label name="name"/>
<field name="name"/>
<label name="business_unit"/>
<field name="business_unit"/>
<newline/>
<label name="department"/>
<field name="department"/>
<label name="city"/>
<field name="city"/>
</group>
<newline/>
<notebook colspan="6">
<page string="Contact methods" id="contact_methods">
<field name="contact_methods" colspan="2"/>
</page>
<page string="About prospect" id="contact_methods">
<label name="rating"/>
<field name="rating"/>
<newline/>
<label name="comments"/>
<field name="comments"/>
</page>
</notebook>
<newline/>
<group col="6" colspan="5" id="footer" yalign="0">
<label name="assigned_operator"/>
<field name="assigned_operator"/>
<label name="state"/>
<field name="state"/>
<group col="-1" colspan="1" id="checkboxes">
<label name="active"/>
<field name="active" xexpand="0" width="25"/>
</group>
</group>
</form>

View File

@@ -0,0 +1,38 @@
<?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" colspan="5" id="header" yalign="0">
<label name="prospect"/>
<field name="prospect"/>
<label name="prospect_business_unit"/>
<field name="prospect_business_unit"/>
<label name="prospect_city"/>
<field name="prospect_city"/>
</group>
<group col="6" colspan="5" id="trace_data" yalign="0">
<label name="current_interest"/>
<field name="current_interest"/>
</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/>
<field name="prospect_contacts" colspan="6"/>
<label name="pending_call"/>
<field name="pending_call"/>
<label 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>

View 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. -->
<tree>
<field name="prospect" expand="1"/>
<field name="prospect_business_unit" expand="1"/>
<field name="prospect_city" expand="1"/>
<field name="current_interest" expand="1"/>
<field name="calls" expand="1"/>
<field name="pending_call" expand="1"/>
<field name="prospect_assigned_operator" expand="1"/>
</tree>

11
view/prospect_tree.xml Normal file
View File

@@ -0,0 +1,11 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tree>
<field name="name" expand="1"/>
<field name="business_unit" expand="1"/>
<field name="department" expand="1"/>
<field name="city" expand="1"/>
<field name="assigned_operator" expand="1"/>
<field name="rating" expand="1"/>
</tree>

View 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>

View 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. -->
<form>
<label name="prospect"/>
<field name="prospect"/>
<label name="new_operator"/>
<field name="new_operator"/>
</form>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form>
<label name="date_time"/>
<field name="date_time"/>
</form>

9
view/user_form.xml Normal file
View 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>