
    /j,                     R   d Z ddlZddlmc mZ ddlmZ ddl	Z	ddl
Z
ddlmZmZmZmZmZmZ ddddd	d
Zdddddd
Zdddd	dd
Z ed      Z G d d      Z G d d      Z G d d      Z G d d      Z G d d      Z G d d      Z G d  d!      Z G d" d#      Z G d$ d%      Zy)&u(   Amortization engine tests — Story 6.2.    N)Decimal)calculate_avalanchecalculate_snowballcalculate_highest_balancecalculate_proportionalcalculate_customAmortizationResult   Visa1000.0020.0025.00idnamebalanceaprmin_payment   
Mastercardz2000.0015.00z40.00   Discover500.00200.00c                   <    e Zd Zd Zd Zd Zd Zd Zd Zd Z	d Z
y	)
TestAmortizationResultStructurec                 x   t        t        gt        d            }t        |t              }|sddt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d }y )N505assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstanceresultr	   py0py1py2py4)r   CARD_Ar   r!   r	   @py_builtinslocals
@pytest_ar_should_repr_global_name	_safereprAssertionError_format_explanation)selfr"   @py_assert3@py_format5s       A/var/www/html/financials/tests/test_services/test_amortization.py test_returns_amortization_resultz@TestAmortizationResultStructure.test_returns_amortization_result   s    $fXwt}=&"455555555z555z555555&555&555555"4555"45555555555    c                 L   t        t        gt        d            }|j                  }t	        |t
              }|sddt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  t
              rt        j                  t
              ndt        j                  |      dz  }t        t        j                  |            d x}}|j                  }d}||k(  }|st        j                  d|fd	||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      d
z  }dd|iz  }	t        t        j                  |	            d x}x}}y )Nr   zSassert %(py6)s
{%(py6)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.strategy
}, %(py4)s)
}r!   r"   strr$   r%   py3r'   py6	avalanche==z0%(py2)s
{%(py2)s = %(py0)s.strategy
} == %(py5)sr$   r&   py5assert %(py7)spy7)r   r(   r   strategyr!   r7   r)   r*   r+   r,   r-   r.   r/   _call_reprcompare
r0   r"   @py_assert2@py_assert5@py_format7@py_assert1@py_assert4r1   @py_format6@py_format8s
             r3   test_strategy_name_is_stringz<TestAmortizationResultStructure.test_strategy_name_is_string   s   $fXwt}= ///z/3////////z///z//////&///&//////////3///3//////////-+-+----+------v---v------+-------r5   c                 L   t        t        gt        d            }|j                  }t	        |t
              }|sddt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  t
              rt        j                  t
              ndt        j                  |      dz  }t        t        j                  |            d x}}|j                  }d}||kD  }|st        j                  d|fd	||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      d
