Introduction
MEND & MOSS est prêt à appliquer les mises à jour des fournisseurs. Son poste de réception dispose déjà d’une livraison chargée en zone intermédiaire et de l’inspection de base du TP précédent. Cet environnement est indépendant : aucun fichier d’une VM précédente n’est nécessaire.
Certaines lignes qui semblent utilisables se contredisent au sujet d’une même édition. D’autres arrivent en retard. Vous étendrez l’inspection pour rejeter ces contradictions, puis enregistrerez un script de mise à jour qui n’applique que les révisions plus récentes, tout en conservant les notes locales d’emplacement du magasin. Les bases SQL du premier TP guidé sont supposées acquises ; les vérifications de conflit, UPSERT et les transactions sont expliqués ici.
Utilisez Terminal tout au long du TP. Vous pouvez modifier inspect.sql, créer apply.sql et recharger raw_delivery. Conservez les identités et les notes d’emplacement du stock d’origine, les fournisseurs et les deux fichiers CSV. Les valeurs de libellé/prix/révision gérées par les fournisseurs peuvent évoluer selon les règles ci-dessous.
Rejeter les éditions contradictoires
Dans cette étape, vous distinguerez une ligne répétée à l’identique d’un conflit d’édition. Commencez dans Terminal :
cd /home/labex/project/supplier-desk
Lisez la véritable livraison de cette unité et le script d’inspection fourni :
cat deliveries/current.csv
cat inspect.sql
Les dix lignes de livraison sont déjà chargées en zone intermédiaire. Les lignes 3 et 7 répètent la même identité, le même libellé, le même prix et la même révision du ruban de réparation ; répéter un fait n’en fait pas un nouveau produit. Les lignes 8 et 9 décrivent toutes deux N / PIN-2, révision 2, mais donnent des prix différents. Aucune n’est une réponse approuvée. La ligne 10 donne à N / WASH-2, révision 1, un prix différent de celui de la révision 1 déjà en stock. Un numéro d’édition ne peut pas désigner deux contenus différents.
Les règles du premier TP s’appliquent toujours. Deux motifs de rejet s’ajoutent : delivery conflict lorsque des lignes autrement valides ont le même fournisseur/SKU/révision, mais des libellés ou des prix entiers différents ; et stock conflict lorsque cette édition contredit le stock actuel. Le conflit de livraison est prioritaire si les deux s’appliquent. Les répétitions identiques sont acceptées. Des éditions plus anciennes peuvent être acceptées lors de l’inspection, mais ne doivent jamais écraser un stock plus récent.
Regardez le stock d’origine avant de le modifier :
sqlite3 -header -column stock.db 'SELECT * FROM stock ORDER BY supplier,sku;'
Exécutez l’inspection de base pour que ses vues existent :
sqlite3 -bail stock.db < inspect.sql
Avant toute modification, faites une copie de secours du script fourni. cp copie le premier chemin vers le second sans modifier l’original :
cp inspect.sql inspect-start.sql
Le SQL suivant utilise les alias t, other, s et e pour désigner une ligne de livraison, une autre ligne de livraison, une ligne de stock et une ligne d’erreur. EXISTS (SELECT 1 ...) demande s’il existe une ligne correspondante ; le 1 n’est qu’une valeur de remplacement, car le contenu de la ligne n’est pas renvoyé. AND impose la correspondance de tous les champs de la clé. <> signifie différent. NOT EXISTS conserve les lignes sans erreur. UNION ALL réunit les erreurs de base et les conflits sans perdre les identités distinctes des lignes.
Ajoutez l’extension à la fin de inspect.sql. >> ajoute au lieu de remplacer : conservez donc les définitions de base fournies au-dessus. Collez ce bloc une seule fois. Le répéter est sans danger ici, car chaque extension ne recrée que les deux vues finales, mais évitez de dupliquer le texte inutilement :
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
Exécutez à nouveau tout le script enregistré :
sqlite3 -bail stock.db < inspect.sql
sqlite3 -header -column stock.db 'SELECT * FROM delivery_errors ORDER BY delivery_line;'
Vous devez obtenir six erreurs : ligne 4 invalid price, 5 unknown supplier, 6 missing SKU, 8 et 9 delivery conflict, et 10 stock conflict. Le ruban de réparation apparaît deux fois dans l’examen des données acceptées, car les deux lignes sources sont acceptables ; une paire de lignes identiques ne doit pas doubler un prix ni créer deux articles en stock.
sqlite3 -header -column stock.db 'SELECT * FROM delivery_ready ORDER BY supplier,sku;'
Il y a quatre lignes de livraison acceptées représentant trois identités de produit. Le stock n’a toujours pas changé. Si seules les trois erreurs de base apparaissent, vérifiez la présence du bloc ajouté et relancez le script complet. En cas d’erreur de syntaxe dans le bloc ajouté, restaurez la base fournie avec cp inspect-start.sql inspect.sql, puis répétez le bloc d’ajout complet et relancez le script. Cette récupération laisse le stock et les deux fichiers CSV inchangés.
Appliquer les valeurs plus récentes et répéter la livraison sans risque
Dans cette étape, vous appliquerez les lignes acceptables sans modifier les notes locales d’emplacement, puis prouverez que répéter la même livraison ou en recevoir une plus ancienne n’annule pas votre travail. Commencez dans le même répertoire de Terminal.
La table stock possède une clé primaire sur (supplier,sku) : ces deux champs identifient une ligne. Une opération UPSERT insère une identité absente ou traite un conflit avec cette clé existante. excluded désigne la ligne entrante proposée. Sa révision doit être supérieure à la révision actuelle du stock pour qu’une mise à jour ait lieu. La colonne fournie shelf_note appartient au magasin : excluez-la à la fois des valeurs entrantes et des affectations de mise à jour. Une nouvelle identité en stock reçoit la valeur par défaut préparée : une note vide.
BEGIN démarre une transaction et COMMIT l’enregistre comme un tout. Une erreur arrête cette commande -bail ; la fermeture de sa connexion annule une transaction inachevée. Cet exemple met à jour une petite base préparée ; ce n’est pas un système de synchronisation concurrente ni de sauvegarde.
Le SELECT lit la véritable vue des données acceptées. Son WHERE true conserve toutes ces lignes tout en empêchant SQLite de confondre le ON CONFLICT suivant avec une condition de jointure. Enregistrez le script complet :
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
Activez les clés étrangères sur la connexion utilisée pour l’appliquer. -cmd exécute d’abord le réglage de connexion entre guillemets ; il n’est pas enregistré globalement. Ensuite, < apply.sql fournit le SQL :
sqlite3 -bail -cmd 'PRAGMA foreign_keys=ON;' stock.db < apply.sql
sqlite3 -header -column stock.db 'SELECT * FROM stock ORDER BY supplier,sku;'
Vous devez obtenir quatre lignes de stock :
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 rondelle reste à 40, car son édition contradictoire a été rejetée. Aucun article correspondant à une goupille, un capuchon invalide, un fournisseur inconnu ou un SKU vide n’a été ajouté au stock. Les notes d’origine des deux boulons sont conservées. Le ruban de réparation n’a qu’une ligne, même s’il apparaissait deux fois dans la livraison.
Répétez le même script :
sqlite3 -bail -cmd 'PRAGMA foreign_keys=ON;' stock.db < apply.sql
sqlite3 -header -column stock.db 'SELECT * FROM stock ORDER BY supplier,sku;'
Le résultat reste identique. La condition sur la révision rend sans danger la répétition d’un import identique ; elle n’ajoute pas le prix et ne remplace pas la note locale.
Lisez maintenant la livraison plus ancienne avant de l’utiliser :
cat deliveries/older.csv
Il s’agit d’éditions plus anciennes des boulons. Rechargez uniquement la table intermédiaire à l’aide du shell interactif :
sqlite3 stock.db
DELETE FROM raw_delivery;
.import --csv --skip 1 deliveries/older.csv raw_delivery
.quit
Les vues lisent automatiquement les lignes actuelles de la table. Exécutez la mise à jour inchangée, puis examinez le stock :
sqlite3 -bail -cmd 'PRAGMA foreign_keys=ON;' stock.db < apply.sql
sqlite3 -header -column stock.db 'SELECT * FROM stock ORDER BY supplier,sku;'
Les quatre lignes conservent les mêmes valeurs. L’inspection accepte les nombres valides plus anciens, mais leur application ne peut pas faire revenir le stock en arrière. Ce cas diffère d’une livraison invalide ou contradictoire.
Laissez le poste prêt à réexaminer la livraison du jour. Vider la zone intermédiaire ne vide pas le stock :
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;'
Les six lignes rejetées restent visibles avec leurs motifs. Conservez les deux scripts : inspect.sql décrit comment examiner une autre livraison compatible ; apply.sql décrit comment ses lignes sûres font évoluer le stock. Un mauvais chemin se corrige avec le cd absolu ; un script mal saisi peut être remplacé à partir du bloc complet. Ne recréez pas stock.db et ne supprimez pas d’enregistrements pour réparer une faute de frappe.
Résumé
Vous avez utilisé de véritables lignes SQLite pour relier les identités des fournisseurs, les valeurs livrées et le stock local. Vous avez interprété les enregistrements réellement acceptés et rejetés, conservé les sources d’origine et enregistré du SQL réutilisable pour la prochaine livraison.



