En diversas aplicaciones, la tarea surge regularmente de apoyar la lógica del cambio en el tiempo de algún atributo de un objeto en relación con un determinado sujeto (o sujetos). Por ejemplo, esto puede ser un cambio en el precio minorista de los bienes en las tiendas o indicadores KPI para los empleados.
En este artículo, mostraré qué lógica de dominio e interfaces se pueden construir para resolver este problema. Inmediatamente haré una reserva de que se referirá a la influencia administrativa del usuario en el atributo, y no al reflejo del cambio histórico.
La implementación se presentará sobre la base de la plataforma
lsFusion abierta y gratuita, pero se puede aplicar un esquema similar al usar cualquier otra tecnología.
Introduccion
Para una presentación y comprensión más simples del artículo, tomamos el precio como un atributo, el producto como el objeto y el almacén será el tema. En este caso, el intervalo mínimo posible para establecer el atributo será la fecha. Por lo tanto, el usuario podrá determinar cuál será el precio para una fecha en particular para cualquier producto y almacén.
El esquema de entrada del usuario para los cambios de precios será similar al utilizado en los sistemas de control de versiones clásicos. Cualquier cambio, desde el punto de vista de la lógica de dominio, será una
confirmación única, en función de la cual se calculará el estado de una fecha determinada. En muchas áreas temáticas, estos compromisos se denominan documentos o transacciones. En este caso, por este compromiso nos referiremos a la llamada lista de precios. Cada lista de precios especificará los bienes y almacenes que están incluidos en ella, así como el período de validez.
El esquema descrito tiene las siguientes ventajas:
- Atomicidad Cada cambio se emite como un documento separado. Por lo tanto, estos documentos pueden guardarse temporalmente, pero no publicarse. Con una entrada errónea, es fácil revertir todo el cambio.
- Transparencia Es fácil determinar quién realizó el cambio y cuándo, así como indicar el motivo haciendo un comentario sobre el documento.
La principal diferencia con el sistema de control de versiones es que las confirmaciones explícitas son independientes entre sí. Por lo tanto, es posible eliminar todas las confirmaciones relativamente sin dolor en cualquier momento. Además, cada uno de estos commits puede configurarse para finalizar cuando deja de funcionar, lo que por supuesto no está en el sistema de control de versiones.
Implementación
Comenzamos la definición de lógica de dominio con almacenes. Vamos a complicar un poco la solución combinando almacenes en una jerarquía de un grupo de profundidad dinámica. Según qué principio se hace esto, se describe en el
artículo correspondiente, por lo que solo daré un fragmento de código que declara grupos y crea formularios para editarlos:
Anuncio de grupo de almacenes Ejemplo de jerarquía grupal A continuación, declare los almacenes que se pueden vincular a cualquiera de los grupos:
Y finalmente, declare la lógica de los bienes:
Procedemos directamente a crear la lógica de las listas de precios. Primero, establecemos la clase de
lista de precios en sí, así como su período de validez:
Creemos que si no
se ha establecido una
Fecha , entonces la lista de precios es interminable.
Agregamos un evento que, al crear la lista de precios, anotará automáticamente la fecha actual a partir de la cual comenzará a funcionar.
La palabra clave
LOCAL significa que el evento no se activará cuando se aplique el guardado a la base de datos, sino inmediatamente cuando se realice el cambio.
Luego agregue el usuario que lo creó y el tiempo de creación:
Ahora cree un evento que los llene automáticamente:
Este evento, a diferencia del anterior, se activará solo cuando se haga clic en el botón Guardar. Es decir, durante una transacción de guardar en la base de datos.
A continuación, cree las líneas de la lista de precios en las que se establecerán los bienes y precios:
El atributo
NONULL indica que la propiedad
priceList siempre debe establecerse, y
DELETE indica que cuando el valor de la propiedad se pone a cero (por ejemplo, al eliminar la lista de precios), la línea correspondiente se debe eliminar automáticamente.
Para uso futuro, crearemos propiedades que determinarán el período de validez de las líneas de la lista de precios:
Ahora vincularemos la lista de precios a los almacenes para los que operará. Primero, agregue la propiedad principal, que será verdadera si todo el grupo de almacenes está incluido en la lista de precios:
Calculamos la "inclusión" del grupo teniendo en cuenta a los padres seleccionados (como se describe en el artículo sobre jerarquías):
Agregue la propiedad principal, con la que puede especificar que la lista de precios actúe en un almacén específico:
Calculamos la propiedad final, que determinará que la lista de precios cambia los precios en el almacén correspondiente, teniendo en cuenta los grupos:
Cree una propiedad que muestre los nombres de todos los grupos y almacenes seleccionados de la lista de precios, para que un usuario más conveniente vea la lista de listas de precios:
El paso final en la descripción de la lógica de dominio calculará directamente el precio actual de las mercancías en el almacén. Para hacer esto, cree una propiedad que encuentre la última línea de fecha de la lista de precios con los bienes, el almacén y el período de validez deseados:
En la lógica de calcular esta propiedad, son posibles varias variaciones. Puede cambiar tanto el filtro para golpear filas (por ejemplo, agregar una condición en
DONDE se publica la lista de precios) como el pedido. Cabe señalar que el objeto mismo, o más bien su identificador interno, se ha agregado al orden de selección mediante el segundo parámetro. Esto es necesario para que el valor del precio siempre se determine de una manera única.
Según la línea de lista de precios recibida, determinamos el valor del precio y su período de validez:
Se seguirán utilizando en las tablas de la interfaz de usuario.
A continuación, pasamos a construir la interfaz de usuario. Primero, dibujamos un formulario para editar la lista de precios. Cree un formulario y agregue el "encabezado" del documento allí:
Agregue la línea de la lista de precios al formulario:
A continuación, agregue un árbol en el que habrá grupos y almacenes:
Las propiedades para grupos y almacenes se agregan al árbol al mismo tiempo. La plataforma, según el objeto, mostrará esta o aquella propiedad en el orden en que se agregan al formulario.
Personalizamos el diseño del formulario para que los bienes y almacenes se dibujen en pestañas separadas:
El formulario de edición se verá así:
Queda por construir la forma básica de gestión de precios. Consistirá en dos pestañas. El primero mostrará una lista de todas las listas de precios (similar a la lista de confirmaciones). La segunda pestaña mostrará los precios actuales de un almacén específico para la fecha seleccionada.
Para implementar la primera pestaña, agregue al formulario una lista de listas de precios con líneas para una vista previa rápida:
Para la segunda pestaña, primero agregamos la fecha en la que se muestran los precios, el árbol de los grupos de almacenes, así como los propios almacenes:
La lista de almacenes mostrará todos los almacenes que son descendientes del grupo seleccionado en la parte superior.
A continuación, agregue al formulario una lista de productos para los que hay precios válidos para el almacén en la fecha seleccionada:
Tanto el precio en sí como el período de validez se agregan a las columnas. También puede agregar el número de la lista de precios; luego, esta tabla se parecerá a la lógica de las anotaciones en los sistemas de control de versiones.
Para que el usuario entienda de dónde proviene ese precio, agregamos la lista de líneas de lista de precios con productos y almacenes adecuados:
Usando el atributo
BACKGROUND, resalte la fila que determinó el precio que se muestra en la tabla.
Además, para la comodidad del usuario, agregaremos la posibilidad de abrir el formulario de edición de la lista de precios correspondiente en una nueva sesión inmediatamente a partir de esta historia:
Para lograr esto, debe especificar la acción que se realizará cuando intente editar una línea implementando la acción de
edición incorporada. Luego, un botón estándar para editar un objeto a través de una llamada de diálogo se agrega al formulario de la manera estándar.
Y finalmente, formamos el diseño final del formulario:
Aquí, el contenedor del
panel se agrega primero, que consta de dos pestañas:
listas de precios y
precios . El primero de ellos solo agrega una lista de listas de precios y líneas. En el segundo, se crean dos paneles:
leftPane y
rightPane . El panel izquierdo contiene la fecha y los almacenes, y el panel derecho contiene los bienes y el historial de precios.
Resultado
Considere las principales opciones para usar la lógica resultante.
Supongamos que tenemos dos listas de precios separadas para diferentes grupos de bienes. Luego, dependiendo del almacén seleccionado, en la pestaña con precios, solo se mostrarán los productos de las listas de precios correspondientes:
Ahora cree una nueva lista de precios con un período de validez limitado, una lista reducida de almacenes y un nuevo precio. En la segunda pestaña, si seleccionamos una fecha en el rango de la nueva lista de precios, obtendremos un nuevo precio. Tan pronto como expire el período de validez, el precio anterior volverá nuevamente del precio original:
Usando el mismo mecanismo, puede "cancelar" la acción de precios específicos desde una fecha determinada. Por ejemplo, si ingresa un nuevo precio sin especificar un precio, resulta que el precio se restablecerá y los productos desaparecerán del filtro. En este caso, al eliminar el documento ingresado, todo vuelve al estado anterior:
La propiedad resultante con el precio de los bienes por el almacén en la fecha se puede utilizar en varios eventos u otras formas. Por ejemplo, puede realizar precios automáticos en un orden basado en esta lógica de precios:
Una buena ventaja en esta lógica será que cuando agregue un nuevo almacén al grupo, los precios de las listas de precios ya creadas se aplicarán automáticamente. Lo mismo sucederá cuando cambie el grupo para el almacén.
Si lo desea, puede editar la columna con el precio en la pestaña con los precios actuales y agregar un botón que creará un nuevo compromiso para los precios modificados.
Conclusión
En la solución a nivel de plataforma, no se utilizan libros de referencia, ni documentos con cadenas, ni registros, ni informes y otras abstracciones innecesarias. Todo se hace exclusivamente en los conceptos de clases y propiedades. Tenga en cuenta que esta lógica bastante compleja se implementó en aproximadamente 150 líneas de código significativas en lsFusion. Implementarlo en la misma formulación en otras plataformas (por ejemplo, 1C) es una tarea mucho más difícil.
El esquema descrito anteriormente se usa ampliamente en la
solución ERP basada en lsFusion. Utilizándolo, con varias modificaciones, se admiten listas de precios de proveedores, precios minoristas de gestión, existencias y muchos otros parámetros de gestión.
La plantilla puede complicarse agregando varias entidades al documento (por ejemplo, se puede agregar un proveedor al almacén), así como definiendo varios atributos en un documento a la vez. En particular, puede agregar el Tipo de precio de la entidad y, en la línea del documento, establecer el precio de la tupla de la línea y el tipo de precio correspondiente. En la lógica descrita anteriormente, solo necesita agregar algunos parámetros adicionales a algunas propiedades.
Con la ayuda de varias líneas de código adicionales, es posible desnormalizar todos los registros de cambios en una tabla sobre la cual construir el índice correspondiente. Luego, la selección de cualquier valor para cualquier fecha se realizará en un tiempo logarítmico. Dicha optimización es necesaria cuando hay varios cientos de millones de registros en esta tabla.
Puede probar el ejemplo creado en línea en la
página correspondiente
del sitio (sección Plataforma). Aquí está todo el código fuente que necesita pegar en el campo deseado: