3

\u4                 @   s6  d dl 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 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 eddZeddZeddZeddZeddZeddZeddZeddZe Z G dd deZ!G dd de"Z#G dd  d e#Z$G d!d" d"e#Z%G d#d$ d$e"Z&dS )%    N)	timedelta)Decimal)ROUND_UP)AvgCountSum)TemplateResponse)now)TemplateView)AbstractPromotion)get_user_model)	get_class	get_modelzdashboard.widgetsRelatedFieldWidgetWrapperofferConditionalOffervoucherVoucherbasketBasketpartner
StockAlert	catalogueProductorderOrderLinec                   s`   e Zd ZdZdd Z fddZdd Zdd	 Zefd
dZ	dddZ
dddZdd Z  ZS )	IndexViewa  
    An overview view which displays several reports about the shop.

    Supports the permission-based dashboard. It is recommended to add a
    index_nonstaff.html template because Oscar's default template will
    display potentially sensitive store information.
    c             C   s   | j jjrdgS ddgS d S )Nzdashboard/index.htmlzdashboard/index_nonstaff.html)requestuseris_staff)self r"   5/var/www/html/oscar2019/oscar/apps/dashboard/views.pyget_template_names#   s    
zIndexView.get_template_namesc                s    t  jf |}|j| j  |S )N)superget_context_dataupdate	get_stats)r!   kwargsctx)	__class__r"   r#   r&   )   s    zIndexView.get_context_datac             C   s   t jjt t jdS )z
        Return active conditional offers of type "site offer". The returned
        ``Queryset`` of site offers is filtered by end date greater then
        the current date.
        )end_datetime__gt
offer_type)r   objectsfilterr	   SITE)r!   r"   r"   r#   get_active_site_offers.   s    z IndexView.get_active_site_offersc             C   s   t jjt dS )z
        Get all active vouchers. The returned ``Queryset`` of vouchers
        is filtered by end date greater then the current date.
        )r,   )r   r.   r/   r	   )r!   r"   r"   r#   get_active_vouchers7   s    zIndexView.get_active_vouchersc             C   s@   d}x6|j  D ]*}|jjr*|| j|7 }q||jj 7 }qW |S )z
        Get the number of promotions for all promotions derived from
        *abstract_base*. All subclasses of *abstract_base* are queried
        and if another abstract base class is found this method is executed
        recursively.
        r   )__subclasses___metaabstractget_number_of_promotionsr.   count)r!   Zabstract_basetotalclsr"   r"   r#   r6   >   s    z"IndexView.get_number_of_promotionsNc             C   s$   |dkri }t j|d< t jjf |S )z
        Get all open baskets. If *filters* dictionary is provided they will
        be applied on all open baskets and return only filtered results.
        Nstatus)r   OPENr.   r/   )r!   filtersr"   r"   r#   get_open_basketsM   s    
zIndexView.get_open_baskets   
   c             C   s  t  jddd}|t|d d }tjj|d}g }x^td|dD ]N}|tdd }|j||d}	|	jtdd	 pzt	d
}
|j
||
d |}qBW tdd |D }d}x||d k r|d9 }qW || jt	dtd}||9 }|rV|t	d }x |D ]}t|d | |d< qW g }|t	t| }xFtt|d D ]}|j
||  q<W ng }x|D ]}d|d< q`W |||d}|S )a   
        Get report of order revenue split up in hourly chunks. A report is
        generated for the last *hours* (default=24) from the current time.
        The report provides ``max_revenue`` of the hourly order revenue sum,
        ``y-range`` as the labeling for the y-axis in a template and
        ``order_total_hourly``, a list of properties for hourly chunks.
        *segments* defines the number of labeling segments used for the y-axis
        when generating the y-axis labels (default=10).
        r   )minutesecond   )hours)date_placed__gt   )rD   date_placed__lttotal_incl_taxtotal_incl_tax__sumz0.0)end_timerG   c             S   s   g | ]}|d  qS )rG   r"   ).0xr"   r"   r#   
<listcomp>u   s    z/IndexView.get_hourly_report.<locals>.<listcomp>2   r?   1)roundingz100.0Z
percentage)order_total_hourlyZmax_revenuey_range)r	   replacer   r   r.   r/   range	aggregater   Dappendmaxquantizer   intstrreversed)r!   rC   segmentsZtime_now
start_timeorders_last_dayrP   hourrI   Zhourly_ordersr8   	max_valueZdivisorZsegment_sizeitemrQ   Zy_axis_stepsidxr*   r"   r"   r#   get_hourly_reportW   sH    


zIndexView.get_hourly_reportc             C   sF  t  tdd }tjj }|j|d}tjjtjd}tjjtjd}t	jj|dj
 }|j
 ||jtdd pxtd|jtdd	 ptd| jddtjj|d
