Ë
    P Si'P  ã                  óð   — d 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mZ dd
lmZ ddlmZ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y)zDTests for investment start_date logic and reward calculation timing.é    )Úannotations)ÚdateÚ	timedelta)ÚDecimal)ÚTestCase)Úreverse)Útimezone)Ústatus)Ú	APIClientÚAPITestCase)ÚCalculateRewardsTask)Ú
InvestmentÚReward)ÚUserc                  ó0   — e Zd ZdZdd„Zd„ Zd„ Zd„ Zd„ Zy)	ÚInvestmentStartDateTestszBStandard tests for investment start_date being created_at + 1 day.c                ó$  — t         j                  j                  ddd¬«      | _        t	        d«      | j                  _        | j                  j                  «        t        «       | _        | j                  j                  | j                  ¬«       y)ú)Set up test user with sufficient balance.i‰  ÚTestUserÚtestuser©Útelegram_user_idÚ
first_nameÚusernamez20000.00000000©ÚuserN©
r   ÚobjectsÚcreate_userr   r   Úcredit_balanceÚsaver   ÚclientÚforce_authenticate©Úselfs    ú]/home/cursorai/projects/telegram-earn/backend/apps/investments/tests/test_start_date_logic.pyÚsetUpzInvestmentStartDateTests.setUp   ój   € ä—L‘L×,Ñ,Ø!Ø!Øð -ó 
ˆŒ	ô
 $+Ð+;Ó#<ˆ�	‰	Ô Ø�	‰	�‰ÔÜ“kˆŒØ�‰×&Ñ&¨D¯I©IÐ&Õ6ó    c                ó   — t        d«      }t        j                  «       }| j                  j	                  |ddid¬«      }| j                  |j                  t        j                  «       t        j                  j                  |j                  d   ¬«      }|j                  t        d¬	«      z   }t        |j                   |z
  j#                  «       «      }| j%                  |dd
«       | j'                  |j                   |j                  «       y)z+Standard: start_date is created_at + 1 day.úinvestment-listÚamountÚ1000Újson©ÚformatÚid©r1   é   ©Údaysz/start_date should be exactly created_at + 1 dayN)r   r	   Únowr"   ÚpostÚassertEqualÚstatus_coder
   ÚHTTP_201_CREATEDr   r   ÚgetÚdataÚ
created_atr   ÚabsÚ
start_dateÚtotal_secondsÚ
assertLessÚassertGreater)r%   ÚurlÚbefore_creationÚresponseÚ
investmentÚexpected_startÚ	time_diffs          r&   Ú*test_start_date_is_next_day_after_creationzCInvestmentStartDateTests.test_start_date_is_next_day_after_creation"   sÚ   € äÐ'Ó(ˆÜ"Ÿ,™,›.ˆà—;‘;×#Ñ# C¨(°FÐ);ÀFÐ#ÓKˆà×Ñ˜×-Ñ-¬v×/FÑ/FÔGÜ×'Ñ'×+Ñ+¨x¯}©}¸TÑ/BÐ+ÓCˆ
ð $×.Ñ.´ÀÔ1BÑBˆÜ˜×.Ñ.°Ñ?×NÑNÓPÓQˆ	Ø�‰˜	 1Ð&WÔXð 	×Ñ˜:×0Ñ0°*×2GÑ2GÕHr)   c                óÀ  — t        d«      }| j                  j                  |ddid¬«      }| j                  |j                  t
        j                  «       t        j                  j                  |j                  d   ¬«      }|j                  t        |j                  ¬«      z   }t        |j                  |z
  j!                  «       «      }| j#                  |d	d
«       y)z0Standard: end_date = start_date + duration_days.r+   r,   r-   r.   r/   r1   r2   r4   r3   z-end_date should be start_date + duration_daysN)r   r"   r7   r8   r9   r
   r:   r   r   r;   r<   r?   r   Úduration_daysr>   Úend_dater@   rA   )r%   rC   rE   rF   Úexpected_endrH   s         r&   Ú)test_end_date_is_start_date_plus_durationzBInvestmentStartDateTests.test_end_date_is_start_date_plus_duration4   s·   € äÐ'Ó(ˆØ—;‘;×#Ñ# C¨(°FÐ);ÀFÐ#ÓKˆà×Ñ˜×-Ñ-¬v×/FÑ/FÔGÜ×'Ñ'×+Ñ+¨x¯}©}¸TÑ/BÐ+ÓCˆ
