invoices history ready
This commit is contained in:
@@ -44,12 +44,22 @@ class BillingRepositoryImpl implements BillingRepository {
|
||||
/// Fetches the history of paid invoices.
|
||||
@override
|
||||
Future<List<Invoice>> getInvoiceHistory() async {
|
||||
final List<Invoice> invoices = await _financialRepository.getInvoices(
|
||||
'current_business',
|
||||
);
|
||||
return invoices
|
||||
.where((Invoice i) => i.status == InvoiceStatus.paid)
|
||||
.toList();
|
||||
final String? businessId =
|
||||
data_connect.ClientSessionStore.instance.session?.business?.id;
|
||||
if (businessId == null || businessId.isEmpty) {
|
||||
return <Invoice>[];
|
||||
}
|
||||
|
||||
final fdc.QueryResult<data_connect.ListInvoicesByBusinessIdData,
|
||||
data_connect.ListInvoicesByBusinessIdVariables> result =
|
||||
await _dataConnect
|
||||
.listInvoicesByBusinessId(
|
||||
businessId: businessId,
|
||||
)
|
||||
.limit(10)
|
||||
.execute();
|
||||
|
||||
return result.data.invoices.map(_mapInvoice).toList();
|
||||
}
|
||||
|
||||
/// Fetches pending invoices (Open or Disputed).
|
||||
@@ -161,6 +171,42 @@ class BillingRepositoryImpl implements BillingRepository {
|
||||
(dateTime.millisecondsSinceEpoch % 1000) * 1000000;
|
||||
return fdc.Timestamp(nanoseconds, seconds);
|
||||
}
|
||||
|
||||
Invoice _mapInvoice(data_connect.ListInvoicesByBusinessIdInvoices invoice) {
|
||||
return Invoice(
|
||||
id: invoice.id,
|
||||
eventId: invoice.orderId,
|
||||
businessId: invoice.businessId,
|
||||
status: _mapInvoiceStatus(invoice.status),
|
||||
totalAmount: invoice.amount,
|
||||
workAmount: invoice.amount,
|
||||
addonsAmount: invoice.otherCharges ?? 0,
|
||||
invoiceNumber: invoice.invoiceNumber,
|
||||
issueDate: invoice.issueDate.toDateTime(),
|
||||
);
|
||||
}
|
||||
|
||||
InvoiceStatus _mapInvoiceStatus(
|
||||
data_connect.EnumValue<data_connect.InvoiceStatus> status,
|
||||
) {
|
||||
if (status is data_connect.Known<data_connect.InvoiceStatus>) {
|
||||
switch (status.value) {
|
||||
case data_connect.InvoiceStatus.PAID:
|
||||
return InvoiceStatus.paid;
|
||||
case data_connect.InvoiceStatus.OVERDUE:
|
||||
return InvoiceStatus.overdue;
|
||||
case data_connect.InvoiceStatus.DISPUTED:
|
||||
return InvoiceStatus.disputed;
|
||||
case data_connect.InvoiceStatus.APPROVED:
|
||||
return InvoiceStatus.verified;
|
||||
case data_connect.InvoiceStatus.PENDING_REVIEW:
|
||||
case data_connect.InvoiceStatus.PENDING:
|
||||
case data_connect.InvoiceStatus.DRAFT:
|
||||
return InvoiceStatus.open;
|
||||
}
|
||||
}
|
||||
return InvoiceStatus.open;
|
||||
}
|
||||
}
|
||||
|
||||
class _RoleSummary {
|
||||
|
||||
@@ -114,17 +114,21 @@ class BillingBloc extends Bloc<BillingEvent, BillingState> {
|
||||
// In a real app, fetches related Event/Business names via ID.
|
||||
// For now, mapping available fields and hardcoding missing UI placeholders.
|
||||
// Preserving "Existing Behavior" means we show something.
|
||||
final String dateLabel = invoice.issueDate == null
|
||||
? '2024-01-24'
|
||||
: invoice.issueDate!.toIso8601String().split('T').first;
|
||||
final String titleLabel = invoice.invoiceNumber ?? invoice.id;
|
||||
return BillingInvoice(
|
||||
id: invoice.id,
|
||||
id: titleLabel,
|
||||
title: 'Invoice #${invoice.id}', // Placeholder as Invoice lacks title
|
||||
locationAddress:
|
||||
'Location for ${invoice.eventId}', // Placeholder for address
|
||||
clientName: 'Client ${invoice.businessId}', // Placeholder for client name
|
||||
date: '2024-01-24', // Placeholder date
|
||||
date: dateLabel,
|
||||
totalAmount: invoice.totalAmount,
|
||||
workersCount: 5, // Placeholder count
|
||||
totalHours: invoice.workAmount / 25.0, // Estimating hours from amount
|
||||
status: invoice.status.name,
|
||||
status: invoice.status.name.toUpperCase(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ class _InvoiceItem extends StatelessWidget {
|
||||
'\$${invoice.totalAmount.toStringAsFixed(2)}',
|
||||
style: UiTypography.body2b.textPrimary,
|
||||
),
|
||||
const _PaidBadge(),
|
||||
_StatusBadge(status: invoice.status),
|
||||
],
|
||||
),
|
||||
const SizedBox(width: UiConstants.space2),
|
||||
@@ -125,21 +125,24 @@ class _InvoiceItem extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _PaidBadge extends StatelessWidget {
|
||||
const _PaidBadge();
|
||||
class _StatusBadge extends StatelessWidget {
|
||||
const _StatusBadge({required this.status});
|
||||
|
||||
final String status;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final bool isPaid = status.toUpperCase() == 'PAID';
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.tagSuccess,
|
||||
color: isPaid ? UiColors.tagSuccess : UiColors.tagPending,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: Text(
|
||||
t.client_billing.paid_badge,
|
||||
isPaid ? t.client_billing.paid_badge : t.client_billing.pending_badge,
|
||||
style: UiTypography.titleUppercase4b.copyWith(
|
||||
color: UiColors.iconSuccess,
|
||||
color: isPaid ? UiColors.iconSuccess : UiColors.textWarning,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user