Ë
    ˜Í>iÁ£  ã                   ó^  — 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 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Ú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    úH/home/cursorai/projects/django-wallet-utils/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)r0   Ú	add_pointr.   Úidr   ÚassertIsInstanceÚintÚassertGreaterÚrefresh_from_dbÚassertEqualr%   ©r2   Útransaction_ids     r3   Útest_add_point_standardz2WalletServiceAddPointTests.test_add_point_standard1   s‡   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜8Ó$Ø"ð	 0ó 
ˆð 	×Ñ˜n¬cÔ2Ø×Ñ˜>¨1Ô-ð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸8Ó3DÕEr6   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)r0   r>   r.   r?   r   r   r@   rA   Úget_transaction_by_idÚassertIsNotNonerD   rL   Útype©r2   rF   r	   s      r3   Ú$test_add_point_with_transaction_typez?WalletServiceAddPointTests.test_add_point_with_transaction_typeA   s™   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜7Ó#ØÜ%ð 0ó 
ˆð 	×Ñ˜n¬cÔ2ð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜[Ô)Ø×Ñ˜×/Ñ/´Ô@Ø×Ñ˜×)Ñ)¨3Õ/r6   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©r0   r>   r.   r?   r   rN   rD   rV   )r2   Úinitiator_idrF   r	   s       r3   Útest_add_point_with_iidz2WalletServiceAddPointTests.test_add_point_with_iidS   sf   € àˆØŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜7Ó#Ø"Øð 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜Ÿ™¨,Õ7r6   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 depositr9   éœÿÿÿNrW   rQ   s      r3   Útest_add_point_system_initiatedz:WalletServiceAddPointTests.test_add_point_system_initiateda   s^   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜7Ó#Ø$ð	 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜Ÿ™¨$Õ/r6   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%   r8   zDeposit with extra dataÚdatai90  Úbank_transfer)Ú
payment_idÚsource©r:   r;   r<   r=   Úparamsra   rb   N©r0   r>   r.   r?   r   rN   rD   Ú
extra_datarQ   s      r3   Útest_add_point_with_extra_dataz9WalletServiceAddPointTests.test_add_point_with_extra_datam   s“   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜8Ó$Ø-àØ"'Ø-ñðð 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜×/Ñ/°Ñ=¸uÔEØ×Ñ˜×/Ñ/°Ñ9¸?ÕKr6   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%   r8   zCredit depositr9   r&   Ú50zReward pointsr'   ú
0.00000001zCrypto depositN©
r0   r>   r.   r?   r   rC   rD   r%   r&   r'   r1   s    r3   Ú#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ÕIr6   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 roundingr9   z101.00r&   z50.7Ú51r'   z0.123456789z
0.12345679Nrk   r1   s    r3   Ú 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ÕIr6   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 r9   z60.00N)r   r0   r>   r.   r?   rC   rD   r%   ©r2   Úamountsr<   s      r3   Ú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ÕDr6   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 depositr9   N)
r0   r>   r.   r?   r   r@   rA   rC   rD   r%   rE   s     r3   Útest_add_point_zero_amountz5WalletServiceAddPointTests.test_add_point_zero_amountÎ   ss   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜6“?Ø"ð	 0ó 
ˆð 	×Ñ˜n¬cÔ2Ø�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸6³?ÕCr6   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'   rj   zVery small depositr9   N)
r0   r>   r.   r?   r   r@   rA   rC   rD   r'   rE   s     r3   Ú 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ÕIr6   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 depositr9   N)
r   r0   r>   r.   r?   r@   rA   rC   rD   r%   )r2   Úlarge_amountrF   s      r3   Ú 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°<Õ@r6   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_typer8   ÚTestr9   N)
ÚassertRaisesr   r0   r>   r.   r?   r   rD   Ú	exceptionr;   ©r2   Úcms     r3   Ú!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%   r8   r‚   ú
not a dictrc   Nr>   ©
rƒ   r   r0   r>   r.   r?   r   rD   r„   Úmethodr…   s     r3   Ú&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%   r8   r‚   r_   r‰   rc   Nr>   rŠ   r…   s     r3   Ú+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?   ÚwtyperV   ÚuidrP   r<   ÚbalancerL   ÚdescrÚcdater%   r8   r‚   r_   Úvaluerc   Nr>   rŠ   )r2   Úreserved_fieldsÚfieldr†   s       r3   Ú+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%   r8   r‚   r9   N)rƒ   r   r0   r>   r   r1   s    r3   Útest_add_point_nonexistent_userz:WalletServiceAddPointTests.test_add_point_nonexistent_user/  sG   € ð ×ÑÔ3Õ4Ø�L‰L×"Ñ"ØØ+Ü˜xÓ(Øð	 #ô ÷ 5×4Ñ4ús   –)AÁAN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r4   rG   rR   rY   r]   rg   rl   rr   rw   rz   r|   r   r‡   rŒ   rŽ   r˜   r›   © r6   r3   r   r       sd   „ Ù'ò0òFò 0ò$8ò
0òLò&Jò>Jò@EòDòJòAò$
Bò;ò;ò?ó	r6   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 depositr9   N©r   r,   r-   r.   r*   r   r/   r
   r0   r>   r?   r   r1   s    r3   r4   z#WalletServiceDeductPointTests.setUp>  s‘   € ä×$Ñ$×+Ñ+°ZÐGYÐ+ÓZˆŒ	àØØñ
ˆÔô
 %ÜØ×(Ñ(ô
ˆŒ	ô % T§Y¡YÓ/ˆŒð 	�‰×ÑØ—I‘I—L‘LØ'Ü˜9Ó%Ø%ð	 	õ 	
r6   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%   r8   Ú
Withdrawalr9   r   z900.00N)r0   Údeduct_pointr.   r?   r   r@   rA   rB   rC   rD   r%   rE   s     r3   Útest_deduct_point_standardz8WalletServiceDeductPointTests.test_deduct_point_standardT  s‡   € àŸ™×2Ñ2Ø—I‘I—L‘LØ'Ü˜8Ó$Ø ð	 3ó 
ˆð 	×Ñ˜n¬cÔ2Ø×Ñ˜>¨1Ô-ð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸8Ó3DÕEr6   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%   rI   r¨   rK   ÚdN)
r0   r©   r.   r?   r   r   rN   rD   rL   rP   rQ   s      r3   Ú'test_deduct_point_with_transaction_typezEWalletServiceDeductPointTests.test_deduct_point_with_transaction_typed  sy   € àŸ™×2Ñ2Ø—I‘I—L‘LØ'Ü˜7Ó#Ø Ü&ð 3ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜×/Ñ/´ÔAØ×Ñ˜×)Ñ)¨3Õ/r6   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 withdrawalr9   Ng     @Ÿ@)rƒ   r   r0   r©   r.   r?   r   rO   r„   Ú	availableÚ	requestedrD   r…   s     r3   Ú&test_deduct_point_insufficient_balancezDWalletServiceDeductPointTests.test_deduct_point_insufficient_balancer  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 withdrawalr9   ry   N)
r.   rC   r%   r0   r©   r?   r@   rA   rD   r   )r2   Úcurrent_balancerF   s      r3   Ú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³?ÕCr6   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)
r0   r©   r.   r?   r   r@   rA   rC   rD   r%   rE   s     r3   Ú 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ÕGr6   c                 ó  — | j                   j                  | j                  j                  dt	        d«      d¬«       | j                  j                  «        | j                  | j                  j                  t	        d«      «       y)rn   r%   ro   rp   r9   z899.00N)r0   r©   r.   r?   r   rC   rD   r%   r1   s    r3   Ú#test_deduct_point_decimal_precisionzAWalletServiceDeductPointTests.test_deduct_point_decimal_precisionž  se   € ð 	�‰×!Ñ!Ø—I‘I—L‘LØ'Ü˜9Ó%Ø#ð	 	"ô 	
ð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸8Ó3DÕEr6   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%   ry   zZero withdrawalr9   N)
r.   rC   r%   r0   r©   r?   r   r@   rA   rD   )r2   Úinitial_balancerF   s      r3   Ú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°?ÕCr6   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.r8   z200.00z300.00r%   úWithdrawal r9   ú400.00N)r   r0   r©   r.   r?   rC   rD   r%   ru   s      r3   Ú%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ÕEr6   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 testr9   Nr¤   )
rƒ   r   r0   r©   r.   r?   r   rC   rD   r%   r1   s    r3   Ú+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Ÿ   r4   rª   r­   r²   rµ   r¹   r»   r¾   rÂ   rÄ   r    r6   r3   r¢   r¢   ;  s>   „ Ù*ò
ò,Fò 0ò:òDò Hò
FòDò"FóGr6   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.00rt   rK   é   é   r&   Ú100zReward N)r   r,   r-   rÈ   rÉ   r*   r   r/   r
   r0   Útransaction_idsÚranger>   r?   r   r   Úappendr   )r2   ÚiÚtids      r3   r4   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ð × Ñ ×'Ñ'¨Õ,ñ r6   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)r0   Úget_transaction_historyrÈ   r?   rD   Úlenr‘   ©r2   ÚtransactionsÚtxns      r3   Ú'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ñ  r6   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)r0   rÙ   rÈ   r?   rD   rÚ   r�   rÛ   s      r3   Ú*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ñ  r6   c                 óÈ   — | j                   j                  t        ¬«      }| j                  t	        |«      d«       |D ]"  }| j                  |j
                  t        «       Œ$ y)z(Get transactions filtered by trans_type.©rL   r#   N)r0   rÙ   r   rD   rÚ   rL   rÛ   s      r3   Ú*test_get_transaction_history_by_trans_typezOWalletServiceTransactionHistoryTests.test_get_transaction_history_by_trans_type&  sS   € à—|‘|×;Ñ;Ü%ð <ó 
ˆð 	×Ñœ˜\Ó*¨AÔ.ÛˆCØ×Ñ˜SŸ^™^¬^Õ<ñ  r6   c                 ó¸   — | j                   j                  d¬«      }| j                  t        |«      d«       |D ]  }| j                  |j                  d«       Œ  y)z2Get transactions filtered by transaction_type='c'.rM   ©Útransaction_typerÌ   N)r0   rÙ   rD   rÚ   rP   rÛ   s      r3   Ú7test_get_transaction_history_by_transaction_type_creditz\WalletServiceTransactionHistoryTests.test_get_transaction_history_by_transaction_type_credit0  sS   € à—|‘|×;Ñ;Ø ð <ó 
ˆð 	×Ñœ˜\Ó*¨BÔ/ÛˆCØ×Ñ˜SŸX™X sÕ+ñ  r6   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¨   r9   r¬   ræ   rÍ   r   N)	r0   r©   rÈ   r?   r   rÙ   rD   rÚ   rP   ©r2   rÜ   s     r3   Ú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Õ3r6   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.rT   r%   rI   r‚   rU   )rV   rÍ   r   N)	r0   r>   rÈ   r?   r   rÙ   rD   rÚ   rV   )r2   rX   rÜ   s      r3   Ú#test_get_transaction_history_by_iidzHWalletServiceTransactionHistoryTests.test_get_transaction_history_by_iidK  s„   € ð ˆØ�‰×ÑØ—J‘J—M‘MØ'Ü˜7Ó#ØØð 	ô 	
ð —|‘|×;Ñ;ÀÐ;ÓMˆØ×Ñœ˜\Ó*¨AÔ.Ø×Ñ˜ a™×,Ñ,¨lÕ;r6   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%   r8   zRecent depositr9   rÍ   )Úminutes©Ú
start_dateÚend_date)r   r   ÚtimeÚsleepr0   r>   rÈ   r?   r   ÚnowrÙ   ÚassertGreaterEqualrÚ   )r2   r   r   ró   rò   rñ   rÜ   s          r3   Ú'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Õ5r6   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õ   r0   rÙ   Ú	isoformatrö   rÚ   )r2   r   r   rò   rñ   rÜ   s         r3   Ú.test_get_transaction_history_date_range_stringzSWalletServiceTransactionHistoryTests.test_get_transaction_history_date_range_stringw  si   € ç0à�8—<‘<“>ˆØ¡	¨qÔ 1Ñ1ˆ
à—|‘|×;Ñ;Ø!×+Ñ+Ó-Ø×'Ñ'Ó)ð <ó 
ˆð 	×Ñ¤ LÓ 1°2Õ6r6   c                 óœ   — | j                   j                  | j                  j                  d¬«      }| j	                  t        |«      d«       y)zGet transactions with limit.rÎ   )r:   ÚlimitN)r0   rÙ   rÈ   r?   rD   rÚ   rê   s     r3   Ú-test_get_transaction_history_pagination_limitzRWalletServiceTransactionHistoryTests.test_get_transaction_history_pagination_limit†  s@   € à—|‘|×;Ñ;Ø—J‘J—M‘MØð <ó 
ˆð
 	×Ñœ˜\Ó*¨AÕ.r6   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)r0   rÙ   rÈ   r?   rD   rÚ   ÚassertNotEqual)r2   Úall_transactionsÚoffset_transactionss      r3   Ú.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ÕNr6   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)
