-- ---------------------------------------------------------------------------
-- O CONVENIO DAS VENDAS ANTIGAS PELO MOTIVO DO ITEM (07/11/2026, a fatia 132, CONVENIO-SEGUE-O-ITEM; o D632, a
-- resposta 358 do dono, (c) com a (b): "acertar as de antes: um roteiro, rodado por voce na producao, grava nas
-- vendas antigas o convenio pelo nome que esta no motivo (as que citam um convenio que mudou de nome ou nao existe
-- mais ficam como estao)", e "a venda segue o convenio do item que o recebe [...] Se uma venda tiver itens de dois
-- convenios [...], vale o do ultimo item lancado").
--
--   mysql franquia_producao < acertar-convenio-das-vendas.sql | tee /root/acertar-convenio-das-vendas-<data>.txt; echo "o mysql saiu com ${PIPESTATUS[0]}"
--   docker exec -i franquiabv-mysql-1 mysql -uroot -proot <banco descartavel> < scripts/acertar-convenio-das-vendas.sql
--
-- QUEM RODA E QUANDO: O DONO, NA PRODUCAO, QUANDO QUISER, fora da janela do corte (como o `baixar-debitos-em-dobro.sql`
-- da fatia 101): nao e passo do procedimento, e nada no corte depende dele. O MELHOR MOMENTO e depois da etapa 1, com o
-- codigo novo no lugar -- dali em diante o lancamento ja grava na venda o convenio do item
-- (`VendaProdutoService::aVendaSegueOConvenioDoItem`), e o roteiro acerta tudo o que veio antes de uma vez. Rodado
-- antes, com o codigo antigo ainda no ar, ele acerta o passado e o codigo antigo continua criando vendas assim ate a
-- troca: rode de novo depois dela (e idempotente). Na producao, o arquivo copiado para o servidor (a arvore de la e a
-- antiga). NA COPIA franquiabv_dev NAO RODA: so a contagem (os SELECT do passo 2); o roteiro inteiro, num banco
-- descartavel, para ensaiar. Depois da etapa 2, o irmao `postgres/acertar-convenio-das-vendas.sql`.
--
-- O ITEM DO CONVENIO E O DO MOTIVO QUE O SISTEMA ESCREVE: comeca EXATAMENTE por "Convênio " (com o acento e a
-- maiuscula, comparado byte a byte -- a colacao da coluna, utf8mb3_general_ci, igualaria "convenio" e "CONVÊNIO", que
-- sao motivos digitados a mao: 651 itens na copia, que os Descontos ja contam como manual) e nao tem a marca do cupom
-- ("CUPOM VIP:", a linha em que o cupom venceu o convenio: a origem dela e o cupom, e o lancamento novo tambem nao leva
-- a venda por ela). O NOME DO CONVENIO e o resto do motivo: o motivo inteiro e "Convênio <nome>" (cortado em 100
-- caracteres, como `RegraDoItemDaComanda::motivoDoConvenio`), ou comeca por "Convênio <nome>; " (o desconto do balcao
-- por cima, a 177 (c)). Comparado byte a byte com `convenios.nome`: o convenio renomeado depois da venda (mesmo so na
-- maiuscula) nao bate.
--
-- A VENDA E DECIDIDA PELO ULTIMO ITEM DO CONVENIO (o maior id, a ordem do lancamento): o nome dele bate com
-- EXATAMENTE UM convenio, e a venda passa a guardar esse, se esta sem convenio ou com outro -- os dois casos da
-- pergunta, como o lancamento novo faz. O ultimo item com um nome que nao existe mais, ou que dois convenios tem (12
-- convenios na copia repetem o nome de outro), deixa a venda como esta: o roteiro conta e lista essas a parte. A venda
-- sem item do convenio nao e tocada (tambem a que guarda um convenio sem nenhum desconto dele: a pergunta da troca de
-- cliente: desde a fatia 136 o lancamento a reve, a 362 (a)). Toda venda, de qualquer situacao (concluida, cancelada,
-- aberta). DESDE A FATIA 136 O LANCAMENTO DIZ O MESMO: a venda que perde o item do convenio (tirado, ou com o cupom
-- vencendo na linha) passa ao do ultimo item do convenio que ficou, pelo mesmo criterio
-- (`VendaProdutoService::aVendaReveOConvenio`, a 362 (a)).
--
-- SO A COLUNA `vendas.convenio`, E A "ULTIMA VENDA" DOS CONVENIOS QUE RECEBEM VENDA CONCLUIDA. Nada de `data_alteracao`
-- (a venda nao mudou para quem a vendeu), nada do item, do dinheiro nem do cliente. Sem DELETE, sem coluna nova. As
-- tabelas temporarias sao da sessao, e somem com ela.
--
-- A "ULTIMA VENDA" ANDA, NUNCA VOLTA (08/11/2026, a fatia 136; o D632, a resposta 363 (a) do dono: "o roteiro tambem
-- avanca a 'ultima venda' desses convenios para a data da venda acertada mais nova, quando ela for mais recente que a
-- gravada (nunca a volta para tras), com a lista do valor de antes."). `convenios.data_ultima_venda` e a coluna que a
-- lista de convenios mostra e que o finalizar grava (`VendaPagamentoService`, o `setDataUltimaVenda`, no convenio DA
-- VENDA, com a hora do fechamento -- a mesma que ele grava em `vendas.data_criacao`). "Venda acertada" e a que o roteiro
-- passa a este convenio (sem convenio, ou com outro), e so a CONCLUIDA (`status` 1): a aberta e a cancelada nao
-- atualizam a "ultima venda" no finalizar, e aqui tambem nao. A data nova e a `data_criacao` da mais nova delas; grava
-- so quando passa da gravada (ou a gravada e nula). O convenio que PERDE a venda fica como esta (a data nunca volta).
-- A LISTA vem antes da escrita: o convenio, a data de antes e a nova (so ids e datas). Na copia, 8 convenios (a
-- pergunta 363, contagem de 07/11/2026). PARA DESFAZER: `UPDATE convenios SET data_ultima_venda = <a de antes, ou
-- NULL> WHERE id = <convenio>;` para cada linha da lista.
--
-- NA COPIA (franquiabv_dev, 07/11/2026, so SELECT de contagem): 15.152 vendas com item do convenio; 1.181 mudariam por
-- estar sem convenio (1.152 concluidas) e 46 por guardar outro (44 concluidas); 13.760 ja estao certas; 38 ficam por
-- citar um nome que nao existe e 127 por citar um nome que dois convenios tem. "Ficam" e "o roteiro nao as toca": das
-- 127, 120 ja guardam um dos convenios desse nome e so 7 estao sem convenio; das 38, 34 estao sem convenio. A linha
-- "sem o convenio na venda" dos Descontos so le as concluidas: o roteiro tira dela 1.152 vendas, e ficam 41 (34 e 7).
--
-- A CONTAGEM VEM ANTES, e a LISTA com o convenio de antes de cada venda (nulo ou o id): o `tee` da linha de cima a
-- guarda, e e o caminho de volta exato. So ids: nenhum nome, telefone nem e-mail.
--
-- IDEMPOTENTE: depois da escrita, toda venda que o roteiro decide ja guarda o convenio do ultimo item; a segunda rodada
-- conta zero a mudar e nao escreve nada. A conferencia no fim refaz a conta do zero (sem a tabela temporaria).
--
-- PARA DESFAZER, pela lista guardada: `UPDATE vendas SET convenio = <o de antes, ou NULL> WHERE id = <venda>;` para
-- cada linha dela.
-- ---------------------------------------------------------------------------

SET NAMES utf8mb4;

-- 1. As vendas com item do convenio: o ultimo item de cada uma, quantos convenios tem o nome dele, e o convenio.
DROP TEMPORARY TABLE IF EXISTS d632_vendas;

CREATE TEMPORARY TABLE d632_vendas AS
SELECT x.venda, x.item AS ultimo_item, x.convenios_do_nome, x.convenio_do_item, v.convenio AS convenio_de_antes, v.status
  FROM (SELECT i.item, i.venda, i.convenios_do_nome, i.convenio_do_item,
               ROW_NUMBER() OVER (PARTITION BY i.venda ORDER BY i.item DESC) AS ordem
          FROM (SELECT vp.id AS item, vp.venda, COUNT(c.id) AS convenios_do_nome, MIN(c.id) AS convenio_do_item
                  FROM vendas_produtos vp
                  LEFT JOIN convenios c
                    ON CAST(vp.desconto_motivo AS BINARY) = CAST(LEFT(CONCAT('Convênio ', c.nome), 100) AS BINARY)
                    OR CAST(LEFT(vp.desconto_motivo, CHAR_LENGTH(c.nome) + 11) AS BINARY) = CAST(CONCAT('Convênio ', c.nome, CHAR(59 USING utf8mb4), ' ') AS BINARY)
                 WHERE CAST(LEFT(vp.desconto_motivo, 9) AS BINARY) = CAST('Convênio ' AS BINARY)
                   AND LOCATE(CAST('CUPOM VIP:' AS BINARY), CAST(vp.desconto_motivo AS BINARY)) = 0
                 GROUP BY vp.id, vp.venda) i) x
  JOIN vendas v ON v.id = x.venda
 WHERE x.ordem = 1;

-- 1b. A "ultima venda" que anda (a 363 (a)): os convenios que recebem venda concluida acertada, com a data da mais
-- nova delas, quando passa da gravada. Lida antes da escrita, com a data de antes.
DROP TEMPORARY TABLE IF EXISTS d632_ultima_venda;

CREATE TEMPORARY TABLE d632_ultima_venda AS
SELECT c.id AS convenio, c.data_ultima_venda AS data_de_antes, n.data_nova
  FROM (
        SELECT a.convenio_do_item AS convenio,
               MAX(v.data_criacao) AS data_nova
          FROM d632_vendas a
          JOIN vendas v ON v.id = a.venda
         WHERE a.convenios_do_nome = 1 AND a.status = 1
           AND (a.convenio_de_antes IS NULL OR a.convenio_de_antes <> a.convenio_do_item)
         GROUP BY a.convenio_do_item) n
  JOIN convenios c ON c.id = n.convenio
 WHERE c.data_ultima_venda IS NULL OR c.data_ultima_venda < n.data_nova;

-- 2. A contagem, antes.
SELECT COUNT(*) AS vendas_com_item_do_convenio,
       COALESCE(SUM(convenios_do_nome = 1 AND convenio_de_antes IS NULL), 0) AS mudam_sem_convenio,
       COALESCE(SUM(convenios_do_nome = 1 AND convenio_de_antes IS NOT NULL AND convenio_de_antes <> convenio_do_item), 0) AS mudam_de_outro,
       COALESCE(SUM(convenios_do_nome = 1 AND convenio_de_antes = convenio_do_item), 0) AS ja_certas,
       COALESCE(SUM(convenios_do_nome = 0), 0) AS ficam_nome_que_nao_existe,
       COALESCE(SUM(convenios_do_nome > 1), 0) AS ficam_nome_de_dois_convenios
  FROM d632_vendas;

-- 3. A lista do que muda, com o convenio de antes (o caminho de volta).
SELECT venda, ultimo_item, convenio_de_antes, convenio_do_item AS convenio_novo, status
  FROM d632_vendas
 WHERE convenios_do_nome = 1 AND (convenio_de_antes IS NULL OR convenio_de_antes <> convenio_do_item)
 ORDER BY venda;

-- 4. A lista a parte: as vendas que ficam, porque o nome do ultimo item nao bate com exatamente um convenio.
SELECT venda, ultimo_item, convenios_do_nome, convenio_de_antes, status
  FROM d632_vendas
 WHERE convenios_do_nome <> 1
 ORDER BY venda;

-- 4b. A lista da "ultima venda" que anda: o convenio, a data de antes e a nova (o caminho de volta).
SELECT convenio, data_de_antes, data_nova
  FROM d632_ultima_venda
 ORDER BY convenio;

-- 5. A escrita: `vendas.convenio`.
UPDATE vendas v
  JOIN d632_vendas a ON a.venda = v.id
   SET v.convenio = a.convenio_do_item
 WHERE a.convenios_do_nome = 1 AND (v.convenio IS NULL OR v.convenio <> a.convenio_do_item);

SELECT ROW_COUNT() AS vendas_acertadas_agora;

-- 5b. A escrita da "ultima venda": so para a frente.
UPDATE convenios c
  JOIN d632_ultima_venda u ON u.convenio = c.id
   SET c.data_ultima_venda = u.data_nova
 WHERE c.data_ultima_venda IS NULL OR c.data_ultima_venda < u.data_nova;

SELECT ROW_COUNT() AS convenios_com_a_ultima_venda_avancada;

-- 5c. A conferencia da "ultima venda". O esperado: 0 atras.
SELECT COUNT(*) AS ultima_venda_atras_depois
  FROM d632_ultima_venda u
  JOIN convenios c ON c.id = u.convenio
 WHERE c.data_ultima_venda IS NULL OR c.data_ultima_venda < u.data_nova;

DROP TEMPORARY TABLE IF EXISTS d632_ultima_venda;
DROP TEMPORARY TABLE IF EXISTS d632_vendas;

-- 6. A conferencia, refeita do zero. O esperado: 0 a mudar.
SELECT COUNT(*) AS vendas_com_item_do_convenio_depois,
       COALESCE(SUM(x.convenios_do_nome = 1 AND (v.convenio IS NULL OR v.convenio <> x.convenio_do_item)), 0) AS a_mudar_depois
  FROM (SELECT i.item, i.venda, i.convenios_do_nome, i.convenio_do_item,
               ROW_NUMBER() OVER (PARTITION BY i.venda ORDER BY i.item DESC) AS ordem
          FROM (SELECT vp.id AS item, vp.venda, COUNT(c.id) AS convenios_do_nome, MIN(c.id) AS convenio_do_item
                  FROM vendas_produtos vp
                  LEFT JOIN convenios c
                    ON CAST(vp.desconto_motivo AS BINARY) = CAST(LEFT(CONCAT('Convênio ', c.nome), 100) AS BINARY)
                    OR CAST(LEFT(vp.desconto_motivo, CHAR_LENGTH(c.nome) + 11) AS BINARY) = CAST(CONCAT('Convênio ', c.nome, CHAR(59 USING utf8mb4), ' ') AS BINARY)
                 WHERE CAST(LEFT(vp.desconto_motivo, 9) AS BINARY) = CAST('Convênio ' AS BINARY)
                   AND LOCATE(CAST('CUPOM VIP:' AS BINARY), CAST(vp.desconto_motivo AS BINARY)) = 0
                 GROUP BY vp.id, vp.venda) i) x
  JOIN vendas v ON v.id = x.venda
 WHERE x.ordem = 1;
