/** * 会员控制器 * * 功能:处理会员管理的业务逻辑 */ const { Member, Coupon } = require('../models/Member'); const { validateRequired, validateBatch } = require('../utils/validator'); const { success } = require('../utils/response'); const { BusinessError, ValidationError, AuthorizationError } = require('../middleware/errorHandler'); // ======================================== // 会员相关控制器 // ======================================== /** * 获取会员列表(分页、筛选) * GET /api/members * 需要管理员权限 */ const getMembers = async (req, res, next) => { try { const { page = 1, pageSize = 10, level, search } = req.query; const result = await Member.findAll({ page: parseInt(page), pageSize: parseInt(pageSize), level, search }); res.json(success({ list: result.list, pagination: { total: result.total, page: result.page, pageSize: result.pageSize, totalPages: Math.ceil(result.total / result.pageSize) } }, '获取会员列表成功')); } catch (err) { next(err); } }; /** * 获取会员详情 * GET /api/members/:userId */ const getMemberByUserId = async (req, res, next) => { try { const { userId } = req.params; // 权限控制:普通用户只能查看自己的会员信息 if (req.user.role === 'customer' && parseInt(userId) !== req.user.id) { throw new AuthorizationError('您没有权限查看此会员信息'); } const member = await Member.findByUserId(userId); if (!member) { throw new BusinessError('会员信息不存在', 404); } res.json(success(member, '获取会员详情成功')); } catch (err) { next(err); } }; /** * 获取我的会员信息 * GET /api/members/my/info */ const getMyMemberInfo = async (req, res, next) => { try { let member = await Member.findByUserId(req.user.id); // 如果用户还不是会员,自动创建会员资格 if (!member) { member = await Member.create(req.user.id); } // 获取会员折扣信息 const discount = Member.getDiscount(member.level); res.json(success({ ...member, discount, discount_percent: Math.round((1 - discount) * 100) // 折扣百分比 }, '获取我的会员信息成功')); } catch (err) { next(err); } }; /** * 创建会员 * POST /api/members * 需要管理员权限 */ const createMember = async (req, res, next) => { try { const { user_id } = req.body; // 数据验证 const validation = validateRequired(user_id, '用户ID'); if (!validation.valid) { throw new ValidationError('数据验证失败', validation.errors); } // 检查用户是否已是会员 const isMember = await Member.isMember(user_id); if (isMember) { throw new BusinessError('该用户已是会员'); } const member = await Member.create(user_id); res.status(201).json(success(member, '创建会员成功')); } catch (err) { next(err); } }; /** * 更新会员等级 * PUT /api/members/:userId/level * 需要管理员权限 */ const updateMemberLevel = async (req, res, next) => { try { const { userId } = req.params; const { level } = req.body; // 数据验证 const validation = validateRequired(level, '会员等级'); if (!validation.valid) { throw new ValidationError('数据验证失败', validation.errors); } // 验证等级值 const validLevels = ['bronze', 'silver', 'gold', 'diamond']; if (!validLevels.includes(level)) { throw new ValidationError(`会员等级必须是以下之一: ${validLevels.join(', ')}`); } const member = await Member.updateLevel(userId, level); res.json(success(member, '更新会员等级成功')); } catch (err) { next(err); } }; /** * 增加会员积分 * POST /api/members/:userId/points/add * 需要管理员权限 */ const addMemberPoints = async (req, res, next) => { try { const { userId } = req.params; const { points, reason } = req.body; // 数据验证 const validation = validateRequired(points, '积分数量'); if (!validation.valid) { throw new ValidationError('数据验证失败', validation.errors); } if (parseInt(points) <= 0) { throw new ValidationError('积分数量必须大于0'); } const member = await Member.addPoints( userId, parseInt(points), reason || '管理员手动添加' ); res.json(success(member, '增加积分成功')); } catch (err) { next(err); } }; /** * 扣减会员积分 * POST /api/members/:userId/points/deduct * 需要管理员权限 */ const deductMemberPoints = async (req, res, next) => { try { const { userId } = req.params; const { points, reason } = req.body; // 数据验证 const validation = validateRequired(points, '积分数量'); if (!validation.valid) { throw new ValidationError('数据验证失败', validation.errors); } if (parseInt(points) <= 0) { throw new ValidationError('积分数量必须大于0'); } const member = await Member.deductPoints( userId, parseInt(points), reason || '管理员手动扣减' ); res.json(success(member, '扣减积分成功')); } catch (err) { next(err); } }; /** * 获取会员统计信息 * GET /api/members/statistics * 需要管理员权限 */ const getMemberStatistics = async (req, res, next) => { try { const stats = await Member.getStatistics(); res.json(success(stats, '获取会员统计成功')); } catch (err) { next(err); } }; // ======================================== // 优惠券相关控制器 // ======================================== /** * 获取优惠券列表 * GET /api/members/coupons */ const getCoupons = async (req, res, next) => { try { const { page = 1, pageSize = 10, type, is_active } = req.query; const result = await Coupon.findAll({ page: parseInt(page), pageSize: parseInt(pageSize), type, is_active: is_active !== undefined ? parseInt(is_active) : undefined }); res.json(success({ list: result.list, pagination: { total: result.total, page: result.page, pageSize: result.pageSize, totalPages: Math.ceil(result.total / result.pageSize) } }, '获取优惠券列表成功')); } catch (err) { next(err); } }; /** * 获取优惠券详情 * GET /api/members/coupons/:id */ const getCouponById = async (req, res, next) => { try { const { id } = req.params; const coupon = await Coupon.findById(id); if (!coupon) { throw new BusinessError('优惠券不存在', 404); } res.json(success(coupon, '获取优惠券详情成功')); } catch (err) { next(err); } }; /** * 创建优惠券 * POST /api/members/coupons * 需要管理员权限 */ const createCoupon = async (req, res, next) => { try { const { name, type, discount_value, min_amount, max_discount, valid_from, valid_to, total_quantity, points_required, is_active } = req.body; // 数据验证 const validation = validateBatch([ validateRequired(name, '优惠券名称'), validateRequired(type, '优惠券类型'), validateRequired(discount_value, '优惠值'), validateRequired(valid_from, '有效期开始时间'), validateRequired(valid_to, '有效期结束时间'), validateRequired(total_quantity, '发放数量') ]); if (!validation.valid) { throw new ValidationError('数据验证失败', validation.errors); } // 验证优惠券类型 const validTypes = ['discount', 'cash']; if (!validTypes.includes(type)) { throw new ValidationError('优惠券类型必须是 discount 或 cash'); } // 验证优惠值 if (parseFloat(discount_value) <= 0) { throw new ValidationError('优惠值必须大于0'); } if (type === 'discount' && parseFloat(discount_value) >= 1) { throw new ValidationError('折扣类型的优惠值必须小于1(如0.9表示9折)'); } // 验证数量 if (parseInt(total_quantity) <= 0) { throw new ValidationError('发放数量必须大于0'); } const coupon = await Coupon.create({ name, type, discount_value: parseFloat(discount_value), min_amount: min_amount ? parseFloat(min_amount) : null, max_discount: max_discount ? parseFloat(max_discount) : null, valid_from, valid_to, total_quantity: parseInt(total_quantity), points_required: points_required ? parseInt(points_required) : 0, is_active: is_active !== undefined ? parseInt(is_active) : 1 }); res.status(201).json(success(coupon, '创建优惠券成功')); } catch (err) { next(err); } }; /** * 更新优惠券 * PUT /api/members/coupons/:id * 需要管理员权限 */ const updateCoupon = async (req, res, next) => { try { const { id } = req.params; const { name, discount_value, min_amount, max_discount, valid_from, valid_to, total_quantity, points_required, is_active } = req.body; // 检查优惠券是否存在 const coupon = await Coupon.findById(id); if (!coupon) { throw new BusinessError('优惠券不存在', 404); } const updatedCoupon = await Coupon.update(id, { name, discount_value: discount_value !== undefined ? parseFloat(discount_value) : undefined, min_amount: min_amount !== undefined ? (min_amount ? parseFloat(min_amount) : null) : undefined, max_discount: max_discount !== undefined ? (max_discount ? parseFloat(max_discount) : null) : undefined, valid_from, valid_to, total_quantity: total_quantity !== undefined ? parseInt(total_quantity) : undefined, points_required: points_required !== undefined ? parseInt(points_required) : undefined, is_active: is_active !== undefined ? parseInt(is_active) : undefined }); res.json(success(updatedCoupon, '更新优惠券成功')); } catch (err) { next(err); } }; /** * 删除优惠券 * DELETE /api/members/coupons/:id * 需要管理员权限 */ const deleteCoupon = async (req, res, next) => { try { const { id } = req.params; // 检查优惠券是否存在 const coupon = await Coupon.findById(id); if (!coupon) { throw new BusinessError('优惠券不存在', 404); } await Coupon.delete(id); res.json(success(null, '删除优惠券成功')); } catch (err) { next(err); } }; /** * 领取优惠券 * POST /api/members/coupons/:id/claim */ const claimCoupon = async (req, res, next) => { try { const { id } = req.params; const userCoupon = await Coupon.claimByUser(req.user.id, id); res.status(201).json(success(userCoupon, '领取优惠券成功')); } catch (err) { next(err); } }; /** * 获取我的优惠券 * GET /api/members/my/coupons */ const getMyCoupons = async (req, res, next) => { try { const { status } = req.query; const coupons = await Coupon.getUserCoupons(req.user.id, status || null); res.json(success({ count: coupons.length, coupons }, '获取我的优惠券成功')); } catch (err) { next(err); } }; // 导出所有控制器函数 module.exports = { // 会员相关 getMembers, getMemberByUserId, getMyMemberInfo, createMember, updateMemberLevel, addMemberPoints, deductMemberPoints, getMemberStatistics, // 优惠券相关 getCoupons, getCouponById, createCoupon, updateCoupon, deleteCoupon, claimCoupon, getMyCoupons };