Introdução
A MEND & MOSS está pronta para aplicar as atualizações dos fornecedores. Seu posto de recebimento já tem um recebimento carregado na tabela intermediária e a inspeção básica do lab anterior. Este é um ambiente independente: nenhum arquivo de uma VM anterior é necessário.
Algumas linhas aparentemente utilizáveis divergem sobre a mesma edição. Outras chegam atrasadas. Você ampliará a inspeção para rejeitar essas contradições e salvará um script de atualização que avança apenas revisões mais novas, preservando as notas locais de localização da loja. Pressupõe-se o SQL básico do primeiro Lab Guiado; verificações de conflito, UPSERT e transações são explicados aqui.
Use Terminal durante todo o lab. Você pode alterar inspect.sql, criar apply.sql e recarregar raw_delivery. Preserve as identidades e as notas de localização originais do estoque, os fornecedores e os dois arquivos CSV. Os valores de título/preço/revisão que pertencem ao fornecedor podem avançar conforme as regras abaixo.
Rejeitar edições contraditórias
Nesta etapa, você distinguirá uma linha idêntica repetida de um conflito de edição. Comece em Terminal:
cd /home/labex/project/supplier-desk
Leia o recebimento real desta unidade e o script de inspeção fornecido:
cat deliveries/current.csv
cat inspect.sql
As dez linhas do recebimento já estão carregadas na tabela intermediária. As linhas 3 e 7 repetem a mesma identidade, título, preço e revisão da fita de reparo; repetir um fato não o transforma em um novo produto. As linhas 8 e 9 descrevem N / PIN-2, revisão 2, mas divergem quanto ao preço. Nenhuma delas é uma resposta aprovada. A linha 10 atribui a N / WASH-2, revisão 1, um preço diferente do existente no estoque para a revisão 1. Um número de edição não pode significar dois conteúdos diferentes.
As regras do primeiro lab continuam válidas. Há dois motivos adicionais de rejeição: delivery conflict, quando linhas que seriam válidas têm o mesmo fornecedor/SKU/revisão, mas título ou preço inteiro diferentes, e stock conflict, quando essa edição diverge do estoque atual. Um conflito de recebimento tem precedência se ambos se aplicarem. Repetições idênticas são aceitas. Edições inferiores podem ser aceitas na inspeção, mas nunca devem sobrescrever um estoque mais recente.
Consulte o estoque original antes de alterá-lo:
sqlite3 -header -column stock.db 'SELECT * FROM stock ORDER BY supplier,sku;'
Execute a inspeção básica para que suas views existam:
sqlite3 -bail stock.db < inspect.sql
Antes de editar, faça uma cópia de recuperação do script fornecido. cp copia o primeiro caminho para o segundo sem alterar o original:
cp inspect.sql inspect-start.sql
O próximo SQL usa os aliases t, other, s e e para nomear uma linha de recebimento, outra linha de recebimento, uma linha de estoque e uma linha de erro. EXISTS (SELECT 1 ...) pergunta se existe alguma linha correspondente; o 1 é apenas um marcador, pois o conteúdo da linha não é retornado. AND exige que todos os campos da chave correspondam. <> significa diferente. NOT EXISTS mantém linhas sem erro. UNION ALL combina erros básicos e conflitos sem perder as identidades separadas das linhas.
Acrescente a extensão a inspect.sql. >> acrescenta em vez de substituir, portanto mantenha acima dela as definições básicas fornecidas. Cole este bloco uma vez. Repeti-lo é inofensivo aqui, porque cada extensão recria apenas as duas views finais, mas evite texto duplicado desnecessário:
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
Execute novamente todo o script salvo:
sqlite3 -bail stock.db < inspect.sql
sqlite3 -header -column stock.db 'SELECT * FROM delivery_errors ORDER BY delivery_line;'
Espere seis erros: linha 4 invalid price, 5 unknown supplier, 6 missing SKU, 8 e 9 delivery conflict e 10 stock conflict. A fita de reparo aparece duas vezes na análise dos dados aceitos, pois ambas as linhas de origem são aceitáveis; um par de linhas idênticas não deve dobrar um preço nem criar dois itens de estoque.
sqlite3 -header -column stock.db 'SELECT * FROM delivery_ready ORDER BY supplier,sku;'
Há quatro linhas de recebimento aceitas, representando três identidades de produto. O estoque continua inalterado. Se você vir apenas os três erros básicos, verifique se o bloco acrescentado está presente e execute novamente o script completo. Para um erro de sintaxe no bloco acrescentado, restaure a base fornecida com cp inspect-start.sql inspect.sql, repita o bloco de acréscimo completo e execute o script novamente. Essa recuperação mantém o estoque e os dois arquivos CSV inalterados.
Aplicar valores mais novos e repetir o recebimento com segurança
Nesta etapa, você aplicará as linhas aceitáveis sem alterar as notas locais de localização e comprovará que repetir o mesmo recebimento ou receber um mais antigo não desfaz seu trabalho. Comece no mesmo diretório em Terminal.
A tabela stock tem uma chave primária em (supplier,sku): esses dois campos identificam uma linha. Um UPSERT insere uma identidade ausente ou trata um conflito com essa chave existente. excluded se refere à linha de entrada proposta. Sua revisão deve ser maior que a revisão atual do estoque para que uma atualização ocorra. A coluna fornecida shelf_note pertence à loja: deixe-a fora tanto dos valores recebidos quanto das atribuições da atualização. Uma nova identidade de estoque recebe o valor padrão preparado de nota vazia.
BEGIN inicia uma transação, e COMMIT a salva como uma unidade. Um erro interrompe este comando -bail; fechar sua conexão desfaz uma transação não concluída. Este exemplo atualiza um banco de dados pequeno e preparado; não é um sistema de sincronização concorrente nem de backup.
O SELECT consulta a view real dos dados aceitos. Seu WHERE true mantém todas essas linhas e impede que o SQLite confunda o ON CONFLICT seguinte com uma condição de junção. Salve o 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
Ative as chaves estrangeiras na conexão usada para aplicá-lo. -cmd executa primeiro a configuração de conexão entre aspas; ela não é salva globalmente. Depois, < apply.sql fornece o SQL:
sqlite3 -bail -cmd 'PRAGMA foreign_keys=ON;' stock.db < apply.sql
sqlite3 -header -column stock.db 'SELECT * FROM stock ORDER BY supplier,sku;'
Espere quatro linhas de estoque:
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
A arruela permanece em 40 porque sua edição contraditória foi rejeitada. Não foi adicionado nenhum pino, tampão inválido, fornecedor desconhecido ou item de estoque com SKU vazio. As duas notas originais dos parafusos são preservadas. A fita de reparo tem uma linha, embora tenha aparecido duas vezes no recebimento.
Repita o mesmo script:
sqlite3 -bail -cmd 'PRAGMA foreign_keys=ON;' stock.db < apply.sql
sqlite3 -header -column stock.db 'SELECT * FROM stock ORDER BY supplier,sku;'
O resultado permanece igual. A condição de revisão torna segura uma importação idêntica repetida; ela não soma o preço nem substitui a nota local.
Agora leia o recebimento mais antigo antes de usá-lo:
cat deliveries/older.csv
Essas são edições mais antigas dos parafusos. Recarregue apenas a tabela intermediária usando o shell interativo:
sqlite3 stock.db
DELETE FROM raw_delivery;
.import --csv --skip 1 deliveries/older.csv raw_delivery
.quit
As views consultam automaticamente as linhas atuais da tabela. Execute a atualização sem alterações e inspecione o estoque:
sqlite3 -bail -cmd 'PRAGMA foreign_keys=ON;' stock.db < apply.sql
sqlite3 -header -column stock.db 'SELECT * FROM stock ORDER BY supplier,sku;'
As quatro linhas ainda têm os mesmos valores. A inspeção aceita números válidos mais antigos, mas aplicá-los não pode fazer o estoque retroceder. Isso é diferente de um recebimento inválido ou contraditório.
Deixe o posto pronto para analisar novamente o recebimento de hoje. Limpar a tabela intermediária não limpa o estoque:
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;'
As seis linhas rejeitadas continuam visíveis com seus motivos. Preserve os dois scripts: inspect.sql descreve como analisar outro recebimento compatível; apply.sql descreve como suas linhas seguras avançam o estoque. Um caminho incorreto pode ser corrigido com o cd absoluto; um script digitado incorretamente pode ser substituído pelo bloco completo. Não recrie stock.db nem exclua registros para corrigir um erro de digitação.
Resumo
Você usou linhas reais do SQLite para relacionar identidades de fornecedores, valores recebidos e estoque local. Interpretou os registros efetivamente aceitos e rejeitados, preservou as fontes originais e salvou SQL reutilizável para o próximo recebimento.



