erp_be/src/docs/assets-routes.yaml

929 lines
39 KiB
YAML

tags:
- name: Assets
components:
schemas:
AssetsCreateBody:
type: object
required: [asset_name, item_category_id, item_subcategory_id, location_id]
properties:
asset_name: { type: string, example: 'CNC Lathe Machine' }
item_category_id: { type: integer, example: 1 }
item_subcategory_id: { type: integer, example: 1 }
location_id: { type: integer, example: 1, description: 'Location id (plant or warehouse)' }
brand_model: { type: string }
manufacturer: { type: string }
serial_number: { type: string }
part_number: { type: string }
department_id: { type: integer, nullable: true }
location_detail: { type: string }
assigned_to_user_id: { type: integer, nullable: true }
maintenance_incharge_user_id: { type: integer, nullable: true, description: 'User responsible for periodic maintenance checklist' }
maintenance_frequency_in_days: { type: integer, nullable: true, example: 30, description: 'Days between maintenance checklists' }
maintenance_checklist_json:
type: array
nullable: true
description: 'Checklist TEMPLATE stored on the asset'
items:
type: object
required: [key, label]
properties:
key: { type: string, example: 'oil_level' }
label: { type: string, example: 'Check oil level' }
required: { type: boolean, example: true }
vendor_id: { type: integer, nullable: true }
po_id: { type: integer, nullable: true }
grn_id: { type: integer, nullable: true }
grn_item_id: { type: integer, nullable: true }
commencement_date: { type: string, format: date, nullable: true, description: 'Asset usage start date — used for depreciation (falls back to purchase_date)' }
purchase_date: { type: string, format: date, nullable: true }
purchase_cost: { type: number, example: 850000 }
useful_life_years: { type: integer, example: 10 }
depreciation_method: { type: string, enum: [SLM, WDV, OTHER], example: SLM }
depreciation_rate: { type: number, nullable: true, example: 10, description: 'Required for OTHER; auto-calculated for SLM/WDV when omitted' }
salvage_value: { type: number, example: 50000 }
warranty_expiry_date: { type: string, format: date, nullable: true }
condition: { type: string, enum: [NEW, GOOD, FAIR, POOR] }
status: { type: string, enum: [IN_USE, IDLE, UNDER_MAINTENANCE, DISPOSED, SCRAPPED] }
qr_code_value: { type: string }
disposal_date: { type: string, format: date, nullable: true }
disposal_reason: { type: string }
disposal_value: { type: number }
remarks: { type: string }
is_active: { type: boolean }
AssetsUpdateBody:
type: object
minProperties: 1
properties:
asset_name: { type: string }
item_category_id: { type: integer }
item_subcategory_id: { type: integer }
location_id: { type: integer }
brand_model: { type: string }
manufacturer: { type: string }
serial_number: { type: string }
part_number: { type: string }
department_id: { type: integer, nullable: true }
location_detail: { type: string }
assigned_to_user_id: { type: integer, nullable: true }
maintenance_incharge_user_id: { type: integer, nullable: true }
maintenance_frequency_in_days: { type: integer, nullable: true }
maintenance_checklist_json:
type: array
nullable: true
items:
type: object
required: [key, label]
properties:
key: { type: string }
label: { type: string }
required: { type: boolean }
vendor_id: { type: integer, nullable: true }
po_id: { type: integer, nullable: true }
grn_id: { type: integer, nullable: true }
grn_item_id: { type: integer, nullable: true }
commencement_date: { type: string, format: date, nullable: true }
purchase_date: { type: string, format: date, nullable: true }
purchase_cost: { type: number }
useful_life_years: { type: integer }
depreciation_method: { type: string, enum: [SLM, WDV, OTHER] }
depreciation_rate: { type: number, nullable: true }
salvage_value: { type: number }
warranty_expiry_date: { type: string, format: date, nullable: true }
condition: { type: string, enum: [NEW, GOOD, FAIR, POOR] }
status: { type: string, enum: [IN_USE, IDLE, UNDER_MAINTENANCE, DISPOSED, SCRAPPED] }
qr_code_value: { type: string }
disposal_date: { type: string, format: date, nullable: true }
disposal_reason: { type: string }
disposal_value: { type: number }
remarks: { type: string }
is_active: { type: boolean }
DepreciationCalculateBody:
type: object
required: [depreciation_method]
properties:
depreciation_method: { type: string, enum: [SLM, WDV, OTHER] }
depreciation_rate: { type: number, nullable: true }
purchase_cost: { type: number, example: 850000 }
salvage_value: { type: number, example: 50000 }
useful_life_years: { type: integer, example: 10 }
commencement_date: { type: string, format: date, description: 'Preferred depreciation start date' }
purchase_date: { type: string, format: date }
as_of_date: { type: string, format: date }
MaintenanceLogCreateBody:
type: object
required: [performed_date, checklist_json]
properties:
performed_date: { type: string, format: date }
next_due_date: { type: string, format: date, nullable: true, description: 'Optional override; defaults to performed_date + frequency' }
remarks: { type: string }
checklist_json:
type: array
minItems: 1
items:
type: object
required: [key, status]
properties:
key: { type: string, example: 'oil_level' }
label: { type: string, example: 'Check oil level' }
status: { type: string, enum: [OK, NOT_OK, NA] }
remarks: { type: string, nullable: true }
TransferAssetBody:
type: object
required: [transfer_date]
properties:
transfer_date: { type: string, format: date }
to_location_id: { type: integer, nullable: true }
to_department_id: { type: integer, nullable: true }
to_user_id: { type: integer, nullable: true }
reason: { type: string }
description: At least one of to_location_id, to_department_id, to_user_id is required
AmcContractBody:
type: object
required: [vendor_id, start_date, end_date]
properties:
vendor_id: { type: integer, example: 1 }
contract_no: { type: string, example: AMC-2026-001 }
contract_type: { type: string, enum: [COMPREHENSIVE, LABOUR_ONLY, PARTS_ONLY, PREVENTIVE_ONLY] }
start_date: { type: string, format: date }
end_date: { type: string, format: date }
renewal_date: { type: string, format: date, nullable: true }
annual_cost: { type: number, example: 50000 }
payment_frequency: { type: string, enum: [MONTHLY, QUARTERLY, HALF_YEARLY, ANNUAL] }
service_frequency: { type: string, enum: [MONTHLY, QUARTERLY, HALF_YEARLY, ANNUAL], nullable: true }
visits_per_year: { type: integer, nullable: true, example: 4 }
contact_person: { type: string }
contact_phone: { type: string }
contact_email: { type: string, format: email }
scope_of_work: { type: string }
exclusions: { type: string }
remarks: { type: string }
is_active: { type: boolean }
AmcContractUpdateBody:
type: object
minProperties: 1
properties:
vendor_id: { type: integer }
contract_no: { type: string }
contract_type: { type: string, enum: [COMPREHENSIVE, LABOUR_ONLY, PARTS_ONLY, PREVENTIVE_ONLY] }
start_date: { type: string, format: date }
end_date: { type: string, format: date }
renewal_date: { type: string, format: date, nullable: true }
annual_cost: { type: number }
payment_frequency: { type: string, enum: [MONTHLY, QUARTERLY, HALF_YEARLY, ANNUAL] }
service_frequency: { type: string, enum: [MONTHLY, QUARTERLY, HALF_YEARLY, ANNUAL], nullable: true }
visits_per_year: { type: integer, nullable: true }
contact_person: { type: string }
contact_phone: { type: string }
contact_email: { type: string, format: email }
scope_of_work: { type: string }
exclusions: { type: string }
remarks: { type: string }
is_active: { type: boolean }
AmcRenewBody:
type: object
required: [start_date, end_date]
properties:
start_date: { type: string, format: date }
end_date: { type: string, format: date }
vendor_id: { type: integer }
contract_no: { type: string }
contract_type: { type: string, enum: [COMPREHENSIVE, LABOUR_ONLY, PARTS_ONLY, PREVENTIVE_ONLY] }
renewal_date: { type: string, format: date, nullable: true }
annual_cost: { type: number }
payment_frequency: { type: string, enum: [MONTHLY, QUARTERLY, HALF_YEARLY, ANNUAL] }
service_frequency: { type: string, enum: [MONTHLY, QUARTERLY, HALF_YEARLY, ANNUAL], nullable: true }
visits_per_year: { type: integer, nullable: true }
contact_person: { type: string }
contact_phone: { type: string }
contact_email: { type: string, format: email }
scope_of_work: { type: string }
exclusions: { type: string }
remarks: { type: string }
ServiceVisitBody:
type: object
required: [visit_type, visit_date]
properties:
visit_type: { type: string, enum: [PREVENTIVE, BREAKDOWN, INSPECTION, INSTALLATION, CALIBRATION, OTHER] }
visit_date: { type: string, format: date }
amc_contract_id: { type: integer, nullable: true }
complaint_no: { type: string, example: CMP-001 }
complaint_date: { type: string, format: date, nullable: true }
complaint_desc: { type: string }
engineer_name: { type: string }
engineer_phone: { type: string }
vendor_id: { type: integer, nullable: true }
work_done: { type: string }
parts_replaced: { type: string }
next_service_date: { type: string, format: date, nullable: true }
status: { type: string, enum: [SCHEDULED, IN_PROGRESS, COMPLETED, CANCELLED, PENDING_PARTS] }
downtime_hours: { type: number, example: 2.5 }
service_cost: { type: number, example: 1500 }
is_under_amc: { type: boolean }
asset_condition_after: { type: string, enum: [GOOD, FAIR, POOR, NEEDS_REPLACEMENT], nullable: true }
remarks: { type: string }
ServiceVisitUpdateBody:
type: object
minProperties: 1
properties:
visit_type: { type: string, enum: [PREVENTIVE, BREAKDOWN, INSPECTION, INSTALLATION, CALIBRATION, OTHER] }
visit_date: { type: string, format: date }
amc_contract_id: { type: integer, nullable: true }
complaint_no: { type: string }
complaint_date: { type: string, format: date, nullable: true }
complaint_desc: { type: string }
engineer_name: { type: string }
engineer_phone: { type: string }
vendor_id: { type: integer, nullable: true }
work_done: { type: string }
parts_replaced: { type: string }
next_service_date: { type: string, format: date, nullable: true }
status: { type: string, enum: [SCHEDULED, IN_PROGRESS, COMPLETED, CANCELLED, PENDING_PARTS] }
downtime_hours: { type: number }
service_cost: { type: number }
is_under_amc: { type: boolean }
asset_condition_after: { type: string, enum: [GOOD, FAIR, POOR, NEEDS_REPLACEMENT], nullable: true }
remarks: { type: string }
ServiceVisitStatusBody:
type: object
required: [status]
properties:
status: { type: string, enum: [SCHEDULED, IN_PROGRESS, COMPLETED, CANCELLED, PENDING_PARTS] }
remarks: { type: string }
InsurancePolicyBody:
type: object
required: [policy_no, insurer_name, policy_start_date, policy_end_date]
properties:
policy_no: { type: string, example: POL-2026-001 }
insurer_name: { type: string, example: 'ICICI Lombard' }
insurer_branch: { type: string }
insurer_contact: { type: string }
insurer_phone: { type: string }
insurer_email: { type: string, format: email }
policy_type: { type: string, enum: [FIRE_AND_ALLIED, MACHINERY_BREAKDOWN, COMPREHENSIVE, THIRD_PARTY, VEHICLE, OTHER] }
sum_insured: { type: number, example: 1000000 }
annual_premium: { type: number, example: 25000 }
policy_start_date: { type: string, format: date }
policy_end_date: { type: string, format: date }
renewal_date: { type: string, format: date, nullable: true }
is_auto_renewal: { type: boolean }
premium_paid: { type: boolean }
premium_paid_date: { type: string, format: date, nullable: true }
remarks: { type: string }
is_active: { type: boolean }
InsurancePolicyUpdateBody:
type: object
minProperties: 1
properties:
policy_no: { type: string }
insurer_name: { type: string }
insurer_branch: { type: string }
insurer_contact: { type: string }
insurer_phone: { type: string }
insurer_email: { type: string, format: email }
policy_type: { type: string, enum: [FIRE_AND_ALLIED, MACHINERY_BREAKDOWN, COMPREHENSIVE, THIRD_PARTY, VEHICLE, OTHER] }
sum_insured: { type: number }
annual_premium: { type: number }
policy_start_date: { type: string, format: date }
policy_end_date: { type: string, format: date }
renewal_date: { type: string, format: date, nullable: true }
is_auto_renewal: { type: boolean }
premium_paid: { type: boolean }
premium_paid_date: { type: string, format: date, nullable: true }
remarks: { type: string }
is_active: { type: boolean }
InsuranceRenewBody:
type: object
required: [policy_start_date, policy_end_date]
properties:
policy_start_date: { type: string, format: date }
policy_end_date: { type: string, format: date }
policy_no: { type: string }
insurer_name: { type: string }
insurer_branch: { type: string }
insurer_contact: { type: string }
insurer_phone: { type: string }
insurer_email: { type: string, format: email }
policy_type: { type: string, enum: [FIRE_AND_ALLIED, MACHINERY_BREAKDOWN, COMPREHENSIVE, THIRD_PARTY, VEHICLE, OTHER] }
sum_insured: { type: number }
annual_premium: { type: number }
renewal_date: { type: string, format: date, nullable: true }
is_auto_renewal: { type: boolean }
premium_paid: { type: boolean }
premium_paid_date: { type: string, format: date, nullable: true }
remarks: { type: string }
AssetAttachmentResponse:
type: object
properties:
id: { type: string, example: '1' }
asset_id: { type: string, example: '1' }
attachment_type:
type: string
enum: [DOCUMENT, PHOTO, WARRANTY, INVOICE, AMC_CONTRACT, SERVICE_REPORT, INSURANCE_POLICY, OTHER]
example: DOCUMENT
amc_contract_id: { type: string, nullable: true, example: '1' }
service_visit_id: { type: string, nullable: true, example: '1' }
insurance_id: { type: string, nullable: true, example: '1' }
file_name: { type: string, example: 'warranty-card.pdf' }
file_type: { type: string, example: 'application/pdf' }
file_size: { type: integer, example: 245760 }
uploaded_by_user:
type: object
nullable: true
properties:
id: { type: string }
full_name: { type: string }
employee_code: { type: string, nullable: true }
created_at: { type: string, format: date-time }
paths:
/assets/options:
get:
tags: [Assets]
summary: All asset module dropdown options in one call
description: Returns contract_types, visit_types, policy_types, conditions, statuses, frequencies, etc.
responses:
'200':
description: Options fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/contract-types:
get:
tags: [Assets]
summary: AMC contract type dropdown options
responses:
'200':
description: Contract types fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/visit-types:
get:
tags: [Assets]
summary: Service visit type dropdown options
responses:
'200':
description: Visit types fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/policy-types:
get:
tags: [Assets]
summary: Insurance policy type dropdown options
responses:
'200':
description: Policy types fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/conditions:
get:
tags: [Assets]
summary: Asset condition dropdown options
responses:
'200':
description: Asset conditions fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/statuses:
get:
tags: [Assets]
summary: Asset status dropdown options
responses:
'200':
description: Asset statuses fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/payment-frequencies:
get:
tags: [Assets]
summary: AMC payment frequency dropdown options
responses:
'200':
description: Payment frequencies fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/service-frequencies:
get:
tags: [Assets]
summary: AMC service frequency dropdown options
responses:
'200':
description: Service frequencies fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/visit-statuses:
get:
tags: [Assets]
summary: Service visit status dropdown options
responses:
'200':
description: Visit statuses fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/visit-conditions-after:
get:
tags: [Assets]
summary: Asset condition after visit dropdown options
responses:
'200':
description: Visit condition options fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/depreciation-methods:
get:
tags: [Assets]
summary: List depreciation method dropdown options (SLM, WDV, OTHER)
responses:
'200':
description: Depreciation methods fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/depreciation/calculate:
post:
tags: [Assets]
summary: Preview depreciation calculation for selected method/rate
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/DepreciationCalculateBody' }
responses:
'200':
description: Depreciation calculated
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/alerts/expiry:
get:
tags: [Assets]
summary: Expiry alerts (AMC, Insurance, Warranty)
parameters:
- { name: days, in: query, schema: { type: integer, example: 30 } }
- { name: type, in: query, schema: { type: string, enum: [AMC, INSURANCE, WARRANTY] } }
- { name: page, in: query, schema: { type: integer } }
- { name: limit, in: query, schema: { type: integer } }
responses:
'200':
description: Expiry alerts fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/alerts/service:
get:
tags: [Assets]
summary: Service due/overdue alerts
parameters:
- { name: status, in: query, schema: { type: string, enum: [OVERDUE, DUE_THIS_WEEK, DUE_THIS_MONTH, UPCOMING] } }
- { name: page, in: query, schema: { type: integer } }
- { name: limit, in: query, schema: { type: integer } }
responses:
'200':
description: Service alerts fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/maintenance/my:
get:
tags: [Assets]
summary: List assets assigned to me as maintenance incharge
description: |
Returns assets where `maintenance_incharge_user_id` equals the logged-in user.
Use `due_only=true` to show only assets whose next checklist is due/overdue.
Each asset includes a `maintenance` summary (`is_due`, `next_due_date`, `checklist`, etc.).
parameters:
- { name: page, in: query, schema: { type: integer } }
- { name: limit, in: query, schema: { type: integer } }
- { name: search, in: query, schema: { type: string } }
- { name: due_only, in: query, schema: { type: boolean } }
- { name: status, in: query, schema: { type: string } }
- { name: location_id, in: query, schema: { type: integer } }
- { name: is_active, in: query, schema: { type: boolean } }
responses:
'200':
description: Maintenance assets fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/export:
get:
tags: [Assets]
summary: Export assets CSV (same filters as list)
description: |
Requires `ASSET` → `export`. Returns CSV (opens in Excel).
No `id` column; date/datetime values formatted as `dd-mm-yyyy hh:mm`.
parameters:
- { name: search, in: query, schema: { type: string } }
- { name: status, in: query, schema: { type: string } }
- { name: condition, in: query, schema: { type: string } }
- { name: item_category_id, in: query, schema: { type: integer } }
- { name: item_subcategory_id, in: query, schema: { type: integer } }
- { name: location_id, in: query, schema: { type: integer } }
- { name: department_id, in: query, schema: { type: integer } }
- { name: maintenance_incharge_user_id, in: query, schema: { type: integer } }
- { name: due_only, in: query, schema: { type: boolean }, description: 'When true, only assets whose maintenance is due/overdue' }
- { name: is_active, in: query, schema: { type: boolean } }
responses:
'200':
description: CSV export
content:
text/csv:
schema: { type: string }
/assets:
get:
tags: [Assets]
summary: List assets
parameters:
- { name: page, in: query, schema: { type: integer } }
- { name: limit, in: query, schema: { type: integer } }
- { name: search, in: query, schema: { type: string } }
- { name: status, in: query, schema: { type: string } }
- { name: condition, in: query, schema: { type: string } }
- { name: item_category_id, in: query, schema: { type: integer } }
- { name: item_subcategory_id, in: query, schema: { type: integer } }
- { name: location_id, in: query, schema: { type: integer } }
- { name: department_id, in: query, schema: { type: integer } }
- { name: maintenance_incharge_user_id, in: query, schema: { type: integer } }
- { name: due_only, in: query, schema: { type: boolean } }
- { name: is_active, in: query, schema: { type: boolean } }
responses:
'200':
description: Assets fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
post:
tags: [Assets]
summary: Create asset
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/AssetsCreateBody' }
responses:
'201':
description: Asset created
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/{id}:
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
get:
tags: [Assets]
summary: Get asset (includes depreciation summary)
responses:
'200':
description: Asset fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
put:
tags: [Assets]
summary: Update asset
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/AssetsUpdateBody' }
responses:
'200':
description: Asset updated
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
delete:
tags: [Assets]
summary: Soft delete asset
responses:
'200':
description: Asset deleted
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/{id}/transfer:
post:
tags: [Assets]
summary: Transfer asset
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/TransferAssetBody' }
responses:
'200':
description: Asset transferred
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/{id}/transfer-history:
get:
tags: [Assets]
summary: Asset transfer history
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
responses:
'200':
description: Transfer history fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/{id}/maintenance-logs:
get:
tags: [Assets]
summary: List maintenance checklist logs for an asset
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
- { name: page, in: query, schema: { type: integer } }
- { name: limit, in: query, schema: { type: integer } }
responses:
'200':
description: Maintenance logs fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
post:
tags: [Assets]
summary: Submit a maintenance checklist (incharge only)
description: |
Only the asset's `maintenance_incharge_user_id` may submit.
Required checklist keys from `maintenance_checklist_json` must be present with status OK/NOT_OK/NA.
`next_due_date` defaults to performed_date + maintenance_frequency_in_days.
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/MaintenanceLogCreateBody' }
responses:
'201':
description: Checklist submitted
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
'403': { description: Not the maintenance incharge }
/assets/{id}/maintenance-logs/{logId}:
get:
tags: [Assets]
summary: Get a maintenance log by id
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
- { name: logId, in: path, required: true, schema: { type: string } }
responses:
'200':
description: Maintenance log fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
delete:
tags: [Assets]
summary: Soft-delete a maintenance log (incharge only)
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
- { name: logId, in: path, required: true, schema: { type: string } }
responses:
'200':
description: Maintenance log deleted
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/{assetId}/attachments:
get:
tags: [Assets]
summary: List asset attachments
parameters:
- { name: assetId, in: path, required: true, schema: { type: string, example: '1' } }
responses:
'200':
description: Attachments fetched
content:
application/json:
schema:
allOf:
- { $ref: '#/components/schemas/ApiResponse' }
- type: object
properties:
data:
type: array
items: { $ref: '#/components/schemas/AssetAttachmentResponse' }
'404': { description: Asset not found }
post:
tags: [Assets]
summary: Upload asset attachment
description: Multipart upload. Optional fields link file to AMC, service visit, or insurance policy.
parameters:
- { name: assetId, in: path, required: true, schema: { type: string, example: '1' } }
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required: [file]
properties:
file:
type: string
format: binary
attachment_type:
type: string
enum: [DOCUMENT, PHOTO, WARRANTY, INVOICE, AMC_CONTRACT, SERVICE_REPORT, INSURANCE_POLICY, OTHER]
default: DOCUMENT
amc_contract_id: { type: integer, nullable: true }
service_visit_id: { type: integer, nullable: true }
insurance_id: { type: integer, nullable: true }
responses:
'201':
description: Attachment uploaded
content:
application/json:
schema: { $ref: '#/components/schemas/ApiResponse' }
'400': { description: Invalid attachment_type or missing file }
'404': { description: Asset or linked record not found }
/assets/{assetId}/attachments/{attachmentId}:
get:
tags: [Assets]
summary: Get asset attachment metadata
parameters:
- { name: assetId, in: path, required: true, schema: { type: string, example: '1' } }
- { name: attachmentId, in: path, required: true, schema: { type: string, example: '1' } }
responses:
'200':
description: Attachment fetched
content:
application/json:
schema: { $ref: '#/components/schemas/ApiResponse' }
'404': { description: Not found }
delete:
tags: [Assets]
summary: Delete asset attachment
parameters:
- { name: assetId, in: path, required: true, schema: { type: string, example: '1' } }
- { name: attachmentId, in: path, required: true, schema: { type: string, example: '1' } }
responses:
'200':
description: Attachment deleted
content:
application/json:
schema: { $ref: '#/components/schemas/ApiResponse' }
'404': { description: Not found }
/assets/{assetId}/attachments/{attachmentId}/download:
get:
tags: [Assets]
summary: Download asset attachment file
parameters:
- { name: assetId, in: path, required: true, schema: { type: string, example: '1' } }
- { name: attachmentId, in: path, required: true, schema: { type: string, example: '1' } }
responses:
'200':
description: File download
content:
application/octet-stream:
schema: { type: string, format: binary }
'404': { description: Not found }
/assets/{id}/amc:
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
get:
tags: [Assets]
summary: List AMC contracts for asset
responses:
'200':
description: AMC contracts fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
post:
tags: [Assets]
summary: Create AMC contract
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/AmcContractBody' }
responses:
'201':
description: AMC contract created
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/{id}/amc/{contractId}:
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
- { name: contractId, in: path, required: true, schema: { type: string } }
get:
tags: [Assets]
summary: Get AMC contract
responses:
'200':
description: AMC contract fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
put:
tags: [Assets]
summary: Update AMC contract
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/AmcContractUpdateBody' }
responses:
'200':
description: AMC contract updated
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/{id}/amc/{contractId}/renew:
patch:
tags: [Assets]
summary: Renew AMC contract
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
- { name: contractId, in: path, required: true, schema: { type: string } }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/AmcRenewBody' }
responses:
'200':
description: AMC renewed
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/{id}/service-visits:
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
get:
tags: [Assets]
summary: List service visits
parameters:
- { name: status, in: query, schema: { type: string } }
- { name: visit_type, in: query, schema: { type: string } }
responses:
'200':
description: Service visits fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
post:
tags: [Assets]
summary: Log service visit
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/ServiceVisitBody' }
responses:
'201':
description: Service visit created
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/{id}/service-visits/{visitId}:
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
- { name: visitId, in: path, required: true, schema: { type: string } }
get:
tags: [Assets]
summary: Get service visit
responses:
'200':
description: Service visit fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
put:
tags: [Assets]
summary: Update service visit
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/ServiceVisitUpdateBody' }
responses:
'200':
description: Service visit updated
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/{id}/service-visits/{visitId}/status:
patch:
tags: [Assets]
summary: Update service visit status
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
- { name: visitId, in: path, required: true, schema: { type: string } }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/ServiceVisitStatusBody' }
responses:
'200':
description: Status updated
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/{id}/insurance:
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
get:
tags: [Assets]
summary: List insurance policies
responses:
'200':
description: Insurance policies fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
post:
tags: [Assets]
summary: Create insurance policy
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/InsurancePolicyBody' }
responses:
'201':
description: Insurance policy created
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/{id}/insurance/{policyId}:
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
- { name: policyId, in: path, required: true, schema: { type: string } }
get:
tags: [Assets]
summary: Get insurance policy
responses:
'200':
description: Insurance policy fetched
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
put:
tags: [Assets]
summary: Update insurance policy
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/InsurancePolicyUpdateBody' }
responses:
'200':
description: Insurance policy updated
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }
/assets/{id}/insurance/{policyId}/renew:
patch:
tags: [Assets]
summary: Renew insurance policy
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
- { name: policyId, in: path, required: true, schema: { type: string } }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/InsuranceRenewBody' }
responses:
'200':
description: Insurance renewed
content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } }