UNPKG

@tomei/live-price

Version:

Tomei live-price Package

480 lines 23.6 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TomeiPriceHistory = void 0; const general_1 = require("@tomei/general"); const log_1 = require("@tomei/log"); const tomei_price_repository_1 = require("./tomei-price.repository"); const tomei_price_latest_repository_1 = require("./tomei-price-latest.repository"); const sequelize_1 = require("sequelize"); const price_feed_history_entity_1 = require("../../models/price-feed-history.entity"); const feed_manual_price_history_1 = require("../feed-manual-price-history/feed-manual-price-history"); const feed_1 = require("../feed/feed"); const feed_enum_1 = require("../../enum/feed.enum"); const company_feed_access_1 = require("../company-feed-access/company-feed-access"); class TomeiPriceHistory extends general_1.ObjectBase { get TomeiPriceHistoryId() { return this.ObjectId; } set TomeiPriceHistoryId(value) { this.ObjectId = value; } constructor(tomeiPriceHistoryAttr) { super(); if (tomeiPriceHistoryAttr) { this.TomeiPriceHistoryId = tomeiPriceHistoryAttr.TomeiPriceHistoryId; this.FeedHistoryId = tomeiPriceHistoryAttr.FeedHistoryId; this.FeedName = tomeiPriceHistoryAttr.FeedName; this.DateTime = tomeiPriceHistoryAttr.DateTime; this.AdjustBuyPercentage = tomeiPriceHistoryAttr.AdjustBuyPercentage; this.AdjustSellPercentage = tomeiPriceHistoryAttr.AdjustSellPercentage; this.TomeiBuyPrice = tomeiPriceHistoryAttr.TomeiBuyPrice; this.TomeiSellPrice = tomeiPriceHistoryAttr.TomeiSellPrice; this.AdjustedById = tomeiPriceHistoryAttr.AdjustedById; this.Currency = tomeiPriceHistoryAttr.Currency; this.AdjustedDateTime = tomeiPriceHistoryAttr.AdjustedDateTime; this.IsManualPriceActivatedYN = tomeiPriceHistoryAttr.IsManualPriceActivatedYN; this.BuyLabourCharges = tomeiPriceHistoryAttr.BuyLabourCharges; this.SellLabourCharges = tomeiPriceHistoryAttr.SellLabourCharges; this.CompanyCode = tomeiPriceHistoryAttr.CompanyCode; } } static init(dbTransaction, tomeiPriceHistoryId) { return __awaiter(this, void 0, void 0, function* () { try { if (tomeiPriceHistoryId) { const data = yield TomeiPriceHistory._Repo.findByPk(tomeiPriceHistoryId, dbTransaction); if (data) { return new TomeiPriceHistory(data); } else { const error = new general_1.ClassError('TomeiPriceHistory', 'TomeiPriceHistoryErrMsg00', 'TomeiPriceHistory Not Found'); yield TomeiPriceHistory.logger.error({ error, methodName: 'init', transaction: dbTransaction, }); throw error; } } return new TomeiPriceHistory(); } catch (error) { yield TomeiPriceHistory.logger.error({ error, methodName: 'init', transaction: dbTransaction, }); throw new general_1.ClassError('TomeiPriceHistory', 'TomeiPriceHistoryErrMsg00', 'TomeiPriceHistory To Initialize FeedHistory'); } }); } saveTomeiPrice(feedName_1, feedHistory_1, loginUser_1, adjustmentPercentage_1, manualPrice_1) { return __awaiter(this, arguments, void 0, function* (feedName, feedHistory, loginUser, adjustmentPercentage, manualPrice, companyCode = 'CTH', dbTransaction) { try { if (!feedHistory || !feedHistory.FeedHistoryId) { const error = new general_1.ClassError('TomeiPriceHistory', 'TomeiPriceHistoryErrMsg01', 'FeedHistoryId is required to create tomei price'); yield TomeiPriceHistory.logger.error({ error, methodName: 'saveTomeiPrice', transaction: dbTransaction, }); throw error; } let adjustmentBy = null; let adjustmentDateTime = new Date(); const latestPrice = yield TomeiPriceHistory.getLatestPrice(feedName, feedHistory.Currency, companyCode, undefined, dbTransaction); if (!adjustmentPercentage) { if (!latestPrice) { adjustmentPercentage = { adjustBuyPercentage: 0, adjustSellPercentage: 0, buyLabourCharges: 0, sellLabourCharges: 0, }; } else { adjustmentPercentage = { adjustBuyPercentage: latestPrice.AdjustBuyPercentage, adjustSellPercentage: latestPrice.AdjustSellPercentage, buyLabourCharges: latestPrice.BuyLabourCharges, sellLabourCharges: latestPrice.SellLabourCharges, }; adjustmentBy = latestPrice.AdjustedById; adjustmentDateTime = latestPrice.AdjustedDateTime; } } else if (!loginUser && adjustmentPercentage) { const error = new general_1.ClassError('TomeiPriceHistory', 'TomeiPriceHistoryErrMsg01', 'Login user is required to create tomei price when updating adjustment buy and sell percentage'); yield TomeiPriceHistory.logger.error({ error, methodName: 'saveTomeiPrice', transaction: dbTransaction, }); throw error; } const priceResult = yield this.calculateTomeiPrices(feedName, feedHistory, adjustmentPercentage, companyCode, manualPrice, latestPrice, dbTransaction); const { tomeiBuyPrice, tomeiSellPrice, IsManualPriceActivatedYN } = priceResult; const payload = { TomeiPriceHistoryId: this.createId(), FeedHistoryId: feedHistory.FeedHistoryId, FeedName: feedName, DateTime: new Date(), Currency: feedHistory.Currency, AdjustBuyPercentage: adjustmentPercentage.adjustBuyPercentage, AdjustSellPercentage: adjustmentPercentage.adjustSellPercentage, TomeiBuyPrice: tomeiBuyPrice, TomeiSellPrice: tomeiSellPrice, AdjustedById: loginUser ? loginUser.ObjectId : adjustmentBy, AdjustedDateTime: adjustmentDateTime, IsManualPriceActivatedYN: IsManualPriceActivatedYN, BuyLabourCharges: adjustmentPercentage.buyLabourCharges, SellLabourCharges: adjustmentPercentage.sellLabourCharges, CompanyCode: companyCode, }; const tomeiPriceHistory = yield TomeiPriceHistory._Repo.create(payload, { transaction: dbTransaction, }); if (tomeiPriceHistory) { yield TomeiPriceHistory.upsertTomeiPriceLatest(payload, dbTransaction); return new TomeiPriceHistory(tomeiPriceHistory); } else { const error = new general_1.ClassError('TomeiPriceHistory', 'TomeiPriceHistoryErrMsg01', 'TomeiPriceHistory To Save TomeiPrice'); throw error; } } catch (error) { yield TomeiPriceHistory.logger.error({ error, methodName: 'saveTomeiPrice', transaction: dbTransaction, }); throw error; } }); } static upsertTomeiPriceLatest(payload, dbTransaction) { return __awaiter(this, void 0, void 0, function* () { try { const latestPayload = { FeedName: payload.FeedName, TomeiPriceHistoryId: payload.TomeiPriceHistoryId, Currency: payload.Currency, CompanyCode: payload.CompanyCode, DateTime: payload.DateTime, AdjustBuyPercentage: payload.AdjustBuyPercentage, AdjustSellPercentage: payload.AdjustSellPercentage, TomeiBuyPrice: payload.TomeiBuyPrice, TomeiSellPrice: payload.TomeiSellPrice, AdjustedById: payload.AdjustedById, AdjustedDateTime: payload.AdjustedDateTime, UpdatedAt: new Date(), }; const existingRecord = yield TomeiPriceHistory._LatestRepo.findOne({ where: { FeedName: payload.FeedName, Currency: payload.Currency, }, transaction: dbTransaction, }); if (existingRecord) { yield TomeiPriceHistory._LatestRepo.update(latestPayload, { where: { FeedName: payload.FeedName, Currency: payload.Currency, }, transaction: dbTransaction, }); } else { yield TomeiPriceHistory._LatestRepo.create(latestPayload, { transaction: dbTransaction, }); } } catch (error) { yield TomeiPriceHistory.logger.error({ error, methodName: 'upsertTomeiPriceLatest', transaction: dbTransaction, }); throw error; } }); } calculateTomeiPrices(feedName, feedHistory, adjustmentPercentage, companyCode, manualPrice, latestPrice, dbTransaction) { return __awaiter(this, void 0, void 0, function* () { if (manualPrice) { return this.applyManualPrice(manualPrice); } const feedManualPrice = yield this.getFeedManualPrice(feedName, companyCode, dbTransaction); if (feedManualPrice) { return this.applyFeedManualPrice(feedManualPrice, latestPrice); } return yield this.calculatePriceFromFeed(feedName, feedHistory, adjustmentPercentage, companyCode, dbTransaction); }); } applyManualPrice(manualPrice) { return { tomeiBuyPrice: manualPrice.buyPrice, tomeiSellPrice: manualPrice.sellPrice, IsManualPriceActivatedYN: 'Y', }; } getFeedManualPrice(feedName, companyCode, dbTransaction) { return __awaiter(this, void 0, void 0, function* () { const feedManualPrice = yield feed_manual_price_history_1.FeedManualPriceHistory.findAll(1, 1, Object.assign({ FeedName: feedName, Status: feed_enum_1.ManualPriceStatus.ACTIVE }, (companyCode && { CompanyCode: companyCode })), dbTransaction); return feedManualPrice.count > 0 ? feedManualPrice.rows[0] : null; }); } applyFeedManualPrice(feedManualPrice, latestPrice) { var _a, _b, _c, _d; return { tomeiBuyPrice: (_b = (_a = feedManualPrice.BuyPrice) !== null && _a !== void 0 ? _a : latestPrice === null || latestPrice === void 0 ? void 0 : latestPrice.TomeiBuyPrice) !== null && _b !== void 0 ? _b : 0, tomeiSellPrice: (_d = (_c = feedManualPrice.SellPrice) !== null && _c !== void 0 ? _c : latestPrice === null || latestPrice === void 0 ? void 0 : latestPrice.TomeiSellPrice) !== null && _d !== void 0 ? _d : 0, IsManualPriceActivatedYN: 'Y', }; } calculatePriceFromFeed(feedName, feedHistory, adjustmentPercentage, companyCode, dbTransaction) { return __awaiter(this, void 0, void 0, function* () { var _a; if (feedHistory.FeedBuyPrice <= 0 || feedHistory.FeedSellPrice <= 0) { return { tomeiBuyPrice: 0, tomeiSellPrice: 0, IsManualPriceActivatedYN: 'N', }; } const feed = yield feed_1.Feed.init(dbTransaction, feedName); const weight = (_a = feed.Weight) !== null && _a !== void 0 ? _a : 0; const pricingLogic = yield company_feed_access_1.CompanyFeedAccess.getPricingLogic(dbTransaction, feedName, companyCode); return this.applyPricingLogic(feedHistory, weight, adjustmentPercentage, pricingLogic); }); } applyPricingLogic(feedHistory, weight, adjustmentPercentage, pricingLogic) { if (pricingLogic === feed_enum_1.PricingLogic.BUY_BUY_SELL) { return { tomeiBuyPrice: feedHistory.FeedBuyPrice * weight * (1 + adjustmentPercentage.adjustBuyPercentage / 100) + adjustmentPercentage.buyLabourCharges, tomeiSellPrice: feedHistory.FeedSellPrice * weight * (1 + adjustmentPercentage.adjustSellPercentage / 100) + adjustmentPercentage.sellLabourCharges, IsManualPriceActivatedYN: 'N', }; } else { return { tomeiBuyPrice: feedHistory.FeedSellPrice * weight * (1 + adjustmentPercentage.adjustBuyPercentage / 100) + adjustmentPercentage.buyLabourCharges, tomeiSellPrice: feedHistory.FeedSellPrice * weight * (1 + adjustmentPercentage.adjustSellPercentage / 100) + adjustmentPercentage.sellLabourCharges, IsManualPriceActivatedYN: 'N', }; } } static getLatestPrice(feedName_1, currency_1) { return __awaiter(this, arguments, void 0, function* (feedName, currency, companyCode = 'CTH', timestamp, dbTransaction) { var _a, _b; try { if (timestamp) { return yield TomeiPriceHistory.getClosestHistoricalPrice(feedName, currency, companyCode, timestamp, dbTransaction); } const latestPrice = yield TomeiPriceHistory.getFromLatestTable(feedName, currency, companyCode, dbTransaction); if (latestPrice) return latestPrice; const historicalPrice = yield TomeiPriceHistory.getMostRecentHistoricalPrice(feedName, currency, companyCode, dbTransaction); if (!historicalPrice) { return null; } return historicalPrice; } catch (error) { yield log_1.ApplicationLog.warning({ message: 'Non-critical error in getLatestPrice, returning null', details: { error: error.message, feedName, currency, companyCode, timestamp, }, source: 'live-price', className: 'TomeiPriceHistory', methodName: 'getLatestPrice', transaction: dbTransaction, }); if (error.name === 'SequelizeConnectionError' || error.name === 'SequelizeDatabaseError' || ((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes('connection')) || ((_b = error.message) === null || _b === void 0 ? void 0 : _b.includes('database'))) { const classError = new general_1.ClassError('TomeiPriceHistory', 'DatabaseConnectionError', `Database error while retrieving latest price: ${error.message}`); yield TomeiPriceHistory.logger.error({ error, methodName: 'getLatestPrice', transaction: dbTransaction, }); throw classError; } return null; } }); } static getLatestPriceRequired(feedName_1, currency_1) { return __awaiter(this, arguments, void 0, function* (feedName, currency, companyCode = 'CTH', timestamp, dbTransaction) { const latestPrice = yield TomeiPriceHistory.getLatestPrice(feedName, currency, companyCode, timestamp, dbTransaction); if (!latestPrice) { const error = new general_1.ClassError('TomeiPriceHistory', 'NoDataFoundError', `No price data found for feed ${feedName}, currency ${currency}, company ${companyCode}`); yield TomeiPriceHistory.logger.error({ error, methodName: 'getLatestPriceRequired', transaction: dbTransaction, }); throw error; } return latestPrice; }); } static getClosestHistoricalPrice(feedName, currency, companyCode, timestamp, dbTransaction) { return __awaiter(this, void 0, void 0, function* () { try { const options = { where: { FeedName: feedName, Currency: currency, CompanyCode: companyCode, }, order: [ [ sequelize_1.Sequelize.literal(`ABS(TIMESTAMPDIFF(SECOND, DateTime, '${timestamp.toISOString()}'))`), 'ASC', ], ], limit: 1, transaction: dbTransaction, }; return yield TomeiPriceHistory._Repo.findOne(options); } catch (error) { return null; } }); } static getFromLatestTable(feedName, currency, companyCode, dbTransaction) { return __awaiter(this, void 0, void 0, function* () { try { const latestPrice = yield TomeiPriceHistory._LatestRepo.findOne({ where: { FeedName: feedName, Currency: currency, CompanyCode: companyCode, }, transaction: dbTransaction, }); if (!latestPrice) return null; const tomeiPrice = yield TomeiPriceHistory.init(dbTransaction, latestPrice.TomeiPriceHistoryId); return { TomeiPriceHistoryId: latestPrice.TomeiPriceHistoryId, FeedHistoryId: tomeiPrice.FeedHistoryId, FeedName: latestPrice.FeedName, Currency: latestPrice.Currency, DateTime: latestPrice.DateTime, AdjustBuyPercentage: latestPrice.AdjustBuyPercentage, AdjustSellPercentage: latestPrice.AdjustSellPercentage, TomeiBuyPrice: latestPrice.TomeiBuyPrice, TomeiSellPrice: latestPrice.TomeiSellPrice, AdjustedById: latestPrice.AdjustedById, AdjustedDateTime: latestPrice.AdjustedDateTime, IsManualPriceActivatedYN: tomeiPrice.IsManualPriceActivatedYN, BuyLabourCharges: tomeiPrice.BuyLabourCharges, SellLabourCharges: tomeiPrice.SellLabourCharges, CompanyCode: latestPrice.CompanyCode, }; } catch (error) { return null; } }); } static getMostRecentHistoricalPrice(feedName, currency, companyCode, dbTransaction) { return __awaiter(this, void 0, void 0, function* () { try { const options = { where: { FeedName: feedName, Currency: currency, CompanyCode: companyCode, }, order: [['DateTime', 'DESC']], limit: 1, transaction: dbTransaction, }; return yield TomeiPriceHistory._Repo.findOne(options); } catch (error) { return null; } }); } static findAll(page, row, feedName, search, dbTransaction) { return __awaiter(this, void 0, void 0, function* () { try { const queryObj = { FeedName: feedName, }; const options = { transaction: dbTransaction, limit: row, offset: row * (page - 1), order: [['DateTime', 'DESC']], include: [ { model: price_feed_history_entity_1.default, }, ], }; if (search) { if (search.DateTime) { queryObj.DateTime = { [sequelize_1.Op.between]: [search.DateTime.startDate, search.DateTime.endDate], }; } if (search.CompanyCode) { queryObj.CompanyCode = search.CompanyCode; } } return yield TomeiPriceHistory._Repo.findAllWithPagination(Object.assign({ where: queryObj }, options)); } catch (error) { yield TomeiPriceHistory.logger.error({ error, methodName: 'findAll', transaction: dbTransaction, }); throw error; } }); } } exports.TomeiPriceHistory = TomeiPriceHistory; TomeiPriceHistory.logger = new log_1.ApplicationLog('live-price', 'TomeiPriceHistory'); TomeiPriceHistory._Repo = new tomei_price_repository_1.TomeiPriceHistoryRepository(); TomeiPriceHistory._LatestRepo = new tomei_price_latest_repository_1.TomeiPriceLatestRepository(); //# sourceMappingURL=tomei-price.js.map