Checkpoint: Ajout du bouton "Vérifier maintenant" pour forcer une vérification immédiate des emails sans attendre le prochain cycle automatique.
This commit is contained in:
26
.manus/db/db-query-1770806523006.json
Normal file
26
.manus/db/db-query-1770806523006.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"query": "SELECT * FROM importSettings;",
|
||||
"command": "mysql --batch --raw --column-names --default-character-set=utf8mb4 --host gateway02.us-east-1.prod.aws.tidbcloud.com --port 4000 --user 4CrrYuB5tme73Qo.bd4328423008 --database fo4DRyBgjsuiigFAgNLuWm --execute SELECT * FROM importSettings;",
|
||||
"rows": [
|
||||
{
|
||||
"id": "1",
|
||||
"userId": "1",
|
||||
"manualImportEnabled": "1",
|
||||
"autoImportEnabled": "0",
|
||||
"autoImportSourcePath": "NULL",
|
||||
"autoImportFrequency": "60",
|
||||
"emailImportEnabled": "1",
|
||||
"emailImportAddress": "test-applicatif@itinova.org",
|
||||
"emailImportPassword": "X.184037964588um",
|
||||
"emailImportHost": "outlook.office365.com",
|
||||
"emailImportPort": "993",
|
||||
"emailImportFrequency": "2",
|
||||
"createdAt": "2026-02-11 10:07:32",
|
||||
"updatedAt": "2026-02-11 10:34:09"
|
||||
}
|
||||
],
|
||||
"messages": [],
|
||||
"stdout": "id\tuserId\tmanualImportEnabled\tautoImportEnabled\tautoImportSourcePath\tautoImportFrequency\temailImportEnabled\temailImportAddress\temailImportPassword\temailImportHost\temailImportPort\temailImportFrequency\tcreatedAt\tupdatedAt\n1\t1\t1\t0\tNULL\t60\t1\ttest-applicatif@itinova.org\tX.184037964588um\toutlook.office365.com\t993\t2\t2026-02-11 10:07:32\t2026-02-11 10:34:09\n",
|
||||
"stderr": "",
|
||||
"execution_time_ms": 225
|
||||
}
|
||||
18
.manus/db/db-query-1770806548135.json
Normal file
18
.manus/db/db-query-1770806548135.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"query": "SELECT \n userId,\n emailImportEnabled,\n emailImportAddress,\n emailImportHost,\n emailImportPort,\n emailImportFrequency\nFROM importSettings;",
|
||||
"command": "mysql --batch --raw --column-names --default-character-set=utf8mb4 --host gateway02.us-east-1.prod.aws.tidbcloud.com --port 4000 --user 4CrrYuB5tme73Qo.bd4328423008 --database fo4DRyBgjsuiigFAgNLuWm --execute SELECT \n userId,\n emailImportEnabled,\n emailImportAddress,\n emailImportHost,\n emailImportPort,\n emailImportFrequency\nFROM importSettings;",
|
||||
"rows": [
|
||||
{
|
||||
"userId": "1",
|
||||
"emailImportEnabled": "1",
|
||||
"emailImportAddress": "test-applicatif@itinova.org",
|
||||
"emailImportHost": "outlook.office365.com",
|
||||
"emailImportPort": "993",
|
||||
"emailImportFrequency": "2"
|
||||
}
|
||||
],
|
||||
"messages": [],
|
||||
"stdout": "userId\temailImportEnabled\temailImportAddress\temailImportHost\temailImportPort\temailImportFrequency\n1\t1\ttest-applicatif@itinova.org\toutlook.office365.com\t993\t2\n",
|
||||
"stderr": "",
|
||||
"execution_time_ms": 54
|
||||
}
|
||||
8
.manus/db/db-query-error-1770806532942.json
Normal file
8
.manus/db/db-query-error-1770806532942.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"query": "SELECT \n userId,\n manualImportEnabled,\n folderImportEnabled,\n folderImportPath,\n folderImportFrequency,\n emailImportEnabled,\n emailImportAddress,\n emailImportHost,\n emailImportPort,\n emailImportFrequency\nFROM importSettings;",
|
||||
"command": "mysql --batch --raw --column-names --default-character-set=utf8mb4 --host gateway02.us-east-1.prod.aws.tidbcloud.com --port 4000 --user 4CrrYuB5tme73Qo.bd4328423008 --database fo4DRyBgjsuiigFAgNLuWm --execute SELECT \n userId,\n manualImportEnabled,\n folderImportEnabled,\n folderImportPath,\n folderImportFrequency,\n emailImportEnabled,\n emailImportAddress,\n emailImportHost,\n emailImportPort,\n emailImportFrequency\nFROM importSettings;",
|
||||
"returncode": 1,
|
||||
"logs": [
|
||||
"ERROR 1054 (42S22) at line 1: Unknown column 'folderimportenabled' in 'field list'"
|
||||
]
|
||||
}
|
||||
@@ -16,6 +16,8 @@ export default function ImportSettings() {
|
||||
const updateMutation = trpc.importSettings.update.useMutation();
|
||||
const startEmailServiceMutation = trpc.emailImportService.start.useMutation();
|
||||
const stopEmailServiceMutation = trpc.emailImportService.stop.useMutation();
|
||||
const checkNowEmailMutation = trpc.emailImportService.checkNow.useMutation();
|
||||
const utils = trpc.useUtils();
|
||||
const startFolderServiceMutation = trpc.folderImportService.start.useMutation();
|
||||
const stopFolderServiceMutation = trpc.folderImportService.stop.useMutation();
|
||||
|
||||
@@ -413,6 +415,42 @@ export default function ImportSettings() {
|
||||
Service actif
|
||||
</span>
|
||||
)}
|
||||
|
||||
{emailServiceStatus?.isRunning && (
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={async () => {
|
||||
try {
|
||||
toast.info("V\u00e9rification en cours...", {
|
||||
description: "Connexion au serveur IMAP et recherche de nouveaux emails.",
|
||||
});
|
||||
const result = await checkNowEmailMutation.mutateAsync();
|
||||
if (result.success) {
|
||||
await utils.importLogs.getByUser.invalidate();
|
||||
toast.success("V\u00e9rification termin\u00e9e", {
|
||||
description: result.message,
|
||||
});
|
||||
} else {
|
||||
toast.error("Erreur", {
|
||||
description: result.message,
|
||||
});
|
||||
}
|
||||
} catch (error: any) {
|
||||
toast.error("Erreur", {
|
||||
description: error.message || "Impossible de v\u00e9rifier les emails.",
|
||||
});
|
||||
}
|
||||
}}
|
||||
disabled={checkNowEmailMutation.isPending}
|
||||
>
|
||||
{checkNowEmailMutation.isPending ? (
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
) : (
|
||||
<Mail className="mr-2 h-4 w-4" />
|
||||
)}
|
||||
V\u00e9rifier maintenant
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -442,6 +442,40 @@ export function isEmailImportServiceRunning(userId: number): boolean {
|
||||
return activeIntervals.has(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually trigger an immediate email check for a user
|
||||
*/
|
||||
export async function triggerEmailCheck(userId: number): Promise<{ success: boolean; message: string }> {
|
||||
try {
|
||||
// Get user's import settings
|
||||
const settings = await getImportSettingsByUser(userId);
|
||||
|
||||
if (!settings || settings.emailImportEnabled !== 1) {
|
||||
return { success: false, message: "Import par email non activ\u00e9" };
|
||||
}
|
||||
|
||||
if (!settings.emailImportAddress || !settings.emailImportPassword || !settings.emailImportHost) {
|
||||
return { success: false, message: "Configuration IMAP incompl\u00e8te" };
|
||||
}
|
||||
|
||||
const config: EmailImportConfig = {
|
||||
userId,
|
||||
emailAddress: settings.emailImportAddress,
|
||||
password: settings.emailImportPassword,
|
||||
host: settings.emailImportHost,
|
||||
port: settings.emailImportPort || 993,
|
||||
};
|
||||
|
||||
console.log(`[EmailImport] Manual check triggered for user ${userId}`);
|
||||
await checkEmailsForPDFs(config);
|
||||
|
||||
return { success: true, message: "V\u00e9rification termin\u00e9e avec succ\u00e8s" };
|
||||
} catch (error: any) {
|
||||
console.error(`[EmailImport] Error during manual check for user ${userId}:`, error);
|
||||
return { success: false, message: `Erreur: ${error.message}` };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop all email import services
|
||||
*/
|
||||
|
||||
@@ -34,7 +34,7 @@ import { loginLocal, hashPassword, getAzureAuthUrl, isAzureAdConfigured, generat
|
||||
import { extractInvoicesWithMistral, generateMetadataJSON } from "./invoiceExtractor";
|
||||
import { localStoragePut, generateStorageKey } from "./localStorage";
|
||||
import { testSftpConnection, exportInvoiceToSftp, getUserSftpConfig } from "./sftpExport";
|
||||
import { startEmailImportService, stopEmailImportService, isEmailImportServiceRunning } from "./emailImportService";
|
||||
import { startEmailImportService, stopEmailImportService, isEmailImportServiceRunning, triggerEmailCheck } from "./emailImportService";
|
||||
import { startFolderImportService, stopFolderImportService, isFolderImportServiceRunning } from "./folderImportService";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
|
||||
@@ -614,8 +614,12 @@ export const appRouter = router({
|
||||
}),
|
||||
|
||||
status: protectedProcedure.query(async ({ ctx }) => {
|
||||
const isRunning = isEmailImportServiceRunning(ctx.user.id);
|
||||
return { isRunning };
|
||||
return { isRunning: isEmailImportServiceRunning(ctx.user.id) };
|
||||
}),
|
||||
|
||||
checkNow: protectedProcedure.mutation(async ({ ctx }) => {
|
||||
const result = await triggerEmailCheck(ctx.user.id);
|
||||
return result;
|
||||
}),
|
||||
}),
|
||||
|
||||
|
||||
8
todo.md
8
todo.md
@@ -183,3 +183,11 @@
|
||||
- [x] Ajouter bouton "Effacer les logs" dans la page History
|
||||
- [x] Ajouter confirmation avant suppression (AlertDialog)
|
||||
- [x] Tester la fonctionnalité
|
||||
|
||||
## Bug : Import automatique par email ne fonctionne pas
|
||||
- [x] Vérifier la configuration IMAP dans la base de données
|
||||
- [x] Vérifier si le service d'import email est démarré
|
||||
- [x] Ajouter un bouton "Vérifier maintenant" pour forcer une vérification immédiate
|
||||
- [x] Ajouter fonction triggerEmailCheck dans emailImportService
|
||||
- [x] Ajouter route tRPC emailImportService.checkNow
|
||||
- [ ] Tester avec un email réel et diagnostiquer les erreurs IMAP
|
||||
|
||||
Reference in New Issue
Block a user