z  }dd|iz  }	t        t        j                  |	            d x}x}}y )Nr   z[assert %(py6)s
{%(py6)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.months_to_payoff
}, %(py4)s)
}r!   r"   intr8   r   >z7%(py2)s
{%(py2)s = %(py0)s.months_to_payoff
} > %(py5)sr?   rA   rB   )r   r(   r   months_to_payoffr!   rO   r)   r*   r+   r,   r-   r.   r/   rD   rE   s
             r3   test_months_to_payoff_is_intz<TestAmortizationResultStructure.test_months_to_payoff_is_int$   s&   $fXwt}= 117z1377777777z777z777777&777&7771777777377737777777777&&**&****&******v***v***&**********r5   c                    t        t        gt        d            }|j                  }t	        |t              }|sddt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d x}}y )Nr   z^assert %(py6)s
{%(py6)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.total_interest_paid
}, %(py4)s)
}r!   r"   r   r8   )r   r(   r   total_interest_paidr!   r)   r*   r+   r,   r-   r.   r/   )r0   r"   rF   rG   rH   s        r3   test_total_interest_is_decimalz>TestAmortizationResultStructure.test_total_interest_is_decimal)   s    $fXwt}= 44>z4g>>>>>>>>z>>>z>>>>>>&>>>&>>>4>>>>>>g>>>g>>>>>>>>>>r5   c           	          t        t        gt        d            }|j                  }t        j
                  }t        ||      }|s3ddt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        t        j                  |            d x}x}}y )Nr   zpassert %(py8)s
{%(py8)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.payoff_date
}, %(py6)s
{%(py6)s = %(py4)s.date
})
}r!   r"   datetime)r$   r%   r9   r'   r:   py8)r   r(   r   payoff_daterY   dater!   r)   r*   r+   r,   r-   r.   r/   )r0   r"   rF   rG   @py_assert7@py_format9s         r3   test_payoff_date_is_datez8TestAmortizationResultStructure.test_payoff_date_is_date-   s    $fXwt}= ,,<hmm<z,m<<<<<<<<z<<<z<<<<<<&<<<&<<<,<<<<<<h<<<h<<<m<<<<<<<<<<r5   c                 "   t        t        gt        d            }|j                  }t	        |t
              }|sddt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  t
              rt        j                  t
              ndt        j                  |      dz  }t        t        j                  |            d x}}|j                  }t        |      }d}||k(  }|s
t        j                  d|fd	||f      d
t        j                         v st        j                  t              rt        j                  t              nd
dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            d x}x}x}}y )Nr   z\assert %(py6)s
{%(py6)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.per_card_schedule
}, %(py4)s)
}r!   r"   listr8   r
   r<   )zW%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.per_card_schedule
})
} == %(py8)slen)r$   r%   r9   r@   rZ   zassert %(py10)spy10)r   r(   r   per_card_scheduler!   ra   r)   r*   r+   r,   r-   r.   r/   rb   rD   )
r0   r"   rF   rG   rH   rJ   r]   @py_assert6r^   @py_format11s
             r3   test_per_card_schedule_is_listz>TestAmortizationResultStructure.test_per_card_schedule_is_list1   s\   $fXwt}= 229z2D99999999z999z999999&999&9992999999D999D9999999999++1s+,11,1111,111111s111s11111161116111+111,1111111111r5   c                    t        t        gt        d            }|j                  d   }d}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }dd	|iz  }t        t	        j                  |            d x}}d
}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }dd	|iz  }t        t	        j                  |            d x}}d}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }dd	|iz  }t        t	        j                  |            d x}}d}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }dd	|iz  }t        t	        j                  |            d x}}d}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }dd	|iz  }t        t	        j                  |            d x}}d}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }dd	|iz  }t        t	        j                  |            d x}}y )Nr   r   
account_idinz%(py1)s in %(py3)scardr%   r9   assert %(py5)sr@   account_namepayoff_monthr[   total_interestschedule)r   r(   r   rd   r+   rD   r-   r)   r*   r,   r.   r/   )r0   r"   rm   @py_assert0rF   @py_format4rK   s          r3   (test_per_card_schedule_has_required_keyszHTestAmortizationResultStructure.test_per_card_schedule_has_required_keys6   s=   $fXwt}=''*#|t####|t###|######t###t#######%~%%%%~%%%~%%%%%%%%%%%%%%%%%~%%%%~%%%~%%%%%%%%%%%%%%%%$}$$$$}$$$}$$$$$$$$$$$$$$$$'4''''4'''''''''4'''4'''''''!zT!!!!zT!!!z!!!!!!T!!!T!!!!!!!r5   c                    t        t        gt        d            }|j                  d   d   d   }dD ]  }||v }|st	        j
                  d|fd||f      dt        j                         v st	        j                  |      rt	        j                  |      nddt        j                         v st	        j                  |      rt	        j                  |      ndd	z  }d
