Implemented new set article mechanism for unscannable articles
This commit is contained in:
@ -14,3 +14,7 @@ A few resources to get you started if this is your first Flutter project:
|
|||||||
For help getting started with Flutter development, view the
|
For help getting started with Flutter development, view the
|
||||||
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
||||||
samples, guidance on mobile development, and a full API reference.
|
samples, guidance on mobile development, and a full API reference.
|
||||||
|
|
||||||
|
## JSON code generation
|
||||||
|
|
||||||
|
use `dart run build_runner watch --delete-conflicting-outputs` for generating
|
||||||
23
lib/dto/set_article_amount_request.dart
Normal file
23
lib/dto/set_article_amount_request.dart
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
|
part 'set_article_amount_request.g.dart';
|
||||||
|
|
||||||
|
@JsonSerializable(fieldRename: FieldRename.snake)
|
||||||
|
class SetArticleAmountRequestDTO {
|
||||||
|
SetArticleAmountRequestDTO({
|
||||||
|
required this.articleId,
|
||||||
|
required this.deliveryId,
|
||||||
|
required this.amount,
|
||||||
|
this.reason
|
||||||
|
});
|
||||||
|
|
||||||
|
String deliveryId;
|
||||||
|
int amount;
|
||||||
|
String articleId;
|
||||||
|
String? reason;
|
||||||
|
|
||||||
|
factory SetArticleAmountRequestDTO.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SetArticleAmountRequestDTOFromJson(json);
|
||||||
|
|
||||||
|
Map<dynamic, dynamic> toJson() => _$SetArticleAmountRequestDTOToJson(this);
|
||||||
|
}
|
||||||
21
lib/dto/set_article_amount_response.dart
Normal file
21
lib/dto/set_article_amount_response.dart
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import 'package:hl_lieferservice/dto/basic_response.dart';
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
|
part 'set_article_amount_response.g.dart';
|
||||||
|
|
||||||
|
@JsonSerializable(fieldRename: FieldRename.snake)
|
||||||
|
class SetArticleAmountResponseDTO extends BasicResponseDTO {
|
||||||
|
SetArticleAmountResponseDTO({
|
||||||
|
required super.succeeded,
|
||||||
|
required super.message,
|
||||||
|
this.noteId
|
||||||
|
});
|
||||||
|
|
||||||
|
String? noteId;
|
||||||
|
|
||||||
|
factory SetArticleAmountResponseDTO.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SetArticleAmountResponseDTOFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<dynamic, dynamic> toJson() => _$SetArticleAmountResponseDTOToJson(this);
|
||||||
|
}
|
||||||
@ -5,7 +5,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:hl_lieferservice/feature/delivery/bloc/tour_event.dart';
|
import 'package:hl_lieferservice/feature/delivery/bloc/tour_event.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/bloc/tour_state.dart';
|
import 'package:hl_lieferservice/feature/delivery/bloc/tour_state.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/overview/model/sorting_information.dart';
|
import 'package:hl_lieferservice/feature/delivery/overview/model/sorting_information.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/overview/repository/tour_repository.dart';
|
import 'package:hl_lieferservice/feature/delivery/repository/tour_repository.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/overview/service/distance_service.dart';
|
import 'package:hl_lieferservice/feature/delivery/overview/service/distance_service.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/overview/service/reorder_service.dart';
|
import 'package:hl_lieferservice/feature/delivery/overview/service/reorder_service.dart';
|
||||||
import 'package:hl_lieferservice/model/tour.dart';
|
import 'package:hl_lieferservice/model/tour.dart';
|
||||||
@ -55,6 +55,7 @@ class TourBloc extends Bloc<TourEvent, TourState> {
|
|||||||
on<RequestSortingInformationEvent>(_requestSortingInformation);
|
on<RequestSortingInformationEvent>(_requestSortingInformation);
|
||||||
on<ReorderDeliveryEvent>(_reorderDelivery);
|
on<ReorderDeliveryEvent>(_reorderDelivery);
|
||||||
on<CarsLoadedEvent>(_carsLoaded);
|
on<CarsLoadedEvent>(_carsLoaded);
|
||||||
|
on<SetArticleAmountEvent>(_setArticleAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -64,6 +65,33 @@ class TourBloc extends Bloc<TourEvent, TourState> {
|
|||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _setArticleAmount(
|
||||||
|
SetArticleAmountEvent event,
|
||||||
|
Emitter<TourState> emit,
|
||||||
|
) async {
|
||||||
|
final currentState = state;
|
||||||
|
if (currentState is TourLoaded) {
|
||||||
|
opBloc.add(LoadOperation());
|
||||||
|
try {
|
||||||
|
await tourRepository.setArticleAmount(
|
||||||
|
event.deliveryId,
|
||||||
|
event.articleId,
|
||||||
|
event.amount,
|
||||||
|
event.reason
|
||||||
|
);
|
||||||
|
|
||||||
|
opBloc.add(FinishOperation());
|
||||||
|
} catch (e, st) {
|
||||||
|
opBloc.add(
|
||||||
|
FailOperation(message: "Fehler beim Ändern der Menge des Artikels"),
|
||||||
|
);
|
||||||
|
|
||||||
|
debugPrint("$e");
|
||||||
|
debugPrint("$st");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _carsLoaded(CarsLoadedEvent event, Emitter<TourState> emit) {
|
void _carsLoaded(CarsLoadedEvent event, Emitter<TourState> emit) {
|
||||||
final currentState = state;
|
final currentState = state;
|
||||||
if (currentState is TourLoaded) {
|
if (currentState is TourLoaded) {
|
||||||
@ -78,13 +106,16 @@ class TourBloc extends Bloc<TourEvent, TourState> {
|
|||||||
) async {
|
) async {
|
||||||
final currentState = state;
|
final currentState = state;
|
||||||
if (currentState is TourLoaded) {
|
if (currentState is TourLoaded) {
|
||||||
int newPosition = event.newPosition == currentState.sortingInformation.sorting.length ? event.newPosition - 1 : event.newPosition;
|
int newPosition =
|
||||||
SortingInformation informationOld = currentState.sortingInformation.sorting
|
event.newPosition == currentState.sortingInformation.sorting.length
|
||||||
.firstWhere((info) => info.position == event.oldPosition);
|
? event.newPosition - 1
|
||||||
|
: event.newPosition;
|
||||||
SortingInformation information = currentState
|
SortingInformation informationOld = currentState
|
||||||
.sortingInformation
|
.sortingInformation
|
||||||
.sorting
|
.sorting
|
||||||
|
.firstWhere((info) => info.position == event.oldPosition);
|
||||||
|
|
||||||
|
SortingInformation information = currentState.sortingInformation.sorting
|
||||||
.firstWhere((info) => info.position == newPosition);
|
.firstWhere((info) => info.position == newPosition);
|
||||||
|
|
||||||
information.position = event.oldPosition;
|
information.position = event.oldPosition;
|
||||||
|
|||||||
@ -203,3 +203,17 @@ class FinishDeliveryEvent extends TourEvent {
|
|||||||
Uint8List customerSignature;
|
Uint8List customerSignature;
|
||||||
Uint8List driverSignature;
|
Uint8List driverSignature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SetArticleAmountEvent extends TourEvent {
|
||||||
|
final String deliveryId;
|
||||||
|
final String articleId;
|
||||||
|
final String? reason;
|
||||||
|
final int amount;
|
||||||
|
|
||||||
|
SetArticleAmountEvent({
|
||||||
|
required this.deliveryId,
|
||||||
|
required this.articleId,
|
||||||
|
required this.amount,
|
||||||
|
this.reason,
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -23,6 +23,10 @@ class _ArticleListItem extends State<ArticleListItem> {
|
|||||||
Color? color;
|
Color? color;
|
||||||
Color? textColor;
|
Color? textColor;
|
||||||
|
|
||||||
|
if (!widget.article.scannable) {
|
||||||
|
amount = widget.article.amount;
|
||||||
|
}
|
||||||
|
|
||||||
if (amount == 0) {
|
if (amount == 0) {
|
||||||
color = Colors.redAccent;
|
color = Colors.redAccent;
|
||||||
textColor = Theme.of(context).colorScheme.onSecondary;
|
textColor = Theme.of(context).colorScheme.onSecondary;
|
||||||
@ -56,7 +60,8 @@ class _ArticleListItem extends State<ArticleListItem> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (widget.article.unscanned()) {
|
if ((widget.article.unscanned() && widget.article.scannable) ||
|
||||||
|
!widget.article.scannable && widget.article.amount == 0) {
|
||||||
actionButton = IconButton.outlined(
|
actionButton = IconButton.outlined(
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
backgroundColor: WidgetStatePropertyAll(Colors.blueAccent),
|
backgroundColor: WidgetStatePropertyAll(Colors.blueAccent),
|
||||||
|
|||||||
@ -20,33 +20,86 @@ class ResetArticleAmountDialog extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ResetArticleAmountDialogState extends State<ResetArticleAmountDialog> {
|
class _ResetArticleAmountDialogState extends State<ResetArticleAmountDialog> {
|
||||||
|
int _selectedAmount = 1;
|
||||||
|
|
||||||
void _reset() {
|
void _reset() {
|
||||||
context.read<TourBloc>().add(
|
String deliveryId = widget.deliveryId;
|
||||||
ResetScanAmountEvent(
|
String articleId = widget.article.internalId.toString();
|
||||||
articleId: widget.article.internalId.toString(),
|
|
||||||
deliveryId: widget.deliveryId,
|
if (widget.article.scannable) {
|
||||||
),
|
context.read<TourBloc>().add(
|
||||||
);
|
ResetScanAmountEvent(
|
||||||
|
articleId: widget.article.internalId.toString(),
|
||||||
|
deliveryId: widget.deliveryId,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
debugPrint("ID: $articleId");
|
||||||
|
debugPrint("AMOUNT :$_selectedAmount");
|
||||||
|
|
||||||
|
context.read<TourBloc>().add(
|
||||||
|
SetArticleAmountEvent(
|
||||||
|
deliveryId: deliveryId,
|
||||||
|
articleId: articleId,
|
||||||
|
amount: _selectedAmount,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _amountSelection() {
|
||||||
|
final list = List.generate(3, (index) => index + 1);
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text("Anzahl:", style: Theme.of(context).textTheme.labelLarge),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(10),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
|
children:
|
||||||
|
list
|
||||||
|
.map(
|
||||||
|
(index) => ChoiceChip(
|
||||||
|
label: Text("$index"),
|
||||||
|
selected: _selectedAmount == index,
|
||||||
|
onSelected: (bool selected) {
|
||||||
|
setState(() {
|
||||||
|
_selectedAmount = index;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: const Text("Anzahl Artikel zurücksetzen?"),
|
title: const Text("Anzahl Artikel zurücksetzen?"),
|
||||||
content: SizedBox(
|
content: SizedBox(
|
||||||
height: 120,
|
height: MediaQuery.of(context).size.height * 0.25,
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
const Text("Wollen Sie die entfernten Artikel wieder hinzufügen?"),
|
const Text("Wollen Sie die entfernten Artikel wieder hinzufügen?"),
|
||||||
|
!widget.article.scannable ? _amountSelection() : Container(),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children: [
|
children: [
|
||||||
FilledButton(
|
FilledButton(
|
||||||
onPressed: _reset,
|
onPressed: _reset,
|
||||||
child: const Text("Zurücksetzen"),
|
child:
|
||||||
|
widget.article.scannable
|
||||||
|
? const Text("Zurücksetzen")
|
||||||
|
: const Text("Hinzufügen"),
|
||||||
),
|
),
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
|||||||
@ -7,7 +7,11 @@ import 'package:hl_lieferservice/feature/delivery/bloc/tour_event.dart';
|
|||||||
import '../../../../../model/article.dart';
|
import '../../../../../model/article.dart';
|
||||||
|
|
||||||
class ArticleUnscanDialog extends StatefulWidget {
|
class ArticleUnscanDialog extends StatefulWidget {
|
||||||
const ArticleUnscanDialog({super.key, required this.article, required this.deliveryId});
|
const ArticleUnscanDialog({
|
||||||
|
super.key,
|
||||||
|
required this.article,
|
||||||
|
required this.deliveryId,
|
||||||
|
});
|
||||||
|
|
||||||
final String deliveryId;
|
final String deliveryId;
|
||||||
final Article article;
|
final Article article;
|
||||||
@ -23,14 +27,32 @@ class _ArticleUnscanDialogState extends State<ArticleUnscanDialog> {
|
|||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
void _unscan() {
|
void _unscan() {
|
||||||
context.read<TourBloc>().add(
|
int amountToBeDeleted = int.parse(unscanAmountController.text);
|
||||||
UnscanArticleEvent(
|
String deliveryId = widget.deliveryId;
|
||||||
deliveryId: widget.deliveryId,
|
String articleId = widget.article.internalId.toString();
|
||||||
articleId: widget.article.internalId.toString(),
|
String reason = unscanNoteController.text;
|
||||||
newAmount: int.parse(unscanAmountController.text),
|
|
||||||
reason: unscanNoteController.text,
|
if (widget.article.scannable) {
|
||||||
),
|
context.read<TourBloc>().add(
|
||||||
);
|
UnscanArticleEvent(
|
||||||
|
deliveryId: deliveryId,
|
||||||
|
articleId: articleId,
|
||||||
|
newAmount: amountToBeDeleted,
|
||||||
|
reason: reason,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// If the article is not scannable we need to adjust the quantity of the article
|
||||||
|
// directly.
|
||||||
|
context.read<TourBloc>().add(
|
||||||
|
SetArticleAmountEvent(
|
||||||
|
deliveryId: deliveryId,
|
||||||
|
articleId: articleId,
|
||||||
|
amount: widget.article.amount - amountToBeDeleted,
|
||||||
|
reason: reason
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -136,6 +136,9 @@ class _DeliveryDetailState extends State<DeliveryDetail> {
|
|||||||
driverSignature: driver,
|
driverSignature: driver,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Navigator.pop(context);
|
||||||
|
Navigator.pop(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _stepsNavigation(Delivery delivery) {
|
Widget _stepsNavigation(Delivery delivery) {
|
||||||
|
|||||||
@ -117,8 +117,6 @@ class _SignatureViewState extends State<SignatureView> {
|
|||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final current = state;
|
final current = state;
|
||||||
|
|
||||||
debugPrint("STATE: $current");
|
|
||||||
|
|
||||||
if (current is NoteLoaded) {
|
if (current is NoteLoaded) {
|
||||||
if (current.notes.isEmpty) {
|
if (current.notes.isEmpty) {
|
||||||
return const SizedBox(
|
return const SizedBox(
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import 'package:hl_lieferservice/dto/discount_remove_response.dart';
|
|||||||
import 'package:hl_lieferservice/dto/discount_update_response.dart';
|
import 'package:hl_lieferservice/dto/discount_update_response.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/detail/repository/note_repository.dart';
|
import 'package:hl_lieferservice/feature/delivery/detail/repository/note_repository.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/detail/service/notes_service.dart';
|
import 'package:hl_lieferservice/feature/delivery/detail/service/notes_service.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/overview/service/delivery_info_service.dart';
|
import 'package:hl_lieferservice/feature/delivery/service/tour_service.dart';
|
||||||
import 'package:hl_lieferservice/model/delivery.dart';
|
import 'package:hl_lieferservice/model/delivery.dart';
|
||||||
|
|
||||||
class DeliveryRepository {
|
class DeliveryRepository {
|
||||||
|
|||||||
@ -60,7 +60,7 @@ class _DeliveryListState extends State<DeliveryList> {
|
|||||||
.where(
|
.where(
|
||||||
(delivery) =>
|
(delivery) =>
|
||||||
delivery.carId == widget.selectedCarId &&
|
delivery.carId == widget.selectedCarId &&
|
||||||
delivery.allArticlesScanned(),
|
delivery.allArticlesScanned() || delivery.state == DeliveryState.finished,
|
||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:hl_lieferservice/feature/delivery/overview/service/delivery_info_service.dart';
|
import 'package:hl_lieferservice/dto/set_article_amount_response.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/service/tour_service.dart';
|
||||||
import 'package:hl_lieferservice/model/delivery.dart';
|
import 'package:hl_lieferservice/model/delivery.dart';
|
||||||
import 'package:hl_lieferservice/model/tour.dart';
|
import 'package:hl_lieferservice/model/tour.dart';
|
||||||
import 'package:rxdart/rxdart.dart';
|
import 'package:rxdart/rxdart.dart';
|
||||||
@ -9,8 +10,8 @@ import '../../../../dto/discount_add_response.dart';
|
|||||||
import '../../../../dto/discount_remove_response.dart';
|
import '../../../../dto/discount_remove_response.dart';
|
||||||
import '../../../../dto/discount_update_response.dart';
|
import '../../../../dto/discount_update_response.dart';
|
||||||
import '../../../../model/article.dart';
|
import '../../../../model/article.dart';
|
||||||
import '../../detail/repository/note_repository.dart';
|
import '../detail/repository/note_repository.dart';
|
||||||
import '../../detail/service/notes_service.dart';
|
import '../detail/service/notes_service.dart';
|
||||||
|
|
||||||
enum ScanResult { scanned, alreadyScanned, notFound }
|
enum ScanResult { scanned, alreadyScanned, notFound }
|
||||||
|
|
||||||
@ -172,13 +173,19 @@ class TourRepository {
|
|||||||
Delivery delivery = tour.deliveries.firstWhere(
|
Delivery delivery = tour.deliveries.firstWhere(
|
||||||
(delivery) => delivery.id == deliveryId,
|
(delivery) => delivery.id == deliveryId,
|
||||||
);
|
);
|
||||||
|
Article discountArticle = Article.fromDTO(response.values.article);
|
||||||
delivery.totalNetValue = response.values.receipt.net;
|
delivery.totalNetValue = response.values.receipt.net;
|
||||||
delivery.totalGrossValue = response.values.receipt.gross;
|
delivery.totalGrossValue = response.values.receipt.gross;
|
||||||
|
|
||||||
delivery.discount = Discount(
|
delivery.discount = Discount(
|
||||||
article: Article.fromDTO(response.values.article),
|
article: Article.fromDTO(response.values.article),
|
||||||
note: response.values.note.noteDescription,
|
note: response.values.note.noteDescription,
|
||||||
noteId: response.values.note.rowId,
|
noteId: response.values.note.rowId,
|
||||||
);
|
);
|
||||||
|
delivery.articles = [
|
||||||
|
...delivery.articles,
|
||||||
|
discountArticle,
|
||||||
|
];
|
||||||
|
|
||||||
_tourStream.add(tour);
|
_tourStream.add(tour);
|
||||||
}
|
}
|
||||||
@ -275,6 +282,45 @@ class TourRepository {
|
|||||||
|
|
||||||
Future<void> finishDelivery(String deliveryId) async {
|
Future<void> finishDelivery(String deliveryId) async {
|
||||||
await _changeState(deliveryId, DeliveryState.finished);
|
await _changeState(deliveryId, DeliveryState.finished);
|
||||||
|
Delivery delivery = _tourStream.value!.deliveries.firstWhere(
|
||||||
|
(delivery) => delivery.id == deliveryId,
|
||||||
|
);
|
||||||
|
|
||||||
|
await _updateDelivery(delivery);
|
||||||
|
await service.finishDelivery(deliveryId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setArticleAmount(
|
||||||
|
String deliveryId,
|
||||||
|
String articleId,
|
||||||
|
int amount,
|
||||||
|
String? reason,
|
||||||
|
) async {
|
||||||
|
if (!_tourStream.hasValue) {
|
||||||
|
throw TourNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
SetArticleAmountResponseDTO dto = await service.setArticleAmount(
|
||||||
|
deliveryId,
|
||||||
|
articleId,
|
||||||
|
amount,
|
||||||
|
reason,
|
||||||
|
);
|
||||||
|
|
||||||
|
Delivery delivery = _tourStream.value!.deliveries.firstWhere(
|
||||||
|
(delivery) => delivery.id == deliveryId,
|
||||||
|
);
|
||||||
|
Article article = delivery.articles.firstWhere(
|
||||||
|
(article) => article.internalId == int.parse(articleId),
|
||||||
|
);
|
||||||
|
|
||||||
|
article.amount = amount;
|
||||||
|
article.removeNoteId = dto.noteId;
|
||||||
|
_tourStream.add(_tourStream.value);
|
||||||
|
} catch (_) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _changeState(String deliveryId, DeliveryState state) async {
|
Future<void> _changeState(String deliveryId, DeliveryState state) async {
|
||||||
@ -7,18 +7,20 @@ import 'package:hl_lieferservice/dto/delivery_update.dart';
|
|||||||
import 'package:hl_lieferservice/dto/delivery_update_response.dart';
|
import 'package:hl_lieferservice/dto/delivery_update_response.dart';
|
||||||
import 'package:hl_lieferservice/dto/payment.dart';
|
import 'package:hl_lieferservice/dto/payment.dart';
|
||||||
import 'package:hl_lieferservice/dto/payments.dart';
|
import 'package:hl_lieferservice/dto/payments.dart';
|
||||||
|
import 'package:hl_lieferservice/dto/set_article_amount_request.dart';
|
||||||
|
import 'package:hl_lieferservice/dto/set_article_amount_response.dart';
|
||||||
import 'package:hl_lieferservice/model/car.dart';
|
import 'package:hl_lieferservice/model/car.dart';
|
||||||
import 'package:hl_lieferservice/model/delivery.dart';
|
import 'package:hl_lieferservice/model/delivery.dart';
|
||||||
import 'package:hl_lieferservice/model/tour.dart';
|
import 'package:hl_lieferservice/model/tour.dart';
|
||||||
import 'package:hl_lieferservice/util.dart';
|
import 'package:hl_lieferservice/util.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
|
|
||||||
import '../../../../dto/basic_response.dart';
|
import '../../../dto/basic_response.dart';
|
||||||
import '../../../../dto/discount_add_response.dart';
|
import '../../../dto/discount_add_response.dart';
|
||||||
import '../../../../dto/discount_remove_response.dart';
|
import '../../../dto/discount_remove_response.dart';
|
||||||
import '../../../../dto/discount_update_response.dart';
|
import '../../../dto/discount_update_response.dart';
|
||||||
import '../../../../dto/scan_response.dart';
|
import '../../../dto/scan_response.dart';
|
||||||
import '../../../authentication/exceptions.dart';
|
import '../../authentication/exceptions.dart';
|
||||||
|
|
||||||
class TourService {
|
class TourService {
|
||||||
TourService();
|
TourService();
|
||||||
@ -267,6 +269,76 @@ class TourService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<BasicResponseDTO> finishDelivery(String deliveryId) async {
|
||||||
|
try {
|
||||||
|
var response = await post(
|
||||||
|
urlBuilder("_web_finishDelivery"),
|
||||||
|
headers: getSessionOrThrow(),
|
||||||
|
body: {"delivery_id": deliveryId},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == HttpStatus.unauthorized) {
|
||||||
|
throw UserUnauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
debugPrint("BODY: ${response.body}");
|
||||||
|
Map<String, dynamic> responseJson = jsonDecode(response.body);
|
||||||
|
|
||||||
|
// let it throw, if the values are invalid
|
||||||
|
return BasicResponseDTO.fromJson(responseJson);
|
||||||
|
} catch (e, st) {
|
||||||
|
debugPrint("ERROR while adding discount");
|
||||||
|
debugPrint(e.toString());
|
||||||
|
debugPrint(st.toString());
|
||||||
|
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<SetArticleAmountResponseDTO> setArticleAmount(
|
||||||
|
String deliveryId,
|
||||||
|
String articleId,
|
||||||
|
int amount,
|
||||||
|
String? reason,
|
||||||
|
) async {
|
||||||
|
try {
|
||||||
|
var response = await post(
|
||||||
|
urlBuilder("_web_setArticleAmount"),
|
||||||
|
headers: {...getSessionOrThrow(), "Content-Type": "application/json"},
|
||||||
|
body: jsonEncode(
|
||||||
|
SetArticleAmountRequestDTO(
|
||||||
|
articleId: articleId,
|
||||||
|
deliveryId: deliveryId,
|
||||||
|
amount: amount,
|
||||||
|
reason: reason,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == HttpStatus.unauthorized) {
|
||||||
|
throw UserUnauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
debugPrint("BODY: ${response.body}");
|
||||||
|
|
||||||
|
Map<String, dynamic> responseJson = jsonDecode(response.body);
|
||||||
|
// let it throw, if the values are invalid
|
||||||
|
SetArticleAmountResponseDTO responseDto =
|
||||||
|
SetArticleAmountResponseDTO.fromJson(responseJson);
|
||||||
|
|
||||||
|
if (!responseDto.succeeded) {
|
||||||
|
throw responseDto.message;
|
||||||
|
} else {
|
||||||
|
return responseDto;
|
||||||
|
}
|
||||||
|
} catch (e, st) {
|
||||||
|
debugPrint(e.toString());
|
||||||
|
debugPrint(st.toString());
|
||||||
|
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<DiscountRemoveResponseDTO> removeDiscount(String deliveryId) async {
|
Future<DiscountRemoveResponseDTO> removeDiscount(String deliveryId) async {
|
||||||
try {
|
try {
|
||||||
var response = await post(
|
var response = await post(
|
||||||
@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:hl_lieferservice/feature/delivery/bloc/tour_bloc.dart';
|
import 'package:hl_lieferservice/feature/delivery/bloc/tour_bloc.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/bloc/tour_state.dart';
|
import 'package:hl_lieferservice/feature/delivery/bloc/tour_state.dart';
|
||||||
import 'package:hl_lieferservice/feature/scan/presentation/scan_screen.dart';
|
import 'package:hl_lieferservice/feature/scan/presentation/scan_screen.dart';
|
||||||
|
import 'package:hl_lieferservice/model/delivery.dart';
|
||||||
import 'package:hl_lieferservice/model/tour.dart';
|
import 'package:hl_lieferservice/model/tour.dart';
|
||||||
import 'package:hl_lieferservice/widget/home/bloc/navigation_bloc.dart';
|
import 'package:hl_lieferservice/widget/home/bloc/navigation_bloc.dart';
|
||||||
import 'package:hl_lieferservice/widget/home/bloc/navigation_event.dart';
|
import 'package:hl_lieferservice/widget/home/bloc/navigation_event.dart';
|
||||||
@ -36,7 +37,7 @@ class _ScanPageState extends State<ScanPage> {
|
|||||||
|
|
||||||
Widget _tourSteps(Tour tour) {
|
Widget _tourSteps(Tour tour) {
|
||||||
var allArticlesScanned = tour.deliveries.every(
|
var allArticlesScanned = tour.deliveries.every(
|
||||||
(delivery) => delivery.allArticlesScanned(),
|
(delivery) => delivery.allArticlesScanned() || delivery.state == DeliveryState.finished,
|
||||||
);
|
);
|
||||||
|
|
||||||
return Stepper(
|
return Stepper(
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:hl_lieferservice/dto/contact_person.dart';
|
import 'package:hl_lieferservice/dto/contact_person.dart';
|
||||||
import 'package:hl_lieferservice/dto/delivery.dart';
|
import 'package:hl_lieferservice/dto/delivery.dart';
|
||||||
import 'package:hl_lieferservice/dto/image_note_response.dart';
|
import 'package:hl_lieferservice/dto/image_note_response.dart';
|
||||||
@ -297,11 +296,7 @@ class Delivery implements Comparable<Delivery> {
|
|||||||
List<Article> getDeliveredArticles() {
|
List<Article> getDeliveredArticles() {
|
||||||
return articles
|
return articles
|
||||||
.where(
|
.where(
|
||||||
(article) {
|
(article) => article.scannedAmount > 0 || !article.scannable,
|
||||||
debugPrint("Scannable: ${article.scannable}");
|
|
||||||
|
|
||||||
return article.scannedAmount > 0 || !article.scannable;
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,13 +6,13 @@ import 'package:hl_lieferservice/feature/authentication/presentation/login_enfor
|
|||||||
import 'package:hl_lieferservice/feature/authentication/service/userinfo.dart';
|
import 'package:hl_lieferservice/feature/authentication/service/userinfo.dart';
|
||||||
import 'package:hl_lieferservice/feature/cars/presentation/car_management_page.dart';
|
import 'package:hl_lieferservice/feature/cars/presentation/car_management_page.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/bloc/tour_bloc.dart';
|
import 'package:hl_lieferservice/feature/delivery/bloc/tour_bloc.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/overview/repository/tour_repository.dart';
|
import 'package:hl_lieferservice/feature/delivery/repository/tour_repository.dart';
|
||||||
import 'package:hl_lieferservice/widget/home/bloc/navigation_bloc.dart';
|
import 'package:hl_lieferservice/widget/home/bloc/navigation_bloc.dart';
|
||||||
import 'package:hl_lieferservice/widget/operations/bloc/operation_bloc.dart';
|
import 'package:hl_lieferservice/widget/operations/bloc/operation_bloc.dart';
|
||||||
import 'package:hl_lieferservice/widget/operations/presentation/operation_view_enforcer.dart';
|
import 'package:hl_lieferservice/widget/operations/presentation/operation_view_enforcer.dart';
|
||||||
|
|
||||||
import 'package:hl_lieferservice/bloc/app_states.dart';
|
import 'package:hl_lieferservice/bloc/app_states.dart';
|
||||||
import '../feature/delivery/overview/service/delivery_info_service.dart';
|
import '../feature/delivery/service/tour_service.dart';
|
||||||
import 'home/presentation/home.dart';
|
import 'home/presentation/home.dart';
|
||||||
|
|
||||||
class DeliveryApp extends StatefulWidget {
|
class DeliveryApp extends StatefulWidget {
|
||||||
|
|||||||
Reference in New Issue
Block a user