feat: profit sharing
Build & Deploy iOS to TestFlight / build-and-deploy (push) Canceled after 0s

This commit is contained in:
efrilm
2026-08-21 22:31:54 +07:00
parent f9bfb69254
commit 2e4c77888e
48 changed files with 12553 additions and 162 deletions
@@ -14,3 +14,4 @@ part 'dto/product_analytic_dto.dart';
part 'dto/payment_method_analytic_dto.dart';
part 'dto/purchasing_analytic_dto.dart';
part 'dto/exclusive_summary_dto.dart';
part 'dto/profit_sharing_dto.dart';
File diff suppressed because it is too large Load Diff
@@ -1121,3 +1121,289 @@ Map<String, dynamic> _$$ExclusiveSummaryTransactionDtoImplToJson(
'amount': instance.amount,
'source': instance.source,
};
_$ProfitSharingDtoImpl _$$ProfitSharingDtoImplFromJson(
Map<String, dynamic> json,
) => _$ProfitSharingDtoImpl(
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),
data: (json['data'] as List<dynamic>?)
?.map((e) => ProfitSharingCategoryDto.fromJson(e as Map<String, dynamic>))
.toList(),
budget: json['budget'] == null
? null
: ProfitSharingBudgetDto.fromJson(json['budget'] as Map<String, dynamic>),
);
Map<String, dynamic> _$$ProfitSharingDtoImplToJson(
_$ProfitSharingDtoImpl 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(),
'data': instance.data,
'budget': instance.budget,
};
_$ProfitSharingCategoryDtoImpl _$$ProfitSharingCategoryDtoImplFromJson(
Map<String, dynamic> json,
) => _$ProfitSharingCategoryDtoImpl(
parentCategoryId: json['parent_category_id'] as String?,
parentCategoryName: json['parent_category_name'] as String?,
totalRevenue: json['total_revenue'] as num?,
totalQuantity: json['total_quantity'] as num?,
categoryCount: json['category_count'] as num?,
productCount: json['product_count'] as num?,
orderCount: json['order_count'] as num?,
totalStandardHpp: json['total_standard_hpp'] as num?,
totalFifoHpp: json['total_fifo_hpp'] as num?,
totalMovingAverageHpp: json['total_moving_average_hpp'] as num?,
);
Map<String, dynamic> _$$ProfitSharingCategoryDtoImplToJson(
_$ProfitSharingCategoryDtoImpl instance,
) => <String, dynamic>{
'parent_category_id': instance.parentCategoryId,
'parent_category_name': instance.parentCategoryName,
'total_revenue': instance.totalRevenue,
'total_quantity': instance.totalQuantity,
'category_count': instance.categoryCount,
'product_count': instance.productCount,
'order_count': instance.orderCount,
'total_standard_hpp': instance.totalStandardHpp,
'total_fifo_hpp': instance.totalFifoHpp,
'total_moving_average_hpp': instance.totalMovingAverageHpp,
};
_$ProfitSharingBudgetDtoImpl _$$ProfitSharingBudgetDtoImplFromJson(
Map<String, dynamic> json,
) => _$ProfitSharingBudgetDtoImpl(
percentages: json['percentages'] == null
? null
: ProfitSharingPercentageDto.fromJson(
json['percentages'] as Map<String, dynamic>,
),
cutOffFrom: json['cut_off_from'] == null
? null
: DateTime.parse(json['cut_off_from'] as String),
cutOffTo: json['cut_off_to'] == null
? null
: DateTime.parse(json['cut_off_to'] as String),
total: json['total'] == null
? null
: ProfitSharingPeriodDto.fromJson(json['total'] as Map<String, dynamic>),
weekly: (json['weekly'] as List<dynamic>?)
?.map((e) => ProfitSharingPeriodDto.fromJson(e as Map<String, dynamic>))
.toList(),
monthly: (json['monthly'] as List<dynamic>?)
?.map((e) => ProfitSharingPeriodDto.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$$ProfitSharingBudgetDtoImplToJson(
_$ProfitSharingBudgetDtoImpl instance,
) => <String, dynamic>{
'percentages': instance.percentages,
'cut_off_from': instance.cutOffFrom?.toIso8601String(),
'cut_off_to': instance.cutOffTo?.toIso8601String(),
'total': instance.total,
'weekly': instance.weekly,
'monthly': instance.monthly,
};
_$ProfitSharingPercentageDtoImpl _$$ProfitSharingPercentageDtoImplFromJson(
Map<String, dynamic> json,
) => _$ProfitSharingPercentageDtoImpl(
purchase: json['purchase'] as num?,
owner: json['owner'] as num?,
team: json['team'] as num?,
);
Map<String, dynamic> _$$ProfitSharingPercentageDtoImplToJson(
_$ProfitSharingPercentageDtoImpl instance,
) => <String, dynamic>{
'purchase': instance.purchase,
'owner': instance.owner,
'team': instance.team,
};
_$ProfitSharingPeriodDtoImpl _$$ProfitSharingPeriodDtoImplFromJson(
Map<String, dynamic> json,
) => _$ProfitSharingPeriodDtoImpl(
periodStart: json['period_start'] == null
? null
: DateTime.parse(json['period_start'] as String),
periodEnd: json['period_end'] == null
? null
: DateTime.parse(json['period_end'] as String),
revenue: json['revenue'] as num?,
orderCount: json['order_count'] as num?,
limitPurchase: json['limit_purchase'] as num?,
limitOwner: json['limit_owner'] as num?,
limitTeam: json['limit_team'] as num?,
month: json['month'] as String?,
weekCount: json['week_count'] as num?,
);
Map<String, dynamic> _$$ProfitSharingPeriodDtoImplToJson(
_$ProfitSharingPeriodDtoImpl instance,
) => <String, dynamic>{
'period_start': instance.periodStart?.toIso8601String(),
'period_end': instance.periodEnd?.toIso8601String(),
'revenue': instance.revenue,
'order_count': instance.orderCount,
'limit_purchase': instance.limitPurchase,
'limit_owner': instance.limitOwner,
'limit_team': instance.limitTeam,
'month': instance.month,
'week_count': instance.weekCount,
};
_$ProfitSharingDetailDtoImpl _$$ProfitSharingDetailDtoImplFromJson(
Map<String, dynamic> json,
) => _$ProfitSharingDetailDtoImpl(
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),
parentCategoryId: json['parent_category_id'] as String?,
parentCategoryName: json['parent_category_name'] as String?,
summary: json['summary'] == null
? null
: ProfitSharingSummaryDto.fromJson(
json['summary'] as Map<String, dynamic>,
),
categories: (json['categories'] as List<dynamic>?)
?.map(
(e) => ProfitSharingSubCategoryDto.fromJson(e as Map<String, dynamic>),
)
.toList(),
budget: json['budget'] == null
? null
: ProfitSharingBudgetDto.fromJson(json['budget'] as Map<String, dynamic>),
);
Map<String, dynamic> _$$ProfitSharingDetailDtoImplToJson(
_$ProfitSharingDetailDtoImpl 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(),
'parent_category_id': instance.parentCategoryId,
'parent_category_name': instance.parentCategoryName,
'summary': instance.summary,
'categories': instance.categories,
'budget': instance.budget,
};
_$ProfitSharingSummaryDtoImpl _$$ProfitSharingSummaryDtoImplFromJson(
Map<String, dynamic> json,
) => _$ProfitSharingSummaryDtoImpl(
totalRevenue: json['total_revenue'] as num?,
totalQuantity: json['total_quantity'] as num?,
categoryCount: json['category_count'] as num?,
productCount: json['product_count'] as num?,
orderCount: json['order_count'] as num?,
totalStandardHpp: json['total_standard_hpp'] as num?,
totalFifoHpp: json['total_fifo_hpp'] as num?,
totalMovingAverageHpp: json['total_moving_average_hpp'] as num?,
);
Map<String, dynamic> _$$ProfitSharingSummaryDtoImplToJson(
_$ProfitSharingSummaryDtoImpl instance,
) => <String, dynamic>{
'total_revenue': instance.totalRevenue,
'total_quantity': instance.totalQuantity,
'category_count': instance.categoryCount,
'product_count': instance.productCount,
'order_count': instance.orderCount,
'total_standard_hpp': instance.totalStandardHpp,
'total_fifo_hpp': instance.totalFifoHpp,
'total_moving_average_hpp': instance.totalMovingAverageHpp,
};
_$ProfitSharingSubCategoryDtoImpl _$$ProfitSharingSubCategoryDtoImplFromJson(
Map<String, dynamic> json,
) => _$ProfitSharingSubCategoryDtoImpl(
categoryId: json['category_id'] as String?,
categoryName: json['category_name'] as String?,
totalRevenue: json['total_revenue'] as num?,
totalQuantity: json['total_quantity'] as num?,
productCount: json['product_count'] as num?,
orderCount: json['order_count'] as num?,
totalStandardHpp: json['total_standard_hpp'] as num?,
totalFifoHpp: json['total_fifo_hpp'] as num?,
totalMovingAverageHpp: json['total_moving_average_hpp'] as num?,
products: (json['products'] as List<dynamic>?)
?.map((e) => ProfitSharingProductDto.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$$ProfitSharingSubCategoryDtoImplToJson(
_$ProfitSharingSubCategoryDtoImpl instance,
) => <String, dynamic>{
'category_id': instance.categoryId,
'category_name': instance.categoryName,
'total_revenue': instance.totalRevenue,
'total_quantity': instance.totalQuantity,
'product_count': instance.productCount,
'order_count': instance.orderCount,
'total_standard_hpp': instance.totalStandardHpp,
'total_fifo_hpp': instance.totalFifoHpp,
'total_moving_average_hpp': instance.totalMovingAverageHpp,
'products': instance.products,
};
_$ProfitSharingProductDtoImpl _$$ProfitSharingProductDtoImplFromJson(
Map<String, dynamic> json,
) => _$ProfitSharingProductDtoImpl(
productId: json['product_id'] as String?,
productName: json['product_name'] as String?,
productSku: json['product_sku'] as String?,
productPrice: json['product_price'] as num?,
quantitySold: json['quantity_sold'] as num?,
revenue: json['revenue'] as num?,
averagePrice: json['average_price'] as num?,
orderCount: json['order_count'] as num?,
standardHppPerUnit: json['standard_hpp_per_unit'] as num?,
standardHppTotal: json['standard_hpp_total'] as num?,
fifoHppPerUnit: json['fifo_hpp_per_unit'] as num?,
fifoHppTotal: json['fifo_hpp_total'] as num?,
movingAverageHppPerUnit: json['moving_average_hpp_per_unit'] as num?,
movingAverageHppTotal: json['moving_average_hpp_total'] as num?,
);
Map<String, dynamic> _$$ProfitSharingProductDtoImplToJson(
_$ProfitSharingProductDtoImpl instance,
) => <String, dynamic>{
'product_id': instance.productId,
'product_name': instance.productName,
'product_sku': instance.productSku,
'product_price': instance.productPrice,
'quantity_sold': instance.quantitySold,
'revenue': instance.revenue,
'average_price': instance.averagePrice,
'order_count': instance.orderCount,
'standard_hpp_per_unit': instance.standardHppPerUnit,
'standard_hpp_total': instance.standardHppTotal,
'fifo_hpp_per_unit': instance.fifoHppPerUnit,
'fifo_hpp_total': instance.fifoHppTotal,
'moving_average_hpp_per_unit': instance.movingAverageHppPerUnit,
'moving_average_hpp_total': instance.movingAverageHppTotal,
};
@@ -295,4 +295,74 @@ class AnalyticRemoteDataProvider {
return DC.error(AnalyticFailure.serverError(e));
}
}
Future<DC<AnalyticFailure, ProfitSharingDto>> fetchProfitSharing({
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
String groupBy = 'day',
}) async {
try {
final Map<String, dynamic> params = {
'date_from': dateFrom.toServerDate,
'date_to': dateTo.toServerDate,
'group_by': groupBy,
};
if (outletId != null) params['outlet_id'] = outletId;
final response = await _apiClient.get(
ApiPath.parentCategoryAnalytic,
params: params,
headers: getAuthorizationHeader(),
);
if (response.data['data'] == null) {
return DC.error(AnalyticFailure.empty());
}
final dto = ProfitSharingDto.fromJson(response.data['data']);
return DC.data(dto);
} on ApiFailure catch (e, s) {
log('fetchProfitSharingError', name: _logName, error: e, stackTrace: s);
return DC.error(AnalyticFailure.serverError(e));
}
}
Future<DC<AnalyticFailure, ProfitSharingDetailDto>> fetchProfitSharingDetail({
required String parentCategoryId,
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.parentCategoryAnalytic}/$parentCategoryId',
params: params,
headers: getAuthorizationHeader(),
);
if (response.data['data'] == null) {
return DC.error(AnalyticFailure.empty());
}
final dto = ProfitSharingDetailDto.fromJson(response.data['data']);
return DC.data(dto);
} on ApiFailure catch (e, s) {
log(
'fetchProfitSharingDetailError',
name: _logName,
error: e,
stackTrace: s,
);
return DC.error(AnalyticFailure.serverError(e));
}
}
}
@@ -0,0 +1,294 @@
part of '../analytic_dtos.dart';
@freezed
class ProfitSharingDto with _$ProfitSharingDto {
const ProfitSharingDto._();
const factory ProfitSharingDto({
@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: 'data') List<ProfitSharingCategoryDto>? data,
@JsonKey(name: 'budget') ProfitSharingBudgetDto? budget,
}) = _ProfitSharingDto;
factory ProfitSharingDto.fromJson(Map<String, dynamic> json) =>
_$ProfitSharingDtoFromJson(json);
ProfitSharing toDomain() => ProfitSharing(
organizationId: organizationId ?? '',
outletId: outletId ?? '',
outletName: outletName ?? '',
dateFrom: dateFrom?.toLocal() ?? DateTime.fromMillisecondsSinceEpoch(0),
dateTo: dateTo?.toLocal() ?? DateTime.fromMillisecondsSinceEpoch(0),
categories: data?.map((e) => e.toDomain()).toList() ?? [],
budget: budget?.toDomain() ?? ProfitSharingBudget.empty(),
);
}
@freezed
class ProfitSharingCategoryDto with _$ProfitSharingCategoryDto {
const ProfitSharingCategoryDto._();
const factory ProfitSharingCategoryDto({
@JsonKey(name: 'parent_category_id') String? parentCategoryId,
@JsonKey(name: 'parent_category_name') String? parentCategoryName,
@JsonKey(name: 'total_revenue') num? totalRevenue,
@JsonKey(name: 'total_quantity') num? totalQuantity,
@JsonKey(name: 'category_count') num? categoryCount,
@JsonKey(name: 'product_count') num? productCount,
@JsonKey(name: 'order_count') num? orderCount,
@JsonKey(name: 'total_standard_hpp') num? totalStandardHpp,
@JsonKey(name: 'total_fifo_hpp') num? totalFifoHpp,
@JsonKey(name: 'total_moving_average_hpp') num? totalMovingAverageHpp,
}) = _ProfitSharingCategoryDto;
factory ProfitSharingCategoryDto.fromJson(Map<String, dynamic> json) =>
_$ProfitSharingCategoryDtoFromJson(json);
ProfitSharingCategory toDomain() => ProfitSharingCategory(
parentCategoryId: parentCategoryId ?? '',
parentCategoryName: parentCategoryName ?? '',
totalRevenue: totalRevenue?.toInt() ?? 0,
totalQuantity: totalQuantity?.toInt() ?? 0,
categoryCount: categoryCount?.toInt() ?? 0,
productCount: productCount?.toInt() ?? 0,
orderCount: orderCount?.toInt() ?? 0,
totalStandardHpp: totalStandardHpp?.toInt() ?? 0,
totalFifoHpp: totalFifoHpp?.toInt() ?? 0,
totalMovingAverageHpp: totalMovingAverageHpp?.toInt() ?? 0,
);
}
@freezed
class ProfitSharingBudgetDto with _$ProfitSharingBudgetDto {
const ProfitSharingBudgetDto._();
const factory ProfitSharingBudgetDto({
@JsonKey(name: 'percentages') ProfitSharingPercentageDto? percentages,
@JsonKey(name: 'cut_off_from') DateTime? cutOffFrom,
@JsonKey(name: 'cut_off_to') DateTime? cutOffTo,
@JsonKey(name: 'total') ProfitSharingPeriodDto? total,
@JsonKey(name: 'weekly') List<ProfitSharingPeriodDto>? weekly,
@JsonKey(name: 'monthly') List<ProfitSharingPeriodDto>? monthly,
}) = _ProfitSharingBudgetDto;
factory ProfitSharingBudgetDto.fromJson(Map<String, dynamic> json) =>
_$ProfitSharingBudgetDtoFromJson(json);
ProfitSharingBudget toDomain() => ProfitSharingBudget(
percentages: percentages?.toDomain() ?? ProfitSharingPercentage.empty(),
cutOffFrom: cutOffFrom?.toLocal() ?? DateTime.fromMillisecondsSinceEpoch(0),
cutOffTo: cutOffTo?.toLocal() ?? DateTime.fromMillisecondsSinceEpoch(0),
total: total?.toDomain() ?? ProfitSharingPeriod.empty(),
weekly: weekly?.map((e) => e.toDomain()).toList() ?? [],
monthly: monthly?.map((e) => e.toDomain()).toList() ?? [],
);
}
@freezed
class ProfitSharingPercentageDto with _$ProfitSharingPercentageDto {
const ProfitSharingPercentageDto._();
const factory ProfitSharingPercentageDto({
@JsonKey(name: 'purchase') num? purchase,
@JsonKey(name: 'owner') num? owner,
@JsonKey(name: 'team') num? team,
}) = _ProfitSharingPercentageDto;
factory ProfitSharingPercentageDto.fromJson(Map<String, dynamic> json) =>
_$ProfitSharingPercentageDtoFromJson(json);
ProfitSharingPercentage toDomain() => ProfitSharingPercentage(
purchase: purchase?.toDouble() ?? 0,
owner: owner?.toDouble() ?? 0,
team: team?.toDouble() ?? 0,
);
}
@freezed
class ProfitSharingPeriodDto with _$ProfitSharingPeriodDto {
const ProfitSharingPeriodDto._();
const factory ProfitSharingPeriodDto({
@JsonKey(name: 'period_start') DateTime? periodStart,
@JsonKey(name: 'period_end') DateTime? periodEnd,
@JsonKey(name: 'revenue') num? revenue,
@JsonKey(name: 'order_count') num? orderCount,
@JsonKey(name: 'limit_purchase') num? limitPurchase,
@JsonKey(name: 'limit_owner') num? limitOwner,
@JsonKey(name: 'limit_team') num? limitTeam,
@JsonKey(name: 'month') String? month,
@JsonKey(name: 'week_count') num? weekCount,
}) = _ProfitSharingPeriodDto;
factory ProfitSharingPeriodDto.fromJson(Map<String, dynamic> json) =>
_$ProfitSharingPeriodDtoFromJson(json);
ProfitSharingPeriod toDomain() => ProfitSharingPeriod(
periodStart:
periodStart?.toLocal() ?? DateTime.fromMillisecondsSinceEpoch(0),
periodEnd: periodEnd?.toLocal() ?? DateTime.fromMillisecondsSinceEpoch(0),
revenue: revenue?.toInt() ?? 0,
orderCount: orderCount?.toInt() ?? 0,
limitPurchase: limitPurchase?.toInt() ?? 0,
limitOwner: limitOwner?.toInt() ?? 0,
limitTeam: limitTeam?.toInt() ?? 0,
month: month ?? '',
weekCount: weekCount?.toInt() ?? 0,
);
}
@freezed
class ProfitSharingDetailDto with _$ProfitSharingDetailDto {
const ProfitSharingDetailDto._();
const factory ProfitSharingDetailDto({
@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: 'parent_category_id') String? parentCategoryId,
@JsonKey(name: 'parent_category_name') String? parentCategoryName,
@JsonKey(name: 'summary') ProfitSharingSummaryDto? summary,
@JsonKey(name: 'categories') List<ProfitSharingSubCategoryDto>? categories,
@JsonKey(name: 'budget') ProfitSharingBudgetDto? budget,
}) = _ProfitSharingDetailDto;
factory ProfitSharingDetailDto.fromJson(Map<String, dynamic> json) =>
_$ProfitSharingDetailDtoFromJson(json);
ProfitSharingDetail toDomain() => ProfitSharingDetail(
organizationId: organizationId ?? '',
outletId: outletId ?? '',
outletName: outletName ?? '',
dateFrom: dateFrom?.toLocal() ?? DateTime.fromMillisecondsSinceEpoch(0),
dateTo: dateTo?.toLocal() ?? DateTime.fromMillisecondsSinceEpoch(0),
parentCategoryId: parentCategoryId ?? '',
parentCategoryName: parentCategoryName ?? '',
summary:
summary?.toDomain(
parentCategoryId: parentCategoryId ?? '',
parentCategoryName: parentCategoryName ?? '',
) ??
ProfitSharingCategory.empty(),
categories: categories?.map((e) => e.toDomain()).toList() ?? [],
budget: budget?.toDomain() ?? ProfitSharingBudget.empty(),
);
}
/// Ringkasan kategori induk pada endpoint detail — bentuknya sama dengan item
/// pada endpoint daftar, hanya saja id & nama kategori ada di level atas.
@freezed
class ProfitSharingSummaryDto with _$ProfitSharingSummaryDto {
const ProfitSharingSummaryDto._();
const factory ProfitSharingSummaryDto({
@JsonKey(name: 'total_revenue') num? totalRevenue,
@JsonKey(name: 'total_quantity') num? totalQuantity,
@JsonKey(name: 'category_count') num? categoryCount,
@JsonKey(name: 'product_count') num? productCount,
@JsonKey(name: 'order_count') num? orderCount,
@JsonKey(name: 'total_standard_hpp') num? totalStandardHpp,
@JsonKey(name: 'total_fifo_hpp') num? totalFifoHpp,
@JsonKey(name: 'total_moving_average_hpp') num? totalMovingAverageHpp,
}) = _ProfitSharingSummaryDto;
factory ProfitSharingSummaryDto.fromJson(Map<String, dynamic> json) =>
_$ProfitSharingSummaryDtoFromJson(json);
ProfitSharingCategory toDomain({
required String parentCategoryId,
required String parentCategoryName,
}) => ProfitSharingCategory(
parentCategoryId: parentCategoryId,
parentCategoryName: parentCategoryName,
totalRevenue: totalRevenue?.toInt() ?? 0,
totalQuantity: totalQuantity?.toInt() ?? 0,
categoryCount: categoryCount?.toInt() ?? 0,
productCount: productCount?.toInt() ?? 0,
orderCount: orderCount?.toInt() ?? 0,
totalStandardHpp: totalStandardHpp?.toInt() ?? 0,
totalFifoHpp: totalFifoHpp?.toInt() ?? 0,
totalMovingAverageHpp: totalMovingAverageHpp?.toInt() ?? 0,
);
}
@freezed
class ProfitSharingSubCategoryDto with _$ProfitSharingSubCategoryDto {
const ProfitSharingSubCategoryDto._();
const factory ProfitSharingSubCategoryDto({
@JsonKey(name: 'category_id') String? categoryId,
@JsonKey(name: 'category_name') String? categoryName,
@JsonKey(name: 'total_revenue') num? totalRevenue,
@JsonKey(name: 'total_quantity') num? totalQuantity,
@JsonKey(name: 'product_count') num? productCount,
@JsonKey(name: 'order_count') num? orderCount,
@JsonKey(name: 'total_standard_hpp') num? totalStandardHpp,
@JsonKey(name: 'total_fifo_hpp') num? totalFifoHpp,
@JsonKey(name: 'total_moving_average_hpp') num? totalMovingAverageHpp,
@JsonKey(name: 'products') List<ProfitSharingProductDto>? products,
}) = _ProfitSharingSubCategoryDto;
factory ProfitSharingSubCategoryDto.fromJson(Map<String, dynamic> json) =>
_$ProfitSharingSubCategoryDtoFromJson(json);
ProfitSharingSubCategory toDomain() => ProfitSharingSubCategory(
categoryId: categoryId ?? '',
categoryName: categoryName ?? '',
totalRevenue: totalRevenue?.toInt() ?? 0,
totalQuantity: totalQuantity?.toInt() ?? 0,
productCount: productCount?.toInt() ?? 0,
orderCount: orderCount?.toInt() ?? 0,
totalStandardHpp: totalStandardHpp?.toInt() ?? 0,
totalFifoHpp: totalFifoHpp?.toInt() ?? 0,
totalMovingAverageHpp: totalMovingAverageHpp?.toInt() ?? 0,
products: products?.map((e) => e.toDomain()).toList() ?? [],
);
}
@freezed
class ProfitSharingProductDto with _$ProfitSharingProductDto {
const ProfitSharingProductDto._();
const factory ProfitSharingProductDto({
@JsonKey(name: 'product_id') String? productId,
@JsonKey(name: 'product_name') String? productName,
@JsonKey(name: 'product_sku') String? productSku,
@JsonKey(name: 'product_price') num? productPrice,
@JsonKey(name: 'quantity_sold') num? quantitySold,
@JsonKey(name: 'revenue') num? revenue,
@JsonKey(name: 'average_price') num? averagePrice,
@JsonKey(name: 'order_count') num? orderCount,
@JsonKey(name: 'standard_hpp_per_unit') num? standardHppPerUnit,
@JsonKey(name: 'standard_hpp_total') num? standardHppTotal,
@JsonKey(name: 'fifo_hpp_per_unit') num? fifoHppPerUnit,
@JsonKey(name: 'fifo_hpp_total') num? fifoHppTotal,
@JsonKey(name: 'moving_average_hpp_per_unit') num? movingAverageHppPerUnit,
@JsonKey(name: 'moving_average_hpp_total') num? movingAverageHppTotal,
}) = _ProfitSharingProductDto;
factory ProfitSharingProductDto.fromJson(Map<String, dynamic> json) =>
_$ProfitSharingProductDtoFromJson(json);
ProfitSharingProduct toDomain() => ProfitSharingProduct(
productId: productId ?? '',
productName: productName ?? '',
productSku: productSku ?? '',
productPrice: productPrice?.toInt() ?? 0,
quantitySold: quantitySold?.toInt() ?? 0,
revenue: revenue?.toInt() ?? 0,
averagePrice: averagePrice?.toDouble() ?? 0,
orderCount: orderCount?.toInt() ?? 0,
standardHppPerUnit: standardHppPerUnit?.toDouble() ?? 0,
standardHppTotal: standardHppTotal?.toInt() ?? 0,
fifoHppPerUnit: fifoHppPerUnit?.toDouble() ?? 0,
fifoHppTotal: fifoHppTotal?.toInt() ?? 0,
movingAverageHppPerUnit: movingAverageHppPerUnit?.toDouble() ?? 0,
movingAverageHppTotal: movingAverageHppTotal?.toInt() ?? 0,
);
}
@@ -220,4 +220,50 @@ class AnalyticRepository implements IAnalyticRepository {
return left(const AnalyticFailure.unexpectedError());
}
}
@override
Future<Either<AnalyticFailure, ProfitSharing>> getProfitSharing({
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
String groupBy = 'day',
}) async {
try {
final result = await _dataProvider.fetchProfitSharing(
dateFrom: dateFrom,
dateTo: dateTo,
outletId: _resolveOutletId(outletId),
groupBy: groupBy,
);
if (result.hasError) return left(result.error!);
return right(result.data!.toDomain());
} catch (e, s) {
log('getProfitSharingError', name: _logName, error: e, stackTrace: s);
return left(const AnalyticFailure.unexpectedError());
}
}
@override
Future<Either<AnalyticFailure, ProfitSharingDetail>> getProfitSharingDetail({
required String parentCategoryId,
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
}) async {
try {
final result = await _dataProvider.fetchProfitSharingDetail(
parentCategoryId: parentCategoryId,
dateFrom: dateFrom,
dateTo: dateTo,
outletId: _resolveOutletId(outletId),
);
if (result.hasError) return left(result.error!);
return right(result.data!.toDomain());
} catch (e, s) {
log('getProfitSharingDetailError', name: _logName, error: e, stackTrace: s);
return left(const AnalyticFailure.unexpectedError());
}
}
}