o
    ȟ1i3                     @   s   d dl Z d dlZd dlZd dlZd dlmZ d dlmZ d dlmZ d dl	Z	d dl
mZ d dl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 d dlmZmZmZ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( G dd dZ)dS )    N)datetime)Any)DateTime)func)
joinedload)get_dbsettings)SendEnrollmentEmail)GenericError)
send_emailsend_order_summary_email)CartCourseBursaryDiscountApplicationParticipantBursaryCourseAllocationPaymentParentBursaryDiscountInfoWalletHistoryPaymentDetails
Attendance)DiscountCoupon)PaymentDetailsBaseCartBaseSchemac                   @   s   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd Zdd Zdd ZdededefddZdefddZd d! Zd"d# Zd$d% Zd&efd'd(Zd)efd*d+Zd,S )-PaymentServicegbpc                 C   s  g }d}t  }|  z|jD ]}|t|j}|tt	tj
t	jkt	jdkt	j|kt	j|jktjdktj|jk}| dkrn| }	|ttjt  ktjt  ktj|	jjk dkrn|	j}| ||}
t|
t| }|tt |d |d |d dkr|d nd ||j|j |||dkrdndd
 q|!t"| |#  W n t$y } z|%  t&| t'dd	d
d }~ww W d    d S 1 sw   Y  d S )Nr   TFid	user_typeparent)
cart_line_item_id
cart_ownerr   	parent_idparticipant_id	course_idcourse_original_amountdiscount_amountfinal_amountis_discount_applied  zCould not add to cartstatus_codeexc)(r   beginr#   queryr   getr$   r   joinr   bursary_discount_application_idr   filteris_approvedacademic_year_idis_usedcountfirstr   end_dater   todaydate
start_dateapplicationdiscount_priceget_course_amountfloatappendstruuiduuid4amountbulk_insert_mappingsr   commit	Exceptionrollbackprintr
   )selfrequestuser
cart_itemsr&   dbrowcourse_instanceZdiscount_queryZdiscount_instancecourse_amountr'   e rS   /app/services/payment.pyadd_to_cart   sh   



	

"zPaymentService.add_to_cartc                 C   s~   |j }|jt  k r=|tjtj	|j
k  }t| t|dk|jd u|jd ugr=|j| }t|d|j }|S )Nr   )rD   r;   r   nowr:   r.   r   attendance_dater2   r$   r   distinctr6   rI   allno_of_classesrate_per_classmax)rJ   rN   courserQ   Zno_of_attendanceZremaining_classrS   rS   rT   r>   H   s   "
z PaymentService.get_course_amountc           
   
   C   s   t  h}g }|tj tj|d ktjdk }dd |D }|D ]<}|t	
|}|ttj|d ktj|ktjdk }dd |D }	|||j|jtdd |	D |	d q%|W  d    S 1 snw   Y  d S )	Nr   Fc                 S      g | ]}|d  qS r   rS   .0rO   rS   rS   rT   
<listcomp>b       z2PaymentService.list_cart_items.<locals>.<listcomp>c                 S   s   g | ]	}t | qS rS   )r   model_validate
model_dumpra   itemrS   rS   rT   rb   h   s    c                 s   s     | ]}| d dpdV  qdS )r'   r   N)r/   )ra   Zcart_rowrS   rS   rT   	<genexpr>m   s    z1PaymentService.list_cart_items.<locals>.<genexpr>)r#   participant_first_nameparticipant_last_nametotal_amountcourse_details)r   r.   r   r#   rX   r2   r!   is_cart_processedrY   r   r/   r@   
first_name	last_namesum)
rJ   rL   rN   Z	cart_dataZparticipant_list_queryZparticipant_listr#   participantZcart_item_queryrl   rS   rS   rT   list_cart_items]   s4   
$zPaymentService.list_cart_itemsc                 C   sZ   t   }|ttj|ktj|d k  |  W d    d S 1 s&w   Y  d S )Nr   )r   r.   r   r2   r    r!   deleterF   )rJ   r    rL   rN   rS   rS   rT   remove_cart_items   s   &
"zPaymentService.remove_cart_itemc                 C   s0   t t d }t|dd  }| d| dS )Ni  i-z-lwxbu)inttimerA   )rJ   user_id	timestampbase_idrS   rS   rT   generate_transaction_idx   s   z&PaymentService.generate_transaction_idc                 C   s   d}|j rVt F}|d dkr|t|d j}n+|d dkr>|ttj|d ktj	
d  j}W d    |S W d    |S W d    |S 1 sQw   Y  |S )Nr   r   r   r   rq   )
use_walletr   r.   r   r/   wallet_amountr   r2   r   r"   is_r7   )rJ   rK   rL   r}   rN   rS   rS   rT   fetch_wallet_amount~   s*   



