o
    wh\                     @   s\  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 ZCeddd2d3 ZDeddd4d5 ZEeddd6d7 ZFeddej<d8d9 ZGeddej<d:d; ZHd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/hyperkenya/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   sF  | d }stdddddS | d}|ttjvr%tdddddS d }| d	 }rKz	tjj |d
}W n tjyJ   tddddd Y S w t|||}|rU|S t	| |||}zt
|| W n ty } ztdt|dddW  Y d }~S d }~ww |dkr|r||j td|jt|jt|jpdt|jdS )Nitemsre   zNo sale items providedr   r   r   r0   zInvalid payment methodcustomer_idr   zCustomer not foundi  r3   successr   )r   r   r-   
change_duebalance_due)r   r   dictr   PAYMENT_METHOD_CHOICESr   rf   DoesNotExistvalidate_payment_methodcreate_sale_recordprocess_sale_itemsr   r   update_credit_balancerD   r5   r-   r   outstanding_credit)	rp   r   r   r0   rI   r   validation_errorr   rv   r|   r|   r}   r   >  s>   
"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   cheque_datezCheque number and date requiredr   z0Invalid cheque date format (YYYY-MM-DD required)r3   z"Customer required for credit saleszCustomer credit limit exceeded)r   r   r   r   r   r   can_purchase_on_credit)r   r0   rI   r|   r|   r}   r   j  sj   &

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   quantityN)r   int)r   itemr|   r|   r}   	<genexpr>  s
    
z%create_sale_record.<locals>.<genexpr>r   r3   )rI   r-   r0   r   r   r.   r   )r   r   r2   r   r4   r   r   )r   r   credit_paidr   rD   r|   )sumr   updater   r   r   rf   create)rp   r   rI   r0   r-   	sale_datar|   r|   r}   r     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_products  s   r  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   Fr
  )r   r   r   r  r   rf   r1   r   ri   r   rn   )rp   r   r   r|   r|   r}   search_customers   s   r  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_sale	  sV   

"

r!  c              
   C   s^  t t|d}| jdkrzT|j D ]}|j}| j|j7  _|  t	
d|j d|j d q|j}|  t	
d| d | jdd	krUt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 stockzSale #z deleted successfullyr  r  T)r   r   z8Sale deleted successfully and stock quantities restored.r   z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   r5   deleter  r   r   r    r   r   rc   re   r   )rp   r   r   r   r   sale_numberrv   r|   r|   r}   delete_saleL  s0   

"r%  )I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   modelsr   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  r  r!  r%  r|   r|   r|   r}   <module>   st   


 
M

,,!
 

A