report category

This commit is contained in:
efrilm 2025-11-03 23:24:16 +07:00
parent 13941d4881
commit 2a44ce023e
18 changed files with 2163 additions and 1 deletions

View File

@ -0,0 +1,52 @@
import 'package:bloc/bloc.dart';
import 'package:dartz/dartz.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:injectable/injectable.dart';
import '../../../domain/analytic/analytic.dart';
part 'category_analytic_loader_event.dart';
part 'category_analytic_loader_state.dart';
part 'category_analytic_loader_bloc.freezed.dart';
@injectable
class CategoryAnalyticLoaderBloc
extends Bloc<CategoryAnalyticLoaderEvent, CategoryAnalyticLoaderState> {
final IAnalyticRepository _analyticRepository;
CategoryAnalyticLoaderBloc(this._analyticRepository)
: super(CategoryAnalyticLoaderState.initial()) {
on<CategoryAnalyticLoaderEvent>(_onCategoryAnalyticLoaderEvent);
}
Future<void> _onCategoryAnalyticLoaderEvent(
CategoryAnalyticLoaderEvent event,
Emitter<CategoryAnalyticLoaderState> emit,
) {
return event.map(
fetched: (e) async {
emit(state.copyWith(isFetching: true, failureOption: none()));
final result = await _analyticRepository.getCategories(
dateFrom: e.startDate,
dateTo: e.endDate,
);
await result.fold(
(failure) async {
emit(
state.copyWith(
isFetching: false,
failureOption: optionOf(failure),
),
);
},
(categories) async {
emit(
state.copyWith(isFetching: false, categoryAnalytic: categories),
);
},
);
},
);
}
}

View File

@ -0,0 +1,476 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'category_analytic_loader_bloc.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models',
);
/// @nodoc
mixin _$CategoryAnalyticLoaderEvent {
DateTime get startDate => throw _privateConstructorUsedError;
DateTime get endDate => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(DateTime startDate, DateTime endDate) fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(DateTime startDate, DateTime endDate)? fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(DateTime startDate, DateTime endDate)? fetched,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Fetched value) fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_Fetched value)? fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Fetched value)? fetched,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
/// Create a copy of CategoryAnalyticLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$CategoryAnalyticLoaderEventCopyWith<CategoryAnalyticLoaderEvent>
get copyWith => throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $CategoryAnalyticLoaderEventCopyWith<$Res> {
factory $CategoryAnalyticLoaderEventCopyWith(
CategoryAnalyticLoaderEvent value,
$Res Function(CategoryAnalyticLoaderEvent) then,
) =
_$CategoryAnalyticLoaderEventCopyWithImpl<
$Res,
CategoryAnalyticLoaderEvent
>;
@useResult
$Res call({DateTime startDate, DateTime endDate});
}
/// @nodoc
class _$CategoryAnalyticLoaderEventCopyWithImpl<
$Res,
$Val extends CategoryAnalyticLoaderEvent
>
implements $CategoryAnalyticLoaderEventCopyWith<$Res> {
_$CategoryAnalyticLoaderEventCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of CategoryAnalyticLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({Object? startDate = null, Object? endDate = null}) {
return _then(
_value.copyWith(
startDate: null == startDate
? _value.startDate
: startDate // ignore: cast_nullable_to_non_nullable
as DateTime,
endDate: null == endDate
? _value.endDate
: endDate // ignore: cast_nullable_to_non_nullable
as DateTime,
)
as $Val,
);
}
}
/// @nodoc
abstract class _$$FetchedImplCopyWith<$Res>
implements $CategoryAnalyticLoaderEventCopyWith<$Res> {
factory _$$FetchedImplCopyWith(
_$FetchedImpl value,
$Res Function(_$FetchedImpl) then,
) = __$$FetchedImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({DateTime startDate, DateTime endDate});
}
/// @nodoc
class __$$FetchedImplCopyWithImpl<$Res>
extends _$CategoryAnalyticLoaderEventCopyWithImpl<$Res, _$FetchedImpl>
implements _$$FetchedImplCopyWith<$Res> {
__$$FetchedImplCopyWithImpl(
_$FetchedImpl _value,
$Res Function(_$FetchedImpl) _then,
) : super(_value, _then);
/// Create a copy of CategoryAnalyticLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({Object? startDate = null, Object? endDate = null}) {
return _then(
_$FetchedImpl(
startDate: null == startDate
? _value.startDate
: startDate // ignore: cast_nullable_to_non_nullable
as DateTime,
endDate: null == endDate
? _value.endDate
: endDate // ignore: cast_nullable_to_non_nullable
as DateTime,
),
);
}
}
/// @nodoc
class _$FetchedImpl implements _Fetched {
const _$FetchedImpl({required this.startDate, required this.endDate});
@override
final DateTime startDate;
@override
final DateTime endDate;
@override
String toString() {
return 'CategoryAnalyticLoaderEvent.fetched(startDate: $startDate, endDate: $endDate)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$FetchedImpl &&
(identical(other.startDate, startDate) ||
other.startDate == startDate) &&
(identical(other.endDate, endDate) || other.endDate == endDate));
}
@override
int get hashCode => Object.hash(runtimeType, startDate, endDate);
/// Create a copy of CategoryAnalyticLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$FetchedImplCopyWith<_$FetchedImpl> get copyWith =>
__$$FetchedImplCopyWithImpl<_$FetchedImpl>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(DateTime startDate, DateTime endDate) fetched,
}) {
return fetched(startDate, endDate);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(DateTime startDate, DateTime endDate)? fetched,
}) {
return fetched?.call(startDate, endDate);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(DateTime startDate, DateTime endDate)? fetched,
required TResult orElse(),
}) {
if (fetched != null) {
return fetched(startDate, endDate);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Fetched value) fetched,
}) {
return fetched(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_Fetched value)? fetched,
}) {
return fetched?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Fetched value)? fetched,
required TResult orElse(),
}) {
if (fetched != null) {
return fetched(this);
}
return orElse();
}
}
abstract class _Fetched implements CategoryAnalyticLoaderEvent {
const factory _Fetched({
required final DateTime startDate,
required final DateTime endDate,
}) = _$FetchedImpl;
@override
DateTime get startDate;
@override
DateTime get endDate;
/// Create a copy of CategoryAnalyticLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$FetchedImplCopyWith<_$FetchedImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
mixin _$CategoryAnalyticLoaderState {
CategoryAnalytic get categoryAnalytic => throw _privateConstructorUsedError;
Option<AnalyticFailure> get failureOption =>
throw _privateConstructorUsedError;
bool get isFetching => throw _privateConstructorUsedError;
/// Create a copy of CategoryAnalyticLoaderState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$CategoryAnalyticLoaderStateCopyWith<CategoryAnalyticLoaderState>
get copyWith => throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $CategoryAnalyticLoaderStateCopyWith<$Res> {
factory $CategoryAnalyticLoaderStateCopyWith(
CategoryAnalyticLoaderState value,
$Res Function(CategoryAnalyticLoaderState) then,
) =
_$CategoryAnalyticLoaderStateCopyWithImpl<
$Res,
CategoryAnalyticLoaderState
>;
@useResult
$Res call({
CategoryAnalytic categoryAnalytic,
Option<AnalyticFailure> failureOption,
bool isFetching,
});
$CategoryAnalyticCopyWith<$Res> get categoryAnalytic;
}
/// @nodoc
class _$CategoryAnalyticLoaderStateCopyWithImpl<
$Res,
$Val extends CategoryAnalyticLoaderState
>
implements $CategoryAnalyticLoaderStateCopyWith<$Res> {
_$CategoryAnalyticLoaderStateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of CategoryAnalyticLoaderState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? categoryAnalytic = null,
Object? failureOption = null,
Object? isFetching = null,
}) {
return _then(
_value.copyWith(
categoryAnalytic: null == categoryAnalytic
? _value.categoryAnalytic
: categoryAnalytic // ignore: cast_nullable_to_non_nullable
as CategoryAnalytic,
failureOption: null == failureOption
? _value.failureOption
: failureOption // ignore: cast_nullable_to_non_nullable
as Option<AnalyticFailure>,
isFetching: null == isFetching
? _value.isFetching
: isFetching // ignore: cast_nullable_to_non_nullable
as bool,
)
as $Val,
);
}
/// Create a copy of CategoryAnalyticLoaderState
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$CategoryAnalyticCopyWith<$Res> get categoryAnalytic {
return $CategoryAnalyticCopyWith<$Res>(_value.categoryAnalytic, (value) {
return _then(_value.copyWith(categoryAnalytic: value) as $Val);
});
}
}
/// @nodoc
abstract class _$$CategoryAnalyticLoaderStateImplCopyWith<$Res>
implements $CategoryAnalyticLoaderStateCopyWith<$Res> {
factory _$$CategoryAnalyticLoaderStateImplCopyWith(
_$CategoryAnalyticLoaderStateImpl value,
$Res Function(_$CategoryAnalyticLoaderStateImpl) then,
) = __$$CategoryAnalyticLoaderStateImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({
CategoryAnalytic categoryAnalytic,
Option<AnalyticFailure> failureOption,
bool isFetching,
});
@override
$CategoryAnalyticCopyWith<$Res> get categoryAnalytic;
}
/// @nodoc
class __$$CategoryAnalyticLoaderStateImplCopyWithImpl<$Res>
extends
_$CategoryAnalyticLoaderStateCopyWithImpl<
$Res,
_$CategoryAnalyticLoaderStateImpl
>
implements _$$CategoryAnalyticLoaderStateImplCopyWith<$Res> {
__$$CategoryAnalyticLoaderStateImplCopyWithImpl(
_$CategoryAnalyticLoaderStateImpl _value,
$Res Function(_$CategoryAnalyticLoaderStateImpl) _then,
) : super(_value, _then);
/// Create a copy of CategoryAnalyticLoaderState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? categoryAnalytic = null,
Object? failureOption = null,
Object? isFetching = null,
}) {
return _then(
_$CategoryAnalyticLoaderStateImpl(
categoryAnalytic: null == categoryAnalytic
? _value.categoryAnalytic
: categoryAnalytic // ignore: cast_nullable_to_non_nullable
as CategoryAnalytic,
failureOption: null == failureOption
? _value.failureOption
: failureOption // ignore: cast_nullable_to_non_nullable
as Option<AnalyticFailure>,
isFetching: null == isFetching
? _value.isFetching
: isFetching // ignore: cast_nullable_to_non_nullable
as bool,
),
);
}
}
/// @nodoc
class _$CategoryAnalyticLoaderStateImpl
implements _CategoryAnalyticLoaderState {
_$CategoryAnalyticLoaderStateImpl({
required this.categoryAnalytic,
required this.failureOption,
this.isFetching = false,
});
@override
final CategoryAnalytic categoryAnalytic;
@override
final Option<AnalyticFailure> failureOption;
@override
@JsonKey()
final bool isFetching;
@override
String toString() {
return 'CategoryAnalyticLoaderState(categoryAnalytic: $categoryAnalytic, failureOption: $failureOption, isFetching: $isFetching)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$CategoryAnalyticLoaderStateImpl &&
(identical(other.categoryAnalytic, categoryAnalytic) ||
other.categoryAnalytic == categoryAnalytic) &&
(identical(other.failureOption, failureOption) ||
other.failureOption == failureOption) &&
(identical(other.isFetching, isFetching) ||
other.isFetching == isFetching));
}
@override
int get hashCode =>
Object.hash(runtimeType, categoryAnalytic, failureOption, isFetching);
/// Create a copy of CategoryAnalyticLoaderState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$CategoryAnalyticLoaderStateImplCopyWith<_$CategoryAnalyticLoaderStateImpl>
get copyWith =>
__$$CategoryAnalyticLoaderStateImplCopyWithImpl<
_$CategoryAnalyticLoaderStateImpl
>(this, _$identity);
}
abstract class _CategoryAnalyticLoaderState
implements CategoryAnalyticLoaderState {
factory _CategoryAnalyticLoaderState({
required final CategoryAnalytic categoryAnalytic,
required final Option<AnalyticFailure> failureOption,
final bool isFetching,
}) = _$CategoryAnalyticLoaderStateImpl;
@override
CategoryAnalytic get categoryAnalytic;
@override
Option<AnalyticFailure> get failureOption;
@override
bool get isFetching;
/// Create a copy of CategoryAnalyticLoaderState
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$CategoryAnalyticLoaderStateImplCopyWith<_$CategoryAnalyticLoaderStateImpl>
get copyWith => throw _privateConstructorUsedError;
}

