Ë
    Æ|Si“\  ã                  ó  — d Z ddlmZ ddlmZ ddlmZmZ ddlm	Z	 ddl
mZ ddlmZmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ  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)zAUnit tests for wallet-utils integration in investment operations.é    )Úannotations)ÚDecimal)ÚTestCaseÚTransactionTestCase)Úreverse)Ústatus)Ú	APIClientÚAPITestCase)ÚInsufficientBalanceError)ÚWalletTransaction)Ú
Investment)ÚTransaction)ÚUser©ÚMAKE_INVESTMENTc                  ó6   — e Zd ZdZd	d„Zd„ Zd„ Zd„ Zd„ Zd„ Z	y)
Ú InvestmentWalletIntegrationTestsz@Standard test cases for wallet-utils integration in investments.c                ó¼   — t         j                  j                  ddd¬«      | _        t	        «       | _        | j
                  j                  | j                  ¬«       y)úSet up test user and client.ié  ÚTestUserÚtestuser©Útelegram_user_idÚ
first_nameÚusername©ÚuserN©r   ÚobjectsÚcreate_userr   r	   ÚclientÚforce_authenticate©Úselfs    ú_/home/cursorai/projects/telegram-earn/backend/apps/investments/tests/test_wallet_integration.pyÚsetUpz&InvestmentWalletIntegrationTests.setUp   óJ   € ä—L‘L×,Ñ,Ø!Ø!Øð -ó 
ˆŒ	ô
  “kˆŒØ�‰×&Ñ&¨D¯I©IÐ&Õ6ó    c                óÌ  — t        d«      }t        d«      }|| j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |dt        |«      id¬«      }| j                  |j                  t        j                  «       | j                  j                  «        ||z
  }| j                  | j                  j                  |«       y)z7Standard: Investment successfully deducts user balance.ú1000.00000000ú100.00000000úinvestment-listÚamountÚjson©ÚformatN©r   r   Úcredit_balanceÚsaver   r!   ÚpostÚstrÚassertEqualÚstatus_coder   ÚHTTP_201_CREATEDÚrefresh_from_db©r$   Úinitial_balanceÚinvestment_amountÚurlÚresponseÚexpected_balances         r%   Ú*test_successful_investment_deducts_balancezKInvestmentWalletIntegrationTests.test_successful_investment_deducts_balance"   s¶   € ä! /Ó2ˆÜ# NÓ3ÐØ#2ˆ�	‰	Ô Ø�	‰	�‰ÔäÐ'Ó(ˆØ—;‘;×#Ñ# C¨(´CÐ8IÓ4JÐ)KÐTZÐ#Ó[ˆà×Ñ˜×-Ñ-¬v×/FÑ/FÔGØ�	‰	×!Ñ!Ô#Ø*Ð->Ñ>ÐØ×Ñ˜Ÿ™×1Ñ1Ð3CÕDr(   c                ó  — t        d«      }t        d«      }|| j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |dt        |«      id¬«      }| j                  |j                  t        j                  «       t        j                  j                  | j                  j                  dt         ¬«      }| j                  |j#                  «       d	«       |j%                  «       }| j                  |j&                  d
«       | j                  |j(                  |«       | j                  |j*                  | j                  j                  «       | j-                  d|j.                  «       y)z@Standard: Wallet transaction record is created via wallet-utils.ú500.00000000z150.00000000r,   r-   r.   r/   r2   )ÚuidÚwtypeÚ
trans_typeé   ÚdúInvestment in tierN)r   r   r2   r3   r   r!   r4   r5   r6   r7   r   r8   r   r   ÚfilterÚidr   ÚcountÚfirstÚtyper-   ÚiidÚassertInÚdescr)r$   r;   r<   r=   r>   Úwallet_txnsÚ
wallet_txns          r%   Ú"test_wallet_transaction_is_createdzCInvestmentWalletIntegrationTests.test_wallet_transaction_is_created1   s2  € ä! .Ó1ˆÜ# NÓ3ÐØ#2ˆ�	‰	Ô Ø�	‰	�‰ÔäÐ'Ó(ˆØ—;‘;×#Ñ# C¨(´CÐ8IÓ4JÐ)KÐTZÐ#Ó[ˆà×Ñ˜×-Ñ-¬v×/FÑ/FÔGô (×/Ñ/×6Ñ6Ø—	‘	—‘Ø"Ü&ð 7ó 
ˆð
 	×Ñ˜×*Ñ*Ó,¨aÔ0à ×&Ñ&Ó(ˆ
Ø×Ñ˜Ÿ™¨#Ô.Ø×Ñ˜×*Ñ*Ð,=Ô>Ø×Ñ˜Ÿ™¨¯©¯©Ô6Ø�‰Ð*¨J×,<Ñ,<Õ=r(   c                ón  — t        d«      }t        d«      }|| j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |dt        |«      id¬«      }| j                  |j                  t        j                  «       t        j                  j                  | j                  t        j                  ¬«      }| j                  |j!                  «       d«       |j#                  «       }| j                  |j$                  |«       | j                  |j                  t        j&                  «       | j                  |j(                  |«       | j                  |j*                  ||z
  «       | j                  |j,                  d	   |j,                  d
   «       y)z<Standard: App Transaction record is created for audit trail.ú200.00000000ú50.00000000r,   r-   r.   r/   ©r   Útransaction_typerF   Úinvestment_idrJ   N)r   r   r2   r3   r   r!   r4   r5   r6   r7   r   r8   r   r   rI   ÚTYPE_INVESTMENTrK   rL   r-   ÚSTATUS_COMPLETEDÚbalance_beforeÚbalance_afterÚdata)r$   r;   r<   r=   r>   Úapp_txnsÚapp_txns          r%   Ú&test_app_transaction_record_is_createdzGInvestmentWalletIntegrationTests.test_app_transaction_record_is_createdK   sT  € ä! .Ó1ˆÜ# MÓ2ÐØ#2ˆ�	‰	Ô Ø�	‰	�‰ÔäÐ'Ó(ˆØ—;‘;×#Ñ# C¨(´CÐ8IÓ4JÐ)KÐTZÐ#Ó[ˆà×Ñ˜×-Ñ-¬v×/FÑ/FÔGô ×&Ñ&×-Ñ-Ø—‘Ü(×8Ñ8ð .ó 
