add payments screen
This commit is contained in:
@@ -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"
|
||||
}
|
||||
]
|
||||
''';
|
||||
}
|
||||
Reference in New Issue
Block a user