diff --git a/lib/base/strings.dart b/lib/base/strings.dart index de8dd2f06..a3f2951bb 100644 --- a/lib/base/strings.dart +++ b/lib/base/strings.dart @@ -138,6 +138,7 @@ abstract class Strings { static const confirmSwipe = 'Confirm use of ticket'; static const confirmPurchase = 'Confirm purchase'; static const tapHereToCancel = 'Tap here to cancel'; + static const String paymentConfirmationButtonRedeem = 'Get your free product'; static String paymentConfirmationTopTickets(int amount, String title) { return "You're buying $amount $title tickets"; @@ -147,7 +148,7 @@ abstract class Strings { return "You're buying and swiping $amount $title"; } - static String paymentConfirmationBottom(int price) { + static String paymentConfirmationBottomPurchase(int price) { return 'Pay $price,- with...'; } diff --git a/lib/cubits/purchase/purchase_cubit.dart b/lib/cubits/purchase/purchase_cubit.dart index 62f313e4e..dc09bd6b1 100644 --- a/lib/cubits/purchase/purchase_cubit.dart +++ b/lib/cubits/purchase/purchase_cubit.dart @@ -16,20 +16,21 @@ class PurchaseCubit extends Cubit { PurchaseCubit({required this.paymentHandler, required this.product}) : super(const PurchaseInitial()); - Future payWithMobilePay() async { + Future pay() async { + sl().beginCheckoutEvent(product); + if (state is PurchaseInitial) { - sl().beginCheckoutEvent(product); emit(const PurchaseStarted()); final either = await paymentHandler.initPurchase(product.id); either.fold( (error) => emit(PurchaseError(error.reason)), - (payment) async { - if (payment.status != PaymentStatus.error) { + (payment) { + if (payment.status == PaymentStatus.completed) { + emit(PurchaseCompleted(payment)); + } else if (payment.status == PaymentStatus.awaitingPayment) { emit(PurchaseProcessing(payment)); - await paymentHandler - .invokePaymentMethod(Uri.parse(payment.deeplink)); } else { emit(PurchasePaymentRejected(payment)); } diff --git a/lib/cubits/receipt/receipt_cubit.dart b/lib/cubits/receipt/receipt_cubit.dart index 274eca0f5..8ca7bcf56 100644 --- a/lib/cubits/receipt/receipt_cubit.dart +++ b/lib/cubits/receipt/receipt_cubit.dart @@ -1,5 +1,5 @@ import 'package:coffeecard/base/strings.dart'; -import 'package:coffeecard/data/repositories/v1/receipt_repository.dart'; +import 'package:coffeecard/data/repositories/v2/receipt_repository.dart'; import 'package:coffeecard/models/receipts/receipt.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/lib/data/repositories/v1/receipt_repository.dart b/lib/data/repositories/v1/receipt_repository.dart deleted file mode 100644 index f978fbbf8..000000000 --- a/lib/data/repositories/v1/receipt_repository.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'package:coffeecard/core/errors/failures.dart'; -import 'package:coffeecard/core/network/network_request_executor.dart'; -import 'package:coffeecard/generated/api/coffeecard_api.swagger.dart'; -import 'package:coffeecard/models/receipts/receipt.dart'; -import 'package:dartz/dartz.dart'; - -class ReceiptRepository { - ReceiptRepository({ - required this.apiV1, - required this.executor, - }); - - final CoffeecardApi apiV1; - final NetworkRequestExecutor executor; - - /// Retrieves all of the users receipts - /// This includes both their used tickets and purchased tickets - Future>> getUserReceipts() async { - final usedTicketsEither = await executor( - () => apiV1.apiV1TicketsGet(used: true), - ); - - final purchasedTicketsEither = await executor( - apiV1.apiV1PurchasesGet, - ); - - return usedTicketsEither.bind( - (usedTickets) => purchasedTicketsEither.map( - (purchasedTickets) { - final allTickets = [ - ...usedTickets.map(Receipt.fromTicketDTO), - ...purchasedTickets.map(Receipt.fromPurchaseDTO) - ]; - allTickets.sort((a, b) => b.timeUsed.compareTo(a.timeUsed)); - return allTickets; - }, - ), - ); - } -} diff --git a/lib/data/repositories/v1/ticket_repository.dart b/lib/data/repositories/v1/ticket_repository.dart index 5479c18da..a0872c21f 100644 --- a/lib/data/repositories/v1/ticket_repository.dart +++ b/lib/data/repositories/v1/ticket_repository.dart @@ -47,6 +47,6 @@ class TicketRepository { ), ); - return result.map(Receipt.fromTicketDTO); + return result.map(Receipt.fromTicketDto); } } diff --git a/lib/data/repositories/v2/receipt_repository.dart b/lib/data/repositories/v2/receipt_repository.dart new file mode 100644 index 000000000..54ccf0325 --- /dev/null +++ b/lib/data/repositories/v2/receipt_repository.dart @@ -0,0 +1,50 @@ +import 'package:coffeecard/core/errors/failures.dart'; +import 'package:coffeecard/core/network/network_request_executor.dart'; +import 'package:coffeecard/data/repositories/v1/product_repository.dart'; +import 'package:coffeecard/generated/api/coffeecard_api_v2.swagger.dart'; +import 'package:coffeecard/models/receipts/receipt.dart'; +import 'package:dartz/dartz.dart'; + +class ReceiptRepository { + ReceiptRepository({ + required this.productRepository, + required this.apiV2, + required this.executor, + }); + + final CoffeecardApiV2 apiV2; + final ProductRepository productRepository; + final NetworkRequestExecutor executor; + + /// Retrieves all of the users receipts + /// This includes both their used tickets and purchased tickets + Future>> getUserReceipts() async { + final usedTicketsFutureEither = executor( + () => apiV2.apiV2TicketsGet(includeUsed: true), + ); + final purchasedTicketsFutureEither = executor( + apiV2.apiV2PurchasesGet, + ); + + final usedTicketsEither = (await usedTicketsFutureEither) + .map((dto) => dto.map(Receipt.fromTicketResponse)); + final purchasedTicketsEither = (await purchasedTicketsFutureEither).map( + (r) => r.map( + (purchase) => Receipt.fromSimplePurchaseResponse( + purchase, + ), + ), + ); + + return usedTicketsEither.fold( + (l) => Left(l), + (usedTickets) => purchasedTicketsEither.map( + (purchasedTickets) { + final allTickets = [...usedTickets, ...purchasedTickets]; + allTickets.sort((a, b) => b.timeUsed.compareTo(a.timeUsed)); + return allTickets; + }, + ), + ); + } +} diff --git a/lib/models/purchase/payment.dart b/lib/models/purchase/payment.dart index 175421330..1a5faf686 100644 --- a/lib/models/purchase/payment.dart +++ b/lib/models/purchase/payment.dart @@ -2,7 +2,6 @@ import 'package:coffeecard/models/purchase/payment_status.dart'; class Payment { final int id; - final String paymentId; final PaymentStatus status; final String deeplink; final int price; @@ -14,7 +13,6 @@ class Payment { required this.id, required this.price, required this.purchaseTime, - required this.paymentId, required this.status, required this.deeplink, required this.productId, @@ -33,7 +31,6 @@ class Payment { }) { return Payment( id: id ?? this.id, - paymentId: paymentId ?? this.paymentId, status: status ?? this.status, deeplink: deeplink ?? this.deeplink, price: price ?? this.price, diff --git a/lib/models/purchase/payment_status.dart b/lib/models/purchase/payment_status.dart index 995ed7d90..3a8ae8350 100644 --- a/lib/models/purchase/payment_status.dart +++ b/lib/models/purchase/payment_status.dart @@ -1,3 +1,5 @@ +import 'package:coffeecard/generated/api/coffeecard_api_v2.enums.swagger.dart'; + enum PaymentStatus { /// Payment is completed completed, @@ -8,11 +10,27 @@ enum PaymentStatus { /// Payment is not yet complete reserved, - // User has not approved the purchase + /// User has not approved the purchase awaitingPayment, - // User has rejected payment + /// User has rejected payment rejectedPayment, - awaitingCompletionAfterRetry, + /// Payment has been refunded + refunded; + + static PaymentStatus fromPurchaseStatus(PurchaseStatus status) { + switch (status) { + case PurchaseStatus.swaggerGeneratedUnknown: + return PaymentStatus.error; + case PurchaseStatus.completed: + return PaymentStatus.completed; + case PurchaseStatus.cancelled: + return PaymentStatus.rejectedPayment; + case PurchaseStatus.pendingpayment: + return PaymentStatus.awaitingPayment; + case PurchaseStatus.refunded: + return PaymentStatus.refunded; + } + } } diff --git a/lib/models/purchase/single_purchase.dart b/lib/models/purchase/single_purchase.dart index 7879868e6..2f62ca7e5 100644 --- a/lib/models/purchase/single_purchase.dart +++ b/lib/models/purchase/single_purchase.dart @@ -1,17 +1,18 @@ import 'package:coffeecard/generated/api/coffeecard_api_v2.swagger.dart'; +import 'package:coffeecard/models/purchase/payment_status.dart'; class SinglePurchase { final int id; final int totalAmount; final Map paymentDetails; - final String purchaseStatus; + final PaymentStatus status; final DateTime dateCreated; const SinglePurchase({ required this.id, required this.totalAmount, required this.paymentDetails, - required this.purchaseStatus, + required this.status, required this.dateCreated, }); @@ -19,6 +20,8 @@ class SinglePurchase { : id = dto.id, totalAmount = dto.totalAmount, paymentDetails = dto.paymentDetails as Map, - purchaseStatus = dto.purchaseStatus as String, + status = PaymentStatus.fromPurchaseStatus( + purchaseStatusFromJson(dto.purchaseStatus), + ), dateCreated = dto.dateCreated; } diff --git a/lib/models/receipts/receipt.dart b/lib/models/receipts/receipt.dart index 6bac01d6b..6c89e695c 100644 --- a/lib/models/receipts/receipt.dart +++ b/lib/models/receipts/receipt.dart @@ -1,4 +1,5 @@ import 'package:coffeecard/generated/api/coffeecard_api.swagger.dart'; +import 'package:coffeecard/generated/api/coffeecard_api_v2.models.swagger.dart'; enum TransactionType { purchase, ticketSwipe, placeholder } @@ -21,7 +22,7 @@ class Receipt { }); /// Creates a receipt from a used ticket DTO - Receipt.fromTicketDTO(TicketDto dto) + Receipt.fromTicketDto(TicketDto dto) : productName = dto.productName, transactionType = TransactionType.ticketSwipe, timeUsed = dto @@ -30,12 +31,23 @@ class Receipt { amountPurchased = 1, id = dto.id; - /// Creates a receipt from a purchase DTO - Receipt.fromPurchaseDTO(PurchaseDto dto) + /// Creates a receipt from a used ticket DTO + Receipt.fromTicketResponse(TicketResponse dto) : productName = dto.productName, + transactionType = TransactionType.ticketSwipe, + timeUsed = dto + .dateUsed!, // will not be null as the dto is a ticket that has been used at some point + price = 1, + amountPurchased = 1, + id = dto.id; + + /// Creates a receipt from a purchase DTO + Receipt.fromSimplePurchaseResponse( + SimplePurchaseResponse dto, + ) : productName = dto.productName, transactionType = TransactionType.purchase, timeUsed = dto.dateCreated, - price = dto.price, + price = dto.totalAmount, amountPurchased = dto.numberOfTickets, id = dto.id; } diff --git a/lib/payment/free_product_service.dart b/lib/payment/free_product_service.dart new file mode 100644 index 000000000..a0f7715df --- /dev/null +++ b/lib/payment/free_product_service.dart @@ -0,0 +1,36 @@ +import 'package:coffeecard/core/errors/failures.dart'; +import 'package:coffeecard/generated/api/coffeecard_api_v2.enums.swagger.dart'; +import 'package:coffeecard/models/purchase/payment.dart'; +import 'package:coffeecard/models/purchase/payment_status.dart'; +import 'package:coffeecard/payment/payment_handler.dart'; +import 'package:dartz/dartz.dart'; + +class FreeProductService extends PaymentHandler { + const FreeProductService({ + required super.purchaseRepository, + required super.context, + }); + + @override + Future> initPurchase(int productId) async { + final response = await purchaseRepository.initiatePurchase( + productId, + PaymentType.freepurchase, + ); + + return response.fold( + (error) => Left(error), + (purchase) => Right( + Payment( + id: purchase.id, + status: PaymentStatus.completed, + deeplink: '', + purchaseTime: purchase.dateCreated, + price: purchase.totalAmount, + productId: purchase.productId, + productName: purchase.productName, + ), + ), + ); + } +} diff --git a/lib/payment/mobilepay_service.dart b/lib/payment/mobilepay_service.dart index eb9892049..fb73f2b4e 100644 --- a/lib/payment/mobilepay_service.dart +++ b/lib/payment/mobilepay_service.dart @@ -1,31 +1,30 @@ import 'dart:io'; import 'package:coffeecard/core/errors/failures.dart'; -import 'package:coffeecard/data/repositories/v2/purchase_repository.dart'; import 'package:coffeecard/generated/api/coffeecard_api_v2.swagger.dart'; +import 'package:coffeecard/models/purchase/initiate_purchase.dart'; import 'package:coffeecard/models/purchase/payment.dart'; import 'package:coffeecard/models/purchase/payment_status.dart'; import 'package:coffeecard/payment/payment_handler.dart'; import 'package:coffeecard/utils/api_uri_constants.dart'; import 'package:coffeecard/utils/launch.dart'; import 'package:dartz/dartz.dart'; -import 'package:flutter/widgets.dart'; import 'package:url_launcher/url_launcher.dart'; -class MobilePayService implements PaymentHandler { - final PurchaseRepository _repository; - final BuildContext _context; - - MobilePayService(this._repository, this._context); - +class MobilePayService extends PaymentHandler { + MobilePayService({ + required super.purchaseRepository, + required super.context, + }); @override Future> initPurchase(int productId) async { - final response = await _repository.initiatePurchase( + final Either response; + response = await purchaseRepository.initiatePurchase( productId, PaymentType.mobilepay, ); - return response.map( + final either = response.map( (response) { final paymentDetails = MobilePayPaymentDetails.fromJsonFactory( response.paymentDetails, @@ -33,7 +32,6 @@ class MobilePayService implements PaymentHandler { return Payment( id: response.id, - paymentId: paymentDetails.paymentId, status: PaymentStatus.awaitingPayment, deeplink: paymentDetails.mobilePayAppRedirectUri, purchaseTime: response.dateCreated, @@ -43,67 +41,42 @@ class MobilePayService implements PaymentHandler { ); }, ); - } - @override - Future invokePaymentMethod(Uri uri) async { - if (await canLaunchUrl(uri)) { - await launchUrl(uri, mode: LaunchMode.externalApplication); - } else { - final Uri url; + await _invokeMobilePayApp(either); // Sideeffect - // MobilePay not installed, send user to appstore - if (Platform.isAndroid) { - url = ApiUriConstants.mobilepayAndroid; - } else if (Platform.isIOS) { - url = ApiUriConstants.mobilepayIOS; - } else { - throw UnsupportedError('Unsupported platform'); - } - if (_context.mounted) { - launchUrlExternalApplication(url, _context); - } - } + return either; } - @override - Future> verifyPurchase( - int purchaseId, + Future _invokeMobilePayApp( + Either paymentEither, ) async { - // Call API endpoint, receive PaymentStatus - final either = await _repository.getPurchase(purchaseId); + paymentEither.map( + (payment) async { + final Uri mobilepayLink = Uri.parse(payment.deeplink); - return either.map((purchase) { - final paymentDetails = - MobilePayPaymentDetails.fromJsonFactory(purchase.paymentDetails); + if (await canLaunchUrl(mobilepayLink)) { + await launchUrl(mobilepayLink, mode: LaunchMode.externalApplication); - final status = _mapPaymentStateToStatus(paymentDetails.state); - if (status == PaymentStatus.completed) { - return PaymentStatus.completed; - } + return; + } else { + final Uri url = _getAppStoreUri(); - // TODO(marfavi): Cover more cases for PaymentStatus, https://github.com/AnalogIO/coffeecard_app/issues/385 - return PaymentStatus.error; - }); + // MobilePay not installed, send user to appstore + if (context.mounted) { + await launchUrlExternalApplication(url, context); + } + } + }, + ); } - PaymentStatus _mapPaymentStateToStatus(String? state) { - PaymentStatus status; - switch (state) { - case 'Initiated': - status = PaymentStatus.awaitingPayment; - break; - case 'Reserved': - status = PaymentStatus.reserved; - break; - case 'Captured': - status = PaymentStatus.completed; - break; - // Cases (cancelledByMerchant, cancelledBySystem, cancelledByUser) - default: - status = PaymentStatus.rejectedPayment; - break; + Uri _getAppStoreUri() { + if (Platform.isAndroid) { + return ApiUriConstants.mobilepayAndroid; + } else if (Platform.isIOS) { + return ApiUriConstants.mobilepayIOS; + } else { + throw UnsupportedError('Unsupported platform'); } - return status; } } diff --git a/lib/payment/payment_handler.dart b/lib/payment/payment_handler.dart index baed185a8..427643f67 100644 --- a/lib/payment/payment_handler.dart +++ b/lib/payment/payment_handler.dart @@ -2,6 +2,7 @@ import 'package:coffeecard/core/errors/failures.dart'; import 'package:coffeecard/data/repositories/v2/purchase_repository.dart'; import 'package:coffeecard/models/purchase/payment.dart'; import 'package:coffeecard/models/purchase/payment_status.dart'; +import 'package:coffeecard/payment/free_product_service.dart'; import 'package:coffeecard/payment/mobilepay_service.dart'; import 'package:coffeecard/service_locator.dart'; import 'package:dartz/dartz.dart'; @@ -9,13 +10,37 @@ import 'package:flutter/widgets.dart'; enum InternalPaymentType { mobilePay, + free, } abstract class PaymentHandler { - factory PaymentHandler(InternalPaymentType type, BuildContext context) { - switch (type) { + final PurchaseRepository purchaseRepository; + // Certain implementations of the payment handler require access to the build context, even if it does not do so itself. + // ignore: unused_field + final BuildContext context; + + const PaymentHandler({ + required this.purchaseRepository, + required this.context, + }); + + static PaymentHandler createPaymentHandler( + InternalPaymentType paymentType, + BuildContext context, + ) { + final repository = sl.get(); + + switch (paymentType) { case InternalPaymentType.mobilePay: - return MobilePayService(sl.get(), context); + return MobilePayService( + purchaseRepository: repository, + context: context, + ); + case InternalPaymentType.free: + return FreeProductService( + purchaseRepository: repository, + context: context, + ); default: throw UnimplementedError(); } @@ -23,7 +48,14 @@ abstract class PaymentHandler { Future> initPurchase(int productId); - Future> verifyPurchase(int purchaseId); + Future> verifyPurchase( + int purchaseId, + ) async { + // Call API endpoint, receive PaymentStatus + final either = await purchaseRepository.getPurchase(purchaseId); - Future invokePaymentMethod(Uri uri); + return either.map( + (purchase) => purchase.status, + ); + } } diff --git a/lib/service_locator.dart b/lib/service_locator.dart index b5884bd36..8b8157cd7 100644 --- a/lib/service_locator.dart +++ b/lib/service_locator.dart @@ -5,12 +5,12 @@ import 'package:coffeecard/data/api/interceptors/authentication_interceptor.dart import 'package:coffeecard/data/repositories/external/contributor_repository.dart'; import 'package:coffeecard/data/repositories/shared/account_repository.dart'; import 'package:coffeecard/data/repositories/v1/product_repository.dart'; -import 'package:coffeecard/data/repositories/v1/receipt_repository.dart'; import 'package:coffeecard/data/repositories/v1/ticket_repository.dart'; import 'package:coffeecard/data/repositories/v1/voucher_repository.dart'; import 'package:coffeecard/data/repositories/v2/app_config_repository.dart'; import 'package:coffeecard/data/repositories/v2/leaderboard_repository.dart'; import 'package:coffeecard/data/repositories/v2/purchase_repository.dart'; +import 'package:coffeecard/data/repositories/v2/receipt_repository.dart'; import 'package:coffeecard/data/storage/secure_storage.dart'; import 'package:coffeecard/env/env.dart'; import 'package:coffeecard/features/occupation/data/datasources/occupation_remote_data_source.dart'; @@ -93,10 +93,10 @@ void configureServices() { ); // Repositories - // v1 sl.registerFactory( () => ReceiptRepository( - apiV1: sl(), + productRepository: sl(), + apiV2: sl(), executor: sl(), ), ); diff --git a/lib/widgets/components/purchase/purchase_overlay.dart b/lib/widgets/components/purchase/purchase_overlay.dart index c61c3880d..d2b6a7228 100644 --- a/lib/widgets/components/purchase/purchase_overlay.dart +++ b/lib/widgets/components/purchase/purchase_overlay.dart @@ -22,7 +22,8 @@ Future showPurchaseOverlay({ onWillPop: () async => false, child: BlocProvider( create: (context) => PurchaseCubit( - paymentHandler: PaymentHandler(paymentType, context), + paymentHandler: + PaymentHandler.createPaymentHandler(paymentType, context), product: product, ), child: BlocListener( diff --git a/lib/widgets/components/purchase/purchase_process.dart b/lib/widgets/components/purchase/purchase_process.dart index a079a7b11..2e5a9275f 100644 --- a/lib/widgets/components/purchase/purchase_process.dart +++ b/lib/widgets/components/purchase/purchase_process.dart @@ -48,7 +48,7 @@ class _PurchaseProcessState extends State } if (state is PurchaseInitial) { // Not related to previous check, hence a separate if statement - cubit.payWithMobilePay(); + cubit.pay(); return makeLoadingDialog( title: Strings.purchaseTalking, ); diff --git a/lib/widgets/components/tickets/buy_ticket_bottom_modal_sheet.dart b/lib/widgets/components/tickets/buy_ticket_bottom_modal_sheet.dart index 0d980258b..413f7b015 100644 --- a/lib/widgets/components/tickets/buy_ticket_bottom_modal_sheet.dart +++ b/lib/widgets/components/tickets/buy_ticket_bottom_modal_sheet.dart @@ -65,7 +65,9 @@ class _ModalContent extends StatelessWidget { ), const Gap(4), Text( - Strings.paymentConfirmationBottom(product.price), + product.price != 0 + ? Strings.paymentConfirmationBottomPurchase(product.price) + : Strings.paymentConfirmationButtonRedeem, style: AppTextStyle.price, ), const Gap(12), @@ -92,6 +94,33 @@ class _BottomModalSheetButtonBarState extends State<_BottomModalSheetButtonBar> { @override Widget build(BuildContext context) { + final isFreeProduct = widget.product.price == 0; + if (isFreeProduct) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _BottomModalSheetButton( + text: 'Redeem product', + productId: widget.product.id, + price: widget.product.price, + onTap: () async { + final payment = await showPurchaseOverlay( + paymentType: InternalPaymentType.free, + product: widget.product, + context: context, + ); + + if (!mounted) return; + // Remove this bottom modal sheet. + Navigator.pop( + context, + payment, + ); + }, + ), + ], + ); + } return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/widgets/components/tickets/swipe_ticket_confirm.dart b/lib/widgets/components/tickets/swipe_ticket_confirm.dart index 7c6947332..0b65a0c61 100644 --- a/lib/widgets/components/tickets/swipe_ticket_confirm.dart +++ b/lib/widgets/components/tickets/swipe_ticket_confirm.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:coffeecard/base/strings.dart'; import 'package:coffeecard/base/style/colors.dart'; import 'package:coffeecard/base/style/text_styles.dart'; +import 'package:coffeecard/cubits/receipt/receipt_cubit.dart'; import 'package:coffeecard/cubits/tickets/tickets_cubit.dart'; import 'package:coffeecard/widgets/components/card.dart'; import 'package:coffeecard/widgets/components/tickets/bottom_modal_sheet_helper.dart'; @@ -133,6 +134,7 @@ class _ModalContentState extends State<_ModalContent> widget.context .read() .useTicket(widget.productId); + widget.context.read().fetchReceipts(); }, ), ), diff --git a/lib/widgets/pages/home_page.dart b/lib/widgets/pages/home_page.dart index 263b87a0c..e415c1df6 100644 --- a/lib/widgets/pages/home_page.dart +++ b/lib/widgets/pages/home_page.dart @@ -6,9 +6,9 @@ import 'package:coffeecard/base/style/text_styles.dart'; import 'package:coffeecard/cubits/receipt/receipt_cubit.dart'; import 'package:coffeecard/cubits/statistics/statistics_cubit.dart'; import 'package:coffeecard/cubits/tickets/tickets_cubit.dart'; -import 'package:coffeecard/data/repositories/v1/receipt_repository.dart'; import 'package:coffeecard/data/repositories/v1/ticket_repository.dart'; import 'package:coffeecard/data/repositories/v2/leaderboard_repository.dart'; +import 'package:coffeecard/data/repositories/v2/receipt_repository.dart'; import 'package:coffeecard/features/opening_hours/opening_hours.dart'; import 'package:coffeecard/features/user/presentation/cubit/user_cubit.dart'; import 'package:coffeecard/service_locator.dart'; diff --git a/openapi/coffeecard_api_v2.swagger.json b/openapi/coffeecard_api_v2.swagger.json index 9f1cf5983..419531b96 100644 --- a/openapi/coffeecard_api_v2.swagger.json +++ b/openapi/coffeecard_api_v2.swagger.json @@ -1647,4 +1647,4 @@ } } } -} \ No newline at end of file +} diff --git a/test/cubits/receipt/receipt_cubit_test.dart b/test/cubits/receipt/receipt_cubit_test.dart index 4bd71cfb4..554bc9ce5 100644 --- a/test/cubits/receipt/receipt_cubit_test.dart +++ b/test/cubits/receipt/receipt_cubit_test.dart @@ -2,7 +2,7 @@ import 'package:bloc_test/bloc_test.dart'; import 'package:coffeecard/base/strings.dart'; import 'package:coffeecard/core/errors/failures.dart'; import 'package:coffeecard/cubits/receipt/receipt_cubit.dart'; -import 'package:coffeecard/data/repositories/v1/receipt_repository.dart'; +import 'package:coffeecard/data/repositories/v2/receipt_repository.dart'; import 'package:coffeecard/models/receipts/receipt.dart'; import 'package:dartz/dartz.dart'; import 'package:flutter_test/flutter_test.dart';