r0   rÙ   rÈ   r?   rÒ   rÚ   r   Úfromisoformatr”   rö   )r2   rÜ   rÔ   Údate1Údate2s        r3   Ú%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ñ	 .r6   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%   rM   )r:   r;   rç   rL   rË   N)r0   rÙ   rÈ   r?   r   rD   rÚ   r‘   r�   rP   rL   rÛ   s      r3   Ú-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Ÿ^™^¬^Õ<ñ	  r6   c                 ó  — | j                   d   }| j                  j                  |«      }| j                  |«       | j	                  |j
                  |«       | j	                  |j                  | j                  j
                  «       y)zGet a single transaction by ID.r   N)rÑ   r0   rN   rO   rD   r?   r‘   rÈ   rQ   s      r3   Útest_get_transaction_by_idz?WalletServiceTransactionHistoryTests.test_get_transaction_by_id»  sd   € à×-Ñ-¨aÑ0ˆØ—l‘l×8Ñ8¸ÓHˆà×Ñ˜[Ô)Ø×Ñ˜Ÿ™¨Ô8Ø×Ñ˜Ÿ™¨$¯*©*¯-©-Õ8r6   c                 ó\   — | j                   j                  d«      }| j                  |«       y)z#Get transaction by non-existent ID.rš   N)r0   rN   ÚassertIsNone)r2   r	   s     r3   Ú$test_get_transaction_by_id_not_foundzIWalletServiceTransactionHistoryTests.test_get_transaction_by_id_not_foundÄ  s$   € à—l‘l×8Ñ8¸Ó?ˆØ×Ñ˜+Õ&r6   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)r0   Úcount_transactionsrÈ   r?   rD   r   )r2   Úcounts     r3   Útest_count_transactionsz<WalletServiceTransactionHistoryTests.test_count_transactionsÉ  s‘   € à—‘×/Ñ/¸¿
