diff --git a/docs/invoice.sh b/docs/invoice.sh
new file mode 100644
index 0000000..1042149
--- /dev/null
+++ b/docs/invoice.sh
@@ -0,0 +1,97 @@
+#get list of invoices
+curl --location 'https://land.dbiz.com//api/method/building_material.building_material.api.invoice.get_list' \
+--header 'Cookie: sid=a0cbe3ea6f9a7e9cf083bbe3139eada68d2357eac0167bcc66cda17d; full_name=Ha%20Duy%20Lam; sid=a0cbe3ea6f9a7e9cf083bbe3139eada68d2357eac0167bcc66cda17d; system_user=yes; user_id=lamhd%40gmail.com; user_image=/files/avatar_0986788766_1763627962.jpg' \
+--header 'X-Frappe-Csrf-Token: 6ff3be4d1f887dbebf86ba4502b05d94b30c0b0569de49b74a7171a9' \
+--header 'Content-Type: application/json' \
+--data '{
+ "limit_page_length" : 0,
+ "limit_start" : 0
+}'
+
+#response
+{
+ "message": [
+ {
+ "name": "ACC-SINV-2025-00041",
+ "posting_date": "2025-12-02",
+ "status": "Chưa thanh toán",
+ "status_color": "Danger",
+ "order_id": null,
+ "grand_total": 486400.0
+ },
+ {
+ "name": "ACC-SINV-2025-00026",
+ "posting_date": "2025-11-25",
+ "status": "Đã trả",
+ "status_color": "Success",
+ "order_id": "SAL-ORD-2025-00119",
+ "grand_total": 1153433.6
+ },
+ {
+ "name": "ACC-SINV-2025-00025",
+ "posting_date": "2025-11-24",
+ "status": "Đã trả",
+ "status_color": "Success",
+ "order_id": "SAL-ORD-2025-00104",
+ "grand_total": 3580257.894
+ }
+ ]
+}
+
+#get invoice detail
+curl --location 'https://land.dbiz.com//api/method/building_material.building_material.api.invoice.get_detail' \
+--header 'Cookie: sid=a0cbe3ea6f9a7e9cf083bbe3139eada68d2357eac0167bcc66cda17d; full_name=Ha%20Duy%20Lam; sid=a0cbe3ea6f9a7e9cf083bbe3139eada68d2357eac0167bcc66cda17d; system_user=yes; user_id=lamhd%40gmail.com; user_image=/files/avatar_0986788766_1763627962.jpg' \
+--header 'X-Frappe-Csrf-Token: 6ff3be4d1f887dbebf86ba4502b05d94b30c0b0569de49b74a7171a9' \
+--header 'Content-Type: application/json' \
+--data '{
+ "name" : "ACC-SINV-2025-00041"
+}'
+
+#response
+{
+ "message": {
+ "name": "ACC-SINV-2025-00041",
+ "posting_date": "2025-12-02",
+ "status": "Chưa thanh toán",
+ "status_color": "Danger",
+ "customer_name": "Ha Duy Lam",
+ "order_id": null,
+ "seller_info": {
+ "phone": "0243 543 0726",
+ "email": "info@viglacera.com.vn",
+ "fax": "(024) 3553 6671",
+ "tax_code": "0105908818",
+ "company_name": "Công Ty Cổ Phần Kinh Doanh Gạch Ốp Lát Viglacera",
+ "address_line1": "Tầng 2 tòa nhà Viglacera, số 1 đại lộ Thăng Long",
+ "city_code": "01",
+ "ward_code": "00637",
+ "city_name": "Thành phố Hà Nội",
+ "ward_name": "Phường Đại Mỗ"
+ },
+ "buyer_info": {
+ "name": "phuoc-thanh toán",
+ "address_title": "phuoc",
+ "address_line1": "123 tt",
+ "phone": "0985225855",
+ "email": null,
+ "fax": null,
+ "tax_code": null,
+ "city_code": "75",
+ "ward_code": "25252",
+ "city_name": "Tỉnh Đồng Nai",
+ "ward_name": "Xã Phú Riềng"
+ },
+ "items": [
+ {
+ "item_name": "Hội An HOA E01",
+ "item_code": "HOA E01",
+ "qty": 1.0,
+ "rate": 486400.0,
+ "amount": 486400.0
+ }
+ ],
+ "total": 486400.0,
+ "discount_amount": 0.0,
+ "grand_total": 486400.0
+ }
+}
\ No newline at end of file
diff --git a/html/invoice-detail.html b/html/invoice-detail.html
new file mode 100644
index 0000000..a2ff811
--- /dev/null
+++ b/html/invoice-detail.html
@@ -0,0 +1,632 @@
+
+
+
+
+
+ Chi tiết Hóa đơn - EuroTile Worker
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Đơn vị bán hàng
+
+
Công ty: CÔNG TY CP EUROTILE VIỆT NAM
+
Mã số thuế: 0301234567
+
Địa chỉ: 123 Đường Nguyễn Văn Linh, Quận 7, TP.HCM
+
Điện thoại: (028) 1900 1234
+
Email: sales@eurotile.vn
+
+
+
+
+
+ Đơn vị mua hàng
+
+
Người mua hàng: Lê Hoàng Hiệp
+
Tên đơn vị: Công ty TNHH Xây dựng Minh Long
+
Mã số thuế: 0134000687
+
Địa chỉ: 11 Đường Hoàng Hữu Nam, Phường Linh Chiểu, TP. Thủ Đức, TP.HCM
+
Điện thoại: 0339797979
+
Email: minhlong.org@gmail.com
+
+
+
+
+
+
+
+
+ Chi tiết hàng hóa
+
+
+
+
+
+ | # |
+ Tên hàng hóa |
+
+ Số lượng |
+ Đơn giá |
+ Thành tiền |
+
+
+
+
+ | 1 |
+
+ Gạch Eurotile MỘC LAM E03
+ SKU: ET-ML-E03-60x60
+ |
+
+ 30,12 |
+ 285.000đ |
+ 8.550.000đ |
+
+
+ | 2 |
+
+ Gạch Eurotile STONE GREY S02
+ SKU: ET-SG-S02-80x80
+ |
+
+ 20,24 |
+ 217.500đ |
+ 4.350.000đ |
+
+
+
+
+
+
+
+ Tổng tiền hàng:
+ 12.900.000đ
+
+
+ Chiết khấu VIP (1%):
+ -129.000đ
+
+
+
+
+ TỔNG THANH TOÁN:
+ 12.771.000đ
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/html/invoice-list.html b/html/invoice-list.html
new file mode 100644
index 0000000..4dfb2f4
--- /dev/null
+++ b/html/invoice-list.html
@@ -0,0 +1,351 @@
+
+
+
+
+
+ Hóa đơn đã mua - EuroTile Worker
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Đơn hàng:
+ #DH001234
+
+
+ Tổng tiền:
+ 12.771.000đ
+
+
+
+
+
+
+
+
+
+
+
+
+ Đơn hàng:
+ #DH001198
+
+
+ Tổng tiền:
+ 85.600.000đ
+
+
+
+
+
+
+
+
+
+
+
+
+ Đơn hàng:
+ #DH001087
+
+
+ Tổng tiền:
+ 42.500.000đ
+
+
+
+
+
+
+
+
+
+
+
+
+ Đơn hàng:
+ #DH000945
+
+
+ Tổng tiền:
+ 28.300.000đ
+
+
+
+
+
+
+
+
+
+
+
+
+ Đơn hàng:
+ #DH000821
+
+
+ Tổng tiền:
+ 56.750.000đ
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lib/core/constants/api_constants.dart b/lib/core/constants/api_constants.dart
index fd351be..a296b51 100644
--- a/lib/core/constants/api_constants.dart
+++ b/lib/core/constants/api_constants.dart
@@ -283,6 +283,18 @@ class ApiConstants {
static const String getPaymentDetail =
'/building_material.building_material.api.payment.get_detail';
+ /// Get invoice list (Frappe API)
+ /// POST /api/method/building_material.building_material.api.invoice.get_list
+ /// Body: { "limit_start": 0, "limit_page_length": 0 }
+ static const String getInvoiceList =
+ '/building_material.building_material.api.invoice.get_list';
+
+ /// Get invoice detail (Frappe API)
+ /// POST /api/method/building_material.building_material.api.invoice.get_detail
+ /// Body: { "name": "ACC-SINV-2025-00041" }
+ static const String getInvoiceDetail =
+ '/building_material.building_material.api.invoice.get_detail';
+
// ============================================================================
// Project Endpoints (Frappe ERPNext)
// ============================================================================
diff --git a/lib/core/router/app_router.dart b/lib/core/router/app_router.dart
index 5131e8d..1ce7af6 100644
--- a/lib/core/router/app_router.dart
+++ b/lib/core/router/app_router.dart
@@ -52,6 +52,8 @@ import 'package:worker/features/showrooms/presentation/pages/design_request_deta
import 'package:worker/features/showrooms/presentation/pages/model_house_detail_page.dart';
import 'package:worker/features/showrooms/presentation/pages/model_houses_page.dart';
import 'package:worker/features/account/presentation/pages/theme_settings_page.dart';
+import 'package:worker/features/invoices/presentation/pages/invoices_page.dart';
+import 'package:worker/features/invoices/presentation/pages/invoice_detail_page.dart';
/// Router Provider
///
@@ -488,6 +490,27 @@ final routerProvider = Provider((ref) {
MaterialPage(key: state.pageKey, child: const ThemeSettingsPage()),
),
+ // Invoices Route
+ GoRoute(
+ path: RouteNames.invoices,
+ name: RouteNames.invoices,
+ pageBuilder: (context, state) =>
+ MaterialPage(key: state.pageKey, child: const InvoicesPage()),
+ ),
+
+ // Invoice Detail Route
+ GoRoute(
+ path: RouteNames.invoiceDetail,
+ name: RouteNames.invoiceDetail,
+ pageBuilder: (context, state) {
+ final invoiceId = state.pathParameters['id'];
+ return MaterialPage(
+ key: state.pageKey,
+ child: InvoiceDetailPage(invoiceId: invoiceId ?? ''),
+ );
+ },
+ ),
+
// Chat List Route
GoRoute(
path: RouteNames.chat,
@@ -638,6 +661,10 @@ class RouteNames {
static const String themeSettings = '$account/theme-settings';
static const String settings = '$account/settings';
+ // Invoice Routes
+ static const String invoices = '/invoices';
+ static const String invoiceDetail = '$invoices/:id';
+
// Promotions & Notifications Routes
static const String promotions = '/promotions';
static const String promotionDetail = '$promotions/:id';
diff --git a/lib/features/account/presentation/pages/account_page.dart b/lib/features/account/presentation/pages/account_page.dart
index a7eed8b..8ff7919 100644
--- a/lib/features/account/presentation/pages/account_page.dart
+++ b/lib/features/account/presentation/pages/account_page.dart
@@ -140,6 +140,14 @@ class AccountPage extends ConsumerWidget {
context.push(RouteNames.orders);
},
),
+ AccountMenuItem(
+ icon: FontAwesomeIcons.fileInvoiceDollar,
+ title: 'Hóa đơn đã mua',
+ subtitle: 'Xem các hóa đơn đã xuất',
+ onTap: () {
+ context.push(RouteNames.invoices);
+ },
+ ),
AccountMenuItem(
icon: FontAwesomeIcons.locationDot,
title: 'Địa chỉ đã lưu',
diff --git a/lib/features/invoices/data/datasources/invoice_remote_datasource.dart b/lib/features/invoices/data/datasources/invoice_remote_datasource.dart
new file mode 100644
index 0000000..2fb7259
--- /dev/null
+++ b/lib/features/invoices/data/datasources/invoice_remote_datasource.dart
@@ -0,0 +1,80 @@
+/// Invoice Remote Data Source
+///
+/// Handles API calls for invoice-related data.
+library;
+
+import 'package:worker/core/constants/api_constants.dart';
+import 'package:worker/core/network/dio_client.dart';
+import 'package:worker/features/invoices/data/models/invoice_model.dart';
+
+/// Invoice Remote Data Source
+class InvoiceRemoteDataSource {
+ const InvoiceRemoteDataSource(this._dioClient);
+
+ final DioClient _dioClient;
+
+ /// Get invoices list
+ ///
+ /// Calls: POST /api/method/building_material.building_material.api.invoice.get_list
+ /// Returns: List of invoices
+ Future> getInvoicesList({
+ int limitStart = 0,
+ int limitPageLength = 0,
+ }) async {
+ try {
+ final response = await _dioClient.post