The runner
runCertification does the whole HTML side of the certification in the order the SII expects it, and resumes from a store: run it again after a fix and it continues where the saved state says, without repeating what already stands. Under it, every step is a function you can call on its own (sendTestSet, declareTestSets, runBooks…), and so is every portal operation (downloadTestSet, declareProgress, readProgress…).
Nothing here has been run against the portals yet. The tests use synthetic pages, so every page shape is still unproven. For your first enrolled run, keep the artefacts the store writes (every portal answer is there) as fixtures. See Status.
Two things cannot be undone. Downloading the test set again regenerates it
at the SII and voids everything sent for the earlier one. The declaration of
compliance is the sworn statement of the legal representative: the runner
makes it only with declareCompliance: true. Without that option the run ends
at the stop compliance.
Basic usage#
import { readFileSync } from 'node:fs'
import { createSiiClient, loadCertificateFromPkcs12 } from 'dte-sdk'
import { createDirectoryFolioRegistry } from 'dte-sdk/node'
import { createPortalClient, createDirectoryCertificationStore, runCertification } from 'dte-sdk/portal'
import { readPrintedSamples } from 'dte-sdk/pdf'
const certificate = loadCertificateFromPkcs12(readFileSync('firma.pfx'), process.env.PFX_PASSWORD!)
const companyRut = '76543210-3'
const deps = {
portal: createPortalClient({ environment: 'certification', certificate, companyRut }),
sii: createSiiClient({ environment: 'certification', certificate, companyRut }),
store: createDirectoryCertificationStore({ dir: './certification' }), // state.json and the artefacts; holds CAF keys
registry: createDirectoryFolioRegistry({ dir: './folios' }),
issuer: { rut: companyRut, businessName: 'Comercial Andina SpA', address: 'Av. Los Aromos 1540' },
certificate,
// receiver: the test receiver 66666666-6 by default
// resolution: number 0 with the UTC date of the day the run starts, by default
onProgress: (event) => console.log(event.step),
}
// First run: downloads the test set, gets the folios, sends and declares the four sets,
// the books, the simulation, answers the exchange, then stops until the samples are given
const first = await runCertification(deps)
first.stopped // 'printedSamples' when everything went well
// Second run: uploads the samples and stops at `compliance`: the sworn statement needs an explicit go
const second = await runCertification(deps, { samples: () => readPrintedSamples('./certification/samples') })
second.stopped // 'compliance'
// Third run, once you have read the pages the store kept and you are sure
const third = await runCertification(deps, { declareCompliance: true })
third.stopped // 'done'Run it again after any stop that is not done. A refusal, a block or a time-out comes back as data (stopped, detail) with the state saved, so you can read it, fix the cause and run again. An error thrown by the portal, the SII or the folios propagates after the state is saved, with a CERT_ERROR event.
Dependencies#
runCertification(dependencies, options) takes a CertificationDependencies. Every step function takes the same object.
| Field | Meaning |
|---|---|
portal | PortalClient on the certification environment (createPortalClient) |
sii | SiiClient on the certification environment (createSiiClient) |
store | The CertificationStore where state and artefacts live |
registry | The folio registry: createDirectoryFolioRegistry (dte-sdk/node) or createMemoryFolioRegistry |
issuer | The company: rut, businessName and address are required. The line of business, activity code, commune and city take defaults |
certificate | The signing certificate |
receiver | Optional, field by field: the test receiver by default |
resolution | Optional { number, date }: number 0 and the UTC date of the run's day by default |
now | Clock. Dates the run writes for the SII are Chile dates of it |
sleep | Wait function. The real waits by default; inject one to test without waiting |
onProgress | Receives every CertificationProgressEvent |
contact | The contact (name, mail, phone) the exchange answers name |
Options and result#
| Option | Meaning |
|---|---|
until | A CertificationStage: stop once that stage is complete |
optionalSets | The optional sets to tick when downloading, as SETnn codes. DEFAULT_OPTIONAL_SETS by default |
declareCompliance | Make the declaration of compliance. Off by default |
exchangeSetXml | The exchange set, when you downloaded it by hand |
samples | The PDFs to upload, or a function that returns them (readPrintedSamples). Without it the run stops at printedSamples |
runCertification returns { state, stopped, detail? }: the state as saved, why it stopped, and a word or sentence on why.
stopped | Meaning |
|---|---|
done | The declaration of compliance was made |
compliance | Everything is done up to the declaration, which waits for declareCompliance: true |
printedSamples | The samples are waiting for the samples option |
exchange | The exchange set could not be downloaded, or the company is not in the exchange stage. detail says which: see Exchange and samples |
until | The stage you asked to stop at is complete |
rejected | The SII or the portal refused: a declaration that was not taken, a set or the simulation rejected, a review rejected, or a portal that did not move past the books. detail carries its sentence |
blocked | The portal says the application is not at the stage (the samples, or the final declaration). detail carries its sentence |
timedOut | A wait ran out without an answer |
incomplete | A mandatory book could not be sent |
The order of the run#
Test sets
The test set is downloaded once (when the state holds no plan), parsed and
planned. The run gets the folios it needs, then issues and sends each set the
plan holds and the state has not sent yet, in the order basic, guide,
exempt, purchase. It declares the four track ids and waits for the approval.
Books
The purchase, sales and guide books (and the exempt purchase book when the test set brought one) are built, sent, declared and awaited. With the three mandatory books sent, the run asks the portal for the next stage.
Simulation
Fresh folios, every case issued again in one envelope, sent, declared and confirmed.
Exchange
The exchange set is downloaded (or given), answered with three signed files, uploaded and confirmed.
Printed samples
The PDFs in samples go up as a review, which is submitted and read again.
Without samples the run stops here.
Compliance
The declaration of compliance, only with declareCompliance: true.
until is checked between stages: the run returns until as soon as the saved stage is later than the one you asked for.
Resuming from the store#
The state records where the run stands (stage), so a run starts at the stage it saved. Within it nothing is repeated:
- a set with a track id is not sent again, and the test set is not downloaded again while the state holds a plan;
- a simulation that is confirmed is not declared again, a confirmed exchange is not answered again, and a review already submitted is not uploaded again;
- the books phase is the exception: it starts over on every run, and which books stand approved is what the portal shows, not what the state remembers. See The books phase.
An error that stops a step leaves the state as saved by the last thing that succeeded. Every CAF obtained is saved at once, so a step that ends short of folios leaves them in hand for the next attempt instead of asking the SII for them again.
Every step on its own#
Each step takes the dependencies and the state and returns { state, outcome, detail? } with the state it saved. Use them after the SII rejected a set with observations, to redo one piece without running the rest:
let state = (await deps.store.load())!
state = (await sendTestSet(deps, state, { kind: 'basic' })).state
state = (await declareTestSets(deps, state)).state| Step | What it does | Outcomes |
|---|---|---|
obtainTestSet | Downloads the test set, parses it, plans it and keeps the text and the plan as artefacts. Downloading regenerates the set at the SII: a state that already had a plan starts over (everything sent is void), keeping only its CAFs and used folios | loaded, regenerated |
prepareFolios | Makes sure the run holds the folios each type needs. See Folios | ready (and the cafs to issue with) |
sendTestSet | Issues one set with the registry's folios, keeps the envelope and every document as artefacts, uploads it, marks the folios sent whatever happened, and records the track id and Chile date | sent. Throws on a refusal |
declareTestSets | Declares the sets sent so far with today's Chile date, and keeps any diagnosis | A DeclarationOutcome, plus success |
waitForTestSetsApproval | Polls the progress page until the sets are approved | approved, rejected, timedOut |
runBooks | The books phase | approved, incomplete, rejected, timedOut |
advanceToNextStage | Asks the portal for the stage after the books | advanced, unchanged, failed, timedOut |
sendSimulation | Gets fresh folios (never the sets' CAFs), issues and sends the simulation | sent |
declareSimulation | Declares the simulation, unless the portal already names the exchange as the stage | A DeclarationOutcome or skipped, plus success |
waitForSimulationApproval | Polls until the simulation is approved and confirmed | done, confirmed, rejected, timedOut |
runExchange | The exchange stage | done, alreadyDone, setUnavailable, notInExchange |
uploadPrintedSamples | The printed samples stage | submitted, alreadySubmitted, blocked, rejected |
declareComplianceFinal | One more request to advance, then the declaration of compliance | declared, blocked |
Details that matter when you call them alone:
sendTestSetthrowsMISSING_FIELD(plan) without the set's plan. When the upload fails it still marks the folios as sent in the registry (a time-out may have delivered the envelope, and a folio sent twice rejects the next envelope) and emitsSET_ERROR.declareTestSetsthrowsMISSING_FIELD(sets) when nothing was sent.sendSimulationanddeclareSimulationthrowMISSING_FIELD(plan,simulation) when their input is missing.declareComplianceFinalthrowsSII_PORTAL_UNEXPECTED_PAGEwhen the last page does not confirm. See The compliance stop.setFolioNeeds,simulationFolioNeeds,previousPeriodandnextFreePeriodare exported helpers of the folio and books steps.
The portal operations beneath#
The steps are built on these functions of dte-sdk/portal. Each takes the PortalClient first and, as a last argument, optional call overrides.
| Operation | What it does |
|---|---|
downloadTestSet(portal, { optionalSets, download, previousAttentionNumber }) | Generates and downloads the test set. Returns its text, attention number and whether it was regenerated. With download: false it only reads the state table. Throws SII_PORTAL_REJECTED with notEnrolled for a company that is not enrolled |
queryCertificationSets(portal) | Reads the state of every set and book, and whether the required ones are approved |
declareProgress(portal, { entries }) | Declares track ids and dates. See Declarations |
readProgress(portal) | Reads the progress page: the stage, the state of each set and book, whether the simulation awaits confirmation |
advanceStage(portal) | Asks for the next stage: advanced, unchanged (the portal says it is already there) or failed, with the sentence |
listBookHistory(portal, { year }) | Lists the books the SII holds for a year. Every period listed is occupied for a new total submission |
declareCompliance(portal) | The declaration of compliance: declared, blocked or unconfirmed, with the sentence |
The store#
A CertificationStore is where the state and the artefacts of a run live:
type CertificationStore = {
load: () => Promise<CertificationState | null>
save: (state: CertificationState) => Promise<void>
writeArtefact: (name: string, content: string) => Promise<void>
readArtefact: (name: string) => Promise<string | null>
listArtefacts: () => Promise<readonly string[]>
}Artefact names are relative paths with / as separator, made only of letters, digits, ., _ and -; anything else throws INVALID_OPTION (name). createMemoryCertificationStore() keeps everything in memory, for tests and short runs. createDirectoryCertificationStore({ dir }) keeps state.json (written atomically, through a temporary file and a rename) and the artefacts as files, with a / in a name as a sub-directory. A service can implement the type over its own storage.
The state is a secret. It holds the CAF files, each with a private key. The directory store creates its directories private to you (mode 0700) and its files unreadable by others (0600); a directory that already exists keeps its mode. It is meant for a single process. Keep the directory out of version control.
createCertificationState(companyRut) makes a fresh state. The state is a plain JSON value; its main fields:
| Field | Holds |
|---|---|
stage | Where the run stands: a CertificationStage |
setText, attentionNumber, plan | The downloaded test set, its attention number and the plan |
setReadDate | The UTC day the set was read on: its month is the base period of the books |
cafs | The CAF files the run holds (with private keys) |
usedFolios | Every folio the run used |
annulledRanges | The ranges the SII reported annulled or received, by document type |
sets, setsApproved | The sets sent (track id, Chile date, instant, cases) and whether they are approved |
books | The period in use, occupied periods, adjustments tried, accumulated totals and each book sent |
simulation | The simulation sent, and whether it was confirmed |
lastDeclaration | The last declaration made and how it ended |
diagnosis | What the SOAP status said of an envelope, by track id |
exchange, samples | The exchange and printed samples stages |
blocked | The sentence that blocked the declaration of compliance |
The artefacts are what you inspect, and what the printed samples are built from:
| Artefact | What it is |
|---|---|
set-texto.txt, estructuras.json | The test set text and the plan |
sets-prueba/envio-set-basico.xml, …-guia.xml, …-exenta.xml, …-compra.xml | The envelope of each set |
sets-prueba/dtes/dte-<type>-<folio>.xml | Each document of the sets (SET_ARTEFACT_NAMES names the envelopes) |
libro-ventas.xml, libro-compras.xml, libro-guias.xml, libro-compras-exentos.xml | The books (BOOK_ARTEFACT_NAMES) |
simulacion/envio-simulacion.xml, simulacion/dtes/… | The simulation |
declaracion-sets-<n>.html, declaracion-libros-<n>.html, declaracion-simulacion-<n>.html (and …-pe_avance2-<n>.html, …-estado-<key>-<trackId>.xml) | Every declaration page and SOAP status answer |
intercambio/…, muestras/… | Every portal answer of the exchange and the printed samples, and the exchange answers |
findEnvelopeFiles from dte-sdk/pdf picks the set and simulation envelopes
out of this directory by name, so writePrintedSamples can build the PDFs
straight from it. See Exchange and samples.
Progress events#
onProgress receives one CertificationProgressEvent per step of the run. The names are listed in CERTIFICATION_STEPS:
| Phase | Events |
|---|---|
| Test set | SETS_DOWNLOADING, SETS_LOADED, SETS_REGENERATED |
| Folios | CAF_REQUESTING and CAF_OK, each with the document type |
| Sets | SET_START (with set), SET_OK (with set and trackId), SET_ERROR (with set and error), SETS_DECLARING, SETS_DECLARED, SETS_APPROVED, SETS_REJECTED |
| Waits | POLLING with attempt, max and label: sets, declaration, books or simulation |
| Books | BOOKS_START, BOOK_SKIPPED, BOOK_SENDING, BOOK_OK (with trackId), BOOK_ERROR (with error), BOOK_PERIOD_RETRY (with period and attempt), BOOKS_DECLARING, BOOKS_DONE (with books and success) |
| Advance | ADVANCE_WAITING, ADVANCE_DONE (with the portal's stage wording) |
| Simulation | SIM_START, SIM_SENDING, SIM_OK (with trackId), SIM_DECLARING, SIM_DONE |
| Exchange | INTERCAMBIO_START, INTERCAMBIO_DESCARGADO, INTERCAMBIO_DONE (with uploaded) |
| Samples | MUESTRAS_UPLOADING (with count), MUESTRAS_DONE (with success) |
| End | CERT_DONE, CERT_ERROR (with error) |
The final advance of declareComplianceFinal reads no stage, so it emits no event.
Folios#
prepareFolios makes sure the run holds the folios each type needs, in the order the SII rations them. It never asks for more than the sets not yet sent need, because unused authorized folios make the SII ration the next request.
- The CAFs in hand first. An expired CAF is skipped, because the SII refuses its folios. Folios of this run that the SII never received (a send that failed) are given back to the registry. Folios the SII already received, from an earlier run or other software, are marked used so they are skipped.
- Then the quota. The portal's maximum is read. A refusal or a failure reading it is not a stop: the run goes on with no maximum. A blocked quota, or a short one with unused folios at the SII, re-obtains them for the whole need of the type. A whole answer ends the type; a short one is kept, in place of the CAFs in hand, only if it downloaded something that covers more than they do.
- Then a request. A blocked maximum asks the portal for nothing. Otherwise one exact request, or batches when the maximum is below the need (as many batches as folios are missing), falling back to batches when the exact request falls short with a maximum that is not zero. A block on the person tries the re-obtaining once before anything else.
- Annulling is the last resort. Only when the refusal is rationing and the SII shows more unused folios than the run holds, unused ranges of the last 180 days are annulled: at most 10 per pass, in up to four passes. It never touches a range the run downloaded (the CAFs of the state, expired ones included, the ones just obtained, and the ones a re-obtaining brought and the run did not keep). The ranges the SII reported annulled are kept in the state (
annulledRanges) and not tried again. If any was annulled, the maximum is read again and the request repeated following it. An annulment that fails before the SII answers counts as none.
Still short throws FOLIO_OUT_OF_RANGE with type, required, available, maxAuthorized, availableFolios, rejection and a reason (noUnusedFolios or unusedFoliosBlock). When the batches stopped on a failure and not on the SII's answer, the CAFs they obtained are already in the state, and the step throws that failure's code instead, with type, operation: 'requestCafInBatches' and step (queryFolioQuota or requestCaf). Before 0.5.0 the same code came out of the batches themselves, and the CAFs they had obtained were lost.
A re-obtaining whose downloads stopped on a failure, or an annulment cut short once the SII had answered, ends the step the same way: what the re-obtaining brought is kept by the rule of step 2, and what the annulment annulled goes into annulledRanges, then the step throws the failure's code with type, operation (reobtainFolios or annulFolios), step and, when the SII refused, rejection. Before 0.6.0 an annulment cut short counted as none and the step ended with FOLIO_OUT_OF_RANGE, which read a network failure as rationing. The thrown error, and the CERT_ERROR event, carry only the code and those keys: the original error, with its reason, httpStatus and attempts, goes to the portal client's logger as sii portal flow stopped, keeping what it holds, its texts redacted and without what a page said or its url.
A request the SII answers with the request form again, with no folios and no reason, ends with rejection: 'stampingUncertain'. It is not a rationing refusal, so nothing is annulled because of it. The SII may have authorized the range: check the ranges that can be re-obtained before running again.
A later batch the SII refuses keeps its kind too. Before 0.7.0 any refusal of a second or later trip, but stampingUncertain, came out of the batches as quotaCapReached, which reads as rationing: a refusal of the company or of the option led the step to annul folios, and a block on the person was not lifted first. Now only one folio over the maximum after a grant (quotaExceeded) reads as quotaCapReached, so a later refusal that is not rationing never leads to annulling, and a block on the person is first lifted by re-obtaining, as on the first trip.
Annulling cannot be undone and counts against the quota for six months. The runner does it only as the last resort, when the SII rations the type and shows more unused folios than the run holds. See Portal.
Folios are checked against the SII before issuing. Before a set is issued, the SII is asked whether it already holds the folios the run is about to use (as the company, up to 30 queries per CAF, oldest CAF first, until the need is covered); one it holds is marked used. A folio the SII cannot answer for is used. A range obtained again is used only through the folios the SII showed free: every other folio of it is marked used as soon as the CAF is kept, so the registry counts exactly the free ones. The registry hands out its lowest free folio, not the next after the last one. sendTestSet and sendSimulation mark every folio sent in the registry whatever the outcome of the send.
Declarations#
declareProgress(portal, { entries }) declares envelopes on the SII's progress form (pe_avance2). An entry is { trackId, date } with the date as YYYY-MM-DD; the keys are the rows of the form (basic, guide, exempt, purchase, the books, simulation).
- The form is read for its hidden fields and for the index of each row's field, found by the row's label (the indexes move as sets are approved). A page without a form posts nothing and the outcome is
declined. - Every
NUM_ENV,FEC_ENV,SETandESTfield up toTOTREGis posted in form order, with the values already on the page: the track id without leading zeros and the date asdd-mm-yyyy. A row with no field (approved, or in review) adds nothing and the form is posted all the same. - The page is read again to verify. The declaration stands when no declared field came back empty, or some row shows
EN REVISION. A row left empty is asked again by the loop. - Today's Chile date goes with every track id, whatever day the envelope was sent on.
ENVIO CON ERRORES O REPAROSis a state of an envelope, not a failure of the declaration. The answer names the rows concerned (contentErrors); the declaration may still stand. The run asks the SOAP status of those envelopes once each and keeps the answer as a diagnosis.
outcome | Meaning |
|---|---|
accepted, inReview | The declaration stands |
contentErrors | The SII finds errors in some envelopes (the declaration itself may still stand, see success) |
allRejected | Every declared row came back empty: the SII took none |
notSaved | Some declared rows came back empty |
inconsistent | A date or number the SII says does not match |
declined | There was no form to post |
failed | A post the portal did not take |
The loop of the run (declareTestSets, declareSimulation, and the books phase) waits 10 s, then makes up to 10 attempts 5 s apart. A declaration that stands ends it, unless the answer says the SII has not processed the envelopes yet, which is asked again (a lost session reads that way, and the next attempt logs in again). Content errors are asked again while the declared fields come back empty (the SII has not seen the track ids yet); with the fields in place they are diagnosed and the loop ends. A declaration that was not saved is asked again; every declared row empty ends the loop, except for the simulation, where it is retried because the portal shows the simulation as not declared while it still processes the track id. The last attempt returns whatever it got, and every page goes to the artefacts.
Uploads of the run#
Every envelope and book of the run goes through one upload routine.
- Retries. An upload is sent again only for a network failure that names a reset socket, a timed-out connection or an unresolved host: 8 attempts, 2 s growing by 1.8 up to 15 s, no jitter. A request that timed out on the client's own clock, a refused connection and every answer of the SII are not retried.
- Reading the reply. Only
STATUS0 with aTRACKIDelement is a sent file.STATUS7 is a duplicate: with aTRACKIDelement the track id is recovered and the upload goes on as a sent one, unless its first error line names a charset or schema refusal.STATUS99, and anything else, is a failed send:SII_UPLOAD_REJECTEDwithstatusanderrors. A duplicate with no track id, where one is needed, is that same error withduplicate: true. - Reading a status. The status of an envelope is asked once, on the SOAP channel, without retries. States are classified by code: successful (
EPR,RPR,LOK), intermediate (REC,SOK,FOK,PRD,CRT,DNK,PDR,LSO,0, and the query service's own error codes-1to-14, which read as "ask again") and rejected (RPT,RFR,VOF,RCT,RCH,RLV,RSC,LNC,LRH). A status that never answered, or that has no state, is neither.
The books phase#
runBooks builds, sends, declares and waits for the books.
- The period. The history of books the SII holds is read year by year (until two empty years) and marks the occupied periods. The period is the UTC month the test set was read in when the set brought a purchase book, otherwise the current UTC month, or the first free month below it, searched anew on every run.
- What is sent. A book the portal shows as
REVISADO CONFORMEis skipped. The purchase, sales and guide books (and the exempt purchase book, when the plan has one) are built, kept as artefacts and uploaded. A purchase book the SII already holds for the period goes again as an adjustment. - Mandatory books. Without the three mandatory books (
MANDATORY_BOOK_KEYS) sent or skipped, the phase endsincomplete. This is the only case whererunBooksendsincomplete. - Before declaring. The SOAP status of the books sent is read for about a minute. A rejected book is left out of the wait.
- Declaring. The books are declared together with the four sets. While every declared row comes back empty, at most 24 times, every book goes again: as an adjustment once per period when the totals of the sales or purchase book are kept, otherwise as a total submission in the next free period.
- Waiting. A declaration that stands is followed by the approval wait (40 polls 15 s apart, the SOAP status every second poll, because the portal shows a rejected envelope as declared forever). A row the page leaves rejected, closed or declared and never reviewed keeps the search going even if it is of a book this run does not send (an exempt purchase book the test set did not bring): nothing is sent for it, but the books are declared again and that row is awaited, up to 24 times.
When a period is taken, every book goes again as an adjustment, the guide book and the exempt purchase book too. Books the declaration names with ENVIO CON ERRORES O REPAROS, or that the SOAP status rejects, are not awaited but sent again. No portal read of this phase stops the run: a page that cannot be read only uses up its poll.
Advancing the stage#
With the three mandatory books sent, the runner asks the portal for the next stage whether or not the books were approved: the portal decides. advanceToNextStage reads the progress page (up to 30 times, 10 s apart, while it cannot be read), asks for the advance at once with the first page that reads, then reads the page again for the stage. The state's stage moves to the portal's when that is later.
| Outcome | Meaning |
|---|---|
advanced | The portal moved on |
unchanged | The portal says it is already at that step |
failed | The portal refused, or the request could not be made. detail is its sentence |
timedOut | The progress page could not be read in 30 tries |
Nothing in it throws for a portal answer. If the portal did not move and the stage is still the books, runCertification stops with rejected and the portal's sentence.
Defaults for the operator#
The operator gives less than the SII needs, and the run fills in the rest.
| What | Default |
|---|---|
| Receiver | DEFAULT_CERTIFICATION_RECEIVER: RUT 66666666-6, CLIENTE TEST, ACTIVIDADES VARIAS, AVENIDA PRINCIPAL 123, Santiago. A field you give wins, field by field; an empty one takes the default |
| Issuer | DEFAULT_CERTIFICATION_ISSUER: line of business ACTIVIDADES DE PROGRAMACION INFORMATICA, activity code 620200, commune and city Santiago. The RUT, business name and address have no default |
| Resolution | Number 0 and the UTC date of the day the run started |
The default resolution date is only right on the day the SII resolved the
application. On any other day, give resolution.date yourself. A resolution
left out is dated once, when the run starts, so every envelope of the run
carries the same date.
A receiver's line of business is cut at its 40 characters instead of being refused, and so is the issuer's where the issuer is the receiver of its own documents (the purchase set, internal transfers, the simulation). As issuer, it keeps its 80.
The waits#
| Wait | Behaviour |
|---|---|
| Approval of the sets | 5 polls 10 s apart, sleeping first |
| Declaration loop | 10 s first, then up to 10 attempts 5 s apart |
| Approval of the books | 40 polls 15 s apart, sleeping first |
| Approval of the simulation | 30 polls 10 s apart, polling first |
| Reading the progress page to advance | Up to 30 reads 10 s apart |
| SOAP status of the books before declaring | 3 rounds 15 s apart, after a first wait of 15 s |
Inject sleep and now in the dependencies to test without waiting. A read that fails during a wait only uses up its attempt.
The compliance stop#
When the printed samples are submitted, the stage is compliance and the run stops with compliance until you pass declareCompliance: true. Then declareComplianceFinal asks the portal to advance the stage once more (a refusal or an error only goes to the log), and makes the declaration.
- The declaration counts as made when the last page no longer shows its form. Keep the page the store saves and check it.
- A block (the portal says the certification is not finished) is data:
stopped: 'blocked', with the sentence also instate.blocked. - A last page that does not confirm throws
SII_PORTAL_UNEXPECTED_PAGE. - A declaration ends the run: the stage is
doneandCERT_DONEis emitted.
Only the legal representative can make the declaration, and it cannot be undone. Check the printed samples review is approved in the portal first.
Catalogs#
| Export | What it holds |
|---|---|
SET_KEYS | The four sets in the order they are sent: basic, guide, exempt, purchase |
BOOK_KEYS | The books in the order they are sent: purchaseBook, salesBook, guideBook, exemptPurchaseBook |
MANDATORY_BOOK_KEYS | The books every certification must get approved: purchaseBook, salesBook, guideBook |
CERTIFICATION_STAGES | testSets, books, simulation, exchange, printedSamples, compliance, done |
CERTIFICATION_STEPS | The names of the progress events |
DEFAULT_OPTIONAL_SETS | SET03 guides, SET06 exempt invoices, SET07 sales book, SET08 purchase book, SET09 guide book, SET15 purchase book for exempt taxpayers and SET72 the purchase set. The basic set (SET01) is always requested. Export and settlement are never ticked |
BOOK_FILE_NAMES, BOOK_ARTEFACT_NAMES, SET_ARTEFACT_NAMES | The file name each book travels under, and the artefact names of the books and of the set envelopes |
PORTAL_STAGE_WORDS | The wording the portal uses for each stage |
Errors#
Refusals come back as data. Everything else is a DteError that propagates after the state is saved: the portal codes (SII_PORTAL_REJECTED with a rejection, SII_PORTAL_SESSION_EXPIRED, SII_PORTAL_UNEXPECTED_PAGE, SII_PORTAL_CERT_NOT_ENABLED), the SII upload codes (SII_UPLOAD_REJECTED), FOLIO_OUT_OF_RANGE and MISSING_FIELD. See Errors.
Next steps#
- The last stages in detail: Exchange and samples.
- What each set issues: Test sets.
- Folios and the registry: Portal.