File

src/orders/ingestion/ingestion.controller.ts

Prefix

ingestions

Index

Methods

Methods

Async approve
approve(id: string, userId: string)
Decorators :
@Post(':id/approve')
@ApiOperation({summary: 'Approve ingestion and create orders from extracted data'})
Parameters :
Name Type Optional
id string No
userId string No
Returns : unknown
Async autoAllocate
autoAllocate(orgId: string)
Decorators :
@Post('auto-allocate')
@ApiOperation({summary: 'Re-run auto-allocation on all unallocated orders', description: 'Finds orders without trucks, registers new vehicles from Excel plates, and assigns them using route balancing + zone permits.'})
Parameters :
Name Type Optional
orgId string No
Returns : unknown
Async deleteRule
deleteRule(id: string)
Decorators :
@Delete('allocation-rules/:id')
@ApiOperation({summary: 'Delete an allocation rule'})
Parameters :
Name Type Optional
id string No
Returns : unknown
Async findOne
findOne(id: string)
Decorators :
@Get(':id')
@ApiOperation({summary: 'Get ingestion details by ID'})
Parameters :
Name Type Optional
id string No
Returns : unknown
Async getActiveRule
getActiveRule(orgId: string)
Decorators :
@Get('allocation-rules/active')
@ApiOperation({summary: 'Get the active allocation rule'})
Parameters :
Name Type Optional
orgId string No
Returns : unknown
Async list
list(orgId: string, query: literal type)
Decorators :
@Get()
@ApiOperation({summary: 'List ingestions for the organization'})
Parameters :
Name Type Optional
orgId string No
query literal type No
Returns : unknown
Async listRules
listRules(orgId: string)
Decorators :
@Get('allocation-rules')
@ApiOperation({summary: 'List allocation rules'})
Parameters :
Name Type Optional
orgId string No
Returns : unknown
Async reject
reject(id: string, reason: string)
Decorators :
@Post(':id/reject')
@ApiOperation({summary: 'Reject an ingestion'})
Parameters :
Name Type Optional
id string No
reason string No
Returns : unknown
Async resetRules
resetRules(orgId: string)
Decorators :
@Post('allocation-rules/reset')
@ApiOperation({summary: 'Reset to default allocation rule'})
Parameters :
Name Type Optional
orgId string No
Returns : unknown
Async upload
upload(file: Express.Multer.File, clientId: string, orgId: string, userId: string)
Decorators :
@Post('upload')
@ApiOperation({summary: 'Upload Excel/CSV file for AI-powered order extraction'})
@ApiConsumes('multipart/form-data')
@UseInterceptors(undefined)
Parameters :
Name Type Optional
file Express.Multer.File No
clientId string No
orgId string No
userId string No
Returns : unknown
Async upsertRule
upsertRule(orgId: string, body: Record)
Decorators :
@Post('allocation-rules')
@ApiOperation({summary: 'Create or update an allocation rule'})
Parameters :
Name Type Optional
orgId string No
body Record<string | any> No
Returns : unknown
import {
  Controller,
  Post,
  Get,
  Patch,
  Delete,
  Param,
  Query,
  Body,
  UseGuards,
  UseInterceptors,
  UploadedFile,
  BadRequestException,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { ApiTags, ApiBearerAuth, ApiOperation, ApiConsumes } from '@nestjs/swagger';
import { JwtAuthGuard } from '../../auth/guards/jwt-auth.guard';
import { RolesGuard } from '../../auth/guards/roles.guard';
import { CurrentUser } from '../../auth/decorators/current-user.decorator';
import { IngestionService } from './ingestion.service';
import { AllocationRulesService } from './allocation/allocation-rules.service';

const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10 MB

@ApiTags('Ingestions')
@ApiBearerAuth()
@UseGuards(JwtAuthGuard, RolesGuard)
@Controller('ingestions')
export class IngestionController {
  constructor(
    private readonly ingestionService: IngestionService,
    private readonly allocationRulesService: AllocationRulesService,
  ) {}

  @Post('upload')
  @ApiOperation({ summary: 'Upload Excel/CSV file for AI-powered order extraction' })
  @ApiConsumes('multipart/form-data')
  @UseInterceptors(
    FileInterceptor('file', {
      storage: undefined, // Use memory storage (default)
      limits: { fileSize: MAX_FILE_SIZE },
      fileFilter: (_req, file, cb) => {
        const allowed = [
          'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
          'application/vnd.ms-excel',
          'text/csv',
          'application/csv',
        ];
        const ext = file.originalname.toLowerCase();
        if (
          allowed.includes(file.mimetype) ||
          ext.endsWith('.xlsx') ||
          ext.endsWith('.xls') ||
          ext.endsWith('.csv')
        ) {
          cb(null, true);
        } else {
          cb(
            new BadRequestException(
              `Unsupported file type "${file.mimetype}". Upload .xlsx, .xls, or .csv files.`,
            ),
            false,
          );
        }
      },
    }),
  )
  async upload(
    @UploadedFile() file: Express.Multer.File,
    @Body('clientId') clientId: string,
    @CurrentUser('organizationId') orgId: string,
    @CurrentUser('id') userId: string,
  ) {
    if (!file) {
      throw new BadRequestException('No file uploaded. Attach a file with field name "file".');
    }
    return this.ingestionService.processUpload(file, clientId || null, orgId, userId);
  }

  @Get()
  @ApiOperation({ summary: 'List ingestions for the organization' })
  async list(
    @CurrentUser('organizationId') orgId: string,
    @Query() query: { status?: string; page?: string; limit?: string },
  ) {
    return this.ingestionService.findAll(orgId, query);
  }

  @Get(':id')
  @ApiOperation({ summary: 'Get ingestion details by ID' })
  async findOne(@Param('id') id: string) {
    return this.ingestionService.findOne(id);
  }

  @Post(':id/approve')
  @ApiOperation({ summary: 'Approve ingestion and create orders from extracted data' })
  async approve(
    @Param('id') id: string,
    @CurrentUser('id') userId: string,
  ) {
    return this.ingestionService.approveIngestion(id, userId);
  }

  @Post(':id/reject')
  @ApiOperation({ summary: 'Reject an ingestion' })
  async reject(
    @Param('id') id: string,
    @Body('reason') reason: string,
  ) {
    return this.ingestionService.rejectIngestion(id, reason);
  }

  @Post('auto-allocate')
  @ApiOperation({
    summary: 'Re-run auto-allocation on all unallocated orders',
    description: 'Finds orders without trucks, registers new vehicles from Excel plates, and assigns them using route balancing + zone permits.',
  })
  async autoAllocate(
    @CurrentUser('organizationId') orgId: string,
  ) {
    return this.ingestionService.autoAllocateOrders(orgId);
  }

  // ── Allocation Rules ──────────────────────────────

  @Get('allocation-rules')
  @ApiOperation({ summary: 'List allocation rules' })
  async listRules(@CurrentUser('organizationId') orgId: string) {
    return this.allocationRulesService.findAll(orgId);
  }

  @Get('allocation-rules/active')
  @ApiOperation({ summary: 'Get the active allocation rule' })
  async getActiveRule(@CurrentUser('organizationId') orgId: string) {
    return this.allocationRulesService.getActiveRule(orgId);
  }

  @Post('allocation-rules')
  @ApiOperation({ summary: 'Create or update an allocation rule' })
  async upsertRule(
    @CurrentUser('organizationId') orgId: string,
    @Body() body: Record<string, any>,
  ) {
    return this.allocationRulesService.upsert(orgId, body);
  }

  @Delete('allocation-rules/:id')
  @ApiOperation({ summary: 'Delete an allocation rule' })
  async deleteRule(@Param('id') id: string) {
    return this.allocationRulesService.remove(id);
  }

  @Post('allocation-rules/reset')
  @ApiOperation({ summary: 'Reset to default allocation rule' })
  async resetRules(@CurrentUser('organizationId') orgId: string) {
    return this.allocationRulesService.resetToDefault(orgId);
  }
}

results matching ""

    No results matching ""