Skip to content

Commit b81fbae

Browse files
author
Olufunbi
committed
feat/[BACKEND] Implement Vendor Contract Management Module #295
1 parent cf73033 commit b81fbae

16 files changed

+434
-4
lines changed

backend/package-lock.json

Lines changed: 53 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"@nestjs/mapped-types": "*",
2929
"@nestjs/passport": "^11.0.5",
3030
"@nestjs/platform-express": "^10.0.0",
31+
"@nestjs/schedule": "^6.0.1",
3132
"@nestjs/swagger": "^7.3.0",
3233
"@nestjs/typeorm": "^10.0.2",
3334
"@types/multer": "^2.0.0",
@@ -36,6 +37,7 @@
3637
"bwip-js": "^4.7.0",
3738
"class-transformer": "^0.5.1",
3839
"class-validator": "^0.14.0",
40+
"date-fns": "^4.1.0",
3941
"json2csv": "^6.0.0-alpha.2",
4042
"multer": "^2.0.2",
4143
"nestjs-i18n": "^10.5.1",

backend/src/app.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { FileUpload } from './file-uploads/entities/file-upload.entity';
1919
import { Asset } from './assets/entities/assest.entity';
2020
import { Supplier } from './suppliers/entities/supplier.entity';
2121
import { QrBarcodeModule } from './qr-barcode/qr-barcode.module';
22+
import { VendorContractsModule } from './vendor-contracts/vendor-contracts.module';
2223

2324
@Module({
2425
imports: [
@@ -56,6 +57,7 @@ import { QrBarcodeModule } from './qr-barcode/qr-barcode.module';
5657
RiskModule,
5758
ReportingModule,
5859
QrBarcodeModule,
60+
VendorContractsModule,
5961
],
6062
controllers: [AppController],
6163
providers: [AppService],
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Injectable, Logger } from '@nestjs/common';
2+
import {
3+
ContractExpiryPayload,
4+
NotificationService,
5+
} from './interfaces/notification.interface';
6+
7+
@Injectable()
8+
export class ConsoleNotificationService implements NotificationService {
9+
private readonly logger = new Logger(ConsoleNotificationService.name);
10+
11+
async notifyContractExpiring(payload: ContractExpiryPayload) {
12+
// Replace with real email/push logic
13+
this.logger.warn(
14+
`Contract expiring soon: ${payload.contractName} (id=${payload.contractId}) for supplier ${payload.supplierId}. Expires in ${payload.daysUntilExpiry} days on ${payload.endDate}`,
15+
);
16+
// e.g., call mailerService.sendMail(...) or push to queue
17+
}
18+
}

backend/src/notifications/interfaces/notification.interface.ts

Whitespace-only changes.
Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +0,0 @@
1-
import { PartialType } from '@nestjs/swagger';
2-
import { CreateQrBarcodeDto } from './generate-qr-barcode.dto';
3-
4-
export class UpdateQrBarcodeDto extends PartialType(CreateQrBarcodeDto) {}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import {
2+
IsUUID,
3+
IsString,
4+
IsDateString,
5+
IsOptional,
6+
IsUrl,
7+
Length,
8+
} from 'class-validator';
9+
10+
export class CreateVendorContractDto {
11+
@IsUUID()
12+
supplierId: string;
13+
14+
@IsString()
15+
@Length(1, 255)
16+
contractName: string;
17+
18+
@IsDateString()
19+
startDate: string;
20+
21+
@IsDateString()
22+
endDate: string;
23+
24+
@IsOptional()
25+
@IsUrl()
26+
fileUrl?: string;
27+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { IsOptional, IsUUID, IsNumberString } from 'class-validator';
2+
3+
export class QueryVendorContractDto {
4+
@IsOptional()
5+
@IsUUID()
6+
supplierId?: string;
7+
8+
@IsOptional()
9+
search?: string;
10+
11+
// simple pagination
12+
@IsOptional()
13+
@IsNumberString()
14+
page?: string;
15+
16+
@IsOptional()
17+
@IsNumberString()
18+
limit?: string;
19+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { PartialType } from '@nestjs/mapped-types';
2+
import { CreateVendorContractDto } from './create-vendor-contract.dto';
3+
import { IsOptional, IsBoolean } from 'class-validator';
4+
5+
export class UpdateVendorContractDto extends PartialType(
6+
CreateVendorContractDto,
7+
) {
8+
@IsOptional()
9+
@IsBoolean()
10+
isActive?: boolean;
11+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import {
2+
Entity,
3+
PrimaryGeneratedColumn,
4+
Column,
5+
CreateDateColumn,
6+
UpdateDateColumn,
7+
Index,
8+
} from 'typeorm';
9+
10+
@Entity({ name: 'vendor_contracts' })
11+
export class VendorContract {
12+
@PrimaryGeneratedColumn('uuid')
13+
id: string;
14+
15+
// Could be a FK to suppliers table (uuid). Keep simple as UUID.
16+
@Column({ type: 'uuid' })
17+
@Index()
18+
supplierId: string;
19+
20+
@Column({ type: 'varchar', length: 255 })
21+
contractName: string;
22+
23+
@Column({ type: 'date' })
24+
startDate: string; // ISO date string
25+
26+
@Column({ type: 'date' })
27+
@Index()
28+
endDate: string; // ISO date string
29+
30+
@Column({ type: 'text', nullable: true })
31+
fileUrl?: string;
32+
33+
@Column({ type: 'boolean', default: true })
34+
isActive: boolean;
35+
36+
@CreateDateColumn()
37+
createdAt: Date;
38+
39+
@UpdateDateColumn()
40+
updatedAt: Date;
41+
}

0 commit comments

Comments
 (0)