diff --git a/lib/features/chat/models/order_id_to_conversation_model.dart b/lib/features/chat/models/order_id_to_conversation_model.dart new file mode 100644 index 00000000..8e83a12c --- /dev/null +++ b/lib/features/chat/models/order_id_to_conversation_model.dart @@ -0,0 +1,15 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'order_id_to_conversation_model.freezed.dart'; +part 'order_id_to_conversation_model.g.dart'; + +@freezed +abstract class OrderIdToConversationModel with _$OrderIdToConversationModel { + factory OrderIdToConversationModel({ + @JsonKey(name: 'chosen_plan_id') required int chosenPlanId, + @JsonKey(name: 'conversation_uuid') required String conversationUuid, + }) = _OrderIdToConversationModel; + + factory OrderIdToConversationModel.fromJson(Map json) => + _$OrderIdToConversationModelFromJson(json); +} diff --git a/lib/features/chat/models/payment_model.dart b/lib/features/chat/models/payment_model.dart index e2c5fbba..6413d5df 100644 --- a/lib/features/chat/models/payment_model.dart +++ b/lib/features/chat/models/payment_model.dart @@ -5,10 +5,12 @@ part 'payment_model.g.dart'; @freezed abstract class PaymentModel with _$PaymentModel { - factory PaymentModel({ @JsonKey(name: 'checkout_url') required String paymentUrl, + @JsonKey(name: 'order_id') String? orderId, + @JsonKey(name: 'payment_provider') String? paymentProvider, }) = _PaymentModel; - factory PaymentModel.fromJson(Map json) => _$PaymentModelFromJson(json); -} \ No newline at end of file + factory PaymentModel.fromJson(Map json) => + _$PaymentModelFromJson(json); +} diff --git a/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart b/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart index dc56a0c1..bb4a8ebd 100644 --- a/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart +++ b/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart @@ -297,7 +297,7 @@ class ChatRoomCubit extends Cubit { try { final planId = (state as ChatRoomStateLoaded).chatRoom.chosenPlan?.id; if (planId == null) return null; - final paymentModel = await chatRepository.getPaymentLink(id: planId); + final paymentModel = await chatRepository.getPaymentLink(id: planId, paymentProvider: 'alfa-bank'); return paymentModel.paymentUrl; } catch (e, st) { await reportFrom(e, st, this); diff --git a/lib/features/chat/repositories/chat_repository.dart b/lib/features/chat/repositories/chat_repository.dart index fc079241..ade2ed26 100644 --- a/lib/features/chat/repositories/chat_repository.dart +++ b/lib/features/chat/repositories/chat_repository.dart @@ -6,6 +6,7 @@ import 'package:eatvio_app/features/chat/models/chat_message_model.dart'; import 'package:eatvio_app/features/chat/models/chat_messages_model.dart'; import 'package:eatvio_app/features/chat/models/chat_room_model.dart'; import 'package:eatvio_app/features/chat/models/chat_room_pagination_model.dart'; +import 'package:eatvio_app/features/chat/models/order_id_to_conversation_model.dart'; import 'package:eatvio_app/features/chat/models/payment_model.dart'; import 'package:eatvio_app/features/chat/models/plan_complain_model.dart'; import 'package:eatvio_app/features/chat/services/chat_service.dart'; @@ -98,8 +99,19 @@ class ChatRepository { Future getPaymentLink({ required int id, + required String paymentProvider, }) async { - return await chatService.getPaymentLink(id: id); + return await chatService.getPaymentLink( + id: id, + body: {'payment_provider': paymentProvider}, + ); + + } + + Future resolveOrderIdToConversation({ + required String orderId, + }) async { + return await chatService.resolveOrderIdToConversation(orderId: orderId); } diff --git a/lib/features/chat/services/chat_service.dart b/lib/features/chat/services/chat_service.dart index a2bf52cf..2d5ceaac 100644 --- a/lib/features/chat/services/chat_service.dart +++ b/lib/features/chat/services/chat_service.dart @@ -3,6 +3,7 @@ import 'package:eatvio_app/features/chat/models/chat_message_model.dart'; import 'package:eatvio_app/features/chat/models/chat_messages_model.dart'; import 'package:eatvio_app/features/chat/models/chat_room_model.dart'; import 'package:eatvio_app/features/chat/models/chat_room_pagination_model.dart'; +import 'package:eatvio_app/features/chat/models/order_id_to_conversation_model.dart'; import 'package:eatvio_app/features/chat/models/payment_model.dart'; import 'package:eatvio_app/features/chat/models/plan_complain_model.dart'; import 'package:eatvio_app/features/plans/models/chosen_plan_model.dart'; @@ -65,6 +66,12 @@ abstract class ChatService { @POST('/api/chosen_plans/{id}/start_payment_process') Future getPaymentLink({ @Path() required int id, + @Body() required Map body, + }); + + @GET('/api/consultation/resolve/order_id_to_conversation/{orderId}') + Future resolveOrderIdToConversation({ + @Path() required String orderId, }); @GET('/api/chosen_plans/show/{id}') diff --git a/lib/features/order_info/cubit/order_info_cubit.dart b/lib/features/order_info/cubit/order_info_cubit.dart index ff331c01..1c1630b6 100644 --- a/lib/features/order_info/cubit/order_info_cubit.dart +++ b/lib/features/order_info/cubit/order_info_cubit.dart @@ -14,7 +14,7 @@ class OrderInfoCubit extends Cubit { try { final plan = state.chosenPlan; if (plan == null) return null; - final paymentModel = await chatRepository.getPaymentLink(id: plan.id); + final paymentModel = await chatRepository.getPaymentLink(id: plan.id, paymentProvider: 'alfa-bank'); return paymentModel.paymentUrl; } catch (e, st) { await reportFrom(e, st, this); diff --git a/test/features/chat/models/order_id_to_conversation_model_test.dart b/test/features/chat/models/order_id_to_conversation_model_test.dart new file mode 100644 index 00000000..d64441b7 --- /dev/null +++ b/test/features/chat/models/order_id_to_conversation_model_test.dart @@ -0,0 +1,22 @@ +import 'package:eatvio_app/features/chat/models/order_id_to_conversation_model.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../../../fixtures/fixture_reader.dart'; + +void main() { + group('OrderIdToConversationModel', () { + test('fromJson создаёт модель из JSON фикстуры', () { + final json = FixtureReader.readAsMap( + 'chat/payments/order_id_to_chat_uuid_response.json', + ); + + final model = OrderIdToConversationModel.fromJson(json); + + expect(model.chosenPlanId, 12); + expect( + model.conversationUuid, + 'fbd81429-8019-499a-80e8-e3933cc4d872', + ); + }); + }); +} diff --git a/test/features/chat/models/payment_model_test.dart b/test/features/chat/models/payment_model_test.dart index 8e26a01e..59675ab0 100644 --- a/test/features/chat/models/payment_model_test.dart +++ b/test/features/chat/models/payment_model_test.dart @@ -1,25 +1,37 @@ import 'package:eatvio_app/features/chat/models/payment_model.dart'; import 'package:flutter_test/flutter_test.dart'; +import '../../../fixtures/fixture_reader.dart'; + void main() { group('PaymentModel', () { test('создает PaymentModel с правильными значениями', () { - final model = PaymentModel( - paymentUrl: 'https://example.com/payment', - ); + final model = PaymentModel(paymentUrl: 'https://example.com/payment'); expect(model.paymentUrl, 'https://example.com/payment'); }); test('fromJson создает PaymentModel из JSON', () { - final json = { - 'checkout_url': 'https://example.com/payment', - }; + final json = {'checkout_url': 'https://example.com/payment'}; final model = PaymentModel.fromJson(json); expect(model.paymentUrl, 'https://example.com/payment'); }); + + test( + 'fromJson парсит ответ alfa-bank (checkout_url, order_id, payment_provider)', + () { + final json = FixtureReader.readAsMap( + 'chat/payments/payment_response_alfa_bank.json', + ); + + final model = PaymentModel.fromJson(json); + + expect(model.paymentUrl, 'https://qr.nspk.ru/ASDFASDFASDFASDF'); + expect(model.orderId, 'alfa_c29_k15138_t1712345678_r1234'); + expect(model.paymentProvider, 'alfa-bank'); + }, + ); }); } - diff --git a/test/features/chat/presentation/bloc/chat_room_cubit_test.dart b/test/features/chat/presentation/bloc/chat_room_cubit_test.dart index 9dd43523..b59f16d8 100644 --- a/test/features/chat/presentation/bloc/chat_room_cubit_test.dart +++ b/test/features/chat/presentation/bloc/chat_room_cubit_test.dart @@ -678,7 +678,7 @@ void main() { when(mockChatRepository.getChatRoom(uuid)).thenAnswer((_) async => chatRoomWithPlan); when(mockChatRepository.getChatMessages(uuid, 1)).thenAnswer((_) async => testChatMessages); when(mockChatRepository.getChosenPlan(id: planId)).thenAnswer((_) async => chosenPlan); - when(mockChatRepository.getPaymentLink(id: planId)).thenAnswer((_) async => PaymentModel(paymentUrl: paymentUrl)); + when(mockChatRepository.getPaymentLink(id: planId, paymentProvider: 'mock')).thenAnswer((_) async => PaymentModel(paymentUrl: paymentUrl)); when(mockWsManager.client).thenReturn(null); when(mockWsManager.initPrivateDirectChatChannel(any)).thenAnswer((_) async => Future.value()); when(mockWsManager.subscribeDirectChatChannel()).thenReturn(null); @@ -691,7 +691,7 @@ void main() { final result = await chatRoomCubit.getPaymentLink(); expect(result, paymentUrl); - verify(mockChatRepository.getPaymentLink(id: planId)).called(1); + verify(mockChatRepository.getPaymentLink(id: planId, paymentProvider: 'mock')).called(1); }); test('getPaymentLink - обрабатывает ошибку', () async { @@ -730,7 +730,7 @@ void main() { when(mockChatRepository.getChatRoom(uuid)).thenAnswer((_) async => chatRoomWithPlan); when(mockChatRepository.getChatMessages(uuid, 1)).thenAnswer((_) async => testChatMessages); when(mockChatRepository.getChosenPlan(id: planId)).thenAnswer((_) async => chosenPlan); - when(mockChatRepository.getPaymentLink(id: planId)).thenThrow(Exception('Payment error')); + when(mockChatRepository.getPaymentLink(id: planId, paymentProvider: 'mock')).thenThrow(Exception('Payment error')); when(mockWsManager.client).thenReturn(null); when(mockWsManager.initPrivateDirectChatChannel(any)).thenAnswer((_) async => Future.value()); when(mockWsManager.subscribeDirectChatChannel()).thenReturn(null); diff --git a/test/features/chat/repositories/chat_repository_test.dart b/test/features/chat/repositories/chat_repository_test.dart index f60e028e..0fb35bf4 100644 --- a/test/features/chat/repositories/chat_repository_test.dart +++ b/test/features/chat/repositories/chat_repository_test.dart @@ -8,6 +8,7 @@ import 'package:eatvio_app/features/chat/models/chat_messages_model.dart'; import 'package:eatvio_app/features/chat/models/chat_room_model.dart' as chat_room; import 'package:eatvio_app/features/chat/models/chat_room_pagination_model.dart'; +import 'package:eatvio_app/features/chat/models/order_id_to_conversation_model.dart'; import 'package:eatvio_app/features/chat/models/payment_model.dart'; import 'package:eatvio_app/features/chat/models/plan_complain_model.dart'; import 'package:eatvio_app/features/chat/repositories/chat_repository.dart'; @@ -303,14 +304,83 @@ void main() { final expectedPayment = PaymentModel.fromJson(paymentFixture); when( - mockChatService.getPaymentLink(id: planId), + mockChatService.getPaymentLink( + id: planId, + body: {'payment_provider': 'mock'}, + ), ).thenAnswer((_) async => expectedPayment); - final result = await chatRepository.getPaymentLink(id: planId); + final result = await chatRepository.getPaymentLink( + id: planId, + paymentProvider: 'mock', + ); expect(result, isA()); expect(result.paymentUrl, 'https://example.com/checkout/payment-123'); - verify(mockChatService.getPaymentLink(id: planId)).called(1); + verify( + mockChatService.getPaymentLink( + id: planId, + body: {'payment_provider': 'mock'}, + ), + ).called(1); + }); + + test( + 'getPaymentLink - передаёт payment_provider в тело запроса alfa-bank', + () async { + const planId = 123; + final paymentFixture = FixtureReader.readAsMap( + 'chat/payments/payment_response_alfa_bank.json', + ); + final expectedPayment = PaymentModel.fromJson(paymentFixture); + + when( + mockChatService.getPaymentLink( + id: planId, + body: {'payment_provider': 'alfa-bank'}, + ), + ).thenAnswer((_) async => expectedPayment); + + final result = await chatRepository.getPaymentLink( + id: planId, + paymentProvider: 'alfa-bank', + ); + + expect(result, isA()); + expect(result.paymentUrl, 'https://qr.nspk.ru/ASDFASDFASDFASDF'); + expect(result.orderId, 'alfa_c29_k15138_t1712345678_r1234'); + expect(result.paymentProvider, 'alfa-bank'); + verify( + mockChatService.getPaymentLink( + id: planId, + body: {'payment_provider': 'alfa-bank'}, + ), + ).called(1); + }, + ); + + test('resolveOrderIdToConversation - получает модель по orderId', () async { + const orderId = 'alfa_c29_k15138_t1712345678_r1234'; + final fixture = FixtureReader.readAsMap( + 'chat/payments/order_id_to_chat_uuid_response.json', + ); + final expected = OrderIdToConversationModel.fromJson(fixture); + + when( + mockChatService.resolveOrderIdToConversation(orderId: orderId), + ).thenAnswer((_) async => expected); + + final result = await chatRepository.resolveOrderIdToConversation( + orderId: orderId, + ); + + expect(result, isA()); + expect(result.chosenPlanId, 12); + expect(result.conversationUuid, "fbd81429-8019-499a-80e8-e3933cc4d872"); + + verify( + mockChatService.resolveOrderIdToConversation(orderId: orderId), + ).called(1); }); test('getChosenPlan - получает выбранный план', () async { diff --git a/test/features/chat/services/chat_service_test.dart b/test/features/chat/services/chat_service_test.dart index 95c6cda9..68750a7e 100644 --- a/test/features/chat/services/chat_service_test.dart +++ b/test/features/chat/services/chat_service_test.dart @@ -4,6 +4,7 @@ import 'package:eatvio_app/features/chat/models/chat_messages_model.dart'; import 'package:eatvio_app/features/chat/models/chat_room_model.dart' as chat_room; import 'package:eatvio_app/features/chat/models/chat_room_pagination_model.dart'; +import 'package:eatvio_app/features/chat/models/order_id_to_conversation_model.dart'; import 'package:eatvio_app/features/chat/models/payment_model.dart'; import 'package:eatvio_app/features/chat/models/plan_complain_model.dart'; import 'package:eatvio_app/features/chat/services/chat_service.dart'; @@ -221,14 +222,17 @@ void main() { final expectedPayment = PaymentModel.fromJson(paymentFixture); when( - mockChatService.getPaymentLink(id: planId), + mockChatService.getPaymentLink(id: planId, body: {'payment_provider': 'mock'}), ).thenAnswer((_) async => expectedPayment); - final result = await mockChatService.getPaymentLink(id: planId); + final result = await mockChatService.getPaymentLink( + id: planId, + body: {'payment_provider': 'mock'}, + ); expect(result, isA()); expect(result.paymentUrl, 'https://example.com/checkout/payment-123'); - verify(mockChatService.getPaymentLink(id: planId)).called(1); + verify(mockChatService.getPaymentLink(id: planId, body: {'payment_provider': 'mock'})).called(1); }); test('getChosenPlan - возвращает выбранный план', () async { @@ -291,6 +295,31 @@ void main() { }, ); + test( + 'resolveOrderIdToConversation - возвращает модель по orderId', + () async { + const orderId = 'alfa_c29_k15138_t1712345678_r1234'; + final fixture = FixtureReader.readAsMap( + 'chat/payments/order_id_to_chat_uuid_response.json', + ); + final expected = OrderIdToConversationModel.fromJson(fixture); + + when( + mockChatService.resolveOrderIdToConversation(orderId: orderId), + ).thenAnswer((_) async => expected); + + final result = await mockChatService.resolveOrderIdToConversation( + orderId: orderId, + ); + + expect(result, isA()); + expect(result.chosenPlanId, 12); + verify( + mockChatService.resolveOrderIdToConversation(orderId: orderId), + ).called(1); + }, + ); + test('getChatByUserSlug - возвращает HttpResponse', () async { const slug = 'user-slug'; const chatId = 'chat-id-123'; diff --git a/test/features/order_info/cubit/order_info_cubit_test.dart b/test/features/order_info/cubit/order_info_cubit_test.dart index de00ad94..b1925972 100644 --- a/test/features/order_info/cubit/order_info_cubit_test.dart +++ b/test/features/order_info/cubit/order_info_cubit_test.dart @@ -200,20 +200,20 @@ void main() { .thenAnswer((_) async => chosenPlan); await cubit.getChosenPlan(id: 1); - when(mockChatRepository.getPaymentLink(id: 1)) + when(mockChatRepository.getPaymentLink(id: 1, paymentProvider: 'mock')) .thenAnswer((_) async => paymentModel); final result = await cubit.getPaymentLink(); expect(result, equals('https://payment.url')); - verify(mockChatRepository.getPaymentLink(id: 1)).called(1); + verify(mockChatRepository.getPaymentLink(id: 1, paymentProvider: 'mock')).called(1); }); test('getPaymentLink - возвращает null, если план не выбран', () async { final result = await cubit.getPaymentLink(); expect(result, isNull); - verifyNever(mockChatRepository.getPaymentLink(id: anyNamed('id'))); + verifyNever(mockChatRepository.getPaymentLink(id: anyNamed('id'), paymentProvider: anyNamed('paymentProvider'))); }); test('getPaymentLink - обработка ошибки', () async { @@ -254,7 +254,7 @@ void main() { .thenAnswer((_) async => chosenPlan); await cubit.getChosenPlan(id: 1); - when(mockChatRepository.getPaymentLink(id: 1)) + when(mockChatRepository.getPaymentLink(id: 1, paymentProvider: 'mock')) .thenThrow(Exception('Ошибка')); final result = await cubit.getPaymentLink();