Ë
    /e=iØ£  ã                   ób  — d 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
 ddlmZmZ ddlmZmZmZmZ ddlmZmZmZmZmZmZ dd	lmZmZm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$ G d„ de«      Z% G d„ de«      Z&y)z˜
Comprehensive tests for WalletService covering all documented functionality.

Tests cover:
- Standard cases
- Edge cases
- Error cases
- Outlier cases
é    )ÚDecimal©ÚdatetimeÚ	timedelta)ÚTestCaseÚTransactionTestCase)Útransaction)ÚWalletServiceÚWalletRepository)ÚInsufficientBalanceErrorÚInvalidPointTypeErrorÚInvalidParamsErrorÚWalletOperationError)ÚWALLET_DEPOSITÚWALLET_WITHDRAWÚROI_DISTRIBUTIONÚREFERRAL_BONUSÚget_transaction_typeÚget_transaction_type_name)ÚTestUserÚ
TestWalletÚTestWalletCustomFieldc                   óv   — e Zd ZdZd„ Zd„ Zd„ Zd„ Zd„ Zd„ Z	d„ Z
d	„ Zd
„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zy)ÚWalletServiceAddPointTestszTests for add_point() method.c                 óÚ   — t         j                  j                  dd¬«      | _        ddddœ| _        t        t         | j                  ¬«      | _        t        | j                  «      | _        y	©
úSet up test fixtures.Útestuserútest@example.com©ÚusernameÚemailé   r   é   ©Úcredit_balanceÚreward_pointsÚcrypto_balance©Ú
user_modelÚpoint_typesN©	r   ÚobjectsÚcreateÚuserr+   r   Úrepor
   Úservice©Úselfs    úS/home/cursorai/projects/telegram-earn/sandbox/test_app/tests/test_wallet_service.pyÚsetUpz WalletServiceAddPointTests.setUp$   ó_   € ä×$Ñ$×+Ñ+°ZÐGYÐ+ÓZˆŒ	àØØñ
ˆÔô
 %ÜØ×(Ñ(ô
ˆŒ	ô % T§Y¡YÓ/ˆ�ó    c                 ó^  — | j                   j                  | j                  j                  dt	        d«      d¬«      }| j                  |t        «       | j                  |d«       | j                  j                  «        | j                  | j                  j                  t	        d«      «       y)z)Standard case: Add points to user wallet.r&   ú100.00zTest deposit©Úuser_idÚ
point_typeÚamountÚremarksr   N)r1   Ú	add_pointr/   Úidr   ÚassertIsInstanceÚintÚassertGreaterÚrefresh_from_dbÚassertEqualr&   ©r3   Útransaction_ids     r4   Útest_add_point_standardz2WalletServiceAddPointTests.test_add_point_standard2   s‡   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜8Ó$Ø"ð	 0ó 
ˆð 	×Ñ˜n¬cÔ2Ø×Ñ˜>¨1Ô-ð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸8Ó3DÕEr7   c                 ó‚  — | j                   j                  | j                  j                  dt	        d«      dt
        ¬«      }| j                  |t        «       | j                   j                  |«      }| j                  |«       | j                  |j                  t
        «       | j                  |j                  d«       y)z*Add points with transaction type constant.r&   ú50.00ÚDeposit©r;   r<   r=   r>   Ú
trans_typeÚcN)r1   r?   r/   r@   r   r   rA   rB   Úget_transaction_by_idÚassertIsNotNonerE   rM   Útype©r3   rG   r	   s      r4   Ú$test_add_point_with_transaction_typez?WalletServiceAddPointTests.test_add_point_with_transaction_typeB   s™   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜7Ó#ØÜ%ð 0ó 
ˆð 	×Ñ˜n¬cÔ2ð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜[Ô)Ø×Ñ˜×/Ñ/´Ô@Ø×Ñ˜×)Ñ)¨3Õ/r7   c                 óð   — d}| j                   j                  | j                  j                  dt	        d«      d|¬«      }| j                   j                  |«      }| j                  |j                  |«       y)z.Add points with initiator ID (user-initiated).éç  r&   z25.00zUser deposit©r;   r<   r=   r>   ÚiidN©r1   r?   r/   r@   r   rO   rE   rW   )r3   Úinitiator_idrG   r	   s       r4   Útest_add_point_with_iidz2WalletServiceAddPointTests.test_add_point_with_iidT   sf   € àˆØŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜7Ó#Ø"Øð 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜Ÿ™¨,Õ7r7   c                 óê   — | j                   j                  | j                  j                  dt	        d«      d¬«      }| j                   j                  |«      }| j                  |j                  d«       y)z4Add points with system initiator (default iid=-100).r&   ú10.00zSystem depositr:   éœÿÿÿNrX   rR   s      r4   Útest_add_point_system_initiatedz:WalletServiceAddPointTests.test_add_point_system_initiatedb   s^   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜7Ó#Ø$ð	 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜Ÿ™¨$Õ/r7   c           
      ó:  — | j                   j                  | j                  j                  dt	        d«      dddddœi¬«      }| j                   j                  |«      }| j                  |j                  d	   d«       | j                  |j                  d
   d«       y)z%Add points with extra data in params.r&   r9   zDeposit with extra dataÚdatai90  Úbank_transfer)Ú
