renaming services to more suitable names
This commit is contained in:
parent
3ae9de8376
commit
be6afef832
69 changed files with 41 additions and 2956 deletions
|
|
@ -0,0 +1,204 @@
|
|||
import { getLogger } from '@stock-bot/logger';
|
||||
import { getMongoDBClient } from "@stock-bot/mongodb-client";
|
||||
import { getPostgreSQLClient } from '@stock-bot/postgres-client';
|
||||
import type { JobPayload, SyncResult } from '../../../types/job-payloads';
|
||||
|
||||
const logger = getLogger('enhanced-sync-qm-provider-mappings');
|
||||
|
||||
export async function syncQMProviderMappings(payload: JobPayload): Promise<SyncResult> {
|
||||
logger.info('Starting QM provider exchange mappings sync...');
|
||||
|
||||
const result: SyncResult = {
|
||||
processed: 0,
|
||||
created: 0,
|
||||
updated: 0,
|
||||
skipped: 0,
|
||||
errors: 0,
|
||||
};
|
||||
|
||||
try {
|
||||
const mongoClient = getMongoDBClient();
|
||||
const postgresClient = getPostgreSQLClient();
|
||||
|
||||
// Start transaction
|
||||
await postgresClient.query('BEGIN');
|
||||
|
||||
// Get unique exchange combinations from QM symbols
|
||||
const db = mongoClient.getDatabase();
|
||||
const pipeline = [
|
||||
{
|
||||
$group: {
|
||||
_id: {
|
||||
exchangeCode: '$exchangeCode',
|
||||
exchange: '$exchange',
|
||||
countryCode: '$countryCode',
|
||||
},
|
||||
count: { $sum: 1 },
|
||||
sampleExchange: { $first: '$exchange' },
|
||||
},
|
||||
},
|
||||
{
|
||||
$project: {
|
||||
exchangeCode: '$_id.exchangeCode',
|
||||
exchange: '$_id.exchange',
|
||||
countryCode: '$_id.countryCode',
|
||||
count: 1,
|
||||
sampleExchange: 1,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const qmExchanges = await db.collection('qmSymbols').aggregate(pipeline).toArray();
|
||||
logger.info(`Found ${qmExchanges.length} unique QM exchange combinations`);
|
||||
|
||||
for (const exchange of qmExchanges) {
|
||||
try {
|
||||
// Create provider exchange mapping for QM
|
||||
await createProviderExchangeMapping(
|
||||
'qm', // provider
|
||||
exchange.exchangeCode,
|
||||
exchange.sampleExchange || exchange.exchangeCode,
|
||||
exchange.countryCode,
|
||||
exchange.countryCode === 'CA' ? 'CAD' : 'USD', // Simple currency mapping
|
||||
0.8 // good confidence for QM data
|
||||
);
|
||||
|
||||
result.processed++;
|
||||
result.created++;
|
||||
} catch (error) {
|
||||
logger.error('Failed to process QM exchange mapping', { error, exchange });
|
||||
result.errors++;
|
||||
}
|
||||
}
|
||||
|
||||
await postgresClient.query('COMMIT');
|
||||
|
||||
logger.info('QM provider exchange mappings sync completed', result);
|
||||
return result;
|
||||
} catch (error) {
|
||||
const postgresClient = getPostgreSQLClient();
|
||||
await postgresClient.query('ROLLBACK');
|
||||
logger.error('QM provider exchange mappings sync failed', { error });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function createProviderExchangeMapping(
|
||||
provider: string,
|
||||
providerExchangeCode: string,
|
||||
providerExchangeName: string,
|
||||
countryCode: string | null,
|
||||
currency: string | null,
|
||||
confidence: number
|
||||
): Promise<void> {
|
||||
if (!providerExchangeCode) {
|
||||
return;
|
||||
}
|
||||
|
||||
const postgresClient = getPostgreSQLClient();
|
||||
|
||||
// Check if mapping already exists
|
||||
const existingMapping = await findProviderExchangeMapping(provider, providerExchangeCode);
|
||||
if (existingMapping) {
|
||||
// Don't override existing mappings to preserve manual work
|
||||
return;
|
||||
}
|
||||
|
||||
// Find or create master exchange
|
||||
const masterExchange = await findOrCreateMasterExchange(
|
||||
providerExchangeCode,
|
||||
providerExchangeName,
|
||||
countryCode,
|
||||
currency
|
||||
);
|
||||
|
||||
// Create the provider exchange mapping
|
||||
const query = `
|
||||
INSERT INTO provider_exchange_mappings
|
||||
(provider, provider_exchange_code, provider_exchange_name, master_exchange_id,
|
||||
country_code, currency, confidence, active, auto_mapped)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, false, true)
|
||||
ON CONFLICT (provider, provider_exchange_code) DO NOTHING
|
||||
`;
|
||||
|
||||
await postgresClient.query(query, [
|
||||
provider,
|
||||
providerExchangeCode,
|
||||
providerExchangeName,
|
||||
masterExchange.id,
|
||||
countryCode,
|
||||
currency,
|
||||
confidence,
|
||||
]);
|
||||
}
|
||||
|
||||
async function findProviderExchangeMapping(provider: string, providerExchangeCode: string): Promise<any> {
|
||||
const postgresClient = getPostgreSQLClient();
|
||||
const query = 'SELECT * FROM provider_exchange_mappings WHERE provider = $1 AND provider_exchange_code = $2';
|
||||
const result = await postgresClient.query(query, [provider, providerExchangeCode]);
|
||||
return result.rows[0] || null;
|
||||
}
|
||||
|
||||
async function findOrCreateMasterExchange(
|
||||
providerCode: string,
|
||||
providerName: string,
|
||||
countryCode: string | null,
|
||||
currency: string | null
|
||||
): Promise<any> {
|
||||
const postgresClient = getPostgreSQLClient();
|
||||
|
||||
// First, try to find exact match
|
||||
let masterExchange = await findExchangeByCode(providerCode);
|
||||
|
||||
if (masterExchange) {
|
||||
return masterExchange;
|
||||
}
|
||||
|
||||
// Try to find by similar codes (basic mapping)
|
||||
const basicMapping = getBasicExchangeMapping(providerCode);
|
||||
if (basicMapping) {
|
||||
masterExchange = await findExchangeByCode(basicMapping);
|
||||
if (masterExchange) {
|
||||
return masterExchange;
|
||||
}
|
||||
}
|
||||
|
||||
// Create new master exchange (inactive by default)
|
||||
const query = `
|
||||
INSERT INTO exchanges (code, name, country, currency, active)
|
||||
VALUES ($1, $2, $3, $4, false)
|
||||
ON CONFLICT (code) DO UPDATE SET
|
||||
name = COALESCE(EXCLUDED.name, exchanges.name),
|
||||
country = COALESCE(EXCLUDED.country, exchanges.country),
|
||||
currency = COALESCE(EXCLUDED.currency, exchanges.currency)
|
||||
RETURNING id, code, name, country, currency
|
||||
`;
|
||||
|
||||
const result = await postgresClient.query(query, [
|
||||
providerCode,
|
||||
providerName || providerCode,
|
||||
countryCode || 'US',
|
||||
currency || 'USD',
|
||||
]);
|
||||
|
||||
return result.rows[0];
|
||||
}
|
||||
|
||||
function getBasicExchangeMapping(providerCode: string): string | null {
|
||||
const mappings: Record<string, string> = {
|
||||
NYE: 'NYSE',
|
||||
NAS: 'NASDAQ',
|
||||
TO: 'TSX',
|
||||
LN: 'LSE',
|
||||
LON: 'LSE',
|
||||
};
|
||||
|
||||
return mappings[providerCode.toUpperCase()] || null;
|
||||
}
|
||||
|
||||
async function findExchangeByCode(code: string): Promise<any> {
|
||||
const postgresClient = getPostgreSQLClient();
|
||||
const query = 'SELECT * FROM exchanges WHERE code = $1';
|
||||
const result = await postgresClient.query(query, [code]);
|
||||
return result.rows[0] || null;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue