
    0j	I                     B   d dl mZmZ d dlmZmZ d dlmZmZmZm	Z	m
Z
mZ d dlmZ d dlmZ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 d dlmZm Z m!Z!m"Z"m#Z# d dl$m%Z% g dZ&ee e!e"dZ'd Z(d Z)d Z* ejV                  d      d        Z, ejV                  dddg      d        Z- ejV                  dddg      d        Z. ejV                  dddg      d        Z/ ejV                  d      d        Z0 ejV                  d       d!        Z1 ejV                  d"dg      d#        Z2d$ Z3 ejV                  d%      d&        Z4 ejV                  d'dg      d(        Z5 ejV                  d)dg      d*        Z6 ejV                  d+      d,        Z7d- Z8y.)/    )DecimalInvalidOperation)datedatetime)render_templateredirecturl_forflashrequestabort)
paydown_bp)CreditCardFormExtraPaymentForm
ActionForm)db)Account)Settings)PaydownPlan)PaydownPlanCard)PaydownBalanceUpdate)calculate_avalanchecalculate_snowballcalculate_highest_balancecalculate_proportionalcalculate_custom)get_monitor_statuses))	avalanche	AvalanchezHighest APR first)snowballSnowballzLowest balance first)highest_balancezHighest BalancezLargest balance first)proportionalProportionalzDistributed by balance)customCustomzYou specify each card)r   r   r!   r"   c                  `    t         j                  j                  dd      j                         S )NcreditT)type	is_active)r   query	filter_byall     9/var/www/html/financials/app/blueprints/paydown/routes.py_credit_cardsr0   %   s%    ==""D"AEEGGr.   c           
      4   | D cg c]  }|j                   xs t        d      t        d      kD  ra|j                  |j                  |j                   xs t        d      |j                  xs t        d      |j
                  xs t        d      d c}S c c}w )N0idnamebalanceaprmin_payment)current_balancer   r4   r5   r7   r8   )cardscs     r/   _cards_as_dictsr<   )   s     
 -= $$FF((8GCL55(GCL==8GCL	

 
 
s   BBc                  ^    t         j                  j                  d      j                         S )Nactivestatus)r   r*   r+   firstr-   r.   r/   _active_planrB   7   s%    &&h&7==??r.   /c                      t               } t               }t        j                  j	                         }|r|j
                  nd }t               }t        d| |||d      S )Nzpaydown/index.htmlpaydown)r:   extraactive_planformactive_page)r0   rB   r   r*   rA   extra_monthly_paymentr   r   )r:   rG   settingsrF   rH   s        r/   indexrL   =   sW    OE.K~~##%H.6H**DE<D r.   z/cards/createGETPOST)methodsc                      t               } | j                         rt        |       }|r,|D ]  }t        |d        t	        d| t        d      dd      S t        | j                  j                  j                         | j                  j                  xs dj                         xs d dd	t        | j                  j                  j                               t        | j                  j                  j                               t        | j                  j                  j                               | j                  j                  xs dj                         r-t        | j                  j                  j                               nd 
      }t         j"                  j%                  |       t         j"                  j'                          t        dd       t)        t        d            S t	        d| t        d      dd      S )Nerrorpaydown/card_form.htmlzpaydown.create_cardzAdd Credit CardrE   rH   
action_urltitlerI    r'   T)r5   institution_namer(   r)   r9   r7   r8   credit_limitzCard added.successpaydown.index)r   validate_on_submit_validate_card_formr
   r   r	   r   r5   datastriprW   r   r9   r7   r8   rX   r   sessionaddcommitr   )rH   errorsmsgcards       r/   create_cardre   P   s   D $T* $c7#$"#;$.56K.L):	S S %%'"3388>BEEGO4#D$8$8$=$=$C$C$EF++-. 0 0 5 5 ; ; =>EIEVEVE[E[Ea_aDhDhDj!2!2!7!7!=!=!?@pt	
 	

t


