feat: item sales report
This commit is contained in:
@@ -6,6 +6,7 @@ import 'package:enaklo_pos/core/constants/variables.dart';
|
||||
import 'package:enaklo_pos/core/network/dio_client.dart';
|
||||
import 'package:enaklo_pos/data/datasources/auth_local_datasource.dart';
|
||||
import 'package:enaklo_pos/data/models/response/payment_method_analytic_response_model.dart';
|
||||
import 'package:enaklo_pos/data/models/response/sales_analytic_response_model.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
class AnalyticRemoteDatasource {
|
||||
@@ -34,7 +35,41 @@ class AnalyticRemoteDatasource {
|
||||
if (response.statusCode == 200) {
|
||||
return right(PaymentMethodAnalyticResponseModel.fromMap(response.data));
|
||||
} else {
|
||||
return left(response.data.toString());
|
||||
return left('Terjadi Kesalahan, Coba lagi nanti.');
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
log('Dio error: ${e.message}');
|
||||
return left(e.response?.data.toString() ?? e.message ?? 'Unknown error');
|
||||
} catch (e) {
|
||||
log('Unexpected error: $e');
|
||||
return left('Unexpected error occurred');
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<String, SalesAnalyticResponseModel>> getSales({
|
||||
required DateTime dateFrom,
|
||||
required DateTime dateTo,
|
||||
}) async {
|
||||
final authData = await AuthLocalDataSource().getAuthData();
|
||||
final headers = {
|
||||
'Authorization': 'Bearer ${authData.token}',
|
||||
'Accept': 'application/json',
|
||||
};
|
||||
|
||||
try {
|
||||
final response = await dio.get(
|
||||
'${Variables.baseUrl}/api/v1/analytics/sales',
|
||||
queryParameters: {
|
||||
'date_from': DateFormat('dd-MM-yyyy').format(dateFrom),
|
||||
'date_to': DateFormat('dd-MM-yyyy').format(dateTo),
|
||||
},
|
||||
options: Options(headers: headers),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return right(SalesAnalyticResponseModel.fromMap(response.data));
|
||||
} else {
|
||||
return left('Terjadi Kesalahan, Coba lagi nanti.');
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
log('Dio error: ${e.message}');
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
class SalesAnalyticResponseModel {
|
||||
final bool success;
|
||||
final SalesAnalyticData data;
|
||||
final dynamic errors;
|
||||
|
||||
SalesAnalyticResponseModel({
|
||||
required this.success,
|
||||
required this.data,
|
||||
this.errors,
|
||||
});
|
||||
|
||||
factory SalesAnalyticResponseModel.fromJson(Map<String, dynamic> json) =>
|
||||
SalesAnalyticResponseModel.fromMap(json);
|
||||
|
||||
Map<String, dynamic> toJson() => toMap();
|
||||
|
||||
factory SalesAnalyticResponseModel.fromMap(Map<String, dynamic> map) {
|
||||
return SalesAnalyticResponseModel(
|
||||
success: map['success'],
|
||||
data: SalesAnalyticData.fromMap(map['data']),
|
||||
errors: map['errors'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'success': success,
|
||||
'data': data.toMap(),
|
||||
'errors': errors,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class SalesAnalyticData {
|
||||
final String organizationId;
|
||||
final String outletId;
|
||||
final DateTime dateFrom;
|
||||
final DateTime dateTo;
|
||||
final String groupBy;
|
||||
final SalesSummary summary;
|
||||
final List<SalesAnalyticItem> data;
|
||||
|
||||
SalesAnalyticData({
|
||||
required this.organizationId,
|
||||
required this.outletId,
|
||||
required this.dateFrom,
|
||||
required this.dateTo,
|
||||
required this.groupBy,
|
||||
required this.summary,
|
||||
required this.data,
|
||||
});
|
||||
|
||||
factory SalesAnalyticData.fromJson(Map<String, dynamic> json) =>
|
||||
SalesAnalyticData.fromMap(json);
|
||||
|
||||
Map<String, dynamic> toJson() => toMap();
|
||||
|
||||
factory SalesAnalyticData.fromMap(Map<String, dynamic> map) {
|
||||
return SalesAnalyticData(
|
||||
organizationId: map['organization_id'],
|
||||
outletId: map['outlet_id'],
|
||||
dateFrom: DateTime.parse(map['date_from']),
|
||||
dateTo: DateTime.parse(map['date_to']),
|
||||
groupBy: map['group_by'],
|
||||
summary: SalesSummary.fromMap(map['summary']),
|
||||
data: List<SalesAnalyticItem>.from(
|
||||
map['data']?.map((x) => SalesAnalyticItem.fromMap(x)) ?? [],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'organization_id': organizationId,
|
||||
'outlet_id': outletId,
|
||||
'date_from': dateFrom.toIso8601String(),
|
||||
'date_to': dateTo.toIso8601String(),
|
||||
'group_by': groupBy,
|
||||
'summary': summary.toMap(),
|
||||
'data': data.map((x) => x.toMap()).toList(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class SalesSummary {
|
||||
final int totalSales;
|
||||
final int totalOrders;
|
||||
final int totalItems;
|
||||
final double averageOrderValue;
|
||||
final int totalTax;
|
||||
final int totalDiscount;
|
||||
final int netSales;
|
||||
|
||||
SalesSummary({
|
||||
required this.totalSales,
|
||||
required this.totalOrders,
|
||||
required this.totalItems,
|
||||
required this.averageOrderValue,
|
||||
required this.totalTax,
|
||||
required this.totalDiscount,
|
||||
required this.netSales,
|
||||
});
|
||||
|
||||
factory SalesSummary.fromJson(Map<String, dynamic> json) =>
|
||||
SalesSummary.fromMap(json);
|
||||
|
||||
Map<String, dynamic> toJson() => toMap();
|
||||
|
||||
factory SalesSummary.fromMap(Map<String, dynamic> map) {
|
||||
return SalesSummary(
|
||||
totalSales: map['total_sales'],
|
||||
totalOrders: map['total_orders'],
|
||||
totalItems: map['total_items'],
|
||||
averageOrderValue: (map['average_order_value'] as num).toDouble(),
|
||||
totalTax: map['total_tax'],
|
||||
totalDiscount: map['total_discount'],
|
||||
netSales: map['net_sales'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'total_sales': totalSales,
|
||||
'total_orders': totalOrders,
|
||||
'total_items': totalItems,
|
||||
'average_order_value': averageOrderValue,
|
||||
'total_tax': totalTax,
|
||||
'total_discount': totalDiscount,
|
||||
'net_sales': netSales,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class SalesAnalyticItem {
|
||||
final DateTime date;
|
||||
final int sales;
|
||||
final int orders;
|
||||
final int items;
|
||||
final int tax;
|
||||
final int discount;
|
||||
final int netSales;
|
||||
|
||||
SalesAnalyticItem({
|
||||
required this.date,
|
||||
required this.sales,
|
||||
required this.orders,
|
||||
required this.items,
|
||||
required this.tax,
|
||||
required this.discount,
|
||||
required this.netSales,
|
||||
});
|
||||
|
||||
factory SalesAnalyticItem.fromJson(Map<String, dynamic> json) =>
|
||||
SalesAnalyticItem.fromMap(json);
|
||||
|
||||
Map<String, dynamic> toJson() => toMap();
|
||||
|
||||
factory SalesAnalyticItem.fromMap(Map<String, dynamic> map) {
|
||||
return SalesAnalyticItem(
|
||||
date: DateTime.parse(map['date']),
|
||||
sales: map['sales'],
|
||||
orders: map['orders'],
|
||||
items: map['items'],
|
||||
tax: map['tax'],
|
||||
discount: map['discount'],
|
||||
netSales: map['net_sales'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'date': date.toIso8601String(),
|
||||
'sales': sales,
|
||||
'orders': orders,
|
||||
'items': items,
|
||||
'tax': tax,
|
||||
'discount': discount,
|
||||
'net_sales': netSales,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class SalesInsights {
|
||||
final List<SalesAnalyticItem> originalData;
|
||||
final List<SalesAnalyticItem> sortedDailyData;
|
||||
final SalesAnalyticItem? highestRevenueDay;
|
||||
final SalesSummary summary;
|
||||
|
||||
SalesInsights({
|
||||
required this.originalData,
|
||||
required this.sortedDailyData,
|
||||
required this.highestRevenueDay,
|
||||
required this.summary,
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user