d|iz  }t        t	        j                  |            d } y )Nr   r   rs   )monthr\   payment	principalinterestr   rj   )z%(py0)s in %(py2)skeyrow)r$   r&   zassert %(py4)sr'   )r   r(   r   rd   r+   rD   r)   r*   r,   r-   r.   r/   )r0   r"   r}   r|   rI   @py_format3r2   s          r3   %test_schedule_rows_have_required_keyszETestAmortizationResultStructure.test_schedule_rows_have_required_keys@   s    $fXwt}=&&q)*5a8S 	C#:3#33##	r5   N)__name__
__module____qualname__r4   rM   rT   rW   r_   rg   rv   r    r5   r3   r   r      s*    6.
+
?=2
"r5   r   c                   "    e Zd ZdZd Zd Zd Zy)TestKnownScenariozESingle card: $1000 balance, 20% APR, $25 min, $0 extra => ~48 months.c           	         dddddd}t        |gt        d            }|j                  }d}||kD  }|st        j                  d	|fd
||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}|j                  d   d   d   }|d   }t        |      }d}	t        |	      }
||
k(  }|s&t        j                  d|fd||
f      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |	      t        j                  |
      dz  }dd|iz  }t        t        j                  |            d x}x}x}x}	}
y )Nr
   Ar   r   r   r   0r   rP   rR   r"   r?   rA   rB   rs   r   0.00r<   zP%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py10)s
{%(py10)s = %(py6)s(%(py8)s)
}r   r$   r&   r'   r:   rZ   rc   assert %(py12)spy12)r   r   rS   r+   rD   r)   r*   r,   r-   r.   r/   rd   )r0   rm   r"   rI   rJ   r1   rK   rL   last_rowr]   @py_assert9rG   rf   @py_format13s                 r3   $test_single_card_eventually_pays_offz6TestKnownScenario.test_single_card_eventually_pays_offL   so   7[bc$dVWS\:&&**&****&******v***v***&**********++A.z:2>	*>w*+>v>wv>+>>>>+>>>>>>w>>>w>>>*>>>+>>>>>>w>>>w>>>v>>>>>>>>>>>r5   c                    dddddd}t        |gt        d            }t        |gt        d            }|j                  }|j                  }||k  }|st        j                  d	|fd
||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}y )Nr
   r   r   r   r   r   r   100<)z]%(py2)s
{%(py2)s = %(py0)s.months_to_payoff
} < %(py6)s
{%(py6)s = %(py4)s.months_to_payoff
}r_with_extra
r_no_extrar$   r&   r'   r:   assert %(py8)srZ   )r   r   rS   r+   rD   r)   r*   r,   r-   r.   r/   	r0   rm   r   r   rI   rG   r1   rH   r^   s	            r3   &test_extra_payment_reduces_payoff_timez8TestKnownScenario.test_extra_payment_reduces_payoff_timeS   s    7[bc($>
*D675>B,,Jz/J/JJ,/JJJJJ,/JJJJJJJ|JJJ|JJJ,JJJJJJzJJJzJJJ/JJJJJJJJr5   c                    dddddd}t        |gt        d            }t        |gt        d            }|j                  }|j                  }||k  }|st        j                  d	|fd
||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}y )Nr
   r   r   r   r   r   r   r   r   )zc%(py2)s
{%(py2)s = %(py0)s.total_interest_paid
} < %(py6)s
{%(py6)s = %(py4)s.total_interest_paid
}r   r   r   r   rZ   )r   r   rV   r+   rD   r)   r*   r,   r-   r.   r/   r   s	            r3   #test_extra_payment_reduces_interestz5TestKnownScenario.test_extra_payment_reduces_interestY   s    7[bc($>
*D675>B//P*2P2PP/2PPPPP/2PPPPPPP|PPP|PPP/PPPPPP*PPP*PPP2PPPPPPPPr5   N)r   r   r   __doc__r   r   r   r   r5   r3   r   r   I   s    O?KQr5   r   c                       e Zd Zd Zd Zy)TestZeroExtrac           	         t        t        gt        d            }|j                  }d}||kD  }|st	        j
                  d|fd||f      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d x}x}}|j                  d   d	   d
   d   }t        |      }d}t        |      }||k(  }	|	s&t	        j
                  d|	fd||f      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      t	        j                  |      dz  }
