From 50b06da62732292bb7910d42cdb7f2074a1e04b6 Mon Sep 17 00:00:00 2001 From: efrilm Date: Sun, 17 Aug 2025 22:36:46 +0700 Subject: [PATCH] feat: profit loss --- .../profit_loss_loader_bloc.dart | 44 + .../profit_loss_loader_bloc.freezed.dart | 384 ++++ .../profit_loss_loader_event.dart | 6 + .../profit_loss_loader_state.dart | 15 + lib/common/url/api_path.dart | 1 + lib/domain/analytic/analytic.dart | 1 + lib/domain/analytic/analytic.freezed.dart | 1420 ++++++++++++++ .../entities/profit_loss_analytic_entity.dart | 117 ++ .../repositories/i_analytic_repository.dart | 4 + .../analytic/analytic_dtos.dart | 1 + .../analytic/analytic_dtos.freezed.dart | 1653 +++++++++++++++++ .../analytic/analytic_dtos.g.dart | 126 ++ .../datasource/remote_data_provider.dart | 27 + .../dto/profit_loss_analytic_dto.dart | 137 ++ .../repositories/analytic_repository.dart | 24 + lib/injection.config.dart | 17 +- .../pages/finance/finance_page.dart | 287 +-- .../pages/finance/widgets/cash_flow.dart | 490 +++-- .../pages/finance/widgets/product.dart | 148 ++ .../pages/finance/widgets/profit_loss.dart | 52 +- .../pages/finance/widgets/summary_card.dart | 18 - 21 files changed, 4548 insertions(+), 424 deletions(-) create mode 100644 lib/application/profit_loss/profit_loss_loader/profit_loss_loader_bloc.dart create mode 100644 lib/application/profit_loss/profit_loss_loader/profit_loss_loader_bloc.freezed.dart create mode 100644 lib/application/profit_loss/profit_loss_loader/profit_loss_loader_event.dart create mode 100644 lib/application/profit_loss/profit_loss_loader/profit_loss_loader_state.dart create mode 100644 lib/domain/analytic/entities/profit_loss_analytic_entity.dart create mode 100644 lib/infrastructure/analytic/dto/profit_loss_analytic_dto.dart create mode 100644 lib/presentation/pages/finance/widgets/product.dart diff --git a/lib/application/profit_loss/profit_loss_loader/profit_loss_loader_bloc.dart b/lib/application/profit_loss/profit_loss_loader/profit_loss_loader_bloc.dart new file mode 100644 index 0000000..85758ce --- /dev/null +++ b/lib/application/profit_loss/profit_loss_loader/profit_loss_loader_bloc.dart @@ -0,0 +1,44 @@ +import 'package:dartz/dartz.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../domain/analytic/analytic.dart'; +import '../../../domain/analytic/repositories/i_analytic_repository.dart'; + +part 'profit_loss_loader_event.dart'; +part 'profit_loss_loader_state.dart'; +part 'profit_loss_loader_bloc.freezed.dart'; + +@injectable +class ProfitLossLoaderBloc + extends Bloc { + final IAnalyticRepository _repository; + ProfitLossLoaderBloc(this._repository) + : super(ProfitLossLoaderState.initial()) { + on(_onProfitLossLoaderEvent); + } + + Future _onProfitLossLoaderEvent( + ProfitLossLoaderEvent event, + Emitter emit, + ) { + return event.map( + fetched: (e) async { + emit(state.copyWith(isFetching: true, failureOptionProfitLoss: none())); + + final result = await _repository.getProfitLoss( + dateFrom: DateTime.now().subtract(const Duration(days: 30)), + dateTo: DateTime.now(), + ); + + var data = result.fold( + (f) => state.copyWith(failureOptionProfitLoss: optionOf(f)), + (profitLoss) => state.copyWith(profitLoss: profitLoss), + ); + + emit(data.copyWith(isFetching: false)); + }, + ); + } +} diff --git a/lib/application/profit_loss/profit_loss_loader/profit_loss_loader_bloc.freezed.dart b/lib/application/profit_loss/profit_loss_loader/profit_loss_loader_bloc.freezed.dart new file mode 100644 index 0000000..2fb5db5 --- /dev/null +++ b/lib/application/profit_loss/profit_loss_loader/profit_loss_loader_bloc.freezed.dart @@ -0,0 +1,384 @@ +// 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 'profit_loss_loader_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$ProfitLossLoaderEvent { + @optionalTypeArgs + TResult when({ + required TResult Function() fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_Fetched value) fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Fetched value)? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossLoaderEventCopyWith<$Res> { + factory $ProfitLossLoaderEventCopyWith( + ProfitLossLoaderEvent value, + $Res Function(ProfitLossLoaderEvent) then, + ) = _$ProfitLossLoaderEventCopyWithImpl<$Res, ProfitLossLoaderEvent>; +} + +/// @nodoc +class _$ProfitLossLoaderEventCopyWithImpl< + $Res, + $Val extends ProfitLossLoaderEvent +> + implements $ProfitLossLoaderEventCopyWith<$Res> { + _$ProfitLossLoaderEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossLoaderEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$FetchedImplCopyWith<$Res> { + factory _$$FetchedImplCopyWith( + _$FetchedImpl value, + $Res Function(_$FetchedImpl) then, + ) = __$$FetchedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$FetchedImplCopyWithImpl<$Res> + extends _$ProfitLossLoaderEventCopyWithImpl<$Res, _$FetchedImpl> + implements _$$FetchedImplCopyWith<$Res> { + __$$FetchedImplCopyWithImpl( + _$FetchedImpl _value, + $Res Function(_$FetchedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossLoaderEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$FetchedImpl implements _Fetched { + const _$FetchedImpl(); + + @override + String toString() { + return 'ProfitLossLoaderEvent.fetched()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$FetchedImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({required TResult Function() fetched}) { + return fetched(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({TResult? Function()? fetched}) { + return fetched?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_Fetched value) fetched, + }) { + return fetched(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Fetched value)? fetched, + }) { + return fetched?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(this); + } + return orElse(); + } +} + +abstract class _Fetched implements ProfitLossLoaderEvent { + const factory _Fetched() = _$FetchedImpl; +} + +/// @nodoc +mixin _$ProfitLossLoaderState { + ProfitLossAnalytic get profitLoss => throw _privateConstructorUsedError; + Option get failureOptionProfitLoss => + throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + + /// Create a copy of ProfitLossLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProfitLossLoaderStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossLoaderStateCopyWith<$Res> { + factory $ProfitLossLoaderStateCopyWith( + ProfitLossLoaderState value, + $Res Function(ProfitLossLoaderState) then, + ) = _$ProfitLossLoaderStateCopyWithImpl<$Res, ProfitLossLoaderState>; + @useResult + $Res call({ + ProfitLossAnalytic profitLoss, + Option failureOptionProfitLoss, + bool isFetching, + }); + + $ProfitLossAnalyticCopyWith<$Res> get profitLoss; +} + +/// @nodoc +class _$ProfitLossLoaderStateCopyWithImpl< + $Res, + $Val extends ProfitLossLoaderState +> + implements $ProfitLossLoaderStateCopyWith<$Res> { + _$ProfitLossLoaderStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? profitLoss = null, + Object? failureOptionProfitLoss = null, + Object? isFetching = null, + }) { + return _then( + _value.copyWith( + profitLoss: null == profitLoss + ? _value.profitLoss + : profitLoss // ignore: cast_nullable_to_non_nullable + as ProfitLossAnalytic, + failureOptionProfitLoss: null == failureOptionProfitLoss + ? _value.failureOptionProfitLoss + : failureOptionProfitLoss // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + ) + as $Val, + ); + } + + /// Create a copy of ProfitLossLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ProfitLossAnalyticCopyWith<$Res> get profitLoss { + return $ProfitLossAnalyticCopyWith<$Res>(_value.profitLoss, (value) { + return _then(_value.copyWith(profitLoss: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$ProfitLossLoaderStateImplCopyWith<$Res> + implements $ProfitLossLoaderStateCopyWith<$Res> { + factory _$$ProfitLossLoaderStateImplCopyWith( + _$ProfitLossLoaderStateImpl value, + $Res Function(_$ProfitLossLoaderStateImpl) then, + ) = __$$ProfitLossLoaderStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + ProfitLossAnalytic profitLoss, + Option failureOptionProfitLoss, + bool isFetching, + }); + + @override + $ProfitLossAnalyticCopyWith<$Res> get profitLoss; +} + +/// @nodoc +class __$$ProfitLossLoaderStateImplCopyWithImpl<$Res> + extends + _$ProfitLossLoaderStateCopyWithImpl<$Res, _$ProfitLossLoaderStateImpl> + implements _$$ProfitLossLoaderStateImplCopyWith<$Res> { + __$$ProfitLossLoaderStateImplCopyWithImpl( + _$ProfitLossLoaderStateImpl _value, + $Res Function(_$ProfitLossLoaderStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? profitLoss = null, + Object? failureOptionProfitLoss = null, + Object? isFetching = null, + }) { + return _then( + _$ProfitLossLoaderStateImpl( + profitLoss: null == profitLoss + ? _value.profitLoss + : profitLoss // ignore: cast_nullable_to_non_nullable + as ProfitLossAnalytic, + failureOptionProfitLoss: null == failureOptionProfitLoss + ? _value.failureOptionProfitLoss + : failureOptionProfitLoss // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$ProfitLossLoaderStateImpl implements _ProfitLossLoaderState { + const _$ProfitLossLoaderStateImpl({ + required this.profitLoss, + required this.failureOptionProfitLoss, + this.isFetching = false, + }); + + @override + final ProfitLossAnalytic profitLoss; + @override + final Option failureOptionProfitLoss; + @override + @JsonKey() + final bool isFetching; + + @override + String toString() { + return 'ProfitLossLoaderState(profitLoss: $profitLoss, failureOptionProfitLoss: $failureOptionProfitLoss, isFetching: $isFetching)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProfitLossLoaderStateImpl && + (identical(other.profitLoss, profitLoss) || + other.profitLoss == profitLoss) && + (identical( + other.failureOptionProfitLoss, + failureOptionProfitLoss, + ) || + other.failureOptionProfitLoss == failureOptionProfitLoss) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching)); + } + + @override + int get hashCode => + Object.hash(runtimeType, profitLoss, failureOptionProfitLoss, isFetching); + + /// Create a copy of ProfitLossLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProfitLossLoaderStateImplCopyWith<_$ProfitLossLoaderStateImpl> + get copyWith => + __$$ProfitLossLoaderStateImplCopyWithImpl<_$ProfitLossLoaderStateImpl>( + this, + _$identity, + ); +} + +abstract class _ProfitLossLoaderState implements ProfitLossLoaderState { + const factory _ProfitLossLoaderState({ + required final ProfitLossAnalytic profitLoss, + required final Option failureOptionProfitLoss, + final bool isFetching, + }) = _$ProfitLossLoaderStateImpl; + + @override + ProfitLossAnalytic get profitLoss; + @override + Option get failureOptionProfitLoss; + @override + bool get isFetching; + + /// Create a copy of ProfitLossLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProfitLossLoaderStateImplCopyWith<_$ProfitLossLoaderStateImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/application/profit_loss/profit_loss_loader/profit_loss_loader_event.dart b/lib/application/profit_loss/profit_loss_loader/profit_loss_loader_event.dart new file mode 100644 index 0000000..2a69fcc --- /dev/null +++ b/lib/application/profit_loss/profit_loss_loader/profit_loss_loader_event.dart @@ -0,0 +1,6 @@ +part of 'profit_loss_loader_bloc.dart'; + +@freezed +class ProfitLossLoaderEvent with _$ProfitLossLoaderEvent { + const factory ProfitLossLoaderEvent.fetched() = _Fetched; +} diff --git a/lib/application/profit_loss/profit_loss_loader/profit_loss_loader_state.dart b/lib/application/profit_loss/profit_loss_loader/profit_loss_loader_state.dart new file mode 100644 index 0000000..783bfe4 --- /dev/null +++ b/lib/application/profit_loss/profit_loss_loader/profit_loss_loader_state.dart @@ -0,0 +1,15 @@ +part of 'profit_loss_loader_bloc.dart'; + +@freezed +class ProfitLossLoaderState with _$ProfitLossLoaderState { + const factory ProfitLossLoaderState({ + required ProfitLossAnalytic profitLoss, + required Option failureOptionProfitLoss, + @Default(false) bool isFetching, + }) = _ProfitLossLoaderState; + + factory ProfitLossLoaderState.initial() => ProfitLossLoaderState( + profitLoss: ProfitLossAnalytic.empty(), + failureOptionProfitLoss: none(), + ); +} diff --git a/lib/common/url/api_path.dart b/lib/common/url/api_path.dart index d71dcfd..9d510ac 100644 --- a/lib/common/url/api_path.dart +++ b/lib/common/url/api_path.dart @@ -5,6 +5,7 @@ class ApiPath { // Analytic static const String salesAnalytic = '/api/v1/analytics/sales'; + static const String profitLossAnalytic = '/api/v1/analytics/profit-loss'; // Category static const String category = '/api/v1/categories'; diff --git a/lib/domain/analytic/analytic.dart b/lib/domain/analytic/analytic.dart index 8190576..0a045d0 100644 --- a/lib/domain/analytic/analytic.dart +++ b/lib/domain/analytic/analytic.dart @@ -6,3 +6,4 @@ part 'analytic.freezed.dart'; part 'entities/sales_analytic_entity.dart'; part 'failures/analytic_failure.dart'; +part 'entities/profit_loss_analytic_entity.dart'; diff --git a/lib/domain/analytic/analytic.freezed.dart b/lib/domain/analytic/analytic.freezed.dart index c2a75be..14c924b 100644 --- a/lib/domain/analytic/analytic.freezed.dart +++ b/lib/domain/analytic/analytic.freezed.dart @@ -1508,3 +1508,1423 @@ abstract class _DynamicErrorMessage implements AnalyticFailure { _$$DynamicErrorMessageImplCopyWith<_$DynamicErrorMessageImpl> get copyWith => throw _privateConstructorUsedError; } + +/// @nodoc +mixin _$ProfitLossAnalytic { + String get organizationId => throw _privateConstructorUsedError; + String get dateFrom => throw _privateConstructorUsedError; + String get dateTo => throw _privateConstructorUsedError; + String get groupBy => throw _privateConstructorUsedError; + ProfitLossSummary get summary => throw _privateConstructorUsedError; + List get data => throw _privateConstructorUsedError; + List get productData => + throw _privateConstructorUsedError; + + /// Create a copy of ProfitLossAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProfitLossAnalyticCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossAnalyticCopyWith<$Res> { + factory $ProfitLossAnalyticCopyWith( + ProfitLossAnalytic value, + $Res Function(ProfitLossAnalytic) then, + ) = _$ProfitLossAnalyticCopyWithImpl<$Res, ProfitLossAnalytic>; + @useResult + $Res call({ + String organizationId, + String dateFrom, + String dateTo, + String groupBy, + ProfitLossSummary summary, + List data, + List productData, + }); + + $ProfitLossSummaryCopyWith<$Res> get summary; +} + +/// @nodoc +class _$ProfitLossAnalyticCopyWithImpl<$Res, $Val extends ProfitLossAnalytic> + implements $ProfitLossAnalyticCopyWith<$Res> { + _$ProfitLossAnalyticCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = null, + Object? dateFrom = null, + Object? dateTo = null, + Object? groupBy = null, + Object? summary = null, + Object? data = null, + Object? productData = null, + }) { + return _then( + _value.copyWith( + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + dateFrom: null == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String, + dateTo: null == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String, + groupBy: null == groupBy + ? _value.groupBy + : groupBy // ignore: cast_nullable_to_non_nullable + as String, + summary: null == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as ProfitLossSummary, + data: null == data + ? _value.data + : data // ignore: cast_nullable_to_non_nullable + as List, + productData: null == productData + ? _value.productData + : productData // ignore: cast_nullable_to_non_nullable + as List, + ) + as $Val, + ); + } + + /// Create a copy of ProfitLossAnalytic + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ProfitLossSummaryCopyWith<$Res> get summary { + return $ProfitLossSummaryCopyWith<$Res>(_value.summary, (value) { + return _then(_value.copyWith(summary: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$ProfitLossAnalyticImplCopyWith<$Res> + implements $ProfitLossAnalyticCopyWith<$Res> { + factory _$$ProfitLossAnalyticImplCopyWith( + _$ProfitLossAnalyticImpl value, + $Res Function(_$ProfitLossAnalyticImpl) then, + ) = __$$ProfitLossAnalyticImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String organizationId, + String dateFrom, + String dateTo, + String groupBy, + ProfitLossSummary summary, + List data, + List productData, + }); + + @override + $ProfitLossSummaryCopyWith<$Res> get summary; +} + +/// @nodoc +class __$$ProfitLossAnalyticImplCopyWithImpl<$Res> + extends _$ProfitLossAnalyticCopyWithImpl<$Res, _$ProfitLossAnalyticImpl> + implements _$$ProfitLossAnalyticImplCopyWith<$Res> { + __$$ProfitLossAnalyticImplCopyWithImpl( + _$ProfitLossAnalyticImpl _value, + $Res Function(_$ProfitLossAnalyticImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = null, + Object? dateFrom = null, + Object? dateTo = null, + Object? groupBy = null, + Object? summary = null, + Object? data = null, + Object? productData = null, + }) { + return _then( + _$ProfitLossAnalyticImpl( + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + dateFrom: null == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String, + dateTo: null == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String, + groupBy: null == groupBy + ? _value.groupBy + : groupBy // ignore: cast_nullable_to_non_nullable + as String, + summary: null == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as ProfitLossSummary, + data: null == data + ? _value._data + : data // ignore: cast_nullable_to_non_nullable + as List, + productData: null == productData + ? _value._productData + : productData // ignore: cast_nullable_to_non_nullable + as List, + ), + ); + } +} + +/// @nodoc + +class _$ProfitLossAnalyticImpl implements _ProfitLossAnalytic { + const _$ProfitLossAnalyticImpl({ + required this.organizationId, + required this.dateFrom, + required this.dateTo, + required this.groupBy, + required this.summary, + required final List data, + required final List productData, + }) : _data = data, + _productData = productData; + + @override + final String organizationId; + @override + final String dateFrom; + @override + final String dateTo; + @override + final String groupBy; + @override + final ProfitLossSummary summary; + final List _data; + @override + List get data { + if (_data is EqualUnmodifiableListView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_data); + } + + final List _productData; + @override + List get productData { + if (_productData is EqualUnmodifiableListView) return _productData; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_productData); + } + + @override + String toString() { + return 'ProfitLossAnalytic(organizationId: $organizationId, dateFrom: $dateFrom, dateTo: $dateTo, groupBy: $groupBy, summary: $summary, data: $data, productData: $productData)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProfitLossAnalyticImpl && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo) && + (identical(other.groupBy, groupBy) || other.groupBy == groupBy) && + (identical(other.summary, summary) || other.summary == summary) && + const DeepCollectionEquality().equals(other._data, _data) && + const DeepCollectionEquality().equals( + other._productData, + _productData, + )); + } + + @override + int get hashCode => Object.hash( + runtimeType, + organizationId, + dateFrom, + dateTo, + groupBy, + summary, + const DeepCollectionEquality().hash(_data), + const DeepCollectionEquality().hash(_productData), + ); + + /// Create a copy of ProfitLossAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProfitLossAnalyticImplCopyWith<_$ProfitLossAnalyticImpl> get copyWith => + __$$ProfitLossAnalyticImplCopyWithImpl<_$ProfitLossAnalyticImpl>( + this, + _$identity, + ); +} + +abstract class _ProfitLossAnalytic implements ProfitLossAnalytic { + const factory _ProfitLossAnalytic({ + required final String organizationId, + required final String dateFrom, + required final String dateTo, + required final String groupBy, + required final ProfitLossSummary summary, + required final List data, + required final List productData, + }) = _$ProfitLossAnalyticImpl; + + @override + String get organizationId; + @override + String get dateFrom; + @override + String get dateTo; + @override + String get groupBy; + @override + ProfitLossSummary get summary; + @override + List get data; + @override + List get productData; + + /// Create a copy of ProfitLossAnalytic + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProfitLossAnalyticImplCopyWith<_$ProfitLossAnalyticImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$ProfitLossSummary { + int get totalRevenue => throw _privateConstructorUsedError; + int get totalCost => throw _privateConstructorUsedError; + int get grossProfit => throw _privateConstructorUsedError; + double get grossProfitMargin => throw _privateConstructorUsedError; + int get totalTax => throw _privateConstructorUsedError; + int get totalDiscount => throw _privateConstructorUsedError; + int get netProfit => throw _privateConstructorUsedError; + double get netProfitMargin => throw _privateConstructorUsedError; + int get totalOrders => throw _privateConstructorUsedError; + double get averageProfit => throw _privateConstructorUsedError; + double get profitabilityRatio => throw _privateConstructorUsedError; + + /// Create a copy of ProfitLossSummary + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProfitLossSummaryCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossSummaryCopyWith<$Res> { + factory $ProfitLossSummaryCopyWith( + ProfitLossSummary value, + $Res Function(ProfitLossSummary) then, + ) = _$ProfitLossSummaryCopyWithImpl<$Res, ProfitLossSummary>; + @useResult + $Res call({ + int totalRevenue, + int totalCost, + int grossProfit, + double grossProfitMargin, + int totalTax, + int totalDiscount, + int netProfit, + double netProfitMargin, + int totalOrders, + double averageProfit, + double profitabilityRatio, + }); +} + +/// @nodoc +class _$ProfitLossSummaryCopyWithImpl<$Res, $Val extends ProfitLossSummary> + implements $ProfitLossSummaryCopyWith<$Res> { + _$ProfitLossSummaryCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossSummary + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalRevenue = null, + Object? totalCost = null, + Object? grossProfit = null, + Object? grossProfitMargin = null, + Object? totalTax = null, + Object? totalDiscount = null, + Object? netProfit = null, + Object? netProfitMargin = null, + Object? totalOrders = null, + Object? averageProfit = null, + Object? profitabilityRatio = null, + }) { + return _then( + _value.copyWith( + totalRevenue: null == totalRevenue + ? _value.totalRevenue + : totalRevenue // ignore: cast_nullable_to_non_nullable + as int, + totalCost: null == totalCost + ? _value.totalCost + : totalCost // ignore: cast_nullable_to_non_nullable + as int, + grossProfit: null == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int, + grossProfitMargin: null == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + totalTax: null == totalTax + ? _value.totalTax + : totalTax // ignore: cast_nullable_to_non_nullable + as int, + totalDiscount: null == totalDiscount + ? _value.totalDiscount + : totalDiscount // ignore: cast_nullable_to_non_nullable + as int, + netProfit: null == netProfit + ? _value.netProfit + : netProfit // ignore: cast_nullable_to_non_nullable + as int, + netProfitMargin: null == netProfitMargin + ? _value.netProfitMargin + : netProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + totalOrders: null == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int, + averageProfit: null == averageProfit + ? _value.averageProfit + : averageProfit // ignore: cast_nullable_to_non_nullable + as double, + profitabilityRatio: null == profitabilityRatio + ? _value.profitabilityRatio + : profitabilityRatio // ignore: cast_nullable_to_non_nullable + as double, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProfitLossSummaryImplCopyWith<$Res> + implements $ProfitLossSummaryCopyWith<$Res> { + factory _$$ProfitLossSummaryImplCopyWith( + _$ProfitLossSummaryImpl value, + $Res Function(_$ProfitLossSummaryImpl) then, + ) = __$$ProfitLossSummaryImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + int totalRevenue, + int totalCost, + int grossProfit, + double grossProfitMargin, + int totalTax, + int totalDiscount, + int netProfit, + double netProfitMargin, + int totalOrders, + double averageProfit, + double profitabilityRatio, + }); +} + +/// @nodoc +class __$$ProfitLossSummaryImplCopyWithImpl<$Res> + extends _$ProfitLossSummaryCopyWithImpl<$Res, _$ProfitLossSummaryImpl> + implements _$$ProfitLossSummaryImplCopyWith<$Res> { + __$$ProfitLossSummaryImplCopyWithImpl( + _$ProfitLossSummaryImpl _value, + $Res Function(_$ProfitLossSummaryImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossSummary + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalRevenue = null, + Object? totalCost = null, + Object? grossProfit = null, + Object? grossProfitMargin = null, + Object? totalTax = null, + Object? totalDiscount = null, + Object? netProfit = null, + Object? netProfitMargin = null, + Object? totalOrders = null, + Object? averageProfit = null, + Object? profitabilityRatio = null, + }) { + return _then( + _$ProfitLossSummaryImpl( + totalRevenue: null == totalRevenue + ? _value.totalRevenue + : totalRevenue // ignore: cast_nullable_to_non_nullable + as int, + totalCost: null == totalCost + ? _value.totalCost + : totalCost // ignore: cast_nullable_to_non_nullable + as int, + grossProfit: null == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int, + grossProfitMargin: null == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + totalTax: null == totalTax + ? _value.totalTax + : totalTax // ignore: cast_nullable_to_non_nullable + as int, + totalDiscount: null == totalDiscount + ? _value.totalDiscount + : totalDiscount // ignore: cast_nullable_to_non_nullable + as int, + netProfit: null == netProfit + ? _value.netProfit + : netProfit // ignore: cast_nullable_to_non_nullable + as int, + netProfitMargin: null == netProfitMargin + ? _value.netProfitMargin + : netProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + totalOrders: null == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int, + averageProfit: null == averageProfit + ? _value.averageProfit + : averageProfit // ignore: cast_nullable_to_non_nullable + as double, + profitabilityRatio: null == profitabilityRatio + ? _value.profitabilityRatio + : profitabilityRatio // ignore: cast_nullable_to_non_nullable + as double, + ), + ); + } +} + +/// @nodoc + +class _$ProfitLossSummaryImpl implements _ProfitLossSummary { + const _$ProfitLossSummaryImpl({ + required this.totalRevenue, + required this.totalCost, + required this.grossProfit, + required this.grossProfitMargin, + required this.totalTax, + required this.totalDiscount, + required this.netProfit, + required this.netProfitMargin, + required this.totalOrders, + required this.averageProfit, + required this.profitabilityRatio, + }); + + @override + final int totalRevenue; + @override + final int totalCost; + @override + final int grossProfit; + @override + final double grossProfitMargin; + @override + final int totalTax; + @override + final int totalDiscount; + @override + final int netProfit; + @override + final double netProfitMargin; + @override + final int totalOrders; + @override + final double averageProfit; + @override + final double profitabilityRatio; + + @override + String toString() { + return 'ProfitLossSummary(totalRevenue: $totalRevenue, totalCost: $totalCost, grossProfit: $grossProfit, grossProfitMargin: $grossProfitMargin, totalTax: $totalTax, totalDiscount: $totalDiscount, netProfit: $netProfit, netProfitMargin: $netProfitMargin, totalOrders: $totalOrders, averageProfit: $averageProfit, profitabilityRatio: $profitabilityRatio)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProfitLossSummaryImpl && + (identical(other.totalRevenue, totalRevenue) || + other.totalRevenue == totalRevenue) && + (identical(other.totalCost, totalCost) || + other.totalCost == totalCost) && + (identical(other.grossProfit, grossProfit) || + other.grossProfit == grossProfit) && + (identical(other.grossProfitMargin, grossProfitMargin) || + other.grossProfitMargin == grossProfitMargin) && + (identical(other.totalTax, totalTax) || + other.totalTax == totalTax) && + (identical(other.totalDiscount, totalDiscount) || + other.totalDiscount == totalDiscount) && + (identical(other.netProfit, netProfit) || + other.netProfit == netProfit) && + (identical(other.netProfitMargin, netProfitMargin) || + other.netProfitMargin == netProfitMargin) && + (identical(other.totalOrders, totalOrders) || + other.totalOrders == totalOrders) && + (identical(other.averageProfit, averageProfit) || + other.averageProfit == averageProfit) && + (identical(other.profitabilityRatio, profitabilityRatio) || + other.profitabilityRatio == profitabilityRatio)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + totalRevenue, + totalCost, + grossProfit, + grossProfitMargin, + totalTax, + totalDiscount, + netProfit, + netProfitMargin, + totalOrders, + averageProfit, + profitabilityRatio, + ); + + /// Create a copy of ProfitLossSummary + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProfitLossSummaryImplCopyWith<_$ProfitLossSummaryImpl> get copyWith => + __$$ProfitLossSummaryImplCopyWithImpl<_$ProfitLossSummaryImpl>( + this, + _$identity, + ); +} + +abstract class _ProfitLossSummary implements ProfitLossSummary { + const factory _ProfitLossSummary({ + required final int totalRevenue, + required final int totalCost, + required final int grossProfit, + required final double grossProfitMargin, + required final int totalTax, + required final int totalDiscount, + required final int netProfit, + required final double netProfitMargin, + required final int totalOrders, + required final double averageProfit, + required final double profitabilityRatio, + }) = _$ProfitLossSummaryImpl; + + @override + int get totalRevenue; + @override + int get totalCost; + @override + int get grossProfit; + @override + double get grossProfitMargin; + @override + int get totalTax; + @override + int get totalDiscount; + @override + int get netProfit; + @override + double get netProfitMargin; + @override + int get totalOrders; + @override + double get averageProfit; + @override + double get profitabilityRatio; + + /// Create a copy of ProfitLossSummary + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProfitLossSummaryImplCopyWith<_$ProfitLossSummaryImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$ProfitLossDailyData { + String get date => throw _privateConstructorUsedError; + int get revenue => throw _privateConstructorUsedError; + int get cost => throw _privateConstructorUsedError; + int get grossProfit => throw _privateConstructorUsedError; + double get grossProfitMargin => throw _privateConstructorUsedError; + int get tax => throw _privateConstructorUsedError; + int get discount => throw _privateConstructorUsedError; + int get netProfit => throw _privateConstructorUsedError; + double get netProfitMargin => throw _privateConstructorUsedError; + int get orders => throw _privateConstructorUsedError; + + /// Create a copy of ProfitLossDailyData + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProfitLossDailyDataCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossDailyDataCopyWith<$Res> { + factory $ProfitLossDailyDataCopyWith( + ProfitLossDailyData value, + $Res Function(ProfitLossDailyData) then, + ) = _$ProfitLossDailyDataCopyWithImpl<$Res, ProfitLossDailyData>; + @useResult + $Res call({ + String date, + int revenue, + int cost, + int grossProfit, + double grossProfitMargin, + int tax, + int discount, + int netProfit, + double netProfitMargin, + int orders, + }); +} + +/// @nodoc +class _$ProfitLossDailyDataCopyWithImpl<$Res, $Val extends ProfitLossDailyData> + implements $ProfitLossDailyDataCopyWith<$Res> { + _$ProfitLossDailyDataCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossDailyData + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = null, + Object? revenue = null, + Object? cost = null, + Object? grossProfit = null, + Object? grossProfitMargin = null, + Object? tax = null, + Object? discount = null, + Object? netProfit = null, + Object? netProfitMargin = null, + Object? orders = null, + }) { + return _then( + _value.copyWith( + date: null == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as String, + revenue: null == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int, + cost: null == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int, + grossProfit: null == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int, + grossProfitMargin: null == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + tax: null == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as int, + discount: null == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as int, + netProfit: null == netProfit + ? _value.netProfit + : netProfit // ignore: cast_nullable_to_non_nullable + as int, + netProfitMargin: null == netProfitMargin + ? _value.netProfitMargin + : netProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + orders: null == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as int, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProfitLossDailyDataImplCopyWith<$Res> + implements $ProfitLossDailyDataCopyWith<$Res> { + factory _$$ProfitLossDailyDataImplCopyWith( + _$ProfitLossDailyDataImpl value, + $Res Function(_$ProfitLossDailyDataImpl) then, + ) = __$$ProfitLossDailyDataImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String date, + int revenue, + int cost, + int grossProfit, + double grossProfitMargin, + int tax, + int discount, + int netProfit, + double netProfitMargin, + int orders, + }); +} + +/// @nodoc +class __$$ProfitLossDailyDataImplCopyWithImpl<$Res> + extends _$ProfitLossDailyDataCopyWithImpl<$Res, _$ProfitLossDailyDataImpl> + implements _$$ProfitLossDailyDataImplCopyWith<$Res> { + __$$ProfitLossDailyDataImplCopyWithImpl( + _$ProfitLossDailyDataImpl _value, + $Res Function(_$ProfitLossDailyDataImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossDailyData + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = null, + Object? revenue = null, + Object? cost = null, + Object? grossProfit = null, + Object? grossProfitMargin = null, + Object? tax = null, + Object? discount = null, + Object? netProfit = null, + Object? netProfitMargin = null, + Object? orders = null, + }) { + return _then( + _$ProfitLossDailyDataImpl( + date: null == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as String, + revenue: null == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int, + cost: null == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int, + grossProfit: null == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int, + grossProfitMargin: null == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + tax: null == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as int, + discount: null == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as int, + netProfit: null == netProfit + ? _value.netProfit + : netProfit // ignore: cast_nullable_to_non_nullable + as int, + netProfitMargin: null == netProfitMargin + ? _value.netProfitMargin + : netProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + orders: null == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as int, + ), + ); + } +} + +/// @nodoc + +class _$ProfitLossDailyDataImpl implements _ProfitLossDailyData { + const _$ProfitLossDailyDataImpl({ + required this.date, + required this.revenue, + required this.cost, + required this.grossProfit, + required this.grossProfitMargin, + required this.tax, + required this.discount, + required this.netProfit, + required this.netProfitMargin, + required this.orders, + }); + + @override + final String date; + @override + final int revenue; + @override + final int cost; + @override + final int grossProfit; + @override + final double grossProfitMargin; + @override + final int tax; + @override + final int discount; + @override + final int netProfit; + @override + final double netProfitMargin; + @override + final int orders; + + @override + String toString() { + return 'ProfitLossDailyData(date: $date, revenue: $revenue, cost: $cost, grossProfit: $grossProfit, grossProfitMargin: $grossProfitMargin, tax: $tax, discount: $discount, netProfit: $netProfit, netProfitMargin: $netProfitMargin, orders: $orders)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProfitLossDailyDataImpl && + (identical(other.date, date) || other.date == date) && + (identical(other.revenue, revenue) || other.revenue == revenue) && + (identical(other.cost, cost) || other.cost == cost) && + (identical(other.grossProfit, grossProfit) || + other.grossProfit == grossProfit) && + (identical(other.grossProfitMargin, grossProfitMargin) || + other.grossProfitMargin == grossProfitMargin) && + (identical(other.tax, tax) || other.tax == tax) && + (identical(other.discount, discount) || + other.discount == discount) && + (identical(other.netProfit, netProfit) || + other.netProfit == netProfit) && + (identical(other.netProfitMargin, netProfitMargin) || + other.netProfitMargin == netProfitMargin) && + (identical(other.orders, orders) || other.orders == orders)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + date, + revenue, + cost, + grossProfit, + grossProfitMargin, + tax, + discount, + netProfit, + netProfitMargin, + orders, + ); + + /// Create a copy of ProfitLossDailyData + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProfitLossDailyDataImplCopyWith<_$ProfitLossDailyDataImpl> get copyWith => + __$$ProfitLossDailyDataImplCopyWithImpl<_$ProfitLossDailyDataImpl>( + this, + _$identity, + ); +} + +abstract class _ProfitLossDailyData implements ProfitLossDailyData { + const factory _ProfitLossDailyData({ + required final String date, + required final int revenue, + required final int cost, + required final int grossProfit, + required final double grossProfitMargin, + required final int tax, + required final int discount, + required final int netProfit, + required final double netProfitMargin, + required final int orders, + }) = _$ProfitLossDailyDataImpl; + + @override + String get date; + @override + int get revenue; + @override + int get cost; + @override + int get grossProfit; + @override + double get grossProfitMargin; + @override + int get tax; + @override + int get discount; + @override + int get netProfit; + @override + double get netProfitMargin; + @override + int get orders; + + /// Create a copy of ProfitLossDailyData + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProfitLossDailyDataImplCopyWith<_$ProfitLossDailyDataImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$ProfitLossProductData { + String get productId => throw _privateConstructorUsedError; + String get productName => throw _privateConstructorUsedError; + String get categoryId => throw _privateConstructorUsedError; + String get categoryName => throw _privateConstructorUsedError; + int get quantitySold => throw _privateConstructorUsedError; + int get revenue => throw _privateConstructorUsedError; + int get cost => throw _privateConstructorUsedError; + int get grossProfit => throw _privateConstructorUsedError; + double get grossProfitMargin => throw _privateConstructorUsedError; + int get averagePrice => throw _privateConstructorUsedError; + int get averageCost => throw _privateConstructorUsedError; + int get profitPerUnit => throw _privateConstructorUsedError; + + /// Create a copy of ProfitLossProductData + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProfitLossProductDataCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossProductDataCopyWith<$Res> { + factory $ProfitLossProductDataCopyWith( + ProfitLossProductData value, + $Res Function(ProfitLossProductData) then, + ) = _$ProfitLossProductDataCopyWithImpl<$Res, ProfitLossProductData>; + @useResult + $Res call({ + String productId, + String productName, + String categoryId, + String categoryName, + int quantitySold, + int revenue, + int cost, + int grossProfit, + double grossProfitMargin, + int averagePrice, + int averageCost, + int profitPerUnit, + }); +} + +/// @nodoc +class _$ProfitLossProductDataCopyWithImpl< + $Res, + $Val extends ProfitLossProductData +> + implements $ProfitLossProductDataCopyWith<$Res> { + _$ProfitLossProductDataCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossProductData + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = null, + Object? productName = null, + Object? categoryId = null, + Object? categoryName = null, + Object? quantitySold = null, + Object? revenue = null, + Object? cost = null, + Object? grossProfit = null, + Object? grossProfitMargin = null, + Object? averagePrice = null, + Object? averageCost = null, + Object? profitPerUnit = null, + }) { + return _then( + _value.copyWith( + productId: null == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String, + productName: null == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String, + 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, + quantitySold: null == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int, + revenue: null == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int, + cost: null == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int, + grossProfit: null == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int, + grossProfitMargin: null == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + averagePrice: null == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as int, + averageCost: null == averageCost + ? _value.averageCost + : averageCost // ignore: cast_nullable_to_non_nullable + as int, + profitPerUnit: null == profitPerUnit + ? _value.profitPerUnit + : profitPerUnit // ignore: cast_nullable_to_non_nullable + as int, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProfitLossProductDataImplCopyWith<$Res> + implements $ProfitLossProductDataCopyWith<$Res> { + factory _$$ProfitLossProductDataImplCopyWith( + _$ProfitLossProductDataImpl value, + $Res Function(_$ProfitLossProductDataImpl) then, + ) = __$$ProfitLossProductDataImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String productId, + String productName, + String categoryId, + String categoryName, + int quantitySold, + int revenue, + int cost, + int grossProfit, + double grossProfitMargin, + int averagePrice, + int averageCost, + int profitPerUnit, + }); +} + +/// @nodoc +class __$$ProfitLossProductDataImplCopyWithImpl<$Res> + extends + _$ProfitLossProductDataCopyWithImpl<$Res, _$ProfitLossProductDataImpl> + implements _$$ProfitLossProductDataImplCopyWith<$Res> { + __$$ProfitLossProductDataImplCopyWithImpl( + _$ProfitLossProductDataImpl _value, + $Res Function(_$ProfitLossProductDataImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossProductData + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = null, + Object? productName = null, + Object? categoryId = null, + Object? categoryName = null, + Object? quantitySold = null, + Object? revenue = null, + Object? cost = null, + Object? grossProfit = null, + Object? grossProfitMargin = null, + Object? averagePrice = null, + Object? averageCost = null, + Object? profitPerUnit = null, + }) { + return _then( + _$ProfitLossProductDataImpl( + productId: null == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String, + productName: null == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String, + 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, + quantitySold: null == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int, + revenue: null == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int, + cost: null == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int, + grossProfit: null == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int, + grossProfitMargin: null == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + averagePrice: null == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as int, + averageCost: null == averageCost + ? _value.averageCost + : averageCost // ignore: cast_nullable_to_non_nullable + as int, + profitPerUnit: null == profitPerUnit + ? _value.profitPerUnit + : profitPerUnit // ignore: cast_nullable_to_non_nullable + as int, + ), + ); + } +} + +/// @nodoc + +class _$ProfitLossProductDataImpl implements _ProfitLossProductData { + const _$ProfitLossProductDataImpl({ + required this.productId, + required this.productName, + required this.categoryId, + required this.categoryName, + required this.quantitySold, + required this.revenue, + required this.cost, + required this.grossProfit, + required this.grossProfitMargin, + required this.averagePrice, + required this.averageCost, + required this.profitPerUnit, + }); + + @override + final String productId; + @override + final String productName; + @override + final String categoryId; + @override + final String categoryName; + @override + final int quantitySold; + @override + final int revenue; + @override + final int cost; + @override + final int grossProfit; + @override + final double grossProfitMargin; + @override + final int averagePrice; + @override + final int averageCost; + @override + final int profitPerUnit; + + @override + String toString() { + return 'ProfitLossProductData(productId: $productId, productName: $productName, categoryId: $categoryId, categoryName: $categoryName, quantitySold: $quantitySold, revenue: $revenue, cost: $cost, grossProfit: $grossProfit, grossProfitMargin: $grossProfitMargin, averagePrice: $averagePrice, averageCost: $averageCost, profitPerUnit: $profitPerUnit)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProfitLossProductDataImpl && + (identical(other.productId, productId) || + other.productId == productId) && + (identical(other.productName, productName) || + other.productName == productName) && + (identical(other.categoryId, categoryId) || + other.categoryId == categoryId) && + (identical(other.categoryName, categoryName) || + other.categoryName == categoryName) && + (identical(other.quantitySold, quantitySold) || + other.quantitySold == quantitySold) && + (identical(other.revenue, revenue) || other.revenue == revenue) && + (identical(other.cost, cost) || other.cost == cost) && + (identical(other.grossProfit, grossProfit) || + other.grossProfit == grossProfit) && + (identical(other.grossProfitMargin, grossProfitMargin) || + other.grossProfitMargin == grossProfitMargin) && + (identical(other.averagePrice, averagePrice) || + other.averagePrice == averagePrice) && + (identical(other.averageCost, averageCost) || + other.averageCost == averageCost) && + (identical(other.profitPerUnit, profitPerUnit) || + other.profitPerUnit == profitPerUnit)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + productId, + productName, + categoryId, + categoryName, + quantitySold, + revenue, + cost, + grossProfit, + grossProfitMargin, + averagePrice, + averageCost, + profitPerUnit, + ); + + /// Create a copy of ProfitLossProductData + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProfitLossProductDataImplCopyWith<_$ProfitLossProductDataImpl> + get copyWith => + __$$ProfitLossProductDataImplCopyWithImpl<_$ProfitLossProductDataImpl>( + this, + _$identity, + ); +} + +abstract class _ProfitLossProductData implements ProfitLossProductData { + const factory _ProfitLossProductData({ + required final String productId, + required final String productName, + required final String categoryId, + required final String categoryName, + required final int quantitySold, + required final int revenue, + required final int cost, + required final int grossProfit, + required final double grossProfitMargin, + required final int averagePrice, + required final int averageCost, + required final int profitPerUnit, + }) = _$ProfitLossProductDataImpl; + + @override + String get productId; + @override + String get productName; + @override + String get categoryId; + @override + String get categoryName; + @override + int get quantitySold; + @override + int get revenue; + @override + int get cost; + @override + int get grossProfit; + @override + double get grossProfitMargin; + @override + int get averagePrice; + @override + int get averageCost; + @override + int get profitPerUnit; + + /// Create a copy of ProfitLossProductData + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProfitLossProductDataImplCopyWith<_$ProfitLossProductDataImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/domain/analytic/entities/profit_loss_analytic_entity.dart b/lib/domain/analytic/entities/profit_loss_analytic_entity.dart new file mode 100644 index 0000000..3828307 --- /dev/null +++ b/lib/domain/analytic/entities/profit_loss_analytic_entity.dart @@ -0,0 +1,117 @@ +part of '../analytic.dart'; + +@freezed +class ProfitLossAnalytic with _$ProfitLossAnalytic { + const factory ProfitLossAnalytic({ + required String organizationId, + required String dateFrom, + required String dateTo, + required String groupBy, + required ProfitLossSummary summary, + required List data, + required List productData, + }) = _ProfitLossAnalytic; + + factory ProfitLossAnalytic.empty() => ProfitLossAnalytic( + organizationId: '', + dateFrom: '', + dateTo: '', + groupBy: '', + summary: ProfitLossSummary.empty(), + data: [], + productData: [], + ); +} + +@freezed +class ProfitLossSummary with _$ProfitLossSummary { + const factory ProfitLossSummary({ + required int totalRevenue, + required int totalCost, + required int grossProfit, + required double grossProfitMargin, + required int totalTax, + required int totalDiscount, + required int netProfit, + required double netProfitMargin, + required int totalOrders, + required double averageProfit, + required double profitabilityRatio, + }) = _ProfitLossSummary; + + factory ProfitLossSummary.empty() => ProfitLossSummary( + totalRevenue: 0, + totalCost: 0, + grossProfit: 0, + grossProfitMargin: 0, + totalTax: 0, + totalDiscount: 0, + netProfit: 0, + netProfitMargin: 0, + totalOrders: 0, + averageProfit: 0, + profitabilityRatio: 0, + ); +} + +@freezed +class ProfitLossDailyData with _$ProfitLossDailyData { + const factory ProfitLossDailyData({ + required String date, + required int revenue, + required int cost, + required int grossProfit, + required double grossProfitMargin, + required int tax, + required int discount, + required int netProfit, + required double netProfitMargin, + required int orders, + }) = _ProfitLossDailyData; + + factory ProfitLossDailyData.empty() => ProfitLossDailyData( + date: '', + revenue: 0, + cost: 0, + grossProfit: 0, + grossProfitMargin: 0, + tax: 0, + discount: 0, + netProfit: 0, + netProfitMargin: 0, + orders: 0, + ); +} + +@freezed +class ProfitLossProductData with _$ProfitLossProductData { + const factory ProfitLossProductData({ + required String productId, + required String productName, + required String categoryId, + required String categoryName, + required int quantitySold, + required int revenue, + required int cost, + required int grossProfit, + required double grossProfitMargin, + required int averagePrice, + required int averageCost, + required int profitPerUnit, + }) = _ProfitLossProductData; + + factory ProfitLossProductData.empty() => ProfitLossProductData( + productId: '', + productName: '', + categoryId: '', + categoryName: '', + quantitySold: 0, + revenue: 0, + cost: 0, + grossProfit: 0, + grossProfitMargin: 0, + averagePrice: 0, + averageCost: 0, + profitPerUnit: 0, + ); +} diff --git a/lib/domain/analytic/repositories/i_analytic_repository.dart b/lib/domain/analytic/repositories/i_analytic_repository.dart index 6826dde..95dfd2b 100644 --- a/lib/domain/analytic/repositories/i_analytic_repository.dart +++ b/lib/domain/analytic/repositories/i_analytic_repository.dart @@ -7,4 +7,8 @@ abstract class IAnalyticRepository { required DateTime dateFrom, required DateTime dateTo, }); + Future> getProfitLoss({ + required DateTime dateFrom, + required DateTime dateTo, + }); } diff --git a/lib/infrastructure/analytic/analytic_dtos.dart b/lib/infrastructure/analytic/analytic_dtos.dart index 277bb65..94a2ac3 100644 --- a/lib/infrastructure/analytic/analytic_dtos.dart +++ b/lib/infrastructure/analytic/analytic_dtos.dart @@ -6,3 +6,4 @@ part 'analytic_dtos.freezed.dart'; part 'analytic_dtos.g.dart'; part 'dto/sales_analytic_dto.dart'; +part 'dto/profit_loss_analytic_dto.dart'; diff --git a/lib/infrastructure/analytic/analytic_dtos.freezed.dart b/lib/infrastructure/analytic/analytic_dtos.freezed.dart index d2f58d4..4d03fe3 100644 --- a/lib/infrastructure/analytic/analytic_dtos.freezed.dart +++ b/lib/infrastructure/analytic/analytic_dtos.freezed.dart @@ -1017,3 +1017,1656 @@ abstract class _SalesAnalyticDataDto extends SalesAnalyticDataDto { _$$SalesAnalyticDataDtoImplCopyWith<_$SalesAnalyticDataDtoImpl> get copyWith => throw _privateConstructorUsedError; } + +ProfitLossAnalyticDto _$ProfitLossAnalyticDtoFromJson( + Map json, +) { + return _ProfitLossAnalyticDto.fromJson(json); +} + +/// @nodoc +mixin _$ProfitLossAnalyticDto { + @JsonKey(name: 'organization_id') + String? get organizationId => throw _privateConstructorUsedError; + @JsonKey(name: 'date_from') + String? get dateFrom => throw _privateConstructorUsedError; + @JsonKey(name: 'date_to') + String? get dateTo => throw _privateConstructorUsedError; + @JsonKey(name: 'group_by') + String? get groupBy => throw _privateConstructorUsedError; + @JsonKey(name: 'summary') + ProfitLossSummaryDto? get summary => throw _privateConstructorUsedError; + @JsonKey(name: 'data') + List? get data => throw _privateConstructorUsedError; + @JsonKey(name: 'product_data') + List? get productData => + throw _privateConstructorUsedError; + + /// Serializes this ProfitLossAnalyticDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ProfitLossAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProfitLossAnalyticDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossAnalyticDtoCopyWith<$Res> { + factory $ProfitLossAnalyticDtoCopyWith( + ProfitLossAnalyticDto value, + $Res Function(ProfitLossAnalyticDto) then, + ) = _$ProfitLossAnalyticDtoCopyWithImpl<$Res, ProfitLossAnalyticDto>; + @useResult + $Res call({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'group_by') String? groupBy, + @JsonKey(name: 'summary') ProfitLossSummaryDto? summary, + @JsonKey(name: 'data') List? data, + @JsonKey(name: 'product_data') List? productData, + }); + + $ProfitLossSummaryDtoCopyWith<$Res>? get summary; +} + +/// @nodoc +class _$ProfitLossAnalyticDtoCopyWithImpl< + $Res, + $Val extends ProfitLossAnalyticDto +> + implements $ProfitLossAnalyticDtoCopyWith<$Res> { + _$ProfitLossAnalyticDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = freezed, + Object? dateFrom = freezed, + Object? dateTo = freezed, + Object? groupBy = freezed, + Object? summary = freezed, + Object? data = freezed, + Object? productData = freezed, + }) { + return _then( + _value.copyWith( + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + dateFrom: freezed == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String?, + dateTo: freezed == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String?, + groupBy: freezed == groupBy + ? _value.groupBy + : groupBy // ignore: cast_nullable_to_non_nullable + as String?, + summary: freezed == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as ProfitLossSummaryDto?, + data: freezed == data + ? _value.data + : data // ignore: cast_nullable_to_non_nullable + as List?, + productData: freezed == productData + ? _value.productData + : productData // ignore: cast_nullable_to_non_nullable + as List?, + ) + as $Val, + ); + } + + /// Create a copy of ProfitLossAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ProfitLossSummaryDtoCopyWith<$Res>? get summary { + if (_value.summary == null) { + return null; + } + + return $ProfitLossSummaryDtoCopyWith<$Res>(_value.summary!, (value) { + return _then(_value.copyWith(summary: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$ProfitLossAnalyticDtoImplCopyWith<$Res> + implements $ProfitLossAnalyticDtoCopyWith<$Res> { + factory _$$ProfitLossAnalyticDtoImplCopyWith( + _$ProfitLossAnalyticDtoImpl value, + $Res Function(_$ProfitLossAnalyticDtoImpl) then, + ) = __$$ProfitLossAnalyticDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'group_by') String? groupBy, + @JsonKey(name: 'summary') ProfitLossSummaryDto? summary, + @JsonKey(name: 'data') List? data, + @JsonKey(name: 'product_data') List? productData, + }); + + @override + $ProfitLossSummaryDtoCopyWith<$Res>? get summary; +} + +/// @nodoc +class __$$ProfitLossAnalyticDtoImplCopyWithImpl<$Res> + extends + _$ProfitLossAnalyticDtoCopyWithImpl<$Res, _$ProfitLossAnalyticDtoImpl> + implements _$$ProfitLossAnalyticDtoImplCopyWith<$Res> { + __$$ProfitLossAnalyticDtoImplCopyWithImpl( + _$ProfitLossAnalyticDtoImpl _value, + $Res Function(_$ProfitLossAnalyticDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = freezed, + Object? dateFrom = freezed, + Object? dateTo = freezed, + Object? groupBy = freezed, + Object? summary = freezed, + Object? data = freezed, + Object? productData = freezed, + }) { + return _then( + _$ProfitLossAnalyticDtoImpl( + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + dateFrom: freezed == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String?, + dateTo: freezed == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String?, + groupBy: freezed == groupBy + ? _value.groupBy + : groupBy // ignore: cast_nullable_to_non_nullable + as String?, + summary: freezed == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as ProfitLossSummaryDto?, + data: freezed == data + ? _value._data + : data // ignore: cast_nullable_to_non_nullable + as List?, + productData: freezed == productData + ? _value._productData + : productData // ignore: cast_nullable_to_non_nullable + as List?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$ProfitLossAnalyticDtoImpl extends _ProfitLossAnalyticDto { + const _$ProfitLossAnalyticDtoImpl({ + @JsonKey(name: 'organization_id') this.organizationId, + @JsonKey(name: 'date_from') this.dateFrom, + @JsonKey(name: 'date_to') this.dateTo, + @JsonKey(name: 'group_by') this.groupBy, + @JsonKey(name: 'summary') this.summary, + @JsonKey(name: 'data') final List? data, + @JsonKey(name: 'product_data') + final List? productData, + }) : _data = data, + _productData = productData, + super._(); + + factory _$ProfitLossAnalyticDtoImpl.fromJson(Map json) => + _$$ProfitLossAnalyticDtoImplFromJson(json); + + @override + @JsonKey(name: 'organization_id') + final String? organizationId; + @override + @JsonKey(name: 'date_from') + final String? dateFrom; + @override + @JsonKey(name: 'date_to') + final String? dateTo; + @override + @JsonKey(name: 'group_by') + final String? groupBy; + @override + @JsonKey(name: 'summary') + final ProfitLossSummaryDto? summary; + final List? _data; + @override + @JsonKey(name: 'data') + List? get data { + final value = _data; + if (value == null) return null; + if (_data is EqualUnmodifiableListView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + final List? _productData; + @override + @JsonKey(name: 'product_data') + List? get productData { + final value = _productData; + if (value == null) return null; + if (_productData is EqualUnmodifiableListView) return _productData; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + @override + String toString() { + return 'ProfitLossAnalyticDto(organizationId: $organizationId, dateFrom: $dateFrom, dateTo: $dateTo, groupBy: $groupBy, summary: $summary, data: $data, productData: $productData)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProfitLossAnalyticDtoImpl && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo) && + (identical(other.groupBy, groupBy) || other.groupBy == groupBy) && + (identical(other.summary, summary) || other.summary == summary) && + const DeepCollectionEquality().equals(other._data, _data) && + const DeepCollectionEquality().equals( + other._productData, + _productData, + )); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + organizationId, + dateFrom, + dateTo, + groupBy, + summary, + const DeepCollectionEquality().hash(_data), + const DeepCollectionEquality().hash(_productData), + ); + + /// Create a copy of ProfitLossAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProfitLossAnalyticDtoImplCopyWith<_$ProfitLossAnalyticDtoImpl> + get copyWith => + __$$ProfitLossAnalyticDtoImplCopyWithImpl<_$ProfitLossAnalyticDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$ProfitLossAnalyticDtoImplToJson(this); + } +} + +abstract class _ProfitLossAnalyticDto extends ProfitLossAnalyticDto { + const factory _ProfitLossAnalyticDto({ + @JsonKey(name: 'organization_id') final String? organizationId, + @JsonKey(name: 'date_from') final String? dateFrom, + @JsonKey(name: 'date_to') final String? dateTo, + @JsonKey(name: 'group_by') final String? groupBy, + @JsonKey(name: 'summary') final ProfitLossSummaryDto? summary, + @JsonKey(name: 'data') final List? data, + @JsonKey(name: 'product_data') + final List? productData, + }) = _$ProfitLossAnalyticDtoImpl; + const _ProfitLossAnalyticDto._() : super._(); + + factory _ProfitLossAnalyticDto.fromJson(Map json) = + _$ProfitLossAnalyticDtoImpl.fromJson; + + @override + @JsonKey(name: 'organization_id') + String? get organizationId; + @override + @JsonKey(name: 'date_from') + String? get dateFrom; + @override + @JsonKey(name: 'date_to') + String? get dateTo; + @override + @JsonKey(name: 'group_by') + String? get groupBy; + @override + @JsonKey(name: 'summary') + ProfitLossSummaryDto? get summary; + @override + @JsonKey(name: 'data') + List? get data; + @override + @JsonKey(name: 'product_data') + List? get productData; + + /// Create a copy of ProfitLossAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProfitLossAnalyticDtoImplCopyWith<_$ProfitLossAnalyticDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +ProfitLossSummaryDto _$ProfitLossSummaryDtoFromJson(Map json) { + return _ProfitLossSummaryDto.fromJson(json); +} + +/// @nodoc +mixin _$ProfitLossSummaryDto { + @JsonKey(name: 'total_revenue') + int? get totalRevenue => throw _privateConstructorUsedError; + @JsonKey(name: 'total_cost') + int? get totalCost => throw _privateConstructorUsedError; + @JsonKey(name: 'gross_profit') + int? get grossProfit => throw _privateConstructorUsedError; + @JsonKey(name: 'gross_profit_margin') + double? get grossProfitMargin => throw _privateConstructorUsedError; + @JsonKey(name: 'total_tax') + int? get totalTax => throw _privateConstructorUsedError; + @JsonKey(name: 'total_discount') + int? get totalDiscount => throw _privateConstructorUsedError; + @JsonKey(name: 'net_profit') + int? get netProfit => throw _privateConstructorUsedError; + @JsonKey(name: 'net_profit_margin') + double? get netProfitMargin => throw _privateConstructorUsedError; + @JsonKey(name: 'total_orders') + int? get totalOrders => throw _privateConstructorUsedError; + @JsonKey(name: 'average_profit') + double? get averageProfit => throw _privateConstructorUsedError; + @JsonKey(name: 'profitability_ratio') + double? get profitabilityRatio => throw _privateConstructorUsedError; + + /// Serializes this ProfitLossSummaryDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ProfitLossSummaryDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProfitLossSummaryDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossSummaryDtoCopyWith<$Res> { + factory $ProfitLossSummaryDtoCopyWith( + ProfitLossSummaryDto value, + $Res Function(ProfitLossSummaryDto) then, + ) = _$ProfitLossSummaryDtoCopyWithImpl<$Res, ProfitLossSummaryDto>; + @useResult + $Res call({ + @JsonKey(name: 'total_revenue') int? totalRevenue, + @JsonKey(name: 'total_cost') int? totalCost, + @JsonKey(name: 'gross_profit') int? grossProfit, + @JsonKey(name: 'gross_profit_margin') double? grossProfitMargin, + @JsonKey(name: 'total_tax') int? totalTax, + @JsonKey(name: 'total_discount') int? totalDiscount, + @JsonKey(name: 'net_profit') int? netProfit, + @JsonKey(name: 'net_profit_margin') double? netProfitMargin, + @JsonKey(name: 'total_orders') int? totalOrders, + @JsonKey(name: 'average_profit') double? averageProfit, + @JsonKey(name: 'profitability_ratio') double? profitabilityRatio, + }); +} + +/// @nodoc +class _$ProfitLossSummaryDtoCopyWithImpl< + $Res, + $Val extends ProfitLossSummaryDto +> + implements $ProfitLossSummaryDtoCopyWith<$Res> { + _$ProfitLossSummaryDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossSummaryDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalRevenue = freezed, + Object? totalCost = freezed, + Object? grossProfit = freezed, + Object? grossProfitMargin = freezed, + Object? totalTax = freezed, + Object? totalDiscount = freezed, + Object? netProfit = freezed, + Object? netProfitMargin = freezed, + Object? totalOrders = freezed, + Object? averageProfit = freezed, + Object? profitabilityRatio = freezed, + }) { + return _then( + _value.copyWith( + totalRevenue: freezed == totalRevenue + ? _value.totalRevenue + : totalRevenue // ignore: cast_nullable_to_non_nullable + as int?, + totalCost: freezed == totalCost + ? _value.totalCost + : totalCost // ignore: cast_nullable_to_non_nullable + as int?, + grossProfit: freezed == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int?, + grossProfitMargin: freezed == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + totalTax: freezed == totalTax + ? _value.totalTax + : totalTax // ignore: cast_nullable_to_non_nullable + as int?, + totalDiscount: freezed == totalDiscount + ? _value.totalDiscount + : totalDiscount // ignore: cast_nullable_to_non_nullable + as int?, + netProfit: freezed == netProfit + ? _value.netProfit + : netProfit // ignore: cast_nullable_to_non_nullable + as int?, + netProfitMargin: freezed == netProfitMargin + ? _value.netProfitMargin + : netProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + totalOrders: freezed == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int?, + averageProfit: freezed == averageProfit + ? _value.averageProfit + : averageProfit // ignore: cast_nullable_to_non_nullable + as double?, + profitabilityRatio: freezed == profitabilityRatio + ? _value.profitabilityRatio + : profitabilityRatio // ignore: cast_nullable_to_non_nullable + as double?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProfitLossSummaryDtoImplCopyWith<$Res> + implements $ProfitLossSummaryDtoCopyWith<$Res> { + factory _$$ProfitLossSummaryDtoImplCopyWith( + _$ProfitLossSummaryDtoImpl value, + $Res Function(_$ProfitLossSummaryDtoImpl) then, + ) = __$$ProfitLossSummaryDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'total_revenue') int? totalRevenue, + @JsonKey(name: 'total_cost') int? totalCost, + @JsonKey(name: 'gross_profit') int? grossProfit, + @JsonKey(name: 'gross_profit_margin') double? grossProfitMargin, + @JsonKey(name: 'total_tax') int? totalTax, + @JsonKey(name: 'total_discount') int? totalDiscount, + @JsonKey(name: 'net_profit') int? netProfit, + @JsonKey(name: 'net_profit_margin') double? netProfitMargin, + @JsonKey(name: 'total_orders') int? totalOrders, + @JsonKey(name: 'average_profit') double? averageProfit, + @JsonKey(name: 'profitability_ratio') double? profitabilityRatio, + }); +} + +/// @nodoc +class __$$ProfitLossSummaryDtoImplCopyWithImpl<$Res> + extends _$ProfitLossSummaryDtoCopyWithImpl<$Res, _$ProfitLossSummaryDtoImpl> + implements _$$ProfitLossSummaryDtoImplCopyWith<$Res> { + __$$ProfitLossSummaryDtoImplCopyWithImpl( + _$ProfitLossSummaryDtoImpl _value, + $Res Function(_$ProfitLossSummaryDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossSummaryDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalRevenue = freezed, + Object? totalCost = freezed, + Object? grossProfit = freezed, + Object? grossProfitMargin = freezed, + Object? totalTax = freezed, + Object? totalDiscount = freezed, + Object? netProfit = freezed, + Object? netProfitMargin = freezed, + Object? totalOrders = freezed, + Object? averageProfit = freezed, + Object? profitabilityRatio = freezed, + }) { + return _then( + _$ProfitLossSummaryDtoImpl( + totalRevenue: freezed == totalRevenue + ? _value.totalRevenue + : totalRevenue // ignore: cast_nullable_to_non_nullable + as int?, + totalCost: freezed == totalCost + ? _value.totalCost + : totalCost // ignore: cast_nullable_to_non_nullable + as int?, + grossProfit: freezed == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int?, + grossProfitMargin: freezed == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + totalTax: freezed == totalTax + ? _value.totalTax + : totalTax // ignore: cast_nullable_to_non_nullable + as int?, + totalDiscount: freezed == totalDiscount + ? _value.totalDiscount + : totalDiscount // ignore: cast_nullable_to_non_nullable + as int?, + netProfit: freezed == netProfit + ? _value.netProfit + : netProfit // ignore: cast_nullable_to_non_nullable + as int?, + netProfitMargin: freezed == netProfitMargin + ? _value.netProfitMargin + : netProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + totalOrders: freezed == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int?, + averageProfit: freezed == averageProfit + ? _value.averageProfit + : averageProfit // ignore: cast_nullable_to_non_nullable + as double?, + profitabilityRatio: freezed == profitabilityRatio + ? _value.profitabilityRatio + : profitabilityRatio // ignore: cast_nullable_to_non_nullable + as double?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$ProfitLossSummaryDtoImpl extends _ProfitLossSummaryDto { + const _$ProfitLossSummaryDtoImpl({ + @JsonKey(name: 'total_revenue') this.totalRevenue, + @JsonKey(name: 'total_cost') this.totalCost, + @JsonKey(name: 'gross_profit') this.grossProfit, + @JsonKey(name: 'gross_profit_margin') this.grossProfitMargin, + @JsonKey(name: 'total_tax') this.totalTax, + @JsonKey(name: 'total_discount') this.totalDiscount, + @JsonKey(name: 'net_profit') this.netProfit, + @JsonKey(name: 'net_profit_margin') this.netProfitMargin, + @JsonKey(name: 'total_orders') this.totalOrders, + @JsonKey(name: 'average_profit') this.averageProfit, + @JsonKey(name: 'profitability_ratio') this.profitabilityRatio, + }) : super._(); + + factory _$ProfitLossSummaryDtoImpl.fromJson(Map json) => + _$$ProfitLossSummaryDtoImplFromJson(json); + + @override + @JsonKey(name: 'total_revenue') + final int? totalRevenue; + @override + @JsonKey(name: 'total_cost') + final int? totalCost; + @override + @JsonKey(name: 'gross_profit') + final int? grossProfit; + @override + @JsonKey(name: 'gross_profit_margin') + final double? grossProfitMargin; + @override + @JsonKey(name: 'total_tax') + final int? totalTax; + @override + @JsonKey(name: 'total_discount') + final int? totalDiscount; + @override + @JsonKey(name: 'net_profit') + final int? netProfit; + @override + @JsonKey(name: 'net_profit_margin') + final double? netProfitMargin; + @override + @JsonKey(name: 'total_orders') + final int? totalOrders; + @override + @JsonKey(name: 'average_profit') + final double? averageProfit; + @override + @JsonKey(name: 'profitability_ratio') + final double? profitabilityRatio; + + @override + String toString() { + return 'ProfitLossSummaryDto(totalRevenue: $totalRevenue, totalCost: $totalCost, grossProfit: $grossProfit, grossProfitMargin: $grossProfitMargin, totalTax: $totalTax, totalDiscount: $totalDiscount, netProfit: $netProfit, netProfitMargin: $netProfitMargin, totalOrders: $totalOrders, averageProfit: $averageProfit, profitabilityRatio: $profitabilityRatio)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProfitLossSummaryDtoImpl && + (identical(other.totalRevenue, totalRevenue) || + other.totalRevenue == totalRevenue) && + (identical(other.totalCost, totalCost) || + other.totalCost == totalCost) && + (identical(other.grossProfit, grossProfit) || + other.grossProfit == grossProfit) && + (identical(other.grossProfitMargin, grossProfitMargin) || + other.grossProfitMargin == grossProfitMargin) && + (identical(other.totalTax, totalTax) || + other.totalTax == totalTax) && + (identical(other.totalDiscount, totalDiscount) || + other.totalDiscount == totalDiscount) && + (identical(other.netProfit, netProfit) || + other.netProfit == netProfit) && + (identical(other.netProfitMargin, netProfitMargin) || + other.netProfitMargin == netProfitMargin) && + (identical(other.totalOrders, totalOrders) || + other.totalOrders == totalOrders) && + (identical(other.averageProfit, averageProfit) || + other.averageProfit == averageProfit) && + (identical(other.profitabilityRatio, profitabilityRatio) || + other.profitabilityRatio == profitabilityRatio)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + totalRevenue, + totalCost, + grossProfit, + grossProfitMargin, + totalTax, + totalDiscount, + netProfit, + netProfitMargin, + totalOrders, + averageProfit, + profitabilityRatio, + ); + + /// Create a copy of ProfitLossSummaryDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProfitLossSummaryDtoImplCopyWith<_$ProfitLossSummaryDtoImpl> + get copyWith => + __$$ProfitLossSummaryDtoImplCopyWithImpl<_$ProfitLossSummaryDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$ProfitLossSummaryDtoImplToJson(this); + } +} + +abstract class _ProfitLossSummaryDto extends ProfitLossSummaryDto { + const factory _ProfitLossSummaryDto({ + @JsonKey(name: 'total_revenue') final int? totalRevenue, + @JsonKey(name: 'total_cost') final int? totalCost, + @JsonKey(name: 'gross_profit') final int? grossProfit, + @JsonKey(name: 'gross_profit_margin') final double? grossProfitMargin, + @JsonKey(name: 'total_tax') final int? totalTax, + @JsonKey(name: 'total_discount') final int? totalDiscount, + @JsonKey(name: 'net_profit') final int? netProfit, + @JsonKey(name: 'net_profit_margin') final double? netProfitMargin, + @JsonKey(name: 'total_orders') final int? totalOrders, + @JsonKey(name: 'average_profit') final double? averageProfit, + @JsonKey(name: 'profitability_ratio') final double? profitabilityRatio, + }) = _$ProfitLossSummaryDtoImpl; + const _ProfitLossSummaryDto._() : super._(); + + factory _ProfitLossSummaryDto.fromJson(Map json) = + _$ProfitLossSummaryDtoImpl.fromJson; + + @override + @JsonKey(name: 'total_revenue') + int? get totalRevenue; + @override + @JsonKey(name: 'total_cost') + int? get totalCost; + @override + @JsonKey(name: 'gross_profit') + int? get grossProfit; + @override + @JsonKey(name: 'gross_profit_margin') + double? get grossProfitMargin; + @override + @JsonKey(name: 'total_tax') + int? get totalTax; + @override + @JsonKey(name: 'total_discount') + int? get totalDiscount; + @override + @JsonKey(name: 'net_profit') + int? get netProfit; + @override + @JsonKey(name: 'net_profit_margin') + double? get netProfitMargin; + @override + @JsonKey(name: 'total_orders') + int? get totalOrders; + @override + @JsonKey(name: 'average_profit') + double? get averageProfit; + @override + @JsonKey(name: 'profitability_ratio') + double? get profitabilityRatio; + + /// Create a copy of ProfitLossSummaryDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProfitLossSummaryDtoImplCopyWith<_$ProfitLossSummaryDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +ProfitLossDailyDataDto _$ProfitLossDailyDataDtoFromJson( + Map json, +) { + return _ProfitLossDailyDataDto.fromJson(json); +} + +/// @nodoc +mixin _$ProfitLossDailyDataDto { + @JsonKey(name: 'date') + String? get date => throw _privateConstructorUsedError; + @JsonKey(name: 'revenue') + int? get revenue => throw _privateConstructorUsedError; + @JsonKey(name: 'cost') + int? get cost => throw _privateConstructorUsedError; + @JsonKey(name: 'gross_profit') + int? get grossProfit => throw _privateConstructorUsedError; + @JsonKey(name: 'gross_profit_margin') + double? get grossProfitMargin => throw _privateConstructorUsedError; + @JsonKey(name: 'tax') + int? get tax => throw _privateConstructorUsedError; + @JsonKey(name: 'discount') + int? get discount => throw _privateConstructorUsedError; + @JsonKey(name: 'net_profit') + int? get netProfit => throw _privateConstructorUsedError; + @JsonKey(name: 'net_profit_margin') + double? get netProfitMargin => throw _privateConstructorUsedError; + @JsonKey(name: 'orders') + int? get orders => throw _privateConstructorUsedError; + + /// Serializes this ProfitLossDailyDataDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ProfitLossDailyDataDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProfitLossDailyDataDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossDailyDataDtoCopyWith<$Res> { + factory $ProfitLossDailyDataDtoCopyWith( + ProfitLossDailyDataDto value, + $Res Function(ProfitLossDailyDataDto) then, + ) = _$ProfitLossDailyDataDtoCopyWithImpl<$Res, ProfitLossDailyDataDto>; + @useResult + $Res call({ + @JsonKey(name: 'date') String? date, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'gross_profit') int? grossProfit, + @JsonKey(name: 'gross_profit_margin') double? grossProfitMargin, + @JsonKey(name: 'tax') int? tax, + @JsonKey(name: 'discount') int? discount, + @JsonKey(name: 'net_profit') int? netProfit, + @JsonKey(name: 'net_profit_margin') double? netProfitMargin, + @JsonKey(name: 'orders') int? orders, + }); +} + +/// @nodoc +class _$ProfitLossDailyDataDtoCopyWithImpl< + $Res, + $Val extends ProfitLossDailyDataDto +> + implements $ProfitLossDailyDataDtoCopyWith<$Res> { + _$ProfitLossDailyDataDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossDailyDataDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = freezed, + Object? revenue = freezed, + Object? cost = freezed, + Object? grossProfit = freezed, + Object? grossProfitMargin = freezed, + Object? tax = freezed, + Object? discount = freezed, + Object? netProfit = freezed, + Object? netProfitMargin = freezed, + Object? orders = freezed, + }) { + return _then( + _value.copyWith( + date: freezed == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as String?, + revenue: freezed == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int?, + cost: freezed == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int?, + grossProfit: freezed == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int?, + grossProfitMargin: freezed == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + tax: freezed == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as int?, + discount: freezed == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as int?, + netProfit: freezed == netProfit + ? _value.netProfit + : netProfit // ignore: cast_nullable_to_non_nullable + as int?, + netProfitMargin: freezed == netProfitMargin + ? _value.netProfitMargin + : netProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + orders: freezed == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as int?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProfitLossDailyDataDtoImplCopyWith<$Res> + implements $ProfitLossDailyDataDtoCopyWith<$Res> { + factory _$$ProfitLossDailyDataDtoImplCopyWith( + _$ProfitLossDailyDataDtoImpl value, + $Res Function(_$ProfitLossDailyDataDtoImpl) then, + ) = __$$ProfitLossDailyDataDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'date') String? date, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'gross_profit') int? grossProfit, + @JsonKey(name: 'gross_profit_margin') double? grossProfitMargin, + @JsonKey(name: 'tax') int? tax, + @JsonKey(name: 'discount') int? discount, + @JsonKey(name: 'net_profit') int? netProfit, + @JsonKey(name: 'net_profit_margin') double? netProfitMargin, + @JsonKey(name: 'orders') int? orders, + }); +} + +/// @nodoc +class __$$ProfitLossDailyDataDtoImplCopyWithImpl<$Res> + extends + _$ProfitLossDailyDataDtoCopyWithImpl<$Res, _$ProfitLossDailyDataDtoImpl> + implements _$$ProfitLossDailyDataDtoImplCopyWith<$Res> { + __$$ProfitLossDailyDataDtoImplCopyWithImpl( + _$ProfitLossDailyDataDtoImpl _value, + $Res Function(_$ProfitLossDailyDataDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossDailyDataDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = freezed, + Object? revenue = freezed, + Object? cost = freezed, + Object? grossProfit = freezed, + Object? grossProfitMargin = freezed, + Object? tax = freezed, + Object? discount = freezed, + Object? netProfit = freezed, + Object? netProfitMargin = freezed, + Object? orders = freezed, + }) { + return _then( + _$ProfitLossDailyDataDtoImpl( + date: freezed == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as String?, + revenue: freezed == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int?, + cost: freezed == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int?, + grossProfit: freezed == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int?, + grossProfitMargin: freezed == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + tax: freezed == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as int?, + discount: freezed == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as int?, + netProfit: freezed == netProfit + ? _value.netProfit + : netProfit // ignore: cast_nullable_to_non_nullable + as int?, + netProfitMargin: freezed == netProfitMargin + ? _value.netProfitMargin + : netProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + orders: freezed == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as int?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$ProfitLossDailyDataDtoImpl extends _ProfitLossDailyDataDto { + const _$ProfitLossDailyDataDtoImpl({ + @JsonKey(name: 'date') this.date, + @JsonKey(name: 'revenue') this.revenue, + @JsonKey(name: 'cost') this.cost, + @JsonKey(name: 'gross_profit') this.grossProfit, + @JsonKey(name: 'gross_profit_margin') this.grossProfitMargin, + @JsonKey(name: 'tax') this.tax, + @JsonKey(name: 'discount') this.discount, + @JsonKey(name: 'net_profit') this.netProfit, + @JsonKey(name: 'net_profit_margin') this.netProfitMargin, + @JsonKey(name: 'orders') this.orders, + }) : super._(); + + factory _$ProfitLossDailyDataDtoImpl.fromJson(Map json) => + _$$ProfitLossDailyDataDtoImplFromJson(json); + + @override + @JsonKey(name: 'date') + final String? date; + @override + @JsonKey(name: 'revenue') + final int? revenue; + @override + @JsonKey(name: 'cost') + final int? cost; + @override + @JsonKey(name: 'gross_profit') + final int? grossProfit; + @override + @JsonKey(name: 'gross_profit_margin') + final double? grossProfitMargin; + @override + @JsonKey(name: 'tax') + final int? tax; + @override + @JsonKey(name: 'discount') + final int? discount; + @override + @JsonKey(name: 'net_profit') + final int? netProfit; + @override + @JsonKey(name: 'net_profit_margin') + final double? netProfitMargin; + @override + @JsonKey(name: 'orders') + final int? orders; + + @override + String toString() { + return 'ProfitLossDailyDataDto(date: $date, revenue: $revenue, cost: $cost, grossProfit: $grossProfit, grossProfitMargin: $grossProfitMargin, tax: $tax, discount: $discount, netProfit: $netProfit, netProfitMargin: $netProfitMargin, orders: $orders)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProfitLossDailyDataDtoImpl && + (identical(other.date, date) || other.date == date) && + (identical(other.revenue, revenue) || other.revenue == revenue) && + (identical(other.cost, cost) || other.cost == cost) && + (identical(other.grossProfit, grossProfit) || + other.grossProfit == grossProfit) && + (identical(other.grossProfitMargin, grossProfitMargin) || + other.grossProfitMargin == grossProfitMargin) && + (identical(other.tax, tax) || other.tax == tax) && + (identical(other.discount, discount) || + other.discount == discount) && + (identical(other.netProfit, netProfit) || + other.netProfit == netProfit) && + (identical(other.netProfitMargin, netProfitMargin) || + other.netProfitMargin == netProfitMargin) && + (identical(other.orders, orders) || other.orders == orders)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + date, + revenue, + cost, + grossProfit, + grossProfitMargin, + tax, + discount, + netProfit, + netProfitMargin, + orders, + ); + + /// Create a copy of ProfitLossDailyDataDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProfitLossDailyDataDtoImplCopyWith<_$ProfitLossDailyDataDtoImpl> + get copyWith => + __$$ProfitLossDailyDataDtoImplCopyWithImpl<_$ProfitLossDailyDataDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$ProfitLossDailyDataDtoImplToJson(this); + } +} + +abstract class _ProfitLossDailyDataDto extends ProfitLossDailyDataDto { + const factory _ProfitLossDailyDataDto({ + @JsonKey(name: 'date') final String? date, + @JsonKey(name: 'revenue') final int? revenue, + @JsonKey(name: 'cost') final int? cost, + @JsonKey(name: 'gross_profit') final int? grossProfit, + @JsonKey(name: 'gross_profit_margin') final double? grossProfitMargin, + @JsonKey(name: 'tax') final int? tax, + @JsonKey(name: 'discount') final int? discount, + @JsonKey(name: 'net_profit') final int? netProfit, + @JsonKey(name: 'net_profit_margin') final double? netProfitMargin, + @JsonKey(name: 'orders') final int? orders, + }) = _$ProfitLossDailyDataDtoImpl; + const _ProfitLossDailyDataDto._() : super._(); + + factory _ProfitLossDailyDataDto.fromJson(Map json) = + _$ProfitLossDailyDataDtoImpl.fromJson; + + @override + @JsonKey(name: 'date') + String? get date; + @override + @JsonKey(name: 'revenue') + int? get revenue; + @override + @JsonKey(name: 'cost') + int? get cost; + @override + @JsonKey(name: 'gross_profit') + int? get grossProfit; + @override + @JsonKey(name: 'gross_profit_margin') + double? get grossProfitMargin; + @override + @JsonKey(name: 'tax') + int? get tax; + @override + @JsonKey(name: 'discount') + int? get discount; + @override + @JsonKey(name: 'net_profit') + int? get netProfit; + @override + @JsonKey(name: 'net_profit_margin') + double? get netProfitMargin; + @override + @JsonKey(name: 'orders') + int? get orders; + + /// Create a copy of ProfitLossDailyDataDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProfitLossDailyDataDtoImplCopyWith<_$ProfitLossDailyDataDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +ProfitLossProductDataDto _$ProfitLossProductDataDtoFromJson( + Map json, +) { + return _ProfitLossProductDataDto.fromJson(json); +} + +/// @nodoc +mixin _$ProfitLossProductDataDto { + @JsonKey(name: 'product_id') + String? get productId => throw _privateConstructorUsedError; + @JsonKey(name: 'product_name') + String? get productName => throw _privateConstructorUsedError; + @JsonKey(name: 'category_id') + String? get categoryId => throw _privateConstructorUsedError; + @JsonKey(name: 'category_name') + String? get categoryName => throw _privateConstructorUsedError; + @JsonKey(name: 'quantity_sold') + int? get quantitySold => throw _privateConstructorUsedError; + @JsonKey(name: 'revenue') + int? get revenue => throw _privateConstructorUsedError; + @JsonKey(name: 'cost') + int? get cost => throw _privateConstructorUsedError; + @JsonKey(name: 'gross_profit') + int? get grossProfit => throw _privateConstructorUsedError; + @JsonKey(name: 'gross_profit_margin') + double? get grossProfitMargin => throw _privateConstructorUsedError; + @JsonKey(name: 'average_price') + int? get averagePrice => throw _privateConstructorUsedError; + @JsonKey(name: 'average_cost') + int? get averageCost => throw _privateConstructorUsedError; + @JsonKey(name: 'profit_per_unit') + int? get profitPerUnit => throw _privateConstructorUsedError; + + /// Serializes this ProfitLossProductDataDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ProfitLossProductDataDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProfitLossProductDataDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossProductDataDtoCopyWith<$Res> { + factory $ProfitLossProductDataDtoCopyWith( + ProfitLossProductDataDto value, + $Res Function(ProfitLossProductDataDto) then, + ) = _$ProfitLossProductDataDtoCopyWithImpl<$Res, ProfitLossProductDataDto>; + @useResult + $Res call({ + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'product_name') String? productName, + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'category_name') String? categoryName, + @JsonKey(name: 'quantity_sold') int? quantitySold, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'gross_profit') int? grossProfit, + @JsonKey(name: 'gross_profit_margin') double? grossProfitMargin, + @JsonKey(name: 'average_price') int? averagePrice, + @JsonKey(name: 'average_cost') int? averageCost, + @JsonKey(name: 'profit_per_unit') int? profitPerUnit, + }); +} + +/// @nodoc +class _$ProfitLossProductDataDtoCopyWithImpl< + $Res, + $Val extends ProfitLossProductDataDto +> + implements $ProfitLossProductDataDtoCopyWith<$Res> { + _$ProfitLossProductDataDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossProductDataDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = freezed, + Object? productName = freezed, + Object? categoryId = freezed, + Object? categoryName = freezed, + Object? quantitySold = freezed, + Object? revenue = freezed, + Object? cost = freezed, + Object? grossProfit = freezed, + Object? grossProfitMargin = freezed, + Object? averagePrice = freezed, + Object? averageCost = freezed, + Object? profitPerUnit = freezed, + }) { + return _then( + _value.copyWith( + productId: freezed == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String?, + productName: freezed == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String?, + 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?, + quantitySold: freezed == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int?, + revenue: freezed == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int?, + cost: freezed == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int?, + grossProfit: freezed == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int?, + grossProfitMargin: freezed == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + averagePrice: freezed == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as int?, + averageCost: freezed == averageCost + ? _value.averageCost + : averageCost // ignore: cast_nullable_to_non_nullable + as int?, + profitPerUnit: freezed == profitPerUnit + ? _value.profitPerUnit + : profitPerUnit // ignore: cast_nullable_to_non_nullable + as int?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProfitLossProductDataDtoImplCopyWith<$Res> + implements $ProfitLossProductDataDtoCopyWith<$Res> { + factory _$$ProfitLossProductDataDtoImplCopyWith( + _$ProfitLossProductDataDtoImpl value, + $Res Function(_$ProfitLossProductDataDtoImpl) then, + ) = __$$ProfitLossProductDataDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'product_name') String? productName, + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'category_name') String? categoryName, + @JsonKey(name: 'quantity_sold') int? quantitySold, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'gross_profit') int? grossProfit, + @JsonKey(name: 'gross_profit_margin') double? grossProfitMargin, + @JsonKey(name: 'average_price') int? averagePrice, + @JsonKey(name: 'average_cost') int? averageCost, + @JsonKey(name: 'profit_per_unit') int? profitPerUnit, + }); +} + +/// @nodoc +class __$$ProfitLossProductDataDtoImplCopyWithImpl<$Res> + extends + _$ProfitLossProductDataDtoCopyWithImpl< + $Res, + _$ProfitLossProductDataDtoImpl + > + implements _$$ProfitLossProductDataDtoImplCopyWith<$Res> { + __$$ProfitLossProductDataDtoImplCopyWithImpl( + _$ProfitLossProductDataDtoImpl _value, + $Res Function(_$ProfitLossProductDataDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossProductDataDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = freezed, + Object? productName = freezed, + Object? categoryId = freezed, + Object? categoryName = freezed, + Object? quantitySold = freezed, + Object? revenue = freezed, + Object? cost = freezed, + Object? grossProfit = freezed, + Object? grossProfitMargin = freezed, + Object? averagePrice = freezed, + Object? averageCost = freezed, + Object? profitPerUnit = freezed, + }) { + return _then( + _$ProfitLossProductDataDtoImpl( + productId: freezed == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String?, + productName: freezed == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String?, + 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?, + quantitySold: freezed == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int?, + revenue: freezed == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int?, + cost: freezed == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int?, + grossProfit: freezed == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int?, + grossProfitMargin: freezed == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + averagePrice: freezed == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as int?, + averageCost: freezed == averageCost + ? _value.averageCost + : averageCost // ignore: cast_nullable_to_non_nullable + as int?, + profitPerUnit: freezed == profitPerUnit + ? _value.profitPerUnit + : profitPerUnit // ignore: cast_nullable_to_non_nullable + as int?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$ProfitLossProductDataDtoImpl extends _ProfitLossProductDataDto { + const _$ProfitLossProductDataDtoImpl({ + @JsonKey(name: 'product_id') this.productId, + @JsonKey(name: 'product_name') this.productName, + @JsonKey(name: 'category_id') this.categoryId, + @JsonKey(name: 'category_name') this.categoryName, + @JsonKey(name: 'quantity_sold') this.quantitySold, + @JsonKey(name: 'revenue') this.revenue, + @JsonKey(name: 'cost') this.cost, + @JsonKey(name: 'gross_profit') this.grossProfit, + @JsonKey(name: 'gross_profit_margin') this.grossProfitMargin, + @JsonKey(name: 'average_price') this.averagePrice, + @JsonKey(name: 'average_cost') this.averageCost, + @JsonKey(name: 'profit_per_unit') this.profitPerUnit, + }) : super._(); + + factory _$ProfitLossProductDataDtoImpl.fromJson(Map json) => + _$$ProfitLossProductDataDtoImplFromJson(json); + + @override + @JsonKey(name: 'product_id') + final String? productId; + @override + @JsonKey(name: 'product_name') + final String? productName; + @override + @JsonKey(name: 'category_id') + final String? categoryId; + @override + @JsonKey(name: 'category_name') + final String? categoryName; + @override + @JsonKey(name: 'quantity_sold') + final int? quantitySold; + @override + @JsonKey(name: 'revenue') + final int? revenue; + @override + @JsonKey(name: 'cost') + final int? cost; + @override + @JsonKey(name: 'gross_profit') + final int? grossProfit; + @override + @JsonKey(name: 'gross_profit_margin') + final double? grossProfitMargin; + @override + @JsonKey(name: 'average_price') + final int? averagePrice; + @override + @JsonKey(name: 'average_cost') + final int? averageCost; + @override + @JsonKey(name: 'profit_per_unit') + final int? profitPerUnit; + + @override + String toString() { + return 'ProfitLossProductDataDto(productId: $productId, productName: $productName, categoryId: $categoryId, categoryName: $categoryName, quantitySold: $quantitySold, revenue: $revenue, cost: $cost, grossProfit: $grossProfit, grossProfitMargin: $grossProfitMargin, averagePrice: $averagePrice, averageCost: $averageCost, profitPerUnit: $profitPerUnit)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProfitLossProductDataDtoImpl && + (identical(other.productId, productId) || + other.productId == productId) && + (identical(other.productName, productName) || + other.productName == productName) && + (identical(other.categoryId, categoryId) || + other.categoryId == categoryId) && + (identical(other.categoryName, categoryName) || + other.categoryName == categoryName) && + (identical(other.quantitySold, quantitySold) || + other.quantitySold == quantitySold) && + (identical(other.revenue, revenue) || other.revenue == revenue) && + (identical(other.cost, cost) || other.cost == cost) && + (identical(other.grossProfit, grossProfit) || + other.grossProfit == grossProfit) && + (identical(other.grossProfitMargin, grossProfitMargin) || + other.grossProfitMargin == grossProfitMargin) && + (identical(other.averagePrice, averagePrice) || + other.averagePrice == averagePrice) && + (identical(other.averageCost, averageCost) || + other.averageCost == averageCost) && + (identical(other.profitPerUnit, profitPerUnit) || + other.profitPerUnit == profitPerUnit)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + productId, + productName, + categoryId, + categoryName, + quantitySold, + revenue, + cost, + grossProfit, + grossProfitMargin, + averagePrice, + averageCost, + profitPerUnit, + ); + + /// Create a copy of ProfitLossProductDataDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProfitLossProductDataDtoImplCopyWith<_$ProfitLossProductDataDtoImpl> + get copyWith => + __$$ProfitLossProductDataDtoImplCopyWithImpl< + _$ProfitLossProductDataDtoImpl + >(this, _$identity); + + @override + Map toJson() { + return _$$ProfitLossProductDataDtoImplToJson(this); + } +} + +abstract class _ProfitLossProductDataDto extends ProfitLossProductDataDto { + const factory _ProfitLossProductDataDto({ + @JsonKey(name: 'product_id') final String? productId, + @JsonKey(name: 'product_name') final String? productName, + @JsonKey(name: 'category_id') final String? categoryId, + @JsonKey(name: 'category_name') final String? categoryName, + @JsonKey(name: 'quantity_sold') final int? quantitySold, + @JsonKey(name: 'revenue') final int? revenue, + @JsonKey(name: 'cost') final int? cost, + @JsonKey(name: 'gross_profit') final int? grossProfit, + @JsonKey(name: 'gross_profit_margin') final double? grossProfitMargin, + @JsonKey(name: 'average_price') final int? averagePrice, + @JsonKey(name: 'average_cost') final int? averageCost, + @JsonKey(name: 'profit_per_unit') final int? profitPerUnit, + }) = _$ProfitLossProductDataDtoImpl; + const _ProfitLossProductDataDto._() : super._(); + + factory _ProfitLossProductDataDto.fromJson(Map json) = + _$ProfitLossProductDataDtoImpl.fromJson; + + @override + @JsonKey(name: 'product_id') + String? get productId; + @override + @JsonKey(name: 'product_name') + String? get productName; + @override + @JsonKey(name: 'category_id') + String? get categoryId; + @override + @JsonKey(name: 'category_name') + String? get categoryName; + @override + @JsonKey(name: 'quantity_sold') + int? get quantitySold; + @override + @JsonKey(name: 'revenue') + int? get revenue; + @override + @JsonKey(name: 'cost') + int? get cost; + @override + @JsonKey(name: 'gross_profit') + int? get grossProfit; + @override + @JsonKey(name: 'gross_profit_margin') + double? get grossProfitMargin; + @override + @JsonKey(name: 'average_price') + int? get averagePrice; + @override + @JsonKey(name: 'average_cost') + int? get averageCost; + @override + @JsonKey(name: 'profit_per_unit') + int? get profitPerUnit; + + /// Create a copy of ProfitLossProductDataDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProfitLossProductDataDtoImplCopyWith<_$ProfitLossProductDataDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/infrastructure/analytic/analytic_dtos.g.dart b/lib/infrastructure/analytic/analytic_dtos.g.dart index ebd7a0a..2ffcf80 100644 --- a/lib/infrastructure/analytic/analytic_dtos.g.dart +++ b/lib/infrastructure/analytic/analytic_dtos.g.dart @@ -87,3 +87,129 @@ Map _$$SalesAnalyticDataDtoImplToJson( 'discount': instance.discount, 'net_sales': instance.netSales, }; + +_$ProfitLossAnalyticDtoImpl _$$ProfitLossAnalyticDtoImplFromJson( + Map json, +) => _$ProfitLossAnalyticDtoImpl( + organizationId: json['organization_id'] as String?, + dateFrom: json['date_from'] as String?, + dateTo: json['date_to'] as String?, + groupBy: json['group_by'] as String?, + summary: json['summary'] == null + ? null + : ProfitLossSummaryDto.fromJson(json['summary'] as Map), + data: (json['data'] as List?) + ?.map((e) => ProfitLossDailyDataDto.fromJson(e as Map)) + .toList(), + productData: (json['product_data'] as List?) + ?.map((e) => ProfitLossProductDataDto.fromJson(e as Map)) + .toList(), +); + +Map _$$ProfitLossAnalyticDtoImplToJson( + _$ProfitLossAnalyticDtoImpl instance, +) => { + 'organization_id': instance.organizationId, + 'date_from': instance.dateFrom, + 'date_to': instance.dateTo, + 'group_by': instance.groupBy, + 'summary': instance.summary, + 'data': instance.data, + 'product_data': instance.productData, +}; + +_$ProfitLossSummaryDtoImpl _$$ProfitLossSummaryDtoImplFromJson( + Map json, +) => _$ProfitLossSummaryDtoImpl( + totalRevenue: (json['total_revenue'] as num?)?.toInt(), + totalCost: (json['total_cost'] as num?)?.toInt(), + grossProfit: (json['gross_profit'] as num?)?.toInt(), + grossProfitMargin: (json['gross_profit_margin'] as num?)?.toDouble(), + totalTax: (json['total_tax'] as num?)?.toInt(), + totalDiscount: (json['total_discount'] as num?)?.toInt(), + netProfit: (json['net_profit'] as num?)?.toInt(), + netProfitMargin: (json['net_profit_margin'] as num?)?.toDouble(), + totalOrders: (json['total_orders'] as num?)?.toInt(), + averageProfit: (json['average_profit'] as num?)?.toDouble(), + profitabilityRatio: (json['profitability_ratio'] as num?)?.toDouble(), +); + +Map _$$ProfitLossSummaryDtoImplToJson( + _$ProfitLossSummaryDtoImpl instance, +) => { + 'total_revenue': instance.totalRevenue, + 'total_cost': instance.totalCost, + 'gross_profit': instance.grossProfit, + 'gross_profit_margin': instance.grossProfitMargin, + 'total_tax': instance.totalTax, + 'total_discount': instance.totalDiscount, + 'net_profit': instance.netProfit, + 'net_profit_margin': instance.netProfitMargin, + 'total_orders': instance.totalOrders, + 'average_profit': instance.averageProfit, + 'profitability_ratio': instance.profitabilityRatio, +}; + +_$ProfitLossDailyDataDtoImpl _$$ProfitLossDailyDataDtoImplFromJson( + Map json, +) => _$ProfitLossDailyDataDtoImpl( + date: json['date'] as String?, + revenue: (json['revenue'] as num?)?.toInt(), + cost: (json['cost'] as num?)?.toInt(), + grossProfit: (json['gross_profit'] as num?)?.toInt(), + grossProfitMargin: (json['gross_profit_margin'] as num?)?.toDouble(), + tax: (json['tax'] as num?)?.toInt(), + discount: (json['discount'] as num?)?.toInt(), + netProfit: (json['net_profit'] as num?)?.toInt(), + netProfitMargin: (json['net_profit_margin'] as num?)?.toDouble(), + orders: (json['orders'] as num?)?.toInt(), +); + +Map _$$ProfitLossDailyDataDtoImplToJson( + _$ProfitLossDailyDataDtoImpl instance, +) => { + 'date': instance.date, + 'revenue': instance.revenue, + 'cost': instance.cost, + 'gross_profit': instance.grossProfit, + 'gross_profit_margin': instance.grossProfitMargin, + 'tax': instance.tax, + 'discount': instance.discount, + 'net_profit': instance.netProfit, + 'net_profit_margin': instance.netProfitMargin, + 'orders': instance.orders, +}; + +_$ProfitLossProductDataDtoImpl _$$ProfitLossProductDataDtoImplFromJson( + Map json, +) => _$ProfitLossProductDataDtoImpl( + productId: json['product_id'] as String?, + productName: json['product_name'] as String?, + categoryId: json['category_id'] as String?, + categoryName: json['category_name'] as String?, + quantitySold: (json['quantity_sold'] as num?)?.toInt(), + revenue: (json['revenue'] as num?)?.toInt(), + cost: (json['cost'] as num?)?.toInt(), + grossProfit: (json['gross_profit'] as num?)?.toInt(), + grossProfitMargin: (json['gross_profit_margin'] as num?)?.toDouble(), + averagePrice: (json['average_price'] as num?)?.toInt(), + averageCost: (json['average_cost'] as num?)?.toInt(), + profitPerUnit: (json['profit_per_unit'] as num?)?.toInt(), +); + +Map _$$ProfitLossProductDataDtoImplToJson( + _$ProfitLossProductDataDtoImpl instance, +) => { + 'product_id': instance.productId, + 'product_name': instance.productName, + 'category_id': instance.categoryId, + 'category_name': instance.categoryName, + 'quantity_sold': instance.quantitySold, + 'revenue': instance.revenue, + 'cost': instance.cost, + 'gross_profit': instance.grossProfit, + 'gross_profit_margin': instance.grossProfitMargin, + 'average_price': instance.averagePrice, + 'average_cost': instance.averageCost, + 'profit_per_unit': instance.profitPerUnit, +}; diff --git a/lib/infrastructure/analytic/datasource/remote_data_provider.dart b/lib/infrastructure/analytic/datasource/remote_data_provider.dart index 4c55fa4..91c1d26 100644 --- a/lib/infrastructure/analytic/datasource/remote_data_provider.dart +++ b/lib/infrastructure/analytic/datasource/remote_data_provider.dart @@ -44,4 +44,31 @@ class AnalyticRemoteDataProvider { return DC.error(AnalyticFailure.serverError(e)); } } + + Future> fetchProfitLoss({ + required DateTime dateFrom, + required DateTime dateTo, + }) async { + try { + final response = await _apiClient.get( + ApiPath.profitLossAnalytic, + params: { + 'date_from': dateFrom.toServerDate, + 'date_to': dateTo.toServerDate, + }, + headers: getAuthorizationHeader(), + ); + + if (response.data['data'] == null) { + return DC.error(AnalyticFailure.empty()); + } + + final dto = ProfitLossAnalyticDto.fromJson(response.data['data']); + + return DC.data(dto); + } on ApiFailure catch (e, s) { + log('fetchProfitLossError', name: _logName, error: e, stackTrace: s); + return DC.error(AnalyticFailure.serverError(e)); + } + } } diff --git a/lib/infrastructure/analytic/dto/profit_loss_analytic_dto.dart b/lib/infrastructure/analytic/dto/profit_loss_analytic_dto.dart new file mode 100644 index 0000000..2741495 --- /dev/null +++ b/lib/infrastructure/analytic/dto/profit_loss_analytic_dto.dart @@ -0,0 +1,137 @@ +part of '../analytic_dtos.dart'; + +@freezed +class ProfitLossAnalyticDto with _$ProfitLossAnalyticDto { + const ProfitLossAnalyticDto._(); + + const factory ProfitLossAnalyticDto({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'group_by') String? groupBy, + @JsonKey(name: 'summary') ProfitLossSummaryDto? summary, + @JsonKey(name: 'data') List? data, + @JsonKey(name: 'product_data') List? productData, + }) = _ProfitLossAnalyticDto; + + factory ProfitLossAnalyticDto.fromJson(Map json) => + _$ProfitLossAnalyticDtoFromJson(json); + + ProfitLossAnalytic toDomain() => ProfitLossAnalytic( + organizationId: organizationId ?? '', + dateFrom: dateFrom ?? '', + dateTo: dateTo ?? '', + groupBy: groupBy ?? '', + summary: summary?.toDomain() ?? ProfitLossSummary.empty(), + data: (data ?? []).map((e) => e.toDomain()).toList(), + productData: (productData ?? []).map((e) => e.toDomain()).toList(), + ); +} + +@freezed +class ProfitLossSummaryDto with _$ProfitLossSummaryDto { + const ProfitLossSummaryDto._(); + + const factory ProfitLossSummaryDto({ + @JsonKey(name: 'total_revenue') int? totalRevenue, + @JsonKey(name: 'total_cost') int? totalCost, + @JsonKey(name: 'gross_profit') int? grossProfit, + @JsonKey(name: 'gross_profit_margin') double? grossProfitMargin, + @JsonKey(name: 'total_tax') int? totalTax, + @JsonKey(name: 'total_discount') int? totalDiscount, + @JsonKey(name: 'net_profit') int? netProfit, + @JsonKey(name: 'net_profit_margin') double? netProfitMargin, + @JsonKey(name: 'total_orders') int? totalOrders, + @JsonKey(name: 'average_profit') double? averageProfit, + @JsonKey(name: 'profitability_ratio') double? profitabilityRatio, + }) = _ProfitLossSummaryDto; + + factory ProfitLossSummaryDto.fromJson(Map json) => + _$ProfitLossSummaryDtoFromJson(json); + + ProfitLossSummary toDomain() => ProfitLossSummary( + totalRevenue: totalRevenue ?? 0, + totalCost: totalCost ?? 0, + grossProfit: grossProfit ?? 0, + grossProfitMargin: grossProfitMargin ?? 0.0, + totalTax: totalTax ?? 0, + totalDiscount: totalDiscount ?? 0, + netProfit: netProfit ?? 0, + netProfitMargin: netProfitMargin ?? 0.0, + totalOrders: totalOrders ?? 0, + averageProfit: averageProfit ?? 0.0, + profitabilityRatio: profitabilityRatio ?? 0.0, + ); +} + +@freezed +class ProfitLossDailyDataDto with _$ProfitLossDailyDataDto { + const ProfitLossDailyDataDto._(); + + const factory ProfitLossDailyDataDto({ + @JsonKey(name: 'date') String? date, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'gross_profit') int? grossProfit, + @JsonKey(name: 'gross_profit_margin') double? grossProfitMargin, + @JsonKey(name: 'tax') int? tax, + @JsonKey(name: 'discount') int? discount, + @JsonKey(name: 'net_profit') int? netProfit, + @JsonKey(name: 'net_profit_margin') double? netProfitMargin, + @JsonKey(name: 'orders') int? orders, + }) = _ProfitLossDailyDataDto; + + factory ProfitLossDailyDataDto.fromJson(Map json) => + _$ProfitLossDailyDataDtoFromJson(json); + + ProfitLossDailyData toDomain() => ProfitLossDailyData( + date: date ?? '', + revenue: revenue ?? 0, + cost: cost ?? 0, + grossProfit: grossProfit ?? 0, + grossProfitMargin: grossProfitMargin ?? 0.0, + tax: tax ?? 0, + discount: discount ?? 0, + netProfit: netProfit ?? 0, + netProfitMargin: netProfitMargin ?? 0.0, + orders: orders ?? 0, + ); +} + +@freezed +class ProfitLossProductDataDto with _$ProfitLossProductDataDto { + const ProfitLossProductDataDto._(); + + const factory ProfitLossProductDataDto({ + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'product_name') String? productName, + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'category_name') String? categoryName, + @JsonKey(name: 'quantity_sold') int? quantitySold, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'gross_profit') int? grossProfit, + @JsonKey(name: 'gross_profit_margin') double? grossProfitMargin, + @JsonKey(name: 'average_price') int? averagePrice, + @JsonKey(name: 'average_cost') int? averageCost, + @JsonKey(name: 'profit_per_unit') int? profitPerUnit, + }) = _ProfitLossProductDataDto; + + factory ProfitLossProductDataDto.fromJson(Map json) => + _$ProfitLossProductDataDtoFromJson(json); + + ProfitLossProductData toDomain() => ProfitLossProductData( + productId: productId ?? '', + productName: productName ?? '', + categoryId: categoryId ?? '', + categoryName: categoryName ?? '', + quantitySold: quantitySold ?? 0, + revenue: revenue ?? 0, + cost: cost ?? 0, + grossProfit: grossProfit ?? 0, + grossProfitMargin: grossProfitMargin ?? 0.0, + averagePrice: averagePrice ?? 0, + averageCost: averageCost ?? 0, + profitPerUnit: profitPerUnit ?? 0, + ); +} diff --git a/lib/infrastructure/analytic/repositories/analytic_repository.dart b/lib/infrastructure/analytic/repositories/analytic_repository.dart index a615956..5cd3412 100644 --- a/lib/infrastructure/analytic/repositories/analytic_repository.dart +++ b/lib/infrastructure/analytic/repositories/analytic_repository.dart @@ -37,4 +37,28 @@ class AnalyticRepository implements IAnalyticRepository { return left(const AnalyticFailure.unexpectedError()); } } + + @override + Future> getProfitLoss({ + required DateTime dateFrom, + required DateTime dateTo, + }) async { + try { + final result = await _dataProvider.fetchProfitLoss( + dateFrom: dateFrom, + dateTo: dateTo, + ); + + if (result.hasError) { + return left(result.error!); + } + + final auth = result.data!.toDomain(); + + return right(auth); + } catch (e, s) { + log('getProfitLossError', name: _logName, error: e, stackTrace: s); + return left(const AnalyticFailure.unexpectedError()); + } + } } diff --git a/lib/injection.config.dart b/lib/injection.config.dart index c80fd33..aec6edc 100644 --- a/lib/injection.config.dart +++ b/lib/injection.config.dart @@ -20,6 +20,8 @@ import 'package:apskel_owner_flutter/application/language/language_bloc.dart' as _i455; import 'package:apskel_owner_flutter/application/product/product_loader/product_loader_bloc.dart' as _i458; +import 'package:apskel_owner_flutter/application/profit_loss/profit_loss_loader/profit_loss_loader_bloc.dart' + as _i608; import 'package:apskel_owner_flutter/application/sales/sales_loader/sales_loader_bloc.dart' as _i882; import 'package:apskel_owner_flutter/common/api/api_client.dart' as _i115; @@ -104,18 +106,18 @@ extension GetItInjectableX on _i174.GetIt { () => _i115.ApiClient(gh<_i361.Dio>(), gh<_i6.Env>()), ); gh.factory<_i6.Env>(() => _i6.ProdEnv(), registerFor: {_prod}); - gh.factory<_i17.AuthRemoteDataProvider>( - () => _i17.AuthRemoteDataProvider(gh<_i115.ApiClient>()), - ); - gh.factory<_i866.AnalyticRemoteDataProvider>( - () => _i866.AnalyticRemoteDataProvider(gh<_i115.ApiClient>()), - ); gh.factory<_i333.CategoryRemoteDataProvider>( () => _i333.CategoryRemoteDataProvider(gh<_i115.ApiClient>()), ); + gh.factory<_i17.AuthRemoteDataProvider>( + () => _i17.AuthRemoteDataProvider(gh<_i115.ApiClient>()), + ); gh.factory<_i823.ProductRemoteDataProvider>( () => _i823.ProductRemoteDataProvider(gh<_i115.ApiClient>()), ); + gh.factory<_i866.AnalyticRemoteDataProvider>( + () => _i866.AnalyticRemoteDataProvider(gh<_i115.ApiClient>()), + ); gh.factory<_i477.IAnalyticRepository>( () => _i393.AnalyticRepository(gh<_i866.AnalyticRemoteDataProvider>()), ); @@ -134,6 +136,9 @@ extension GetItInjectableX on _i174.GetIt { gh.factory<_i458.ProductLoaderBloc>( () => _i458.ProductLoaderBloc(gh<_i419.IProductRepository>()), ); + gh.factory<_i608.ProfitLossLoaderBloc>( + () => _i608.ProfitLossLoaderBloc(gh<_i477.IAnalyticRepository>()), + ); gh.factory<_i183.CategoryLoaderBloc>( () => _i183.CategoryLoaderBloc(gh<_i1020.ICategoryRepository>()), ); diff --git a/lib/presentation/pages/finance/finance_page.dart b/lib/presentation/pages/finance/finance_page.dart index b38a86d..e77e0a7 100644 --- a/lib/presentation/pages/finance/finance_page.dart +++ b/lib/presentation/pages/finance/finance_page.dart @@ -1,20 +1,33 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:line_icons/line_icons.dart'; +import '../../../application/profit_loss/profit_loss_loader/profit_loss_loader_bloc.dart'; +import '../../../common/extension/extension.dart'; import '../../../common/theme/theme.dart'; +import '../../../domain/analytic/analytic.dart'; +import '../../../injection.dart'; import '../../components/appbar/appbar.dart'; import 'widgets/cash_flow.dart'; import 'widgets/category.dart'; +import 'widgets/product.dart'; import 'widgets/profit_loss.dart'; import 'widgets/summary_card.dart'; @RoutePage() -class FinancePage extends StatefulWidget { +class FinancePage extends StatefulWidget implements AutoRouteWrapper { const FinancePage({super.key}); @override State createState() => _FinancePageState(); + + @override + Widget wrappedRoute(BuildContext context) => BlocProvider( + create: (_) => + getIt()..add(ProfitLossLoaderEvent.fetched()), + child: this, + ); } class _FinancePageState extends State @@ -90,69 +103,74 @@ class _FinancePageState extends State Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColor.background, - body: CustomScrollView( - slivers: [ - // SliverAppBar with animated background - SliverAppBar( - expandedHeight: 120, - floating: false, - pinned: true, - backgroundColor: AppColor.primary, - elevation: 0, - flexibleSpace: CustomAppBar(title: 'Keuangan'), - ), + body: BlocBuilder( + builder: (context, state) { + return CustomScrollView( + slivers: [ + // SliverAppBar with animated background + SliverAppBar( + expandedHeight: 120, + floating: false, + pinned: true, + backgroundColor: AppColor.primary, + elevation: 0, + flexibleSpace: CustomAppBar(title: 'Keuangan'), + ), - // Header dengan filter periode - SliverToBoxAdapter( - child: FadeTransition( - opacity: _fadeAnimation, - child: _buildPeriodSelector(), - ), - ), + // Header dengan filter periode + SliverToBoxAdapter( + child: FadeTransition( + opacity: _fadeAnimation, + child: _buildPeriodSelector(), + ), + ), - // Summary Cards - SliverToBoxAdapter( - child: SlideTransition( - position: _slideAnimation, - child: _buildSummaryCards(), - ), - ), + // Summary Cards + SliverToBoxAdapter( + child: SlideTransition( + position: _slideAnimation, + child: _buildSummaryCards(state.profitLoss.summary), + ), + ), - // Cash Flow Analysis - SliverToBoxAdapter( - child: ScaleTransition( - scale: _scaleAnimation, - child: FinanceCashFlow(), - ), - ), + // Cash Flow Analysis + SliverToBoxAdapter( + child: ScaleTransition( + scale: _scaleAnimation, + child: FinanceCashFlow(dailyData: state.profitLoss.data), + ), + ), - // Profit Loss Detail - SliverToBoxAdapter( - child: FadeTransition( - opacity: _fadeAnimation, - child: FinanceProfitLoss(), - ), - ), + // Profit Loss Detail + SliverToBoxAdapter( + child: FadeTransition( + opacity: _fadeAnimation, + child: FinanceProfitLoss(data: state.profitLoss.summary), + ), + ), - // Transaction Categories - SliverToBoxAdapter( - child: SlideTransition( - position: _slideAnimation, - child: FinanceCategory(), - ), - ), + SliverToBoxAdapter( + child: SlideTransition( + position: _slideAnimation, + child: FinanceCategory(), + ), + ), - // Monthly Comparison - SliverToBoxAdapter( - child: ScaleTransition( - scale: _scaleAnimation, - child: _buildMonthlyComparison(), - ), - ), + // Product Analysis Section + SliverToBoxAdapter( + child: SlideTransition( + position: _slideAnimation, + child: _buildProductAnalysis(state.profitLoss.productData), + ), + ), - // Bottom spacing - const SliverToBoxAdapter(child: SizedBox(height: 100)), - ], + // Transaction Categories + + // Bottom spacing + const SliverToBoxAdapter(child: SizedBox(height: 100)), + ], + ); + }, ), ); } @@ -210,7 +228,7 @@ class _FinancePageState extends State ); } - Widget _buildSummaryCards() { + Widget _buildSummaryCards(ProfitLossSummary summary) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( @@ -220,10 +238,9 @@ class _FinancePageState extends State Expanded( child: FinanceSummaryCard( title: 'Total Pendapatan', - amount: 'Rp 25.840.000', + amount: summary.totalRevenue.currencyFormatRp, icon: LineIcons.arrowUp, color: AppColor.success, - change: '+12.5%', isPositive: true, ), ), @@ -231,10 +248,9 @@ class _FinancePageState extends State Expanded( child: FinanceSummaryCard( title: 'Total Pengeluaran', - amount: 'Rp 18.320.000', + amount: summary.totalCost.currencyFormatRp, icon: LineIcons.arrowDown, color: AppColor.error, - change: '+8.2%', isPositive: false, ), ), @@ -246,10 +262,9 @@ class _FinancePageState extends State Expanded( child: FinanceSummaryCard( title: 'Keuntungan Bersih', - amount: 'Rp 7.520.000', + amount: summary.netProfit.currencyFormatRp, icon: LineIcons.lineChart, color: AppColor.info, - change: '+15.3%', isPositive: true, ), ), @@ -257,10 +272,9 @@ class _FinancePageState extends State Expanded( child: FinanceSummaryCard( title: 'Margin Profit', - amount: '29.1%', + amount: '${summary.profitabilityRatio.round()}%', icon: LineIcons.percent, color: AppColor.warning, - change: '+2.1%', isPositive: true, ), ), @@ -271,7 +285,7 @@ class _FinancePageState extends State ); } - Widget _buildMonthlyComparison() { + Widget _buildProductAnalysis(List products) { return Container( margin: const EdgeInsets.all(16), padding: const EdgeInsets.all(20), @@ -295,138 +309,41 @@ class _FinancePageState extends State Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: AppColor.warning.withOpacity(0.1), + color: AppColor.info.withOpacity(0.1), borderRadius: BorderRadius.circular(8), ), child: const Icon( - LineIcons.calendarCheck, - color: AppColor.warning, + LineIcons.shoppingBag, + color: AppColor.info, size: 20, ), ), const SizedBox(width: 12), Text( - 'Perbandingan Bulanan', + 'Analisis Produk', style: AppStyle.lg.copyWith(fontWeight: FontWeight.bold), ), - ], - ), - const SizedBox(height: 20), - - Row( - children: [ - Expanded( - child: _buildComparisonCard( - 'Bulan Ini', - 'Rp 7.52M', - '+15.3%', - true, - AppColor.primary, - ), - ), - const SizedBox(width: 12), - Expanded( - child: _buildComparisonCard( - 'Bulan Lalu', - 'Rp 6.53M', - '-2.1%', - false, - AppColor.textSecondary, + const Spacer(), + TextButton( + onPressed: () {}, + child: Text( + 'Lihat Semua', + style: AppStyle.sm.copyWith(color: AppColor.primary), ), ), ], ), - const SizedBox(height: 16), - - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: AppColor.success.withOpacity(0.05), - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColor.success.withOpacity(0.2)), - ), - child: Row( - children: [ - const Icon( - LineIcons.thumbsUp, - color: AppColor.success, - size: 20, - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Performa Bagus!', - style: AppStyle.md.copyWith( - fontWeight: FontWeight.bold, - color: AppColor.success, - ), - ), - Text( - 'Keuntungan meningkat 15.3% dari bulan lalu', - style: AppStyle.sm.copyWith( - color: AppColor.textSecondary, - ), - ), - ], - ), - ), - ], - ), - ), - ], - ), - ); - } - - Widget _buildComparisonCard( - String period, - String amount, - String change, - bool isPositive, - Color color, - ) { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: color.withOpacity(0.05), - borderRadius: BorderRadius.circular(12), - border: Border.all(color: color.withOpacity(0.2)), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - period, - style: AppStyle.sm.copyWith(color: AppColor.textSecondary), - ), - const SizedBox(height: 8), - Text( - amount, - style: AppStyle.lg.copyWith( - fontWeight: FontWeight.bold, - color: color, - ), - ), - const SizedBox(height: 4), - Row( - children: [ - Icon( - isPositive ? LineIcons.arrowUp : LineIcons.arrowDown, - size: 14, - color: isPositive ? AppColor.success : AppColor.error, - ), - const SizedBox(width: 4), - Text( - change, - style: AppStyle.xs.copyWith( - color: isPositive ? AppColor.success : AppColor.error, - fontWeight: FontWeight.w600, - ), - ), - ], + // Product list + ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: const EdgeInsets.only(top: 12), + itemCount: products.length, + separatorBuilder: (context, index) => const SizedBox(height: 12), + itemBuilder: (context, index) { + final product = products[index]; + return ProfitLossProduct(product: product); + }, ), ], ), diff --git a/lib/presentation/pages/finance/widgets/cash_flow.dart b/lib/presentation/pages/finance/widgets/cash_flow.dart index 5c45492..fa11cbb 100644 --- a/lib/presentation/pages/finance/widgets/cash_flow.dart +++ b/lib/presentation/pages/finance/widgets/cash_flow.dart @@ -1,14 +1,23 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import 'package:line_icons/line_icons.dart'; +import 'package:intl/intl.dart'; import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; class FinanceCashFlow extends StatelessWidget { - const FinanceCashFlow({super.key}); + final List dailyData; + + const FinanceCashFlow({super.key, required this.dailyData}); @override Widget build(BuildContext context) { + // Calculate totals from daily data + final totalCashIn = _calculateTotalCashIn(); + final totalCashOut = _calculateTotalCashOut(); + final netFlow = totalCashIn - totalCashOut; + return Container( margin: const EdgeInsets.all(16), padding: const EdgeInsets.all(20), @@ -70,7 +79,7 @@ class FinanceCashFlow extends StatelessWidget { Expanded( child: _buildCashFlowIndicator( 'Cash In', - 'Rp 28.5M', + _formatCurrency(totalCashIn), LineIcons.arrowUp, AppColor.success, ), @@ -79,7 +88,7 @@ class FinanceCashFlow extends StatelessWidget { Expanded( child: _buildCashFlowIndicator( 'Cash Out', - 'Rp 21.2M', + _formatCurrency(totalCashOut), LineIcons.arrowDown, AppColor.error, ), @@ -88,7 +97,7 @@ class FinanceCashFlow extends StatelessWidget { Expanded( child: _buildCashFlowIndicator( 'Net Flow', - 'Rp 7.3M', + _formatCurrency(netFlow), LineIcons.equals, AppColor.info, ), @@ -110,7 +119,7 @@ class FinanceCashFlow extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Grafik Cash Flow 7 Hari Terakhir', + 'Grafik Cash Flow ${dailyData.length} Hari Terakhir', style: AppStyle.sm.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w600, @@ -118,207 +127,9 @@ class FinanceCashFlow extends StatelessWidget { ), const SizedBox(height: 16), Expanded( - child: LineChart( - LineChartData( - gridData: FlGridData( - show: true, - drawVerticalLine: false, - horizontalInterval: 5000000, // 5M interval - getDrawingHorizontalLine: (value) { - return FlLine( - color: AppColor.borderLight, - strokeWidth: 1, - ); - }, - ), - titlesData: FlTitlesData( - show: true, - rightTitles: AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - topTitles: AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - bottomTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - reservedSize: 30, - interval: 1, - getTitlesWidget: (double value, TitleMeta meta) { - const style = TextStyle( - color: AppColor.textSecondary, - fontWeight: FontWeight.w500, - fontSize: 10, - ); - Widget text; - switch (value.toInt()) { - case 0: - text = const Text('Sen', style: style); - break; - case 1: - text = const Text('Sel', style: style); - break; - case 2: - text = const Text('Rab', style: style); - break; - case 3: - text = const Text('Kam', style: style); - break; - case 4: - text = const Text('Jum', style: style); - break; - case 5: - text = const Text('Sab', style: style); - break; - case 6: - text = const Text('Min', style: style); - break; - default: - text = const Text('', style: style); - break; - } - return SideTitleWidget(meta: meta, child: text); - }, - ), - ), - leftTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - interval: 10000000, // 10M interval - reservedSize: 42, - getTitlesWidget: (double value, TitleMeta meta) { - return Text( - '${(value / 1000000).toInt()}M', - style: const TextStyle( - color: AppColor.textSecondary, - fontWeight: FontWeight.w500, - fontSize: 10, - ), - textAlign: TextAlign.left, - ); - }, - ), - ), - ), - borderData: FlBorderData( - show: true, - border: Border.all(color: AppColor.borderLight), - ), - minX: 0, - maxX: 6, - minY: -5000000, - maxY: 30000000, - lineBarsData: [ - // Cash In Line - LineChartBarData( - spots: const [ - FlSpot(0, 25000000), // Monday - FlSpot(1, 22000000), // Tuesday - FlSpot(2, 28000000), // Wednesday - FlSpot(3, 24000000), // Thursday - FlSpot(4, 30000000), // Friday - FlSpot(5, 18000000), // Saturday - FlSpot(6, 26000000), // Sunday - ], - isCurved: true, - gradient: LinearGradient( - colors: [ - AppColor.success.withOpacity(0.8), - AppColor.success, - ], - ), - barWidth: 3, - isStrokeCapRound: true, - dotData: FlDotData( - show: true, - getDotPainter: (spot, percent, barData, index) { - return FlDotCirclePainter( - radius: 4, - color: AppColor.success, - strokeWidth: 2, - strokeColor: AppColor.white, - ); - }, - ), - belowBarData: BarAreaData( - show: true, - gradient: LinearGradient( - colors: [ - AppColor.success.withOpacity(0.1), - AppColor.success.withOpacity(0.0), - ], - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - ), - ), - ), - // Cash Out Line - LineChartBarData( - spots: const [ - FlSpot(0, 20000000), // Monday - FlSpot(1, 18000000), // Tuesday - FlSpot(2, 23000000), // Wednesday - FlSpot(3, 19000000), // Thursday - FlSpot(4, 25000000), // Friday - FlSpot(5, 15000000), // Saturday - FlSpot(6, 21000000), // Sunday - ], - isCurved: true, - gradient: LinearGradient( - colors: [ - AppColor.error.withOpacity(0.8), - AppColor.error, - ], - ), - barWidth: 3, - isStrokeCapRound: true, - dotData: FlDotData( - show: true, - getDotPainter: (spot, percent, barData, index) { - return FlDotCirclePainter( - radius: 4, - color: AppColor.error, - strokeWidth: 2, - strokeColor: AppColor.white, - ); - }, - ), - ), - // Net Flow Line - LineChartBarData( - spots: const [ - FlSpot(0, 5000000), // Monday - FlSpot(1, 4000000), // Tuesday - FlSpot(2, 5000000), // Wednesday - FlSpot(3, 5000000), // Thursday - FlSpot(4, 5000000), // Friday - FlSpot(5, 3000000), // Saturday - FlSpot(6, 5000000), // Sunday - ], - isCurved: true, - gradient: LinearGradient( - colors: [ - AppColor.info.withOpacity(0.8), - AppColor.info, - ], - ), - barWidth: 3, - isStrokeCapRound: true, - dotData: FlDotData( - show: true, - getDotPainter: (spot, percent, barData, index) { - return FlDotCirclePainter( - radius: 4, - color: AppColor.info, - strokeWidth: 2, - strokeColor: AppColor.white, - ); - }, - ), - ), - ], - ), - ), + child: dailyData.isEmpty + ? _buildEmptyChart() + : LineChart(_buildLineChartData()), ), const SizedBox(height: 12), // Legend @@ -340,6 +151,273 @@ class FinanceCashFlow extends StatelessWidget { ); } + LineChartData _buildLineChartData() { + final maxValue = _getMaxChartValue(); + final minValue = _getMinChartValue(); + + return LineChartData( + gridData: FlGridData( + show: true, + drawVerticalLine: false, + horizontalInterval: (maxValue / 5).roundToDouble(), + getDrawingHorizontalLine: (value) { + return FlLine(color: AppColor.borderLight, strokeWidth: 1); + }, + ), + titlesData: FlTitlesData( + show: true, + rightTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), + topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 30, + interval: 1, + getTitlesWidget: (double value, TitleMeta meta) { + final index = value.toInt(); + if (index >= 0 && index < dailyData.length) { + final date = DateTime.parse(dailyData[index].date); + final dayName = _getDayName(date.weekday); + return SideTitleWidget( + meta: meta, + child: Text( + dayName, + style: const TextStyle( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + fontSize: 10, + ), + ), + ); + } + return SideTitleWidget(meta: meta, child: Text('')); + }, + ), + ), + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + interval: (maxValue / 3).roundToDouble(), + reservedSize: 42, + getTitlesWidget: (double value, TitleMeta meta) { + return Text( + _formatChartValue(value), + style: const TextStyle( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + fontSize: 10, + ), + textAlign: TextAlign.left, + ); + }, + ), + ), + ), + borderData: FlBorderData( + show: true, + border: Border.all(color: AppColor.borderLight), + ), + minX: 0, + maxX: (dailyData.length - 1).toDouble(), + minY: minValue, + maxY: maxValue, + lineBarsData: [ + // Cash In Line (Revenue) + LineChartBarData( + spots: _buildCashInSpots(), + isCurved: true, + gradient: LinearGradient( + colors: [AppColor.success.withOpacity(0.8), AppColor.success], + ), + barWidth: 3, + isStrokeCapRound: true, + dotData: FlDotData( + show: true, + getDotPainter: (spot, percent, barData, index) { + return FlDotCirclePainter( + radius: 4, + color: AppColor.success, + strokeWidth: 2, + strokeColor: AppColor.white, + ); + }, + ), + belowBarData: BarAreaData( + show: true, + gradient: LinearGradient( + colors: [ + AppColor.success.withOpacity(0.1), + AppColor.success.withOpacity(0.0), + ], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + ), + ), + // Cash Out Line (Total Cost) + LineChartBarData( + spots: _buildCashOutSpots(), + isCurved: true, + gradient: LinearGradient( + colors: [AppColor.error.withOpacity(0.8), AppColor.error], + ), + barWidth: 3, + isStrokeCapRound: true, + dotData: FlDotData( + show: true, + getDotPainter: (spot, percent, barData, index) { + return FlDotCirclePainter( + radius: 4, + color: AppColor.error, + strokeWidth: 2, + strokeColor: AppColor.white, + ); + }, + ), + ), + // Net Flow Line (Net Profit) + LineChartBarData( + spots: _buildNetFlowSpots(), + isCurved: true, + gradient: LinearGradient( + colors: [AppColor.info.withOpacity(0.8), AppColor.info], + ), + barWidth: 3, + isStrokeCapRound: true, + dotData: FlDotData( + show: true, + getDotPainter: (spot, percent, barData, index) { + return FlDotCirclePainter( + radius: 4, + color: AppColor.info, + strokeWidth: 2, + strokeColor: AppColor.white, + ); + }, + ), + ), + ], + ); + } + + Widget _buildEmptyChart() { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + LineIcons.lineChart, + size: 48, + color: AppColor.textSecondary.withOpacity(0.3), + ), + const SizedBox(height: 12), + Text( + 'Tidak ada data untuk ditampilkan', + style: AppStyle.sm.copyWith(color: AppColor.textSecondary), + ), + ], + ), + ); + } + + // Helper methods for calculating data + int _calculateTotalCashIn() { + return dailyData.fold(0, (sum, data) => sum + data.revenue); + } + + int _calculateTotalCashOut() { + return dailyData.fold( + 0, + (sum, data) => sum + data.cost + data.tax + data.discount, + ); + } + + double _getMaxChartValue() { + if (dailyData.isEmpty) return 30000000; + + final maxRevenue = dailyData + .map((e) => e.revenue) + .reduce((a, b) => a > b ? a : b); + final maxCost = dailyData + .map((e) => e.cost + e.tax + e.discount) + .reduce((a, b) => a > b ? a : b); + final maxValue = maxRevenue > maxCost ? maxRevenue : maxCost; + + return (maxValue * 1.2).toDouble(); // Add 20% padding + } + + double _getMinChartValue() { + if (dailyData.isEmpty) return -5000000; + + final minNetProfit = dailyData + .map((e) => e.netProfit) + .reduce((a, b) => a < b ? a : b); + return minNetProfit < 0 ? (minNetProfit * 1.2).toDouble() : 0; + } + + List _buildCashInSpots() { + return dailyData.asMap().entries.map((entry) { + return FlSpot(entry.key.toDouble(), entry.value.revenue.toDouble()); + }).toList(); + } + + List _buildCashOutSpots() { + return dailyData.asMap().entries.map((entry) { + final totalCost = + entry.value.cost + entry.value.tax + entry.value.discount; + return FlSpot(entry.key.toDouble(), totalCost.toDouble()); + }).toList(); + } + + List _buildNetFlowSpots() { + return dailyData.asMap().entries.map((entry) { + return FlSpot(entry.key.toDouble(), entry.value.netProfit.toDouble()); + }).toList(); + } + + String _getDayName(int weekday) { + switch (weekday) { + case 1: + return 'Sen'; + case 2: + return 'Sel'; + case 3: + return 'Rab'; + case 4: + return 'Kam'; + case 5: + return 'Jum'; + case 6: + return 'Sab'; + case 7: + return 'Min'; + default: + return ''; + } + } + + String _formatChartValue(double value) { + if (value.abs() >= 1000000) { + return '${(value / 1000000).toStringAsFixed(0)}M'; + } else if (value.abs() >= 1000) { + return '${(value / 1000).toStringAsFixed(0)}K'; + } else { + return value.toStringAsFixed(0); + } + } + + String _formatCurrency(int amount) { + if (amount.abs() >= 1000000000) { + return 'Rp ${(amount / 1000000000).toStringAsFixed(1)}B'; + } else if (amount.abs() >= 1000000) { + return 'Rp ${(amount / 1000000).toStringAsFixed(1)}M'; + } else if (amount.abs() >= 1000) { + return 'Rp ${(amount / 1000).toStringAsFixed(1)}K'; + } else { + return 'Rp ${NumberFormat('#,###', 'id_ID').format(amount)}'; + } + } + Widget _buildChartLegend(String label, Color color) { return Row( mainAxisSize: MainAxisSize.min, diff --git a/lib/presentation/pages/finance/widgets/product.dart b/lib/presentation/pages/finance/widgets/product.dart new file mode 100644 index 0000000..d545d82 --- /dev/null +++ b/lib/presentation/pages/finance/widgets/product.dart @@ -0,0 +1,148 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; + +class ProfitLossProduct extends StatelessWidget { + final ProfitLossProductData product; + const ProfitLossProduct({super.key, required this.product}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: AppColor.background, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: AppColor.border.withOpacity(0.5)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Product header + Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + product.productName, + style: AppStyle.md.copyWith(fontWeight: FontWeight.bold), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 2), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 2, + ), + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Text( + product.categoryName, + style: AppStyle.xs.copyWith(color: AppColor.primary), + ), + ), + ], + ), + ), + const SizedBox(width: 12), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + '${product.quantitySold} terjual', + style: AppStyle.sm.copyWith(color: AppColor.textSecondary), + ), + Text( + '${product.grossProfitMargin.toStringAsFixed(1)}%', + style: AppStyle.md.copyWith( + fontWeight: FontWeight.bold, + color: product.grossProfitMargin > 25 + ? AppColor.success + : product.grossProfitMargin > 15 + ? AppColor.warning + : AppColor.error, + ), + ), + ], + ), + ], + ), + const SizedBox(height: 16), + + // Financial metrics + Row( + children: [ + Expanded( + child: _buildMetricColumn( + 'Pendapatan', + product.revenue.currencyFormatRp, + AppColor.success, + ), + ), + Expanded( + child: _buildMetricColumn( + 'Biaya', + product.cost.currencyFormatRp, + AppColor.error, + ), + ), + Expanded( + child: _buildMetricColumn( + 'Laba Kotor', + product.grossProfit.currencyFormatRp, + AppColor.info, + ), + ), + ], + ), + const SizedBox(height: 12), + + // Average metrics + Row( + children: [ + Expanded( + child: _buildMetricColumn( + 'Harga Rata-rata', + product.averagePrice.currencyFormatRp, + AppColor.textSecondary, + ), + ), + Expanded( + child: _buildMetricColumn( + 'Laba per Unit', + product.profitPerUnit.currencyFormatRp, + AppColor.primary, + ), + ), + const Expanded(child: SizedBox()), + ], + ), + ], + ), + ); + } + + Widget _buildMetricColumn(String label, String value, Color color) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(label, style: AppStyle.xs.copyWith(color: AppColor.textSecondary)), + const SizedBox(height: 2), + Text( + value, + style: AppStyle.sm.copyWith( + fontWeight: FontWeight.w600, + color: color, + ), + ), + ], + ); + } +} diff --git a/lib/presentation/pages/finance/widgets/profit_loss.dart b/lib/presentation/pages/finance/widgets/profit_loss.dart index a3fa885..8692aba 100644 --- a/lib/presentation/pages/finance/widgets/profit_loss.dart +++ b/lib/presentation/pages/finance/widgets/profit_loss.dart @@ -1,10 +1,14 @@ import 'package:flutter/material.dart'; import 'package:line_icons/line_icons.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; class FinanceProfitLoss extends StatelessWidget { - const FinanceProfitLoss({super.key}); + final ProfitLossSummary data; + + const FinanceProfitLoss({super.key, required this.data}); @override Widget build(BuildContext context) { @@ -49,52 +53,77 @@ class FinanceProfitLoss extends StatelessWidget { ), const SizedBox(height: 20), + // Total Revenue (Penjualan Kotor) _buildPLItem( 'Penjualan Kotor', - 'Rp 25.840.000', + data.totalRevenue.currencyFormatRp, AppColor.success, true, ), - _buildPLItem('Diskon & Retur', '- Rp 560.000', AppColor.error, false), + + // Discount (Diskon & Retur) + _buildPLItem( + 'Diskon & Retur', + '- ${data.totalDiscount.currencyFormatRp}', + AppColor.error, + false, + ), + const Divider(height: 24), + + // Net Sales (Penjualan Bersih = Total Revenue - Discount) _buildPLItem( 'Penjualan Bersih', - 'Rp 25.280.000', + (data.totalRevenue - data.totalDiscount).currencyFormatRp, AppColor.textPrimary, true, isHeader: true, ), + const SizedBox(height: 12), + + // Cost of Goods Sold (HPP) _buildPLItem( 'HPP (Harga Pokok Penjualan)', - '- Rp 15.120.000', + '- ${data.totalCost.currencyFormatRp}', AppColor.error, false, ), + const Divider(height: 24), + + // Gross Profit (Laba Kotor) _buildPLItem( 'Laba Kotor', - 'Rp 10.160.000', + data.grossProfit.currencyFormatRp, AppColor.success, true, isHeader: true, + showPercentage: true, + percentage: '${data.grossProfitMargin.toStringAsFixed(1)}%', ), + const SizedBox(height: 12), + + // Operational Cost (Biaya Operasional) - calculated as difference _buildPLItem( 'Biaya Operasional', - '- Rp 2.640.000', + '- ${_calculateOperationalCost().currencyFormatRp}', AppColor.error, false, ), + const Divider(height: 24), + + // Net Profit (Laba Bersih) _buildPLItem( 'Laba Bersih', - 'Rp 7.520.000', + data.netProfit.currencyFormatRp, AppColor.primary, true, isHeader: true, showPercentage: true, - percentage: '29.8%', + percentage: '${data.netProfitMargin.round()}%', ), ], ), @@ -155,4 +184,9 @@ class FinanceProfitLoss extends StatelessWidget { ), ); } + + // Calculate operational cost as the difference between gross profit and net profit + int _calculateOperationalCost() { + return data.grossProfit - data.netProfit - data.totalTax; + } } diff --git a/lib/presentation/pages/finance/widgets/summary_card.dart b/lib/presentation/pages/finance/widgets/summary_card.dart index 94689d3..26daaf6 100644 --- a/lib/presentation/pages/finance/widgets/summary_card.dart +++ b/lib/presentation/pages/finance/widgets/summary_card.dart @@ -9,7 +9,6 @@ class FinanceSummaryCard extends StatelessWidget { required this.amount, required this.icon, required this.color, - required this.change, required this.isPositive, }); @@ -17,7 +16,6 @@ class FinanceSummaryCard extends StatelessWidget { final String amount; final IconData icon; final Color color; - final String change; final bool isPositive; @override @@ -50,22 +48,6 @@ class FinanceSummaryCard extends StatelessWidget { ), child: Icon(icon, color: color, size: 20), ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: isPositive - ? AppColor.success.withOpacity(0.1) - : AppColor.error.withOpacity(0.1), - borderRadius: BorderRadius.circular(12), - ), - child: Text( - change, - style: AppStyle.xs.copyWith( - color: isPositive ? AppColor.success : AppColor.error, - fontWeight: FontWeight.w600, - ), - ), - ), ], ), const SizedBox(height: 12),