edit status of tenders
This commit is contained in:
@@ -88,6 +88,50 @@ class TendersService {
|
||||
|
||||
private readonly EXTRA_META_START = '[EXTRA_TENDER_META]';
|
||||
private readonly EXTRA_META_END = '[/EXTRA_TENDER_META]';
|
||||
private getCompanyTodayDate(): Date {
|
||||
const parts = new Intl.DateTimeFormat('en-US', {
|
||||
timeZone: 'Asia/Riyadh',
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
}).formatToParts(new Date());
|
||||
|
||||
const year = parts.find((p) => p.type === 'year')?.value;
|
||||
const month = parts.find((p) => p.type === 'month')?.value;
|
||||
const day = parts.find((p) => p.type === 'day')?.value;
|
||||
|
||||
return new Date(`${year}-${month}-${day}T00:00:00.000Z`);
|
||||
}
|
||||
|
||||
private toDateOnly(value: Date | string | null | undefined): Date | null {
|
||||
if (!value) return null;
|
||||
|
||||
const date = value instanceof Date ? value : new Date(value);
|
||||
|
||||
if (Number.isNaN(date.getTime())) return null;
|
||||
|
||||
const year = date.getUTCFullYear();
|
||||
const month = String(date.getUTCMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getUTCDate()).padStart(2, '0');
|
||||
|
||||
return new Date(`${year}-${month}-${day}T00:00:00.000Z`);
|
||||
}
|
||||
|
||||
private getEffectiveTenderStatus(tender: {
|
||||
status?: string | null;
|
||||
closingDate?: Date | string | null;
|
||||
}) {
|
||||
if (tender.status === 'ACTIVE') {
|
||||
const closingDate = this.toDateOnly(tender.closingDate);
|
||||
const today = this.getCompanyTodayDate();
|
||||
|
||||
if (closingDate && closingDate < today) {
|
||||
return 'EXPIRED';
|
||||
}
|
||||
}
|
||||
|
||||
return tender.status || 'ACTIVE';
|
||||
}
|
||||
|
||||
private extractTenderExtraMeta(notes?: string | null) {
|
||||
if (!notes) {
|
||||
@@ -208,11 +252,17 @@ class TendersService {
|
||||
return cleanedNotes ? `${cleanedNotes}\n${metaBlock}` : metaBlock;
|
||||
}
|
||||
|
||||
private mapTenderExtraFields<T extends { notes?: string | null; bondValue?: any }>(tender: T) {
|
||||
private mapTenderExtraFields<T extends {
|
||||
notes?: string | null;
|
||||
bondValue?: any;
|
||||
status?: string | null;
|
||||
closingDate?: Date | string | null;
|
||||
}>(tender: T) {
|
||||
const { cleanNotes, meta } = this.extractTenderExtraMeta(tender.notes);
|
||||
|
||||
return {
|
||||
...tender,
|
||||
status: this.getEffectiveTenderStatus(tender),
|
||||
notes: cleanNotes || null,
|
||||
initialBondValue: meta.initialBondValue ?? Number(tender.bondValue ?? 0),
|
||||
finalBondValue: meta.finalBondValue ?? null,
|
||||
@@ -345,7 +395,15 @@ class TendersService {
|
||||
{ issuingBodyName: { contains: filters.search, mode: 'insensitive' } },
|
||||
];
|
||||
}
|
||||
if (filters.status) where.status = filters.status;
|
||||
if (filters.status === 'EXPIRED') {
|
||||
where.status = 'ACTIVE';
|
||||
where.closingDate = { lt: this.getCompanyTodayDate() };
|
||||
} else if (filters.status === 'ACTIVE') {
|
||||
where.status = 'ACTIVE';
|
||||
where.closingDate = { gte: this.getCompanyTodayDate() };
|
||||
} else if (filters.status) {
|
||||
where.status = filters.status;
|
||||
}
|
||||
if (filters.source) where.source = filters.source;
|
||||
if (filters.announcementType) where.announcementType = filters.announcementType;
|
||||
|
||||
@@ -624,6 +682,9 @@ class TendersService {
|
||||
if (tender.status === 'CONVERTED_TO_DEAL') {
|
||||
throw new AppError(400, 'Tender already converted to deal');
|
||||
}
|
||||
if (this.getEffectiveTenderStatus(tender) === 'EXPIRED') {
|
||||
throw new AppError(400, 'Cannot convert expired tender to deal');
|
||||
}
|
||||
|
||||
const pipeline = await prisma.pipeline.findUnique({
|
||||
where: { id: data.pipelineId },
|
||||
|
||||
Reference in New Issue
Block a user