Merge pull request #499 from R0m1k3/1.1

1.1
This commit is contained in:
LogiFlow authored and GitHub committed 2025-11-04 10:21:25 +01:00
commit 39c096d009
4 files changed
+84 -110

No files matched your search

+6
View File
@@ -46,6 +46,7 @@ export class InvoiceVerificationService {
invoiceReference: cached.invoiceReference, invoiceReference: cached.invoiceReference,
supplierName: cached.supplierName, supplierName: cached.supplierName,
invoiceAmount: cached.invoiceAmount ? parseFloat(cached.invoiceAmount) : undefined, invoiceAmount: cached.invoiceAmount ? parseFloat(cached.invoiceAmount) : undefined,
invoiceAmountTTC: cached.invoiceAmountTTC ? parseFloat(cached.invoiceAmountTTC) : undefined,
dueDate: cached.dueDate ? new Date(cached.dueDate).toISOString() : null, dueDate: cached.dueDate ? new Date(cached.dueDate).toISOString() : null,
fromCache: true, fromCache: true,
permanent: true permanent: true
@@ -62,6 +63,7 @@ export class InvoiceVerificationService {
invoiceReference: cached.invoiceReference, invoiceReference: cached.invoiceReference,
supplierName: cached.supplierName, supplierName: cached.supplierName,
invoiceAmount: cached.invoiceAmount ? parseFloat(cached.invoiceAmount) : undefined, invoiceAmount: cached.invoiceAmount ? parseFloat(cached.invoiceAmount) : undefined,
invoiceAmountTTC: cached.invoiceAmountTTC ? parseFloat(cached.invoiceAmountTTC) : undefined,
dueDate: cached.dueDate ? new Date(cached.dueDate).toISOString() : null, dueDate: cached.dueDate ? new Date(cached.dueDate).toISOString() : null,
fromCache: true, fromCache: true,
permanent: false permanent: false
@@ -122,6 +124,7 @@ export class InvoiceVerificationService {
invoiceReference, invoiceReference,
supplierName: supplierName || null, supplierName: supplierName || null,
invoiceAmount: result.invoiceAmount || null, invoiceAmount: result.invoiceAmount || null,
invoiceAmountTTC: result.invoiceAmountTTC || null,
dueDate: result.dueDate ? new Date(result.dueDate) : null, dueDate: result.dueDate ? new Date(result.dueDate) : null,
exists: result.exists, exists: result.exists,
matchType: result.matchType, matchType: result.matchType,
@@ -405,6 +408,7 @@ export class InvoiceVerificationService {
matchType: 'invoice_reference' as const, matchType: 'invoice_reference' as const,
invoiceReference: matchResult.data.invoice_reference || invoiceReference, invoiceReference: matchResult.data.invoice_reference || invoiceReference,
invoiceAmount: parseFloat(matchResult.data[group.nocodbAmountColumnName || 'amount'] || '0'), invoiceAmount: parseFloat(matchResult.data[group.nocodbAmountColumnName || 'amount'] || '0'),
invoiceAmountTTC: parseFloat(matchResult.data[group.nocodbInvoiceAmountTTCColumnName || 'Montant TTC'] || '0'),
supplierName: matchResult.data[group.nocodbSupplierColumnName || 'supplier'] || 'Inconnu', supplierName: matchResult.data[group.nocodbSupplierColumnName || 'supplier'] || 'Inconnu',
dueDate: matchResult.data[group.nocodbDueDateColumnName || 'Echeance'] || null dueDate: matchResult.data[group.nocodbDueDateColumnName || 'Echeance'] || null
}; };
@@ -442,6 +446,7 @@ export class InvoiceVerificationService {
matchType: 'bl_number' as const, matchType: 'bl_number' as const,
invoiceReference: matchResult.data.invoice_reference || `BL_${invoiceReference}`, invoiceReference: matchResult.data.invoice_reference || `BL_${invoiceReference}`,
invoiceAmount: parseFloat(matchResult.data[group.nocodbAmountColumnName || 'amount'] || '0'), invoiceAmount: parseFloat(matchResult.data[group.nocodbAmountColumnName || 'amount'] || '0'),
invoiceAmountTTC: parseFloat(matchResult.data[group.nocodbInvoiceAmountTTCColumnName || 'Montant TTC'] || '0'),
supplierName: matchResult.data[group.nocodbSupplierColumnName || 'supplier'] || 'Inconnu', supplierName: matchResult.data[group.nocodbSupplierColumnName || 'supplier'] || 'Inconnu',
dueDate: matchResult.data[group.nocodbDueDateColumnName || 'Echeance'] || null dueDate: matchResult.data[group.nocodbDueDateColumnName || 'Echeance'] || null
}; };
@@ -807,6 +812,7 @@ export class InvoiceVerificationService {
matchType: 'bl_number' as const, matchType: 'bl_number' as const,
invoiceReference: matchResult.data[group.invoiceColumnName || 'RefFacture'] || `BL_${blNumber}`, invoiceReference: matchResult.data[group.invoiceColumnName || 'RefFacture'] || `BL_${blNumber}`,
invoiceAmount: parseFloat(matchResult.data[group.nocodbAmountColumnName || 'amount'] || '0'), invoiceAmount: parseFloat(matchResult.data[group.nocodbAmountColumnName || 'amount'] || '0'),
invoiceAmountTTC: parseFloat(matchResult.data[group.nocodbInvoiceAmountTTCColumnName || 'Montant TTC'] || '0'),
supplierName: foundSupplier || supplierName, supplierName: foundSupplier || supplierName,
dueDate: matchResult.data[group.nocodbDueDateColumnName || 'Echeance'] || null dueDate: matchResult.data[group.nocodbDueDateColumnName || 'Echeance'] || null
}; };
+15 -6
View File
@@ -110,7 +110,6 @@ import {
insertAnnouncementSchema, insertAnnouncementSchema,
insertNocodbConfigSchema, insertNocodbConfigSchema,
insertSavTicketSchema, insertSavTicketSchema,
insertSavTicketHistorySchema,
insertWeatherDataSchema, insertWeatherDataSchema,
insertWeatherSettingsSchema, insertWeatherSettingsSchema,
insertWebhookBapConfigSchema, insertWebhookBapConfigSchema,
@@ -1881,7 +1880,7 @@ export async function registerRoutes(app: Express): Promise<Server> {
console.log('✅ Résultat vérification:', result); console.log('✅ Résultat vérification:', result);
// CRITICAL FIX: Sauvegarder les données dans la table deliveries après vérification réussie // CRITICAL FIX: Sauvegarder les données dans la table deliveries après vérification réussie
if (result.exists && (result.invoiceAmount !== undefined || result.dueDate !== undefined || result.invoiceReference !== undefined)) { if (result.exists && (result.invoiceAmount !== undefined || result.invoiceAmountTTC !== undefined || result.dueDate !== undefined || result.invoiceReference !== undefined)) {
try { try {
const updateData: any = {}; const updateData: any = {};
@@ -1890,11 +1889,16 @@ export async function registerRoutes(app: Express): Promise<Server> {
updateData.invoiceReference = result.invoiceReference; updateData.invoiceReference = result.invoiceReference;
} }
// Ajouter le montant facture si trouvé // Ajouter le montant facture HT si trouvé
if (result.invoiceAmount !== undefined && result.invoiceAmount !== null) { if (result.invoiceAmount !== undefined && result.invoiceAmount !== null) {
updateData.invoiceAmount = result.invoiceAmount.toString(); updateData.invoiceAmount = result.invoiceAmount.toString();
} }
// Ajouter le montant facture TTC si trouvé
if (result.invoiceAmountTTC !== undefined && result.invoiceAmountTTC !== null) {
updateData.invoiceAmountTTC = result.invoiceAmountTTC.toString();
}
// Ajouter l'échéance si trouvée // Ajouter l'échéance si trouvée
if (result.dueDate) { if (result.dueDate) {
const normalizedDateString = normalizeDateString(result.dueDate); const normalizedDateString = normalizeDateString(result.dueDate);
@@ -4823,14 +4827,19 @@ RÉSUMÉ DU SCAN
} }
// Parse and validate history entry // Parse and validate history entry
const historyData = insertSavTicketHistorySchema.parse({ // const historyData = insertSavTicketHistorySchema.parse({
// ticketId: ticketId,
// action: 'comment',
// description: req.body.description,
// createdBy: user.id,
// });
const history = await storage.addSavTicketHistory({
ticketId: ticketId, ticketId: ticketId,
action: 'comment', action: 'comment',
description: req.body.description, description: req.body.description,
createdBy: user.id, createdBy: user.id,
}); });
const history = await storage.addSavTicketHistory(historyData);
res.status(201).json(history); res.status(201).json(history);
} catch (error) { } catch (error) {
console.error("Error adding SAV ticket history:", error); console.error("Error adding SAV ticket history:", error);
+47 -72
View File
@@ -16,7 +16,6 @@ import {
invoiceVerificationCache, invoiceVerificationCache,
reconciliationComments, reconciliationComments,
savTickets, savTickets,
savTicketHistory,
weatherData, weatherData,
weatherSettings, weatherSettings,
type User, type User,
@@ -62,7 +61,6 @@ import {
type InsertInvoiceVerificationCache, type InsertInvoiceVerificationCache,
type SavTicket, type SavTicket,
type InsertSavTicket, type InsertSavTicket,
type SavTicketHistory,
type InsertSavTicketHistory, type InsertSavTicketHistory,
type SavTicketWithRelations, type SavTicketWithRelations,
type SavTicketHistoryWithCreator, type SavTicketHistoryWithCreator,
@@ -688,6 +686,7 @@ export class DatabaseStorage implements IStorage {
blAmount: deliveries.blAmount, blAmount: deliveries.blAmount,
invoiceReference: deliveries.invoiceReference, invoiceReference: deliveries.invoiceReference,
invoiceAmount: deliveries.invoiceAmount, invoiceAmount: deliveries.invoiceAmount,
invoiceAmountTTC: deliveries.invoiceAmountTTC,
dueDate: deliveries.dueDate, dueDate: deliveries.dueDate,
reconciled: deliveries.reconciled, reconciled: deliveries.reconciled,
validatedAt: deliveries.validatedAt, validatedAt: deliveries.validatedAt,
@@ -757,6 +756,7 @@ export class DatabaseStorage implements IStorage {
blAmount: deliveries.blAmount, blAmount: deliveries.blAmount,
invoiceReference: deliveries.invoiceReference, invoiceReference: deliveries.invoiceReference,
invoiceAmount: deliveries.invoiceAmount, invoiceAmount: deliveries.invoiceAmount,
invoiceAmountTTC: deliveries.invoiceAmountTTC,
dueDate: deliveries.dueDate, dueDate: deliveries.dueDate,
reconciled: deliveries.reconciled, reconciled: deliveries.reconciled,
validatedAt: deliveries.validatedAt, validatedAt: deliveries.validatedAt,
@@ -879,6 +879,7 @@ export class DatabaseStorage implements IStorage {
blAmount: deliveries.blAmount, blAmount: deliveries.blAmount,
invoiceReference: deliveries.invoiceReference, invoiceReference: deliveries.invoiceReference,
invoiceAmount: deliveries.invoiceAmount, invoiceAmount: deliveries.invoiceAmount,
invoiceAmountTTC: deliveries.invoiceAmountTTC,
dueDate: deliveries.dueDate, dueDate: deliveries.dueDate,
reconciled: deliveries.reconciled, reconciled: deliveries.reconciled,
validatedAt: deliveries.validatedAt, validatedAt: deliveries.validatedAt,
@@ -1012,6 +1013,7 @@ export class DatabaseStorage implements IStorage {
blAmount: deliveries.blAmount, blAmount: deliveries.blAmount,
invoiceReference: deliveries.invoiceReference, invoiceReference: deliveries.invoiceReference,
invoiceAmount: deliveries.invoiceAmount, invoiceAmount: deliveries.invoiceAmount,
invoiceAmountTTC: deliveries.invoiceAmountTTC,
dueDate: deliveries.dueDate, dueDate: deliveries.dueDate,
reconciled: deliveries.reconciled, reconciled: deliveries.reconciled,
validatedAt: deliveries.validatedAt, validatedAt: deliveries.validatedAt,
@@ -2619,12 +2621,12 @@ export class DatabaseStorage implements IStorage {
.returning(); .returning();
// Add initial history entry // Add initial history entry
await this.addSavTicketHistory({ // await this.addSavTicketHistory({
ticketId: ticket.id, // ticketId: ticket.id,
action: 'created', // action: 'created',
description: `Ticket créé avec le statut "${ticket.status}"`, // description: `Ticket créé avec le statut "${ticket.status}"`,
createdBy: ticket.createdBy, // createdBy: ticket.createdBy,
}); // });
return ticket; return ticket;
} }
@@ -2641,35 +2643,37 @@ export class DatabaseStorage implements IStorage {
async deleteSavTicket(id: number): Promise<void> { async deleteSavTicket(id: number): Promise<void> {
// Delete history first // Delete history first
await db.delete(savTicketHistory).where(eq(savTicketHistory.ticketId, id)); // await db.delete(savTicketHistory).where(eq(savTicketHistory.ticketId, id));
// Delete ticket // Delete ticket
await db.delete(savTickets).where(eq(savTickets.id, id)); await db.delete(savTickets).where(eq(savTickets.id, id));
} }
async getSavTicketHistory(ticketId: number): Promise<SavTicketHistoryWithCreator[]> { async getSavTicketHistory(ticketId: number): Promise<SavTicketHistoryWithCreator[]> {
const results = await db // const results = await db
.select({ // .select({
history: savTicketHistory, // history: savTicketHistory,
creator: users, // creator: users,
}) // })
.from(savTicketHistory) // .from(savTicketHistory)
.leftJoin(users, eq(savTicketHistory.createdBy, users.id)) // .leftJoin(users, eq(savTicketHistory.createdBy, users.id))
.where(eq(savTicketHistory.ticketId, ticketId)) // .where(eq(savTicketHistory.ticketId, ticketId))
.orderBy(desc(savTicketHistory.createdAt)); // .orderBy(desc(savTicketHistory.createdAt));
return results.map(result => ({ // return results.map(result => ({
...result.history, // ...result.history,
creator: result.creator!, // creator: result.creator!,
})); // }));
return [];
} }
async addSavTicketHistory(historyData: InsertSavTicketHistory): Promise<SavTicketHistory> { async addSavTicketHistory(historyData: InsertSavTicketHistory): Promise<any> {
const [history] = await db // const [history] = await db
.insert(savTicketHistory) // .insert(savTicketHistory)
.values(historyData) // .values(historyData)
.returning(); // .returning();
return history; // return history;
return null;
} }
async getSavTicketStats(groupIds?: number[]): Promise<{ async getSavTicketStats(groupIds?: number[]): Promise<{
@@ -3298,7 +3302,6 @@ export class MemStorage implements IStorage {
private announcements = new Map<number, Announcement>(); private announcements = new Map<number, Announcement>();
private avoirs = new Map<number, Avoir>(); private avoirs = new Map<number, Avoir>();
private savTickets = new Map<number, SavTicket>(); private savTickets = new Map<number, SavTicket>();
private savTicketHistories = new Map<number, SavTicketHistory[]>();
private invoiceVerificationCache = new Map<string, InvoiceVerificationCache>(); private invoiceVerificationCache = new Map<string, InvoiceVerificationCache>();
private idCounters = { private idCounters = {
@@ -3313,7 +3316,6 @@ export class MemStorage implements IStorage {
announcement: 1, announcement: 1,
avoir: 1, avoir: 1,
savTicket: 1, savTicket: 1,
savTicketHistory: 1,
reconciliationComment: 1, reconciliationComment: 1,
}; };
@@ -4761,44 +4763,17 @@ export class MemStorage implements IStorage {
async deleteSavTicket(id: number): Promise<void> { async deleteSavTicket(id: number): Promise<void> {
// Delete history first // Delete history first
this.savTicketHistories.delete(id); // this.savTicketHistories.delete(id);
// Delete ticket // Delete ticket
this.savTickets.delete(id); this.savTickets.delete(id);
} }
async getSavTicketHistory(ticketId: number): Promise<SavTicketHistoryWithCreator[]> { async getSavTicketHistory(ticketId: number): Promise<SavTicketHistoryWithCreator[]> {
const histories = this.savTicketHistories.get(ticketId) || []; return [];
const historiesWithCreators = histories.map(history => {
const creator = this.users.get(history.createdBy);
return {
...history,
creator: creator!,
};
});
// Sort by creation date (newest first)
return historiesWithCreators.sort((a, b) => {
const dateA = a.createdAt || new Date(0);
const dateB = b.createdAt || new Date(0);
return dateB.getTime() - dateA.getTime();
});
} }
async addSavTicketHistory(historyData: InsertSavTicketHistory): Promise<SavTicketHistory> { async addSavTicketHistory(historyData: InsertSavTicketHistory): Promise<any> {
const id = this.idCounters.savTicketHistory++; return null;
const history: SavTicketHistory = {
id,
...historyData,
createdAt: new Date(),
};
const existingHistories = this.savTicketHistories.get(historyData.ticketId) || [];
existingHistories.push(history);
this.savTicketHistories.set(historyData.ticketId, existingHistories);
return history;
} }
async getSavTicketStats(groupIds?: number[]): Promise<{ async getSavTicketStats(groupIds?: number[]): Promise<{
@@ -4968,20 +4943,20 @@ export class MemStorage implements IStorage {
]; ];
// Initialize history for each ticket // Initialize history for each ticket
histories.forEach((historyEntry) => { // histories.forEach((historyEntry) => {
const id = this.idCounters.savTicketHistory++; // const id = this.idCounters.savTicketHistory++;
const history: SavTicketHistory = { // const history: SavTicketHistory = {
id, // id,
...historyEntry, // ...historyEntry,
}; // };
const existingHistories = this.savTicketHistories.get(historyEntry.ticketId) || []; // const existingHistories = this.savTicketHistories.get(historyEntry.ticketId) || [];
existingHistories.push(history); // existingHistories.push(history);
this.savTicketHistories.set(historyEntry.ticketId, existingHistories); // this.savTicketHistories.set(historyEntry.ticketId, existingHistories);
}); // });
this.idCounters.savTicket = 6; this.idCounters.savTicket = 6;
console.log('✅ SAV test data initialized with 5 tickets and comprehensive history'); console.log('✅ SAV test data initialized with 5 tickets');
} }
// Weather operations // Weather operations
+16 -32
View File
@@ -56,7 +56,8 @@ export const groups = pgTable("groups", {
// Mapping des colonnes par magasin dans leur table NocoDB // Mapping des colonnes par magasin dans leur table NocoDB
invoiceColumnName: varchar("invoice_column_name"), // Nom de la colonne facture dans leur table invoiceColumnName: varchar("invoice_column_name"), // Nom de la colonne facture dans leur table
nocodbBlColumnName: varchar("nocodb_bl_column_name"), // Nom de la colonne BL dans leur table nocodbBlColumnName: varchar("nocodb_bl_column_name"), // Nom de la colonne BL dans leur table
nocodbAmountColumnName: varchar("nocodb_amount_column_name"), // Nom de la colonne montant dans leur table nocodbAmountColumnName: varchar("nocodb_amount_column_name"), // Nom de la colonne montant HT dans leur table
nocodbInvoiceAmountTTCColumnName: varchar("nocodb_invoice_amount_ttc_column_name"), // Nom de la colonne montant TTC dans leur table
nocodbSupplierColumnName: varchar("nocodb_supplier_column_name"), // Nom de la colonne fournisseur dans leur table nocodbSupplierColumnName: varchar("nocodb_supplier_column_name"), // Nom de la colonne fournisseur dans leur table
nocodbDueDateColumnName: varchar("nocodb_due_date_column_name"), // Nom de la colonne date d'échéance dans leur table nocodbDueDateColumnName: varchar("nocodb_due_date_column_name"), // Nom de la colonne date d'échéance dans leur table
webhookUrl: varchar("webhook_url", { length: 500 }), // URL de webhook pour notifications par magasin webhookUrl: varchar("webhook_url", { length: 500 }), // URL de webhook pour notifications par magasin
@@ -118,7 +119,8 @@ export const deliveries = pgTable("deliveries", {
blNumber: varchar("bl_number"), // Numéro de Bon de Livraison blNumber: varchar("bl_number"), // Numéro de Bon de Livraison
blAmount: decimal("bl_amount", { precision: 10, scale: 2 }), // Montant BL blAmount: decimal("bl_amount", { precision: 10, scale: 2 }), // Montant BL
invoiceReference: varchar("invoice_reference"), // Référence facture invoiceReference: varchar("invoice_reference"), // Référence facture
invoiceAmount: decimal("invoice_amount", { precision: 10, scale: 2 }), // Montant facture invoiceAmount: decimal("invoice_amount", { precision: 10, scale: 2 }), // Montant facture HT
invoiceAmountTTC: decimal("invoice_amount_ttc", { precision: 10, scale: 2 }), // Montant facture TTC
dueDate: timestamp("due_date"), // Date d'échéance de paiement (récupérée depuis NocoDB) dueDate: timestamp("due_date"), // Date d'échéance de paiement (récupérée depuis NocoDB)
reconciled: boolean("reconciled").default(false), // Rapprochement effectué reconciled: boolean("reconciled").default(false), // Rapprochement effectué
validatedAt: timestamp("validated_at"), // Date de validation de la livraison validatedAt: timestamp("validated_at"), // Date de validation de la livraison
@@ -173,7 +175,8 @@ export const invoiceVerificationCache = pgTable("invoice_verification_cache", {
groupId: integer("group_id").notNull(), groupId: integer("group_id").notNull(),
invoiceReference: varchar("invoice_reference", { length: 255 }).notNull(), invoiceReference: varchar("invoice_reference", { length: 255 }).notNull(),
supplierName: varchar("supplier_name", { length: 255 }), supplierName: varchar("supplier_name", { length: 255 }),
invoiceAmount: decimal("invoice_amount", { precision: 10, scale: 2 }), // Montant de la facture invoiceAmount: decimal("invoice_amount", { precision: 10, scale: 2 }), // Montant de la facture HT
invoiceAmountTTC: decimal("invoice_amount_ttc", { precision: 10, scale: 2 }), // Montant de la facture TTC
dueDate: timestamp("due_date"), // Date d'échéance dueDate: timestamp("due_date"), // Date d'échéance
exists: boolean("exists").notNull(), exists: boolean("exists").notNull(),
matchType: varchar("match_type", { length: 50 }).notNull(), matchType: varchar("match_type", { length: 50 }).notNull(),
@@ -826,14 +829,6 @@ export const savTickets = pgTable("sav_tickets", {
closedAt: timestamp("closed_at"), closedAt: timestamp("closed_at"),
}); });
export const savTicketHistory = pgTable("sav_ticket_history", {
id: serial("id").primaryKey(),
ticketId: integer("ticket_id").notNull(),
action: varchar("action", { length: 100 }).notNull(), // status_change, comment, resolution, etc.
description: text("description"),
createdBy: varchar("created_by", { length: 255 }).notNull(),
createdAt: timestamp("created_at").defaultNow(),
});
// SAV Relations // SAV Relations
export const savTicketRelations = relations(savTickets, ({ one, many }) => ({ export const savTicketRelations = relations(savTickets, ({ one, many }) => ({
@@ -849,19 +844,8 @@ export const savTicketRelations = relations(savTickets, ({ one, many }) => ({
fields: [savTickets.createdBy], fields: [savTickets.createdBy],
references: [users.id], references: [users.id],
}), }),
history: many(savTicketHistory),
})); }));
export const savTicketHistoryRelations = relations(savTicketHistory, ({ one }) => ({
ticket: one(savTickets, {
fields: [savTicketHistory.ticketId],
references: [savTickets.id],
}),
creator: one(users, {
fields: [savTicketHistory.createdBy],
references: [users.id],
}),
}));
// SAV Zod Schemas // SAV Zod Schemas
export const insertSavTicketSchema = createInsertSchema(savTickets).omit({ export const insertSavTicketSchema = createInsertSchema(savTickets).omit({
@@ -877,27 +861,27 @@ export const insertSavTicketSchema = createInsertSchema(savTickets).omit({
problemType: z.enum(["defectueux", "pieces_manquantes", "non_conforme", "autre"]).default("defectueux"), problemType: z.enum(["defectueux", "pieces_manquantes", "non_conforme", "autre"]).default("defectueux"),
}); });
export const insertSavTicketHistorySchema = createInsertSchema(savTicketHistory).omit({ // export const insertSavTicketHistorySchema = createInsertSchema(savTicketHistory).omit({
id: true, // id: true,
createdAt: true, // createdAt: true,
}); // });
// SAV Types // SAV Types
export type SavTicket = typeof savTickets.$inferSelect; export type SavTicket = typeof savTickets.$inferSelect;
export type InsertSavTicket = z.infer<typeof insertSavTicketSchema>; export type InsertSavTicket = z.infer<typeof insertSavTicketSchema>;
export type SavTicketHistory = typeof savTicketHistory.$inferSelect; // export type SavTicketHistory = typeof savTicketHistory.$inferSelect;
export type InsertSavTicketHistory = z.infer<typeof insertSavTicketHistorySchema>; // export type InsertSavTicketHistory = z.infer<typeof insertSavTicketHistorySchema>;
export type InsertSavTicketHistory = any;
export type SavTicketHistory = any;
export type SavTicketWithRelations = SavTicket & { export type SavTicketWithRelations = SavTicket & {
supplier: Supplier; supplier: Supplier;
group: Group; group: Group;
creator: User; creator: User;
history: (SavTicketHistory & { creator: User })[]; history: any[];
}; };
export type SavTicketHistoryWithCreator = SavTicketHistory & { export type SavTicketHistoryWithCreator = any;
creator: User;
};
// Weather Tables // Weather Tables
export const weatherData = pgTable("weather_data", { export const weatherData = pgTable("weather_data", {