
    Bi1                        d Z ddlZddlZddlZddlZddlmZmZmZ ddlm	Z	 ddl
mZ ddlmZ ddlmZ ddlmZ d	 Zdd
lmZ ddlmZmZmZmZmZ ddlmZ ddlmZ ddlm Z m!Z!m"Z"  ej#        e$          Z% ed          Z&dede'defdZ( ej)        d          d             Z* ej)        d          d             Z+d Z, ej)        d          d             Z-dS )uF   
Celery 태스크 정의
정기구독 자동 갱신 및 결제 처리
    N)datetime	timedeltadate)
monthrange)ZoneInfo)celery)db)Flaskc                      ddl m}  | S )u   Flask 앱 인스턴스 반환r   app)src.mainr   r   s    B/var/www/html/web/mlink/mlink_AI_Server/mlink-backend/src/tasks.pyget_appr      s    J    )User)SubscriptionSubscriptionStatusProductPaymentStatusPaymentMethod)PaymentHistory)send_payment_link_email)TOSS_CONFIGget_front_urlget_back_urlz
Asia/Seoul	base_date	start_dayreturnc                     | j         dk    r| j        dz   d}}n| j        | j         dz   }}t          ||          d         }t          ||          }t	          |||          S )uO   base_date 기준으로 +1개월, 시작일의 '일(day)' 유지. 말일 보정.      )monthyearr   minr   )r   r   ymlast_daykeep_days         r   _add_one_month_same_dayr*      sh    "~!11~y21!Q"H9h''H1hr   z%src.tasks.check_subscription_renewals)namec                  T   t                      } |                                 5  	 t          j        t                    }|                                }t          j                            t          j	        t          j        k    t          j        dk    t          j                            d          t          j                            t          j                  |k                                              }t$                              dt)          |           d           |D ]k}	 t*                              |j                   ## t0          $ r<}t$                              d|j         dt5          |                      Y d}~dd}~ww xY wdt)          |          |                                dcddd           S # t0          $ rR}t$                              dt5          |                      d	t5          |          d
cY d}~cddd           S d}~ww xY w# 1 swxY w Y   dS )u   
    정기구독 갱신 체크 태스크
    next_billing_date가 오늘인 구독을 찾아 결제 링크 생성 및 이메일 발송
    TNu   정기구독 갱신 체크: u   개 구독 발견u   구독 u    갱신 처리 실패: )successchecked	timestampu#   정기구독 갱신 체크 실패: Fr-   error)r   app_contextr   nowKSTr   r   queryfilterstatusr   ACTIVE
auto_renewnext_billing_dateisnotr	   funcallloggerinfolen"create_payment_link_and_send_emaildelayid	Exceptionr1   str	isoformat)r   now_ksttodaysubscriptionssubscriptiones         r   check_subscription_renewalsrL   *   s    ))C			 ! ! 	l3''GLLNNE ).55#'9'@@'4/.44T::\;<<E	 
 cee  KK\s=7I7I\\\]]] - ] ]]6<<\_MMMM  ] ] ]LL![<?![![SVWXSYSY![![\\\\\\\\]  }--$..00 -! ! ! ! ! ! ! !8  	 	 	LLGs1vvGGHHH Q      =! ! ! ! ! ! ! !8	9! ! ! ! ! ! ! ! ! !se   HC>F>$EF>
F
2F F>F

'F>>
H;HHHHHH!$H!z,src.tasks.create_payment_link_and_send_emailc                    t                      }|                                5  	 t          j                            |           }|s.t
                              d|             dddcddd           S |j        t          j	        k    r6t
          
                    d|  d|j                    dddcddd           S t          j                            d	          }|s3t
                              d
|j                    dddcddd           S t          j                            |j                  }|s3t
                              d|j                    dddcddd           S |j        p|j        pd}|dk    r"t!          |d          r|j        n	|j        dz  }n|j        }d|j         dt)          j                    j        dd          dt/          t1          j                                                               }t7          |||j        ||j        |j                  }|r|                    d          s.t
                              d|             dddcddd           S |d         }	|                    dd          }