payment_idÚsource©r;   r<   r=   r>   Úparamsrb   rc   N©r1   r?   r/   r@   r   rO   rE   Ú
extra_datarR   s      r4   Útest_add_point_with_extra_dataz9WalletServiceAddPointTests.test_add_point_with_extra_datan   s“   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜8Ó$Ø-àØ"'Ø-ñðð 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜×/Ñ/°Ñ=¸uÔEØ×Ñ˜×/Ñ/°Ñ9¸?ÕKr7   c                 óº  — | j                   j                  | j                  j                  dt	        d«      d¬«       | j                   j                  | j                  j                  dt	        d«      d¬«       | j                   j                  | j                  j                  dt	        d	«      d
¬«       | j                  j                  «        | j                  | j                  j                  t	        d«      «       | j                  | j                  j                  t	        d«      «       | j                  | j                  j                  t	        d	«      «       y)z$Add points to different point types.r&   r9   zCredit depositr:   r'   Ú50zReward pointsr(   ú
0.00000001zCrypto depositN©
r1   r?   r/   r@   r   rD   rE   r&   r'   r(   r2   s    r4   Ú#test_add_point_multiple_point_typesz>WalletServiceAddPointTests.test_add_point_multiple_point_types�   s  € ð 	�‰×ÑØ—I‘I—L‘LØ'Ü˜8Ó$Ø$ð	 	ô 	
ð 	�‰×ÑØ—I‘I—L‘LØ&Ü˜4“=Ø#ð	 	ô 	
ð 	�‰×ÑØ—I‘I—L‘LØ'Ü˜<Ó(Ø$ð	 	ô 	
ð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸8Ó3DÔEØ×Ñ˜Ÿ™×0Ñ0´'¸$³-Ô@Ø×Ñ˜Ÿ™×1Ñ1´7¸<Ó3HÕIr7   c                 ó"  — | j                   j                  | j                  j                  dt	        d«      d¬«       | j                  j                  «        | j                  | j                  j                  t	        d«      «       | j                   j                  | j                  j                  dt	        d«      d¬«       | j                  j                  «        | j                  | j                  j                  t	        d«      «       | j                   j                  | j                  j                  d	t	        d
«      d¬«       | j                  j                  «        | j                  | j                  j                  t	        d«      «       y)ú Test decimal precision handling.r&   ú100.999úTest roundingr:   z101.00r'   z50.7Ú51r(   z0.123456789z
0.12345679Nrl   r2   s    r4   Ú test_add_point_decimal_precisionz;WalletServiceAddPointTests.test_add_point_decimal_precision    s)  € ð 	�‰×ÑØ—I‘I—L‘LØ'Ü˜9Ó%Ø#ð	 	ô 	
ð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸8Ó3DÔEð 	�‰×ÑØ—I‘I—L‘LØ&Ü˜6“?Ø#ð	 	ô 	
ð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×0Ñ0´'¸$³-Ô@ð 	�‰×ÑØ—I‘I—L‘LØ'Ü˜=Ó)Ø#ð	 	ô 	
ð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸<Ó3HÕIr7   c                 óP  — t        d«      t        d«      t        d«      g}|D ]8  }| j                  j                  | j                  j                  d|d|› �¬«       Œ: | j                  j                  «        | j                  | j                  j                  t        d«      «       y)	z-Test multiple additions accumulate correctly.r\   z20.00z30.00r&   úDeposit r:   z60.00N)r   r1   r?   r/   r@   rD   rE   r&   ©r3   Úamountsr=   s      r4   Útest_add_point_accumulationz6WalletServiceAddPointTests.test_add_point_accumulationÀ   sŠ   € ä˜7Ó#¤W¨WÓ%5´w¸wÓ7GÐHˆãˆFØ�L‰L×"Ñ"ØŸ	™	Ÿ™Ø+ØØ" 6 (Ð+ð	 #õ ð ð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸7Ó3CÕDr7   c                 ó:  — | j                   j                  | j                  j                  dt	        d«      d¬«      }| j                  |t        «       | j                  j                  «        | j                  | j                  j                  t	        d«      «       y)zEdge case: Add zero amount.r&   ú0.00zZero depositr:   N)
r1   r?   r/   r@   r   rA   rB   rD   rE   r&   rF   s     r4   Útest_add_point_zero_amountz5WalletServiceAddPointTests.test_add_point_zero_amountÏ   ss   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜6“?Ø"ð	 0ó 
ˆð 	×Ñ˜n¬cÔ2Ø�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸6³?ÕCr7   c                 ó:  — | j                   j                  | j                  j                  dt	        d«      d¬«      }| j                  |t        «       | j                  j                  «        | j                  | j                  j                  t	        d«      «       y)z!Edge case: Add very small amount.r(   rk   zVery small depositr:   N)
r1   r?   r/   r@   r   rA   rB   rD   rE   r(   rF   s     r4   Ú test_add_point_very_small_amountz;WalletServiceAddPointTests.test_add_point_very_small_amountÜ   su   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜<Ó(Ø(ð	 0ó 
ˆð 	×Ñ˜n¬cÔ2Ø�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸<Ó3HÕIr7   c                 ó,  — t        d«      }| j                  j                  | j                  j                  d|d¬«      }| j                  |t        «       | j                  j                  «        | j                  | j                  j                  |«       y)z!Edge case: Add very large amount.z9999999999999.99r&   zLarge depositr:   N)
r   r1   r?   r/   r@   rA   rB   rD   rE   r&   )r3   Úlarge_amountrG   s      r4   Ú test_add_point_very_large_amountz;WalletServiceAddPointTests.test_add_point_very_large_amounté   sx   € ô Ð1Ó2ˆØŸ™×/Ñ/Ø—I‘I—L‘LØ'ØØ#ð	 0ó 
ˆð 	×Ñ˜n¬cÔ2Ø�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1°<Õ@r7   c                 ó  — | j                  t        «      5 }| j                  j                  | j                  j
                  dt        d«      d¬«       ddd«       | j                  j                  j                  d«       y# 1 sw Y   Œ0xY w)zError case: Invalid point type.Úinvalid_typer9   ÚTestr:   N)
