{"openapi":"3.0.0","info":{"title":"CRM API","version":"1.0.0","description":"A comprehensive CRM API for managing companies, branches, employees, clients, cars, orders, and inventory","contact":{"name":"API Support","email":"support@example.com"}},"servers":[{"url":"http://localhost:3001","description":"Local development server"},{"url":"http://45.153.184.216:3010","description":"Remote server"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT Authorization header using the Bearer scheme"}},"schemas":{"ErrorResponse":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Error message"}}},"ValidationError":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Validation error"}}},"SuccessResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Operation completed successfully"}}},"Pagination":{"type":"object","properties":{"page":{"type":"integer","example":1},"limit":{"type":"integer","example":10},"total":{"type":"integer","example":100},"pages":{"type":"integer","example":10}}},"Company":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000"},"name":{"type":"string","example":"ACME Corp"},"logo":{"type":"string","nullable":true,"example":"https://example.com/company-logo.png","description":"Company logo URL"},"includeVat":{"type":"boolean","description":"Whether to include VAT (ПДВ) in order calculations","example":true},"hideArticlesFromClients":{"type":"boolean","description":"Whether client-facing documents should hide product articles/SKUs","example":false},"createdAt":{"type":"string","format":"date-time","example":"2023-01-01T00:00:00Z"},"updatedAt":{"type":"string","format":"date-time","example":"2023-01-01T00:00:00Z"},"branches":{"type":"array","items":{"$ref":"#/components/schemas/Branch"}},"_count":{"type":"object","properties":{"branches":{"type":"integer"},"clients":{"type":"integer"}}}}},"CreateCompany":{"type":"object","required":["name"],"properties":{"name":{"type":"string","example":"ACME Corp"},"logo":{"type":"string","example":"https://example.com/company-logo.png","description":"Company logo URL (optional)"},"includeVat":{"type":"boolean","description":"Whether to include VAT (ПДВ) in order calculations","default":true,"example":true},"hideArticlesFromClients":{"type":"boolean","description":"Whether client-facing documents should hide product articles/SKUs","default":false,"example":false}}},"Branch":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000"},"companyId":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000"},"name":{"type":"string","example":"Main Branch"},"address":{"type":"string","nullable":true,"example":"123 Main St, City, State 12345"},"managerId":{"type":"string","format":"uuid","nullable":true,"example":"123e4567-e89b-12d3-a456-426614174000"},"phone":{"type":"string","example":"+380501234567","description":"Branch contact phone number"},"taxId":{"type":"string","nullable":true,"example":"12345678","description":"Tax identification number (ЄДРПОУ/ІПН)"},"bankDetails":{"type":"string","nullable":true,"example":"Bank Name, Account: 1234567890, MFO: 123456","description":"Bank account details for payments"},"ownerName":{"type":"string","nullable":true,"example":"John Smith","description":"Branch owner name"},"logo":{"type":"string","nullable":true,"example":"https://example.com/branch-logo.png","description":"Branch logo URL"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CreateBranch":{"type":"object","required":["name","address"],"properties":{"name":{"type":"string","example":"Main Branch"},"address":{"type":"string","example":"123 Main St, City, State 12345"},"phone":{"type":"string","example":"+380501234567","description":"Branch contact phone number (optional)"},"taxId":{"type":"string","example":"12345678","description":"Tax identification number (ЄДРПОУ/ІПН) (optional)"},"bankDetails":{"type":"string","example":"Bank Name, Account: 1234567890, MFO: 123456","description":"Bank account details for payments (optional)"},"ownerName":{"type":"string","example":"John Smith","description":"Branch owner name (optional)"},"managerId":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000"},"logo":{"type":"string","example":"https://example.com/branch-logo.png","description":"Branch logo URL (optional)"}}},"Employee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"branchId":{"type":"string","format":"uuid"},"name":{"type":"string","example":"John Doe"},"phone":{"type":"string","nullable":true,"example":"+1-234-567-8900"},"email":{"type":"string","format":"email","nullable":true,"example":"john.doe@example.com"},"skills":{"type":"array","items":{"type":"string"},"example":["Engine Repair","Brake Service"]},"hourlyRate":{"type":"number","format":"decimal","nullable":true,"example":25.5},"schedule":{"type":"object","nullable":true},"role":{"type":"string","enum":["APP_ADMIN","COMPANY_ADMIN","BRANCH_ADMIN","STAFF"],"example":"STAFF"},"profitType":{"type":"string","enum":["FIXED","PERCENTAGE"],"description":"Employee profit calculation type","example":"FIXED"},"profitValue":{"type":"number","format":"decimal","description":"Profit value (hourly rate for FIXED, percentage for PERCENTAGE)","example":1000,"nullable":true},"authStatus":{"type":"object","properties":{"hasCredentials":{"type":"boolean","description":"Whether employee has authentication credentials"},"canInvite":{"type":"boolean","description":"Whether employee can be invited (has email but no credentials)"},"hasEmail":{"type":"boolean","description":"Whether employee has email address"},"invitationSent":{"type":"boolean","description":"Whether invitation was sent"},"emailVerified":{"type":"boolean","description":"Whether email is verified"},"passwordCreated":{"type":"boolean","description":"Whether password was created"},"invitedAt":{"type":"string","format":"date-time","nullable":true,"description":"When invitation was sent"}}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CreateEmployee":{"type":"object","required":["name"],"properties":{"name":{"type":"string","example":"John Doe"},"phone":{"type":"string","example":"+1-234-567-8900"},"email":{"type":"string","format":"email","example":"john.doe@example.com"},"skills":{"type":"array","items":{"type":"string"},"example":["Engine Repair","Brake Service"]},"hourlyRate":{"type":"number","format":"decimal","example":25.5},"schedule":{"type":"object"},"role":{"type":"string","enum":["APP_ADMIN","COMPANY_ADMIN","BRANCH_ADMIN","STAFF"],"example":"STAFF"}}},"Car":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"vin":{"type":"string","nullable":true,"example":"1HGBH41JXMN109186"},"make":{"type":"string","nullable":true,"example":"Honda"},"model":{"type":"string","nullable":true,"example":"Civic"},"year":{"type":"integer","nullable":true,"example":2020},"trim":{"type":"string","nullable":true,"example":"LX"},"mileage":{"type":"integer","nullable":true,"example":50000},"color":{"type":"string","nullable":true,"example":"синий"},"licensePlate":{"type":"string","nullable":true,"example":"AB1234CD","description":"Vehicle license plate number"},"engineVolume":{"type":"string","example":"2.0L","description":"Engine displacement volume"},"photos":{"type":"array","items":{"type":"string"},"example":["photo1.jpg","photo2.jpg"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CreateCar":{"type":"object","description":"Partial vehicle data. At least one of vin, licensePlate, or make must be provided.","properties":{"vin":{"type":"string","example":"1HGBH41JXMN109186"},"make":{"type":"string","example":"Honda"},"model":{"type":"string","example":"Civic"},"year":{"type":"integer","example":2020},"trim":{"type":"string","example":"LX"},"mileage":{"type":"integer","example":50000},"color":{"type":"string","example":"синий"},"licensePlate":{"type":"string","example":"AB1234CD","description":"Vehicle license plate number"},"engineVolume":{"type":"string","example":"2.0L","description":"Engine displacement volume"},"photos":{"type":"array","items":{"type":"string"},"example":["photo1.jpg","photo2.jpg"]}}},"Client":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"carId":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Jane Smith"},"phone":{"type":"string","nullable":true,"example":"+1-234-567-8901"},"email":{"type":"string","format":"email","nullable":true,"example":"jane.smith@example.com"},"address":{"type":"string","nullable":true,"example":"456 Oak Ave, City, State 12346"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CreateClient":{"type":"object","required":["name","carId"],"properties":{"name":{"type":"string","example":"Jane Smith"},"carId":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000"},"phone":{"type":"string","example":"+1-234-567-8901"},"email":{"type":"string","format":"email","example":"jane.smith@example.com"},"address":{"type":"string","example":"456 Oak Ave, City, State 12346"}}},"WorkType":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Oil Change"},"isHourlyRate":{"type":"boolean","description":"Whether this work type uses hourly pricing (true) or fixed pricing (false)","example":true},"price":{"type":"number","format":"decimal","example":75,"description":"Price (hourly rate if isHourlyRate=true, fixed price if isHourlyRate=false)"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CreateWorkType":{"type":"object","required":["name","isHourlyRate","price"],"properties":{"name":{"type":"string","example":"Oil Change"},"isHourlyRate":{"type":"boolean","description":"Whether this work type uses hourly pricing (true) or fixed pricing (false)","example":true},"price":{"type":"number","format":"decimal","example":75,"description":"Price (hourly rate if isHourlyRate=true, fixed price if isHourlyRate=false)"}}},"Vendor":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Parts Supplier Inc"},"location":{"type":"string","nullable":true,"example":"789 Industrial Blvd, City, State 12347"},"contactInfo":{"type":"object","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CreateVendor":{"type":"object","required":["name"],"properties":{"name":{"type":"string","example":"Parts Supplier Inc"},"location":{"type":"string","example":"789 Industrial Blvd, City, State 12347"},"contactInfo":{"type":"object"}}},"Warehouse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Main Warehouse"},"location":{"type":"string","nullable":true,"example":"123 Storage Way, City, State 12348"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CreateWarehouse":{"type":"object","required":["name"],"properties":{"name":{"type":"string","example":"Main Warehouse"},"location":{"type":"string","example":"123 Storage Way, City, State 12348"}}},"Order":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"branchId":{"type":"string","format":"uuid"},"carId":{"type":"string","format":"uuid"},"clientId":{"type":"string","format":"uuid"},"responsibleEmployeeId":{"type":"string","format":"uuid"},"car":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"vin":{"type":"string","example":"1HGBH41JXMN109186"},"make":{"type":"string","example":"Honda"},"model":{"type":"string","example":"Civic"},"year":{"type":"integer","example":2020},"licensePlate":{"type":"string","example":"AB1234CD"},"engineVolume":{"type":"string","example":"2.0L"}}},"client":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Jane Smith"},"phone":{"type":"string","example":"+1-234-567-8901"},"email":{"type":"string","format":"email","example":"jane.smith@example.com"}}},"responsibleEmployee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"John Doe"},"role":{"type":"string","enum":["APP_ADMIN","COMPANY_ADMIN","BRANCH_ADMIN","STAFF"]},"skills":{"type":"array","items":{"type":"string"},"example":["Engine Repair","Brake Service"]}}},"branch":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Main Branch"},"company":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"ACME Corp"}}}}},"_count":{"type":"object","properties":{"orderWorks":{"type":"integer"},"orderItems":{"type":"integer"}}},"financialSummary":{"type":"object","description":"Consolidated financial summary for the order","properties":{"clientCosts":{"type":"object","description":"Totals presented to the client","properties":{"partsCost":{"type":"number","format":"decimal","description":"Total parts cost charged to the client"},"workCost":{"type":"number","format":"decimal","description":"Total labour cost charged to the client"},"subtotal":{"type":"number","format":"decimal","description":"Subtotal before VAT"},"vatAmount":{"type":"number","format":"decimal","description":"VAT amount charged to the client"},"vatRate":{"type":"number","format":"decimal","description":"Applied VAT rate percentage"},"total":{"type":"number","format":"decimal","description":"Total client charge including VAT"},"includeVat":{"type":"boolean","description":"Indicates if VAT was applied"}}},"internalCosts":{"type":"object","description":"Internal cost structure used for profit calculations","properties":{"partsCost":{"type":"number","format":"decimal","description":"Internal cost of parts used in the order"},"totalCost":{"type":"number","format":"decimal","description":"Combined internal costs"}}},"profit":{"type":"object","description":"Profit metrics calculated for the order","properties":{"totalPartsProfit":{"type":"number","format":"decimal","description":"Profit derived from parts"},"totalEmployeeProfit":{"type":"number","format":"decimal","description":"Profit attributed to employee labour"},"netProfit":{"type":"number","format":"decimal","description":"Combined parts and labour profit"},"profitMargin":{"type":"number","format":"decimal","description":"Profit margin percentage relative to client subtotal"}}}}},"status":{"type":"string","enum":["PENDING","IN_PROGRESS","WAITING_FOR_PARTS","QUALITY_CHECK","COMPLETED","CANCELLED"],"example":"PENDING"},"description":{"type":"string","nullable":true,"example":"Regular maintenance service"},"photos":{"type":"array","items":{"type":"string"},"example":["before1.jpg","before2.jpg"]},"videos":{"type":"array","items":{"type":"string"},"example":["inspection.mp4"]},"entryDate":{"type":"string","format":"date-time","description":"Order entry date (automatically set)"},"exitDate":{"type":"string","format":"date-time","nullable":true,"description":"Order completion date (set when order is completed)"},"totalWorkAmount":{"type":"number","format":"decimal","description":"Total amount for work services","example":150.5},"totalPartsAmount":{"type":"number","format":"decimal","description":"Total amount for parts used","example":89.99},"totalAmount":{"type":"number","format":"decimal","description":"Total order amount (work + parts)","example":240.49},"orderNumber":{"type":"string","description":"Unique order number","example":"ORD-2024-001"},"subtotalAmount":{"type":"number","format":"decimal","description":"Subtotal amount before VAT","example":200.41},"vatRate":{"type":"number","format":"decimal","description":"VAT rate percentage","example":20},"vatAmount":{"type":"number","format":"decimal","description":"VAT amount","example":40.08},"warrantyPeriod":{"type":"string","nullable":true,"description":"Warranty period","example":"6 months"},"warrantyTerms":{"type":"string","nullable":true,"description":"Warranty terms and conditions","example":"Standard warranty terms apply"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CreateOrder":{"type":"object","required":["carId","clientId","responsibleEmployeeId"],"properties":{"carId":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000"},"clientId":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000"},"responsibleEmployeeId":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000"},"status":{"type":"string","enum":["PENDING","IN_PROGRESS","WAITING_FOR_PARTS","QUALITY_CHECK","COMPLETED","CANCELLED"],"example":"PENDING"},"description":{"type":"string","example":"Regular maintenance service"},"photos":{"type":"array","items":{"type":"string"},"example":["before1.jpg","before2.jpg"]},"videos":{"type":"array","items":{"type":"string"},"example":["inspection.mp4"]}}},"InventoryItemType":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Engine Oil 5W-30"},"unitOfMeasure":{"type":"string","example":"liters"},"storageType":{"type":"string","enum":["BATCH","UNIT"],"example":"BATCH"},"vendorId":{"type":"string","format":"uuid","nullable":true},"purchasePrice":{"type":"number","nullable":true,"minimum":0,"example":25.5,"description":"Purchase price per unit"},"salePrice":{"type":"number","nullable":true,"minimum":0,"example":35.75,"description":"Sale price per unit"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CreateInventoryItemType":{"type":"object","required":["name","unitOfMeasure","storageType"],"properties":{"name":{"type":"string","example":"Engine Oil 5W-30"},"unitOfMeasure":{"type":"string","example":"liters"},"storageType":{"type":"string","enum":["BATCH","UNIT"],"example":"BATCH"},"vendorId":{"type":"string","format":"uuid"},"purchasePrice":{"type":"number","minimum":0,"example":25.5,"description":"Purchase price per unit"},"salePrice":{"type":"number","minimum":0,"example":35.75,"description":"Sale price per unit"}}},"LoginRequest":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email","example":"user@example.com"},"password":{"type":"string","example":"password123"}}},"LoginResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"token":{"type":"string","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."},"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"John Doe"},"email":{"type":"string","format":"email","example":"john.doe@example.com"},"role":{"type":"string","enum":["APP_ADMIN","COMPANY_ADMIN","BRANCH_ADMIN","STAFF"],"example":"STAFF"},"branch":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Main Branch"},"company":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"ACME Corp"}}}}}}}}},"message":{"type":"string","example":"Login successful"}}},"HealthResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"status":{"type":"string","example":"healthy"},"timestamp":{"type":"string","format":"date-time","example":"2023-01-01T00:00:00Z"},"database":{"type":"string","example":"connected"},"environment":{"type":"string","example":"development"}}},"message":{"type":"string","example":"Service is healthy"}}},"PaginationInfo":{"type":"object","properties":{"page":{"type":"integer","example":1},"limit":{"type":"integer","example":10},"total":{"type":"integer","example":50},"pages":{"type":"integer","example":5}}},"EmployeeBranchAssignment":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"branchId":{"type":"string","format":"uuid"},"branch":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Downtown Branch"}}}}},"EmployeeWithCompanyDetails":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000"},"name":{"type":"string","example":"John Smith"},"phone":{"type":"string","example":"+1234567890","nullable":true},"email":{"type":"string","format":"email","example":"john.smith@company.com","nullable":true},"skills":{"type":"array","items":{"type":"string"},"example":["Management","Customer Service"]},"hourlyRate":{"type":"number","format":"decimal","example":50,"nullable":true},"schedule":{"type":"object","nullable":true},"role":{"type":"string","enum":["APP_ADMIN","COMPANY_ADMIN","BRANCH_ADMIN","STAFF"],"example":"STAFF"},"profitType":{"type":"string","enum":["FIXED","PERCENTAGE"],"description":"Employee profit calculation type","example":"FIXED"},"profitValue":{"type":"number","format":"decimal","description":"Profit value (hourly rate for FIXED, percentage for PERCENTAGE)","example":1000,"nullable":true},"companyId":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"company":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"ACME Corp"}}},"branches":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Downtown Branch"},"address":{"type":"string","example":"123 Main St"},"assignmentId":{"type":"string","format":"uuid"}}}}}},"CreateCompanyEmployeeRequest":{"type":"object","required":["name","role"],"properties":{"name":{"type":"string","example":"John Smith","minLength":1,"maxLength":255},"phone":{"type":"string","example":"+1234567890","pattern":"^[+]?[0-9()-\\s]+$"},"email":{"type":"string","format":"email","example":"john.smith@company.com"},"skills":{"type":"array","items":{"type":"string"},"maxItems":20,"example":["Management","Customer Service"]},"hourlyRate":{"type":"number","format":"decimal","minimum":0,"maximum":10000,"example":50},"schedule":{"type":"object","description":"JSON object representing work schedule"},"role":{"type":"string","enum":["APP_ADMIN","COMPANY_ADMIN","BRANCH_ADMIN","STAFF"],"default":"STAFF"},"profitType":{"type":"string","enum":["FIXED","PERCENTAGE"],"description":"Employee profit calculation type","default":"FIXED","example":"FIXED"},"profitValue":{"type":"number","format":"decimal","description":"Profit value (hourly rate for FIXED, percentage for PERCENTAGE)","minimum":0,"maximum":100000,"example":1000},"branches":{"type":"array","maxItems":10,"items":{"type":"object","required":["branchId"],"properties":{"branchId":{"type":"string","format":"uuid"}}}}}},"UpdateEmployeeRequest":{"type":"object","properties":{"name":{"type":"string","example":"John Smith Updated","minLength":1,"maxLength":255},"phone":{"type":"string","example":"+1234567890","pattern":"^[+]?[0-9()-\\s]+$"},"email":{"type":"string","format":"email","example":"john.updated@company.com"},"skills":{"type":"array","items":{"type":"string"},"maxItems":20,"example":["Management","Leadership","Strategy"]},"hourlyRate":{"type":"number","format":"decimal","minimum":0,"maximum":10000,"example":55},"schedule":{"type":"object","description":"JSON object representing work schedule"},"role":{"type":"string","enum":["APP_ADMIN","COMPANY_ADMIN","BRANCH_ADMIN","STAFF"]},"profitType":{"type":"string","enum":["FIXED","PERCENTAGE"],"description":"Employee profit calculation type","example":"PERCENTAGE"},"profitValue":{"type":"number","format":"decimal","description":"Profit value (hourly rate for FIXED, percentage for PERCENTAGE)","minimum":0,"maximum":100000,"example":15},"branches":{"type":"array","maxItems":10,"description":"Replace all branch assignments","items":{"type":"object","required":["branchId"],"properties":{"branchId":{"type":"string","format":"uuid"}}}}}},"OrderItemAllocationStatus":{"type":"string","enum":["RESERVED","CONSUMED","RELEASED","WRITTEN_OFF"],"description":"Status of an inventory reservation/allocation","example":"RESERVED"},"PricingType":{"type":"string","enum":["HOURLY","FIXED"],"description":"Pricing type for work types","example":"HOURLY"},"OrderWork":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Order work ID"},"orderId":{"type":"string","format":"uuid","description":"Order ID"},"workTypeId":{"type":"string","format":"uuid","description":"Work type ID"},"executorEmployeeId":{"type":"string","format":"uuid","nullable":true,"description":"ID of employee who executed the work"},"hours":{"type":"number","format":"decimal","description":"Hours worked","example":2.5},"workType":{"$ref":"#/components/schemas/WorkType"},"executorEmployee":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"John Doe"},"email":{"type":"string","format":"email","nullable":true},"role":{"type":"string","enum":["APP_ADMIN","COMPANY_ADMIN","BRANCH_ADMIN","STAFF"]}}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CreateOrderWork":{"type":"object","required":["workTypeId","hours"],"properties":{"workTypeId":{"type":"string","format":"uuid","description":"Work type ID"},"executorEmployeeId":{"type":"string","format":"uuid","description":"ID of employee who will execute the work (optional)"},"hours":{"type":"number","format":"decimal","minimum":0.01,"description":"Hours worked","example":2.5}}},"Appointment":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Appointment ID"},"branchId":{"type":"string","format":"uuid","description":"Branch ID"},"clientId":{"type":"string","format":"uuid","description":"Client ID"},"carId":{"type":"string","format":"uuid","description":"Car ID"},"responsibleEmployeeId":{"type":"string","format":"uuid","nullable":true,"description":"Responsible employee ID"},"startTime":{"type":"string","format":"date-time","description":"Appointment start time","example":"2024-12-01T10:00:00Z"},"endTime":{"type":"string","format":"date-time","description":"Appointment end time","example":"2024-12-01T11:30:00Z"},"estimatedDuration":{"type":"integer","description":"Estimated duration in minutes","example":90},"description":{"type":"string","nullable":true,"description":"Appointment description","example":"Oil change and tire rotation"},"notes":{"type":"string","nullable":true,"description":"Internal notes","example":"Client prefers synthetic oil"},"status":{"type":"string","enum":["SCHEDULED","CONFIRMED","CANCELLED","NO_SHOW"],"description":"Appointment status","example":"SCHEDULED"},"orderId":{"type":"string","format":"uuid","nullable":true,"description":"Related order ID (if appointment was converted to order)"},"branch":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Main Branch"}}},"client":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Jane Smith"},"phone":{"type":"string","example":"+1-234-567-8901"},"email":{"type":"string","format":"email","example":"jane.smith@example.com"}}},"car":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"vin":{"type":"string","example":"1HGBH41JXMN109186"},"make":{"type":"string","example":"Honda"},"model":{"type":"string","example":"Civic"},"year":{"type":"integer","example":2020},"licensePlate":{"type":"string","example":"AB1234CD"},"engineVolume":{"type":"string","example":"2.0L"}}},"responsibleEmployee":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"John Doe"},"role":{"type":"string","enum":["APP_ADMIN","COMPANY_ADMIN","BRANCH_ADMIN","STAFF"]},"skills":{"type":"array","items":{"type":"string"},"example":["Engine Repair","Brake Service"]}}},"order":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"orderNumber":{"type":"string","example":"ORD-2024-001"},"status":{"type":"string","enum":["PENDING","IN_PROGRESS","WAITING_FOR_PARTS","QUALITY_CHECK","COMPLETED","CANCELLED"]}}},"createdAt":{"type":"string","format":"date-time","description":"Creation timestamp"},"updatedAt":{"type":"string","format":"date-time","description":"Last update timestamp"}}},"CreateAppointment":{"type":"object","required":["clientId","carId","startTime","endTime","estimatedDuration"],"properties":{"clientId":{"type":"string","format":"uuid","description":"Client ID","example":"d20f2f80-8ab7-4186-9a78-c187c7ff13f6"},"carId":{"type":"string","format":"uuid","description":"Car ID","example":"137fe84a-91cf-4614-91ef-e46f7a9501b6"},"responsibleEmployeeId":{"type":"string","format":"uuid","description":"Responsible employee ID (optional)","example":"07f88b87-43d0-4e4a-8350-e9907a6d155b"},"startTime":{"type":"string","format":"date-time","description":"Appointment start time","example":"2024-12-01T10:00:00Z"},"endTime":{"type":"string","format":"date-time","description":"Appointment end time (must be after startTime)","example":"2024-12-01T11:30:00Z"},"estimatedDuration":{"type":"integer","minimum":1,"maximum":1440,"description":"Estimated duration in minutes (1-1440)","example":90},"description":{"type":"string","maxLength":2000,"description":"Appointment description (optional)","example":"Oil change and tire rotation"},"notes":{"type":"string","maxLength":2000,"description":"Internal notes (optional)","example":"Client prefers synthetic oil"},"status":{"type":"string","enum":["SCHEDULED","CONFIRMED","CANCELLED","NO_SHOW"],"description":"Initial appointment status (optional, defaults to SCHEDULED)","default":"SCHEDULED","example":"SCHEDULED"}}},"UpdateAppointment":{"type":"object","properties":{"clientId":{"type":"string","format":"uuid","description":"Client ID (optional)"},"carId":{"type":"string","format":"uuid","description":"Car ID (optional)"},"responsibleEmployeeId":{"type":"string","format":"uuid","nullable":true,"description":"Responsible employee ID (optional)"},"startTime":{"type":"string","format":"date-time","description":"Appointment start time (optional)"},"endTime":{"type":"string","format":"date-time","description":"Appointment end time (optional, must be after startTime)"},"estimatedDuration":{"type":"integer","minimum":1,"maximum":1440,"description":"Estimated duration in minutes (optional)"},"description":{"type":"string","maxLength":2000,"nullable":true,"description":"Appointment description (optional)"},"notes":{"type":"string","maxLength":2000,"nullable":true,"description":"Internal notes (optional)"},"status":{"type":"string","enum":["SCHEDULED","CONFIRMED","CANCELLED","NO_SHOW"],"description":"Appointment status (optional)"},"orderId":{"type":"string","format":"uuid","nullable":true,"description":"Related order ID (optional)"}}},"DaySchedule":{"type":"object","required":["isOpen"],"properties":{"isOpen":{"type":"boolean","description":"Whether the branch is open on this day","example":true},"openTime":{"type":"string","pattern":"^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$","nullable":true,"description":"Opening time in HH:MM format (24-hour)","example":"09:00"},"closeTime":{"type":"string","pattern":"^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$","nullable":true,"description":"Closing time in HH:MM format (24-hour)","example":"18:00"}}}},"responses":{"BadRequest":{"description":"Bad request - invalid input data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Unauthorized - authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Forbidden":{"description":"Forbidden - insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"InternalError":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"parameters":{"PageParam":{"in":"query","name":"page","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number for pagination"},"LimitParam":{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":10},"description":"Number of items per page"},"SearchParam":{"in":"query","name":"search","schema":{"type":"string"},"description":"Search term for filtering results"},"CompanyIdPath":{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},"BranchIdPath":{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},"EmployeeIdPath":{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Employee ID"},"CarIdPath":{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Car ID"}}},"security":[{"bearerAuth":[]}],"paths":{"/api/admin/order-reopen-requests":{"get":{"summary":"List global order reopen requests","description":"Retrieves order reopen requests across companies for app administrators.","tags":["Order Reopen Requests"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"status","required":false,"schema":{"type":"string","enum":["PENDING","APPROVED","REJECTED","EXECUTED"]},"description":"Optional reopen request status filter"},{"in":"query","name":"companyId","required":false,"schema":{"type":"string","format":"uuid"},"description":"Optional company ID filter"}],"responses":{"200":{"description":"Order reopen requests retrieved successfully"},"400":{"description":"Invalid query parameters"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - app admin access required"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/admin/subscriptions/{subscriptionId}/cancel":{"post":{"summary":"Cancel a subscription manually","tags":["Admin Subscriptions"],"security":[{"bearerAuth":[]}]}},"/api/admin/subscriptions/{subscriptionId}":{"patch":{"summary":"Update a subscription manually","tags":["Admin Subscriptions"],"security":[{"bearerAuth":[]}]}},"/api/admin/subscriptions/company/{companyId}":{"post":{"summary":"Create or update a company's latest subscription manually","tags":["Admin Subscriptions"],"security":[{"bearerAuth":[]}]},"delete":{"summary":"Remove a company from active admin lists while preserving client history","tags":["Admin Subscriptions"],"security":[{"bearerAuth":[]}]}},"/api/admin/subscriptions":{"get":{"summary":"List company subscriptions for app admins","tags":["Admin Subscriptions"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Company subscriptions retrieved successfully"},"403":{"description":"Forbidden - app admin access required"}}}},"/api/appointments/{appointmentId}/convert-to-order":{"post":{"summary":"Convert an appointment to an order","description":"Converts an appointment into an order. This is used when a client arrives\nand work is ready to begin. The appointment data (client, car, employee, description)\nis copied to create a new order, and the appointment is linked to this order.\n\nRequirements:\n- Appointment must exist and not be CANCELLED\n- Appointment must not already be converted (orderId must be null)\n- Car must be specified (either in appointment or in request body)\n- User must have STAFF or higher permissions\n","tags":["Appointments"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"appointmentId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Appointment ID to convert"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"carId":{"type":"string","format":"uuid","description":"Car ID (required if appointment doesn't have one)","example":"137fe84a-91cf-4614-91ef-e46f7a9501b6"},"completedMileage":{"type":"integer","minimum":0,"description":"Current vehicle mileage (optional)","example":50000},"additionalDescription":{"type":"string","maxLength":2000,"description":"Additional details after vehicle inspection (optional)","example":"After inspection: found brake pad wear"},"initialStatus":{"type":"string","enum":["PENDING","IN_PROGRESS","WAITING_FOR_PARTS","QUALITY_CHECK","COMPLETED","CANCELLED"],"default":"IN_PROGRESS","description":"Initial status for the created order"}}}}}},"responses":{"200":{"description":"Appointment successfully converted to order","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Appointment converted to order successfully"},"data":{"type":"object","properties":{"appointment":{"$ref":"#/components/schemas/Appointment"},"order":{"$ref":"#/components/schemas/Order"}}}}}}}},"400":{"description":"Bad request - appointment already converted or cancelled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"already_converted":{"value":{"success":false,"error":"Appointment is already converted to an order"}},"cancelled":{"value":{"success":false,"error":"Cannot convert cancelled appointment to order"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Appointment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/auth/change-email/confirm":{"post":{"summary":"Finalize email change after user clicks Supabase link","description":"Accepts the `access_token` from the Supabase email-change action link, updates the local employee email, and marks it verified.","tags":["Authentication"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"accessToken":{"type":"string","description":"access_token query param from the Supabase action link"}}}}}},"responses":{"200":{"description":"Email updated locally to match Supabase"},"400":{"description":"Validation error"},"404":{"description":"Employee or auth user not found"},"409":{"description":"Email already used by another employee"},"500":{"description":"Internal server error"}}}},"/api/auth/change-email":{"post":{"summary":"Change account email (immediate)","description":"Updates Supabase auth email and the local employee record after verifying the current password.","tags":["Authentication"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["newEmail","currentPassword"],"properties":{"newEmail":{"type":"string","format":"email","description":"New email for the account"},"currentPassword":{"type":"string","description":"Current account password for verification"}}}}}},"responses":{"200":{"description":"Email updated immediately"},"400":{"description":"Validation error or incorrect credentials"},"401":{"description":"Unauthorized"},"409":{"description":"Email already in use"},"500":{"description":"Internal server error"}}}},"/api/auth/change-password":{"post":{"summary":"Change user password","description":"Allows an authenticated Supabase user to change their password after providing the current password.","tags":["Authentication"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["currentPassword","newPassword","confirmPassword"],"properties":{"currentPassword":{"type":"string","description":"Current account password"},"newPassword":{"type":"string","description":"New password that meets security policy"},"confirmPassword":{"type":"string","description":"Must match newPassword"}}}}}},"responses":{"200":{"description":"Password changed successfully"},"400":{"description":"Validation error or incorrect current password"},"401":{"description":"Unauthorized"},"404":{"description":"Supabase user not found"},"500":{"description":"Internal server error"}}}},"/api/auth/confirm-code":{"post":{"summary":"Confirm email by code","description":"Verifies the signup confirmation code sent by email and marks the employee as verified.","tags":["Authentication"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","code"],"properties":{"email":{"type":"string","format":"email"},"code":{"type":"string","example":"123456"}}}}}},"responses":{"200":{"description":"Email confirmed successfully"},"400":{"description":"Validation error or invalid code"},"404":{"description":"Employee record not found"}}}},"/api/auth/delete-account":{"delete":{"summary":"Delete current account","description":"Deletes authenticated user's access to the system, detaches active assignments, and anonymizes profile data.","tags":["Authentication"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Account deleted successfully"},"401":{"description":"Unauthorized"},"404":{"description":"User not found"},"409":{"description":"Conflict - deleting this account is not allowed (e.g. last company admin)"},"500":{"description":"Internal server error"}}}},"/api/auth/login":{"post":{"summary":"Authenticate user","description":"Authenticates an employee with email and password using Supabase Auth","tags":["Authentication"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email","description":"User's email address"},"password":{"type":"string","description":"User's password"}}}}}},"responses":{"200":{"description":"Login successful","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"token":{"type":"string","description":"Supabase access token"},"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":"string"},"role":{"type":"string","enum":["APP_ADMIN","COMPANY_ADMIN","BRANCH_ADMIN","STAFF"]},"branch":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"company":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}}}}}}},"session":{"type":"object","description":"Supabase session data"}}}}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Authentication failed - various scenarios","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"code":{"type":"string","enum":["EMAIL_NOT_FOUND","INVALID_PASSWORD","AUTHENTICATION_FAILED"],"description":"Specific error code for authentication failure"}}}]},"examples":{"email_not_found":{"summary":"Email not found in system","value":{"success":false,"error":"No account found with this email address","code":"EMAIL_NOT_FOUND"}},"invalid_password":{"summary":"Wrong password for existing email","value":{"success":false,"error":"Incorrect password. Please check your password and try again.","code":"INVALID_PASSWORD"}},"auth_failed":{"summary":"General authentication failure","value":{"success":false,"error":"Unable to authenticate. Please try again or contact support.","code":"AUTHENTICATION_FAILED"}}}}}},"403":{"description":"Access forbidden - email not verified","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"code":{"type":"string","enum":["EMAIL_NOT_VERIFIED"],"description":"Error code indicating email verification is required"}}}]},"example":{"success":false,"error":"Email not verified. Please check your email and click the verification link before logging in.","code":"EMAIL_NOT_VERIFIED"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/auth/logout":{"post":{"summary":"Log out user","description":"Logs out the authenticated user by invalidating their session","tags":["Authentication"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Logout successful","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/auth/me":{"get":{"summary":"Get current user profile","description":"Retrieves the authenticated user's profile information","tags":["Authentication"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"User profile retrieved successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"role":{"type":"string","enum":["APP_ADMIN","COMPANY_ADMIN","BRANCH_ADMIN","STAFF"]},"skills":{"type":"array","items":{"type":"string"}},"hourlyRate":{"type":"number","format":"decimal"},"schedule":{"type":"object"},"authId":{"type":"string","format":"uuid","description":"Supabase Auth user ID"},"branch":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"},"company":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}}}},"stats":{"type":"object","properties":{"responsibleOrders":{"type":"integer"},"managedBranches":{"type":"integer"}}}}}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"User not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/auth/oauth/apple":{"post":{"summary":"Apple OAuth login for mobile clients","description":"Authenticates a mobile user using an Apple identity token from native Sign in with Apple.","tags":["Authentication"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["identityToken"],"properties":{"identityToken":{"type":"string","description":"Apple Identity Token (JWT) from native Sign in with Apple"},"fullName":{"type":"object","description":"User's name (Apple sends only on first sign-in)","properties":{"givenName":{"type":"string","nullable":true},"familyName":{"type":"string","nullable":true}}},"nonce":{"type":"string","nullable":true,"description":"Raw nonce for replay attack prevention"}}}}}},"responses":{"200":{"description":"OAuth login successful","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"OAuth login successful"},"data":{"type":"object","properties":{"session":{"type":"object","properties":{"access_token":{"type":"string"},"refresh_token":{"type":"string","nullable":true},"expires_at":{"type":"integer","description":"Unix timestamp (seconds)"},"token_type":{"type":"string","enum":["Bearer"]}}},"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"created_at":{"type":"string"}}},"needs_onboarding":{"type":"boolean"}}}}}}}},"400":{"description":"Validation error"},"401":{"description":"Invalid token"}}}},"/api/auth/oauth/google":{"post":{"summary":"Google OAuth login for mobile clients","description":"Authenticates a mobile user using a Google ID token from native Google SDK.","tags":["Authentication"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["idToken"],"properties":{"idToken":{"type":"string","description":"Google ID Token (JWT) issued by native Google SDK"}}}}}},"responses":{"200":{"description":"OAuth login successful","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"OAuth login successful"},"data":{"type":"object","properties":{"session":{"type":"object","properties":{"access_token":{"type":"string"},"refresh_token":{"type":"string","nullable":true},"expires_at":{"type":"integer","description":"Unix timestamp (seconds)"},"token_type":{"type":"string","enum":["Bearer"],"example":"Bearer"}}},"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"needs_onboarding":{"type":"boolean","description":"True when user has no branch assignments yet"}}}}}}}},"400":{"description":"Invalid request payload or OAuth processing error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid or expired Google ID token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/auth/refresh":{"post":{"summary":"Refresh an expired session","description":"Exchanges a Supabase refresh token for a fresh access token (and a rotated refresh token). Used by mobile clients (Bearer flow) to keep a session alive past the ~1h access-token lifetime without forcing the user to log in again. The refresh token may be supplied in the JSON body or via the httpOnly `refresh_token` cookie (web same-origin flow).\n","tags":["Authentication"],"security":[],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"refresh_token":{"type":"string","description":"Supabase refresh token issued at login."}}}}}},"responses":{"200":{"description":"Session refreshed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"session":{"type":"object","properties":{"access_token":{"type":"string"},"refresh_token":{"type":"string","nullable":true},"expires_at":{"type":"integer","description":"Unix timestamp (seconds)"},"token_type":{"type":"string","enum":["Bearer"]}}}}}}}}}},"400":{"description":"Missing refresh token"},"401":{"description":"Refresh token invalid or expired"}}}},"/api/auth/register-company-owner":{"post":{"summary":"Register a new business owner with complete company setup","description":"Creates a complete business registration including Supabase Auth user, company, branch, and company admin employee in a single transaction","tags":["Authentication","Company Registration"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["user","company","branch","employee"],"properties":{"user":{"type":"object","required":["email","password","name"],"properties":{"email":{"type":"string","format":"email","description":"Business owner's email address","example":"owner@autofix.com"},"password":{"type":"string","minLength":8,"pattern":"^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]","description":"Strong password (uppercase, lowercase, number, special char)","example":"SecurePass123!"},"name":{"type":"string","description":"Business owner's full name","example":"John Smith"}}},"company":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Company name","example":"AutoFix Pro Services"}}},"branch":{"type":"object","required":["name","address","phone"],"properties":{"name":{"type":"string","description":"Main branch name","example":"Main Location"},"address":{"type":"string","description":"Branch address","example":"123 Main St, City, State 12345"},"phone":{"type":"string","pattern":"^[+]?[0-9()-\\s]+$","minLength":10,"maxLength":20,"description":"Branch contact phone number","example":"+380501234567"}}},"employee":{"type":"object","properties":{"phone":{"type":"string","description":"Business owner's phone number","example":"+1-555-123-4567"},"skills":{"type":"array","items":{"type":"string"},"description":"Owner's skills and expertise","default":["Management","Customer Service"],"example":["Management","Customer Service","Auto Repair"]}}}}}}}},"responses":{"201":{"description":"Business registration completed successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Supabase Auth user ID"},"email":{"type":"string","format":"email","description":"User's email address"},"name":{"type":"string","description":"User's full name"}}},"company":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Created company ID"},"name":{"type":"string","description":"Company name"},"createdAt":{"type":"string","format":"date-time","description":"Company creation timestamp"}}},"branch":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Main branch ID"},"name":{"type":"string","description":"Branch name"},"address":{"type":"string","description":"Branch address"},"managerId":{"type":"string","format":"uuid","description":"Branch manager (owner) ID"},"createdAt":{"type":"string","format":"date-time","description":"Branch creation timestamp"}}},"employee":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Employee record ID"},"name":{"type":"string","description":"Employee name"},"email":{"type":"string","format":"email","description":"Employee email"},"phone":{"type":"string","description":"Employee phone number"},"role":{"type":"string","enum":["COMPANY_ADMIN"],"description":"Employee role (always COMPANY_ADMIN)"},"skills":{"type":"array","items":{"type":"string"},"description":"Employee skills"},"authId":{"type":"string","format":"uuid","description":"Link to Supabase Auth user"}}},"session":{"type":"object","properties":{"access_token":{"type":"string","description":"JWT access token for immediate login"},"refresh_token":{"type":"string","description":"Refresh token for session management"},"expires_in":{"type":"number","description":"Token expiration time in seconds"},"token_type":{"type":"string","default":"bearer","description":"Token type"}}}}}}}]}}}},"400":{"description":"Validation errors","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"code":{"type":"string","enum":["WEAK_PASSWORD","INVALID_EMAIL"],"description":"Specific validation error code"}}}]},"examples":{"weak_password":{"summary":"Password too weak","value":{"success":false,"error":"Password is too weak. Please choose a stronger password.","code":"WEAK_PASSWORD"}},"invalid_email":{"summary":"Invalid email format","value":{"success":false,"error":"Please provide a valid email address","code":"INVALID_EMAIL"}}}}}},"409":{"description":"Email or company name already exists","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"code":{"type":"string","enum":["EMAIL_ALREADY_EXISTS","COMPANY_NAME_EXISTS"],"description":"Specific error code for duplicate resources"}}}]},"examples":{"email_exists":{"summary":"Email already registered","value":{"success":false,"error":"An account with this email already exists","code":"EMAIL_ALREADY_EXISTS"}},"company_exists":{"summary":"Company name exists","value":{"success":false,"error":"A company with this name already exists","code":"COMPANY_NAME_EXISTS"}}}}}},"500":{"description":"Internal server error or transaction failure","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"auth_failure":{"summary":"Supabase Auth creation failed","value":{"success":false,"error":"Failed to create user account"}},"transaction_failure":{"summary":"Database transaction failed","value":{"success":false,"error":"Business registration failed - all changes rolled back"}}}}}}}}},"/api/auth/reset-password/confirm":{"post":{"summary":"Confirm password reset","description":"Updates a user's password using the Supabase recovery access token from a password reset email.","tags":["Authentication"],"security":[]}},"/api/auth/reset-password":{"post":{"summary":"Request password reset email","description":"Sends a Supabase password recovery email when the email belongs to a CRM employee with an auth account. The response is intentionally neutral to avoid account enumeration.","tags":["Authentication"],"security":[]}},"/api/auth/sessions/{sessionId}":{"delete":{"summary":"Revoke one session of the current account","description":"Terminates a single session of the authenticated user. The session's refresh tokens are invalidated immediately and the device receives a 401 on its next request. The current session cannot be revoked this way — use logout instead.\n","tags":["Authentication"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"sessionId","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Session revoked"},"400":{"description":"Invalid session id or attempt to revoke the current session"},"401":{"description":"Unauthorized"},"404":{"description":"Session not found for this account"}}}},"/api/auth/sessions/revoke-others":{"post":{"summary":"Sign out all other sessions","description":"Terminates every session of the authenticated user except the one used for this request. Affected devices receive a 401 on their next request.\n","tags":["Authentication"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Other sessions revoked","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"revokedCount":{"type":"integer"}}}}}]}}}},"400":{"description":"Request is not authenticated with a Supabase session token"},"401":{"description":"Unauthorized"}}}},"/api/auth/sessions":{"get":{"summary":"List active sessions of the current account","description":"Returns all live Supabase sessions of the authenticated user enriched with client metadata (device, IP, app version) captured at login and refresh time. The session used for this request is flagged as current. Stale web sessions are lazily cleaned up.\n","tags":["Authentication"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Sessions retrieved successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"sessions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"isCurrent":{"type":"boolean"},"isUnknownDevice":{"type":"boolean","description":"True when the session predates metadata capture"},"clientType":{"type":"string","enum":["WEB","MOBILE_ANDROID","MOBILE_IOS","UNKNOWN"]},"deviceName":{"type":"string","nullable":true},"appVersion":{"type":"string","nullable":true},"loginMethod":{"type":"string","nullable":true},"ip":{"type":"string","nullable":true},"lastIp":{"type":"string","nullable":true},"signedInAt":{"type":"string","format":"date-time"},"lastSeenAt":{"type":"string","format":"date-time"}}}}}}}}]}}}},"400":{"description":"Account has no linked Supabase auth user"},"401":{"description":"Unauthorized"}}}},"/api/auth/set-password-authenticated":{"post":{"summary":"Set password for authenticated user who doesn't have one yet (OAuth users)","description":"Allows an authenticated user (e.g., signed in via Google OAuth) to set a password so they can also login via email/password.","tags":["Authentication"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["password","confirmPassword"],"properties":{"password":{"type":"string","minLength":8},"confirmPassword":{"type":"string"}}}}}},"responses":{"200":{"description":"Password set successfully"},"400":{"description":"Validation error or password already set"},"401":{"description":"Unauthorized"}}}},"/api/auth/set-password":{"post":{"summary":"Set password for invited user","description":"Allows a user who received an invitation email to set their password. Uses the access token from the invitation link.","tags":["Authentication"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["password","confirmPassword","accessToken"],"properties":{"password":{"type":"string","minLength":8,"description":"New password for the user"},"confirmPassword":{"type":"string","description":"Password confirmation (must match password)"},"accessToken":{"type":"string","description":"Access token from the invitation email link"}}},"example":{"password":"newSecurePassword123","confirmPassword":"newSecurePassword123","accessToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}}}},"responses":{"200":{"description":"Password set successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"name":{"type":"string"},"role":{"type":"string"},"company":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}}}}},"passwordSet":{"type":"boolean","example":true},"canLogin":{"type":"boolean","example":true}}},"message":{"type":"string","example":"Password set successfully. You can now login with your email and password."}}}}}},"400":{"description":"Validation error or invalid token","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"code":{"type":"string","enum":["VALIDATION_ERROR","INVALID_TOKEN","WEAK_PASSWORD"]}}}]},"examples":{"validation_error":{"summary":"Password validation failed","value":{"success":false,"error":"Passwords don't match","code":"VALIDATION_ERROR"}},"invalid_token":{"summary":"Invalid or expired token","value":{"success":false,"error":"Invalid or expired access token","code":"INVALID_TOKEN"}},"weak_password":{"summary":"Password too weak","value":{"success":false,"error":"Password is too weak. Please choose a stronger password.","code":"WEAK_PASSWORD"}}}}}},"404":{"description":"User not found","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"code":{"type":"string","enum":["USER_NOT_FOUND"]}}}]},"example":{"success":false,"error":"Employee record not found","code":"USER_NOT_FOUND"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/auth/signup":{"post":{"summary":"Register a new user","description":"Creates a new user in Supabase Auth and corresponding Employee record","tags":["Authentication"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password","name","branchId"],"properties":{"email":{"type":"string","format":"email","description":"User's email address"},"password":{"type":"string","minLength":8,"description":"User's password"},"name":{"type":"string","description":"User's full name"},"phone":{"type":"string","description":"User's phone number (optional)"},"branchId":{"type":"string","format":"uuid","description":"Branch ID where user will be assigned"},"role":{"type":"string","enum":["APP_ADMIN","COMPANY_ADMIN","BRANCH_ADMIN","STAFF"],"default":"STAFF","description":"User's role in the system"},"skills":{"type":"array","items":{"type":"string"},"description":"List of user's skills"},"hourlyRate":{"type":"number","minimum":0,"description":"User's hourly rate"},"schedule":{"type":"object","description":"User's work schedule"}}}}}},"responses":{"201":{"description":"User created successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":"string"},"role":{"type":"string"},"branch":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"company":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}}}}}}},"session":{"type":"object","description":"Supabase session data"}}}}}]}}}},"400":{"description":"Validation or weak password error","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"code":{"type":"string","enum":["WEAK_PASSWORD","INVALID_EMAIL"],"description":"Specific validation error code"}}}]},"examples":{"weak_password":{"summary":"Password too weak","value":{"success":false,"error":"Password is too weak. Please choose a stronger password.","code":"WEAK_PASSWORD"}},"invalid_email":{"summary":"Invalid email format","value":{"success":false,"error":"Please provide a valid email address","code":"INVALID_EMAIL"}}}}}},"409":{"description":"Account already exists","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"code":{"type":"string","enum":["EMAIL_ALREADY_EXISTS"],"description":"Specific error code for duplicate email"}}}]},"example":{"success":false,"error":"An account with this email already exists","code":"EMAIL_ALREADY_EXISTS"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/billing/plans":{"get":{"summary":"List subscription plans","tags":["Billing"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Subscription plans retrieved"}}}},"/api/billing/subscription/cancel":{"post":{"summary":"Cancel subscription","tags":["Billing"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Subscription cancelled"}}}},"/api/billing/subscription/change":{"post":{"summary":"Change subscription (upgrade/downgrade)","tags":["Billing"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Subscription changed"}}}},"/api/billing/subscription/create":{"post":{"summary":"Create subscription","tags":["Billing"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Subscription created"}}}},"/api/billing/subscription/limits":{"get":{"summary":"Get subscription limits and usage information","tags":["Billing"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Subscription limits information","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"hasActiveSubscription":{"type":"boolean"},"limits":{"type":"object","properties":{"smsLimit":{"type":"number"},"branchLimit":{"type":"number"},"adminLimit":{"type":"number"},"features":{"type":"array","items":{"type":"string"}}}},"usage":{"type":"object","properties":{"smsUsed":{"type":"number"},"branchesCount":{"type":"number"},"adminsCount":{"type":"number"}}},"warnings":{"type":"array","items":{"type":"string"}},"recommendations":{"type":"array","items":{"type":"string"}},"limitInfo":{"type":"object","properties":{"sms":{"type":"object","properties":{"used":{"type":"number"},"limit":{"type":"number"},"remaining":{"type":"number"},"percentage":{"type":"number"}}},"branches":{"type":"object","properties":{"used":{"type":"number"},"limit":{"type":"number"},"remaining":{"type":"number"},"percentage":{"type":"number"}}},"admins":{"type":"object","properties":{"used":{"type":"number"},"limit":{"type":"number"},"remaining":{"type":"number"},"percentage":{"type":"number"}}}}}}}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}}}},"/api/billing/subscription/payments":{"get":{"summary":"List subscription payments","tags":["Billing"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Payments list"}}}},"/api/billing/subscription/paywall/postpone":{"post":{"summary":"Postpone paywall for 24 hours during grace period","tags":["Billing"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Paywall postponed"}}}},"/api/billing/subscription/poll":{"post":{"summary":"Poll subscription payments from provider","tags":["Billing"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Subscription payments polled"}}}},"/api/billing/subscription/promo":{"post":{"summary":"Apply promo code","tags":["Billing"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Promo applied"}}}},"/api/billing/subscription/revenuecat/sync":{"post":{"summary":"Pull the company's store subscription from RevenueCat (after a purchase / restore in the app)","tags":["Billing"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Subscription state after sync"}}}},"/api/billing/subscription":{"get":{"summary":"Get current subscription","tags":["Billing"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Current subscription retrieved"}}}},"/api/billing/subscription/sync":{"post":{"summary":"Sync subscription with provider","tags":["Billing"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Subscription synced"}}}},"/api/billing/webhooks/revenuecat":{"post":{"summary":"RevenueCat webhook (App Store / Google Play subscription events)","tags":["Billing"],"responses":{"200":{"description":"Event stored and applied (or ignored)"}}}},"/api/branches/{branchId}/appointments/{id}":{"get":{"summary":"Get a specific appointment","description":"Retrieves detailed information about a specific appointment","tags":["Appointments"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Appointment ID"}],"responses":{"200":{"description":"Appointment retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Appointment"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"summary":"Update a specific appointment","description":"Updates appointment information.\nRequires STAFF or higher role.\n","tags":["Appointments"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Appointment ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAppointment"},"example":{"status":"CONFIRMED","responsibleEmployeeId":"07f88b87-43d0-4e4a-8350-e9907a6d155b","notes":"Client confirmed appointment via phone"}}}},"responses":{"200":{"description":"Appointment updated successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Appointment"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"summary":"Delete a specific appointment","description":"Deletes an appointment from the calendar.\nRequires BRANCH_ADMIN or higher role.\n","tags":["Appointments"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Appointment ID"}],"responses":{"200":{"description":"Appointment deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/appointments":{"get":{"summary":"Get appointments for a specific branch","description":"Retrieves a paginated list of appointments for the specified branch","tags":["Appointments"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"query","name":"page","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number for pagination"},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":10},"description":"Number of items per page"},{"in":"query","name":"status","schema":{"type":"string","enum":["SCHEDULED","CONFIRMED","IN_PROGRESS","COMPLETED","CANCELLED","NO_SHOW"]},"description":"Filter by appointment status"},{"in":"query","name":"clientId","schema":{"type":"string","format":"uuid"},"description":"Filter by client ID"},{"in":"query","name":"carId","schema":{"type":"string","format":"uuid"},"description":"Filter by car ID"},{"in":"query","name":"responsibleEmployeeId","schema":{"type":"string","format":"uuid"},"description":"Filter by responsible employee ID"},{"in":"query","name":"dateFrom","schema":{"type":"string","format":"date-time"},"description":"Filter appointments starting from this date"},{"in":"query","name":"dateTo","schema":{"type":"string","format":"date-time"},"description":"Filter appointments until this date"}],"responses":{"200":{"description":"Appointments retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Appointment"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"summary":"Create appointment for a specific branch","description":"Creates a new appointment in the branch calendar.\nRequires STAFF or higher role.\n","tags":["Appointments"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppointment"},"example":{"clientId":"d20f2f80-8ab7-4186-9a78-c187c7ff13f6","carId":"137fe84a-91cf-4614-91ef-e46f7a9501b6","responsibleEmployeeId":"07f88b87-43d0-4e4a-8350-e9907a6d155b","startTime":"2024-12-01T10:00:00Z","endTime":"2024-12-01T11:30:00Z","estimatedDuration":90,"description":"Oil change and tire rotation","notes":"Client prefers synthetic oil","status":"SCHEDULED"}}}},"responses":{"200":{"description":"Appointment created successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Appointment"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/employees/{id}":{"get":{"summary":"Get employee by ID","description":"Retrieve detailed information about a specific employee within a branch","tags":["Employees"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Employee ID"}],"responses":{"200":{"description":"Employee retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"allOf":[{"$ref":"#/components/schemas/EmployeeWithCompanyDetails"},{"type":"object","properties":{"authStatus":{"type":"object","properties":{"invitationSent":{"type":"boolean","description":"Whether invitation email has been sent"},"emailVerified":{"type":"boolean","description":"Whether employee has verified their email address"},"passwordCreated":{"type":"boolean","description":"Whether employee has created their password"},"invitedAt":{"type":"string","format":"date-time","nullable":true,"description":"When the invitation was sent"}}}}}]},"message":{"type":"string","example":"Employee retrieved successfully"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"summary":"Update employee","description":"Update an existing employee's information. Only COMPANY_ADMIN+ can update employees.","tags":["Employees"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Employee ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEmployeeRequest"},"example":{"name":"John Smith","email":"john.smith@newcompany.com","skills":["Diagnostics","Engine Repair","Electrical Systems"],"hourlyRate":50}}}},"responses":{"200":{"description":"Employee updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/EmployeeWithCompanyDetails"},"message":{"type":"string","example":"Employee updated successfully"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Conflict - Employee with this email already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error":"Employee with this email already exists"}}}}}},"delete":{"summary":"Delete employee","description":"Delete an employee from the system. Only COMPANY_ADMIN+ can delete employees. Cannot delete employee with active orders.","tags":["Employees"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Employee ID"}],"responses":{"200":{"description":"Employee deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Employee deleted successfully"}}}}}},"400":{"description":"Bad request - Employee has active orders","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error":"Cannot delete employee with active orders"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/branches/{branchId}/employees":{"get":{"summary":"Get employees for a branch with filters","description":"Retrieve all employees assigned to a branch. Supports individual filtering by name, email, phone, skills and roles.","tags":["Employees"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"query","name":"search","schema":{"type":"string"},"description":"Universal search term for employee name, email, phone, skills, or role (case-insensitive partial match)"},{"in":"query","name":"page","schema":{"type":"integer","default":1},"description":"Page number"},{"in":"query","name":"limit","schema":{"type":"integer","default":10},"description":"Items per page"}],"responses":{"200":{"description":"Employees retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/EmployeeWithCompanyDetails"},{"type":"object","properties":{"authStatus":{"type":"object","properties":{"invitationSent":{"type":"boolean","description":"Whether invitation email has been sent"},"emailVerified":{"type":"boolean","description":"Whether employee has verified their email address"},"passwordCreated":{"type":"boolean","description":"Whether employee has created their password"},"invitedAt":{"type":"string","format":"date-time","nullable":true,"description":"When the invitation was sent"}}}}}]}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"summary":"Create employee for branch","description":"Create a new employee and assign to branch (legacy endpoint)","tags":["Employees"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEmployee"}}}},"responses":{"201":{"description":"Employee created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/EmployeeWithCompanyDetails"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/branches/{branchId}/financial-reports/employees-salaries-breakdown":{"get":{"summary":"Get detailed employee salaries breakdown","description":"Returns comprehensive breakdown of employee salaries with detailed work history:\n- Every employee with total earned, hours worked, and orders count\n- Complete list of all works performed by each employee\n- Average hourly rate and earnings per employee\n- Can filter by specific employee\n- Excludes COMPANY_ADMIN from salary calculations\n\nRequires COMPANY_ADMIN or higher role.\n","tags":["Financial Reports"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"query","name":"startDate","required":true,"schema":{"type":"string","format":"date","example":"2024-01-01"}},{"in":"query","name":"endDate","required":true,"schema":{"type":"string","format":"date","example":"2024-01-31"}},{"in":"query","name":"employeeId","required":false,"schema":{"type":"string","format":"uuid"},"description":"Filter by specific employee ID"}],"responses":{"200":{"description":"Employee salaries breakdown generated successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"period":{"type":"object","properties":{"startDate":{"type":"string"},"endDate":{"type":"string"}}},"summary":{"type":"object","properties":{"totalSalaries":{"type":"number"},"employeesCount":{"type":"integer"},"totalHoursWorked":{"type":"number"},"totalWorksCompleted":{"type":"integer"},"averageSalaryPerEmployee":{"type":"number"},"averageHourlyRate":{"type":"number"}}},"employees":{"type":"array","items":{"type":"object","properties":{"employeeId":{"type":"string"},"employeeName":{"type":"string"},"role":{"type":"string"},"profitType":{"type":"string"},"profitValue":{"type":"number","nullable":true},"totalEarned":{"type":"number"},"hoursWorked":{"type":"number"},"worksCount":{"type":"integer"},"ordersCount":{"type":"integer"},"averageEarnedPerHour":{"type":"number"},"works":{"type":"array","items":{"type":"object","properties":{"orderId":{"type":"string"},"orderNumber":{"type":"string"},"workTypeName":{"type":"string"},"workTypeCode":{"type":"string","nullable":true},"hours":{"type":"number"},"revenue":{"type":"number"},"earned":{"type":"number"},"completedAt":{"type":"string","format":"date-time","nullable":true}}}}}}}}}}}]}}}},"400":{"description":"Invalid parameters"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Branch not found"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/financial-reports/net-profit-breakdown":{"get":{"summary":"Get detailed net profit breakdown by components","description":"Returns comprehensive breakdown of net profit composition:\n- Total net profit with profit margin\n- Breakdown by parts profit vs works owner profit\n- Percentage contribution of each component\n- Detailed stats for each category (revenue, costs, margins)\n- Top 10 most profitable orders\n\nRequires COMPANY_ADMIN or higher role.\n","tags":["Financial Reports"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"query","name":"startDate","required":true,"schema":{"type":"string","format":"date","example":"2024-01-01"}},{"in":"query","name":"endDate","required":true,"schema":{"type":"string","format":"date","example":"2024-01-31"}}],"responses":{"200":{"description":"Net profit breakdown generated successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"period":{"type":"object","properties":{"startDate":{"type":"string"},"endDate":{"type":"string"}}},"totalNetProfit":{"type":"number","description":"Total net profit (parts + works)"},"profitMargin":{"type":"number","description":"Overall profit margin percentage"},"components":{"type":"object","properties":{"partsProfit":{"type":"object","properties":{"amount":{"type":"number"},"percentage":{"type":"number","description":"Percentage of total net profit"},"details":{"type":"object","properties":{"totalPartsRevenue":{"type":"number"},"totalPartsCost":{"type":"number"},"margin":{"type":"number","description":"Parts profit margin percentage"},"itemsCount":{"type":"integer"}}}}},"worksOwnerProfit":{"type":"object","properties":{"amount":{"type":"number"},"percentage":{"type":"number","description":"Percentage of total net profit"},"details":{"type":"object","properties":{"totalWorkRevenue":{"type":"number"},"totalEmployeeSalaries":{"type":"number"},"ownerShare":{"type":"number"},"totalHours":{"type":"number"}}}}}}},"topProfitableOrders":{"type":"array","description":"Top 10 most profitable orders","items":{"type":"object","properties":{"orderId":{"type":"string"},"orderNumber":{"type":"string"},"netProfit":{"type":"number"},"revenue":{"type":"number"},"profitMargin":{"type":"number"}}}}}}}}]}}}},"400":{"description":"Invalid parameters"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Branch not found"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/financial-reports/orders-list":{"get":{"summary":"Get paginated list of orders with financial details","description":"Returns a paginated and filterable list of orders with complete financial breakdown:\n- Full financial details for each order (revenue, profit, costs)\n- Client and car information\n- Advanced filtering (status, revenue range, profit range, client)\n- Multiple sorting options (revenue, profit, date)\n- Pagination support\n- Summary statistics for displayed orders\n\nRequires COMPANY_ADMIN or higher role.\n","tags":["Financial Reports"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"query","name":"startDate","required":true,"schema":{"type":"string","format":"date","example":"2024-01-01"}},{"in":"query","name":"endDate","required":true,"schema":{"type":"string","format":"date","example":"2024-01-31"}},{"in":"query","name":"status","required":false,"schema":{"type":"string","enum":["PENDING","IN_PROGRESS","COMPLETED","CANCELLED"]},"description":"Filter by order status"},{"in":"query","name":"minRevenue","required":false,"schema":{"type":"number"},"description":"Minimum revenue filter"},{"in":"query","name":"maxRevenue","required":false,"schema":{"type":"number"},"description":"Maximum revenue filter"},{"in":"query","name":"minProfit","required":false,"schema":{"type":"number"},"description":"Minimum profit filter"},{"in":"query","name":"maxProfit","required":false,"schema":{"type":"number"},"description":"Maximum profit filter"},{"in":"query","name":"clientId","required":false,"schema":{"type":"string","format":"uuid"},"description":"Filter by client ID"},{"in":"query","name":"sortBy","required":false,"schema":{"type":"string","enum":["revenue","netProfit","completedAt","createdAt"],"default":"createdAt"},"description":"Field to sort by"},{"in":"query","name":"sortOrder","required":false,"schema":{"type":"string","enum":["asc","desc"],"default":"desc"},"description":"Sort order"},{"in":"query","name":"page","required":false,"schema":{"type":"integer","default":1,"minimum":1},"description":"Page number"},{"in":"query","name":"limit","required":false,"schema":{"type":"integer","default":20,"minimum":1,"maximum":100},"description":"Items per page"}],"responses":{"200":{"description":"Orders list generated successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"period":{"type":"object","properties":{"startDate":{"type":"string"},"endDate":{"type":"string"}}},"summary":{"type":"object","properties":{"totalOrders":{"type":"integer","description":"Total orders matching filters"},"displayedOrders":{"type":"integer","description":"Orders in current page"},"totalRevenue":{"type":"number","description":"Total revenue of filtered orders"},"totalNetProfit":{"type":"number","description":"Total net profit of filtered orders"},"averageOrderRevenue":{"type":"number"},"averageOrderProfit":{"type":"number"}}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}}},"orders":{"type":"array","items":{"type":"object","properties":{"orderId":{"type":"string"},"orderNumber":{"type":"string"},"status":{"type":"string"},"completedAt":{"type":"string","format":"date-time","nullable":true},"revenue":{"type":"number"},"partsRevenue":{"type":"number"},"workRevenue":{"type":"number"},"partsCost":{"type":"number"},"partsProfit":{"type":"number"},"employeeSalaries":{"type":"number"},"ownerProfit":{"type":"number"},"netProfit":{"type":"number"},"clientName":{"type":"string","nullable":true},"carInfo":{"type":"string","nullable":true,"description":"Formatted car info (brand model year plate)"}}}}}}}}]}}}},"400":{"description":"Invalid parameters"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Branch not found"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/financial-reports/parts-breakdown":{"get":{"summary":"Get detailed parts breakdown for financial analysis","description":"Returns comprehensive breakdown of all parts sold during the period:\n- Every part item with sale price, purchase price, and profit\n- Breakdown by type (OrderItem, OrderPartBatch, OrderPartUnit)\n- Shows exact calculation logic for revenue and profit\n- Helps identify which parts are most/least profitable\n\nRequires COMPANY_ADMIN or higher role.\n","tags":["Financial Reports"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"query","name":"startDate","required":true,"schema":{"type":"string","format":"date"}},{"in":"query","name":"endDate","required":true,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Parts breakdown generated successfully"},"400":{"description":"Invalid date parameters"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Branch not found"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/financial-reports/revenue-breakdown":{"get":{"summary":"Get detailed revenue breakdown by sources","description":"Returns comprehensive breakdown of revenue sources:\n- Total revenue split by parts and works\n- Percentage contribution of each source\n- Average revenue per item/hour\n- Items/hours count for each source\n- Top 10 highest revenue orders\n\nRequires COMPANY_ADMIN or higher role.\n","tags":["Financial Reports"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"query","name":"startDate","required":true,"schema":{"type":"string","format":"date","example":"2024-01-01"}},{"in":"query","name":"endDate","required":true,"schema":{"type":"string","format":"date","example":"2024-01-31"}}],"responses":{"200":{"description":"Revenue breakdown generated successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"period":{"type":"object","properties":{"startDate":{"type":"string"},"endDate":{"type":"string"}}},"totalRevenue":{"type":"number","description":"Total revenue from all sources"},"sources":{"type":"object","properties":{"parts":{"type":"object","properties":{"amount":{"type":"number","description":"Revenue from parts"},"percentage":{"type":"number","description":"Percentage of total revenue"},"itemsCount":{"type":"integer","description":"Number of parts sold"},"averagePerItem":{"type":"number","description":"Average revenue per part"}}},"works":{"type":"object","properties":{"amount":{"type":"number","description":"Revenue from works"},"percentage":{"type":"number","description":"Percentage of total revenue"},"hoursCount":{"type":"number","description":"Total hours worked"},"averagePerHour":{"type":"number","description":"Average revenue per hour"},"worksCount":{"type":"integer","description":"Number of works performed"}}}}},"topRevenueOrders":{"type":"array","description":"Top 10 orders by revenue","items":{"type":"object","properties":{"orderId":{"type":"string"},"orderNumber":{"type":"string"},"revenue":{"type":"number"},"partsRevenue":{"type":"number"},"workRevenue":{"type":"number"},"completedAt":{"type":"string","format":"date-time","nullable":true}}}}}}}}]}}}},"400":{"description":"Invalid parameters"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Branch not found"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/financial-reports":{"get":{"summary":"Generate financial report for a branch over a specified period","description":"Generates a comprehensive financial report including:\n- Overall revenue and profit breakdown\n- Employee salaries based on completed works (excludes COMPANY_ADMIN)\n- Parts profit (sale price - purchase price)\n- Works profit (revenue - employee share)\n- Optionally includes detailed order-by-order breakdown\n\nRequires COMPANY_ADMIN or higher role (branch admins CANNOT access).\n","tags":["Financial Reports"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"query","name":"startDate","required":true,"schema":{"type":"string","format":"date","example":"2024-01-01"},"description":"Start date of the reporting period (ISO 8601 format)"},{"in":"query","name":"endDate","required":true,"schema":{"type":"string","format":"date","example":"2024-01-31"},"description":"End date of the reporting period (ISO 8601 format)"},{"in":"query","name":"includeOrderDetails","required":false,"schema":{"type":"boolean","default":false},"description":"Include detailed breakdown for each order"}],"responses":{"200":{"description":"Financial report generated successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"period":{"type":"object","properties":{"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"}}},"summary":{"type":"object","properties":{"totalRevenue":{"type":"number","description":"Total revenue from all orders"},"totalPartsRevenue":{"type":"number","description":"Revenue from parts"},"totalWorkRevenue":{"type":"number","description":"Revenue from work"},"totalPartsCost":{"type":"number","description":"Internal cost of parts"},"totalPartsProfit":{"type":"number","description":"Profit from parts (revenue - cost)"},"totalEmployeeSalaries":{"type":"number","description":"Total salaries earned by employees"},"totalOwnerProfitFromWork":{"type":"number","description":"Owner's profit from work (after employee salaries)"},"netProfit":{"type":"number","description":"Total net profit (parts profit + owner's work profit)"},"profitMargin":{"type":"number","description":"Profit margin percentage"},"ordersCount":{"type":"integer","description":"Total number of orders in period"},"completedOrdersCount":{"type":"integer","description":"Number of completed orders"}}},"payments":{"type":"object","properties":{"totalReceived":{"type":"number","description":"Confirmed non-refund payments received in period"},"cash":{"type":"number"},"card":{"type":"number"},"bankTransfer":{"type":"number"},"crypto":{"type":"number"},"other":{"type":"number"},"refunds":{"type":"number","description":"Confirmed refunds in period"},"netInflow":{"type":"number","description":"totalReceived - refunds"},"outstandingReceivables":{"type":"number","description":"Branch-level open receivables based on order totals minus confirmed paid totals"}}},"employeeSalaries":{"type":"array","description":"Salary breakdown by employee","items":{"type":"object","properties":{"employeeId":{"type":"string","format":"uuid"},"employeeName":{"type":"string"},"totalEarned":{"type":"number","description":"Total earned by this employee"},"hoursWorked":{"type":"number","description":"Total hours worked"},"ordersCount":{"type":"integer","description":"Number of orders worked on"},"profitType":{"type":"string","enum":["FIXED","PERCENTAGE"]},"profitValue":{"type":"number","nullable":true},"works":{"type":"array","description":"Detailed work items (if includeOrderDetails=true)","items":{"type":"object","properties":{"orderId":{"type":"string"},"orderNumber":{"type":"string"},"workTypeName":{"type":"string"},"hours":{"type":"number"},"earned":{"type":"number"}}}}}}},"partsProfit":{"type":"object","properties":{"totalRevenue":{"type":"number"},"totalCost":{"type":"number"},"profit":{"type":"number"},"margin":{"type":"number","description":"Profit margin percentage for parts"},"itemsCount":{"type":"integer","description":"Total number of parts sold"}}},"worksProfit":{"type":"object","properties":{"totalRevenue":{"type":"number"},"employeeShare":{"type":"number"},"ownerShare":{"type":"number"},"totalHours":{"type":"number"}}},"orders":{"type":"array","description":"Order-by-order breakdown (if includeOrderDetails=true)","items":{"type":"object","properties":{"orderId":{"type":"string"},"orderNumber":{"type":"string"},"status":{"type":"string"},"revenue":{"type":"number"},"partsRevenue":{"type":"number"},"workRevenue":{"type":"number"},"partsCost":{"type":"number"},"partsProfit":{"type":"number"},"employeeSalaries":{"type":"number"},"ownerProfit":{"type":"number"},"netProfit":{"type":"number"}}}}}}}}]}}}},"400":{"description":"Invalid date parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Insufficient permissions or cannot access branch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Branch not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/financial-reports/works-breakdown":{"get":{"summary":"Get detailed works breakdown for financial analysis","description":"Returns comprehensive breakdown of all work performed during the period:\n- Every work item with revenue, employee salary, and owner profit\n- Shows which works have executors and which don't\n- Breakdown by employee with aggregated stats\n- Helps identify works without assigned executors\n- Shows exact calculation logic for salaries and profit\n\nRequires COMPANY_ADMIN or higher role.\n","tags":["Financial Reports"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"query","name":"startDate","required":true,"schema":{"type":"string","format":"date"}},{"in":"query","name":"endDate","required":true,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Works breakdown generated successfully"},"400":{"description":"Invalid date parameters"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Branch not found"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/financial-settlements":{"get":{"summary":"Get branch settlements and payments analytics","description":"Returns read-only settlements analytics for the selected period:\n- Planned receivables from orders created in period\n- Received payments and refunds in period\n- Outstanding balances\n- Breakdown by payment channels\n- Orders with unpaid balances\n- Payment history in period\n\nRequires COMPANY_ADMIN or higher role.\n","tags":["Financial Settlements"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"query","name":"startDate","required":true,"schema":{"type":"string","format":"date","example":"2024-01-01"}},{"in":"query","name":"endDate","required":true,"schema":{"type":"string","format":"date","example":"2024-01-31"}}],"responses":{"200":{"description":"Settlements analytics generated successfully"},"400":{"description":"Invalid parameters"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Branch not found"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/orders/{orderId}/complete":{"post":{"summary":"Complete an order","description":"Marks an order as completed with required mileage information. This endpoint automatically sets the order status to COMPLETED and updates the associated car's mileage.","tags":["Order Management"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["completedMileage"],"properties":{"completedMileage":{"type":"integer","minimum":0,"maximum":9999999,"description":"Current car mileage when order was completed (REQUIRED)","example":50000},"vin":{"type":"string","minLength":17,"maxLength":17,"description":"Required when the order car does not have a VIN yet","example":"1HGBH41JXMN109186"},"useExistingCar":{"type":"boolean","description":"Explicitly rebind the order to the existing car record when the provided VIN is already in the database"},"carDetails":{"type":"object","description":"Vehicle data reviewed after lookup. Provided values overwrite the selected car record.","properties":{"make":{"type":"string"},"model":{"type":"string"},"year":{"type":"integer"},"trim":{"type":"string"},"color":{"type":"string"},"licensePlate":{"type":"string"},"vehicleType":{"type":"string","enum":["ICE","HYBRID","ELECTRIC"]},"engineVolume":{"type":"string"}}},"title":{"type":"string","maxLength":255,"description":"Optional custom order title; if omitted, the system will generate one automatically","example":"ТО-60К: Замена масла и тормозных колодок"}}}}}},"responses":{"200":{"description":"Order completed successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["COMPLETED"]},"exitDate":{"type":"string","format":"date-time"},"car":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"mileage":{"type":"integer","description":"Updated car mileage"}}}}}}}]}}}},"400":{"description":"Bad request - validation error or order cannot be completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - Cannot access this branch or insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Branch or order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict - Order is already completed or cannot be completed from current status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/orders/{orderId}/delete-photo":{"delete":{"summary":"Delete a photo from a specific order","description":"Removes a photo from an order and deletes it from storage. Requires STAFF or higher role.","tags":["Order Management"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"photoUrl":{"type":"string","format":"uri","description":"URL of the photo to delete"}},"required":["photoUrl"]}}}},"responses":{"200":{"description":"Photo deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Photo deleted successfully"}}}}}},"400":{"description":"Bad request - invalid input or photo not found in order"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - Cannot access this branch or insufficient permissions"},"404":{"description":"Branch or order not found"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/orders/{orderId}/delete-video":{"delete":{"summary":"Delete a video from a specific order","description":"Removes a video from an order and deletes it from storage. Requires STAFF or higher role.","tags":["Order Management"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoUrl":{"type":"string","format":"uri","description":"URL of the video to delete"}},"required":["videoUrl"]}}}},"responses":{"200":{"description":"Video deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Video deleted successfully"}}}}}},"400":{"description":"Bad request - invalid input or video not found in order"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - Cannot access this branch or insufficient permissions"},"404":{"description":"Branch or order not found"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/orders/{orderId}/financials":{"get":{"summary":"Get financial information for a specific order","description":"Retrieves comprehensive financial breakdown including client costs, internal costs, and profit calculations for a specific order","tags":["Order Management"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order ID"}],"responses":{"200":{"description":"Financial information retrieved successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"orderId":{"type":"string","format":"uuid","description":"Order ID"},"orderNumber":{"type":"string","description":"Order number"},"clientCosts":{"type":"object","description":"Totals visible to the customer","properties":{"partsCost":{"type":"number","format":"decimal","description":"Amount paid by the client for parts"},"workCost":{"type":"number","format":"decimal","description":"Amount paid by the client for labour"},"subtotal":{"type":"number","format":"decimal","description":"Total before VAT"},"vatAmount":{"type":"number","format":"decimal","description":"VAT amount charged to the client"},"vatRate":{"type":"number","format":"decimal","description":"Applied VAT rate percentage"},"total":{"type":"number","format":"decimal","description":"Total amount charged to the client including VAT"},"includeVat":{"type":"boolean","description":"Indicates whether VAT was applied"}}},"internalCosts":{"type":"object","description":"Internal cost structure used to calculate profit","properties":{"partsCost":{"type":"number","format":"decimal","description":"Internal cost of parts used in the order"},"totalCost":{"type":"number","format":"decimal","description":"Combined internal costs (currently parts only)"}}},"profit":{"type":"object","description":"Profit metrics derived from the order","properties":{"totalPartsProfit":{"type":"number","format":"decimal","description":"Profit from parts (client price minus purchase price)"},"totalEmployeeProfit":{"type":"number","format":"decimal","description":"Total amount that goes to employees (their salary/commission)"},"totalOwnerProfitFromWork":{"type":"number","format":"decimal","description":"Total profit from work that goes to the owner (work cost minus employee share)"},"netProfit":{"type":"number","format":"decimal","description":"Combined profit from parts and owner's share of work"},"profitMargin":{"type":"number","format":"decimal","description":"Profit margin percentage relative to client subtotal"}}}}}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - Cannot access this branch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Branch or order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/orders/{orderId}/mileage-correction-requests":{"post":{"summary":"Create a mileage correction request","description":"Allows RSTO managers to request a mileage correction for a completed order","tags":["Mileage Correction"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["requestedMileage"],"properties":{"requestedMileage":{"type":"integer","minimum":0,"maximum":9999999,"description":"The corrected mileage value","example":50500},"reason":{"type":"string","maxLength":500,"description":"Optional reason for the correction","example":"Accidentally entered 50000 instead of 50500"}}}}}},"responses":{"201":{"description":"Mileage correction request created successfully"},"400":{"description":"Bad request - validation error or business rule violation"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - insufficient permissions"},"404":{"description":"Order not found"},"409":{"description":"Conflict - pending request already exists"},"500":{"$ref":"#/components/responses/InternalError"}}},"get":{"summary":"Get mileage correction requests for an order","description":"Retrieves all mileage correction requests associated with a specific order","tags":["Mileage Correction"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order ID"}],"responses":{"200":{"description":"List of mileage correction requests"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - insufficient permissions"},"404":{"description":"Order not found"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/orders/{orderId}/pdf-status":{"get":{"summary":"Check PDF generation readiness","description":"Checks if order is ready for PDF generation and returns status information","tags":["Orders","PDF"],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string"},"description":"Order ID"}],"responses":{"200":{"description":"PDF status information","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"isReady":{"type":"boolean","description":"Whether order is ready for PDF generation"},"missingFields":{"type":"array","items":{"type":"string"},"description":"List of missing required fields"},"orderSummary":{"type":"object","properties":{"orderNumber":{"type":"string"},"customerName":{"type":"string"},"vehicleInfo":{"type":"string"},"totalAmount":{"type":"number"},"worksCount":{"type":"integer"},"partsCount":{"type":"integer"},"entryDate":{"type":"string"},"exitDate":{"type":"string"},"isReadyForPDF":{"type":"boolean"},"missingData":{"type":"array","items":{"type":"string"}}}}}}}}}}},"404":{"description":"Order not found"},"500":{"description":"Status check failed"}},"security":[{"BearerAuth":[]}]}},"/api/branches/{branchId}/orders/{orderId}/pdf":{"get":{"summary":"Generate PDF document for order","description":"Generates a PDF document (work order) for the specified order","tags":["Orders","PDF"],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string"},"description":"Order ID"},{"in":"query","name":"format","schema":{"type":"string","enum":["A4","Letter"],"default":"A4"},"description":"PDF page format"},{"in":"query","name":"download","schema":{"type":"boolean","default":true},"description":"Whether to download the PDF or display inline"},{"in":"query","name":"density","schema":{"type":"string","enum":["compact","standard","spacious"],"default":"compact"},"description":"Document layout density"}],"responses":{"200":{"description":"PDF document generated successfully","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Order not ready for PDF generation","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Order is missing required fields"},"missingFields":{"type":"array","items":{"type":"string"}}}}}}},"404":{"description":"Order not found"},"500":{"description":"PDF generation failed"}},"security":[{"BearerAuth":[]}]},"post":{"summary":"Generate PDF with custom options","description":"Generates a PDF document with custom formatting options","tags":["Orders","PDF"],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string"},"description":"Order ID"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"format":{"type":"string","enum":["A4","Letter"],"default":"A4"},"orientation":{"type":"string","enum":["portrait","landscape"],"default":"portrait"},"margin":{"type":"object","properties":{"top":{"type":"string","example":"15mm"},"right":{"type":"string","example":"15mm"},"bottom":{"type":"string","example":"15mm"},"left":{"type":"string","example":"15mm"}}},"printBackground":{"type":"boolean","default":true},"download":{"type":"boolean","default":true},"density":{"type":"string","enum":["compact","standard","spacious"],"default":"compact"}}}}}},"responses":{"200":{"description":"PDF document generated successfully","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Invalid request or order not ready"},"404":{"description":"Order not found"},"500":{"description":"PDF generation failed"}},"security":[{"BearerAuth":[]}]}},"/api/branches/{branchId}/orders/{orderId}/preview":{"get":{"summary":"Get PDF preview of order document","description":"Returns the same paginated A4 PDF document that will be downloaded, but inline for preview","tags":["Orders","PDF"],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string"},"description":"Order ID"},{"in":"query","name":"density","schema":{"type":"string","enum":["compact","standard","spacious"],"default":"compact"},"description":"Document layout density"}],"responses":{"200":{"description":"PDF preview generated successfully","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Order not ready for preview"},"404":{"description":"Order not found"},"500":{"description":"Preview generation failed"}},"security":[{"BearerAuth":[]}]}},"/api/branches/{branchId}/orders/{orderId}/reopen-requests":{"post":{"summary":"Create an order reopen request","description":"Creates a request to reopen a completed order and return it to IN_PROGRESS after company approval.","tags":["Order Reopen Requests"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Completed order ID"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","maxLength":1000,"example":"Need to continue work after an additional inspection"}}}}}},"responses":{"201":{"description":"Order reopen request created successfully"},"400":{"description":"Invalid input or order is not completed"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - insufficient permissions"},"404":{"description":"Branch or order not found"},"409":{"description":"A pending reopen request already exists for this order"},"500":{"$ref":"#/components/responses/InternalError"}}},"get":{"summary":"List order reopen requests for an order","description":"Retrieves reopen requests associated with a specific order in a branch.","tags":["Order Reopen Requests"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order ID"}],"responses":{"200":{"description":"Order reopen requests retrieved successfully"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - insufficient permissions"},"404":{"description":"Branch or order not found"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/orders/{orderId}":{"get":{"summary":"Get a specific order by ID","description":"Retrieves detailed information about a specific order including branch, car, client, employee, work items, and parts used. For financial information, use GET /api/branches/{branchId}/orders/{orderId}/financials","tags":["Order Management"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order ID"}],"responses":{"200":{"description":"Order retrieved successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Order ID"},"orderNumber":{"type":"string","description":"Unique order number","example":"ORD-001-2024"},"status":{"type":"string","enum":["PENDING","IN_PROGRESS","WAITING_FOR_PARTS","QUALITY_CHECK","COMPLETED","CANCELLED"],"description":"Current order status"},"description":{"type":"string","nullable":true,"description":"Order description"},"entryDate":{"type":"string","format":"date-time","description":"Order entry date"},"exitDate":{"type":"string","format":"date-time","nullable":true,"description":"Order completion date"},"totalWorkAmount":{"type":"number","format":"decimal","description":"Total amount for work services"},"totalPartsAmount":{"type":"number","format":"decimal","description":"Total amount for parts used"},"subtotalAmount":{"type":"number","format":"decimal","description":"Subtotal before VAT"},"vatRate":{"type":"number","format":"decimal","description":"VAT rate percentage"},"vatAmount":{"type":"number","format":"decimal","description":"VAT amount"},"totalAmount":{"type":"number","format":"decimal","description":"Total order amount"},"warrantyPeriod":{"type":"string","nullable":true,"description":"Warranty period"},"warrantyTerms":{"type":"string","nullable":true,"description":"Warranty terms and conditions"},"photos":{"type":"array","items":{"type":"string"},"description":"Order photos"},"videos":{"type":"array","items":{"type":"string"},"description":"Order videos"},"branch":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","description":"Branch name"},"company":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","description":"Company name"}}}}},"car":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"vin":{"type":"string","description":"Vehicle identification number"},"make":{"type":"string","description":"Car manufacturer"},"model":{"type":"string","description":"Car model"},"year":{"type":"integer","description":"Car year"},"trim":{"type":"string","nullable":true,"description":"Car trim level"},"mileage":{"type":"integer","nullable":true,"description":"Car mileage"},"licensePlate":{"type":"string","description":"License plate number"},"engineVolume":{"type":"string","description":"Engine displacement volume"}}},"client":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","description":"Client name"},"phone":{"type":"string","nullable":true,"description":"Client phone number"},"email":{"type":"string","format":"email","nullable":true,"description":"Client email address"},"address":{"type":"string","nullable":true,"description":"Client address"}}},"responsibleEmployee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","description":"Employee name"},"role":{"type":"string","enum":["APP_ADMIN","COMPANY_ADMIN","BRANCH_ADMIN","STAFF"],"description":"Employee role"},"skills":{"type":"array","items":{"type":"string"},"description":"Employee skills"}}},"orderWorks":{"type":"array","description":"Work items performed on the order","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"hours":{"type":"number","format":"decimal","description":"Hours worked"},"workType":{"$ref":"#/components/schemas/WorkType"}}}},"orderItems":{"type":"array","description":"Items/parts used in the order (unified system)","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","description":"Item name"},"quantityUsed":{"type":"integer","description":"Quantity used"},"baseUnitPrice":{"type":"number","format":"decimal","description":"Original price from inventory"},"unitPrice":{"type":"number","format":"decimal","description":"Final price (may be overridden)"},"overrideUnitPrice":{"type":"number","format":"decimal","nullable":true,"description":"Manager's override price"},"totalPrice":{"type":"number","format":"decimal","description":"Total price for this item"},"inventoryProduct":{"type":"object","nullable":true,"description":"Linked inventory product (null for manual items)"}}}},"_count":{"type":"object","description":"Count summaries","properties":{"orderWorks":{"type":"integer","description":"Number of work items"},"orderItems":{"type":"integer","description":"Number of items/parts used"}}},"createdAt":{"type":"string","format":"date-time","description":"Order creation timestamp"},"updatedAt":{"type":"string","format":"date-time","description":"Order last update timestamp"}}}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - Cannot access this branch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Branch or order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"$ref":"#/components/responses/InternalError"}}},"put":{"summary":"Update a specific order","description":"Updates order information including status, description, and other properties. Requires STAFF or higher role. NOTE - To complete an order (set status to COMPLETED), use the dedicated POST /complete endpoint instead.","tags":["Order Management"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOrder"}}}},"responses":{"200":{"description":"Order updated successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Order"}}}]}}}},"400":{"description":"Bad request - validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - Cannot access this branch or insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Branch or order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"summary":"Partially update a specific order","description":"Partially updates order information including status, description, and other properties. Requires STAFF or higher role. NOTE - To complete an order (set status to COMPLETED), use the dedicated POST /complete endpoint instead.","tags":["Order Management"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order ID"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["PENDING","IN_PROGRESS","WAITING_FOR_PARTS","QUALITY_CHECK","COMPLETED","CANCELLED"],"description":"Order status (optional)"},"description":{"type":"string","description":"Order description (optional)"},"entryDate":{"type":"string","format":"date-time","description":"Order entry/start date (optional)"},"photos":{"type":"array","items":{"type":"string","format":"binary"},"description":"New photos to upload (optional)"},"videos":{"type":"array","items":{"type":"string","format":"binary"},"description":"New videos to upload (optional)"},"deletedPhotos":{"type":"array","items":{"type":"string","format":"url"},"description":"URLs of existing photos to delete (optional)"},"deletedVideos":{"type":"array","items":{"type":"string","format":"url"},"description":"URLs of existing videos to delete (optional)"}},"additionalProperties":false,"minProperties":1}}}},"responses":{"200":{"description":"Order updated successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Order"}}}]}}}},"400":{"description":"Bad request - validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - Cannot access this branch or insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Branch or order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"summary":"Delete an order","description":"Deletes a non-completed order. Completed orders require the approval flow. Existing payroll rows are preserved and any payroll effects linked to the order are offset with negative reversal accruals instead of deleting payroll history or rewriting payout totals.","tags":["Order Management"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order ID"}],"responses":{"200":{"description":"Order deleted successfully"},"400":{"description":"Invalid input data"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Cannot access this branch or insufficient permissions"},"404":{"description":"Branch or order not found"},"409":{"description":"Completed orders require admin approval","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"completedOrderRequiresApproval":{"summary":"Completed order requires approval flow","value":{"success":false,"error":"Closed orders require admin approval request before deletion"}}}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/orders/{orderId}/upload-photo":{"post":{"summary":"Upload a photo for a specific order","description":"Uploads a single photo for an order and associates it with the order. Requires STAFF or higher role.","tags":["Order Management"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order ID"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"photo":{"type":"string","format":"binary","description":"Image file to upload"}}}}}},"responses":{"200":{"description":"Photo uploaded successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Photo uploaded successfully"},"data":{"type":"object","properties":{"url":{"type":"string","description":"URL of the uploaded photo"}}}}}}}},"400":{"description":"Bad request - no file uploaded or invalid input"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - Cannot access this branch or insufficient permissions"},"404":{"description":"Branch or order not found"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/orders/{orderId}/upload-video":{"post":{"summary":"Upload a video for a specific order","description":"Uploads a single video for an order and associates it with the order. Requires STAFF or higher role.","tags":["Order Management"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order ID"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"video":{"type":"string","format":"binary","description":"Video file to upload"}}}}}},"responses":{"200":{"description":"Video uploaded successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Video uploaded successfully"},"data":{"type":"object","properties":{"url":{"type":"string","description":"URL of the uploaded video"}}}}}}}},"400":{"description":"Bad request - no file uploaded or invalid input"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - Cannot access this branch or insufficient permissions"},"404":{"description":"Branch or order not found"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/orders/{orderId}/works/{id}":{"get":{"summary":"Get a specific work entry for an order","description":"Retrieves a specific work entry by ID for the specified order","tags":["Order Management"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Work entry ID"}],"responses":{"200":{"description":"Order work retrieved successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workType":{"$ref":"#/components/schemas/WorkType"},"executorEmployee":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"John Doe"},"email":{"type":"string","format":"email","nullable":true},"role":{"type":"string","enum":["APP_ADMIN","COMPANY_ADMIN","BRANCH_ADMIN","STAFF"]}}},"hours":{"type":"number","format":"decimal"},"totalCost":{"type":"number","format":"decimal"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Cannot access this branch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Branch, order, or work entry not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"summary":"Update a work entry for an order","description":"Updates a specific work entry for the specified order. Requires STAFF or higher role.","tags":["Order Management"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Work entry ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"executorEmployeeId":{"type":"string","format":"uuid","nullable":true,"description":"ID of the employee who executed the work (optional, can be null to unassign)"},"hours":{"type":"number","minimum":0.1,"description":"Number of hours worked"},"overridePrice":{"type":"number","minimum":0,"nullable":true,"description":"IMPORTANT: This is the FINAL TOTAL PRICE for the entire work, not price per hour!\nExample: If base calculation is 5 hours × 100 UAH = 500 UAH,\nand you want to give a discount to 400 UAH, send overridePrice: 400\n(NOT 80 as new hourly rate!)\nSet to null to remove the override and use base calculation.\n"}}}}}},"responses":{"200":{"description":"Order work updated successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workType":{"$ref":"#/components/schemas/WorkType"},"executorEmployee":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"John Doe"},"email":{"type":"string","format":"email","nullable":true},"role":{"type":"string","enum":["APP_ADMIN","COMPANY_ADMIN","BRANCH_ADMIN","STAFF"]}}},"hours":{"type":"number","format":"decimal"},"totalCost":{"type":"number","format":"decimal"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions or cannot access branch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Order work not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"summary":"Delete a work entry for an order","description":"Deletes a specific work entry for the specified order. Requires STAFF or higher role.","tags":["Order Management"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Work entry ID"}],"responses":{"200":{"description":"Order work deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions or cannot access branch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Order work not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/branches/{branchId}/orders/{orderId}/works":{"get":{"summary":"Get works for an order","description":"Retrieves a list of works (labor) for the specified order","tags":["Order Management"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order ID"},{"in":"query","name":"page","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number for pagination"},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":5000,"default":10},"description":"Number of items per page"},{"in":"query","name":"workTypeId","schema":{"type":"string","format":"uuid"},"description":"Filter by work type"}],"responses":{"200":{"description":"Order works retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workType":{"$ref":"#/components/schemas/WorkType"},"executorEmployee":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"John Doe"},"email":{"type":"string","format":"email","nullable":true},"role":{"type":"string","enum":["APP_ADMIN","COMPANY_ADMIN","BRANCH_ADMIN","STAFF"]}}},"hours":{"type":"number","format":"decimal"},"totalCost":{"type":"number","format":"decimal"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Cannot access this branch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Branch or order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"summary":"Add work to an order","description":"Creates a new work entry (labor) for the specified order. Requires STAFF or higher role.","tags":["Order Management"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"path","name":"orderId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["workTypeId","hours"],"properties":{"workTypeId":{"type":"string","format":"uuid","description":"ID of the work type"},"executorEmployeeId":{"type":"string","format":"uuid","description":"ID of the employee who will execute the work (optional)"},"hours":{"type":"number","minimum":0.1,"description":"Number of hours worked"},"overridePrice":{"type":"number","minimum":0,"nullable":true,"description":"IMPORTANT: This is the FINAL TOTAL PRICE for the entire work, not price per hour!\nExample: If base calculation is 5 hours × 100 UAH = 500 UAH,\nand you want to give a discount to 400 UAH, send overridePrice: 400\n(NOT 80 as new hourly rate!)\n"}}}}}},"responses":{"200":{"description":"Order work added successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workType":{"$ref":"#/components/schemas/WorkType"},"executorEmployee":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"John Doe"},"email":{"type":"string","format":"email","nullable":true},"role":{"type":"string","enum":["APP_ADMIN","COMPANY_ADMIN","BRANCH_ADMIN","STAFF"]}}},"hours":{"type":"number","format":"decimal"},"totalCost":{"type":"number","format":"decimal"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Branch, order, or work type not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Work type already assigned to this order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/branches/{branchId}/orders":{"get":{"summary":"Get orders for a specific branch","description":"Retrieves a list of orders for the specified branch","tags":["Orders"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"},{"in":"query","name":"page","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number for pagination"},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":10},"description":"Number of items per page"},{"in":"query","name":"status","schema":{"type":"string","enum":["PENDING","IN_PROGRESS","WAITING_FOR_PARTS","QUALITY_CHECK","COMPLETED","CANCELLED"]},"description":"Filter by order status"},{"in":"query","name":"clientId","schema":{"type":"string","format":"uuid"},"description":"Filter by client ID"},{"in":"query","name":"employeeId","schema":{"type":"string","format":"uuid"},"description":"Filter by responsible employee ID"},{"in":"query","name":"activeFirst","schema":{"type":"boolean","default":true},"description":"Show unfinished orders before completed and cancelled orders"}],"responses":{"200":{"description":"Orders retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Order"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Cannot access this branch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Branch not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"summary":"Create order for a specific branch","description":"Creates a new order for the specified branch with basic information only.\nPhotos and videos should be uploaded separately using the upload endpoints after order creation.\nRequires STAFF or higher role.\n","tags":["Orders"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["carId","clientId"],"properties":{"carId":{"type":"string","format":"uuid","description":"Car ID for the order"},"clientId":{"type":"string","format":"uuid","description":"Client ID for the order"},"responsibleEmployeeId":{"type":"string","format":"uuid","description":"Employee responsible for the order (optional)"},"status":{"type":"string","enum":["PENDING","IN_PROGRESS","WAITING_FOR_PARTS","QUALITY_CHECK","COMPLETED","CANCELLED"],"description":"Initial order status (optional, defaults to PENDING)"},"description":{"type":"string","maxLength":2000,"description":"Order description (optional)"},"entryDate":{"type":"string","format":"date-time","description":"Order start date (optional, defaults to current time)"}},"example":{"carId":"d20f2f80-8ab7-4186-9a78-c187c7ff13f6","clientId":"137fe84a-91cf-4614-91ef-e46f7a9501b6","responsibleEmployeeId":"07f88b87-43d0-4e4a-8350-e9907a6d155b","status":"WAITING_FOR_PARTS","description":"Engine repair needed","entryDate":"2024-01-15T10:30:00Z"}}}}},"responses":{"200":{"description":"Order created successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Order"}}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions or cannot access branch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Branch, car, client, or employee not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/branches/{branchId}":{"get":{"summary":"Get branch details","description":"Retrieve detailed information about a specific branch","tags":["Branches"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"}],"responses":{"200":{"description":"Branch details retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Branch"},"message":{"type":"string","example":"Branch retrieved successfully"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"put":{"summary":"Update branch","description":"Update a specific branch's information","tags":["Branches"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","example":"Updated Branch Name"},"address":{"type":"string","example":"456 New St, City, State 12345"},"phone":{"type":"string","example":"+1-555-987-6543"},"taxId":{"type":"string","minLength":1,"maxLength":50,"description":"Tax identification number (ЄДРПОУ/ІПН)","example":"12345678"},"bankDetails":{"type":"string","minLength":1,"maxLength":1000,"description":"Bank account details for payments","example":"Bank Name, Account: 1234567890, MFO: 123456"},"managerId":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000"}}}}}},"responses":{"200":{"description":"Branch updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Branch"},"message":{"type":"string","example":"Branch updated successfully"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"summary":"Delete branch","description":"Delete a specific branch (APP_ADMIN and COMPANY_ADMIN can perform this action)","tags":["Branches"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"}],"responses":{"200":{"description":"Branch deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Branch deleted successfully"}}}}}},"400":{"description":"Cannot delete branch with dependencies","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"has_employees":{"summary":"Branch has employees","value":{"success":false,"error":"Cannot delete branch with existing employees"}},"has_orders":{"summary":"Branch has orders","value":{"success":false,"error":"Cannot delete branch with existing orders"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Insufficient permissions - requires COMPANY_ADMIN or APP_ADMIN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/upload-logo":{"post":{"summary":"Upload a logo for a specific branch","description":"Uploads a single logo for a branch. Requires BRANCH_ADMIN or higher role.","tags":["Branch Management"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"logo":{"type":"string","format":"binary","description":"Image file to upload as logo"}}}}}},"responses":{"200":{"description":"Logo uploaded successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Branch logo uploaded successfully"},"data":{"type":"object","properties":{"url":{"type":"string","description":"URL of the uploaded logo"}}}}}}}},"400":{"description":"Bad request - no file uploaded or invalid input"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - Cannot access this branch or insufficient permissions"},"404":{"description":"Branch not found"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"summary":"Delete branch logo","description":"Removes the logo from a branch. Requires BRANCH_ADMIN or higher role.","tags":["Branch Management"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"}],"responses":{"200":{"description":"Logo deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Branch logo deleted successfully"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - Cannot access this branch or insufficient permissions"},"404":{"description":"Branch not found"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/branches/{branchId}/working-hours":{"get":{"summary":"Get working hours for a branch","description":"Retrieves the working hours schedule for a specific branch","tags":["Branches"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"}],"responses":{"200":{"description":"Working hours retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"workingHours":{"type":"object","nullable":true,"properties":{"monday":{"$ref":"#/components/schemas/DaySchedule"},"tuesday":{"$ref":"#/components/schemas/DaySchedule"},"wednesday":{"$ref":"#/components/schemas/DaySchedule"},"thursday":{"$ref":"#/components/schemas/DaySchedule"},"friday":{"$ref":"#/components/schemas/DaySchedule"},"saturday":{"$ref":"#/components/schemas/DaySchedule"},"sunday":{"$ref":"#/components/schemas/DaySchedule"}}}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Cannot access this branch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Branch not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"summary":"Update working hours for a branch","description":"Updates the working hours schedule for a specific branch. Requires BRANCH_ADMIN or higher role.","tags":["Branches"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"branchId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Branch ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"monday":{"$ref":"#/components/schemas/DaySchedule"},"tuesday":{"$ref":"#/components/schemas/DaySchedule"},"wednesday":{"$ref":"#/components/schemas/DaySchedule"},"thursday":{"$ref":"#/components/schemas/DaySchedule"},"friday":{"$ref":"#/components/schemas/DaySchedule"},"saturday":{"$ref":"#/components/schemas/DaySchedule"},"sunday":{"$ref":"#/components/schemas/DaySchedule"}},"example":{"monday":{"isOpen":true,"openTime":"09:00","closeTime":"18:00"},"tuesday":{"isOpen":true,"openTime":"09:00","closeTime":"18:00"},"wednesday":{"isOpen":true,"openTime":"09:00","closeTime":"18:00"},"thursday":{"isOpen":true,"openTime":"09:00","closeTime":"18:00"},"friday":{"isOpen":true,"openTime":"09:00","closeTime":"18:00"},"saturday":{"isOpen":true,"openTime":"10:00","closeTime":"15:00"},"sunday":{"isOpen":false,"openTime":null,"closeTime":null}}}}}},"responses":{"200":{"description":"Working hours updated successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"branchId":{"type":"string","format":"uuid"},"workingHours":{"type":"object"}}}}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions or cannot access branch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Branch not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/car-dictionary/brands/{brand}/models/{model}/years":{"get":{"summary":"List production years by brand and model","description":"Returns all distinct production years for the specified car brand and model combination.","tags":["Car Dictionary"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"brand","required":true,"schema":{"type":"string"},"description":"Car brand name.","example":"Audi"},{"in":"path","name":"model","required":true,"schema":{"type":"string"},"description":"Model name within the specified brand.","example":"Q5"}],"responses":{"200":{"description":"Production years retrieved successfully.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"array","items":{"type":"integer","format":"int32"},"example":[2018,2019,2020]}}}]}}}},"400":{"description":"Brand or model parameter is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Failed to fetch car production years.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/car-dictionary/brands/{brand}/models":{"get":{"summary":"List models by brand","description":"Returns all distinct models for the specified car brand.","tags":["Car Dictionary"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"brand","required":true,"schema":{"type":"string"},"description":"Car brand to filter models by.","example":"Audi"}],"responses":{"200":{"description":"Car models retrieved successfully.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"array","items":{"type":"string"},"example":["A3","A4","Q5"]}}}]}}}},"400":{"description":"Brand parameter is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Failed to fetch car models.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/car-dictionary/brands":{"get":{"summary":"Get car brands","description":"Retrieves list of car brands with optional search","tags":["Car Dictionary"],"parameters":[{"in":"query","name":"search","schema":{"type":"string"},"description":"Search brands by name"},{"in":"query","name":"limit","schema":{"type":"integer","default":100},"description":"Maximum number of results"}],"responses":{"200":{"description":"Brands retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"}}}}}}}}},"500":{"description":"Internal server error"}}},"post":{"summary":"Create car brand","description":"Creates a car brand if it does not exist","tags":["Car Dictionary"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","example":"Toyota"}}}}}},"responses":{"200":{"description":"Brand created or already exists","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"}}}}}}}},"400":{"description":"Invalid input data"},"500":{"description":"Internal server error"}}}},"/api/car-dictionary/models":{"get":{"summary":"Get car models","description":"Retrieves list of car models for a brand","tags":["Car Dictionary"],"parameters":[{"in":"query","name":"brandId","schema":{"type":"integer"},"description":"Filter by brand ID"},{"in":"query","name":"brandName","schema":{"type":"string"},"description":"Filter by brand name (alternative to brandId)"},{"in":"query","name":"search","schema":{"type":"string"},"description":"Search models by name (requires brandId)"},{"in":"query","name":"limit","schema":{"type":"integer","default":100},"description":"Maximum number of results"}],"responses":{"200":{"description":"Models retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"brandId":{"type":"integer"},"name":{"type":"string"}}}}}}}}},"400":{"description":"Missing required parameters"},"500":{"description":"Internal server error"}}},"post":{"summary":"Create car model","description":"Creates a car model for the specified brand if it does not exist","tags":["Car Dictionary"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["brandId","name"],"properties":{"brandId":{"type":"integer"},"name":{"type":"string","example":"Camry"},"year":{"type":"integer"}}}}}},"responses":{"200":{"description":"Model created or already exists"},"400":{"description":"Invalid input data"},"404":{"description":"Brand not found"},"500":{"description":"Internal server error"}}}},"/api/car-info/health":{"get":{"summary":"Check CarInfoParser service health","description":"Checks the availability and status of the CarInfoParser microservice","tags":["Car Info"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Health check completed successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"service_available":{"type":"boolean","example":true},"service_url":{"type":"string","example":"http://car-info-parser:5000"},"configuration":{"type":"object","properties":{"timeout":{"type":"number","example":30000},"retries":{"type":"number","example":3}}},"service_info":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"service":{"type":"string","example":"car-info-service"},"version":{"type":"string","example":"1.0.0"},"timestamp":{"type":"string","format":"date-time","example":"2024-01-15T10:30:00"},"features":{"type":"array","items":{"type":"string"},"example":["baza-gai.com.ua parsing","vininfo library integration"]}}},"response_time":{"type":"number","description":"Response time in milliseconds","example":150}}}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"CarInfoParser service unavailable","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"service_available":{"type":"boolean","example":false},"service_url":{"type":"string","example":"http://car-info-parser:5000"},"error_details":{"type":"string","example":"Connection refused"}}}}}]}}}}}}},"/api/car-info":{"post":{"summary":"Get car information","description":"Retrieves detailed car information using VIN code or license plate through CarInfoParser service","tags":["Car Info"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"vin":{"type":"string","pattern":"^[A-HJ-NPR-Z0-9]{17}$","description":"17-character VIN code (cannot contain I, O, Q)","example":"1HGCM82633A123456"},"licensePlate":{"type":"string","maxLength":20,"description":"License plate number (not supported in current version)","example":"AA1234BB"}},"oneOf":[{"required":["vin"]},{"required":["licensePlate"]}]}}}},"responses":{"200":{"description":"Car information retrieved successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"vin":{"type":"string","example":"1HGCM82633A123456"},"manufacturer":{"type":"string","example":"HONDA"},"model":{"type":"string","example":"ACCORD"},"year":{"type":"string","example":"2003"},"license_plate":{"type":"string","example":"AA1234BB"},"color":{"type":"string","example":"Silver"},"body_type":{"type":"string","example":"Sedan"},"engine":{"type":"string","example":"2.4L"},"processing_time":{"type":"number","example":1.5},"sources_count":{"type":"string","example":"2/3"}}}}}]}}}},"400":{"description":"Invalid input data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Car information not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"CarInfoParser service unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"summary":"Get batch car information","description":"Retrieves information for multiple cars using batch VIN processing","tags":["Car Info"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"vins":{"type":"array","items":{"type":"string","pattern":"^[A-HJ-NPR-Z0-9]{17}$"},"minItems":1,"maxItems":5,"description":"Array of VIN codes (maximum 5)","example":["1HGCM82633A123456","JHMFA16217S123456"]}},"required":["vins"]}}}},"responses":{"200":{"description":"Batch processing completed","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"total":{"type":"number","example":2},"successful":{"type":"number","example":1},"failed":{"type":"number","example":1},"results":{"type":"array","items":{"type":"object","properties":{"vin":{"type":"string"},"success":{"type":"boolean"},"data":{"type":"object","description":"Car information object (when success=true)"},"error":{"type":"string","description":"Error message (when success=false)"}}}}}}}}]}}}},"400":{"description":"Invalid input data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"CarInfoParser service unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/car-info/validate/{vin}":{"get":{"summary":"Validate VIN code","description":"Validates VIN code format and checks it against CarInfoParser service","tags":["Car Info"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"vin","required":true,"schema":{"type":"string","pattern":"^[A-HJ-NPR-Z0-9]{17}$"},"description":"17-character VIN code to validate","example":"1HGCM82633A123456"}],"responses":{"200":{"description":"VIN validation completed","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"vin":{"type":"string","example":"1HGCM82633A123456"},"valid":{"type":"boolean","example":true},"message":{"type":"string","example":"VIN код валиден"},"local_validation":{"type":"object","properties":{"format_valid":{"type":"boolean","example":true},"length_valid":{"type":"boolean","example":true},"character_valid":{"type":"boolean","example":true}}},"service_validation":{"type":"object","properties":{"available":{"type":"boolean","example":true},"valid":{"type":"boolean","example":true},"message":{"type":"string","example":"VIN код валиден"}}}}}}}]}}}},"400":{"description":"Invalid VIN format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/cars/{id}":{"get":{"summary":"Get car details","description":"Retrieve detailed information about a specific car including clients and order history","tags":["Cars"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Car ID"}],"responses":{"200":{"description":"Car details retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Car"},"message":{"type":"string","example":"Car retrieved successfully"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"put":{"summary":"Update car","description":"Update a specific car's information (role-based permissions apply)","tags":["Cars"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Car ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCar"}}}},"responses":{"200":{"description":"Car updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Car"},"message":{"type":"string","example":"Car updated successfully"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Insufficient permissions or business rule violation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"summary":"Delete car","description":"Delete a specific car (only COMPANY_ADMIN+ can perform this action)","tags":["Cars"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Car ID"}],"responses":{"200":{"description":"Car deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Car deleted successfully"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Cannot delete car with existing orders","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/cars":{"get":{"summary":"Get cars","description":"Retrieves a list of cars with optional search functionality","tags":["Cars"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"page","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number for pagination"},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":10},"description":"Number of items per page"},{"in":"query","name":"search","schema":{"type":"string"},"description":"Search cars by VIN, make, model, or year"},{"in":"query","name":"make","schema":{"type":"string"},"description":"Filter by car make"},{"in":"query","name":"model","schema":{"type":"string"},"description":"Filter by car model"},{"in":"query","name":"year","schema":{"type":"integer"},"description":"Filter by car year"}],"responses":{"200":{"description":"Cars retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Car"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"summary":"Create car","description":"Creates a new car record","tags":["Cars"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCar"}}}},"responses":{"200":{"description":"Car created successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Car"}}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"VIN already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/companies/{companyId}/branches":{"get":{"summary":"List branches for a company","description":"Retrieve all branches belonging to a specific company with pagination","tags":["Branches"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"query","name":"page","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number for pagination"},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":10},"description":"Number of items per page"}],"responses":{"200":{"description":"Branches retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Branch"}},"pagination":{"$ref":"#/components/schemas/Pagination"},"message":{"type":"string","example":"Branches retrieved successfully"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Company not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"summary":"Create a new branch","description":"Create a new branch for a specific company","tags":["Branches"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"New Branch Location"},"address":{"type":"string","maxLength":1000,"example":"789 Business Ave, City, State 12345","description":"Branch address (optional — can be filled later)"},"phone":{"type":"string","pattern":"^[+]?[0-9()-\\s]+$","minLength":10,"maxLength":20,"example":380501234567,"description":"Branch contact phone number (optional)"},"taxId":{"type":"string","minLength":1,"maxLength":50,"example":12345678,"description":"Tax identification number (ЄДРПОУ/ІПН) (optional — can be filled later)"},"bankDetails":{"type":"string","minLength":1,"maxLength":1000,"example":"Bank Name, Account: 1234567890, MFO: 123456","description":"Bank account details for payments (optional)"},"managerId":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000"}}}}}},"responses":{"201":{"description":"Branch created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Branch"},"message":{"type":"string","example":"Branch created successfully"}}}}}},"400":{"description":"Validation error or invalid manager","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Cannot create branch for this company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Company not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/companies/{companyId}/cars":{"get":{"summary":"Get cars for a specific company","description":"Retrieves a list of cars associated with clients of the specified company","tags":["Cars"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"query","name":"page","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number for pagination"},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":10},"description":"Number of items per page"},{"in":"query","name":"search","schema":{"type":"string"},"description":"Search cars by VIN, make, model, or year"},{"in":"query","name":"make","schema":{"type":"string"},"description":"Filter by car make"},{"in":"query","name":"year","schema":{"type":"integer"},"description":"Filter by car year"}],"responses":{"200":{"description":"Cars retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Car"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Cannot access this company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Company not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"summary":"Create car for a specific company","description":"Creates a new car that can be associated with clients of the specified company. Requires BRANCH_ADMIN or higher role.","tags":["Cars"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCar"}}}},"responses":{"200":{"description":"Car created successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Car"}}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions or cannot access company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Company not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Car with this VIN already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/companies/{companyId}/clients/{id}/cars/{carId}":{"put":{"summary":"Update client-car relationship","description":"Updates the relationship between a client and car (e.g., setting as primary)","tags":["Clients","Cars"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Client ID"},{"in":"path","name":"carId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Car ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"isPrimary":{"type":"boolean","description":"Whether this should be the client's primary car"}}}}}},"responses":{"200":{"description":"Client-car relationship updated successfully"},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions or cannot access company"},"404":{"description":"Company, client, car, or relationship not found"},"500":{"description":"Internal server error"}}},"delete":{"summary":"Remove car from client","description":"Removes the association between a client and car. Requires BRANCH_ADMIN or higher role.","tags":["Clients","Cars"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Client ID"},{"in":"path","name":"carId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Car ID"}],"responses":{"200":{"description":"Car removed from client successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Car removed from client successfully"}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions or cannot access company"},"404":{"description":"Company, client, car, or relationship not found"},"409":{"description":"Cannot remove car with existing orders"},"500":{"description":"Internal server error"}}}},"/api/companies/{companyId}/clients/{id}/cars/find-or-create":{"put":{"summary":"Find or create car and assign to client","description":"Searches for an existing car when VIN is provided. Otherwise creates a partial car and assigns it to the client. At least VIN, license plate, or make must be provided.","tags":["Clients","Cars"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Client ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"vin":{"type":"string","minLength":1,"maxLength":17,"description":"Vehicle identification number","example":"1HGBH41JXMN109186"},"make":{"type":"string","minLength":1,"description":"Car manufacturer","example":"Honda"},"model":{"type":"string","minLength":1,"description":"Car model","example":"Civic"},"year":{"type":"integer","minimum":1900,"description":"Manufacturing year","example":2020},"trim":{"type":"string","description":"Car trim level","example":"LX"},"mileage":{"type":"integer","minimum":0,"description":"Current mileage","example":50000},"color":{"type":"string","maxLength":50,"description":"Vehicle color","example":"синий"},"licensePlate":{"type":"string","minLength":1,"description":"Vehicle license plate number","example":"AB1234CD"},"engineVolume":{"type":"string","minLength":1,"description":"Engine displacement volume","example":"2.0L"},"photos":{"type":"array","items":{"type":"string"},"description":"Array of photo URLs","example":["photo1.jpg","photo2.jpg"]},"isPrimary":{"type":"boolean","default":false,"description":"Whether this should be the client's primary car"}}}}}},"responses":{"200":{"description":"Car found/created and assigned to client successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"isPrimary":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"car":{"$ref":"#/components/schemas/Car"},"wasCarCreated":{"type":"boolean","description":"Indicates if a new car was created or existing one was used"}}}}}]}}}},"400":{"description":"Validation error or car already associated with client"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions or cannot access company"},"404":{"description":"Company or client not found"},"500":{"description":"Internal server error"}}}},"/api/companies/{companyId}/clients/{id}/cars":{"get":{"summary":"Get all cars for a specific client","description":"Retrieves all cars associated with a specific client","tags":["Clients","Cars"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Client ID"}],"responses":{"200":{"description":"Client cars retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"isPrimary":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"car":{"$ref":"#/components/schemas/Car"}}}}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Cannot access this company or insufficient permissions"},"404":{"description":"Company or client not found"},"500":{"description":"Internal server error"}}},"post":{"summary":"Add a car to a client","description":"Associates a car with a client. Requires BRANCH_ADMIN or higher role.","tags":["Clients","Cars"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Client ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["carId"],"properties":{"carId":{"type":"string","format":"uuid","description":"ID of the car to associate with the client"},"isPrimary":{"type":"boolean","default":false,"description":"Whether this should be the client's primary car"}}}}}},"responses":{"200":{"description":"Car added to client successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"isPrimary":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"car":{"$ref":"#/components/schemas/Car"}}}}}]}}}},"400":{"description":"Validation error or car already associated with client"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions or cannot access company"},"404":{"description":"Company, client, or car not found"},"500":{"description":"Internal server error"}}}},"/api/companies/{companyId}/clients/{id}/orders":{"get":{"summary":"Get orders for a specific client","description":"Retrieves a list of orders for the specified client. All orders across all branches of the company are included.","tags":["Orders","Clients"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Client ID"},{"in":"query","name":"page","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number for pagination"},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":10},"description":"Number of items per page"},{"in":"query","name":"status","schema":{"type":"string","enum":["PENDING","IN_PROGRESS","WAITING_FOR_PARTS","QUALITY_CHECK","COMPLETED","CANCELLED"]},"description":"Filter by order status"},{"in":"query","name":"branchId","schema":{"type":"string","format":"uuid"},"description":"Filter by branch ID"},{"in":"query","name":"carId","schema":{"type":"string","format":"uuid"},"description":"Filter by car ID"},{"in":"query","name":"sortBy","schema":{"type":"string","enum":["createdAt","updatedAt","status","totalAmount"],"default":"createdAt"},"description":"Sort orders by field"},{"in":"query","name":"sortOrder","schema":{"type":"string","enum":["asc","desc"],"default":"desc"},"description":"Sort order"}],"responses":{"200":{"description":"Client orders retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"orderNumber":{"type":"string"},"status":{"type":"string","enum":["PENDING","IN_PROGRESS","WAITING_FOR_PARTS","QUALITY_CHECK","COMPLETED","CANCELLED"]},"description":{"type":"string"},"totalAmount":{"type":"number","format":"decimal"},"subtotalAmount":{"type":"number","format":"decimal"},"vatAmount":{"type":"number","format":"decimal"},"entryDate":{"type":"string","format":"date-time"},"exitDate":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time"},"branch":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}},"car":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"vin":{"type":"string"},"make":{"type":"string"},"model":{"type":"string"},"year":{"type":"integer"}}},"responsibleEmployee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"role":{"type":"string"}}},"_count":{"type":"object","properties":{"orderWorks":{"type":"integer"},"orderItems":{"type":"integer"}}}}}},"pagination":{"$ref":"#/components/schemas/Pagination"},"summary":{"type":"object","properties":{"totalOrders":{"type":"integer"},"completedOrders":{"type":"integer"},"pendingOrders":{"type":"integer"},"totalValue":{"type":"number","format":"decimal"},"averageOrderValue":{"type":"number","format":"decimal"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Cannot access this company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Company or client not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/companies/{companyId}/clients/{id}":{"get":{"summary":"Get a specific client for a company","description":"Retrieves a specific client by ID for the specified company","tags":["Clients"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Client ID"}],"responses":{"200":{"description":"Client retrieved successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Client"}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Cannot access this company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Company or client not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"summary":"Update a client for a company","description":"Updates a specific client for the specified company. Requires BRANCH_ADMIN or higher role.","tags":["Clients"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Client ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","example":"Jane Smith"},"carId":{"type":"string","format":"uuid"},"phone":{"type":"string","example":"+1-234-567-8901"},"email":{"type":"string","format":"email","example":"jane.smith@example.com"},"address":{"type":"string","example":"456 Oak Ave, City, State 12346"}}}}}},"responses":{"200":{"description":"Client updated successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Client"}}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions or cannot access company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"summary":"Delete a client for a company","description":"Deletes a specific client for the specified company. Requires BRANCH_ADMIN or higher role.","tags":["Clients"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Client ID"}],"responses":{"200":{"description":"Client deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions or cannot access company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Client has orders and cannot be deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/companies/{companyId}/clients":{"get":{"summary":"Get clients for a specific company","description":"Retrieves a list of clients for the specified company","tags":["Clients"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"query","name":"page","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number for pagination"},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":10},"description":"Number of items per page"},{"in":"query","name":"search","schema":{"type":"string"},"description":"Search clients by name, phone, or vehicle license plate (general search)"},{"in":"query","name":"name","schema":{"type":"string"},"description":"Filter by client name (case-insensitive partial match)"},{"in":"query","name":"phone","schema":{"type":"string"},"description":"Filter by client phone number (case-insensitive partial match)"},{"in":"query","name":"licensePlate","schema":{"type":"string"},"description":"Filter by vehicle license plate (case-insensitive exact match)"},{"in":"query","name":"vin","schema":{"type":"string"},"description":"Filter by vehicle VIN (case-insensitive exact match)"}],"responses":{"200":{"description":"Clients retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Client"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Cannot access this company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Company not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"summary":"Create client for a specific company","description":"Creates a new client for the specified company. Requires BRANCH_ADMIN or higher role.","tags":["Clients"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","carIds"],"properties":{"name":{"type":"string","description":"Client name","example":"John Doe"},"carIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Array of car IDs to associate with the client","minItems":1,"example":["550e8400-e29b-41d4-a716-446655440000"]},"primaryCarId":{"type":"string","format":"uuid","description":"ID of the primary car (must be one of the carIds)","example":"550e8400-e29b-41d4-a716-446655440000"},"phone":{"type":"string","description":"Client phone number","example":"+1-555-0123"},"email":{"type":"string","format":"email","description":"Client email address","example":"john.doe@example.com"},"address":{"type":"string","description":"Client address","example":"123 Main St, City, State 12345"}}}}}},"responses":{"200":{"description":"Client created successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"address":{"type":"string"},"company":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}},"clientCars":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"isPrimary":{"type":"boolean"},"car":{"$ref":"#/components/schemas/Car"}}}}}}}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"code":{"type":"string","enum":["VALIDATION_ERROR"],"description":"Specific validation error code"}}}]},"example":{"success":false,"error":"Invalid input data","code":"VALIDATION_ERROR"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions or cannot access company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Company or car not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/companies/{companyId}/employees/{employeeId}/auth-status":{"get":{"summary":"Get employee authentication status","description":"Check if employee has Supabase credentials, when they were last updated, and their current auth status. COMPANY_ADMIN+ can check auth status.","tags":["Employees"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"employeeId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Employee ID"}],"responses":{"200":{"description":"Auth status retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"employeeId":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email","nullable":true,"description":"Employee email (null if not set)"},"lastUpdated":{"type":"string","format":"date-time","description":"When employee record was last updated"},"supabaseUser":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"email":{"type":"string"},"emailConfirmed":{"type":"boolean"},"lastSignIn":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time"}}},"invitationSent":{"type":"boolean","description":"Whether invitation email has been sent"},"emailVerified":{"type":"boolean","description":"Whether employee has verified their email address"},"passwordCreated":{"type":"boolean","description":"Whether employee has created their password"},"invitedAt":{"type":"string","format":"date-time","nullable":true,"description":"When the invitation was sent"}}},"message":{"type":"string","example":"Employee auth status retrieved successfully"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/companies/{companyId}/employees/{employeeId}/credentials":{"post":{"summary":"Admin updates employee email and/or password","description":"COMPANY_ADMIN+ can immediately update a user's Supabase email and/or password and sync the local employee record.","tags":["Employees"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"path","name":"employeeId","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"password":{"type":"string"}}}}}},"responses":{"200":{"description":"Credentials updated"},"400":{"description":"Validation error or missing Supabase account"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Employee not found"}}}},"/api/companies/{companyId}/employees/{employeeId}/invite":{"post":{"summary":"Send invitation email to employee","description":"Send a Supabase auth invitation email to an employee who doesn't have credentials yet. Only COMPANY_ADMIN+ can send invites.","tags":["Employees"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"employeeId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Employee ID"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"redirectTo":{"type":"string","format":"uri","description":"URL to redirect to after accepting invitation","example":"https://yourapp.com/employees/init"}}},"example":{"redirectTo":"https://yourapp.com/employees/init"}}}},"responses":{"200":{"description":"Invitation sent successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"invitedAt":{"type":"string","format":"date-time"},"invitationEmail":{"type":"string","format":"email"}}},"message":{"type":"string","example":"Invitation sent successfully to employee@email.com"}}}}}},"400":{"description":"Bad Request - Employee already has credentials or no email"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/companies/{companyId}/employees/{employeeId}/reset-credentials":{"post":{"summary":"Reset employee authentication credentials","description":"Remove Supabase authentication credentials from an employee, allowing them to be re-invited or manually set up. Only COMPANY_ADMIN+ can reset credentials.","tags":["Employees"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"employeeId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Employee ID"}],"responses":{"200":{"description":"Credentials reset successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"employeeId":{"type":"string","format":"uuid"},"resetAt":{"type":"string","format":"date-time"},"supabaseUserDeleted":{"type":"boolean"}}},"message":{"type":"string","example":"Employee credentials reset successfully"}}}}}},"400":{"description":"Bad Request - Employee doesn't have credentials to reset"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/companies/{companyId}/employees/{employeeId}":{"get":{"summary":"Get company employee details","description":"Get detailed information about a specific employee in the company","tags":["Employees"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"employeeId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Employee ID"}],"responses":{"200":{"description":"Employee details retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/EmployeeWithCompanyDetails"},"message":{"type":"string","example":"Employee details retrieved successfully"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"summary":"Update company employee","description":"Update an employee's information. Only COMPANY_ADMIN+ can update employees.","tags":["Employees"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"employeeId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Employee ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEmployeeRequest"},"example":{"name":"John Smith Updated","branches":[{"branchId":"550e8400-e29b-41d4-a716-446655440001"},{"branchId":"550e8400-e29b-41d4-a716-446655440002"}],"hourlyRate":55,"skills":["Management","Leadership","Strategy"],"profitType":"PERCENTAGE","profitValue":15}}}},"responses":{"200":{"description":"Employee updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/EmployeeWithCompanyDetails"},"message":{"type":"string","example":"Employee updated successfully"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Conflict - Email already exists"}}},"delete":{"summary":"Delete company employee","description":"Delete an employee from the company. Only COMPANY_ADMIN+ can delete employees.","tags":["Employees"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"employeeId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Employee ID"}],"responses":{"200":{"description":"Employee deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Employee deleted successfully"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/companies/{companyId}/employees/init":{"get":{"summary":"Initialize employee data for current user","description":"Get employee information for the currently authenticated user to initialize the application UI","tags":["Employees"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"}],"responses":{"200":{"description":"Employee initialization data retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"employee":{"$ref":"#/components/schemas/EmployeeWithCompanyDetails"},"initialized":{"type":"boolean","description":"Whether employee has completed setup"},"setupStatus":{"type":"object","properties":{"emailVerified":{"type":"boolean"},"passwordCreated":{"type":"boolean"},"invitationSent":{"type":"boolean"}}}}},"message":{"type":"string","example":"Employee initialization data retrieved successfully"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/companies/{companyId}/employees":{"get":{"summary":"List company employees","description":"Get all employees in a company across all branches with pagination and optional filtering","tags":["Employees"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"query","name":"page","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number for pagination"},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":10},"description":"Number of items per page"},{"in":"query","name":"role","schema":{"type":"string","enum":["APP_ADMIN","COMPANY_ADMIN","BRANCH_ADMIN","STAFF"]},"description":"Filter employees by role"},{"in":"query","name":"branchId","schema":{"type":"string","format":"uuid"},"description":"Filter employees by branch assignment"},{"in":"query","name":"search","schema":{"type":"string"},"description":"Search employees by name, email, phone, or skills"}],"responses":{"200":{"description":"Employees retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/EmployeeWithCompanyDetails"},{"type":"object","properties":{"authStatus":{"type":"object","properties":{"invitationSent":{"type":"boolean","description":"Whether invitation email has been sent"},"emailVerified":{"type":"boolean","description":"Whether employee has verified their email address"},"passwordCreated":{"type":"boolean","description":"Whether employee has created their password"},"invitedAt":{"type":"string","format":"date-time","nullable":true,"description":"When the invitation was sent"}}}}}]}},"pagination":{"$ref":"#/components/schemas/PaginationInfo"},"message":{"type":"string","example":"Company employees retrieved successfully"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"summary":"Create company-level employee","description":"Create a new employee at company level with optional branch assignments. Only COMPANY_ADMIN+ can create employees.","tags":["Employees"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCompanyEmployeeRequest"},"example":{"name":"John Smith","email":"john.smith@company.com","phone":"+1234567890","branches":[{"branchId":"550e8400-e29b-41d4-a716-446655440000"},{"branchId":"550e8400-e29b-41d4-a716-446655440001"}],"skills":["Management","Customer Service"],"hourlyRate":50,"role":"COMPANY_ADMIN","profitType":"FIXED","profitValue":1000}}}},"responses":{"200":{"description":"Employee created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/EmployeeWithCompanyDetails"},"message":{"type":"string","example":"Employee created successfully"}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"code":{"type":"string","enum":["VALIDATION_ERROR"],"description":"Specific validation error code"}}}]},"example":{"success":false,"error":"Invalid input data","code":"VALIDATION_ERROR"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Conflict - Account with this email already exists","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"code":{"type":"string","enum":["EMAIL_ALREADY_EXISTS"],"description":"Specific error code for duplicate email"}}}]},"example":{"success":false,"error":"An account with this email already exists","code":"EMAIL_ALREADY_EXISTS"}}}}}}},"/api/companies/{companyId}/extension/devices/{deviceId}":{"delete":{"summary":"Revoke/delete an extension device","tags":["Extensions"],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"path","name":"deviceId","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Device revoked"},"404":{"description":"Device not found"}}}},"/api/companies/{companyId}/extension/devices":{"get":{"summary":"List paired extension devices for a company","tags":["Extensions"],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"List of devices"}}}},"/api/companies/{companyId}/order-delete-requests/{requestId}":{"patch":{"summary":"Review an order delete request","description":"APP_ADMIN-only review. Approves and executes a pending completed-order delete request, or rejects it with an optional comment. Approval preserves existing payroll rows and creates negative reversal accruals for payroll effects linked to the order instead of deleting payroll history or rewriting payout totals.","tags":["Order Delete Requests"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"requestId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order delete request ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["approved"],"properties":{"approved":{"type":"boolean","description":"Whether to approve and execute the delete request","example":true},"comment":{"type":"string","maxLength":1000,"description":"Optional review comment","example":"Approved duplicate order cleanup"}}}}}},"responses":{"200":{"description":"Order delete request reviewed successfully"},"400":{"description":"Invalid request body"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - insufficient permissions"},"404":{"description":"Order delete request not found"},"409":{"description":"Request already reviewed or order can no longer be deleted via approval flow"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/companies/{companyId}/order-reopen-requests/{requestId}":{"patch":{"summary":"Review an order reopen request","description":"APP_ADMIN-only review. Approves and executes a pending reopen request, or rejects it with an optional comment. Approval preserves existing payroll rows, creates negative reversal accruals for payroll effects linked to the order, and returns the completed order to IN_PROGRESS without rewriting payout totals.","tags":["Order Reopen Requests"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"requestId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order reopen request ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["approved"],"properties":{"approved":{"type":"boolean","description":"Whether to approve and execute the reopen request","example":true},"comment":{"type":"string","maxLength":1000,"description":"Optional review comment","example":"Approved for additional diagnostics"}}}}}},"responses":{"200":{"description":"Order reopen request reviewed successfully"},"400":{"description":"Invalid request body"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - insufficient permissions"},"404":{"description":"Order reopen request or order not found"},"409":{"description":"Request already reviewed or order can no longer be reopened"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/companies/{companyId}/order-reopen-requests":{"get":{"summary":"List company order reopen requests","description":"Retrieves order reopen requests for a company, optionally filtered by status.","tags":["Order Reopen Requests"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"query","name":"status","required":false,"schema":{"type":"string","enum":["PENDING","APPROVED","REJECTED","EXECUTED"]},"description":"Optional reopen request status filter"}],"responses":{"200":{"description":"Order reopen requests retrieved successfully"},"400":{"description":"Invalid query parameters"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - insufficient permissions"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/companies/{companyId}":{"get":{"summary":"Get company details","description":"Retrieve detailed information about a specific company including branches, clients, work types, vendors, and warehouses","tags":["Companies"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"}],"responses":{"200":{"description":"Company details retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Company"},"message":{"type":"string","example":"Company retrieved successfully"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"put":{"summary":"Update company","description":"Update a specific company's information (APP_ADMIN can update any company, COMPANY_ADMIN can update their own company)","tags":["Companies"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"Updated Company Name"},"includeVat":{"type":"boolean","description":"Whether to include VAT (ПДВ) in order calculations","example":true},"hideArticlesFromClients":{"type":"boolean","description":"Whether client-facing documents hide product articles/SKUs","example":false}}}}}},"responses":{"200":{"description":"Company updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Company"},"message":{"type":"string","example":"Company updated successfully"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Only APP_ADMIN can update companies","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"summary":"Delete company","description":"Remove a specific company from active access while preserving historical clients, orders, and estimates","tags":["Companies"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"}],"responses":{"200":{"description":"Company deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Company deleted successfully"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Only APP_ADMIN can delete companies","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/companies/{companyId}/upload-logo":{"post":{"summary":"Upload a logo for a specific company","description":"Uploads a single logo for a company. Requires COMPANY_ADMIN or higher role.","tags":["Company Management"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"logo":{"type":"string","format":"binary","description":"Image file to upload as logo"}}}}}},"responses":{"200":{"description":"Logo uploaded successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Company logo uploaded successfully"},"data":{"type":"object","properties":{"url":{"type":"string","description":"URL of the uploaded logo"}}}}}}}},"400":{"description":"Bad request - no file uploaded or invalid input"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - Cannot access this company or insufficient permissions"},"404":{"description":"Company not found"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"summary":"Delete company logo","description":"Removes the logo from a company. Requires COMPANY_ADMIN or higher role.","tags":["Company Management"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"}],"responses":{"200":{"description":"Logo deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Company logo deleted successfully"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden - Cannot access this company or insufficient permissions"},"404":{"description":"Company not found"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/companies/{companyId}/vendors/{id}":{"get":{"summary":"Get a specific vendor for a company","description":"Retrieves a specific vendor by ID for the specified company","tags":["Vendors"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Vendor ID"}],"responses":{"200":{"description":"Vendor retrieved successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Vendor"}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Cannot access this company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Company or vendor not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"summary":"Update a vendor for a company","description":"Updates a specific vendor for the specified company. Requires COMPANY_ADMIN or higher role.","tags":["Vendors"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Vendor ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","example":"Parts Supplier Inc"},"location":{"type":"string","example":"789 Industrial Blvd, City, State 12347"},"contactInfo":{"type":"object"}}}}}},"responses":{"200":{"description":"Vendor updated successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Vendor"}}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions or cannot access company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Vendor not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Vendor name already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"summary":"Delete a vendor for a company","description":"Deletes a specific vendor for the specified company. Requires COMPANY_ADMIN or higher role.","tags":["Vendors"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Vendor ID"}],"responses":{"200":{"description":"Vendor deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions or cannot access company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Vendor not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Vendor is in use and cannot be deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/companies/{companyId}/vendors":{"get":{"summary":"Get vendors for a specific company","description":"Retrieves a list of vendors for the specified company","tags":["Vendors"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"query","name":"page","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number for pagination"},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":10},"description":"Number of items per page"},{"in":"query","name":"search","schema":{"type":"string"},"description":"Search vendors by name"}],"responses":{"200":{"description":"Vendors retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Vendor"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Cannot access this company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Company not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"summary":"Create vendor for a specific company","description":"Creates a new vendor for the specified company. Requires COMPANY_ADMIN or higher role.","tags":["Vendors"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateVendor"}}}},"responses":{"200":{"description":"Vendor created successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Vendor"}}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions or cannot access company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Company not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Vendor name already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/companies/{companyId}/warehouses/{id}":{"get":{"summary":"Get a specific warehouse for a company","description":"Retrieves a specific warehouse by ID for the specified company","tags":["Warehouses"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Warehouse ID"}],"responses":{"200":{"description":"Warehouse retrieved successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Warehouse"}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Cannot access this company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Company or warehouse not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"summary":"Update a warehouse for a company","description":"Updates a specific warehouse for the specified company. Requires COMPANY_ADMIN or higher role.","tags":["Warehouses"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Warehouse ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","example":"Main Warehouse"},"location":{"type":"string","example":"123 Storage Way, City, State 12348"}}}}}},"responses":{"200":{"description":"Warehouse updated successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Warehouse"}}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions or cannot access company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Warehouse not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Warehouse name already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"summary":"Delete a warehouse for a company","description":"Deletes a specific warehouse for the specified company. Requires COMPANY_ADMIN or higher role.","tags":["Warehouses"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Warehouse ID"}],"responses":{"200":{"description":"Warehouse deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions or cannot access company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Warehouse not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Warehouse is in use and cannot be deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/companies/{companyId}/warehouses":{"get":{"summary":"Get warehouses for a specific company","description":"Retrieves a list of warehouses for the specified company","tags":["Warehouses"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"query","name":"page","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number for pagination"},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":10},"description":"Number of items per page"},{"in":"query","name":"search","schema":{"type":"string"},"description":"Search warehouses by name"}],"responses":{"200":{"description":"Warehouses retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Warehouse"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Cannot access this company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Company not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"summary":"Create warehouse for a specific company","description":"Creates a new warehouse for the specified company. Requires COMPANY_ADMIN or higher role.","tags":["Warehouses"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWarehouse"}}}},"responses":{"200":{"description":"Warehouse created successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Warehouse"}}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions or cannot access company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Company not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Warehouse name already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/companies/{companyId}/work-types/{id}":{"get":{"summary":"Get a specific work type for a company","description":"Retrieves a specific work type by ID for the specified company","tags":["Work Types"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Work type ID"}],"responses":{"200":{"description":"Work type retrieved successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WorkType"}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Cannot access this company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Company or work type not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"summary":"Update a work type for a company","description":"Updates a specific work type for the specified company. Requires BRANCH_ADMIN or higher role.","tags":["Work Types"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Work type ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","example":"Oil Change"},"hourlyRate":{"type":"number","format":"decimal","example":75}}}}}},"responses":{"200":{"description":"Work type updated successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WorkType"}}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions or cannot access company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Work type not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Work type name already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"summary":"Delete a work type for a company","description":"Deletes a specific work type for the specified company. Requires BRANCH_ADMIN or higher role.","tags":["Work Types"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Work type ID"}],"responses":{"200":{"description":"Work type deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions or cannot access company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Work type not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Work type is in use and cannot be deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/companies/{companyId}/work-types":{"get":{"summary":"Get work types for a specific company","description":"Retrieves a list of work types for the specified company","tags":["Work Types"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"},{"in":"query","name":"page","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number for pagination"},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":10},"description":"Number of items per page"},{"in":"query","name":"search","schema":{"type":"string"},"description":"Search work types by name"}],"responses":{"200":{"description":"Work types retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/WorkType"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Cannot access this company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Company not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"summary":"Create work type for a specific company","description":"Creates a new work type for the specified company. Requires BRANCH_ADMIN or higher role.","tags":["Work Types"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"companyId","required":true,"schema":{"type":"string","format":"uuid"},"description":"Company ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWorkType"}}}},"responses":{"200":{"description":"Work type created successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WorkType"}}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions or cannot access company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Company not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Work type name already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/companies":{"get":{"summary":"Get companies","description":"Retrieves a list of companies. APP_ADMINs can see all companies with pagination, others see only their own company.","tags":["Companies"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"page","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number for pagination"},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":10},"description":"Number of items per page"}],"responses":{"200":{"description":"Companies retrieved successfully","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Company"}}}}]},{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Company"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Company not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"summary":"Create company","description":"Creates a new company. Only APP_ADMIN users can create companies.","tags":["Companies"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCompany"}}}},"responses":{"200":{"description":"Company created successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Company"}}}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Only app administrators can create companies","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/crm/extensions/pairing-codes":{"post":{"summary":"Create one-time pairing code for Chrome Extension","description":"Generates a short-lived, single-use pairing code.","tags":["Extensions"],"responses":{"200":{"description":"Pairing code created"}}}},"/api/docs":{"get":{"summary":"Get OpenAPI specification","description":"Returns the OpenAPI specification for the CRM API","tags":["Documentation"],"responses":{"200":{"description":"OpenAPI specification","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/estimates/{estimateId}/pdf":{"get":{"summary":"Generate PDF document for estimate","description":"Generates a PDF document (прорахунок) for the specified estimate","tags":["Estimates","PDF"],"parameters":[{"in":"path","name":"estimateId","required":true,"schema":{"type":"string"},"description":"Estimate ID"},{"in":"query","name":"format","schema":{"type":"string","enum":["A4","Letter"],"default":"A4"},"description":"PDF page format"},{"in":"query","name":"download","schema":{"type":"boolean","default":true},"description":"Whether to download the PDF or display inline"},{"in":"query","name":"density","schema":{"type":"string","enum":["compact","standard","spacious"],"default":"compact"},"description":"Document layout density"}],"responses":{"200":{"description":"PDF document generated successfully","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"Estimate not found"},"500":{"description":"PDF generation failed"}},"security":[{"BearerAuth":[]}]},"post":{"summary":"Generate PDF with custom options","description":"Generates a PDF document with custom formatting options","tags":["Estimates","PDF"],"parameters":[{"in":"path","name":"estimateId","required":true,"schema":{"type":"string"},"description":"Estimate ID"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"format":{"type":"string","enum":["A4","Letter"],"default":"A4"},"orientation":{"type":"string","enum":["portrait","landscape"],"default":"portrait"},"margin":{"type":"object","properties":{"top":{"type":"string","example":"15mm"},"right":{"type":"string","example":"15mm"},"bottom":{"type":"string","example":"15mm"},"left":{"type":"string","example":"15mm"}}},"printBackground":{"type":"boolean","default":true},"download":{"type":"boolean","default":true},"density":{"type":"string","enum":["compact","standard","spacious"],"default":"compact"}}}}}},"responses":{"200":{"description":"PDF document generated successfully","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Invalid request"},"404":{"description":"Estimate not found"},"500":{"description":"PDF generation failed"}},"security":[{"BearerAuth":[]}]}},"/api/estimates/{estimateId}/preview":{"get":{"summary":"Get PDF preview of estimate document","description":"Returns the same paginated A4 PDF document that will be downloaded, but inline for preview","tags":["Estimates","PDF"],"parameters":[{"in":"path","name":"estimateId","required":true,"schema":{"type":"string"},"description":"Estimate ID"},{"in":"query","name":"density","schema":{"type":"string","enum":["compact","standard","spacious"],"default":"compact"},"description":"Document layout density"}],"responses":{"200":{"description":"PDF preview generated successfully","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"Estimate not found"},"500":{"description":"Preview generation failed"}},"security":[{"BearerAuth":[]}]}},"/api/extension/auth/exchange-code":{"post":{"summary":"Exchange a one-time pairing code for an extension access token","description":"Validates a short-lived pairing code and returns a deviceId + accessToken.","tags":["Extensions"],"security":[],"responses":{"200":{"description":"Exchanged successfully"}}}}},"tags":[{"name":"System","description":"System health and status endpoints"},{"name":"Authentication","description":"User authentication and authorization"},{"name":"Companies","description":"Company management endpoints"},{"name":"Branches","description":"Branch management endpoints"},{"name":"Employees","description":"Employee management endpoints"},{"name":"Cars","description":"Car management endpoints"},{"name":"Clients","description":"Client management endpoints. For client order history, see Orders section."},{"name":"Work Types","description":"Work type management endpoints"},{"name":"Vendors","description":"Vendor management endpoints"},{"name":"Warehouses","description":"Warehouse management endpoints"},{"name":"Orders","description":"Order management endpoints including client order history"},{"name":"Inventory","description":"Inventory management endpoints"},{"name":"Documentation","description":"API documentation endpoints"}]}