Files
MBTI_wang/api/app/controller/admin/Finance.php

233 lines
8.7 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\controller\admin;
use app\BaseController;
use app\common\service\WechatService;
use think\facade\Db;
use think\facade\Request;
/**
* 企业财务控制器(企业管理端)
*/
class Finance extends BaseController
{
/**
* 财务概览
*/
public function overview()
{
$enterpriseId = $this->resolveEnterpriseId();
if (!$enterpriseId) {
return error('未获取到企业信息', 400);
}
try {
$enterprise = Db::name('enterprises')
->where('id', $enterpriseId)
->field('id, name, balance')
->find();
if (!$enterprise) {
return error('企业不存在', 404);
}
$todayStart = strtotime(date('Y-m-d 00:00:00'));
$monthStart = strtotime(date('Y-m-01 00:00:00'));
$baseOrderQuery = Db::name('orders')
->where('enterpriseId', $enterpriseId)
->whereIn('status', ['paid', 'completed'])
->whereIn('productType', ['face', 'mbti', 'sbti', 'disc', 'pdp', 'ai_deep_report']);
$totalIncomeFen = (int) ((clone $baseOrderQuery)->sum('amount') ?? 0);
$todayIncomeFen = (int) ((clone $baseOrderQuery)->where('payTime', '>=', $todayStart)->sum('amount') ?? 0);
$monthIncomeFen = (int) ((clone $baseOrderQuery)->where('payTime', '>=', $monthStart)->sum('amount') ?? 0);
$paidOrderCount = (int) ((clone $baseOrderQuery)->count());
$manualRechargeFen = (int) (Db::name('finance_records')
->where('enterpriseId', $enterpriseId)
->where('type', 'recharge')
->whereNull('orderId')
->sum('amount') ?? 0);
$frozenCommissionFen = (int) (Db::name('commission_records')
->where('enterpriseId', $enterpriseId)
->where('status', 'frozen')
->sum('commissionFen') ?? 0);
// 本月累计扣款(平台扣费 + 佣金扣减)
$monthConsumeFen = (int) (Db::name('finance_records')
->where('enterpriseId', $enterpriseId)
->where('type', 'consume')
->where('createdAt', '>=', $monthStart)
->sum('amount') ?? 0);
// 今日扣款
$todayConsumeFen = (int) (Db::name('finance_records')
->where('enterpriseId', $enterpriseId)
->where('type', 'consume')
->where('createdAt', '>=', $todayStart)
->sum('amount') ?? 0);
// 建议充值:按本月实际天数日均 × 14 天,低于 500 元按 500 元兜底;余额足够则 0
$balanceFen = (int) ($enterprise['balance'] ?? 0);
$daysElapsed = max(1, (int) date('j'));
$avgDaily = $monthConsumeFen > 0 ? intval($monthConsumeFen / $daysElapsed) : 0;
$suggestThreshold = $avgDaily * 14;
$suggestRechargeFen = 0;
if ($avgDaily > 0 && $balanceFen < $suggestThreshold) {
$suggestRechargeFen = max($suggestThreshold - $balanceFen, 50000); // ≥ 500 元
}
return success([
'enterpriseId' => $enterpriseId,
'enterpriseName' => $enterprise['name'] ?? '',
'balanceFen' => $balanceFen,
'totalIncomeFen' => $totalIncomeFen,
'todayIncomeFen' => $todayIncomeFen,
'monthIncomeFen' => $monthIncomeFen,
'manualRechargeFen' => $manualRechargeFen,
'frozenCommissionFen' => $frozenCommissionFen,
'paidOrderCount' => $paidOrderCount,
'monthConsumeFen' => $monthConsumeFen,
'todayConsumeFen' => $todayConsumeFen,
'avgDailyConsumeFen' => $avgDaily,
'suggestRechargeFen' => $suggestRechargeFen,
]);
} catch (\Throwable $e) {
return error('获取企业财务概览失败:' . $e->getMessage(), 500);
}
}
/**
* 财务流水
*/
public function records()
{
$enterpriseId = $this->resolveEnterpriseId();
if (!$enterpriseId) {
return error('未获取到企业信息', 400);
}
try {
$page = max(1, (int) Request::param('page', 1));
$pageSize = min(100, max(1, (int) Request::param('pageSize', 20)));
$query = Db::name('finance_records')
->where('enterpriseId', $enterpriseId)
->order('createdAt', 'desc')
->order('id', 'desc');
$total = (int) (clone $query)->count();
$list = (clone $query)
->page($page, $pageSize)
->select()
->toArray();
$result = array_map(function ($row) {
$type = (string) ($row['type'] ?? '');
$orderId = isset($row['orderId']) ? (int) $row['orderId'] : 0;
$direction = $type === 'consume' ? 'out' : 'in';
$description = (string) ($row['description'] ?? '');
$typeLabel = $type === 'consume'
? (strpos($description, '平台扣费:') === 0 ? '平台扣费' : '佣金扣减')
: (strpos($description, '企业余额充值') !== false ? '余额充值' : ($orderId > 0 ? '测试收入' : '余额充值'));
return [
'id' => (int) ($row['id'] ?? 0),
'type' => $type,
'typeLabel' => $typeLabel,
'direction' => $direction,
'amountFen' => (int) ($row['amount'] ?? 0),
'balanceBeforeFen' => (int) ($row['balanceBefore'] ?? 0),
'balanceAfterFen' => (int) ($row['balanceAfter'] ?? 0),
'description' => $description,
'orderId' => $orderId ?: null,
'createdAt' => (int) ($row['createdAt'] ?? 0),
];
}, $list);
return success([
'list' => $result,
'total' => $total,
'page' => $page,
'pageSize' => $pageSize,
]);
} catch (\Throwable $e) {
return error('获取财务流水失败:' . $e->getMessage(), 500);
}
}
/**
* 企业手动充值
*/
public function rechargeQrcode()
{
$enterpriseId = $this->resolveEnterpriseId();
if (!$enterpriseId) {
return error('未获取到企业信息', 400);
}
try {
$amountFen = (int) Request::param('amountFen', 0);
if ($amountFen <= 0) {
return error('充值金额必须大于 0', 400);
}
$enterprise = Db::name('enterprises')
->where('id', $enterpriseId)
->field('id, name')
->find();
if (!$enterprise) {
return error('企业不存在', 404);
}
// scene 长度要尽量短,避免超过微信限制
$scene = 'eid=' . $enterpriseId . '&a=' . $amountFen . '&r=1';
$page = 'pages/recharge/index';
$result = WechatService::getWxacodeUnlimited($scene, $page, 430);
if (isset($result['errcode'])) {
return error('获取充值小程序码失败:' . ($result['errmsg'] ?? ''), 500);
}
$binary = $result['binary'] ?? '';
if ($binary === '') {
return error('充值小程序码生成失败', 500);
}
return success([
'enterpriseId' => $enterpriseId,
'enterpriseName' => (string) ($enterprise['name'] ?? ''),
'amountFen' => $amountFen,
'amountYuan' => number_format($amountFen / 100, 2, '.', ''),
'scene' => $scene,
'page' => $page,
'qrcode' => 'data:image/png;base64,' . base64_encode($binary),
]);
} catch (\Throwable $e) {
return error('生成充值二维码失败:' . $e->getMessage(), 500);
}
}
/**
* 解析当前管理账号所属企业
*/
protected function resolveEnterpriseId(): ?int
{
$user = $this->request->user ?? null;
if (!$user || !in_array($user['role'] ?? '', ['admin', 'enterprise_admin'], true)) {
return null;
}
$enterpriseId = (int) ($user['enterpriseId'] ?? 0);
if ($enterpriseId > 0) {
return $enterpriseId;
}
$adminId = (int) ($user['userId'] ?? 0);
if ($adminId <= 0) {
return null;
}
return (int) (Db::name('users')->where('id', $adminId)->value('enterpriseId') ?? 0) ?: null;
}
}