ð "×,Ñ,¬y¸j×>VÑ>VÔ/WÑWˆÜ˜×,Ñ,¨|Ñ;×JÑJÓLÓMˆ	Ø�‰˜	 1Ð&UÕVr)   c                óž  — t        d«      }| j                  j                  |ddid¬«      }| j                  j                  |ddid¬«      }| j                  j                  |ddid¬«      }t        j                  j                  |j                  d   ¬	«      }t        j                  j                  |j                  d   ¬	«      }t        j                  j                  |j                  d   ¬	«      }|||fD ]S  }|j                  t        d
¬«      z   }	t        |j                  |	z
  j                  «       «      }
| j                  |
d
«       ŒU y)zOStandard: Multiple investments created same day each get start_date = next day.r+   r,   Ú100r.   r/   Ú500r-   r1   r2   r3   r4   N)r   r"   r7   r   r   r;   r<   r=   r   r>   r?   r@   rA   )r%   rC   Ú	response1Ú	response2Ú	response3Úinv1Úinv2Úinv3ÚinvrG   rH   s              r&   Ú:test_multiple_investments_same_day_independent_start_dateszSInvestmentStartDateTests.test_multiple_investments_same_day_independent_start_datesA   s%  € äÐ'Ó(ˆð —K‘K×$Ñ$ S¨8°UÐ*;ÀFÐ$ÓKˆ	Ø—K‘K×$Ñ$ S¨8°UÐ*;ÀFÐ$ÓKˆ	Ø—K‘K×$Ñ$ S¨8°VÐ*<ÀVÐ$ÓLˆ	ä×!Ñ!×%Ñ%¨¯©¸Ñ)=Ð%Ó>ˆÜ×!Ñ!×%Ñ%¨¯©¸Ñ)=Ð%Ó>ˆÜ×!Ñ!×%Ñ%¨¯©¸Ñ)=Ð%Ó>ˆð ˜$ Ó%ˆCØ Ÿ^™^¬i¸QÔ.?Ñ?ˆNÜ˜SŸ^™^¨nÑ<×KÑKÓMÓNˆIØ�O‰O˜I qÕ)ñ &r)   c           	     ó<  — t        d«      }g d¢}g d¢}t        ||«      D ]ú  \  }}| j                  j                  |d|id¬«      }| j	                  |j
                  t        j                  d|› d|j                  › �«       t        j                  j                  |j                  d	   ¬
«      }| j	                  |j                  |«       |j                  t        d¬«      z   }t        |j                   |z
  j#                  «       «      }	| j%                  |	d«       Œü y)zCStandard: All tiers use same start_date logic regardless of amount.r+   )Ú50r-   Ú10000)r3   é   é   r,   r.   r/   z(Failed to create investment with amount z: r1   r2   r3   r4   N)r   Úzipr"   r7   r8   r9   r
   r:   r<   r   r   r;   Útierr=   r   r>   r?   r@   rA   )
r%   rC   ÚamountsÚexpected_tiersr,   Úexpected_tierrE   rX   rG   rH   s
             r&   Ú*test_different_tiers_same_start_date_logiczCInvestmentStartDateTests.test_different_tiers_same_start_date_logicT   sù   € äÐ'Ó(ˆò *ˆÚ"ˆä%(¨°.Ö%AÑ!ˆF�MØ—{‘{×'Ñ'¨¨h¸Ð-?ÈÐ'ÓOˆHØ×Ñ˜X×1Ñ1´6×3JÑ3JØEÀfÀXÈRÐPX×P]ÑP]ÈÐ_ôaä×$Ñ$×(Ñ(¨H¯M©M¸$Ñ,?Ð(Ó@ˆCà×Ñ˜SŸX™X }Ô5Ø Ÿ^™^¬i¸QÔ.?Ñ?ˆNÜ˜SŸ^™^¨nÑ<×KÑKÓMÓNˆIØ�O‰O˜I qÕ)ñ &Br)   N©ÚreturnÚNone)	Ú__name__Ú
