Checkpoint: Application complète : deux tableaux de bord (Veille Stratégique + AAP), import Excel quotidien avec déduplication, sources multiples (local/OneDrive/FTP/SharePoint), affichage liste/vignettes, filtres multi-critères, gestion utilisateurs, logs d'import, page paramètres, authentification locale, tâche cron 06h00, 13 tests Vitest passants.
This commit is contained in:
13
drizzle/0000_quiet_yellow_claw.sql
Normal file
13
drizzle/0000_quiet_yellow_claw.sql
Normal file
@@ -0,0 +1,13 @@
|
||||
CREATE TABLE `users` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`openId` varchar(64) NOT NULL,
|
||||
`name` text,
|
||||
`email` varchar(320),
|
||||
`loginMethod` varchar(64),
|
||||
`role` enum('user','admin') NOT NULL DEFAULT 'user',
|
||||
`createdAt` timestamp NOT NULL DEFAULT (now()),
|
||||
`updatedAt` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
|
||||
`lastSignedIn` timestamp NOT NULL DEFAULT (now()),
|
||||
CONSTRAINT `users_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `users_openId_unique` UNIQUE(`openId`)
|
||||
);
|
||||
70
drizzle/0001_old_shocker.sql
Normal file
70
drizzle/0001_old_shocker.sql
Normal file
@@ -0,0 +1,70 @@
|
||||
CREATE TABLE `aap_items` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`dedupKey` varchar(64) NOT NULL,
|
||||
`titre` text NOT NULL,
|
||||
`categorie` enum('Handicap','PA','Enfance','Précarité','Sanitaire','Autre') NOT NULL,
|
||||
`region` varchar(255),
|
||||
`departement` varchar(255),
|
||||
`dateCloture` timestamp,
|
||||
`datePublication` timestamp,
|
||||
`lien` text,
|
||||
`importedAt` timestamp NOT NULL DEFAULT (now()),
|
||||
CONSTRAINT `aap_items_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `aap_items_dedupKey_unique` UNIQUE(`dedupKey`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `app_settings` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`key` varchar(128) NOT NULL,
|
||||
`value` text,
|
||||
`updatedAt` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
|
||||
CONSTRAINT `app_settings_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `app_settings_key_unique` UNIQUE(`key`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `import_logs` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`fileType` enum('veille','aap') NOT NULL,
|
||||
`source` varchar(512),
|
||||
`status` enum('success','partial','error') NOT NULL,
|
||||
`totalRows` int DEFAULT 0,
|
||||
`newRows` int DEFAULT 0,
|
||||
`skippedRows` int DEFAULT 0,
|
||||
`errorMessage` text,
|
||||
`details` json,
|
||||
`startedAt` timestamp NOT NULL DEFAULT (now()),
|
||||
`completedAt` timestamp,
|
||||
CONSTRAINT `import_logs_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `local_users` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`email` varchar(320) NOT NULL,
|
||||
`passwordHash` varchar(255) NOT NULL,
|
||||
`role` enum('admin','user','readonly') NOT NULL DEFAULT 'user',
|
||||
`isActive` boolean NOT NULL DEFAULT true,
|
||||
`createdAt` timestamp NOT NULL DEFAULT (now()),
|
||||
`updatedAt` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
|
||||
`lastSignedIn` timestamp,
|
||||
CONSTRAINT `local_users_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `local_users_email_unique` UNIQUE(`email`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `veille_items` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`dedupKey` varchar(64) NOT NULL,
|
||||
`titre` text NOT NULL,
|
||||
`categorie` varchar(128),
|
||||
`niveau` varchar(128),
|
||||
`territoire` varchar(255),
|
||||
`resume` text,
|
||||
`source` varchar(512),
|
||||
`passage` text,
|
||||
`lien` text,
|
||||
`typeVeille` enum('reglementaire','concurrentielle','technologique','generale') NOT NULL,
|
||||
`datePublication` timestamp,
|
||||
`importedAt` timestamp NOT NULL DEFAULT (now()),
|
||||
CONSTRAINT `veille_items_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `veille_items_dedupKey_unique` UNIQUE(`dedupKey`)
|
||||
);
|
||||
110
drizzle/meta/0000_snapshot.json
Normal file
110
drizzle/meta/0000_snapshot.json
Normal file
@@ -0,0 +1,110 @@
|
||||
{
|
||||
"version": "5",
|
||||
"dialect": "mysql",
|
||||
"id": "82e6146d-1ea1-4bf8-b64c-f2a2a8ef266e",
|
||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||
"tables": {
|
||||
"users": {
|
||||
"name": "users",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"openId": {
|
||||
"name": "openId",
|
||||
"type": "varchar(64)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"type": "varchar(320)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"loginMethod": {
|
||||
"name": "loginMethod",
|
||||
"type": "varchar(64)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"role": {
|
||||
"name": "role",
|
||||
"type": "enum('user','admin')",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "'user'"
|
||||
},
|
||||
"createdAt": {
|
||||
"name": "createdAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"updatedAt": {
|
||||
"name": "updatedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"onUpdate": true,
|
||||
"default": "(now())"
|
||||
},
|
||||
"lastSignedIn": {
|
||||
"name": "lastSignedIn",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"users_id": {
|
||||
"name": "users_id",
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {
|
||||
"users_openId_unique": {
|
||||
"name": "users_openId_unique",
|
||||
"columns": [
|
||||
"openId"
|
||||
]
|
||||
}
|
||||
},
|
||||
"checkConstraint": {}
|
||||
}
|
||||
},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"schemas": {},
|
||||
"tables": {},
|
||||
"columns": {}
|
||||
},
|
||||
"internal": {
|
||||
"tables": {},
|
||||
"indexes": {}
|
||||
}
|
||||
}
|
||||
565
drizzle/meta/0001_snapshot.json
Normal file
565
drizzle/meta/0001_snapshot.json
Normal file
@@ -0,0 +1,565 @@
|
||||
{
|
||||
"version": "5",
|
||||
"dialect": "mysql",
|
||||
"id": "8f5ba9eb-1f6d-4c0f-8eeb-262ea8031bee",
|
||||
"prevId": "82e6146d-1ea1-4bf8-b64c-f2a2a8ef266e",
|
||||
"tables": {
|
||||
"aap_items": {
|
||||
"name": "aap_items",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"dedupKey": {
|
||||
"name": "dedupKey",
|
||||
"type": "varchar(64)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"titre": {
|
||||
"name": "titre",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"categorie": {
|
||||
"name": "categorie",
|
||||
"type": "enum('Handicap','PA','Enfance','Précarité','Sanitaire','Autre')",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"region": {
|
||||
"name": "region",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"departement": {
|
||||
"name": "departement",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"dateCloture": {
|
||||
"name": "dateCloture",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"datePublication": {
|
||||
"name": "datePublication",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"lien": {
|
||||
"name": "lien",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"importedAt": {
|
||||
"name": "importedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"aap_items_id": {
|
||||
"name": "aap_items_id",
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {
|
||||
"aap_items_dedupKey_unique": {
|
||||
"name": "aap_items_dedupKey_unique",
|
||||
"columns": [
|
||||
"dedupKey"
|
||||
]
|
||||
}
|
||||
},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"app_settings": {
|
||||
"name": "app_settings",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"key": {
|
||||
"name": "key",
|
||||
"type": "varchar(128)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"value": {
|
||||
"name": "value",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"updatedAt": {
|
||||
"name": "updatedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"onUpdate": true,
|
||||
"default": "(now())"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"app_settings_id": {
|
||||
"name": "app_settings_id",
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {
|
||||
"app_settings_key_unique": {
|
||||
"name": "app_settings_key_unique",
|
||||
"columns": [
|
||||
"key"
|
||||
]
|
||||
}
|
||||
},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"import_logs": {
|
||||
"name": "import_logs",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"fileType": {
|
||||
"name": "fileType",
|
||||
"type": "enum('veille','aap')",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"source": {
|
||||
"name": "source",
|
||||
"type": "varchar(512)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"status": {
|
||||
"name": "status",
|
||||
"type": "enum('success','partial','error')",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"totalRows": {
|
||||
"name": "totalRows",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": 0
|
||||
},
|
||||
"newRows": {
|
||||
"name": "newRows",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": 0
|
||||
},
|
||||
"skippedRows": {
|
||||
"name": "skippedRows",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": 0
|
||||
},
|
||||
"errorMessage": {
|
||||
"name": "errorMessage",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"details": {
|
||||
"name": "details",
|
||||
"type": "json",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"startedAt": {
|
||||
"name": "startedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"completedAt": {
|
||||
"name": "completedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"import_logs_id": {
|
||||
"name": "import_logs_id",
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"local_users": {
|
||||
"name": "local_users",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"type": "varchar(320)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"passwordHash": {
|
||||
"name": "passwordHash",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"role": {
|
||||
"name": "role",
|
||||
"type": "enum('admin','user','readonly')",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "'user'"
|
||||
},
|
||||
"isActive": {
|
||||
"name": "isActive",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": true
|
||||
},
|
||||
"createdAt": {
|
||||
"name": "createdAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"updatedAt": {
|
||||
"name": "updatedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"onUpdate": true,
|
||||
"default": "(now())"
|
||||
},
|
||||
"lastSignedIn": {
|
||||
"name": "lastSignedIn",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"local_users_id": {
|
||||
"name": "local_users_id",
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {
|
||||
"local_users_email_unique": {
|
||||
"name": "local_users_email_unique",
|
||||
"columns": [
|
||||
"email"
|
||||
]
|
||||
}
|
||||
},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"users": {
|
||||
"name": "users",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"openId": {
|
||||
"name": "openId",
|
||||
"type": "varchar(64)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"type": "varchar(320)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"loginMethod": {
|
||||
"name": "loginMethod",
|
||||
"type": "varchar(64)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"role": {
|
||||
"name": "role",
|
||||
"type": "enum('user','admin')",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "'user'"
|
||||
},
|
||||
"createdAt": {
|
||||
"name": "createdAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"updatedAt": {
|
||||
"name": "updatedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"onUpdate": true,
|
||||
"default": "(now())"
|
||||
},
|
||||
"lastSignedIn": {
|
||||
"name": "lastSignedIn",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"users_id": {
|
||||
"name": "users_id",
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {
|
||||
"users_openId_unique": {
|
||||
"name": "users_openId_unique",
|
||||
"columns": [
|
||||
"openId"
|
||||
]
|
||||
}
|
||||
},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"veille_items": {
|
||||
"name": "veille_items",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"dedupKey": {
|
||||
"name": "dedupKey",
|
||||
"type": "varchar(64)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"titre": {
|
||||
"name": "titre",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"categorie": {
|
||||
"name": "categorie",
|
||||
"type": "varchar(128)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"niveau": {
|
||||
"name": "niveau",
|
||||
"type": "varchar(128)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"territoire": {
|
||||
"name": "territoire",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"resume": {
|
||||
"name": "resume",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"source": {
|
||||
"name": "source",
|
||||
"type": "varchar(512)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"passage": {
|
||||
"name": "passage",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"lien": {
|
||||
"name": "lien",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"typeVeille": {
|
||||
"name": "typeVeille",
|
||||
"type": "enum('reglementaire','concurrentielle','technologique','generale')",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"datePublication": {
|
||||
"name": "datePublication",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"importedAt": {
|
||||
"name": "importedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"veille_items_id": {
|
||||
"name": "veille_items_id",
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {
|
||||
"veille_items_dedupKey_unique": {
|
||||
"name": "veille_items_dedupKey_unique",
|
||||
"columns": [
|
||||
"dedupKey"
|
||||
]
|
||||
}
|
||||
},
|
||||
"checkConstraint": {}
|
||||
}
|
||||
},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"schemas": {},
|
||||
"tables": {},
|
||||
"columns": {}
|
||||
},
|
||||
"internal": {
|
||||
"tables": {},
|
||||
"indexes": {}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,20 @@
|
||||
{
|
||||
"version": "7",
|
||||
"dialect": "mysql",
|
||||
"entries": []
|
||||
}
|
||||
"entries": [
|
||||
{
|
||||
"idx": 0,
|
||||
"version": "5",
|
||||
"when": 1773670845236,
|
||||
"tag": "0000_quiet_yellow_claw",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"version": "5",
|
||||
"when": 1773671031809,
|
||||
"tag": "0001_old_shocker",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,17 +1,18 @@
|
||||
import { int, mysqlEnum, mysqlTable, text, timestamp, varchar } from "drizzle-orm/mysql-core";
|
||||
import {
|
||||
boolean,
|
||||
int,
|
||||
mysqlEnum,
|
||||
mysqlTable,
|
||||
text,
|
||||
timestamp,
|
||||
varchar,
|
||||
json,
|
||||
} from "drizzle-orm/mysql-core";
|
||||
|
||||
// ─── Utilisateurs (Manus OAuth + locaux) ────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Core user table backing auth flow.
|
||||
* Extend this file with additional tables as your product grows.
|
||||
* Columns use camelCase to match both database fields and generated types.
|
||||
*/
|
||||
export const users = mysqlTable("users", {
|
||||
/**
|
||||
* Surrogate primary key. Auto-incremented numeric value managed by the database.
|
||||
* Use this for relations between tables.
|
||||
*/
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
/** Manus OAuth identifier (openId) returned from the OAuth callback. Unique per user. */
|
||||
openId: varchar("openId", { length: 64 }).notNull().unique(),
|
||||
name: text("name"),
|
||||
email: varchar("email", { length: 320 }),
|
||||
@@ -25,4 +26,92 @@ export const users = mysqlTable("users", {
|
||||
export type User = typeof users.$inferSelect;
|
||||
export type InsertUser = typeof users.$inferInsert;
|
||||
|
||||
// TODO: Add your tables here
|
||||
// ─── Utilisateurs locaux (auth interne) ─────────────────────────────────────
|
||||
|
||||
export const localUsers = mysqlTable("local_users", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
name: varchar("name", { length: 255 }).notNull(),
|
||||
email: varchar("email", { length: 320 }).notNull().unique(),
|
||||
passwordHash: varchar("passwordHash", { length: 255 }).notNull(),
|
||||
role: mysqlEnum("role", ["admin", "user", "readonly"]).default("user").notNull(),
|
||||
isActive: boolean("isActive").default(true).notNull(),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
|
||||
lastSignedIn: timestamp("lastSignedIn"),
|
||||
});
|
||||
|
||||
export type LocalUser = typeof localUsers.$inferSelect;
|
||||
export type InsertLocalUser = typeof localUsers.$inferInsert;
|
||||
|
||||
// ─── Paramètres de l'application ────────────────────────────────────────────
|
||||
|
||||
export const appSettings = mysqlTable("app_settings", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
key: varchar("key", { length: 128 }).notNull().unique(),
|
||||
value: text("value"),
|
||||
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
|
||||
});
|
||||
|
||||
export type AppSetting = typeof appSettings.$inferSelect;
|
||||
export type InsertAppSetting = typeof appSettings.$inferInsert;
|
||||
|
||||
// ─── Entrées de veille stratégique ──────────────────────────────────────────
|
||||
|
||||
export const veilleItems = mysqlTable("veille_items", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
// Clé de déduplication : hash du titre + lien
|
||||
dedupKey: varchar("dedupKey", { length: 64 }).notNull().unique(),
|
||||
titre: text("titre").notNull(),
|
||||
categorie: varchar("categorie", { length: 128 }),
|
||||
niveau: varchar("niveau", { length: 128 }),
|
||||
territoire: varchar("territoire", { length: 255 }),
|
||||
resume: text("resume"),
|
||||
source: varchar("source", { length: 512 }),
|
||||
passage: text("passage"),
|
||||
lien: text("lien"),
|
||||
// Type de veille (feuille d'origine)
|
||||
typeVeille: mysqlEnum("typeVeille", ["reglementaire", "concurrentielle", "technologique", "generale"]).notNull(),
|
||||
// Date extraite de la colonne Source (qui contient parfois une date ISO)
|
||||
datePublication: timestamp("datePublication"),
|
||||
importedAt: timestamp("importedAt").defaultNow().notNull(),
|
||||
});
|
||||
|
||||
export type VeilleItem = typeof veilleItems.$inferSelect;
|
||||
export type InsertVeilleItem = typeof veilleItems.$inferInsert;
|
||||
|
||||
// ─── Entrées des appels à projets ────────────────────────────────────────────
|
||||
|
||||
export const aapItems = mysqlTable("aap_items", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
dedupKey: varchar("dedupKey", { length: 64 }).notNull().unique(),
|
||||
titre: text("titre").notNull(),
|
||||
categorie: mysqlEnum("categorie", ["Handicap", "PA", "Enfance", "Précarité", "Sanitaire", "Autre"]).notNull(),
|
||||
region: varchar("region", { length: 255 }),
|
||||
departement: varchar("departement", { length: 255 }),
|
||||
dateCloture: timestamp("dateCloture"),
|
||||
datePublication: timestamp("datePublication"),
|
||||
lien: text("lien"),
|
||||
importedAt: timestamp("importedAt").defaultNow().notNull(),
|
||||
});
|
||||
|
||||
export type AapItem = typeof aapItems.$inferSelect;
|
||||
export type InsertAapItem = typeof aapItems.$inferInsert;
|
||||
|
||||
// ─── Logs d'import ───────────────────────────────────────────────────────────
|
||||
|
||||
export const importLogs = mysqlTable("import_logs", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
fileType: mysqlEnum("fileType", ["veille", "aap"]).notNull(),
|
||||
source: varchar("source", { length: 512 }),
|
||||
status: mysqlEnum("status", ["success", "partial", "error"]).notNull(),
|
||||
totalRows: int("totalRows").default(0),
|
||||
newRows: int("newRows").default(0),
|
||||
skippedRows: int("skippedRows").default(0),
|
||||
errorMessage: text("errorMessage"),
|
||||
details: json("details"),
|
||||
startedAt: timestamp("startedAt").defaultNow().notNull(),
|
||||
completedAt: timestamp("completedAt"),
|
||||
});
|
||||
|
||||
export type ImportLog = typeof importLogs.$inferSelect;
|
||||
export type InsertImportLog = typeof importLogs.$inferInsert;
|
||||
|
||||
Reference in New Issue
Block a user