Files
account/modules/Account/app/Services/BillService.php
2026-01-18 20:17:59 +08:00

315 lines
9.1 KiB
PHP
Raw 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 Modules\Account\Services;
use Illuminate\Http\Request;
use Modules\Account\Models\Bill;
use Illuminate\Support\Facades\DB;
class BillService
{
/**
* 获取账单列表
*/
public function getList(Request $request)
{
$userId = auth('api')->user()['uid'];
$page = $request->input('page', 1);
$limit = $request->input('limit', 20);
$type = $request->input('type');
$year = $request->input('year');
$month = $request->input('month');
$startDate = $request->input('start_date');
$endDate = $request->input('end_date');
$familyId = $request->input('family_id');
// 获取用户所在的家庭ID
$userFamilyId = $this->getUserFamilyId($userId);
$query = Bill::with(['user:uid,nickname,username', 'family:id,name']);
// 如果用户加入了家庭且没有指定family_id则显示家庭账单
if ($userFamilyId && !$familyId) {
$query->where('family_id', $userFamilyId);
} elseif ($familyId) {
// 如果指定了family_id则显示该家庭的账单
$query->where('family_id', $familyId);
} else {
// 否则显示个人账单
$query->where('user_id', $userId);
}
// 年月筛选
if ($year && $month) {
$startDate = $year . '-' . str_pad($month, 2, '0', STR_PAD_LEFT) . '-01';
$endDate = $year . '-' . str_pad($month, 2, '0', STR_PAD_LEFT) . '-31';
}
// 日期范围筛选
if ($startDate) {
$query->where('bill_date', '>=', $startDate);
}
if ($endDate) {
$query->where('bill_date', '<=', $endDate);
}
// 类型筛选
if ($type && in_array($type, ['income', 'expense'])) {
$query->where('type', $type);
}
$bills = $query->orderBy('bill_date', 'desc')
->orderBy('created_at', 'desc')
->paginate($limit, ['*'], 'page', $page);
// 计算本月收支
$monthExpense = Bill::query();
$monthIncome = Bill::query();
// 同样的家庭查询逻辑
if ($userFamilyId && !$familyId) {
$monthExpense->where('family_id', $userFamilyId);
$monthIncome->where('family_id', $userFamilyId);
} elseif ($familyId) {
$monthExpense->where('family_id', $familyId);
$monthIncome->where('family_id', $familyId);
} else {
$monthExpense->where('user_id', $userId);
$monthIncome->where('user_id', $userId);
}
if ($startDate) {
$monthExpense->where('bill_date', '>=', $startDate);
$monthIncome->where('bill_date', '>=', $startDate);
}
if ($endDate) {
$monthExpense->where('bill_date', '<=', $endDate);
$monthIncome->where('bill_date', '<=', $endDate);
}
$monthExpense->where('type', 'expense');
$monthIncome->where('type', 'income');
// 转换数据格式以匹配前端
$list = collect($bills->items())->map(function($bill) {
return [
'id' => $bill->id,
'type' => $bill->type,
'amount' => (float)$bill->amount,
'category' => $bill->category,
'category_id' => $this->getCategoryId($bill->category, $bill->type),
'remark' => $bill->remark,
'date' => $bill->bill_date,
'bill_date' => $bill->bill_date,
'created_at' => $bill->created_at->format('Y-m-d H:i:s'),
'user' => $bill->user,
'family' => $bill->family
];
})->toArray();
return [
'list' => $list,
'month_expense' => (float)$monthExpense->sum('amount'),
'month_income' => (float)$monthIncome->sum('amount'),
'pagination' => [
'current_page' => $bills->currentPage(),
'total' => $bills->total(),
'per_page' => $bills->perPage(),
'last_page' => $bills->lastPage()
]
];
}
/**
* 根据分类名称获取分类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 add(Request $request)
{
$userId = auth('api')->user()['uid'];
$data = $request->validate([
'type' => 'required|in:income,expense',
'amount' => 'required|numeric|min:0.01',
'category_id' => 'required|integer',
'remark' => 'nullable|string|max:255',
'date' => 'required|date',
'family_id' => 'nullable|integer|exists:account_families,id'
]);
// 将category_id转换为category字符串
$categoryMap = $this->getCategoryMap($data['type']);
if (!isset($categoryMap[$data['category_id']])) {
throw new \Exception('分类不存在');
}
$data['category'] = $categoryMap[$data['category_id']];
$data['bill_date'] = $data['date'];
// 检查家庭权限
if (!empty($data['family_id'])) {
$this->checkFamilyAccess($userId, $data['family_id']);
}
$data['user_id'] = $userId;
// 移除前端字段
unset($data['category_id'], $data['date']);
return Bill::create($data);
}
/**
* 获取分类映射
*/
private function getCategoryMap($type)
{
if ($type === 'income') {
return [
101 => '工资',
102 => '奖金',
103 => '投资',
104 => '兼职',
105 => '其他'
];
} else {
return [
1 => '餐饮',
2 => '交通',
3 => '购物',
4 => '娱乐',
5 => '医疗',
6 => '教育',
7 => '居住',
8 => '其他'
];
}
}
/**
* 编辑账单
*/
public function edit(Request $request)
{
$userId = auth('api')->user()['uid'];
$id = $request->input('id');
$bill = Bill::findOrFail($id);
// 验证权限
if ($bill->user_id != $userId) {
throw new \Exception('无权操作此账单');
}
$data = $request->validate([
'type' => 'required|in:income,expense',
'amount' => 'required|numeric|min:0.01',
'category' => 'required|string|max:50',
'remark' => 'nullable|string|max:255',
'bill_date' => 'required|date',
'family_id' => 'nullable|integer|exists:account_families,id'
]);
// 检查家庭权限
if (!empty($data['family_id'])) {
$this->checkFamilyAccess($userId, $data['family_id']);
}
$bill->update($data);
return $bill;
}
/**
* 删除账单
*/
public function delete(Request $request)
{
$userId = auth('api')->user()['uid'];
$id = $request->input('id');
$bill = Bill::findOrFail($id);
// 验证权限
if ($bill->user_id != $userId) {
throw new \Exception('无权删除此账单');
}
return $bill->delete();
}
/**
* 获取账单详情
*/
public function detail(Request $request)
{
$userId = auth('api')->user()['uid'];
$id = $request->input('id');
$bill = Bill::with(['user:uid,nickname,username', 'family:id,name,owner_id'])
->findOrFail($id);
// 验证权限
if ($bill->user_id != $userId && !in_array($userId, $bill->family->members->pluck('uid')->toArray())) {
throw new \Exception('无权查看此账单');
}
return $bill;
}
/**
* 检查家庭访问权限
*/
private function checkFamilyAccess($userId, $familyId)
{
$isMember = DB::table('account_family_members')
->where('family_id', $familyId)
->where('user_id', $userId)
->exists();
if (!$isMember) {
throw new \Exception('您不是该家庭成员');
}
}
/**
* 获取用户所在的家庭ID
*/
private function getUserFamilyId($userId)
{
$familyMember = DB::table('account_family_members')
->where('user_id', $userId)
->first();
return $familyMember ? $familyMember->family_id : null;
}
}