many fixes resultnig from latest refactoring
Some checks failed
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Failing after 5m11s

This commit is contained in:
2025-12-08 22:12:04 -08:00
parent 158778c2ec
commit e156c385a5
39 changed files with 867 additions and 141 deletions

View File

@@ -312,6 +312,58 @@ export class AdminRepository {
}
}
/**
* Resolves an unmatched flyer item by linking it to a master grocery item.
* This is a transactional operation.
* @param unmatchedFlyerItemId The ID from the `unmatched_flyer_items` table.
* @param masterItemId The ID of the `master_grocery_items` to link to.
*/
async resolveUnmatchedFlyerItem(unmatchedFlyerItemId: number, masterItemId: number): Promise<void> {
const client = await getPool().connect();
try {
await client.query('BEGIN');
// First, get the flyer_item_id from the unmatched record
const unmatchedRes = await client.query<{ flyer_item_id: number }>(
'SELECT flyer_item_id FROM public.unmatched_flyer_items WHERE unmatched_flyer_item_id = $1 FOR UPDATE',
[unmatchedFlyerItemId]
);
if (unmatchedRes.rowCount === 0) {
throw new Error(`Unmatched flyer item with ID ${unmatchedFlyerItemId} not found.`);
}
const { flyer_item_id } = unmatchedRes.rows[0];
// Next, update the original flyer_items table with the correct master_item_id
await client.query('UPDATE public.flyer_items SET master_item_id = $1 WHERE flyer_item_id = $2', [masterItemId, flyer_item_id]);
// Finally, update the status of the unmatched record to 'resolved'
await client.query("UPDATE public.unmatched_flyer_items SET status = 'resolved' WHERE unmatched_flyer_item_id = $1", [unmatchedFlyerItemId]);
await client.query('COMMIT');
logger.info(`Successfully resolved unmatched item ${unmatchedFlyerItemId} to master item ${masterItemId}.`);
} catch (error) {
await client.query('ROLLBACK');
logger.error('Database transaction error in resolveUnmatchedFlyerItem:', { error, unmatchedFlyerItemId, masterItemId });
throw new Error('Failed to resolve unmatched flyer item.');
} finally {
client.release();
}
}
/**
* Ignores an unmatched flyer item by updating its status.
* @param unmatchedFlyerItemId The ID from the `unmatched_flyer_items` table.
*/
async ignoreUnmatchedFlyerItem(unmatchedFlyerItemId: number): Promise<void> {
try {
await this.db.query("UPDATE public.unmatched_flyer_items SET status = 'ignored' WHERE unmatched_flyer_item_id = $1", [unmatchedFlyerItemId]);
} catch (error) {
logger.error('Database error in ignoreUnmatchedFlyerItem:', { error, unmatchedFlyerItemId });
throw new Error('Failed to ignore unmatched flyer item.');
}
}
/**
* Retrieves a paginated list of recent activities from the activity log.
* @param limit The number of log entries to retrieve.
@@ -377,6 +429,25 @@ export class AdminRepository {
}
}
/**
* Resets the failed login attempt counter for a user upon successful login.
* @param userId The ID of the user.
* @param ipAddress The IP address from which the successful login occurred.
*/
async resetFailedLoginAttempts(userId: string, ipAddress: string): Promise<void> {
try {
await this.db.query(
`UPDATE public.users
SET failed_login_attempts = 0, last_failed_login = NULL, last_login_ip = $2, last_login_at = NOW()
WHERE user_id = $1 AND failed_login_attempts > 0`,
[userId, ipAddress]
);
} catch (error) {
// This is a non-critical operation, so we just log the error and continue.
logger.error('Database error in resetFailedLoginAttempts:', { error, userId });
}
}
/**
* Updates the logo URL for a specific brand.
* @param brandId The ID of the brand to update.