t;          |j        |j        |
||t<          j        t@          j!        |j        |j        ||t1          j                              }tD          j#        $                    |           tD          j#        %                                 |j&        r|j&        '                    d          nd}tQ          |j)        |j*        |j        |	||          }|r&t
          +                    d|  d |j)                    n%t
          
                    d!|  d |j)                    d"| ||	|d#cddd           S # tX          $ rp}tD          j#        -                                 t
                              d$t]          |                      dt]          |          dcY d}~cddd           S d}~ww xY w# 1 swxY w Y   dS )%ue   
    결제 링크 생성 및 이메일 발송
    
    Args:
        subscription_id: 구독 ID
    u#   구독을 찾을 수 없습니다: Fu"   구독을 찾을 수 없습니다.r0   Nu)   구독이 활성 상태가 아닙니다: u
   , 상태: u(   구독이 활성 상태가 아닙니다.   u&   사용자를 찾을 수 없습니다: u%   사용자를 찾을 수 없습니다.u#   상품을 찾을 수 없습니다: u"   상품을 찾을 수 없습니다.monthlyyearly
price_yearr!   mlink_renew__   )order_idamountproduct_namebilling_cycleuser_idsubscription_idpayment_linku   결제 링크 생성 실패: u   결제 링크 생성 실패	pay_token )rY   rZ   payment_keyrU   rV   r7   payment_method
product_idrW   product_pricerX   
created_atu   %Y년 %m월 %d일u   오늘)
user_email	user_namesubscription_namer[   billing_daterV   u.   결제 링크 이메일 발송 완료: 구독 u   , 사용자 u.   결제 링크 이메일 발송 실패: 구독 T)r-   rZ   rU   r[   
email_sentu2   결제 링크 생성 및 이메일 발송 실패: )/r   r2   r   r5   getr>   r1   r7   r   r8   warningr   rY   r   r`   rX   hasattrrQ   pricerC   uuiduuid4hexintr   r3   r/   create_toss_payment_linkr+   r   r   PENDINGr   TOSS_PAYMENTSr	   sessionaddcommitr:   strftimer   emailusernamer?   rD   rollbackrE   )rZ   r   rJ   userproductrX   rV   rU   payment_resultr[   r\   payment_historyrf   rg   rK   s                  r   rA   rA   T   s    ))C			 c cb	'-11/BBL YT?TTUUU#(3WXXc c c c c c c c "&8&???{?{{frfy{{|||#(3]^^c c c c c c c c :>>"%%D \\lFZ\\]]]#(3Z[[!c c c c c c c c& m''(?@@G Y\<CZ\\]]]#(3WXX-c c c c c c c c2 )6\':O\S\M((/6w/M/Me++SZS`ceSe  qlopp
8H!8LppsS[S_SaSaSkSkSmSmOnOnppH 6!$\+$, ,  N " R););N)K)K RN_NNOOO#(3PQQ]c c c c c c c c` *.9L&**;;;I -$, ,%!$,,:":$\$+#<>>  O JNN?+++J \h[y  H<9BBCVWWW  @HL0:-"),))  J  {v_vvjnjtvvwwwwyP_yymqmwyyzzz  #2$ ,( kc c c c c c c cz  	 	 	J!!!LLVcRSffVVWWW Q      Ac c c c c c c cz	{c c c c c c c c c cs^   QAO	4>O	?AO	AO	,C9O	2E
O		
QAP>,Q-Q>QQQ
Q
c                    	 t          |dz            }||z
  }t          j                    t          d          z   }|                    d          }	| |d||| dt
          d         dd	d
t                       d|  d| t                       d|  d| |	d}
t          j        t
          d         ddi|