View File

@ -0,0 +1,9 @@
part of 'category_analytic_loader_bloc.dart';
@freezed
class CategoryAnalyticLoaderEvent with _$CategoryAnalyticLoaderEvent {
const factory CategoryAnalyticLoaderEvent.fetched({
required DateTime startDate,
required DateTime endDate,
}) = _Fetched;
}

View File

@ -0,0 +1,15 @@
part of 'category_analytic_loader_bloc.dart';
@freezed
class CategoryAnalyticLoaderState with _$CategoryAnalyticLoaderState {
factory CategoryAnalyticLoaderState({
required CategoryAnalytic categoryAnalytic,
required Option<AnalyticFailure> failureOption,
@Default(false) bool isFetching,
}) = _CategoryAnalyticLoaderState;
factory CategoryAnalyticLoaderState.initial() => CategoryAnalyticLoaderState(
categoryAnalytic: CategoryAnalytic.empty(),
failureOption: none(),
);
}

View File

@ -14,4 +14,5 @@ class ApiPath {
static const String analyticPaymentMethods =
'/api/v1/analytics/payment-methods';
static const String analyticProfitLoss = '/api/v1/analytics/profit-loss';
static const String analyticCategories = '/api/v1/analytics/categories';
}

View File

@ -10,5 +10,6 @@ part 'entities/sales_entity.dart';
part 'entities/product_analytic_entity.dart';
part 'entities/payment_method_analytic_entity.dart';
part 'entities/profit_loss_analytic_entity.dart';
part 'entities/category_analytic_entity.dart';
part 'failures/analytic_failure.dart';
part 'repositories/i_analytic_repository.dart';

View File