j
 | jd|ij
 tjj
 |j
 |j
 | j j
 | j j
 | j tjj
 | j j
 |j
 t	jj
 |jtdd	 p"td|jdjdjtddd}|S )Nr>   )rC   )rD   )r:   )Z	order__inrG   Ztotal_incl_tax__avgz0.00rH   )Zdate_joined__gtZdate_created__gtr:   id)freq)Ztotal_orders_last_daytotal_lines_last_dayZaverage_order_costsZtotal_revenue_last_dayZhourly_report_dictZtotal_customers_last_dayZtotal_open_baskets_last_dayZtotal_productsZtotal_open_stock_alertsZtotal_closed_stock_alertsZtotal_site_offersZtotal_vouchersZtotal_promotionsZtotal_customersZtotal_open_basketsZtotal_ordersZtotal_linestotal_revenueZorder_status_breakdown)r	   r   r   r.   allr/   r   r;   CLOSEDr   r7   rT   r   rU   r   rc   Userr=   r   r1   r2   r6   order_byvaluesannotater   )r!   Zdatetime_24hrs_agoordersr^   Zopen_alertsZclosed_alertsrf   statsr"   r"   r#   r(      sJ    





zIndexView.get_stats)N)r>   r?   )__name__
__module____qualname____doc__r$   r&   r1   r2   r   r6   r=   rc   r(   __classcell__r"   r"   )r+   r#   r      s   	


9r   c                   s(   e Zd Z fddZ fddZ  ZS )PopUpWindowCreateUpdateMixinc                s   t  jf |}tj| jjks*tj| jjkrZ| jjjtj| jjjtj}||d< tj|d< tj| jjksvtj| jjkr| jjjtj| jjjtj}||d< tj|d< |S )Nto_fieldto_field_varis_popupis_popup_var)	r%   r&   r   TO_FIELD_VARr   GETPOSTgetIS_POPUP_VAR)r!   r)   r*   rv   rx   )r+   r"   r#   r&      s    

z-PopUpWindowCreateUpdateMixin.get_context_datac                s(   d| _ tj| jjkrd| _ t j||S )NFT)rx   r   r~   r   r|   r%   forms_valid)r!   formformset)r+   r"   r#   r      s    z(PopUpWindowCreateUpdateMixin.forms_valid)rp   rq   rr   r&   r   rt   r"   r"   )r+   r#   ru      s   ru   c                   s   e Zd Z fddZ  ZS )PopUpWindowCreateMixinc       	         s   t  j||}tj| jjkr~|j}| jjjtj}|r@t	|}n
|j
jj}|j|}tjt	|t	|d}t| jdd|iS |S d S )N)valueobjz%dashboard/widgets/popup_response.htmlpopup_response_data)r%   r   r   r~   r   r|   instancer}   rz   rZ   r4   pkattnameserializable_valuejsondumpsr   )	r!   r   r   responser   rv   attrr   r   )r+   r"   r#   r      s    



z"PopUpWindowCreateMixin.forms_valid)rp   rq   rr   r   rt   r"   r"   )r+   r#   r      s   	r   c                   s   e Zd Z fddZ  ZS )PopUpWindowUpdateMixinc                s   t  j||}tj| jjkr|j}|j}| jjjtj	}|rFt
|}n|jj}| jjjd }|j|}	tjdt
|t
|t
|	d}
t| jdd|
iS |S d S )Nr   change)actionr   r   	new_valuez%dashboard/widgets/popup_response.htmlr   )r%   r   r   r~   r   r|   r   r4   r}   rz   rZ   r   r   resolver_matchr)   r   r   r   r   )r!   r   r   r   r   optsrv   r   r   r   r   )r+   r"   r#   r     s$    


z"PopUpWindowUpdateMixin.forms_valid)rp   rq   rr   r   rt   r"   r"   )r+   r#   r     s   	r   c                   s(   e Zd Z fddZ fddZ  ZS )PopUpWindowDeleteMixinc                s>   t  jf |}tj| jjkr:| jjjtj|d< tj|d< |S )Nrx   ry   )r%   r&   r   r~   r   r{   r}   )r!   r)   r*   )r+   r"   r#   r&   -  s
    
z'PopUpWindowDeleteMixin.get_context_datac                st   d| _ tj| jjkrd| _ | j }t j|f||}tj|jkrl|j}t	j
dt|d}t|dd|iS |S dS )z
        Calls the delete() method on the fetched object and then
        redirects to the success URL, or closes the popup, it it is one.
        FTdelete)r   r   z%dashboard/widgets/popup_response.htmlr   N)rx   r   r~   r   r|   
get_objectr%   r   r   r   r   rZ   r   )r!   r   argsr)   r   r   obj_idr   )r+   r"   r#   r   6  s    
zPopUpWindowDeleteMixin.delete)rp   rq   rr   r&   r   rt   r"   r"   )r+   r#   r   +  s   	r   )'r   datetimer   decimalr   rU   r   django.db.modelsr   r   r   django.template.responser   Zdjango.utils.timezoner	   Zdjango.views.genericr
   oscar.apps.promotions.modelsr   oscar.core.compatr   oscar.core.loadingr   r   r   r   r   r   r   r   r   r   rj   r   objectru   r   r   r   r"   r"   r"   r#   <module>   s2   







 . %