
    ^iV                        d Z ddlmZmZmZmZ ddlmZ ddlm	Z	m
Z
 ddlmZmZ ddlmZmZ ddlmZ ddlmZ dd	lmZmZmZmZmZmZmZmZ dd
lmZ ddlm Z m!Z!  e       Z" G d de       Z# G d de       Z$ G d de       Z% G d de       Z& G d de       Z' G d de       Z( G d de       Z)e"jU                  dee#          ee      fdefd       Z+e"jU                  de$       ee       ee      fdefd       Z,e"j[                  de$d !       ee       ee      fd"e(defd#       Z.e"jU                  d$e%       ee       ee      fdefd%       Z/e"jU                  d&ee&         d'd ee       ee      fd(e0d)e0defd*       Z1e"j[                  d&e&d !       ee       ee      fd"e)defd+       Z2e"jU                  d,ee'         d- ee       ee      fd(e0defd.       Z3e"j[                  d/       ee       ee      fdefd0       Z4e"j[                  d1       ee       ee      fd"e5defd2       Z6y3)4uH   
API для управления биллингом и тарифами
    )	APIRouterDependsHTTPExceptionstatus)Session)funcand_)ListOptional)datetime	timedeltaDecimal)get_db)PlanSubscriptionUsageRecordPayment
LimitAlertTenantNotificationDelivery)get_current_user)	BaseModelFieldc                   n    e Zd ZU eed<   eed<   ee   ed<   eed<   eed<   eed<   e	ed<    G d d	      Z
y
)PlanOutidnamedescriptionmonthly_pricenotifications_limitfeatures	is_activec                       e Zd ZdZy)PlanOut.ConfigTN__name__
__module____qualname__from_attributes     )/var/www/notifications/app/api/billing.pyConfigr&           r-   r/   N)r(   r)   r*   int__annotations__strr   r   dictboolr/   r,   r-   r.   r   r      s6    G
I#NO r-   r   c                   x    e Zd ZU eed<   eed<   eed<   eed<   eed<   eed<   ee   ed<   e	ed<    G d	 d
      Z
y)SubscriptionOutr   	tenant_idplan_idplanr   
started_at
expires_at
auto_renewc                       e Zd ZdZy)SubscriptionOut.ConfigTNr'   r,   r-   r.   r/   r?   .   r0   r-   r/   N)r(   r)   r*   r1   r2   r   r3   r   r   r5   r/   r,   r-   r.   r7   r7   $   s<    GNL
MK"" r-   r7   c                   @    e Zd ZU eed<   eed<   eed<   eed<   eed<   y)UsageOutnotifications_sentr"   percentage_usedperiod_start
period_endN)r(   r)   r*   r1   r2   floatr   r,   r-   r.   rA   rA   2   s     r-   rA   c                       e Zd ZU eed<   eed<   eed<   eed<   ee   ed<   ee   ed<   eed<   ee   ed<    G d	 d
      Z	y)
