Files
edr-platform/apps/edr-freight-api/src/modules/dropdown-settings/dropdown-settings.service.ts
2026-05-23 10:52:31 +03:00

204 lines
5.1 KiB
TypeScript

import {
ConflictException,
Inject,
Injectable,
NotFoundException,
} from "@nestjs/common";
import { CreateDropdownOptionDto } from "./dto/create-dropdown-option.dto";
import { CreateDropdownSettingDto } from "./dto/create-dropdown-setting.dto";
import { UpdateDropdownOptionDto } from "./dto/update-dropdown-option.dto";
import { UpdateDropdownSettingDto } from "./dto/update-dropdown-setting.dto";
import { DropdownOption } from "./entities/dropdown-option.entity";
import { DropdownSetting } from "./entities/dropdown-setting.entity";
import {
DROPDOWN_SETTINGS_REPOSITORY,
IDropdownSettingsRepository,
} from "./interfaces/dropdown-settings.repository.interface";
const STATIONS_TER_CODE = "stations_ter";
const DEFAULT_STATION_OPTIONS: CreateDropdownOptionDto[] = [
{
value: "inside_addis_ababa",
label: "Addis Ababa",
note: "Inside country",
order: 1,
},
{
value: "inside_adama",
label: "Adama",
note: "Inside country",
order: 2,
},
{
value: "inside_mojo",
label: "Mojo",
note: "Inside country",
order: 3,
},
{
value: "inside_awash",
label: "Awash",
note: "Inside country",
order: 4,
},
{
value: "inside_mieso",
label: "Mieso",
note: "Inside country",
order: 5,
},
{
value: "inside_dire_dawa",
label: "Dire Dawa",
note: "Inside country",
order: 6,
},
{
value: "outside_ali_sabieh",
label: "Ali Sabieh",
note: "Outside country",
order: 7,
},
{
value: "outside_holhol",
label: "Holhol",
note: "Outside country",
order: 8,
},
{
value: "outside_djibouti_city",
label: "Djibouti City",
note: "Outside country",
order: 9,
},
{
value: "outside_doraleh_terminal",
label: "Doraleh Terminal",
note: "Outside country",
order: 10,
},
];
@Injectable()
export class DropdownSettingsService {
constructor(
@Inject(DROPDOWN_SETTINGS_REPOSITORY)
private readonly repository: IDropdownSettingsRepository,
) {}
list(): Promise<DropdownSetting[]> {
return this.repository.findAll();
}
async getById(id: string): Promise<DropdownSetting> {
const setting = await this.repository.findById(id);
if (!setting) throw new NotFoundException(`Setting ${id} not found`);
return setting;
}
async getByCode(code: string): Promise<DropdownSetting> {
const setting = await this.repository.findByCode(code);
if (!setting) throw new NotFoundException(`Setting "${code}" not found`);
return setting;
}
async create(dto: CreateDropdownSettingDto): Promise<DropdownSetting> {
const existing = await this.repository.findByCode(dto.code);
if (existing) {
throw new ConflictException(
`Dropdown setting with code "${dto.code}" already exists`,
);
}
const setting = await this.repository.create({
code: dto.code,
label: dto.label,
description: dto.description ?? null,
multiple: dto.multiple ?? false,
meta: dto.meta ?? null,
});
if (dto.children && dto.children.length > 0) {
await this.repository.replaceOptions(setting.id, dto.children);
}
return this.getById(setting.id);
}
async seedDefaultStations(): Promise<void> {
const existing = await this.repository.findByCode(STATIONS_TER_CODE);
if (!existing) {
await this.create({
code: STATIONS_TER_CODE,
label: "Stations TER",
description:
"Temporary freight station list used by booking origin and destination yards.",
multiple: false,
meta: {
searchable: true,
clearable: true,
version: "temporary",
},
children: DEFAULT_STATION_OPTIONS,
});
return;
}
if ((existing.children?.length ?? 0) === 0) {
await this.repository.replaceOptions(
existing.id,
DEFAULT_STATION_OPTIONS,
);
}
}
async update(
id: string,
dto: UpdateDropdownSettingDto,
): Promise<DropdownSetting> {
await this.getById(id);
const updated = await this.repository.update(id, dto);
if (!updated) throw new NotFoundException(`Setting ${id} not found`);
return this.getById(id);
}
async remove(id: string): Promise<void> {
await this.getById(id);
await this.repository.softDelete(id);
}
/* ------------------------ option operations ------------------------ */
async replaceOptions(
settingId: string,
options: CreateDropdownOptionDto[],
): Promise<DropdownOption[]> {
await this.getById(settingId);
return this.repository.replaceOptions(settingId, options);
}
async addOption(
settingId: string,
dto: CreateDropdownOptionDto,
): Promise<DropdownOption> {
await this.getById(settingId);
return this.repository.addOption(settingId, dto);
}
async updateOption(
optionId: string,
dto: UpdateDropdownOptionDto,
): Promise<DropdownOption> {
const updated = await this.repository.updateOption(optionId, dto);
if (!updated) throw new NotFoundException(`Option ${optionId} not found`);
return updated;
}
async removeOption(optionId: string): Promise<void> {
await this.repository.removeOption(optionId);
}
}