CRMEB/crmeb/app/services/user/member/MemberCardServices.php
2026-03-23 14:57:47 +08:00

380 lines
16 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
namespace app\services\user\member;
use app\dao\user\MemberCardDao;
use app\services\BaseServices;
use app\services\order\OtherOrderServices;
use app\services\order\StoreOrderCreateServices;
use app\services\user\UserServices;
use crmeb\exceptions\AdminException;
use crmeb\exceptions\ApiException;
use crmeb\services\SystemConfigService;
class MemberCardServices extends BaseServices
{
/**
* @var MemberCardDao
*/
protected $dao;
/** 初始化获得dao层句柄
* MemberCardServices constructor.
* @param MemberCardDao $memberCardDao
*/
public static $_memberTypePrefix = ['month', 'quarter', 'year', 'ever', 'free', 'owner'];
public function __construct(MemberCardDao $memberCardDao)
{
$this->dao = $memberCardDao;
}
public function getSearchList(array $where = [])
{
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
[$page, $limit] = $this->getPageValue();
$where['batch_card_id'] = $where['card_batch_id'];
if ($where['is_use'] != "") {
if ($where['is_use'] == 0) {
$where['use_time'] = 0;
} else {
$where['use_time'] = 1;
}
}
unset($where['is_use']);
$list = $this->dao->getSearchList($where, $page, $limit);
$userIds = array_column($list->toArray(), 'use_uid');
$userList = $userService->getColumn([['uid', 'in', $userIds]], 'nickname,phone,real_name', 'uid');
foreach ($list as $k => $v) {
if ($v['use_uid']) {
$list[$k]['username'] = $userList[$v['use_uid']]['real_name'] ?: $userList[$v['use_uid']]['nickname'];
$list[$k]['phone'] = $userList[$v['use_uid']] ? $userList[$v['use_uid']]['phone'] : "";
}
$list[$k]['add_time'] = date('Y-m-d H:i:s', $v['add_time']);
$list[$k]['use_time'] = $v['use_time'] != 0 ? date('Y-m-d H:i:s', $v['use_time']) : "未使用";
}
$count = $this->dao->count($where);
return compact('list', 'count');
}
/** 生成免费会员卡
* @param array $data
*/
public function addCard(array $data)
{
if (!isset($data['card_batch_id']) || !$data['card_batch_id'] || $data['card_batch_id'] == 0 || !isset($data['total_num']) || !$data['total_num'] || $data['total_num'] == 0) {
throw new AdminException('参数错误');
}
try {
if (!isset($data['total_num'])) throw new AdminException('参数错误');
$num = $data['total_num'];
unset($data['total_num']);
$res = [];
for ($i = 0; $i < $num; $i++) {
$data['card_number'] = $this->makeRandomNumber("CR", $data['card_batch_id']);
$data['card_password'] = $this->makeRandomNumber();
$data['status'] = 1;
$data['add_time'] = time();
$res[] = $data;
}
//数据切片批量插入,提高性能。
$chunk_inster_card = array_chunk($res, 100, true);
foreach ($chunk_inster_card as $v) {
$this->dao->saveAll($v);
}
return true;
} catch (\Exception $exception) {
throw new AdminException('生成卡失败');
}
}
/**获取制卡卡号随机数
* @param bool $prefix
* @param bool $random
* @return string
*/
public function makeRandomNumber($prefix = false, $random = false)
{
if (!$prefix) {
$prefix = "";
}
if (!$random || !is_numeric($random)) {
$one_random = mt_rand(11111, 99999);
} else {
$one_random = sprintf("%05d", $random);
}
$date_random = date('ymd', time());
$random_tmp = strlen($one_random);
$two_randow = str_pad(mt_rand(1, 99999), $random_tmp, '0', STR_PAD_LEFT);
if (!$random) {
return $two_randow;
} else {
return $prefix . $one_random . $date_random . $two_randow;
}
}
/** 领取会员卡
* @param array $data
* @param int $uid
*/
public function drawMemberCard(array $data, int $uid)
{
if (!$uid || !$data) throw new ApiException('参数错误');
$isOpenMember = $this->isOpenMemberCard();
if (!$isOpenMember) throw new ApiException('会员功能暂未开启');
if (!isset($data['member_card_code']) || !$data['member_card_code']) throw new ApiException('请输入会员卡号');
if (!isset($data['member_card_code']) || !$data['member_card_pwd']) throw new ApiException('请输入领取卡密');
$card_info = $this->dao->getOneByWhere(['card_number' => trim($data['member_card_code'])]);
if (!$card_info) throw new ApiException('会员卡不存在');
/** @var MemberCardBatchServices $memberBatchServices */
$memberBatchServices = app()->make(MemberCardBatchServices::class);
$batch_info = $memberBatchServices->getOne($card_info['card_batch_id']);
if (!$batch_info) throw new ApiException('会员卡未激活,暂无法使用');
if ($batch_info->status != 1) throw new ApiException('会员卡未激活,暂无法使用');
if ($card_info['status'] == 0) throw new ApiException('会员卡未激活,暂无法使用');
if ($card_info['card_password'] != trim($data['member_card_pwd'])) throw new ApiException('会员卡密码有误');
if ($card_info['use_uid'] && $card_info['use_time']) throw new ApiException('会员卡已使用');
/** @var UserServices $userServices */
$userServices = app()->make(UserServices::class);
$user_info = $userServices->getUserInfo($uid);
if (!$user_info) throw new ApiException('用户不存在');
if ($user_info->is_money_level > 0 && $user_info->is_ever_level == 1) throw new ApiException('您已是永久会员,无需再领取,可以将此卡转送亲朋好友,一起享受优惠');
/**
* 批次卡具体使用期限,业务需要打开即可,勿删。
*/
if ($card_info->status != 1) throw new ApiException('会员卡未激活,暂无法使用');
$this->transaction(function () use ($card_info, $user_info, $batch_info, $memberBatchServices, $userServices, $data) {
$res1 = $this->dao->update($card_info->id, ['use_uid' => $user_info->uid, 'use_time' => time(), 'update_time' => time()], 'id');
if ($res1) {
$res2 = $memberBatchServices->useCardSetInc($batch_info->id, 'use_num', 1);
$overdue_time = 0;
switch ($user_info->is_money_level) {
case 1:
case 2:
case 3:
$overdue_time = bcadd(bcmul($batch_info->use_day, 86400, 0), $user_info->overdue_time, 0);
$overdue_time = mktime(date('H'), date('i'), date('s'), date('m', $overdue_time), date('d', $overdue_time), date('Y', $overdue_time));
break;
case 0:
$overdue_time = bcadd(bcmul($batch_info->use_day, 86400, 0), time(), 0);
break;
}
$channel_type = $data['from'];
/** @var OtherOrderServices $OtherOrderServices */
$OtherOrderServices = app()->make(OtherOrderServices::class);
$storeOrderCreateService = app()->make(StoreOrderCreateServices::class);
$record_data['uid'] = $user_info->uid;
$record_data['member_code'] = $card_info->card_number;
$record_data['use_day'] = $batch_info->use_day;
$record_data['overdue_time'] = $overdue_time;
$record_data['order_id'] = $storeOrderCreateService->getNewOrderId();
$record_data['channel_type'] = $channel_type;
$record_data['member_type'] = "free";
$record_data['vip_day'] = $batch_info->use_day;
$record_data['type'] = 2;
$record_data['paid'] = 1;
$record_data['pay_time'] = time();
$res3 = $OtherOrderServices->addOtherOrderData($record_data);
//if ($res3) $res4 = $userServices->update($user_info->uid, ['level' => 1, 'overdue_time' => $overdue_time, 'is_permanent' => 0], 'uid');
/** @var UserServices $userServices */
$userServices = app()->make(UserServices::class);
$res4 = $userServices->setMemberOverdueTime($batch_info->use_day, $user_info->uid, 2, $record_data['member_type']);
$res5 = $res1 && $res2 && $res3 && $res4;
return $res5;
}
});
}
/** 验证是否存在此类型会员卡
* @param string $member_type
* @return bool
*/
public function checkmemberType(string $member_type)
{
$member_type_arr = $this->getMemberTypeInfo();
if (!array_key_exists($member_type, $member_type_arr)) throw new ApiException('暂无此类型会员卡');
return true;
}
/** 获取会员权益和说明配置
* @return array
*/
public function getMemberRightsInfo()
{
/** @var MemberRightServices $memberRightService */
$memberRightService = app()->make(MemberRightServices::class);
$memberRight = $memberRightService->getSearchList(['status' => 1]);
if ($memberRight['list']) {
foreach ($memberRight['list'] as $k => &$v) {
$v['title'] = $v['show_title'];
$v['pic'] = $v['image'];
$v['right'] = $v['explain'];
if ($v['right_type'] == 'offline') $v['explain'] = '线下支付打' . floatval(bcdiv((string)$v['number'], '10', 1)) . '折';
if ($v['right_type'] == 'sign') $v['explain'] = '签到多得' . (int)$v['number'] . '倍积分';
if ($v['right_type'] == 'express') $v['explain'] = '运费打' . floatval(bcdiv((string)$v['number'], '10', 1)) . '折';
if ($v['right_type'] == 'integral') $v['explain'] = '消费多返' . (int)$v['number'] . '倍积分';
}
}
return ['member_right' => $memberRight['list']];
}
/**获取会员卡配置
* @return array
*/
public function getMemberTypeInfo()
{
/** @var SystemConfigService $systemConfigService */
$systemConfigService = app()->make(SystemConfigService::class);
$data = [];
foreach (self::$_memberTypePrefix as $v) {
$data[$v] = $systemConfigService::more([$v . '_title', $v . '_vip_day', $v . '_pre_price', $v . '_price']);
}
return $data;
}
/**会员卡数据处理
* @return array
*/
public function DoMemberType()
{
$data = array();
/** @var MemberShipServices $memberShipService */
$memberShipService = app()->make(MemberShipServices::class);
$list = $memberShipService->getApiList(['is_del' => 0]);
foreach ($list as $v) {
$data[] = [
'mc_id' => $v['id'],
'title' => $v['title'],
'type' => $v['type'],
'vip_day' => $v['vip_day'],
'pre_price' => $v['pre_price'],
'price' => $v['price'],
];
}
return $data;
}
/**会员类型数据
* @return bool
*/
public function getMemberTypeValue()
{
$member_type = $this->DoMemberType();
if (!$member_type) return false;
$new_member_data = [];
foreach ($member_type as $k => $v) {
$new_member_data[$v['mc_id']] = $v;
}
return $new_member_data;
}
/**导出会员卡
* @param $where
* @return \think\Collection
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getExportData($where)
{
$data = $this->dao->getSearchList($where);
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
/** @var MemberCardBatchServices $batchService */
$batchService = app()->make(MemberCardBatchServices::class);
foreach ($data as $k => $v) {
$data[$k]['use_time'] = $v['use_time'] != 0 ? date('Y-m-d H:i:s', $v['use_time']) : "";
$data[$k]['user_name'] = '';
$data[$k]['user_phone'] = '';
if ($v['use_uid'] != 0) {
$userInfo = $userService->get($v['use_uid']);
$data[$k]['user_name'] = $userInfo['nickname'] ?: $userInfo['account'];
$data[$k]['user_phone'] = $userInfo['phone'];
}
}
$batchInfo = $batchService->getOne($where['batch_card_id']);
$dataArray['title'] = $batchInfo ? $batchInfo['title'] : "";
$dataArray['data'] = $data;
return $dataArray;
}
/**获取会员记录
* @param array $where
* @return array
*/
public function getSearchRecordList(array $where)
{
/** @var OtherOrderServices $otherOrderSevice */
$otherOrderSevice = app()->make(OtherOrderServices::class);
return $otherOrderSevice->getMemberRecord($where);
}
/**
* 看是否开启会员功能
* @param string $rightType
* @param bool $get_number
* @return bool|mixed
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function isOpenMemberCard(string $rightType = '', bool $get_number = true)
{
$isOpen = sys_config('member_card_status', 1);
//如果传入权益类别,查看是否具有某权益
if (!$rightType) {
if ($isOpen) return true;
return false;
} else {
/** @var MemberRightServices $memberRightService */
$memberRightService = app()->make(MemberRightServices::class);
$memberRight = $memberRightService->getOne(['right_type' => $rightType], 'status,number');
if ($isOpen && $memberRight && $memberRight['status']) {
if ($get_number) {
$number = $memberRight['number'];
if (!$number) return false;
return $number;
}
return true;
}
return false;
}
}
/**
* 修改会员卡状态
* @param $id
* @param $status
* @return bool
*/
public function setStatus($id, $status)
{
$card_batch_id = $this->dao->value(['id' => $id], 'card_batch_id');
$card_batch_status = app()->make(MemberCardBatchServices::class)->value(['id' => $card_batch_id], 'status');
if ($card_batch_status == 0) {
throw new AdminException('批次未激活,暂无法使用');
}
$res = $this->dao->update($id, ['status' => $status]);
if ($res) return true;
return false;
}
}