__module__Ú__qualname__Ú__doc__r'   rI   rN   rY   rd   © r)   r&   r   r      s    „ ÙLó
7òIò$Wò*ó&*r)   r   c                  ó0   — e Zd ZdZdd„Zd„ Zd„ Zd„ Zd„ Zy)	Ú InvestmentStartDateEdgeCaseTestsz0Edge case tests for investment start_date logic.c                ó$  — t         j                  j                  ddd¬«      | _        t	        d«      | j                  _        | j                  j                  «        t        «       | _        | j                  j                  | j                  ¬«       y)r   iŠ  ÚEdgeUserÚedgeuserr   ú10000.00000000r   Nr   r$   s    r&   r'   z&InvestmentStartDateEdgeCaseTests.setUpk   r(   r)   c                ó@  — t        j                  «       j                  dddd¬«      }t        j                  t        d«      «      }t        j                  j                  | j                  t        d«      |d   |d   |d   t        j                  |t        d¬«      z   |t        d¬«      z   t        |d   ¬«      z   ¬	«      }||_        |j                  «        |t        d¬«      z   }| j                  |j                  j                  «       |j                  «       «       y
)z-Edge: Investment created at exactly 00:00:00.r   ©ÚhourÚminuteÚsecondÚmicrosecondr-   r`   ÚrateÚdurationr3   r4   ©r   r,   r`   Údaily_reward_raterK   r
   r?   rL   N)r	   r6   Úreplacer   Úget_tier_infor   r   Úcreater   ÚSTATUS_PENDINGr   r=   r!   r8   r?   r   )r%   ÚmidnightÚ	tier_inforF   rG   s        r&   Ú#test_investment_created_at_midnightzDInvestmentStartDateEdgeCaseTests.test_investment_created_at_midnightw   sø   € ô —<‘<“>×)Ñ)¨q¸À1ÐRSÐ)ÓTˆÜ×,Ñ,¬W°V«_Ó=ˆ	ä×'Ñ'×.Ñ.Ø—‘Ü˜6“?Ø˜6Ñ"Ø'¨Ñ/Ø# JÑ/Ü×,Ñ,Ø¤)°Ô"3Ñ3Ø¤	¨qÔ 1Ñ1´IÀ9ÈZÑCXÔ4YÑYð /ó 	
ˆ
ð !)ˆ
ÔØ�‰Ôð "¤I°1Ô$5Ñ5ˆØ×Ñ˜×.Ñ.×3Ñ3Ó5°~×7JÑ7JÓ7LÕMr)   c                óÚ  — t        d«      }| j                  j                  |ddid¬«      }t        j                  j                  |j                  d   ¬«      }|j                  t        d¬	«      z   }t        |j                  |z
  j                  «       «      }| j                  |d«       | j                  |j                  j                  «       |j                  j                  «       «       y
)z%Edge: Investment created at 23:59:59.r+   r,   r-   r.   r/   r1   r2   r3   r4   N)r   r"   r7   r   r   r;   r<   r=   r   r>   r?   r@   rA   ÚassertNotEqualr   ©r%   rC   rE   rF   rG   rH   s         r&   Ú,test_investment_created_just_before_midnightzMInvestmentStartDateEdgeCaseTests.test_investment_created_just_before_midnightŽ   sÄ   € ô Ð'Ó(ˆØ—;‘;×#Ñ# C¨(°FÐ);ÀFÐ#ÓKˆä×'Ñ'×+Ñ+¨x¯}©}¸TÑ/BÐ+ÓCˆ
ð $×.Ñ.´ÀÔ1BÑBˆÜ˜×.Ñ.°Ñ?×NÑNÓPÓQˆ	Ø�‰˜	 1Ô%ð 	×Ñ˜J×1Ñ1×6Ñ6Ó8¸*×:OÑ:O×:TÑ:TÓ:VÕWr)   c                ó  — t        d«      }t        d«      | j                  _        | j                  j	                  «        | j
                  j                  |ddid¬«      }| j                  |j                  t        j                  «       t        j                  j                  |j                  d   ¬«      }|j                  t!        d	¬
