report dashboard
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
import '../../domain/analytic/analytic.dart';
|
||||
|
||||
part 'analytic_dtos.freezed.dart';
|
||||
part 'analytic_dtos.g.dart';
|
||||
|
||||
part 'dtos/dashboard_dto.dart';
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,139 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'analytic_dtos.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$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,
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:data_channel/data_channel.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
|
||||
import '../../../common/api/api_client.dart';
|
||||
import '../../../common/api/api_failure.dart';
|
||||
import '../../../common/extension/extension.dart';
|
||||
import '../../../common/function/app_function.dart';
|
||||
import '../../../common/url/api_path.dart';
|
||||
import '../../../domain/analytic/analytic.dart';
|
||||
import '../analytic_dtos.dart';
|
||||
|
||||
@injectable
|
||||
class AnalyticRemoteDataProvider {
|
||||
final ApiClient _apiClient;
|
||||
|
||||
final _logName = 'AnalyticRemoteDataProvider';
|
||||
|
||||
AnalyticRemoteDataProvider(this._apiClient);
|
||||
|
||||
Future<DC<AnalyticFailure, DashboardAnalyticDto>> fetchDashboard({
|
||||
required DateTime dateFrom,
|
||||
required DateTime dateTo,
|
||||
}) async {
|
||||
try {
|
||||
final response = await _apiClient.get(
|
||||
ApiPath.analyticDashboard,
|
||||
params: {
|
||||
'date_from': dateFrom.toServerDate(),
|
||||
'date_to': dateTo.toServerDate(),
|
||||
},
|
||||
headers: getAuthorizationHeader(),
|
||||
);
|
||||
|
||||
if (response.data['success'] == false) {
|
||||
return DC.error(AnalyticFailure.unexpectedError());
|
||||
}
|
||||
|
||||
final dashboard = DashboardAnalyticDto.fromJson(
|
||||
response.data['data'] as Map<String, dynamic>,
|
||||
);
|
||||
|
||||
return DC.data(dashboard);
|
||||
} on ApiFailure catch (e, s) {
|
||||
log('fetchDashboard', name: _logName, error: e, stackTrace: s);
|
||||
return DC.error(AnalyticFailure.serverError(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
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);
|
||||
|
||||
// Optional mapping ke domain
|
||||
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);
|
||||
|
||||
// Optional mapping ke domain
|
||||
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);
|
||||
|
||||
// Optional mapping ke domain
|
||||
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);
|
||||
|
||||
// Optional mapping ke domain
|
||||
DashboardPaymentMethod toDomain() => DashboardPaymentMethod(
|
||||
paymentMethodId: paymentMethodId ?? '',
|
||||
paymentMethodName: paymentMethodName ?? '',
|
||||
paymentMethodType: paymentMethodType ?? '',
|
||||
totalAmount: totalAmount ?? 0,
|
||||
orderCount: orderCount ?? 0,
|
||||
paymentCount: paymentCount ?? 0,
|
||||
percentage: percentage ?? 0.0,
|
||||
);
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
// Optional mapping ke domain
|
||||
DashboardRecentSale toDomain() => DashboardRecentSale(
|
||||
date: date ?? '',
|
||||
sales: sales ?? 0,
|
||||
orders: orders ?? 0,
|
||||
items: items ?? 0,
|
||||
tax: tax ?? 0,
|
||||
discount: discount ?? 0,
|
||||
netSales: netSales ?? 0,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
|
||||
import '../../../domain/analytic/analytic.dart';
|
||||
import '../datasources/remote_data_provider.dart';
|
||||
|
||||
@Injectable(as: IAnalyticRepository)
|
||||
class AnalyticRepository implements IAnalyticRepository {
|
||||
final AnalyticRemoteDataProvider _dataProvider;
|
||||
|
||||
final _logName = 'AnalyticRepository';
|
||||
|
||||
AnalyticRepository(this._dataProvider);
|
||||
|
||||
@override
|
||||
Future<Either<AnalyticFailure, DashboardAnalytic>> getDashboard({
|
||||
required DateTime dateFrom,
|
||||
required DateTime dateTo,
|
||||
}) async {
|
||||
try {
|
||||
final result = await _dataProvider.fetchDashboard(
|
||||
dateFrom: dateFrom,
|
||||
dateTo: dateTo,
|
||||
);
|
||||
|
||||
if (result.hasError) {
|
||||
return left(result.error!);
|
||||
}
|
||||
|
||||
final dashboard = result.data!.toDomain();
|
||||
|
||||
return right(dashboard);
|
||||
} catch (e) {
|
||||
log('getDashboardError', name: _logName, error: e);
|
||||
return left(const AnalyticFailure.unexpectedError());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user