Skip to main content

Update address

PUT 

/company/address/

Updates the data of an existing address identified by the '_id' field in the request body.

Operation Flow:

  1. Authentication via valid JWT
  2. Validation of the mandatory '_id' field in the body
  3. Verification that the address belongs to the user's company
  4. Validation of fields and formats
  5. Processing of Google Maps data (reverse geocoding)
  6. If is_default=true, unmarks any existing primary address
  7. Persistence of changes in the database
  8. Return of the updated address

Important Features:

  • The address ID must be sent in the '_id' field of the body
  • Requires a valid JWT token with admin/editor permissions
  • Mandatory 'name' field (3-100 characters)
  • Google Maps data must include:
    • formatted_address: Complete formatted address
    • geometry.location: Coordinates {lat, lng}
  • If is_default=true, unmarks any existing primary address

Request Example:

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

{
_id: 507f1f77bcf86cd799439011,
name: Updated Logistics Warehouse,
company_name: CargoOffer SL,
phone: +34912345678,
address_google_maps: {
formatted_address: Calle de la Logística, 123, 28045 Madrid, Spain,
geometry: {
location: {
lat: 40.123456,
lng: -3.987654
}
}
},
is_default: false
}

Successful Response Example:

\{
_id: 507f1f77bcf86cd799439011,
name: Updated Logistics Warehouse,
company_name: CargoOffer SL,
phone: +34912345678,
street: Calle de la Logística, 123,
city: Madrid,
zipcode: 28045,
country: ES,
location: \{
type: Point,
coordinates: [-3.987654, 40.123456]
\},
is_default: false,
can_be_deleted: true
\}