@ -5357,6 +5357,515 @@ abstract class _ProfitLossAnalyticProduct implements ProfitLossAnalyticProduct {
get copyWith => throw _privateConstructorUsedError;
}
/// @nodoc
mixin _$CategoryAnalytic {
String get organizationId => throw _privateConstructorUsedError;
String get outletId => throw _privateConstructorUsedError;
DateTime get dateFrom => throw _privateConstructorUsedError;
DateTime get dateTo => throw _privateConstructorUsedError;
List<CategoryAnalyticItem> get data => throw _privateConstructorUsedError;
/// Create a copy of CategoryAnalytic
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$CategoryAnalyticCopyWith<CategoryAnalytic> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $CategoryAnalyticCopyWith<$Res> {
factory $CategoryAnalyticCopyWith(
CategoryAnalytic value,
$Res Function(CategoryAnalytic) then,
) = _$CategoryAnalyticCopyWithImpl<$Res, CategoryAnalytic>;
@useResult
$Res call({
String organizationId,
String outletId,
DateTime dateFrom,
DateTime dateTo,
List<CategoryAnalyticItem> data,
});
}
/// @nodoc
class _$CategoryAnalyticCopyWithImpl<$Res, $Val extends CategoryAnalytic>
implements $CategoryAnalyticCopyWith<$Res> {
_$CategoryAnalyticCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of CategoryAnalytic
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? organizationId = null,
Object? outletId = null,
Object? dateFrom = null,
Object? dateTo = null,
Object? data = null,
}) {
return _then(
_value.copyWith(
organizationId: null == organizationId
? _value.organizationId
: organizationId // ignore: cast_nullable_to_non_nullable
as String,
outletId: null == outletId
? _value.outletId
: outletId // ignore: cast_nullable_to_non_nullable
as String,
dateFrom: null == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as DateTime,
dateTo: null == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as DateTime,
data: null == data
? _value.data
: data // ignore: cast_nullable_to_non_nullable
as List<CategoryAnalyticItem>,
)
as $Val,
);
}
}
/// @nodoc
abstract class _$$CategoryAnalyticImplCopyWith<$Res>
implements $CategoryAnalyticCopyWith<$Res> {
factory _$$CategoryAnalyticImplCopyWith(
_$CategoryAnalyticImpl value,
$Res Function(_$CategoryAnalyticImpl) then,
) = __$$CategoryAnalyticImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({
String organizationId,
String outletId,
DateTime dateFrom,
DateTime dateTo,
List<CategoryAnalyticItem> data,
});
}
/// @nodoc
class __$$CategoryAnalyticImplCopyWithImpl<$Res>
extends _$CategoryAnalyticCopyWithImpl<$Res, _$CategoryAnalyticImpl>
implements _$$CategoryAnalyticImplCopyWith<$Res> {
__$$CategoryAnalyticImplCopyWithImpl(
_$CategoryAnalyticImpl _value,
$Res Function(_$CategoryAnalyticImpl) _then,
) : super(_value, _then);
/// Create a copy of CategoryAnalytic
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? organizationId = null,
Object? outletId = null,
Object? dateFrom = null,
Object? dateTo = null,
Object? data = null,
}) {
return _then(
_$CategoryAnalyticImpl(
organizationId: null == organizationId
? _value.organizationId
: organizationId // ignore: cast_nullable_to_non_nullable
as String,
outletId: null == outletId
? _value.outletId
: outletId // ignore: cast_nullable_to_non_nullable
as String,
dateFrom: null == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as DateTime,
dateTo: null == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as DateTime,
data: null == data
? _value._data
: data // ignore: cast_nullable_to_non_nullable
as List<CategoryAnalyticItem>,
),
);
}
}
/// @nodoc
class _$CategoryAnalyticImpl extends _CategoryAnalytic {
const _$CategoryAnalyticImpl({
required this.organizationId,
required this.outletId,
required this.dateFrom,
required this.dateTo,
required final List<CategoryAnalyticItem> data,
}) : _data = data,
super._();
@override
final String organizationId;
@override
final String outletId;
@override
final DateTime dateFrom;
@override
final DateTime dateTo;
final List<CategoryAnalyticItem> _data;
@override
List<CategoryAnalyticItem> get data {
if (_data is EqualUnmodifiableListView) return _data;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_data);
}
@override
String toString() {
return 'CategoryAnalytic(organizationId: $organizationId, outletId: $outletId, dateFrom: $dateFrom, dateTo: $dateTo, data: $data)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$CategoryAnalyticImpl &&
(identical(other.organizationId, organizationId) ||
other.organizationId == organizationId) &&
(identical(other.outletId, outletId) ||
other.outletId == outletId) &&
(identical(other.dateFrom, dateFrom) ||
other.dateFrom == dateFrom) &&
(identical(other.dateTo, dateTo) || other.dateTo == dateTo) &&
const DeepCollectionEquality().equals(other._data, _data));
}
@override
int get hashCode => Object.hash(
runtimeType,
organizationId,
outletId,
dateFrom,
dateTo,
const DeepCollectionEquality().hash(_data),
);
/// Create a copy of CategoryAnalytic
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$CategoryAnalyticImplCopyWith<_$CategoryAnalyticImpl> get copyWith =>
__$$CategoryAnalyticImplCopyWithImpl<_$CategoryAnalyticImpl>(
this,
_$identity,
);
}
abstract class _CategoryAnalytic extends CategoryAnalytic {
const factory _CategoryAnalytic({
required final String organizationId,
required final String outletId,
required final DateTime dateFrom,
required final DateTime dateTo,
required final List<CategoryAnalyticItem> data,
}) = _$CategoryAnalyticImpl;
const _CategoryAnalytic._() : super._();
@override
String get organizationId;
@override
String get outletId;
@override
DateTime get dateFrom;
@override
DateTime get dateTo;
@override
List<CategoryAnalyticItem> get data;
/// Create a copy of CategoryAnalytic
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$CategoryAnalyticImplCopyWith<_$CategoryAnalyticImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
mixin _$CategoryAnalyticItem {
String get categoryId => throw _privateConstructorUsedError;
String get categoryName => throw _privateConstructorUsedError;
int get totalRevenue => throw _privateConstructorUsedError;
int get totalQuantity => throw _privateConstructorUsedError;
int get productCount => throw _privateConstructorUsedError;
int get orderCount => throw _privateConstructorUsedError;
/// Create a copy of CategoryAnalyticItem
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$CategoryAnalyticItemCopyWith<CategoryAnalyticItem> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $CategoryAnalyticItemCopyWith<$Res> {
factory $CategoryAnalyticItemCopyWith(
CategoryAnalyticItem value,
$Res Function(CategoryAnalyticItem) then,
) = _$CategoryAnalyticItemCopyWithImpl<$Res, CategoryAnalyticItem>;
@useResult
$Res call({
String categoryId,
String categoryName,
int totalRevenue,
int totalQuantity,
int productCount,
int orderCount,
});
}
/// @nodoc
class _$CategoryAnalyticItemCopyWithImpl<
$Res,
$Val extends CategoryAnalyticItem
>
implements $CategoryAnalyticItemCopyWith<$Res> {
_$CategoryAnalyticItemCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of CategoryAnalyticItem
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? categoryId = null,
Object? categoryName = null,
Object? totalRevenue = null,
Object? totalQuantity = null,
Object? productCount = null,
Object? orderCount = null,
}) {
return _then(
_value.copyWith(
categoryId: null == categoryId
? _value.categoryId
: categoryId // ignore: cast_nullable_to_non_nullable
as String,
categoryName: null == categoryName
? _value.categoryName
: categoryName // ignore: cast_nullable_to_non_nullable
as String,
totalRevenue: null == totalRevenue
? _value.totalRevenue
: totalRevenue // ignore: cast_nullable_to_non_nullable
as int,
totalQuantity: null == totalQuantity
? _value.totalQuantity
: totalQuantity // ignore: cast_nullable_to_non_nullable
as int,
productCount: null == productCount
? _value.productCount
: productCount // ignore: cast_nullable_to_non_nullable
as int,
orderCount: null == orderCount
? _value.orderCount
: orderCount // ignore: cast_nullable_to_non_nullable
as int,
)
as $Val,
);
}
}
/// @nodoc
abstract class _$$CategoryAnalyticItemImplCopyWith<$Res>
implements $CategoryAnalyticItemCopyWith<$Res> {
factory _$$CategoryAnalyticItemImplCopyWith(
_$CategoryAnalyticItemImpl value,
$Res Function(_$CategoryAnalyticItemImpl) then,
) = __$$CategoryAnalyticItemImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({
String categoryId,
String categoryName,
int totalRevenue,
int totalQuantity,
int productCount,
int orderCount,
});
}
/// @nodoc
class __$$CategoryAnalyticItemImplCopyWithImpl<$Res>
extends _$CategoryAnalyticItemCopyWithImpl<$Res, _$CategoryAnalyticItemImpl>
implements _$$CategoryAnalyticItemImplCopyWith<$Res> {
__$$CategoryAnalyticItemImplCopyWithImpl(
_$CategoryAnalyticItemImpl _value,
$Res Function(_$CategoryAnalyticItemImpl) _then,
) : super(_value, _then);
/// Create a copy of CategoryAnalyticItem
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? categoryId = null,
Object? categoryName = null,
Object? totalRevenue = null,
Object? totalQuantity = null,
Object? productCount = null,
Object? orderCount = null,
}) {
return _then(
_$CategoryAnalyticItemImpl(
categoryId: null == categoryId
? _value.categoryId
: categoryId // ignore: cast_nullable_to_non_nullable
as String,
categoryName: null == categoryName
? _value.categoryName
: categoryName // ignore: cast_nullable_to_non_nullable
as String,
totalRevenue: null == totalRevenue
? _value.totalRevenue
: totalRevenue // ignore: cast_nullable_to_non_nullable
as int,
totalQuantity: null == totalQuantity
? _value.totalQuantity
: totalQuantity // ignore: cast_nullable_to_non_nullable
as int,
productCount: null == productCount
? _value.productCount
: productCount // ignore: cast_nullable_to_non_nullable
as int,
orderCount: null == orderCount
? _value.orderCount
: orderCount // ignore: cast_nullable_to_non_nullable
as int,
),
);
}
}
/// @nodoc
class _$CategoryAnalyticItemImpl implements _CategoryAnalyticItem {
const _$CategoryAnalyticItemImpl({
required this.categoryId,
required this.categoryName,
required this.totalRevenue,
required this.totalQuantity,
required this.productCount,
required this.orderCount,
});
@override
final String categoryId;
@override
final String categoryName;
@override
final int totalRevenue;
@override
final int totalQuantity;
@override
final int productCount;
@override
final int orderCount;
@override
String toString() {
return 'CategoryAnalyticItem(categoryId: $categoryId, categoryName: $categoryName, totalRevenue: $totalRevenue, totalQuantity: $totalQuantity, productCount: $productCount, orderCount: $orderCount)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$CategoryAnalyticItemImpl &&
(identical(other.categoryId, categoryId) ||
other.categoryId == categoryId) &&
(identical(other.categoryName, categoryName) ||
other.categoryName == categoryName) &&
(identical(other.totalRevenue, totalRevenue) ||
other.totalRevenue == totalRevenue) &&
(identical(other.totalQuantity, totalQuantity) ||
other.totalQuantity == totalQuantity) &&
(identical(other.productCount, productCount) ||
other.productCount == productCount) &&
(identical(other.orderCount, orderCount) ||
other.orderCount == orderCount));
}
@override
int get hashCode => Object.hash(
runtimeType,
categoryId,
categoryName,
totalRevenue,
totalQuantity,
productCount,
orderCount,
);
/// Create a copy of CategoryAnalyticItem
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$CategoryAnalyticItemImplCopyWith<_$CategoryAnalyticItemImpl>
get copyWith =>
__$$CategoryAnalyticItemImplCopyWithImpl<_$CategoryAnalyticItemImpl>(
this,
_$identity,
);
}
abstract class _CategoryAnalyticItem implements CategoryAnalyticItem {
const factory _CategoryAnalyticItem({
required final String categoryId,
required final String categoryName,
required final int totalRevenue,
required final int totalQuantity,
required final int productCount,
required final int orderCount,
}) = _$CategoryAnalyticItemImpl;
@override
String get categoryId;
@override
String get categoryName;
@override
int get totalRevenue;
@override
int get totalQuantity;
@override
int get productCount;
@override
int get orderCount;
/// Create a copy of CategoryAnalyticItem
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$CategoryAnalyticItemImplCopyWith<_$CategoryAnalyticItemImpl>
get copyWith => throw _privateConstructorUsedError;
}
/// @nodoc
mixin _$AnalyticFailure {
@optionalTypeArgs

View File

@ -0,0 +1,50 @@
part of '../analytic.dart';
@freezed
class CategoryAnalytic with _$CategoryAnalytic {
const CategoryAnalytic._();
const factory CategoryAnalytic({
required String organizationId,
required String outletId,
required DateTime dateFrom,
required DateTime dateTo,
required List<CategoryAnalyticItem> data,
}) = _CategoryAnalytic;
factory CategoryAnalytic.empty() => CategoryAnalytic(
organizationId: '',
outletId: '',
dateFrom: DateTime.now(),
dateTo: DateTime.now(),
data: const [],
);
int get totalRevenue => data.fold(0, (sum, item) => sum + item.totalRevenue);
int get totalQuantity =>
data.fold(0, (sum, item) => sum + item.totalQuantity);
int get totalOrders => data.fold(0, (sum, item) => sum + item.orderCount);
}
@freezed
class CategoryAnalyticItem with _$CategoryAnalyticItem {
const factory CategoryAnalyticItem({
required String categoryId,
required String categoryName,
required int totalRevenue,
required int totalQuantity,
required int productCount,
required int orderCount,
}) = _CategoryAnalyticItem;
factory CategoryAnalyticItem.empty() => const CategoryAnalyticItem(
categoryId: '',
categoryName: '',
totalRevenue: 0,
totalQuantity: 0,
productCount: 0,
orderCount: 0,
);
}

View File

@ -21,4 +21,8 @@ abstract class IAnalyticRepository {
required DateTime dateFrom,
required DateTime dateTo,
});
Future<Either<AnalyticFailure, CategoryAnalytic>> getCategories({
required DateTime dateFrom,
required DateTime dateTo,
});
}

