Update address
PUT/company/address/
Updates the data of an existing address identified by the '_id' field in the request body.
Operation Flow:
- Authentication via valid JWT
- Validation of the mandatory '_id' field in the body
- Verification that the address belongs to the user's company
- Validation of fields and formats
- Processing of Google Maps data (reverse geocoding)
- If is_default=true, unmarks any existing primary address
- Persistence of changes in the database
- 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>