<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":"Data required to create a new address","required":["name","addressGoogleMaps"],"properties":{"_id":{"type":"string","description":"Unique ID of the address to update","example":"507f1f77bcf86cd799439011"},"name":{"type":"string","description":"Descriptive name for the address (3-100 characters)","example":"Almacén Logístico"},"company_name":{"type":"string","description":"Company's legal name at this address (optional)","example":"CargoOffer SL"},"phone":{"type":"string","description":"International format contact phone (optional)","example":"+34912345678"},"addressGoogleMaps":{"type":"object","description":"Google Maps data for geolocation","properties":{"formatted_address":{"type":"string","description":"Full formatted address","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":"Latitude in decimal degrees","example":40.123456},"lng":{"type":"number","format":"float","description":"Length in decimal degrees","example":-3.987654}},"required":["lat","lng"]}},"required":["location"]}},"required":["formatted_address","geometry"]},"is_default":{"type":"boolean","description":"Indicate if this will be the company's main address.","example":false}},"example":{"_id":"507f1f77bcf86cd799439011","name":"Almacén Logístico","company_name":"CargoOffer SL","phone":"+34912345678","address_google_maps":{"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":"Address updated successfully","content":{"application/json":{"schema":{"type":"object","description":"Represents a physical address associated with a company for loading/unloading operations.\n**Functionality**: - Origin point (ETL - Expected Time of Loading) or destination (ETD - Expected Time of Delivery) in transport auctions - Stored per company and reusable across multiple operations - Automatically geocoded via Google Maps API upon creation - Validated against use in active auctions/deliveries before deletion\n**Model**: `src/features/models/address.model.js`\n**Controller**: `src/features/company/address/controller.js`","properties":{"_id":{"type":"string","description":"MongoDB unique identifier of the address (24 hexadecimal characters). Automatically generated by the system when the address is created. Used as a reference in auction models (auction.etl_address, auction.etd_address) and delivery models (delivery.etl_address, delivery.etd_address).","pattern":"^[a-f0-9]{24}$","example":"507f1f77bcf86cd799439011"},"name":{"type":"string","description":"Descriptive name or custom alias for the location assigned by the user. Used for quick identification in lists and address selection. **Required** - Minimum 3 characters, maximum 100. Examples: North Warehouse, Head Office, Client ABC - Madrid Plant","minLength":3,"maxLength":100,"example":"Oficina Central"},"company_name":{"type":"string","description":"Legal or trade name of the company at this location. **Required** - Appears on official documents (CMR, contracts). May differ from the main company name if it is a customer/supplier address. Minimum 2 characters, maximum 100.","minLength":2,"maxLength":100,"example":"CargoOffer SL"},"phone":{"type":"string","description":"Contact phone number for logistics coordination at this address. **Optional** - Recommended international format (E.164 with +country code). Used by carriers to confirm arrival and resolve incidents. Validated with pattern: 9-15 digits.","pattern":"^\\+?[0-9]{9,15}$","maxLength":20,"example":"+34912345678"},"street":{"type":"string","description":"Full street with number, automatically generated from addressGoogleMaps. Format: Street Name, Number. Used in display and CSV exports. Legacy combined field (see street_address + street_number for separate fields).","example":"Calle Ejemplo 123"},"street_address":{"type":"string","description":"Street name without number (separate field). Parsed from Google Maps API response (route component).","example":"Calle de Alcalá"},"street_number":{"type":"string","description":"Street number as an independent field. Parsed from the Google Maps API response (street_number component).","example":"42"},"city":{"type":"string","description":"City normalized in lowercase, automatically extracted from coordinates via Google Maps Geocoding API. Used in search filters and grouping addresses by area. Type: Google Maps locality or administrative_area_level_2.","example":"madrid"},"state":{"type":"string","description":"State, autonomous community, or administrative region (normalized in lowercase). Extracted from Google Maps' administrative_area_level_1. Optional - May be empty in countries without regional divisions.","example":"comunidad de madrid"},"zipcode":{"type":"string","description":"Postal code in the format of the corresponding country. Extracted from the postal_code component of the Google Maps API. Used for zone validations and fare calculations.","example":"28045"},"country":{"type":"string","description":"ISO 3166-1 alpha-2 country code in UPPERCASE (2 letters). **Critical** for: TaxID validation, license plate format, fee calculation, ADR restrictions. Extracted from the country component (short_name) of the Google Maps API. Must match active countries in the 'countries' collection.","pattern":"^[A-Z]{2}$","example":"ES"},"neighborhood":{"type":"string","description":"Neighborhood or area within the city (optional). Extracted from Google Maps' neighborhood or sublocality. Used for precision in large urban areas.","example":"centro"},"province":{"type":"string","description":"Province or provincial administrative division. Extracted from administrative_area_level_2 in Google Maps (in countries with provinces). Optional - Primarily relevant in Spain, Italy, etc.","example":"madrid"},"location":{"type":"object","description":"Geographic coordinates in GeoJSON Point format according to RFC 7946 standard. Reference system: WGS84 (EPSG:4326). **REQUIRED** - Used by MongoDB for geospatial queries ($near, $geoWithin). **CRITICAL**: Order in the coordinates array is [longitude, latitude] (X, Y) - DO NOT invert. Used for: distance calculations, optimal routing, service area validation.","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Point"],"description":"GeoJSON geometry type. Must always be Point for addresses. Other types (LineString, Polygon) are not valid in this context.","example":"Point"},"coordinates":{"type":"array","description":"Array of two numbers: [longitude, latitude] in decimal degrees. **CRITICAL ORDER**: longitude first (X-axis, -180 to 180), latitude second (Y-axis, -90 to 90). Valid example: [-3.70379, 40.416775] = 3.70° West, 40.41° North (Madrid). **COMMON ERROR**: Reversing the order causes incorrect calculations. Used 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":"Unique and immutable Google Place ID for this location. Used for: reverse geocoding, change validation, fetching updated details. Format: Alphanumeric string typically beginning with ChIJ. Persisted to avoid repeated geocoding (API cost savings).","example":"ChIJi-AoYTIoQg0RnHvWosEVABQ"},"name_address":{"type":"string","description":"Complete formatted address generated by Google Maps (formatted_address). Includes: street, number, postal code, city, country in local format. Used in: user display, exports, official documents. Not manually editable - regenerated automatically when coordinates are updated.","example":"Calle de Alcalá, 42, 28014 Madrid, España"},"isDefault":{"type":"boolean","description":"Indicates whether this is the company's primary/default address. **Constraint**: There can only be one address with isDefault=true per company. When setting isDefault=true on an address, the previous address with this flag is automatically set to false. Used in: Form autocompletion, default address for new auctions. Also stored in: company.address_default (reference to this address's _id).","default":false,"example":true},"can_be_deleted":{"type":"boolean","description":"Flag dynamically calculated at query time (not stored in DB). **false**: The address is referenced in active auctions or deliveries (status != canceled/delivered). **true**: The address has no dependencies and can be safely deleted. Calculated in: controller.get() by checking the count of auction/delivery where etl_address or etd_address == this._id Prevents: accidental deletion of addresses in use, which would cause orphaned data.","example":false},"destinations":{"type":"array","description":"Array of frequent destinations with precalculated routes from this address. **Optimization**: Avoids recalculating repetitive routes, improves performance in auction searches. Populated in: nightly cron or on-demand for frequent address pairs. Used in: /company/minimal endpoint for cost/distance calculations without calling external API. Structure: [{address: ObjectId, minimalRoute: {distance: Number(km), timeCost: Number(min)}}]","items":{"type":"object","properties":{"address":{"type":"string","description":"Destination address ObjectId","example":"507f1f77bcf86cd799439012"},"minimalRoute":{"type":"object","properties":{"distance":{"type":"number","description":"Distance calculated in kilometers (via route API)","example":523.7},"timeCost":{"type":"number","description":"Estimated travel time in minutes (considering average speed)","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":"Invalid input data","headers":{}},"401":{"description":"Unauthorized (invalid or missing JWT token)","headers":{}},"403":{"description":"NOT_ALLOWED - The address does not belong to this company","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"NOT_ALLOWED"}}}}},"headers":{}},"404":{"description":"Address not found","headers":{}}}}
>

</StatusCodes>