317 lines
10 KiB
PHP
317 lines
10 KiB
PHP
<?php
|
|
|
|
namespace Modules\Account\Services;
|
|
|
|
use Illuminate\Http\Request;
|
|
use Modules\Account\Models\Bill;
|
|
use Modules\Account\Models\FamilyMember;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class StatisticsService
|
|
{
|
|
/**
|
|
* 获取统计概览
|
|
*/
|
|
public function getOverview(Request $request)
|
|
{
|
|
$userId = auth('api')->user()['uid'];
|
|
$year = $request->input('year');
|
|
$month = $request->input('month');
|
|
$dataType = $request->input('data_type', 'family'); // 默认为家庭数据
|
|
|
|
// 获取用户所在的家庭ID
|
|
$userFamilyId = $this->getUserFamilyId($userId);
|
|
|
|
// 查询当月的账单
|
|
$query = Bill::query();
|
|
|
|
if ($year && $month) {
|
|
$query->whereMonth('bill_date', str_pad($month, 2, '0', STR_PAD_LEFT))
|
|
->whereYear('bill_date', $year);
|
|
} else {
|
|
$query->whereMonth('bill_date', date('m'))
|
|
->whereYear('bill_date', date('Y'));
|
|
}
|
|
|
|
// 根据data_type参数判断数据类型
|
|
if ($dataType === 'personal') {
|
|
// 个人数据:只显示当前用户的账单
|
|
$query->where('user_id', $userId);
|
|
} elseif ($dataType === 'family' && $userFamilyId) {
|
|
// 家庭数据:显示用户所在家庭的账单
|
|
$query->where('family_id', $userFamilyId);
|
|
} else {
|
|
// 默认显示个人数据
|
|
$query->where('user_id', $userId);
|
|
}
|
|
|
|
$bills = $query->get();
|
|
|
|
$income = (float) $bills->where('type', 'income')->sum('amount');
|
|
$expense = (float) $bills->where('type', 'expense')->sum('amount');
|
|
|
|
return [
|
|
'income' => $income,
|
|
'expense' => $expense,
|
|
'balance' => $income - $expense
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 获取收支趋势
|
|
*/
|
|
public function getTrend(Request $request)
|
|
{
|
|
$userId = auth('api')->user()['uid'];
|
|
$year = $request->input('year');
|
|
$month = $request->input('month');
|
|
$days = 7; // 最近7天
|
|
$dataType = $request->input('data_type', 'family'); // 默认为家庭数据
|
|
|
|
// 获取用户所在的家庭ID
|
|
$userFamilyId = $this->getUserFamilyId($userId);
|
|
|
|
$data = [];
|
|
for ($i = $days - 1; $i >= 0; $i--) {
|
|
$date = date('Y-m-d', strtotime("-$i days"));
|
|
|
|
$query = Bill::whereDate('bill_date', $date);
|
|
|
|
// 根据data_type参数判断数据类型
|
|
if ($dataType === 'personal') {
|
|
// 个人数据:只显示当前用户的账单
|
|
$query->where('user_id', $userId);
|
|
} elseif ($dataType === 'family' && $userFamilyId) {
|
|
// 家庭数据:显示用户所在家庭的账单
|
|
$query->where('family_id', $userFamilyId);
|
|
} else {
|
|
// 默认显示个人数据
|
|
$query->where('user_id', $userId);
|
|
}
|
|
|
|
$bills = $query->get();
|
|
$data[] = [
|
|
'date' => $date,
|
|
'income' => (float) $bills->where('type', 'income')->sum('amount'),
|
|
'expense' => (float) $bills->where('type', 'expense')->sum('amount')
|
|
];
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* 获取分类统计
|
|
*/
|
|
public function getCategory(Request $request)
|
|
{
|
|
$userId = auth('api')->user()['uid'];
|
|
$type = $request->input('type', 'expense');
|
|
$year = $request->input('year');
|
|
$month = $request->input('month');
|
|
$dataType = $request->input('data_type', 'family'); // 默认为家庭数据
|
|
|
|
// 获取用户所在的家庭ID
|
|
$userFamilyId = $this->getUserFamilyId($userId);
|
|
|
|
$query = Bill::where('type', $type);
|
|
|
|
if ($year && $month) {
|
|
$query->whereMonth('bill_date', str_pad($month, 2, '0', STR_PAD_LEFT))
|
|
->whereYear('bill_date', $year);
|
|
} else {
|
|
$query->whereMonth('bill_date', date('m'))
|
|
->whereYear('bill_date', date('Y'));
|
|
}
|
|
|
|
// 根据data_type参数判断数据类型
|
|
if ($dataType === 'personal') {
|
|
// 个人数据:只显示当前用户的账单
|
|
$query->where('user_id', $userId);
|
|
} elseif ($dataType === 'family' && $userFamilyId) {
|
|
// 家庭数据:显示用户所在家庭的账单
|
|
$query->where('family_id', $userFamilyId);
|
|
} else {
|
|
// 默认显示个人数据
|
|
$query->where('user_id', $userId);
|
|
}
|
|
|
|
$bills = $query->get();
|
|
|
|
// 按分类汇总
|
|
$data = $bills->groupBy('category')->map(function ($items) use ($type) {
|
|
return [
|
|
'category_id' => $this->getCategoryId($items->first()->category, $type),
|
|
'amount' => (float) $items->sum('amount')
|
|
];
|
|
})->sortByDesc('amount')->values();
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* 根据分类名称获取分类ID
|
|
*/
|
|
private function getCategoryId($categoryName, $type)
|
|
{
|
|
$expenseMap = [
|
|
'餐饮' => 1, '交通' => 2, '购物' => 3, '娱乐' => 4,
|
|
'医疗' => 5, '教育' => 6, '居住' => 7, '其他' => 8
|
|
];
|
|
$incomeMap = [
|
|
'工资' => 101, '奖金' => 102, '投资' => 103, '兼职' => 104, '其他' => 105
|
|
];
|
|
|
|
$map = $type === 'income' ? $incomeMap : $expenseMap;
|
|
return $map[$categoryName] ?? ($type === 'income' ? 105 : 8);
|
|
}
|
|
|
|
/**
|
|
* 获取月度报表
|
|
*/
|
|
public function getMonthly(Request $request)
|
|
{
|
|
$userId = auth('api')->user()['uid'];
|
|
$year = $request->input('year', date('Y'));
|
|
$dataType = $request->input('data_type', 'family'); // 默认为家庭数据
|
|
|
|
// 获取用户所在的家庭ID
|
|
$userFamilyId = $this->getUserFamilyId($userId);
|
|
|
|
$data = [];
|
|
for ($month = 1; $month <= 12; $month++) {
|
|
$query = Bill::whereMonth('bill_date', $month)
|
|
->whereYear('bill_date', $year);
|
|
|
|
// 根据data_type参数判断数据类型
|
|
if ($dataType === 'personal') {
|
|
// 个人数据:只显示当前用户的账单
|
|
$query->where('user_id', $userId);
|
|
} elseif ($dataType === 'family' && $userFamilyId) {
|
|
// 家庭数据:显示用户所在家庭的账单
|
|
$query->where('family_id', $userFamilyId);
|
|
} else {
|
|
// 默认显示个人数据
|
|
$query->where('user_id', $userId);
|
|
}
|
|
|
|
$bills = $query->get();
|
|
|
|
$data[] = [
|
|
'month' => sprintf('%d-%02d', $year, $month),
|
|
'income' => (float) number_format($bills->where('type', 'income')->sum('amount'), 2),
|
|
'expense' => (float) number_format($bills->where('type', 'expense')->sum('amount'), 2),
|
|
'bill_count' => $bills->count()
|
|
];
|
|
}
|
|
|
|
return [
|
|
'year' => $year,
|
|
'data' => $data
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 获取年度报表
|
|
*/
|
|
public function getYearly(Request $request)
|
|
{
|
|
$userId = auth('api')->user()['uid'];
|
|
$years = $request->input('years', 5);
|
|
$dataType = $request->input('data_type', 'family'); // 默认为家庭数据
|
|
|
|
// 获取用户所在的家庭ID
|
|
$userFamilyId = $this->getUserFamilyId($userId);
|
|
|
|
$data = [];
|
|
for ($i = $years - 1; $i >= 0; $i--) {
|
|
$year = date('Y', strtotime("-$i years"));
|
|
|
|
$query = Bill::whereYear('bill_date', $year);
|
|
|
|
// 根据data_type参数判断数据类型
|
|
if ($dataType === 'personal') {
|
|
// 个人数据:只显示当前用户的账单
|
|
$query->where('user_id', $userId);
|
|
} elseif ($dataType === 'family' && $userFamilyId) {
|
|
// 家庭数据:显示用户所在家庭的账单
|
|
$query->where('family_id', $userFamilyId);
|
|
} else {
|
|
// 默认显示个人数据
|
|
$query->where('user_id', $userId);
|
|
}
|
|
|
|
$bills = $query->get();
|
|
|
|
$data[] = [
|
|
'year' => $year,
|
|
'income' => (float) number_format($bills->where('type', 'income')->sum('amount'), 2),
|
|
'expense' => (float) number_format($bills->where('type', 'expense')->sum('amount'), 2),
|
|
'bill_count' => $bills->count()
|
|
];
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* 获取用户所在的家庭ID
|
|
*/
|
|
private function getUserFamilyId($userId)
|
|
{
|
|
$familyMember = FamilyMember::where('user_id', $userId)->first();
|
|
return $familyMember ? $familyMember->family_id : null;
|
|
}
|
|
|
|
/**
|
|
* 获取个人中心统计数据
|
|
*/
|
|
public function getDashboardStats(Request $request)
|
|
{
|
|
$userId = auth('api')->user()['uid'];
|
|
$dataType = $request->input('data_type', 'family'); // 默认为家庭数据
|
|
|
|
// 获取用户所在的家庭ID
|
|
$userFamilyId = $this->getUserFamilyId($userId);
|
|
|
|
// 统计账单数
|
|
$billQuery = Bill::query();
|
|
|
|
// 根据data_type参数判断数据类型
|
|
if ($dataType === 'personal') {
|
|
// 个人数据:只统计当前用户的账单
|
|
$billQuery->where('user_id', $userId);
|
|
} elseif ($dataType === 'family' && $userFamilyId) {
|
|
// 家庭数据:统计用户所在家庭的账单
|
|
$billQuery->where('family_id', $userFamilyId);
|
|
} else {
|
|
// 默认统计个人数据
|
|
$billQuery->where('user_id', $userId);
|
|
}
|
|
|
|
$billCount = $billQuery->count();
|
|
|
|
// 统计记账天数(计算从第一个账单到现在的天数)
|
|
$days = 0;
|
|
$firstBill = $billQuery->orderBy('bill_date', 'asc')->first();
|
|
if ($firstBill) {
|
|
$firstDate = new \DateTime($firstBill->bill_date);
|
|
$now = new \DateTime();
|
|
$interval = $firstDate->diff($now);
|
|
$days = $interval->days + 1; // +1 包含当天
|
|
}
|
|
|
|
// 统计家庭成员数
|
|
$familyMembers = 0;
|
|
if ($userFamilyId) {
|
|
$familyMembers = FamilyMember::where('family_id', $userFamilyId)->count();
|
|
}
|
|
|
|
return [
|
|
'bill_count' => $billCount,
|
|
'days' => $days,
|
|
'family_members' => $familyMembers
|
|
];
|
|
}
|
|
}
|