-- ---------------------------------------------------------------------------
-- Quando a venda foi cancelada, e qual gerente autorizou; e quem lancou o
-- desconto manual do item (03/11/2026, a fatia 70 da fila das telas que faltam,
-- PDV-CANCELAMENTO; a P0 de `docs/f3-relatorios/spec-ordem.md`, secao 4.1).
--
--   mysql franquia_producao < scripts/migracao-venda-cancelamento.sql
--
-- A PERGUNTA 2 DO DONO (01/10/2026): gravar o instante e o gerente que autorizou o
-- cancelamento; a rotina das comandas abandonadas grava so o instante. E quem lancou
-- o desconto manual de cada item. Hoje o cancelamento confere a senha do gerente nas
-- duas telas (`VendasController::cancelarAction` e `Adm\VendasController`) e a
-- descarta: a venda fica so com o motivo, e "quando" e "quem" se perdem.
--
-- AS TRES COLUNAS SAO NULAS, e nao podia ser diferente: nenhuma venda de antes tem o
-- registro, e inventar um seria gravar como fato o que ninguem conferiu.
--
--   vendas.cancelado_em             o instante do cancelamento. NULL = sem registro (a
--                                   venda de antes desta coluna, ou nao cancelada)
--   vendas.cancelado_por            o gerente que autorizou. NULL = a rotina (com o
--                                   instante), ou sem registro (sem o instante)
--   vendas_produtos.desconto_lancado_por  quem lancou o desconto manual do item; o
--                                   escritor entra na fatia 71 (PDV-DESCONTO-LANCADO-POR)
--
-- QUEM GRAVA: `VendaService::cancelar` (a porta unica das duas telas, depois da senha
-- do gerente conferida) grava as duas de `vendas`; a rotina
-- `CronJobService::comandasCancelar` grava so o instante. O portao
-- `scripts/conferir-escritores-do-cancelamento.php` vigia que ninguem mais as grave.
--
-- ESTA MIGRACAO NAO GRAVA A DATA EM `colunas_gravadas` (a nota 4 da fatia 70): a linha
-- `cancelamento` diz "o PDV grava desde aqui", e so e verdade com o codigo que grava no
-- ar. Ela se escreve a parte, por `scripts/colunas-gravadas-cancelamento.sql`, DEPOIS do
-- codigo -- na copia, no dia desta fatia; em producao, no passo 7 da janela, com a
-- aplicacao nova apontada e antes de liberar (o `docs/procedimento-de-corte.md`).
--
-- NA COPIA LOCAL DESDE 03/11/2026, nos dois bancos (a resposta 83 do dono, a opcao (a):
-- o esquema que so acrescenta entra nas duas copias locais). Os bancos da suite e o do
-- contrato nascem com as colunas (`mysql.sql` e o `postgres/schema.sql` do gerador).
--
-- IDEMPOTENTE: cada `ALTER` so roda se a coluna ainda nao existir (o
-- `information_schema`); a segunda vez nao faz nada e sai 0.
--
-- COPIA AS DUAS TABELAS: a chave estrangeira, com `foreign_key_checks` ligado, so entra
-- pelo algoritmo COPY (como a do fiado). Na copia, em 03/11/2026, medido: o ALTER de
-- `vendas` e o de `vendas_produtos` (ver o `docs/roadmap.md`, a entrada da fatia 70).
-- Rode fora do movimento.
--
-- PARA DESFAZER:
--   ALTER TABLE vendas DROP FOREIGN KEY FK_VENDAS_cancelado_por, DROP KEY FK_VENDAS_cancelado_por,
--     DROP COLUMN cancelado_por, DROP COLUMN cancelado_em;
--   ALTER TABLE vendas_produtos DROP FOREIGN KEY FK_VENDAS_PRODUTOS_desconto_lancado_por,
--     DROP KEY FK_VENDAS_PRODUTOS_desconto_lancado_por, DROP COLUMN desconto_lancado_por;
--   DELETE FROM colunas_gravadas WHERE nome = 'cancelamento';
--
-- ---------------------------------------------------------------------------
-- ESTA MIGRACAO PRECISA ESTAR EM PRODUCAO ANTES DO PASSO 1 -- o passo 0 (D323).
--
-- O passo 1 refaz o `mysql.sql` a partir da estrutura de producao. Sem as colunas la,
-- elas somem do `mysql.sql` e do `schema.sql`, e o cancelamento da tela nova morre no
-- primeiro `flush`. Para o codigo antigo de producao as colunas nulas sao inofensivas:
-- ele nao as le nem as escreve.
-- ---------------------------------------------------------------------------

SET @existe = (
    SELECT COUNT(*) FROM information_schema.columns
     WHERE table_schema = DATABASE()
       AND table_name = 'vendas'
       AND column_name = 'cancelado_em'
);

SET @sql = IF(@existe = 0,
    'ALTER TABLE vendas
       ADD COLUMN cancelado_em datetime DEFAULT NULL
       COMMENT ''Instante do cancelamento. NULL = sem registro.''
       AFTER cancelado_motivo,
       ADD COLUMN cancelado_por int DEFAULT NULL
       COMMENT ''Gerente que autorizou o cancelamento. NULL com o instante = a rotina; sem o instante = sem registro.''
       AFTER cancelado_em,
       ADD KEY FK_VENDAS_cancelado_por (cancelado_por),
       ADD CONSTRAINT FK_VENDAS_cancelado_por
           FOREIGN KEY (cancelado_por) REFERENCES usuarios (id)',
    'SELECT ''vendas: colunas ja existem, nada a fazer'' AS aviso'
);

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @existe = (
    SELECT COUNT(*) FROM information_schema.columns
     WHERE table_schema = DATABASE()
       AND table_name = 'vendas_produtos'
       AND column_name = 'desconto_lancado_por'
);

SET @sql = IF(@existe = 0,
    'ALTER TABLE vendas_produtos
       ADD COLUMN desconto_lancado_por int DEFAULT NULL
       COMMENT ''Quem lancou o desconto manual do item. NULL = sem desconto manual, ou sem registro.''
       AFTER desconto_motivo,
       ADD KEY FK_VENDAS_PRODUTOS_desconto_lancado_por (desconto_lancado_por),
       ADD CONSTRAINT FK_VENDAS_PRODUTOS_desconto_lancado_por
           FOREIGN KEY (desconto_lancado_por) REFERENCES usuarios (id)',
    'SELECT ''vendas_produtos: coluna ja existe, nada a fazer'' AS aviso'
);

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

-- Conferencia. O esperado logo depois: nenhuma venda com o instante nem com o autor, e
-- nenhum item com quem lancou o desconto.
SELECT
    COUNT(*)                          AS vendas,
    SUM(status = 0)                   AS canceladas,
    SUM(cancelado_em IS NOT NULL)     AS com_instante,
    SUM(cancelado_por IS NOT NULL)    AS com_autor
FROM vendas;

SELECT COUNT(*) AS itens, SUM(desconto_lancado_por IS NOT NULL) AS com_quem_lancou FROM vendas_produtos;
