Applicazioni per e‑commerce: indirizzi corretti e checkout più veloce

Integrare i database CAP nel flusso d’ordine permette di autocompilare Comune/Provincia/Regione,
validare gli indirizzi e applicare regole tariffarie/logistiche per aree.
In questa guida trovi architettura consigliata, schema dati, esempi pronti, checklist e best practice per
ridurre errori, tempi e costi di consegna.

1) Panoramica e obiettivi

  • Ridurre gli errori di digitazione con autocompilazione CAP → Comune/Provincia/Regione.
  • Velocizzare il checkout e migliorare la conversione.
  • Uniformare le anagrafiche per report e BI (Regione/Provincia coerenti).
  • Ottimizzare le spedizioni: supplementi/tempi per isole e aree remote, blocco CAP non serviti.
  • Taggare geograficamente i clienti per campagne e analisi.

2) Architettura consigliata (client/server)

Client (form): intercetta l’evento sul campo CAP e chiama un endpoint di lookup. Effettua autofill e prime verifiche UX.

Server (API/DB): espone un endpoint veloce (<100ms) che restituisce Comune/Provincia/Regione (+ opzionali lat/lon/zone).
Valida di nuovo lato server prima di salvare l’ordine.

  • Fallback offline: bundle JSON leggero con i CAP più usati per resilienza.
  • Cache: transient/Redis per ridurre i roundtrip al DB.
  • Versioning dataset: aggiorna i CAP con pacchetti delta (nuovi, cambiati, deprecati).

3) Schema dati e indici

Campi minimi: cap, comune, provincia, regione. Consigliati: lat, lon, zona_logistica, note, stato.

-- MySQL/MariaDB
CREATE TABLE cap_it (
  cap CHAR(5) PRIMARY KEY,
  comune VARCHAR(128) NOT NULL,
  provincia CHAR(2) NOT NULL,
  regione VARCHAR(64) NOT NULL,
  lat DECIMAL(9,6) NULL,
  lon DECIMAL(9,6) NULL,
  zona_logistica VARCHAR(32) NULL,   -- es. ISOLE, REMOTE, STD
  note VARCHAR(255) NULL,
  stato ENUM('ATTIVO','DEPRECATO') DEFAULT 'ATTIVO'
) ENGINE=InnoDB;

-- Indici utili (separati per lookup secondari)
CREATE INDEX idx_cap_regione ON cap_it (regione);
CREATE INDEX idx_cap_provincia ON cap_it (provincia);

Nota: mantieni comune in forma standardizzata (maiuscolo, senza accenti dove serve per matching).

4) Normalizzazione e validazione indirizzi

  • Case folding: confronta sempre in UPPER.
  • Rimozione accenti/punteggiatura per il matching (es. “Sant’Antimo” ≈ “SANTANTIMO”).
  • Regola CAP→Comune come fonte primaria: se l’utente sovrascrive, verifica e avvisa.
  • CAP deprecati: mantieni mapping e suggerisci aggiornamento all’utente.
  • Prefissi CAP: utili per logistica rapida (prime 2–3 cifre) ma non sostituiscono il lookup puntuale.

5) Implementazione (step-by-step)

  1. Ingest: importa CSV/SQL/JSON; validalo (righe duplicate, CAP non numerici, campi mancanti).
  2. Endpoint: esponi /cap/lookup?cap=XXXXX con output JSON coerente.
  3. UI Hook: al blur/change del CAP → chiama l’endpoint → autocompila i campi.
  4. Regole business: supplementi, blocchi, tempi aggiuntivi per zona.
  5. Verifica server-side: prima di salvare l’ordine, riesegui il controllo CAP–Comune.
  6. Log & monitor: salva mismatch/fallimenti per migliorare copy e dataset.

6) Esempi pratici (Excel/SQL/JSON/JS/PHP)

Excel — autocompilazione Comune/Provincia

=LET(cap; F2; XLOOKUP(cap; TabCAP[cap]; TabCAP[comune]; "CAP non trovato"))
=LET(cap; F2; XLOOKUP(cap; TabCAP[cap]; TabCAP[provincia]; "CAP non trovato"))

SQL — verifica massiva di incongruenze CAP–Comune

SELECT o.order_id, o.cap, UPPER(o.comune_digitato) AS comune_user,
       UPPER(c.comune) AS comune_ref
FROM ordini o
JOIN cap_it c ON o.cap = c.cap
WHERE o.comune_digitato IS NOT NULL
  AND UPPER(o.comune_digitato) <> UPPER(c.comune);

JSON — risposta minima per autocompletamento

{
  "cap": "20121",
  "comune": "Milano",
  "provincia": "MI",
  "regione": "Lombardia",
  "lat": 45.4669,
  "lon": 9.1900,
  "zona_logistica": "STD"
}

JavaScript — lookup lato frontend (mock semplice)

<form id="addr-form">
  <input id="cap" name="cap" maxlength="5" placeholder="CAP" />
  <input id="comune" name="comune" placeholder="Comune" />
  <input id="provincia" name="provincia" placeholder="Provincia" />
  <input id="regione" name="regione" placeholder="Regione" />
</form>
<script>
const CAP = {
  "20121": { comune:"MILANO", provincia:"MI", regione:"LOMBARDIA" },
  "80138": { comune:"NAPOLI", provincia:"NA", regione:"CAMPANIA" }
};
const $ = (s) => document.querySelector(s);
$("#cap").addEventListener("blur", () => {
  const v = $("#cap").value.trim();
  const r = CAP[v];
  if (r) {
    $("#comune").value = r.comune;
    $("#provincia").value = r.provincia;
    $("#regione").value = r.regione;
  } else { alert("CAP non trovato"); }
});
</script>

