permission[] = 'flowDraft';
$this->permission[] = 'flowAudit';
$this->permission[] = 'flowLog';
$this->permission[] = 'flowRead';
$this->permission[] = 'flowStep';
$this->permission[] = 'flowUser';
$this->permission[] = 'flowReturn';
$this->permission[] = 'flowRevise';
$this->permission[] = 'flowReset';
parent::__construct();
}
/**
* 流程审核
*/
public function flowAudit()
{
$gets = Request::all();
if (Request::method() == 'POST') {
$master = $gets['master'];
$keys = AES::decrypt($master['key'], config('app.key'));
list($bill_id, $id) = explode('.', $keys);
$bill = Bill::find($bill_id);
$models = ModelService::getModels($bill->model_id);
$model = $models[0];
if (intval($gets['step_next_id']) == 0) {
return $this->json('审批进程必须选择。');
}
// 获取审核用户
$step_user_ids = array_filter(explode(',', $gets['step_next_user']));
$run_id = $master['run_id'];
$step_id = $master['step_id'];
// 审批步骤数据
if ($run_id > 0) {
$step = RunStep::where('bill_id', $bill_id)
->where('run_id', $run_id)
->where('step_id', $step_id)
->first();
} else {
$step = Step::where('bill_id', $bill_id)
->where('type', 'start')
->first();
}
if (empty($step)) {
return $this->json('当前审批节点不存在。');
}
if ($run_id > 0) {
$step_next = RunStep::where('bill_id', $bill_id)
->where('run_id', $run_id)
->where('step_id', $gets['step_next_id'])
->first();
} else {
$step_next = Step::where('bill_id', $bill_id)
->where('id', $gets['step_next_id'])
->first(['*', 'id as step_id']);
}
if (empty($step_next)) {
return $this->json('转入审核节点不存在。');
}
if ($step_next['type'] == 'end') {
// 流程结束节点
$gets['step_next_type'] = 'end';
} else {
if (empty($step_user_ids)) {
return $this->json('审核人不能为空。');
}
}
// 执行模式
$run_mode = $step_next['run_mode'];
if ($run_mode == 1) {
if (count($step_user_ids) > 1) {
return $this->json('单人执行不能多个审核人。');
}
}
$gets['remark'] = trim($gets['remark']);
// 表单存在审核意见字段
if (isset($gets['step_remark'])) {
// 审核对话框没有填写审核意见
if ($gets['remark'] == '') {
$gets['remark'] = $gets['step_remark'][$step_id];
} else {
if (empty($gets['step_remark'][$step_id])) {
$gets['step_remark'][$step_id] = $gets['remark'];
}
}
} else {
if ($gets['remark'] != '') {
$gets['step_remark'][$step_id] = $gets['remark'];
}
}
// 转到步骤条件检查
if ($gets['step_next_type'] == 'next' || $gets['step_next_type'] == 'end') {
// 获取数据
if (intval($bill['form_type']) == 0) {
foreach($models as $model) {
if ($model['parent_id'] == 0) {
$gets[$model['table']] = DB::table($model['table'])->where('id', $id)->first();
} else {
$gets[$model['table']]['rows'] = DB::table($model['table'])->where($model['relation'], $id)->get()->toArray();
}
}
}
// 检查表单
$valid = Form::flowRules($models, $gets);
if ($valid['rules']) {
$v = Validator::make($gets, $valid['rules'], $valid['messages'], $valid['attributes']);
if ($v->fails()) {
$errors = $v->errors()->all();
return $this->json(join('
', $errors));
}
}
}
$gets['run_mode'] = $run_mode;
$gets['step_user_ids'] = $step_user_ids;
$step_next_inform = array_filter((array)$gets['step_next_inform']);
$notify_user_ids = array_keys($step_next_inform);
$notify_step_ids = array_values($step_next_inform);
$gets['step_next_inform'] = $step_next_inform;
$gets['notify_step_ids'] = $notify_step_ids;
$gets['notify_user_ids'] = $notify_user_ids;
// 保存数据
if ($bill['form_type'] == 1) {
$id = Form::store($bill, $models, $gets, $id, 'audit');
} else {
$id = Form::audit($bill, $models, $gets, $id);
}
$url = url($master['uri'].'/show', ['id' => $id, 'client' => $master['client']]);
return $this->json($bill['name'].'审核成功', $url);
}
$keys = AES::decrypt($gets['key'], config('app.key'));
list($bill_id, $id) = explode('.', $keys);
$bill = Bill::find($bill_id);
$model = ModelService::getModel($bill->model_id);
$run_id = $gets['run_id'];
$step_id = $gets['step_id'];
// 有办理记录
if ($run_id > 0) {
$run_step = RunStep::where('bill_id', $bill_id)
->where('run_id', $run_id)
->where('step_id', $step_id)
->first();
$join = explode(',', $run_step->join);
$run_steps = RunStep::where('bill_id', $bill_id)
->where('run_id', $run_id)
->where('option', 1)
->whereIn('step_id', $join)
->get();
} else {
$run_step = Step::where('bill_id', $bill_id)
->where('type', 'start')
->first();
$join = explode(',', $run_step->join);
$run_steps = Step::where('bill_id', $bill_id)
->where('option', 1)
->whereIn('id', $join)
->get(['*', 'id as step_id']);
}
return view('model/flowAudit', [
'run_step' => $run_step,
'run_steps' => $run_steps,
'table' => $model->table,
]);
}
/**
* 撤回流程
*/
public function recall()
{
$gets = Request::all();
if (Request::method() == 'POST') {
$auth = auth()->user();
$bill_id = $gets['bill_id'];
$data_id = $gets['data_id'];
$log_id = $gets['log_id'];
$remark = $gets['remark'];
if (trim($remark) == '') {
return $this->json('撤回原因必须填写');
}
$bill = Bill::find($bill_id);
$model = Model::find($bill->model_id);
// 单据生效后无法撤回
$data = DB::table($model['table'])->where('id', $data_id)->first();
if ($data['status'] == 1) {
return $this->json($bill->name.'['.$data['sn'].']已生效,无法撤回。');
}
// 撤回的节点
$log = RunLog::where('bill_id', $bill_id)
->where('id', $log_id)
->first();
// 当前流程实例运行id
$run_id = $log['run_id'];
$next_logs = RunLog::where('bill_id', $bill_id)
->where('run_id', $run_id)
->where('parent_id', $log_id)->get();
foreach ($next_logs as $next_log) {
// 已经办理无法撤回
if ($next_log['status'] == 1) {
return $this->json($bill->name.'['.$next_log['run_name'].']已办理,无法撤回。');
}
}
DB::beginTransaction();
try {
foreach ($next_logs as $next_log) {
if ($next_log['option'] > 0) {
$next_log['remark'] = $remark;
$next_log['run_status'] = 'recall';
$next_log['updated_id'] = $auth['id'];
$next_log['updated_by'] = $auth['name'];
$next_log['updated_at'] = time();
$next_log->save();
} else {
// 知会节点直接删除
$next_log->delete();
}
}
// 更新撤回节点数据
if ($log['parent_id'] > 0) {
// 不是开始节点更新所有节点
RunLog::where('bill_id', $bill_id)
->where('run_id', $run_id)
->where('parent_id', $log['parent_id'])
->update([
'status' => 0,
//'updated_id' => 0,
//'updated_at' => 0,
//'updated_by' => '',
]);
} else {
// 是开始节点只更新自己
$log->status = 0;
//$log->updated_id = 0;
//$log->updated_at = 0;
//$log->updated_by = '';
$log->save();
}
$status = $log['parent_id'] > 0 ? '-1' : '0';
DB::table($model['table'])
->where('id', $data_id)
->update([
'status' => $status,
]);
DB::commit();
} catch (\Exception $e) {
DB::rollback();
abort_error($bill->name.'撤回失败:'.$e->getMessage());
}
return $this->json($bill->name.'流程撤回成功', true);
}
$keys = AES::decrypt($gets['key'], config('app.key'));
list($bill_id, $data_id) = explode('.', $keys);
$log_id = $gets['log_id'];
return view('model/recall', [
'bill_id' => $bill_id,
'data_id' => $data_id,
'log_id' => $log_id,
]);
}
/**
* 弃审流程
*/
public function abort()
{
$gets = Request::all();
if (Request::method() == 'POST') {
$bill_id = $gets['bill_id'];
$data_id = $gets['data_id'];
$remark = $gets['remark'];
if ($remark == '') {
return $this->json('弃审原因必须填写');
}
$bill = Bill::find($bill_id);
$model = Model::find($bill->model_id);
$run = Run::where('bill_id', $bill_id)->where('data_id', $data_id)->first();
$data = DB::table($model->table)->find($data_id);
if (empty($data)) {
return $this->json('流程任务不存在。');
}
DB::beginTransaction();
try {
Hook::fire($model->table.'.onBeforeAbort', ['data' => $data, 'table' => $model->table, 'id' => $data_id]);
// 获取结束节点
$logs = RunLog::where('run_id', $run->id)
->where('bill_id', $bill_id)
->where('run_status', 'end')
->get();
if ($logs->isEmpty()) {
return $this->json('流程无结束节点无法弃审。');
}
// 删除结束节点前下一步节点(主要是知会节点)
RunLog::where('run_id', $run->id)
->where('bill_id', $bill_id)
->whereIn('parent_id', $logs->pluck('id'))
->delete();
foreach ($logs as $log) {
$log->run_status = 'draft';
$log->status = 0;
//$log->updated_at = 0;
//$log->updated_id = 0;
//$log->updated_by = '';
$log->remark = $remark;
$log->save();
}
Run::where('bill_id', $bill_id)->where('data_id', $data_id)
->update([
'actived_at' => 0,
'actived_id' => 0,
'actived_by' => ''
]);
DB::table($model->table)
->where('id', $data_id)
->update([
'status' => '2',
]);
DB::commit();
return $this->json($bill->name.'流程弃审成功', true);
} catch (\Exception $e) {
DB::rollback();
abort_error($bill->name.'弃审:'.$e->getMessage());
}
}
$keys = AES::decrypt($gets['key'], config('app.key'));
list($bill_id, $data_id) = explode('.', $keys);
return view('model/abort', [
'bill_id' => $bill_id,
'data_id' => $data_id,
]);
}
/**
* 标记已阅读
*/
public function flowRead()
{
if (Request::method() == 'POST') {
$gets = Request::get('master');
if ($gets['run_log_id']) {
RunLog::where('id', $gets['run_log_id'])->update(['status' => 1, 'run_status' => 'read']);
}
return $this->json('阅读成功', true);
}
}
/**
* 流程清除重置
*/
public function flowReset()
{
if (Request::method() == 'POST') {
$master = Request::get('master');
$keys = AES::decrypt($master['key'], config('app.key'));
list($bill_id, $id) = explode('.', $keys);
$bill = Bill::find($bill_id);
$model = ModelService::getModel($bill->model_id);
if ($master['run_id']) {
DB::beginTransaction();
try {
Run::where('id', $master['run_id'])->delete();
RunStep::where('run_id', $master['run_id'])->delete();
RunLog::where('run_id', $master['run_id'])->delete();
DB::table($model->table)->where('id', $id)->update(['status' => 0]);
DB::commit();
return $this->json('流程重置成功。', true);
} catch (\Exception $e) {
DB::rollBack();
return $this->json($e->getMessage());
}
}
}
}
/**
* 保存草稿
*/
public function flowDraft()
{
$gets = Request::all();
$master = $gets['master'];
$keys = AES::decrypt($master['key'], config('app.key'));
list($bill_id, $id) = explode('.', $keys);
$bill = Bill::find($bill_id);
$models = ModelService::getModels($bill->model_id);
if (Request::method() == 'POST') {
// 检查表单
$valid = Form::flowRules($models, $gets);
if ($valid['rules']) {
$v = Validator::make($gets, $valid['rules'], $valid['messages'], $valid['attributes']);
if ($v->fails()) {
$errors = $v->errors()->all();
return $this->json(join('
', $errors));
}
}
// 保存草稿
$id = Form::store($bill, $models, $gets, $id);
// 保存草稿跳转到编辑界面
if ($bill['audit_type'] == 1 && $bill['form_type'] == 1) {
$uri = $master['uri'].'/audit';
} else {
$uri = $master['uri'].'/show';
}
// 保存草稿跳转到编辑界面
$url = url($uri, ['id' => $id, 'client' => $master['client']]);
return $this->json($bill['name'].'保存成功。', $url);
}
}
/**
* 获取办理步骤
*/
public function flowStep()
{
$gets = Request::all();
$master = $gets['master'];
$keys = AES::decrypt($master['key'], config('app.key'));
list($bill_id, $id) = explode('.', $keys);
$type = $gets['step_next_type'];
$bill_id = $master['bill_id'];
$run_id = $master['run_id'];
$step_id = $master['step_id'];
$run_log_id = $master['run_log_id'];
$bill = Bill::find($bill_id);
$model = Model::where('id', $bill->model_id)->first();
$auth = auth()->user();
$table = $model->table;
if ($bill['form_type'] == 1) {
$data = $gets[$table];
} else {
$data = DB::table($table)->where('id', $master['id'])->first();
$gets[$table] = $data;
}
$gets['master']['table'] = $table;
$gets['master']['auth'] = $auth;
// 有办理记录
if ($run_id > 0) {
$run_step = RunStep::where('bill_id', $bill_id)
->where('run_id', $run_id)
->where('step_id', $step_id)
->first();
// 获取本流程所有节点
$steps = RunStep::where('bill_id', $bill_id)
->where('run_id', $run_id)
->get()->keyBy('step_id')->toArray();
} else {
// 新建表单
$run_step = Step::where('bill_id', $bill_id)
->where('type', 'start')
->first(['*', 'id as step_id']);
// 获取本流程所有节点
$steps = Step::where('bill_id', $bill_id)
->get(['*', 'id as step_id'])
->keyBy('step_id')->toArray();
}
$log = RunLog::where('id', $run_log_id)->first();
$next_steps = [];
switch ($type) {
case 'next':
$next_steps = StepService::getNextSteps($steps, $run_step['step_id'], $gets);
break;
case 'back':
$next_steps = StepService::getBackSteps($steps, $run_step['step_id'], $gets);
break;
}
$modes = [
1 => '单人执行',
2 => '多人执行',
3 => '全体执行',
4 => '竞争执行',
];
$tree_steps = array_nest($next_steps);
$tpl = '';
$inform_text = '请您及时办理由'.$auth->name.'转交的'.$model['name'].'('.$data['sn'].')。';
$step_ids = $informs = $users = $inform_sms = [];
if (not_empty($tree_steps)) {
$notify_user_ids = [];
$notify_step_ids = [];
foreach ($tree_steps as $tree_step) {
if ($type == 'back') {
} else {
if ($tree_step['option'] == 0) {
$parent_id = $tree_step['parent'][0];
$user_ids = $tree_step['user_ids'];
if (not_empty($user_ids)) {
$notify_user_ids[$parent_id] = array_merge((array)$notify_user_ids[$parent_id], $user_ids);
$notify_step_ids[$parent_id][$tree_step['step_id']] = join(',', $user_ids);
}
}
}
}
$index = 0;
foreach ($tree_steps as $step) {
if ($step['hide']) {
continue;
}
if ($step['option'] == 1) {
$name = 'step_next_id';
$step['name'] = $step['type'] == 'end' ? $step['name'] : $step['name'].' '.$modes[$step['run_mode']].'';
$tpl .= '