rapid order
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_modular/flutter_modular.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 'domain/repositories/client_create_order_repository_interface.dart';
|
||||
import 'domain/usecases/create_one_time_order_usecase.dart';
|
||||
@@ -29,7 +30,8 @@ class ClientCreateOrderModule extends Module {
|
||||
// Repositories
|
||||
i.addLazySingleton<ClientCreateOrderRepositoryInterface>(
|
||||
() => ClientCreateOrderRepositoryImpl(
|
||||
orderMock: i.get<OrderRepositoryMock>(),
|
||||
firebaseAuth: firebase.FirebaseAuth.instance,
|
||||
dataConnect: ExampleConnector.instance,
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:krow_data_connect/krow_data_connect.dart' hide OrderType;
|
||||
import 'package:krow_domain/krow_domain.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart' as firebase;
|
||||
import 'package:firebase_data_connect/firebase_data_connect.dart' as fdc;
|
||||
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
||||
import 'package:krow_domain/krow_domain.dart' as domain;
|
||||
import '../../domain/repositories/client_create_order_repository_interface.dart';
|
||||
|
||||
/// Implementation of [ClientCreateOrderRepositoryInterface].
|
||||
@@ -12,29 +14,218 @@ import '../../domain/repositories/client_create_order_repository_interface.dart'
|
||||
/// on delegation and data mapping, without business logic.
|
||||
class ClientCreateOrderRepositoryImpl
|
||||
implements ClientCreateOrderRepositoryInterface {
|
||||
/// Creates a [ClientCreateOrderRepositoryImpl].
|
||||
///
|
||||
/// Requires the [OrderRepositoryMock] from the shared Data Connect package.
|
||||
/// TODO: Inject and use ExampleConnector when real mutations are available.
|
||||
ClientCreateOrderRepositoryImpl({required OrderRepositoryMock orderMock})
|
||||
: _orderMock = orderMock;
|
||||
final OrderRepositoryMock _orderMock;
|
||||
ClientCreateOrderRepositoryImpl({
|
||||
required firebase.FirebaseAuth firebaseAuth,
|
||||
required dc.ExampleConnector dataConnect,
|
||||
}) : _firebaseAuth = firebaseAuth,
|
||||
_dataConnect = dataConnect;
|
||||
|
||||
final firebase.FirebaseAuth _firebaseAuth;
|
||||
final dc.ExampleConnector _dataConnect;
|
||||
|
||||
@override
|
||||
Future<List<OrderType>> getOrderTypes() {
|
||||
// Delegates to Data Connect layer
|
||||
return _orderMock.getOrderTypes();
|
||||
Future<List<domain.OrderType>> getOrderTypes() {
|
||||
return Future.value(const <domain.OrderType>[
|
||||
domain.OrderType(
|
||||
id: 'rapid',
|
||||
titleKey: 'client_create_order.types.rapid',
|
||||
descriptionKey: 'client_create_order.types.rapid_desc',
|
||||
),
|
||||
domain.OrderType(
|
||||
id: 'one-time',
|
||||
titleKey: 'client_create_order.types.one_time',
|
||||
descriptionKey: 'client_create_order.types.one_time_desc',
|
||||
),
|
||||
domain.OrderType(
|
||||
id: 'recurring',
|
||||
titleKey: 'client_create_order.types.recurring',
|
||||
descriptionKey: 'client_create_order.types.recurring_desc',
|
||||
),
|
||||
domain.OrderType(
|
||||
id: 'permanent',
|
||||
titleKey: 'client_create_order.types.permanent',
|
||||
descriptionKey: 'client_create_order.types.permanent_desc',
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> createOneTimeOrder(OneTimeOrder order) {
|
||||
// Delegates to Data Connect layer
|
||||
return _orderMock.createOneTimeOrder(order);
|
||||
Future<void> createOneTimeOrder(domain.OneTimeOrder order) {
|
||||
return Future.value();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> createRapidOrder(String description) {
|
||||
// Delegates to Data Connect layer
|
||||
return _orderMock.createRapidOrder(description);
|
||||
Future<void> createRapidOrder(String description) async {
|
||||
final businessId = dc.ClientSessionStore.instance.session?.business?.id;
|
||||
if (businessId == null || businessId.isEmpty) {
|
||||
await _firebaseAuth.signOut();
|
||||
throw Exception('Business is missing. Please sign in again.');
|
||||
}
|
||||
|
||||
final payload = _requestIa(description);
|
||||
final orderTimestamp = _toTimestamp(payload.date);
|
||||
|
||||
final orderResult = await _dataConnect
|
||||
.createOrder(businessId: businessId, orderType: dc.OrderType.RAPID)
|
||||
.vendorId(payload.vendorId)
|
||||
.hub(payload.hub)
|
||||
.location(payload.location)
|
||||
.status(dc.OrderStatus.POSTED)
|
||||
.date(orderTimestamp)
|
||||
.execute();
|
||||
|
||||
final orderId = orderResult.data?.order_insert.id;
|
||||
if (orderId == null) {
|
||||
throw Exception('Order creation failed.');
|
||||
}
|
||||
|
||||
final shiftIds = <String>[];
|
||||
for (var i = 0; i < payload.shifts.length; i++) {
|
||||
final shiftPayload = payload.shifts[i];
|
||||
final shiftTitle = 'Shift ${i + 1} ${_formatDate(payload.date)}';
|
||||
final shiftCost = shiftPayload.roles.fold<double>(
|
||||
0,
|
||||
(sum, role) => sum + role.totalValue,
|
||||
);
|
||||
|
||||
final shiftResult = await _dataConnect
|
||||
.createShift(title: shiftTitle, orderId: orderId)
|
||||
.date(orderTimestamp)
|
||||
.location(payload.location)
|
||||
.locationAddress(payload.location)
|
||||
.status(dc.ShiftStatus.PENDING)
|
||||
.workersNeeded(shiftPayload.workersNeeded)
|
||||
.filled(0)
|
||||
.durationDays(1)
|
||||
.cost(shiftCost)
|
||||
.execute();
|
||||
|
||||
final shiftId = shiftResult.data?.shift_insert.id;
|
||||
if (shiftId == null) {
|
||||
throw Exception('Shift creation failed.');
|
||||
}
|
||||
shiftIds.add(shiftId);
|
||||
|
||||
for (final role in shiftPayload.roles) {
|
||||
await _dataConnect
|
||||
.createShiftRole(
|
||||
shiftId: shiftId,
|
||||
roleId: role.roleId,
|
||||
count: role.count,
|
||||
)
|
||||
.startTime(_toTimestamp(role.startTime))
|
||||
.endTime(_toTimestamp(role.endTime))
|
||||
.hours(role.hours)
|
||||
.totalValue(role.totalValue)
|
||||
.execute();
|
||||
}
|
||||
}
|
||||
|
||||
await _dataConnect
|
||||
.updateOrder(id: orderId)
|
||||
.shifts(fdc.AnyValue(shiftIds))
|
||||
.execute();
|
||||
}
|
||||
|
||||
_RapidOrderPayload _requestIa(String description) {
|
||||
final now = DateTime.now().toUtc();
|
||||
final shiftStart = DateTime.utc(
|
||||
now.year,
|
||||
now.month,
|
||||
now.day,
|
||||
8,
|
||||
0,
|
||||
);
|
||||
final shiftEnd = shiftStart.add(const Duration(hours: 6));
|
||||
|
||||
return _RapidOrderPayload(
|
||||
vendorId: '00000000-0000-0000-0000-000000000001',
|
||||
hub: 'Main Hub',
|
||||
location: 'Main Location',
|
||||
date: DateTime.utc(now.year, now.month, now.day),
|
||||
shifts: [
|
||||
_RapidShiftPayload(
|
||||
workersNeeded: 3,
|
||||
roles: [
|
||||
_RapidShiftRolePayload(
|
||||
roleId: '00000000-0000-0000-0000-000000000010',
|
||||
count: 2,
|
||||
startTime: shiftStart,
|
||||
endTime: shiftEnd,
|
||||
totalValue: 120,
|
||||
),
|
||||
_RapidShiftRolePayload(
|
||||
roleId: '00000000-0000-0000-0000-000000000011',
|
||||
count: 1,
|
||||
startTime: shiftStart,
|
||||
endTime: shiftEnd,
|
||||
totalValue: 80,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
fdc.Timestamp _toTimestamp(DateTime dateTime) {
|
||||
final utc = dateTime.toUtc();
|
||||
final seconds = utc.millisecondsSinceEpoch ~/ 1000;
|
||||
final nanoseconds = (utc.microsecondsSinceEpoch % 1000000) * 1000;
|
||||
return fdc.Timestamp(nanoseconds, seconds);
|
||||
}
|
||||
|
||||
String _formatDate(DateTime dateTime) {
|
||||
final utc = dateTime.toUtc();
|
||||
final year = utc.year.toString().padLeft(4, '0');
|
||||
final month = utc.month.toString().padLeft(2, '0');
|
||||
final day = utc.day.toString().padLeft(2, '0');
|
||||
return '$year-$month-$day';
|
||||
}
|
||||
}
|
||||
|
||||
class _RapidOrderPayload {
|
||||
final String vendorId;
|
||||
final String hub;
|
||||
final String location;
|
||||
final DateTime date;
|
||||
final List<_RapidShiftPayload> shifts;
|
||||
|
||||
const _RapidOrderPayload({
|
||||
required this.vendorId,
|
||||
required this.hub,
|
||||
required this.location,
|
||||
required this.date,
|
||||
required this.shifts,
|
||||
});
|
||||
}
|
||||
|
||||
class _RapidShiftPayload {
|
||||
final int workersNeeded;
|
||||
final List<_RapidShiftRolePayload> roles;
|
||||
|
||||
const _RapidShiftPayload({
|
||||
required this.workersNeeded,
|
||||
required this.roles,
|
||||
});
|
||||
}
|
||||
|
||||
class _RapidShiftRolePayload {
|
||||
final String roleId;
|
||||
final int count;
|
||||
final DateTime startTime;
|
||||
final DateTime endTime;
|
||||
final double totalValue;
|
||||
|
||||
const _RapidShiftRolePayload({
|
||||
required this.roleId,
|
||||
required this.count,
|
||||
required this.startTime,
|
||||
required this.endTime,
|
||||
required this.totalValue,
|
||||
});
|
||||
|
||||
double get hours {
|
||||
final minutes = endTime.difference(startTime).inMinutes;
|
||||
return minutes / 60.0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user