WordPress/WooCommerce — endpoint REST + hook form

<?php
// functions.php — endpoint di lookup
add_action('rest_api_init', function(){
  register_rest_route('cap/v1', '/lookup', [
    'methods' => 'GET',
    'callback' => function($req){
      $cap = preg_replace('/[^0-9]/','', $req->get_param('cap'));
      if(strlen($cap) !== 5){ return new WP_Error('bad_request','Formato CAP non valido',['status'=>400]); }
      global $wpdb;
      $row = $wpdb->get_row($wpdb->prepare(
        "SELECT comune, provincia, regione, zona_logistica FROM {$wpdb->prefix}cap_it WHERE cap=%s", $cap
      ));
      return $row ?: new WP_Error('not_found','CAP non trovato',['status'=>404]);
    }
  ]);
});

// Verifica server-side in checkout
add_action('woocommerce_after_checkout_validation', function($data, $errors){
  $cap = isset($data['billing_postcode']) ? preg_replace('/[^0-9]/','', $data['billing_postcode']) : '';
  if($cap){
    global $wpdb;
    $row = $wpdb->get_row($wpdb->prepare(
      "SELECT comune FROM {$wpdb->prefix}cap_it WHERE cap=%s", $cap
    ));
    if($row && !empty($data['billing_city']) && strtoupper($data['billing_city']) !== strtoupper($row->comune)){
      $errors->add('validation', 'Il Comune non corrisponde al CAP inserito.');
    }
  }
}, 10, 2);
?>

7) Spedizioni avanzate: zone, supplementi, blocchi

Gestisci logiche per ISOLE, AREE REMOTE, NON SERVITI con una tabella di mapping e prefissi.

-- Esempio tabella zone logistiche
CREATE TABLE cap_zone (
  cap CHAR(5) PRIMARY KEY,
  zona ENUM('STD','ISOLE','REMOTE','BLOCCO') NOT NULL DEFAULT 'STD',
  extra_costo DECIMAL(8,2) DEFAULT 0.00,
  extra_giorni TINYINT DEFAULT 0
);

WooCommerce — modifica tariffe a runtime

<?php
add_filter('woocommerce_package_rates', function($rates){
  $postcode = WC()->customer->get_shipping_postcode();
  if(!$postcode) return $rates;
  global $wpdb;
  $z = $wpdb->get_row($wpdb->prepare("SELECT zona, extra_costo FROM {$wpdb->prefix}cap_zone WHERE cap=%s", $postcode));
  if($z && $z->zona === 'BLOCCO'){
    wc_add_notice('CAP non servito: scegli un altro indirizzo', 'error');
    return [];
  }
  foreach($rates as $id => $rate){
    if($z && floatval($z->extra_costo)>0){ $rates[$id]->cost += floatval($z->extra_costo); }
  }
  return $rates;
}, 10); ?>

Pseudocodice calcolo ETA/costi

costo = base; eta = base_eta;
if (zona == 'ISOLE')  { costo += 4.90; eta += 1; }
if (zona == 'REMOTE') { costo += 6.90; eta += 2; }
if (zona == 'BLOCCO') { stop("CAP non servito"); }

8) UX & accessibilità

  • Microcopy: “Inserisci il tuo CAP (5 cifre) — esempio: 20121”.
  • Messaggi chiari: “Il CAP 20121 corrisponde a Milano (MI)”.
  • Non bloccare subito: consenti override con warning e spiega come correggere.
  • Keyboard-first: focus management e ARIA live region per gli esiti di lookup.
  • Colori & contrasto: avvisi leggibili e conformi a WCAG AA.

9) Performance, caching e scalabilità

  • Indice sul CAP (Primary Key) → lookup O(1).
  • Cache risultati per CAP ripetuti (transient/Redis).
  • Minimizza payload: JSON essenziale (comune/provincia/regione).
  • CDN per script statici e compressione GZIP/Brotli.
  • Monitor: 95° percentile < 150ms per l’endpoint.

10) QA, KPI e controllo qualità

  • Test unitari su CAP noti (campione per ogni regione).
  • Test regressione a ogni aggiornamento dataset (diff su righe cambiate).
  • KPI: % ordini con mismatch, tempo medio compilazione form, tasso resi per indirizzo errato, % CAP non trovati.
  • A/B test: verifica impatto dell’autofill su conversione.

11) Privacy/GDPR e sicurezza

  • CAP non è dato personale ma rientra nei dati di contatto: trattalo con policy trasparente.
  • Limitazione dati: restituisci solo ciò che serve (principio di minimizzazione).
  • Rate limiting e sanitizzazione input per l’endpoint.

12) Estensione multi-paese

Adotta un campo Paese e tabelle specifiche (IT/ES/FR/DE). Ogni nazione ha regole proprie (formato, lunghezza, prefissi, codici INSEE/INE).

CREATE TABLE cap_xx (
  country CHAR(2) NOT NULL, -- IT, ES, FR...
  cap VARCHAR(12) NOT NULL,
  comune VARCHAR(128),
  provincia VARCHAR(8),
  regione VARCHAR(64),
  PRIMARY KEY(country, cap)
);

FAQ

Come gestire CAP con più località? Il CAP è la chiave: restituisci il comune prevalente o proponi una lista se necessario.

E i CAP “storici” o deprecati? Mantieni una tabella di mapping e suggerisci l’aggiornamento verso il CAP attivo.

Serve lat/lon? Non obbligatorio, ma utile per ETA/distanze e mappe “ritiro vicino a te”.

← Torna alle Applicazioni d’uso