import 'package:flutter/widgets.dart'; import 'package:mobile_scanner/mobile_scanner.dart'; import 'package:seshat/data/repositories/bal_repository.dart'; import 'package:seshat/data/repositories/book_instance_repository.dart'; import 'package:seshat/data/repositories/book_repository.dart'; import 'package:seshat/data/repositories/owner_repository.dart'; import 'package:seshat/domain/models/bal.dart'; import 'package:seshat/domain/models/book.dart'; import 'package:seshat/domain/models/book_instance.dart'; import 'package:seshat/domain/models/book_stack.dart'; import 'package:seshat/domain/models/owner.dart'; import 'package:seshat/utils/command.dart'; import 'package:seshat/utils/result.dart'; class SellViewModel extends ChangeNotifier { SellViewModel({ required BalRepository balRepository, required BookInstanceRepository bookInstanceRepository, required BookRepository bookRepository, required OwnerRepository ownerRepository, }) : _balRepository = balRepository, _bookInstanceRepository = bookInstanceRepository, _bookRepository = bookRepository, _ownerRepository = ownerRepository { load = Command0(_load)..execute(); } final BalRepository _balRepository; final BookInstanceRepository _bookInstanceRepository; final BookRepository _bookRepository; final OwnerRepository _ownerRepository; bool _showScan = false; bool get showScan => _showScan; set showScan(bool newValue) { _showScan = newValue; notifyListeners(); } /* * =============================== * =====[ BOOKS & INSTANCES ]===== * =============================== */ final List _soldBooks = []; List get soldBooks => _soldBooks; final List _scannedBooks = []; List get scannedBooks => _scannedBooks; bool isScanLoaded = false; bool isSendingSell = false; double minimumAmount = 0; void sellBook(BookStack addedBook) { minimumAmount += addedBook.instance.price; _soldBooks.add(addedBook); notifyListeners(); } void sendSell(double givenAmount) async { isSendingSell = true; notifyListeners(); List toSend = []; int nbOfPl = 0; for (BookStack book in _soldBooks) { if (book.instance.price != 0) { book.instance.soldPrice = book.instance.price; givenAmount -= book.instance.price; toSend.add(book.instance); } else { nbOfPl++; } } if (nbOfPl != 0) { double amountPerPl = givenAmount / nbOfPl; for (BookStack book in _soldBooks) { if (book.instance.price == 0) { book.instance.soldPrice = amountPerPl; toSend.add(book.instance); } } } await _bookInstanceRepository.sellBooks(toSend); _soldBooks.clear(); isSendingSell = false; notifyListeners(); } void deleteBook(int id) { _soldBooks.removeWhere((book) => book.instance.id == id); notifyListeners(); } Future scanBook(BarcodeCapture barcode) async { int ean = int.parse(barcode.barcodes.first.rawValue!); Bal? bal = await _balRepository.ongoingBal(); _scannedBooks.clear(); final result = await _bookInstanceRepository.getByEan(bal!.id, ean); switch (result) { case Ok(): for (BookInstance instance in result.value) { if (instance.available == false) { continue; } if (_soldBooks .where((book) => book.instance.id == instance.id) .isNotEmpty) { continue; } Book book; final result2 = await _bookRepository.getBookById(instance.bookId); switch (result2) { case Ok(): book = result2.value; break; case Error(): continue; } Owner owner; final result3 = await _ownerRepository.getOwnerById(instance.ownerId); switch (result3) { case Ok(): owner = result3.value; break; case Error(): continue; } _scannedBooks.add(BookStack(book, instance, owner)); } break; case Error(): break; } isScanLoaded = true; notifyListeners(); return; } /* * ================= * =====[ BAL ]===== * ================= */ Bal? _currentBal; get currentBal => _currentBal; /* * ================================= * =====[ COMMAND AND LOADING ]===== * ================================= */ late final Command0 load; bool isLoaded = false; Future> _load() async { final result1 = await _loadBal(); switch (result1) { case Ok(): isLoaded = true; break; default: break; } notifyListeners(); return result1; } Future> _loadBal() async { final result = await _balRepository.getBals(); switch (result) { case Ok(): _currentBal = result.value .where((bal) => bal.state == BalState.ongoing) .firstOrNull; break; case Error(): break; } return result; } }