Họ và tên: Nguyễn Đình Hiếu
Mã sinh viên: 23010827
Lớp: CNTT_9
Mục đích chính của đề tài này là phát triển một ứng dụng quản lý chi tiêu cá nhân hiệu quả, nhằm giúp người dùng theo dõi, kiểm soát và lập kế hoạch chi tiêu một cách thông minh và hiệu quả. Một trong những mục tiêu quan trọng nhất là xây dựng một ứng dụng dễ dàng sử dụng. Việc thiết kế giao diện và trải nghiệm của người dùng là yếu tố quan trọng giúp tăng cường tính tiếp cận và số lượng sử dụng của người dùng.
Ngoài ra ứng dụng cũng cần tích hợp các tính năng cần thiết để hỗ trợ người dung trong việc quản lý tài chính cá nhân. Các tính năng này có thể bao gồm:
Khả năng nhập thông tin chi tiêu dễ dàng và nhanh chóng.
Tính năng tự động phân loại các khoản chi tiêu theo danh mục khác nhau (ví dụ: ăn uống, đi lại, giải trí,…).
Khả năng thiết lập mục tiêu tiết kiệm và theo dõi tiến độ đối với các mục tiêu này.
Cung cấp các báo cáo, phân tích chi tiêu để người dùng hiểu rõ hơn về mô hình chi tiêu của mình và từ đó có thể đưa ra các quyết định tài chính thông minh hơn trong tương lai.
Đối tượng nghiên cứu: Hệ thống ứng dụng quản lý chi tiêu.
Đối tượng sử dụng: Các cá nhân có nhu cầu quản lý chi tiêu cá nhân.
PHP (Laravel framework)
Laravel Breeze
MySQL (Aiven Cloud)
Eloquent ORM (Hệ thống ORM giúp tương tác với CSDL)
Frontend & UI (Blade engine, Tailwind CSS, Bootstrap 5)
Laravel Security (Framework hỗ trợ)
Sơ đồ tổng quát
Sử dụng hệ thống
Link README.MD: https://hieudinhnguyen.github.io/Web_chi_tieu_ca_nhan/
Link Repo: https://github.com/HieuDinhNguyen/Web_chi_tieu_ca_nhan
Link demo: https://youtu.be/AsZ90fDY3xs
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Factories\HasFactory;
class Expense extends Model { use HasFactory;
protected $fillable = ['description', 'amount', 'date', 'expense_category_id'];
public function category()
{
return $this->belongsTo(ExpenseCategory::class, 'expense_category_id');
} } ```
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Factories\HasFactory;
class ExpenseCategory extends Model { use HasFactory; protected $fillable = [ ‘name’ ]; public function expenses() { return $this->hasMany(Expense::class); } }
* Income
```markdown
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Income extends Model
{
use HasFactory;
protected $fillable = [
'description',
'amount',
'date'
];
public function category()
{
return $this->belongsTo(IncomeCategory::class, 'income_category_id');
}
}
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Factories\HasFactory;
class IncomeCategory extends Model { use HasFactory; protected $fillable = [ ‘name’ ]; public function incomes() { return $this->hasMany(Income::class); } }
## Xây dựng CRUD cho các đối tượng
* ExpenseController
```markdown
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Expense;
use App\Models\ExpenseCategory;
use Exception;
class ExpenseController extends Controller
{
public function index()
{
$expenses = Expense::with('category')->latest()->get();
return view('Expense.index', compact('expenses'));
}
// Hiển thị form thêm mới
public function create()
{
$categories = ExpenseCategory::all();
return view('Expense.create', compact('categories'));
}
// Lưu chi tiêu mới
public function store(Request $request)
{
$validated = $request->validate([
'description' => 'required|string|max:255',
'amount' => 'required|numeric|min:0',
'date' => 'required|date',
'expense_category_id' => 'required|exists:expense_categories,id',
]);
try {
Expense::create($validated);
return redirect()->route('Expense.index')->with('success', 'Thêm chi tiêu thành công!');
} catch (Exception $e) {
return redirect()->back()->with('error', 'Không thể thêm chi tiêu.');
}
}
// Hiển thị form sửa
public function edit($id)
{
$expense = Expense::findOrFail($id);
$categories = ExpenseCategory::all();
return view('Expense.edit', compact('expense', 'categories'));
}
// Cập nhật chi tiêu
public function update(Request $request, $id)
{
$expense = Expense::findOrFail($id);
$validated = $request->validate([
'description' => 'required|string|max:255',
'amount' => 'required|numeric|min:0',
'date' => 'required|date',
'expense_category_id' => 'required|exists:expense_categories,id',
]);
try {
$expense->update($validated);
return redirect()->route('Expense.index')->with('success', 'Cập nhật chi tiêu thành công!');
} catch (Exception $e) {
return redirect()->back()->with('error', 'Không thể cập nhật chi tiêu.');
}
}
// Xoá chi tiêu
public function destroy($id)
{
$expense = Expense::findOrFail($id);
try {
$expense->delete();
return redirect()->route('Expense.index')->with('success', 'Xoá chi tiêu thành công!');
} catch (Exception $e) {
return redirect()->back()->with('error', 'Không thể xoá chi tiêu.');
}
}
// Hiển thị chi tiết chi tiêu
public function show($id)
{
$expense = Expense::with('category')->findOrFail($id);
return view('Expense.show', compact('expense'));
}
}
use Illuminate\Http\Request; use App\Models\ExpenseCategory;
class ExpenseCategoryController extends Controller { public function index() { $categories = ExpenseCategory::all(); return view(‘ExpenseCategory.index’, compact(‘categories’)); }
public function create()
{
return view('ExpenseCategory.create');
}
public function store(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
]);
ExpenseCategory::create($request->only('name'));
return redirect()->route('ExpenseCategory.index')->with('success', 'Danh mục đã được thêm.');
}
public function edit(ExpenseCategory $expenseCategory)
{
return view('ExpenseCategory.edit', compact('expenseCategory'));
}
public function update(Request $request, ExpenseCategory $expenseCategory)
{
$request->validate([
'name' => 'required|string|max:255',
]);
$expenseCategory->update($request->only('name'));
return redirect()->route('ExpenseCategory.index')->with('success', 'Cập nhật thành công.');
}
public function destroy(ExpenseCategory $expenseCategory)
{
$expenseCategory->delete();
return redirect()->route('ExpenseCategory.index')->with('success', 'Đã xoá danh mục.');
}
public function show(ExpenseCategory $expenseCategory)
{
return view('ExpenseCategory.show', compact('expenseCategory'));
} } ``` * IncomeController ```markdown namespace App\Http\Controllers;
use Illuminate\Http\Request; use App\Models\Income; use App\Models\IncomeCategory;
class IncomeController extends Controller { public function index() { $incomes = Income::with(‘category’)->latest()->paginate(10); return view(‘Income.index’, compact(‘incomes’)); }
public function create()
{
$categories = IncomeCategory::all();
return view('Income.create', compact('categories'));
}
public function store(Request $request)
{
$request->validate([
'description' => 'nullable|string|max:255',
'amount' => 'required|numeric|min:0',
'date' => 'required|date',
'income_category_id' => 'required|exists:income_categories,id',
]);
Income::create($request->all());
return redirect()->route('Income.index')->with('success', 'Thu nhập đã được thêm.');
}
public function show(Income $income)
{
return view('Income.show', compact('income'));
}
public function edit(Income $income)
{
$categories = IncomeCategory::all();
return view('Income.edit', compact('income', 'categories'));
}
public function update(Request $request, Income $income)
{
$request->validate([
'description' => 'nullable|string|max:255',
'amount' => 'required|numeric|min:0',
'date' => 'required|date',
'income_category_id' => 'required|exists:income_categories,id',
]);
$income->update($request->all());
return redirect()->route('Income.index')->with('success', 'Thu nhập đã được cập nhật.');
}
public function destroy(Income $income)
{
$income->delete();
return redirect()->route('Income.index')->with('success', 'Thu nhập đã được xoá.');
}
}
* IncomeCategoryController
```markdown
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\IncomeCategory;
class IncomeCategoryController extends Controller
{
public function index()
{
$categories = IncomeCategory::withCount('incomes')->get();
return view('IncomeCategory.index', compact('categories'));
}
public function create()
{
return view('IncomeCategory.create');
}
public function store(Request $request)
{
$request->validate(['name' => 'required|string|max:255']);
IncomeCategory::create($request->only('name'));
return redirect()->route('IncomeCategory.index')->with('success', 'Đã thêm danh mục.');
}
public function show(IncomeCategory $incomeCategory)
{
$incomeCategory->load('incomes');
return view('IncomeCategory.show', compact('incomeCategory'));
}
public function edit(IncomeCategory $incomeCategory)
{
return view('IncomeCategory.edit', compact('incomeCategory'));
}
public function update(Request $request, IncomeCategory $incomeCategory)
{
$request->validate(['name' => 'required|string|max:255']);
$incomeCategory->update($request->only('name'));
return redirect()->route('IncomeCategory.index')->with('success', 'Đã cập nhật.');
}
public function destroy(IncomeCategory $incomeCategory)
{
$incomeCategory->delete();
return redirect()->route('IncomeCategory.index')->with('success', 'Đã xoá danh mục.');
}
}
@csrf @method('PUT')
<div class="mb-3">
<label class="form-label">Mô tả</label>
<input type="text" name="description" class="form-control" value="">
</div>