ÚassertRaisesr   r1   r?   r/   r@   r   rE   Ú	exceptionr<   ©r3   Úcms     r4   Ú!test_add_point_invalid_point_typez<WalletServiceAddPointTests.test_add_point_invalid_point_typeû   sm   € à×ÑÔ4Ô5¸Ø�L‰L×"Ñ"ØŸ	™	Ÿ™Ø)Ü˜xÓ(Øð	 #ô ÷ 6ð 	×Ñ˜Ÿ™×0Ñ0°.ÕA÷ 6Ð5ús   –=BÂBc                 ó  — | j                  t        «      5 }| j                  j                  | j                  j
                  dt        d«      dd¬«       ddd«       | j                  j                  j                  d«       y# 1 sw Y   Œ0xY w)z!Error case: params is not a dict.r&   r9   rƒ   ú
not a dictrd   Nr?   ©
r„   r   r1   r?   r/   r@   r   rE   r…   Úmethodr†   s     r4   Ú&test_add_point_invalid_params_not_dictzAWalletServiceAddPointTests.test_add_point_invalid_params_not_dict  sp   € à×ÑÔ1Ô2°bØ�L‰L×"Ñ"ØŸ	™	Ÿ™Ø+Ü˜xÓ(ØØ#ð #ô ÷ 3ð 	×Ñ˜Ÿ™×,Ñ,¨kÕ:÷ 3Ð2ús   –>BÂBc           	      ó"  — | j                  t        «      5 }| j                  j                  | j                  j
                  dt        d«      dddi¬«       ddd«       | j                  j                  j                  d«       y# 1 sw Y   Œ0xY w)	z)Error case: params['data'] is not a dict.r&   r9   rƒ   r`   rŠ   rd   Nr?   r‹   r†   s     r4   Ú+test_add_point_invalid_params_data_not_dictzFWalletServiceAddPointTests.test_add_point_invalid_params_data_not_dict  su   € à×ÑÔ1Ô2°bØ�L‰L×"Ñ"ØŸ	™	Ÿ™Ø+Ü˜xÓ(ØØ Ð-ð #ô ÷ 3ð 	×Ñ˜Ÿ™×,Ñ,¨kÕ:÷ 3Ð2ús   –A BÂBc                 ó<  — g d¢}|D ]‡  }| j                  t        «      5 }| j                  j                  | j                  j
                  dt        d«      dd|dii¬«       ddd«       | j                  j                  j                  d	«       Œ‰ y# 1 sw Y   Œ2xY w)
z)Error case: Reserved field in extra_data.)
r@   ÚwtyperW   ÚuidrQ   r=   ÚbalancerM   ÚdescrÚcdater&   r9   rƒ   r`   Úvaluerd   Nr?   r‹   )r3   Úreserved_fieldsÚfieldr‡   s       r4   Ú+test_add_point_reserved_field_in_extra_datazFWalletServiceAddPointTests.test_add_point_reserved_field_in_extra_data!  s‡   € âtˆã$ˆEØ×"Ñ"Ô#5Ô6¸"Ø—‘×&Ñ&Ø ŸI™IŸL™LØ/Ü" 8Ó,Ø"Ø" U¨GÐ$4Ð5ð 'ô ÷ 7ð ×Ñ˜RŸ\™\×0Ñ0°+Õ>ñ %ß6Ð6ús   ŸABÂB	c                 ó¨   — | j                  t        «      5  | j                  j                  ddt	        d«      d¬«       ddd«       y# 1 sw Y   yxY w)z+Edge case: Add points to non-existent user.éŸ† r&   r9   rƒ   r:   N)r„   r   r1   r?   r   r2   s    r4   Útest_add_point_nonexistent_userz:WalletServiceAddPointTests.test_add_point_nonexistent_user0  sG   € ð ×ÑÔ3Õ4Ø�L‰L×"Ñ"ØØ+Ü˜xÓ(Øð	 #ô ÷ 5×4Ñ4ús   –)AÁAN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r5   rH   rS   rZ   r^   rh   rm   rs   rx   r{   r}   r€   rˆ   r�   r�   r™   rœ   © r7   r4   r   r   !   sd   „ Ù'ò0òFò 0ò$8ò
0òLò&Jò>Jò@EòDòJòAò$
Bò;ò;ò?ó	r7   r   c                   óL   — e Zd ZdZd„ Zd„ Zd„ Zd„ Zd„ Zd„ Z	d„ Z
d	„ Zd
„ Zd„ Zy)ÚWalletServiceDeductPointTestsz Tests for deduct_point() method.c                 óR  — t         j                  j                  dd¬«      | _        ddddœ| _        t        t         | j                  ¬«      | _        t        | j                  «      | _        | j                  j                  | j                  j                  d	t        d
«      d¬«       y)r   r   r   r    r#   r   r$   r%   r)   r&   ú1000.00úInitial depositr:   N©r   r-   r.   r/   r+   r   r0   r
   r1   r?   r@   r   r2   s    r4   r5   z#WalletServiceDeductPointTests.setUp?  s‘   € ä×$Ñ$×+Ñ+°ZÐGYÐ+ÓZˆŒ	àØØñ
ˆÔô
 %ÜØ×(Ñ(ô
ˆŒ	ô % T§Y¡YÓ/ˆŒð 	�‰×ÑØ—I‘I—L‘LØ'Ü˜9Ó%Ø%ð	 	õ 	
r7   c                 ó^  — | j                   j                  | j                  j                  dt	        d«      d¬«      }| j                  |t        «       | j                  |d«       | j                  j                  «        | j                  | j                  j                  t	        d«      «       y)z)Standard case: Deduct points from wallet.r&   r9   Ú
Withdrawalr:   r   z900.00N)r1   Údeduct_pointr/   r@   r   rA   rB   rC   rD   rE   r&   rF   s     r4   Útest_deduct_point_standardz8WalletServiceDeductPointTests.test_deduct_point_standardU  s‡   € àŸ™×2Ñ2Ø—I‘I—L‘LØ'Ü˜8Ó$Ø ð	 3ó 
ˆð 	×Ñ˜n¬cÔ2Ø×Ñ˜>¨1Ô-ð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸8Ó3DÕEr7   c                 ó4  — | j                   j                  | j                  j                  dt	        d«      dt
        ¬«      }| j                   j                  |«      }| j                  |j                  t
        «       | j                  |j                  d«       y)z-Deduct points with transaction type constant.r&   rJ   r©   rL   ÚdN)
r1   rª   r/   r@   r   r   rO   rE   rM   rQ   rR   s      r4   Ú'test_deduct_point_with_transaction_typezEWalletServiceDeductPointTests.test_deduct_point_with_transaction_typee  sy   € àŸ™×2Ñ2Ø—I‘I—L‘LØ'Ü˜7Ó#Ø Ü&ð 3ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜×/Ñ/´ÔAØ×Ñ˜×)Ñ)¨3Õ/r7   c                 ó°  — | j                  t        «      5 }| j                  j                  | j                  j
                  dt        d«      d¬«       ddd«       | j                  j                  j                  «       | j                  |j                  j                  «       | j                  |j                  j                  d«       y# 1 sw Y   ŒzxY w)z!Error case: Insufficient balance.r&   ú2000.00zLarge withdrawalr:   Ng     @Ÿ@)r„   r   r1   rª   r/   r@   r   rP   r…   Ú	availableÚ	requestedrE   r†   s     r4   Ú&test_deduct_point_insufficient_balancezDWalletServiceDeductPointTests.test_deduct_point_insufficient_balances  s�   € à×ÑÔ7Ô8¸BØ�L‰L×%Ñ%ØŸ	™	Ÿ™Ø+Ü˜yÓ)Ø*ð	 &ô ÷ 9ð 	×Ñ˜RŸ\™\×3Ñ3Ô4Ø×Ñ˜RŸ\™\×3Ñ3Ô4Ø×Ñ˜Ÿ™×/Ñ/°Õ9÷ 9Ð8ús   –=CÃCc                 óˆ  — | j                   j                  «        | j                   j                  }| j                  j	                  | j                   j
                  d|d¬«      }| j                  |t        «       | j                   j                  «        | j                  | j                   j                  t        d«      «       y)z Edge case: Deduct exact balance.r&   zFull withdrawalr:   rz   N)
r/   rD   r&   r1   rª   r@   rA   rB   rE   r   )r3   Úcurrent_balancerG   s      r4   Útest_deduct_point_exact_balancez=WalletServiceDeductPointTests.test_deduct_point_exact_balance�  sŽ   € à�	‰	×!Ñ!Ô#ØŸ)™)×2Ñ2ˆàŸ™×2Ñ2Ø—I‘I—L‘LØ'Ø"Ø%ð	 3ó 
ˆð 	×Ñ˜n¬cÔ2Ø�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸6³?ÕCr7   c                 ó<  — | j                   j                  | j                  j                  dt	        d«      dd¬«      }| j                  |t        «       | j                  j                  «        | j                  | j                  j                  t	        d«      «       y)z"Edge case: Allow negative balance.r&   r°   Ú	OverdraftT)r;   r<   r=   r>   Úallow_negativez-1000.00N)
r1   rª   r/   r@   r   rA   rB   rD   rE   r&   rF   s     r4   Ú test_deduct_point_allow_negativez>WalletServiceDeductPointTests.test_deduct_point_allow_negative‘  sx   € àŸ™×2Ñ2Ø—I‘I—L‘LØ'Ü˜9Ó%ØØð 3ó 
ˆð 	×Ñ˜n¬cÔ2Ø�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸:Ó3FÕGr7   c                 ó  — | j                   j                  | j                  j                  dt	        d«      d¬«       | j                  j                  «        | j                  | j                  j                  t	        d«      «       y)ro   r&   rp   rq   r:   z899.00N)r1   rª   r/   r@   r   rD   rE   r&   r2   s    r4   Ú#test_deduct_point_decimal_precisionzAWalletServiceDeductPointTests.test_deduct_point_decimal_precisionŸ  se   € ð 	�‰×!Ñ!Ø—I‘I—L‘LØ'Ü˜9Ó%Ø#ð	 	"ô 	
ð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸8Ó3DÕEr7   c                 óˆ  — | j                   j                  «        | j                   j                  }| j                  j	                  | j                   j
                  dt        d«      d¬«      }| j                  |t        «       | j                   j                  «        | j                  | j                   j                  |«       y)zEdge case: Deduct zero amount.r&   rz   zZero withdrawalr:   N)
r/   rD   r&   r1   rª   r@   r   rA   rB   rE   )r3   Úinitial_balancerG   s      r4   Útest_deduct_point_zero_amountz;WalletServiceDeductPointTests.test_deduct_point_zero_amount«  s�   € ð 	�	‰	×!Ñ!Ô#ØŸ)™)×2Ñ2ˆàŸ™×2Ñ2Ø—I‘I—L‘LØ'Ü˜6“?Ø%ð	 3ó 
ˆð 	×Ñ˜n¬cÔ2Ø�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1°?ÕCr7   c                 óP  — t        d«      t        d«      t        d«      g}|D ]8  }| j                  j                  | j                  j                  d|d|› �¬«       Œ: | j                  j                  «        | j                  | j                  j                  t        d«      «       y)	zTest multiple deductions.r9   z200.00z300.00r&   úWithdrawal r:   ú400.00N)r   r1   rª   r/   r@   rD   rE   r&   rv   s      r4   Ú%test_deduct_point_multiple_deductionszCWalletServiceDeductPointTests.test_deduct_point_multiple_deductions¼  sŠ   € ä˜8Ó$¤g¨hÓ&7¼ÀÓ9JÐKˆãˆFØ�L‰L×%Ñ%ØŸ	™	Ÿ™Ø+ØØ% f XÐ.ð	 &õ ð ð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸8Ó3DÕEr7   c                 ób  — | j                  t        «      5  | j                  j                  | j                  j
                  dt        d«      d¬«       ddd«       | j                  j                  «        | j                  | j                  j                  t        d«      «       y# 1 sw Y   ŒSxY w)z/Test atomic deduction prevents race conditions.r&   r°   zRace condition testr:   Nr¥   )
r„   r   r1   rª   r/   r@   r   rD   rE   r&   r2   s    r4   Ú+test_deduct_point_race_condition_preventionzIWalletServiceDeductPointTests.test_deduct_point_race_condition_preventionË  s‚   € ð ×ÑÔ7Õ8Ø�L‰L×%Ñ%ØŸ	™	Ÿ™Ø+Ü˜yÓ)Ø-ð	 &ô ÷ 9ð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸9Ó3EÕF÷ 9Ð8ús   –=B%Â%B.N)r�   rž   rŸ   r    r5   r«   r®   r³   r¶   rº   r¼   r¿   rÃ   rÅ   r¡   r7   r4   r£   r£   <  s>   „ Ù*ò
ò,Fò 0ò:òDò Hò
FòDò"FóGr7   r£   c                   ó|   — e Zd ZdZd„ Zd„ Zd„ Zd„ Zd„ Zd„ Z	d„ Z
d	„ Zd
„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zy)Ú$WalletServiceTransactionHistoryTestsz0Tests for transaction history retrieval methods.c           
      ó  — t         j                  j                  dd¬«      | _        t         j                  j                  dd¬«      | _        dddœ| _        t        t         | j
                  ¬	«      | _        t        | j                  «      | _	        g | _
        t        d
«      D ]m  }| j                  j                  | j                  j                  dt        d|dz   z  › d�«      d|dz   › �t        ¬«      }| j                  j!                  |«       Œo t        d«      D ]m  }| j                  j                  | j                  j                  dt        d|dz   z  › d�«      d|dz   › �t        ¬«      }| j                  j!                  |«       Œo t        d«      D ]d  }| j                  j                  | j                  j                  dt        d«      d|dz   › �t"        ¬«      }| j                  j!                  |«       Œf y)r   Úuser1zuser1@example.comr    Úuser2zuser2@example.comr#   r   ©r&   r'   r)   é   r&   é
   é   z.00ru   rL   é   é   r'   Ú100zReward N)r   r-   r.   rÉ   rÊ   r+   r   r0   r
   r1   Útransaction_idsÚranger?   r@   r   r   Úappendr   )r3   ÚiÚtids      r4   r5   z*WalletServiceTransactionHistoryTests.setUpá  sÔ  € ä×%Ñ%×,Ñ,°gÐEXÐ,ÓYˆŒ
Ü×%Ñ%×,Ñ,°gÐEXÐ,ÓYˆŒ
ð  Øñ
ˆÔô %ÜØ×(Ñ(ô
ˆŒ	ô % T§Y¡YÓ/ˆŒð  "ˆÔô �q–ˆAØ—,‘,×(Ñ(ØŸ
™
Ÿ™Ø+Ü "¨¨A©¡, ¨sÐ3Ó4Ø" 1 Q¡3 %Ð(Ü)ð )ó ˆCð × Ñ ×'Ñ'¨Õ,ð ô �q–ˆAØ—,‘,×(Ñ(ØŸ
™
Ÿ™Ø+Ü "¨¨A©¡, ¨sÐ3Ó4Ø" 1 Q¡3 %Ð(Ü)ð )ó ˆCð × Ñ ×'Ñ'¨Õ,ð ô �q–ˆAØ—,‘,×(Ñ(ØŸ
™
Ÿ™Ø*Ü˜u“~Ø! ! A¡# ˜Ü+ð )ó ˆCð × Ñ ×'Ñ'¨Õ,ñ r7   c                 ó  — | j                   j                  | j                  j                  ¬«      }| j	                  t        |«      d«       |D ]2  }| j	                  |j                  | j                  j                  «       Œ4 y)z%Get transactions filtered by user_id.©r;   é   N)r1   Úget_transaction_historyrÉ   r@   rE   Úlenr’   ©r3   ÚtransactionsÚtxns      r4   Ú'test_get_transaction_history_by_user_idzLWalletServiceTransactionHistoryTests.test_get_transaction_history_by_user_id  s\   € à—|‘|×;Ñ;ÀDÇJÁJÇMÁMÐ;ÓRˆà×Ñœ˜\Ó*¨AÔ.ÛˆCØ×Ñ˜SŸW™W d§j¡j§m¡mÕ4ñ  r7   c                 óâ   — | j                   j                  | j                  j                  d¬«      }| j	                  t        |«      d«       |D ]  }| j	                  |j                  d«       Œ  y)z(Get transactions filtered by point_type.r&   ©r;   r<   rÌ   N)r1   rÚ   rÉ   r@   rE   rÛ   r‘   rÜ   s      r4   Ú*test_get_transaction_history_by_point_typezOWalletServiceTransactionHistoryTests.test_get_transaction_history_by_point_type  s_   € à—|‘|×;Ñ;Ø—J‘J—M‘MØ'ð <ó 
ˆð
 	×Ñœ˜\Ó*¨AÔ.ÛˆCØ×Ñ˜SŸY™YÐ(8Õ9ñ  r7   c                 óÈ   — | j                   j                  t        ¬«      }| j                  t	        |«      d«       |D ]"  }| j                  |j
                  t        «       Œ$ y)z(Get transactions filtered by trans_type.©rM   r$   N)r1   rÚ   r   rE   rÛ   rM   rÜ   s      r4   Ú*test_get_transaction_history_by_trans_typezOWalletServiceTransactionHistoryTests.test_get_transaction_history_by_trans_type'  sS   € à—|‘|×;Ñ;Ü%ð <ó 
ˆð 	×Ñœ˜\Ó*¨AÔ.ÛˆCØ×Ñ˜SŸ^™^¬^Õ<ñ  r7   c                 ó¸   — | j                   j                  d¬«      }| j                  t        |«      d«       |D ]  }| j                  |j                  d«       Œ  y)z2Get transactions filtered by transaction_type='c'.rN   ©Útransaction_typerÍ   N)r1   rÚ   rE   rÛ   rQ   rÜ   s      r4   Ú7test_get_transaction_history_by_transaction_type_creditz\WalletServiceTransactionHistoryTests.test_get_transaction_history_by_transaction_type_credit1  sS   € à—|‘|×;Ñ;Ø ð <ó 
ˆð 	×Ñœ˜\Ó*¨BÔ/ÛˆCØ×Ñ˜SŸX™X sÕ+ñ  r7   c                 ó(  — | j                   j                  | j                  j                  dt	        d«      d¬«       | j                   j                  d¬«      }| j                  t        |«      d«       | j                  |d   j                  d«       y	)
z2Get transactions filtered by transaction_type='d'.r&   r\   r©   r:   r­   rç   rÎ   r   N)	r1   rª   rÉ   r@   r   rÚ   rE   rÛ   rQ   ©r3   rÝ   s     r4   Ú6test_get_transaction_history_by_transaction_type_debitz[WalletServiceTransactionHistoryTests.test_get_transaction_history_by_transaction_type_debit;  sƒ   € ð 	�‰×!Ñ!Ø—J‘J—M‘MØ'Ü˜7Ó#Ø ð	 	"ô 	
ð —|‘|×;Ñ;Ø ð <ó 
ˆð 	×Ñœ˜\Ó*¨AÔ.Ø×Ñ˜ a™×-Ñ-¨sÕ3r7   c                 ó.  — d}| j                   j                  | j                  j                  dt	        d«      d|¬«       | j                   j                  |¬«      }| j                  t        |«      d«       | j                  |d   j                  |«       y	)
z*Get transactions filtered by initiator ID.rU   r&   rJ   rƒ   rV   )rW   rÎ   r   N)	r1   r?   rÉ   r@   r   rÚ   rE   rÛ   rW   )r3   rY   rÝ   s      r4   Ú#test_get_transaction_history_by_iidzHWalletServiceTransactionHistoryTests.test_get_transaction_history_by_iidL  s„   € ð ˆØ�‰×ÑØ—J‘J—M‘MØ'Ü˜7Ó#ØØð 	ô 	
ð —|‘|×;Ñ;ÀÐ;ÓMˆØ×Ñœ˜\Ó*¨AÔ.Ø×Ñ˜ a™×,Ñ,¨lÕ;r7   c                 ó`  — ddl m }m} ddl}|j                  d«       | j                  j                  | j                  j                  dt        d«      d¬«        |j                  «       }| |d	¬
«      z
  }| j                  j                  ||¬«      }| j                  t        |«      d	«       y)z(Get transactions filtered by date range.r   r   Ngš™™™™™¹?r&   r9   zRecent depositr:   rÎ   )Úminutes©Ú