mY'0113$&-.C&D!2	K Kr.   z/cards/<int:card_id>/editc                    t         j                  j                  | d      j                         }t	        |      }t
        j                  dk(  rt        |j                  xs d      |j                  _	        t        |j                  xs d      |j                  _	        t        |j                  xs d      |j                  _	        t        |j                  xs d      |j                  _	        t        d|t        d|       d	d
      S |j                         rt!        |      }|r.|D ]  }t#        |d        t        d|t        d|       d	d
      S |j$                  j                  j'                         |_        |j(                  j                  xs dj'                         xs d |_        t+        t        |j                  j                        j'                               |_        t+        t        |j                  j                        j'                               |_
        t+        t        |j                  j                        j'                               |_        t        |j                  j                  xs d      j'                         }|rt+        |      nd |_        t,        j.                  j1                          t#        dd       t3        t        d            S t        d|t        d|       d	d
      S )Nr'   )r4   r(   )objrM   rV   rR   zpaydown.edit_card)card_idzEdit Credit CardrE   rS   rQ   zCard updated.rY   rZ   )r   r*   r+   first_or_404r   r   methodstrr9   r]   r7   r8   rX   r   r	   r[   r\   r
   r5   r^   rW   r   r   r_   ra   r   )rh   rd   rH   rb   rc   	raw_limits         r/   	edit_cardrm   p   s]   ==""gH"=JJLDd#D~~$'(<(<(B$C!DHHN+ #D$4$4$: ;!$T%6%6%<"!=7d*12Ew*W%7YP 	P  $T* $c7#$"#;$.56ISZ.[);T T IINN((*	!%!6!6!;!;!Ar H H J Rd&s4+?+?+D+D'E'K'K'MN3txx}}-3356"3t'7'7'<'<#=#C#C#EF))..4"5;;=	2;GI.


oy)0113$&-.A7&S!3L Lr.   z/extra-paymentc                  x   t         j                  j                         } t               }t        j
                  dk(  r@| r0| j                  $t        | j                        |j                  _        t        d|d      S |j                         r|j                  j                  xs dj                         }	 t        |      }|dk  r3|j                  j                  j                  d       t        d|d      S | -t        d	|
      } t         j"                  j%                  |        n|| _        t         j"                  j'                          t)        dd       t+        t-        d            S t        d|d      S # t        $ r6 |j                  j                  j                  d       t        d|d      cY S w xY w)NrM   zpaydown/extra_payment.htmlrE   )rH   rI   rV   zEnter a valid numeric amount.r   zAmount must be zero or greater.   )r4   rJ   zExtra monthly payment saved.rY   paydown.compare)r   r*   rA   r   r   rj   rJ   rk   r]   r   r[   r^   r   r   rb   appendr   r_   r`   ra   r
   r   r	   )rK   rH   rawamounts       r/   extra_paymentrt      su   ~~##%HD~~66B.1(2P2P.QD&&+;$T]^^ ))..4";;=	cS\F A:&&--445VW"#?dXabb1FCHJJNN8$-3H*


,i8 12337dPYZZ!   	c&&--445TU"#?dXabb	cs   5E: :<F98F9z/comparec            
      l   t               } t        |       }t        j                  j	                         }|r|j
                  nd }t               }|t        t        d            S |st        dd| d      S i }t        j                         D ]  \  }} |||      ||<    t        ddt        || ||d      S )Nzpaydown.extra_paymentzpaydown/compare.htmlTrE   )no_debtr:   rI   F)rv   
strategiesresultsr:   rF   rG   rI   )r0   r<   r   r*   rA   rJ   rB   r   r	   r   _STRATEGY_CALCitems_STRATEGIES)r:   
card_dictsrK   rF   rG   rx   keyfns           r/   comparer      s    OE 'J~~##%H.6H**DE.K} 7899"!	
 	
 G!'') -R*e,- 	 	r.   z/strategy/<strategy_name>c                    | t         vr| dk7  rt        d       t               }t        |      }t        j
                  j                         }|r|j                  n
t        d      }t               }| dk(  rt        |i       }nt        |    ||      }t        D ci c]  }|d   |d    }}t               }	t        d|| |j                  | |       ||||	d	      S c c}w )	Nr$     r2   r   ro   zpaydown/strategy_detail.htmlrE   )resultstrategy_namestrategy_labelr:   rF   rG   action_formrI   )ry   r   r0   r<   r   r*   rA   rJ   r   rB   r   r{   r   r   get)
r   r:   r|   rK   rF   rG   r   sstrategy_labelsr   s
             r/   strategy_detailr      s    N*}/Hc
OE 'J~~##%H.6H**GCLE.K !*b1.z5A+67aqtQqTz7O7,K&#&**=-H
 
 8s   Cz/activate/<strategy_name>c                    | t         vr| dk7  rt        d       t               }t        |      }t        j
                  j                         }|r|j                  n
