Commit ede124b8 by Augusto

Users Signature, Partner Logo, InspectionPhotos isPrincipal, IsResume, arrange in order

parent 933b118d
ALTER TABLE "Inspection" ALTER COLUMN "finalCommentStatus" DROP DEFAULT;--> statement-breakpoint
ALTER TABLE "Inspection" ALTER COLUMN "finalCommentStatus" SET DATA TYPE "public"."InspectionStatus" USING "finalCommentStatus"::text::"public"."InspectionStatus";--> statement-breakpoint
ALTER TABLE "Inspection" ALTER COLUMN "finalCommentStatus" SET DEFAULT 'PENDING';--> statement-breakpoint
DROP TYPE "public"."FinalCommentStatus";
\ No newline at end of file
ALTER TABLE "User" ALTER COLUMN "isActive" SET DEFAULT true;
\ No newline at end of file
ALTER TABLE "InspectionPhoto" ADD COLUMN "order" integer DEFAULT 0 NOT NULL;--> statement-breakpoint
ALTER TABLE "Inspection" ADD COLUMN "submittedById" integer;--> statement-breakpoint
ALTER TABLE "Inspection" ADD COLUMN "approvedById" integer;--> statement-breakpoint
ALTER TABLE "Inspection" ADD CONSTRAINT "Inspection_submittedById_User_id_fk" FOREIGN KEY ("submittedById") REFERENCES "public"."User"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "Inspection" ADD CONSTRAINT "Inspection_approvedById_User_id_fk" FOREIGN KEY ("approvedById") REFERENCES "public"."User"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "Inspection_submittedById_idx" ON "Inspection" USING btree ("submittedById");--> statement-breakpoint
CREATE INDEX "Inspection_approvedById_idx" ON "Inspection" USING btree ("approvedById");
\ No newline at end of file
ALTER TABLE "InspectionPhoto" ADD COLUMN "isPrincipal" boolean DEFAULT false NOT NULL;
\ No newline at end of file
ALTER TABLE "InspectionPhoto" ADD COLUMN "isResume" boolean DEFAULT false NOT NULL;
\ No newline at end of file
ALTER TABLE "Partner" ADD COLUMN "logo" varchar(500);--> statement-breakpoint
ALTER TABLE "User" ADD COLUMN "signature" varchar(500);
\ No newline at end of file
{
"id": "9b74fd2b-8ee8-4c5d-b293-cb7992d972d2",
"prevId": "638cb10c-afc9-4e9c-aaa6-8cd0d2eb4fdf",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.InspectionPhoto": {
"name": "InspectionPhoto",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"url": {
"name": "url",
"type": "varchar(500)",
"primaryKey": false,
"notNull": true
},
"filename": {
"name": "filename",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"mimeType": {
"name": "mimeType",
"type": "varchar(100)",
"primaryKey": false,
"notNull": true
},
"size": {
"name": "size",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"inspectionId": {
"name": "inspectionId",
"type": "integer",
"primaryKey": false,
"notNull": true
}
},
"indexes": {
"InspectionPhoto_inspectionId_idx": {
"name": "InspectionPhoto_inspectionId_idx",
"columns": [
{
"expression": "inspectionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"InspectionPhoto_inspectionId_Inspection_id_fk": {
"name": "InspectionPhoto_inspectionId_Inspection_id_fk",
"tableFrom": "InspectionPhoto",
"tableTo": "Inspection",
"columnsFrom": [
"inspectionId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.InspectionQuestion": {
"name": "InspectionQuestion",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"question": {
"name": "question",
"type": "text",
"primaryKey": false,
"notNull": true
},
"orderIndex": {
"name": "orderIndex",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.InspectionResponse": {
"name": "InspectionResponse",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"response": {
"name": "response",
"type": "InspectionResponseOption",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"comment": {
"name": "comment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"questionId": {
"name": "questionId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"inspectionId": {
"name": "inspectionId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"InspectionResponse_questionId_idx": {
"name": "InspectionResponse_questionId_idx",
"columns": [
{
"expression": "questionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"InspectionResponse_inspectionId_idx": {
"name": "InspectionResponse_inspectionId_idx",
"columns": [
{
"expression": "inspectionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"InspectionResponse_inspectionId_questionId_key": {
"name": "InspectionResponse_inspectionId_questionId_key",
"columns": [
{
"expression": "inspectionId",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "questionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"InspectionResponse_questionId_InspectionQuestion_id_fk": {
"name": "InspectionResponse_questionId_InspectionQuestion_id_fk",
"tableFrom": "InspectionResponse",
"tableTo": "InspectionQuestion",
"columnsFrom": [
"questionId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"InspectionResponse_inspectionId_Inspection_id_fk": {
"name": "InspectionResponse_inspectionId_Inspection_id_fk",
"tableFrom": "InspectionResponse",
"tableTo": "Inspection",
"columnsFrom": [
"inspectionId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.Inspection": {
"name": "Inspection",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"date": {
"name": "date",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"deadline": {
"name": "deadline",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"comment": {
"name": "comment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"finalComment": {
"name": "finalComment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"finalCommentStatus": {
"name": "finalCommentStatus",
"type": "InspectionStatus",
"typeSchema": "public",
"primaryKey": false,
"notNull": false,
"default": "'PENDING'"
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"createdById": {
"name": "createdById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"updatedById": {
"name": "updatedById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "InspectionStatus",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'PENDING'"
}
},
"indexes": {
"Inspection_siteId_idx": {
"name": "Inspection_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_createdById_idx": {
"name": "Inspection_createdById_idx",
"columns": [
{
"expression": "createdById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_updatedById_idx": {
"name": "Inspection_updatedById_idx",
"columns": [
{
"expression": "updatedById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_status_idx": {
"name": "Inspection_status_idx",
"columns": [
{
"expression": "status",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_finalCommentStatus_idx": {
"name": "Inspection_finalCommentStatus_idx",
"columns": [
{
"expression": "finalCommentStatus",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"Inspection_siteId_Site_id_fk": {
"name": "Inspection_siteId_Site_id_fk",
"tableFrom": "Inspection",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"Inspection_createdById_User_id_fk": {
"name": "Inspection_createdById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"createdById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Inspection_updatedById_User_id_fk": {
"name": "Inspection_updatedById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"updatedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.PartnerSite": {
"name": "PartnerSite",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"partnerId": {
"name": "partnerId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"PartnerSite_partnerId_siteId_key": {
"name": "PartnerSite_partnerId_siteId_key",
"columns": [
{
"expression": "partnerId",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"PartnerSite_partnerId_idx": {
"name": "PartnerSite_partnerId_idx",
"columns": [
{
"expression": "partnerId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"PartnerSite_siteId_idx": {
"name": "PartnerSite_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"PartnerSite_partnerId_Partner_id_fk": {
"name": "PartnerSite_partnerId_Partner_id_fk",
"tableFrom": "PartnerSite",
"tableTo": "Partner",
"columnsFrom": [
"partnerId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"PartnerSite_siteId_Site_id_fk": {
"name": "PartnerSite_siteId_Site_id_fk",
"tableFrom": "PartnerSite",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.Partner": {
"name": "Partner",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"isActive": {
"name": "isActive",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"Partner_name_idx": {
"name": "Partner_name_idx",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"Partner_name_unique": {
"name": "Partner_name_unique",
"nullsNotDistinct": false,
"columns": [
"name"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.RefreshToken": {
"name": "RefreshToken",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"token": {
"name": "token",
"type": "varchar(500)",
"primaryKey": false,
"notNull": true
},
"userId": {
"name": "userId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"expiresAt": {
"name": "expiresAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"RefreshToken_token_idx": {
"name": "RefreshToken_token_idx",
"columns": [
{
"expression": "token",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"RefreshToken_userId_idx": {
"name": "RefreshToken_userId_idx",
"columns": [
{
"expression": "userId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"RefreshToken_userId_User_id_fk": {
"name": "RefreshToken_userId_User_id_fk",
"tableFrom": "RefreshToken",
"tableTo": "User",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"RefreshToken_token_unique": {
"name": "RefreshToken_token_unique",
"nullsNotDistinct": false,
"columns": [
"token"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.Site": {
"name": "Site",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"siteCode": {
"name": "siteCode",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"siteName": {
"name": "siteName",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"latitude": {
"name": "latitude",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"longitude": {
"name": "longitude",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"createdById": {
"name": "createdById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"updatedById": {
"name": "updatedById",
"type": "integer",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"Site_siteCode_idx": {
"name": "Site_siteCode_idx",
"columns": [
{
"expression": "siteCode",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"Site_createdById_User_id_fk": {
"name": "Site_createdById_User_id_fk",
"tableFrom": "Site",
"tableTo": "User",
"columnsFrom": [
"createdById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Site_updatedById_User_id_fk": {
"name": "Site_updatedById_User_id_fk",
"tableFrom": "Site",
"tableTo": "User",
"columnsFrom": [
"updatedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"Site_siteCode_unique": {
"name": "Site_siteCode_unique",
"nullsNotDistinct": false,
"columns": [
"siteCode"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.spatial_ref_sys": {
"name": "spatial_ref_sys",
"schema": "",
"columns": {
"srid": {
"name": "srid",
"type": "integer",
"primaryKey": true,
"notNull": true
},
"auth_name": {
"name": "auth_name",
"type": "varchar(256)",
"primaryKey": false,
"notNull": false
},
"auth_srid": {
"name": "auth_srid",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"srtext": {
"name": "srtext",
"type": "varchar(2048)",
"primaryKey": false,
"notNull": false
},
"proj4text": {
"name": "proj4text",
"type": "varchar(2048)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.TelecommunicationStationIdentification": {
"name": "TelecommunicationStationIdentification",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"stationIdentifier": {
"name": "stationIdentifier",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"serialNumber": {
"name": "serialNumber",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"isFirstCertification": {
"name": "isFirstCertification",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"modelReference": {
"name": "modelReference",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"TelecommunicationStationIdentification_siteId_idx": {
"name": "TelecommunicationStationIdentification_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"TelecommunicationStationIdentification_stationIdentifier_idx": {
"name": "TelecommunicationStationIdentification_stationIdentifier_idx",
"columns": [
{
"expression": "stationIdentifier",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"TelecommunicationStationIdentification_siteId_Site_id_fk": {
"name": "TelecommunicationStationIdentification_siteId_Site_id_fk",
"tableFrom": "TelecommunicationStationIdentification",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"TelecommunicationStationIdentification_siteId_unique": {
"name": "TelecommunicationStationIdentification_siteId_unique",
"nullsNotDistinct": false,
"columns": [
"siteId"
]
},
"TelecommunicationStationIdentification_stationIdentifier_unique": {
"name": "TelecommunicationStationIdentification_stationIdentifier_unique",
"nullsNotDistinct": false,
"columns": [
"stationIdentifier"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.UserSite": {
"name": "UserSite",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"userId": {
"name": "userId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"UserSite_userId_siteId_key": {
"name": "UserSite_userId_siteId_key",
"columns": [
{
"expression": "userId",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"UserSite_userId_idx": {
"name": "UserSite_userId_idx",
"columns": [
{
"expression": "userId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"UserSite_siteId_idx": {
"name": "UserSite_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"UserSite_userId_User_id_fk": {
"name": "UserSite_userId_User_id_fk",
"tableFrom": "UserSite",
"tableTo": "User",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"UserSite_siteId_Site_id_fk": {
"name": "UserSite_siteId_Site_id_fk",
"tableFrom": "UserSite",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.User": {
"name": "User",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"email": {
"name": "email",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"password": {
"name": "password",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"role": {
"name": "role",
"type": "Role",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'VIEWER'"
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"resetToken": {
"name": "resetToken",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"resetTokenExpiry": {
"name": "resetTokenExpiry",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"isActive": {
"name": "isActive",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"partnerId": {
"name": "partnerId",
"type": "integer",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"User_email_idx": {
"name": "User_email_idx",
"columns": [
{
"expression": "email",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"User_role_idx": {
"name": "User_role_idx",
"columns": [
{
"expression": "role",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"User_partnerId_idx": {
"name": "User_partnerId_idx",
"columns": [
{
"expression": "partnerId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"User_partnerId_Partner_id_fk": {
"name": "User_partnerId_Partner_id_fk",
"tableFrom": "User",
"tableTo": "Partner",
"columnsFrom": [
"partnerId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"User_email_unique": {
"name": "User_email_unique",
"nullsNotDistinct": false,
"columns": [
"email"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {
"public.CompanyName": {
"name": "CompanyName",
"schema": "public",
"values": [
"VODAFONE",
"MEO",
"NOS",
"DIGI"
]
},
"public.InspectionResponseOption": {
"name": "InspectionResponseOption",
"schema": "public",
"values": [
"YES",
"NO",
"NA"
]
},
"public.InspectionStatus": {
"name": "InspectionStatus",
"schema": "public",
"values": [
"PENDING",
"IN_PROGRESS",
"COMPLETED",
"CANCELLED",
"APPROVING",
"REJECTED",
"APPROVED"
]
},
"public.Role": {
"name": "Role",
"schema": "public",
"values": [
"SUPERADMIN",
"ADMIN",
"MANAGER",
"PARTNER",
"OPERATOR",
"VIEWER"
]
}
},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
\ No newline at end of file
{
"id": "c53c2a65-03a4-4f75-a391-9510e8d52aa3",
"prevId": "9b74fd2b-8ee8-4c5d-b293-cb7992d972d2",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.InspectionPhoto": {
"name": "InspectionPhoto",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"url": {
"name": "url",
"type": "varchar(500)",
"primaryKey": false,
"notNull": true
},
"filename": {
"name": "filename",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"mimeType": {
"name": "mimeType",
"type": "varchar(100)",
"primaryKey": false,
"notNull": true
},
"size": {
"name": "size",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"inspectionId": {
"name": "inspectionId",
"type": "integer",
"primaryKey": false,
"notNull": true
}
},
"indexes": {
"InspectionPhoto_inspectionId_idx": {
"name": "InspectionPhoto_inspectionId_idx",
"columns": [
{
"expression": "inspectionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"InspectionPhoto_inspectionId_Inspection_id_fk": {
"name": "InspectionPhoto_inspectionId_Inspection_id_fk",
"tableFrom": "InspectionPhoto",
"tableTo": "Inspection",
"columnsFrom": [
"inspectionId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.InspectionQuestion": {
"name": "InspectionQuestion",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"question": {
"name": "question",
"type": "text",
"primaryKey": false,
"notNull": true
},
"orderIndex": {
"name": "orderIndex",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.InspectionResponse": {
"name": "InspectionResponse",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"response": {
"name": "response",
"type": "InspectionResponseOption",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"comment": {
"name": "comment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"questionId": {
"name": "questionId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"inspectionId": {
"name": "inspectionId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"InspectionResponse_questionId_idx": {
"name": "InspectionResponse_questionId_idx",
"columns": [
{
"expression": "questionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"InspectionResponse_inspectionId_idx": {
"name": "InspectionResponse_inspectionId_idx",
"columns": [
{
"expression": "inspectionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"InspectionResponse_inspectionId_questionId_key": {
"name": "InspectionResponse_inspectionId_questionId_key",
"columns": [
{
"expression": "inspectionId",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "questionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"InspectionResponse_questionId_InspectionQuestion_id_fk": {
"name": "InspectionResponse_questionId_InspectionQuestion_id_fk",
"tableFrom": "InspectionResponse",
"tableTo": "InspectionQuestion",
"columnsFrom": [
"questionId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"InspectionResponse_inspectionId_Inspection_id_fk": {
"name": "InspectionResponse_inspectionId_Inspection_id_fk",
"tableFrom": "InspectionResponse",
"tableTo": "Inspection",
"columnsFrom": [
"inspectionId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.Inspection": {
"name": "Inspection",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"date": {
"name": "date",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"deadline": {
"name": "deadline",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"comment": {
"name": "comment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"finalComment": {
"name": "finalComment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"finalCommentStatus": {
"name": "finalCommentStatus",
"type": "InspectionStatus",
"typeSchema": "public",
"primaryKey": false,
"notNull": false,
"default": "'PENDING'"
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"createdById": {
"name": "createdById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"updatedById": {
"name": "updatedById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "InspectionStatus",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'PENDING'"
}
},
"indexes": {
"Inspection_siteId_idx": {
"name": "Inspection_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_createdById_idx": {
"name": "Inspection_createdById_idx",
"columns": [
{
"expression": "createdById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_updatedById_idx": {
"name": "Inspection_updatedById_idx",
"columns": [
{
"expression": "updatedById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_status_idx": {
"name": "Inspection_status_idx",
"columns": [
{
"expression": "status",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_finalCommentStatus_idx": {
"name": "Inspection_finalCommentStatus_idx",
"columns": [
{
"expression": "finalCommentStatus",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"Inspection_siteId_Site_id_fk": {
"name": "Inspection_siteId_Site_id_fk",
"tableFrom": "Inspection",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"Inspection_createdById_User_id_fk": {
"name": "Inspection_createdById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"createdById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Inspection_updatedById_User_id_fk": {
"name": "Inspection_updatedById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"updatedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.PartnerSite": {
"name": "PartnerSite",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"partnerId": {
"name": "partnerId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"PartnerSite_partnerId_siteId_key": {
"name": "PartnerSite_partnerId_siteId_key",
"columns": [
{
"expression": "partnerId",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"PartnerSite_partnerId_idx": {
"name": "PartnerSite_partnerId_idx",
"columns": [
{
"expression": "partnerId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"PartnerSite_siteId_idx": {
"name": "PartnerSite_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"PartnerSite_partnerId_Partner_id_fk": {
"name": "PartnerSite_partnerId_Partner_id_fk",
"tableFrom": "PartnerSite",
"tableTo": "Partner",
"columnsFrom": [
"partnerId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"PartnerSite_siteId_Site_id_fk": {
"name": "PartnerSite_siteId_Site_id_fk",
"tableFrom": "PartnerSite",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.Partner": {
"name": "Partner",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"isActive": {
"name": "isActive",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"Partner_name_idx": {
"name": "Partner_name_idx",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"Partner_name_unique": {
"name": "Partner_name_unique",
"nullsNotDistinct": false,
"columns": [
"name"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.RefreshToken": {
"name": "RefreshToken",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"token": {
"name": "token",
"type": "varchar(500)",
"primaryKey": false,
"notNull": true
},
"userId": {
"name": "userId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"expiresAt": {
"name": "expiresAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"RefreshToken_token_idx": {
"name": "RefreshToken_token_idx",
"columns": [
{
"expression": "token",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"RefreshToken_userId_idx": {
"name": "RefreshToken_userId_idx",
"columns": [
{
"expression": "userId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"RefreshToken_userId_User_id_fk": {
"name": "RefreshToken_userId_User_id_fk",
"tableFrom": "RefreshToken",
"tableTo": "User",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"RefreshToken_token_unique": {
"name": "RefreshToken_token_unique",
"nullsNotDistinct": false,
"columns": [
"token"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.Site": {
"name": "Site",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"siteCode": {
"name": "siteCode",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"siteName": {
"name": "siteName",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"latitude": {
"name": "latitude",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"longitude": {
"name": "longitude",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"createdById": {
"name": "createdById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"updatedById": {
"name": "updatedById",
"type": "integer",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"Site_siteCode_idx": {
"name": "Site_siteCode_idx",
"columns": [
{
"expression": "siteCode",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"Site_createdById_User_id_fk": {
"name": "Site_createdById_User_id_fk",
"tableFrom": "Site",
"tableTo": "User",
"columnsFrom": [
"createdById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Site_updatedById_User_id_fk": {
"name": "Site_updatedById_User_id_fk",
"tableFrom": "Site",
"tableTo": "User",
"columnsFrom": [
"updatedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"Site_siteCode_unique": {
"name": "Site_siteCode_unique",
"nullsNotDistinct": false,
"columns": [
"siteCode"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.spatial_ref_sys": {
"name": "spatial_ref_sys",
"schema": "",
"columns": {
"srid": {
"name": "srid",
"type": "integer",
"primaryKey": true,
"notNull": true
},
"auth_name": {
"name": "auth_name",
"type": "varchar(256)",
"primaryKey": false,
"notNull": false
},
"auth_srid": {
"name": "auth_srid",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"srtext": {
"name": "srtext",
"type": "varchar(2048)",
"primaryKey": false,
"notNull": false
},
"proj4text": {
"name": "proj4text",
"type": "varchar(2048)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.TelecommunicationStationIdentification": {
"name": "TelecommunicationStationIdentification",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"stationIdentifier": {
"name": "stationIdentifier",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"serialNumber": {
"name": "serialNumber",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"isFirstCertification": {
"name": "isFirstCertification",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"modelReference": {
"name": "modelReference",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"TelecommunicationStationIdentification_siteId_idx": {
"name": "TelecommunicationStationIdentification_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"TelecommunicationStationIdentification_stationIdentifier_idx": {
"name": "TelecommunicationStationIdentification_stationIdentifier_idx",
"columns": [
{
"expression": "stationIdentifier",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"TelecommunicationStationIdentification_siteId_Site_id_fk": {
"name": "TelecommunicationStationIdentification_siteId_Site_id_fk",
"tableFrom": "TelecommunicationStationIdentification",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"TelecommunicationStationIdentification_siteId_unique": {
"name": "TelecommunicationStationIdentification_siteId_unique",
"nullsNotDistinct": false,
"columns": [
"siteId"
]
},
"TelecommunicationStationIdentification_stationIdentifier_unique": {
"name": "TelecommunicationStationIdentification_stationIdentifier_unique",
"nullsNotDistinct": false,
"columns": [
"stationIdentifier"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.UserSite": {
"name": "UserSite",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"userId": {
"name": "userId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"UserSite_userId_siteId_key": {
"name": "UserSite_userId_siteId_key",
"columns": [
{
"expression": "userId",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"UserSite_userId_idx": {
"name": "UserSite_userId_idx",
"columns": [
{
"expression": "userId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"UserSite_siteId_idx": {
"name": "UserSite_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"UserSite_userId_User_id_fk": {
"name": "UserSite_userId_User_id_fk",
"tableFrom": "UserSite",
"tableTo": "User",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"UserSite_siteId_Site_id_fk": {
"name": "UserSite_siteId_Site_id_fk",
"tableFrom": "UserSite",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.User": {
"name": "User",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"email": {
"name": "email",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"password": {
"name": "password",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"role": {
"name": "role",
"type": "Role",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'VIEWER'"
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"resetToken": {
"name": "resetToken",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"resetTokenExpiry": {
"name": "resetTokenExpiry",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"isActive": {
"name": "isActive",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"partnerId": {
"name": "partnerId",
"type": "integer",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"User_email_idx": {
"name": "User_email_idx",
"columns": [
{
"expression": "email",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"User_role_idx": {
"name": "User_role_idx",
"columns": [
{
"expression": "role",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"User_partnerId_idx": {
"name": "User_partnerId_idx",
"columns": [
{
"expression": "partnerId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"User_partnerId_Partner_id_fk": {
"name": "User_partnerId_Partner_id_fk",
"tableFrom": "User",
"tableTo": "Partner",
"columnsFrom": [
"partnerId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"User_email_unique": {
"name": "User_email_unique",
"nullsNotDistinct": false,
"columns": [
"email"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {
"public.CompanyName": {
"name": "CompanyName",
"schema": "public",
"values": [
"VODAFONE",
"MEO",
"NOS",
"DIGI"
]
},
"public.InspectionResponseOption": {
"name": "InspectionResponseOption",
"schema": "public",
"values": [
"YES",
"NO",
"NA"
]
},
"public.InspectionStatus": {
"name": "InspectionStatus",
"schema": "public",
"values": [
"PENDING",
"IN_PROGRESS",
"COMPLETED",
"CANCELLED",
"APPROVING",
"REJECTED",
"APPROVED"
]
},
"public.Role": {
"name": "Role",
"schema": "public",
"values": [
"SUPERADMIN",
"ADMIN",
"MANAGER",
"PARTNER",
"OPERATOR",
"VIEWER"
]
}
},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
\ No newline at end of file
{
"id": "cd3170ec-08ca-4c42-8d84-367b61f7a504",
"prevId": "c53c2a65-03a4-4f75-a391-9510e8d52aa3",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.InspectionPhoto": {
"name": "InspectionPhoto",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"url": {
"name": "url",
"type": "varchar(500)",
"primaryKey": false,
"notNull": true
},
"filename": {
"name": "filename",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"mimeType": {
"name": "mimeType",
"type": "varchar(100)",
"primaryKey": false,
"notNull": true
},
"size": {
"name": "size",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"order": {
"name": "order",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"inspectionId": {
"name": "inspectionId",
"type": "integer",
"primaryKey": false,
"notNull": true
}
},
"indexes": {
"InspectionPhoto_inspectionId_idx": {
"name": "InspectionPhoto_inspectionId_idx",
"columns": [
{
"expression": "inspectionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"InspectionPhoto_inspectionId_Inspection_id_fk": {
"name": "InspectionPhoto_inspectionId_Inspection_id_fk",
"tableFrom": "InspectionPhoto",
"tableTo": "Inspection",
"columnsFrom": [
"inspectionId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.InspectionQuestion": {
"name": "InspectionQuestion",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"question": {
"name": "question",
"type": "text",
"primaryKey": false,
"notNull": true
},
"orderIndex": {
"name": "orderIndex",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.InspectionResponse": {
"name": "InspectionResponse",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"response": {
"name": "response",
"type": "InspectionResponseOption",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"comment": {
"name": "comment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"questionId": {
"name": "questionId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"inspectionId": {
"name": "inspectionId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"InspectionResponse_questionId_idx": {
"name": "InspectionResponse_questionId_idx",
"columns": [
{
"expression": "questionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"InspectionResponse_inspectionId_idx": {
"name": "InspectionResponse_inspectionId_idx",
"columns": [
{
"expression": "inspectionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"InspectionResponse_inspectionId_questionId_key": {
"name": "InspectionResponse_inspectionId_questionId_key",
"columns": [
{
"expression": "inspectionId",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "questionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"InspectionResponse_questionId_InspectionQuestion_id_fk": {
"name": "InspectionResponse_questionId_InspectionQuestion_id_fk",
"tableFrom": "InspectionResponse",
"tableTo": "InspectionQuestion",
"columnsFrom": [
"questionId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"InspectionResponse_inspectionId_Inspection_id_fk": {
"name": "InspectionResponse_inspectionId_Inspection_id_fk",
"tableFrom": "InspectionResponse",
"tableTo": "Inspection",
"columnsFrom": [
"inspectionId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.Inspection": {
"name": "Inspection",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"date": {
"name": "date",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"deadline": {
"name": "deadline",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"comment": {
"name": "comment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"finalComment": {
"name": "finalComment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"finalCommentStatus": {
"name": "finalCommentStatus",
"type": "InspectionStatus",
"typeSchema": "public",
"primaryKey": false,
"notNull": false,
"default": "'PENDING'"
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"createdById": {
"name": "createdById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"updatedById": {
"name": "updatedById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"submittedById": {
"name": "submittedById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"approvedById": {
"name": "approvedById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "InspectionStatus",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'PENDING'"
}
},
"indexes": {
"Inspection_siteId_idx": {
"name": "Inspection_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_createdById_idx": {
"name": "Inspection_createdById_idx",
"columns": [
{
"expression": "createdById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_updatedById_idx": {
"name": "Inspection_updatedById_idx",
"columns": [
{
"expression": "updatedById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_submittedById_idx": {
"name": "Inspection_submittedById_idx",
"columns": [
{
"expression": "submittedById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_approvedById_idx": {
"name": "Inspection_approvedById_idx",
"columns": [
{
"expression": "approvedById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_status_idx": {
"name": "Inspection_status_idx",
"columns": [
{
"expression": "status",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_finalCommentStatus_idx": {
"name": "Inspection_finalCommentStatus_idx",
"columns": [
{
"expression": "finalCommentStatus",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"Inspection_siteId_Site_id_fk": {
"name": "Inspection_siteId_Site_id_fk",
"tableFrom": "Inspection",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"Inspection_createdById_User_id_fk": {
"name": "Inspection_createdById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"createdById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Inspection_updatedById_User_id_fk": {
"name": "Inspection_updatedById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"updatedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Inspection_submittedById_User_id_fk": {
"name": "Inspection_submittedById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"submittedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Inspection_approvedById_User_id_fk": {
"name": "Inspection_approvedById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"approvedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.PartnerSite": {
"name": "PartnerSite",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"partnerId": {
"name": "partnerId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"PartnerSite_partnerId_siteId_key": {
"name": "PartnerSite_partnerId_siteId_key",
"columns": [
{
"expression": "partnerId",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"PartnerSite_partnerId_idx": {
"name": "PartnerSite_partnerId_idx",
"columns": [
{
"expression": "partnerId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"PartnerSite_siteId_idx": {
"name": "PartnerSite_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"PartnerSite_partnerId_Partner_id_fk": {
"name": "PartnerSite_partnerId_Partner_id_fk",
"tableFrom": "PartnerSite",
"tableTo": "Partner",
"columnsFrom": [
"partnerId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"PartnerSite_siteId_Site_id_fk": {
"name": "PartnerSite_siteId_Site_id_fk",
"tableFrom": "PartnerSite",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.Partner": {
"name": "Partner",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"isActive": {
"name": "isActive",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"Partner_name_idx": {
"name": "Partner_name_idx",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"Partner_name_unique": {
"name": "Partner_name_unique",
"nullsNotDistinct": false,
"columns": [
"name"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.RefreshToken": {
"name": "RefreshToken",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"token": {
"name": "token",
"type": "varchar(500)",
"primaryKey": false,
"notNull": true
},
"userId": {
"name": "userId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"expiresAt": {
"name": "expiresAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"RefreshToken_token_idx": {
"name": "RefreshToken_token_idx",
"columns": [
{
"expression": "token",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"RefreshToken_userId_idx": {
"name": "RefreshToken_userId_idx",
"columns": [
{
"expression": "userId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"RefreshToken_userId_User_id_fk": {
"name": "RefreshToken_userId_User_id_fk",
"tableFrom": "RefreshToken",
"tableTo": "User",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"RefreshToken_token_unique": {
"name": "RefreshToken_token_unique",
"nullsNotDistinct": false,
"columns": [
"token"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.Site": {
"name": "Site",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"siteCode": {
"name": "siteCode",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"siteName": {
"name": "siteName",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"latitude": {
"name": "latitude",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"longitude": {
"name": "longitude",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"createdById": {
"name": "createdById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"updatedById": {
"name": "updatedById",
"type": "integer",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"Site_siteCode_idx": {
"name": "Site_siteCode_idx",
"columns": [
{
"expression": "siteCode",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"Site_createdById_User_id_fk": {
"name": "Site_createdById_User_id_fk",
"tableFrom": "Site",
"tableTo": "User",
"columnsFrom": [
"createdById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Site_updatedById_User_id_fk": {
"name": "Site_updatedById_User_id_fk",
"tableFrom": "Site",
"tableTo": "User",
"columnsFrom": [
"updatedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"Site_siteCode_unique": {
"name": "Site_siteCode_unique",
"nullsNotDistinct": false,
"columns": [
"siteCode"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.spatial_ref_sys": {
"name": "spatial_ref_sys",
"schema": "",
"columns": {
"srid": {
"name": "srid",
"type": "integer",
"primaryKey": true,
"notNull": true
},
"auth_name": {
"name": "auth_name",
"type": "varchar(256)",
"primaryKey": false,
"notNull": false
},
"auth_srid": {
"name": "auth_srid",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"srtext": {
"name": "srtext",
"type": "varchar(2048)",
"primaryKey": false,
"notNull": false
},
"proj4text": {
"name": "proj4text",
"type": "varchar(2048)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.TelecommunicationStationIdentification": {
"name": "TelecommunicationStationIdentification",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"stationIdentifier": {
"name": "stationIdentifier",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"serialNumber": {
"name": "serialNumber",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"isFirstCertification": {
"name": "isFirstCertification",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"modelReference": {
"name": "modelReference",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"TelecommunicationStationIdentification_siteId_idx": {
"name": "TelecommunicationStationIdentification_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"TelecommunicationStationIdentification_stationIdentifier_idx": {
"name": "TelecommunicationStationIdentification_stationIdentifier_idx",
"columns": [
{
"expression": "stationIdentifier",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"TelecommunicationStationIdentification_siteId_Site_id_fk": {
"name": "TelecommunicationStationIdentification_siteId_Site_id_fk",
"tableFrom": "TelecommunicationStationIdentification",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"TelecommunicationStationIdentification_siteId_unique": {
"name": "TelecommunicationStationIdentification_siteId_unique",
"nullsNotDistinct": false,
"columns": [
"siteId"
]
},
"TelecommunicationStationIdentification_stationIdentifier_unique": {
"name": "TelecommunicationStationIdentification_stationIdentifier_unique",
"nullsNotDistinct": false,
"columns": [
"stationIdentifier"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.UserSite": {
"name": "UserSite",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"userId": {
"name": "userId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"UserSite_userId_siteId_key": {
"name": "UserSite_userId_siteId_key",
"columns": [
{
"expression": "userId",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"UserSite_userId_idx": {
"name": "UserSite_userId_idx",
"columns": [
{
"expression": "userId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"UserSite_siteId_idx": {
"name": "UserSite_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"UserSite_userId_User_id_fk": {
"name": "UserSite_userId_User_id_fk",
"tableFrom": "UserSite",
"tableTo": "User",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"UserSite_siteId_Site_id_fk": {
"name": "UserSite_siteId_Site_id_fk",
"tableFrom": "UserSite",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.User": {
"name": "User",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"email": {
"name": "email",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"password": {
"name": "password",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"role": {
"name": "role",
"type": "Role",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'VIEWER'"
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"resetToken": {
"name": "resetToken",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"resetTokenExpiry": {
"name": "resetTokenExpiry",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"isActive": {
"name": "isActive",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"partnerId": {
"name": "partnerId",
"type": "integer",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"User_email_idx": {
"name": "User_email_idx",
"columns": [
{
"expression": "email",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"User_role_idx": {
"name": "User_role_idx",
"columns": [
{
"expression": "role",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"User_partnerId_idx": {
"name": "User_partnerId_idx",
"columns": [
{
"expression": "partnerId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"User_partnerId_Partner_id_fk": {
"name": "User_partnerId_Partner_id_fk",
"tableFrom": "User",
"tableTo": "Partner",
"columnsFrom": [
"partnerId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"User_email_unique": {
"name": "User_email_unique",
"nullsNotDistinct": false,
"columns": [
"email"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {
"public.CompanyName": {
"name": "CompanyName",
"schema": "public",
"values": [
"VODAFONE",
"MEO",
"NOS",
"DIGI"
]
},
"public.InspectionResponseOption": {
"name": "InspectionResponseOption",
"schema": "public",
"values": [
"YES",
"NO",
"NA"
]
},
"public.InspectionStatus": {
"name": "InspectionStatus",
"schema": "public",
"values": [
"PENDING",
"IN_PROGRESS",
"COMPLETED",
"CANCELLED",
"APPROVING",
"REJECTED",
"APPROVED"
]
},
"public.Role": {
"name": "Role",
"schema": "public",
"values": [
"SUPERADMIN",
"ADMIN",
"MANAGER",
"PARTNER",
"OPERATOR",
"VIEWER"
]
}
},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
\ No newline at end of file
{
"id": "437e2688-7fbf-45dc-b324-6383453e7817",
"prevId": "cd3170ec-08ca-4c42-8d84-367b61f7a504",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.InspectionPhoto": {
"name": "InspectionPhoto",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"url": {
"name": "url",
"type": "varchar(500)",
"primaryKey": false,
"notNull": true
},
"filename": {
"name": "filename",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"mimeType": {
"name": "mimeType",
"type": "varchar(100)",
"primaryKey": false,
"notNull": true
},
"size": {
"name": "size",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"order": {
"name": "order",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"isPrincipal": {
"name": "isPrincipal",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"inspectionId": {
"name": "inspectionId",
"type": "integer",
"primaryKey": false,
"notNull": true
}
},
"indexes": {
"InspectionPhoto_inspectionId_idx": {
"name": "InspectionPhoto_inspectionId_idx",
"columns": [
{
"expression": "inspectionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"InspectionPhoto_inspectionId_Inspection_id_fk": {
"name": "InspectionPhoto_inspectionId_Inspection_id_fk",
"tableFrom": "InspectionPhoto",
"tableTo": "Inspection",
"columnsFrom": [
"inspectionId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.InspectionQuestion": {
"name": "InspectionQuestion",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"question": {
"name": "question",
"type": "text",
"primaryKey": false,
"notNull": true
},
"orderIndex": {
"name": "orderIndex",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.InspectionResponse": {
"name": "InspectionResponse",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"response": {
"name": "response",
"type": "InspectionResponseOption",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"comment": {
"name": "comment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"questionId": {
"name": "questionId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"inspectionId": {
"name": "inspectionId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"InspectionResponse_questionId_idx": {
"name": "InspectionResponse_questionId_idx",
"columns": [
{
"expression": "questionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"InspectionResponse_inspectionId_idx": {
"name": "InspectionResponse_inspectionId_idx",
"columns": [
{
"expression": "inspectionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"InspectionResponse_inspectionId_questionId_key": {
"name": "InspectionResponse_inspectionId_questionId_key",
"columns": [
{
"expression": "inspectionId",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "questionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"InspectionResponse_questionId_InspectionQuestion_id_fk": {
"name": "InspectionResponse_questionId_InspectionQuestion_id_fk",
"tableFrom": "InspectionResponse",
"tableTo": "InspectionQuestion",
"columnsFrom": [
"questionId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"InspectionResponse_inspectionId_Inspection_id_fk": {
"name": "InspectionResponse_inspectionId_Inspection_id_fk",
"tableFrom": "InspectionResponse",
"tableTo": "Inspection",
"columnsFrom": [
"inspectionId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.Inspection": {
"name": "Inspection",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"date": {
"name": "date",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"deadline": {
"name": "deadline",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"comment": {
"name": "comment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"finalComment": {
"name": "finalComment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"finalCommentStatus": {
"name": "finalCommentStatus",
"type": "InspectionStatus",
"typeSchema": "public",
"primaryKey": false,
"notNull": false,
"default": "'PENDING'"
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"createdById": {
"name": "createdById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"updatedById": {
"name": "updatedById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"submittedById": {
"name": "submittedById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"approvedById": {
"name": "approvedById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "InspectionStatus",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'PENDING'"
}
},
"indexes": {
"Inspection_siteId_idx": {
"name": "Inspection_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_createdById_idx": {
"name": "Inspection_createdById_idx",
"columns": [
{
"expression": "createdById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_updatedById_idx": {
"name": "Inspection_updatedById_idx",
"columns": [
{
"expression": "updatedById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_submittedById_idx": {
"name": "Inspection_submittedById_idx",
"columns": [
{
"expression": "submittedById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_approvedById_idx": {
"name": "Inspection_approvedById_idx",
"columns": [
{
"expression": "approvedById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_status_idx": {
"name": "Inspection_status_idx",
"columns": [
{
"expression": "status",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_finalCommentStatus_idx": {
"name": "Inspection_finalCommentStatus_idx",
"columns": [
{
"expression": "finalCommentStatus",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"Inspection_siteId_Site_id_fk": {
"name": "Inspection_siteId_Site_id_fk",
"tableFrom": "Inspection",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"Inspection_createdById_User_id_fk": {
"name": "Inspection_createdById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"createdById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Inspection_updatedById_User_id_fk": {
"name": "Inspection_updatedById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"updatedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Inspection_submittedById_User_id_fk": {
"name": "Inspection_submittedById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"submittedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Inspection_approvedById_User_id_fk": {
"name": "Inspection_approvedById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"approvedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.PartnerSite": {
"name": "PartnerSite",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"partnerId": {
"name": "partnerId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"PartnerSite_partnerId_siteId_key": {
"name": "PartnerSite_partnerId_siteId_key",
"columns": [
{
"expression": "partnerId",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"PartnerSite_partnerId_idx": {
"name": "PartnerSite_partnerId_idx",
"columns": [
{
"expression": "partnerId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"PartnerSite_siteId_idx": {
"name": "PartnerSite_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"PartnerSite_partnerId_Partner_id_fk": {
"name": "PartnerSite_partnerId_Partner_id_fk",
"tableFrom": "PartnerSite",
"tableTo": "Partner",
"columnsFrom": [
"partnerId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"PartnerSite_siteId_Site_id_fk": {
"name": "PartnerSite_siteId_Site_id_fk",
"tableFrom": "PartnerSite",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.Partner": {
"name": "Partner",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"isActive": {
"name": "isActive",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"Partner_name_idx": {
"name": "Partner_name_idx",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"Partner_name_unique": {
"name": "Partner_name_unique",
"nullsNotDistinct": false,
"columns": [
"name"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.RefreshToken": {
"name": "RefreshToken",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"token": {
"name": "token",
"type": "varchar(500)",
"primaryKey": false,
"notNull": true
},
"userId": {
"name": "userId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"expiresAt": {
"name": "expiresAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"RefreshToken_token_idx": {
"name": "RefreshToken_token_idx",
"columns": [
{
"expression": "token",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"RefreshToken_userId_idx": {
"name": "RefreshToken_userId_idx",
"columns": [
{
"expression": "userId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"RefreshToken_userId_User_id_fk": {
"name": "RefreshToken_userId_User_id_fk",
"tableFrom": "RefreshToken",
"tableTo": "User",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"RefreshToken_token_unique": {
"name": "RefreshToken_token_unique",
"nullsNotDistinct": false,
"columns": [
"token"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.Site": {
"name": "Site",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"siteCode": {
"name": "siteCode",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"siteName": {
"name": "siteName",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"latitude": {
"name": "latitude",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"longitude": {
"name": "longitude",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"createdById": {
"name": "createdById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"updatedById": {
"name": "updatedById",
"type": "integer",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"Site_siteCode_idx": {
"name": "Site_siteCode_idx",
"columns": [
{
"expression": "siteCode",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"Site_createdById_User_id_fk": {
"name": "Site_createdById_User_id_fk",
"tableFrom": "Site",
"tableTo": "User",
"columnsFrom": [
"createdById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Site_updatedById_User_id_fk": {
"name": "Site_updatedById_User_id_fk",
"tableFrom": "Site",
"tableTo": "User",
"columnsFrom": [
"updatedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"Site_siteCode_unique": {
"name": "Site_siteCode_unique",
"nullsNotDistinct": false,
"columns": [
"siteCode"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.spatial_ref_sys": {
"name": "spatial_ref_sys",
"schema": "",
"columns": {
"srid": {
"name": "srid",
"type": "integer",
"primaryKey": true,
"notNull": true
},
"auth_name": {
"name": "auth_name",
"type": "varchar(256)",
"primaryKey": false,
"notNull": false
},
"auth_srid": {
"name": "auth_srid",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"srtext": {
"name": "srtext",
"type": "varchar(2048)",
"primaryKey": false,
"notNull": false
},
"proj4text": {
"name": "proj4text",
"type": "varchar(2048)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.TelecommunicationStationIdentification": {
"name": "TelecommunicationStationIdentification",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"stationIdentifier": {
"name": "stationIdentifier",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"serialNumber": {
"name": "serialNumber",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"isFirstCertification": {
"name": "isFirstCertification",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"modelReference": {
"name": "modelReference",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"TelecommunicationStationIdentification_siteId_idx": {
"name": "TelecommunicationStationIdentification_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"TelecommunicationStationIdentification_stationIdentifier_idx": {
"name": "TelecommunicationStationIdentification_stationIdentifier_idx",
"columns": [
{
"expression": "stationIdentifier",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"TelecommunicationStationIdentification_siteId_Site_id_fk": {
"name": "TelecommunicationStationIdentification_siteId_Site_id_fk",
"tableFrom": "TelecommunicationStationIdentification",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"TelecommunicationStationIdentification_siteId_unique": {
"name": "TelecommunicationStationIdentification_siteId_unique",
"nullsNotDistinct": false,
"columns": [
"siteId"
]
},
"TelecommunicationStationIdentification_stationIdentifier_unique": {
"name": "TelecommunicationStationIdentification_stationIdentifier_unique",
"nullsNotDistinct": false,
"columns": [
"stationIdentifier"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.UserSite": {
"name": "UserSite",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"userId": {
"name": "userId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"UserSite_userId_siteId_key": {
"name": "UserSite_userId_siteId_key",
"columns": [
{
"expression": "userId",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"UserSite_userId_idx": {
"name": "UserSite_userId_idx",
"columns": [
{
"expression": "userId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"UserSite_siteId_idx": {
"name": "UserSite_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"UserSite_userId_User_id_fk": {
"name": "UserSite_userId_User_id_fk",
"tableFrom": "UserSite",
"tableTo": "User",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"UserSite_siteId_Site_id_fk": {
"name": "UserSite_siteId_Site_id_fk",
"tableFrom": "UserSite",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.User": {
"name": "User",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"email": {
"name": "email",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"password": {
"name": "password",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"role": {
"name": "role",
"type": "Role",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'VIEWER'"
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"resetToken": {
"name": "resetToken",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"resetTokenExpiry": {
"name": "resetTokenExpiry",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"isActive": {
"name": "isActive",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"partnerId": {
"name": "partnerId",
"type": "integer",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"User_email_idx": {
"name": "User_email_idx",
"columns": [
{
"expression": "email",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"User_role_idx": {
"name": "User_role_idx",
"columns": [
{
"expression": "role",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"User_partnerId_idx": {
"name": "User_partnerId_idx",
"columns": [
{
"expression": "partnerId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"User_partnerId_Partner_id_fk": {
"name": "User_partnerId_Partner_id_fk",
"tableFrom": "User",
"tableTo": "Partner",
"columnsFrom": [
"partnerId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"User_email_unique": {
"name": "User_email_unique",
"nullsNotDistinct": false,
"columns": [
"email"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {
"public.CompanyName": {
"name": "CompanyName",
"schema": "public",
"values": [
"VODAFONE",
"MEO",
"NOS",
"DIGI"
]
},
"public.InspectionResponseOption": {
"name": "InspectionResponseOption",
"schema": "public",
"values": [
"YES",
"NO",
"NA"
]
},
"public.InspectionStatus": {
"name": "InspectionStatus",
"schema": "public",
"values": [
"PENDING",
"IN_PROGRESS",
"COMPLETED",
"CANCELLED",
"APPROVING",
"REJECTED",
"APPROVED"
]
},
"public.Role": {
"name": "Role",
"schema": "public",
"values": [
"SUPERADMIN",
"ADMIN",
"MANAGER",
"PARTNER",
"OPERATOR",
"VIEWER"
]
}
},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
\ No newline at end of file
{
"id": "3f9651da-53c0-457d-aa93-623772881b62",
"prevId": "437e2688-7fbf-45dc-b324-6383453e7817",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.InspectionPhoto": {
"name": "InspectionPhoto",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"url": {
"name": "url",
"type": "varchar(500)",
"primaryKey": false,
"notNull": true
},
"filename": {
"name": "filename",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"mimeType": {
"name": "mimeType",
"type": "varchar(100)",
"primaryKey": false,
"notNull": true
},
"size": {
"name": "size",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"order": {
"name": "order",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"isPrincipal": {
"name": "isPrincipal",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"isResume": {
"name": "isResume",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"inspectionId": {
"name": "inspectionId",
"type": "integer",
"primaryKey": false,
"notNull": true
}
},
"indexes": {
"InspectionPhoto_inspectionId_idx": {
"name": "InspectionPhoto_inspectionId_idx",
"columns": [
{
"expression": "inspectionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"InspectionPhoto_inspectionId_Inspection_id_fk": {
"name": "InspectionPhoto_inspectionId_Inspection_id_fk",
"tableFrom": "InspectionPhoto",
"tableTo": "Inspection",
"columnsFrom": [
"inspectionId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.InspectionQuestion": {
"name": "InspectionQuestion",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"question": {
"name": "question",
"type": "text",
"primaryKey": false,
"notNull": true
},
"orderIndex": {
"name": "orderIndex",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.InspectionResponse": {
"name": "InspectionResponse",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"response": {
"name": "response",
"type": "InspectionResponseOption",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"comment": {
"name": "comment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"questionId": {
"name": "questionId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"inspectionId": {
"name": "inspectionId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"InspectionResponse_questionId_idx": {
"name": "InspectionResponse_questionId_idx",
"columns": [
{
"expression": "questionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"InspectionResponse_inspectionId_idx": {
"name": "InspectionResponse_inspectionId_idx",
"columns": [
{
"expression": "inspectionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"InspectionResponse_inspectionId_questionId_key": {
"name": "InspectionResponse_inspectionId_questionId_key",
"columns": [
{
"expression": "inspectionId",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "questionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"InspectionResponse_questionId_InspectionQuestion_id_fk": {
"name": "InspectionResponse_questionId_InspectionQuestion_id_fk",
"tableFrom": "InspectionResponse",
"tableTo": "InspectionQuestion",
"columnsFrom": [
"questionId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"InspectionResponse_inspectionId_Inspection_id_fk": {
"name": "InspectionResponse_inspectionId_Inspection_id_fk",
"tableFrom": "InspectionResponse",
"tableTo": "Inspection",
"columnsFrom": [
"inspectionId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.Inspection": {
"name": "Inspection",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"date": {
"name": "date",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"deadline": {
"name": "deadline",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"comment": {
"name": "comment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"finalComment": {
"name": "finalComment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"finalCommentStatus": {
"name": "finalCommentStatus",
"type": "InspectionStatus",
"typeSchema": "public",
"primaryKey": false,
"notNull": false,
"default": "'PENDING'"
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"createdById": {
"name": "createdById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"updatedById": {
"name": "updatedById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"submittedById": {
"name": "submittedById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"approvedById": {
"name": "approvedById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "InspectionStatus",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'PENDING'"
}
},
"indexes": {
"Inspection_siteId_idx": {
"name": "Inspection_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_createdById_idx": {
"name": "Inspection_createdById_idx",
"columns": [
{
"expression": "createdById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_updatedById_idx": {
"name": "Inspection_updatedById_idx",
"columns": [
{
"expression": "updatedById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_submittedById_idx": {
"name": "Inspection_submittedById_idx",
"columns": [
{
"expression": "submittedById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_approvedById_idx": {
"name": "Inspection_approvedById_idx",
"columns": [
{
"expression": "approvedById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_status_idx": {
"name": "Inspection_status_idx",
"columns": [
{
"expression": "status",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_finalCommentStatus_idx": {
"name": "Inspection_finalCommentStatus_idx",
"columns": [
{
"expression": "finalCommentStatus",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"Inspection_siteId_Site_id_fk": {
"name": "Inspection_siteId_Site_id_fk",
"tableFrom": "Inspection",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"Inspection_createdById_User_id_fk": {
"name": "Inspection_createdById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"createdById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Inspection_updatedById_User_id_fk": {
"name": "Inspection_updatedById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"updatedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Inspection_submittedById_User_id_fk": {
"name": "Inspection_submittedById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"submittedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Inspection_approvedById_User_id_fk": {
"name": "Inspection_approvedById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"approvedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.PartnerSite": {
"name": "PartnerSite",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"partnerId": {
"name": "partnerId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"PartnerSite_partnerId_siteId_key": {
"name": "PartnerSite_partnerId_siteId_key",
"columns": [
{
"expression": "partnerId",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"PartnerSite_partnerId_idx": {
"name": "PartnerSite_partnerId_idx",
"columns": [
{
"expression": "partnerId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"PartnerSite_siteId_idx": {
"name": "PartnerSite_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"PartnerSite_partnerId_Partner_id_fk": {
"name": "PartnerSite_partnerId_Partner_id_fk",
"tableFrom": "PartnerSite",
"tableTo": "Partner",
"columnsFrom": [
"partnerId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"PartnerSite_siteId_Site_id_fk": {
"name": "PartnerSite_siteId_Site_id_fk",
"tableFrom": "PartnerSite",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.Partner": {
"name": "Partner",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"isActive": {
"name": "isActive",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"Partner_name_idx": {
"name": "Partner_name_idx",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"Partner_name_unique": {
"name": "Partner_name_unique",
"nullsNotDistinct": false,
"columns": [
"name"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.RefreshToken": {
"name": "RefreshToken",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"token": {
"name": "token",
"type": "varchar(500)",
"primaryKey": false,
"notNull": true
},
"userId": {
"name": "userId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"expiresAt": {
"name": "expiresAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"RefreshToken_token_idx": {
"name": "RefreshToken_token_idx",
"columns": [
{
"expression": "token",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"RefreshToken_userId_idx": {
"name": "RefreshToken_userId_idx",
"columns": [
{
"expression": "userId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"RefreshToken_userId_User_id_fk": {
"name": "RefreshToken_userId_User_id_fk",
"tableFrom": "RefreshToken",
"tableTo": "User",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"RefreshToken_token_unique": {
"name": "RefreshToken_token_unique",
"nullsNotDistinct": false,
"columns": [
"token"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.Site": {
"name": "Site",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"siteCode": {
"name": "siteCode",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"siteName": {
"name": "siteName",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"latitude": {
"name": "latitude",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"longitude": {
"name": "longitude",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"createdById": {
"name": "createdById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"updatedById": {
"name": "updatedById",
"type": "integer",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"Site_siteCode_idx": {
"name": "Site_siteCode_idx",
"columns": [
{
"expression": "siteCode",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"Site_createdById_User_id_fk": {
"name": "Site_createdById_User_id_fk",
"tableFrom": "Site",
"tableTo": "User",
"columnsFrom": [
"createdById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Site_updatedById_User_id_fk": {
"name": "Site_updatedById_User_id_fk",
"tableFrom": "Site",
"tableTo": "User",
"columnsFrom": [
"updatedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"Site_siteCode_unique": {
"name": "Site_siteCode_unique",
"nullsNotDistinct": false,
"columns": [
"siteCode"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.spatial_ref_sys": {
"name": "spatial_ref_sys",
"schema": "",
"columns": {
"srid": {
"name": "srid",
"type": "integer",
"primaryKey": true,
"notNull": true
},
"auth_name": {
"name": "auth_name",
"type": "varchar(256)",
"primaryKey": false,
"notNull": false
},
"auth_srid": {
"name": "auth_srid",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"srtext": {
"name": "srtext",
"type": "varchar(2048)",
"primaryKey": false,
"notNull": false
},
"proj4text": {
"name": "proj4text",
"type": "varchar(2048)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.TelecommunicationStationIdentification": {
"name": "TelecommunicationStationIdentification",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"stationIdentifier": {
"name": "stationIdentifier",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"serialNumber": {
"name": "serialNumber",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"isFirstCertification": {
"name": "isFirstCertification",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"modelReference": {
"name": "modelReference",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"TelecommunicationStationIdentification_siteId_idx": {
"name": "TelecommunicationStationIdentification_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"TelecommunicationStationIdentification_stationIdentifier_idx": {
"name": "TelecommunicationStationIdentification_stationIdentifier_idx",
"columns": [
{
"expression": "stationIdentifier",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"TelecommunicationStationIdentification_siteId_Site_id_fk": {
"name": "TelecommunicationStationIdentification_siteId_Site_id_fk",
"tableFrom": "TelecommunicationStationIdentification",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"TelecommunicationStationIdentification_siteId_unique": {
"name": "TelecommunicationStationIdentification_siteId_unique",
"nullsNotDistinct": false,
"columns": [
"siteId"
]
},
"TelecommunicationStationIdentification_stationIdentifier_unique": {
"name": "TelecommunicationStationIdentification_stationIdentifier_unique",
"nullsNotDistinct": false,
"columns": [
"stationIdentifier"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.UserSite": {
"name": "UserSite",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"userId": {
"name": "userId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"UserSite_userId_siteId_key": {
"name": "UserSite_userId_siteId_key",
"columns": [
{
"expression": "userId",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"UserSite_userId_idx": {
"name": "UserSite_userId_idx",
"columns": [
{
"expression": "userId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"UserSite_siteId_idx": {
"name": "UserSite_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"UserSite_userId_User_id_fk": {
"name": "UserSite_userId_User_id_fk",
"tableFrom": "UserSite",
"tableTo": "User",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"UserSite_siteId_Site_id_fk": {
"name": "UserSite_siteId_Site_id_fk",
"tableFrom": "UserSite",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.User": {
"name": "User",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"email": {
"name": "email",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"password": {
"name": "password",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"role": {
"name": "role",
"type": "Role",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'VIEWER'"
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"resetToken": {
"name": "resetToken",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"resetTokenExpiry": {
"name": "resetTokenExpiry",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"isActive": {
"name": "isActive",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"partnerId": {
"name": "partnerId",
"type": "integer",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"User_email_idx": {
"name": "User_email_idx",
"columns": [
{
"expression": "email",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"User_role_idx": {
"name": "User_role_idx",
"columns": [
{
"expression": "role",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"User_partnerId_idx": {
"name": "User_partnerId_idx",
"columns": [
{
"expression": "partnerId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"User_partnerId_Partner_id_fk": {
"name": "User_partnerId_Partner_id_fk",
"tableFrom": "User",
"tableTo": "Partner",
"columnsFrom": [
"partnerId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"User_email_unique": {
"name": "User_email_unique",
"nullsNotDistinct": false,
"columns": [
"email"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {
"public.CompanyName": {
"name": "CompanyName",
"schema": "public",
"values": [
"VODAFONE",
"MEO",
"NOS",
"DIGI"
]
},
"public.InspectionResponseOption": {
"name": "InspectionResponseOption",
"schema": "public",
"values": [
"YES",
"NO",
"NA"
]
},
"public.InspectionStatus": {
"name": "InspectionStatus",
"schema": "public",
"values": [
"PENDING",
"IN_PROGRESS",
"COMPLETED",
"CANCELLED",
"APPROVING",
"REJECTED",
"APPROVED"
]
},
"public.Role": {
"name": "Role",
"schema": "public",
"values": [
"SUPERADMIN",
"ADMIN",
"MANAGER",
"PARTNER",
"OPERATOR",
"VIEWER"
]
}
},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
\ No newline at end of file
{
"id": "9bcdebf6-6471-40a9-972e-3e5fdc48930b",
"prevId": "3f9651da-53c0-457d-aa93-623772881b62",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.InspectionPhoto": {
"name": "InspectionPhoto",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"url": {
"name": "url",
"type": "varchar(500)",
"primaryKey": false,
"notNull": true
},
"filename": {
"name": "filename",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"mimeType": {
"name": "mimeType",
"type": "varchar(100)",
"primaryKey": false,
"notNull": true
},
"size": {
"name": "size",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"order": {
"name": "order",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"isPrincipal": {
"name": "isPrincipal",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"isResume": {
"name": "isResume",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"inspectionId": {
"name": "inspectionId",
"type": "integer",
"primaryKey": false,
"notNull": true
}
},
"indexes": {
"InspectionPhoto_inspectionId_idx": {
"name": "InspectionPhoto_inspectionId_idx",
"columns": [
{
"expression": "inspectionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"InspectionPhoto_inspectionId_Inspection_id_fk": {
"name": "InspectionPhoto_inspectionId_Inspection_id_fk",
"tableFrom": "InspectionPhoto",
"tableTo": "Inspection",
"columnsFrom": [
"inspectionId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.InspectionQuestion": {
"name": "InspectionQuestion",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"question": {
"name": "question",
"type": "text",
"primaryKey": false,
"notNull": true
},
"orderIndex": {
"name": "orderIndex",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.InspectionResponse": {
"name": "InspectionResponse",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"response": {
"name": "response",
"type": "InspectionResponseOption",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"comment": {
"name": "comment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"questionId": {
"name": "questionId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"inspectionId": {
"name": "inspectionId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"InspectionResponse_questionId_idx": {
"name": "InspectionResponse_questionId_idx",
"columns": [
{
"expression": "questionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"InspectionResponse_inspectionId_idx": {
"name": "InspectionResponse_inspectionId_idx",
"columns": [
{
"expression": "inspectionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"InspectionResponse_inspectionId_questionId_key": {
"name": "InspectionResponse_inspectionId_questionId_key",
"columns": [
{
"expression": "inspectionId",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "questionId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"InspectionResponse_questionId_InspectionQuestion_id_fk": {
"name": "InspectionResponse_questionId_InspectionQuestion_id_fk",
"tableFrom": "InspectionResponse",
"tableTo": "InspectionQuestion",
"columnsFrom": [
"questionId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"InspectionResponse_inspectionId_Inspection_id_fk": {
"name": "InspectionResponse_inspectionId_Inspection_id_fk",
"tableFrom": "InspectionResponse",
"tableTo": "Inspection",
"columnsFrom": [
"inspectionId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.Inspection": {
"name": "Inspection",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"date": {
"name": "date",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"deadline": {
"name": "deadline",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"comment": {
"name": "comment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"finalComment": {
"name": "finalComment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"finalCommentStatus": {
"name": "finalCommentStatus",
"type": "InspectionStatus",
"typeSchema": "public",
"primaryKey": false,
"notNull": false,
"default": "'PENDING'"
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"createdById": {
"name": "createdById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"updatedById": {
"name": "updatedById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"submittedById": {
"name": "submittedById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"approvedById": {
"name": "approvedById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "InspectionStatus",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'PENDING'"
}
},
"indexes": {
"Inspection_siteId_idx": {
"name": "Inspection_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_createdById_idx": {
"name": "Inspection_createdById_idx",
"columns": [
{
"expression": "createdById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_updatedById_idx": {
"name": "Inspection_updatedById_idx",
"columns": [
{
"expression": "updatedById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_submittedById_idx": {
"name": "Inspection_submittedById_idx",
"columns": [
{
"expression": "submittedById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_approvedById_idx": {
"name": "Inspection_approvedById_idx",
"columns": [
{
"expression": "approvedById",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_status_idx": {
"name": "Inspection_status_idx",
"columns": [
{
"expression": "status",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"Inspection_finalCommentStatus_idx": {
"name": "Inspection_finalCommentStatus_idx",
"columns": [
{
"expression": "finalCommentStatus",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"Inspection_siteId_Site_id_fk": {
"name": "Inspection_siteId_Site_id_fk",
"tableFrom": "Inspection",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"Inspection_createdById_User_id_fk": {
"name": "Inspection_createdById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"createdById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Inspection_updatedById_User_id_fk": {
"name": "Inspection_updatedById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"updatedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Inspection_submittedById_User_id_fk": {
"name": "Inspection_submittedById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"submittedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Inspection_approvedById_User_id_fk": {
"name": "Inspection_approvedById_User_id_fk",
"tableFrom": "Inspection",
"tableTo": "User",
"columnsFrom": [
"approvedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.PartnerSite": {
"name": "PartnerSite",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"partnerId": {
"name": "partnerId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"PartnerSite_partnerId_siteId_key": {
"name": "PartnerSite_partnerId_siteId_key",
"columns": [
{
"expression": "partnerId",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"PartnerSite_partnerId_idx": {
"name": "PartnerSite_partnerId_idx",
"columns": [
{
"expression": "partnerId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"PartnerSite_siteId_idx": {
"name": "PartnerSite_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"PartnerSite_partnerId_Partner_id_fk": {
"name": "PartnerSite_partnerId_Partner_id_fk",
"tableFrom": "PartnerSite",
"tableTo": "Partner",
"columnsFrom": [
"partnerId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"PartnerSite_siteId_Site_id_fk": {
"name": "PartnerSite_siteId_Site_id_fk",
"tableFrom": "PartnerSite",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.Partner": {
"name": "Partner",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"logo": {
"name": "logo",
"type": "varchar(500)",
"primaryKey": false,
"notNull": false
},
"isActive": {
"name": "isActive",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"Partner_name_idx": {
"name": "Partner_name_idx",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"Partner_name_unique": {
"name": "Partner_name_unique",
"nullsNotDistinct": false,
"columns": [
"name"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.RefreshToken": {
"name": "RefreshToken",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"token": {
"name": "token",
"type": "varchar(500)",
"primaryKey": false,
"notNull": true
},
"userId": {
"name": "userId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"expiresAt": {
"name": "expiresAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"RefreshToken_token_idx": {
"name": "RefreshToken_token_idx",
"columns": [
{
"expression": "token",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"RefreshToken_userId_idx": {
"name": "RefreshToken_userId_idx",
"columns": [
{
"expression": "userId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"RefreshToken_userId_User_id_fk": {
"name": "RefreshToken_userId_User_id_fk",
"tableFrom": "RefreshToken",
"tableTo": "User",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"RefreshToken_token_unique": {
"name": "RefreshToken_token_unique",
"nullsNotDistinct": false,
"columns": [
"token"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.Site": {
"name": "Site",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"siteCode": {
"name": "siteCode",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"siteName": {
"name": "siteName",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"latitude": {
"name": "latitude",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"longitude": {
"name": "longitude",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"createdById": {
"name": "createdById",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"updatedById": {
"name": "updatedById",
"type": "integer",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"Site_siteCode_idx": {
"name": "Site_siteCode_idx",
"columns": [
{
"expression": "siteCode",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"Site_createdById_User_id_fk": {
"name": "Site_createdById_User_id_fk",
"tableFrom": "Site",
"tableTo": "User",
"columnsFrom": [
"createdById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"Site_updatedById_User_id_fk": {
"name": "Site_updatedById_User_id_fk",
"tableFrom": "Site",
"tableTo": "User",
"columnsFrom": [
"updatedById"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"Site_siteCode_unique": {
"name": "Site_siteCode_unique",
"nullsNotDistinct": false,
"columns": [
"siteCode"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.spatial_ref_sys": {
"name": "spatial_ref_sys",
"schema": "",
"columns": {
"srid": {
"name": "srid",
"type": "integer",
"primaryKey": true,
"notNull": true
},
"auth_name": {
"name": "auth_name",
"type": "varchar(256)",
"primaryKey": false,
"notNull": false
},
"auth_srid": {
"name": "auth_srid",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"srtext": {
"name": "srtext",
"type": "varchar(2048)",
"primaryKey": false,
"notNull": false
},
"proj4text": {
"name": "proj4text",
"type": "varchar(2048)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.TelecommunicationStationIdentification": {
"name": "TelecommunicationStationIdentification",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"stationIdentifier": {
"name": "stationIdentifier",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"serialNumber": {
"name": "serialNumber",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"isFirstCertification": {
"name": "isFirstCertification",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"modelReference": {
"name": "modelReference",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"TelecommunicationStationIdentification_siteId_idx": {
"name": "TelecommunicationStationIdentification_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"TelecommunicationStationIdentification_stationIdentifier_idx": {
"name": "TelecommunicationStationIdentification_stationIdentifier_idx",
"columns": [
{
"expression": "stationIdentifier",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"TelecommunicationStationIdentification_siteId_Site_id_fk": {
"name": "TelecommunicationStationIdentification_siteId_Site_id_fk",
"tableFrom": "TelecommunicationStationIdentification",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"TelecommunicationStationIdentification_siteId_unique": {
"name": "TelecommunicationStationIdentification_siteId_unique",
"nullsNotDistinct": false,
"columns": [
"siteId"
]
},
"TelecommunicationStationIdentification_stationIdentifier_unique": {
"name": "TelecommunicationStationIdentification_stationIdentifier_unique",
"nullsNotDistinct": false,
"columns": [
"stationIdentifier"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.UserSite": {
"name": "UserSite",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"userId": {
"name": "userId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"siteId": {
"name": "siteId",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"UserSite_userId_siteId_key": {
"name": "UserSite_userId_siteId_key",
"columns": [
{
"expression": "userId",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"UserSite_userId_idx": {
"name": "UserSite_userId_idx",
"columns": [
{
"expression": "userId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"UserSite_siteId_idx": {
"name": "UserSite_siteId_idx",
"columns": [
{
"expression": "siteId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"UserSite_userId_User_id_fk": {
"name": "UserSite_userId_User_id_fk",
"tableFrom": "UserSite",
"tableTo": "User",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"UserSite_siteId_Site_id_fk": {
"name": "UserSite_siteId_Site_id_fk",
"tableFrom": "UserSite",
"tableTo": "Site",
"columnsFrom": [
"siteId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.User": {
"name": "User",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"email": {
"name": "email",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"password": {
"name": "password",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"role": {
"name": "role",
"type": "Role",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'VIEWER'"
},
"signature": {
"name": "signature",
"type": "varchar(500)",
"primaryKey": false,
"notNull": false
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"resetToken": {
"name": "resetToken",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"resetTokenExpiry": {
"name": "resetTokenExpiry",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"isActive": {
"name": "isActive",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"partnerId": {
"name": "partnerId",
"type": "integer",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"User_email_idx": {
"name": "User_email_idx",
"columns": [
{
"expression": "email",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"User_role_idx": {
"name": "User_role_idx",
"columns": [
{
"expression": "role",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"User_partnerId_idx": {
"name": "User_partnerId_idx",
"columns": [
{
"expression": "partnerId",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"User_partnerId_Partner_id_fk": {
"name": "User_partnerId_Partner_id_fk",
"tableFrom": "User",
"tableTo": "Partner",
"columnsFrom": [
"partnerId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"User_email_unique": {
"name": "User_email_unique",
"nullsNotDistinct": false,
"columns": [
"email"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {
"public.CompanyName": {
"name": "CompanyName",
"schema": "public",
"values": [
"VODAFONE",
"MEO",
"NOS",
"DIGI"
]
},
"public.InspectionResponseOption": {
"name": "InspectionResponseOption",
"schema": "public",
"values": [
"YES",
"NO",
"NA"
]
},
"public.InspectionStatus": {
"name": "InspectionStatus",
"schema": "public",
"values": [
"PENDING",
"IN_PROGRESS",
"COMPLETED",
"CANCELLED",
"APPROVING",
"REJECTED",
"APPROVED"
]
},
"public.Role": {
"name": "Role",
"schema": "public",
"values": [
"SUPERADMIN",
"ADMIN",
"MANAGER",
"PARTNER",
"OPERATOR",
"VIEWER"
]
}
},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
\ No newline at end of file
...@@ -22,6 +22,48 @@ ...@@ -22,6 +22,48 @@
"when": 1758185080204, "when": 1758185080204,
"tag": "0002_furry_genesis", "tag": "0002_furry_genesis",
"breakpoints": true "breakpoints": true
},
{
"idx": 3,
"version": "7",
"when": 1758642221769,
"tag": "0003_stiff_songbird",
"breakpoints": true
},
{
"idx": 4,
"version": "7",
"when": 1759245696335,
"tag": "0004_curvy_the_order",
"breakpoints": true
},
{
"idx": 5,
"version": "7",
"when": 1759738370590,
"tag": "0005_pink_fantastic_four",
"breakpoints": true
},
{
"idx": 6,
"version": "7",
"when": 1759738458247,
"tag": "0006_large_puppet_master",
"breakpoints": true
},
{
"idx": 7,
"version": "7",
"when": 1759738687335,
"tag": "0007_flimsy_malcolm_colcord",
"breakpoints": true
},
{
"idx": 8,
"version": "7",
"when": 1759738883201,
"tag": "0008_adorable_quentin_quire",
"breakpoints": true
} }
] ]
} }
\ No newline at end of file
-- Migration script to add submittedById and approvedById fields to Inspection table
-- This script adds the fields to track who submitted inspections to APPROVING status
-- and who approved the inspections
-- Add the new columns to the Inspection table
ALTER TABLE "Inspection"
ADD COLUMN "submittedById" INTEGER REFERENCES "User"("id"),
ADD COLUMN "approvedById" INTEGER REFERENCES "User"("id");
-- Create indexes for the new columns for better query performance
CREATE INDEX "Inspection_submittedById_idx" ON "Inspection"("submittedById");
CREATE INDEX "Inspection_approvedById_idx" ON "Inspection"("approvedById");
-- Optional: Add comments to document the purpose of these fields
COMMENT ON COLUMN "Inspection"."submittedById" IS 'User who submitted the inspection to APPROVING status';
COMMENT ON COLUMN "Inspection"."approvedById" IS 'User who approved the inspection (status APPROVED)';
-- Verify the changes
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_name = 'Inspection'
AND column_name IN ('submittedById', 'approvedById');
-- Check indexes were created
SELECT indexname, indexdef
FROM pg_indexes
WHERE tablename = 'Inspection'
AND indexname IN ('Inspection_submittedById_idx', 'Inspection_approvedById_idx');
-- Migration script to update finalCommentStatus from FinalCommentStatus to InspectionStatus
-- This script safely converts existing data
-- Step 1: Drop the default constraint
ALTER TABLE "Inspection" ALTER COLUMN "finalCommentStatus" DROP DEFAULT;
-- Step 2: Change the column type from FinalCommentStatus to InspectionStatus
-- This will convert: VALIDATED -> APPROVED, PENDING -> PENDING, REJECTED -> REJECTED
ALTER TABLE "Inspection" ALTER COLUMN "finalCommentStatus" SET DATA TYPE "public"."InspectionStatus"
USING CASE
WHEN "finalCommentStatus"::text = 'VALIDATED' THEN 'APPROVED'::"public"."InspectionStatus"
WHEN "finalCommentStatus"::text = 'PENDING' THEN 'PENDING'::"public"."InspectionStatus"
WHEN "finalCommentStatus"::text = 'REJECTED' THEN 'REJECTED'::"public"."InspectionStatus"
ELSE 'PENDING'::"public"."InspectionStatus"
END;
-- Step 3: Set the new default
ALTER TABLE "Inspection" ALTER COLUMN "finalCommentStatus" SET DEFAULT 'PENDING';
-- Step 4: Drop the old enum type
DROP TYPE "public"."FinalCommentStatus";
-- Migration to add constraint for maximum 6 resume photos per inspection
-- This ensures data integrity at the database level
-- First, let's create a function to check the constraint
CREATE OR REPLACE FUNCTION check_max_resume_photos()
RETURNS TRIGGER AS $$
BEGIN
-- Only check when isResume is being set to true
IF NEW.isResume = true THEN
-- Count existing resume photos for this inspection
IF (
SELECT COUNT(*)
FROM "InspectionPhoto"
WHERE "inspectionId" = NEW."inspectionId"
AND "isResume" = true
AND "id" != COALESCE(NEW."id", 0)
) >= 6 THEN
RAISE EXCEPTION 'Maximum of 6 resume photos allowed per inspection';
END IF;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Create trigger for INSERT operations
DROP TRIGGER IF EXISTS check_resume_photos_insert ON "InspectionPhoto";
CREATE TRIGGER check_resume_photos_insert
BEFORE INSERT ON "InspectionPhoto"
FOR EACH ROW
EXECUTE FUNCTION check_max_resume_photos();
-- Create trigger for UPDATE operations
DROP TRIGGER IF EXISTS check_resume_photos_update ON "InspectionPhoto";
CREATE TRIGGER check_resume_photos_update
BEFORE UPDATE ON "InspectionPhoto"
FOR EACH ROW
EXECUTE FUNCTION check_max_resume_photos();
import { Controller, Get } from '@nestjs/common'; import { Controller, Get, Res } from '@nestjs/common';
import { AppService } from './app.service'; import { AppService } from './app.service';
import { Response } from 'express';
import * as fs from 'fs';
import * as path from 'path';
@Controller() @Controller()
export class AppController { export class AppController {
...@@ -9,4 +12,39 @@ export class AppController { ...@@ -9,4 +12,39 @@ export class AppController {
getHello(): string { getHello(): string {
return this.appService.getHello(); return this.appService.getHello();
} }
@Get('debug/files')
async debugFiles(@Res() res: Response) {
const uploadBasePath =
process.env.UPLOAD_BASE_PATH ||
(process.env.NODE_ENV === 'production'
? '/home/api-verticalflow/public_html/uploads'
: path.join(process.cwd(), 'uploads'));
const signaturesDir = path.join(uploadBasePath, 'signatures');
const logosDir = path.join(uploadBasePath, 'logos');
const inspectionDir = path.join(uploadBasePath, 'inspection');
const debugInfo = {
uploadBasePath,
signaturesDir: {
exists: fs.existsSync(signaturesDir),
files: fs.existsSync(signaturesDir)
? fs.readdirSync(signaturesDir)
: [],
},
logosDir: {
exists: fs.existsSync(logosDir),
files: fs.existsSync(logosDir) ? fs.readdirSync(logosDir) : [],
},
inspectionDir: {
exists: fs.existsSync(inspectionDir),
files: fs.existsSync(inspectionDir)
? fs.readdirSync(inspectionDir)
: [],
},
};
res.json(debugInfo);
}
} }
import * as fs from 'fs';
import * as path from 'path';
import { promisify } from 'util';
const mkdir = promisify(fs.mkdir);
const writeFile = promisify(fs.writeFile);
/**
* Saves uploaded signature image to the file system
* @param file Uploaded file
* @param userId The ID of the user
* @returns Saved file path
*/
export async function saveUserSignature(
file: Express.Multer.File,
userId: number,
): Promise<string> {
if (!file || !file.buffer) {
throw new Error('Invalid file provided - missing buffer');
}
// Validate userId
if (!userId || userId <= 0) {
throw new Error('Invalid user ID provided');
}
// Use environment variable for upload path, with fallback to default
const baseUploadPath =
process.env.UPLOAD_BASE_PATH ||
(process.env.NODE_ENV === 'production'
? '/home/api-verticalflow/public_html/uploads'
: path.join(process.cwd(), 'uploads'));
const uploadDir = path.join(baseUploadPath, 'signatures');
// Create directory if it doesn't exist
let finalUploadDir = uploadDir;
try {
// First, try to create the base uploads directory if it doesn't exist
await mkdir(baseUploadPath, { recursive: true, mode: 0o755 });
// Then create the signatures directory
await mkdir(uploadDir, { recursive: true, mode: 0o755 });
console.log(`Created signatures directory: ${uploadDir}`);
} catch (error) {
console.error('Error creating upload directory:', error);
// Fallback to temp directory if main upload directory fails
finalUploadDir = path.join('/tmp', 'uploads', 'signatures');
try {
await mkdir(finalUploadDir, { recursive: true, mode: 0o755 });
console.log(`Created fallback signatures directory: ${finalUploadDir}`);
} catch (fallbackError) {
console.error('Error creating fallback directory:', fallbackError);
throw new Error('Failed to create upload directory');
}
}
// Generate unique filename
const timestamp = Date.now();
const extension = path.extname(file.originalname || '');
const filename = `user_${userId}_signature_${timestamp}${extension}`;
const filePath = path.join(finalUploadDir, filename);
try {
await writeFile(filePath, file.buffer);
console.log(`Signature file saved to: ${filePath}`);
// Generate the URL path based on the actual directory used
let urlPath;
if (finalUploadDir.startsWith('/tmp')) {
// For fallback directory, use a different URL pattern
urlPath = `/tmp-uploads/signatures/${filename}`;
} else {
urlPath = `/uploads/signatures/${filename}`;
}
console.log(`Signature file URL: ${urlPath}`);
return urlPath;
} catch (error) {
console.error(`Error saving signature file ${filename}:`, error);
throw new Error(
`Failed to save signature file ${filename}: ${error.message}`,
);
}
}
/**
* Saves uploaded logo image to the file system
* @param file Uploaded file
* @param partnerId The ID of the partner
* @returns Saved file path
*/
export async function savePartnerLogo(
file: Express.Multer.File,
partnerId: number,
): Promise<string> {
if (!file || !file.buffer) {
throw new Error('Invalid file provided - missing buffer');
}
// Validate partnerId
if (!partnerId || partnerId <= 0) {
throw new Error('Invalid partner ID provided');
}
// Use environment variable for upload path, with fallback to default
const baseUploadPath =
process.env.UPLOAD_BASE_PATH ||
(process.env.NODE_ENV === 'production'
? '/home/api-verticalflow/public_html/uploads'
: path.join(process.cwd(), 'uploads'));
const uploadDir = path.join(baseUploadPath, 'logos');
// Create directory if it doesn't exist
let finalUploadDir = uploadDir;
try {
// First, try to create the base uploads directory if it doesn't exist
await mkdir(baseUploadPath, { recursive: true, mode: 0o755 });
// Then create the logos directory
await mkdir(uploadDir, { recursive: true, mode: 0o755 });
console.log(`Created logos directory: ${uploadDir}`);
} catch (error) {
console.error('Error creating upload directory:', error);
// Fallback to temp directory if main upload directory fails
finalUploadDir = path.join('/tmp', 'uploads', 'logos');
try {
await mkdir(finalUploadDir, { recursive: true, mode: 0o755 });
console.log(`Created fallback logos directory: ${finalUploadDir}`);
} catch (fallbackError) {
console.error('Error creating fallback directory:', fallbackError);
throw new Error('Failed to create upload directory');
}
}
// Generate unique filename
const timestamp = Date.now();
const extension = path.extname(file.originalname || '');
const filename = `partner_${partnerId}_logo_${timestamp}${extension}`;
const filePath = path.join(finalUploadDir, filename);
try {
await writeFile(filePath, file.buffer);
console.log(`Logo file saved to: ${filePath}`);
// Generate the URL path based on the actual directory used
let urlPath;
if (finalUploadDir.startsWith('/tmp')) {
// For fallback directory, use a different URL pattern
urlPath = `/tmp-uploads/logos/${filename}`;
} else {
urlPath = `/uploads/logos/${filename}`;
}
console.log(`Logo file URL: ${urlPath}`);
return urlPath;
} catch (error) {
console.error(`Error saving logo file ${filename}:`, error);
throw new Error(`Failed to save logo file ${filename}: ${error.message}`);
}
}
...@@ -46,12 +46,6 @@ export const inspectionStatusEnum = pgEnum('InspectionStatus', [ ...@@ -46,12 +46,6 @@ export const inspectionStatusEnum = pgEnum('InspectionStatus', [
'APPROVED', 'APPROVED',
]); ]);
export const finalCommentStatusEnum = pgEnum('FinalCommentStatus', [
'PENDING', // Operator created, waiting for partner validation
'VALIDATED', // Partner validated, visible to admin/superadmin/manager
'REJECTED', // Partner rejected, needs revision
]);
// Tables // Tables
export const users = pgTable( export const users = pgTable(
'User', 'User',
...@@ -61,11 +55,12 @@ export const users = pgTable( ...@@ -61,11 +55,12 @@ export const users = pgTable(
name: varchar('name', { length: 255 }).notNull(), name: varchar('name', { length: 255 }).notNull(),
password: varchar('password', { length: 255 }).notNull(), password: varchar('password', { length: 255 }).notNull(),
role: roleEnum('role').notNull().default('VIEWER'), role: roleEnum('role').notNull().default('VIEWER'),
signature: varchar('signature', { length: 500 }),
createdAt: timestamp('createdAt').notNull().defaultNow(), createdAt: timestamp('createdAt').notNull().defaultNow(),
updatedAt: timestamp('updatedAt').notNull().defaultNow(), updatedAt: timestamp('updatedAt').notNull().defaultNow(),
resetToken: varchar('resetToken', { length: 255 }), resetToken: varchar('resetToken', { length: 255 }),
resetTokenExpiry: timestamp('resetTokenExpiry'), resetTokenExpiry: timestamp('resetTokenExpiry'),
isActive: boolean('isActive').notNull().default(false), isActive: boolean('isActive').notNull().default(true),
partnerId: integer('partnerId').references(() => partners.id), partnerId: integer('partnerId').references(() => partners.id),
}, },
(table) => ({ (table) => ({
...@@ -98,6 +93,7 @@ export const partners = pgTable( ...@@ -98,6 +93,7 @@ export const partners = pgTable(
id: serial('id').primaryKey(), id: serial('id').primaryKey(),
name: varchar('name', { length: 255 }).notNull().unique(), name: varchar('name', { length: 255 }).notNull().unique(),
description: text('description'), description: text('description'),
logo: varchar('logo', { length: 500 }),
isActive: boolean('isActive').notNull().default(true), isActive: boolean('isActive').notNull().default(true),
createdAt: timestamp('createdAt').notNull().defaultNow(), createdAt: timestamp('createdAt').notNull().defaultNow(),
updatedAt: timestamp('updatedAt').notNull().defaultNow(), updatedAt: timestamp('updatedAt').notNull().defaultNow(),
...@@ -188,7 +184,7 @@ export const inspections = pgTable( ...@@ -188,7 +184,7 @@ export const inspections = pgTable(
comment: text('comment'), comment: text('comment'),
finalComment: text('finalComment'), finalComment: text('finalComment'),
finalCommentStatus: finalCommentStatus:
finalCommentStatusEnum('finalCommentStatus').default('PENDING'), inspectionStatusEnum('finalCommentStatus').default('PENDING'),
siteId: integer('siteId') siteId: integer('siteId')
.notNull() .notNull()
.references(() => sites.id, { onDelete: 'cascade' }), .references(() => sites.id, { onDelete: 'cascade' }),
...@@ -196,12 +192,18 @@ export const inspections = pgTable( ...@@ -196,12 +192,18 @@ export const inspections = pgTable(
updatedAt: timestamp('updatedAt').notNull().defaultNow(), updatedAt: timestamp('updatedAt').notNull().defaultNow(),
createdById: integer('createdById').references(() => users.id), createdById: integer('createdById').references(() => users.id),
updatedById: integer('updatedById').references(() => users.id), updatedById: integer('updatedById').references(() => users.id),
submittedById: integer('submittedById').references(() => users.id),
approvedById: integer('approvedById').references(() => users.id),
status: inspectionStatusEnum('status').notNull().default('PENDING'), status: inspectionStatusEnum('status').notNull().default('PENDING'),
}, },
(table) => ({ (table) => ({
siteIdx: index('Inspection_siteId_idx').on(table.siteId), siteIdx: index('Inspection_siteId_idx').on(table.siteId),
createdByIdx: index('Inspection_createdById_idx').on(table.createdById), createdByIdx: index('Inspection_createdById_idx').on(table.createdById),
updatedByIdx: index('Inspection_updatedById_idx').on(table.updatedById), updatedByIdx: index('Inspection_updatedById_idx').on(table.updatedById),
submittedByIdx: index('Inspection_submittedById_idx').on(
table.submittedById,
),
approvedByIdx: index('Inspection_approvedById_idx').on(table.approvedById),
statusIdx: index('Inspection_status_idx').on(table.status), statusIdx: index('Inspection_status_idx').on(table.status),
finalCommentStatusIdx: index('Inspection_finalCommentStatus_idx').on( finalCommentStatusIdx: index('Inspection_finalCommentStatus_idx').on(
table.finalCommentStatus, table.finalCommentStatus,
...@@ -247,6 +249,9 @@ export const inspectionPhotos = pgTable( ...@@ -247,6 +249,9 @@ export const inspectionPhotos = pgTable(
mimeType: varchar('mimeType', { length: 100 }).notNull(), mimeType: varchar('mimeType', { length: 100 }).notNull(),
size: integer('size').notNull(), size: integer('size').notNull(),
description: text('description'), description: text('description'),
order: integer('order').notNull().default(0),
isPrincipal: boolean('isPrincipal').notNull().default(false),
isResume: boolean('isResume').notNull().default(false),
createdAt: timestamp('createdAt').notNull().defaultNow(), createdAt: timestamp('createdAt').notNull().defaultNow(),
updatedAt: timestamp('updatedAt').notNull().defaultNow(), updatedAt: timestamp('updatedAt').notNull().defaultNow(),
inspectionId: integer('inspectionId') inspectionId: integer('inspectionId')
...@@ -384,6 +389,16 @@ export const inspectionsRelations = relations(inspections, ({ one, many }) => ({ ...@@ -384,6 +389,16 @@ export const inspectionsRelations = relations(inspections, ({ one, many }) => ({
references: [users.id], references: [users.id],
relationName: 'inspectionUpdater', relationName: 'inspectionUpdater',
}), }),
submittedBy: one(users, {
fields: [inspections.submittedById],
references: [users.id],
relationName: 'inspectionSubmitter',
}),
approvedBy: one(users, {
fields: [inspections.approvedById],
references: [users.id],
relationName: 'inspectionApprover',
}),
responses: many(inspectionResponses), responses: many(inspectionResponses),
photos: many(inspectionPhotos), photos: many(inspectionPhotos),
})); }));
......
...@@ -30,10 +30,44 @@ async function bootstrap() { ...@@ -30,10 +30,44 @@ async function bootstrap() {
? '/home/api-verticalflow/public_html/uploads' ? '/home/api-verticalflow/public_html/uploads'
: join(__dirname, '..', 'uploads')); : join(__dirname, '..', 'uploads'));
app.use('/uploads', express.static(uploadBasePath)); // Serve static files with explicit options
app.use(
'/uploads',
express.static(uploadBasePath, {
dotfiles: 'ignore',
etag: true,
lastModified: true,
maxAge: '1d',
setHeaders: (res, path) => {
// Set proper headers for images
if (
path.endsWith('.png') ||
path.endsWith('.jpg') ||
path.endsWith('.jpeg') ||
path.endsWith('.gif')
) {
res.setHeader('Content-Type', 'image/png');
}
},
}),
);
// Debug: Log static file serving configuration
console.log(`Static file serving configured for: ${uploadBasePath}`);
console.log(
`Files should be accessible at: /uploads/signatures/ and /uploads/logos/`,
);
// Serve fallback uploads from /tmp if needed // Serve fallback uploads from /tmp if needed
app.use('/tmp-uploads', express.static('/tmp/uploads')); app.use(
'/tmp-uploads',
express.static('/tmp/uploads', {
dotfiles: 'ignore',
etag: true,
lastModified: true,
maxAge: '1d',
}),
);
// Swagger configuration // Swagger configuration
const config = new DocumentBuilder() const config = new DocumentBuilder()
......
...@@ -73,8 +73,8 @@ export class AuthService { ...@@ -73,8 +73,8 @@ export class AuthService {
sub: user.id, sub: user.id,
email: user.email, email: user.email,
role: user.role, role: user.role,
// Include partnerId in the payload if user is a PARTNER and has a partnerId // Include partnerId in the payload if user is a PARTNER or OPERATOR and has a partnerId
...(user.role === 'PARTNER' && ...((user.role === 'PARTNER' || user.role === 'OPERATOR') &&
userDetail.partnerId && { partnerId: userDetail.partnerId }), userDetail.partnerId && { partnerId: userDetail.partnerId }),
}; };
...@@ -163,8 +163,8 @@ export class AuthService { ...@@ -163,8 +163,8 @@ export class AuthService {
sub: user.id, sub: user.id,
email: user.email, email: user.email,
role: user.role, role: user.role,
// Include partnerId in the payload if user is a PARTNER and has a partnerId // Include partnerId in the payload if user is a PARTNER or OPERATOR and has a partnerId
...(user.role === 'PARTNER' && ...((user.role === 'PARTNER' || user.role === 'OPERATOR') &&
userDetail.partnerId && { partnerId: userDetail.partnerId }), userDetail.partnerId && { partnerId: userDetail.partnerId }),
}; };
......
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { IsNumber, IsOptional, IsString, IsPositive } from 'class-validator'; import {
IsNumber,
IsOptional,
IsString,
IsPositive,
IsBoolean,
} from 'class-validator';
import { Transform } from 'class-transformer'; import { Transform } from 'class-transformer';
export class CreateInspectionPhotoDto { export class CreateInspectionPhotoDto {
...@@ -27,4 +33,35 @@ export class CreateInspectionPhotoDto { ...@@ -27,4 +33,35 @@ export class CreateInspectionPhotoDto {
@IsOptional() @IsOptional()
@IsString() @IsString()
description?: string; description?: string;
@ApiPropertyOptional({
description:
'Order/position of the photo within the inspection (for sorting)',
example: 1,
type: Number,
})
@IsOptional()
@IsNumber()
@IsPositive()
order?: number;
@ApiPropertyOptional({
description:
'Whether this photo is the principal/cover photo for the inspection',
example: false,
type: Boolean,
})
@IsOptional()
@IsBoolean()
isPrincipal?: boolean;
@ApiPropertyOptional({
description:
'Whether this photo is one of the 6 resume photos for the inspection',
example: false,
type: Boolean,
})
@IsOptional()
@IsBoolean()
isResume?: boolean;
} }
...@@ -44,6 +44,30 @@ export class InspectionPhotoResponseDto { ...@@ -44,6 +44,30 @@ export class InspectionPhotoResponseDto {
description?: string; description?: string;
@ApiProperty({ @ApiProperty({
description:
'Order/position of the photo within the inspection (for sorting)',
example: 1,
type: Number,
})
order: number;
@ApiProperty({
description:
'Whether this photo is the principal/cover photo for the inspection',
example: false,
type: Boolean,
})
isPrincipal: boolean;
@ApiProperty({
description:
'Whether this photo is one of the 6 resume photos for the inspection',
example: false,
type: Boolean,
})
isResume: boolean;
@ApiProperty({
description: 'ID of the inspection this photo belongs to', description: 'ID of the inspection this photo belongs to',
example: 1, example: 1,
type: Number, type: Number,
......
import { ApiPropertyOptional } from '@nestjs/swagger'; import { ApiPropertyOptional } from '@nestjs/swagger';
import { IsOptional, IsString } from 'class-validator'; import {
IsOptional,
IsString,
IsNumber,
IsPositive,
IsBoolean,
} from 'class-validator';
export class UpdateInspectionPhotoDto { export class UpdateInspectionPhotoDto {
@ApiPropertyOptional({ @ApiPropertyOptional({
...@@ -10,4 +16,35 @@ export class UpdateInspectionPhotoDto { ...@@ -10,4 +16,35 @@ export class UpdateInspectionPhotoDto {
@IsOptional() @IsOptional()
@IsString() @IsString()
description?: string; description?: string;
@ApiPropertyOptional({
description:
'Order/position of the photo within the inspection (for sorting)',
example: 2,
type: Number,
})
@IsOptional()
@IsNumber()
@IsPositive()
order?: number;
@ApiPropertyOptional({
description:
'Whether this photo is the principal/cover photo for the inspection',
example: true,
type: Boolean,
})
@IsOptional()
@IsBoolean()
isPrincipal?: boolean;
@ApiPropertyOptional({
description:
'Whether this photo is one of the 6 resume photos for the inspection',
example: true,
type: Boolean,
})
@IsOptional()
@IsBoolean()
isResume?: boolean;
} }
...@@ -41,6 +41,31 @@ export class InspectionPhotosService { ...@@ -41,6 +41,31 @@ export class InspectionPhotosService {
// Save file to disk // Save file to disk
const filePaths = await saveInspectionPhotos([file], dto.inspectionId); const filePaths = await saveInspectionPhotos([file], dto.inspectionId);
// If this photo is being set as principal, unset any existing principal photo
if (dto.isPrincipal) {
await this.databaseService.db
.update(inspectionPhotos)
.set({ isPrincipal: false })
.where(eq(inspectionPhotos.inspectionId, dto.inspectionId));
}
// If this photo is being set as resume, check if we already have 6 resume photos
if (dto.isResume) {
const resumeCount = await this.databaseService.db
.select({ count: count() })
.from(inspectionPhotos)
.where(
and(
eq(inspectionPhotos.inspectionId, dto.inspectionId),
eq(inspectionPhotos.isResume, true),
),
);
if (resumeCount[0]?.count >= 6) {
throw new Error('Maximum of 6 resume photos allowed per inspection');
}
}
// Create photo record in database // Create photo record in database
const now = new Date(); const now = new Date();
const [photo] = await this.databaseService.db const [photo] = await this.databaseService.db
...@@ -51,6 +76,9 @@ export class InspectionPhotosService { ...@@ -51,6 +76,9 @@ export class InspectionPhotosService {
size: file.size, size: file.size,
url: filePaths[0], url: filePaths[0],
description: dto.description, description: dto.description,
order: dto.order || 0,
isPrincipal: dto.isPrincipal || false,
isResume: dto.isResume || false,
inspectionId: dto.inspectionId, inspectionId: dto.inspectionId,
createdAt: now, createdAt: now,
updatedAt: now, updatedAt: now,
...@@ -77,7 +105,7 @@ export class InspectionPhotosService { ...@@ -77,7 +105,7 @@ export class InspectionPhotosService {
.select() .select()
.from(inspectionPhotos) .from(inspectionPhotos)
.where(whereCondition) .where(whereCondition)
.orderBy(desc(inspectionPhotos.createdAt)); .orderBy(asc(inspectionPhotos.order), desc(inspectionPhotos.createdAt));
return photos.map(this.mapToDto); return photos.map(this.mapToDto);
} }
...@@ -102,16 +130,60 @@ export class InspectionPhotosService { ...@@ -102,16 +130,60 @@ export class InspectionPhotosService {
id: number, id: number,
dto: UpdateInspectionPhotoDto, dto: UpdateInspectionPhotoDto,
): Promise<InspectionPhotoResponseDto> { ): Promise<InspectionPhotoResponseDto> {
// First get the inspectionId of the photo being updated
const photoList = await this.databaseService.db
.select({ inspectionId: inspectionPhotos.inspectionId })
.from(inspectionPhotos)
.where(eq(inspectionPhotos.id, id))
.limit(1);
if (photoList.length === 0) {
throw new NotFoundException(`Inspection photo with ID ${id} not found`);
}
const inspectionId = photoList[0].inspectionId;
// If this photo is being set as principal, unset any existing principal photo
if (dto.isPrincipal) {
await this.databaseService.db
.update(inspectionPhotos)
.set({ isPrincipal: false })
.where(eq(inspectionPhotos.inspectionId, inspectionId));
}
// If this photo is being set as resume, check if we already have 6 resume photos
if (dto.isResume) {
// First check if the current photo is already a resume photo
const currentPhoto = await this.databaseService.db
.select({ isResume: inspectionPhotos.isResume })
.from(inspectionPhotos)
.where(eq(inspectionPhotos.id, id))
.limit(1);
// Only count other resume photos if the current photo is not already a resume photo
if (!currentPhoto[0]?.isResume) {
const resumeCount = await this.databaseService.db
.select({ count: count() })
.from(inspectionPhotos)
.where(
and(
eq(inspectionPhotos.inspectionId, inspectionId),
eq(inspectionPhotos.isResume, true),
),
);
if (resumeCount[0]?.count >= 6) {
throw new Error('Maximum of 6 resume photos allowed per inspection');
}
}
}
const [updatedPhoto] = await this.databaseService.db const [updatedPhoto] = await this.databaseService.db
.update(inspectionPhotos) .update(inspectionPhotos)
.set(dto) .set(dto)
.where(eq(inspectionPhotos.id, id)) .where(eq(inspectionPhotos.id, id))
.returning(); .returning();
if (!updatedPhoto) {
throw new NotFoundException(`Inspection photo with ID ${id} not found`);
}
return this.mapToDto(updatedPhoto); return this.mapToDto(updatedPhoto);
} }
...@@ -122,7 +194,7 @@ export class InspectionPhotosService { ...@@ -122,7 +194,7 @@ export class InspectionPhotosService {
.select() .select()
.from(inspectionPhotos) .from(inspectionPhotos)
.where(eq(inspectionPhotos.inspectionId, inspectionId)) .where(eq(inspectionPhotos.inspectionId, inspectionId))
.orderBy(desc(inspectionPhotos.createdAt)); .orderBy(asc(inspectionPhotos.order), desc(inspectionPhotos.createdAt));
return photos.map(this.mapToDto); return photos.map(this.mapToDto);
} }
...@@ -166,6 +238,9 @@ export class InspectionPhotosService { ...@@ -166,6 +238,9 @@ export class InspectionPhotosService {
size: photo.size, size: photo.size,
url: photo.url, url: photo.url,
description: photo.description, description: photo.description,
order: photo.order,
isPrincipal: photo.isPrincipal,
isResume: photo.isResume,
inspectionId: photo.inspectionId, inspectionId: photo.inspectionId,
createdAt: photo.createdAt, createdAt: photo.createdAt,
updatedAt: photo.updatedAt, updatedAt: photo.updatedAt,
......
...@@ -2,10 +2,7 @@ import { InspectionResponseOption } from './inspection-response-option.enum'; ...@@ -2,10 +2,7 @@ import { InspectionResponseOption } from './inspection-response-option.enum';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
// Import the status enum from Prisma // Import the status enum from Prisma
import { import { inspectionStatusEnum } from '../../../database/schema';
inspectionStatusEnum,
finalCommentStatusEnum,
} from '../../../database/schema';
export class InspectionQuestionDto { export class InspectionQuestionDto {
@ApiProperty({ @ApiProperty({
...@@ -130,11 +127,11 @@ export class InspectionDto { ...@@ -130,11 +127,11 @@ export class InspectionDto {
@ApiPropertyOptional({ @ApiPropertyOptional({
description: 'Status of the final comment validation', description: 'Status of the final comment validation',
enum: finalCommentStatusEnum.enumValues, enum: inspectionStatusEnum.enumValues,
example: 'PENDING', example: 'PENDING',
enumName: 'FinalCommentStatus', enumName: 'InspectionStatus',
}) })
finalCommentStatus?: (typeof finalCommentStatusEnum.enumValues)[number]; finalCommentStatus?: (typeof inspectionStatusEnum.enumValues)[number];
@ApiProperty({ @ApiProperty({
description: 'ID of the site where inspection was performed', description: 'ID of the site where inspection was performed',
...@@ -165,6 +162,36 @@ export class InspectionDto { ...@@ -165,6 +162,36 @@ export class InspectionDto {
}) })
updatedAt: Date; updatedAt: Date;
@ApiPropertyOptional({
description: 'User who submitted the inspection to APPROVING status',
type: 'object',
properties: {
id: { type: 'number', example: 1 },
name: { type: 'string', example: 'John Doe' },
email: { type: 'string', example: 'john.doe@example.com' },
},
})
submittedBy?: {
id: number;
name: string;
email: string;
};
@ApiPropertyOptional({
description: 'User who approved the inspection',
type: 'object',
properties: {
id: { type: 'number', example: 2 },
name: { type: 'string', example: 'Jane Smith' },
email: { type: 'string', example: 'jane.smith@example.com' },
},
})
approvedBy?: {
id: number;
name: string;
email: string;
};
@ApiProperty({ @ApiProperty({
description: 'Responses to inspection questions', description: 'Responses to inspection questions',
type: [InspectionResponseDto], type: [InspectionResponseDto],
......
import { import {
Body, Body,
Controller, Controller,
Delete,
Get, Get,
Param, Param,
ParseIntPipe, ParseIntPipe,
...@@ -687,4 +688,75 @@ export class InspectionController { ...@@ -687,4 +688,75 @@ export class InspectionController {
validationDto.comment, validationDto.comment,
); );
} }
@Delete(':id')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles(Role.ADMIN, Role.SUPERADMIN)
@ApiOperation({
summary: 'Delete a specific inspection',
description:
'Deletes an inspection record and all its related data (responses and photos). Only ADMIN and SUPERADMIN roles can delete inspections.',
})
@ApiParam({
name: 'id',
type: 'number',
description: 'Inspection ID to delete',
})
@ApiResponse({
status: 200,
description: 'The inspection has been successfully deleted.',
schema: {
type: 'object',
properties: {
message: {
type: 'string',
example: 'Inspection with ID 1 has been deleted',
},
},
},
})
@ApiResponse({ status: 401, description: 'Unauthorized.' })
@ApiResponse({
status: 403,
description: 'Forbidden - Insufficient permissions.',
})
@ApiResponse({ status: 404, description: 'Inspection not found.' })
async deleteInspection(@Param('id', ParseIntPipe) id: number) {
return this.inspectionService.deleteInspection(id);
}
@Delete()
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles(Role.SUPERADMIN)
@ApiOperation({
summary: 'Delete all inspections',
description:
'Deletes all inspection records and their related data (responses and photos). Only SUPERADMIN role can perform this action.',
})
@ApiResponse({
status: 200,
description: 'All inspections have been successfully deleted.',
schema: {
type: 'object',
properties: {
message: {
type: 'string',
example: 'All 25 inspections have been deleted',
},
deletedCount: {
type: 'number',
example: 25,
description: 'Number of inspections that were deleted',
},
},
},
})
@ApiResponse({ status: 401, description: 'Unauthorized.' })
@ApiResponse({
status: 403,
description: 'Forbidden - Only SUPERADMIN can delete all inspections.',
})
async deleteAllInspections() {
return this.inspectionService.deleteAllInspections();
}
} }
...@@ -262,8 +262,59 @@ export class InspectionService { ...@@ -262,8 +262,59 @@ export class InspectionService {
.where(whereCondition) .where(whereCondition)
.orderBy(desc(inspections.createdAt)); .orderBy(desc(inspections.createdAt));
// Fetch user information for submittedBy and approvedBy
const inspectionIds = inspectionList.map((i) => i.id);
const userInfo = new Map();
if (inspectionIds.length > 0) {
// Get submittedBy users
const submittedByUsers = await this.databaseService.db
.select({
inspectionId: inspections.id,
userId: users.id,
userName: users.name,
userEmail: users.email,
})
.from(inspections)
.leftJoin(users, eq(users.id, inspections.submittedById))
.where(inArray(inspections.id, inspectionIds));
// Get approvedBy users
const approvedByUsers = await this.databaseService.db
.select({
inspectionId: inspections.id,
userId: users.id,
userName: users.name,
userEmail: users.email,
})
.from(inspections)
.leftJoin(users, eq(users.id, inspections.approvedById))
.where(inArray(inspections.id, inspectionIds));
// Build user info map
submittedByUsers.forEach((user) => {
if (user.userId) {
userInfo.set(`${user.inspectionId}_submitted`, {
id: user.userId,
name: user.userName,
email: user.userEmail,
});
}
});
approvedByUsers.forEach((user) => {
if (user.userId) {
userInfo.set(`${user.inspectionId}_approved`, {
id: user.userId,
name: user.userName,
email: user.userEmail,
});
}
});
}
return inspectionList.map((inspection) => return inspectionList.map((inspection) =>
this.mapToInspectionDto(inspection), this.mapToInspectionDto(inspection, [], [], userInfo),
); );
} }
...@@ -305,7 +356,50 @@ export class InspectionService { ...@@ -305,7 +356,50 @@ export class InspectionService {
.from(inspectionPhotos) .from(inspectionPhotos)
.where(eq(inspectionPhotos.inspectionId, id)); .where(eq(inspectionPhotos.inspectionId, id));
return this.mapToInspectionDto(inspection, responses, photos); // Fetch user information for submittedBy and approvedBy
const userInfo = new Map();
// Get submittedBy user
const submittedByUser = await this.databaseService.db
.select({
userId: users.id,
userName: users.name,
userEmail: users.email,
})
.from(inspections)
.leftJoin(users, eq(users.id, inspections.submittedById))
.where(eq(inspections.id, id))
.limit(1);
// Get approvedBy user
const approvedByUser = await this.databaseService.db
.select({
userId: users.id,
userName: users.name,
userEmail: users.email,
})
.from(inspections)
.leftJoin(users, eq(users.id, inspections.approvedById))
.where(eq(inspections.id, id))
.limit(1);
if (submittedByUser[0]?.userId) {
userInfo.set(`${id}_submitted`, {
id: submittedByUser[0].userId,
name: submittedByUser[0].userName,
email: submittedByUser[0].userEmail,
});
}
if (approvedByUser[0]?.userId) {
userInfo.set(`${id}_approved`, {
id: approvedByUser[0].userId,
name: approvedByUser[0].userName,
email: approvedByUser[0].userEmail,
});
}
return this.mapToInspectionDto(inspection, responses, photos, userInfo);
} }
async getInspectionQuestions() { async getInspectionQuestions() {
...@@ -607,12 +701,24 @@ export class InspectionService { ...@@ -607,12 +701,24 @@ export class InspectionService {
// For now, implementing basic CRUD operations to get the module working // For now, implementing basic CRUD operations to get the module working
async updateInspectionStatus(id: number, status: string, userId: number) { async updateInspectionStatus(id: number, status: string, userId: number) {
const updateData: any = {
status: status as any,
updatedById: userId,
};
// Set submittedById when status changes to APPROVING
if (status === 'APPROVING') {
updateData.submittedById = userId;
}
// Set approvedById when status changes to APPROVED
if (status === 'APPROVED') {
updateData.approvedById = userId;
}
const [updatedInspection] = await this.databaseService.db const [updatedInspection] = await this.databaseService.db
.update(inspections) .update(inspections)
.set({ .set(updateData)
status: status as any,
updatedById: userId,
})
.where(eq(inspections.id, id)) .where(eq(inspections.id, id))
.returning(); .returning();
...@@ -690,10 +796,10 @@ export class InspectionService { ...@@ -690,10 +796,10 @@ export class InspectionService {
// Set finalCommentStatus based on user role // Set finalCommentStatus based on user role
if (userRole === 'OPERATOR') { if (userRole === 'OPERATOR') {
// Operators can create/update final comments, but they need validation // Operators can create/update final comments, but they need validation
updateData.finalCommentStatus = 'PENDING'; updateData.finalCommentStatus = 'APPROVING';
} else if (userRole === 'PARTNER') { } else if (userRole === 'PARTNER') {
// Partners can validate final comments // Partners can validate final comments
updateData.finalCommentStatus = 'VALIDATED'; updateData.finalCommentStatus = 'APPROVED';
} }
// Other roles (ADMIN, SUPERADMIN, MANAGER) can see validated comments but don't change status // Other roles (ADMIN, SUPERADMIN, MANAGER) can see validated comments but don't change status
...@@ -772,14 +878,14 @@ export class InspectionService { ...@@ -772,14 +878,14 @@ export class InspectionService {
); );
} }
// Check if the final comment is in PENDING status // Check if the final comment is in APPROVING status
if (inspection.finalCommentStatus !== 'PENDING') { if (inspection.finalCommentStatus !== 'APPROVING') {
throw new ForbiddenException( throw new ForbiddenException(
'Final comment is not in PENDING status for validation', 'Final comment is not in APPROVING status for validation',
); );
} }
const newStatus = action === 'validate' ? 'VALIDATED' : 'REJECTED'; const newStatus = action === 'validate' ? 'APPROVED' : 'REJECTED';
const [updatedInspection] = await this.databaseService.db const [updatedInspection] = await this.databaseService.db
.update(inspections) .update(inspections)
...@@ -851,7 +957,11 @@ export class InspectionService { ...@@ -851,7 +957,11 @@ export class InspectionService {
inspection: any, inspection: any,
responses: any[] = [], responses: any[] = [],
photos: any[] = [], photos: any[] = [],
userInfo?: Map<string, any>,
): InspectionDto { ): InspectionDto {
const submittedBy = userInfo?.get(`${inspection.id}_submitted`);
const approvedBy = userInfo?.get(`${inspection.id}_approved`);
return { return {
id: inspection.id, id: inspection.id,
date: inspection.date, date: inspection.date,
...@@ -863,6 +973,8 @@ export class InspectionService { ...@@ -863,6 +973,8 @@ export class InspectionService {
status: inspection.status, status: inspection.status,
createdAt: inspection.createdAt, createdAt: inspection.createdAt,
updatedAt: inspection.updatedAt, updatedAt: inspection.updatedAt,
submittedBy: submittedBy || null,
approvedBy: approvedBy || null,
responses: responses.map((response) => ({ responses: responses.map((response) => ({
id: response.id, id: response.id,
response: response.response, response: response.response,
...@@ -877,4 +989,59 @@ export class InspectionService { ...@@ -877,4 +989,59 @@ export class InspectionService {
})), })),
}; };
} }
async deleteInspection(id: number): Promise<{ message: string }> {
// Check if inspection exists
const existingInspection = await this.databaseService.db
.select()
.from(inspections)
.where(eq(inspections.id, id))
.limit(1);
if (existingInspection.length === 0) {
throw new NotFoundException(`Inspection with ID ${id} not found`);
}
// Delete related records first (inspection responses and photos)
await this.databaseService.db
.delete(inspectionResponses)
.where(eq(inspectionResponses.inspectionId, id));
await this.databaseService.db
.delete(inspectionPhotos)
.where(eq(inspectionPhotos.inspectionId, id));
// Delete the inspection
await this.databaseService.db
.delete(inspections)
.where(eq(inspections.id, id));
return { message: `Inspection with ID ${id} has been deleted` };
}
async deleteAllInspections(): Promise<{
message: string;
deletedCount: number;
}> {
// Get count before deletion
const [countResult] = await this.databaseService.db
.select({ count: count() })
.from(inspections);
const deletedCount = Number(countResult.count);
// Delete all inspection responses
await this.databaseService.db.delete(inspectionResponses);
// Delete all inspection photos
await this.databaseService.db.delete(inspectionPhotos);
// Delete all inspections
await this.databaseService.db.delete(inspections);
return {
message: `All ${deletedCount} inspections have been deleted`,
deletedCount,
};
}
} }
...@@ -28,4 +28,13 @@ export class CreatePartnerDto { ...@@ -28,4 +28,13 @@ export class CreatePartnerDto {
@IsOptional() @IsOptional()
@IsBoolean() @IsBoolean()
isActive?: boolean = true; isActive?: boolean = true;
@ApiProperty({
description: 'URL to the partner logo image',
example: '/uploads/logos/partner123_logo.png',
required: false,
})
@IsOptional()
@IsString()
logo?: string;
} }
...@@ -40,6 +40,13 @@ export class PartnerResponseDto { ...@@ -40,6 +40,13 @@ export class PartnerResponseDto {
isActive: boolean; isActive: boolean;
@ApiProperty({ @ApiProperty({
description: 'URL to the partner logo image',
example: '/uploads/logos/partner123_logo.png',
required: false,
})
logo?: string;
@ApiProperty({
description: 'Partner creation timestamp', description: 'Partner creation timestamp',
example: '2023-05-13T15:25:41.358Z', example: '2023-05-13T15:25:41.358Z',
}) })
......
...@@ -23,4 +23,11 @@ export class UpdatePartnerDto extends PartialType(CreatePartnerDto) { ...@@ -23,4 +23,11 @@ export class UpdatePartnerDto extends PartialType(CreatePartnerDto) {
required: false, required: false,
}) })
isActive?: boolean; isActive?: boolean;
@ApiProperty({
description: 'URL to the partner logo image',
example: '/uploads/logos/partner123_logo.png',
required: false,
})
logo?: string;
} }
...@@ -8,13 +8,18 @@ import { ...@@ -8,13 +8,18 @@ import {
Delete, Delete,
ParseIntPipe, ParseIntPipe,
UseGuards, UseGuards,
UseInterceptors,
UploadedFile,
} from '@nestjs/common'; } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { import {
ApiTags, ApiTags,
ApiOperation, ApiOperation,
ApiResponse, ApiResponse,
ApiBearerAuth, ApiBearerAuth,
ApiParam, ApiParam,
ApiConsumes,
ApiBody,
} from '@nestjs/swagger'; } from '@nestjs/swagger';
import { PartnersService } from './partners.service'; import { PartnersService } from './partners.service';
import { CreatePartnerDto, UpdatePartnerDto, PartnerResponseDto } from './dto'; import { CreatePartnerDto, UpdatePartnerDto, PartnerResponseDto } from './dto';
...@@ -24,6 +29,8 @@ import { PartnerAuthGuard } from '../auth/guards/partner-auth.guard'; ...@@ -24,6 +29,8 @@ import { PartnerAuthGuard } from '../auth/guards/partner-auth.guard';
import { Roles } from '../auth/decorators/roles.decorator'; import { Roles } from '../auth/decorators/roles.decorator';
import { User } from '../auth/decorators/user.decorator'; import { User } from '../auth/decorators/user.decorator';
import { Partner } from '../auth/decorators/partner.decorator'; import { Partner } from '../auth/decorators/partner.decorator';
import { multerConfig } from '../../common/multer/multer.config';
import { savePartnerLogo } from '../../common/utils/file-upload.utils';
// Role enum values as constants // Role enum values as constants
const Role = { const Role = {
ADMIN: 'ADMIN', ADMIN: 'ADMIN',
...@@ -281,4 +288,69 @@ export class PartnersController { ...@@ -281,4 +288,69 @@ export class PartnersController {
) { ) {
return this.partnersService.switchPartnerForSite(siteId, newPartnerId); return this.partnersService.switchPartnerForSite(siteId, newPartnerId);
} }
@Post(':id/logo')
@Roles(Role.ADMIN, Role.SUPERADMIN)
@UseInterceptors(FileInterceptor('logo', multerConfig))
@ApiOperation({
summary: 'Upload partner logo',
description:
'Uploads a logo image for a partner. Only users with ADMIN or SUPERADMIN roles can upload logos.',
})
@ApiResponse({
status: 200,
description: 'The logo has been successfully uploaded.',
})
@ApiResponse({ status: 400, description: 'Invalid input data.' })
@ApiResponse({ status: 401, description: 'Unauthorized.' })
@ApiResponse({
status: 403,
description: 'Forbidden - Insufficient permissions.',
})
@ApiResponse({ status: 404, description: 'Partner not found.' })
@ApiConsumes('multipart/form-data')
@ApiBody({
description: 'Logo upload data',
schema: {
type: 'object',
required: ['logo'],
properties: {
logo: {
type: 'string',
format: 'binary',
description: 'Logo image file (max 5MB, images only)',
},
},
},
})
@ApiParam({
name: 'id',
type: Number,
description: 'ID of the partner',
example: 1,
})
async uploadPartnerLogo(
@Param('id', ParseIntPipe) id: number,
@UploadedFile() file: Express.Multer.File,
) {
try {
if (!file) {
throw new Error('No file provided. Please upload a logo file.');
}
// Save the logo file
const logoUrl = await savePartnerLogo(file, id);
// Update the partner with the logo URL
await this.partnersService.update(id, { logo: logoUrl });
return {
message: 'Logo uploaded successfully',
logoUrl,
};
} catch (error) {
console.error('Error uploading partner logo:', error);
throw error;
}
}
} }
...@@ -161,7 +161,7 @@ export class PartnersService { ...@@ -161,7 +161,7 @@ export class PartnersService {
.update(users) .update(users)
.set({ .set({
partnerId, partnerId,
role: 'OPERATOR', // Set role to OPERATOR by default (normal partner user) // Don't change the user's role - keep their existing role
}) })
.where(eq(users.id, userId)) .where(eq(users.id, userId))
.returning(); .returning();
......
...@@ -47,4 +47,13 @@ export class CreateSiteDto { ...@@ -47,4 +47,13 @@ export class CreateSiteDto {
@Min(-180) @Min(-180)
@Max(180) @Max(180)
longitude: number; longitude: number;
@ApiPropertyOptional({
description: 'Partner ID to associate with this site',
example: 1,
})
@IsOptional()
@IsNumber()
@Min(1)
partnerId?: number;
} }
...@@ -11,6 +11,20 @@ export class UserResponseDto { ...@@ -11,6 +11,20 @@ export class UserResponseDto {
email: string; email: string;
} }
export class PartnerResponseDto {
@ApiProperty({ description: 'Partner ID' })
id: number;
@ApiProperty({ description: 'Partner name' })
name: string;
@ApiProperty({ description: 'Partner description', required: false })
description?: string;
@ApiProperty({ description: 'Partner active status' })
isActive: boolean;
}
export class SiteResponseDto { export class SiteResponseDto {
@ApiProperty({ description: 'Site ID' }) @ApiProperty({ description: 'Site ID' })
id: number; id: number;
...@@ -58,6 +72,14 @@ export class SiteResponseDto { ...@@ -58,6 +72,14 @@ export class SiteResponseDto {
updatedBy: UserResponseDto; updatedBy: UserResponseDto;
@ApiProperty({ @ApiProperty({
description: 'Partner associated with this site',
type: PartnerResponseDto,
required: false,
nullable: true,
})
partner?: PartnerResponseDto | null;
@ApiProperty({
description: 'Number of candidates associated with this site', description: 'Number of candidates associated with this site',
}) })
_count?: { _count?: {
......
...@@ -85,7 +85,7 @@ export class SitesController { ...@@ -85,7 +85,7 @@ export class SitesController {
@Get() @Get()
@UseGuards(JwtAuthGuard, RolesGuard) @UseGuards(JwtAuthGuard, RolesGuard)
@Roles(Role.ADMIN, Role.MANAGER, Role.SUPERADMIN, Role.PARTNER) @Roles(Role.ADMIN, Role.MANAGER, Role.OPERATOR, Role.SUPERADMIN, Role.PARTNER)
@ApiOperation({ @ApiOperation({
summary: 'Get all sites for list view (with pagination)', summary: 'Get all sites for list view (with pagination)',
description: description:
...@@ -117,7 +117,23 @@ export class SitesController { ...@@ -117,7 +117,23 @@ export class SitesController {
}) })
async findAll(@Query() findSitesDto: FindSitesDto, @Request() req) { async findAll(@Query() findSitesDto: FindSitesDto, @Request() req) {
const partnerId = const partnerId =
req.user.role === Role.PARTNER ? req.user.partnerId : null; req.user.role === Role.PARTNER || req.user.role === Role.OPERATOR
? req.user.partnerId
: null;
// Debug logging to help identify the issue
if (
(req.user.role === Role.PARTNER || req.user.role === Role.OPERATOR) &&
!partnerId
) {
console.log(
'⚠️ User with role',
req.user.role,
'does not have partnerId set:',
req.user,
);
}
return this.sitesService.findAll(findSitesDto, partnerId); return this.sitesService.findAll(findSitesDto, partnerId);
} }
...@@ -161,9 +177,19 @@ export class SitesController { ...@@ -161,9 +177,19 @@ export class SitesController {
@Param('id', ParseIntPipe) id: number, @Param('id', ParseIntPipe) id: number,
@Partner() partnerId: number | null, @Partner() partnerId: number | null,
@User('role') role: string, @User('role') role: string,
@Request() req,
) { ) {
// For PARTNER role, we restrict access to only see sites associated with their partnerId // For PARTNER and OPERATOR roles, we restrict access to only see sites associated with their partnerId
if (role === Role.PARTNER) { if (role === Role.PARTNER || role === Role.OPERATOR) {
// Debug logging to help identify the issue
if (!partnerId) {
console.log(
'⚠️ User with role',
role,
'does not have partnerId set:',
req.user,
);
}
return this.sitesService.findOneFilteredByPartner(id, partnerId); return this.sitesService.findOneFilteredByPartner(id, partnerId);
} }
return this.sitesService.findOne(id); return this.sitesService.findOne(id);
...@@ -197,8 +223,8 @@ export class SitesController { ...@@ -197,8 +223,8 @@ export class SitesController {
@User('role') role: string, @User('role') role: string,
@Query('partnerId') filterPartnerId?: number, @Query('partnerId') filterPartnerId?: number,
) { ) {
// For PARTNER role, we restrict access to only see candidates created with their partnerId // For PARTNER and OPERATOR roles, we restrict access to only see candidates created with their partnerId
if (role === Role.PARTNER) { if (role === Role.PARTNER || role === Role.OPERATOR) {
return this.sitesService.findOneWithCandidates(id, partnerId); return this.sitesService.findOneWithCandidates(id, partnerId);
} }
// If a specific partnerId is provided in the query, use that for filtering // If a specific partnerId is provided in the query, use that for filtering
...@@ -223,6 +249,26 @@ export class SitesController { ...@@ -223,6 +249,26 @@ export class SitesController {
return this.sitesService.update(id, updateSiteDto, userId); return this.sitesService.update(id, updateSiteDto, userId);
} }
@Patch(':id/partner')
@Roles(Role.SUPERADMIN, Role.ADMIN, Role.MANAGER)
@ApiOperation({ summary: 'Update site partner association' })
@ApiResponse({
status: 200,
description: 'The site partner association has been successfully updated.',
})
@ApiResponse({ status: 404, description: 'Site or partner not found.' })
@ApiResponse({
status: 409,
description: 'Site already associated with this partner.',
})
updateSitePartner(
@Param('id', ParseIntPipe) id: number,
@Body('partnerId') partnerId: number | null,
@User('id') userId: number,
) {
return this.sitesService.updateSitePartner(id, partnerId, userId);
}
@Delete(':id') @Delete(':id')
@Roles(Role.SUPERADMIN, Role.ADMIN) @Roles(Role.SUPERADMIN, Role.ADMIN)
@ApiOperation({ summary: 'Delete a site' }) @ApiOperation({ summary: 'Delete a site' })
......
...@@ -10,6 +10,8 @@ import { ...@@ -10,6 +10,8 @@ import {
inspections, inspections,
users, users,
telecommunicationStationIdentifications, telecommunicationStationIdentifications,
partners,
partnerSites,
} from '../../database/schema'; } from '../../database/schema';
import { import {
eq, eq,
...@@ -18,6 +20,7 @@ import { ...@@ -18,6 +20,7 @@ import {
ilike, ilike,
ne, ne,
isNull, isNull,
isNotNull,
count, count,
gt, gt,
asc, asc,
...@@ -115,6 +118,56 @@ export class SitesService { ...@@ -115,6 +118,56 @@ export class SitesService {
}) })
.returning(); .returning();
// If partnerId is provided, create the partner-site association
if (createSiteDto.partnerId) {
// Validate that the partner exists
const partnerList = await this.databaseService.db
.select()
.from(partners)
.where(eq(partners.id, createSiteDto.partnerId))
.limit(1);
if (partnerList.length === 0) {
throw new NotFoundException(
`Partner with ID ${createSiteDto.partnerId} not found`,
);
}
// Check if the site is already associated with any partner
const existingAssociation = await this.databaseService.db
.select()
.from(partnerSites)
.where(eq(partnerSites.siteId, newSite.id))
.limit(1);
if (existingAssociation.length > 0) {
throw new ConflictException(
`Site with ID ${newSite.id} is already associated with a partner`,
);
}
// Create the partner-site association
try {
await this.databaseService.db.insert(partnerSites).values({
partnerId: createSiteDto.partnerId,
siteId: newSite.id,
createdAt: now,
updatedAt: now,
});
} catch (insertError) {
// Handle unique constraint violation for partner-site association
if (
insertError.code === '23505' ||
insertError.message?.includes('duplicate key')
) {
throw new ConflictException(
`Site with ID ${newSite.id} is already associated with partner ID ${createSiteDto.partnerId}`,
);
}
throw insertError;
}
}
// For now, return the created site with minimal user info // For now, return the created site with minimal user info
// We can expand this later to include full user relations if needed // We can expand this later to include full user relations if needed
return { return {
...@@ -152,21 +205,26 @@ export class SitesService { ...@@ -152,21 +205,26 @@ export class SitesService {
const siteWhereCondition = const siteWhereCondition =
siteConditions.length > 0 ? and(...siteConditions) : undefined; siteConditions.length > 0 ? and(...siteConditions) : undefined;
// Get total count // Get total count with partner filtering if needed
const [{ totalCount }] = await this.databaseService.db let countQuery;
.select({ totalCount: count() }) if (partnerId) {
.from(sites) countQuery = this.databaseService.db
.where(siteWhereCondition); .select({ totalCount: count() })
.from(sites)
// Build inspection status filter condition .leftJoin(partnerSites, eq(partnerSites.siteId, sites.id))
const inspectionConditions: SQL[] = []; .where(and(siteWhereCondition, eq(partnerSites.partnerId, partnerId)));
if (findSitesDto?.inspectionStatus) { } else {
inspectionConditions.push( countQuery = this.databaseService.db
eq(inspections.status, findSitesDto.inspectionStatus as any), .select({ totalCount: count() })
); .from(sites)
.where(siteWhereCondition);
} }
// Get sites with latest inspection data const [{ totalCount }] = await countQuery;
// Inspection status filter is now handled in the WHERE clause
// Get sites with latest inspection data and partner information
const sitesList = await this.databaseService.db const sitesList = await this.databaseService.db
.select({ .select({
id: sites.id, id: sites.id,
...@@ -180,6 +238,10 @@ export class SitesService { ...@@ -180,6 +238,10 @@ export class SitesService {
updatedById: sites.updatedById, updatedById: sites.updatedById,
latestInspectionStatus: inspections.status, latestInspectionStatus: inspections.status,
latestInspectionDate: inspections.date, latestInspectionDate: inspections.date,
partnerId: partners.id,
partnerName: partners.name,
partnerDescription: partners.description,
partnerIsActive: partners.isActive,
}) })
.from(sites) .from(sites)
.leftJoin( .leftJoin(
...@@ -192,11 +254,24 @@ export class SitesService { ...@@ -192,11 +254,24 @@ export class SitesService {
FROM "Inspection" FROM "Inspection"
WHERE "siteId" = ${sites.id} WHERE "siteId" = ${sites.id}
)`, )`,
// Apply inspection status filter if provided
...inspectionConditions,
), ),
) )
.where(siteWhereCondition) .leftJoin(partnerSites, eq(partnerSites.siteId, sites.id))
.leftJoin(partners, eq(partners.id, partnerSites.partnerId))
.where(
and(
partnerId
? and(siteWhereCondition, eq(partnerSites.partnerId, partnerId))
: siteWhereCondition,
// Apply inspection status filter in WHERE clause to exclude null values
findSitesDto?.inspectionStatus
? and(
isNotNull(inspections.status),
eq(inspections.status, findSitesDto.inspectionStatus as any),
)
: undefined,
),
)
.limit(limit) .limit(limit)
.offset(offset); .offset(offset);
...@@ -208,6 +283,14 @@ export class SitesService { ...@@ -208,6 +283,14 @@ export class SitesService {
nextInspectionDueDate: this.calculateNextInspectionDueDate( nextInspectionDueDate: this.calculateNextInspectionDueDate(
site.latestInspectionDate, site.latestInspectionDate,
), ),
partner: site.partnerId
? {
id: site.partnerId,
name: site.partnerName,
description: site.partnerDescription,
isActive: site.partnerIsActive,
}
: null,
_count: { candidates: 0 }, _count: { candidates: 0 },
})), })),
meta: { meta: {
...@@ -233,6 +316,10 @@ export class SitesService { ...@@ -233,6 +316,10 @@ export class SitesService {
updatedById: sites.updatedById, updatedById: sites.updatedById,
latestInspectionStatus: inspections.status, latestInspectionStatus: inspections.status,
latestInspectionDate: inspections.date, latestInspectionDate: inspections.date,
partnerId: partners.id,
partnerName: partners.name,
partnerDescription: partners.description,
partnerIsActive: partners.isActive,
}) })
.from(sites) .from(sites)
.leftJoin( .leftJoin(
...@@ -247,6 +334,8 @@ export class SitesService { ...@@ -247,6 +334,8 @@ export class SitesService {
)`, )`,
), ),
) )
.leftJoin(partnerSites, eq(partnerSites.siteId, sites.id))
.leftJoin(partners, eq(partners.id, partnerSites.partnerId))
.where(eq(sites.id, id)) .where(eq(sites.id, id))
.limit(1); .limit(1);
...@@ -263,16 +352,86 @@ export class SitesService { ...@@ -263,16 +352,86 @@ export class SitesService {
nextInspectionDueDate: this.calculateNextInspectionDueDate( nextInspectionDueDate: this.calculateNextInspectionDueDate(
site.latestInspectionDate, site.latestInspectionDate,
), ),
partner: site.partnerId
? {
id: site.partnerId,
name: site.partnerName,
description: site.partnerDescription,
isActive: site.partnerIsActive,
}
: null,
_count: { candidates: 0 }, _count: { candidates: 0 },
}; };
} }
async findOneFilteredByPartner(id: number, partnerId: number | null) { async findOneFilteredByPartner(id: number, partnerId: number | null) {
if (!partnerId) { if (!partnerId) {
throw new ForbiddenException('Partner access required'); throw new ForbiddenException(
'User does not have access to any partner resources. Please contact an administrator to assign you to a partner.',
);
}
const sitesList = await this.databaseService.db
.select({
id: sites.id,
siteCode: sites.siteCode,
siteName: sites.siteName,
latitude: sites.latitude,
longitude: sites.longitude,
createdAt: sites.createdAt,
updatedAt: sites.updatedAt,
createdById: sites.createdById,
updatedById: sites.updatedById,
latestInspectionStatus: inspections.status,
latestInspectionDate: inspections.date,
partnerId: partners.id,
partnerName: partners.name,
partnerDescription: partners.description,
partnerIsActive: partners.isActive,
})
.from(sites)
.leftJoin(
inspections,
and(
eq(inspections.siteId, sites.id),
// Get the latest inspection for this site
sql`${inspections.id} = (
SELECT MAX(id)
FROM "Inspection"
WHERE "siteId" = ${sites.id}
)`,
),
)
.leftJoin(partnerSites, eq(partnerSites.siteId, sites.id))
.leftJoin(partners, eq(partners.id, partnerSites.partnerId))
.where(and(eq(sites.id, id), eq(partnerSites.partnerId, partnerId)))
.limit(1);
if (sitesList.length === 0) {
throw new NotFoundException(
`Site with ID ${id} not found or not associated with your partner`,
);
} }
return this.findOne(id); const site = sitesList[0];
return {
...site,
highestCandidateStatus: null,
latestInspectionStatus: site.latestInspectionStatus,
nextInspectionDueDate: this.calculateNextInspectionDueDate(
site.latestInspectionDate,
),
partner: site.partnerId
? {
id: site.partnerId,
name: site.partnerName,
description: site.partnerDescription,
isActive: site.partnerIsActive,
}
: null,
_count: { candidates: 0 },
};
} }
async findOneWithCandidates(id: number, partnerId?: number | null) { async findOneWithCandidates(id: number, partnerId?: number | null) {
...@@ -322,6 +481,102 @@ export class SitesService { ...@@ -322,6 +481,102 @@ export class SitesService {
} }
} }
async updateSitePartner(
siteId: number,
partnerId: number | null,
userId: number,
) {
try {
// Check if site exists
const siteList = await this.databaseService.db
.select()
.from(sites)
.where(eq(sites.id, siteId))
.limit(1);
if (siteList.length === 0) {
throw new NotFoundException(`Site with ID ${siteId} not found`);
}
// If partnerId is null, remove any existing partner association
if (partnerId === null) {
await this.databaseService.db
.delete(partnerSites)
.where(eq(partnerSites.siteId, siteId));
return { message: `Partner association removed from site ${siteId}` };
}
// Validate that the partner exists
const partnerList = await this.databaseService.db
.select()
.from(partners)
.where(eq(partners.id, partnerId))
.limit(1);
if (partnerList.length === 0) {
throw new NotFoundException(`Partner with ID ${partnerId} not found`);
}
// Check if the site is already associated with this specific partner
const existingAssociation = await this.databaseService.db
.select()
.from(partnerSites)
.where(
and(
eq(partnerSites.siteId, siteId),
eq(partnerSites.partnerId, partnerId),
),
)
.limit(1);
if (existingAssociation.length > 0) {
throw new ConflictException(
`Site with ID ${siteId} is already associated with partner ID ${partnerId}`,
);
}
// Remove any existing partner association for this site
await this.databaseService.db
.delete(partnerSites)
.where(eq(partnerSites.siteId, siteId));
// Create the new partner-site association
const now = new Date();
try {
await this.databaseService.db.insert(partnerSites).values({
partnerId: partnerId,
siteId: siteId,
createdAt: now,
updatedAt: now,
});
} catch (insertError) {
// Handle unique constraint violation for partner-site association
if (
insertError.code === '23505' ||
insertError.message?.includes('duplicate key')
) {
throw new ConflictException(
`Site with ID ${siteId} is already associated with partner ID ${partnerId}`,
);
}
throw insertError;
}
return {
message: `Site ${siteId} is now associated with partner ${partnerId}`,
};
} catch (error) {
if (
error instanceof NotFoundException ||
error instanceof ConflictException
) {
throw error;
}
throw error;
}
}
async remove(id: number) { async remove(id: number) {
try { try {
const deletedSites = await this.databaseService.db const deletedSites = await this.databaseService.db
...@@ -356,6 +611,10 @@ export class SitesService { ...@@ -356,6 +611,10 @@ export class SitesService {
updatedById: sites.updatedById, updatedById: sites.updatedById,
latestInspectionStatus: inspections.status, latestInspectionStatus: inspections.status,
latestInspectionDate: inspections.date, latestInspectionDate: inspections.date,
partnerId: partners.id,
partnerName: partners.name,
partnerDescription: partners.description,
partnerIsActive: partners.isActive,
}) })
.from(sites) .from(sites)
.leftJoin( .leftJoin(
...@@ -370,6 +629,8 @@ export class SitesService { ...@@ -370,6 +629,8 @@ export class SitesService {
)`, )`,
), ),
) )
.leftJoin(partnerSites, eq(partnerSites.siteId, sites.id))
.leftJoin(partners, eq(partners.id, partnerSites.partnerId))
.where(eq(sites.siteCode, siteCode)) .where(eq(sites.siteCode, siteCode))
.limit(1); .limit(1);
...@@ -386,6 +647,14 @@ export class SitesService { ...@@ -386,6 +647,14 @@ export class SitesService {
nextInspectionDueDate: this.calculateNextInspectionDueDate( nextInspectionDueDate: this.calculateNextInspectionDueDate(
site.latestInspectionDate, site.latestInspectionDate,
), ),
partner: site.partnerId
? {
id: site.partnerId,
name: site.partnerName,
description: site.partnerDescription,
isActive: site.partnerIsActive,
}
: null,
_count: { candidates: 0 }, _count: { candidates: 0 },
}; };
} }
...@@ -414,6 +683,10 @@ export class SitesService { ...@@ -414,6 +683,10 @@ export class SitesService {
longitude: sites.longitude, longitude: sites.longitude,
latestInspectionStatus: inspections.status, latestInspectionStatus: inspections.status,
latestInspectionDate: inspections.date, latestInspectionDate: inspections.date,
partnerId: partners.id,
partnerName: partners.name,
partnerDescription: partners.description,
partnerIsActive: partners.isActive,
}) })
.from(sites) .from(sites)
.leftJoin( .leftJoin(
...@@ -428,7 +701,20 @@ export class SitesService { ...@@ -428,7 +701,20 @@ export class SitesService {
)`, )`,
), ),
) )
.where(whereCondition); .leftJoin(partnerSites, eq(partnerSites.siteId, sites.id))
.leftJoin(partners, eq(partners.id, partnerSites.partnerId))
.where(
and(
whereCondition,
// Apply inspection status filter in WHERE clause to exclude null values
findSitesDto?.inspectionStatus
? and(
isNotNull(inspections.status),
eq(inspections.status, findSitesDto.inspectionStatus as any),
)
: undefined,
),
);
return sitesList.map((site) => ({ return sitesList.map((site) => ({
...site, ...site,
...@@ -437,6 +723,14 @@ export class SitesService { ...@@ -437,6 +723,14 @@ export class SitesService {
nextInspectionDueDate: this.calculateNextInspectionDueDate( nextInspectionDueDate: this.calculateNextInspectionDueDate(
site.latestInspectionDate, site.latestInspectionDate,
), ),
partner: site.partnerId
? {
id: site.partnerId,
name: site.partnerName,
description: site.partnerDescription,
isActive: site.partnerIsActive,
}
: null,
})); }));
} }
} }
...@@ -48,7 +48,7 @@ export class TelecommunicationStationIdentificationController { ...@@ -48,7 +48,7 @@ export class TelecommunicationStationIdentificationController {
@Post() @Post()
@UseGuards(RolesGuard) @UseGuards(RolesGuard)
@Roles(Role.ADMIN, Role.SUPERADMIN) @Roles(Role.ADMIN, Role.SUPERADMIN, Role.OPERATOR, Role.PARTNER)
@ApiOperation({ @ApiOperation({
summary: 'Create a new telecommunication station identification', summary: 'Create a new telecommunication station identification',
}) })
...@@ -234,7 +234,7 @@ export class TelecommunicationStationIdentificationController { ...@@ -234,7 +234,7 @@ export class TelecommunicationStationIdentificationController {
@Put(':id') @Put(':id')
@UseGuards(RolesGuard) @UseGuards(RolesGuard)
@Roles(Role.ADMIN, Role.SUPERADMIN) @Roles(Role.ADMIN, Role.SUPERADMIN, Role.OPERATOR, Role.PARTNER)
@ApiOperation({ @ApiOperation({
summary: 'Update a telecommunication station identification', summary: 'Update a telecommunication station identification',
}) })
......
...@@ -5,6 +5,7 @@ import { ...@@ -5,6 +5,7 @@ import {
IsNotEmpty, IsNotEmpty,
IsString, IsString,
MinLength, MinLength,
IsOptional,
} from 'class-validator'; } from 'class-validator';
import { roleEnum } from '../../../database/schema'; import { roleEnum } from '../../../database/schema';
...@@ -43,4 +44,13 @@ export class CreateUserDto { ...@@ -43,4 +44,13 @@ export class CreateUserDto {
}) })
@IsEnum(roleEnum.enumValues) @IsEnum(roleEnum.enumValues)
role: (typeof roleEnum.enumValues)[number] = 'VIEWER'; role: (typeof roleEnum.enumValues)[number] = 'VIEWER';
@ApiProperty({
description: 'URL to the user signature image',
example: '/uploads/signatures/user123_signature.png',
required: false,
})
@IsOptional()
@IsString()
signature?: string;
} }
...@@ -16,4 +16,13 @@ export class UpdateUserDto extends PartialType(CreateUserDto) { ...@@ -16,4 +16,13 @@ export class UpdateUserDto extends PartialType(CreateUserDto) {
@IsOptional() @IsOptional()
@IsDate() @IsDate()
resetTokenExpiry?: Date | null; resetTokenExpiry?: Date | null;
@ApiProperty({
description: 'URL to the user signature image',
example: '/uploads/signatures/user123_signature.png',
required: false,
})
@IsOptional()
@IsString()
signature?: string;
} }
...@@ -9,7 +9,10 @@ import { ...@@ -9,7 +9,10 @@ import {
ParseIntPipe, ParseIntPipe,
UseGuards, UseGuards,
Query, Query,
UseInterceptors,
UploadedFile,
} from '@nestjs/common'; } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { UsersService } from './users.service'; import { UsersService } from './users.service';
import { CreateUserDto } from './dto/create-user.dto'; import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto'; import { UpdateUserDto } from './dto/update-user.dto';
...@@ -20,6 +23,9 @@ import { ...@@ -20,6 +23,9 @@ import {
ApiResponse, ApiResponse,
ApiBearerAuth, ApiBearerAuth,
ApiQuery, ApiQuery,
ApiConsumes,
ApiBody,
ApiParam,
} from '@nestjs/swagger'; } from '@nestjs/swagger';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { Roles } from '../auth/decorators/roles.decorator'; import { Roles } from '../auth/decorators/roles.decorator';
...@@ -34,6 +40,8 @@ const Role = { ...@@ -34,6 +40,8 @@ const Role = {
PARTNER: 'PARTNER', PARTNER: 'PARTNER',
} as const; } as const;
import { User } from '../auth/decorators/user.decorator'; import { User } from '../auth/decorators/user.decorator';
import { multerConfig } from '../../common/multer/multer.config';
import { saveUserSignature } from '../../common/utils/file-upload.utils';
@ApiTags('users') @ApiTags('users')
@Controller('users') @Controller('users')
...@@ -203,4 +211,76 @@ export class UsersController { ...@@ -203,4 +211,76 @@ export class UsersController {
) { ) {
return this.usersService.deactivateUser(id, role); return this.usersService.deactivateUser(id, role);
} }
@Post(':id/signature')
@Roles(
Role.SUPERADMIN,
Role.ADMIN,
Role.MANAGER,
Role.PARTNER,
Role.OPERATOR,
Role.VIEWER,
)
@UseInterceptors(FileInterceptor('signature', multerConfig))
@ApiOperation({
summary: 'Upload user signature',
description:
'Uploads a signature image for a user. Only users with SUPERADMIN, ADMIN, or MANAGER roles can upload signatures.',
})
@ApiResponse({
status: 200,
description: 'The signature has been successfully uploaded.',
})
@ApiResponse({ status: 400, description: 'Invalid input data.' })
@ApiResponse({ status: 401, description: 'Unauthorized.' })
@ApiResponse({
status: 403,
description: 'Forbidden - Insufficient permissions.',
})
@ApiResponse({ status: 404, description: 'User not found.' })
@ApiConsumes('multipart/form-data')
@ApiBody({
description: 'Signature upload data',
schema: {
type: 'object',
required: ['signature'],
properties: {
signature: {
type: 'string',
format: 'binary',
description: 'Signature image file (max 5MB, images only)',
},
},
},
})
@ApiParam({
name: 'id',
type: Number,
description: 'ID of the user',
example: 1,
})
async uploadUserSignature(
@Param('id', ParseIntPipe) id: number,
@UploadedFile() file: Express.Multer.File,
) {
try {
if (!file) {
throw new Error('No file provided. Please upload a signature file.');
}
// Save the signature file
const signatureUrl = await saveUserSignature(file, id);
// Update the user with the signature URL
await this.usersService.update(id, { signature: signatureUrl });
return {
message: 'Signature uploaded successfully',
signatureUrl,
};
} catch (error) {
console.error('Error uploading user signature:', error);
throw error;
}
}
} }
...@@ -142,6 +142,7 @@ export class UsersService { ...@@ -142,6 +142,7 @@ export class UsersService {
email: users.email, email: users.email,
name: users.name, name: users.name,
role: users.role, role: users.role,
signature: users.signature,
isActive: users.isActive, isActive: users.isActive,
createdAt: users.createdAt, createdAt: users.createdAt,
updatedAt: users.updatedAt, updatedAt: users.updatedAt,
...@@ -172,9 +173,11 @@ export class UsersService { ...@@ -172,9 +173,11 @@ export class UsersService {
email: users.email, email: users.email,
name: users.name, name: users.name,
role: users.role, role: users.role,
signature: users.signature,
isActive: users.isActive, isActive: users.isActive,
createdAt: users.createdAt, createdAt: users.createdAt,
updatedAt: users.updatedAt, updatedAt: users.updatedAt,
partnerId: users.partnerId,
}) })
.from(users) .from(users)
.where(eq(users.id, id)) .where(eq(users.id, id))
...@@ -207,6 +210,7 @@ export class UsersService { ...@@ -207,6 +210,7 @@ export class UsersService {
isActive: users.isActive, isActive: users.isActive,
createdAt: users.createdAt, createdAt: users.createdAt,
updatedAt: users.updatedAt, updatedAt: users.updatedAt,
partnerId: users.partnerId,
}); });
if (updatedUsers.length === 0) { if (updatedUsers.length === 0) {
...@@ -282,6 +286,7 @@ export class UsersService { ...@@ -282,6 +286,7 @@ export class UsersService {
isActive: users.isActive, isActive: users.isActive,
createdAt: users.createdAt, createdAt: users.createdAt,
updatedAt: users.updatedAt, updatedAt: users.updatedAt,
partnerId: users.partnerId,
}); });
if (updatedUsers.length === 0) { if (updatedUsers.length === 0) {
...@@ -315,6 +320,7 @@ export class UsersService { ...@@ -315,6 +320,7 @@ export class UsersService {
isActive: users.isActive, isActive: users.isActive,
createdAt: users.createdAt, createdAt: users.createdAt,
updatedAt: users.updatedAt, updatedAt: users.updatedAt,
partnerId: users.partnerId,
}); });
if (updatedUsers.length === 0) { if (updatedUsers.length === 0) {
...@@ -337,6 +343,7 @@ export class UsersService { ...@@ -337,6 +343,7 @@ export class UsersService {
isActive: users.isActive, isActive: users.isActive,
createdAt: users.createdAt, createdAt: users.createdAt,
updatedAt: users.updatedAt, updatedAt: users.updatedAt,
partnerId: users.partnerId,
}) })
.from(users) .from(users)
.where(eq(users.isActive, false)); .where(eq(users.isActive, false));
......
-- Test script to verify the resume photo constraint
-- This script tests various scenarios to ensure the constraint works correctly
-- Test 1: Insert 6 resume photos (should succeed)
INSERT INTO "InspectionPhoto" ("url", "filename", "mimeType", "size", "inspectionId", "isResume", "order", "isPrincipal", "createdAt", "updatedAt")
VALUES
('/test1.jpg', 'test1.jpg', 'image/jpeg', 1000, 1, true, 1, false, NOW(), NOW()),
('/test2.jpg', 'test2.jpg', 'image/jpeg', 1000, 1, true, 2, false, NOW(), NOW()),
('/test3.jpg', 'test3.jpg', 'image/jpeg', 1000, 1, true, 3, false, NOW(), NOW()),
('/test4.jpg', 'test4.jpg', 'image/jpeg', 1000, 1, true, 4, false, NOW(), NOW()),
('/test5.jpg', 'test5.jpg', 'image/jpeg', 1000, 1, true, 5, false, NOW(), NOW()),
('/test6.jpg', 'test6.jpg', 'image/jpeg', 1000, 1, true, 6, false, NOW(), NOW());
-- Test 2: Try to insert a 7th resume photo (should fail)
INSERT INTO "InspectionPhoto" ("url", "filename", "mimeType", "size", "inspectionId", "isResume", "order", "isPrincipal", "createdAt", "updatedAt")
VALUES ('/test7.jpg', 'test7.jpg', 'image/jpeg', 1000, 1, true, 7, false, NOW(), NOW());
-- Test 3: Try to update a non-resume photo to resume (should fail if already 6 resume photos)
UPDATE "InspectionPhoto" SET "isResume" = true WHERE "filename" = 'non-resume.jpg' AND "inspectionId" = 1;
-- Test 4: Update an existing resume photo (should succeed)
UPDATE "InspectionPhoto" SET "order" = 10 WHERE "filename" = 'test1.jpg' AND "inspectionId" = 1;
-- Test 5: Set a resume photo to non-resume (should succeed)
UPDATE "InspectionPhoto" SET "isResume" = false WHERE "filename" = 'test1.jpg' AND "inspectionId" = 1;
-- Test 6: Try to set a non-resume photo to resume (should succeed now that we have 5 resume photos)
UPDATE "InspectionPhoto" SET "isResume" = true WHERE "filename" = 'non-resume.jpg' AND "inspectionId" = 1;
-- Clean up test data
DELETE FROM "InspectionPhoto" WHERE "inspectionId" = 1;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment