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' => 1, 'source_type' => 'manual', 'source_id' => null ]; $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; } }