feat(suframa): add isValidSuframa, formatSuframa, parseSuframa and generateSuframa - #559
hyanmandian wants to merge 2 commits into
Conversation
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (6)
Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review. 📝 WalkthroughWalkthroughAdds SUFRAMA parsing, validation, formatting, and generation utilities. The APIs are exported from the package, mapped in JSR, tested, documented in English and Portuguese, and included in the public API contract. ChangesSUFRAMA utilities
Priority: ⬇️ Low Estimated code review effort: 3 (Moderate) | ~25 minutes Change: Feature Merge Risk: ⚪ Minimal · up to The SUFRAMA changes have no remaining actionable merge-blocking issue. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Tree-shaking report✅ No size regression. 4 new out of 161 exports.
What changed (4)
All exports (161)
How this is measuredEvery export is imported alone into an esbuild consumer bundle (minified, tree-shaken) built from the head and from the base of this pull request; the sizes are the resulting bundles, gzip is their gzipped size. 🔴 marks a regression: a pre-existing export that grew more than 20% and more than 256 B, or the bundle importing every pre-existing export growing more than 5%. 🟡 is growth under the threshold, 🟢 a decrease, ⚪ no change, 🆕 an export that does not exist on the base (never a regression), 🗑️ an export that was removed. An intentional increase is accepted with the |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## claude/get-cpf-info #559 +/- ##
=====================================================
Coverage 100.00% 100.00%
=====================================================
Files 187 191 +4
Lines 2077 2094 +17
Branches 614 618 +4
=====================================================
+ Hits 2077 2094 +17
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
cda619f to
c46a785
Compare
|
@coderabbitai review |
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
c46a785 to
91ede6a
Compare
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
commit: |
|
@coderabbitai review |
✅ Action performedReview finished.
|
…nerateSuframa The Inscrição SUFRAMA goes in the ISUF field of the NF-e recipient and a wrong one is rejected by the SEFAZ (rejection 235), so issuers need to check it before sending the document. The rules come from Anexo XII.01 of the NF-e Manual de Orientação do Contribuinte 6.0: the number is SS.NNNN.LLD (sector, sequence, locality, check digit), the field holds 8 or 9 digits because a sector code such as 01 loses its leading zero, the sector code is never 00, and the check digit is módulo 11 with weights 2 to 9 and 0 for a remainder of 0 or 1. That is the existing mod11 "arrecadacao" rule, so no new internal is needed. The manual lists the sector and locality codes only as examples, so they are not validated against a table.
The four utilities cited a SEFAZ-SP copy of the superseded MOC 6.0. The current national manual, MOC 7.0, is published by CONFAZ and says the same in the Visão Geral, section 8.4: the composition SS.NNNN.LLD, the numeric field with 8 or 9 positions whose SS may start with 0 but never be 00, and the módulo 11 check digit with weights 2 to 9. Its Anexo I still types field 79 (E18, ISUF) as numeric with 8 to 9 positions and still rejects an invalid check digit through rule E18-20 (rejection 235), so nothing in the code changes, only the citation. That also answers the open point about MOC 7.0 changing the annex: it does not. The docs never showed what formatSuframa does to an 8 digit value without pad, although 8 positions is a valid ISUF length, so a reader could not see that the mask is progressive and groups one position early. Both docs and the example block now show it next to the padded form. The test that guarded against a 10 digit value was also named after the first 9 digits being valid while its second vector, 1234567090, is the opposite case: 123456709 has check digit 3, not 9, and it is the last 9 digits, 234567090, that are valid. Split into the two named cases.
91ede6a to
5b2b199
Compare
|
@coderabbitai review |
|
What
Adds the Inscrição SUFRAMA family: the registration number the Superintendência da Zona Franca de Manaus gives to companies with tax incentives, carried by the
ISUFfield (E18) of the NF-e recipient. A wrong one is rejected by the SEFAZ with rejection 235.New utilities, modelled on the PIS family:
isValidSuframa,formatSuframa,parseSuframa,generateSuframa. No new internal: the check digit is the existingmod11with the"arrecadacao"rule (weights 2 to 9 from the right, 0 for a remainder of 0 or 1). One shared constant,src/_internals/constants/suframa.ts(SUFRAMA_LENGTH).API
Rules implemented, all from the official source below:
SS.NNNN.LLD: sector of activity, sequential number, locality of the SUFRAMA unit, check digit. Note that this differs from the order in the task description (sequence first): the manual puts the sector first.SSmay start with0(so the number loses it and has 8 digits) but can never be00. An 8 digit value is validated with the zero back in place, so an 8 digit value starting with0is rejected as sector00.11 - remainder, 0 when the remainder is 0 or 1.generateSuframaalways returns the 9 digit form, never with sector00.Sources
SS.NNNN.LLD, "Campo: Numérico, com 8 ou 9 posições / Considerar que "SS" pode começar por "0", mas não pode ser "00"", "D: Dígito Verificador, Módulo 11, Pesos de 2 a 9 / considerar DV=0 se o resto da divisão for "0" ou "1"", and the worked example12345678with sum 156, remainder 2, DV 9. That example is a test vector (123456789).E18ISUFis numeric, occurrence 0-1, size 8-9; validation rule E18-20 "Inscrição com dígito verificador inválido", rejection 235. The SEFAZ itself checks only the check digit.is-valid-nfe-keyandget-nfe-key-info.Verification
npm run check: passnpm run test -- --run/npm run test:coverage: 188 files, 6224 tests pass, 100% statements, branches, functions and linesnpm run test:bun: 6224 pass, 0 fail.npm run test:deno: 6224 passed, 0 failednpm run build: pass (attw and publint clean)npm run check:api:update: report updated and committednpm run check:unused: passnpm run check:duplication: 0 clonesnpm run check:commits: passnpm run test:mutationon the four new source files: 100% (51 killed, 2 timeouts, 0 survived)npm run build:docsandnpm run build:jsr: run, output committed (jsr.jsongains./is-valid-suframa,./format-suframa,./parse-suframaand./generate-suframa)check:tree-shaking(its CI job was broken on every branch rebased past feat: Standard Schema wrapper, JSR, pkg.pr.new, docs previews and a playground #556; fix(build): the document field templates stop breaking the package build #588, now at the bottom of this stack, fixes it, and the job is green here)Re-verified after the rebase onto
claude/get-cpf-info:check,test:coverage(192 files, 6309 tests, 100% statements, branches, functions and lines),build,check:unused,check:duplicationandcheck:commitsall pass on the rebased branch.Rebase onto #558
Rebased onto
claude/get-cpf-infoafter #556 landed onmain. Conflicts resolved:docs/llms.txtanddocs/llms-full.txtare no longer tracked (they are generated now), so both weregit rm-ed.docs/utilities.mdanddocs/pt-br/utilities.mdwas ported into the new per-utility format: a###heading per function, a short paragraph, a bullet list for the options and the edge cases, ajavascriptblock, and one sharedSource:line at the end of the family. The family intro paragraph was folded intoisValidSuframa, and the MOC 7.0 and Anexo I citations moved to thatSource:line.src/index.tsandsrc/index.test.tskept strictly alphabetical.jsr.json(new onmain) regenerated withnpm run build:jsr.Open points
SS) and locality (LL) codes are not validated against a table. The manual lists them only "conforme exemplos abaixo" (01 and 02 Cooperativa, 10 and 11 Comércio, 20 Indústria com Projeto Pleno, 60 Serviços; 01 Manaus, 10 Boa Vista, 30 Porto Velho), and I found no official exhaustive list from SUFRAMA. For the same reason there is nogetSuframaInfoandgenerateSuframauses random sector and locality codes.sintegra.gov.br/insc_suframa.html) returns 404. MOC 7.0 was downloaded from CONFAZ and read: section 8.4 and the Anexo I entries forISUFsay exactly what MOC 6.0 said, so the rules did not change with the new manual.formatSuframamasks progressively likeformatPis, so an 8 digit value needs{ pad: true }to get the leading zero back; without it the separators fall one position early. Both docs and the@exampleblock now show that unpadded output (formatSuframa("10001018"); // "10.0010.18") next to the padded one, since 8 positions is a validISUFlength.Summary by CodeRabbit
New Features
00.0000.000mask and optional zero-padding.Documentation