View File

@ -10,3 +10,4 @@ part 'dtos/sales_dto.dart';
part 'dtos/product_analytic_dto.dart';
part 'dtos/payment_method_analytic_dto.dart';
part 'dtos/profit_loss_analytic_dto.dart';
part 'dtos/category_analytic_dto.dart';

View File

@ -6032,3 +6032,588 @@ abstract class _ProfitLossAnalyticProductDto
>
get copyWith => throw _privateConstructorUsedError;
}
CategoryAnalyticDto _$CategoryAnalyticDtoFromJson(Map<String, dynamic> json) {
return _CategoryAnalyticDto.fromJson(json);
}
/// @nodoc
mixin _$CategoryAnalyticDto {
@JsonKey(name: "organization_id")
String? get organizationId => throw _privateConstructorUsedError;
@JsonKey(name: "outlet_id")
String? get outletId => throw _privateConstructorUsedError;
@JsonKey(name: "date_from")
DateTime? get dateFrom => throw _privateConstructorUsedError;
@JsonKey(name: "date_to")
DateTime? get dateTo => throw _privateConstructorUsedError;
List<CategoryAnalyticItemDto>? get data => throw _privateConstructorUsedError;
/// Serializes this CategoryAnalyticDto to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of CategoryAnalyticDto
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$CategoryAnalyticDtoCopyWith<CategoryAnalyticDto> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $CategoryAnalyticDtoCopyWith<$Res> {
factory $CategoryAnalyticDtoCopyWith(
CategoryAnalyticDto value,
$Res Function(CategoryAnalyticDto) then,
) = _$CategoryAnalyticDtoCopyWithImpl<$Res, CategoryAnalyticDto>;
@useResult
$Res call({
@JsonKey(name: "organization_id") String? organizationId,
@JsonKey(name: "outlet_id") String? outletId,
@JsonKey(name: "date_from") DateTime? dateFrom,
@JsonKey(name: "date_to") DateTime? dateTo,
List<CategoryAnalyticItemDto>? data,
});
}
/// @nodoc
class _$CategoryAnalyticDtoCopyWithImpl<$Res, $Val extends CategoryAnalyticDto>
implements $CategoryAnalyticDtoCopyWith<$Res> {
_$CategoryAnalyticDtoCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of CategoryAnalyticDto
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? organizationId = freezed,
Object? outletId = freezed,
Object? dateFrom = freezed,
Object? dateTo = freezed,
Object? data = freezed,
}) {
return _then(
_value.copyWith(
organizationId: freezed == organizationId
? _value.organizationId
: organizationId // ignore: cast_nullable_to_non_nullable
as String?,
outletId: freezed == outletId
? _value.outletId
: outletId // ignore: cast_nullable_to_non_nullable
as String?,
dateFrom: freezed == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as DateTime?,
dateTo: freezed == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as DateTime?,
data: freezed == data
? _value.data
: data // ignore: cast_nullable_to_non_nullable
as List<CategoryAnalyticItemDto>?,
)
as $Val,
);
}
}
/// @nodoc
abstract class _$$CategoryAnalyticDtoImplCopyWith<$Res>
implements $CategoryAnalyticDtoCopyWith<$Res> {
factory _$$CategoryAnalyticDtoImplCopyWith(
_$CategoryAnalyticDtoImpl value,
$Res Function(_$CategoryAnalyticDtoImpl) then,
) = __$$CategoryAnalyticDtoImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({
@JsonKey(name: "organization_id") String? organizationId,
@JsonKey(name: "outlet_id") String? outletId,
@JsonKey(name: "date_from") DateTime? dateFrom,
@JsonKey(name: "date_to") DateTime? dateTo,
List<CategoryAnalyticItemDto>? data,
});
}
/// @nodoc
class __$$CategoryAnalyticDtoImplCopyWithImpl<$Res>
extends _$CategoryAnalyticDtoCopyWithImpl<$Res, _$CategoryAnalyticDtoImpl>
implements _$$CategoryAnalyticDtoImplCopyWith<$Res> {
__$$CategoryAnalyticDtoImplCopyWithImpl(
_$CategoryAnalyticDtoImpl _value,
$Res Function(_$CategoryAnalyticDtoImpl) _then,
) : super(_value, _then);
/// Create a copy of CategoryAnalyticDto
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? organizationId = freezed,
Object? outletId = freezed,
Object? dateFrom = freezed,
Object? dateTo = freezed,
Object? data = freezed,
}) {
return _then(
_$CategoryAnalyticDtoImpl(
organizationId: freezed == organizationId
? _value.organizationId
: organizationId // ignore: cast_nullable_to_non_nullable
as String?,
outletId: freezed == outletId
? _value.outletId
: outletId // ignore: cast_nullable_to_non_nullable
as String?,
dateFrom: freezed == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as DateTime?,
dateTo: freezed == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as DateTime?,
data: freezed == data
? _value._data
: data // ignore: cast_nullable_to_non_nullable
as List<CategoryAnalyticItemDto>?,
),
);
}
}
/// @nodoc
@JsonSerializable()
class _$CategoryAnalyticDtoImpl extends _CategoryAnalyticDto {
const _$CategoryAnalyticDtoImpl({
@JsonKey(name: "organization_id") this.organizationId,
@JsonKey(name: "outlet_id") this.outletId,
@JsonKey(name: "date_from") this.dateFrom,
@JsonKey(name: "date_to") this.dateTo,
final List<CategoryAnalyticItemDto>? data,
}) : _data = data,
super._();
factory _$CategoryAnalyticDtoImpl.fromJson(Map<String, dynamic> json) =>
_$$CategoryAnalyticDtoImplFromJson(json);
@override
@JsonKey(name: "organization_id")
final String? organizationId;
@override
@JsonKey(name: "outlet_id")
final String? outletId;
@override
@JsonKey(name: "date_from")
final DateTime? dateFrom;
@override
@JsonKey(name: "date_to")
final DateTime? dateTo;
final List<CategoryAnalyticItemDto>? _data;
@override
List<CategoryAnalyticItemDto>? get data {
final value = _data;
if (value == null) return null;
if (_data is EqualUnmodifiableListView) return _data;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(value);
}
@override
String toString() {
return 'CategoryAnalyticDto(organizationId: $organizationId, outletId: $outletId, dateFrom: $dateFrom, dateTo: $dateTo, data: $data)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$CategoryAnalyticDtoImpl &&
(identical(other.organizationId, organizationId) ||
other.organizationId == organizationId) &&
(identical(other.outletId, outletId) ||
other.outletId == outletId) &&
(identical(other.dateFrom, dateFrom) ||
other.dateFrom == dateFrom) &&
(identical(other.dateTo, dateTo) || other.dateTo == dateTo) &&
const DeepCollectionEquality().equals(other._data, _data));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(
runtimeType,
organizationId,
outletId,
dateFrom,
dateTo,
const DeepCollectionEquality().hash(_data),
);
/// Create a copy of CategoryAnalyticDto
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$CategoryAnalyticDtoImplCopyWith<_$CategoryAnalyticDtoImpl> get copyWith =>
__$$CategoryAnalyticDtoImplCopyWithImpl<_$CategoryAnalyticDtoImpl>(
this,
_$identity,
);
@override
Map<String, dynamic> toJson() {
return _$$CategoryAnalyticDtoImplToJson(this);
}
}
abstract class _CategoryAnalyticDto extends CategoryAnalyticDto {
const factory _CategoryAnalyticDto({
@JsonKey(name: "organization_id") final String? organizationId,
@JsonKey(name: "outlet_id") final String? outletId,
@JsonKey(name: "date_from") final DateTime? dateFrom,
@JsonKey(name: "date_to") final DateTime? dateTo,
final List<CategoryAnalyticItemDto>? data,
}) = _$CategoryAnalyticDtoImpl;
const _CategoryAnalyticDto._() : super._();
factory _CategoryAnalyticDto.fromJson(Map<String, dynamic> json) =
_$CategoryAnalyticDtoImpl.fromJson;
@override
@JsonKey(name: "organization_id")
String? get organizationId;
@override
@JsonKey(name: "outlet_id")
String? get outletId;
@override
@JsonKey(name: "date_from")
DateTime? get dateFrom;
@override
@JsonKey(name: "date_to")
DateTime? get dateTo;
@override
List<CategoryAnalyticItemDto>? get data;
/// Create a copy of CategoryAnalyticDto
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$CategoryAnalyticDtoImplCopyWith<_$CategoryAnalyticDtoImpl> get copyWith =>
throw _privateConstructorUsedError;
}
CategoryAnalyticItemDto _$CategoryAnalyticItemDtoFromJson(
Map<String, dynamic> json,
) {
return _CategoryAnalyticItemDto.fromJson(json);
}
/// @nodoc
mixin _$CategoryAnalyticItemDto {
@JsonKey(name: "category_id")
String? get categoryId => throw _privateConstructorUsedError;
@JsonKey(name: "category_name")
String? get categoryName => throw _privateConstructorUsedError;
@JsonKey(name: "total_revenue")
int? get totalRevenue => throw _privateConstructorUsedError;
@JsonKey(name: "total_quantity")
int? get totalQuantity => throw _privateConstructorUsedError;
@JsonKey(name: "product_count")
int? get productCount => throw _privateConstructorUsedError;
@JsonKey(name: "order_count")
int? get orderCount => throw _privateConstructorUsedError;
/// Serializes this CategoryAnalyticItemDto to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of CategoryAnalyticItemDto
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$CategoryAnalyticItemDtoCopyWith<CategoryAnalyticItemDto> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $CategoryAnalyticItemDtoCopyWith<$Res> {
factory $CategoryAnalyticItemDtoCopyWith(
CategoryAnalyticItemDto value,
$Res Function(CategoryAnalyticItemDto) then,
) = _$CategoryAnalyticItemDtoCopyWithImpl<$Res, CategoryAnalyticItemDto>;
@useResult
$Res call({
@JsonKey(name: "category_id") String? categoryId,
@JsonKey(name: "category_name") String? categoryName,
@JsonKey(name: "total_revenue") int? totalRevenue,
@JsonKey(name: "total_quantity") int? totalQuantity,
@JsonKey(name: "product_count") int? productCount,
@JsonKey(name: "order_count") int? orderCount,
});
}
/// @nodoc
class _$CategoryAnalyticItemDtoCopyWithImpl<
$Res,
$Val extends CategoryAnalyticItemDto
>
implements $CategoryAnalyticItemDtoCopyWith<$Res> {
_$CategoryAnalyticItemDtoCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of CategoryAnalyticItemDto
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? categoryId = freezed,
Object? categoryName = freezed,
Object? totalRevenue = freezed,
Object? totalQuantity = freezed,
Object? productCount = freezed,
Object? orderCount = freezed,
}) {
return _then(
_value.copyWith(
categoryId: freezed == categoryId
? _value.categoryId
: categoryId // ignore: cast_nullable_to_non_nullable
as String?,
categoryName: freezed == categoryName
? _value.categoryName
: categoryName // ignore: cast_nullable_to_non_nullable
as String?,
totalRevenue: freezed == totalRevenue
? _value.totalRevenue
: totalRevenue // ignore: cast_nullable_to_non_nullable
as int?,
totalQuantity: freezed == totalQuantity
? _value.totalQuantity
: totalQuantity // ignore: cast_nullable_to_non_nullable
as int?,
productCount: freezed == productCount
? _value.productCount
: productCount // ignore: cast_nullable_to_non_nullable
as int?,
orderCount: freezed == orderCount
? _value.orderCount
: orderCount // ignore: cast_nullable_to_non_nullable
as int?,
)
as $Val,
);
}
}
/// @nodoc
abstract class _$$CategoryAnalyticItemDtoImplCopyWith<$Res>
implements $CategoryAnalyticItemDtoCopyWith<$Res> {
factory _$$CategoryAnalyticItemDtoImplCopyWith(
_$CategoryAnalyticItemDtoImpl value,
$Res Function(_$CategoryAnalyticItemDtoImpl) then,
) = __$$CategoryAnalyticItemDtoImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({
@JsonKey(name: "category_id") String? categoryId,
@JsonKey(name: "category_name") String? categoryName,
@JsonKey(name: "total_revenue") int? totalRevenue,
@JsonKey(name: "total_quantity") int? totalQuantity,
@JsonKey(name: "product_count") int? productCount,
@JsonKey(name: "order_count") int? orderCount,
});
}
/// @nodoc
class __$$CategoryAnalyticItemDtoImplCopyWithImpl<$Res>
extends
_$CategoryAnalyticItemDtoCopyWithImpl<
$Res,
_$CategoryAnalyticItemDtoImpl
>
implements _$$CategoryAnalyticItemDtoImplCopyWith<$Res> {
__$$CategoryAnalyticItemDtoImplCopyWithImpl(
_$CategoryAnalyticItemDtoImpl _value,
$Res Function(_$CategoryAnalyticItemDtoImpl) _then,
) : super(_value, _then);
/// Create a copy of CategoryAnalyticItemDto
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? categoryId = freezed,
Object? categoryName = freezed,
Object? totalRevenue = freezed,
Object? totalQuantity = freezed,
Object? productCount = freezed,
Object? orderCount = freezed,
}) {
return _then(
_$CategoryAnalyticItemDtoImpl(
categoryId: freezed == categoryId
? _value.categoryId
: categoryId // ignore: cast_nullable_to_non_nullable
as String?,
categoryName: freezed == categoryName
? _value.categoryName
: categoryName // ignore: cast_nullable_to_non_nullable
as String?,
totalRevenue: freezed == totalRevenue
? _value.totalRevenue
: totalRevenue // ignore: cast_nullable_to_non_nullable
as int?,
totalQuantity: freezed == totalQuantity
? _value.totalQuantity
: totalQuantity // ignore: cast_nullable_to_non_nullable
as int?,
productCount: freezed == productCount
? _value.productCount
: productCount // ignore: cast_nullable_to_non_nullable
as int?,
orderCount: freezed == orderCount
? _value.orderCount
: orderCount // ignore: cast_nullable_to_non_nullable
as int?,
),
);
}
}
/// @nodoc
@JsonSerializable()
class _$CategoryAnalyticItemDtoImpl extends _CategoryAnalyticItemDto {
const _$CategoryAnalyticItemDtoImpl({
@JsonKey(name: "category_id") this.categoryId,
@JsonKey(name: "category_name") this.categoryName,
@JsonKey(name: "total_revenue") this.totalRevenue,
@JsonKey(name: "total_quantity") this.totalQuantity,
@JsonKey(name: "product_count") this.productCount,
@JsonKey(name: "order_count") this.orderCount,
}) : super._();
factory _$CategoryAnalyticItemDtoImpl.fromJson(Map<String, dynamic> json) =>
_$$CategoryAnalyticItemDtoImplFromJson(json);
@override
@JsonKey(name: "category_id")
final String? categoryId;
@override
@JsonKey(name: "category_name")
final String? categoryName;
@override
@JsonKey(name: "total_revenue")
final int? totalRevenue;
@override
@JsonKey(name: "total_quantity")
final int? totalQuantity;
@override
@JsonKey(name: "product_count")
final int? productCount;
@override
@JsonKey(name: "order_count")
final int? orderCount;
@override
String toString() {
return 'CategoryAnalyticItemDto(categoryId: $categoryId, categoryName: $categoryName, totalRevenue: $totalRevenue, totalQuantity: $totalQuantity, productCount: $productCount, orderCount: $orderCount)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$CategoryAnalyticItemDtoImpl &&
(identical(other.categoryId, categoryId) ||
other.categoryId == categoryId) &&
(identical(other.categoryName, categoryName) ||
other.categoryName == categoryName) &&
(identical(other.totalRevenue, totalRevenue) ||
other.totalRevenue == totalRevenue) &&
(identical(other.totalQuantity, totalQuantity) ||
other.totalQuantity == totalQuantity) &&
(identical(other.productCount, productCount) ||
other.productCount == productCount) &&
(identical(other.orderCount, orderCount) ||
other.orderCount == orderCount));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(
runtimeType,
categoryId,
categoryName,
totalRevenue,
totalQuantity,
productCount,
orderCount,
);
/// Create a copy of CategoryAnalyticItemDto
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$CategoryAnalyticItemDtoImplCopyWith<_$CategoryAnalyticItemDtoImpl>
get copyWith =>
__$$CategoryAnalyticItemDtoImplCopyWithImpl<
_$CategoryAnalyticItemDtoImpl
>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$CategoryAnalyticItemDtoImplToJson(this);
}
}
abstract class _CategoryAnalyticItemDto extends CategoryAnalyticItemDto {
const factory _CategoryAnalyticItemDto({
@JsonKey(name: "category_id") final String? categoryId,
@JsonKey(name: "category_name") final String? categoryName,
@JsonKey(name: "total_revenue") final int? totalRevenue,
@JsonKey(name: "total_quantity") final int? totalQuantity,
@JsonKey(name: "product_count") final int? productCount,
@JsonKey(name: "order_count") final int? orderCount,
}) = _$CategoryAnalyticItemDtoImpl;
const _CategoryAnalyticItemDto._() : super._();
factory _CategoryAnalyticItemDto.fromJson(Map<String, dynamic> json) =
_$CategoryAnalyticItemDtoImpl.fromJson;
@override
@JsonKey(name: "category_id")
String? get categoryId;
@override
@JsonKey(name: "category_name")
String? get categoryName;
@override
@JsonKey(name: "total_revenue")
int? get totalRevenue;
@override
@JsonKey(name: "total_quantity")
int? get totalQuantity;
@override
@JsonKey(name: "product_count")
int? get productCount;
@override
@JsonKey(name: "order_count")
int? get orderCount;
/// Create a copy of CategoryAnalyticItemDto
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$CategoryAnalyticItemDtoImplCopyWith<_$CategoryAnalyticItemDtoImpl>
get copyWith => throw _privateConstructorUsedError;
}

