import { BaseRepository } from "@edr/api-common"; import { PaginatedResponse } from "@edr/types"; import { Injectable } from "@nestjs/common"; import { InjectRepository } from "@nestjs/typeorm"; import { Repository } from "typeorm"; import { paginateQuery } from "../../common/utils/pagination.util"; import { ListDropdownSettingsQueryDto } from "./dto/list-dropdown-settings-query.dto"; import { DropdownOption } from "./entities/dropdown-option.entity"; import { DropdownSetting } from "./entities/dropdown-setting.entity"; import type { IDropdownSettingsRepository } from "./interfaces/dropdown-settings.repository.interface"; @Injectable() export class DropdownSettingsRepository extends BaseRepository implements IDropdownSettingsRepository { constructor( @InjectRepository(DropdownSetting) repository: Repository, @InjectRepository(DropdownOption) private readonly optionsRepository: Repository, ) { super(repository); } findByCode(code: string): Promise { return this.repository.findOne({ where: { code }, relations: { children: true }, order: { children: { order: "ASC" } }, }); } override findById(id: string): Promise { return this.repository.findOne({ where: { id }, relations: { children: true }, order: { children: { order: "ASC" } }, }); } override findAll(): Promise { return this.repository.find({ order: { label: "ASC", children: { order: "ASC" } }, relations: { children: true }, }); } findPaged( query: ListDropdownSettingsQueryDto, ): Promise> { // Soft-deleted rows are excluded automatically by the query builder // (BaseEntity's deletedAt column). Ordering mirrors findAll (label ASC). const qb = this.repository .createQueryBuilder("setting") .leftJoinAndSelect("setting.children", "option") .orderBy("setting.label", query.sortOrder ?? "ASC") .addOrderBy("option.order", "ASC"); if (query.search) { qb.andWhere( "(setting.code ILIKE :search OR setting.label ILIKE :search OR setting.description ILIKE :search)", { search: `%${query.search}%` }, ); } return paginateQuery(qb, query); } async replaceOptions( settingId: string, options: Array>, ): Promise { await this.optionsRepository.delete({ settingId }); if (options.length === 0) return []; const entities = options.map((o, idx) => this.optionsRepository.create({ ...o, settingId, order: o.order ?? idx + 1, }), ); return this.optionsRepository.save(entities); } async addOption( settingId: string, option: Partial, ): Promise { const entity = this.optionsRepository.create({ ...option, settingId }); return this.optionsRepository.save(entity); } async updateOption( optionId: string, data: Partial, ): Promise { await this.optionsRepository.update(optionId, data as never); return this.optionsRepository.findOne({ where: { id: optionId } }); } async removeOption(optionId: string): Promise { await this.optionsRepository.softDelete(optionId); } }