Create simplified address
POST/company/address/simple
Crea un nuovo indirizzo in modo semplificato utilizzando solo coordinate e dati di base.
Questo endpoint è ottimizzato per i casi in cui si conoscono le coordinate esatte ed è necessario creare un indirizzo rapidamente senza la complessità dei dati di Google Maps.
Flusso operativo:
- Autenticazione tramite JWT valido
- Validazione dei campi minimi obbligatori (lat, lng, name, company_name)
- Geocodifica inversa automatica dalle coordinate
- Creazione automatica dell’indirizzo completo
- Associazione alla compagnia dell’utente
- Restituzione dell’indirizzo creato
Vantaggi di questo endpoint:
- Richiede solo 4 campi obbligatori rispetto ai ~15 dell’endpoint standard
- Geocodifica automatica dalle coordinate
- Riutilizza la logica collaudata del sistema di importazione massiva
- Mantiene la stessa qualità dei dati della creazione normale
Casi d’uso tipici:
- Applicazioni mobili con GPS
- Integrazione da sistemi di terze parti con coordinate
- Creazione rapida da mappe interattive
- Creazione in blocco semplificata
Esempio di richiesta:
POST /company/address/simple
Authorization: Bearer {token}
Content-Type: application/json
{
lat: 40.416775,
lng: -3.703790,
name: Sede Centrale,
company_name: CargoOffer SL,
phone: +34912345678,
isDefault: false
}
Esempio di risposta di successo:
\{
_id: 507f1f77bcf86cd799439011,
name: Sede Centrale,
company_name: CargoOffer SL,
phone: +34912345678,
street: Calle de Alcalá, 42,
city: madrid,
zipcode: 28014,
country: es,
location: \{
type: Point,
coordinates
<Heading
id={"request"}
as={"h2"}
className={"openapi-tabs__heading"}
children={"Request"}
>
</Heading>
<ParamsDetails
parameters={[]}
>
</ParamsDetails>
<RequestSchema
title={"Body"}
body={{"content":{"application/json":{"schema":{"type":"object","properties":{"lat":{"type":"number","description":"Latitud in gradi decimali (WGS84)","minimum":-90,"maximum":90,"example":40.416775},"lng":{"type":"number","description":"Lunghezza in gradi decimali (WGS84)","minimum":-180,"maximum":180,"example":-3.70379},"name":{"type":"string","description":"Nome descrittivo dell'indirizzo","minLength":3,"maxLength":100,"example":"Oficina Central"},"company_name":{"type":"string","description":"Ragione sociale della società a questo indirizzo","minLength":2,"maxLength":100,"example":"CargoOffer SL"},"phone":{"type":"string","description":"Telefono di contatto (opzionale, formato internazionale consigliato)","maxLength":20,"example":"+34912345678"},"isDefault":{"type":"boolean","description":"Indica se questo sarà l'indirizzo principale della società.","default":false,"example":false}},"required":["lat","lng","name","company_name"],"example":{"lat":40.416775,"lng":-3.70379,"name":"Oficina Central","company_name":"CargoOffer SL","phone":"+34912345678","isDefault":false}},"example":{"lat":40.416775,"lng":-3.70379,"name":"Oficina Central","company_name":"CargoOffer SL","phone":"+34912345678","isDefault":false}}},"required":true}}
>
</RequestSchema>
<StatusCodes
id={undefined}
label={undefined}
responses={{"200":{"description":"Indirizzo creato con successo.","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"}}},"headers":{}},"400":{"description":"Errore di convalida - Campi obbligatori mancanti o formato non valido","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["MISSING_FIELD_LAT","MISSING_FIELD_LNG","MISSING_FIELD_NAME","MISSING_FIELD_COMPANY_NAME","INVALID_COORDINATES"],"example":"MISSING_FIELD_LAT"}}}}},"headers":{}},"401":{"description":"Errore di autenticazione - Token non valido o azienda non trovata","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["USER_NOT_FOUND","CIA_NOT_FOUND"],"example":"CIA_NOT_FOUND"}}}}},"headers":{}},"404":{"description":"Utente non trovato","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"USER_NOT_FOUND"}}}}},"headers":{}},"500":{"description":"Errore interno del server","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["CANNOT_SAVE_ADDRESS","INTERNAL_ERROR"],"example":"CANNOT_SAVE_ADDRESS"}}}}},"headers":{}}}}
>
</StatusCodes>