start_dateÚend_date)r   r   ÚtimeÚsleepr1   r?   rÉ   r@   r   ÚnowrÚ   ÚassertGreaterEqualrÛ   )r3   r   r   rô   ró   rò   rÝ   s          r4   Ú'test_get_transaction_history_date_rangezLWalletServiceTransactionHistoryTests.test_get_transaction_history_date_range\  s›   € ç0ó 	Ø�
‰
�3Œð 	�‰×ÑØ—J‘J—M‘MØ'Ü˜8Ó$Ø$ð	 	ô 	
ð  �8—<‘<“>ˆØ¡	°!Ô 4Ñ4ˆ
à—|‘|×;Ñ;Ø!Øð <ó 
ˆð 	×Ñ¤ LÓ 1°1Õ5r7   c                 óö   — ddl m }m}  |j                  «       }| |d¬«      z
  }| j                  j	                  |j                  «       |j                  «       ¬«      }| j                  t        |«      d«       y)z<Get transactions filtered by date range (ISO string format).r   r   rÎ   )Údaysrñ   rÍ   N)r   r   rö   r1   rÚ   Ú	isoformatr÷   rÛ   )r3   r   r   ró   rò   rÝ   s         r4   Ú.test_get_transaction_history_date_range_stringzSWalletServiceTransactionHistoryTests.test_get_transaction_history_date_range_stringx  si   € ç0à�8—<‘<“>ˆØ¡	¨qÔ 1Ñ1ˆ