¹
¿¹Ð/ÓFˆØ×Ñ˜ Ô"à—‘×/Ñ/Ø—J‘J—M‘MØ'ð 0ó 
ˆð 	×Ñ˜ Ô"à—‘×/Ñ/¼>Ð/ÓJˆØ×Ñ˜ Õ"r6   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   r0   rÙ   r1   s    r3   Ú/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   r0   rÙ   r1   s    r3   Ú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Ÿ   r4   rÞ   rá   rä   rè   rë   rí   r÷   rû   rþ   r  r	  r  r  r  r  r  r  r    r6   r3   rÆ   rÆ   Ý  sa   „ Ù:ò1-òf5ò	:ò=ò,ò4ò"<ò 6ò87ò/òOò2ò=ò 9ò'ò
#òór6   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   r/   r
   r0   r1   s    r3   r4   z+WalletServiceSeparateWalletModelTests.setUpé  s‘   € ä×$Ñ$×+Ñ+°ZÐGYÐ+ÓZˆŒ	Ü ×(Ñ(×/Ñ/Ø—I‘I—L‘LÜ" 8Ó,ð 0ó 
ˆŒð  Øñ
ˆÔô %ÜÜ!+Ø×(Ñ(ô
ˆŒ	ô
 % T§Y¡YÓ/ˆ�r6   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%   r8   rJ   r9   ú600.00ry   N©r0   r>   r.   r?   r   r@   rA   r   rC   rD   r%   rE   s     r3   Ú$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³?ÕCr6   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%   r8   r¨   r9   rÁ   N)r0   r©   r.   r?   r   r@   rA   r   rC   rD   r%   rE   s     r3   Ú'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ÕGr6   c                 ó®   — | j                   j                  j                  | j                  j                  d«      }| j                  |t        d«      «       y)z'Get balance from separate wallet model.r%   r  N)r0   Ú
repositoryÚget_user_balancer.   r?   rD   r   )r2   r’   s     r3   Ú+test_get_user_balance_separate_wallet_modelzQWalletServiceSeparateWalletModelTests.test_get_user_balance_separate_wallet_model  sA   € à—,‘,×)Ñ)×:Ñ:Ø�I‰I�L‰LØó
ˆð
 	×Ñ˜¤'¨(Ó"3Õ4r6   N)rœ   r�   rž   rŸ   r4   r$  r&  r*  r    r6   r3   r  r  æ  s   „ Ù8ò0ò&Dò$Hó5r6   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+   r1   s    r3   r4   z'WalletServiceCustomFieldNameTests.setUp)  sg   € ä×$Ñ$×+Ñ+°ZÐGYÐ+ÓZˆŒ	ð ˜Qð