View File

@ -479,3 +479,51 @@ Map<String, dynamic> _$$ProfitLossAnalyticProductDtoImplToJson(
'average_cost': instance.averageCost,
'profit_per_unit': instance.profitPerUnit,
};
_$CategoryAnalyticDtoImpl _$$CategoryAnalyticDtoImplFromJson(
Map<String, dynamic> json,
) => _$CategoryAnalyticDtoImpl(
organizationId: json['organization_id'] as String?,
outletId: json['outlet_id'] 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) => CategoryAnalyticItemDto.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$$CategoryAnalyticDtoImplToJson(
_$CategoryAnalyticDtoImpl instance,
) => <String, dynamic>{
'organization_id': instance.organizationId,
'outlet_id': instance.outletId,
'date_from': instance.dateFrom?.toIso8601String(),
'date_to': instance.dateTo?.toIso8601String(),
'data': instance.data,
};
_$CategoryAnalyticItemDtoImpl _$$CategoryAnalyticItemDtoImplFromJson(
Map<String, dynamic> json,
) => _$CategoryAnalyticItemDtoImpl(
categoryId: json['category_id'] as String?,
categoryName: json['category_name'] as String?,
totalRevenue: (json['total_revenue'] as num?)?.toInt(),
totalQuantity: (json['total_quantity'] as num?)?.toInt(),
productCount: (json['product_count'] as num?)?.toInt(),
orderCount: (json['order_count'] as num?)?.toInt(),
);
Map<String, dynamic> _$$CategoryAnalyticItemDtoImplToJson(
_$CategoryAnalyticItemDtoImpl 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,
};

