add payments screen

This commit is contained in:
Phuoc Nguyen
2025-10-27 10:45:03 +07:00
parent 830ef7e2a2
commit 90a02e1000
8 changed files with 1508 additions and 5 deletions

View File

@@ -0,0 +1,248 @@
/// Local Data Source: Invoices
///
/// Provides mock invoice data for development and testing.
library;
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:worker/features/orders/data/models/invoice_model.dart';
/// Invoices Local Data Source
///
/// Manages local mock invoice data.
class InvoicesLocalDataSource {
/// Get all mock invoices
Future<List<InvoiceModel>> getAllInvoices() async {
try {
debugPrint('[InvoicesLocalDataSource] Loading mock invoices...');
// Parse mock JSON data
final decoded = jsonDecode(_mockInvoicesJson);
if (decoded is! List) {
throw Exception('Invalid JSON format: expected List');
}
final invoices = (decoded as List<dynamic>)
.map((json) => InvoiceModel.fromJson(json as Map<String, dynamic>))
.toList();
debugPrint('[InvoicesLocalDataSource] Loaded ${invoices.length} invoices');
return invoices;
} catch (e, stackTrace) {
debugPrint('[InvoicesLocalDataSource] Error loading invoices: $e');
debugPrint('Stack trace: $stackTrace');
rethrow;
}
}
/// Get invoices by status
Future<List<InvoiceModel>> getInvoicesByStatus(String status) async {
try {
final allInvoices = await getAllInvoices();
final filtered = allInvoices
.where((invoice) => invoice.status.name == status)
.toList();
debugPrint(
'[InvoicesLocalDataSource] Filtered ${filtered.length} invoices with status: $status',
);
return filtered;
} catch (e) {
debugPrint('[InvoicesLocalDataSource] Error filtering invoices: $e');
rethrow;
}
}
/// Search invoices by invoice number or order ID
Future<List<InvoiceModel>> searchInvoices(String query) async {
try {
if (query.isEmpty) {
return getAllInvoices();
}
final allInvoices = await getAllInvoices();
final filtered = allInvoices
.where(
(invoice) =>
invoice.invoiceNumber.toLowerCase().contains(query.toLowerCase()) ||
(invoice.orderId?.toLowerCase().contains(query.toLowerCase()) ?? false),
)
.toList();
debugPrint(
'[InvoicesLocalDataSource] Found ${filtered.length} invoices matching "$query"',
);
return filtered;
} catch (e) {
debugPrint('[InvoicesLocalDataSource] Error searching invoices: $e');
rethrow;
}
}
/// Get invoice by ID
Future<InvoiceModel?> getInvoiceById(String invoiceId) async {
try {
final allInvoices = await getAllInvoices();
final invoice = allInvoices.firstWhere(
(invoice) => invoice.invoiceId == invoiceId,
orElse: () => throw Exception('Invoice not found: $invoiceId'),
);
debugPrint('[InvoicesLocalDataSource] Found invoice: ${invoice.invoiceNumber}');
return invoice;
} catch (e) {
debugPrint('[InvoicesLocalDataSource] Error getting invoice: $e');
return null;
}
}
/// Get overdue invoices
Future<List<InvoiceModel>> getOverdueInvoices() async {
try {
final allInvoices = await getAllInvoices();
final overdue = allInvoices
.where((invoice) => invoice.isOverdue)
.toList();
debugPrint('[InvoicesLocalDataSource] Found ${overdue.length} overdue invoices');
return overdue;
} catch (e) {
debugPrint('[InvoicesLocalDataSource] Error getting overdue invoices: $e');
rethrow;
}
}
/// Get unpaid invoices (issued but not paid)
Future<List<InvoiceModel>> getUnpaidInvoices() async {
try {
final allInvoices = await getAllInvoices();
final unpaid = allInvoices
.where((invoice) => invoice.status.name == 'issued' && !invoice.isPaid)
.toList();
debugPrint('[InvoicesLocalDataSource] Found ${unpaid.length} unpaid invoices');
return unpaid;
} catch (e) {
debugPrint('[InvoicesLocalDataSource] Error getting unpaid invoices: $e');
rethrow;
}
}
/// Mock invoices JSON data
/// Matches the HTML design with 5 sample invoices
static const String _mockInvoicesJson = '''
[
{
"invoice_id": "inv_001",
"invoice_number": "INV001",
"user_id": "user_001",
"order_id": "ord_001",
"invoice_type": "sales",
"issue_date": "2025-08-03T00:00:00.000Z",
"due_date": "2025-08-13T00:00:00.000Z",
"currency": "VND",
"subtotal_amount": 85000000,
"tax_amount": 0,
"discount_amount": 0,
"shipping_amount": 0,
"total_amount": 85000000,
"amount_paid": 25000000,
"amount_remaining": 60000000,
"status": "overdue",
"payment_terms": "Thanh toán trong 10 ngày",
"notes": "Hóa đơn cho đơn hàng DH001234",
"created_at": "2025-08-03T00:00:00.000Z",
"updated_at": "2025-08-03T00:00:00.000Z"
},
{
"invoice_id": "inv_002",
"invoice_number": "INV002",
"user_id": "user_001",
"order_id": "ord_002",
"invoice_type": "sales",
"issue_date": "2025-07-15T00:00:00.000Z",
"due_date": "2025-08-15T00:00:00.000Z",
"currency": "VND",
"subtotal_amount": 42500000,
"tax_amount": 0,
"discount_amount": 0,
"shipping_amount": 0,
"total_amount": 42500000,
"amount_paid": 0,
"amount_remaining": 42500000,
"status": "issued",
"payment_terms": "Thanh toán trong 30 ngày",
"notes": "Hóa đơn cho đơn hàng DH001233",
"created_at": "2025-07-15T00:00:00.000Z",
"updated_at": "2025-07-15T00:00:00.000Z"
},
{
"invoice_id": "inv_003",
"invoice_number": "INV003",
"user_id": "user_001",
"order_id": "ord_003",
"invoice_type": "sales",
"issue_date": "2025-06-01T00:00:00.000Z",
"due_date": "2025-07-01T00:00:00.000Z",
"currency": "VND",
"subtotal_amount": 150000000,
"tax_amount": 0,
"discount_amount": 0,
"shipping_amount": 0,
"total_amount": 150000000,
"amount_paid": 75000000,
"amount_remaining": 75000000,
"status": "partiallyPaid",
"payment_terms": "Thanh toán theo tiến độ",
"notes": "Hóa đơn cho đơn hàng DH001232 - Đã thanh toán 50%",
"created_at": "2025-06-01T00:00:00.000Z",
"updated_at": "2025-06-15T00:00:00.000Z"
},
{
"invoice_id": "inv_004",
"invoice_number": "INV004",
"user_id": "user_001",
"order_id": "ord_004",
"invoice_type": "sales",
"issue_date": "2025-05-10T00:00:00.000Z",
"due_date": "2025-06-10T00:00:00.000Z",
"currency": "VND",
"subtotal_amount": 32800000,
"tax_amount": 0,
"discount_amount": 0,
"shipping_amount": 0,
"total_amount": 32800000,
"amount_paid": 32800000,
"amount_remaining": 0,
"status": "paid",
"payment_terms": "Thanh toán ngay",
"notes": "Hóa đơn cho đơn hàng DH001231 - Đã thanh toán đầy đủ",
"created_at": "2025-05-10T00:00:00.000Z",
"updated_at": "2025-05-12T00:00:00.000Z"
},
{
"invoice_id": "inv_005",
"invoice_number": "INV005",
"user_id": "user_001",
"order_id": "ord_005",
"invoice_type": "sales",
"issue_date": "2025-04-20T00:00:00.000Z",
"due_date": "2025-05-20T00:00:00.000Z",
"currency": "VND",
"subtotal_amount": 95300000,
"tax_amount": 0,
"discount_amount": 0,
"shipping_amount": 0,
"total_amount": 95300000,
"amount_paid": 0,
"amount_remaining": 95300000,
"status": "overdue",
"payment_terms": "Thanh toán trong 30 ngày",
"notes": "Hóa đơn cho đơn hàng DH001230 - Đã quá hạn",
"created_at": "2025-04-20T00:00:00.000Z",
"updated_at": "2025-04-20T00:00:00.000Z"
}
]
''';
}