Files
GTI_GERENCIADOR_FISCAL/scripts/build_operator_company_questions.py
T

59 lines
6.5 KiB
Python

"""docs/OPERATOR_COMPANY_QUESTIONS_V1.md: ONLY company-wide decisions (category C) in plain Portuguese, plus the residual counts. Read-only over the state files."""
import gzip, json, pickle, sys
from collections import Counter
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]; ST = ROOT / "docs/runs/local_completion"
DBS = ["CONSTRUCAO", "MMMODAS", "RINCAO", "UNIAO", "TESTESOFICIAIS"]
Q = json.loads((ROOT / "docs/LOCAL_FISCAL_CONTEXT_QUESTIONS_V2.json").read_text(encoding="utf-8"))["questions"]
summ = {n: json.loads((ST / f"{n}_dryrun_summary.json").read_text(encoding="utf-8")) for n in DBS}
ipi_cells, entry_dist, rows_n = {}, {}, {}
for n in DBS:
snap = pickle.load(gzip.open(ST / f"{n}_before.pkl.gz", "rb")); cols = snap["columns"]
ipi_cells[n] = 0; rows_n[n] = len(snap["rows"])
for l in gzip.open(ST / f"{n}_second.ndjson.gz", "rt", encoding="utf-8"):
r = json.loads(l)
if r["field"] == "IPI" and r["status"] == "ALREADY_CORRECT" and r["before"] not in (None, ""):
ipi_cells[n] += 1
entry_dist[n] = Counter((r[cols.index("CFOP_ENTRADA")] or "").strip()[:1] or "(vazio)" for r in snap["rows"].values())
crt = {n: summ[n]["company"]["crt"] for n in DBS}
by = lambda key: [q for q in Q if q["KEY"] == key and q["CATEGORY"] == "C"] # noqa: E731
regime = {"1": "Simples Nacional", "3": "Regime normal (Lucro Presumido/Real)"}
out = ["# Perguntas de empresa — respostas necessárias ANTES da camada de IA", "",
"Só entram decisões que valem para a **empresa inteira**. Nada aqui é preenchido automaticamente: sem resposta, as células continuam pendentes.",
"Como responder: preencher a coluna `VALUE` da linha do mesmo QUESTION_ID em `docs/LOCAL_FISCAL_CONTEXT_QUESTIONS_V2.csv` e importar com `scripts/import_fiscal_context.py`.", ""]
n_q = 0; cells_total = 0
def block(qid, banco, pergunta, opcoes, rec, prods, cells, expl):
global n_q, cells_total
n_q += 1; cells_total += cells
out.extend([f"### {qid} — {banco}", f"- **Pergunta:** {pergunta}", f"- **Opções:** {opcoes}", f"- **Recomendação:** {rec}", f"- **Produtos afetados:** {prods}", f"- **Células afetadas:** {cells}", f"- **Explicação:** {expl}", ""])
out.append("## 1. Perfil de PIS/COFINS (por empresa)")
for q in by("pis_cofins_profile"):
n = q["DATABASE"]
block(q["QUESTION_ID"], f"{n} ({regime.get(crt[n], crt[n])})", "Qual o enquadramento de PIS/COFINS desta empresa para produtos que NÃO estão em regime especial (monofásico, alíquota zero, etc.)?",
"JSON com pis_in_cst, pis_out_cst, pis_rate, cofins_in_cst, cofins_out_cst, cofins_rate (CSTs da tabela oficial 4.3.3/4.3.4). Ex. regime não cumulativo: saída 01, alíquotas 1,65 / 7,6; cumulativo: 0,65 / 3,0",
"nenhuma provada (depende do regime tributário real da empresa: cumulativo ou não cumulativo, dado que só o contador confirma)", q["PRODUCTS_AFFECTED"], q["CELLS"],
"A tabela oficial da Receita já resolveu os produtos em regime especial; os demais dependem do enquadramento da empresa. " + ("Nesta base o SGV não usa estes campos na emissão (100% dos itens de NFC-e saíram sem CST de PIS/COFINS); a resposta só completa poucos produtos com valor inválido no cadastro." if summ[n]["company"].get("pis_cofins_unused_by_emission") else "O histórico de NFC-e desta base emite CST de PIS/COFINS preenchido, então o campo do produto é usado na emissão."))
out.append("## 2. Escopo das compras (CFOP de entrada)")
for q in by("entry_scope"):
n = q["DATABASE"]; d = entry_dist[n]; tot = sum(d.values())
block(q["QUESTION_ID"], f"{n}", "As compras de mercadoria desta empresa são, em regra, dentro do estado (INTRA, CFOP 1xxx) ou de outro estado (INTER, CFOP 2xxx)?",
"INTRA | INTER", f"nenhuma provada. Só informativo: nos cadastros existentes desta base, CFOP de entrada 1xxx = {d.get('1', 0)}, 2xxx = {d.get('2', 0)}, vazio = {d.get('(vazio)', 0)} de {tot} produtos (declarações históricas, não prova de regra)",
q["PRODUCTS_AFFECTED"], q["CELLS"], "Só é usado nos produtos cujo CFOP de entrada está vazio. Produtos que já têm CFOP de entrada válido não são alterados.")
out.append("## 3. Alíquota padrão de ICMS")
for q in by("icms_rate"):
block(q["QUESTION_ID"], q["DATABASE"], "Qual a alíquota interna de ICMS padrão desta empresa (regime normal)?", "número em % (ex.: 20,5)", "nenhuma provada (a alíquota depende da mercadoria; não vale 20,5% universal)", q["PRODUCTS_AFFECTED"], q["CELLS"],
"Um único produto da base de testes depende desta resposta. As demais empresas são Simples Nacional e não destacam ICMS: não perguntado.")
out.append("## 4. IPI no cadastro de empresa varejista (STORE_IPI_PROFILE)")
out.append("Evidência do próprio SGV: em TODAS as bases `CONTRIBUINTE_IPI = N`; 745 itens vendidos na base de testes de produtos com alíquota de IPI cadastrada geraram IPI = 0 (nenhum valor de IPI foi calculado), e mais de 1,6 milhão de itens vendidos nas demais bases também têm IPI 0. O campo do cadastro é, portanto, apenas referência para empresa não contribuinte. **O SGV não impõe preencher.** Decisão de política:")
out.append("")
for n in DBS:
n_q += 1; cells_total += ipi_cells[n]
out.extend([f"### QIPI-{n} — {n}", "- **Pergunta:** Guardar no cadastro dos produtos a alíquota oficial da TIPI como referência (mesmo a empresa não sendo indústria/importadora)?", "- **Opções:** `POPULATE_REFERENCE_RATE` (guardar) | `LEAVE_NOT_APPLICABLE` (deixar em branco)",
"- **Recomendação:** nenhuma (é política da empresa; ambas as opções são válidas)", f"- **Produtos afetados:** {ipi_cells[n]}", f"- **Células afetadas:** {ipi_cells[n]} (já gravadas com o valor oficial; se responder LEAVE_NOT_APPLICABLE, serão revertidas com `scripts/rollback_field.py`)",
"- **Explicação:** enquanto não houver resposta, nenhum novo valor de IPI é gravado. Chave: `store_ipi_profile` (escopo COMPANY).", ""])
out.append("## 5. Origem da mercadoria — NÃO é decisão de empresa")
out.append("A origem (0 a 8) é atributo real de cada mercadoria e o ERP não a registra em lugar nenhum (o primeiro dígito do CST é só preenchimento). **Não existe uma resposta padrão de empresa** e nenhum valor será assumido. Só responda por GRUPO/PRODUTO quando puder garantir (ex.: grupo inteiro de importados = 1). Essas perguntas continuam nos arquivos V2, fora desta lista.")
out += ["", f"**Total desta lista: {n_q} perguntas de empresa.**"]
(ROOT / "docs/OPERATOR_COMPANY_QUESTIONS_V1.md").write_text("\n".join(out) + "\n", encoding="utf-8")
print(n_q, cells_total)