src/orders/orders.controller.ts
orders
Methods |
|
| Async assignVehicle |
assignVehicle(id: string, orgId: string, userId: string, body: literal type)
|
Decorators :
@Patch(':id/assign-vehicle')
|
|
Defined in src/orders/orders.controller.ts:153
|
|
Returns :
unknown
|
| Async bulkCreate | ||||||||||||
bulkCreate(orgId: string, userId: string, orders: CreateOrderDto[])
|
||||||||||||
Decorators :
@Post('bulk')
|
||||||||||||
|
Defined in src/orders/orders.controller.ts:59
|
||||||||||||
|
Parameters :
Returns :
unknown
|
| Async bulkSendToJobs |
bulkSendToJobs(orgId: string, userId: string)
|
Decorators :
@Post('bulk-send-to-jobs')
|
|
Defined in src/orders/orders.controller.ts:197
|
|
Returns :
unknown
|
| Async confirmLoading |
confirmLoading(id: string, userId: string, orgId: string, body: literal type)
|
Decorators :
@Patch(':id/confirm-loading')
|
|
Defined in src/orders/orders.controller.ts:123
|
|
Returns :
unknown
|
| Async create | ||||||||||||
create(orgId: string, userId: string, dto: CreateOrderDto)
|
||||||||||||
Decorators :
@Post()
|
||||||||||||
|
Defined in src/orders/orders.controller.ts:48
|
||||||||||||
|
Parameters :
Returns :
unknown
|
| Async findAll | |||||||||
findAll(orgId: string, filters: OrderFilterDto)
|
|||||||||
Decorators :
@Get()
|
|||||||||
|
Defined in src/orders/orders.controller.ts:75
|
|||||||||
|
Parameters :
Returns :
unknown
|
| Async findOne |
findOne(orgId: string, id: string)
|
Decorators :
@Get(':id')
|
|
Defined in src/orders/orders.controller.ts:84
|
|
Returns :
unknown
|
| Async getJobs | ||||||
getJobs(orgId: string)
|
||||||
Decorators :
@Get('jobs/list')
|
||||||
|
Defined in src/orders/orders.controller.ts:134
|
||||||
|
Parameters :
Returns :
unknown
|
| Async getStats | ||||||
getStats(orgId: string)
|
||||||
Decorators :
@Get('stats')
|
||||||
|
Defined in src/orders/orders.controller.ts:69
|
||||||
|
Parameters :
Returns :
unknown
|
| Async remove |
remove(orgId: string, id: string)
|
Decorators :
@Delete(':id')
|
|
Defined in src/orders/orders.controller.ts:111
|
|
Returns :
unknown
|
| Async sendToJobs |
sendToJobs(orgId: string, id: string, userId: string)
|
Decorators :
@Post(':id/send-to-jobs')
|
|
Defined in src/orders/orders.controller.ts:186
|
|
Returns :
unknown
|
| Async update | ||||||||||||||||||
update(orgId: string, id: string, userId: string, role: string, dto: UpdateOrderDto)
|
||||||||||||||||||
Decorators :
@Patch(':id')
|
||||||||||||||||||
|
Defined in src/orders/orders.controller.ts:98
|
||||||||||||||||||
|
Parameters :
Returns :
unknown
|
| Async updateJobStatus |
updateJobStatus(orgId: string, id: string, userId: string, body: literal type)
|
Decorators :
@Patch(':id/job-status')
|
|
Defined in src/orders/orders.controller.ts:141
|
|
Returns :
unknown
|
| Async waiveField | |||||||||||||||||||||
waiveField(orgId: string, id: string, userId: string, firstName: string, lastName: string, body: literal type)
|
|||||||||||||||||||||
Decorators :
@Patch(':id/waive-field')
|
|||||||||||||||||||||
|
Defined in src/orders/orders.controller.ts:165
|
|||||||||||||||||||||
|
Parameters :
Returns :
unknown
|
import {
Controller,
Get,
Post,
Put,
Patch,
Delete,
Body,
Param,
Query,
UseGuards,
} from '@nestjs/common';
import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger';
import { OrdersService } from './orders.service';
import { CreateOrderDto } from './dto/create-order.dto';
import { UpdateOrderDto } from './dto/update-order.dto';
import { OrderFilterDto } from './dto/order-filter.dto';
import { CombinedAuthGuard } from '../auth/guards/combined-auth.guard';
import { RolesGuard } from '../auth/guards/roles.guard';
import { Roles } from '../auth/decorators/roles.decorator';
import { CurrentUser } from '../auth/decorators/current-user.decorator';
/**
* Roles allowed to MUTATE orders. Reads are open to all authenticated
* staff (drivers see only their own via the trips endpoint, not /orders).
*/
const ORDER_WRITERS = [
'SUPER_ADMIN',
'ADMIN',
'OPERATIONS_MANAGER',
'PLANNER',
'DISPATCHER',
'CUSTOMER_SERVICE',
] as const;
const ORDER_DELETERS = ['SUPER_ADMIN', 'ADMIN', 'OPERATIONS_MANAGER'] as const;
@ApiTags('Orders')
@ApiBearerAuth()
@UseGuards(CombinedAuthGuard, RolesGuard)
@Controller('orders')
export class OrdersController {
constructor(private readonly ordersService: OrdersService) {}
@Post()
@Roles(...ORDER_WRITERS)
@ApiOperation({ summary: 'Create a new order' })
async create(
@CurrentUser('organizationId') orgId: string,
@CurrentUser('id') userId: string,
@Body() dto: CreateOrderDto,
) {
return this.ordersService.create(orgId, dto, userId);
}
@Post('bulk')
@Roles(...ORDER_WRITERS)
@ApiOperation({ summary: 'Bulk create orders' })
async bulkCreate(
@CurrentUser('organizationId') orgId: string,
@CurrentUser('id') userId: string,
@Body() orders: CreateOrderDto[],
) {
return this.ordersService.bulkCreate(orgId, orders, userId);
}
@Get('stats')
@ApiOperation({ summary: 'Get order statistics by status' })
async getStats(@CurrentUser('organizationId') orgId: string) {
return this.ordersService.getStats(orgId);
}
@Get()
@ApiOperation({ summary: 'List orders with filtering and pagination' })
async findAll(
@CurrentUser('organizationId') orgId: string,
@Query() filters: OrderFilterDto,
) {
return this.ordersService.findAll(orgId, filters);
}
@Get(':id')
@ApiOperation({ summary: 'Get order by ID (org-scoped)' })
async findOne(
@CurrentUser('organizationId') orgId: string,
@Param('id') id: string,
) {
return this.ordersService.findOne(orgId, id);
}
@Patch(':id')
// Drivers update their assigned orders (status changes) from the
// mobile app. The service enforces driver-self-service rules:
// they can only update orders linked to their own trip and may
// only change a small whitelist of fields.
@Roles(...ORDER_WRITERS, 'DRIVER')
@ApiOperation({ summary: 'Update an order (org-scoped, drivers can change own status)' })
async update(
@CurrentUser('organizationId') orgId: string,
@Param('id') id: string,
@CurrentUser('id') userId: string,
@CurrentUser('role') role: string,
@Body() dto: UpdateOrderDto,
) {
return this.ordersService.update(orgId, id, dto, userId, role);
}
@Delete(':id')
@Roles(...ORDER_DELETERS)
@ApiOperation({ summary: 'Delete an order (blocked when on an active trip)' })
async remove(
@CurrentUser('organizationId') orgId: string,
@Param('id') id: string,
) {
return this.ordersService.remove(orgId, id);
}
@Patch(':id/confirm-loading')
// Drivers need to confirm loading from the mobile app, so they're
// included alongside the writer set.
@Roles(...ORDER_WRITERS, 'DRIVER')
@ApiOperation({ summary: 'Confirm loading — requires GPS location at the loading bay' })
async confirmLoading(
@Param('id') id: string,
@CurrentUser('id') userId: string,
@CurrentUser('organizationId') orgId: string,
@Body() body: { latitude?: number; longitude?: number },
) {
return this.ordersService.confirmLoading(id, userId, orgId, body.latitude, body.longitude);
}
@Get('jobs/list')
@ApiOperation({ summary: 'List orders in job stage (VALIDATED or READY)' })
async getJobs(@CurrentUser('organizationId') orgId: string) {
return this.ordersService.getJobs(orgId);
}
@Patch(':id/job-status')
@Roles(...ORDER_WRITERS)
@ApiOperation({ summary: 'Update job status: PENDING -> VALIDATED -> READY -> ALLOCATED' })
async updateJobStatus(
@CurrentUser('organizationId') orgId: string,
@Param('id') id: string,
@CurrentUser('id') userId: string,
@Body() body: { jobStatus: string },
) {
return this.ordersService.updateJobStatus(orgId, id, body.jobStatus, userId);
}
@Patch(':id/assign-vehicle')
@Roles(...ORDER_WRITERS)
@ApiOperation({ summary: 'Manually assign a vehicle to an order and create a trip' })
async assignVehicle(
@Param('id') id: string,
@CurrentUser('organizationId') orgId: string,
@CurrentUser('id') userId: string,
@Body() body: { vehicleId: string },
) {
return this.ordersService.assignVehicle(id, body.vehicleId, orgId, userId);
}
@Patch(':id/waive-field')
@Roles(...ORDER_WRITERS)
@ApiOperation({ summary: 'Waive a missing field — mark it as intentionally skipped' })
async waiveField(
@CurrentUser('organizationId') orgId: string,
@Param('id') id: string,
@CurrentUser('id') userId: string,
@CurrentUser('firstName') firstName: string,
@CurrentUser('lastName') lastName: string,
@Body() body: { field: string; reason?: string },
) {
return this.ordersService.waiveField(
orgId,
id,
body.field,
userId,
`${firstName || ''} ${lastName || ''}`.trim(),
body.reason,
);
}
@Post(':id/send-to-jobs')
@Roles(...ORDER_WRITERS)
@ApiOperation({ summary: 'Send order to Jobs board — only if all missing fields are filled or waived' })
async sendToJobs(
@CurrentUser('organizationId') orgId: string,
@Param('id') id: string,
@CurrentUser('id') userId: string,
) {
return this.ordersService.sendToJobs(orgId, id, userId);
}
@Post('bulk-send-to-jobs')
@Roles(...ORDER_WRITERS)
@ApiOperation({ summary: 'Send all eligible imported orders to Jobs — rejects orders with unresolved missing data' })
async bulkSendToJobs(
@CurrentUser('organizationId') orgId: string,
@CurrentUser('id') userId: string,
) {
return this.ordersService.bulkSendToJobs(orgId, userId);
}
}