«      z   }t#        |j$                  |z
  j'                  «       «      }| j)                  |d	«       y)z:Edge: Minimum investment ($10) uses same start_date logic.r+   z10.00000000r,   Ú10r.   r/   r1   r2   r3   r4   N)r   r   r   r    r!   r"   r7   r8   r9   r
   r:   r   r   r;   r<   r=   r   r>   r?   r@   rA   r†   s         r&   Ú)test_minimum_investment_amount_start_datezJInvestmentStartDateEdgeCaseTests.test_minimum_investment_amount_start_datež   sË   € äÐ'Ó(ˆÜ#*¨=Ó#9ˆ�	‰	Ô Ø�	‰	�‰Ôà—;‘;×#Ñ# C¨(°DÐ)9À&Ð#ÓIˆà×Ñ˜×-Ñ-¬v×/FÑ/FÔGÜ×'Ñ'×+Ñ+¨x¯}©}¸TÑ/BÐ+ÓCˆ
à#×.Ñ.´ÀÔ1BÑBˆÜ˜×.Ñ.°Ñ?×NÑNÓPÓQˆ	Ø�‰˜	 1Õ%r)   c                óŽ  — t        d«      }| j                  j                  |ddid¬«      }t        j                  j                  |j                  d   ¬«      }| j                  |j                  d«       |j                  t        d	¬
«      z   }t        |j                  |z
  j                  «       «      }| j                  |d	«       y)z;Edge: Large investment (tier 6) uses same start_date logic.r+   r,   r\   r.   r/   r1   r2   r^   r3   r4   N)r   r"   r7   r   r   r;   r<   r8   r`   r=   r   r>   r?   r@   rA   r†   s         r&   Ú'test_maximum_tier_investment_start_datezHInvestmentStartDateEdgeCaseTests.test_maximum_tier_investment_start_date­   s¤   € äÐ'Ó(ˆØ—;‘;×#Ñ# C¨(°GÐ)<ÀVÐ#ÓLˆä×'Ñ'×+Ñ+¨x¯}©}¸TÑ/BÐ+ÓCˆ
Ø×Ñ˜Ÿ™¨!Ô,à#×.Ñ.´ÀÔ1BÑBˆÜ˜×.Ñ.°Ñ?×NÑNÓPÓQˆ	Ø�‰˜	 1Õ%r)   Nre   )	rh   ri   rj   rk   r'   rƒ   r‡   rŠ   rŒ   rl   r)   r&   rn   rn   h   s    „ Ù:ó
7òNò.Xò &ó
&r)   rn   c                  ó0   — e Zd ZdZdd„Zd„ Zd„ Zd„ Zd„ Zy)	ÚRewardCalculationTimingTestsz:Standard tests for reward calculation based on start_date.c                óº   — t         j                  j                  ddd¬«      | _        t	        d«      | j                  _        | j                  j                  «        y)z Set up test user and investment.i‹  Ú
RewardUserÚ
rewarduserr   rr   N©r   r   r   r   r   r    r!   r$   s    r&   r'   z"RewardCalculationTimingTests.setUp½   sH   € ä—L‘L×,Ñ,Ø!Ø#Ø!ð -ó 
ˆŒ	ô
 $+Ð+;Ó#<ˆ�	‰	Ô Ø�	‰	�‰Õr)   c                ó®  — t        j                  «       }|j                  dddd¬«      }t        j                  t        d«      «      }t        j                  j                  | j                  t        d«      |d   |d   |d   t        j                  |t        d¬	«      z   |t        d¬	«      z   t        |d   ¬	«      z   ¬