à—|‘|×;Ñ;Ø!×+Ñ+Ó-Ø×'Ñ'Ó)ð <ó 
ˆð 	×Ñ¤ LÓ 1°2Õ6r7   c                 óœ   — | j                   j                  | j                  j                  d¬«      }| j	                  t        |«      d«       y)zGet transactions with limit.rÏ   )r;   ÚlimitN)r1   rÚ   rÉ   r@   rE   rÛ   rë   s     r4   Ú-test_get_transaction_history_pagination_limitzRWalletServiceTransactionHistoryTests.test_get_transaction_history_pagination_limit‡  s@   € à—|‘|×;Ñ;Ø—J‘J—M‘MØð <ó 
ˆð
 	×Ñœ˜\Ó*¨AÕ.r7   c                 ól  — | j                   j                  | j                  j                  ¬«      }| j                   j                  | j                  j                  d¬«      }| j	                  t        |«      t        |«      dz
  «       | j                  |d   j                  |d   j                  «       y)zGet transactions with offset.rØ   r#   )r;   Úoffsetr   N)r1   rÚ   rÉ   r@   rE   rÛ   ÚassertNotEqual)r3   Úall_transactionsÚoffset_transactionss      r4   Ú.test_get_transaction_history_pagination_offsetzSWalletServiceTransactionHistoryTests.test_get_transaction_history_pagination_offset�  sž   € àŸ<™<×?Ñ?Ø—J‘J—M‘Mð @ó 
Ðð #Ÿl™l×BÑBØ—J‘J—M‘MØð Có 
Ðð
 	×ÑœÐ0Ó1´3Ð7GÓ3HÈ1Ñ3LÔMà×ÑÐ,¨QÑ/×2Ñ2Ð4GÈÑ4J×4MÑ4MÕNr7   c                 óN  — | j                   j                  | j                  j                  ¬«      }t	        t        |«      dz
  «      D ][  }t        j                  ||   j                  «      }t        j                  ||dz      j                  «      }| j                  ||«       Œ] y)zCTest that transactions are ordered by creation date (newest first).rØ   rÎ   N)
r1   rÚ   rÉ   r@   rÓ   rÛ   r   Úfromisoformatr•   r÷   )r3   rÝ   rÕ   Údate1Údate2s        r4   Ú%test_get_transaction_history_orderingzJWalletServiceTransactionHistoryTests.test_get_transaction_history_orderingŸ  sŠ   € à—|‘|×;Ñ;Ø—J‘J—M‘Mð <ó 
ˆô
 ”s˜<Ó(¨1Ñ,Ö-ˆAä×*Ñ*¨<¸©?×+@Ñ+@ÓAˆEÜ×*Ñ*¨<¸¸A¹Ñ+>×+DÑ+DÓEˆEØ×#Ñ# E¨5Õ1ñ	 .r7   c                 óÆ  — | j                   j                  | j                  j                  ddt        ¬«      }| j                  t        |«      d«       |D ]Š  }| j                  |j                  | j                  j                  «       | j                  |j                  d«       | j                  |j                  d«       | j                  |j                  t        «       ŒŒ y)z'Get transactions with multiple filters.r&   rN   )r;   r<   rè   rM   rÌ   N)r1   rÚ   rÉ   r@   r   rE   rÛ   r’   r‘   rQ   rM   rÜ   s      r4   Ú-test_get_transaction_history_combined_filterszRWalletServiceTransactionHistoryTests.test_get_transaction_history_combined_filters¬  s©   € à—|‘|×;Ñ;Ø—J‘J—M‘MØ'Ø Ü%ð	 <ó 
ˆð 	×Ñœ˜\Ó*¨AÔ.ÛˆCØ×Ñ˜SŸW™W d§j¡j§m¡mÔ4Ø×Ñ˜SŸY™YÐ(8Ô9Ø×Ñ˜SŸX™X sÔ+Ø×Ñ˜SŸ^™^¬^Õ<ñ	  r7   c                 ó  — | j                   d   }| j                  j                  |«      }| j                  |«       | j	                  |j
                  |«       | j	                  |j                  | j                  j
                  «       y)zGet a single transaction by ID.r   N)rÒ   r1   rO   rP   rE   r@   r’   rÉ   rR   s      r4   Útest_get_transaction_by_idz?WalletServiceTransactionHistoryTests.test_get_transaction_by_id¼  sd   € à×-Ñ-¨aÑ0ˆØ—l‘l×8Ñ8¸ÓHˆà×Ñ˜[Ô)Ø×Ñ˜Ÿ™¨Ô8Ø×Ñ˜Ÿ™¨$¯*©*¯-©-Õ8r7   c                 ó\   — | j                   j                  d«      }| j                  |«       y)z#Get transaction by non-existent ID.r›   N)r1   rO   ÚassertIsNone)r3   r	   s     r4   Ú$test_get_transaction_by_id_not_foundzIWalletServiceTransactionHistoryTests.test_get_transaction_by_id_not_foundÅ  s$   € à—l‘l×8Ñ8¸Ó?ˆØ×Ñ˜+Õ&r7   c                 ór  — | j                   j                  | j                  j                  ¬«      }| j	                  |d«       | j                   j                  | j                  j                  d¬«      }| j	                  |d«       | j                   j                  t
        ¬«      }| j	                  |d«       y)	z$Count transactions matching filters.rØ   rÙ   r&   rá   rÌ   rä   r$   N)r1   Úcount_transactionsrÉ   r@   rE   r   )r3   Úcounts     r4   Útest_count_transactionsz<WalletServiceTransactionHistoryTests.test_count_transactionsÊ  s‘   € à—‘×/Ñ/¸¿
