diff options
| author | Murilo Ijanc <[email protected]> | 2026-07-27 20:39:38 -0300 |
|---|---|---|
| committer | Murilo Ijanc <[email protected]> | 2026-07-27 20:39:38 -0300 |
| commit | 4014037e505876ed8c4df229ace3a65092e64ca8 (patch) | |
| tree | 367a84c87c75df41fb7218604a3a7d0260cd6cb5 /src/cepis-lookup.cob | |
| parent | f979d07d23098b96e758b3feb555cd06d85d9b2d (diff) | |
| download | cobol-0.2.0.tar.gz | |
A CEP that fails is rarely a random number: it is someone who knows the
city and guessed the digits, and the classic guess is the -000 that 957
municipalities never received. The API now attaches that municipality to
the 404, and a caller left with nothing but "does not exist" cannot tell
a typo in a real city from a CEP that was never plausible.
It goes in CEPIS-STATUS, not CEPIS-ADDRESS. The call has still failed
and the address is still empty; putting a localidade where the address
lives would let a caller that forgets to test the status read Areal as
the answer to a CEP that does not exist.
Parsing is best effort throughout. faixa is omitted rather than sent as
null for a band no municipality owns, so its absence is the normal case
and there is a flag instead of a marker value; a block that is missing,
is not an object, or is short of localidade, uf, cep_ini, cep_fim and
ceps is dropped and the not-found comes back clean. Failing a 404 the
caller already understands over a decoration on it would be a poor
trade.
cep_ini and cep_fim are the CEPs that exist, not the bounds the Correios
publish, and the span between them is mostly empty -- hence ceps beside
them, so the pair is not read as a list.
Diffstat (limited to 'src/cepis-lookup.cob')
| -rw-r--r-- | src/cepis-lookup.cob | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/cepis-lookup.cob b/src/cepis-lookup.cob index cc6e412..90f1502 100644 --- a/src/cepis-lookup.cob +++ b/src/cepis-lookup.cob @@ -22,6 +22,13 @@ PROGRAM-ID. CEPIS-LOOKUP. *> means the CEP is a whole municipality and the point is its centroid, *> with a radius of 7 to 40 km. Computing shipping from the second is *> wrong by tens of kilometres. +*> +*> A CEPIS-NOT-FOUND may come back with CEPIS-FAIXA filled: the +*> municipality the CEP would have belonged to. A CEP that fails is +*> rarely a random number -- it is usually someone who knows the city and +*> guessed the digits, and the classic guess is the -000 that 957 +*> municipalities never received. The lookup has still failed and the +*> address is still empty; CEPIS-FAIXA only names where the guess landed. *> --------------------------------------------------------------------- DATA DIVISION. @@ -38,6 +45,17 @@ COPY "cepis-json.cpy". 01 WS-LON PIC S9(3)V9(6). 01 WS-RAIO PIC 9(9). 01 WS-PRECISAO PIC X(16). +01 WS-FAIXA-FROM PIC 9(9). +01 WS-FAIXA-TO PIC 9(9). +01 WS-FAIXA-OK PIC X. +01 WS-F-LOCALIDADE PIC X(100). +01 WS-F-UF PIC X(2). +01 WS-F-ESTADO PIC X(60). +01 WS-F-REGIAO PIC X(30). +01 WS-F-IBGE PIC X(10). +01 WS-F-CEP-INI PIC X(8). +01 WS-F-CEP-FIM PIC X(8). +01 WS-F-CEPS PIC 9(9). 01 WS-I PIC 9(4). 01 WS-C PIC X. 01 WS-DOTS PIC 9(4). @@ -82,6 +100,7 @@ MAIN-START. STRING "CEP " WS-CEP " does not exist in the DNE database" DELIMITED BY SIZE INTO CEPIS-STATUS-MESSAGE END-STRING + PERFORM PARSE-FAIXA WHEN 400 SET CEPIS-INVALID-CEP TO TRUE PERFORM API-MESSAGE @@ -133,6 +152,13 @@ GET-GEO-MEMBER. END-CALL. *> ------------------------------------------------------------------- +GET-FAIXA-MEMBER. + MOVE WS-FAIXA-FROM TO JS-FROM + MOVE WS-FAIXA-TO TO JS-TO + CALL "CEPIS-JSON-GET" USING HTTP-BODY CEPIS-JSON-SCAN + END-CALL. + +*> ------------------------------------------------------------------- PARSE-ADDRESS. MOVE "cep" TO JS-KEY PERFORM GET-MEMBER @@ -290,6 +316,115 @@ PARSE-GEO. END-IF. *> ------------------------------------------------------------------- +*> The 404 body may name the municipality the CEP would have belonged +*> to. It is context for the error and nothing else: the status stays +*> CEPIS-NOT-FOUND and CEPIS-ADDRESS stays empty, because a CEP that the +*> DNE does not have is not an address no matter which city it is near. +*> +*> "faixa" is omitted -- never sent as null -- when the CEP falls in a +*> band no municipality owns, so its absence is the normal case, not an +*> error. Everything here is therefore best effort: a faixa that is +*> missing, is not an object, or is short of the members below is +*> dropped, and the caller still gets a clean not-found. Turning a 404 +*> the caller already understands into CEPIS-INVALID-RESPONSE over a +*> decoration would be a poor trade. +*> +*> cep_ini and cep_fim must both be eight digits and ceps must be a +*> number, or the whole block is dropped. The span is sparse -- Areal's +*> 118 CEPs are spread over the ~4900 numbers between 25845001 and +*> 25849899 -- so handing a caller the pair without the count invites +*> reading it as a list of valid CEPs, which it is not. +PARSE-FAIXA. + INITIALIZE CEPIS-FAIXA + SET CEPIS-FAIXA-ABSENT TO TRUE + MOVE "faixa" TO JS-KEY + PERFORM GET-MEMBER + IF JS-TYPE NOT = "O" + EXIT PARAGRAPH + END-IF + MOVE JS-VSTART TO WS-FAIXA-FROM + MOVE JS-VEND TO WS-FAIXA-TO + MOVE "Y" TO WS-FAIXA-OK + + MOVE "localidade" TO JS-KEY + PERFORM GET-FAIXA-MEMBER + IF JS-TYPE = "S" AND JS-VALUE-LEN > 0 + MOVE JS-VALUE TO WS-F-LOCALIDADE + ELSE + MOVE "N" TO WS-FAIXA-OK + END-IF + + MOVE "uf" TO JS-KEY + PERFORM GET-FAIXA-MEMBER + IF JS-TYPE = "S" AND JS-VALUE-LEN = 2 + MOVE JS-VALUE TO WS-F-UF + ELSE + MOVE "N" TO WS-FAIXA-OK + END-IF + + MOVE "cep_ini" TO JS-KEY + PERFORM GET-FAIXA-MEMBER + IF JS-TYPE = "S" AND JS-VALUE-LEN = 8 + MOVE JS-VALUE TO WS-F-CEP-INI + ELSE + MOVE "N" TO WS-FAIXA-OK + END-IF + + MOVE "cep_fim" TO JS-KEY + PERFORM GET-FAIXA-MEMBER + IF JS-TYPE = "S" AND JS-VALUE-LEN = 8 + MOVE JS-VALUE TO WS-F-CEP-FIM + ELSE + MOVE "N" TO WS-FAIXA-OK + END-IF + + MOVE "ceps" TO JS-KEY + PERFORM GET-FAIXA-MEMBER + PERFORM CHECK-NUMERIC + IF WS-NUM-OK = "Y" + COMPUTE WS-F-CEPS ROUNDED = FUNCTION NUMVAL (JS-VALUE) + ELSE + MOVE "N" TO WS-FAIXA-OK + END-IF + + IF WS-FAIXA-OK NOT = "Y" + EXIT PARAGRAPH + END-IF + + *> The three below are decoration: a faixa the API sends without + *> them still names the municipality, so they never fail the block. + MOVE SPACES TO WS-F-ESTADO + MOVE "estado" TO JS-KEY + PERFORM GET-FAIXA-MEMBER + IF JS-TYPE = "S" + MOVE JS-VALUE TO WS-F-ESTADO + END-IF + + MOVE SPACES TO WS-F-REGIAO + MOVE "regiao" TO JS-KEY + PERFORM GET-FAIXA-MEMBER + IF JS-TYPE = "S" + MOVE JS-VALUE TO WS-F-REGIAO + END-IF + + MOVE SPACES TO WS-F-IBGE + MOVE "ibge" TO JS-KEY + PERFORM GET-FAIXA-MEMBER + IF JS-TYPE = "S" + MOVE JS-VALUE TO WS-F-IBGE + END-IF + + SET CEPIS-FAIXA-KNOWN TO TRUE + MOVE WS-F-LOCALIDADE TO CEPIS-FAIXA-LOCALIDADE + MOVE WS-F-UF TO CEPIS-FAIXA-UF + MOVE WS-F-ESTADO TO CEPIS-FAIXA-ESTADO + MOVE WS-F-REGIAO TO CEPIS-FAIXA-REGIAO + MOVE WS-F-IBGE TO CEPIS-FAIXA-IBGE + MOVE WS-F-CEP-INI TO CEPIS-FAIXA-CEP-INI + MOVE WS-F-CEP-FIM TO CEPIS-FAIXA-CEP-FIM + MOVE WS-F-CEPS TO CEPIS-FAIXA-CEPS. + +*> ------------------------------------------------------------------- *> FUNCTION NUMVAL answers 0 for text it cannot read, which would turn *> "lat": "not a number" into a coordinate off the coast of Africa. The *> text is therefore checked before it is converted. |