«      }||_        |j                  «        |j                  «       }t        |«      }|j                  |«      }| j!                  |d«       | j!                  t"        j                  j%                  |¬«      j'                  «       d«       y)zCStandard: No rewards calculated for investment on its creation day.é   r   rt   r-   r`   ry   rz   r3   r4   r{   ©rF   N©r	   r6   r}   r   r~   r   r   r   r   r€   r   r=   r!   r   r   Ú_calculate_pending_rewardsr8   r   ÚfilterÚcount)r%   r6   Úcreation_dater‚   rF   Útarget_dateÚtaskr™   s           r&   Útest_no_reward_on_creation_dayz;RewardCalculationTimingTests.test_no_reward_on_creation_dayÇ   s(  € ô �l‰l‹nˆØŸ™¨°A¸aÈQ˜ÓOˆä×,Ñ,¬W°V«_Ó=ˆ	Ü×'Ñ'×.Ñ.Ø—‘Ü˜6“?Ø˜6Ñ"Ø'¨Ñ/Ø# JÑ/Ü×,Ñ,Ø$¤y°aÔ'8Ñ8Ø"¤Y°AÔ%6Ñ6¼È	ÐR\ÑH]Ô9^Ñ^ð /ó 	
ˆ
ð !.ˆ
ÔØ�‰Ôð $×(Ñ(Ó*ˆÜ# KÓ0ˆØ×/Ñ/°Ó<ˆð 	×Ñ˜ Ô"Ø×ÑœŸ™×.Ñ.¸*Ð.ÓE×KÑKÓMÈqÕQr)   c                ót  — t        j                  «       }|j                  dddd¬«      }|t        d¬«      z   }t	        j
                  t        d«      «      }t        j                  j                  | j                  t        d«      |d   |d   |d	   t        j                  ||t        |d	   ¬«      z   ¬
«      }||_        |j                  «        |j                  «       }t        |«      }|j                  |«      }| j!                  |d«       |t        d¬«      z   j                  «       }t        |«      }|j                  |«      }| j!                  |d«       t"        j                  j%                  |¬«      }	| j!                  |	j&                  |«       | j!                  |	j(                  t        d«      «       y)z;Standard: First reward calculated the day AFTER start_date.r”   r   rt   r3   r4   r-   r`   ry   rz   r{   r•   z20.00000000N)r	   r6   r}   r   r   r~   r   r   r   r   r€   r=   r!   r   r   r—   r8   r   r;   Úreward_dater,   )
r%   r6   rš   r?   r‚   rF   r›   rœ   r™   Úrewards
             r&   Útest_first_reward_on_start_datez<RewardCalculationTimingTests.test_first_reward_on_start_dateä   s}  € ô �l‰l‹nˆØŸ™¨°A¸aÈQ˜ÓOˆØ"¤Y°AÔ%6Ñ6ˆ