¹
¿¹Ð/ÓFˆØ×Ñ˜ Ô"à—‘×/Ñ/Ø—J‘J—M‘MØ'ð 0ó 
ˆð 	×Ñ˜ Ô"à—‘×/Ñ/¼>Ð/ÓJˆØ×Ñ˜ Õ"r7   c                 ó�   — | j                  t        «      5  | j                  j                  d¬«       ddd«       y# 1 sw Y   yxY w)z)Error case: Invalid point type in filter.r‚   )r<   N)r„   r   r1   rÚ   r2   s    r4   Ú/test_get_transaction_history_invalid_point_typezTWalletServiceTransactionHistoryTests.test_get_transaction_history_invalid_point_typeØ  s7   € à×ÑÔ4Õ5Ø�L‰L×0Ñ0Ø)ð 1ô ÷ 6×5Ñ5úó	   –<¼Ac                 ó�   — | j                  t        «      5  | j                  j                  d¬«       ddd«       y# 1 sw Y   yxY w)z+Error case: Invalid transaction_type value.Úxrç   N)r„   r   r1   rÚ   r2   s    r4   Ú5test_get_transaction_history_invalid_transaction_typezZWalletServiceTransactionHistoryTests.test_get_transaction_history_invalid_transaction_typeß  s7   € à×ÑÔ1Õ2Ø�L‰L×0Ñ0Ø!$ð 1ô ÷ 3×2Ñ2úr  N)r�   rž   rŸ   r    r5   rß   râ   rå   ré   rì   rî   rø   rü   rÿ   r  r
  r  r  r  r  r  r  r¡   r7   r4   rÇ   rÇ   Þ  sa   „ Ù:ò1-òf5ò	:ò=ò,ò4ò"<ò 6ò87ò/òOò2ò=ò 9ò'ò
#òór7   rÇ   c                   ó(   — e Zd ZdZd„ Zd„ Zd„ Zd„ Zy)Ú%WalletServiceSeparateWalletModelTestsz.Tests for using separate wallet balance model.c                 óh  — t         j                  j                  dd¬«      | _        t        j                  j                  | j                  j
                  t        d«      ¬«      | _        dddœ| _        t        t         t        | j                  ¬	«      | _
        t        | j                  «      | _        y
)r   r   r   r    ú500.00)r;   r&   r#   r   rË   )r*   Úwallet_balance_modelr+   N)r   r-   r.   r/   r   r@   r   Úwalletr+   r   r0   r
   r1   r2   s    r4   r5   z+WalletServiceSeparateWalletModelTests.setUpê  s‘   € ä×$Ñ$×+Ñ+°ZÐGYÐ+ÓZˆŒ	Ü ×(Ñ(×/Ñ/Ø—I‘I—L‘LÜ" 8Ó,ð 0ó 
ˆŒð  Øñ
ˆÔô %ÜÜ!+Ø×(Ñ(ô
ˆŒ	ô
 % T§Y¡YÓ/ˆ�r7   c                 óÌ  — | j                   j                  | j                  j                  dt	        d«      d¬«      }| j                  |t        «       | j                  j                  «        | j                  j                  «        | j                  | j                  j                  t	        d«      «       | j                  | j                  j                  t	        d«      «       y)z'Add points using separate wallet model.r&   r9   rK   r:   ú600.00rz   N©r1   r?   r/   r@   r   rA   rB   r!  rD   rE   r&   rF   s     r4   Ú$test_add_point_separate_wallet_modelzJWalletServiceSeparateWalletModelTests.test_add_point_separate_wallet_modelý  s¥   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜8Ó$Øð	 0ó 
ˆð 	×Ñ˜n¬cÔ2ð 	�‰×#Ñ#Ô%Ø�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×3Ñ3´W¸XÓ5FÔGà×Ñ˜Ÿ™×1Ñ1´7¸6³?ÕCr7   c                 ó:  — | j                   j                  | j                  j                  dt	        d«      d¬«      }| j                  |t        «       | j                  j                  «        | j                  | j                  j                  t	        d«      «       y)z*Deduct points using separate wallet model.r&   r9   r©   r:   rÂ   N)r1   rª   r/   r@   r   rA   rB   r!  rD   rE   r&   rF   s     r4   Ú'test_deduct_point_separate_wallet_modelzMWalletServiceSeparateWalletModelTests.test_deduct_point_separate_wallet_model  su   € àŸ™×2Ñ2Ø—I‘I—L‘LØ'Ü˜8Ó$Ø ð	 3ó 
ˆð 	×Ñ˜n¬cÔ2à�‰×#Ñ#Ô%Ø×Ñ˜Ÿ™×3Ñ3´W¸XÓ5FÕGr7   c                 ó®   — | j                   j                  j                  | j                  j                  d«      }| j                  |t        d«      «       y)z'Get balance from separate wallet model.r&   r  N)r1   Ú
repositoryÚget_user_balancer/   r@   rE   r   )r3   r“   s     r4   Ú+test_get_user_balance_separate_wallet_modelzQWalletServiceSeparateWalletModelTests.test_get_user_balance_separate_wallet_model  sA   € à—,‘,×)Ñ)×:Ñ:Ø�I‰I�L‰LØó
ˆð
 	×Ñ˜¤'¨(Ó"3Õ4r7   N)r�   rž   rŸ   r    r5   r%  r'  r+  r¡   r7   r4   r  r  ç  s   „ Ù8ò0ò&Dò$Hó5r7   r  c                   ó   — e Zd ZdZd„ Zd„ Zy)Ú!WalletServiceCustomFieldNameTestsz$Tests for custom field name mapping.c                 óÜ   — t         j                  j                  dd¬«      | _        ddi| _        t        t         | j                  ddi¬«      | _        t        | j                  «      | _        y)	r   r   r   r    r'   r   Úpoints)r*   r+   Úpoint_type_field_mapNr,   r2   s    r4   r5   z'WalletServiceCustomFieldNameTests.setUp*  sg   € ä×$Ñ$×+Ñ+°ZÐGYÐ+ÓZˆŒ	ð ˜Qð
ˆÔô %ÜØ×(Ñ(à ð"ô
ˆŒ	ô % T§Y¡YÓ/ˆ�r7   c                 ó˜  — | j                   j                  | j                  j                  dt	        d«      d¬«      }| j                  |t        «       | j                  j                  «        | j                  | j                  j                  t	        d«      «       | j                  | j                  j                  t	        d«      «       y)z#Add points using custom field name.r'   rÑ   ÚRewardr:   Ú0N)r1   r?   r/   r@   r   rA   rB   rD   rE   r/  r'   rF   s     r4   Ú test_add_point_custom_field_namezBWalletServiceCustomFieldNameTests.test_add_point_custom_field_name:  s“   € àŸ™×/Ñ/Ø—I‘I—L‘LØ&Ü˜5“>Øð	 0ó 
ˆð 	×Ñ˜n¬cÔ2ð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×)Ñ)¬7°5«>Ô:Ø×Ñ˜Ÿ™×0Ñ0´'¸#³,Õ?r7   N)r�   rž   rŸ   r    r5   r4  r¡   r7   r4   r-  r-  '  s   „ Ù.ò0ó @r7   r-  c                   ó   — e Zd ZdZd„ Zd„ Zy)Ú'WalletServiceCustomWalletUserFieldTestsz+Tests for custom wallet user_id field name.c                 óh  — t         j                  j                  dd¬«      | _        t        j                  j                  | j                  j
                  t        d«      ¬«      | _        ddi| _        t        t         t        | j                  d¬	«      | _
        t        | j                  «      | _        y
)r   r   r   r    r  )Úowner_idr&   r&   r#   r8  )r*   r   r+   Úwallet_user_id_fieldN)r   r-   r.   r/   r   r@   r   r!  r+   r   r0   r
   r1   r2   s    r4   r5   z-WalletServiceCustomWalletUserFieldTests.setUpN  s“   € ä×$Ñ$×+Ñ+°ZÐGYÐ+ÓZˆŒ	Ü+×3Ñ3×:Ñ:Ø—Y‘Y—\‘\Ü" 8Ó,ð ;ó 