View File

@ -163,4 +163,33 @@ class AnalyticRemoteDataProvider {
return DC.error(AnalyticFailure.serverError(e));
}
}
Future<DC<AnalyticFailure, CategoryAnalyticDto>> fetchCategories({
required DateTime dateFrom,
required DateTime dateTo,
}) async {
try {
final response = await _apiClient.get(
ApiPath.analyticCategories,
params: {
'date_from': dateFrom.toServerDate(),
'date_to': dateTo.toServerDate(),
},
headers: getAuthorizationHeader(),
);
if (response.data['success'] == false) {
return DC.error(AnalyticFailure.unexpectedError());
}
final categories = CategoryAnalyticDto.fromJson(
response.data['data'] as Map<String, dynamic>,
);
return DC.data(categories);
} on ApiFailure catch (e, s) {
log('fetchCategories', name: _logName, error: e, stackTrace: s);
return DC.error(AnalyticFailure.serverError(e));
}
}
}

View File

@ -0,0 +1,53 @@
part of '../analytic_dtos.dart';
@freezed
class CategoryAnalyticDto with _$CategoryAnalyticDto {
const CategoryAnalyticDto._();
const factory CategoryAnalyticDto({
@JsonKey(name: "organization_id") String? organizationId,
@JsonKey(name: "outlet_id") String? outletId,
@JsonKey(name: "date_from") DateTime? dateFrom,
@JsonKey(name: "date_to") DateTime? dateTo,
List<CategoryAnalyticItemDto>? data,
}) = _CategoryAnalyticDto;
factory CategoryAnalyticDto.fromJson(Map<String, dynamic> json) =>
_$CategoryAnalyticDtoFromJson(json);
// Optional mapper ke entity
CategoryAnalytic toDomain() => CategoryAnalytic(
organizationId: organizationId ?? '',
outletId: outletId ?? '',
dateFrom: dateFrom ?? DateTime.now(),
dateTo: dateTo ?? DateTime.now(),
data: data?.map((e) => e.toDomain()).toList() ?? [],
);
}
@freezed
class CategoryAnalyticItemDto with _$CategoryAnalyticItemDto {
const CategoryAnalyticItemDto._();
const factory CategoryAnalyticItemDto({
@JsonKey(name: "category_id") String? categoryId,
@JsonKey(name: "category_name") String? categoryName,
@JsonKey(name: "total_revenue") int? totalRevenue,
@JsonKey(name: "total_quantity") int? totalQuantity,
@JsonKey(name: "product_count") int? productCount,
@JsonKey(name: "order_count") int? orderCount,
}) = _CategoryAnalyticItemDto;
factory CategoryAnalyticItemDto.fromJson(Map<String, dynamic> json) =>
_$CategoryAnalyticItemDtoFromJson(json);
// Optional mapper ke entity
CategoryAnalyticItem toDomain() => CategoryAnalyticItem(
categoryId: categoryId ?? '',
categoryName: categoryName ?? '',
totalRevenue: totalRevenue ?? 0,
totalQuantity: totalQuantity ?? 0,
productCount: productCount ?? 0,
orderCount: orderCount ?? 0,
);
}

