
    n^jB.                     D   d Z ddlZddl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mZmZ dd	lmZ dd
lmZ 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! e ed      d               Z"e ed      d               Z#e ed      d               Z$de%fdZ&d Z'e ed       eddg      d                      Z(e ed       eddg      d                      Z)e ed       eddg      d                      Z*e ed        eddg      d!                      Z+y)"u7  
budget/views.py
===============
Function-based views for Budget Management (dashboard, bulk upload, settings,
delete endpoints).  CRUD list/form flows live in budget/cbv/.

NOTE: ``horilla.decorators`` (NOT ``horilla_views.cbv_methods``) must be used
here — the latter expects a CBV ``self`` first-argument.
    N)datetime)messages)transaction)ProtectedError)HttpResponseJsonResponse)get_object_or_404redirectrender)gettext_lazy)require_http_methods)login_requiredpermission_required   )BudgetBulkUploadFormBudgetSettingsForm)BudgetAllocation
BudgetHead
BudgetItemBudgetSettingsBudgetSubHeadzbudget.view_budgetheadc                    ddl m} t        j                         j                  }t
        j                  j                  d      j                  d      }t        j                  j                  |      j                  d      j                  d      }|j                   |d	       |d
       |d       |d            }|d   xs d}|d   xs d}|d   xs d}|d   xs d}	||z
  }
|D cg c]  }|j                  s| }}|||||||	|
|t        |      |j                         t         j                  j                  d      j                         d}t#        | d|      S c c}w )zQ
    High-level budget overview: totals, recent allocations, overrun alerts.
    r   )SumT)	is_activesub_heads__items__allocations)fiscal_yearitem__sub_head__headz-allocated_amountallocated_amountdisbursed_amountapproved_amountcommitted_amount)total_allocatedtotal_disbursedtotal_approvedtotal_committedr"   r#   r$   r%   )headsallocationscurrent_yearr"   r#   r$   r%   total_balanceoverrun_itemsoverrun_count
head_count
item_countzbudget/dashboard.html)django.db.modelsr   r   nowyearr   objectsfilterprefetch_relatedr   select_relatedorder_by	aggregate
is_overrunlencountr   r   )requestr   r(   r&   r'   totalsr"   r#   r$   r%   r)   ar*   contexts                 0/var/www/python-projects/worksol/budget/views.pybudget_dashboardr?   '   s    %<<>&&L%%%5FF'E 	  ''L'A	.	/	%	&  ""././,-./	 # F ./41O./41O,-2N./41O#o5M +<1q||Q<M< "$**(*&&]+kkm ((//$/?EEGG '2G<<! =s   ,E#>E#zbudget.change_budgetsettingsc                 0   t        j                         }t        | j                  xs d |      }| j                  dk(  rJ|j                         r:|j                          t        j                  | t        d             t        d      S t        | dd|i      S )N)instancePOSTzBudget settings saved.ze<script>$('#genericModal').removeClass('oh-modal--show');$('#reloadMessagesButton').click();</script>zbudget/settings_form.htmlform)r   get_settingsr   rB   methodis_validsaver   success_r   r   )r:   objrC   s      r>   budget_settingsrK   \   s     
%
%
'Cgll2dSAD~~DMMO		!$<"=>
 	
 '6GG    zbudget.add_budgetitemc           	         t        | j                  xs d| j                  xs d      }d}| j                  dk(  rZ|j	                         rJ|j
                  d   }	 t        |      }t        j                  |  t        d      j                  di |       t        | d||d      S # t        $ rA}t        j                  | t        d      j                  t        |                   Y d}~Ud}~ww xY w)	aF  
    Upload an Excel (.xlsx) or CSV file to bulk create/update budget structure.

    Expected columns (case-insensitive, order-independent):
      head_name, sub_head_name, item_name, description (optional),
      fiscal_year (optional), period_type (optional), period_value (optional),
      allocated_amount (optional)
    NrB   filezIUpload complete: {created} created, {updated} updated, {skipped} skipped.zUpload failed: {}zbudget/bulk_upload.html)rC   results )r   rB   FILESrE   rF   cleaned_data_process_bulk_uploadr   rH   rI   format	Exceptionerrorstrr   )r:   rC   rO   uploadedexcs        r>   budget_bulk_uploadrZ   q   s       4gmm6KtLDG~~DMMO$$V,		M*84Ge]^ee  '4tPW6XYY  	MNN7A&9$:$A$A#c($KLL	Ms   :B$ $	C.-7C))C.returnc                 `	   | j                   j                         }g }|j                  d      r| j                         j	                  d      }t        j                  t        j                  |            }|D cg c]P  }|j                         D ci c]2  \  }}|j                         j                         |j                         4 c}}R }}}}nddl}|j                  | dd      }	|	j                  }