ˆŒð ˜að
ˆÔô %ÜÜ!6Ø×(Ñ(Ø!+ô	
ˆŒ	ô % T§Y¡YÓ/ˆ�r7   c                 ó:  — | j                   j                  | j                  j                  dt	        d«      d¬«      }| j                  |t        «       | j                  j                  «        | j                  | j                  j                  t	        d«      «       y)z+Add points using custom user_id field name.r&   r9   rK   r:   r#  Nr$  rF   s     r4   Ú#test_add_point_custom_user_id_fieldzKWalletServiceCustomWalletUserFieldTests.test_add_point_custom_user_id_fielda  su   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜8Ó$Øð	 0ó 
ˆð 	×Ñ˜n¬cÔ2à�‰×#Ñ#Ô%Ø×Ñ˜Ÿ™×3Ñ3´W¸XÓ5FÕGr7   N)r�   rž   rŸ   r    r5   r;  r¡   r7   r4   r6  r6  K  s   „ Ù5ò0ó&Hr7   r6  c                   ó.   — e Zd ZdZd„ Zd„ Zd„ Zd„ Zd„ Zy)Ú"WalletServiceTransactionTypesTestsz1Tests for transaction type constants and helpers.c                 óÖ   — t         j                  j                  dd¬«      | _        ddi| _        t        t         | j                  ¬«      | _        t        | j                  «      | _        y)r   r   r   r    r&   r#   r)   Nr,   r2   s    r4   r5   z(WalletServiceTransactionTypesTests.setUps  sW   € ä×$Ñ$×+Ñ+°ZÐGYÐ+ÓZˆŒ	Ø,¨aÐ0ˆÔÜ$ÜØ×(Ñ(ô
ˆŒ	ô % T§Y¡YÓ/ˆ�r7   c                 ó  — ddl m}m}m} | j	                  |t
        «       | j	                  |t
        «       | j	                  |t
        «       | j                  |d«       | j                  |d«       | j                  |d«       y)z2Test that transaction type constants are integers.r   )r   r   r   éè  éë  é  N)Úwallet_utils.transaction_typesr   r   r   rA   rB   rE   )r3   r   r   r   s       r4   Útest_transaction_type_constantszBWalletServiceTransactionTypesTests.test_transaction_type_constants}  sp   € ÷	
ñ 	
ð 	×Ñ˜n¬cÔ2Ø×Ñ˜o¬sÔ3Ø×ÑÐ.´Ô4à×Ñ˜¨Ô.Ø×Ñ˜¨$Ô/Ø×ÑÐ)¨4Õ0r7   c                 ó  — | j                  t        d«      d«       | j                  t        d«      d«       | j                  t        d«      d«       | j                  t        «      5  t        d«       ddd«       y# 1 sw Y   yxY w)	z,Test get_transaction_type() helper function.úwallet-depositr@  úwallet-withdrawrA  úroi-distributionrB  zinvalid-typeN)rE   r   r„   Ú
ValueErrorr2   s    r4   Útest_get_transaction_typez<WalletServiceTransactionTypesTests.test_get_transaction_type�  si   € à×ÑÔ-Ð.>Ó?ÀÔFØ×ÑÔ-Ð.?Ó@À$ÔGØ×ÑÔ-Ð.@ÓAÀ4ÔHà×ÑœzÕ*Ü  Ô0÷ +×*Ñ*ús   Á'A<Á<Bc                 óÚ   — | j                  t        d«      d«       | j                  t        d«      d«       | j                  t        d«      d«       | j                  t        d«      «       y)	z1Test get_transaction_type_name() helper function.r@  rF  rA  rG  rB  rH  r›   N)rE   r   r  r2   s    r4   Útest_get_transaction_type_namezAWalletServiceTransactionTypesTests.test_get_transaction_type_name–  s[   € à×ÑÔ2°4Ó8Ð:JÔKØ×ÑÔ2°4Ó8Ð:KÔLØ×ÑÔ2°4Ó8Ð:LÔMØ×ÑÔ3°EÓ:Õ;r7   c                 óJ  — | j                   j                  | j                  j                  dt	        d«      dt
        ¬«      }| j                   j                  |«      }| j                  |j                  t
        «       t        |j                  «      }| j                  |d«       y)z*Test transaction type is stored correctly.r&   r9   rƒ   rL   rF  N)