View File

@ -133,4 +133,28 @@ class AnalyticRepository implements IAnalyticRepository {
return left(const AnalyticFailure.unexpectedError());
}
}
@override
Future<Either<AnalyticFailure, CategoryAnalytic>> getCategories({
required DateTime dateFrom,
required DateTime dateTo,
}) async {
try {
final result = await _dataProvider.fetchCategories(
dateFrom: dateFrom,
dateTo: dateTo,
);
if (result.hasError) {
return left(result.error!);
}
final categories = result.data!.toDomain();
return right(categories);
} catch (e) {
log('getCategoriesError', name: _logName, error: e);
return left(const AnalyticFailure.unexpectedError());
}
}
}

View File

@ -9,6 +9,8 @@
// coverage:ignore-file
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:apskel_pos_flutter_v2/application/analytic/category_analytic_loader/category_analytic_loader_bloc.dart'
as _i911;
import 'package:apskel_pos_flutter_v2/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_bloc.dart'
as _i80;
import 'package:apskel_pos_flutter_v2/application/analytic/payment_method_analytic_loader/payment_method_analytic_loader_bloc.dart'
@ -315,6 +317,9 @@ extension GetItInjectableX on _i174.GetIt {
gh.factory<_i741.ProfitLossAnalyticLoaderBloc>(
() => _i741.ProfitLossAnalyticLoaderBloc(gh<_i346.IAnalyticRepository>()),
);
gh.factory<_i911.CategoryAnalyticLoaderBloc>(
() => _i911.CategoryAnalyticLoaderBloc(gh<_i346.IAnalyticRepository>()),
);
return this;
}
}

View File

