Introducción
MEND & MOSS está listo para aplicar las actualizaciones de los proveedores. Su puesto de recepción ya tiene una entrega cargada en la tabla intermedia y la inspección básica del laboratorio anterior. Este es un entorno independiente: no se necesitan archivos de una VM anterior.
Algunas líneas que parecen utilizables discrepan sobre la misma edición. Otras llegan tarde. Ampliarás la inspección para rechazar esas contradicciones y guardarás un script de actualización que avance solo a revisiones más recientes, conservando las notas locales de ubicación de la tienda. Se presupone el SQL básico del primer laboratorio guiado; aquí se explican las comprobaciones de conflictos, UPSERT y las transacciones.
Usa Terminal durante todo el laboratorio. Puedes modificar inspect.sql, crear apply.sql y volver a cargar raw_delivery. Conserva las identidades y notas de ubicación originales de las existencias, los proveedores y los dos archivos CSV. Los valores de nombre, precio y revisión que pertenecen al proveedor pueden avanzar según las reglas siguientes.
Rechazar ediciones contradictorias
En este paso, distinguirás una línea idéntica repetida de un conflicto de edición. Empieza en Terminal:
cd /home/labex/project/supplier-desk
Lee la entrega real de esta unidad y el script de inspección proporcionado:
cat deliveries/current.csv
cat inspect.sql
Las diez líneas de la entrega ya están cargadas en la tabla intermedia. Las líneas 3 y 7 repiten la misma identidad, nombre, precio y revisión de la cinta de reparación; repetir un dato no lo convierte en un producto nuevo. Las líneas 8 y 9 describen N / PIN-2, revisión 2, pero discrepan sobre el precio. Ninguna es una respuesta aprobada. La línea 10 asigna a N / WASH-2, revisión 1, un precio diferente al de la revisión 1 existente en las existencias. Un número de edición no puede significar dos contenidos diferentes.
Las reglas del primer laboratorio siguen vigentes. Hay dos motivos de rechazo adicionales: delivery conflict cuando filas válidas en los demás aspectos tienen el mismo proveedor/SKU/revisión pero distinto nombre o precio entero, y stock conflict cuando esa edición discrepa de las existencias actuales. Si se cumplen ambos, el conflicto de entrega tiene prioridad. Se aceptan las repeticiones idénticas. Las ediciones inferiores pueden aceptarse para la inspección, pero nunca deben sobrescribir existencias más recientes.
Consulta las existencias originales antes de modificarlas:
sqlite3 -header -column stock.db 'SELECT * FROM stock ORDER BY supplier,sku;'
Ejecuta la inspección básica para que existan sus vistas:
sqlite3 -bail stock.db < inspect.sql
Antes de editar, crea una copia de recuperación del script proporcionado. cp copia la primera ruta a la segunda sin modificar el original:
cp inspect.sql inspect-start.sql
El siguiente SQL usa los alias t, other, s y e para nombrar una fila de entrega, otra fila de entrega, una fila de existencias y una fila de error. EXISTS (SELECT 1 ...) pregunta si existe alguna fila coincidente; el 1 es solo un marcador porque no se devuelve el contenido de la fila. AND exige que coincidan todos los campos clave. <> significa distinto. NOT EXISTS conserva las filas sin error. UNION ALL combina los errores básicos y los conflictos sin perder las identidades de las líneas individuales.
Añade la ampliación al final de inspect.sql. >> añade en lugar de reemplazar, así que conserva encima las definiciones básicas proporcionadas. Pega este bloque una vez. Repetirlo resulta inocuo aquí porque cada ampliación solo vuelve a crear las dos vistas finales, pero evita duplicar texto innecesariamente:
cat >> inspect.sql <<'SQL'
DROP VIEW IF EXISTS delivery_ready;
DROP VIEW IF EXISTS delivery_errors;
CREATE VIEW delivery_errors AS
SELECT delivery_line,reason FROM delivery_check WHERE reason IS NOT NULL
UNION ALL
SELECT t.delivery_line,
CASE WHEN EXISTS (
SELECT 1 FROM typed_delivery AS other
WHERE other.supplier=t.supplier AND other.sku=t.sku
AND other.revision=t.revision
AND (other.title<>t.title OR other.price_cents<>t.price_cents)
) THEN 'delivery conflict' ELSE 'stock conflict' END
FROM typed_delivery AS t
WHERE EXISTS (
SELECT 1 FROM typed_delivery AS other
WHERE other.supplier=t.supplier AND other.sku=t.sku
AND other.revision=t.revision
AND (other.title<>t.title OR other.price_cents<>t.price_cents)
) OR EXISTS (
SELECT 1 FROM stock AS s
WHERE s.supplier=t.supplier AND s.sku=t.sku AND s.revision=t.revision
AND (s.title<>t.title OR s.price_cents<>t.price_cents)
);
CREATE VIEW delivery_ready AS
SELECT supplier,sku,title,price_cents,revision FROM typed_delivery AS t
WHERE NOT EXISTS (
SELECT 1 FROM delivery_errors AS e WHERE e.delivery_line=t.delivery_line
);
SQL
Vuelve a ejecutar todo el script guardado:
sqlite3 -bail stock.db < inspect.sql
sqlite3 -header -column stock.db 'SELECT * FROM delivery_errors ORDER BY delivery_line;'
Deberías ver seis errores: línea 4 invalid price, 5 unknown supplier, 6 missing SKU, 8 y 9 delivery conflict, y 10 stock conflict. La cinta de reparación aparece dos veces en la revisión de datos aceptados porque ambas líneas fuente son aceptables; un par de líneas idénticas no debe duplicar un precio ni crear dos artículos de existencias.
sqlite3 -header -column stock.db 'SELECT * FROM delivery_ready ORDER BY supplier,sku;'
Hay cuatro filas de entrega aceptadas que representan tres identidades de producto. Las existencias siguen sin cambios. Si solo ves los tres errores básicos, comprueba que esté presente el bloque añadido y vuelve a ejecutar el script completo. Si hay un error de sintaxis en el bloque añadido, restaura la base proporcionada con cp inspect-start.sql inspect.sql, repite el bloque de ampliación completo y vuelve a ejecutar el script. Esta recuperación deja sin cambios las existencias y ambos archivos CSV.
Aplicar valores más recientes y repetir la entrega con seguridad
En este paso, aplicarás las filas aceptables sin cambiar las notas locales de ubicación y demostrarás que repetir la misma entrega o recibir una anterior no deshace tu trabajo. Empieza en el mismo directorio de Terminal.
La tabla stock tiene una clave primaria sobre (supplier,sku): esos dos campos identifican una fila. Una operación UPSERT inserta una identidad que falta o gestiona un conflicto con esa clave existente. excluded hace referencia a la fila entrante propuesta. Su revisión debe ser mayor que la revisión actual de las existencias para que se produzca una actualización. La columna proporcionada shelf_note pertenece a la tienda: omítela tanto de los valores entrantes como de las asignaciones de actualización. Una identidad nueva recibe el valor predeterminado preparado de nota vacía.
BEGIN inicia una transacción y COMMIT la guarda como una unidad. Un error detiene este comando con -bail; al cerrar su conexión se revierte una transacción sin terminar. Este ejemplo actualiza una base de datos pequeña y preparada; no es un sistema de sincronización concurrente ni de copias de seguridad.
El SELECT lee la vista real de datos aceptados. Su WHERE true conserva todas esas filas y evita que SQLite confunda el ON CONFLICT posterior con una condición de unión. Guarda el script completo:
cat > apply.sql <<'SQL'
BEGIN;
INSERT INTO stock(supplier,sku,title,price_cents,revision)
SELECT supplier,sku,title,price_cents,revision
FROM delivery_ready WHERE true
ON CONFLICT(supplier,sku) DO UPDATE SET
title=excluded.title,
price_cents=excluded.price_cents,
revision=excluded.revision
WHERE excluded.revision>stock.revision;
COMMIT;
SQL
Activa las claves foráneas en la conexión utilizada para aplicarlo. -cmd ejecuta primero la configuración de conexión entre comillas; no se guarda globalmente. Después, < apply.sql proporciona el SQL:
sqlite3 -bail -cmd 'PRAGMA foreign_keys=ON;' stock.db < apply.sql
sqlite3 -header -column stock.db 'SELECT * FROM stock ORDER BY supplier,sku;'
Deberías ver cuatro filas de existencias:
supplier sku title price_cents revision shelf_note
-------- ------ ----------- ----------- -------- ----------
N BOLT-1 Steel bolt 135 3 Bin A
N TAPE-4 Repair tape 450 1
N WASH-2 Washer 40 1 Bin C
W BOLT-1 Brass bolt 190 2 Drawer 4
La arandela sigue a 40 porque se rechazó su edición contradictoria. No se añadió ningún pasador, tapa no válida, artículo de proveedor desconocido ni artículo con SKU vacío. Se conservan las notas originales de ambos pernos. La cinta de reparación tiene una sola fila aunque aparecía dos veces en la entrega.
Repite el mismo script:
sqlite3 -bail -cmd 'PRAGMA foreign_keys=ON;' stock.db < apply.sql
sqlite3 -header -column stock.db 'SELECT * FROM stock ORDER BY supplier,sku;'
El resultado permanece igual. La condición de revisión permite repetir una importación idéntica con seguridad; no suma el precio ni reemplaza la nota local.
Ahora lee la entrega anterior antes de usarla:
cat deliveries/older.csv
Estas son ediciones anteriores de los pernos. Vuelve a cargar solo la tabla intermedia mediante el intérprete interactivo:
sqlite3 stock.db
DELETE FROM raw_delivery;
.import --csv --skip 1 deliveries/older.csv raw_delivery
.quit
Las vistas leen automáticamente las filas actuales de la tabla. Ejecuta la actualización sin cambios e inspecciona las existencias:
sqlite3 -bail -cmd 'PRAGMA foreign_keys=ON;' stock.db < apply.sql
sqlite3 -header -column stock.db 'SELECT * FROM stock ORDER BY supplier,sku;'
Las cuatro filas siguen teniendo los mismos valores. La inspección acepta números anteriores válidos, pero aplicarlos no puede hacer retroceder las existencias. Esto es distinto de una entrega no válida o contradictoria.
Deja el puesto preparado para revisar de nuevo la entrega de hoy. Vaciar la tabla intermedia no vacía las existencias:
sqlite3 stock.db
DELETE FROM raw_delivery;
.import --csv --skip 1 deliveries/current.csv raw_delivery
.quit
sqlite3 -header -column stock.db 'SELECT * FROM delivery_errors ORDER BY delivery_line;'
Las seis líneas rechazadas siguen visibles con sus motivos. Conserva ambos scripts: inspect.sql describe cómo se revisa otra entrega compatible; apply.sql describe cómo sus filas seguras hacen avanzar las existencias. Puedes recuperarte de una ruta incorrecta con el cd absoluto; un script mal escrito puede reemplazarse a partir del bloque completo. No vuelvas a crear stock.db ni borres registros para corregir un error de escritura.
Resumen
Usaste filas reales de SQLite para relacionar las identidades de los proveedores, los valores de las entregas y las existencias locales. Interpretaste los registros realmente aceptados y rechazados, conservaste las fuentes originales y guardaste SQL reutilizable para la próxima entrega.



