FeeStatisticsController.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. <?php
  2. namespace App\Module\Transfer\AdminControllers;
  3. use App\Module\Transfer\Models\TransferFeeDailyStats;
  4. use App\Module\Transfer\Services\FeeStatisticsService;
  5. use UCore\DcatAdmin\AdminController;
  6. use Dcat\Admin\Grid;
  7. use Dcat\Admin\Show;
  8. use Dcat\Admin\Http\Controllers\AdminController as BaseAdminController;
  9. use Illuminate\Http\Request;
  10. use Carbon\Carbon;
  11. use Dcat\Admin\Layout\Content;
  12. use Dcat\Admin\Widgets\Card;
  13. use Dcat\Admin\Widgets\Table;
  14. use Spatie\RouteAttributes\Attributes\Get;
  15. use Spatie\RouteAttributes\Attributes\Post;
  16. /**
  17. * 手续费统计后台控制器
  18. */
  19. class FeeStatisticsController extends AdminController
  20. {
  21. /**
  22. * 标题
  23. */
  24. protected $title = '手续费统计';
  25. /**
  26. * 模型
  27. */
  28. protected string $model = TransferFeeDailyStats::class;
  29. /**
  30. * 列表页面
  31. */
  32. #[Get('transfer/fee-statistics', name: 'admin.transfer.fee-statistics.index')]
  33. public function index(Content $content)
  34. {
  35. return $content
  36. ->title('手续费统计')
  37. ->description('查看Transfer模块手续费统计数据')
  38. ->body($this->grid());
  39. }
  40. /**
  41. * 详情页面
  42. */
  43. #[Get('transfer/fee-statistics/{id}', name: 'admin.transfer.fee-statistics.show')]
  44. public function show($id, Content $content)
  45. {
  46. return $content
  47. ->title('手续费统计详情')
  48. ->description('查看详细统计信息')
  49. ->body($this->detail($id));
  50. }
  51. /**
  52. * 统计概览页面
  53. */
  54. #[Get('transfer/fee-statistics/overview', name: 'admin.transfer.fee-statistics.overview')]
  55. public function overview(Content $content)
  56. {
  57. return $content
  58. ->title('手续费统计概览')
  59. ->description('查看手续费统计概览和趋势')
  60. ->body($this->overviewCards())
  61. ->body($this->trendChart());
  62. }
  63. /**
  64. * 手动执行统计
  65. */
  66. #[Post('transfer/fee-statistics/run', name: 'admin.transfer.fee-statistics.run')]
  67. public function runStatistics(Request $request)
  68. {
  69. try {
  70. $date = $request->input('date', Carbon::yesterday()->format('Y-m-d'));
  71. $rerun = $request->boolean('rerun', false);
  72. if ($rerun) {
  73. $result = FeeStatisticsService::restatistics($date);
  74. } else {
  75. $result = FeeStatisticsService::runDailyStatistics($date);
  76. }
  77. return response()->json([
  78. 'status' => true,
  79. 'message' => '统计执行成功',
  80. 'data' => $result
  81. ]);
  82. } catch (\Exception $e) {
  83. return response()->json([
  84. 'status' => false,
  85. 'message' => '统计执行失败: ' . $e->getMessage()
  86. ]);
  87. }
  88. }
  89. /**
  90. * 数据验证
  91. */
  92. #[Post('transfer/fee-statistics/validate', name: 'admin.transfer.fee-statistics.validate')]
  93. public function validateStatistics(Request $request)
  94. {
  95. try {
  96. $date = $request->input('date', Carbon::yesterday()->format('Y-m-d'));
  97. $result = FeeStatisticsService::validateStatistics($date);
  98. return response()->json([
  99. 'status' => true,
  100. 'message' => $result['valid'] ? '数据验证通过' : '数据验证失败',
  101. 'data' => $result
  102. ]);
  103. } catch (\Exception $e) {
  104. return response()->json([
  105. 'status' => false,
  106. 'message' => '数据验证失败: ' . $e->getMessage()
  107. ]);
  108. }
  109. }
  110. /**
  111. * 创建数据表格
  112. */
  113. protected function grid(): Grid
  114. {
  115. return Grid::make($this->model::with('transferApp'), function (Grid $grid) {
  116. $grid->column('id', 'ID')->sortable();
  117. $grid->column('stat_date', '统计日期')->display(function ($value) {
  118. return Carbon::parse($value)->format('Y-m-d');
  119. })->sortable();
  120. $grid->column('transferApp.title', '应用名称');
  121. $grid->column('total_order_count', '总订单数')->sortable();
  122. $grid->column('total_amount', '总交易金额')->display(function ($value) {
  123. return number_format($value, 4);
  124. })->sortable();
  125. $grid->column('total_fee_amount', '总手续费')->display(function ($value) {
  126. return number_format($value, 4);
  127. })->sortable();
  128. $grid->column('avg_fee_rate', '平均费率')->display(function ($value) {
  129. return number_format($value * 100, 2) . '%';
  130. });
  131. $grid->column('in_order_count', '转入订单数');
  132. $grid->column('in_fee_amount', '转入手续费')->display(function ($value) {
  133. return number_format($value, 4);
  134. });
  135. $grid->column('out_order_count', '转出订单数');
  136. $grid->column('out_fee_amount', '转出手续费')->display(function ($value) {
  137. return number_format($value, 4);
  138. });
  139. $grid->column('last_processed_order_id', '最后处理订单ID');
  140. $grid->column('created_at', '创建时间')->sortable();
  141. // 筛选器
  142. $grid->filter(function (Grid\Filter $filter) {
  143. $filter->equal('transfer_app_id', '应用')->select(
  144. \App\Module\Transfer\Models\TransferApp::pluck('title', 'id')
  145. );
  146. $filter->date('stat_date', '统计日期');
  147. $filter->between('total_fee_amount', '手续费金额');
  148. });
  149. // 默认排序
  150. $grid->model()->orderBy('stat_date', 'desc');
  151. // 禁用创建、编辑、删除按钮
  152. $grid->disableCreateButton();
  153. $grid->disableActions();
  154. // 添加工具栏按钮
  155. $grid->tools(function (Grid\Tools $tools) {
  156. $tools->append('<a href="' . route('admin.transfer.fee-statistics.overview') . '" class="btn btn-primary">统计概览</a>');
  157. });
  158. });
  159. }
  160. /**
  161. * 创建详情显示
  162. */
  163. protected function detail($id): Show
  164. {
  165. return Show::make($id, $this->model::with('transferApp'), function (Show $show) {
  166. $show->field('id', 'ID');
  167. $show->field('stat_date', '统计日期');
  168. $show->field('transferApp.title', '应用名称');
  169. $show->field('transferApp.keyname', '应用标识');
  170. $show->divider('订单统计');
  171. $show->field('total_order_count', '总订单数');
  172. $show->field('total_amount', '总交易金额')->as(function ($value) {
  173. return number_format($value, 4);
  174. });
  175. $show->field('total_fee_amount', '总手续费')->as(function ($value) {
  176. return number_format($value, 4);
  177. });
  178. $show->field('avg_fee_rate', '平均费率')->as(function ($value) {
  179. return number_format($value * 100, 2) . '%';
  180. });
  181. $show->divider('转入统计');
  182. $show->field('in_order_count', '转入订单数');
  183. $show->field('in_total_amount', '转入总金额')->as(function ($value) {
  184. return number_format($value, 4);
  185. });
  186. $show->field('in_fee_amount', '转入手续费')->as(function ($value) {
  187. return number_format($value, 4);
  188. });
  189. $show->field('in_avg_fee_rate', '转入平均费率')->as(function ($value) {
  190. return number_format($value * 100, 2) . '%';
  191. });
  192. $show->divider('转出统计');
  193. $show->field('out_order_count', '转出订单数');
  194. $show->field('out_total_amount', '转出总金额')->as(function ($value) {
  195. return number_format($value, 4);
  196. });
  197. $show->field('out_fee_amount', '转出手续费')->as(function ($value) {
  198. return number_format($value, 4);
  199. });
  200. $show->field('out_avg_fee_rate', '转出平均费率')->as(function ($value) {
  201. return number_format($value * 100, 2) . '%';
  202. });
  203. $show->divider('处理信息');
  204. $show->field('last_processed_order_id', '最后处理订单ID');
  205. $show->field('created_at', '创建时间');
  206. $show->field('updated_at', '更新时间');
  207. });
  208. }
  209. /**
  210. * 汇总卡片
  211. */
  212. protected function summaryCards()
  213. {
  214. // 获取最近7天的统计数据
  215. $recentStats = FeeStatisticsService::getRecentTrend(7);
  216. $totalOrders = $recentStats['summary']['total_orders'] ?? 0;
  217. $totalFee = $recentStats['summary']['total_fee'] ?? 0;
  218. $avgFeeRate = $recentStats['summary']['avg_fee_rate'] ?? 0;
  219. return new Card('最近7天统计汇总', [
  220. new Table(['指标', '数值'], [
  221. ['总订单数', number_format($totalOrders)],
  222. ['总手续费', number_format((float)$totalFee, 4)],
  223. ['平均费率', number_format((float)$avgFeeRate * 100, 2) . '%'],
  224. ['统计天数', count($recentStats['data'] ?? [])],
  225. ])
  226. ]);
  227. }
  228. /**
  229. * 概览卡片
  230. */
  231. protected function overviewCards()
  232. {
  233. // 获取应用汇总统计
  234. $appSummary = FeeStatisticsService::getAppSummary();
  235. $cards = [];
  236. foreach ($appSummary['data'] as $app) {
  237. $cards[] = new Card($app['transfer_app']['title'] ?? '未知应用', [
  238. new Table(['指标', '数值'], [
  239. ['统计天数', $app['stat_days']],
  240. ['总订单数', number_format($app['total_orders'])],
  241. ['总手续费', number_format($app['total_fee'], 4)],
  242. ['平均费率', number_format($app['avg_fee_rate'] * 100, 2) . '%'],
  243. ])
  244. ]);
  245. }
  246. return $cards;
  247. }
  248. /**
  249. * 趋势图表
  250. */
  251. protected function trendChart()
  252. {
  253. // 这里可以添加图表组件,显示手续费趋势
  254. return new Card('手续费趋势图', '图表功能待实现');
  255. }
  256. }