ˆð 	×Ñ˜Ÿ™Ó)¨1Ô-à—.‘.Ó"ˆØ×Ñ˜Ÿ™Ð):Ô;Ø×Ñ˜Ÿ™¬×)EÑ)EÔFØ×Ñ˜×/Ñ/°ÔAØ×Ñ˜×.Ñ.°ÐBSÑ0SÔTØ×Ñ˜Ÿ™ oÑ6¸¿¹ÀdÑ8KÕLr(   c                ó*  — t        d«      }t        d«      }|| j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |dt        |«      id¬«      }| j                  |j                  t        j                  «       t        j                  j                  | j                  t        j                  ¬«      }| j                  |j                   |«       | j                  |j"                  ||z
  «       y)	z9Standard: Balance before and after are correctly tracked.z300.00000000z75.50000000r,   r-   r.   r/   rW   N)r   r   r2   r3   r   r!   r4   r5   r6   r7   r   r8   r   r   ÚgetrZ   r\   r]   )r$   r;   r<   r=   r>   r`   s         r%   Ú/test_balance_before_and_after_tracked_correctlyzPInvestmentWalletIntegrationTests.test_balance_before_and_after_tracked_correctlye   sÞ   € ä! .Ó1ˆÜ# MÓ2ÐØ#2ˆ�	‰	Ô Ø�	‰	�‰ÔäÐ'Ó(ˆØ—;‘;×#Ñ# C¨(´CÐ8IÓ4JÐ)KÐTZÐ#Ó[ˆà×Ñ˜×-Ñ-¬v×/FÑ/FÔGä×%Ñ%×)Ñ)Ø—‘Ü(×8Ñ8ð *ó 
ˆð 	×Ñ˜×/Ñ/°ÔAØ×Ñ˜×.Ñ.°ÐBSÑ0SÕTr(   c                ó¬  — t        d«      }t        d«      }|| j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |dt        |«      id¬«      }| j                  |j                  t        j                  «       t        j                  j                  |j                  d   ¬«      }| j                  |j                   |«       | j                  |j                  | j                  «       | j                  |j"                  d«       | j                  |j                  t        j$                  «       y	)
zFStandard: Investment record is created with correct tier and metadata.z1500.00000000r,   r-   r.   r/   rJ   ©rJ   é   N)r   r   r2   r3   r   r!   r4   r5   r6   r7   r   r8   r   r   rc   r^   r-   ÚtierÚSTATUS_PENDING)r$   r;   r<   r=   r>   Ú
investments         r%   Ú-test_investment_created_with_correct_metadatazNInvestmentWalletIntegrationTests.test_investment_created_with_correct_metadatax   s   € ä! /Ó2ˆÜ# OÓ4ÐØ#2ˆ�	‰	Ô Ø�	‰	�‰ÔäÐ'Ó(ˆØ—;‘;×#Ñ# C¨(´CÐ8IÓ4JÐ)KÐTZÐ#Ó[ˆà×Ñ˜×-Ñ-¬v×/FÑ/FÔGä×'Ñ'×+Ñ+¨x¯}©}¸TÑ/BÐ+ÓCˆ
Ø×Ñ˜×*Ñ*Ð,=Ô>Ø×Ñ˜Ÿ™¨$¯)©)Ô4Ø×Ñ˜Ÿ™¨!Ô,Ø×Ñ˜×*Ñ*¬J×,EÑ,EÕFr(   N©ÚreturnÚNone)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__r&   r@   rS   ra   rd   rk   © r(   r%   r   r      s'   „ ÙJó7òEò>ò4Mò4Uó&Gr(   r   c                  ó<   — e Zd ZdZd
d„Zd„ Zd„ Zd„ Zd„ Zd„ Z	d„ Z
y	)ÚInvestmentWalletEdgeCasesTestsz-Edge case tests for wallet-utils integration.c                ó¼   — t         j                  j                  ddd¬«      | _        t	        «       | _        | j
                  j                  | j                  ¬«       y)r   iÑ  ÚEdgeUserÚedgeuserr   r   Nr   r#   s    r%   r&   z$InvestmentWalletEdgeCasesTests.setUpŽ   r'   r(   c                ó¾  — t        d«      }|| j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |dt        |«      id¬«      }| j                  |j                  t        j                  «       | j                  j                  «        | j                  | j                  j                  t        d«      «       y)z8Edge: User has exactly the amount needed for investment.r+   r,   r-   r.   r/   ú
0.00000000Nr1   )r$   r<   r=   r>   s       r%   Útest_exact_balance_matchz7InvestmentWalletEdgeCasesTests.test_exact_balance_match˜   s¤   € ä# NÓ3ÐØ#4ˆ�	‰	Ô Ø�	‰	�‰ÔäÐ'Ó(ˆØ—;‘;×#Ñ# C¨(´CÐ8IÓ4JÐ)KÐTZÐ#Ó[ˆà×Ñ˜×-Ñ-¬v×/FÑ/FÔGØ�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸<Ó3HÕIr(   c                óÔ  — t        d«      }t        d«      }|| j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |dt        |«      id¬«      }| j                  |j                  t        j                  «       | j                  j                  «        | j                  | j                  j                  t        d«      «       y)z6Edge: Minimum investment amount ($10) works correctly.z10.00000000r,   r-   r.   r/   rz   Nr1   ©r$   r;   r<   r=   r>   s        r%   Útest_minimum_investment_amountz=InvestmentWalletEdgeCasesTests.test_minimum_investment_amount¥   s®   € ä! -Ó0ˆÜ# MÓ2ÐØ#2ˆ�	‰	Ô Ø�	‰	�‰ÔäÐ'Ó(ˆØ—;‘;×#Ñ# C¨(´CÐ8IÓ4JÐ)KÐTZÐ#Ó[ˆà×Ñ˜×-Ñ-¬v×/FÑ/FÔGØ�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸<Ó3HÕIr(   c                ó^  — t        d«      }t        d«      }|| j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |dt        |«      id¬«      }| j                  |j                  t        j                  «       | j                  j                  «        ||z
  }| j                  | j                  j                  |«       t        j                  j                  |j                   d   ¬«      }| j                  |j"                  d	«       y
)z7Edge: Large investment amount (tier 6) works correctly.ú10000.00000000z6000.00000000r,   r-   r.   r/   rJ   rf   é   N)r   r   r2   r3   r   r!   r4   r5   r6   r7   r   r8   r9   r   r   rc   r^   rh   )r$   r;   r<   r=   r>   r?   rj   s          r%   Útest_large_investment_amountz;InvestmentWalletEdgeCasesTests.test_large_investment_amount³   sí   € ä!Ð"2Ó3ˆÜ# OÓ4ÐØ#2ˆ�	‰	Ô Ø�	‰	�‰ÔäÐ'Ó(ˆØ—;‘;×#Ñ# C¨(´CÐ8IÓ4JÐ)KÐTZÐ#Ó[ˆà×Ñ˜×-Ñ-¬v×/FÑ/FÔGØ�	‰	×!Ñ!Ô#Ø*Ð->Ñ>ÐØ×Ñ˜Ÿ™×1Ñ1Ð3CÔDä×'Ñ'×+Ñ+¨x¯}©}¸TÑ/BÐ+ÓCˆ
Ø×Ñ˜Ÿ™¨!Õ,r(   c                óŒ  — t        d«      }|| j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |ddid¬«      }| j                  |j                  t        j                  «       | j                  j                  «        | j                  | j                  j                  t        d«      «       | j
                  j                  |ddid¬«      }| j                  |j                  t        j                  «       | j                  j                  «        | j                  | j                  j                  t        d	«      «       | j
                  j                  |dd
id¬«      }| j                  |j                  t        j                  «       | j                  j                  «        | j                  | j                  j                  t        d«      «       t        j                  j                  | j                  ¬«      }| j                  |j                  «       d«       y)z@Edge: Multiple investments in sequence correctly deduct balance.rB   r,   r-   Ú100r.   r/   z400.00000000Ú150z250.00000000Ú200rV   r   é   N)r   r   r2   r3   r   r!   r4   r6   r7   r   r8   r9   r   r   rI   rK   ©r$   r;   r=   Ú	response1Ú	response2Ú	response3Úinvestmentss          r%   Ú$test_multiple_sequential_investmentszCInvestmentWalletEdgeCasesTests.test_multiple_sequential_investmentsÅ   s°  € ä! .Ó1ˆØ#2ˆ�	‰	Ô Ø�	‰	�‰Ôô Ð'Ó(ˆØ—K‘K×$Ñ$ S¨8°UÐ*;ÀFÐ$ÓKˆ	Ø×Ñ˜×.Ñ.´×0GÑ0GÔHà�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸>Ó3JÔKð —K‘K×$Ñ$ S¨8°UÐ*;ÀFÐ$ÓKˆ	Ø×Ñ˜×.Ñ.´×0GÑ0GÔHà�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸>Ó3JÔKð —K‘K×$Ñ$ S¨8°UÐ*;ÀFÐ$ÓKˆ	Ø×Ñ˜×.Ñ.´×0GÑ0GÔHà�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸=Ó3IÔJô !×(Ñ(×/Ñ/°T·Y±YÐ/Ó?ˆØ×Ñ˜×*Ñ*Ó,¨aÕ0r(   c                ó¾  — t        d«      }t        d«      }|| j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |dt        |«      id¬«      }| j                  |j                  t        j                  «       | j                  j                  «        ||z
  }| j                  | j                  j                  |«       t        j                  j                  | j                  j                   d¬«      j#                  «       }| j%                  |«       | j                  |j&                  t        d	«      «       y
)zCEdge: Decimal precision of 8 places is maintained for user balance.z100.12345678z50.98765432r,   r-   r.   r/   r2   ©rC   rD   z50.99N)r   r   r2   r3   r   r!   r4   r5   r6   r7   r   r8   r9   r   r   rI   rJ   rL   ÚassertIsNotNoner-   )r$   r;   r<   r=   r>   r?   rR   s          r%   Ú#test_decimal_precision_eight_placeszBInvestmentWalletEdgeCasesTests.test_decimal_precision_eight_placeså   s  € ä! .Ó1ˆÜ# MÓ2ÐØ#2ˆ�	‰	Ô Ø�	‰	�‰ÔäÐ'Ó(ˆØ—;‘;×#Ñ# C¨(´CÐ8IÓ4JÐ)KÐTZÐ#Ó[ˆà×Ñ˜×-Ñ-¬v×/FÑ/FÔGØ�	‰	×!Ñ!Ô#Ø*Ð->Ñ>ÐØ×Ñ˜Ÿ™×1Ñ1Ð3CÔDô
 '×.Ñ.×5Ñ5Ø—	‘	—‘Ø"ð 6ó 
÷ ‰%‹'ð 	ð 	×Ñ˜ZÔ(ð 	×Ñ˜×*Ñ*¬G°GÓ,<Õ=r(   c                ó$  — t        d«      }|| j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |ddid¬«      }| j                  |j                  t        j                  «       | j                  j                  «        | j                  | j                  j                  t        d«      «       | j
                  j                  |ddid¬«      }| j                  |j                  t        j                  «       | j                  j                  «        | j                  | j                  j                  t        d	«      «       | j
                  j                  |dd
id¬«      }| j                  |j                  t        j                  «       | j                  j                  «        | j                  | j                  j                  t        d«      «       t        j                  j                  | j                  ¬«      j                  d«      }| j                  |d   j                   d«       | j                  |d   j                   d«       | j                  |d   j                   d«       y)z:Edge: Different tier investments correctly deduct balance.r€   r,   r-   Ú50r.   r/   z9950.00000000Ú300z9650.00000000Ú800z8850.00000000r   Ú
created_atr   rF   é   r‡   N)r   r   r2   r3   r   r!   r4   r6   r7   r   r8   r9   r   r   rI   Úorder_byrh   rˆ   s          r%   Útest_different_tier_investmentsz>InvestmentWalletEdgeCasesTests.test_different_tier_investments   sñ  € ä!Ð"2Ó3ˆØ#2ˆ�	‰	Ô Ø�	‰	�‰ÔäÐ'Ó(ˆð —K‘K×$Ñ$ S¨8°TÐ*:À6Ð$ÓJˆ	Ø×Ñ˜×.Ñ.´×0GÑ0GÔHØ�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸?Ó3KÔLð —K‘K×$Ñ$ S¨8°UÐ*;ÀFÐ$ÓKˆ	Ø×Ñ˜×.Ñ.´×0GÑ0GÔHØ�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸?Ó3KÔLð —K‘K×$Ñ$ S¨8°UÐ*;ÀFÐ$ÓKˆ	Ø×Ñ˜×.Ñ.´×0GÑ0GÔHØ�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸?Ó3KÔLô !×(Ñ(×/Ñ/°T·Y±YÐ/Ó?×HÑHÈÓVˆØ×Ñ˜ Q™×,Ñ,¨aÔ0Ø×Ñ˜ Q™×,Ñ,¨aÔ0Ø×Ñ˜ Q™×,Ñ,¨aÕ0r(   Nrl   )ro   rp   rq   rr   r&   r{   r~   r‚   r�   r‘   r™   rs   r(   r%   ru   ru   ‹   s+   „ Ù7ó7òJòJò-ò$1ò@>ó61r(   ru   c                  óN   — e Zd ZdZdd„Zd„ Zd„ Zd„ Zd„ Zd„ Z	d„ Z
d	„ Zd
„ Zd„ Zy)ÚInvestmentWalletOutlierTestsz6Outlier/error case tests for wallet-utils integration.c                ó¼   — t         j                  j                  ddd¬«      | _        t	        «       | _        | j
                  j                  | j                  ¬«       y)r   i¹  ÚOutlierUserÚoutlieruserr   r   Nr   r#   s    r%   r&   z"InvestmentWalletOutlierTests.setUp$  sJ   € ä—L‘L×,Ñ,Ø!Ø$Ø"ð -ó 
ˆŒ	ô
  “kˆŒØ�‰×&Ñ&¨D¯I©IÐ&Õ6r(   c                ó0  — t        d«      }t        d«      }|| j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |dt        |«      id¬«      }| j                  |j                  t        j                  «       | j                  d|j                  «       | j                  dt        |j                  d   d   «      «       | j                  dt        |j                  d   d   «      «       | j                  dt        |j                  d   d   «      «       | j                  j                  «        | j                  | j                  j                  |«       | j                  t        j                   j#                  | j                  ¬	«      j%                  «       d«       | j                  t&        j                   j#                  | j                  j(                  ¬
«      j%                  «       d«       y)z:Outlier: Investment with insufficient balance is rejected.rV   r+   r,   r-   r.   r/   úInsufficient balancer   r   )rC   N)r   r   r2   r3   r   r!   r4   r5   r6   r7   r   ÚHTTP_400_BAD_REQUESTrO   r^   r9   r   r   rI   rK   r   rJ   r}   s        r%   Ú,test_insufficient_balance_rejects_investmentzIInvestmentWalletOutlierTests.test_insufficient_balance_rejects_investment.  sŽ  € ä! -Ó0ˆÜ# NÓ3ÐØ#2ˆ�	‰	Ô Ø�	‰	�‰ÔäÐ'Ó(ˆØ—;‘;×#Ñ# C¨(´CÐ8IÓ4JÐ)KÐTZÐ#Ó[ˆà×Ñ˜×-Ñ-¬v×/JÑ/JÔKØ�‰�h §¡Ô.Ø�‰Ð,¬c°(·-±-ÀÑ2IÈ!Ñ2LÓ.MÔNØ�‰�m¤S¨¯©°xÑ)@ÀÑ)CÓ%DÔEØ�‰�n¤c¨(¯-©-¸Ñ*AÀ!Ñ*DÓ&EÔFð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1°?ÔCð 	×Ñœ×+Ñ+×2Ñ2¸¿	¹	Ð2ÓB×HÑHÓJÈAÔNð 	×ÑÜ×%Ñ%×,Ñ,°·±·±Ð,Ó>×DÑDÓFÈõ	
r(   c                ól  — t        d«      | j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |ddid¬«      }| j                  |j                  t        j                  «       | j                  dt        |j                  d   d   «      «       y	)
z.Outlier: User with zero balance cannot invest.rz   r,   r-   Ú10r.   r/   r    r   N)r   r   r2   r3   r   r!   r4   r6   r7   r   r¡   rO   r5   r^   )r$   r=   r>   s      r%   Ú$test_zero_balance_rejects_investmentzAInvestmentWalletOutlierTests.test_zero_balance_rejects_investmentJ  sŠ   € ä#*¨<Ó#8ˆ�	‰	Ô Ø�	‰	�‰ÔäÐ'Ó(ˆØ—;‘;×#Ñ# C¨(°DÐ)9À&Ð#ÓIˆà×Ñ˜×-Ñ-¬v×/JÑ/JÔKØ�‰Ð,¬c°(·-±-ÀÑ2IÈ!Ñ2LÓ.MÕNr(   c                ó˜  — t        d«      }t        d«      }|| j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |dt        |«      id¬«      }| j                  |j                  t        j                  «       | j                  dt        |j                  d   d   «      «       y	)
zLOutlier: Attempting to invest more than balance fails (no negative balance).r+   z100.00000001r,   r-   r.   r/   r    r   N)r   r   r2   r3   r   r!   r4   r5   r6   r7   r   r¡   rO   r^   r}   s        r%   Ú#test_negative_balance_attempt_failsz@InvestmentWalletOutlierTests.test_negative_balance_attempt_failsU  s¡   € ä! .Ó1ˆÜ# NÓ3ÐØ#2ˆ�	‰	Ô Ø�	‰	�‰ÔäÐ'Ó(ˆØ—;‘;×#Ñ# C¨(´CÐ8IÓ4JÐ)KÐTZÐ#Ó[ˆà×Ñ˜×-Ñ-¬v×/JÑ/JÔKØ�‰Ð,¬c°(·-±-ÀÑ2IÈ!Ñ2LÓ.MÕNr(   c                óR  — t        d«      }|| j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |ddid¬«      }| j                  |j                  t        j                  «       | j                  d|j                  «       y)z5Outlier: Amount just below minimum ($10) is rejected.r*   r,   r-   z
9.99999999r.   r/   N©r   r   r2   r3   r   r!   r4   r6   r7   r   r¡   rO   r^   ©r$   r;   r=   r>   s       r%   Útest_amount_just_below_minimumz;InvestmentWalletOutlierTests.test_amount_just_below_minimumb  s   € ä! /Ó2ˆØ#2ˆ�	‰	Ô Ø�	‰	�‰ÔäÐ'Ó(ˆØ—;‘;×#Ñ# C¨(°LÐ)AÈ&Ð#ÓQˆà×Ñ˜×-Ñ-¬v×/JÑ/JÔKØ�‰�h §¡Õ.r(   c                óÌ  — t        d«      }t        d«      }|| j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |dt        |«      id¬«      }| j                  |j                  t        j                  «       | j                  j                  «        ||z
  }| j                  | j                  j                  |«       y)z4Outlier: Very small amount just above minimum works.r+   z10.00000001r,   r-   r.   r/   Nr1   r:   s         r%   Ú$test_very_small_amount_above_minimumzAInvestmentWalletOutlierTests.test_very_small_amount_above_minimumn  s¶   € ä! .Ó1ˆÜ# MÓ2ÐØ#2ˆ�	‰	Ô Ø�	‰	�‰ÔäÐ'Ó(ˆØ—;‘;×#Ñ# C¨(´CÐ8IÓ4JÐ)KÐTZÐ#Ó[ˆà×Ñ˜×-Ñ-¬v×/FÑ/FÔGØ�	‰	×!Ñ!Ô#Ø*Ð->Ñ>ÐØ×Ñ˜Ÿ™×1Ñ1Ð3CÕDr(   c                óÌ  — t        d«      }t        d«      }|| j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |dt        |«      id¬«      }| j                  |j                  t        j                  «       | j                  j                  «        ||z
  }| j                  | j                  j                  |«       y)zEOutlier: Very large investment amount works if balance is sufficient.z1000000.00000000z999999.99999999r,   r-   r.   r/   Nr1   r:   s         r%   Útest_very_large_amountz3InvestmentWalletOutlierTests.test_very_large_amount}  s¸   € ä!Ð"4Ó5ˆÜ#Ð$5Ó6ÐØ#2ˆ�	‰	Ô Ø�	‰	�‰ÔäÐ'Ó(ˆØ—;‘;×#Ñ# C¨(´CÐ8IÓ4JÐ)KÐTZÐ#Ó[ˆà×Ñ˜×-Ñ-¬v×/FÑ/FÔGØ�	‰	×!Ñ!Ô#Ø*Ð->Ñ>ÐØ×Ñ˜Ÿ™×1Ñ1Ð3CÕDr(   c                óR  — t        d«      }|| j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |ddid¬«      }| j                  |j                  t        j                  «       | j                  d|j                  «       y)z>Outlier: Negative amount is rejected by serializer validation.r+   r,   r-   z-10r.   r/   Nr©   rª   s       r%   Útest_negative_amount_rejectedz:InvestmentWalletOutlierTests.test_negative_amount_rejectedŒ  ó   € ä! .Ó1ˆØ#2ˆ�	‰	Ô Ø�	‰	�‰ÔäÐ'Ó(ˆØ—;‘;×#Ñ# C¨(°EÐ):À6Ð#ÓJˆà×Ñ˜×-Ñ-¬v×/JÑ/JÔKØ�‰�h §¡Õ.r(   c                óR  — t        d«      }|| j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |ddid¬«      }| j                  |j                  t        j                  «       | j                  d|j                  «       y)z:Outlier: Zero amount is rejected by serializer validation.r+   r,   r-   Ú0r.   r/   Nr©   rª   s       r%   Útest_zero_amount_rejectedz6InvestmentWalletOutlierTests.test_zero_amount_rejected˜  s~   € ä! .Ó1ˆØ#2ˆ�	‰	Ô Ø�	‰	�‰ÔäÐ'Ó(ˆØ—;‘;×#Ñ# C¨(°C¨ÀÐ#ÓHˆà×Ñ˜×-Ñ-¬v×/JÑ/JÔKØ�‰�h §¡Õ.r(   c                óR  — t        d«      }|| j                  _        | j                  j                  «        t	        d«      }| j
                  j                  |ddid¬«      }| j                  |j                  t        j                  «       | j                  d|j                  «       y)z(Outlier: Non-numeric amount is rejected.r+   r,   r-   Úabcr.   r/   Nr©   rª   s       r%   Ú test_non_numeric_amount_rejectedz=InvestmentWalletOutlierTests.test_non_numeric_amount_rejected¤  r²   r(   Nrl   )ro   rp   rq   rr   r&   r¢   r¥   r§   r«   r­   r¯   r±   rµ   r¸   rs   r(   r%   r›   r›   !  s;   „ Ù@ó7ò
ò8	OòOò
/òEòEò
/ò
/ó
/r(   r›   c                  ó$   — e Zd ZdZdd„Zd„ Zd„ Zy)Ú InvestmentWalletConcurrencyTestsz;Concurrency and race condition tests for wallet operations.c                óR   — t         j                  j                  ddd¬«      | _        y)zSet up test user.i¡  ÚConcurrentUserÚconcurrentuserr   N)r   r   r    r   r#   s    r%   r&   z&InvestmentWalletConcurrencyTests.setUp´  s&   € ä—L‘L×,Ñ,Ø!Ø'Ø%ð -ó 
ˆ�	r(   c                ó¸  ‡ — t        d«      }|‰ j                  _        ‰ j                  j                  «        ˆ fd„} |«       }‰ j	                  |j
                  t        j                  «       ‰ j                  j                  «        ‰ j	                  ‰ j                  j                  t        d«      «        |«       }‰ j	                  |j
                  t        j                  «       ‰ j                  dt        |j                  d   d   «      «       ‰ j	                  t        j                  j                  ‰ j                  ¬«      j!                  «       d«       y	)
z7Outlier: Concurrent investments are handled atomically.rU   c                 ó’   •— t        «       } | j                  ‰j                  ¬«       t        d«      }| j	                  |ddid¬«      S )Nr   r,   r-   r…   r.   r/   )r	   r"   r   r   r4   )r!   r=   r$   s     €r%   Úcreate_investmentznInvestmentWalletConcurrencyTests.test_concurrent_investments_prevent_race_condition.<locals>.create_investmentÄ  sD   ø€ Ü“[ˆFØ×%Ñ%¨4¯9©9Ð%Ô5ÜÐ+Ó,ˆCØ—;‘;˜s X¨uÐ$5¸f�;ÓEÐEr(   rV   r    r-   r   r   rF   N)r   r   r2   r3   r6   r7   r   r8   r9   r¡   rO   r5   r^   r   r   rI   rK   )r$   r;   rÀ   r‰   rŠ   s   `    r%   Ú2test_concurrent_investments_prevent_race_conditionzSInvestmentWalletConcurrencyTests.test_concurrent_investments_prevent_race_condition¼  sý   ø€ ä! .Ó1ˆØ#2ˆ�	‰	Ô Ø�	‰	�‰Ôô	Fñ &Ó'ˆ	Ø×Ñ˜×.Ñ.´×0GÑ0GÔHà�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸=Ó3IÔJñ &Ó'ˆ	Ø×Ñ˜×.Ñ.´×0KÑ0KÔLØ�‰Ð,¬c°)·.±.ÀÑ2JÈ1Ñ2MÓ.NÔOð 	×Ñœ×+Ñ+×2Ñ2¸¿	¹	Ð2ÓB×HÑHÓJÈAÕNr(   c                ó„  — t        d«      }|| j                  _        | j                  j                  «        t	        «       }|j                  | j                  ¬«       t        d«      }|j                  |ddid¬«      }| j                  |j                  t        j                  «       | j                  j                  «        | j                  | j                  j                  t        d«      «       t        j                  j                  |j                   d	   ¬
«      }| j#                  |«       t$        j                  j'                  | j                  j(                  d¬«      j+                  «       }| j#                  |«       t,        j                  j'                  | j                  t,        j.                  ¬«      j+                  «       }| j#                  |«       | j                  |j0                  |«       | j                  |j2                  t        d«      «       | j                  |j4                  t        d«      «       y)z:Outlier: All operations in investment creation are atomic.r+   r   r,   r-   r“   r.   r/   rV   rJ   rf   r2   r�   rW   N)r   r   r2   r3   r	   r"   r   r4   r6   r7   r   r8   r9   r   r   rc   r^   r�   r   rI   rJ   rL   r   rZ   r\   r]   Úbalance)r$   r;   r!   r=   r>   rj   rR   r`   s           r%   Ú#test_atomic_transaction_consistencyzDInvestmentWalletConcurrencyTests.test_atomic_transaction_consistencyÙ  sÅ  € ä! .Ó1ˆØ#2ˆ�	‰	Ô Ø�	‰	�‰Ôô “ˆØ×!Ñ! t§y¡yÐ!Ô1ÜÐ'Ó(ˆØ—;‘;˜s X¨tÐ$4¸V�;ÓDˆà×Ñ˜×-Ñ-¬v×/FÑ/FÔGð 	�	‰	×!Ñ!Ô#Ø×Ñ˜Ÿ™×1Ñ1´7¸=Ó3IÔJô  ×'Ñ'×+Ñ+¨x¯}©}¸TÑ/BÐ+ÓCˆ
Ø×Ñ˜ZÔ(ô '×.Ñ.×5Ñ5Ø—	‘	—‘Ø"ð 6ó 
÷ ‰%‹'ð 	ð 	×Ñ˜ZÔ(ô ×%Ñ%×,Ñ,Ø—‘Ü(×8Ñ8ð -ó 
÷ ‰%‹'ð 	ð 	×Ñ˜WÔ%ð 	×Ñ˜×/Ñ/°ÔAØ×Ñ˜×.Ñ.´¸Ó0FÔGØ×Ñ˜×+Ñ+¬W°]Ó-CÕDr(   Nrl   )ro   rp   rq   rr   r&   rÁ   rÄ   rs   r(   r%   rº   rº   ±  s   „ ÙEó
òOó:'Er(   rº   c                  ó"   — e Zd ZdZd„ Zd„ Zd„ Zy)Ú$InvestmentWalletTransactionTypeTestsz2Tests for transaction type registration and usage.c                ó4   — ddl m} | j                  |d«       y)z8Standard: MAKE_INVESTMENT constant is correctly defined.r   r   i'  N)Úutils.walletr   r6   )r$   r   s     r%   Ú.test_make_investment_transaction_type_constantzSInvestmentWalletTransactionTypeTests.test_make_investment_transaction_type_constant  s   € å0à×Ñ˜¨%Õ0r(   c                ób  — t         j                  j                  ddd¬«      }t        d«      |_        |j                  «        t        «       }|j                  |¬«       t        d«      }|j                  |dd	id
¬«      }| j                  |j                  t        j                  «       t        j                  j                  |j                   d¬«      j#                  «       }| j%                  |«       | j                  |j&                  t(        «       | j                  |j*                  d«       y)zCStandard: Wallet transactions use MAKE_INVESTMENT transaction type.i‰  ÚTypeUserÚtypeuserr   r*   r   r,   r-   r„   r.   r/   r2   r�   rG   N)r   r   r    r   r2   r3   r	   r"   r   r4   r6   r7   r   r8   r   rI   rJ   rL   r�   rE   r   rM   ©r$   r   r!   r=   r>   rR   s         r%   Ú)test_wallet_transaction_uses_correct_typezNInvestmentWalletTransactionTypeTests.test_wallet_transaction_uses_correct_type  sÿ   € ä�|‰|×'Ñ'Ø!Ø!Øð (ó 
ˆô
 & oÓ6ˆÔØ�	‰	Œä“ˆØ×!Ñ! tÐ!Ô,ÜÐ'Ó(ˆØ—;‘;˜s X¨uÐ$5¸f�;ÓEˆà×Ñ˜×-Ñ-¬v×/FÑ/FÔGä&×.Ñ.×5Ñ5Ø—‘Ø"ð 6ó 
