Create new address
POST/company/address/
Crea un nuovo indirizzo associato all'azienda dell'utente autenticato. Questo endpoint consente di registrare ubicazioni fisiche come magazzini, uffici o punti di carico/scarico.
Flusso operativo:
- Autenticazione tramite JWT valido
- Validazione dei campi obbligatori e dei formati
- Elaborazione dei dati di Google Maps (geocodifica inversa)
- Se isDefault=true, rimuove il flag da qualsiasi indirizzo principale esistente
- Persistenza nel database
- Restituzione dell'indirizzo creato con il suo ID
Validazioni importanti:
- Richiede un token JWT valido con permessi di amministratore/editore
- Campo 'name' obbligatorio (3-100 caratteri)
- I dati di Google Maps devono includere:
- formatted_address: Indirizzo completo formattato
- geometry.location: Coordinate {lat, lng}
- Se isDefault=true, rimuove il flag da qualsiasi indirizzo principale esistente
Casi d'uso tipici:
- Registrare una nuova sede aziendale
- Aggiungere un magazzino logistico
- Creare un punto di ritiro per le spedizioni
Nota importante sui telefoni:
- I numeri di telefono (phone) devono avere un formato valido per Spagna, Francia o Portogallo
Richiede abbonamento attivo (validato dal middleware isPaymentUpdate)
I timestamp vengono convertiti in UTC dal middleware checkUTC
Esempio di richiesta:
POST /company/address
Authorization: Bearer \{token\}
Content-Type: application/json
\{
name: Magazzino Logistico,
company_name: CargoOffer SL,
phone: +34912345678,
addressGoogleMaps: \{
formatted_address: Calle de la Logística, 123, 28045 Madrid, Spagna,
geometry: \{
location: \{
lat: 40.123456,
lng: -3.987654
\}
\}
\},
isDefault: false
\}
<Heading
id={"request"}
as={"h2"}
className={"openapi-tabs__heading"}
children={"Request"}
>
</Heading>
<ParamsDetails
parameters={[]}
>
</ParamsDetails>
<RequestSchema
title={"Body"}
body={{"content":{"application/json":{"schema":{"properties":{},"type":"object","description":"Dati richiesti per creare un nuovo indirizzo","required":["name","addressGoogleMaps"],"example":{"_id":"507f1f77bcf86cd799439011","name":"Almacén Logístico","company_name":"CargoOffer SL","phone":"+34912345678","addressGoogleMaps":{"formatted_address":"Calle de la Logística, 123, 28045 Madrid, España","geometry":{"location":{"lat":40.123456,"lng":-3.987654}}},"is_default":false},"title":"CreateAddressRequest"},"example":{"name":"Almacén Logístico","company_name":"CargoOffer SL","phone":"+34912345678","addressGoogleMaps":{"formatted_address":"Calle de la Logística, 123, 28045 Madrid, España","geometry":{"location":{"lat":40.123456,"lng":-3.987654}}},"is_default":false}}},"required":true}}
>
</RequestSchema>
<StatusCodes
id={undefined}
label={undefined}
responses={{"200":{"description":"Operazione riuscita","content":{"application/json":{"schema":{"type":"object","description":"Rappresenta un indirizzo fisico associato a un'azienda per operazioni di carico/scarico.\n**Funzionalità**: - Punto di origine (ETL - Expected Time of Loading) o destinazione (ETD - Expected Time of Delivery) nelle aste di trasporto - Memorizzata per azienda e riutilizzabile in più operazioni - Geocodificata automaticamente tramite Google Maps API alla creazione - Validata rispetto all'uso in aste/consegne attive prima dell'eliminazione\n**Modello**: `src/features/models/address.model.js`\n**Controller**: `src/features/company/address/controller.js`","properties":{"_id":{"type":"string","description":"Identificatore univoco MongoDB dell'indirizzo (24 caratteri esadecimali). Generato automaticamente dal sistema alla creazione dell'indirizzo. Utilizzato come riferimento nei modelli di aste (auction.etl_address, auction.etd_address) e consegne (delivery.etl_address, delivery.etd_address).","pattern":"^[a-f0-9]{24}$","example":"507f1f77bcf86cd799439011"},"name":{"type":"string","description":"Nome descrittivo o alias personalizzato della posizione assegnato dall'utente. Utilizzato per l'identificazione rapida in elenchi e nella selezione degli indirizzi. **Obbligatorio** - Minimo 3 caratteri, massimo 100. Esempi: Magazzino Nord, Sede Centrale, Cliente ABC - Stabilimento Madrid","minLength":3,"maxLength":100,"example":"Oficina Central"},"company_name":{"type":"string","description":"Ragione sociale o nome commerciale dell'azienda in questa sede. **Obbligatorio** - Compare nei documenti ufficiali (CMR, contratti). Può differire dal nome della società principale se si tratta di un indirizzo cliente/fornitore. Minimo 2 caratteri, massimo 100.","minLength":2,"maxLength":100,"example":"CargoOffer SL"},"phone":{"type":"string","description":"Numero di telefono di contatto per il coordinamento logistico a questo indirizzo. **Opzionale** - Formato internazionale consigliato (E.164 con +codice paese). Utilizzato dai trasportatori per confermare l'arrivo e risolvere eventuali problemi. Convalidato con il pattern: 9-15 cifre.","pattern":"^\\+?[0-9]{9,15}$","maxLength":20,"example":"+34912345678"},"street":{"type":"string","description":"Via completa con numero, generata automaticamente da addressGoogleMaps. Formato: 'Nome della Via, Numero'. Utilizzato nella visualizzazione e nelle esportazioni CSV. Campo legacy combinato (vedere street_address + street_number per i campi separati).","example":"Calle Ejemplo 123"},"street_address":{"type":"string","description":"Nome della strada senza numero (campo separato). Parsato dalla risposta dell'API di Google Maps (componente route).","example":"Calle de Alcalá"},"street_number":{"type":"string","description":"Numero civico come campo indipendente. Parsato dalla risposta dell'API di Google Maps (componente street_number).","example":"42"},"city":{"type":"string","description":"Città normalizzata in minuscolo, estratta automaticamente dalle coordinate tramite Google Maps Geocoding API. Utilizzata nei filtri di ricerca e per raggruppare gli indirizzi per zona. Tipo: locality o administrative_area_level_2 di Google Maps.","example":"madrid"},"state":{"type":"string","description":"Stato, comunità autonoma o regione amministrativa (normalizzato in minuscolo). Estratto da administrative_area_level_1 di Google Maps. Opzionale - Può essere vuoto in paesi senza suddivisioni regionali.","example":"comunidad de madrid"},"zipcode":{"type":"string","description":"Codice postale secondo il formato del paese corrispondente. Estratto dal componente postal_code di Google Maps API. Utilizzato per le validazioni di zona e i calcoli delle tariffe.","example":"28045"},"country":{"type":"string","description":"Codice paese ISO 3166-1 alpha-2 in MAIUSCOLO (2 lettere). **Critico** per: validazione TaxID, formato targa, calcolo tariffe, restrizioni ADR. Estratto dal componente country (short_name) di Google Maps API. Deve corrispondere ai paesi attivi nella collection 'countries'.","pattern":"^[A-Z]{2}$","example":"ES"},"neighborhood":{"type":"string","description":"Quartiere o zona all'interno della città (opzionale). Estratto da neighborhood o sublocality di Google Maps. Utilizzato per la precisione in grandi aree urbane.","example":"centro"},"province":{"type":"string","description":"Provincia o divisione amministrativa provinciale. Estratto da administrative_area_level_2 di Google Maps (nei paesi con province). Opzionale - Rilevante principalmente in Spagna, Italia, ecc.","example":"madrid"},"location":{"type":"object","description":"Coordinate geografiche in formato GeoJSON Point secondo lo standard RFC 7946. Sistema di riferimento: WGS84 (EPSG:4326). **OBBLIGATORIO** - Utilizzato da MongoDB per query geospaziali ($near, $geoWithin). **CRITICO**: L'ordine nell'array `coordinates` è [longitudine, latitudine] (X, Y) - NON invertire. Utilizzato per: calcolo delle distanze, percorsi ottimali, validazione delle zone di servizio.","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Point"],"description":"Tipo di geometria GeoJSON. Deve essere sempre Point per gli indirizzi. Altri tipi (LineString, Polygon) non sono validi in questo contesto.","example":"Point"},"coordinates":{"type":"array","description":"Array di due numeri: [longitudine, latitudine] in gradi decimali. **ORDINE CRITICO**: prima la longitudine (asse X, da -180 a 180), poi la latitudine (asse Y, da -90 a 90). Esempio valido: [-3.70379, 40.416775] = 3.70° Ovest, 40.41° Nord (Madrid). **ERRORE COMUNE**: invertire l'ordine causa calcoli errati. Utilizzato in: model.find({location: {$near: {$geometry: {type: 'Point', coordinates: [lng, lat]}}}})","items":{"type":"number"},"minItems":2,"maxItems":2,"example":[-3.70379,40.416775]}}},"placeId":{"type":"string","description":"Identificatore Place ID univoco e immutabile di Google per questa posizione. Utilizzato per: geocodifica inversa, convalida delle modifiche, ottenimento di dettagli aggiornati. Formato: Stringa alfanumerica che inizia generalmente con ChIJ. Persistente per evitare geocodifiche ripetute (risparmio sui costi API).","example":"ChIJi-AoYTIoQg0RnHvWosEVABQ"},"name_address":{"type":"string","description":"Indirizzo completo formattato generato da Google Maps (formatted_address). Include: via, numero, codice postale, città, paese in formato locale. Utilizzato in: visualizzazione per gli utenti, esportazioni, documenti ufficiali. Non modificabile manualmente - rigenerato automaticamente all'aggiornamento delle coordinate.","example":"Calle de Alcalá, 42, 28014 Madrid, España"},"isDefault":{"type":"boolean","description":"Indica se questo è l'indirizzo principale/predefinito dell'azienda. **Restrizione**: Può esserci solo un indirizzo con isDefault=true per azienda. Impostando isDefault=true su un indirizzo, quello precedente con questo flag viene automaticamente impostato a false. Utilizzato in: autocompletamento di moduli, indirizzo predefinito per nuove aste. Memorizzato anche in: company.address_default (riferimento al _id di questo indirizzo).","default":false,"example":true},"can_be_deleted":{"type":"boolean","description":"Flag calcolato dinamicamente al momento della query (non memorizzato nel DB). **false**: L'indirizzo è referenziato in aste o consegne attive (status != canceled/delivered). **true**: L'indirizzo non ha dipendenze e può essere eliminato in sicurezza. Calcolato in: controller.get() verificando il conteggio di auction/delivery dove etl_address o etd_address == this._id Previene: eliminazione accidentale di indirizzi in uso che causerebbe dati orfani.","example":false},"destinations":{"type":"array","description":"Array di destinazioni frequenti con percorsi precalcolati da questo indirizzo. **Ottimizzazione**: Evita il ricalcolo di percorsi ripetitivi, migliora le prestazioni nella ricerca di aste. Popolato in: cron notturno o su richiesta per coppie di indirizzi frequenti. Utilizzato in: endpoint /company/minimal per calcoli di costo/distanza senza chiamare API esterne. Struttura: [{address: ObjectId, minimalRoute: {distance: Number(km), timeCost: Number(min)}}]","items":{"type":"object","properties":{"address":{"type":"string","description":"ObjectId dell'indirizzo di destinazione","example":"507f1f77bcf86cd799439012"},"minimalRoute":{"type":"object","properties":{"distance":{"type":"number","description":"Distanza calcolata in chilometri (tramite API percorsi)","example":523.7},"timeCost":{"type":"number","description":"Tempo stimato di viaggio in minuti (considerando la velocità media)","example":360}}}}}}},"required":["_id","name","location","isDefault","can_be_deleted"],"title":"Address"},"example":{"status":200,"data":{"location":{"type":"Point","coordinates":[0,0]},"phone":"+34912345678","street_number":"","street_address":"","_id":"68f9f8bf0e38c035ea821e58","deleted":false,"destinations":[],"name":"Almacén Logístico","company_name":"CargoOffer SL","createdAt":"2025-10-23T09:43:27.719Z"}}}},"headers":{}},"400":{"description":"Richiesta non valida","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["MISSING_FIELD_NAME","INVALID_GOOGLE_MAPS_DATA","INVALID_ADDRESS_FORMAT"],"example":"INVALID_GOOGLE_MAPS_DATA"}}}}},"headers":{}},"401":{"description":"Non autorizzato","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}},"headers":{}},"404":{"description":"Non trovato","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}},"headers":{}}}}
>
</StatusCodes>