const db = require("../../models"); const business = require("./businessPricing.service"); const money = require("./money"); const applies = (promotion, quantity, at) => promotion.status === "ACTIVE" && (!promotion.starts_at || new Date(promotion.starts_at) <= at) && (!promotion.ends_at || new Date(promotion.ends_at) > at) && (!promotion.minimum_quantity || quantity >= promotion.minimum_quantity); const discount = (price, promotion) => promotion.type === "PERCENTAGE" ? money.percentOff(price, promotion.discount_percent) : promotion.type === "FIXED_AMOUNT" ? String(promotion.discount_amount) : money.subtractFloor(price, promotion.fixed_price); async function quoteVariant({ variantId, businessCustomer, quantity = 1, couponCode, at = new Date() }) { const variant = await db.ProductVariant.findOne({ where: { id: variantId, status: "ACTIVE" } }); if (!variant) throw Object.assign(new Error("Variant not found"), { code: "VARIANT_NOT_FOUND", status: 404 }); const base = await business.resolvePrice({ businessCustomer, variant, quantity, at }); const promotions = await db.Promotion.findAll({ where: { status: "ACTIVE" }, order: [["priority", "DESC"], ["id", "ASC"]] }); const automatic = promotions.filter(p => applies(p, quantity, at))[0] || null; let effective = base.unitPrice; let automaticDiscount = "0.00"; if (automatic) { automaticDiscount = discount(effective, automatic); effective = money.subtractFloor(effective, automaticDiscount); } let coupon = null; if (couponCode) { coupon = await db.Coupon.findOne({ where: { code: couponCode.trim().toUpperCase(), status: "ACTIVE" }, include: [{ model: db.Promotion, as: "promotion" }] }); if (!coupon || (coupon.starts_at && new Date(coupon.starts_at) > at) || (coupon.expires_at && new Date(coupon.expires_at) <= at) || !applies(coupon.promotion, quantity, at)) throw Object.assign(new Error("Coupon is not valid"), { code: "INVALID_COUPON", status: 400 }); if (!automatic || automatic.stackable) effective = money.subtractFloor(effective, discount(effective, coupon.promotion)); } return { cataloguePrice: String(variant.base_price), businessPrice: base.source === "RETAIL" ? null : base.unitPrice, baseEligiblePrice: base.unitPrice, effectiveUnitPrice: effective, currency: variant.currency, minimumQuantity: base.minimumQuantity, automaticPromotion: automatic && { id: automatic.id, name: automatic.name }, coupon: coupon && { code: coupon.code } }; } module.exports = { quoteVariant, applies, discount };