r1   r?   r/   r@   r   r   rO   rE   rM   r   )r3   rG   r	   Únames       r4   Ú+test_transaction_type_in_transaction_recordzNWalletServiceTransactionTypesTests.test_transaction_type_in_transaction_record�  s†   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜8Ó$ØÜ%ð 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜×/Ñ/´Ô@ô )¨×)?Ñ)?Ó@ˆØ×Ñ˜Ð/Õ0r7   N)	r�   rž   rŸ   r    r5   rD  rJ  rL  rO  r¡   r7   r4   r=  r=  p  s   „ Ù;ò0ò1ò 1ò<ó1r7   r=  c                   óF   — e Zd ZdZd„ Zd„ Zd„ Zd„ Zd„ Zd„ Z	d„ Z
d	„ Zd
„ Zy)ÚWalletServiceEdgeCasesTestsz"Tests for edge cases and outliers.c                 óÚ   — t         j                  j                  dd¬«      | _        ddddœ| _        t        t         | j                  ¬«      | _        t        | j                  «      | _        y	r   r,   r2   s    r4   r5   z!WalletServiceEdgeCasesTests.setUp²  r6   r7   c                 óü   — | j                   j                  ddt        d«      dd¬«      }| j                   j                  |«      }| j	                  |j
                  d«       | j	                  |j                  d«       y)z)Test using system user ID (-100) for uid.r]   r&   r9   zSystem walletrV   N)r1   r?   r   rO   rE   r’   rW   rR   s      r4   Útest_system_user_idz/WalletServiceEdgeCasesTests.test_system_user_idÀ  so   € ð Ÿ™×/Ñ/ØØ'Ü˜8Ó$Ø#Øð 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜Ÿ™¨$Ô/Ø×Ñ˜Ÿ™¨$Õ/r7   c                 óô   — ddz  }| j                   j                  | j                  j                  dt	        d«      |¬«      }| j                   j                  |«      }| j                  |j                  |«       y)zTest with very long remarks.ÚAi'  r&   r9   r:   N©r1   r?   r/   r@   r   rO   rE   r”   )r3   Úlong_remarksrG   r	   s       r4   Útest_very_long_remarksz2WalletServiceEdgeCasesTests.test_very_long_remarksÐ  si   € à˜U‘{ˆØŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜8Ó$Ø ð	 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜×*Ñ*¨LÕ9r7   c                 óê   — | j                   j                  | j                  j                  dt	        d«      d¬«      }| j                   j                  |«      }| j                  |j                  d«       y)zTest with empty remarks.r&   r9   Ú r:   NrW  rR   s      r4   Útest_empty_remarksz.WalletServiceEdgeCasesTests.test_empty_remarksÝ  s`   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜8Ó$Øð	 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜×*Ñ*¨BÕ/r7   c                 óê   — | j                   j                  | j                  j                  dt	        d«      dd¬«      }| j                   j                  |«      }| j                  |j                  «       y)z Test with None transaction type.r&   r9   rƒ   NrL   )r1   r?   r/   r@   r   rO   r  rM   rR   s      r4   Útest_none_transaction_typez6WalletServiceEdgeCasesTests.test_none_transaction_typeé  sa   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜8Ó$ØØð 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜+×0Ñ0Õ1r7   c                 óð   — | j                   j                  | j                  j                  dt	        d«      ddi i¬«      }| j                   j                  |«      }| j                  |j                  i «       y)zTest with empty extra_data.r&   r9   rƒ   r`   rd   Nrf   rR   s      r4   Útest_empty_extra_dataz1WalletServiceEdgeCasesTests.test_empty_extra_dataö  sg   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜8Ó$ØØ˜B�<ð 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜×/Ñ/°Õ4r7   c                 óê   — | j                   j                  | j                  j                  dt	        d«      d¬«      }| j                   j                  |«      }| j                  |j                  i «       y)zTest without params parameter.r&   r9   rƒ   r:   Nrf   rR   s      r4   Útest_no_paramsz*WalletServiceEdgeCasesTests.test_no_params  s`   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜8Ó$Øð	 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜×/Ñ/°Õ4r7   c                 ód  — t        d«      D ]A  }| j                  j                  | j                  j                  dt        d«      d|› �¬«       ŒC | j                  j                  «        | j                  | j                  j                  t        d«      «       t        d«      D ]A  }| j                  j                  | j                  j                  dt        d«      d|› �¬«       ŒC | j                  j                  «        | j                  | j                  j                  t        d	«      «       y
)z$Test multiple concurrent operations.rÍ   r&   r\   ru   r:   r9   rÌ   rÁ   rJ   N©
rÓ   r1   r?   r/   r@   r   rD   rE   r&   rª   ©r3   rÕ   s     r4   Ú#test_multiple_concurrent_operationsz?WalletServiceEdgeCasesTests.test_multiple_concurrent_operations  sñ   € ô �r–ˆAØ�L‰L×"Ñ"ØŸ	™	Ÿ™Ø+Ü˜wÓ'Ø" 1 #˜ð	 #õ ð ð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸8Ó3DÔEô �q–ˆAØ�L‰L×%Ñ%ØŸ	™	Ÿ™Ø+Ü˜wÓ'Ø% a SÐ)ð	 &õ ð ð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸7Ó3CÕDr7   c                 ód  — t        d«      D ]A  }| j                  j                  | j                  j                  dt        d«      d|› �¬«       ŒC | j                  j                  «        | j                  | j                  j                  t        d«      «       t        d«      D ]A  }| j                  j                  | j                  j                  dt        d«      d|› �¬«       ŒC | j                  j                  «        | j                  | j                  j                  t        d	«      «       y
)z,Test balance accuracy after many operations.éd   r&   z0.01zMicro deposit r:   z1.00é2   zMicro withdrawal z0.50Nrd  re  s     r4   Ú/test_balance_accuracy_after_multiple_operationszKWalletServiceEdgeCasesTests.test_balance_accuracy_after_multiple_operations)  sî   € ô �s–ˆAØ�L‰L×"Ñ"ØŸ	™	Ÿ™Ø+Ü˜v“Ø(¨¨Ð,ð	 #õ ð ð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸6³?ÔCô �r–ˆAØ�L‰L×%Ñ%ØŸ	™	Ÿ™Ø+Ü˜v“Ø+¨A¨3Ð/ð	 &õ ð ð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸6³?ÕCr7   N)r�   rž   rŸ   r    r5   rT  rY  r\  r^  r`  rb  rf  rj  r¡   r7   r4   rQ  rQ  ¯  s4   „ Ù,ò0ò0ò :ò
0ò2ò5ò
5òEó4Dr7   rQ  c                   ó   — e Zd ZdZd„ Zd„ Zy)ÚWalletServiceRaceConditionTestszCTests for race condition prevention (requires TransactionTestCase).c                 óN  — t         j                  j                  dd¬«      | _        ddi| _        t        t         | j                  ¬«      | _        t        | j                  «      | _        | j                  j                  | j                  j                  dt        d«      d¬	«       y
)r   r   r   r    r&   r#   r)   r¥   r¦   r:   Nr§   r2   s    r4   r5   z%WalletServiceRaceConditionTests.setUpG  s‰   € ä×$Ñ$×+Ñ+°ZÐGYÐ+ÓZˆŒ	Ø,¨aÐ0ˆÔÜ$ÜØ×(Ñ(ô
ˆŒ	ô % T§Y¡YÓ/ˆŒð 	�‰×ÑØ—I‘I—L‘LØ'Ü˜9Ó%Ø%ð	 	õ 	
r7   c                 ót  ‡ — ˆ fd„} |«       } |«       }t        d„ ||fD «       «      }‰ j                  |d«       ‰ j                  j                  «        |dk(  r0‰ j	                  ‰ j                  j
                  t        d«      «       y‰ j	                  ‰ j                  j
                  t        d«      «       y)z4Test that atomic deduction prevents race conditions.c                  óœ   •— 	 ‰ j                   j                  ‰ j                  j                  dt	        d«      d¬«      S # t
        $ r Y y w xY w)Nr&   r#  zConcurrent withdrawalr:   )r1   rª   r/   r@   r   r   r2   s   €r4   Ú
deduct_600zaWalletServiceRaceConditionTests.test_atomic_deduction_prevents_race_condition.<locals>.deduct_600^  sQ   ø€ ðØ—|‘|×0Ñ0Ø ŸI™IŸL™LØ/Ü" 8Ó,Ø3ð	 1ó ð øô ,ò Ùðús   ƒ;? ¿	AÁ
Ac              3   ó&   K  — | ]	  }|€Œd–— Œ y ­w)NrÎ   r¡   )Ú.0Úrs     r4   Ú	<genexpr>z`WalletServiceRaceConditionTests.test_atomic_deduction_prevents_race_condition.<locals>.<genexpr>o  s   è ø€ ÐKÑ'9 !¸Q¹]œAÑ'9ùs   ‚ŠrÎ   rÂ   r¥   N)ÚsumÚassertLessEqualr/   rD   rE   r&   r   )r3   rp  Úresult1Úresult2Úsuccess_counts   `    r4   Ú-test_atomic_deduction_prevents_race_conditionzMWalletServiceRaceConditionTests.test_atomic_deduction_prevents_race_conditionY  s™   ø€ ô
		ñ “,ˆÙ“,ˆô ÑK¨°Ñ'9ÓKÓKˆØ×Ñ˜]¨AÔ.ð 	�	‰	×!Ñ!Ô#Ø˜AÒà×Ñ˜TŸY™Y×5Ñ5´w¸xÓ7HÕIð ×Ñ˜TŸY™Y×5Ñ5´w¸yÓ7IÕJr7   N)r�   rž   rŸ   r    r5   rz  r¡   r7   r4   rl  rl  D  s   „ ÙMò
ó$ Kr7   rl  N)'r    Údecimalr   r   r   Údjango.testr   r   Ú	django.dbr	   Údb_transactionÚwallet_utilsr
   r   Úwallet_utils.exceptionsr   r   r   r   rC  r   r   r   r   r   r   Útest_app.modelsr   r   r   r   r£   rÇ   r  r-  r6  r=  rQ  rl  r¡   r7   r4   Ú<module>r‚     s¿   ðñõ ß (ß 5Ý 3ç 8÷ó ÷÷ ÷ HÑ GôX ô Xôv_G Hô _GôDF¨8ô FôR=5¨Hô =5ô@!@¨ô !@ôH"H¨hô "HôJ<1¨ô <1ô~RD (ô RDôj5KÐ&9õ 5Kr7   