Runtime Flow
Main flow (Motor → NF → Items → Validations)
1) ImpostoMotor.Processar()
File: Models/ImpostoMotor.cs
Observed behavior:
- If
NotaFiscalhas not been instantiated yet, it returns without processing - Otherwise, it calls:
NotaFiscal.Processar()NotaFiscal.ValidationPipes().Validate()
2) NotaFiscal.Processar()
File: Models/NotaFiscal.cs
Observed behavior:
- Runs preconditions through
DoAssert():Emitente.RegimeTributariomust not beNotDefinedDestinatario.ContribuinteIcmsmust not beNotDefinedTotalProdutosNFmust be> 0
- If there are items added via
AddProduto(), it processes all and applies difference adjustment:- Processes each item by calling
Produto.Processar() - Selects the highest-total item (
AsTotalProduto()) and callsProcessarDiffRateio()on it
- Processes each item by calling
- Otherwise, it processes the single
Produto(if available)
3) Produto.Processar()
File: Models/Produto.cs
Observed behavior:
- Runs preconditions through
DoAssert():PrecoUnitario > 0Quantidade > 0Cfop > 0
- Applies product validation rule (by CFOP and other validations):
new RegraProdutoValidar(this).Validar()
- Processes item allocations (proportional to item gross value over
TotalProdutosNF) - Processes taxes:
ProcessarImpostos()(método interno doProduto)
Allocation and difference adjustment
Proportional allocation
Observed allocation pattern (example):
freteRateio = ValorBrutoItem * (FreteEmbutidoNF / TotalProdutosNF)
This pattern appears for embedded freight, insurance, ancillary expenses, surcharge, discount, and other fields.
Difference adjustment (ProcessarDiffRateio)
When multiple items exist:
- The invoice selects the item with highest
AsTotalProduto() - On that item, it runs “diff” routines to adjust possible differences caused by rounding/truncation in allocations
Difference adjustment is inferred from code structure (name and invocation). Exact behavior depends on internal
ProcessarDiff*routines inProduto.
Validations
The validation pipeline (Validations/ValidationPipes.cs) works as follows:
- Rules/validators add entries through
ValidationPipes.Add() - At the end of
Motor.Processar(), the pipeline executes all validators and accumulates failure messages - Consumers can read messages through
NotaFiscal.ValidationPipes().ListMessages()