You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
289 lines
8.7 KiB
289 lines
8.7 KiB
<?php
|
|
// +----------------------------------------------------------------------
|
|
// | Niucloud-admin 企业快速开发的多应用管理平台
|
|
// +----------------------------------------------------------------------
|
|
// | 官方网址:https://www.niucloud.com
|
|
// +----------------------------------------------------------------------
|
|
// | niucloud团队 版权所有 开源版本可自由商用
|
|
// +----------------------------------------------------------------------
|
|
// | Author: Niucloud Team
|
|
// +----------------------------------------------------------------------
|
|
|
|
namespace app\service\admin\contract;
|
|
|
|
use app\model\contract\Contract;
|
|
use app\model\contract\ContractSign;
|
|
use app\model\personnel\Personnel;
|
|
use app\model\member\Member;
|
|
use core\base\BaseAdminService;
|
|
use think\facade\Db;
|
|
|
|
/**
|
|
* 合同分发服务类
|
|
* Class ContractDistributionService
|
|
* @package app\service\admin\contract
|
|
*/
|
|
class ContractDistributionService extends BaseAdminService
|
|
{
|
|
public function __construct()
|
|
{
|
|
parent::__construct();
|
|
$this->model = new ContractSign();
|
|
}
|
|
|
|
/**
|
|
* 手动分发合同
|
|
* @param int $contractId 合同ID
|
|
* @param array $personnelIds 人员ID数组
|
|
* @param int $type 人员类型:1内部员工,2外部会员
|
|
* @return bool
|
|
*/
|
|
public function manualDistribute(int $contractId, array $personnelIds, int $type = 1): bool
|
|
{
|
|
// 验证合同是否存在
|
|
$contract = (new Contract())->find($contractId);
|
|
if (!$contract) {
|
|
throw new \Exception('合同不存在');
|
|
}
|
|
|
|
if (empty($personnelIds)) {
|
|
throw new \Exception('人员列表不能为空');
|
|
}
|
|
|
|
// 验证人员是否存在
|
|
$this->validatePersonnel($personnelIds, $type);
|
|
|
|
// 开启事务
|
|
Db::startTrans();
|
|
try {
|
|
foreach ($personnelIds as $personnelId) {
|
|
// 检查是否已经分发过
|
|
$exists = $this->model->where([
|
|
['contract_id', '=', $contractId],
|
|
['personnel_id', '=', $personnelId],
|
|
['type', '=', $type]
|
|
])->findOrEmpty();
|
|
|
|
if (!$exists->isEmpty()) {
|
|
continue; // 跳过已分发的
|
|
}
|
|
|
|
$data = [
|
|
'contract_id' => $contractId,
|
|
'personnel_id' => $personnelId,
|
|
'type' => $type,
|
|
'status' => 'pending',
|
|
'source_type' => 'manual',
|
|
'source_id' => null,
|
|
'created_at' => time()
|
|
];
|
|
|
|
$this->model->create($data);
|
|
}
|
|
|
|
Db::commit();
|
|
return true;
|
|
} catch (\Exception $e) {
|
|
Db::rollback();
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 自动分发合同(课程购买触发)
|
|
* @param int $contractId 合同ID
|
|
* @param int $memberId 会员ID
|
|
* @param int $sourceId 来源ID(如课程ID、订单ID)
|
|
* @param string $sourceType 来源类型
|
|
* @return bool
|
|
*/
|
|
public function autoDistribute(int $contractId, int $memberId, int $sourceId, string $sourceType = 'auto_course'): bool
|
|
{
|
|
// 验证合同是否存在
|
|
$contract = (new Contract())->find($contractId);
|
|
if (!$contract) {
|
|
throw new \Exception('合同不存在');
|
|
}
|
|
|
|
// 验证会员是否存在
|
|
$member = (new Member())->find($memberId);
|
|
if (!$member) {
|
|
throw new \Exception('会员不存在');
|
|
}
|
|
|
|
// 检查是否已经分发过
|
|
$exists = $this->model->where([
|
|
['contract_id', '=', $contractId],
|
|
['personnel_id', '=', $memberId],
|
|
['type', '=', 2], // 外部会员
|
|
['source_type', '=', $sourceType],
|
|
['source_id', '=', $sourceId]
|
|
])->findOrEmpty();
|
|
|
|
if (!$exists->isEmpty()) {
|
|
return true; // 已分发过,直接返回成功
|
|
}
|
|
|
|
$data = [
|
|
'contract_id' => $contractId,
|
|
'personnel_id' => $memberId,
|
|
'type' => 2, // 外部会员
|
|
'status' => 'pending',
|
|
'source_type' => $sourceType,
|
|
'source_id' => $sourceId,
|
|
'created_at' => time()
|
|
];
|
|
|
|
$result = $this->model->create($data);
|
|
return !empty($result);
|
|
}
|
|
|
|
/**
|
|
* 批量分发合同
|
|
* @param array $distributions 分发配置数组
|
|
* @return bool
|
|
*/
|
|
public function batchDistribute(array $distributions): bool
|
|
{
|
|
if (empty($distributions)) {
|
|
throw new \Exception('分发配置不能为空');
|
|
}
|
|
|
|
Db::startTrans();
|
|
try {
|
|
foreach ($distributions as $distribution) {
|
|
$contractId = $distribution['contract_id'] ?? 0;
|
|
$personnelIds = $distribution['personnel_ids'] ?? [];
|
|
$type = $distribution['type'] ?? 1;
|
|
|
|
if ($contractId && !empty($personnelIds)) {
|
|
$this->manualDistribute($contractId, $personnelIds, $type);
|
|
}
|
|
}
|
|
|
|
Db::commit();
|
|
return true;
|
|
} catch (\Exception $e) {
|
|
Db::rollback();
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取分发记录列表
|
|
* @param array $where 查询条件
|
|
* @return array
|
|
*/
|
|
public function getDistributionList(array $where = []): array
|
|
{
|
|
$field = 'id, contract_id, personnel_id, type, status, source_type, source_id, created_at, sign_time, signature_image';
|
|
$order = 'created_at desc';
|
|
|
|
$search_model = $this->model
|
|
->withSearch(['contract_id', 'personnel_id', 'type', 'status', 'source_type'], $where)
|
|
->field($field)
|
|
->order($order);
|
|
|
|
$list = $this->pageQuery($search_model, $where);
|
|
|
|
// 关联合同和人员信息
|
|
if (!empty($list['data'])) {
|
|
$this->attachRelationInfo($list['data']);
|
|
}
|
|
|
|
return $list;
|
|
}
|
|
|
|
/**
|
|
* 取消分发
|
|
* @param int $id 分发记录ID
|
|
* @return bool
|
|
*/
|
|
public function cancelDistribution(int $id): bool
|
|
{
|
|
$info = $this->model->find($id);
|
|
if (!$info) {
|
|
throw new \Exception('分发记录不存在');
|
|
}
|
|
|
|
if ($info['status'] === 'signed') {
|
|
throw new \Exception('已签署的合同不能取消分发');
|
|
}
|
|
|
|
$result = $info->delete();
|
|
return !empty($result);
|
|
}
|
|
|
|
/**
|
|
* 验证人员是否存在
|
|
* @param array $personnelIds 人员ID数组
|
|
* @param int $type 人员类型
|
|
* @throws \Exception
|
|
*/
|
|
private function validatePersonnel(array $personnelIds, int $type): void
|
|
{
|
|
if ($type === 1) {
|
|
// 内部员工
|
|
$count = (new Personnel())->whereIn('id', $personnelIds)->count();
|
|
} else {
|
|
// 外部会员
|
|
$count = (new Member())->whereIn('id', $personnelIds)->count();
|
|
}
|
|
|
|
if ($count !== count($personnelIds)) {
|
|
throw new \Exception('部分人员不存在');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 关联合同和人员信息
|
|
* @param array $list 分发记录列表
|
|
*/
|
|
private function attachRelationInfo(array &$list): void
|
|
{
|
|
// 获取合同信息
|
|
$contractIds = array_unique(array_column($list, 'contract_id'));
|
|
$contracts = (new Contract())->whereIn('id', $contractIds)->column('name', 'id');
|
|
|
|
// 获取人员信息
|
|
$personnelData = $this->getPersonnelInfo($list);
|
|
|
|
foreach ($list as &$item) {
|
|
$item['contract_name'] = $contracts[$item['contract_id']] ?? '';
|
|
$item['personnel_name'] = $personnelData[$item['type']][$item['personnel_id']] ?? '';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取人员信息
|
|
* @param array $list 分发记录列表
|
|
* @return array
|
|
*/
|
|
private function getPersonnelInfo(array $list): array
|
|
{
|
|
$personnelData = [1 => [], 2 => []];
|
|
|
|
// 分类收集人员ID
|
|
$staffIds = [];
|
|
$memberIds = [];
|
|
foreach ($list as $item) {
|
|
if ($item['type'] === 1) {
|
|
$staffIds[] = $item['personnel_id'];
|
|
} else {
|
|
$memberIds[] = $item['personnel_id'];
|
|
}
|
|
}
|
|
|
|
// 查询员工信息
|
|
if (!empty($staffIds)) {
|
|
$personnelData[1] = (new Personnel())->whereIn('id', array_unique($staffIds))->column('name', 'id');
|
|
}
|
|
|
|
// 查询会员信息
|
|
if (!empty($memberIds)) {
|
|
$personnelData[2] = (new Member())->whereIn('id', array_unique($memberIds))->column('nickname', 'id');
|
|
}
|
|
|
|
return $personnelData;
|
|
}
|
|
}
|
|
|