purchasing analytic repo

This commit is contained in:
Efril
2026-05-19 23:08:01 +07:00
parent e88eff28f0
commit d9a553708b
17 changed files with 4347 additions and 0 deletions
@@ -12,3 +12,4 @@ part 'dto/inventory_analytic_dto.dart';
part 'dto/dashboard_analytic_dto.dart';
part 'dto/product_analytic_dto.dart';
part 'dto/payment_method_analytic_dto.dart';
part 'dto/purchasing_analytic_dto.dart';
File diff suppressed because it is too large Load Diff
@@ -637,3 +637,139 @@ Map<String, dynamic> _$$PaymentMethodSummaryDtoImplToJson(
'total_payments': instance.totalPayments,
'average_order_value': instance.averageOrderValue,
};
_$PurchasingAnalyticDtoImpl _$$PurchasingAnalyticDtoImplFromJson(
Map<String, dynamic> json,
) => _$PurchasingAnalyticDtoImpl(
organizationId: json['organization_id'] as String?,
outletId: json['outlet_id'] as String?,
outletName: json['outlet_name'] as String?,
dateFrom: json['date_from'] == null
? null
: DateTime.parse(json['date_from'] as String),
dateTo: json['date_to'] == null
? null
: DateTime.parse(json['date_to'] as String),
groupBy: json['group_by'] as String?,
summary: json['summary'] == null
? null
: PurchasingAnalyticSummaryDto.fromJson(
json['summary'] as Map<String, dynamic>,
),
data: (json['data'] as List<dynamic>?)
?.map(
(e) => PurchasingAnalyticDataDto.fromJson(e as Map<String, dynamic>),
)
.toList(),
ingredientData: (json['ingredient_data'] as List<dynamic>?)
?.map(
(e) => PurchasingIngredientDataDto.fromJson(e as Map<String, dynamic>),
)
.toList(),
vendorData: (json['vendor_data'] as List<dynamic>?)
?.map((e) => PurchasingVendorDataDto.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$$PurchasingAnalyticDtoImplToJson(
_$PurchasingAnalyticDtoImpl instance,
) => <String, dynamic>{
'organization_id': instance.organizationId,
'outlet_id': instance.outletId,
'outlet_name': instance.outletName,
'date_from': instance.dateFrom?.toIso8601String(),
'date_to': instance.dateTo?.toIso8601String(),
'group_by': instance.groupBy,
'summary': instance.summary,
'data': instance.data,
'ingredient_data': instance.ingredientData,
'vendor_data': instance.vendorData,
};
_$PurchasingAnalyticSummaryDtoImpl _$$PurchasingAnalyticSummaryDtoImplFromJson(
Map<String, dynamic> json,
) => _$PurchasingAnalyticSummaryDtoImpl(
totalPurchases: json['total_purchases'] as num?,
totalPurchaseOrders: json['total_purchase_orders'] as num?,
totalQuantity: json['total_quantity'] as num?,
averagePurchaseOrderValue: json['average_purchase_order_value'] as num?,
totalIngredients: json['total_ingredients'] as num?,
totalVendors: json['total_vendors'] as num?,
);
Map<String, dynamic> _$$PurchasingAnalyticSummaryDtoImplToJson(
_$PurchasingAnalyticSummaryDtoImpl instance,
) => <String, dynamic>{
'total_purchases': instance.totalPurchases,
'total_purchase_orders': instance.totalPurchaseOrders,
'total_quantity': instance.totalQuantity,
'average_purchase_order_value': instance.averagePurchaseOrderValue,
'total_ingredients': instance.totalIngredients,
'total_vendors': instance.totalVendors,
};
_$PurchasingAnalyticDataDtoImpl _$$PurchasingAnalyticDataDtoImplFromJson(
Map<String, dynamic> json,
) => _$PurchasingAnalyticDataDtoImpl(
date: json['date'] == null ? null : DateTime.parse(json['date'] as String),
purchases: json['purchases'] as num?,
purchaseOrders: json['purchase_orders'] as num?,
quantity: json['quantity'] as num?,
ingredients: json['ingredients'] as num?,
vendors: json['vendors'] as num?,
);
Map<String, dynamic> _$$PurchasingAnalyticDataDtoImplToJson(
_$PurchasingAnalyticDataDtoImpl instance,
) => <String, dynamic>{
'date': instance.date?.toIso8601String(),
'purchases': instance.purchases,
'purchase_orders': instance.purchaseOrders,
'quantity': instance.quantity,
'ingredients': instance.ingredients,
'vendors': instance.vendors,
};
_$PurchasingIngredientDataDtoImpl _$$PurchasingIngredientDataDtoImplFromJson(
Map<String, dynamic> json,
) => _$PurchasingIngredientDataDtoImpl(
ingredientId: json['ingredient_id'] as String?,
ingredientName: json['ingredient_name'] as String?,
quantity: json['quantity'] as num?,
totalCost: json['total_cost'] as num?,
averageUnitCost: json['average_unit_cost'] as num?,
purchaseOrderCount: json['purchase_order_count'] as num?,
);
Map<String, dynamic> _$$PurchasingIngredientDataDtoImplToJson(
_$PurchasingIngredientDataDtoImpl instance,
) => <String, dynamic>{
'ingredient_id': instance.ingredientId,
'ingredient_name': instance.ingredientName,
'quantity': instance.quantity,
'total_cost': instance.totalCost,
'average_unit_cost': instance.averageUnitCost,
'purchase_order_count': instance.purchaseOrderCount,
};
_$PurchasingVendorDataDtoImpl _$$PurchasingVendorDataDtoImplFromJson(
Map<String, dynamic> json,
) => _$PurchasingVendorDataDtoImpl(
vendorId: json['vendor_id'] as String?,
vendorName: json['vendor_name'] as String?,
totalCost: json['total_cost'] as num?,
purchaseOrderCount: json['purchase_order_count'] as num?,
ingredientCount: json['ingredient_count'] as num?,
quantity: json['quantity'] as num?,
);
Map<String, dynamic> _$$PurchasingVendorDataDtoImplToJson(
_$PurchasingVendorDataDtoImpl instance,
) => <String, dynamic>{
'vendor_id': instance.vendorId,
'vendor_name': instance.vendorName,
'total_cost': instance.totalCost,
'purchase_order_count': instance.purchaseOrderCount,
'ingredient_count': instance.ingredientCount,
'quantity': instance.quantity,
};
@@ -231,4 +231,35 @@ class AnalyticRemoteDataProvider {
return DC.error(AnalyticFailure.serverError(e));
}
}
Future<DC<AnalyticFailure, PurchasingAnalyticDto>> fetchPurchasing({
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
}) async {
try {
final Map<String, dynamic> params = {
'date_from': dateFrom.toServerDate,
'date_to': dateTo.toServerDate,
};
if (outletId != null) params['outlet_id'] = outletId;
final response = await _apiClient.get(
ApiPath.purchasingAnalytic,
params: params,
headers: getAuthorizationHeader(),
);
if (response.data['data'] == null) {
return DC.error(AnalyticFailure.empty());
}
final dto = PurchasingAnalyticDto.fromJson(response.data['data']);
return DC.data(dto);
} on ApiFailure catch (e, s) {
log('fetchPurchasingError', name: _logName, error: e, stackTrace: s);
return DC.error(AnalyticFailure.serverError(e));
}
}
}
@@ -0,0 +1,143 @@
part of '../analytic_dtos.dart';
@freezed
class PurchasingAnalyticDto with _$PurchasingAnalyticDto {
const PurchasingAnalyticDto._();
const factory PurchasingAnalyticDto({
@JsonKey(name: 'organization_id') String? organizationId,
@JsonKey(name: 'outlet_id') String? outletId,
@JsonKey(name: 'outlet_name') String? outletName,
@JsonKey(name: 'date_from') DateTime? dateFrom,
@JsonKey(name: 'date_to') DateTime? dateTo,
@JsonKey(name: 'group_by') String? groupBy,
@JsonKey(name: 'summary') PurchasingAnalyticSummaryDto? summary,
@JsonKey(name: 'data') List<PurchasingAnalyticDataDto>? data,
@JsonKey(name: 'ingredient_data')
List<PurchasingIngredientDataDto>? ingredientData,
@JsonKey(name: 'vendor_data') List<PurchasingVendorDataDto>? vendorData,
}) = _PurchasingAnalyticDto;
factory PurchasingAnalyticDto.fromJson(Map<String, dynamic> json) =>
_$PurchasingAnalyticDtoFromJson(json);
PurchasingAnalytic toDomain() => PurchasingAnalytic(
organizationId: organizationId ?? '',
outletId: outletId ?? '',
outletName: outletName ?? '',
dateFrom: dateFrom ?? DateTime.fromMillisecondsSinceEpoch(0),
dateTo: dateTo ?? DateTime.fromMillisecondsSinceEpoch(0),
groupBy: groupBy ?? '',
summary: summary?.toDomain() ?? PurchasingAnalyticSummary.empty(),
data: data?.map((e) => e.toDomain()).toList() ?? [],
ingredientData:
ingredientData?.map((e) => e.toDomain()).toList() ?? [],
vendorData: vendorData?.map((e) => e.toDomain()).toList() ?? [],
);
}
@freezed
class PurchasingAnalyticSummaryDto with _$PurchasingAnalyticSummaryDto {
const PurchasingAnalyticSummaryDto._();
const factory PurchasingAnalyticSummaryDto({
@JsonKey(name: 'total_purchases') num? totalPurchases,
@JsonKey(name: 'total_purchase_orders') num? totalPurchaseOrders,
@JsonKey(name: 'total_quantity') num? totalQuantity,
@JsonKey(name: 'average_purchase_order_value')
num? averagePurchaseOrderValue,
@JsonKey(name: 'total_ingredients') num? totalIngredients,
@JsonKey(name: 'total_vendors') num? totalVendors,
}) = _PurchasingAnalyticSummaryDto;
factory PurchasingAnalyticSummaryDto.fromJson(Map<String, dynamic> json) =>
_$PurchasingAnalyticSummaryDtoFromJson(json);
PurchasingAnalyticSummary toDomain() => PurchasingAnalyticSummary(
totalPurchases: totalPurchases?.toInt() ?? 0,
totalPurchaseOrders: totalPurchaseOrders?.toInt() ?? 0,
totalQuantity: totalQuantity?.toInt() ?? 0,
averagePurchaseOrderValue:
averagePurchaseOrderValue?.toDouble() ?? 0,
totalIngredients: totalIngredients?.toInt() ?? 0,
totalVendors: totalVendors?.toInt() ?? 0,
);
}
@freezed
class PurchasingAnalyticDataDto with _$PurchasingAnalyticDataDto {
const PurchasingAnalyticDataDto._();
const factory PurchasingAnalyticDataDto({
@JsonKey(name: 'date') DateTime? date,
@JsonKey(name: 'purchases') num? purchases,
@JsonKey(name: 'purchase_orders') num? purchaseOrders,
@JsonKey(name: 'quantity') num? quantity,
@JsonKey(name: 'ingredients') num? ingredients,
@JsonKey(name: 'vendors') num? vendors,
}) = _PurchasingAnalyticDataDto;
factory PurchasingAnalyticDataDto.fromJson(Map<String, dynamic> json) =>
_$PurchasingAnalyticDataDtoFromJson(json);
PurchasingAnalyticData toDomain() => PurchasingAnalyticData(
date: date ?? DateTime.fromMillisecondsSinceEpoch(0),
purchases: purchases?.toInt() ?? 0,
purchaseOrders: purchaseOrders?.toInt() ?? 0,
quantity: quantity?.toInt() ?? 0,
ingredients: ingredients?.toInt() ?? 0,
vendors: vendors?.toInt() ?? 0,
);
}
@freezed
class PurchasingIngredientDataDto with _$PurchasingIngredientDataDto {
const PurchasingIngredientDataDto._();
const factory PurchasingIngredientDataDto({
@JsonKey(name: 'ingredient_id') String? ingredientId,
@JsonKey(name: 'ingredient_name') String? ingredientName,
@JsonKey(name: 'quantity') num? quantity,
@JsonKey(name: 'total_cost') num? totalCost,
@JsonKey(name: 'average_unit_cost') num? averageUnitCost,
@JsonKey(name: 'purchase_order_count') num? purchaseOrderCount,
}) = _PurchasingIngredientDataDto;
factory PurchasingIngredientDataDto.fromJson(Map<String, dynamic> json) =>
_$PurchasingIngredientDataDtoFromJson(json);
PurchasingIngredientData toDomain() => PurchasingIngredientData(
ingredientId: ingredientId ?? '',
ingredientName: ingredientName ?? '',
quantity: quantity?.toInt() ?? 0,
totalCost: totalCost?.toInt() ?? 0,
averageUnitCost: averageUnitCost?.toDouble() ?? 0,
purchaseOrderCount: purchaseOrderCount?.toInt() ?? 0,
);
}
@freezed
class PurchasingVendorDataDto with _$PurchasingVendorDataDto {
const PurchasingVendorDataDto._();
const factory PurchasingVendorDataDto({
@JsonKey(name: 'vendor_id') String? vendorId,
@JsonKey(name: 'vendor_name') String? vendorName,
@JsonKey(name: 'total_cost') num? totalCost,
@JsonKey(name: 'purchase_order_count') num? purchaseOrderCount,
@JsonKey(name: 'ingredient_count') num? ingredientCount,
@JsonKey(name: 'quantity') num? quantity,
}) = _PurchasingVendorDataDto;
factory PurchasingVendorDataDto.fromJson(Map<String, dynamic> json) =>
_$PurchasingVendorDataDtoFromJson(json);
PurchasingVendorData toDomain() => PurchasingVendorData(
vendorId: vendorId ?? '',
vendorName: vendorName ?? '',
totalCost: totalCost?.toInt() ?? 0,
purchaseOrderCount: purchaseOrderCount?.toInt() ?? 0,
ingredientCount: ingredientCount?.toInt() ?? 0,
quantity: quantity?.toInt() ?? 0,
);
}
@@ -176,4 +176,25 @@ class AnalyticRepository implements IAnalyticRepository {
return left(const AnalyticFailure.unexpectedError());
}
}
@override
Future<Either<AnalyticFailure, PurchasingAnalytic>> getPurchasing({
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
}) async {
try {
final result = await _dataProvider.fetchPurchasing(
dateFrom: dateFrom,
dateTo: dateTo,
outletId: _resolveOutletId(outletId),
);
if (result.hasError) return left(result.error!);
return right(result.data!.toDomain());
} catch (e, s) {
log('getPurchasingError', name: _logName, error: e, stackTrace: s);
return left(const AnalyticFailure.unexpectedError());
}
}
}