@@ -25,9 +25,7 @@ from payments.models import ( PaymentPlan, PaymentPlanFeature, PaymentMethod, - PaymentPlanUserInfo, ) -from authentication.services.email_service import EmailService from payments.schema import UserBalance from payments.schemas import ( ExpensesParamsSchema, @@ -228,25 +226,28 @@ async def create_payment_link(request, body: NewSubscriptionSchema): @router.post('gitlab-webhook', tags=['payments/gitlab-webhook'], auth=None) async def handle_gitlab_webhook(request): - try: - data = orjson.loads(request.body)['object_attributes'] - if data['name'] == 'recurring_payments': - is_active = data['active'] - if not is_active: - deleted_methods_count, deleted_details = await PaymentMethod.objects.all().adelete() - logger.info( - 'Recurring feature disabled: all payment methods removed count=%s', - deleted_methods_count, - ) - updated_count = await PaymentPlanUserInfo.objects.filter( - plan__price__gt=0, - plan__individual=False, - ).aupdate(next_payment_at=None if not is_active else (timezone.now() + timedelta(days=30))) - logger.info( - 'Recurring feature flag synced: active=%s updated_subscriptions=%s', - is_active, - updated_count, - ) - except Exception as exc: - logger.error(exc) + ''' + Currently disabled, pending future feature flags + ''' + # try: + # data = orjson.loads(request.body)['object_attributes'] + # if data['name'] == 'recurring_payments': + # is_active = data['active'] + # if not is_active: + # deleted_methods_count, deleted_details = await PaymentMethod.objects.all().adelete() + # logger.info( + # 'Recurring feature disabled: all payment methods removed count=%s', + # deleted_methods_count, + # ) + # updated_count = await PaymentPlanUserInfo.objects.filter( + # plan__price__gt=0, + # plan__individual=False, + # ).aupdate(next_payment_at=None if not is_active else (timezone.now() + timedelta(days=30))) + # logger.info( + # 'Recurring feature flag synced: active=%s updated_subscriptions=%s', + # is_active, + # updated_count, + # ) + # except Exception as exc: + # logger.error(exc) return 200 @@ -14,7 +14,6 @@ from yookassa import Payment as YookassaPayment from yookassa.domain.response import PaymentResponse as YookassaPaymentResponse from authentication.models import CustomUserModel -from lib.unleash.client import web_client from payments.models.payment import Payment as PaymentModel from payments.models.payment_plan import PaymentPlan, PaymentPlanUserInfo from payments.services.payment_method_service import PaymentMethodService @@ -42,11 +41,6 @@ class PaymentService: } ], } - is_recurring = ( - web_client.get_flag_state('recurring_payments', self.user.email) - and not plan.individual - and web_client.get_flag_state('auto-save-payments-enabled', self.user.email) - ) payment_data = { 'amount': {'value': f'{plan.price}', 'currency': 'RUB'}, 'receipt': receipt_data, @@ -56,16 +50,12 @@ class PaymentService: }, 'description': str(self.user.uid), 'capture': True, - 'save_payment_method': is_recurring, + 'save_payment_method': True, 'metadata': {'plan_uid': str(plan.uid)}, } payment = YookassaPayment.create(payment_data, uuid4()) logger.info( - 'Payment link created: email=%s plan_uid=%s price=%s recurring=%s', - self.user.email, - plan.uid, - plan.price, - is_recurring, + 'Payment link created: email=%s plan_uid=%s price=%s', self.user.email, plan.uid, plan.price ) return payment.confirmation.confirmation_url @@ -113,11 +103,7 @@ class PaymentService: return self.user.payment_plan.current_token_balance + plan.tokens_per_plan def handle_succeeded_payment(self, payment: YookassaPaymentResponse, plan: PaymentPlan) -> None: - if ( - payment.payment_method.saved - and web_client.get_flag_state('recurring_payments', self.user.email) - and not plan.individual - ): + if payment.payment_method.saved and not plan.individual: payment_method = PaymentMethodService(self.user).add_payment_method(payment.payment_method) PaymentPlanUserInfo.objects.filter(user=self.user).update( method=payment_method, next_payment_at=timezone.now() + timedelta(days=30) @@ -128,7 +114,7 @@ class PaymentService: payment_method.uid, ) else: - if web_client.get_flag_state('recurring_payments', self.user.email) and not plan.individual: + if not plan.individual: PaymentPlanUserInfo.objects.filter(user=self.user).update( next_payment_at=timezone.now() + timedelta(days=30) ) @@ -139,7 +125,7 @@ class PaymentService: else: PaymentPlanUserInfo.objects.filter(user=self.user).update(next_payment_at=None) logger.info( - 'Recurring schedule cleared: email=%s reason=feature_disabled_or_individual_plan', + 'Recurring schedule cleared: email=%s reason=individual_plan', self.user.email, ) PaymentMethodService(self.user).delete_payment_method() @@ -14,8 +14,7 @@ from django.utils import timezone from authentication.models.business_host import BusinessUserHost from authentication.models.user import CustomUserModel from authentication.services.email_service import EmailService -from lib.unleash.client import celery_client -from payments.models import PaymentMethod, PaymentPlan, PaymentPlanUserInfo +from payments.models import PaymentPlan, PaymentPlanUserInfo from payments.services.payment_plan_service import PaymentPlanService from yookassa import Payment as YookassaPayment @@ -44,11 +43,6 @@ def withdraw(user_id: UUID, amount: Decimal): @shared_task def execute_recurring_payments() -> None: - if not celery_client.is_feature_enabled('recurring_payments'): - logger.info('Recurring payments feature disabled, skipping execute') - return - - emails = celery_client.get_user_emails('recurring_payments') overdue_payments = ( PaymentPlanUserInfo.objects.select_related('user', 'plan', 'method') .filter( @@ -75,8 +69,6 @@ def execute_recurring_payments() -> None: 'method__attempts', ) ) - if emails: - overdue_payments = overdue_payments.filter(user__email__in=emails) for overdue_payment in overdue_payments.iterator(chunk_size=CHUNK_SIZE): customer = overdue_payment.user plan = overdue_payment.plan @@ -126,54 +118,26 @@ def revoke_recurring_payments() -> None: logger.info('Revoke recurring already running, skipping') return try: - feature_name = 'recurring_payments' - base_qs = PaymentPlanUserInfo.objects.filter( + qs = PaymentPlanUserInfo.objects.filter( next_payment_at__isnull=False, next_payment_at__lte=timezone.now(), plan__price__gt=0, plan__individual=False, plan__is_corporate=False, + method__isnull=True, ) - revoked_count = 0 - canceled_count = 0 - deleted_methods_count = 0 - if not celery_client.is_feature_enabled(feature_name): - flag_off_qs = base_qs - flag_on_qs = base_qs.none() - else: - allowed_emails = celery_client.get_user_emails(feature_name) - if allowed_emails: - flag_off_qs = base_qs.exclude(user__email__in=allowed_emails) - flag_on_qs = base_qs.filter(user__email__in=allowed_emails, method__isnull=True) - else: - flag_off_qs = base_qs.none() - flag_on_qs = base_qs.filter(method__isnull=True) + canceled_count = 0 - uid_iter = flag_off_qs.values_list('uid', flat=True).iterator(chunk_size=CHUNK_SIZE) - while uids := list(islice(uid_iter, CHUNK_SIZE)): + free_regular_plan = PaymentPlan.objects.get_or_create(price=0, is_corporate=False)[0] + qs_iter = qs.values_list('uid', flat=True).iterator(chunk_size=CHUNK_SIZE) + while uids := list(islice(qs_iter, CHUNK_SIZE)): with transaction.atomic(): - deleted_methods_count += PaymentMethod.objects.filter( - user_plan_info__uid__in=uids - ).delete()[0] - revoked_count += flag_off_qs.filter(uid__in=uids).update(next_payment_at=None) - - if flag_on_qs.exists(): - free_regular_plan = PaymentPlan.objects.get_or_create(price=0, is_corporate=False)[0] - flag_on_iter = flag_on_qs.values_list('uid', flat=True).iterator(chunk_size=CHUNK_SIZE) - while uids := list(islice(flag_on_iter, CHUNK_SIZE)): - with transaction.atomic(): - canceled_count += flag_on_qs.filter(uid__in=uids).update( - next_payment_at=None, - plan_id=free_regular_plan.pk, - current_token_balance=0, - ) - - logger.info( - 'Revoke recurring finished: revoked=%s free_regular=%s deleted_methods=%s', - revoked_count, - canceled_count, - deleted_methods_count, - ) + canceled_count += qs.filter(uid__in=uids).update( + next_payment_at=None, + plan_id=free_regular_plan.pk, + current_token_balance=0, + ) + logger.info('Revoke recurring finished: free_regular=%s', canceled_count) finally: cache.delete(lock_key)