diff --git a/app/admin/controller/StockOrdersController.php b/app/admin/controller/StockOrdersController.php index 39806a5..47e694a 100644 --- a/app/admin/controller/StockOrdersController.php +++ b/app/admin/controller/StockOrdersController.php @@ -81,19 +81,22 @@ class StockOrdersController extends BaseController if (!isset($groupedFiles[$file['file_code']])) { $groupedFiles[$file['file_code']] = []; } - $groupedFiles[$file['file_code']][] = $file['file_url']; + $groupedFiles[$file['file_code']][] = [ + 'url' => $file['file_url'], + 'original_name' => $file['original_name'] + ]; } // 映射到对应字段 foreach ($fileTypes as $field => $fileCode) { if (isset($groupedFiles[$fileCode])) { - // 原始URL数组 + // 文件信息数组,包含url和original_name $data[$field] = $groupedFiles[$fileCode]; // 完整URL数组 $fullUrls = []; - foreach ($groupedFiles[$fileCode] as $url) { - $fullUrls[] = (new \app\common\service\OssService)->generatePrivateUrl($url); + foreach ($groupedFiles[$fileCode] as $fileInfo) { + $fullUrls[] = (new \app\common\service\OssService)->generatePrivateUrl($fileInfo['url']); } $data[$field . '_url'] = $fullUrls; } diff --git a/app/admin/controller/SysConfigController.php b/app/admin/controller/SysConfigController.php new file mode 100644 index 0000000..3534079 --- /dev/null +++ b/app/admin/controller/SysConfigController.php @@ -0,0 +1,48 @@ +service = new SysConfigService(); + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + protected function indexFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + return $data; + } + + /** + * 数据格式化 + * + * @param array $data + * @return array + */ + protected function showFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + return $data; + } +} \ No newline at end of file diff --git a/app/admin/controller/UserController.php b/app/admin/controller/UserController.php index 8c24c6c..e9ef8d4 100644 --- a/app/admin/controller/UserController.php +++ b/app/admin/controller/UserController.php @@ -118,6 +118,11 @@ class UserController extends BaseController $data['system_ids'][] = $system['id']; } } + if ($data['reportToInfo']) { + $data['report_to_name'] = $data['reportToInfo']['id'] == $data['id'] ? '/' : $data['reportToInfo']['name']; + } else { + $data['report_to_name'] = '-'; + } return $data; } diff --git a/app/admin/controller/dashboard/FinStatisticsController.php b/app/admin/controller/dashboard/FinStatisticsController.php new file mode 100644 index 0000000..95cf09d --- /dev/null +++ b/app/admin/controller/dashboard/FinStatisticsController.php @@ -0,0 +1,48 @@ +',0); + + $result = []; + //已认领数量 + $result['claimed_num'] = $query->count(); + //已认领金额 + $result['claimed_amount'] = $query->sum('amount'); + + //未入账数量 + $result['unreceived_num'] = FinReceipt::whereNull('received_at')->count(); + //未入账金额 + $result['unreceived_amount'] = FinReceipt::whereNull('received_at')->sum('amount'); + + $query = FinReceipt::whereNull('payment_apply_id'); + + //未认领数量 + $result['unclaimed_num'] = $query->count(); + //未认领金额 + $result['unclaimed_amount'] = $query->sum('amount'); + + //已超时未认领数量 + $result['timeout'] = $query->where('created_at','<',time()-24*3600)->count(); + + return $this->success($result); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + } + +} \ No newline at end of file diff --git a/app/admin/controller/dashboard/OfficeClerkController.php b/app/admin/controller/dashboard/OfficeClerkController.php new file mode 100644 index 0000000..463a874 --- /dev/null +++ b/app/admin/controller/dashboard/OfficeClerkController.php @@ -0,0 +1,182 @@ +where('approver_id', $request->user->uid) + ->where('status', 'approved') + ->count('id'); + + $pending = Db::table('approval_records') + ->where('approver_id', $request->user->uid) + ->where('status', 'pending') + ->count('id'); + + $unclaimed = Db::table('fin_payment_apply') + ->where('doc_user_id', $request->user->uid) + ->where('receipt_id', 0) + ->count('id'); + + $claimed = Db::table('fin_payment_apply') + ->where('doc_user_id', $request->user->uid) + ->where('receipt_id', '>', 0) + ->count('id'); + + $twentyFourHoursAgo = time() - (24 * 3600); + $timeout = Db::table('fin_payment_apply') + ->where('doc_user_id', $request->user->uid) + ->where('fin_payment_apply.submit_files', '') + ->where('receipt_id', '>', 0) + ->where('claimed_at', '<', $twentyFourHoursAgo) + ->count('id'); + + return $this->success([ + 'approved' => $approved, + 'pending' => $pending, + 'unclaimed' => $unclaimed, + 'claimed' => $claimed, + 'timeout' => $timeout + ]); + } + + // 曲线 + public function curve(Request $request) + { + $groupId = Db::table('user_group_members as ugm') + ->join('user_group as ug', 'ugm.group_id', '=', 'ug.id') + ->where('ugm.user_id', $request->user->uid) + ->where('ugm.is_leader', 1) + ->where('ugm.status', 1) + ->where('ug.scenario_code', 'stock_orders') + ->where('ug.status', 1) + ->value('ug.id'); + $userIds = Db::table('user_group_members') + ->where('group_id', $groupId) + ->pluck('user_id'); + $list = Db::table('stock_orders') + ->join('user', 'stock_orders.salesperson_id', '=', 'user.id') + ->whereIn('stock_orders.salesperson_id', $userIds) + ->whereIn('stock_orders.approval_status', [0, 1, 2]) + ->whereNull('stock_orders.deleted_at') + ->groupBy('stock_orders.salesperson_id', 'user.name') + ->selectRaw('user.name, count(*) as count') + ->pluck('count', 'name') + ->toArray(); + $optionType = []; + $counts = []; + foreach ($list as $key=>$val) { + $optionType[] = $key; + $counts[] = $val; + } + $arr = [ + "optionType" => $optionType, + "counts" => $counts + ]; + return $this->success($arr); + } + + // 审批 + public function approval(Request $request) + { + $list = Db::table('approval_records as ar') + ->join('approval_instances as ai', 'ar.instance_id', '=', 'ai.id') + ->join('stock_orders as so', 'ai.biz_id', '=', 'so.id') + ->where('ar.approver_id', $request->user->uid) + ->where('ar.status', 'pending') + ->where('ai.flow_type', 'stock_orders') + ->where('ai.biz_type', 'stock_orders') + ->where('ai.status', 'processing') + ->whereNull('so.deleted_at') + ->select( + 'so.order_no', + 'ai.created_at as approval_created_at', + 'so.salesperson_snapshot as salesperson_name' + ) + ->get() + ->map(function($item) { + return [ + 'order_no' => $item->order_no, + 'approval_created_at' => date('Y-m-d H:i:s', strtotime($item->approval_created_at)), // 格式化时间 + 'salesperson_name' => $item->salesperson_name + ]; + }) + ->toArray(); + return $this->success($list); + } + + // 认领 + public function claim(Request $request) + { + $type = $request->get('type'); + if ($type == 'unclaimed') { + $list = Db::table('fin_payment_apply') + ->join('sys_currency', 'fin_payment_apply.currency_id', '=', 'sys_currency.id') + ->where('fin_payment_apply.doc_user_id', $request->user->uid) + ->where('fin_payment_apply.receipt_id', 0) + ->get([ + 'fin_payment_apply.id', + 'fin_payment_apply.created_at', + 'fin_payment_apply.doc_user_id', + 'fin_payment_apply.payment_entity', + 'fin_payment_apply.payment_account', + 'fin_payment_apply.currency_id', + 'sys_currency.currency_name', + 'fin_payment_apply.amount', + 'fin_payment_apply.apply_no' + ]); + foreach ($list as $key => &$val) { + $val->created_at = date('Y-m-d H:i:s', $val->created_at); + } + unset($val); + } else { + $twentyFourHoursAgo = time() - (24 * 3600); + $list = Db::table('fin_payment_apply') + ->join('user', 'fin_payment_apply.doc_user_id', '=', 'user.id') + ->join('sys_currency', 'fin_payment_apply.currency_id', '=', 'sys_currency.id') + ->where('fin_payment_apply.doc_user_id', $request->user->uid) + ->where('fin_payment_apply.submit_files', '') + ->where('fin_payment_apply.receipt_id', '>', 0) + ->where('fin_payment_apply.claimed_at', '<', $twentyFourHoursAgo) + ->get([ + 'fin_payment_apply.id', + 'fin_payment_apply.created_at', + 'fin_payment_apply.doc_user_id', + 'user.name', + 'fin_payment_apply.payment_entity', + 'fin_payment_apply.payment_account', + 'fin_payment_apply.currency_id', + 'sys_currency.currency_name', + 'fin_payment_apply.amount', + 'fin_payment_apply.apply_no' + ]); + + foreach ($list as $key => &$val) { + $stockIds = Db::table('fin_payment_stock') + ->where('payment_apply_id', $val->id) + ->pluck('stock_id') + ->toArray(); + $val->order_no = Db::table('stock_orders') + ->whereIn('id', $stockIds) + ->pluck('order_no') + ->toArray(); + $val->created_at = date('Y-m-d H:i:s', $val->created_at); + } + unset($val); + } + return $this->success($list); + } +} \ No newline at end of file diff --git a/app/admin/logic/SysConfigLogic.php b/app/admin/logic/SysConfigLogic.php new file mode 100644 index 0000000..60be4a8 --- /dev/null +++ b/app/admin/logic/SysConfigLogic.php @@ -0,0 +1,17 @@ +validator; + } + + /** + * 构建查询条件 + */ + protected function buildQueryConfig(Request $request, string $scene = 'default'): array + { + $p = $request->all(); + + $config = []; + $config['model'] = $this->modelClass; + switch ($scene) { + case 'index': + // ====== ====== 排序 ====== ====== + $config['order']['id'] = 'desc'; + + // ====== ====== 筛选 ====== ====== + // 状态 + if (isset($p['status']) && in_array($p['status'], [0,1])) { + $config['where']['status'] = $p['status']; + } + // 关键字 + if (isset($p['keyword']) && $p['keyword']) { + $k = '%' . $p['keyword'] . '%'; + foreach (['config_key','config_value','description'] as $col) { + $config['orWhere'][] = [$col, 'like', $k]; + } + } + break; + case 'show': + $config['where']['id'] = $p['id']; + //$config['where']['status'] = 1; + break; + case 'store': + break; + case 'update': + $config['where']['id'] = $p['id']; + break; + case 'destroy': + $config['where']['id'] = $p['id']; + break; + } + + return $config; + } + + + public function beforeServiceUpdate($data, Request $request) + { + Redis::del($data['config_key']); + } +} \ No newline at end of file diff --git a/app/admin/service/UserService.php b/app/admin/service/UserService.php index 7f2fadd..9d850a5 100644 --- a/app/admin/service/UserService.php +++ b/app/admin/service/UserService.php @@ -100,6 +100,8 @@ class UserService $config['with']['roles'][] = 'name'; $config['with']['systems'][] = 'id'; $config['with']['systems'][] = 'name'; + $config['with']['reportToInfo'][] = 'id'; + $config['with']['reportToInfo'][] = 'name'; break; case 'show': $config['where']['id'] = $p['id']; diff --git a/app/admin/validate/SysConfigValidate.php b/app/admin/validate/SysConfigValidate.php new file mode 100644 index 0000000..2bb978a --- /dev/null +++ b/app/admin/validate/SysConfigValidate.php @@ -0,0 +1,29 @@ + [ + + ], + + 'update' => [ + + ] + ]; +} \ No newline at end of file diff --git a/app/common/controller/FinPaymentApplyController.php b/app/common/controller/FinPaymentApplyController.php new file mode 100644 index 0000000..0939646 --- /dev/null +++ b/app/common/controller/FinPaymentApplyController.php @@ -0,0 +1,160 @@ +service = new FinPaymentApplyService(); + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + protected function indexFormat($data) + { + if (isset($data['doc_user_id'])) //内勤 + $data['doc_user_name'] = User::where('id', $data['doc_user_id'])->value('name')??''; + if (isset($data['sales_user_id'])) //业务员 + $data['sales_user_name'] = User::where('id', $data['doc_user_id'])->value('name')??''; + if (isset($data['corp_id'])) //公司(渠道) + $data['corp_name'] = SysDictItem::where('id', $data['corp_id'])->value('item_label')??''; + if (isset($data['account_id'])){ //收款账号 + $data['account_name'] = SysAccount::where('id', $data['account_id'])->value('account_name')??''; + $data['account_short_desc'] = SysAccount::where('id', $data['account_id'])->value('short_desc')??''; + } + if (isset($data['country_id'])) //付款来源国家 + $data['country_name'] = Country::where('id', $data['country_id'])->value('cn_addr')??''; + if (isset($data['currency_id'])) //付款币种 + $data['currency_name'] = SysCurrency::where('id', $data['currency_id'])->value('currency_name')??''; + $OssService = new OssService(); + if (!empty($data['submit_files'])){ + $data['submit_files'] = json_decode($data['submit_files'], true); + foreach ($data['submit_files'] as $key => $value) { + $data['submit_files'][$key] = [ + 'file_src' => $value['file_src'], + 'file_full' => $OssService->generatePrivateUrl($value['file_src']), + 'file_name' => $value['file_name'], + ]; + } + }else{ + $data['submit_files'] = []; + } + + if (!empty($data['voucher_file'])){ + $data['voucher_file'] = json_decode($data['voucher_file'], true); + foreach ($data['voucher_file'] as $key => $value) { + $data['voucher_file'][$key] = [ + 'file_src' => $value['file_src'], + 'file_full' => $OssService->generatePrivateUrl($value['file_src']), + 'file_name' => $value['file_name'], + ]; + } + }else{ + $data['voucher_file'] = []; + } + + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + if (isset($data['claimed_at'])){ + $data['enter_file_last'] = date('Y-m-d H:i:s', ($data['claimed_at']+86400)); //入账资料最后提交时间 + $data['claimed_at'] = date('Y-m-d H:i:s', $data['claimed_at']); //认领时间 + } + if (isset($data['id'])){ + $finPaymentStock = FinPaymentStock::where('payment_apply_id', $data['id'])->get(); + $stock = []; + foreach ($finPaymentStock as $v) { + $stock[$v['pi_no']]['pi_no'] = $v['pi_no']; + $stock[$v['pi_no']]['stock_id'][] = [$v['stock_id']]; + } + $data['stock'] = array_values($stock); + } + + return $data; + } + + /** + * 数据格式化 + * + * @param array $data + * @return array + */ + public function showFormat($data) + { + if (isset($data['doc_user_id'])) //内勤 + $data['doc_user_name'] = User::where('id', $data['doc_user_id'])->value('name')??''; + if (isset($data['sales_user_id'])) //业务员 + $data['sales_user_name'] = User::where('id', $data['doc_user_id'])->value('name')??''; + if (isset($data['corp_id'])) //公司(渠道) + $data['corp_name'] = SysDictItem::where('id', $data['corp_id'])->value('item_label')??''; + if (isset($data['account_id'])){ //收款账号 + $data['account_name'] = SysAccount::where('id', $data['account_id'])->value('account_name')??''; + $data['account_short_desc'] = SysAccount::where('id', $data['account_id'])->value('short_desc')??''; + } + if (isset($data['country_id'])) //付款来源国家 + $data['country_name'] = Country::where('id', $data['country_id'])->value('cn_addr')??''; + if (isset($data['currency_id'])) //付款币种 + $data['currency_name'] = SysCurrency::where('id', $data['currency_id'])->value('currency_name')??''; + $OssService = new OssService(); + if (!empty($data['submit_files'])){ + $data['submit_files'] = json_decode($data['submit_files'], true); + foreach ($data['submit_files'] as $key => $value) { + $data['submit_files'][$key] = [ + 'file_src' => $value['file_src'], + 'file_full' => $OssService->generatePrivateUrl($value['file_src']), + 'file_name' => $value['file_name'], + ]; + } + }else{ + $data['submit_files'] = []; + } + + if (!empty($data['voucher_file'])){ + $data['voucher_file'] = json_decode($data['voucher_file'], true); + foreach ($data['voucher_file'] as $key => $value) { + $data['voucher_file'][$key] = [ + 'file_src' => $value['file_src'], + 'file_full' => $OssService->generatePrivateUrl($value['file_src']), + 'file_name' => $value['file_name'], + ]; + } + }else{ + $data['voucher_file'] = []; + } + + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + + $finPaymentStock = FinPaymentStock::where('payment_apply_id', $data['id'])->get(); + $stock = []; + foreach ($finPaymentStock as $v) { + $stock[$v['pi_no']]['pi_no'] = $v['pi_no']; + $stock[$v['pi_no']]['stock_id'][] = [$v['stock_id']]; + } + $data['stock'] = array_values($stock); + return $data; + } +} \ No newline at end of file diff --git a/app/common/controller/FinReceiptController.php b/app/common/controller/FinReceiptController.php new file mode 100644 index 0000000..cade259 --- /dev/null +++ b/app/common/controller/FinReceiptController.php @@ -0,0 +1,184 @@ +service = new FinReceiptService(); + } + + /** + * 确认入账 + * @param Request $request + * @return \support\Response + */ + public function credit(Request $request) + { + try { + $id = $request->input('id'); + $raw = $this->service->credit($id); + return $this->success($raw); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + } + + public function show(Request $request) + { + try { + $raw = $this->service->serviceShow($request); + $data = $this->transformData($raw, method_exists($this, 'showFormat') + ? [$this, 'showFormat'] + : null); + return $this->success($data); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + } + + /** + * 更新 + * + * @param Request $request 请求对象 + * @return mixed 返回更新成功的数据或信息 + */ + public function payment(Request $request) + { + try { + $data = $this->validate($this->service->getValidator(), $request->post(), 'update'); + $res = $this->service->serviceUpdatePayment($request, $data); + return $this->success([], '更新成功'); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + protected function indexFormat($data) + { + if (isset($data['created_at'])){ + $data['claim_timeout'] = (($data['created_at'] < (time()-86400)) && empty($data['payment_apply_id'])) ?1:0; + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + } + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + if (isset($data['arrived_at'])) + $data['arrived_at'] = date('Y-m-d H:i:s', $data['arrived_at']); + if (isset($data['received_at'])) + $data['received_at'] = date('Y-m-d H:i:s', $data['received_at']); + if (isset($data['account_id'])) { //收款账号 + $data['account_name'] = SysAccount::where('id', $data['account_id'])->value('account_name')??''; + $data['account_short_desc'] = SysAccount::where('id', $data['account_id'])->value('short_desc')??''; + } + if (isset($data['country_id'])) //付款来源国家 + $data['country_name'] = Country::where('id', $data['country_id'])->value('cn_addr')??''; + if (isset($data['currency_id'])) //付款币种 + $data['currency_name'] = SysCurrency::where('id', $data['currency_id'])->value('currency_name')??''; + + $OssService = new OssService(); + if (!empty($data['fx_receipt_file'])){ + $data['fx_receipt_file'] = json_decode($data['fx_receipt_file'], true); + foreach ($data['fx_receipt_file'] as $key => $value) { + $data['fx_receipt_file'][$key] = [ + 'file_src' => $value['file_src'], + 'file_full' => $OssService->generatePrivateUrl($value['file_src']), + 'file_name' => $value['file_name'], + ]; + } + }else{ + $data['fx_receipt_file'] = []; + } + return $data; + } + + /** + * 数据格式化 + * + * @param array $data + * @return array + */ + protected function showFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + if (isset($data['arrived_at'])) + $data['arrived_at'] = date('Y-m-d H:i:s', $data['arrived_at']); + if (isset($data['received_at'])) + $data['received_at'] = date('Y-m-d H:i:s', $data['received_at']); + if (isset($data['account_id'])) { //收款账号 + $data['account_name'] = SysAccount::where('id', $data['account_id'])->value('account_name')??''; + $data['account_short_desc'] = SysAccount::where('id', $data['account_id'])->value('short_desc')??''; + } + if (isset($data['country_id'])) //付款来源国家 + $data['country_name'] = Country::where('id', $data['country_id'])->value('cn_addr')??''; + if (isset($data['currency_id'])) //付款币种 + $data['currency_name'] = SysCurrency::where('id', $data['currency_id'])->value('currency_name')??''; + + $OssService = new OssService(); + if (!empty($data['fx_receipt_file'])){ + $data['fx_receipt_file'] = json_decode($data['fx_receipt_file'], true); + foreach ($data['fx_receipt_file'] as $key => $value) { + $data['fx_receipt_file'][$key] = [ + 'file_src' => $value['file_src'], + 'file_full' => $OssService->generatePrivateUrl($value['file_src']), + 'file_name' => $value['file_name'], + ]; + } + }else{ + $data['fx_receipt_file'] = []; + } + + //查询关联的付款记录 + if (!empty($data['payment_apply_id'])) { + $paymentApply = FinPaymentApply::where('id', $data['payment_apply_id'])->first(); + if(!$paymentApply) + return $data; + $paymentApply = $paymentApply->toArray(); + $paymentApply['created_at'] = strtotime($paymentApply['created_at']); + $paymentApply['updated_at'] = strtotime($paymentApply['updated_at']); + $paymentApply = (new FinPaymentApplyController())->showFormat($paymentApply); + $data['payment_apply'] = $paymentApply; + } + return $data; + } + + /** + * 收款记录统计 + * @param Request $request + * @return \support\Response + */ + public function statistics(Request $request) + { + try { + $raw = $this->service->statistics(); + return $this->success($raw); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + } +} \ No newline at end of file diff --git a/app/common/controller/FinReceiptHisController.php b/app/common/controller/FinReceiptHisController.php new file mode 100644 index 0000000..7adcf0d --- /dev/null +++ b/app/common/controller/FinReceiptHisController.php @@ -0,0 +1,98 @@ +service = new FinReceiptHisService(); + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + protected function indexFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + if (isset($data['arrived_at'])) + $data['arrived_at'] = date('Y-m-d H:i:s', $data['arrived_at']); + if (isset($data['received_at'])) + $data['received_at'] = date('Y-m-d H:i:s', $data['received_at']); + if (isset($data['account_id'])) { //收款账号 + $data['account_name'] = SysAccount::where('id', $data['account_id'])->value('account_name')??''; + $data['account_short_desc'] = SysAccount::where('id', $data['account_id'])->value('short_desc')??''; + } + if (isset($data['country_id'])) //付款来源国家 + $data['country_name'] = Country::where('id', $data['country_id'])->value('cn_addr')??''; + if (isset($data['currency_id'])) //付款币种 + $data['currency_name'] = SysCurrency::where('id', $data['currency_id'])->value('currency_name')??''; + if (!empty($data['fx_receipt_file'])){ + $data['fx_receipt_file_full'] = (new OssService)->generatePrivateUrl($data['fx_receipt_file']); + }elseif (isset($data['fx_receipt_file'])){ + $data['fx_receipt_file_full'] = ''; + } + + if (isset($data['created_by'])) + $data['created_by'] = User::where('id', $data['created_by'])->value('name')??''; + if (isset($data['updated_by'])) + $data['updated_by'] = User::where('id', $data['updated_by'])->value('name')??''; + return $data; + } + + /** + * 数据格式化 + * + * @param array $data + * @return array + */ + protected function showFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + if (isset($data['arrived_at'])) + $data['arrived_at'] = date('Y-m-d H:i:s', $data['arrived_at']); + if (isset($data['received_at'])) + $data['received_at'] = date('Y-m-d H:i:s', $data['received_at']); + if (isset($data['account_id'])){ //收款账号 + $data['account_name'] = SysAccount::where('id', $data['account_id'])->value('account_name')??''; + $data['account_short_desc'] = SysAccount::where('id', $data['account_id'])->value('short_desc')??''; + } + if (isset($data['country_id'])) //付款来源国家 + $data['country_name'] = Country::where('id', $data['country_id'])->value('cn_addr')??''; + if (isset($data['currency_id'])) //付款币种 + $data['currency_name'] = SysCurrency::where('id', $data['currency_id'])->value('currency_name')??''; + if (!empty($data['fx_receipt_file'])){ + $data['fx_receipt_file_full'] = (new OssService)->generatePrivateUrl($data['fx_receipt_file']); + }elseif (isset($data['fx_receipt_file'])){ + $data['fx_receipt_file_full'] = ''; + } + + if (isset($data['created_by'])) + $data['created_by'] = User::where('id', $data['created_by'])->value('name')??''; + if (isset($data['updated_by'])) + $data['updated_by'] = User::where('id', $data['updated_by'])->value('name')??''; + return $data; + } +} \ No newline at end of file diff --git a/app/common/logic/AuthLogic.php b/app/common/logic/AuthLogic.php index ee449b9..9abe5e1 100644 --- a/app/common/logic/AuthLogic.php +++ b/app/common/logic/AuthLogic.php @@ -172,7 +172,7 @@ class AuthLogic $payload = $this->buildJwtPayload($user, $system); $token = $this->generateAccessToken($payload); $refreshToken = $this->generateRefreshToken($user->id, $data['system_code']); - $homeUrl = $this->getHome($system->id); + $homeUrl = $this->getHome($system->id, $payload); // 记录 token 到 Redis 和 MySQL $this->recordUserToken($user->id, $token, $data['system_code']); @@ -537,8 +537,22 @@ class AuthLogic } - public function getHome($systemId) + public function getHome($systemId, $data) { + // 2025.10.30 临时处理 ====== start + if ($systemId == 1) { + if (in_array(1, $data['role_ids'])) { + return '/dashboard/console'; + } + if (count($data['role_ids']) == 1 && in_array(5, $data['role_ids'])) { + return '/dashboard/console/backoffice'; + } + if (count($data['role_ids']) == 1 && in_array(6, $data['role_ids'])) { + return '/dashboard/console/finance'; + } + } + // 2025.10.30 临时处理 ====== end + $info = Resource::where('system_id', $systemId) ->where('is_home', 1) ->first(); diff --git a/app/common/logic/FinPaymentApplyLogic.php b/app/common/logic/FinPaymentApplyLogic.php new file mode 100644 index 0000000..09b93e1 --- /dev/null +++ b/app/common/logic/FinPaymentApplyLogic.php @@ -0,0 +1,17 @@ +update(['received_at' => time()]); + } +} \ No newline at end of file diff --git a/app/common/logic/SysConfigLogic.php b/app/common/logic/SysConfigLogic.php new file mode 100644 index 0000000..633d177 --- /dev/null +++ b/app/common/logic/SysConfigLogic.php @@ -0,0 +1,22 @@ +where('config_key', $key)->get(['id', 'config_key', 'config_value']); + } +} \ No newline at end of file diff --git a/app/common/model/FinPaymentApply.php b/app/common/model/FinPaymentApply.php new file mode 100644 index 0000000..0f4d157 --- /dev/null +++ b/app/common/model/FinPaymentApply.php @@ -0,0 +1,65 @@ +hasOne(FinReceipt::class, 'payment_apply_id', 'id'); + } + + /** + * 关联的备货单(通过中间表) + */ + public function stocks() + { + return $this->belongsToMany(StockOrders::class, 'fin_payment_stock', 'payment_apply_id', 'stock_id'); + } +} \ No newline at end of file diff --git a/app/common/model/FinPaymentStock.php b/app/common/model/FinPaymentStock.php new file mode 100644 index 0000000..d5b3d10 --- /dev/null +++ b/app/common/model/FinPaymentStock.php @@ -0,0 +1,67 @@ +belongsTo(FinPaymentApply::class, 'payment_apply_id', 'id'); + } + + // 收款记录 + public function receipt() + { + return $this->belongsTo(FinReceipt::class, 'receipt_id', 'id'); + } + + // 备货单 + public function stock() + { + return $this->belongsTo(StockOrders::class, 'stock_id', 'id'); + } +} \ No newline at end of file diff --git a/app/common/model/FinReceipt.php b/app/common/model/FinReceipt.php new file mode 100644 index 0000000..7347be0 --- /dev/null +++ b/app/common/model/FinReceipt.php @@ -0,0 +1,65 @@ +belongsTo(FinPaymentApply::class, 'payment_apply_id', 'id'); + } + + /** + * 关联的备货单(通过中间表) + */ + public function stocks() + { + return $this->belongsToMany(StockOrders::class, 'fin_payment_stock', 'receipt_id', 'stock_id'); + } +} \ No newline at end of file diff --git a/app/common/model/FinReceiptHis.php b/app/common/model/FinReceiptHis.php new file mode 100644 index 0000000..8a036b3 --- /dev/null +++ b/app/common/model/FinReceiptHis.php @@ -0,0 +1,49 @@ +hasOne(User::class, 'id', 'salesperson_id'); } + + /** + * 客户的标签 + */ + public function payment() + { + return $this->belongsToMany(FinPaymentApply::class, 'fin_payment_stock', 'stock_id', 'payment_apply_id'); + } + + /** + * 关联收款记录(多对多,经由中间表) + */ + public function receipts() + { + return $this->belongsToMany(FinReceipt::class, 'fin_payment_stock', 'stock_id', 'receipt_id'); + } } \ No newline at end of file diff --git a/app/common/model/StockOrdersFiles.php b/app/common/model/StockOrdersFiles.php index 98daa3f..3b78e5c 100644 --- a/app/common/model/StockOrdersFiles.php +++ b/app/common/model/StockOrdersFiles.php @@ -40,7 +40,7 @@ class StockOrdersFiles extends Model /** * 允许自动填充模型字段 */ - protected $fillable = ['id', 'order_id', 'file_name', 'file_code', 'file_url', 'created_at', 'updated_at']; + protected $fillable = ['id', 'order_id', 'file_name', 'file_code', 'file_url', 'original_name', 'created_at', 'updated_at']; /** * 不允许自动填充模型字段 diff --git a/app/common/model/SysConfig.php b/app/common/model/SysConfig.php new file mode 100644 index 0000000..29b4577 --- /dev/null +++ b/app/common/model/SysConfig.php @@ -0,0 +1,49 @@ +validator; + } + + /** + * 构建查询条件 + */ + protected function buildQueryConfig(Request $request, string $scene = 'index'): array + { + $p = $request->all(); + + $config = []; + $config['model'] = $this->modelClass; + switch ($scene) { + case 'index': + // ====== ====== 排序 ====== ====== + $config['order']['id'] = 'desc'; + + // ====== ====== 筛选 ====== ====== + // 汇款国家 + if (isset($p['country_id']) && !empty($p['country_id'])) { + $config['where']['country_id'] = $p['country_id']; + } + + // 收款账户筛选 + if (isset($p['account_id']) && !empty($p['account_id'])) { + $config['where']['account_id'] = $p['account_id']; + } + + // 入账资料超时 + if (isset($p['scene']) && $p['scene'] == 'file_timeout') { + $config['where']['claimed_at'] = ['between', [1, time()-24*60*60]]; + } + + // 关键字 + if (isset($p['keyword']) && $p['keyword']) { + $k = '%' . $p['keyword'] . '%'; + $config['orWhere'][] = ['remitter', 'like', $k]; + } + break; + case 'show': + $config['where']['id'] = $p['id']; + break; + case 'update': + case 'destroy': + $config['where']['id'] = $p['id']; + break; + case 'store': + break; + } + + return $config; + } + + public function beforeServiceStore($data, Request $request) + { + $data['apply_no'] = $this->generateUniqueApplyNo(); + $data['doc_user_id'] = $request->user->uid; + $data['voucher_file'] = json_encode($data['voucher_file']); + $data['submit_files'] = json_encode($data['submit_files']); + redis::set('stock_' . $data['doc_user_id'], json_encode($request->post('stock')), 'EX', 30); + unset($data['stock']); + if($data['voucher_file'] == '[]' || $data['voucher_file'] == '{}' || $data['voucher_file'] == '""') + $data['voucher_file'] = ''; + if($data['submit_files'] == '[]' || $data['submit_files'] == '{}' || $data['submit_files'] == '""') + $data['submit_files'] = ''; + return $data; + } + + + public function afterServiceStore($res) + { + $data = [ + 'payment_apply_id' => $res['id'], + ]; + $piStock = json_decode(redis::get('stock_' . $res['doc_user_id']), true); + redis::del('stock' . $res['doc_user_id']); + foreach ($piStock as $stock) { + foreach ($stock['stock_id'] as $v) { + $data['stock_id'] = $v; + $data['pi_no'] = $stock['pi_on']; + FinPaymentStock::create($data); + } + } + } + + public function beforeServiceUpdate($data, Request $request) + { + unset($data['stock']); + $data['submit_files'] = json_encode($data['submit_files']); + if($data['submit_files'] == '[]' || $data['submit_files'] == '{}' || $data['submit_files'] == '""') + $data['submit_files'] = ''; + $data['voucher_file'] = json_encode($data['voucher_file']); + if($data['voucher_file'] == '[]' || $data['voucher_file'] == '{}' || $data['voucher_file'] == '""') + $data['voucher_file'] = ''; + return $data; + } + + /** + * 生成唯一的付款申请编码 + * 格式:PA + 日期 + 6位字母数字组合 + * + * @return string 唯一编码 + */ + public function generateUniqueApplyNo() + { + $chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $maxAttempts = 10; // 防止无限循环 + $secondChar = 'PA' . date('Ymd'); + + for ($attempt = 0; $attempt < $maxAttempts; $attempt++) { + // 生成后6位随机字符 + $suffix = ''; + for ($i = 0; $i < 6; $i++) { + $suffix .= $chars[rand(0, strlen($chars) - 1)]; + } + + $applyNo = $secondChar . $suffix; + + // 检查是否已存在 + $existing = FinPaymentApply::where('apply_no', $applyNo)->first(); + if (!$existing) { + return $applyNo; + } + } + + // 如果1000次尝试后仍然重复,使用时间戳确保唯一性 + $timestamp = substr(time(), -6); + return $secondChar . $timestamp; + } + + /** + * 根据相似度排序付款记录 + * @param Request $request + * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator|\Illuminate\Pagination\LengthAwarePaginator + */ + public function complexQueryIndex(Request $request) + { + $limit = (int)$request->get('size', 15); + $page = (int)$request->get('current', 1); + $param = $request->all(); + + $where = []; + $orWhere = []; + + // 汇款国家 + if (isset($param['country_id']) && !empty($param['country_id'])) { + $where[] = ['country_id', $param['country_id']]; + } + // 收款账户筛选 + if (isset($param['account_id']) && !empty($param['account_id'])) { + $where[] = ['account_id', $param['account_id']]; + } + + // 入账资料超时 + if (isset($param['scene']) && $param['scene'] == 'file_timeout') { + $where[] = ['submit_files', '']; + $where[] = ['claimed_at', '<', time()-24*60*60]; + $where[] = ['claimed_at', '>', 1]; + } + + // 关键字 + if (isset($param['keyword']) && $param['keyword']) { + $k = '%' . $param['keyword'] . '%'; + $where[] = ['remitter', 'like', $k]; + } + + // 构建查询 + $query = $this->modelClass::where($where); + + // 是否已关联收款记录的筛选 + $correlation = $param['correlation']??''; + if ($correlation === 'receipt') { //已关联 + $query->whereHas('receipt'); + } elseif ($correlation === 'unbind') { //未关联 + $query->whereDoesntHave('receipt'); + } + + if ((isset($param['scene']) && $param['scene'] == 'list') || empty($param['receipt_id'])) { + return $query->orderBy('id','desc')->paginate($limit, ['*'], 'page', $page); + } + + $receipt = FinReceipt::where('id', $param['receipt_id'])->first(); + $account_id = $receipt->account_id; + $currency_id = $receipt->currency_id; + $remitter = $receipt->remitter; + $amount = $receipt->amount; + + // 计算十天前的时间戳 + $sevenDaysAgo = time() - (10 * 24 * 60 * 60); + + // 构建相似度排序逻辑 + $similarityOrder = []; + + // 如果有传入参数,计算相似度 + if (!empty($account_id)) { + $similarityOrder[] = "CASE WHEN account_id = {$account_id} THEN 0 ELSE 1 END"; + } + + if (!empty($currency_id)) { + $similarityOrder[] = "CASE WHEN currency_id = {$currency_id} THEN 0 ELSE 1 END"; + } + + if (!empty($remitter)) { + $similarityOrder[] = "CASE WHEN remitter = '{$remitter}' THEN 0 ELSE 1 END"; + } + + if (!empty($amount)) { + $amount = (float)$amount; + $similarityOrder[] = "ABS(amount - {$amount})"; + $similarityOrder[] = "CASE WHEN (ABS(amount - {$amount}) / {$amount} * 100) <= 5 THEN 0 ELSE 1 END"; + } + + // 构建排序SQL + $orderByClause = ""; + if (!empty($similarityOrder)) { + $orderByClause = "CASE + WHEN created_at >= {$sevenDaysAgo} THEN + (" . implode(' + ', $similarityOrder) . ") + ELSE 0 + END ASC, "; + } + + $orderByClause .= "CASE + WHEN created_at > {$sevenDaysAgo} THEN id + ELSE 999999 + END DESC, "; + + $orderByClause .= "id DESC"; + + $query->orderByRaw($orderByClause); + + return $query->paginate($limit, ['*'], 'page', $page); + } + +} \ No newline at end of file diff --git a/app/common/service/FinReceiptHisService.php b/app/common/service/FinReceiptHisService.php new file mode 100644 index 0000000..f43f77b --- /dev/null +++ b/app/common/service/FinReceiptHisService.php @@ -0,0 +1,62 @@ +validator; + } + + /** + * 构建查询条件 + */ + protected function buildQueryConfig(Request $request, string $scene = 'index'): array + { + $p = $request->all(); + + $config = []; + $config['model'] = $this->modelClass; + switch ($scene) { + case 'index': + if(empty($p['receipt_id'])){ + throw new BusinessException('receipt_id不能为空'); + } + // ====== ====== 排序 ====== ====== + $config['order']['id'] = 'desc'; + + // ====== ====== 筛选 ====== ====== + $config['where']['receipt_id'] = $p['receipt_id']; + + break; + case 'show': + $config['where']['id'] = $p['id']; + break; + } + + return $config; + } +} \ No newline at end of file diff --git a/app/common/service/FinReceiptService.php b/app/common/service/FinReceiptService.php new file mode 100644 index 0000000..6073cdf --- /dev/null +++ b/app/common/service/FinReceiptService.php @@ -0,0 +1,315 @@ +logic = (new FinReceiptLogic()); + } + + /** + * 获取验证器 + */ + public function getValidator() + { + return new $this->validator; + } + + + /** + * 构建查询条件 + */ + protected function buildQueryConfig(Request $request, string $scene = 'index'): array + { + $p = $request->all(); + + $config = []; + $config['model'] = $this->modelClass; + switch ($scene) { + case 'index': + // ====== ====== 排序 ====== ====== + $config['order']['id'] = 'desc'; + + // ====== ====== 筛选 ====== ====== + // 汇款国家 + if (isset($p['country_id']) && !empty($p['country_id'])) { + $config['where']['country_id'] = $p['country_id']; + } + + // 没有付款记录的收款记录 + if (isset($p['payment_apply']) && $p['payment_apply'] == 'not') { //未认领 + $config['where']['payment_apply_id'] = 0; + } elseif (isset($p['payment_apply']) && $p['payment_apply'] == 'already') { //已认领 + $config['where']['payment_apply_id'] = ['>', 0]; + } elseif (isset($p['payment_apply']) && $p['payment_apply'] == 'timeout') { //超时未认领 + $config['where']['payment_apply_id'] = 0; + $config['where']['created_at'] = ['<' ,time() - 24*60*60]; + } + + // 收款申请筛选 + if (isset($p['payment_apply_id']) && !empty($p['payment_apply_id'])) { + $config['where']['payment_apply_id'] = $p['payment_apply_id']; + } + + // 收款账户筛选 + if (isset($p['account_id']) && !empty($p['account_id'])) { + $config['where']['account_id'] = $p['account_id']; + } + + // 关键字 + if (isset($p['keyword']) && $p['keyword']) { + $k = '%' . $p['keyword'] . '%'; + $config['orWhere'][] = ['remitter', 'like', $k]; + } + break; + case 'show': + $config['where']['id'] = $p['id']; + break; + case 'update': + case 'payment': + case 'destroy': + $config['where']['id'] = $p['id']; + break; + case 'store': + break; + } + + return $config; + } + + public function beforeServiceStore($data, Request $request) + { + if(isset($data['payment_apply_id']) && empty($data['payment_apply_id'])){ + unset($data['payment_apply_id']); + } + $data['receipt_no'] = $this->generateUniqueReceipt(); + $data['arrived_at'] = strtotime( $data['arrived_at']); + $data['created_by'] = $request->user->uid; + $data['updated_by'] = $request->user->uid; + $data['fx_receipt_file'] = json_encode($data['fx_receipt_file']); + if($data['fx_receipt_file'] == '[]' || $data['fx_receipt_file'] == '{}' || $data['fx_receipt_file'] == '""') + $data['fx_receipt_file'] = ''; + return $data; + } + + public function afterServiceStore($res) + { + $receipt = FinReceipt::where('id',$res->id)->first()->toArray(); + $receipt = array_merge($receipt,['receipt_id' => $res->id]); + unset($receipt['id']); + FinReceiptHis::create($receipt); + } + + public function beforeServiceUpdate($data, Request $request) + { + $data['updated_by'] = $request->user->uid; + if(isset($data['arrived_at'])) + $data['arrived_at'] = strtotime($data['arrived_at']); + if(isset($data['received_at'])) + $data['received_at'] = strtotime($data['received_at']); + + $data['fx_receipt_file'] = json_encode($data['fx_receipt_file']); + if($data['fx_receipt_file'] == '[]' || $data['fx_receipt_file'] == '{}' || $data['fx_receipt_file'] == '""') + $data['fx_receipt_file'] = ''; + return $data; + } + public function afterServiceUpdate($res) + { + $receipt = FinReceipt::where('id',$res['id'])->first()->toArray(); + $receipt = array_merge($receipt,['receipt_id' => $res['id']]); + unset($receipt['id']); + FinReceiptHis::create($receipt); + } + + + /** + * 生成唯一的付款申请编码 + * 格式:PA + 日期 + 6位字母数字组合 + * + * @return string 唯一编码 + */ + public function generateUniqueReceipt() + { + $chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $maxAttempts = 10; // 防止无限循环 + $secondChar = 'RE' . date('Ymd'); + + for ($attempt = 0; $attempt < $maxAttempts; $attempt++) { + // 生成后6位随机字符 + $suffix = ''; + for ($i = 0; $i < 6; $i++) { + $suffix .= $chars[rand(0, strlen($chars) - 1)]; + } + + $ReceiptNo = $secondChar . $suffix; + + // 检查是否已存在 + $existing = FinReceipt::where('receipt_no', $ReceiptNo)->first(); + if (!$existing) { + return $ReceiptNo; + } + } + + // 如果1000次尝试后仍然重复,使用时间戳确保唯一性 + $timestamp = substr(time(), -6); + return $secondChar . $timestamp; + } + + /** + * 根据相似度排序付款记录 + * @param Request $request + * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator|\Illuminate\Pagination\LengthAwarePaginator + */ + public function complexQueryIndex(Request $request) + { + $limit = (int)$request->get('size', 15); + $page = (int)$request->get('current', 1); + $param = $request->all(); + + $where = []; + + // 汇款国家 + if (isset($param['country_id']) && !empty($param['country_id'])) { + $where[] = ['country_id', $param['country_id']]; + } + // 收款账户筛选 + if (isset($param['account_id']) && !empty($param['account_id'])) { + $where[] = ['account_id', $param['account_id']]; + } + // 收款申请筛选 + if (isset($param['payment_apply_id']) && !empty($param['payment_apply_id'])) { + $where[]['payment_apply_id'] = $param['payment_apply_id']; + } + + // 关键字 + if (isset($param['keyword']) && $param['keyword']) { + $k = '%' . $param['keyword'] . '%'; + $where[] = ['remitter', 'like', $k]; + } + + // 构建查询 + $query = $this->modelClass::where($where); + + // 没有付款记录的收款记录 + if (isset($param['payment_apply']) && $param['payment_apply'] == 'not') { + $query->where('payment_apply_id', 0); + } elseif (isset($param['payment_apply']) && $param['payment_apply'] == 'already') { + $query->where('payment_apply_id', '>', 0); + } elseif (isset($param['payment_apply']) && $param['payment_apply'] == 'timeout') { //超时未认领 + $query->where('payment_apply_id', 0); + $query->where('created_at', '<' ,time() - 24*60*60); + } + + if (isset($param['scene']) && $param['scene'] == 'list') { + return $query->paginate($limit, ['*'], 'page', $page); + } + + // 计算七天前的时间戳 + $sevenDaysAgo = time() - (10 * 24 * 60 * 60); + + // 构建相似度排序逻辑 + $similarityOrder = []; + + // 如果有传入参数,计算相似度 + if (isset($param['account_id']) && !empty($param['account_id'])) { + $similarityOrder[] = "CASE WHEN account_id = {$param['account_id']} THEN 0 ELSE 1 END"; + } + + if (isset($param['country_id']) && !empty($param['country_id'])) { + $similarityOrder[] = "CASE WHEN country_id = {$param['country_id']} THEN 0 ELSE 1 END"; + } + + if (isset($param['keyword']) && $param['keyword']) { + $keyword = addslashes($param['keyword']); + $similarityOrder[] = "CASE WHEN remitter LIKE '%{$keyword}%' THEN 0 ELSE 1 END"; + } + + if (isset($param['amount']) && !empty($param['amount'])) { + $amount = (float)$param['amount']; + $similarityOrder[] = "ABS(amount - {$amount})"; + } + + // 构建排序SQL + $orderByClause = ""; + if (!empty($similarityOrder)) { + $orderByClause = "CASE + WHEN created_at >= {$sevenDaysAgo} THEN + (" . implode(' + ', $similarityOrder) . ") + ELSE 999999 + END ASC, "; + } + + $orderByClause .= "CASE + WHEN created_at < {$sevenDaysAgo} THEN id + ELSE 0 + END DESC"; + + $query->orderByRaw($orderByClause); + + return $query->paginate($limit, ['*'], 'page', $page); + } + + public function credit($id) + { + $finReceipt = FinReceipt::find($id); + if(!empty($finReceipt->received_at)){ + throw new BusinessException('该记录已将确认入账'); + } + $res = $this->logic->credit($id); + $this->afterServiceUpdate(['id'=>$id]); + return $res; + } + + /** + * 更新:绑定收款记录,计算折让金额 + * @param Request $request + * @param array $data + * @param string $scene + * @return mixed + */ + public function serviceUpdatePayment(Request $request, array $data = [], string $scene = 'payment') + { + $payment_apply_id = $request->input('payment_apply_id'); + $id = $request->input('id'); + $data = $this->preProcess(ucfirst($scene), $data, $request); + $config = $this->buildQueryConfig($request, $scene); + FinPaymentApply::where('id', $payment_apply_id)->update(['receipt_id' => $id, 'claimed_at' => time(), 'claimed_by' => $request->user->uid]); + FinPaymentStock::where('payment_apply_id', $payment_apply_id)->update(['receipt_id' => $id]); + + //折让金额 + $payment = FinPaymentApply::where('id', $payment_apply_id)->first(); + $receipt = FinReceipt::find($id); + $data['discount_amount'] = $payment->amount - $receipt->amount ?? 0; + + $updated = $this->logicUpdateBy($config, $data); + return $this->postProcess(ucfirst($scene), $data); + } +} \ No newline at end of file diff --git a/app/common/service/StockOrdersService.php b/app/common/service/StockOrdersService.php index 76d2ab5..d4187a1 100644 --- a/app/common/service/StockOrdersService.php +++ b/app/common/service/StockOrdersService.php @@ -161,7 +161,8 @@ class StockOrdersService { // 启动审批 $appro = new \app\common\utils\approval\service\ApprovalFlowService(); - $appro->start('stock_orders', 'stock_orders', $item->id, [], $item->salesperson_id); + $formData = $this->checkNewOrUsedVehicles($item->id); + $appro->start('stock_orders', 'stock_orders', $item->id, $formData, $item->salesperson_id); // 异步生成pdf文件 \Webman\RedisQueue\Redis::send('stock-order-pdf', ['id'=>$item->id]); } @@ -295,7 +296,8 @@ class StockOrdersService public function approvalNullify($item) { $appro = new \app\common\utils\approval\service\ApprovalFlowService(); - $appro->startNullify('stock_orders_nullify', 'stock_orders', $item->id, [], $item->salesperson_id); + $formData = $this->checkNewOrUsedVehicles($item->id); + $appro->startNullify('stock_orders_nullify', 'stock_orders', $item->id, $formData, $item->salesperson_id); } /** @@ -479,14 +481,19 @@ class StockOrdersService // 检查数据中是否存在该字段且为数组 if (!empty($data[$field]) && is_array($data[$field])) { // 处理该字段下的每个文件 - foreach ($data[$field] as $fileUrl) { + foreach ($data[$field] as $fileInfo) { $fileData = [ 'order_id' => $order->id, 'file_code' => $fileCode, - 'file_url' => $fileUrl, + 'file_url' => $fileInfo['url'] ?? '', 'file_name' => StockOrdersFiles::FILE_CODE[$fileCode], + 'original_name' => $fileInfo['original_name'] ?? StockOrdersFiles::FILE_CODE[$fileCode], ]; - StockOrdersFiles::create($fileData); + + // 只有当file_url不为空时才创建记录 + if (!empty($fileData['file_url'])) { + StockOrdersFiles::create($fileData); + } } } } @@ -905,6 +912,7 @@ class StockOrdersService 'id' => $file->id, 'file_url' => $file->file_url, 'file_full_url' => $this->getFileUrl($file->file_url), + 'original_name' => $file->original_name, ]; } @@ -978,4 +986,42 @@ class StockOrdersService } return (new \app\common\service\OssService)->generatePrivateUrl($fileUrl); } + + /** + * 检查备货单中的车辆是新车还是二手车 + * @param int $stockOrderId 备货单ID + * @return array 返回包含has_new和has_used的数组 + */ + public function checkNewOrUsedVehicles(int $stockOrderId): array + { + // 获取备货单关联的所有车辆项 + $vehicles = StockOrderItems::where('order_id', $stockOrderId)->get(); + + $hasNew = false; + $hasUsed = false; + $submitNote = ''; + + foreach ($vehicles as $vehicle) { + // 判断是否为二手车(mileage > 0) + if ($vehicle->mileage > 0) { + $hasUsed = true; + $submitNote = '本单只有二手车'; + } else { + $hasNew = true; + $submitNote = '本单只有新车'; + } + + // 如果两种类型都已经存在,可以提前退出循环 + if ($hasNew && $hasUsed) { + $submitNote = '本单包含新车和二手车'; + break; + } + } + + return [ + 'has_new' => $hasNew ? 1 : 0, + 'has_used' => $hasUsed ? 1 : 0, + 'submit_note' => $submitNote + ]; + } } \ No newline at end of file diff --git a/app/common/service/SysConfigService.php b/app/common/service/SysConfigService.php new file mode 100644 index 0000000..d52972f --- /dev/null +++ b/app/common/service/SysConfigService.php @@ -0,0 +1,37 @@ +logic = (new SysConfigLogic()); + } + + /** + * 获取系统list + */ + public static function getConfig(string $config_key) + { + $value = Redis::get($config_key); + if (empty($value)) { + $config = (new SysConfigLogic())->findByKey($config_key); + if (empty($config)) { + return null; + } + $value = $config->config_value; + Redis::set($config->config_key, $value, 'EX', 7200); + } + + return $value; + } +} \ No newline at end of file diff --git a/app/common/utils/approval/service/ApprovalFlowService.php b/app/common/utils/approval/service/ApprovalFlowService.php index 6eae8d8..a26b79a 100644 --- a/app/common/utils/approval/service/ApprovalFlowService.php +++ b/app/common/utils/approval/service/ApprovalFlowService.php @@ -68,7 +68,7 @@ class ApprovalFlowService } $this->sendNotification($approverIds, $instance, 'pending', false, $extra); - $this->notifyCCs($firstStep, $instance, 'pending'); + // $this->notifyCCs($firstStep, $instance, 'pending'); $this->pushTodoChanged($approverIds); @@ -193,6 +193,12 @@ class ApprovalFlowService 'updated_at' => $now, ]); $this->onFlowFinalized($instance, $finalStatus); + + // 新增:在流程最终完成时才发本步骤的抄送 + if (!empty($step['cc'])) { + $this->notifyCCs($step, $instance, $notifyAction); + } + $this->sendNotification([$instance->initiator_id], $instance, $notifyAction, false); $this->pushTodoChanged([$approverId]); return ['status' => 'completed', 'msg' => ($finalStatus === 'voided' ? '已作废' : '同意')]; @@ -215,7 +221,7 @@ class ApprovalFlowService $this->insertApprovalRecord($instance, $nextIndex, $uid); } $this->sendNotification($nextApprovers, $instance, 'pending', false); - $this->notifyCCs($nextStep, $instance, 'pending'); + // $this->notifyCCs($nextStep, $instance, 'pending'); $this->pushTodoChanged(array_merge([$approverId], $nextApprovers)); return ['status' => 'next_step', 'msg' => '进行下一步:'.$nextStep['name'] ?? ('Step '.$nextIndex)]; }); diff --git a/app/common/utils/scaffold/templates/paymentFiles.stub b/app/common/utils/scaffold/templates/paymentFiles.stub new file mode 100644 index 0000000..6c9cded --- /dev/null +++ b/app/common/utils/scaffold/templates/paymentFiles.stub @@ -0,0 +1,103 @@ + + +
+ + +
+ 付款单提醒+ |
+
|
+ 您好, +您有新的付款单待处理。请及时查看: + +
请点击下方按钮立即查看详情: + +
+ 立即查看
+
+
+
+ |
+
|
+ © 2025 河南新友合科技有限公司. 保留所有权利。 +这是系统自动发送的邮件,请勿直接回复。 + |
+