@ -2,6 +2,7 @@ import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../../application/analytic/category_analytic_loader/category_analytic_loader_bloc.dart';
import '../../../../../application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_bloc.dart';
import '../../../../../application/analytic/payment_method_analytic_loader/payment_method_analytic_loader_bloc.dart';
import '../../../../../application/analytic/product_analytic_loader/product_analytic_loader_bloc.dart';
@ -16,6 +17,7 @@ import '../../../../components/page/page_title.dart';
import '../../../../components/picker/date_range_picker.dart';
import '../../../../components/spaces/space.dart';
import '../../../../router/app_router.gr.dart';
import 'sections/report_category_section.dart';
import 'sections/report_dashboard_section.dart';
import 'sections/report_payment_method_section.dart';
import 'sections/report_product_section.dart';
@ -184,7 +186,20 @@ class ReportPage extends StatelessWidget implements AutoRouteWrapper {
},
),
6 => Text(state.title),
7 => Text(state.title),
7 =>
BlocBuilder<
CategoryAnalyticLoaderBloc,
CategoryAnalyticLoaderState
>(
builder: (context, category) {
return ReportCategorySection(
menu: reportMenus[state.selectedMenu],
state: category,
startDate: state.startDate,
endDate: state.endDate,
);
},
),
_ => Container(),
},
),
@ -241,6 +256,12 @@ class ReportPage extends StatelessWidget implements AutoRouteWrapper {
);
case 6:
case 7:
return context.read<CategoryAnalyticLoaderBloc>().add(
CategoryAnalyticLoaderEvent.fetched(
startDate: state.startDate,
endDate: state.endDate,
),
);
default:
return;
}
@ -295,6 +316,16 @@ class ReportPage extends StatelessWidget implements AutoRouteWrapper {
),
),
),
BlocProvider(
create: (context) => getIt<CategoryAnalyticLoaderBloc>()
..add(
CategoryAnalyticLoaderEvent.fetched(
startDate: DateTime.now().subtract(const Duration(days: 30)),
endDate: DateTime.now(),
),
),
),
],
child: this,
);

View File

@ -0,0 +1,269 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../../../application/analytic/category_analytic_loader/category_analytic_loader_bloc.dart';
import '../../../../../../common/data/report_menu.dart';
import '../../../../../../common/extension/extension.dart';
import '../../../../../../common/theme/theme.dart';
import '../../../../../../domain/analytic/analytic.dart';
import '../../../../../components/error/analytic_error_state_widget.dart';
import '../../../../../components/loader/loader_with_text.dart';
import '../../../../../components/spaces/space.dart';
import '../../../../../components/widgets/report/report_header.dart';
import '../../../../../components/widgets/report/report_summary_card.dart';
class ReportCategorySection extends StatelessWidget {
final ReportMenu menu;
final CategoryAnalyticLoaderState state;
final DateTime startDate;
final DateTime endDate;
const ReportCategorySection({
super.key,
required this.menu,
required this.state,
required this.startDate,
required this.endDate,
});
@override
Widget build(BuildContext context) {
if (state.isFetching) {
return const Center(child: LoaderWithText());
}
return state.failureOption.fold(
() =>
BlocBuilder<CategoryAnalyticLoaderBloc, CategoryAnalyticLoaderState>(
builder: (context, state) {
return ListView(
padding: const EdgeInsets.all(16),
children: [
ReportHeader(
menu: menu,
endDate: endDate,
startDate: startDate,
),
_buildSummary(state),
Container(
margin: EdgeInsets.only(top: 16),
decoration: BoxDecoration(
color: AppColor.white,
borderRadius: BorderRadius.circular(14),
),
child: Column(
children: [
Container(
decoration: BoxDecoration(
color: AppColor.disabled.withOpacity(0.8),
borderRadius: BorderRadius.vertical(
top: Radius.circular(14),
),
),
padding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 16,
),
child: Row(
children: [
Expanded(
flex: 3,
child: Text(
'Kategori',
style: AppStyle.lg.copyWith(
fontWeight: FontWeight.w600,
color: AppColor.textPrimary,
),
),
),
Expanded(
flex: 2,
child: Text(
'Pendapatan',
textAlign: TextAlign.center,
style: AppStyle.lg.copyWith(
fontWeight: FontWeight.w600,
color: AppColor.textPrimary,
),
),
),
Expanded(
flex: 1,
child: Text(
'Qty',
textAlign: TextAlign.center,
style: AppStyle.lg.copyWith(
fontWeight: FontWeight.w600,
color: AppColor.textPrimary,
),
),
),
Expanded(
flex: 1,
child: Text(
'Order',
textAlign: TextAlign.center,
style: AppStyle.lg.copyWith(
fontWeight: FontWeight.w600,
color: AppColor.textPrimary,
),
),
),
],
),
),
Container(
decoration: BoxDecoration(
color: AppColor.white,
borderRadius: BorderRadius.vertical(
bottom: Radius.circular(14),
),
),
child: ListView.builder(
padding: EdgeInsets.zero,
itemCount: state.categoryAnalytic.data.length,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return _buildCategoryItem(
state.categoryAnalytic.data[index],
index,
state.categoryAnalytic.data.length,
);
},
),
),
],
),
),
],
);
},
),
(f) => AnalyticErrorStateWidget(
failure: f,
menu: menu,
onRefresh: () {
context.read<CategoryAnalyticLoaderBloc>().add(
CategoryAnalyticLoaderEvent.fetched(
startDate: startDate,
endDate: endDate,
),
);
},
),
);
}
Widget _buildCategoryItem(
CategoryAnalyticItem category,
int index,
int totalCount,
) {
final isEven = index % 2 == 0;
final isLast = index == totalCount - 1;
return Container(
decoration: BoxDecoration(
color: isEven ? AppColor.white : AppColor.disabled.withOpacity(0.3),
borderRadius: BorderRadius.vertical(
bottom: Radius.circular(isLast ? 14 : 0),
),
),
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
child: Row(
children: [
Expanded(
flex: 3,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
category.categoryName,
style: AppStyle.lg.copyWith(
fontWeight: FontWeight.w500,
color: AppColor.textPrimary,
),
),
const SizedBox(height: 4),
Text(
'${category.productCount} produk',
style: AppStyle.sm.copyWith(color: AppColor.textSecondary),
),
],
),
),
Expanded(
flex: 2,
child: Column(
children: [
Text(
category.totalRevenue.currencyFormatRpV2,
textAlign: TextAlign.center,
style: AppStyle.md.copyWith(
fontWeight: FontWeight.w500,
color: AppColor.success,
),
),
],
),
),
Expanded(
flex: 1,
child: Text(
'${category.totalQuantity}',
textAlign: TextAlign.center,
style: AppStyle.md.copyWith(
fontWeight: FontWeight.w500,
color: AppColor.textPrimary,
),
),
),
Expanded(
flex: 1,
child: Text(
'${category.orderCount}',
textAlign: TextAlign.center,
style: AppStyle.md.copyWith(
fontWeight: FontWeight.w500,
color: AppColor.textPrimary,
),
),
),
],
),
);
}
Row _buildSummary(CategoryAnalyticLoaderState state) {
return Row(
children: [
Expanded(
child: ReportSummaryCard(
color: AppColor.success,
icon: Icons.trending_up,
title: 'Total Pendapatan',
value: state.categoryAnalytic.totalRevenue.currencyFormatRpV2,
),
),
SpaceWidth(12),
Expanded(
child: ReportSummaryCard(
color: AppColor.info,
icon: Icons.shopping_cart_outlined,
title: 'Total Item Terjual',
value: "${state.categoryAnalytic.totalQuantity} pcs",
),
),
SpaceWidth(12),
Expanded(
child: ReportSummaryCard(
color: AppColor.primary,
icon: Icons.receipt_outlined,
title: 'Total Pesanan',
value: state.categoryAnalytic.totalOrders.toString(),
),
),
],
);
}
}