ä×,Ñ,¬W°V«_Ó=ˆ	Ü×'Ñ'×.Ñ.Ø—‘Ü˜6“?Ø˜6Ñ"Ø'¨Ñ/Ø# JÑ/Ü×,Ñ,Ø!Ø¤)°¸:Ñ1FÔ"GÑGð /ó 	
ˆ
ð !.ˆ
ÔØ�‰Ôð !—o‘oÓ'ˆÜ# KÓ0ˆØ×/Ñ/°Ó<ˆØ×Ñ˜ Ô"ð "¤I°1Ô$5Ñ5×;Ñ;Ó=ˆÜ# KÓ0ˆØ×/Ñ/°Ó<ˆØ×Ñ˜ Ô"Ü—‘×#Ñ#¨zÐ#Ó:ˆØ×Ñ˜×+Ñ+¨[Ô9Ø×Ñ˜Ÿ™¬°Ó(>Õ?r)   c                ój  — t        j                  «       j                  dddd¬«      }t        j                  t        d«      «      }t        j                  j                  | j                  t        d«      |d   |d   |d   t        j                  |t        d¬	«      z   |t        d¬	«      z   t        |d   ¬	«      z   ¬
«      }||_        |j                  «        t        |j                  «       «      }|j                  |j                  «       «      }| j!                  |d«       |t        d¬	«      z   j                  «       }t        |«      }|j                  |«      }| j!                  |d«       | j!                  t"        j                  j%                  |¬«      j'                  «       d«       |t        d¬	«      z   j                  «       }t        |«      }|j                  |«      }| j!                  |d«       | j!                  t"        j                  j%                  |¬«      j'                  «       d«       y)z@Standard: Complete workflow from creation through multiple days.r”   r   rt   r-   r`   ry   rz   r3   r4   r{   r•   é   N)r	   r6   r}   r   r~   r   r   r   r   r€   r   r=   r!   r   r   r—   r8   r   r˜   r™   )r%   Ú	base_timer‚   rF   rœ   r™   Ú	day2_dateÚ	day3_dates           r&   Ú test_reward_calculation_workflowz=RewardCalculationTimingTests.test_reward_calculation_workflow  s×  € ô —L‘L“N×*Ñ*°¸1ÀQÐTUÐ*ÓVˆ	Ü×,Ñ,¬W°V«_Ó=ˆ	ä×'Ñ'×.Ñ.Ø—‘Ü˜6“?Ø˜6Ñ"Ø'¨Ñ/Ø# JÑ/Ü×,Ñ,Ø ¤9°!Ô#4Ñ4Ø¤°Ô!2Ñ2´YÀIÈjÑDYÔ5ZÑZð /ó 	
ˆ
ð !*ˆ
ÔØ�‰Ôô $ I§N¡NÓ$4Ó5ˆØ×/Ñ/°	·±Ó0@ÓAˆØ×Ñ˜ Ô"ð ¤°Ô!2Ñ2×8Ñ8Ó:ˆ	Ü# IÓ.ˆØ×/Ñ/°	Ó:ˆØ×Ñ˜ Ô"Ø×ÑœŸ™×.Ñ.¸*Ð.ÓE×KÑKÓMÈqÔQð ¤°Ô!2Ñ2×8Ñ8Ó:ˆ	Ü# IÓ.ˆØ×/Ñ/°	Ó:ˆØ×Ñ˜ Ô"Ø×ÑœŸ™×.Ñ.¸*Ð.ÓE×KÑKÓMÈqÕQr)   c                ój  — t        j                  «       j                  dddd¬«      }t        j                  t        d«      «      }t        j                  j                  | j                  t        d«      |d   |d   |d   t        j                  |t        d¬	«      z   |t        d¬	«      z   t        |d   ¬	«      z   ¬
«      }||_        |j                  «        t        j                  t        d«      «      }t        j                  j                  | j                  t        d«      |d   |d   |d   t        j                  |t        d¬	«      z   |t        d¬	«      z   t        |d   ¬	«      z   ¬
«      }|t        d¬	«      z   |_        |j                  «        |t        d¬	«      z   j                  «       }t        |«      }|j                  |«       | j!                  t"        j                  j%                  |¬«      j'                  «       d«       | j!                  t"        j                  j%                  |¬«      j'                  «       d«       |t        d¬	«      z   j                  «       }t        |«      }|j                  |«       | j!                  t"        j                  j%                  |¬«      j'                  «       d«       | j!                  t"        j                  j%                  |¬«      j'                  «       d«       |t        d¬	«      z   j                  «       }	t        |	«      }|j                  |	«       | j!                  t"        j                  j%                  |¬«      j'                  «       d«       | j!                  t"        j                  j%                  |¬«      j'                  «       d«       y)zMStandard: Multiple investments created on different days calculate correctly.r”   r   rt   rQ   r`   ry   rz   r3   r4   r{   r-   r]   r£   r•   Nr–   )
r%   r¤   r‚   rU   Ú
tier_info2rV   Úday1rœ   Úday2Úday3s
             r&   Ú(test_multiple_investments_correct_timingzERewardCalculationTimingTests.test_multiple_investments_correct_timing.  sú  € ä—L‘L“N×*Ñ*°¸1ÀQÐTUÐ*ÓVˆ	ô ×,Ñ,¬W°U«^Ó<ˆ	Ü×!Ñ!×(Ñ(Ø—‘Ü˜5“>Ø˜6Ñ"Ø'¨Ñ/Ø# JÑ/Ü×,Ñ,Ø ¤9°!Ô#4Ñ4Ø¤°Ô!2Ñ2´YÀIÈjÑDYÔ5ZÑZð )ó 	
ˆð $ˆŒØ�	‰	Œô  ×-Ñ-¬g°f«oÓ>ˆ
Ü×!Ñ!×(Ñ(Ø—‘Ü˜6“?Ø˜FÑ#Ø(¨Ñ0Ø$ ZÑ0Ü×,Ñ,Ø ¤9°!Ô#4Ñ4Ø¤°Ô!2Ñ2´YÀJÈzÑDZÔ5[Ñ[ð )ó 	
ˆð $¤i°QÔ&7Ñ7ˆŒØ�	‰	Œð œI¨1Ô-Ñ-×3Ñ3Ó5ˆÜ# DÓ)ˆØ×'Ñ'¨Ô-Ø×ÑœŸ™×.Ñ.¸$Ð.Ó?×EÑEÓGÈÔKØ×ÑœŸ™×.Ñ.¸$Ð.Ó?×EÑEÓGÈÔKð œI¨1Ô-Ñ-×3Ñ3Ó5ˆÜ# DÓ)ˆØ×'Ñ'¨Ô-Ø×ÑœŸ™×.Ñ.¸$Ð.Ó?×EÑEÓGÈÔKØ×ÑœŸ™×.Ñ.¸$Ð.Ó?×EÑEÓGÈÔKð œI¨1Ô-Ñ-×3Ñ3Ó5ˆÜ# DÓ)ˆØ×'Ñ'¨Ô-Ø×ÑœŸ™×.Ñ.¸$Ð.Ó?×EÑEÓGÈÔKØ×ÑœŸ™×.Ñ.¸$Ð.Ó?×EÑEÓGÈÕKr)   Nre   )	rh   ri   rj   rk   r'   r�   r¡   r§   r­   rl   r)   r&   rŽ   rŽ   º   s$   „ ÙDóòRò:"@òH$RóL7Lr)   rŽ   c                  ó*   — e Zd ZdZdd„Zd„ Zd„ Zd„ Zy)ÚRewardCalculationEdgeCaseTestsz.Edge case tests for reward calculation timing.c                óº   — t         j                  j                  ddd¬«      | _        t	        d«      | j                  _        | j                  j                  «        y)zSet up test user.iŒ  ÚEdgeRewardUserÚedgerewarduserr   rr   Nr’   r$   s    r&   r'   z$RewardCalculationEdgeCaseTests.setUpk  sH   € ä—L‘L×,Ñ,Ø!Ø'Ø%ð -ó 
ˆŒ	ô
 $+Ð+;Ó#<ˆ�	‰	Ô Ø�	‰	�‰Õr)   c                ó0  — t        j                  «       }t        j                  t	        d«      «      }t        j
                  j                  | j                  t	        d«      |d   |d   dt        j                  ||t        d¬«      z   ¬«      }|j                  «       }t        |«      }|j                  |«      }| j                  |d«       |t        d¬«      z   j                  «       }t        |«      }|j                  |«      }| j                  |d«       y)	zOEdge: Investment with 1-day duration gets 1 reward on the day after start_date.r-   r`   ry   r3   r4   r{   r   N)r	   r6   r   r~   r   r   r   r   r€   r   r   r   r—   r8   )r%   r6   r‚   rF   r›   rœ   r™   Úend_target_dates           r&   Ú$test_investment_expiring_on_last_dayzCRewardCalculationEdgeCaseTests.test_investment_expiring_on_last_dayu  só   € ä�l‰l‹nˆÜ×,Ñ,¬W°V«_Ó=ˆ	ô
  ×'Ñ'×.Ñ.Ø—‘Ü˜6“?Ø˜6Ñ"Ø'¨Ñ/ØÜ×,Ñ,ØØœ9¨!Ô,Ñ,ð /ó 	
