Refactor de estado interno
Este documento resume el análisis e implementación del refactor al actual estado interno, partiendo de la versión v3.07, en pos de representar las distintas perspectivas que existen en el Sistema, al momento de evaluar el estado de un Envio.
Las perspectivas que se identifican, son las que hoy en dia se usan, basadas en la “visibilidad” de los avisos de estado (StepState), por lo tanto son las que se enumeran a continuación:
- Cliente (Client)
- Operador (Carrier)
- iFlow (Backoffice): Indistintamente de la visibilidad configurada.
Gestión
En este apartado se analiza el uso del Estado interno y de las distintas perspectivas, en los flujos del Sistema.
Estado Interno (shippingState)
Este representa el “ultimo estado”, dentro del ciclo satisfactorio de un envio (Registrado -> Procesado,…) y resulta de intereses en varios de los flujos del Sistema, en especial de los procesos asincrónicos, para tomar determinadas decisiones en la lógica de negocio.
Presenta la particularidad que su valor, se ve afectado por Avisos de Estados (StepStates) o bien estadíos de los procesos: Por ejemplo en el flujo de comunicación con VKM, puede adoptar los valores Procesado, Erroneo o Notificado.
Por otro lado, y no menor, hoy en día presenta varias “falencias” como:
- No considera flujos mas recientes como ordenes Pendientes (Presis, pre-pago) o Devolución
- Existen flujos que cambian su estado sin que haya StepStates asociados ( Comunicación con VKM, como se expuso anteriormente)
- Modificación y/o Eliminación de Avisos de estados, no impactan en el.
ChangeState
Este método define el criterio por el cual se setea el valor del estado interno, tras realizar la siguiente evaluación a partir de un nuevo StepState:
- Si el estado es uno del “subconjunto que aplican”, y
- Verifica que sea el último, considerando la transición ideal (Registrado > Procesado > Planificado > Retirado…).
De esta forma evita pisar el valor con un estado “previo”.
Si el StepState cumple con los requisitos previos, actualizará el estado interno, ademas de las fechas del “ciclo satisfactorio”.
Helpers
Existen numerosos “helpers” para evaluar si el valor del estado interno, corresponde con uno en particular. A continuación se enumeran:
- isRegistered([include_reverse_logistic_: true = true]): bool
- isProcessed(): bool
- isPlanned(): bool
- isPickedup([include_reverse_logistic_: true = true]): bool
- isNotified(): bool
- isDischarged([include_reverse_logistic_: true = true]): bool
- isError(): bool
- isReady(): bool
- isDispatched([include_reverse_logistic_: true = true]): bool
- isDelivered([include_reverse_logistic_: true = true]): bool
- isNotDelivered([include_reverse_logistic_: true = true]): bool
- isCancelled(): bool
- isPaymentPending(): bool
- isAccreditationPending(): bool
- isReturnRegistered(): bool
- isInReturnProcess(): bool
Este tipo de métodos, son usados en varias partes del sistema para tomar determinaciones, en determinados flujos, en particular en algunos flujos asincronicos (encolamiento,etc..).
Queries
Existen un puñado de consultas que consumen el estado interno. Al identificarlas, consisten en tan solo 3 metodos dentro del ShippingRepository:
- findByRegistered:
- findByNotificationPending:
- externalFindByRequest:
Excepto el último, los restantes no tienen un uso activo actualmente: excepto que se invoque comandos en desuso por ejemplo.
Perspectivas
Estas representan los estados (StepStates) visibles por los distintos actores del Sistema. Como se mencionó en la introducción se distinguen 3 (iFlow, Cliente y Operador).
Resulta de interes, resolver en los principales flujos del sistema cuales son los estados visibles por actor en particular, y por sobre su último estado, dado que con esté se aplican o no politicas de negocio, o bien esta información esta comprometida en las principales salidas del sistema y/o estrategias de optimizacion (Indices).
Hoy en día existe un costo muy alto para el calculo de las perspectivas, mas cuando se trata de determinar el último estado. E incluso, debido a factores externos, puede ser que difiera el valor del ultimo estado en las salidas del Sistema.
Propuesta
Se propone un refactor que cumpla con los siguientes objetivos:
- El estado interno -> Represente solo información de interés para los procesos (OPCIONAL)
- Desnormalización de los StepStates -> Para considerar las perspectiva, reducir el costo del cálculo y/o aplicar una lógica de negocio para determinar cual se considerará “último” estado. Adicionalmente se considera la posibilidad de hacer esto gestionable (bajo estrictos permisos) para que un usuario especializado de BackOffice pueda incluso “corregir” manualmente algún valor (basado en StepStates de ese Shipping).
- Reducción de tabla de Shipping -> Para reducción de recursos ante listados.
#1 Estado interno (Opcional)
#2 Desnormalización de StepStates segun las perspectivas
Se pretende desnormalizar la información proveniente de los StepStates, por cada una de las perspectivas. Esto implicaría:
- Estado y Fecha de aviso: para evitar en muchas instancias joineos para determinar cambios de estado y/o bien agilizar el impacto de nueva información (política del «mas reciente»).
- Aviso de Estado: para recuperar todos los detalles en casos de que sean necesarios en algunas salidas del sistema.
Para entrar un poco mas en detalle, a los cambios en las estructuras vigentes y nuevos componentes (Services,Commands), se brinda el siguiente gráfico:
Básicamente se propone:
-
Entidad Shipping: Añadir por cada una de las perspectivas:
-
Estado (State actor_perspective_state)
-
Fecha (DateTime actor_perspective_date)
-
Aviso de Estado (StepState actor_perspective_step_state)
-
Entidad State: Se propone un nuevo campo
-
Valor de Estadio (Integer stage_value): Indicará cuanto “peso” tendrá un estado, al ser que está mas avanzado en el ciclo (estadios) de la logística. Servirá como un factor de ponderación.
-
Service ActorPerspectiveService: Centralizá la gestión de los atributos propuestos de Shipping.
-
applyStepState(Shipping $shipping, StepState $step_state):
Se encargará de determinar la aplicación de un StepState considerando todas las perspectivas. -
revertStepState(Shipping $shipping, StepState $step_state):
Analizará el impacto que posea la eliminación de un StepState determinado en las perspectivas. -
modifyStepState(Shipping $shipping, StepState $new_step_state):
Gestionará el impacto de la modificación de un StepState. -
applyPerspectiveCalculus(Shipping $shipping,Boolean $flush):
Llevará a cabo el cálculo de las 3 perspectivas, y las aplicará en el envio. Adicionalmente se propone la posibilidad de simular el calculo sin aplicar ($flush=false).
Este resultará útil para casos de corrección o bien inicializaciones masivas. -
applyStepStateManual(Shipping $shipping, StepState $step_state, String $perspective):
Funcionalidad opcional. Se propone la posibilidad que un Usuario idoneo y debidamente habilitado, pueda aplicar una modificación a una de las perspectivas proveyendo un StepState en particular.
Esta funcionalidad implicaria guardar informacion extra como para indicar esta acción, podria ser en el StepState o bien un atributo en Shipping para tal fin. -
Comando calculateShippingPerspectiveCommand: Se encargará de buscar envios comprendido entre rango de fechas y encolar en una cola especial, un mensaje con un ID.
-
Consumer calculateShippingPerspectiveConsumer: Será el encargado del calculo (asincrónico) de las perspectivas.
#3 Otras adaptaciones propuestas
Reducción del tamaño de la tabla Shipping:
La tabla Shipping posee actualmente: 45 columnas, de las cuales 6 son ForeignKey. Se presume que este tamaño influye en el consumo de recursos, considerando que el ORM al instanciar envios, deberá procesar 39 datos (Strings, DateTimes,etc..), sean o no usados el contexto donde se lo requiera (Listado p. ej.).
Se propone representar una o mas entidades nuevas relacionada con Shipping, que posea los detalles del mismo, identificando que sean “triviales” en los principales flujos del Sistema.
Los atributos candidatos serían:
-
Características físicas: alto, ancho, peso volumetrico,etc..
-
Fechas del “ciclo satisfactorio” (13 Datetimes )
-
Información trivial:
-
Codigo barras propio
-
Integraciones con otros carriers:
-
Codigos externos, codigo de barras, operacion,etc..