ts
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
namespace app\common\utils\approval\service\traits;
|
||||
|
||||
use support\Db;
|
||||
use support\exception\BusinessException;
|
||||
|
||||
trait ApprovalTransferTrait
|
||||
{
|
||||
/** 查看某个实例的转交流水(按时间升序) */
|
||||
public function listTransfers(int $instanceId): array
|
||||
{
|
||||
$rows = Db::table('approval_transfers')
|
||||
->where('instance_id', $instanceId)
|
||||
->orderBy('id', 'asc')
|
||||
->get()
|
||||
->toArray();
|
||||
|
||||
return array_map(function($r){
|
||||
return [
|
||||
'id' => (int)$r->id,
|
||||
'instance_id' => (int)$r->instance_id,
|
||||
'step_index' => (int)$r->step_index,
|
||||
'record_id' => (int)$r->record_id,
|
||||
'from_user_id' => (int)$r->from_user_id,
|
||||
'to_user_id' => (int)$r->to_user_id,
|
||||
'reason' => $r->reason,
|
||||
'created_at' => $r->created_at,
|
||||
];
|
||||
}, $rows);
|
||||
}
|
||||
|
||||
/** 转交当前待办给他人 */
|
||||
public function transferApproval(
|
||||
int $instanceId,
|
||||
int $stepIndex,
|
||||
int $fromUserId,
|
||||
int $toUserId,
|
||||
string $reason = '',
|
||||
?string $userNameColumn = null
|
||||
): array {
|
||||
if ($fromUserId === $toUserId) {
|
||||
return ['status' => 'noop', 'msg' => '目标与来源相同,无需转交'];
|
||||
}
|
||||
|
||||
return \support\Db::transaction(function () use ($instanceId, $stepIndex, $fromUserId, $toUserId, $reason, $userNameColumn) {
|
||||
// 锁实例,避免并发推进
|
||||
$instance = Db::table('approval_instances')->where('id', $instanceId)->lockForUpdate()->first();
|
||||
if (!$instance) throw new BusinessException('审批实例未找到');
|
||||
if ($instance->status !== 'processing') throw new BusinessException('流程非进行中,无法转交');
|
||||
|
||||
// 锁定来源人的 pending 记录
|
||||
$record = Db::table('approval_records')
|
||||
->where('instance_id', $instanceId)
|
||||
->where('round', (int)$instance->round)
|
||||
->where('step_index', $stepIndex)
|
||||
->where('approver_id', $fromUserId)
|
||||
->where('status', 'pending')
|
||||
->lockForUpdate()
|
||||
->first();
|
||||
if (!$record) throw new BusinessException('未找到可转交的待办或已处理');
|
||||
|
||||
$now = date('Y-m-d H:i:s');
|
||||
|
||||
// 若目标已有 pending:合并(本记录置为 skipped)
|
||||
$target = Db::table('approval_records')
|
||||
->where('instance_id', $instanceId)
|
||||
->where('round', (int)$instance->round)
|
||||
->where('step_index', $stepIndex)
|
||||
->where('approver_id', $toUserId)
|
||||
->where('status', 'pending')
|
||||
->lockForUpdate()
|
||||
->first();
|
||||
|
||||
if ($target) {
|
||||
Db::table('approval_records')->where('id', $record->id)->update([
|
||||
'status' => 'skipped',
|
||||
'approved_at' => $now,
|
||||
'updated_at' => $now,
|
||||
'comment' => trim(($record->comment ?? '')."\n[转交给 {$toUserId},目标已有待办,已合并]"),
|
||||
]);
|
||||
$effectiveRecordId = (int)$target->id;
|
||||
} else {
|
||||
// 原地替换 approver_id
|
||||
Db::table('approval_records')->where('id', $record->id)->update([
|
||||
'approver_id' => $toUserId,
|
||||
'updated_at' => $now,
|
||||
'comment' => trim(($record->comment ?? '')."\n[自 {$fromUserId} 转交]"),
|
||||
]);
|
||||
$effectiveRecordId = (int)$record->id;
|
||||
}
|
||||
|
||||
// 组织“转交来源/原因”文案(优先姓名)
|
||||
$fromLabel = (string)$fromUserId;
|
||||
$toLabel = (string)$toUserId;
|
||||
if ($userNameColumn) {
|
||||
$fromName = Db::table('user')->where('id', $fromUserId)->value($userNameColumn);
|
||||
$toName = Db::table('user')->where('id', $toUserId)->value($userNameColumn);
|
||||
if ($fromName) $fromLabel = $fromName;
|
||||
if ($toName) $toLabel = $toName;
|
||||
}
|
||||
$note = "【转交】{$fromLabel} → {$toLabel}";
|
||||
$r = trim($reason);
|
||||
if ($r !== '') $note .= ",原因:{$r}";
|
||||
|
||||
// 通知被转交人(在内容里追加 note)
|
||||
$this->sendNotification([$toUserId], (object)[
|
||||
'id' => (int)$instance->id,
|
||||
'flow_type' => (string)$instance->flow_type,
|
||||
'biz_type' => (string)$instance->biz_type,
|
||||
'biz_id' => (string)$instance->biz_id,
|
||||
'initiator_id' => (int)$instance->initiator_id,
|
||||
'form_data' => $instance->form_data,
|
||||
], 'pending', false, ['note' => $note]);
|
||||
|
||||
// 记转交流水
|
||||
Db::table('approval_transfers')->insert([
|
||||
'instance_id' => (int)$instanceId,
|
||||
'step_index' => (int)$stepIndex,
|
||||
'record_id' => $effectiveRecordId,
|
||||
'from_user_id' => (int)$fromUserId,
|
||||
'to_user_id' => (int)$toUserId,
|
||||
'reason' => $reason,
|
||||
'created_at' => $now,
|
||||
]);
|
||||
|
||||
$this->pushTodoChanged([$fromUserId, $toUserId]);
|
||||
return ['status' => 'ok', 'record_id' => $effectiveRecordId];
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user