feat: Refactor ClientCreateOrderRepositoryImpl and OneTimeOrderBloc to utilize DataConnectService, removing FirebaseAuth dependency
This commit is contained in:
@@ -2,7 +2,6 @@ import 'package:flutter/widgets.dart';
|
|||||||
import 'package:flutter_modular/flutter_modular.dart';
|
import 'package:flutter_modular/flutter_modular.dart';
|
||||||
import 'package:krow_core/core.dart';
|
import 'package:krow_core/core.dart';
|
||||||
import 'package:krow_data_connect/krow_data_connect.dart';
|
import 'package:krow_data_connect/krow_data_connect.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart' as firebase;
|
|
||||||
import 'data/repositories_impl/client_create_order_repository_impl.dart';
|
import 'data/repositories_impl/client_create_order_repository_impl.dart';
|
||||||
import 'domain/repositories/client_create_order_repository_interface.dart';
|
import 'domain/repositories/client_create_order_repository_interface.dart';
|
||||||
import 'domain/usecases/create_one_time_order_usecase.dart';
|
import 'domain/usecases/create_one_time_order_usecase.dart';
|
||||||
@@ -29,12 +28,7 @@ class ClientCreateOrderModule extends Module {
|
|||||||
@override
|
@override
|
||||||
void binds(Injector i) {
|
void binds(Injector i) {
|
||||||
// Repositories
|
// Repositories
|
||||||
i.addLazySingleton<ClientCreateOrderRepositoryInterface>(
|
i.addLazySingleton<ClientCreateOrderRepositoryInterface>(ClientCreateOrderRepositoryImpl.new);
|
||||||
() => ClientCreateOrderRepositoryImpl(
|
|
||||||
firebaseAuth: firebase.FirebaseAuth.instance,
|
|
||||||
dataConnect: ExampleConnector.instance,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// UseCases
|
// UseCases
|
||||||
i.addLazySingleton(GetOrderTypesUseCase.new);
|
i.addLazySingleton(GetOrderTypesUseCase.new);
|
||||||
@@ -44,12 +38,7 @@ class ClientCreateOrderModule extends Module {
|
|||||||
// BLoCs
|
// BLoCs
|
||||||
i.add<ClientCreateOrderBloc>(ClientCreateOrderBloc.new);
|
i.add<ClientCreateOrderBloc>(ClientCreateOrderBloc.new);
|
||||||
i.add<RapidOrderBloc>(RapidOrderBloc.new);
|
i.add<RapidOrderBloc>(RapidOrderBloc.new);
|
||||||
i.add<OneTimeOrderBloc>(
|
i.add<OneTimeOrderBloc>(OneTimeOrderBloc.new);
|
||||||
() => OneTimeOrderBloc(
|
|
||||||
i.get<CreateOneTimeOrderUseCase>(),
|
|
||||||
ExampleConnector.instance,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import 'package:firebase_auth/firebase_auth.dart' as firebase;
|
|
||||||
import 'package:firebase_data_connect/firebase_data_connect.dart' as fdc;
|
import 'package:firebase_data_connect/firebase_data_connect.dart' as fdc;
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
||||||
@@ -13,21 +12,16 @@ import '../../domain/repositories/client_create_order_repository_interface.dart'
|
|||||||
///
|
///
|
||||||
/// It follows the KROW Clean Architecture by keeping the data layer focused
|
/// It follows the KROW Clean Architecture by keeping the data layer focused
|
||||||
/// on delegation and data mapping, without business logic.
|
/// on delegation and data mapping, without business logic.
|
||||||
class ClientCreateOrderRepositoryImpl
|
class ClientCreateOrderRepositoryImpl implements ClientCreateOrderRepositoryInterface {
|
||||||
with dc.DataErrorHandler
|
|
||||||
implements ClientCreateOrderRepositoryInterface {
|
|
||||||
ClientCreateOrderRepositoryImpl({
|
ClientCreateOrderRepositoryImpl({
|
||||||
required firebase.FirebaseAuth firebaseAuth,
|
required dc.DataConnectService service,
|
||||||
required dc.ExampleConnector dataConnect,
|
}) : _service = service;
|
||||||
}) : _firebaseAuth = firebaseAuth,
|
|
||||||
_dataConnect = dataConnect;
|
|
||||||
|
|
||||||
final firebase.FirebaseAuth _firebaseAuth;
|
final dc.DataConnectService _service;
|
||||||
final dc.ExampleConnector _dataConnect;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<domain.OrderType>> getOrderTypes() {
|
Future<List<domain.OrderType>> getOrderTypes() {
|
||||||
return Future.value(const <domain.OrderType>[
|
return Future<List<domain.OrderType>>.value(const <domain.OrderType>[
|
||||||
domain.OrderType(
|
domain.OrderType(
|
||||||
id: 'one-time',
|
id: 'one-time',
|
||||||
titleKey: 'client_create_order.types.one_time',
|
titleKey: 'client_create_order.types.one_time',
|
||||||
@@ -55,100 +49,95 @@ class ClientCreateOrderRepositoryImpl
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> createOneTimeOrder(domain.OneTimeOrder order) async {
|
Future<void> createOneTimeOrder(domain.OneTimeOrder order) async {
|
||||||
final String? businessId = dc.ClientSessionStore.instance.session?.business?.id;
|
return _service.run(() async {
|
||||||
if (businessId == null || businessId.isEmpty) {
|
final String businessId = await _service.getBusinessId();
|
||||||
await _firebaseAuth.signOut();
|
final String? vendorId = order.vendorId;
|
||||||
throw Exception('Business is missing. Please sign in again.');
|
if (vendorId == null || vendorId.isEmpty) {
|
||||||
}
|
throw Exception('Vendor is missing.');
|
||||||
final String? vendorId = order.vendorId;
|
}
|
||||||
if (vendorId == null || vendorId.isEmpty) {
|
final domain.OneTimeOrderHubDetails? hub = order.hub;
|
||||||
throw Exception('Vendor is missing.');
|
if (hub == null || hub.id.isEmpty) {
|
||||||
}
|
throw Exception('Hub is missing.');
|
||||||
final domain.OneTimeOrderHubDetails? hub = order.hub;
|
}
|
||||||
if (hub == null || hub.id.isEmpty) {
|
|
||||||
throw Exception('Hub is missing.');
|
|
||||||
}
|
|
||||||
|
|
||||||
final DateTime orderDateOnly = DateTime(
|
final DateTime orderDateOnly = DateTime(
|
||||||
order.date.year,
|
order.date.year,
|
||||||
order.date.month,
|
order.date.month,
|
||||||
order.date.day,
|
order.date.day,
|
||||||
);
|
);
|
||||||
final fdc.Timestamp orderTimestamp = _toTimestamp(orderDateOnly);
|
final fdc.Timestamp orderTimestamp = _service.toTimestamp(orderDateOnly);
|
||||||
final fdc.OperationResult<dc.CreateOrderData, dc.CreateOrderVariables>
|
final fdc.OperationResult<dc.CreateOrderData, dc.CreateOrderVariables> orderResult =
|
||||||
orderResult = await executeProtected(() => _dataConnect
|
await _service.connector
|
||||||
.createOrder(
|
.createOrder(
|
||||||
businessId: businessId,
|
businessId: businessId,
|
||||||
orderType: dc.OrderType.ONE_TIME,
|
orderType: dc.OrderType.ONE_TIME,
|
||||||
teamHubId: hub.id,
|
teamHubId: hub.id,
|
||||||
|
)
|
||||||
|
.vendorId(vendorId)
|
||||||
|
.eventName(order.eventName)
|
||||||
|
.status(dc.OrderStatus.POSTED)
|
||||||
|
.date(orderTimestamp)
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
final String orderId = orderResult.data.order_insert.id;
|
||||||
|
|
||||||
|
final int workersNeeded = order.positions.fold<int>(
|
||||||
|
0,
|
||||||
|
(int sum, domain.OneTimeOrderPosition position) => sum + position.count,
|
||||||
|
);
|
||||||
|
final String shiftTitle = 'Shift 1 ${_formatDate(order.date)}';
|
||||||
|
final double shiftCost = _calculateShiftCost(order);
|
||||||
|
|
||||||
|
final fdc.OperationResult<dc.CreateShiftData, dc.CreateShiftVariables> shiftResult =
|
||||||
|
await _service.connector
|
||||||
|
.createShift(title: shiftTitle, orderId: orderId)
|
||||||
|
.date(orderTimestamp)
|
||||||
|
.location(hub.name)
|
||||||
|
.locationAddress(hub.address)
|
||||||
|
.latitude(hub.latitude)
|
||||||
|
.longitude(hub.longitude)
|
||||||
|
.placeId(hub.placeId)
|
||||||
|
.city(hub.city)
|
||||||
|
.state(hub.state)
|
||||||
|
.street(hub.street)
|
||||||
|
.country(hub.country)
|
||||||
|
.status(dc.ShiftStatus.PENDING)
|
||||||
|
.workersNeeded(workersNeeded)
|
||||||
|
.filled(0)
|
||||||
|
.durationDays(1)
|
||||||
|
.cost(shiftCost)
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
final String shiftId = shiftResult.data.shift_insert.id;
|
||||||
|
|
||||||
|
for (final domain.OneTimeOrderPosition position in order.positions) {
|
||||||
|
final DateTime start = _parseTime(order.date, position.startTime);
|
||||||
|
final DateTime end = _parseTime(order.date, position.endTime);
|
||||||
|
final DateTime normalizedEnd = end.isBefore(start) ? end.add(const Duration(days: 1)) : end;
|
||||||
|
final double hours = normalizedEnd.difference(start).inMinutes / 60.0;
|
||||||
|
final double rate = order.roleRates[position.role] ?? 0;
|
||||||
|
final double totalValue = rate * hours * position.count;
|
||||||
|
|
||||||
|
await _service.connector
|
||||||
|
.createShiftRole(
|
||||||
|
shiftId: shiftId,
|
||||||
|
roleId: position.role,
|
||||||
|
count: position.count,
|
||||||
)
|
)
|
||||||
.vendorId(vendorId)
|
.startTime(_service.toTimestamp(start))
|
||||||
.eventName(order.eventName)
|
.endTime(_service.toTimestamp(normalizedEnd))
|
||||||
.status(dc.OrderStatus.POSTED)
|
.hours(hours)
|
||||||
.date(orderTimestamp)
|
.breakType(_breakDurationFromValue(position.lunchBreak))
|
||||||
.execute());
|
.isBreakPaid(_isBreakPaid(position.lunchBreak))
|
||||||
|
.totalValue(totalValue)
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
final String orderId = orderResult.data.order_insert.id;
|
await _service.connector
|
||||||
|
.updateOrder(id: orderId, teamHubId: hub.id)
|
||||||
final int workersNeeded = order.positions.fold<int>(
|
.shifts(fdc.AnyValue(<String>[shiftId]))
|
||||||
0,
|
.execute();
|
||||||
(int sum, domain.OneTimeOrderPosition position) => sum + position.count,
|
});
|
||||||
);
|
|
||||||
final String shiftTitle = 'Shift 1 ${_formatDate(order.date)}';
|
|
||||||
final double shiftCost = _calculateShiftCost(order);
|
|
||||||
|
|
||||||
final fdc.OperationResult<dc.CreateShiftData, dc.CreateShiftVariables>
|
|
||||||
shiftResult = await executeProtected(() => _dataConnect
|
|
||||||
.createShift(title: shiftTitle, orderId: orderId)
|
|
||||||
.date(orderTimestamp)
|
|
||||||
.location(hub.name)
|
|
||||||
.locationAddress(hub.address)
|
|
||||||
.latitude(hub.latitude)
|
|
||||||
.longitude(hub.longitude)
|
|
||||||
.placeId(hub.placeId)
|
|
||||||
.city(hub.city)
|
|
||||||
.state(hub.state)
|
|
||||||
.street(hub.street)
|
|
||||||
.country(hub.country)
|
|
||||||
.status(dc.ShiftStatus.PENDING)
|
|
||||||
.workersNeeded(workersNeeded)
|
|
||||||
.filled(0)
|
|
||||||
.durationDays(1)
|
|
||||||
.cost(shiftCost)
|
|
||||||
.execute());
|
|
||||||
|
|
||||||
final String shiftId = shiftResult.data.shift_insert.id;
|
|
||||||
|
|
||||||
for (final domain.OneTimeOrderPosition position in order.positions) {
|
|
||||||
final DateTime start = _parseTime(order.date, position.startTime);
|
|
||||||
final DateTime end = _parseTime(order.date, position.endTime);
|
|
||||||
final DateTime normalizedEnd =
|
|
||||||
end.isBefore(start) ? end.add(const Duration(days: 1)) : end;
|
|
||||||
final double hours = normalizedEnd.difference(start).inMinutes / 60.0;
|
|
||||||
final double rate = order.roleRates[position.role] ?? 0;
|
|
||||||
final double totalValue = rate * hours * position.count;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await executeProtected(() => _dataConnect
|
|
||||||
.createShiftRole(
|
|
||||||
shiftId: shiftId,
|
|
||||||
roleId: position.role,
|
|
||||||
count: position.count,
|
|
||||||
)
|
|
||||||
.startTime(_toTimestamp(start))
|
|
||||||
.endTime(_toTimestamp(normalizedEnd))
|
|
||||||
.hours(hours)
|
|
||||||
.breakType(_breakDurationFromValue(position.lunchBreak))
|
|
||||||
.isBreakPaid(_isBreakPaid(position.lunchBreak))
|
|
||||||
.totalValue(totalValue)
|
|
||||||
.execute());
|
|
||||||
}
|
|
||||||
|
|
||||||
await executeProtected(() => _dataConnect
|
|
||||||
.updateOrder(id: orderId, teamHubId: hub.id)
|
|
||||||
.shifts(fdc.AnyValue(<String>[shiftId]))
|
|
||||||
.execute());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -213,13 +202,6 @@ class ClientCreateOrderRepositoryImpl
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fdc.Timestamp _toTimestamp(DateTime dateTime) {
|
|
||||||
final DateTime utc = dateTime.toUtc();
|
|
||||||
final int seconds = utc.millisecondsSinceEpoch ~/ 1000;
|
|
||||||
final int nanoseconds = (utc.microsecondsSinceEpoch % 1000000) * 1000;
|
|
||||||
return fdc.Timestamp(nanoseconds, seconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
String _formatDate(DateTime dateTime) {
|
String _formatDate(DateTime dateTime) {
|
||||||
final String year = dateTime.year.toString().padLeft(4, '0');
|
final String year = dateTime.year.toString().padLeft(4, '0');
|
||||||
final String month = dateTime.month.toString().padLeft(2, '0');
|
final String month = dateTime.month.toString().padLeft(2, '0');
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import 'one_time_order_state.dart';
|
|||||||
/// BLoC for managing the multi-step one-time order creation form.
|
/// BLoC for managing the multi-step one-time order creation form.
|
||||||
class OneTimeOrderBloc extends Bloc<OneTimeOrderEvent, OneTimeOrderState>
|
class OneTimeOrderBloc extends Bloc<OneTimeOrderEvent, OneTimeOrderState>
|
||||||
with BlocErrorHandler<OneTimeOrderState>, SafeBloc<OneTimeOrderEvent, OneTimeOrderState> {
|
with BlocErrorHandler<OneTimeOrderState>, SafeBloc<OneTimeOrderEvent, OneTimeOrderState> {
|
||||||
OneTimeOrderBloc(this._createOneTimeOrderUseCase, this._dataConnect)
|
OneTimeOrderBloc(this._createOneTimeOrderUseCase, this._service)
|
||||||
: super(OneTimeOrderState.initial()) {
|
: super(OneTimeOrderState.initial()) {
|
||||||
on<OneTimeOrderVendorsLoaded>(_onVendorsLoaded);
|
on<OneTimeOrderVendorsLoaded>(_onVendorsLoaded);
|
||||||
on<OneTimeOrderVendorChanged>(_onVendorChanged);
|
on<OneTimeOrderVendorChanged>(_onVendorChanged);
|
||||||
@@ -28,13 +28,13 @@ class OneTimeOrderBloc extends Bloc<OneTimeOrderEvent, OneTimeOrderState>
|
|||||||
_loadHubs();
|
_loadHubs();
|
||||||
}
|
}
|
||||||
final CreateOneTimeOrderUseCase _createOneTimeOrderUseCase;
|
final CreateOneTimeOrderUseCase _createOneTimeOrderUseCase;
|
||||||
final dc.ExampleConnector _dataConnect;
|
final dc.DataConnectService _service;
|
||||||
|
|
||||||
Future<void> _loadVendors() async {
|
Future<void> _loadVendors() async {
|
||||||
final List<Vendor>? vendors = await handleErrorWithResult(
|
final List<Vendor>? vendors = await handleErrorWithResult(
|
||||||
action: () async {
|
action: () async {
|
||||||
final QueryResult<dc.ListVendorsData, void> result =
|
final QueryResult<dc.ListVendorsData, void> result =
|
||||||
await _dataConnect.listVendors().execute();
|
await _service.connector.listVendors().execute();
|
||||||
return result.data.vendors
|
return result.data.vendors
|
||||||
.map(
|
.map(
|
||||||
(dc.ListVendorsVendors vendor) => Vendor(
|
(dc.ListVendorsVendors vendor) => Vendor(
|
||||||
@@ -57,7 +57,7 @@ class OneTimeOrderBloc extends Bloc<OneTimeOrderEvent, OneTimeOrderState>
|
|||||||
final List<OneTimeOrderRoleOption>? roles = await handleErrorWithResult(
|
final List<OneTimeOrderRoleOption>? roles = await handleErrorWithResult(
|
||||||
action: () async {
|
action: () async {
|
||||||
final QueryResult<dc.ListRolesByVendorIdData, dc.ListRolesByVendorIdVariables>
|
final QueryResult<dc.ListRolesByVendorIdData, dc.ListRolesByVendorIdVariables>
|
||||||
result = await _dataConnect.listRolesByVendorId(vendorId: vendorId).execute();
|
result = await _service.connector.listRolesByVendorId(vendorId: vendorId).execute();
|
||||||
return result.data.roles
|
return result.data.roles
|
||||||
.map(
|
.map(
|
||||||
(dc.ListRolesByVendorIdRoles role) => OneTimeOrderRoleOption(
|
(dc.ListRolesByVendorIdRoles role) => OneTimeOrderRoleOption(
|
||||||
@@ -79,13 +79,9 @@ class OneTimeOrderBloc extends Bloc<OneTimeOrderEvent, OneTimeOrderState>
|
|||||||
Future<void> _loadHubs() async {
|
Future<void> _loadHubs() async {
|
||||||
final List<OneTimeOrderHubOption>? hubs = await handleErrorWithResult(
|
final List<OneTimeOrderHubOption>? hubs = await handleErrorWithResult(
|
||||||
action: () async {
|
action: () async {
|
||||||
final String? businessId =
|
final String businessId = await _service.getBusinessId();
|
||||||
dc.ClientSessionStore.instance.session?.business?.id;
|
|
||||||
if (businessId == null || businessId.isEmpty) {
|
|
||||||
return <OneTimeOrderHubOption>[];
|
|
||||||
}
|
|
||||||
final QueryResult<dc.ListTeamHubsByOwnerIdData, dc.ListTeamHubsByOwnerIdVariables>
|
final QueryResult<dc.ListTeamHubsByOwnerIdData, dc.ListTeamHubsByOwnerIdVariables>
|
||||||
result = await _dataConnect
|
result = await _service.connector
|
||||||
.listTeamHubsByOwnerId(ownerId: businessId)
|
.listTeamHubsByOwnerId(ownerId: businessId)
|
||||||
.execute();
|
.execute();
|
||||||
return result.data.teamHubs
|
return result.data.teamHubs
|
||||||
|
|||||||
Reference in New Issue
Block a user