dd|
iz  }t        t	        j                  |            d x}x}x}	x}}y )Nr   r   rP   rR   r"   r?   rA   rB   rs   r   r   r   r<   r   r   r   r   r   )r   r(   r   rS   r+   rD   r)   r*   r,   r-   r.   r/   rd   )r0   r"   rI   rJ   r1   rK   rL   r]   r   rG   rf   r   s               r3   "test_zero_extra_avalanche_pays_offz0TestZeroExtra.test_zero_extra_avalanche_pays_offc   sc   $fXws|<&&**&****&******v***v***&**********//2:>rB9MawMNaZ`aRYZ`RaaNRaaaaaNRaaaaaaawaaawaaaMaaaNaaaaaaRYaaaRYaaaZ`aaaRaaaaaaaaar5   c                    t        t        gt        d            }|j                  }d}||kD  }|st	        j
                  d|fd||f      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d x}x}}y )	Nr   r   rP   rR   r"   r?   rA   rB   )r   r(   r   rS   r+   rD   r)   r*   r,   r-   r.   r/   r0   r"   rI   rJ   r1   rK   rL   s          r3   !test_zero_extra_snowball_pays_offz/TestZeroExtra.test_zero_extra_snowball_pays_offh   s    #VHgcl;&&**&****&******v***v***&**********r5   N)r   r   r   r   r   r   r5   r3   r   r   b   s    b
+r5   r   c                   $    e Zd Zd Zd Zd Zd Zy)TestAvalancheVsSnowballc                    t        t        t        t        gt              }t        d |j                  D              }t        d |j                  D              }|d   }|d   }||k  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}y	)
zAWith extra money, avalanche should target CARD_C (25% APR) first.c              3   2   K   | ]  }|d    dk(  s|  ywri   r   Nr   .0cs     r3   	<genexpr>zVTestAvalancheVsSnowball.test_avalanche_directs_extra_to_highest_apr.<locals>.<genexpr>t        RAQ|_PQ=QaR   c              3   2   K   | ]  }|d    dk(  s|  yw)ri   r
   Nr   r   s     r3   r   zVTestAvalancheVsSnowball.test_avalanche_directs_extra_to_highest_apr.<locals>.<genexpr>u   r   r   rq   <=z%(py1)s <= %(py4)sr%   r'   assert %(py6)sr:   N)r   r(   CARD_BCARD_CEXTRAnextrd   r+   rD   r-   r.   r/   )	r0   r"   card_ccard_art   r1   rF   r2   rH   s	            r3   +test_avalanche_directs_extra_to_highest_aprzCTestAvalancheVsSnowball.test_avalanche_directs_extra_to_highest_aprp   s    $fff%=uER!9!9RRR!9!9RRn%?)??%)?????%)????%???)????????r5   c                    t        t        t        t        gt              }t        d |j                  D              }t        d |j                  D              }|d   }|d   }||k  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}y	)
