Ë
    ÊBiÚ  ã                   óª   — d 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mZmZmZ ddlmZmZ dd	lmZ dd
lmZ ddlmZ  G d„ de«      Zy)z1Tests for the individual cron tasks (R001, D001).é    )ÚdateÚ	timedelta)ÚDecimal)ÚTestCase)Útimezone)ÚCronExecution)ÚCalculateRewardsTaskÚDistributeRewardsTaskÚCALCULATE_TASK_CODEÚDISTRIBUTE_TASK_CODE)Ú
InvestmentÚReward)Ú
Commission)ÚTransaction)ÚUserc                   ó6   — e Zd Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Z	y)	ÚCronTasksTestc                 óˆ  — t         j                  j                  ddd¬«      | _        t         j                  j                  ddd| j                  ¬«      | _        t        j                  «       }|t        d	¬
«      z
  | _        t        j                  t        d«      «      }t        j                  j                  | j                  t        d«      |d   |d   |d   t        j                  | j                  | j                  t        d¬
«      z   ¬«      | _        | j                  j                  «       t        d¬
«      z   | _        y )Nié  ÚUplineÚupline)Útelegram_user_idÚ
first_nameÚusernameiÑ  ÚDownlineÚdownline)r   r   r   Úreferred_byé   ©ÚdaysÚ1000ÚtierÚrateÚdurationéx   ©ÚuserÚamountr!   Údaily_reward_rateÚduration_daysÚstatusÚ
start_dateÚend_dateé   )r   ÚobjectsÚcreate_userr   r   r   Únowr   r+   r   Úget_tier_infor   ÚcreateÚSTATUS_ACTIVEÚ
investmentr   Útarget_date)Úselfr0   Ú	tier_infos      úW/home/cursorai/projects/telegram-earn/backend/apps/investments/tests/test_cron_tasks.pyÚsetUpzCronTasksTest.setUp   s  € ä—l‘l×.Ñ.Ø!¨hÀð /ó 
ˆŒô Ÿ™×0Ñ0Ø!Ø!ØØŸ™ð	 1ó 
ˆŒô �l‰l‹nˆà¤	¨qÔ 1Ñ1ˆŒÜ×,Ñ,¬W°V«_Ó=ˆ	Ü$×,Ñ,×3Ñ3Ø—‘Ü˜6“?Ø˜6Ñ"Ø'¨Ñ/Ø# JÑ/Ü×+Ñ+Ø—‘Ø—_‘_¤y°cÔ':Ñ:ð 4ó 	
ˆŒð  Ÿ?™?×/Ñ/Ó1´IÀ1Ô4EÑEˆÕó    c                 óR  — t        | j                  «      }|j                  «       }| j                  |j                  «       t
        j                  j                  | j                  | j                  ¬«      }| j                  |j                  t        d«      «       | j                  |j                  «       | j                  j                  «        | j                  | j                  j                  t         j"                  «       | j%                  t&        j                  j)                  «       «       | j%                  t*        j                  j)                  «       «       t,        j                  j                  t.        | j                  ¬«      }| j                  |j                  «       y)z3R001 should create rewards but NOT distribute them.©r4   Úreward_datez20.00000000)Ú	task_codeÚexecution_dateN)r	   r5   ÚrunÚ