PaymentOutr   amountcurrencyr   payment_methodtransaction_id
created_atcompleted_atc                       e Zd ZdZy)PaymentOut.ConfigTNr'   r,   r-   r.   r/   rP   D   r0   r-   r/   N)
r(   r)   r*   r1   r2   r   r3   r   r   r/   r,   r-   r.   rH   rH   :   sE    GOMKSM!SM!8$$ r-   rH   c                   n    e Zd ZU eed<   eed<   eed<   eed<   eed<   ee   ed<   eed<    G d d	      Zy
)LimitAlertOutr   
alert_type	thresholdcurrent_usagelimit_valuemessagerM   c                       e Zd ZdZy)LimitAlertOut.ConfigTNr'   r,   r-   r.   r/   rY   Q   r0   r-   r/   N)	r(   r)   r*   r1   r2   r3   r   r   r/   r,   r-   r.   rR   rR   H   s7    GONc] r-   rR   c                   &    e Zd ZU eed<   dZeed<   y)SubscriptionCreater9   Tr=   N)r(   r)   r*   r1   r2   r=   r5   r,   r-   r.   r[   r[   U   s    LJr-   r[   c                   @    e Zd ZU eed<   eed<   eed<   dZee   ed<   y)PaymentCreatesubscription_idrI   rK   NrL   )	r(   r)   r*   r1   r2   r   r3   rL   r   r,   r-   r.   r]   r]   Z   s!    O$(NHSM(r-   r]   z/plans)response_modeldbc                     | j                  t              j                  t        j                  dk(        j	                         }|S )u}   Получить список всех доступных тарифных планов (публичный эндпоинт)T)queryr   filterr$   all)r`   planss     r.   	get_plansrf   c   s3     HHTN!!$..D"89==?ELr-   z/subscriptionc           	         | j                  t              j                  t        t        j                  |j                  k(  t        j
                  j                  ddg                  j                  t        j                  j                               j                         }|st        t
        j                  d      |S )u?   Получить текущую подписку тенантаactivepending_payment$   Подписка не найденаstatus_codedetail)rb   r   rc   r	   r8   r   in_order_byrM   descfirstr   HTTP_404_NOT_FOUND)r`   current_usersubscriptions      r.   get_current_subscriptionru   j   s     88L)00""l&<&<<##X/@$AB	

 h|&&++-.uuw  119
 	

 r-      )r_   rl   datac                 
   |j                  t              j                  t        j                  | j                  k(        j                         }|st        t        j                  d      |j                  t              j                  t        t        j                  |j                  k(  t        j                  dk(              j                         }|j                  t              j                  t        t        j                  |j                  k(  t        j                  dk(              j                         }|rM|j                  | j                  k(  r4| j                  |_        |j                          |j                  |       |S |rM|j                  | j                  k(  r4| j                  |_        |j                          |j                  |       |S |rd|_        |j                  dkD  rLddlm}m} |j                  |      j                  |j                  |j                  k(        j'                         j                         }|st        t        j(                  d      t+        t-        |j                              }	|j.                  |	k  r,t        t        j(                  d	|	 d
|j.                   d      |j.                  }
|xj.                  |	z  c_        |xj0                  |	z  c_         ||j                  d|	 |
|j.                  d|j2                   d      }|j5                  |       d}nd}t        |j                  | j                  |t7        j8                         t7        j8                         t;        d      z   | j                        }|j5                  |       |j=                          |j                  dkD  rt-        |j                        _        |rd|_        tA        |j                  |j                  t7        j8                         t7        j8                         t;        d      z   d|jB                        }|j5                  |       |j                  dkD  rvtE        |j                  |j                  	ddddtG        t7        j8                         jI                                t7        j8                               }|j5                  |       |j                          |j                  |       |S )uH   Создать новую подписку (обновить тариф)u   План не найденrk   rh   ri   	cancelledr   UserBalanceBalanceTransactionur   Баланс не найден. Пополните баланс для выбора платного тарифа.uP   Недостаточно средств на балансе. Требуется u    Р, доступно uQ    Р. Пополните баланс для выбора этого тарифа.subscription_payment   Оплата подписки Nr8   transaction_typerI   balance_beforebalance_afterr    reference_id   days)r8   r9   r   r;   r<   r=   r8   r^   rD   rE   rB   r"   RUB	completedbalancezBALANCE-r8   r^   rI   rJ   r   rK   rL   rN   )%rb   r   rc   r   r9   rq   r   r   rr   r   r	   r8   r=   commitrefreshr!   app.db.modelsr{   r|   with_for_updateHTTP_400_BAD_REQUESTr   r3   r   total_spentr   addr   utcnowr   flushr   r   r"   r   r1   	timestamp)rw   r`   rs   r:   current_subscriptionpending_subscriptionr{   r|   r   rI   r   transactionsubscription_statusrt   usagepayments                   r.   create_subscriptionr      sL    88D>  DLL!89??AD11/
 	
 88L188""l&<&<<8+	

 eg  88L188""l&<&<<#44	

 eg   4 < < L*.//'
		


'(##  4 < < L*.//'
		


'(## &1# AA ((;'..!!\%;%;;

/
EEG 	 "77 L 
 T//01 ??V#"77ijpiq  rH  IP  IX  IX  HY  Yj  k  !6!v% )",,37)!//8D
 	{ ' '  (("??$??$yb'99??L FF<HHJ A#&|#7  &1# (($__&??$yb'99 44E FF5M A",,(OO$%c(//*;*E*E*G&H%IJ!*	
 	wIIKJJ|r-   z/usagec           	      V   | j                  t              j                  t        t        j                  |j                  k(  t        j
                  dk(              j                         }|st        t
        j                  d      t        j                         }| j                  t              j                  t        t        j                  |j                  k(  t        j                  |k  t        j                  |k\              j                         }|sxt        |j                  |j                  ||t!        d      z   d|j"                  j$                        }| j'                  |       | j)                          | j+                  |       | j                  t-        j.                  t0        j                              j                  t        t0        j                  |j                  k(  t0        j2                  |j                  k\  t0        j2                  |j                  k              j5                         }||_        | j)                          |j$                  dkD  r||j$                  z  dz  nd}t9        ||j$                  t;        |d	      |j                  |j                  
      S )uI   Получить текущее использование лимитовrh   u5   Активная подписка не найденаrk   r   r   r   r   d      )rB   r"   rC   rD   rE   )rb   r   rc   r	   r8   r   rq   r   rr   r   r   r   r^   r   rD   rE   r   r:   r"   r   r   r   r   countr   rM   scalarrB   rA   round)r`   rs   rt   nowr   
sent_countrC   s          r.   	get_usager     s#    88L)00""l&<&<<8+	

 eg  11J
 	
 //
CHH[!((''<??:$$+""c)	
 eg 
 ",,(OOYB//  , 1 1 E E
 	u
		


5 $**\__56==""l&<&<<##u'9'99##u'7'77	
 fh   *EIIKHMHaHadeHezE$=$==CklO%!55oq1''## r-   z	/payments2   limitoffsetc                 2   |j                  t              j                  t        j                  |j                  k(        j	                  t        j
                  j                               j                  |      j                  |       j                         }|S )u0   Получить историю платежей)
rb   r   rc   r8   ro   rM   rp   r   r   rd   )r   r   r`   rs   paymentss        r.   get_paymentsr   W  sj     xx ''\333hw!!&&()&&.ucce  Or-   c           
         |j                  t              j                  t        t        j                  | j
                  k(  t        j                  |j                  k(              j                         }|st        t        j                  d      t        |j                  | j
                  | j                  d| j                  | j                  xs% dt        j                          j#                          t        j                                }|j%                  |       |j'                          |j)                  |       |S )u&   Создать новый платежrj   rk   r   zTXN-)r8   r^   rI   r   rK   rL   rN   )rb   r   rc   r	   r   r^   r8   rq   r   r   rr   r   rI   rK   rL   r   r   r   r   r   r   )rw   r`   rs   rt   r   s        r.   create_paymentr   f  s     88L)00OOt333""l&<&<<	

 eg  119
 	

 ((,,{{****TX__5F5P5P5R4S.T__&G FF7OIIKJJwNr-   z/alerts   c                    |j                  t              j                  t        j                  |j                  k(        j	                  t        j
                  j                               j                  |       j                         }|S )uN   Получить уведомления о превышении лимитов)	rb   r   rc   r8   ro   rM   rp   r   rd   )r   r`   rs   alertss       r.   get_limit_alertsr     sb     XXj!(( 6 66hz$$))+,UU5\##%  Mr-   z/check-limitsc                 B   | j                  t              j                  t        t        j                  |j                  k(  t        j
                  dk(              j                         }|sddiS t        j                         }| j                  t              j                  t        t        j                  |j                  k(  t        j                  |k  t        j                  |k\              j                         }|sddiS | j                  t        j                  t         j                              j                  t        t         j                  |j                  k(  t         j"                  |j                  k\  t         j"                  |j                  k              j%                         }|j&                  dkD  r||j&                  z  dz  nd}g }|dk\  rYt)        |j                  dd||j&                  d| d	|j&                   d
      }| j+                  |       |j-                  d       n|dk\  r]t)        |j                  dd||j&                  d| d	|j&                   d|dd      }| j+                  |       |j-                  d       na|dk\  r\t)        |j                  dd||j&                  d| d	|j&                   d|dd      }| j+                  |       |j-                  d       |r| j/                          t1        |d      |||j&                  dS )u`   Проверить лимиты и создать алерты при необходимостиrh   rW   u(   Нет активной подпискиu5   Нет записей об использованииr   r   exceededu6   Лимит превышен! Использовано u    из u    уведомлений.)r8   rS   rT   rU   rV   rW   Z   criticalu@   Критический уровень! Использовано u    уведомлений (z.1fz%).P   warningu7   Предупреждение! Использовано r   )rC   alerts_createdrU   r   )rb   r   rc   r	   r8   r   rq   r   r   r   r^   r   rD   rE   r   r   r   rM   r   r"   r   r   appendr   r   )	r`   rs   rt   r   r   r   
percentager   alerts	            r.   check_limitsr     s=    88L)00""l&<&<<8+	

 eg  EFF
//
CHH[!((''<??:$$+""c)	
 eg 
 RSS $**\__56==""l&<&<<##u'9'99##u'7'77	
 fh  DIC\C\_`C`*u8883>fgJ NS",,!$11LZLX^_d_x_x^y  zR  S
 	uj)	r	",,!$11VWaVbbhin  jC  jC  iD  D]  ^h  il  ]m  mp  q
 	uj)	r	",, $11Mj\Y_`e`y`y_z  {T  U_  `c  Td  dg  h
 	ui(
		 !Q/(#**	 r-   z/subscription/activatec                 	   ddl m}m} ddlm} | j                  d      }| j                  dd      } |t        | j                  dd                  }|st        t        j                  d	      |j                  t              j                  t        t        j                  |k(  t        j                  |j                  k(  t        j                  d
k(              j!                         }	|	st        t        j"                  d	      |dk(  r|j                  |      j                  |j                  |j                  k(        j!                         }
|
st        t        j                  d	      |j                  |      j                  |j                  |j                  k(        j%                         j!                         }
|
st        t        j                  d	      |
j&                  |k  rt        t        j                  d	      |
j&                  }|
xj&                  |z  c_        |
xj(                  |z  c_         ||j                  d| ||
j&                  d|	j*                  j,                   t        |	j                              }|j/                  |       |j                  t              j                  t        t        j                  |j                  k(  t        j                  dk(  t        j                  |k7              j1                  ddi       |j                  t              j                  t        t        j                  |j                  k(  t        j                  d
k(  t        j                  |k7              j1                  ddi       d|	_        t3        j4                         |	_        t3        j4                         t9        d      z   |	_        t3        j4                         }t=        |j                  |	j                  ||t9        d      z   d|	j*                  j>                        }|j/                  |       tA        |j                  |	j                  |dd||jC                          dtE        t3        j4                         jG                                t3        j4                               }|j/                  |       |jI                          |jK                  |	       d|	dS )uR   Активировать подписку после успешной оплатыr   rz   r   r^   rK   demorI   u%   ID подписки не указанrk   ri   uK   Подписка не найдена или уже активированаr   u   Баланс не найденu;   Недостаточно средств на балансеr}   r~   r   rh   r   ry   r   r   r   r   r   -r   u8   Подписка успешно активирована)rW   rt   )&r   r{   r|   decimalr   getr3   r   r   r   rb   r   rc   r	   r   r8   rq   rr   r   r   r   r:   r   r   updater   r   r;   r   r<   r   r"   r   upperr1   r   r   r   )rw   r`   rs   r{   r|   r   r^   rK   rI   rt   r   r   r   r   usage_recordr   s                   r.   activate_subscriptionr     s    >hh01OXX.7NS(A./0F33:
 	
 88L)00OO.""l&<&<<#44	
 eg  11`
 	
 "((;'..!!\%;%;;

%' 	 "777  ((;'..!!\%;%;;

/
EEG 	 "777 
 ??V#"77T  !6!v% )",,37)!//89J9J9O9O8PQ\__-
 	{ HH\!!""l&<&<<8+OO.	
 fh$% HH\!!""l&<&<<#44OO.	
 fh$% #L&oo/L&oo/)2DDL //
C(($++(--AAL FF< (($%(..013x7H7R7R7T3U2VW__&	G FF7OIIKJJ|Qcoppr-   N)7__doc__fastapir   r   r   r   sqlalchemy.ormr   
sqlalchemyr   r	   typingr
   r   r   r   r   r   app.db.sessionr   r   r   r   r   r   r   r   r   r   app.api.depsr   pydanticr   r   routerr   r7   rA   rH   rR   r[   r]   r   rf   ru   postr   r   r1   r   r   r   r   r4   r   r,   r-   r.   <module>r      s   > = " ! ! (  !   * %	
i 
i y  
I 
 
)I ) HT']3#FO '  4 OO<&/+, =* __#N &/+,O
OO OOd HX.&/+,@@ /@F KZ(89&/+,	 	 : [E &/+,!
!! F!H Id=&9:&/+,


 ;
 _&/+,TT Tn %& &/+,Dq
DqDq 'Dqr-   