Files
huangjingfen/pro_v3.5.1/app/services/activity/card/CardGiftServices.php
panchengyong c1e74d8e68 chore(php): 统一 ScottPan 文件头与注释域名替换
- 按 docs/renew-code-comment.md 将 PHP 文件头改为带边框的 Author 注释\n- 注释中的 crmeb.com 替换为 uj345.cn(代码字符串中的外链未改)\n- 新增 docs/renew-code-comment.md 说明

Made-with: Cursor
2026-03-29 11:22:58 +08:00

437 lines
16 KiB
PHP

<?php
// +----------------------------------------------------------------------
// | Author: ScottPan Team
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\services\activity\card;
use app\dao\activity\card\CardGiftDao;
use app\jobs\activity\card\CardJob;
use app\services\BaseServices;
use app\services\product\product\StoreDescriptionServices;
use app\services\product\product\StoreProductServices;
use app\services\product\sku\StoreProductAttrValueServices;
use crmeb\services\FormBuilder as Form;
use think\annotation\Inject;
use think\exception\ValidateException;
use think\facade\Route as Url;
/**
* 礼品卡
* Class CardGiftServices
* @package app\services\activity\card
* @mixin CardGiftDao
*/
class CardGiftServices extends BaseServices
{
/**
* @var CardGiftDao
*/
#[Inject]
protected CardGiftDao $dao;
/**
* 列表
* @param array $where
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* User: liusl
* DateTime: 2025/5/12 09:37
*/
public function getList(array $where)
{
[$page, $limit] = $this->getPageValue();
$where['is_del'] = 0;
$list = $this->dao->getList($where, '*', $page, $limit, 'sort desc,add_time desc');
$count = $this->dao->count($where);
$bIds = array_column($list, 'batch_id');
$batchList = app()->make(CardBatchServices::class)->search(['id', $bIds])->column('name', 'id');
foreach ($list as &$item) {
$item['batch_name'] = $batchList[$item['batch_id']] ?? '';
$item['fixed_time'] = [
$item['start_time'] ? date('Y-m-d H:i:s', $item['start_time']) : '',
$item['end_time'] ? date('Y-m-d H:i:s', $item['end_time']) : '',
];
}
return compact('list', 'count');
}
/**
* 添加
* @param array $data
* @param int $id
* @return true
* @throws \ReflectionException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* User: liusl
* DateTime: 2025/5/12 09:46
*/
public function saveData(array $data, int $id = 0, int $admin_id = 0)
{
if ($id && !$info = $this->dao->get($id)) {
throw new ValidateException('礼品卡不存在');
}
//验证卡密未使用的数量是否超过礼品卡填写的总量
if (!$id) {
$codeCount = app()->make(CardCodeServices::class)->count(['batch_id' => $data['batch_id'], 'status' => 0, 'card_id' => 0]);
if ($codeCount < $data['total_num']) {
throw new ValidateException('卡密未使用的数量不能超过礼品卡填写的总量');
}
}
if ($data['valid_type'] == 2) {
$data['start_time'] = isset($data['fixed_time'][0]) ? strtotime($data['fixed_time'][0]) : 0;
$data['end_time'] = isset($data['fixed_time'][1]) ? strtotime($data['fixed_time'][1]) : 0;
}
unset($data['fixed_time']);
$this->transaction(function () use ($id, $data, $admin_id) {
$product = $data['product'];
$description = $data['description'];
unset($data['product'], $data['description']);
$data['add_time'] = time();
if ($id) {
$this->dao->update($id, $data);
} else {
$res = $this->dao->save($data);
$id = $res->id;
//修改卡密
$this->saveCode($id, $data, $admin_id);
}
app()->make(StoreDescriptionServices::class)->saveDescription($id, $description, 5);
//保存礼品卡商品
$this->saveProduct($id, $product);
return true;
});
$batch_id = $id ? $info['batch_id'] : $data['batch_id'];
//校验卡密使用数量
CardJob::dispatchDo('allocationCode', [$batch_id]);
return true;
}
/**
* 修改卡密
* @param int $id
* @param array $data
* @return true
* @throws \ReflectionException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* User: liusl
* DateTime: 2025/5/12 09:46
*/
public function saveCode(int $id, array $data, int $admin_id = 0)
{
$cardCodeServices = app()->make(CardCodeServices::class);
$list = $cardCodeServices->search(['batch_id' => $data['batch_id'], 'status' => 0, 'card_id' => 0])->order('id asc')->limit($data['total_num'])->select()->toArray();
if (!$list) {
throw new ValidateException('没有可操作的卡密');
}
$ids = [];
$updateData = [
'type' => $data['type'],
'end_time' => $data['end_time'] ?? 0,
'card_id' => $id,
'status' => 2,
];
$str = '';
$i = $list[0]['id'];
$status = true;
foreach ($list as $k => $item) {
if ($k == 0) {
$str .= $item['card_number'] . '--';
} elseif ($k == count($list) - 1) {
//获取列表最后一条数据
$str .= $item['card_number'];
} else {
if ($item['id'] != $i) {
if ($status) {
$str .= $item['card_number'] . ',';
$status = false;
} else {
$str .= $item['card_number'] . '--';
$status = true;
}
}
}
$i = $item['id'] + 1;
$ids[] = $item['id'];
// 每满100条插入一次并清空缓存
if (count($ids) >= 500) {
$cardCodeServices->batchUpdate($ids, $updateData);
$ids = [];
}
}
if (count($ids)) {
$cardCodeServices->batchUpdate($ids, $updateData);
}
app()->make(CardGiftRecordServices::class)->save([
'gift_id' => $id,
'record' => $str,
'num' => count($list),
'pm' => 1,
'add_time' => time(),
'admin_id' => $admin_id
]);
return true;
}
/**
* 新增商品
* @param int $id
* @param array $productData
* @return true
* User: liusl
* DateTime: 2025/5/12 09:45
*/
public function saveProduct(int $id, array $productData)
{
$auxiliary = app()->make(CardGiftAuxiliaryServices::class);
$auxiliary->delete(['gift_id' => $id]);
$saveData = [];
foreach ($productData as $product) {
$saveData[] = [
'gift_id' => $id,
'product_id' => $product['product_id'] ?? 0,
'limit_num' => $product['limit_num'] ?? 0,
'unique' => $product['unique'] ?? '',
];
}
if (count($saveData)) {
$auxiliary->saveAll($saveData);
}
return true;
}
/**
* 增加卡密表单
* @param int $id
* @return mixed
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* User: liusl
* DateTime: 2025/5/12 15:41
*/
public function otherForm(int $id)
{
$info = $this->dao->get($id);
if (!$info) {
throw new ValidateException('礼品卡不存在');
}
$info = $info->toArray();
$batchInfo = app()->make(CardBatchServices::class)->get($info['batch_id']);
$remain_num = $batchInfo['total_num'] - $batchInfo['used_num'];
$remain_num = max($remain_num, 0);
$batchName = $batchInfo['name'] . "({$remain_num})";
$field[] = Form::input('batch_name', '卡号批次', $batchName)->disabled(true);
$field[] = Form::radio('type', '修改数量', $formData['status'] ?? 1)->options([
['label' => '增加', 'value' => 1],
['label' => '减少', 'value' => 2],
]);
$field[] = Form::number('number', '数量', 0)->min(0);
return create_form('修改数量', $field, Url::buildUrl('/marketing/card/gift/update_other/' . $id), 'POST');
}
/**
* 增加卡密提交
* @param int $id
* @param int $type
* @param int $number
* @return true
* @throws \ReflectionException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* User: liusl
* DateTime: 2025/5/12 15:42
*/
public function updateOther(int $id, int $type, int $number, int $admin_id)
{
$info = $this->dao->get($id);
if (!$info) {
throw new ValidateException('礼品卡不存在');
}
if ($type == 1) {
$total_num = $info->total_num + $number;
//增加
$count = app()->make(CardCodeServices::class)->count(['batch_id' => $info['batch_id'], 'status' => 0, 'card_id' => 0]);
if ($count < $number) {
throw new ValidateException('卡密不足');
}
$this->saveCode($id, ['total_num' => $number, 'batch_id' => $info['batch_id'], 'type' => $info['type']], $admin_id);
} else {
$total_num = $info->total_num - $number;
//减少
$count = app()->make(CardCodeServices::class)->count(['batch_id' => $info['batch_id'], 'status' => 2, 'card_id' => $id]);
if ($count < $number) {
throw new ValidateException('未卡密不足,无法减少,未使用卡密:' . $count);
}
$cardCodeServices = app()->make(CardCodeServices::class);
$list = $cardCodeServices->search(['batch_id' => $info['batch_id'], 'status' => 2, 'card_id' => $id])->order('id asc')->limit($number)->select()->toArray();
if (!$list) {
throw new ValidateException('没有可操作的卡密');
}
$ids = [];
$updateData = [
'type' => 0,
'card_id' => 0,
'end_time' => 0,
'status' => 0,
];
$str = '';
$i = $list[0]['id'];
$status = true;
foreach ($list as $k => $item) {
//检查 id 是否间断, 如果有给$str追加
if ($k == 0) {
$str .= $item['card_number'] . '--';
} elseif ($k == count($list) - 1) {
//获取列表最后一条数据
$str .= $item['card_number'];
} else {
if ($item['id'] != $i) {
if ($status) {
$str .= $item['card_number'] . ',';
$status = false;
} else {
$str .= $item['card_number'] . '--';
$status = true;
}
}
}
$i = $item['id'] + 1;
$ids[] = $item['id'];
// 每满100条插入一次并清空缓存
if (count($ids) >= 500) {
$cardCodeServices->batchUpdate($ids, $updateData);
$ids = [];
}
}
if (count($ids)) {
$cardCodeServices->batchUpdate($ids, $updateData);
}
app()->make(CardGiftRecordServices::class)->save([
'gift_id' => $id,
'record' => $str,
'num' => count($list),
'pm' => 2,
'add_time' => time(),
'admin_id' => $admin_id
]);
}
$info->total_num = $total_num;
$info->save();
//校验卡密使用数量
CardJob::dispatchDo('allocationCode', [$info['batch_id']]);
return true;
}
/**
* 详情
* @param $id
* @return array
* @throws \ReflectionException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* User: liusl
* DateTime: 2025/5/12 15:42
*/
public function getInfo($id)
{
$info = $this->dao->get($id);
if (!$info) {
throw new ValidateException('礼品卡不存在');
}
$info = $info->toArray();
$auxiliaryList = app()->make(CardGiftAuxiliaryServices::class)->search(['gift_id' => $id])->select()->toArray();
$info['product'] = [];
$info['description'] = app()->make(StoreDescriptionServices::class)->getDescription(['product_id' => $id, 'type' => 5]);
$info['fixed_time'] = [
$info['start_time'] ? date('Y-m-d H:i:s', $info['start_time']) : '',
$info['end_time'] ? date('Y-m-d H:i:s', $info['end_time']) : '',
];
if (!$auxiliaryList) {
return $info;
}
$productIds = array_unique(array_column($auxiliaryList, 'product_id'));
$uniques = array_unique(array_column($auxiliaryList, 'unique'));
$productList = app()->make(StoreProductServices::class)->search(['id' => $productIds])->column('store_name', 'id');
$uniqueList = app()->make(StoreProductAttrValueServices::class)->search(['unique' => $uniques])->column('unique,suk,stock,price,image', 'unique');
foreach ($auxiliaryList as &$item) {
$item['store_name'] = $productList[$item['product_id']] ?? '';
$item['suk'] = $uniqueList[$item['unique']]['suk'] ?? '';
$item['stock'] = $uniqueList[$item['unique']]['stock'] ?? '';
$item['price'] = $uniqueList[$item['unique']]['price'] ?? '';
$item['image'] = $uniqueList[$item['unique']]['image'] ?? '';
}
$info['product'] = $auxiliaryList;
return $info;
}
/**
* 删除
* @param $id
* @return mixed
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* User: liusl
* DateTime: 2025/5/12 09:45
*/
public function delete($id)
{
//删除礼品卡,
//删除礼品卡商品
//删除未使用的礼品卡卡密
$info = $this->dao->get($id);
if (!$info) {
throw new ValidateException('礼品卡不存在');
}
return $this->transaction(function () use ($id, $info) {
$res = $this->dao->update($id, ['is_del' => 1]);
$res = $res && app()->make(CardGiftAuxiliaryServices::class)->delete(['gift_id' => $id]);
$res = $res && app()->make(CardCodeServices::class)->update(['card_id' => $id, 'status' => 2], ['type' => 0, 'status' => 0, 'card_id' => 0]);
return !!$res;
});
}
/**
* 获取卡礼品树形结构列表
* @return array
*/
public function getTree()
{
return $this->search(['is_del' => 0])->field('id,name')->order('sort desc,add_time desc')->select()->toArray();
}
/**
* 使用数量矫正
* @return
* User: liusl
* DateTime: 2025/5/24 10:47
*/
public function allocationCardGift($id)
{
$info = $this->dao->get($id);
$used_num = app()->make(CardCodeServices::class)->search(['card_id' => $id, 'status' => 1])->count();
$info->used_num = $used_num;
$info->save();
return true;
}
}