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 { return this.repository.findAll(); } async getById(id: string): Promise { const setting = await this.repository.findById(id); if (!setting) throw new NotFoundException(`Setting ${id} not found`); return setting; } async getByCode(code: string): Promise { const setting = await this.repository.findByCode(code); if (!setting) throw new NotFoundException(`Setting "${code}" not found`); return setting; } async create(dto: CreateDropdownSettingDto): Promise { 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 { 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 { 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 { await this.getById(id); await this.repository.softDelete(id); } /* ------------------------ option operations ------------------------ */ async replaceOptions( settingId: string, options: CreateDropdownOptionDto[], ): Promise { await this.getById(settingId); return this.repository.replaceOptions(settingId, options); } async addOption( settingId: string, dto: CreateDropdownOptionDto, ): Promise { await this.getById(settingId); return this.repository.addOption(settingId, dto); } async updateOption( optionId: string, dto: UpdateDropdownOptionDto, ): Promise { const updated = await this.repository.updateOption(optionId, dto); if (!updated) throw new NotFoundException(`Option ${optionId} not found`); return updated; } async removeOption(optionId: string): Promise { await this.repository.removeOption(optionId); } }