t        d      }|s t        dd       t        t        d            S | dk(  rt        |i       }nt        |    ||      }t        | |||       t        dd       t        t        d	            S )
Nr$   r   r2   zNo credit card debt to plan.rQ   rZ   zPlan activated.rY   paydown.monitor)ry   r   r0   r<   r   r*   rA   rJ   r   r
   r   r	   r   _plan_lifecycle_activate)r   r:   r|   rK   rF   r   s         r/   activate_planr     s    N*}/Hc
OE 'J~~##%H.6H**GCLE,g6011 !*b1.z5A]E:vF	
Y'G-.//r.   c           	         t        j                         }t        j                  j	                  d      j                         }ddlm} |D ]  }d|_         |j                         |_	        ! t        | |d      }t        j                  j                  |       t        j                  j                          |D ]  t        fd|j                  D        d      }	d	   }
|	r*| d
k7  r%|	j!                  dg       }|rt#        |d   d         }
t%        |j&                  d   |
d   d         }t        j                  j                  |        t        j                  j)                          |S )zJArchive any existing active plan and create a new one. Single transaction.r>   r?   r   )r   archived)strategyextra_monthlyr@   c              3   :   K   | ]  }|d    d   k(  s|  yw)
account_idr4   Nr-   ).0r;   	card_dicts     r/   	<genexpr>z+_plan_lifecycle_activate.<locals>.<genexpr>3  s!     W1AlOyQU4VQWs   Nr8   r$   schedulepaymentr4   r6   r7   )plan_idr   monthly_allocationstarting_balancestarting_apr)r   todayr   r*   r+   r,   r   r@   utcnowarchived_atr   r_   r`   flushnextper_card_scheduler   r   r   r4   ra   )r   rF   r|   r   nowexistingr   plannew_plancard_resultmonthly_allocr   	plan_cardr   s                @r/   r   r     sO   
**,C   **(*;??AH! - *8??,-
 H
 JJNN8JJ   "	W00W
 "-0=H4"z26H 'I(> ?#KK ,&y1"5)
	 	

y!%"( JJOr.   z/monitorc            
         t               } t               }| st        dd |d      S | j                  D cg c]  }|j                   }}t
        j                  j                  t
        j                  j                  |            j                         }|D cg c]c  }|j                  |j                  |j                  xs t        d      |j                  xs t        d      |j                  xs t        d      de }}t         j#                  | j$                        }|r ||| j&                        }nt)        |i       }t*        j                  j                  t*        j                  j                  |            j                         }	|	D 
cg c]&  }
|
j                  |
j,                  |
j.                  d( }}
t1        ||      }t        d| ||d      S c c}w c c}w c c}
w )Nzpaydown/monitor.htmlrE   )rG   r   rI   r2   r3   )r   r6   
updated_at)rG   statusesr   rI   )rB   r   r   r:   r   r   r*   filterr4   in_r,   r5   r9   r   r7   r8   ry   r   r   r   r   r   r6   r   r   )rG   r   pcplan_card_idsr:   r;   r|   r~   r   updates_rawuupdate_dictsr   s                r/   monitorr   K  s   .K,K"#!	
 	
 .9->->?rR]]?M?MM  !>?CCEE 	  $$FF((8GCL55(GCL==8GCL	
	J 	 
		K00	1B	J 9 9:!*b1 	""	$//33MB	C	   ||		VL 
 $FL9H A @	.s   GA(G+G#z/monitor/update-balancec                     t               } | s t        dd       t        t        d            S | j                  D ch c]  }|j
                   }}	 t        t        j                  j                  dd            }||vr t        dd       t        t        d            S t        j                  j                  d      xs d	j                         }	 t        |      }|dk  rt        	 t        ||      }t         j"                  j%                  |       t         j"                  j'                          t        dd       t        t        d            S c c}w # t        t        f$ r# t        dd       t        t        d            cY S w xY w# t        t        f$ r# t        d
d       t        t        d            cY S w xY w)u5   Story 7.2 — record a new balance update for a card.zNo active plan.rQ   r   r   r   zInvalid card.zCard not in active plan.r6   rV   z(Enter a valid balance (zero or greater).)r   r6   zBalance updated.rY   )rB   r
   r   r	   r:   r   intr   rH   r   	TypeError
ValueErrorr^   r   r   r   r   r_   r`   ra   )rG   r   r   r   rr   r6   upds          r/   update_balancer     s    .K) 1233-8->->?rR]]?M?4)),:;

 &('2 1233<<I&,"
3
3
5C4#,Q;  *g
FCJJNN3JJ	
i(G-.//3 @ z" 4ow' 12334 j) 48'B 12334s)   E)E F /FF/F=<F=z/switch-strategyc            
      r   t         j                  j                  dd      } | t        vr%| dk7  r t	        dd       t        t        d            S t               }|s t	        dd       t        t        d            S |j                  D cg c]  }|j                   }}t        j                  j                  t        j                  j                  |            j                         }i }t         j                  j                  t         j                  j                  |            j                         }|D ]F  }|j                  |vs'|j"                  ||j                     j"                  kD  s8|||j                  <   H g }|D ]  }	|j                  |	j                        }