d          }|j	        dk    r|
                                }|                    d          }|                    dd          }|rL|r|}n"d| }t                              d|             t                              d|  d|            ||dS t                              d|            dS t                              d|j	         d |j                    dS # t"          $ r5}t                              d!t%          |                      Y d}~dS d}~ww xY w)"uZ  
    토스페이먼츠 결제 링크 생성
    
    Args:
        order_id: 주문 ID
        amount: 결제 금액
        product_name: 상품명
        billing_cycle: 결제 주기
        user_id: 사용자 ID
        subscription_id: 구독 ID
    
    Returns:
        dict: {'payment_link': str, 'pay_token': str} (실패 시 None)
    g?<   )minutesz%Y-%m-%d %H:%M:%Sr   u    추가 구매api_keyTz*https://pay.toss.im/payfront/demo/callbackV2z/payment/success?orderId=z&subscriptionId=z/payment/fail?orderId=)orderNorV   amountTaxFreeamountTaxable	amountVatproductDescapiKeyautoExecuteresultCallbackcallbackVersionretUrlretCancelUrlexpiredTimebase_urlzContent-Typezapplication/json
   )headersjsontimeout   payTokencheckoutPager]   z9https://pay.toss.im/transfer-web/linkgen-mobile?payToken=uC   토스페이먼츠 응답에 checkoutPage가 없어 직접 생성: u0   토스페이먼츠 결제 링크 생성 성공: z, payment_link: )r[   r\   u7   토스페이먼츠 응답에 payToken이 없습니다: Nu&   토스페이먼츠 API 호출 실패: z - u4   토스페이먼츠 결제 링크 생성 중 오류: )ro   r   r3   r   rv   r   r   requestspoststatus_coder   rh   r>   ri   r?   r1   textrD   rE   )rU   rV   rW   rX   rY   rZ   amount_taxable
amount_vatexpiration_datetimeexpired_time_strpayment_dataresponseresultr\   checkout_pager[   rK   s                    r   rp   rp      s\   >Vc\**n,
 'lnny/D/D/DD.778KLL  +#*:::!),J#&nn8nn]lnn,qqhqq`oqq+
 
$ =
##%78	
 
 
 3&&]]__F

:..I"JJ~r::M   u#0LL $k_h#j#jLNN#siq#s#stttwxwwiuwwxxx$0!*  
 _W]__```tLLj(BVjj[c[hjjkkk4   TCPQFFTTUUUttttts$   EF  F  4*F   
G**GGz'src.tasks.cleanup_expired_subscriptionsc                  <   t                      } |                                 5  	 t          j                    }t          j                            t          j        t          j	        k    t          j
        |k                                               }d}|D ]}t          j        |_        d|_        |dz  } t          j                                         t"                              d| d           d||                                dcddd           S # t(          $ rp}t          j                                         t"                              d	t/          |                      dt/          |          d
cY d}~cddd           S d}~ww xY w# 1 swxY w Y   dS )uk   
    만료된 구독 정리 태스크
    end_date가 지난 활성 구독을 만료 상태로 변경
    r   Fr"   u    만료된 구독 정리 완료: u   개T)r-   cleanedr/   Nu    만료된 구독 정리 실패: r0   )r   r2   r   r3   r   r5   r6   r7   r   r8   end_dater=   EXPIREDr9   r	   rs   ru   r>   r?   rF   rD   ry   r1   rE   )r   r3   expired_subscriptionscountrJ   rK   s         r   cleanup_expired_subscriptionsr     s    ))C			    	,..C %1$6$=$=#'9'@@%+% % cee "
 E 5  &8&@#*/'
JKKE5EEEFFF    ]]__ )               4  	 	 	J!!!LLDCFFDDEEE Q      ;               4	5                   s<   FC"D
FAF	7F8F	FFFF).__doc__osrl   r   loggingr   r   r   calendarr   zoneinfor   src.celery_appr   src.models.dbr	   flaskr
   r   src.models.userr   src.models.subscriptionr   r   r   r   r   src.models.paymentr   src.utils.email_servicer   src.routes.payments_v2r   r   r   	getLogger__name__r>   r4   ro   r*   taskrL   rA   rp   r    r   r   <module>r      s-    
			    . . . . . . . . . .             ! ! ! ! ! !               !           k k k k k k k k k k k k k k - - - - - - ; ; ; ; ; ; K K K K K K K K K K		8	$	$h|	 t 	  	  	  	  	  	  9:::' ' ;:'R @AAAk k BAkZM M M^ ;<<<& & =<& & &r   