feat: dashboard
This commit is contained in:
@@ -9,3 +9,4 @@ part 'dto/sales_analytic_dto.dart';
|
||||
part 'dto/profit_loss_analytic_dto.dart';
|
||||
part 'dto/category_analytic_dto.dart';
|
||||
part 'dto/inventory_analytic_dto.dart';
|
||||
part 'dto/dashboard_analytic_dto.dart';
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -385,3 +385,135 @@ Map<String, dynamic> _$$InventoryIngredientDtoImplToJson(
|
||||
'is_zero_stock': instance.isZeroStock,
|
||||
'updated_at': instance.updatedAt,
|
||||
};
|
||||
|
||||
_$DashboardAnalyticDtoImpl _$$DashboardAnalyticDtoImplFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _$DashboardAnalyticDtoImpl(
|
||||
organizationId: json['organization_id'] as String?,
|
||||
outletId: json['outlet_id'] as String?,
|
||||
dateFrom: json['date_from'] as String?,
|
||||
dateTo: json['date_to'] as String?,
|
||||
overview: json['overview'] == null
|
||||
? null
|
||||
: DashboardOverviewDto.fromJson(json['overview'] as Map<String, dynamic>),
|
||||
topProducts: (json['top_products'] as List<dynamic>?)
|
||||
?.map((e) => DashboardTopProductDto.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
paymentMethods: (json['payment_methods'] as List<dynamic>?)
|
||||
?.map(
|
||||
(e) => DashboardPaymentMethodDto.fromJson(e as Map<String, dynamic>),
|
||||
)
|
||||
.toList(),
|
||||
recentSales: (json['recent_sales'] as List<dynamic>?)
|
||||
?.map((e) => DashboardRecentSaleDto.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$DashboardAnalyticDtoImplToJson(
|
||||
_$DashboardAnalyticDtoImpl instance,
|
||||
) => <String, dynamic>{
|
||||
'organization_id': instance.organizationId,
|
||||
'outlet_id': instance.outletId,
|
||||
'date_from': instance.dateFrom,
|
||||
'date_to': instance.dateTo,
|
||||
'overview': instance.overview,
|
||||
'top_products': instance.topProducts,
|
||||
'payment_methods': instance.paymentMethods,
|
||||
'recent_sales': instance.recentSales,
|
||||
};
|
||||
|
||||
_$DashboardOverviewDtoImpl _$$DashboardOverviewDtoImplFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _$DashboardOverviewDtoImpl(
|
||||
totalSales: (json['total_sales'] as num?)?.toInt(),
|
||||
totalOrders: (json['total_orders'] as num?)?.toInt(),
|
||||
averageOrderValue: (json['average_order_value'] as num?)?.toDouble(),
|
||||
totalCustomers: (json['total_customers'] as num?)?.toInt(),
|
||||
voidedOrders: (json['voided_orders'] as num?)?.toInt(),
|
||||
refundedOrders: (json['refunded_orders'] as num?)?.toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$DashboardOverviewDtoImplToJson(
|
||||
_$DashboardOverviewDtoImpl instance,
|
||||
) => <String, dynamic>{
|
||||
'total_sales': instance.totalSales,
|
||||
'total_orders': instance.totalOrders,
|
||||
'average_order_value': instance.averageOrderValue,
|
||||
'total_customers': instance.totalCustomers,
|
||||
'voided_orders': instance.voidedOrders,
|
||||
'refunded_orders': instance.refundedOrders,
|
||||
};
|
||||
|
||||
_$DashboardTopProductDtoImpl _$$DashboardTopProductDtoImplFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _$DashboardTopProductDtoImpl(
|
||||
productId: json['product_id'] as String?,
|
||||
productName: json['product_name'] as String?,
|
||||
categoryId: json['category_id'] as String?,
|
||||
categoryName: json['category_name'] as String?,
|
||||
quantitySold: (json['quantity_sold'] as num?)?.toInt(),
|
||||
revenue: (json['revenue'] as num?)?.toInt(),
|
||||
averagePrice: (json['average_price'] as num?)?.toDouble(),
|
||||
orderCount: (json['order_count'] as num?)?.toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$DashboardTopProductDtoImplToJson(
|
||||
_$DashboardTopProductDtoImpl instance,
|
||||
) => <String, dynamic>{
|
||||
'product_id': instance.productId,
|
||||
'product_name': instance.productName,
|
||||
'category_id': instance.categoryId,
|
||||
'category_name': instance.categoryName,
|
||||
'quantity_sold': instance.quantitySold,
|
||||
'revenue': instance.revenue,
|
||||
'average_price': instance.averagePrice,
|
||||
'order_count': instance.orderCount,
|
||||
};
|
||||
|
||||
_$DashboardPaymentMethodDtoImpl _$$DashboardPaymentMethodDtoImplFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _$DashboardPaymentMethodDtoImpl(
|
||||
paymentMethodId: json['payment_method_id'] as String?,
|
||||
paymentMethodName: json['payment_method_name'] as String?,
|
||||
paymentMethodType: json['payment_method_type'] as String?,
|
||||
totalAmount: (json['total_amount'] as num?)?.toInt(),
|
||||
orderCount: (json['order_count'] as num?)?.toInt(),
|
||||
paymentCount: (json['payment_count'] as num?)?.toInt(),
|
||||
percentage: (json['percentage'] as num?)?.toDouble(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$DashboardPaymentMethodDtoImplToJson(
|
||||
_$DashboardPaymentMethodDtoImpl instance,
|
||||
) => <String, dynamic>{
|
||||
'payment_method_id': instance.paymentMethodId,
|
||||
'payment_method_name': instance.paymentMethodName,
|
||||
'payment_method_type': instance.paymentMethodType,
|
||||
'total_amount': instance.totalAmount,
|
||||
'order_count': instance.orderCount,
|
||||
'payment_count': instance.paymentCount,
|
||||
'percentage': instance.percentage,
|
||||
};
|
||||
|
||||
_$DashboardRecentSaleDtoImpl _$$DashboardRecentSaleDtoImplFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _$DashboardRecentSaleDtoImpl(
|
||||
date: json['date'] as String?,
|
||||
sales: (json['sales'] as num?)?.toInt(),
|
||||
orders: (json['orders'] as num?)?.toInt(),
|
||||
items: (json['items'] as num?)?.toInt(),
|
||||
tax: (json['tax'] as num?)?.toInt(),
|
||||
discount: (json['discount'] as num?)?.toInt(),
|
||||
netSales: (json['net_sales'] as num?)?.toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$DashboardRecentSaleDtoImplToJson(
|
||||
_$DashboardRecentSaleDtoImpl instance,
|
||||
) => <String, dynamic>{
|
||||
'date': instance.date,
|
||||
'sales': instance.sales,
|
||||
'orders': instance.orders,
|
||||
'items': instance.items,
|
||||
'tax': instance.tax,
|
||||
'discount': instance.discount,
|
||||
'net_sales': instance.netSales,
|
||||
};
|
||||
|
||||
@@ -126,4 +126,32 @@ class AnalyticRemoteDataProvider {
|
||||
return DC.error(AnalyticFailure.serverError(e));
|
||||
}
|
||||
}
|
||||
|
||||
Future<DC<AnalyticFailure, DashboardAnalyticDto>> fetchDashboard({
|
||||
required String outletId,
|
||||
required DateTime dateFrom,
|
||||
required DateTime dateTo,
|
||||
}) async {
|
||||
try {
|
||||
final response = await _apiClient.get(
|
||||
ApiPath.dashboardAnalytic,
|
||||
params: {
|
||||
'date_from': dateFrom.toServerDate,
|
||||
'date_to': dateTo.toServerDate,
|
||||
},
|
||||
headers: getAuthorizationHeader(),
|
||||
);
|
||||
|
||||
if (response.data['data'] == null) {
|
||||
return DC.error(AnalyticFailure.empty());
|
||||
}
|
||||
|
||||
final dto = DashboardAnalyticDto.fromJson(response.data['data']);
|
||||
|
||||
return DC.data(dto);
|
||||
} on ApiFailure catch (e, s) {
|
||||
log('fetchDashboardError', name: _logName, error: e, stackTrace: s);
|
||||
return DC.error(AnalyticFailure.serverError(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
part of '../analytic_dtos.dart';
|
||||
|
||||
@freezed
|
||||
class DashboardAnalyticDto with _$DashboardAnalyticDto {
|
||||
const DashboardAnalyticDto._();
|
||||
|
||||
const factory DashboardAnalyticDto({
|
||||
@JsonKey(name: 'organization_id') String? organizationId,
|
||||
@JsonKey(name: 'outlet_id') String? outletId,
|
||||
@JsonKey(name: 'date_from') String? dateFrom,
|
||||
@JsonKey(name: 'date_to') String? dateTo,
|
||||
@JsonKey(name: 'overview') DashboardOverviewDto? overview,
|
||||
@JsonKey(name: 'top_products') List<DashboardTopProductDto>? topProducts,
|
||||
@JsonKey(name: 'payment_methods')
|
||||
List<DashboardPaymentMethodDto>? paymentMethods,
|
||||
@JsonKey(name: 'recent_sales') List<DashboardRecentSaleDto>? recentSales,
|
||||
}) = _DashboardAnalyticDto;
|
||||
|
||||
factory DashboardAnalyticDto.fromJson(Map<String, dynamic> json) =>
|
||||
_$DashboardAnalyticDtoFromJson(json);
|
||||
|
||||
DashboardAnalytic toDomain() => DashboardAnalytic(
|
||||
organizationId: organizationId ?? '',
|
||||
outletId: outletId ?? '',
|
||||
dateFrom: dateFrom ?? '',
|
||||
dateTo: dateTo ?? '',
|
||||
overview: overview?.toDomain() ?? DashboardOverview.empty(),
|
||||
topProducts: topProducts?.map((e) => e.toDomain()).toList() ?? [],
|
||||
paymentMethods: paymentMethods?.map((e) => e.toDomain()).toList() ?? [],
|
||||
recentSales: recentSales?.map((e) => e.toDomain()).toList() ?? [],
|
||||
);
|
||||
}
|
||||
|
||||
@freezed
|
||||
class DashboardOverviewDto with _$DashboardOverviewDto {
|
||||
const DashboardOverviewDto._();
|
||||
|
||||
const factory DashboardOverviewDto({
|
||||
@JsonKey(name: 'total_sales') int? totalSales,
|
||||
@JsonKey(name: 'total_orders') int? totalOrders,
|
||||
@JsonKey(name: 'average_order_value') double? averageOrderValue,
|
||||
@JsonKey(name: 'total_customers') int? totalCustomers,
|
||||
@JsonKey(name: 'voided_orders') int? voidedOrders,
|
||||
@JsonKey(name: 'refunded_orders') int? refundedOrders,
|
||||
}) = _DashboardOverviewDto;
|
||||
|
||||
factory DashboardOverviewDto.fromJson(Map<String, dynamic> json) =>
|
||||
_$DashboardOverviewDtoFromJson(json);
|
||||
|
||||
DashboardOverview toDomain() => DashboardOverview(
|
||||
totalSales: totalSales ?? 0,
|
||||
totalOrders: totalOrders ?? 0,
|
||||
averageOrderValue: averageOrderValue ?? 0.0,
|
||||
totalCustomers: totalCustomers ?? 0,
|
||||
voidedOrders: voidedOrders ?? 0,
|
||||
refundedOrders: refundedOrders ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
@freezed
|
||||
class DashboardTopProductDto with _$DashboardTopProductDto {
|
||||
const DashboardTopProductDto._();
|
||||
|
||||
const factory DashboardTopProductDto({
|
||||
@JsonKey(name: 'product_id') String? productId,
|
||||
@JsonKey(name: 'product_name') String? productName,
|
||||
@JsonKey(name: 'category_id') String? categoryId,
|
||||
@JsonKey(name: 'category_name') String? categoryName,
|
||||
@JsonKey(name: 'quantity_sold') int? quantitySold,
|
||||
@JsonKey(name: 'revenue') int? revenue,
|
||||
@JsonKey(name: 'average_price') double? averagePrice,
|
||||
@JsonKey(name: 'order_count') int? orderCount,
|
||||
}) = _DashboardTopProductDto;
|
||||
|
||||
factory DashboardTopProductDto.fromJson(Map<String, dynamic> json) =>
|
||||
_$DashboardTopProductDtoFromJson(json);
|
||||
|
||||
DashboardTopProduct toDomain() => DashboardTopProduct(
|
||||
productId: productId ?? '',
|
||||
productName: productName ?? '',
|
||||
categoryId: categoryId ?? '',
|
||||
categoryName: categoryName ?? '',
|
||||
quantitySold: quantitySold ?? 0,
|
||||
revenue: revenue ?? 0,
|
||||
averagePrice: averagePrice ?? 0.0,
|
||||
orderCount: orderCount ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
@freezed
|
||||
class DashboardPaymentMethodDto with _$DashboardPaymentMethodDto {
|
||||
const DashboardPaymentMethodDto._();
|
||||
|
||||
const factory DashboardPaymentMethodDto({
|
||||
@JsonKey(name: 'payment_method_id') String? paymentMethodId,
|
||||
@JsonKey(name: 'payment_method_name') String? paymentMethodName,
|
||||
@JsonKey(name: 'payment_method_type') String? paymentMethodType,
|
||||
@JsonKey(name: 'total_amount') int? totalAmount,
|
||||
@JsonKey(name: 'order_count') int? orderCount,
|
||||
@JsonKey(name: 'payment_count') int? paymentCount,
|
||||
@JsonKey(name: 'percentage') double? percentage,
|
||||
}) = _DashboardPaymentMethodDto;
|
||||
|
||||
factory DashboardPaymentMethodDto.fromJson(Map<String, dynamic> json) =>
|
||||
_$DashboardPaymentMethodDtoFromJson(json);
|
||||
|
||||
DashboardPaymentMethod toDomain() => DashboardPaymentMethod(
|
||||
paymentMethodId: paymentMethodId ?? '',
|
||||
paymentMethodName: paymentMethodName ?? '',
|
||||
paymentMethodType: paymentMethodType ?? '',
|
||||
totalAmount: totalAmount ?? 0,
|
||||
orderCount: orderCount ?? 0,
|
||||
paymentCount: paymentCount ?? 0,
|
||||
percentage: percentage ?? 0.0,
|
||||
);
|
||||
}
|
||||
|
||||
/// ===================== RECENT SALE DTO =====================
|
||||
@freezed
|
||||
class DashboardRecentSaleDto with _$DashboardRecentSaleDto {
|
||||
const DashboardRecentSaleDto._();
|
||||
|
||||
const factory DashboardRecentSaleDto({
|
||||
@JsonKey(name: 'date') String? date,
|
||||
@JsonKey(name: 'sales') int? sales,
|
||||
@JsonKey(name: 'orders') int? orders,
|
||||
@JsonKey(name: 'items') int? items,
|
||||
@JsonKey(name: 'tax') int? tax,
|
||||
@JsonKey(name: 'discount') int? discount,
|
||||
@JsonKey(name: 'net_sales') int? netSales,
|
||||
}) = _DashboardRecentSaleDto;
|
||||
|
||||
factory DashboardRecentSaleDto.fromJson(Map<String, dynamic> json) =>
|
||||
_$DashboardRecentSaleDtoFromJson(json);
|
||||
|
||||
DashboardRecentSale toDomain() => DashboardRecentSale(
|
||||
date: date ?? '',
|
||||
sales: sales ?? 0,
|
||||
orders: orders ?? 0,
|
||||
items: items ?? 0,
|
||||
tax: tax ?? 0,
|
||||
discount: discount ?? 0,
|
||||
netSales: netSales ?? 0,
|
||||
);
|
||||
}
|
||||
@@ -115,4 +115,31 @@ class AnalyticRepository implements IAnalyticRepository {
|
||||
return left(const AnalyticFailure.unexpectedError());
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<AnalyticFailure, DashboardAnalytic>> getDashboard({
|
||||
required DateTime dateFrom,
|
||||
required DateTime dateTo,
|
||||
}) async {
|
||||
try {
|
||||
User currentUser = await _authLocalDataProvider.currentUser();
|
||||
|
||||
final result = await _dataProvider.fetchDashboard(
|
||||
outletId: currentUser.outletId,
|
||||
dateFrom: dateFrom,
|
||||
dateTo: dateTo,
|
||||
);
|
||||
|
||||
if (result.hasError) {
|
||||
return left(result.error!);
|
||||
}
|
||||
|
||||
final auth = result.data!.toDomain();
|
||||
|
||||
return right(auth);
|
||||
} catch (e, s) {
|
||||
log('getDashboardError', name: _logName, error: e, stackTrace: s);
|
||||
return left(const AnalyticFailure.unexpectedError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user