o
    ho                     @   sd  d dl Z d dlZe e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 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 d dlmZmZmZmZm Z  d dl!m"Z"m#Z# ddl$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/ d dlmZ d dl0Z0d dl1m2Z2 d dl3m4Z4 d dl5m6Z6 d dlm7Z7 d dl8Z8e dZedddd Z9edddd Z:eddd d! Z;e2ej<edded"d#gd$d% Z=d&d' Z>d(d) Z?d*d+ Z@d,d- ZAd.d/ ZBd0d1 ZCd2d3 ZDeddd4d5 ZEeddd6d7 ZFeddd8d9 ZGeddej<d:d; ZHeddej<d<d= ZIdS )>    N)Decimal)	Paginator)modelformset_factory)renderget_object_or_404redirect)JsonResponseHttpResponse)login_required)transaction)	timedelta)datetime)require_http_methods)SumCountQFDecimalField)
TruncMonthCoalesce   )SaleFormSaleItemForm)SaleSaleItem)Product)Customer)Shop)r   )csrf_exempt)timezone)messages)	localtimesalesz/auth/login/)	login_urlc                 C   sr  z%t   }|t| d }|jdd}|tdd }|tdd }W n% tyJ } ztd|  t	| di i i dd	W  Y d }~S d }~ww z2t
jj|d
jtdtdtdddtdtdddtdtdddtdtdddtdd}W n# ty } ztd|  ddddddd}W Y d }~nd }~ww t
jj|djtdtdtdddtdtdddtdtdddtdtdddd}|tdd }	t
jj|	|djtddd pd}
d}|
dkr|d pd|
 |
 d }t
jj|djtdtdtdddtdtdddtdtdddtdtdddd}t
jj|djtddd jtdtdtdddtdtdddtdtdddtdtddddd }t
jjddjtdttd!td"t d# d$jdd%}|jtd&dd pd}|d'  }t
jjd|d(jtdttd!td"t d# d)jdd*d'd+}|jtd,dd pd}t
jd'd-d d. }t
jjdd t
jjdd/d0 t
jjdd1d0 t
jjdd1d0tdd2 pdd3}d4}d}|dkr|d pd| d }|||t|||d5 pdt|dt|d|||d d6 ||d7}t	| d|S )8N)daysr   )day      z&Error in dashboard date calculations: zsales/sale_dashboard.htmlz6Unable to load dashboard data. Please try again later.)daily_salesweekly_salesmonthly_saleserror_message)sale_date__datetotal_amountcashpayment_method)filtermpesacreditchequeid)total_sales
cash_salesmpesa_salescredit_salescheque_salestransaction_countzError calculating daily sales: r   sale_date__date__gte)r6   r7   r8   r9   r:      )r=   sale_date__date__lt)totalr@   r6   d   	sale_date)monthrC   credit_amount0)output_field)outstanding)outstanding__gtrG   customer)r0   r?   )outstanding_amount)outstanding_amount__gtz-outstanding_amountrJ   
-sale_date
   T)r0   cheque_clearedFtotal_amount__sum)total_chequescleared_chequespending_chequespending_amounti r;      )r(   r)   r*   six_months_salescheque_statsdaily_transactionsweekly_growthmonthly_target_percentagetotal_outstanding_creditcustomers_with_debtoverdue_debtstotal_overdue_amountrecent_sales)r   nowdater   weekdayreplace	Exceptionloggererrorr   r   objectsr1   	aggregater   r   r   annotater   valuesorder_byr   r   r   r   distinctcountselect_relatedlistround)requesttodaystart_of_weekstart_of_monthsix_months_agotwo_weeks_agoer(   r)   prev_week_startprev_week_salesrX   r*   rU   credit_sales_with_balancerZ   r[   r\   r]   r^   rV   monthly_targetrY   context r|   $/var/www/html/kangema/sales/views.py	dashboard#   s  
		


r~   c                 C   s  t jddd}| jdd }|r;|t|dt|dB t|dB t|d	B t|d
B t|dB t|dB }| jdd}|rJ|j|d}| jdd}| jdd}|rtzt	
|d }|j|d}W n	 tys   Y nw |rzt	
|d }|j|d}W n	 ty   Y nw | jddkrtdd}d|d< t|}	|	g d |D ]5}
|
jr|
jj d|
jj nd}|	|
j|
jd||
j|
 |