d}|
j                  d      D ]  }|9|D cg c]-  }|r't        |      j                         j                         nd/ }}>|j!                  t#        |      D ci c]&  \  }}||   |t        |      j                         nd( c}}        |	j%                          dx}x}}g }t'        j(                         5  t#        |d	
      D ]l  \  }}|j+                  d      xs |j+                  dd      }|j+                  d      xs |j+                  dd      }|j+                  d      xs |j+                  dd      }|s|j!                  d| d       |dz  }t,        j.                  j1                  |||j+                  dd      d      \  }}|r|dz  }n|dz  }|st2        j.                  j1                  ||||j+                  dd      d      \  }}|r|dz  }n|dz  }|s#t4        j.                  j1                  ||||j+                  dd      d      \  }}|r|dz  }n3|j+                  d      r|d   |_        |j9                  dg       |dz  }|j+                  dd      }|j+                  d      xs dj                         }|j+                  dd      }|j+                  d d      }|s|s	 t;        |      } t=        |      }!|rt;        |      nd}"t>        j.                  j1                  || ||"d |!i!      \  }#}$|$r|dz  }n|!|#_         |#j9                  d g       |dz  }o 	 ddd       ||||d#S c c}}w c c}}}w c c}w c c}}w # tB        tD        f$ r'}%|j!                  d| d"|%        |dz  }Y d}%~%d}%~%ww xY w# 1 sw Y   axY w)$z
    Parse uploaded file and upsert BudgetHead / BudgetSubHead / BudgetItem
    (and optionally BudgetAllocation) records.
    Returns a summary dict: {created, updated, skipped, errors}.
    z.csvz	utf-8-sigr   NT)	read_only	data_only)values_only    )start	head_namez	head namesub_head_namezsub head name	item_namez	item namezRow u    : missing head_name — skipped.r   head_description)namedescription)name__iexactdefaultssub_head_description)headri   rj   rh   )sub_headri   rj   )update_fieldsr   period_typeannualperiod_valuer   )itemr   ro   rq   rj   u   : allocation parse error — )createdupdatedskippederrors)#rg   lowerendswithreaddecodecsv
DictReaderioStringIOitemsstripopenpyxlload_workbookactive	iter_rowsrW   append	enumeratecloser   atomicgetr   r1   get_or_creater   r   rh   rG   intfloatr   r   
ValueError	TypeError)&uploaded_filerg   rowstextreaderrowkvr   wbwsheaderscirs   rt   ru   rv   idxrc   rd   re   rl   head_createdrm   
sh_createdrr   item_createdfiscal_year_strro   period_value_strallocated_strr   r   rq   allocalloc_createdrY   s&                                         r>   rS   rS      s    ##%DD}}V!!#**;7D 12 
 
 7:iikBdaQWWY__	)B
 
 	##MTT#RYY<<D<1 	CHKL1Q3q6<<>//1B>LLKKS\]`Sab41ac!flln2Eb		 	
"##G#gF				 O!!$a0 N	!HC,HR0HIGGO4TQS8TM,HR0HISE)IJK1 ",!3!3!A!A&"+CGGDVXZ<[\ "B "D, 11  $1#8#8#F#F*"/H^`b@cd $G $ Hj
 11 ",!3!3!A!A!&"+CGGMSU<VW "B "D,
 177=)'*='9D$II]OI<1 "ggmR8O77=1=XDDFK"ww~r:GG$6;M=!"%o"6K',]';$<L3'7#8RVL+;+C+C+Q+Q!$/$/%1"46F!G ,R ,(E= %11A.

2D1E
F1WN	!O!b 7wRXYYO C
 M ch #I. !MMD-J3%"PQqLG![O! O!sb   ;Q7Q
Q2Q $+Q%G?R$R$A5Q+ R$Q+R!:RR$R!!R$$R-c                     t        d      S )zEStandard response after a soft/hard delete triggered from a list row.z<script>$('.filterButton').click();$('#reloadMessagesButton').click();$('#deleteConfirmation').removeClass('oh-modal--show');</script>)r   )r:   s    r>   _hx_delete_responser   
  s     	 rL   zbudget.delete_budgetheadrB   DELETEc                 
   t        t        |      }	 |j                          t        j                  | t        d             t        |       S # t        $ r, t        j                  | t        d             Y t        |       S w xY w)NpkzBudget head deleted.z,Budget head is in use and cannot be deleted.)	r	   r   deleter   rH   rI   r   rV   r   )r:   r   rl   s      r>   delete_budget_headr     t     ZB/DS!$:";< w''  Sw"P QRw''S   /A (BBzbudget.delete_budgetsubheadc                 
   t        t        |      }	 |j                          t        j                  | t        d             t        |       S # t        $ r, t        j                  | t        d             Y t        |       S w xY w)Nr   zBudget sub-head deleted.z0Budget sub-head is in use and cannot be deleted.)	r	   r   r   r   rH   rI   r   rV   r   )r:   r   rm   s      r>   delete_budget_sub_headr   #  su     !26HW!$>"?@ w''  Ww"T UVw''Wr   zbudget.delete_budgetitemc                 
   t        t        |      }	 |j                          t        j                  | t        d             t        |       S # t        $ r, t        j                  | t        d             Y t        |       S w xY w)Nr   zBudget item deleted.z,Budget item is in use and cannot be deleted.)	r	   r   r   r   rH   rI   r   rV   r   )r:   r   rr   s      r>   delete_budget_itemr   0  r   r   zbudget.delete_budgetallocationc                 
   t        t        |      }	 |j                          t        j                  | t        d             t        |       S # t        $ r, t        j                  | t        d             Y t        |       S w xY w)Nr   zBudget allocation deleted.z2Budget allocation is in use and cannot be deleted.)	r	   r   r   r   rH   rI   r   rV   r   )r:   r   
allocations      r>   delete_budget_allocationr   =  sx     ##3;JY!$@"AB w''  Yw"V WXw''Yr   ),__doc__r{   r}   r   django.contribr   	django.dbr   r.   r   django.httpr   r   django.shortcutsr	   r
   r   django.utils.translationr   rI   django.views.decorators.httpr   horilla.decoratorsr   r   formsr   r   modelsr   r   r   r   r   r?   rK   rZ   dictrS   r   r   r   r   r   rP   rL   r>   <module>r      s    	  # ! + 2 @ @ 6 = B ;  -.,= / ,=f 34H 5 H& ,-Z . Z8tZ4 tZv	 /0vx()( * 1 ( 23vx()( * 4 ( /0vx()( * 1 ( 56vx()( * 7 (rL   