mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
Bulk contract templates are now unique per (cargo type, trade direction, customs option) instead of (cargo type, customs option). Intercity is domestic and crosses no border, so it carries no customs variant: with_customs stays null there, enforced by a check constraint. Contract resolution already passed the trade direction through but the bulk lookup dropped it, so one template served all three directions. Container templates are unchanged — cargo_type_id is null on those rows, which keeps them out of both the new index and the constraint. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
83 lines
2.5 KiB
TypeScript
83 lines
2.5 KiB
TypeScript
import { BaseRepository } from "@edr/api-common";
|
|
import { Injectable } from "@nestjs/common";
|
|
import { InjectRepository } from "@nestjs/typeorm";
|
|
import { IsNull, Repository } from "typeorm";
|
|
|
|
import { CargoType } from "../rule-engine/entities/cargo-type.entity";
|
|
import {
|
|
BulkTemplateDirection,
|
|
ContractTemplate,
|
|
} from "./entities/contract-template.entity";
|
|
|
|
@Injectable()
|
|
export class ContractTemplatesRepository extends BaseRepository<ContractTemplate> {
|
|
constructor(
|
|
@InjectRepository(ContractTemplate)
|
|
repository: Repository<ContractTemplate>,
|
|
) {
|
|
super(repository);
|
|
}
|
|
|
|
findByCode(code: string): Promise<ContractTemplate | null> {
|
|
return this.repository.findOne({ where: { code } });
|
|
}
|
|
|
|
override findAll(): Promise<ContractTemplate[]> {
|
|
return this.repository.find({
|
|
relations: { cargoType: true },
|
|
order: { code: "ASC" },
|
|
});
|
|
}
|
|
|
|
findByCargoCombo(
|
|
cargoTypeId: string,
|
|
tradeDirection: BulkTemplateDirection,
|
|
withCustoms: boolean | null,
|
|
): Promise<ContractTemplate | null> {
|
|
return this.repository.findOne({
|
|
where: { cargoTypeId, tradeDirection, withCustoms: withCustoms ?? IsNull() },
|
|
});
|
|
}
|
|
|
|
/**
|
|
* The active bulk template covering this cargo type: written against the
|
|
* cargo type itself or against its parent group (the two are mutually
|
|
* exclusive, so at most one row matches). Intercity templates carry no
|
|
* customs variant, so they are matched on a null flag.
|
|
*/
|
|
findActiveBulkTemplate(
|
|
cargoTypeId: string,
|
|
tradeDirection: BulkTemplateDirection,
|
|
withCustoms: boolean | null,
|
|
): Promise<ContractTemplate | null> {
|
|
return this.repository
|
|
.createQueryBuilder("t")
|
|
.where("t.is_active = true")
|
|
.andWhere("t.trade_direction = :tradeDirection", { tradeDirection })
|
|
.andWhere(
|
|
withCustoms === null
|
|
? "t.with_customs IS NULL"
|
|
: "t.with_customs = :withCustoms",
|
|
withCustoms === null ? {} : { withCustoms },
|
|
)
|
|
.andWhere(
|
|
`(t.cargo_type_id = :cargoTypeId OR t.cargo_type_id = (
|
|
SELECT c.parent_group_id FROM freight.cargo_types c
|
|
WHERE c.id = :cargoTypeId AND c.deleted_at IS NULL
|
|
))`,
|
|
{ cargoTypeId },
|
|
)
|
|
.getOne();
|
|
}
|
|
|
|
findCargoType(id: string): Promise<CargoType | null> {
|
|
return this.repository.manager
|
|
.getRepository(CargoType)
|
|
.findOne({ where: { id } });
|
|
}
|
|
|
|
async saveTemplate(template: ContractTemplate): Promise<ContractTemplate> {
|
|
return this.repository.save(template);
|
|
}
|
|
}
|