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_START = '[EXTRA_TENDER_META]';
|
||||||
private readonly EXTRA_META_END = '[/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) {
|
private extractTenderExtraMeta(notes?: string | null) {
|
||||||
if (!notes) {
|
if (!notes) {
|
||||||
@@ -208,11 +252,17 @@ class TendersService {
|
|||||||
return cleanedNotes ? `${cleanedNotes}\n${metaBlock}` : metaBlock;
|
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);
|
const { cleanNotes, meta } = this.extractTenderExtraMeta(tender.notes);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...tender,
|
...tender,
|
||||||
|
status: this.getEffectiveTenderStatus(tender),
|
||||||
notes: cleanNotes || null,
|
notes: cleanNotes || null,
|
||||||
initialBondValue: meta.initialBondValue ?? Number(tender.bondValue ?? 0),
|
initialBondValue: meta.initialBondValue ?? Number(tender.bondValue ?? 0),
|
||||||
finalBondValue: meta.finalBondValue ?? null,
|
finalBondValue: meta.finalBondValue ?? null,
|
||||||
@@ -345,7 +395,15 @@ class TendersService {
|
|||||||
{ issuingBodyName: { contains: filters.search, mode: 'insensitive' } },
|
{ 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.source) where.source = filters.source;
|
||||||
if (filters.announcementType) where.announcementType = filters.announcementType;
|
if (filters.announcementType) where.announcementType = filters.announcementType;
|
||||||
|
|
||||||
@@ -624,6 +682,9 @@ class TendersService {
|
|||||||
if (tender.status === 'CONVERTED_TO_DEAL') {
|
if (tender.status === 'CONVERTED_TO_DEAL') {
|
||||||
throw new AppError(400, 'Tender already 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({
|
const pipeline = await prisma.pipeline.findUnique({
|
||||||
where: { id: data.pipelineId },
|
where: { id: data.pipelineId },
|
||||||
|
|||||||
Reference in New Issue
Block a user