Skip to main content
A tender (gara d’appalto) is a procurement contract between PagoPA and one or more postal operators. It defines which operators can deliver which postal products, at what price, to which geographic zones, during a specific validity period. Every shipment cost calculation in pn-paper-channel traces back to an active tender.

Tender lifecycle

A PnTender record can be in one of three effective states, computed at runtime by PnTender.getActualStatus():
StatusMeaning
CREATEDTender created but not yet validated
VALIDATEDTender validated; becomes IN_PROGRESS when now is between startDate and endDate
IN_PROGRESSCurrently active — used for cost lookups
ENDEDendDate is in the past — no longer used for new shipments
Only one tender should be IN_PROGRESS at a time for a given product and geographic zone. The system picks the active tender during the Prepare phase via PaperTenderService.getSimplifiedCost().

PnTender entity

PnTender is stored in DynamoDB with tenderCode as the partition key.
DynamoDB attributeJava fieldDescription
tenderCodetenderCodeUnique tender identifier (PK)
descriptiondescriptionHuman-readable description
statusTypestatusCREATED, VALIDATED, IN_PROGRESS, or ENDED
startDatestartDateTender validity start (Instant)
endDateendDateTender validity end (Instant)
authorauthorAuthor of the tender record
datedateCreation timestamp

Delivery drivers

A PnDeliveryDriver represents a postal operator (recapitista) assigned to a tender. One tender can have multiple delivery drivers — for example, a national carrier and regional sub-carriers.

FSU vs. non-FSU

The fsu boolean flag on both PnDeliveryDriver and PnCost distinguishes the two carrier types:

FSU (Fornitore del Servizio Universale)

The national carrier obliged by law to provide universal postal service. FSU rates apply when no non-FSU operator covers a given zone.

Non-FSU

Private operators that may cover specific geographic zones. Non-FSU rates are used when available and the zone is within their coverage.

PnDeliveryDriver entity

PnDeliveryDriver is stored in DynamoDB with tenderCode as the partition key and taxId as the sort key. A secondary index (tender-index) supports lookups by tender.
DynamoDB attributeJava fieldDescription
tenderCodetenderCodeParent tender identifier (PK)
taxIdtaxIdVAT / tax identifier (SK)
uniqueCodeuniqueCodeInternal unique driver code
denominationdenominationLegal name of the operator
businessNamebusinessNameTrading name
fsufsutrue if this is the national carrier (FSU)
pecpecCertified email address
registeredOfficeregisteredOfficeRegistered office address

Cost model

Shipping costs are stored in PnCost records. Each record defines costs for a combination of:
  • Delivery driver (deliveryDriverCode) — the operator being priced
  • Postal product (productType) — the service class
  • Geographic zone (zone) — the delivery area classification
  • CAP list (cap) — the postal codes covered by this cost record

Postal products

CodeFull nameDescription
ARRaccomandata con Ricevuta di RitornoRegistered mail with return receipt
RSRaccomandata SempliceSimple registered mail
890Legge 890/1982Judicial registered mail (law 890/1982)
RIRRaccomandata Internazionale con Ricevuta di RitornoInternational registered mail with receipt
RISRaccomandata Internazionale SempliceInternational simple registered mail

Weight-based pricing tiers

Each PnCost record stores a base price and up to six weight-bracket prices. The correct price is selected based on the total letter weight (grams):
DynamoDB attributeWeight bracketDescription
basePrice0 – 20 gBase price
basePrice5021 – 50 gPrice up to 50 g
basePrice10051 – 100 gPrice up to 100 g
basePrice250101 – 250 gPrice up to 250 g
basePrice350251 – 350 gPrice up to 350 g
basePrice1000351 – 1000 gPrice up to 1000 g
basePrice20001001 – 2000 gPrice up to 2000 g
pagePriceper pagePer-page surcharge
The cost-rounding-mode property (default HALF_UP) controls how calculated costs are rounded.

PnCost entity

PnCost is stored in DynamoDB with driverCode as the partition key and uuidCode as the sort key. A secondary index (tender-index) on tenderCode supports cost lookups by tender.
DynamoDB attributeJava fieldDescription
driverCodedeliveryDriverCodeDelivery driver identifier (PK)
uuidCodeuuidUnique cost record identifier (SK)
tenderCodetenderCodeParent tender (GSI PK)
productTypeproductTypePostal product (AR, RS, 890, etc.)
zoneTypezoneDelivery zone identifier
capcapList of postal codes in this zone
fsufsuWhether this is an FSU cost record

GeoKey concept

A GeoKey maps a specific postal code (CAP) and product combination to a delivery zone and driver. PnPaperChannelGeoKey holds this mapping and is used during the cost lookup step in phase 1 of the Prepare flow. The composite partition key tenderProductGeokey is constructed as:
tenderId#product#geokey
For example: TENDER-2024#AR#00100

PnPaperChannelGeoKey entity

DynamoDB attributeJava fieldDescription
tenderProductGeokeytenderProductGeokeyComposite PK (tenderId#product#geokey)
activationDateactivationDateSort key — when the mapping became active
tenderIdtenderIdParent tender identifier
productproductPostal product code
geokeygeokeyPostal code or country code
lotlotLot number within the tender
zonezoneMapped delivery zone
coverFlagcoverFlagWhether the zone is covered by the driver
dismisseddismissedtrue if this mapping is no longer active

DynamoDB entity summary

EntityTablePartition keyPurpose
PnTenderTenderDynamoTabletenderCodeProcurement contract metadata and validity period
PnDeliveryDriverDeliveryDriverDynamoTabletenderCodePostal operator assigned to a tender
PnCostCostDynamoTabledriverCodeWeight-based cost per driver, product, and zone
PnPaperChannelGeoKeyPaperChannelGeoKeyTabletenderProductGeokeyMaps CAP + product to a zone and delivery driver

Domestic vs. international delivery

The Utility.isNational() helper checks the country field of the resolved address. When a delivery is domestic (Italy), phase 1 of the Prepare flow looks up the cost from the active tender using the postal code (CAP). When the delivery is international, the request is forwarded to the phase-2 queue, which handles attachment processing separately and uses country-code–based zone lookups.
International deliveries use the destination country code as the geokey instead of a CAP. Make sure your tender configuration includes PnCost records for each destination country you intend to serve.

Build docs developers (and LLMs) love