const { Op } = require("sequelize"); const db = require("../../models"); const activeAt = at => ({ status: "ACTIVE", [Op.and]: [{ [Op.or]: [{ starts_at: null }, { starts_at: { [Op.lte]: at } }] }, { [Op.or]: [{ ends_at: null }, { ends_at: { [Op.gt]: at } }] }] }); async function resolvePrice({ businessCustomer, variant, quantity = 1, currency = variant.currency, at = new Date() }) { const retail = { source: "RETAIL", unitPrice: String(variant.base_price), minimumQuantity: 1, volumeTier: null }; if (!businessCustomer || businessCustomer.status !== "ACTIVE" || !businessCustomer.approvedAt) return retail; const common = { variant_id: variant.id, currency, ...activeAt(at) }; let rule = await db.VariantBusinessPrice.findOne({ where: { ...common, business_customer_id: businessCustomer.business_customer_id }, order: [["createdAt", "DESC"]] }); let source = "CUSTOMER"; if (!rule && businessCustomer.business_tier_id) { rule = await db.VariantBusinessPrice.findOne({ where: { ...common, business_customer_id: null, business_tier_id: businessCustomer.business_tier_id }, order: [["createdAt", "DESC"]] }); source = "TIER"; } if (!rule) return retail; if (quantity < rule.minimum_quantity) throw Object.assign(new Error(`Minimum quantity is ${rule.minimum_quantity}`), { code: "MOQ_NOT_MET", status: 400 }); const tier = await db.BusinessPriceTier.findOne({ where: { business_price_id: rule.id, min_quantity: { [Op.lte]: quantity }, [Op.or]: [{ max_quantity: null }, { max_quantity: { [Op.gte]: quantity } }] }, order: [["min_quantity", "DESC"]] }); return { source, unitPrice: String(tier ? tier.unit_price : rule.price), minimumQuantity: rule.minimum_quantity, volumeTier: tier ? { minQuantity: tier.min_quantity, maxQuantity: tier.max_quantity, unitPrice: String(tier.unit_price) } : null }; } module.exports = { resolvePrice };