z=With extra money, snowball should target CARD_C ($500) first.c              3   2   K   | ]  }|d    dk(  s|  ywr   r   r   s     r3   r   zXTestAvalancheVsSnowball.test_snowball_directs_extra_to_lowest_balance.<locals>.<genexpr>{   r   r   c              3   2   K   | ]  }|d    dk(  s|  ywri   r   Nr   r   s     r3   r   zXTestAvalancheVsSnowball.test_snowball_directs_extra_to_lowest_balance.<locals>.<genexpr>|   r   r   rq   r   r   r   r   r:   N)r   r(   r   r   r   r   rd   r+   rD   r-   r.   r/   )	r0   r"   r   card_brt   r1   rF   r2   rH   s	            r3   -test_snowball_directs_extra_to_lowest_balancezETestAvalancheVsSnowball.test_snowball_directs_extra_to_lowest_balancex   s    #VVV$<eDR!9!9RRR!9!9RRn%?)??%)?????%)????%???)????????r5   c                    t        t        t        t        gt              }t        d |j                  D              }t        d |j                  D              }|d   }|d   }||k  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}y	)
z<Highest balance strategy should target CARD_B ($2000) first.c              3   2   K   | ]  }|d    dk(  s|  ywr   r   r   s     r3   r   z`TestAvalancheVsSnowball.test_highest_balance_directs_extra_to_largest_balance.<locals>.<genexpr>   r   r   c              3   2   K   | ]  }|d    dk(  s|  ywr   r   r   s     r3   r   z`TestAvalancheVsSnowball.test_highest_balance_directs_extra_to_largest_balance.<locals>.<genexpr>   r   r   rq   r   r   r   r   r:   N)r   r(   r   r   r   r   rd   r+   rD   r-   r.   r/   )	r0   r"   r   r   rt   r1   rF   r2   rH   s	            r3   5test_highest_balance_directs_extra_to_largest_balancezMTestAvalancheVsSnowball.test_highest_balance_directs_extra_to_largest_balance   s    *FFF+CUKR!9!9RRR!9!9RRn%?)??%)?????%)????%???)????????r5   c                    t        t        t        t        gt              }t        t        t        t        gt              }|j                  }|j                  }||k  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}y)	zUAvalanche should produce <= interest compared to snowball on high-APR-variance cards.r   )zd%(py2)s
{%(py2)s = %(py0)s.total_interest_paid
} <= %(py6)s
{%(py6)s = %(py4)s.total_interest_paid
}r_avr_sbr   r   rZ   N)r   r(   r   r   r   r   rV   r+   rD   r)   r*   r,   r-   r.   r/   )r0   r   r   rI   rG   r1   rH   r^   s           r3   'test_avalanche_minimizes_total_interestz?TestAvalancheVsSnowball.test_avalanche_minimizes_total_interest   s    "FFF#;UC!666":EB''C4+C+CC'+CCCCC'+CCCCCCCtCCCtCCC'CCCCCC4CCC4CCC+CCCCCCCCr5   N)r   r   r   r   r   r   r   r   r5   r3   r   r   o   s    @@@Dr5   r   c                       e Zd Zd Zy)TestSingleCardc                    dddddd}t        d      }t        t        t        t        fD ]  } ||g|      }|j
                  }d}||kD  }|st        j                  d	|fd
||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            d x}x}} y )Nr
   Solor   z18.00r   r   z50.00r   rP   rR   r"   r?   rA   rB   )r   r   r   r   r   rS   r+   rD   r)   r*   r,   r-   r.   r/   )
r0   rm   extrafnr"   rI   rJ   r1   rK   rL   s
             r3   &test_all_strategies_handle_single_cardz5TestSingleCard.test_all_strategies_handle_single_card   s    HW]de &(:<UWmn 	/B&F**.Q.*Q....*Q......6...6...*...Q.......	/r5   N)r   r   r   r   r   r5   r3   r   r      s    /r5   r   c                       e Zd Zd Zd Zy)TestZeroBalanceSkippedc                    dddddd}ddd	d
dd}t        ||gt        d            }t        d |j                  D              }|d   }d	}||k(  }|slt	        j
                  d|fd||f      t	        j                  |      t	        j                  |      dz  }dd|iz  }	t        t	        j                  |	            d x}x}}y )Nr
   Liver   r   r   r   r   Zeror   r   10.00r   c              3   2   K   | ]  }|d    dk(  s|  ywr   r   r   s     r3   r   zWTestZeroBalanceSkipped.test_zero_balance_card_does_not_affect_payoff.<locals>.<genexpr>   s     Uq,ST@TUr   rr   r<   )z%(py1)s == %(py4)sr   r   r:   )	r   r   r   rd   r+   rD   r-   r.   r/   )
r0   	card_live	card_zeror"   	zero_cardrt   r1   rF   r2   rH   s
             r3   -test_zero_balance_card_does_not_affect_payoffzDTestZeroBalanceSkipped.test_zero_balance_card_does_not_affect_payoff   s    f7cjk	f7cjk	$i%;WT]KUF$<$<UU	)*4f4*f4444*f444*444f4444444r5   c                    dddddd}ddd	d
dd}t        ||gt        d            }|j                  D cg c]  }|d   	 }}d}||v }|st        j                  d|fd||f      t        j
                  |      dt        j                         v st        j                  |      rt        j
                  |      nddz  }dd|iz  }	t        t        j                  |	            d x}}y c c}w )Nr
   r   r   r   r   r   r   r   r   r   r   r   ri   rj   rl   idsrn   ro   r@   )r   r   rd   r+   rD   r-   r)   r*   r,   r.   r/   )
r0   r   r   r"   r   r   rt   rF   ru   rK   s
             r3   +test_zero_balance_card_included_in_per_cardzBTestZeroBalanceSkipped.test_zero_balance_card_included_in_per_card   s    f7cjk	f7cjk	$i%;WS\J(.(@(@A1qAAqCxqCqCC Bs   C*N)r   r   r   r   r   r   r5   r3   r   r      s    5r5   r   c                       e Zd Zd Zd Zy)TestProportionalc           
         t        t        t        t        gt              }|j
                  D ]^  }|d   d   d   }t        |      }d}t        |      }||k(  }|s&t        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }d	d
|iz  }	t        t        j                  |	            d x}x}x}x}}a y )Nrs   r   r   r   r<   r   r   r   r   r   )r   r(   r   r   r   rd   r   r+   rD   r)   r*   r,   r-   r.   r/   )
r0   r"   rm   rI   r1   r]   r   rG   rf   r   s
             r3   $test_proportional_pays_off_all_cardsz5TestProportional.test_proportional_pays_off_all_cards   s    '(@%H,, 	OD
+B/	:N7:;NvNwvN;NNNN;NNNNNN7NNN7NNN:NNN;NNNNNNwNNNwNNNvNNNNNNNNNNN	Or5   c                    t        t        gt        d            }|j                  }d}||k(  }|st	        j
                  d|fd||f      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d x}x}}y )	Nr   proportionalr<   r>   r"   r?   rA   rB   )r   r(   r   rC   r+   rD   r)   r*   r,   r-   r.   r/   r   s          r3   test_proportional_strategy_namez0TestProportional.test_proportional_strategy_name   s    ''$-@0.0.0000.000000v000v000000.0000000r5   N)r   r   r   r   r   r   r5   r3   r   r      s    O
1r5   r   c                       e Zd Zd Zd Zd Zy)
TestCustomc                 .   t        d      t        d      d}t        t        t        g|      }t	        |t
              }|sddt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  t
              rt        j                  t
              ndt        j                  |      dz  }t        t        j                  |            d }|j                  }d	}||k(  }|st        j                  d
|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}y )Nr   z300.00)r
   r   r    r!   r"   r	   r#   customr<   r>   r?   rA   rB   )r   r   r(   r   r!   r	   r)   r*   r+   r,   r-   r.   r/   rC   rD   )	r0   allocationsr"   r1   r2   rI   rJ   rK   rL   s	            r3   !test_custom_allocations_respectedz,TestCustom.test_custom_allocations_respected   s   !(+0AB!66"2K@&"455555555z555z555555&555&555555"4555"45555555555*(*(****(******v***v******(*******r5   c           	         dt        d      i}dddddd}t        |g|      }|j                  }d}||kD  }|st        j                  d	|fd
||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|j                  d   d   d   d   }t        |      }d}	t        |	      }
||
k(  }|s&t        j                  d|fd||
f      dt        j                         v st        j                  t               rt        j                  t               ndt        j                  |      t        j                  |      dt        j                         v st        j                  t               rt        j                  t               ndt        j                  |	      t        j                  |
      dz  }dd|iz  }t        t        j                  |            dx}x}x}x}	}
y)z7If custom allocation is below minimum, minimum is used.r
   z5.00r   r   r   r   r   r   rP   rR   r"   r?   rA   rB   Nrs   r   r   r   r<   r   r   r   r   r   )r   r   rS   r+   rD   r)   r*   r,   r-   r.   r/   rd   )r0   r   rm   r"   rI   rJ   r1   rK   rL   r]   r   rG   rf   r   s                 r3   +test_custom_below_minimum_raised_to_minimumz6TestCustom.test_custom_below_minimum_raised_to_minimum   s~   '&/*'Zab!4&+6&&**&****&******v***v***&**********//2:>rB9MawMNaZ`aRYZ`RaaNRaaaaaNRaaaaaaawaaawaaaMaaaNaaaaaaRYaaaRYaaaZ`aaaRaaaaaaaaar5   c           
      X   t        d      t        d      t        d      d}t        t        t        t        g|      }|j
                  D ]^  }|d   d   d   }t        |      }d}t        |      }||k(  }|s&t        j                  d	|fd
||f      dt        j                         v st        j                  t               rt        j                  t               ndt        j                  |      t        j                  |      dt        j                         v st        j                  t               rt        j                  t               ndt        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            d x}x}x}x}}a y )Nz100.00r   z80.00)r
   r   r   rs   r   r   r   r<   r   r   r   r   r   )r   r   r(   r   r   rd   r+   rD   r)   r*   r,   r-   r.   r/   )r0   r   r"   rm   rI   r1   r]   r   rG   rf   r   s              r3   test_custom_pays_off_allz#TestCustom.test_custom_pays_off_all   s   !(+0AggFVW!666":KH,, 	OD
+B/	:N7:;NvNwvN;NNNN;NNNNNN7NNN7NNN:NNN;NNNNNNwNNNwNNNvNNNNNNNNNNN	Or5   N)r   r   r   r   r   r   r   r5   r3   r   r      s    +bOr5   r   c                       e Zd Zd Zd Zy)TestDecimalTypesc                    t        t        gt        d            }|j                  }t	        |      }|t        u }|sCt        j                  d|fd|t        f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }dd	|iz  }t        t        j                  |            d x}x}}y )
Nr   )is)zY%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.total_interest_paid
})
} is %(py7)styper"   r   )r$   r%   r9   r@   rB   zassert %(py9)spy9)r   r(   r   rV   r   r+   rD   r)   r*   r,   r-   r.   r/   )r0   r"   rF   rJ   re   rL   @py_format10s          r3   #test_total_interest_is_decimal_typez4TestDecimalTypes.test_total_interest_is_decimal_type   s    $fXwt}=..:t./:/7::::/7::::::t:::t::::::F:::F:::.:::/::::::7:::7:::::::r5   c                    t        t        gt        d            }|j                  d   d   d   }dD ]1  }t        ||         }t	        |t              }|sddt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      d	z  }t        t        j                  |            d }4 y )
Nr   r   rs   )ry   rz   r{   r   r    r!   valr   r#   )r   r(   r   rd   r!   r)   r*   r+   r,   r-   r.   r/   )r0   r"   r}   r|   r   r1   r2   s          r3   3test_schedule_amounts_are_string_formatted_decimalszDTestDecimalTypes.test_schedule_amounts_are_string_formatted_decimals   s    $fXwt}=&&q)*5a8B 	,C#c(#Cc7++++++++:+++:++++++c+++c++++++7+++7++++++++++	,r5   N)r   r   r   r   r   r   r5   r3   r   r      s    ;,r5   r   )r   builtinsr)   _pytest.assertion.rewrite	assertionrewriter+   decimalr   rY   pytestapp.services.amortizationr   r   r   r   r   r	   r(   r   r   r   r   r   r   r   r   r   r   r   r   r   r5   r3   <module>r     s    .        6Ig^e	f<Ig^e	f:Hg^e	f
* *^Q Q2+ +D D@/ / $1 1O O2
, 
,r5   