model-config.service.ts 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // server/src/model-config/model-config.service.ts
  2. import { Injectable, NotFoundException, ForbiddenException } from '@nestjs/common';
  3. import { InjectRepository } from '@nestjs/typeorm';
  4. import { Repository } from 'typeorm';
  5. import { ModelConfig } from './model-config.entity';
  6. import { CreateModelConfigDto } from './dto/create-model-config.dto';
  7. import { UpdateModelConfigDto } from './dto/update-model-config.dto';
  8. import { User } from '../user/user.entity';
  9. @Injectable()
  10. export class ModelConfigService {
  11. constructor(
  12. @InjectRepository(ModelConfig)
  13. private modelConfigRepository: Repository<ModelConfig>,
  14. ) { }
  15. async create(
  16. userId: string,
  17. tenantId: string,
  18. createModelConfigDto: CreateModelConfigDto,
  19. ): Promise<ModelConfig> {
  20. const modelConfig = this.modelConfigRepository.create({
  21. ...createModelConfigDto,
  22. userId,
  23. tenantId,
  24. });
  25. return this.modelConfigRepository.save(modelConfig);
  26. }
  27. async findAll(userId: string, tenantId: string): Promise<ModelConfig[]> {
  28. return this.modelConfigRepository.createQueryBuilder('model')
  29. .where('model.tenantId = :tenantId OR model.tenantId IS NULL', { tenantId })
  30. .getMany();
  31. }
  32. async findOne(id: string, userId: string, tenantId: string): Promise<ModelConfig> {
  33. const modelConfig = await this.modelConfigRepository.createQueryBuilder('model')
  34. .where('model.id = :id', { id })
  35. .andWhere('(model.tenantId = :tenantId OR model.tenantId IS NULL)', { tenantId })
  36. .getOne();
  37. if (!modelConfig) {
  38. throw new NotFoundException(
  39. `ModelConfig with ID "${id}" not found.`,
  40. );
  41. }
  42. return modelConfig;
  43. }
  44. async findByType(userId: string, tenantId: string, type: string): Promise<ModelConfig[]> {
  45. return this.modelConfigRepository.createQueryBuilder('model')
  46. .where('model.type = :type', { type })
  47. .andWhere('(model.tenantId = :tenantId OR model.tenantId IS NULL)', { tenantId })
  48. .getMany();
  49. }
  50. async update(
  51. userId: string,
  52. tenantId: string,
  53. id: string,
  54. updateModelConfigDto: UpdateModelConfigDto,
  55. ): Promise<ModelConfig> {
  56. const modelConfig = await this.findOne(id, userId, tenantId);
  57. if (!modelConfig) {
  58. throw new NotFoundException(
  59. `ModelConfig with ID "${id}" not found.`,
  60. );
  61. }
  62. // Only allow updating if it belongs to the tenant, or if it's a global admin (not fully implemented, so we check tenantId)
  63. if (modelConfig.tenantId && modelConfig.tenantId !== tenantId) {
  64. throw new ForbiddenException('Cannot update models from another tenant');
  65. }
  66. // Update the model
  67. const updated = this.modelConfigRepository.merge(
  68. modelConfig,
  69. updateModelConfigDto,
  70. );
  71. return this.modelConfigRepository.save(updated);
  72. }
  73. async remove(userId: string, tenantId: string, id: string): Promise<void> {
  74. // Only allow removing if it exists and accessible in current tenant context
  75. const model = await this.findOne(id, userId, tenantId);
  76. if (model.tenantId && model.tenantId !== tenantId) {
  77. throw new ForbiddenException('Cannot delete models from another tenant');
  78. }
  79. const result = await this.modelConfigRepository.delete({ id });
  80. if (result.affected === 0) {
  81. throw new NotFoundException(`ModelConfig with ID "${id}" not found.`);
  82. }
  83. }
  84. /**
  85. * 指定されたモデルをデフォルトに設定
  86. */
  87. async setDefault(userId: string, tenantId: string, id: string): Promise<ModelConfig> {
  88. const modelConfig = await this.findOne(id, userId, tenantId);
  89. // 同じタイプの他のモデルのデフォルトフラグをクリア (現在のテナント内またはglobal)
  90. // 厳密には、現在のテナントのIsDefault設定といった方が正しいですが、シンプルにするため全体のIsDefaultを操作します
  91. await this.modelConfigRepository
  92. .createQueryBuilder()
  93. .update(ModelConfig)
  94. .set({ isDefault: false })
  95. .where('type = :type', { type: modelConfig.type })
  96. .andWhere('(tenantId = :tenantId OR tenantId IS NULL)', { tenantId })
  97. .execute();
  98. modelConfig.isDefault = true;
  99. return this.modelConfigRepository.save(modelConfig);
  100. }
  101. /**
  102. * 指定されたタイプのデフォルトモデルを取得
  103. * テナント固有のデフォルトを優先、なければグローバル
  104. */
  105. async findDefaultByType(tenantId: string, type: string): Promise<ModelConfig | null> {
  106. const models = await this.modelConfigRepository.createQueryBuilder('model')
  107. .where('model.type = :type', { type })
  108. .andWhere('model.isDefault = :isDefault', { isDefault: true })
  109. .andWhere('model.isEnabled = :isEnabled', { isEnabled: true })
  110. .andWhere('(model.tenantId = :tenantId OR model.tenantId IS NULL)', { tenantId })
  111. .orderBy('model.tenantId', 'DESC') // Null will be last in most DBs, or we can fetch all and rank in JS
  112. .getMany();
  113. // Prefer tenant specific model over global
  114. const tenantModel = models.find(m => m.tenantId === tenantId);
  115. return tenantModel || models[0] || null;
  116. }
  117. }