÷ ‰%‹'ð 	ð
 	×Ñ˜ZÔ(Ø×Ñ˜×.Ñ.´Ô@Ø×Ñ˜Ÿ™¨#Õ.r(   c                ó8  — t         j                  j                  ddd¬«      }t        d«      |_        |j                  «        t        «       }|j                  |¬«       t        d«      }|j                  |dd	id
¬«      }| j                  |j                  t        j                  «       t        j                  j                  |j                   d¬«      j#                  «       }| j%                  d|j&                  «       | j%                  d|j&                  «       y)z>Standard: Wallet transaction remarks include tier information.iŠ  ÚRemarksUserÚremarksuserr   z2000.00000000r   r,   r-   Ú1500r.   r/   r2   r�   rH   Ú4N)r   r   r    r   r2   r3   r	   r"   r   r4   r6   r7   r   r8   r   rI   rJ   rL   rO   rP   rÍ   s         r%   Ú,test_wallet_transaction_remarks_include_tierzQInvestmentWalletTransactionTypeTests.test_wallet_transaction_remarks_include_tier&  sð   € ä�|‰|×'Ñ'Ø!Ø$Ø"ð (ó 
ˆô
 & oÓ6ˆÔØ�	‰	Œä“ˆØ×!Ñ! tÐ!Ô,ÜÐ'Ó(ˆØ—;‘;˜s X¨vÐ$6¸v�;ÓFˆà×Ñ˜×-Ñ-¬v×/FÑ/FÔGä&×.Ñ.×5Ñ5Ø—‘Ø"ð 6ó 
÷ ‰%‹'ð 	ð
 	�‰Ð*¨J×,<Ñ,<Ô=Ø�‰�c˜:×+Ñ+Õ,r(   N)ro   rp   rq   rr   rÉ   rÎ   rÔ   rs   r(   r%   rÆ   rÆ     s   „ Ù<ò1ò/ó4-r(   rÆ   N) rr   Ú
__future__r   Údecimalr   Údjango.testr   r   Údjango.urlsr   Úrest_frameworkr   Úrest_framework.testr	   r
   Údjango_wallet_utils.exceptionsr   Údjango_wallet_utils.modelsr   Úapps.investments.modelsr   Úapps.transactions.modelsr   Úapps.users.modelsr   rÈ   r   r   ru   r›   rº   rÆ   rs   r(   r%   Ú<module>rà      sy   ðÙ Gå "å ç 5Ý Ý !ß 6å CÝ 8å .Ý 0Ý "Ý (ôsG {ô sGôlS1 [ô S1ôlM/ ;ô M/ô`OEÐ':ô OEôd:-¨8õ :-r(   