assertTrueÚsuccessr   r.   Úgetr4   ÚassertEqualr'   r   ÚassertIsNoneÚdistributed_atÚrefresh_from_dbr*   r   r3   ÚassertFalser   Úexistsr   r   r   )r6   ÚtaskÚresultÚrewardÚ	executions        r8   Ú+test_calculate_task_creates_pending_rewardsz9CronTasksTest.test_calculate_task_creates_pending_rewards8   s+  € ä# D×$4Ñ$4Ó5ˆØ—‘“ˆà�‰˜Ÿ™Ô'ô —‘×#Ñ#¨t¯©ÈD×L\ÑL\Ð#Ó]ˆØ×Ñ˜Ÿ™¬°Ó(>Ô?Ø×Ñ˜&×/Ñ/Ô0ð 	�‰×'Ñ'Ô)Ø×Ñ˜Ÿ™×/Ñ/´×1IÑ1IÔJð 	×Ñœ×+Ñ+×2Ñ2Ó4Ô5ð 	×Ñœ×,Ñ,×3Ñ3Ó5Ô6ô "×)Ñ)×-Ñ-Ü)¸$×:JÑ:Jð .ó 
ˆ	ð 	�‰˜	×)Ñ)Õ*r:   c                 ó„   — t        | j                  «      }|j                  «       }| j                  |j                  «       y)zHD001 should fail/skip if R001 hasn't run successfully for the same date.N)r
   r5   r@   rA   Úskipped)r6   rJ   rK   s      r8   Ú0test_distribute_task_skips_if_calculate_not_donez>CronTasksTest.test_distribute_task_skips_if_calculate_not_doneT   s1   € ä$ T×%5Ñ%5Ó6ˆð —‘“ˆð 	�‰˜Ÿ™Õ'r:   c                 óü  — t        | j                  «      }|j                  «        t        j                  j                  | j                  | j                  ¬«      }| j                  |j                  «       t        | j                  «      }|j                  «       }| j                  |j                  «       | j                  |j                  «       |j                  «        | j                  |j                  «       t         j                  j#                  | j$                  t         j&                  ¬«      j)                  «       }| j                  |«       | j+                  |j,                  |j,                  «       t.        j                  j#                  |¬«      j)                  «       }| j                  |«       | j+                  |j0                  d«       | j+                  |j2                  | j4                  «       | j+                  |j6                  t.        j8                  «       t         j                  j#                  | j4                  t         j:                  ¬«      j)                  «       }| j                  |«       y)z=D001 should distribute rewards if R001 success record exists.r<   )r&   Útransaction_type)rL   r-   N)r	   r5   r@   r   r.   rC   r4   rE   rF   r
   rA   rB   rH   rP   rG   ÚassertIsNotNoner   Úfilterr   ÚTYPE_REWARDÚfirstrD   r'   r   ÚlevelÚupline_userr   r*   ÚSTATUS_DISTRIBUTEDÚTYPE_COMMISSION)r6   Ú	calc_taskrL   Ú	dist_taskrK   ÚtxÚcommÚctxs           r8   Ú:test_distribute_task_distributes_rewards_after_calculationzHCronTasksTest.test_distribute_task_distributes_rewards_after_calculationa   sÕ  € ô )¨×)9Ñ)9Ó:ˆ	Ø�‰Œô —‘×#Ñ#¨t¯©ÈD×L\ÑL\Ð#Ó]ˆØ×Ñ˜&×/Ñ/Ô0ô *¨$×*:Ñ*:Ó;ˆ	Ø—‘“ˆà�‰˜Ÿ™Ô'Ø×Ñ˜Ÿ™Ô(ð 	×ÑÔ Ø×Ñ˜V×2Ñ2Ô3ô × Ñ ×'Ñ'Ø—‘´×1HÑ1Hð (ó 
ç
‰%‹'ð 	ð 	×Ñ˜RÔ Ø×Ñ˜Ÿ™ F§M¡MÔ2ô ×!Ñ!×(Ñ(°Ð(Ó7×=Ñ=Ó?ˆØ×Ñ˜TÔ"Ø×Ñ˜Ÿ™ QÔ'Ø×Ñ˜×)Ñ)¨4¯;©;Ô7Ø×Ñ˜Ÿ™¤j×&CÑ&CÔDô ×!Ñ!×(Ñ(Ø—‘¬{×/JÑ/Jð )ó 
ç
‰%‹'ð 	ð 	×Ñ˜SÕ!r:   c                 ó8  — t        | j                  «      }|j                  «        t        j                  j                  «       j                  «        |j                  | j                  «       | j                  t        j                  j                  «       d«       y)z8R001 should not duplicate rewards if run multiple times.r-   N)r	   r5   r@   r   r.   ÚallÚdeleteÚexecuterD   r   Úcount)r6   rJ   s     r8   Útest_calculate_task_idempotencyz-CronTasksTest.test_calculate_task_idempotencyŠ   si   € ä# D×$4Ñ$4Ó5ˆØ�‰Œ
ô 	×Ñ×!Ñ!Ó#×*Ñ*Ô,ð 	�‰�T×%Ñ%Ô&à×ÑœŸ™×-Ñ-Ó/°Õ3r:   c                 ó€  — t        | j                  «      j                  «        t        | j                  «      j                  «        t        j
                  j                  «       }| j                  |j                  «       t        j
                  j                  «       }t        | j                  «      }t        j
                  j                  t        ¬«      j                  «        |j                  «       }| j                  d|j                   «       | j#                  t        j
                  j                  «       |«       y)z:D001 should not re-distribute already distributed rewards.)r>   zDistributed 0 rewardsN)r	   r5   r@   r
   r   r.   rW   rT   rF   r   rf   r   rU   r   rd   ÚassertInÚmessagerD   )r6   rL   Úinitial_tx_countrJ   rK   s        r8   Ú test_distribute_task_idempotencyz.CronTasksTest.test_distribute_task_idempotency˜   sâ   € ô 	˜T×-Ñ-Ó.×2Ñ2Ô4Ü˜d×.Ñ.Ó/×3Ñ3Ô5ô —‘×%Ñ%Ó'ˆØ×Ñ˜V×2Ñ2Ô3Ü&×.Ñ.×4Ñ4Ó6Ðô % T×%5Ñ%5Ó6ˆÜ×Ñ×$Ñ$Ô/CÐ$ÓD×KÑKÔMà—‘“ˆð 	�‰Ð-¨v¯~©~Ô>Ø×Ñœ×,Ñ,×2Ñ2Ó4Ð6FÕGr:   c                 ó$  — t         j                  j                  | j                  t	        d«      dddt         j
                  | j                  t        d¬«      z
  | j                  ¬«      }t        | j                  «      }|j                  «        |j                  «        | j                  |j                  t         j                  «       | j                  t        j                  j!                  || j                  ¬«      j#                  «       «       y)z;Investment should be marked pending -> active -> completed.Ú100r-   g      ð?r   r%   r<   N)r   r.   r2   r   r   ÚSTATUS_PENDINGr5   r   r	   r@   rG   rD   r*   ÚSTATUS_COMPLETEDrA   r   rU   rI   )r6   Ú	short_invrJ   s      r8   Ú test_investment_completion_logicz.CronTasksTest.test_investment_completion_logic­   sÒ   € ô ×&Ñ&×-Ñ-Ø—‘Ü˜5“>ØØ!ØÜ×,Ñ,Ø×'Ñ'¬)¸Ô*;Ñ;Ø×%Ñ%ð .ó 	
ˆ	ô $ D×$4Ñ$4Ó5ˆØ�‰Œ
à×!Ñ!Ô#Ø×Ñ˜×)Ñ)¬:×+FÑ+FÔGð 	�‰Ü�N‰N×!Ñ!¨YÀD×DTÑDTÐ!ÓU×\Ñ\Ó^õ	
r:   N)
Ú__name__Ú
__module__Ú__qualname__r9   rN   rQ   ra   rg   rl   rr   © r:   r8   r   r      s)   „ òFòB+ò8	(ò'"òR4òHó*
r:   r   N)Ú__doc__Údatetimer   r   Údecimalr   Údjango.testr   Údjango.utilsr   Údjango_cronjob_utils.modelsr   Úapps.investments.cron_tasksr	   r
   r   r   Úapps.investments.modelsr   r   Úapps.referrals.modelsr   Úapps.transactions.modelsr   Úapps.users.modelsr   r   rv   r:   r8   Ú<module>r‚      s=   ðÙ 7ç $Ý å  Ý !å 5÷ó ÷ 7Ý ,Ý 0Ý "ôr
�Hõ r
r:   