feat: QuickBooks Online integration
- Add QBO OAuth2 client with token refresh (lib/services/qbo-client.ts) - Add QBO sync service for invoices, payments, deposits, purchases, journal entries, reports (lib/services/qbo-sync-service.ts) - Add QBO types (lib/types/qbo.ts) - Add API routes: /api/qbo/auth, /api/qbo/sync, /api/qbo/disconnect - Add /admin/qbo status and sync management page - Add legal pages: /legal/eula, /legal/privacy (Intuit app assessment) - Add QBO nav link under Admin - Fix reports: remove invalid summarize_column_by, add accounting_method from Preferences API, add showrows=all&showcols=all - Add CashFlow report type alongside P&L and BalanceSheet - Add NoReportData check to skip empty report months - Add intuit_tid capture in error messages - Add redirect: follow for cluster routing - Migration 051: qbo_tokens, qbo_invoices, qbo_payments, qbo_deposits, qbo_transactions, qbo_reports tables Also includes earlier work: - Ping flap suppression pipeline step - Ticket digest reports with LLM analysis - Zabbix WAN monitor and gap analysis - Kiosk is_deleted filter fixes - Datto RMM ping target enrichment - Entity sync soft-delete detection
This commit is contained in:
parent
c518eefdb2
commit
b98c67482a
40 changed files with 6223 additions and 15 deletions
|
|
@ -15,13 +15,14 @@ import { isMsgraphConfigured } from './msgraph-factory';
|
|||
import { ZoomSyncService } from './zoom-sync-service';
|
||||
import { isZoomConfigured } from './zoom-factory';
|
||||
import { MorningSummaryService } from './morning-summary-service';
|
||||
import { TicketDigestService } from './ticket-digest-service';
|
||||
|
||||
export interface ScheduleConfig {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
cron_expression: string;
|
||||
sync_type: 'incremental' | 'full' | 'veeam-incremental' | 'veeam-full' | 'veeam-rpo-check' | 'contract-services' | 'engagement-daily' | 'zoom-daily' | 'morning-summary';
|
||||
sync_type: 'incremental' | 'full' | 'veeam-incremental' | 'veeam-full' | 'veeam-rpo-check' | 'contract-services' | 'engagement-daily' | 'zoom-daily' | 'morning-summary' | 'ticket-digest-daily' | 'ticket-digest-weekly' | 'ticket-digest-monthly';
|
||||
years_back?: number;
|
||||
is_enabled: boolean;
|
||||
last_run?: Date;
|
||||
|
|
@ -78,6 +79,14 @@ class SyncScheduler {
|
|||
return this._morningSummaryService;
|
||||
}
|
||||
|
||||
private _ticketDigestService?: TicketDigestService;
|
||||
private getTicketDigestService(): TicketDigestService {
|
||||
if (!this._ticketDigestService) {
|
||||
this._ticketDigestService = new TicketDigestService();
|
||||
}
|
||||
return this._ticketDigestService;
|
||||
}
|
||||
|
||||
private getZoomSyncService(): ZoomSyncService {
|
||||
if (!this._zoomSyncService) {
|
||||
this._zoomSyncService = new ZoomSyncService();
|
||||
|
|
@ -242,6 +251,30 @@ class SyncScheduler {
|
|||
sync_type: 'morning-summary',
|
||||
is_enabled: false,
|
||||
},
|
||||
{
|
||||
id: 'ticket-digest-daily',
|
||||
name: 'Daily Ticket Digest',
|
||||
description: 'LLM-analyzed ticket digest for the previous day, delivered to Teams at 7 AM Mon–Fri',
|
||||
cron_expression: '0 7 * * 1-5',
|
||||
sync_type: 'ticket-digest-daily',
|
||||
is_enabled: false,
|
||||
},
|
||||
{
|
||||
id: 'ticket-digest-weekly',
|
||||
name: 'Weekly Ticket Digest',
|
||||
description: 'LLM-analyzed ticket digest for the previous week, delivered to Teams at 7 AM Monday',
|
||||
cron_expression: '0 7 * * 1',
|
||||
sync_type: 'ticket-digest-weekly',
|
||||
is_enabled: false,
|
||||
},
|
||||
{
|
||||
id: 'ticket-digest-monthly',
|
||||
name: 'Monthly Ticket Digest',
|
||||
description: 'LLM-analyzed ticket digest for the previous month, delivered to Teams at 7 AM on the 1st',
|
||||
cron_expression: '0 7 1 * *',
|
||||
sync_type: 'ticket-digest-monthly',
|
||||
is_enabled: false,
|
||||
},
|
||||
];
|
||||
|
||||
for (const schedule of defaultSchedules) {
|
||||
|
|
@ -367,6 +400,12 @@ class SyncScheduler {
|
|||
}
|
||||
} else if (config.sync_type === 'morning-summary') {
|
||||
await this.getMorningSummaryService().run();
|
||||
} else if (config.sync_type === 'ticket-digest-daily') {
|
||||
await this.getTicketDigestService().run('daily');
|
||||
} else if (config.sync_type === 'ticket-digest-weekly') {
|
||||
await this.getTicketDigestService().run('weekly');
|
||||
} else if (config.sync_type === 'ticket-digest-monthly') {
|
||||
await this.getTicketDigestService().run('monthly');
|
||||
} else if (config.sync_type === 'incremental') {
|
||||
await this.syncService.incrementalSync('scheduled');
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue