| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- const API = require('../../../lib/API.js')
- const db = require('../../../plugin/DataBase/db.js')
- const { BaseStdResponse } = require('../../../BaseStdResponse.js')
- const AccessControl = require('../../../lib/AccessControl.js')
- function parseUsernames(text) {
- if (!text) return []
- return [...new Set(
- String(text)
- .split(/[,,\n\r\s]+/)
- .map((s) => s.trim())
- .filter(Boolean)
- )]
- }
- class SaveCoupon extends API {
- constructor() {
- super()
- this.setPath('/Admin/Coupon/Save')
- this.setMethod('POST')
- }
- async onRequest(req, res) {
- const {
- uuid,
- session,
- id,
- code,
- name,
- discount_type,
- discount_value,
- user_scope,
- goods_scope,
- total_limit,
- per_user_limit,
- min_amount,
- start_time,
- end_time,
- state,
- allowed_usernames,
- allowed_goods_ids
- } = req.body
- if ([uuid, session, code, discount_type, discount_value, user_scope, goods_scope, state].some(
- (v) => v === '' || v == null
- )) {
- return res.json({ ...BaseStdResponse.MISSING_PARAMETER })
- }
- if (!(await AccessControl.checkSession(uuid, session))) {
- return res.status(401).json({ ...BaseStdResponse.ACCESS_DENIED })
- }
- const permission = await AccessControl.getPermission(uuid)
- if (!permission.includes('admin') && !permission.includes('product')) {
- return res.json({ ...BaseStdResponse.PERMISSION_DENIED })
- }
- const normalizedCode = String(code).trim().toUpperCase()
- if (!/^[A-Z0-9_-]{3,32}$/.test(normalizedCode)) {
- return res.json({
- ...BaseStdResponse.ERR,
- msg: '优惠码仅支持 3-32 位字母、数字、下划线或横线'
- })
- }
- if (!['percent', 'fixed'].includes(discount_type)) {
- return res.json({ ...BaseStdResponse.ERR, msg: '折扣类型无效' })
- }
- const dValue = Number(discount_value)
- if (discount_type === 'percent' && (dValue <= 0 || dValue > 100)) {
- return res.json({ ...BaseStdResponse.ERR, msg: '折扣比例需在 1~100 之间' })
- }
- if (discount_type === 'fixed' && dValue <= 0) {
- return res.json({ ...BaseStdResponse.ERR, msg: '减免金额需大于 0' })
- }
- const uScope = Number(user_scope)
- const gScope = Number(goods_scope)
- const usernames = parseUsernames(allowed_usernames)
- const goodsIds = (Array.isArray(allowed_goods_ids) ? allowed_goods_ids : [])
- .map((g) => Number(g))
- .filter((g) => g > 0)
- if (uScope === 1 && usernames.length === 0) {
- return res.json({ ...BaseStdResponse.ERR, msg: '请指定可使用该优惠码的用户' })
- }
- if (gScope === 1 && goodsIds.length === 0) {
- return res.json({ ...BaseStdResponse.ERR, msg: '请指定可使用该优惠码的商品' })
- }
- const dup = await db.query(
- 'SELECT id FROM coupons WHERE code = ? AND id != ? LIMIT 1',
- [normalizedCode, id || 0]
- )
- if (dup && dup.length > 0) {
- return res.json({ ...BaseStdResponse.ERR, msg: '优惠码已存在' })
- }
- const time = Date.now()
- const conn = await db.connect()
- try {
- await conn.beginTransaction()
- let couponId = id ? Number(id) : null
- if (!couponId) {
- const [ins] = await conn.execute(
- `INSERT INTO coupons (
- code, name, discount_type, discount_value, user_scope, goods_scope,
- total_limit, per_user_limit, min_amount, start_time, end_time,
- state, create_user, create_time, update_time
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
- [
- normalizedCode,
- name || '',
- discount_type,
- dValue,
- uScope,
- gScope,
- Number(total_limit || 0),
- Math.max(1, Number(per_user_limit || 1)),
- Number(min_amount || 0),
- start_time || null,
- end_time || null,
- Number(state),
- uuid,
- time,
- time
- ]
- )
- couponId = ins.insertId
- } else {
- await conn.execute(
- `UPDATE coupons SET
- code = ?, name = ?, discount_type = ?, discount_value = ?,
- user_scope = ?, goods_scope = ?, total_limit = ?, per_user_limit = ?,
- min_amount = ?, start_time = ?, end_time = ?, state = ?, update_time = ?
- WHERE id = ?`,
- [
- normalizedCode,
- name || '',
- discount_type,
- dValue,
- uScope,
- gScope,
- Number(total_limit || 0),
- Math.max(1, Number(per_user_limit || 1)),
- Number(min_amount || 0),
- start_time || null,
- end_time || null,
- Number(state),
- time,
- couponId
- ]
- )
- }
- await conn.execute('DELETE FROM coupon_users WHERE coupon_id = ?', [couponId])
- await conn.execute('DELETE FROM coupon_goods WHERE coupon_id = ?', [couponId])
- if (uScope === 1) {
- for (const username of usernames) {
- const [userRows] = await conn.execute(
- 'SELECT uuid FROM users WHERE username = ? LIMIT 1',
- [username]
- )
- if (!userRows || userRows.length !== 1) {
- await conn.rollback()
- return res.json({
- ...BaseStdResponse.ERR,
- msg: `用户不存在:${username}`
- })
- }
- await conn.execute(
- 'INSERT INTO coupon_users (coupon_id, user_uuid) VALUES (?, ?)',
- [couponId, userRows[0].uuid]
- )
- }
- }
- if (gScope === 1) {
- for (const goodsId of goodsIds) {
- await conn.execute(
- 'INSERT INTO coupon_goods (coupon_id, goods_id) VALUES (?, ?)',
- [couponId, goodsId]
- )
- }
- }
- await conn.commit()
- return res.json({ ...BaseStdResponse.OK, id: couponId })
- } catch (err) {
- await conn.rollback()
- this.logger.error(`保存优惠码失败: ${err.stack}`)
- return res.json({ ...BaseStdResponse.ERR, msg: '保存优惠码失败' })
- }
- }
- }
- module.exports.SaveCoupon = SaveCoupon
|