ˆ
ð —h‘h“jˆÜ# KÓ0ˆØ×/Ñ/°Ó<ˆØ×Ñ˜ Ô"ð ¤°Ô!2Ñ2×8Ñ8Ó:ˆÜ# OÓ4ˆØ×/Ñ/°Ó@ˆØ×Ñ˜ Õ"r)   c                ó¸  — t        j                  «       }|t        d¬«      z
  }t        j                  t        d«      «      }t        j                  j                  | j                  t        d«      |d   |d   dt        j                  ||t        d¬«      z   ¬«      }|j                  «       }t        |«      }|j                  |«      }| j                  |d«       y	)
z8Edge: Investment past end_date doesn't generate rewards.é
   r4   r-   r`   ry   é   r{   r   N)r	   r6   r   r   r~   r   r   r   r   ÚSTATUS_ACTIVEr   r   r—   r8   )r%   r6   Ú	past_dater‚   rF   r›   rœ   r™   s           r&   Ú)test_investment_beyond_end_date_no_rewardzHRewardCalculationEdgeCaseTests.test_investment_beyond_end_date_no_reward”  sÀ   € ä�l‰l‹nˆØœ)¨Ô,Ñ,ˆ	Ü×,Ñ,¬W°V«_Ó=ˆ	ô  ×'Ñ'×.Ñ.Ø—‘Ü˜6“?Ø˜6Ñ"Ø'¨Ñ/ØÜ×+Ñ+Ø Ø¤°Ô!2Ñ2ð /ó 	
ˆ
ð —h‘h“jˆÜ# KÓ0ˆØ×/Ñ/°Ó<ˆð 	×Ñ˜ Õ"r)   c                óÞ  — t        j                  «       }|j                  dddd¬«      }|j                  «       }t	        j
                  t        d«      «      }t        j                  j                  | j                  t        d«      |d   |d   |d   t        j                  ||t        |d   ¬«      z   ¬«      }t        |«      }|j                  |«      }| j                  |d«       |t        d	¬«      z   j                  «       }t        |«      }|j                  |«      }| j                  |d	«       t        j                  j!                  |¬
«      }	| j                  |	j"                  |«       y)zPEdge: Boundary condition where start_date.date() == target_date - no reward yet.r   rt   r-   r`   ry   rz   r4   r{   r3   r•   N)r	   r6   r}   r   r   r~   r   r   r   r   r€   r   r   r—   r8   r   r;   rŸ   )
r%   r6   Ústart_datetimer›   r‚   rF   rœ   r™   Ú	next_dater    s
             r&   Ú+test_start_date_equals_target_date_boundaryzJRewardCalculationEdgeCaseTests.test_start_date_equals_target_date_boundary®  sA  € ä�l‰l‹nˆàŸ™¨!°A¸aÈQ˜ÓOˆØ$×)Ñ)Ó+ˆä×,Ñ,¬W°V«_Ó=ˆ	Ü×'Ñ'×.Ñ.Ø—‘Ü˜6“?Ø˜6Ñ"Ø'¨Ñ/Ø# JÑ/Ü×,Ñ,Ø%Ø#¤i°Y¸zÑ5JÔ&KÑKð /ó 	
ˆ
ô $ KÓ0ˆØ×/Ñ/°Ó<ˆØ×Ñ˜ Ô"ð $¤i°QÔ&7Ñ7×=Ñ=Ó?ˆ	Ü# IÓ.ˆØ×/Ñ/°	Ó:ˆØ×Ñ˜ Ô"Ü—‘×#Ñ#¨zÐ#Ó:ˆØ×Ñ˜×+Ñ+¨YÕ7r)   Nre   )rh   ri   rj   rk   r'   rµ   r»   r¿   rl   r)   r&   r¯   r¯   h  s   „ Ù8óò#ò>#ó48r)   r¯   N)rk   Ú
__future__r   Údatetimer   r   Údecimalr   Údjango.testr   Údjango.urlsr   Údjango.utilsr	   Úrest_frameworkr
   Úrest_framework.testr   r   Úapps.investments.cron_tasksr   Úapps.investments.modelsr   r   Úapps.users.modelsr   r   rn   rŽ   r¯   rl   r)   r&   Ú<module>rË      sf   ðÙ Jå "ç $Ý å  Ý Ý !Ý !ß 6å <ß 6Ý "ôR*˜{ô R*ôjO& {ô O&ôdkL 8ô kLô\d8 Xõ d8r)   