|
r|
j$                  n|	j&                  xs t)        d	      }|j+                  |	j                  |	j,                  ||	j.                  xs t)        d	      |	j0                  xs t)        d	      d
        t2        j                  j5                         }|r|j6                  n
t)        d	      }t        j                  |       }|r
 |||      }nt9        |i       }t;        | |||       t	        dd       t        t        d            S c c}w )uR   Story 7.3 — switch to a different strategy, recalculating from current balances.r   rV   r$   zInvalid strategy.rQ   r   zNo active plan to switch from.rp   r2   r3   z&Strategy switched. New plan activated.rY   )r   rH   r   ry   r
   r   r	   rB   r:   r   r   r*   r   r4   r   r,   r   r   r6   r9   r   rq   r5   r7   r8   r   rA   rJ   r   r   )new_strategyrG   r   r   r:   latest_updatesupdatesr   r|   r;   r   r6   rK   rF   r~   r   s                   r/   switch_strategyr     s>    <<##J3L>)lh.F!7+ 1233.K.8 1233 .9->->?rR]]?M?MM  !>?CCEE N""	$//33MB	C	 
  -<<~-q||@\@g@g1g+,N1<<(- J 	  &!$#++1+<+<+L$$FF55(GCL==8GCL
 		 ~~##%H.6H**GCLE			L	)B	J&!*b1\5*fE	
2I>G-.//K @s   J4z/historyc                      t         j                  j                  d      j                  t         j                  j                               j                         } t        d| d      S )u"   Story 7.3 — view archived plans.r   r?   zpaydown/history.htmlrE   )plansrI   )r   r*   r+   order_byr   descr,   r   )r   s    r/   historyr     sV     		*	%	+))..0	1		   r.   c                    g }dD ]R  \  }}t        | |      j                  xs dj                         }	 t        |      }|dk  r|j	                  | d       T t        | j                  j                  xs d      j                         }|r$	 t        |      }|dk  r|j	                  d       |S |S # t
        $ r |j	                  | d       Y w xY w# t
        $ r |j	                  d       Y |S w xY w)N))r9   zCurrent balance)r8   zMinimum payment)r7   APRrV   r   z must be zero or greater.z: enter a valid numeric value.z%Credit limit must be zero or greater.z*Credit limit: enter a valid numeric value.)getattrr]   r^   r   rq   r   rk   rX   )rH   rb   
field_namelabelrr   valrl   s          r/   r\   r\     s   F D
E
 tZ(--3::<	D#,CQw'@ABD D%%**0b1779I	H)$CQwEF M6M   	DMMUG#ABC	D   	HMMFGM	Hs#   $B3!C 3CCC43C4N)9decimalr   r   r   r   flaskr   r   r	   r
   r   r   app.blueprints.paydownr   app.blueprints.paydown.formsr   r   r   app.extensionsr   app.models.accountr   app.models.settingsr   app.models.paydown_planr   app.models.paydown_plan_cardr   !app.models.paydown_balance_updater   app.services.amortizationr   r   r   r   r   app.services.plan_monitorr   r{   ry   r0   r<   rB   routerL   re   rm   rt   r   r   r   r   r   r   r   r   r\   r-   r.   r/   <module>r      s   - # K K - U U  & ( / 8 B  ; +)0-	H@ # $ /E6?;K <K> -vG#L H#LP "UFO<[ =[D * H -. /B -x@0 A00*^ *3 3l +fX> 0 ? 0F $vh720 820j * "r.   