Passa al contenuto principale

Update address

PUT 

/company/address/

Aggiorna i dati di un indirizzo esistente identificato dal campo '_id' nel body della richiesta.

Flusso operativo:

  1. Autenticazione tramite JWT valido
  2. Validazione del campo '_id' obbligatorio nel body
  3. Verifica che l'indirizzo appartenga all'azienda dell'utente
  4. Validazione dei campi e dei formati
  5. Elaborazione dei dati di Google Maps (geocodifica inversa)
  6. Se is_default=true, rimuove il flag da qualsiasi indirizzo principale esistente
  7. Persistenza delle modifiche nel database
  8. Restituzione dell'indirizzo aggiornato

Caratteristiche importanti:

  • L'ID dell'indirizzo deve essere inviato nel campo '_id' del body
  • 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 is_default=true, rimuove il flag da qualsiasi indirizzo principale esistente

Esempio di richiesta:

PUT /company/address
Authorization: Bearer {token}
Content-Type: application/json

{
_id: 507f1f77bcf86cd799439011,
name: Magazzino Logistico Aggiornato,
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
}
}
},
is_default: false
}

Esempio di risposta di successo:

\{
_id: 507f1f77bcf86cd799439011,
name: Magazzino Logistico Aggiornato,
company_name: CargoOffer

<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","description":"Dati richiesti per creare un nuovo indirizzo","required":["name","addressGoogleMaps"],"properties":{"_id":{"type":"string","description":"ID univoco dell'indirizzo da aggiornare","example":"507f1f77bcf86cd799439011"},"name":{"type":"string","description":"Nome descrittivo dell'indirizzo (3-100 caratteri)","example":"Almacén Logístico"},"company_name":{"type":"string","description":"Ragione sociale della società a questo indirizzo (opzionale)","example":"CargoOffer SL"},"phone":{"type":"string","description":"Telefono di contatto in formato internazionale (opzionale)","example":"+34912345678"},"addressGoogleMaps":{"type":"object","description":"Dati di Google Maps per la geolocalizzazione","properties":{"formatted_address":{"type":"string","description":"Indirizzo completo formattato","example":"Calle de la Logística, 123, 28045 Madrid, España"},"geometry":{"type":"object","properties":{"location":{"type":"object","properties":{"lat":{"type":"number","format":"float","description":"Latitudine in gradi decimali","example":40.123456},"lng":{"type":"number","format":"float","description":"Lunghezza in gradi decimali","example":-3.987654}},"required":["lat","lng"]}},"required":["location"]}},"required":["formatted_address","geometry"]},"is_default":{"type":"boolean","description":"Indica se questo sarà l'indirizzo principale della società","example":false}},"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":{"_id":"64917511ef73c37ccae60bc4","name":"Almacén Logístico Actualizado","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}}},"isDefault":false}}},"required":true}}
>

</RequestSchema>

<StatusCodes
id={undefined}
label={undefined}
responses={{"200":{"description":"Indirizzo aggiornato correttamente","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":[-8.995213099999999,42.5668541]},"_id":"64917511ef73c37ccae60bc4","name":"Almacén Logístico Actualizado","company_name":"CargoOffer SL","phone":"+34912345678","city":"ribeira","state":"galicia","country":"españa","zipcode":"15960","street_number":"117","street_address":"Estrada Deán Norte","province":"A Coruña","placeId":"ChIJLdx3TsE5Lw0Rmh7qsvQUqII","name_address":"Estrada Deán Norte, 117, 15960 Ribeira, A Coruña, España","destinations":[],"createdAt":"2024-10-02T18:24:37.606Z","deleted":false}}}},"headers":{}},"400":{"description":"Dati di ingresso non validi","headers":{}},"401":{"description":"Non autorizzato (token JWT non valido o mancante)","headers":{}},"403":{"description":"NON_CONSENTITO - L'indirizzo non appartiene a questa società","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"NOT_ALLOWED"}}}}},"headers":{}},"404":{"description":"Indirizzo non trovato","headers":{}}}}
>

</StatusCodes>