3iHAdZddlZddlmZddlmZmZmZmZmZm Z m Z m Z m Z m Z mZmZddlmZej$eZGddeZGdd eZGd d eZGd d eZy)zc Dialogs for Portfolio Manager. Contains dialogs for Add Holding, Buy/Sell/Dividend transactions. N)datetime) QDialog QVBoxLayout QHBoxLayout QFormLayout QLineEdit QComboBoxQDoubleSpinBox QPushButton QMessageBoxQLabel QDateEdit QTextEdit)QDatec.eZdZdZfdZdZdZxZS)AddHoldingDialogz1Dialog for adding a new holding to the portfolio.ct||||_|jd|j d|j y)zg Initialize Add Holding dialog. Args: parent: MainWindow instance zAdd New HoldingNsuper__init__parentsetWindowTitlesetMinimumWidthinit_uiselfr __class__s =/mnt/ssd/data/python-lab/portfolio-manager/src/gui/dialogs.pyrzAddHoldingDialog.__init__?    -. S! cht|}t}t|_|jj d|j d|jt|_|j j d|j d|j t|_|jjgd|j d|jt|_ |jjd|jjdd |jjd |j d |jt|_|jjd|jjdd |jj!d |j d |j|j#|t%}t'd}|j(j+|j,t'd}|j(j+|j.|j1d|j3|j5||j5||j#|y)Initialize user interface.z e.g., VWCE.MITicker:ze.g., Vanguard FTSE All-WorldzName:)ETFStockCashz Asset Type:r@B shares Quantity:€ z Avg Price:Cancelz Add HoldingTN)rrr txt_tickersetPlaceholderTextaddRowtxt_namer combo_typeaddItemsr spin_quantity setDecimalssetRange setSuffixspin_avg_price setPrefix addLayoutrr clickedconnectreject accept_dialog setDefault addStretch addWidgetrlayout form_layout btn_layout btn_cancelbtn_adds rrzAddHoldingDialog.init_ui#s T""m $+ **?;9doo6"   (()HI7DMM2$+   !9:=$//:,- &&q) ##Aw/ $$Y/;(:(:;-. ''* $$Q0 %%f-<)<)<=%!]  * ""4;;/m, 2 234 Z(W%$r!c |jjjj}|jjj}|j j }|jj}|jj}|stj|ddy|stj|ddy|dkrtj|ddy|dkrtj|ddy |jjj|||||tj!d |d |d |d |j#y#t$$rG}tj'd |dtj(|ddt+|Yd}~yd}~wwxYw)Validate and accept dialog.Validation ErrorTicker is requiredNzName is requiredrQuantity must be greater than 0z$Average price must be greater than 0)tickername asset_typequantity avg_pricezAdded holding:  ( @ )zError adding holding: Texc_infoErrorzFailed to add holding: )r.textstripupperr1r2 currentTextr4valuer8r warningr portfolio add_holdingloggerinfoaccept Exceptionerrorcriticalstr)rrMrNrOrPrQes rr>zAddHoldingDialog.accept_dialogXs%%'--/557}}!!#))+__002 %%++-''--/    &8:N O    &8:L M  q=   &8:[ \  >   &8:` a   KK ! ! - -%!# .  KK/&H:S 1M N KKM  LL1!5L E  *3q6(3   sAE66 G?=GG)__name__ __module__ __qualname____doc__rrr> __classcell__rs@rrrs; 3%j,r!rc:eZdZdZfdZdZdZdZdZxZ S)BuyTransactionDialogz'Dialog for recording a BUY transaction.ct||||_|jd|j d|j y)zk Initialize Buy Transaction dialog. Args: parent: MainWindow instance zBuy TransactionrNrrs rrzBuyTransactionDialog.__init__r r!c(t|}t}t|_|jj d|j |j d|jt|_|jjd|jjdd|jjd|jjj|j|j d|jt|_|jjd|jjdd|jj!d|jjj|j|j d |jt#|_|j$j't)j*|j$j-d|j d |j$t/|_|j0j3d |j d |j0t5d |_|j6j9d|j d|j6|j;|t=}t?d}|j@j|jBt?d}|j@j|jD|jGd|jI|jK||jK||j;|y)r#Tr$r(rr)r*r+r,Price:Date:Optional notes...Notes:€ 0.00#font-weight: bold; font-size: 14px;Total:r-BuyN)&rrr combo_ticker setEditable load_tickersr0r r4r5r6r7 valueChangedr< update_total spin_pricer9r date_editsetDater currentDatesetCalendarPopupr txt_notesr/r lbl_total setStyleSheetr:rr r;r=r>r?r@rA)rrCrDrErFbtn_buys rrzBuyTransactionDialog.init_uisT""m &K %%d+ 9d&7&78,- &&q) ##Aw/ $$Y/ ''//0A0AB;(:(:;)* ##A&   G, !!&) $$,,T->->?8T__5# u0023 ''-7DNN3# ))*=>8T^^4 + $$%JK8T^^4%!]  * ""4;;/e$ 2 234 Z(W%$r!c|jjj}|jj |y)z$Load existing tickers into dropdown.Nr db_managerget_all_tickersrzr3rtickerss rr|z!BuyTransactionDialog.load_tickers.++((88: ""7+r!c|jj}|jj}||z}|jj d|dyzUpdate total amount label.r,z,.2fNr4r\rrsetTextrrPpricetotals rr~z!BuyTransactionDialog.update_totalM%%++-%%'5  eD\23r!c z|jjjj}|jj }|j j }|jjjd}|jjj}|stj|ddy|dkrtj|ddy|dkrtj|ddy |jjj!|||||t"j%d |d |d ||j'y#t($rG}t"j+d |d tj,|ddt/|Yd}~yd}~wwxYw)rI yyyy-MM-ddrJrKNrrLPrice must be greater than 0rMrPrdatenoteszBuy transaction processed:  rSzError processing buy: TrUrWz#Failed to process buy transaction: )rzr[rYrZr4r\rrrtoStringrrXr r]rtransaction_manager process_buyr`rarbrcrdrerf)rrMrPrrrrgs rr>z"BuyTransactionDialog.accept_dialogs""..0668>>@%%++-%%'~~""$--l;##%++-   &8:N O  q=   &8:[ \  A:   &8:X Y   KK + + 7 7! 8  KK5fXQxjE7S T KKM  LL1!5L E  6s1vh?   sAE** F:3=F55F:) rhrirjrkrrr|r~r>rlrms@rroros 1 <%|, 4'r!roc@eZdZdZfdZdZdZdZdZdZ xZ S)SellTransactionDialogz(Dialog for recording a SELL transaction.ct||||_|jd|j d|j y)zl Initialize Sell Transaction dialog. Args: parent: MainWindow instance zSell TransactionrNrrs rrzSellTransactionDialog.__init__s?    ./ S! r!ct|}t}t|_|jjj |j |j|jd|jtd|_ |jd|jt|_ |jjd|jjdd|jjd|jj j |j"|jd|jt|_|j$jd|j$jdd|j$j'd |j$j j |j"|jd |j$t)|_|j*j-t/j0|j*j3d |jd |j*t5|_|j6j9d |jd|j6td|_|j:j=d|jd|j:|j?|tA}tCd}|jDj |jFtCd}|jDj |jH|jKd |jM|jO||jO||j?||j y)r#r$zAvailable: 0 sharesr(rr)r*r+r,rrTrsrtrurvrwrxr-SellN)(rrr rzcurrentIndexChangedr<on_ticker_changedr|r0r lbl_availabler r4r5r6r7r}r~rr9rrrrrrrrr/rrr:rr r;r=r>r?r@rA)rrCrDrErFbtn_sells rrzSellTransactionDialog.init_uisT""m &K --55d6L6LM 9d&7&78$$9:2t112,- &&q) ##Aw/ $$Y/ ''//0A0AB;(:(:;)* ##A&   G, !!&) $$,,T->->?8T__5# u0023 ''-7DNN3# ))*=>8T^^4 + $$%JK8T^^4%!]  * ""4;;/v&  !3!34D!Z(X&$  r!c|jjj}|Dcgc].}|jdkDs|jdk7s#|j 0}}|j j|ycc}w)zLoad tickers with quantity > 0.rr'N)rr^holdingsrPrOrMrzr3)rrhrs rr|z"SellTransactionDialog.load_tickers`s^;;((11%-[aALLTZDZ188[[ ""7+\sA6A6 A6c,|jj}|rx|jjj |}|rP|j j d|jdd|jj|jyyy)z.Update available quantity when ticker changes.z Available: .0fr*N) rzr[rr^ get_holdingrrrPr4 setMaximum)rrMholdings rrz'SellTransactionDialog.on_ticker_changedfs""..0 kk++77?G""**[9I9I#8Ng+VW""--g.>.>? r!c|jj}|jj}||z}|jj d|dyrrrs rr~z"SellTransactionDialog.update_totalorr!c |jj}|jj}|jj}|j j jd}|jjj}|stj|ddy|dkrtj|ddy|dkrtj|ddy |jjj|||||\}}tj |d d |d d |d |dd|dd t"j%d|d|d|d|dd |j'y#t($r*}tj|dt+|Yd}~yd}~wt,$rG}t"j/d|dtj0|ddt+|Yd}~yd}~wwxYw)rIrrJrKNrrLrrz Sale CompletezSold rz shares of z Realized P&L: z+,.2fu € (z+.1fz%)zSell transaction processed: rrSz (P&L: z+.2frTzError processing sell: TrUrWz$Failed to process sell transaction: )rzr[r4r\rrrrrrXrYr r]rr process_sell informationr`rarb ValueErrorrfrcrdre) rrMrPrrr pnl_amount pnl_percentrgs rr>z#SellTransactionDialog.accept_dialogvs""..0%%++-%%'~~""$--l;##%++-   &8:N O  q=   &8:[ \  A:   &8:X Y  &*kk&E&E&R&R! 'S' #J   # #~[9!!+E 2&T8J"N  KK6vhazUGSZ[efjZkklm n KKM B   &8#a& A A  LL21#6L F  7Ax@   s%5BE== G> F++ G>7=G99G>) rhrirjrkrrr|rr~r>rlrms@rrr s'2 C!J, @41r!rc4eZdZdZfdZdZdZdZxZS)DividendDialogz,Dialog for recording a DIVIDEND transaction.ct||||_|jd|j d|j y)zd Initialize Dividend dialog. Args: parent: MainWindow instance DividendrNrrs rrzDividendDialog.__init__s>    J' S! r!ct|}t}t|_|j |j d|jt |_|jjd|jjdd|jjd|j d|jt|_ |jjtj|jj!d|j d|jt#|_|j$j'd |j d |j$|j)|t+}t-d }|j.j1|j2t-d }|j.j1|j4|j7d|j9|j;||j;||j)|y )r#r$r(rr)r,zAmount:Trsz e.g., Q4 2025rur-z Add DividendN)rrr rzr|r0r spin_amountr5r6r9rrrrrrrrr/r:rr r;r<r=r>r?r@rArBs rrzDividendDialog.init_uisT""m &K 9d&7&78*+ $$Q' !!!W- ""6*9d&6&67# u0023 ''-7DNN3# ))/:8T^^4%!]  * ""4;;/n- 2 234 Z(W%$r!c|jjj}|jj |y)zLoad existing tickers.Nrrs rr|zDividendDialog.load_tickersrr!c |jj}|jj}|jj j d}|jjj}|stj|ddy|dkrtj|ddy |jjj||||tj!d|d |d |d |j#y#t$$rG}tj'd |d tj(|ddt+|Yd}~yd}~wwxYw)rIrrJrKNrzAmount must be greater than 0)rMamountrrzDividend processed: u €rRrTzError processing dividend: TrUrWzFailed to process dividend: )rzr[rr\rrrrrXrYr r]rrprocess_dividendr`rarbrcrdrerf)rrMrrrrgs rr>zDividendDialog.accept_dialogsD""..0!!'')~~""$--l;##%++-   &8:N O  Q;   &8:Y Z   KK + + < < =  KK.vhd6("UG1M N KKM  LL6qc:TL J  /Ax8   s>AD E' =E""E') rhrirjrkrrr|r>rlrms@rrrs6 -%^, !r!r)rkloggingrPyQt6.QtWidgetsrrrrrr r r r r rr PyQt6.QtCorer getLoggerrhr`rrorrr!rrsx     8 $qwqhA7AH\G\~eWer!