允许流转到的目标状态 * issued / reject / cancel 为终态 * @var array */ protected $statusFlow = [ 'wait' => ['issued', 'reject'], ]; public function _initialize() { parent::_initialize(); $this->model = new \app\admin\model\Invoice; $this->view->assign("typeList", $this->model->getTypeList()); $this->view->assign("titleTypeList", $this->model->getTitleTypeList()); $this->view->assign("statusList", $this->model->getStatusList()); } /** * 开票申请列表:关联申请人/商户 */ public function index() { $this->request->filter(['strip_tags', 'trim']); if (false === $this->request->isAjax()) { return $this->view->fetch(); } if ($this->request->request('keyField')) { return $this->selectpage(); } [$where, $sort, $order, $offset, $limit] = $this->buildparams(); $list = $this->model ->with(['user', 'merchant']) ->where($where) ->order($sort, $order) ->paginate($limit); $result = ['total' => $list->total(), 'rows' => $list->items()]; return json($result); } /** * 详情回看(复用 edit 只读视图) */ public function detail($ids = null) { $row = $this->model->with(['user', 'merchant'])->where('invoice.id', (int)$ids)->find(); if (!$row) { $this->error(__('No Results were found')); } $linkedOrders = InvoiceService::fetchLinkedOrders((string)$row['order_ids'], (int)$row['id']); $this->view->assign('row', $row); $this->view->assign('linkedOrders', $linkedOrders); $this->view->assign('flowOptions', []); return $this->view->fetch('edit'); } /** * 财务开票处理:申请信息只读,仅允许填写开票结果与上传电子发票文件 */ public function edit($ids = null) { $row = $this->model->with(['user', 'merchant'])->where('invoice.id', (int)$ids)->find(); if (!$row) { $this->error(__('No Results were found')); } if (false === $this->request->isPost()) { $linkedOrders = InvoiceService::fetchLinkedOrders((string)$row['order_ids'], (int)$row['id']); $this->view->assign('row', $row); $this->view->assign('linkedOrders', $linkedOrders); $this->view->assign('flowOptions', $this->statusFlow[$row['status']] ?? []); return $this->view->fetch(); } $status = (string)$this->request->post('row.status'); $invoiceCode = trim((string)$this->request->post('row.invoice_code')); $invoiceNo = trim((string)$this->request->post('row.invoice_no')); $invoiceFile = trim((string)$this->request->post('row.invoice_file')); $auditMsg = trim((string)$this->request->post('row.audit_msg')); if (!isset($this->statusFlow[$row['status']])) { $this->error('该开票申请已处理或已撤回,不允许再次变更'); } if (!in_array($status, $this->statusFlow[$row['status']], true)) { $this->error('状态流转不合法,请刷新后重试'); } if ($status === 'issued' && $invoiceNo === '') { $this->error('标记开票完成必须填写发票号码'); } if ($status === 'reject' && $auditMsg === '') { $this->error('驳回时必须填写驳回原因'); } $now = time(); Db::startTrans(); try { $updateData = [ 'status' => $status, 'invoice_code' => $invoiceCode !== '' ? mb_substr($invoiceCode, 0, 50) : $row['invoice_code'], 'invoice_no' => $invoiceNo !== '' ? mb_substr($invoiceNo, 0, 50) : $row['invoice_no'], 'invoice_file' => $invoiceFile !== '' ? mb_substr($invoiceFile, 0, 500) : $row['invoice_file'], 'audit_msg' => mb_substr($auditMsg, 0, 255), 'updatetime' => $now, ]; if ($status === 'issued') { $updateData['issue_time'] = $now; } // 乐观锁更新状态,防止并发重复处理 $affected = Db::name('invoice') ->where('id', $row['id']) ->where('status', $row['status']) ->update($updateData); if (!$affected) { throw new \Exception('开票申请状态已被其他人变更,请刷新后重试'); } if ($status === 'issued') { InvoiceService::markInvoiceOrdersIssued((int)$row['id'], (string)$row['order_ids'], $now); $msgBody = '您申请的发票 ¥' . number_format((float)$row['amount'], 2, '.', '') . ' 已开具完成,发票号码:' . $invoiceNo; if ($invoiceFile !== '') { $msgBody .= ',您可在「开具发票 - 开票记录」中在线预览或下载电子发票'; } if (!empty($row['email'])) { $msgBody .= '(接收邮箱:' . $row['email'] . ')'; } $this->sendUserMessage((int)$row['user_id'], '发票已开具', $msgBody); } else { InvoiceService::releaseInvoiceOrders((int)$row['id'], (string)$row['order_ids'], $now); $this->sendUserMessage( (int)$row['user_id'], '开票申请已驳回', '您的开票申请 ¥' . number_format((float)$row['amount'], 2, '.', '') . ' 未通过审核:' . ($auditMsg !== '' ? $auditMsg : '请核对开票信息后重新提交') ); } Db::commit(); } catch (PDOException|\Exception $e) { Db::rollback(); $this->error($e->getMessage()); } $this->success(); } /** * 开票申请仅由用户/商户端发起,禁止后台手工添加 */ public function add() { $this->error('开票申请仅支持用户/商户端发起,后台不可手动添加'); } /** * 开票记录禁止删除,保障开票额度统计与账务完整 */ public function del($ids = null) { $this->error('开票申请记录禁止删除'); } /** * 禁止批量修改状态,必须逐单填写开票结果 */ public function multi($ids = null) { $this->error('开票处理不支持批量操作,请逐单填写发票号后处理'); } /** * 向申请人发送站内消息 */ protected function sendUserMessage($userId, $title, $content) { if (!$userId) { return; } Db::name('message')->insert([ 'receive_type' => 'user', 'receive_id' => (int)$userId, 'type' => 'system', 'title' => mb_substr((string)$title, 0, 100), 'content' => mb_substr((string)$content, 0, 500), 'order_id' => 0, 'is_read' => 0, 'createtime' => time(), ]); } }