-- ---------------------------------------------------------------------------
-- O registro da devolucao de credito: `clientes_creditos_devolucoes` (D179; a
-- resposta 89 do dono, a opcao (b), "A (a), e a devolucao sai do caixa aberto como
-- uma retirada", 12/10/2026).
--
--   mysql franquia_producao < scripts/migracao-clientes-creditos-devolucoes.sql
--
-- Roda no laco do passo 0 de `docs/procedimento-de-corte.md`, em PRODUCAO, e no
-- laco da copia do desenvolvimento de `docs/ensaio-geral-do-corte.md`, contra a
-- `franquiabv_dev`; os bancos da suite ja nascem com a tabela (`mysql.sql`, e o
-- `postgres/schema.sql` do gerador). NA COPIA LOCAL DESDE 15/10/2026, nos dois
-- bancos, pela resposta 83 do dono (a opcao (a): o esquema que so acrescenta entra
-- nas duas copias locais quando a resposta pedir), e as duas colunas do D500 desde
-- 16/10/2026, pela resposta 231 (a), que as pede. A base do teste do BVIP fica sem
-- ela ate a proxima copia exportada daqui, pela mao do dono.
--
-- O QUE ELA GUARDA. Devolver credito ao cliente, com a senha do gerente, so baixava
-- o saldo: nao gravava venda, pagamento, saida de caixa, nem quem autorizou e quando,
-- e por isso nenhum extrato explicava o saldo (o D179). Pela resposta 89 do dono,
-- cada devolucao vira uma linha aqui (a opcao (a): "quem autorizou, quem operou,
-- quanto e quando ... e o historico do credito a mostra") e sai do caixa aberto como
-- uma retirada (a (b)):
--
--   cliente,        de quem e o credito, e de que unidade (a da sessao, a mesma
--   unidade         linha de `clientes_creditos` que a devolucao baixa);
--   valor           quanto saiu;
--   autorizado_por  o gerente que confirmou com a senha (chave estrangeira para
--                   `usuarios`, como `pontuacoes_historicos.autorizado_por`);
--   gravado_por,    quem operou, como na vigencia do horario e em Contas a Pagar
--   em_nome_de      (`CrudController::autorDaEscrita`): quem entrou na sessao, e a
--                   pessoa assumida so quando difere. Inteiro sem chave estrangeira,
--                   como la;
--   retirada        a retirada do caixa aberto por onde o dinheiro saiu
--                   (`caixas_retiradas`);
--   data_criacao    quando;
--   desfeita_por,   quem desfez a devolucao e quando (16/10/2026, o D500; a resposta
--   desfeita_em     231 do dono, a opcao (a): "cancelar a retirada da devolucao desfaz
--                   a devolucao -- o credito volta ao cliente, e o registro fica
--                   marcado como desfeito, com quem desfez e quando"). Cancelar a
--                   retirada no caixa devolve o credito e as preenche; nulas, a
--                   devolucao vale. Quem desfez e quem entrou na sessao
--                   (`CrudController::autorDaEscrita`), inteiro sem chave estrangeira,
--                   como `gravado_por`.
--
-- NASCE VAZIA: nenhum saldo do passado muda, e o saldo de hoje e o ponto de partida
-- (a resposta 89). So ganha linhas; nada aqui as apaga.
--
-- IDEMPOTENTE: `CREATE TABLE IF NOT EXISTS`. O DDL e o mesmo do `mysql.sql` (menos o
-- `AUTO_INCREMENT=1`), e o portao do passo 0 compara os dois. E A TABELA QUE JA EXISTE
-- SEM AS DUAS COLUNAS DO D500 (as duas copias locais, criadas em 15/10/2026, antes
-- delas) as recebe pelo `ALTER` depois do `CREATE`, so se a primeira delas nao existir
-- -- o molde de `migracao-saidas-motivos-e-autores.sql`: as duas num `ALTER` so, que no
-- InnoDB e atomico, e `ALGORITHM=INSTANT` (so o dicionario; a tabela nao e copiada). Em
-- producao a tabela nasce do `CREATE` ja com elas, e o `ALTER` diz que nada ha a fazer.
--
-- ---------------------------------------------------------------------------
-- 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 a tabela la,
-- ela some do `mysql.sql` e do `schema.sql`, e a devolucao volta a nao deixar
-- registro: o codigo pergunta se ela existe (`ISBase\Doctrine\ColunaNoBanco`) e, sem
-- ela, devolve e tira do caixa como retirada -- a retirada leva o motivo, com o
-- cliente --, sem quebrar e sem a linha daqui.
--
-- PARA O CODIGO DE PRODUCAO A TABELA VAZIA E INOFENSIVA: ele nao a le nem a escreve.
-- Cria-la nao copia tabela nenhuma; as chaves estrangeiras so pedem uma trava curta
-- de metadados em `clientes`, `unidades`, `usuarios` e `caixas_retiradas`.
-- ---------------------------------------------------------------------------

CREATE TABLE IF NOT EXISTS `clientes_creditos_devolucoes` (
  `id` int NOT NULL AUTO_INCREMENT,
  `cliente` int NOT NULL,
  `unidade` int NOT NULL,
  `valor` double NOT NULL,
  `autorizado_por` int NOT NULL COMMENT 'O gerente que confirmou a devolucao com a senha',
  `gravado_por` int DEFAULT NULL COMMENT 'Quem operou: quem entrou na sessao (CrudController::autorDaEscrita)',
  `em_nome_de` int DEFAULT NULL COMMENT 'A pessoa da sessao, so quando difere de gravado_por (personificacao)',
  `retirada` int NOT NULL COMMENT 'A retirada do caixa aberto por onde o dinheiro saiu',
  `data_criacao` datetime NOT NULL,
  `desfeita_por` int DEFAULT NULL COMMENT 'Quem desfez a devolucao, cancelando a retirada no caixa (CrudController::autorDaEscrita); nulo enquanto ela vale (D500)',
  `desfeita_em` datetime DEFAULT NULL COMMENT 'Quando a devolucao foi desfeita; nulo enquanto ela vale (D500)',
  PRIMARY KEY (`id`),
  KEY `FK_CLIENTES_CREDITOS_DEVOLUCOES_cliente` (`cliente`,`unidade`),
  KEY `FK_CLIENTES_CREDITOS_DEVOLUCOES_unidade` (`unidade`),
  KEY `FK_CLIENTES_CREDITOS_DEVOLUCOES_autorizado_por` (`autorizado_por`),
  KEY `FK_CLIENTES_CREDITOS_DEVOLUCOES_retirada` (`retirada`),
  CONSTRAINT `FK_CLIENTES_CREDITOS_DEVOLUCOES_autorizado_por` FOREIGN KEY (`autorizado_por`) REFERENCES `usuarios` (`id`),
  CONSTRAINT `FK_CLIENTES_CREDITOS_DEVOLUCOES_cliente` FOREIGN KEY (`cliente`) REFERENCES `clientes` (`id`),
  CONSTRAINT `FK_CLIENTES_CREDITOS_DEVOLUCOES_retirada` FOREIGN KEY (`retirada`) REFERENCES `caixas_retiradas` (`id`),
  CONSTRAINT `FK_CLIENTES_CREDITOS_DEVOLUCOES_unidade` FOREIGN KEY (`unidade`) REFERENCES `unidades` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

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

SET @sql = IF(@existe = 0,
    'ALTER TABLE clientes_creditos_devolucoes
       ADD COLUMN desfeita_por int DEFAULT NULL
       COMMENT ''Quem desfez a devolucao, cancelando a retirada no caixa (CrudController::autorDaEscrita); nulo enquanto ela vale (D500)''
       AFTER data_criacao,
       ADD COLUMN desfeita_em datetime DEFAULT NULL
       COMMENT ''Quando a devolucao foi desfeita; nulo enquanto ela vale (D500)''
       AFTER desfeita_por,
       ALGORITHM=INSTANT',
    'SELECT ''clientes_creditos_devolucoes: colunas do D500 ja existem, nada a fazer'' AS aviso'
);

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

-- Conferencia. O esperado: a tabela, com a chave primaria e os quatro indices.
SELECT index_name                                         AS indice,
       GROUP_CONCAT(column_name ORDER BY seq_in_index)    AS colunas,
       MAX(non_unique)                                    AS nao_unico
  FROM information_schema.statistics
 WHERE table_schema = DATABASE()
   AND table_name = 'clientes_creditos_devolucoes'
 GROUP BY index_name
 ORDER BY index_name;

-- E as duas colunas do D500, com as devolucoes que ja estao desfeitas. Antes do codigo
-- novo no ar, o esperado e `desfeita_por` e `desfeita_em`, as duas anulaveis, e nenhuma
-- devolucao desfeita.
SELECT column_name                                        AS coluna,
       column_type                                        AS tipo,
       is_nullable                                        AS anulavel
  FROM information_schema.columns
 WHERE table_schema = DATABASE()
   AND table_name = 'clientes_creditos_devolucoes'
   AND column_name IN ('desfeita_por', 'desfeita_em')
 ORDER BY ordinal_position;

SELECT (SELECT COUNT(*) FROM clientes_creditos_devolucoes)                            AS devolucoes,
       (SELECT COUNT(*) FROM clientes_creditos_devolucoes WHERE desfeita_em IS NOT NULL) AS desfeitas;
