Files
account/modules/Account/app/Services/BillService.php
2026-01-18 22:40:12 +08:00

347 lines
10 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');
$dataType = $request->input('data_type', 'family'); // 默认为家庭数据
// 获取用户所在的家庭ID
$userFamilyId = $this->getUserFamilyId($userId);
$query = Bill::with(['user:uid,nickname,username', 'family:id,name']);
// 根据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);
}
// 年月筛选
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 ($dataType === 'personal') {
$monthExpense->where('user_id', $userId);
$monthIncome->where('user_id', $userId);
} elseif ($dataType === 'family' && $userFamilyId) {
$monthExpense->where('family_id', $userFamilyId);
$monthIncome->where('family_id', $userFamilyId);
} 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'];
// 如果前端没有指定family_id自动获取用户所在的家庭
if (empty($data['family_id'])) {
$userFamilyId = $this->getUserFamilyId($userId);
if ($userFamilyId) {
$data['family_id'] = $userFamilyId;
}
} else {
// 检查家庭权限
$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_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']);
}
// 移除前端字段
unset($data['category_id'], $data['date']);
$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) {
throw new \Exception('无权查看此账单');
}
// 转换数据格式以匹配前端
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
];
}
/**
* 检查家庭访问权限
*/
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;
}
}