jrdnd|
jj|
jpd|
jpdg	 q|S t|d }| jd!}||}d"|i}t | d#|S )$NrI   userrL   search )id__icontains)customer__first_name__icontains)customer__last_name__icontains)customer__phone__icontains)mpesa_reference__icontains)cheque_number__icontains)user__username__icontainsr0   r/   	date_fromdate_to%Y-%m-%dr<   )sale_date__date__lteexportcsvztext/csv)content_typez%attachment; filename="sales_list.csv"zContent-Disposition)	zSale IDDater   AmountzPayment MethodStatusz	Served ByzMpesa ReferencezCheque Number zWalk-inz%Y-%m-%d %H:%MCompletePending   pager"   zsales/sales_list.html)!r   rf   rm   rj   GETgetstripr1   r   r   strptimer`   
ValueErrorr	   r   writerwriterowrI   
first_name	last_namer5   rB   strftimer-   get_payment_method_displayis_completer   usernamempesa_referencecheque_numberr   get_pager   )rp   r"   search_queryr0   r   r   	from_dateto_dateresponser   salecustomer_name	paginatorpage_numberpage_objr{   r|   r|   r}   
sales_list   s|   

 


r   c                 C   s0   t t|d}tjj|d}||d}t| d|S )Nr5   r   )r   
sale_itemszsales/sale_detail.html)r   r   r   rf   r1   r   )rp   sale_idr   r   r{   r|   r|   r}   sale_detail   s   r   r   POSTc              
   C   s   | j dkrt| dtj | jdS zt| j}d|v r"t	|W S t
| |W S  tjy:   tddddd	 Y S  tyV } ztdt|dd
d	W  Y d }~S d }~ww )Nr   zsales/make_sale.html)shopr   queryre   zInvalid JSONstatusmessage  r     )methodr   r   rf   firstr   jsonloadsbodyhandle_live_searchprocess_saleJSONDecodeErrorr   rc   str)rp   datarv   r|   r|   r}   	make_sale  s    

"r   c                 C   s   | d   }| ddkr*tjt|dt|dB d d }tddd	 |D iS | dd
krPtjjt|dt|dB dd}tddd	 |d d D iS tdddddS )Nr   typerI   name__icontainsphone__icontainsrM   	customersc                 S   s   g | ]}|j |j|jd qS )r5   namephoner   ).0cr|   r|   r}   
<listcomp>,  s    z&handle_live_search.<locals>.<listcomp>productbarcode__icontainsr   )stock_quantity__gtproductsc                 S   s&   g | ]}|j |jt|j|jd qS ))r5   r   pricestock)r5   r   r   selling_pricestock_quantity)r   pr|   r|   r}   r   5  s    re   zInvalid search typer   r   r   )r   r   r   rf   r1   r   r   r   )r   r   r   r   r|   r|   r}   r   &  s&   




r   c              
   C   s  | d }stdddddS | dg }|s!tdddddS d }| d	 }rGz	tjj |d
}W n tjyF   tddddd Y S w tdd |D }tdd |D }d}|D ]D}	|	d dkr|	 dddkrd}|s|tddddd  S t|drt|dd}
tt	|	d }|
| |j
krtddddd  S q]|r||k rtdd |D |d }n|rt|dd dn|d }t| ||||}ddlm} |D ][}	|	 dddkr.||	d tt	|	d d }|	d d!kr|	 d"i  d#r|	d" d# |d#< n|	d d$kr%|	 d"r%|	d"  d%|d%< |	d"  d&|d&< |jjd*i | qzt|| W n" tyX } z|  tdt	|dddW  Y d }~S d }~ww td'|jt	|jt	|t	t|| td(d)S )+Nitemsre   zNo sale items providedr   r   r   payment_methodszNo payment methods providedcustomer_idr   zCustomer not foundi  c                 s   ,    | ]}t t|d  t|d  V  qdS r   quantityNr   r   intr   itemr|   r|   r}   	<genexpr>P  s   * zprocess_sale.<locals>.<genexpr>c                 s   0    | ]}| d ddkrtt|d  V  qdS amountr   Nr   r   r   r   r   r|   r|   r}   r   Q     . Fr   r3   r   r   T"Customer required for credit salescredit_limitcurrent_credit_balanceCustomer credit limit exceededc                 s        | ]}|d  dkr|V  qdS )r   r3   Nr|   r   mr|   r|   r}   r   e      c                 S   s   |  ddS )Nr   r   )r   )xr|   r|   r}   <lambda>h  s    zprocess_sale.<locals>.<lambda>)keyr   )SalePayment)r   r0   r   r2   detailsr   r4   r   cheque_datesuccessrE   )r   r   r-   
total_paidbalance_duer|   )r   r   r   rf   DoesNotExistsumhasattrgetattrr   r   r   nextmax create_multi_payment_sale_recordmodelsr   createprocess_sale_itemsr   deleter5   r-   )rp   r   r   r   rI   r   r-   r  
has_creditr   current_creditrD   primary_methodr   r   payment_datarv   r|   r|   r}   r   >  st   
""r   c                 C   s  |dkrt | ddt | d k rtddddd	S d S |d
kr1| ds/tddddd	S d S |dkrf| dr?| dsHtddddd	S zt| d d W d S  tye   tddddd	 Y S w |dkr|sutddddd	S |t | d stddddd	S d S )Nr.   
cash_givenr   r-   re   zInsufficient cash providedr   r   r   r2   r   zM-Pesa reference requiredr4   r   r   zCheque number and date requiredr   z0Invalid cheque date format (YYYY-MM-DD required)r3   r   r   )r   r   r   r   r   r   can_purchase_on_credit)r   r0   rI   r|   r|   r}   validate_payment_method  sj   &

r  c                 C   s\  t dd |d D }t dd |D }|||d | j||kd}|d dkr@t dd |D }||t|| td	d
 ne|d dkrdtdd |D d }	|	rc|	di drc|	d d |d< nA|d dkrtdd |D d }
|
r|
dr||
d d|
d dd n|d dkrt dd |D }||d< d|d< tjj	di |S )Nc                 s   r   r   r   r   r|   r|   r}   r     s
    
z3create_multi_payment_sale_record.<locals>.<genexpr>r   c                 s   r   r   r   r   r|   r|   r}   r     r   r   rI   r-   r0   r   r   r.   c                 s   s<    | ]}|d  dkr| dddkrtt|d V  qdS )r   r.   r   r   Nr   r   r|   r|   r}   r        : rE   r  
change_duer2   c                 s   r   )r   r2   Nr|   r   r|   r|   r}   r     r   r   r   r4   c                 s   r   )r   r4   Nr|   r   r|   r|   r}   r     r   r   r   r   r   r3   c                 s   s<    | ]}|d  dkr| dddkrtt|d V  qdS )r   r3   r   r   Nr   r   r|   r|   r}   r     r  rD   Fr   r|   )
r  r   updater  r   r  r   r   rf   r  )rp   r   rI   r  r   r-   r  	sale_datacash_amountmpesa_methodcheque_methodcredit_paid_nowr|   r|   r}   r	    sD   	
r	  c                 C   s   t dd |d D }|||| j|dkd}|dkr-|t|d t|d | d n*|d	kr8|d
 |d
< n|dkrI||d |d d n|dkrWt|dd|d< tjjdi |S )Nc                 s   s(    | ]}t |d  t|d  V  qdS r   )r   r   r   r|   r|   r}   r     s
    
z%create_sale_record.<locals>.<genexpr>r   r3   r  r.   r  r  r2   r   r4   r   r   r  credit_paidr   rD   r|   )r  r   r  r   r   r   rf   r  )rp   r   rI   r0   r-   r  r|   r|   r}   create_sale_record  s0   	


r!  c              	   C   s   |D ]E}t j j|d d}t|d }|j|k r"td|j t| ||t	|d t	|d | d}t
t|  | j|8  _|  qd S )N
product_idr   r   zInsufficient stock for r   )r   r   r   r   subtotal)r   rf   select_for_updater   r   r   r   r   r   r   supersave)r   r   r   r   r   	sale_itemr|   r|   r}   r    s    


r  c                 C   s   t d}dt| j|iS )NzAfrica/NairobirB   )pytzr   r!   rB   )r   
nairobi_tzr|   r|   r}   get_receipt_data  s   
r*  c                 C   s   t t|d}|j }|jdkr|j}|j|j }nd }d}tj	 |||j|j|||j
|j|j|jj|jd|jrF|jj d|jj nd|jrN|jjnd|jdkrW|jnd d}t| d	|S )
Nr   r3   r   z%Y-%m-%d %H:%M:%Sr   zN/Ar4   )r   r   r   r-   r0   r   r  r  r  r   	served_byrB   r   customer_phoner   zsales/receipt.html)r   r   r   allr0   rD   r-   r   rf   r   r  r  r   r   r   rB   r   rI   r   r   r   r   r   )rp   r   r   r   r   r  r{   r|   r|   r}   receipt_view&  s0   


r.  c                 C   sP   | j dd  }tjt|dt|dB ddddd	}t	t
|d
dS )Nqr   r   r   r5   r   barcoder   r   Fsafe)r   r   r   lowerr   rf   r1   r   ri   r   rn   )rp   r   r   r|   r|   r}   search_productsG  s   r4  c                 C   sX   | j dd  }tjt|dt|dB t|dB dddd	}t	t
|d
dS )Nr/  r   )first_name__icontains)last_name__icontainsr   r5   r   r   r   Fr1  )r   r   r   r3  r   rf   r1   r   ri   r   rn   )rp   r   r   r|   r|   r}   search_customersP  s   r7  c              
   C   s  t t|d}tttddd}| jdkr| jddkrkz2t	| j
}t|d|j|_|d	|j|_|d
}|rBt t|d|_|  tdddW S  tyj } ztdt|dddW  Y d }~S d }~ww t| j|d}|| jtjj|dd}| r| r|  |jdd}	|	D ]#}
tjj|
jd}|j|
j }|
jj j|7  _|
jj  |
  qtdS tdddS | jddkrt|j|j|jr|jjnd d}t|S t|d}|tjj|dd}|||d}t| d|S )Nr   r   T)formextra
can_deleter   x-requested-withXMLHttpRequestr-   r0   r   r   zSale updated successfully!r   re   r   r   )instancer   )querysetF)commitr   zInvalid form data)r-   r0   r   )r   	sale_formr   zsales/update_sale.html) r   r   r   r   r   r   headersr   r   r   r   r   r-   r0   r   rI   r&  r   rc   r   r   r   rf   r1   is_validr5   r   batchr   r   r   r   )rp   r   r   SaleItemFormSetr   r   rv   r@  sale_item_formsetr   r   original_itemstock_adjustmentr{   r|   r|   r}   update_saleY  sV   

"

rH  c              
   C   s  t t|d}| jdkrz|j D ]}|j}| j|j7  _|  t	
d|j d|j d q|jdkrU|jrU|jrUt|jdrUt|jj|j td|j_|j  |j   |j}|  t	
d	| d
 | jddkrtdd	| d
dW S t| d tdW S  ty } z;t	d| dt|  | jddkrtdt|dddW  Y d }~S t| dt|  tdW  Y d }~S d }~ww tddiddS )Nr   r   z	Restored z
 units of z	 to stockr3   r   rE   zSale #z deleted successfullyr;  r<  T)r   r   z8Sale deleted successfully and stock quantities restored.zsales:sales_listzError deleting sale #z: F)r   re   r   r   zError deleting sale: re   zInvalid request method.i  )r   r   r   r   r-  r   r   r   r&  rd   infor   r0   rI   rD   r  r  r   r   paymentsr  r5   rA  r   r   r    r   r   rc   re   r   )rp   r   r   r   r   sale_numberrv   r|   r|   r}   delete_sale  s@   


"rL  )Jloggingr   	getLogger__name__rd   decimalr   django.core.paginatorr   django.formsr   django.shortcutsr   r   r   django.httpr   r	   django.contrib.auth.decoratorsr
   	django.dbr   django.utils.timezoner   r   django.views.decorators.httpr   django.db.modelsr   r   r   r   r   django.db.models.functionsr   r   formsr   r   r
  r   r   inventory.modelsr   customers.modelsr   settings.modelsr   r   django.views.decorators.csrfr   django.utilsr   django.contribr    r!   r(  r~   r   r   atomicr   r   r   r  r	  r!  r  r*  r.  r4  r7  rH  rL  r|   r|   r|   r}   <module>   sv   


 
M

R,*!
 

A