z"PaymentService.fetch_wallet_amountc                 C   s8  |rt  0}|ttj|jktj|ktjdk }||j	kr.t
|dfW  d    S W d    n1 s8w   Y  d}|jr`t
||jkr_|jdkrZt
|t
|j d }nt
|j}n|jdkrqt
|t
|j d }nt
|j}t|dr|jrt|t
|j}t|t
|}tdt
|| }t
||fS )NTr   
percentaged   max_discount)r   r.   r   r2   discount_coupon_idr   
created_byis_payment_completedr6   uses_per_customerr?   	rule_typemin_cart_valuediscount_typediscount_valuehasattrr   minr\   )rJ   cart_total_amountdiscount_coupon_instancerx   rN   usage_countcalculated_discountrS   rS   rT   apply_discount   s:   








zPaymentService.apply_discountc                 C   s  d }d }d}d}d}d }d}	d }
d}t d| t 8}z|ttj|d ktjdk}| dkr;tddd|j	rut
d	d
 |D su|ttj|j	ktjdktjt  ktjt  ktjdk }
|
sutddd| j|d d}| }tdd |D }t d| |
rt
dd
 |D s| ||
|d \}}|jr||d  }t d| |jr|dkrtdt| ||}||k r|}|| }d}n|}|| }d}t|d}t d| |dkr| |||}|j }nd}t }d}	||||||||||	|||
r|
j!nd |jd}| "||| ||d|j|t#j$ d| t#j% d| dW W  d    S  t&yR } z|'  tdd| dd }~ww 1 sWw   Y  d S )Npendingr   Fzsession request datar     zCart is emptyr*   c                 s       | ]}|j d kV  qdS r   Nr&   rf   rS   rS   rT   rh          z9PaymentService.create_checkout_session.<locals>.<genexpr>Tz;Discount coupon is not valid or not applicable to this cart)rx   c                 S   s   g | ]}|j qS rS   )r'   rf   rS   rS   rT   rb      s    z:PaymentService.create_checkout_session.<locals>.<listcomp>r   c                 s   r   r   r   rf   rS   rS   rT   rh      r   g?g           success)rK   rL   rM   r   r}   used_wallet_amountsession_urlpayment_statuspaid_onr   transaction_batch_idcalculated_coupon_discountr   charity/)payment_urlr   r   is_wallet_usedr   success_url
cancel_urlr)   z#Could not create checkout session: )(rI   r   r.   r   r2   r!   rm   r6   r
   discount_coupon_codeanyr   codestatusr;   r   rV   r:   r8   is_applicable_for_courser7   r{   rY   rp   r   r   r|   r\   r?   r   roundgenerate_linkurlr   save_payment_datar   stripe_success_urlstripe_cancel_urlrG   rH   )rJ   rK   rL   r   
session_idr   r}   r   r   r   r   r   rN   rM   r   r   sessionpayment_datarR   rS   rS   rT   create_checkout_session   s   

"





Vz&PaymentService.create_checkout_sessionc                 C   s    t d |jj|g dd}|S )Nzcreating webhook)zpayment_intent.succeededcheckout.session.completedzpayment_intent.payment_failed)r   enabled_events)rI   WebhookEndpointcreate)rJ   stripewebhook_urlwebhookrS   rS   rT   create_webhook  s   zPaymentService.create_webhookc              	   C   s  d dd |D }d| jt|d dd| dd	d
g}tjt_tjjj	dg|dd|itj
 d| tj d| d}tdtj
 d|  tdtj d|  |jrtj d}tj }d}	|D ]}
|
j|krrd}	 nqgt|	 |	s| t| |S )N,c                 S   s   g | ]}|j jqS rS   )r]   namerf   rS   rS   rT   rb     rc   z0PaymentService.generate_link.<locals>.<listcomp>   r   zWac Course Purchasez
Course(s):)r   description)currencyunit_amountproduct_data)quantity
price_datacardpaymentr   r   )payment_method_types
line_itemsmodemetadatar   r   z
sucess urlz
cancel urlz/payment/stripe/webhookFT)r0   r   rv   r   stripe_secret_keyr   api_keycheckoutSessionr   r   r   rI   r   stripe_webhook_urlr   listr   )rJ   rM   rk   r   r   r   r   r   existing_webhooksis_webhook_existsr   rS   rS   rT   r     s>   

zPaymentService.generate_linkc           
      C   s  g }g }|d D ]}| |j t|j|j|j|jd}| | q|t	tj
|j|d dddd td%i d|d	 d
 d|d	 d d|d d|d d|jd|d d|d dddt d|d dd dd d|d d|d d|d d|d d|d d|}|| |  |d dkrt|j |d dkr|d	 d d kr|t|d	 d
 }	|	 j|d 8  _n|t|d	 d
 }	|	 j|d 8  _|t|j|d	 d |d	 d
 |d d!|jd"dd#d$	 |  d S d S d S )&NrM   )purchased_for_idr$   r%   r'   r   T)r   rm   Fsynchronize_sessionr   rL   r   r   
stripe_urlr   total_paid_amountr   r   r   r   payment_methodZCARDintent_created_onr   
payment_idpayment_gateway_session_idr   r   coupon_discounted_amountr   r   payment_detailsr   r   purchaseN/APurchased course(s)	r   r   refund_for_idrD   refund_typetransaction_idnote	is_creditmessagerS   )r@   r   r   r#   r$   r%   r'   r.   r   r2   in_updater   r|   r   rV   addrF   r   r   r/   r}   r   r   r   )
rJ   rN   rK   r   r   Zprocessed_cart_itemrg   pdr   	paid_userrS   rS   rT   r   ;  s   

	




z PaymentService.save_payment_datapayload
sig_headerbackground_tasksc           	      C   s  t  }t|d}|d dkr|d d d d }|d d d d	kr|ttj|k }|s>	 W d    d S |j	d
krU|t
|j}| j|j8  _n|t|j}| j|j8  _|ttj|kjd|d d d dt ddd |ttj|kddi n|ttj|kjddddd |jr|t|j|j	|j|jd|jdddd	 |  |jrt|j W d    d S W d    d S W d    d S 1 sw   Y  d S )Nzutf-8typer   dataobjectr   r   r   paidr   r   payment_intentT)r   r   r   r   fetchr   rm   failedF)r   r   r   r   r   r   )r   jsonloadsdecoder.   r   r2   r   r7   r   r   r/   r   r}   r   r   r   r   rV   r   r   r   r   r   rF   r   r   )	rJ   r   r   r   rN   eventr   Zpayment_instancer   rS   rS   rT   update_payment  sn   

	."zPaymentService.update_paymentr   c                 C   sZ   t   }|ttj|ktjdk}t| dkdW  d    S 1 s&w   Y  d S )NTr   )r   )r   r.   r   r2   r   r   dictr6   )rJ   r   rN   r.   rS   rS   rT   verify_payment  s   $zPaymentService.verify_paymentc                 C   s  t  <}g }g }|tttjttjtjdk}t	|d  |d dkr5|tj
|d k}n|d dkrI|tjdktj
|d k}|jr|tjtj|j }dd |D }|tjtj|j }dd |D }|| |tj
|}|jr|tj|j}|jr|tjtj|j }d	d |D }|tjtj|j }d
d |D }|| |tj
|}| D ]^}	|	j|vr6|	jdkr|t|	j
}
n	|t|	j
}
d }|	jr|	jj|	jj|	jj|	jjd}||	j|	j|
j d|
j  |
j|
j|	j!|	j"|	j|	j|	j#|	j$|d ||	j q|W  d    S 1 sDw   Y  d S )NTr   r   r   rq   c                 S   r^   r_   rS   r`   rS   rS   rT   rb     rc   z2PaymentService.payment_history.<locals>.<listcomp>c                 S   r^   r_   rS   r`   rS   rS   rT   rb     rc   c                 S   r^   r_   rS   r`   rS   rS   rT   rb     rc   c                 S   r^   r_   rS   r`   rS   rS   rT   rb     rc   )Zcoupon_coder&   r   r    )r   r   Zparent_or_participant_full_nameZparent_or_participant_emailZ#parent_or_participant_mobile_numberrk   r   r   r   Zis_wallet_userr   discount_details)%r   r.   r   optionsr   r   discount_couponr2   r   rI   r   r   emailr   r   	icontainsrY   r   extendr   r   r   ilikemobile_numberr   r/   r   r   r   r   r@   rn   ro   r   r   r   r   )rJ   rL   rK   rN   Zdata_without_duplicateZadded_transactionsr.   Z
parent_idsZparticipant_idsrO   Zguardianr   rS   rS   rT   payment_history  s   

  
 

&zPaymentService.payment_historyc           	   	   C   s   t  p}g }|ttj|k }|tttj	tj
|jk }|D ]0}t| }|jj|jjd|d< |j	j|j	j|j	jj|j	jj|j	jjd|d< || q)|j|j|j|j|j|j|d}|W  d    S 1 svw   Y  d S )N)rn   ro   rq   )r   r   	age_grouptermacademic_yearr]   )r   r   rk   r   r   r   r   )r   r.   r   r2   r   r7   r   r  r   r]   r   r   rY   r   rd   re   purchased_participantrn   ro   r   r	  labelr
  r  titler@   r   r   r   r   )	rJ   r   rN   Zhistory_listr   r.   rO   r   Zpayments_details_allrS   rS   rT   payment_history_details  s<   


	$z&PaymentService.payment_history_detailsc                 C   s  t  }|tttjtjkttjtjkt	tj
t	jktjdk}|d dkr8|tj|d k}n|d dkrL|tjdktj|d k}|jrc|tt	jdt	jd|j d}|jro|tj|jk}|jr{|tj|jk}g }| D ];}||j|j|jj|jj|jj|jj d|jj |jj|j |jj!r|jj!j"nd|jj#r|jj#jnd|jj$d	 q|W  d   S 1 sw   Y  dS )
zW
        List all purchased courses for the current user with optional filters
        Tr   r   r   rq   r   %N)r   r$   course_namecourse_start_datecourse_end_dateparticipant_nameZpurchase_dateamount_paidr  r
  r   )%r   r.   r   r0   r   r   r   r   r$   r   r   r2   r   r   r   r  r   concatrn   ro   r  r4   term_idrY   r@   r]   r   r;   r8   r  r   r   r'   r  r  r
  r   )rJ   rL   rK   rN   r.   resultsrg   rS   rS   rT   get_purchased_courses%  sP   
$z$PaymentService.get_purchased_coursesr   c                 C   s  t  u}|tttjtj|k }|st	dddg }|jD ]<}|
|j|j|j|j|j|jr9|jjnd|jrA|jjnd|jrN|jjrN|jjjnd|jr[|jjr[|jjjndd	 q$|j|j|j|j|j|j|dW  d   S 1 s{w   Y  dS )z;
        Get payment and its details by payment ID
        r   zPayment not foundr+   detailN	r   r   r$   r%   r'   r  r  r  r
  )r   r   r   r   r   r   r   )r   r.   r   r  r   r   r2   r   r7   HTTPExceptionr@   r   r$   r%   r'   r  	full_namer]   r   r  r  r
  r   r   r   r   r   )rJ   r   rN   r   r   r  rS   rS   rT   get_payment_by_idZ  s<   


$z PaymentService.get_payment_by_idpayment_details_idc                 C   s   t  T}|ttj|k }|stddd|j|j|j|j	|j
|jr*|jjnd |jr2|jjnd |jr?|jjr?|jjjnd |jrL|jjrL|jjjnd d	W  d    S 1 sZw   Y  d S )Nr   zPayment details not foundr  r  )r   r.   r   r2   r   r7   r  r   r$   r%   r'   r  r  r]   r   r  r  r
  )rJ   r   rN   r   rS   rS   rT   get_payment_details~  s&   
$z"PaymentService.get_payment_detailsN)__name__
__module____qualname__r   rU   r>   rr   rt   r{   r   r   r   r   r   r   rA   r   r   r   r  r  r  r  r!  rS   rS   rS   rT   r      s(    .#g
F2J"5$r   )*r   pprintrw   rB   r   typingr   xmlrpc.clientr   r   
sqlalchemyr   sqlalchemy.ormr   core.configr   r   Zcore.email.configr	   core.security.exceptionsr
   core.utilityr   r   modelsr   r   r   r   r   r   r   r   r   r   r   Zmodels.discount_couponr   schema.paymentr   r   r   rS   rS   rS   rT   <module>   s$    4