ˆÔô %ÜØ×(Ñ(à ð"ô
ˆŒ	ô % T§Y¡YÓ/ˆ�r6   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Ð   ÚRewardr9   Ú0N)r0   r>   r.   r?   r   r@   rA   rC   rD   r.  r&   rE   s     r3   Ú test_add_point_custom_field_namezBWalletServiceCustomFieldNameTests.test_add_point_custom_field_name9  s“   € àŸ™×/Ñ/Ø—I‘I—L‘LØ&Ü˜5“>Øð	 0ó 
ˆð 	×Ñ˜n¬cÔ2ð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×)Ñ)¬7°5«>Ô:Ø×Ñ˜Ÿ™×0Ñ0´'¸#³,Õ?r6   N)rœ   r�   rž   rŸ   r4   r3  r    r6   r3   r,  r,  &  s   „ Ù.ò0ó @r6   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"   r7  )r)   r  r*   Úwallet_user_id_fieldN)r   r,   r-   r.   r   r?   r   r   r*   r   r/   r
   r0   r1   s    r3   r4   z-WalletServiceCustomWalletUserFieldTests.setUpM  s“   € ä×$Ñ$×+Ñ+°ZÐGYÐ+ÓZˆŒ	Ü+×3Ñ3×:Ñ:Ø—Y‘Y—\‘\Ü" 8Ó,ð ;ó 
