| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- const db = require('../plugin/DataBase/db')
- function roundMoney(n) {
- return Math.round(Number(n) * 100) / 100
- }
- function calcDiscount(price, discountType, discountValue) {
- const p = Number(price)
- let discount = 0
- if (discountType === 'percent') {
- const pct = Math.min(100, Math.max(0, Number(discountValue)))
- discount = roundMoney((p * pct) / 100)
- } else {
- discount = roundMoney(Math.min(p, Math.max(0, Number(discountValue))))
- }
- let finalPrice = roundMoney(p - discount)
- if (finalPrice < 0.01) finalPrice = 0.01
- if (finalPrice > p) finalPrice = p
- discount = roundMoney(p - finalPrice)
- return { discountAmount: discount, finalPrice }
- }
- async function countActiveUsage(couponId, userUuid) {
- const totalRows = await db.query(
- `SELECT COUNT(*) AS cnt FROM coupon_usage cu
- INNER JOIN orders o ON o.orderId = cu.order_id
- WHERE cu.coupon_id = ? AND o.state IN (0, 1, 2)`,
- [couponId]
- )
- const userRows = await db.query(
- `SELECT COUNT(*) AS cnt FROM coupon_usage cu
- INNER JOIN orders o ON o.orderId = cu.order_id
- WHERE cu.coupon_id = ? AND cu.user_uuid = ? AND o.state IN (0, 1, 2)`,
- [couponId, userUuid]
- )
- return {
- total: Number(totalRows?.[0]?.cnt || 0),
- perUser: Number(userRows?.[0]?.cnt || 0)
- }
- }
- /**
- * 校验优惠码并计算优惠后价格
- */
- async function validateCoupon({ code, userUuid, goodsId, goodsPrice }) {
- const normalizedCode = String(code || '').trim().toUpperCase()
- if (!normalizedCode) {
- return { ok: false, msg: '请输入优惠码' }
- }
- const rows = await db.query(
- `SELECT * FROM coupons WHERE code = ? AND state = 1 LIMIT 1`,
- [normalizedCode]
- )
- if (!rows || rows.length !== 1) {
- return { ok: false, msg: '优惠码不存在或已失效' }
- }
- const coupon = rows[0]
- const now = Date.now()
- if (coupon.start_time && now < Number(coupon.start_time)) {
- return { ok: false, msg: '优惠码尚未生效' }
- }
- if (coupon.end_time && now > Number(coupon.end_time)) {
- return { ok: false, msg: '优惠码已过期' }
- }
- const price = Number(goodsPrice)
- const minAmount = Number(coupon.min_amount || 0)
- if (minAmount > 0 && price < minAmount) {
- return { ok: false, msg: `订单满 ¥${minAmount} 才可使用该优惠码` }
- }
- if (Number(coupon.goods_scope) === 1) {
- const goodsRows = await db.query(
- 'SELECT 1 FROM coupon_goods WHERE coupon_id = ? AND goods_id = ? LIMIT 1',
- [coupon.id, goodsId]
- )
- if (!goodsRows || goodsRows.length === 0) {
- return { ok: false, msg: '该优惠码不适用于当前商品' }
- }
- }
- if (Number(coupon.user_scope) === 1) {
- const userRows = await db.query(
- 'SELECT 1 FROM coupon_users WHERE coupon_id = ? AND user_uuid = ? LIMIT 1',
- [coupon.id, userUuid]
- )
- if (!userRows || userRows.length === 0) {
- return { ok: false, msg: '您暂无使用该优惠码的权限' }
- }
- }
- const usage = await countActiveUsage(coupon.id, userUuid)
- const totalLimit = Number(coupon.total_limit || 0)
- const perUserLimit = Number(coupon.per_user_limit || 1)
- if (totalLimit > 0 && usage.total >= totalLimit) {
- return { ok: false, msg: '优惠码已达使用上限' }
- }
- if (usage.perUser >= perUserLimit) {
- return { ok: false, msg: '您已达到该优惠码的使用次数上限' }
- }
- const { discountAmount, finalPrice } = calcDiscount(
- price,
- coupon.discount_type,
- coupon.discount_value
- )
- if (discountAmount <= 0) {
- return { ok: false, msg: '优惠码无效,未产生优惠' }
- }
- return {
- ok: true,
- couponId: coupon.id,
- code: coupon.code,
- name: coupon.name,
- discountType: coupon.discount_type,
- discountValue: Number(coupon.discount_value),
- originalPrice: roundMoney(price),
- discountAmount,
- finalPrice,
- displayDiscount:
- coupon.discount_type === 'percent'
- ? `${coupon.discount_value}% 折扣`
- : `立减 ¥${coupon.discount_value}`
- }
- }
- async function recordUsage(couponId, orderId, userUuid, discountAmount) {
- const time = Date.now()
- await db.query(
- `INSERT INTO coupon_usage (coupon_id, order_id, user_uuid, discount_amount, create_time)
- VALUES (?, ?, ?, ?, ?)`,
- [couponId, orderId, userUuid, discountAmount, time]
- )
- await db.query('UPDATE coupons SET used_count = used_count + 1 WHERE id = ?', [couponId])
- }
- async function releaseUsageForOrder(orderId) {
- const rows = await db.query(
- 'SELECT coupon_id FROM orders WHERE orderId = ? AND coupon_id IS NOT NULL LIMIT 1',
- [orderId]
- )
- if (!rows || !rows[0]?.coupon_id) return
- const couponId = rows[0].coupon_id
- const del = await db.query('DELETE FROM coupon_usage WHERE order_id = ?', [orderId])
- if (del?.affectedRows > 0) {
- await db.query(
- 'UPDATE coupons SET used_count = GREATEST(used_count - 1, 0) WHERE id = ?',
- [couponId]
- )
- }
- }
- module.exports = {
- roundMoney,
- calcDiscount,
- validateCoupon,
- recordUsage,
- releaseUsageForOrder
- }
|