File

src/orders/ingestion/allocation/allocation-rules.service.ts

Index

Methods

Constructor

constructor(prisma: PrismaService)
Parameters :
Name Type Optional
prisma PrismaService No

Methods

Async findAll
findAll(organizationId: string)
Parameters :
Name Type Optional
organizationId string No
Returns : unknown
Async getActiveRule
getActiveRule(organizationId: string)

Get the active rule for the org, or return defaults

Parameters :
Name Type Optional
organizationId string No
Returns : unknown
Async remove
remove(id: string)
Parameters :
Name Type Optional
id string No
Returns : unknown
Async resetToDefault
resetToDefault(organizationId: string)
Parameters :
Name Type Optional
organizationId string No
Returns : unknown
Async upsert
upsert(organizationId: string, data: unknown)
Parameters :
Name Type Optional
organizationId string No
data unknown No
Returns : unknown
import { Injectable, NotFoundException, Logger } from '@nestjs/common';
import { PrismaService } from '../../../prisma/prisma.service';

const DEFAULT_RULE = {
  name: 'Default Allocation Rule',
  description: 'Zone permits, route balancing, capacity matching, load balancing, idle time preference',
  isDefault: true,
  isActive: true,
  priority: 0,
  zonePermitWeight: 50,
  zonePermitPenalty: 30,
  routeBalanceBonus: 30,
  routeBalancePenalty: 20,
  capacityOverPenalty: 500,
  loadBalanceFactor: 0.5,
  batchPenalty: 10,
  availableBonus: 20,
  idleTimeMaxBonus: 20,
  maxOrdersPerTruck: 3,
  onlyAvailableVehicles: true,
  respectZonePermits: true,
  enableRouteBalancing: true,
};

@Injectable()
export class AllocationRulesService {
  private readonly logger = new Logger(AllocationRulesService.name);

  constructor(private readonly prisma: PrismaService) {}

  /** Get the active rule for the org, or return defaults */
  async getActiveRule(organizationId: string) {
    const rule = await this.prisma.allocationRule.findFirst({
      where: { organizationId, isActive: true },
      orderBy: { priority: 'desc' },
    });
    if (rule) return rule;

    // Return virtual default (not persisted until user modifies)
    return { id: null, organizationId, ...DEFAULT_RULE };
  }

  async findAll(organizationId: string) {
    const rules = await this.prisma.allocationRule.findMany({
      where: { organizationId },
      orderBy: { priority: 'desc' },
    });
    if (rules.length === 0) {
      return [{ id: null, organizationId, ...DEFAULT_RULE }];
    }
    return rules;
  }

  async upsert(organizationId: string, data: Partial<typeof DEFAULT_RULE> & { id?: string | null }) {
    const { id, ...rest } = data;

    if (id) {
      // Update existing
      const rule = await this.prisma.allocationRule.findUnique({ where: { id } });
      if (!rule) throw new NotFoundException('Allocation rule not found');
      return this.prisma.allocationRule.update({ where: { id }, data: rest });
    }

    // Create — if this is the first rule, make it active + default
    const existing = await this.prisma.allocationRule.findFirst({
      where: { organizationId },
    });

    return this.prisma.allocationRule.create({
      data: {
        organizationId,
        isDefault: !existing,
        isActive: true,
        ...rest,
        name: rest.name || 'Custom Allocation Rule',
      },
    });
  }

  async remove(id: string) {
    const rule = await this.prisma.allocationRule.findUnique({ where: { id } });
    if (!rule) throw new NotFoundException('Allocation rule not found');
    if (rule.isDefault) {
      // Can't delete default — just deactivate
      return this.prisma.allocationRule.update({ where: { id }, data: { isActive: false } });
    }
    await this.prisma.allocationRule.delete({ where: { id } });
    return { deleted: true };
  }

  async resetToDefault(organizationId: string) {
    // Delete all custom rules and create a fresh default
    await this.prisma.allocationRule.deleteMany({ where: { organizationId } });
    return this.prisma.allocationRule.create({
      data: { organizationId, ...DEFAULT_RULE },
    });
  }
}

results matching ""

    No results matching ""