ˆŒð ˜að
ˆÔô %ÜÜ!6Ø×(Ñ(Ø!+ô	
ˆŒ	ô % T§Y¡YÓ/ˆ�r6   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%   r8   rJ   r9   r"  Nr#  rE   s     r3   Ú#test_add_point_custom_user_id_fieldzKWalletServiceCustomWalletUserFieldTests.test_add_point_custom_user_id_field`  su   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜8Ó$Øð	 0ó 
ˆð 	×Ñ˜n¬cÔ2à�‰×#Ñ#Ô%Ø×Ñ˜Ÿ™×3Ñ3´W¸XÓ5FÕGr6   N)rœ   r�   rž   rŸ   r4   r:  r    r6   r3   r5  r5  J  s   „ Ù5ò0ó&Hr6   r5  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+   r1   s    r3   r4   z(WalletServiceTransactionTypesTests.setUpr  sW   € ä×$Ñ$×+Ñ+°ZÐGYÐ+ÓZˆŒ	Ø,¨aÐ0ˆÔÜ$ÜØ×(Ñ(ô
ˆŒ	ô % T§Y¡YÓ/ˆ�r6   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   r@   rA   rD   )r2   r   r   r   s       r3   Útest_transaction_type_constantszBWalletServiceTransactionTypesTests.test_transaction_type_constants|  sp   € ÷	
ñ 	
ð 	×Ñ˜n¬cÔ2Ø×Ñ˜o¬sÔ3Ø×ÑÐ.´Ô4à×Ñ˜¨Ô.Ø×Ñ˜¨$Ô/Ø×ÑÐ)¨4Õ0r6   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-withdrawr@  úroi-distributionrA  zinvalid-typeN)rD   r   rƒ   Ú
ValueErrorr1   s    r3   Ú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?  rE  r@  rF  rA  rG  rš   N)rD   r   r  r1   s    r3   Ú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Ó:Õ;r6   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%   r8   r‚   rK   rE  N)
r0   r>   r.   r?   r   r   rN   rD   rL   r   )r2   rF   r	   Únames       r3   Ú+test_transaction_type_in_transaction_recordzNWalletServiceTransactionTypesTests.test_transaction_type_in_transaction_recordœ  s†   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜8Ó$ØÜ%ð 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜×/Ñ/´Ô@ô )¨×)?Ñ)?Ó@ˆØ×Ñ˜Ð/Õ0r6   N)	rœ   r�   rž   rŸ   r4   rC  rI  rK  rN  r    r6   r3   r<  r<  o  s   „ Ù;ò0ò1ò 1ò<ó1r6   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+   r1   s    r3   r4   z!WalletServiceEdgeCasesTests.setUp±  r5   r6   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%   r8   zSystem walletrU   N)r0   r>   r   rN   rD   r‘   rV   rQ   s      r3   Útest_system_user_idz/WalletServiceEdgeCasesTests.test_system_user_id¿  so   € ð Ÿ™×/Ñ/ØØ'Ü˜8Ó$Ø#Øð 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜Ÿ™¨$Ô/Ø×Ñ˜Ÿ™¨$Õ/r6   c                 óô   — ddz  }| j                   j                  | j                  j                  dt	        d«      |¬«      }| j                   j                  |«      }| j                  |j                  |«       y)zTest with very long remarks.ÚAi'  r%   r8   r9   N©r0   r>   r.   r?   r   rN   rD   r“   )r2   Úlong_remarksrF   r	   s       r3   Útest_very_long_remarksz2WalletServiceEdgeCasesTests.test_very_long_remarksÏ  si   € à˜U‘{ˆØŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜8Ó$Ø ð	 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜×*Ñ*¨LÕ9r6   c                 óê   — | j                   j                  | j                  j                  dt	        d«      d¬«      }| j                   j                  |«      }| j                  |j                  d«       y)zTest with empty remarks.r%   r8   Ú r9   NrV  rQ   s      r3   Útest_empty_remarksz.WalletServiceEdgeCasesTests.test_empty_remarksÜ  s`   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜8Ó$Øð	 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜×*Ñ*¨BÕ/r6   c                 óê   — | j                   j                  | j                  j                  dt	        d«      dd¬«      }| j                   j                  |«      }| j                  |j                  «       y)z Test with None transaction type.r%   r8   r‚   NrK   )r0   r>   r.   r?   r   rN   r  rL   rQ   s      r3   Útest_none_transaction_typez6WalletServiceEdgeCasesTests.test_none_transaction_typeè  sa   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜8Ó$ØØð 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜+×0Ñ0Õ1r6   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%   r8   r‚   r_   rc   Nre   rQ   s      r3   Útest_empty_extra_dataz1WalletServiceEdgeCasesTests.test_empty_extra_dataõ  sg   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜8Ó$ØØ˜B�<ð 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜×/Ñ/°Õ4r6   c                 óê   — | j                   j                  | j                  j                  dt	        d«      d¬«      }| j                   j                  |«      }| j                  |j                  i «       y)zTest without params parameter.r%   r8   r‚   r9   Nre   rQ   s      r3   Útest_no_paramsz*WalletServiceEdgeCasesTests.test_no_params  s`   € àŸ™×/Ñ/Ø—I‘I—L‘LØ'Ü˜8Ó$Øð	 0ó 
ˆð —l‘l×8Ñ8¸ÓHˆØ×Ñ˜×/Ñ/°Õ4r6   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[   rt   r9   r8   rË   rÀ   rI   N©
rÒ   r0   r>   r.   r?   r   rC   rD   r%   r©   ©r2   rÔ   s     r3   Ú#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ÕDr6   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 r9   z1.00é2   zMicro withdrawal z0.50Nrc  rd  s     r3   Ú/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³?ÕCr6   N)rœ   r�   rž   rŸ   r4   rS  rX  r[  r]  r_  ra  re  ri  r    r6   r3   rP  rP  ®  s4   „ Ù,ò0ò0ò :ò
0ò2ò5ò
5òEó4Dr6   rP  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¥   r9   Nr¦   r1   s    r3   r4   z%WalletServiceRaceConditionTests.setUpF  s‰   € ä×$Ñ$×+Ñ+°ZÐGYÐ+ÓZˆŒ	Ø,¨aÐ0ˆÔÜ$ÜØ×(Ñ(ô
ˆŒ	ô % T§Y¡YÓ/ˆŒð 	�‰×ÑØ—I‘I—L‘LØ'Ü˜9Ó%Ø%ð	 	õ 	
r6   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 withdrawalr9   )r0   r©   r.   r?   r   r   r1   s   €r3   Ú
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     r3   Ú	<genexpr>z`WalletServiceRaceConditionTests.test_atomic_deduction_prevents_race_condition.<locals>.<genexpr>n  s   è ø€ ÐKÑ'9 !¸Q¹]œAÑ'9ùs   ‚ŠrÍ   rÁ   r¤   N)ÚsumÚassertLessEqualr.   rC   rD   r%   r   )r2   ro  Úresult1Úresult2Úsuccess_counts   `    r3   Ú-test_atomic_deduction_prevents_race_conditionzMWalletServiceRaceConditionTests.test_atomic_deduction_prevents_race_conditionX  s™   ø€ ô
		ñ “,ˆÙ“,ˆô ÑK¨°Ñ'9ÓKÓKˆØ×Ñ˜]¨AÔ.ð 	�	‰	×!Ñ!Ô#Ø˜AÒà×Ñ˜TŸY™Y×5Ñ5´w¸xÓ7HÕIð ×Ñ˜TŸY™Y×5Ñ5´w¸yÓ7IÕJr6   N)rœ   r�   rž   rŸ   r4   ry  r    r6   r3   rk  rk  C  s   „ ÙMò
ó$ Kr6   rk  N)&rŸ   Údecimalr   r   r   Údjango.testr   r   Ú	django.dbr	   Údb_transactionÚwallet_utilsr
   r   Úwallet_utils.exceptionsr   r   r   r   rB  r   r   r   r   r   Útests.modelsr   r   r   r   r¢   rÆ   r  r,  r5  r<  rP  rk  r    r6   r3   Ú<module>r�     s¿   ðñõ ß (ß 5Ý 3ç 8÷ó ÷õ ÷ EÑ Dô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r6   