update_cow_list_ui

This commit is contained in:
NYD
2026-01-07 15:13:42 +09:00
parent 0780f2e47c
commit dae3808221
10 changed files with 1081 additions and 502 deletions

View File

@@ -806,7 +806,7 @@ export class AdminService {
}
return true;
} catch (error) {
this.logger.error(`[배치업로드] 데이터 저장 실패 (cowId: ${item.cowId}, testDt: ${item.testDt}): ${error.message}`);
this.logger.error(`[배치업로드] 데이터 저장 실패 (cowId: ${item.cowId}, ${error.message}`);
return false;
}
});

View File

@@ -3,6 +3,8 @@ import { TypeOrmModule } from '@nestjs/typeorm';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { UserModel } from '../user/entities/user.entity';
import { FarmModel } from '../farm/entities/farm.entity';
import { GenomeRequestModel } from '../genome/entities/genome-request.entity';
import { JwtModule } from 'src/common/jwt/jwt.module';
import { EmailModule } from 'src/shared/email/email.module';
import { VerificationModule } from 'src/shared/verification/verification.module';
@@ -13,7 +15,7 @@ import { VerificationModule } from 'src/shared/verification/verification.module'
*/
@Module({
imports: [
TypeOrmModule.forFeature([UserModel]),
TypeOrmModule.forFeature([UserModel, FarmModel, GenomeRequestModel]),
JwtModule,
EmailModule,
VerificationModule,

View File

@@ -7,7 +7,9 @@ import {
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { UserModel } from '../user/entities/user.entity';
import { Repository } from 'typeorm';
import { FarmModel } from '../farm/entities/farm.entity';
import { GenomeRequestModel } from '../genome/entities/genome-request.entity';
import { Repository, IsNull } from 'typeorm';
import { LoginDto } from './dto/login.dto';
import { LoginResponseDto } from './dto/login-response.dto';
import { SignupDto } from './dto/signup.dto';
@@ -36,6 +38,10 @@ export class AuthService {
constructor(
@InjectRepository(UserModel)
private readonly userRepository: Repository<UserModel>,
@InjectRepository(FarmModel)
private readonly farmRepository: Repository<FarmModel>,
@InjectRepository(GenomeRequestModel)
private readonly genomeRequestRepository: Repository<GenomeRequestModel>,
private readonly emailService: EmailService,
private readonly verificationService: VerificationService,
private readonly jwtService: JwtService,
@@ -78,7 +84,10 @@ export class AuthService {
const accessToken = this.jwtService.sign(payload as any);
this.logger.log(`[LOGIN] 로그인 성공 - userId: ${userId}`);
// 최근 검사 년도 조회
const defaultAnalysisYear = await this.getDefaultAnalysisYear(user.pkUserNo);
this.logger.log(`[LOGIN] 로그인 성공 - userId: ${userId}, defaultAnalysisYear: ${defaultAnalysisYear}`);
return {
message: '로그인 성공',
@@ -90,9 +99,61 @@ export class AuthService {
userEmail: user.userEmail,
userRole: user.userRole || 'USER',
},
defaultAnalysisYear,
};
}
/**
* 사용자의 최근 검사 년도 조회
* @param userNo - 사용자 번호
* @returns 최근 검사 년도 (없으면 현재 년도)
*/
private async getDefaultAnalysisYear(userNo: number): Promise<number> {
try {
// 1. 사용자의 농장 번호 조회
const farm = await this.farmRepository.findOne({
where: { fkUserNo: userNo, delDt: IsNull() },
select: ['pkFarmNo'],
});
if (!farm) {
this.logger.log(`[getDefaultAnalysisYear] userNo: ${userNo}, No farm found, returning current year`);
return new Date().getFullYear();
}
// 2. 농장의 검사 이력에서 최신 날짜 조회
const result = await this.genomeRequestRepository
.createQueryBuilder('request')
.select('MAX(request.chipReportDt)', 'maxChipDt')
.addSelect('MAX(request.msReportDt)', 'maxMsDt')
.where('request.fkFarmNo = :farmNo', { farmNo: farm.pkFarmNo })
.andWhere('request.delDt IS NULL')
.getRawOne();
const maxChipDt = result?.maxChipDt ? new Date(result.maxChipDt) : null;
const maxMsDt = result?.maxMsDt ? new Date(result.maxMsDt) : null;
// 둘 중 최신 날짜 선택
let latestDate: Date | null = null;
if (maxChipDt && maxMsDt) {
latestDate = maxChipDt > maxMsDt ? maxChipDt : maxMsDt;
} else if (maxChipDt) {
latestDate = maxChipDt;
} else if (maxMsDt) {
latestDate = maxMsDt;
}
const year = latestDate ? latestDate.getFullYear() : new Date().getFullYear();
this.logger.log(`[getDefaultAnalysisYear] userNo: ${userNo}, farmNo: ${farm.pkFarmNo}, maxChipDt: ${maxChipDt?.toISOString()}, maxMsDt: ${maxMsDt?.toISOString()}, year: ${year}`);
return year;
} catch (error) {
this.logger.error(`[getDefaultAnalysisYear] Error: ${error.message}`);
return new Date().getFullYear();
}
}
/**
* 회원가입
*/

View File

@@ -11,4 +11,5 @@ export class LoginResponseDto {
userEmail: string;
userRole: 'USER' | 'ADMIN';
};
defaultAnalysisYear: number; // 최근 검사 년도
}

View File

@@ -115,6 +115,16 @@ export class GenomeController {
return this.genomeService.getYearlyTraitTrend(+farmNo, category, traitName);
}
/**
* GET /genome/latest-analysis-year/:farmNo
* 농장의 가장 최근 분석 연도 조회 (chip_report_dt 또는 ms_report_dt 기준)
* @param farmNo - 농장 번호
*/
@Get('latest-analysis-year/:farmNo')
getLatestAnalysisYear(@Param('farmNo') farmNo: string) {
return this.genomeService.getLatestAnalysisYear(+farmNo);
}
/**
* GET /genome/:cowId
* cowId(개체식별번호)로 유전체 데이터 조회

View File

@@ -1874,4 +1874,69 @@ export class GenomeService {
},
};
}
/**
* 농장의 가장 최근 분석 연도 조회
* chip_report_dt 또는 ms_report_dt 중 가장 최근 날짜의 년도 반환
* 둘 다 없으면 현재 년도 반환
*
* @param farmNo - 농장 번호
* @returns { year: number } - 가장 최근 분석 연도
*/
async getLatestAnalysisYear(farmNo: number): Promise<{ year: number }> {
console.log(`[getLatestAnalysisYear] farmNo: ${farmNo}`);
// 농장의 모든 분석 의뢰 조회
const requests = await this.genomeRequestRepository.find({
where: { fkFarmNo: farmNo, delDt: IsNull() },
select: ['chipReportDt', 'msReportDt'],
});
console.log(`[getLatestAnalysisYear] Found ${requests?.length || 0} requests`);
if (!requests || requests.length === 0) {
console.log('[getLatestAnalysisYear] No requests found, returning current year');
return { year: new Date().getFullYear() };
}
// chip_report_dt와 ms_report_dt 중 가장 최근 날짜 찾기
let latestDate: Date | null = null;
let latestChipDate: Date | null = null;
let latestMsDate: Date | null = null;
for (const request of requests) {
// chip_report_dt 확인
if (request.chipReportDt) {
const chipDate = new Date(request.chipReportDt);
if (!latestChipDate || chipDate > latestChipDate) {
latestChipDate = chipDate;
}
if (!latestDate || chipDate > latestDate) {
latestDate = chipDate;
}
}
// ms_report_dt 확인
if (request.msReportDt) {
const msDate = new Date(request.msReportDt);
if (!latestMsDate || msDate > latestMsDate) {
latestMsDate = msDate;
}
if (!latestDate || msDate > latestDate) {
latestDate = msDate;
}
}
}
console.log(`[getLatestAnalysisYear] Latest chip_report_dt: ${latestChipDate?.toISOString()}`);
console.log(`[getLatestAnalysisYear] Latest ms_report_dt: ${latestMsDate?.toISOString()}`);
console.log(`[getLatestAnalysisYear] Latest date overall: ${latestDate?.toISOString()}`);
// 가장 최근 날짜가 있으면 그 연도, 없으면 현재 연도
const year = latestDate ? latestDate.getFullYear() : new Date().getFullYear();
console.log(`[getLatestAnalysisYear] Returning year: ${year}`);
return { year };
}
}