
    H;i˱                        d dl mZmZmZmZmZ d dlmZ d dlm	Z	m
Z
 d dlmZmZmZmZ d dl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mZ 	 d dlmZ 	 d dl m!Z! d dl"m#Z# dZ$dZ%	 d dl+m,Z, dZ-	 d dl.m/Z/ dZ0	 d dl1m2Z2 dZ3 ejN                  e(      Z4 e       Z5e5jm                  d      dedee7ef   fd       Z8e5js                  deejt                            ed d d       ed d
d!d"#       ee      fd$e;d%e;d&efd'       Z<e5js                  d(eejz                            ed d d)       ed d
d!d*#       ee      fd$e;d%e;d&efd+       Z>e5js                  d,eej~                            ed d d-       ed d
d!d.#       ee      fd$e;d%e;d&efd/       Z@e5js                  d0eej                            ed d d1       ed d
d!d2#       ee      fd$e;d%e;d&efd3       ZBe5js                  d4eej                            ed d d5       ed d
d!d6#       ee      fd$e;d%e;d&efd7       ZDe5js                  d8eej                            ed d d9       ed d
d!d:#       ee      fd$e;d%e;d&efd;       ZFe5js                  d<ej                         ed
d
d=       ed d
d>       edd?@       eddA@       ee      fdBe;dCe;dDe7dEe;d&ef
dF       ZHe5jm                  dG      dH        ZIe5jm                  dI       eddJ@      fdKe7fdL       ZJe5jm                  dM       eddN@      fdKe7fdO       ZKe5js                  dPej                         ed
d
d=       ed d
d>       eddQ@       ee      fdBe;dRe;dDe7d&efdS       ZMe5js                  dT       ed
d
d=       ed d
d!d>#       eddQ@       eddA@       eddU@       eddV@       ee      fdBe;dRe;dDe7dEe;dWe;dXe;d&efdY       ZNe5js                  dZej                         ed[d
d=       ed[d
d d>#       edd\@       ee      fdBe;dRe;dDe7d&efd]       ZPe5js                  d^ej                  d_g`       ed[da@       eddb@       eddc@       eddd@       edde@       ee      fdEe;dWe;dXe;dfe7dge7d&efdh       ZRe5jm                  di       eddJ@      fdKe7fdj       ZSe5js                  dkej                  d_g`       ed
d
d=       edld
d>       eddm@       eddA@       eddU@       eddV@       eddn@       ee      fdBe;dRe;dDe7dEe;dWe;dXe;doeUd&efdp       ZVe5js                  dq       ed
d
d=       ed d
d>       eddA@       eddU@       eddV@       eddr@       ee      fdBe;dRe;dEe;dWe;dXe;dse7d&efdt       ZWe5jm                  du       eddv@      fdwe7fdx       ZXe5jm                  dyej                         ed[dz@      fdEe;fd{       ZZe5jm                  d|ej                         ee      fd}ej                  d&efd~       Z]e5js                  dej                  d_g`       ed[d@       edd@       edd@       edd@       ee      fdEe;dWe;dXe;dDe7d&ef
d       Z_e5js                  dej                  d_g`       ed[d@       edd@       edd@       ee      fdEe;dWe;dDe7d&efd       Zae5js                  dej                  d_g`       ed[da@       edd@       edd@       eddd@       edde@       ee      fdEe;dWe;dXe;dfe7dge7d&efd       Zce5js                  dej                  d_g`       ed[da@       eddb@       edd@       edld
d d#       ee      fdEe;dWee;   dee;   d%e;d&ef
d       Zee5js                  dej                  d_g`       ed[da@       eddb@       edd@       edld
d d#       ee      fdEe;dWee;   dee;   d%e;d&ef
d       Zge5js                  dej                  d_g`       ed[da@       eddb@       edd@       edld
d d#       ee      fdEe;dWee;   dee;   d%e;d&ef
d       Zie5js                  dej                  d_g`       ed
d
d=       edld
d>       eddA@       eddU@       eddV@       edd@       ee      fdBe;dRe;dEe;dWe;dXe;dse7d&efd       Zky# e$ r
 d dlmZ Y w xY w# e$ r9Z& ejN                  e(      Z)e)jU                  de&        dZ!dZ#dZ$dZ%Y dZ&[&dZ&[&ww xY w# e$ r5Z& ejN                  e(      Z)e)jU                  de&        dZ,dZ-Y dZ&[&	dZ&[&ww xY w# e$ r5Z& ejN                  e(      Z)e)jU                  de&        dZ/dZ0Y dZ&[&	<dZ&[&ww xY w# e$ r5Z& ejN                  e(      Z)e)jU                  de&        dZ2dZ3Y dZ&[&	pdZ&[&ww xY w)    )	APIRouterHTTPExceptionRequestDependsQuery)Session)funcdesc)DictAnyListOptionalN)datedatetime)DemandForecast)CompanyDemandForecaster)forecast_series   )schemas
controller)get_db)compute_daily_sales)compute_service_level_dailyTzCould not import Celery tasks: F)compute_inventory_snapshotz*Could not import inventory snapshot task: )#compute_inventory_planning_snapshotz*Could not import inventory planning task: )train_demand_forecast_modelz0Could not import demand forecast training task: z/webhook/movementrequestreturnc                 $  K   	 | j                          d{   }|j                  dd      }t        j                  dt	        j
                         j                                 t        j                  d|        |dk(  r;|j                  di       j                  dd	      }t        j                  d
|        nX|dk(  r;|j                  di       j                  dd	      }t        j                  d|        nt        j                  d|        dd| dt	        j
                         j                         ||dS 7 +# t        $ r?}t        j                  dt        |              t        ddt        |             d}~ww xY ww)a  
    Webhook endpoint to receive order data (purchase orders or sales orders)
    
    Handles different types of inventory movements based on the event_type field:
    
    Expected data format for purchase orders:
    {
        "event_type": "purchase_order_received",
        "timestamp": "2025-11-25T21:13:08+05:30",
        "purchase_order": {...},
        "purchase_order_lines": [...],
        "inventory_movements": [...]
    }
    
    Expected data format for sales orders:
    {
        "event_type": "sales_order_completed",
        "timestamp": "2025-11-25T21:13:08+05:30",
        "sales_order": {...},
        "sales_order_lines": [...],
        "inventory_movements": [...]
    }
    N
event_typeunknownzReceived order webhook at zEvent type: purchase_order_receivedpurchase_orderidzN/AzPurchase Order ID: sales_order_completedsales_orderzSales Order ID: zUnknown event type: successz)Order data received successfully (event: ))statusmessagereceived_atr    dataz Error processing order webhook:   zError processing order data: status_codedetail)jsongetloggerinfor   now	isoformatwarning	Exceptionerrorstrr   )r   r,   r    order_ides        H/var/www/html/hubwallet-dev/src/smart_inventory/apps/inventory/router.pyinventory_movementr>   C   sl    2#
\\^#XXlI6
01I1I1K0LMNl:,/0 22xx 0"599$FHKK-hZ8922xxr266tUCHKK*8*56 NN1*>?  B:,aP#<<>335$
 	
) $8  
7Ax@A23q6(;
 	

s9   FE ED)E FE 	F:FFFz/sales-orders)response_modelzNumber of sales orders to skip)gedescriptiond   i  z Number of sales orders to return)r@   lerA   skiplimitdbc                     	 t        j                  || |      }|S # t        $ r3}t        j	                  dt        |              t        dd      d}~ww xY w)z Get sales orders with paginationrD   rE   zError fetching sales orders:   zError fetching sales ordersr.   N)r   get_sales_ordersr8   r3   r9   r:   r   )rD   rE   rF   sales_ordersr<   s        r=   rJ   rJ      sZ    S!222DN S4SVH=>4QRRS    	A.AAz/sales-order-linesz#Number of sales order lines to skipz%Number of sales order lines to returnc                     	 t        j                  || |      }|S # t        $ r3}t        j	                  dt        |              t        dd      d}~ww xY w)z%Get sales order lines with paginationrH   z"Error fetching sales order lines: rI   z Error fetching sales order linesr.   N)r   get_sales_order_linesr8   r3   r9   r:   r   )rD   rE   rF   sales_order_linesr<   s        r=   rN   rN      \    X&<<RdRWX   X9#a&BC4VWWXrL   z/inventory-batchesz#Number of inventory batches to skipz%Number of inventory batches to returnc                     	 t        j                  || |      }|S # t        $ r3}t        j	                  dt        |              t        dd      d}~ww xY w)z%Get inventory batches with paginationrH   z"Error fetching inventory batches: rI   z Error fetching inventory batchesr.   N)r   get_inventory_batchesr8   r3   r9   r:   r   )rD   rE   rF   inventory_batchesr<   s        r=   rR   rR      rP   rL   z/inventory-movementsz%Number of inventory movements to skipz'Number of inventory movements to returnc                     	 t        j                  || |      }|S # t        $ r3}t        j	                  dt        |              t        dd      d}~ww xY w)z'Get inventory movements with paginationrH   z$Error fetching inventory movements: rI   z"Error fetching inventory movementsr.   N)r   get_inventory_movementsr8   r3   r9   r:   r   )rD   rE   rF   inventory_movementsr<   s        r=   rU   rU      s\    Z(@@$V[\"" Z;CF8DE4XYYZrL   z/purchase-ordersz!Number of purchase orders to skipz#Number of purchase orders to returnc                     	 t        j                  || |      }|S # t        $ r3}t        j	                  dt        |              t        dd      d}~ww xY w)z#Get purchase orders with paginationrH   z Error fetching purchase orders: rI   zError fetching purchase ordersr.   N)r   get_purchase_ordersr8   r3   r9   r:   r   )rD   rE   rF   purchase_ordersr<   s        r=   rX   rX      sZ    V$88$eT V7Ax@A4TUUVrL   z/purchase-order-linesz&Number of purchase order lines to skipz(Number of purchase order lines to returnc                     	 t        j                  || |      }|S # t        $ r3}t        j	                  dt        |              t        dd      d}~ww xY w)z(Get purchase order lines with paginationrH   z%Error fetching purchase order lines: rI   z#Error fetching purchase order linesr.   N)r   get_purchase_order_linesr8   r3   r9   r:   r   )rD   rE   rF   purchase_order_linesr<   s        r=   r[   r[      s\    [)BB2DX]^## [<SVHEF4YZZ[rL   z/analytics/daily-saleszPage numberzNumber of items per pagez>Date in YYYY-MM-DD format to get daily sales for specific date)rA   zFilter by company IDpage	pagelimitr   
company_idc                     	 t        j                  |||| |      }|d   |d   |d   |d   dS # t        $ r3}t        j	                  dt        |              t        dd	
      d}~ww xY w)zGet daily sales records with pagination. If date is provided, returns sales for that specific date. If company_id is provided, filters by company.)r   r_   r]   perpager,   r]   ra   totalr,   r]   ra   rb   zError fetching daily sales: rI   zError fetching daily salesr.   N)r   get_daily_salesr8   r3   r9   r:   r   )r]   r^   r   r_   rF   resultr<   s          r=   rd   rd      s    
R++BTjW[eno6N6Ni(G_	
 	
  R3CF8<=4PQQRs   ,/ 	A+.A&&A+z/celery/compute-daily-salesc                      t         st        dd      	 t        j                         } | j                  dddS # t
        $ r3}t        j                  dt        |              t        dd	      d
}~ww xY w)z1Trigger daily sales computation using Celery task  zOCelery not available. Daily sales computation service is currently unavailable.r.   startedz$Daily sales computation task started)task_idr)   r*   z-Error starting daily sales computation task: rI   z+Error starting daily sales computation taskN)	daily_sales_celery_availabler   r   delayr$   r8   r3   r9   r:   )taskr<   s     r=   trigger_compute_daily_salesrm      s     (d
 	

c"((* ww=
 	
  cDSVHMN4abbcs   #9 	A5.A00A5z/celery/compute-service-levelzDTarget date in YYYY-MM-DD format. If not provided, uses today's datetarget_datec                 x   t         st        dd      	 | rddlm} 	  |j                  | d       t        j                  |       }| rd	|  nd
}|j                  dd| | dS # t        $ r t        dd      w xY w# t        $ r3}t        j                  dt        |              t        dd      d}~ww xY w)z3Trigger service level computation using Celery taskrg   zQCelery not available. Service level computation service is currently unavailable.r.   r   r   %Y-%m-%dr-   #Invalid date format. Use YYYY-MM-DD for 
 for todayrh   z&Service level computation task startedri   r)   r*   rn   z/Error starting service level computation task: rI   z-Error starting service level computation taskN)service_level_celery_availabler   r   strptime
ValueErrorr   rk   r$   r8   r3   r9   r:   rn   r   rl   date_msgr<   s        r=   trigger_compute_service_levelr{     s    
 *f
 	

e)c!!!+z:
 +00=,7U;-(\ ww?zJ&	
 	
  c#<abbc  eFs1vhOP4cdde-   A= A# 1A= #A::A= =	B9.B44B9z"/celery/compute-inventory-snapshotzHTarget date in YYYY-MM-DD format. If not provided, uses yesterday's datec                 x   t         st        dd      	 | rddlm} 	  |j                  | d       t        j                  |       }| rd	|  nd
}|j                  dd| | dS # t        $ r t        dd      w xY w# t        $ r3}t        j                  dt        |              t        dd      d}~ww xY w)z>Trigger daily inventory snapshot computation using Celery taskrg   zVCelery not available. Inventory snapshot computation service is currently unavailable.r.   r   rp   rq   r-   rr   rs   z for yesterdayrh   z+Inventory snapshot computation task startedru   z4Error starting inventory snapshot computation task: rI   z2Error starting inventory snapshot computation taskN)snapshot_celery_availabler   r   rw   rx   r   rk   r$   r8   r3   r9   r:   ry   s        r=   "trigger_compute_inventory_snapshotr   6  s    
 %k
 	

j)c!!!+z:
 *//<,7U;-(=M wwDXJO&	
 	
  c#<abbc  jKCPQF8TU4hiijr|   z/inventory-snapshotsz<Date in YYYY-MM-DD format to get snapshots for specific datera   c                     	 t        j                  ||| |      }|d   |d   |d   |d   dS # t        $ r3}t        j	                  dt        |              t        dd	
      d}~ww xY w)znGet inventory snapshot records with pagination. If date is provided, returns snapshots for that specific date.r   r]   ra   r,   r]   ra   rb   rc   z$Error fetching inventory snapshots: rI   z"Error fetching inventory snapshotsr.   N)r   get_inventory_snapshotsr8   r3   r9   r:   r   r]   ra   r   rF   re   r<   s         r=   r   r   [  s    
Z33BTV]^6N6Ni(G_	
 	
  Z;CF8DE4XYYZ   +. 	A*.A%%A*z%/testing/inventory-planning-snapshotszFilter by location IDzFilter by product IDlocation_id
product_idc           	          	 t        j                  ||| ||||      }|d   |d   |d   |d   dS # t        $ r3}t        j	                  dt        |              t        dd	
      d}~ww xY w)zGet inventory planning snapshot records with pagination and filters. If date is provided, returns snapshots for that specific date.)r   r]   ra   r_   r   r   r,   r]   ra   rb   rc   z-Error fetching inventory planning snapshots: rI   z+Error fetching inventory planning snapshotsr.   N)r    get_inventory_planning_snapshotsr8   r3   r9   r:   r   )	r]   ra   r   r_   r   r   rF   re   r<   s	            r=   r   r   p  s    c<<!#!
 6N6Ni(G_	
 	
  cDSVHMN4abbcs   .1 	A-.A((A-z/testing/service-level.z@Date in YYYY-MM-DD format to get service level for specific datec                     	 t        j                  ||| |      }|d   |d   |d   |d   dS # t        $ r3}t        j	                  dt        |              t        dd	
      d}~ww xY w)zmGet service level records with pagination. If date is provided, returns service level for that specific date.r   r,   r]   ra   rb   rc   zError fetching service level: rI   zError fetching service levelr.   N)r   get_service_levelr8   r3   r9   r:   r   r   s         r=   r   r     s    
T--bt$PWX6N6Ni(G_	
 	
  T5c!fX>?4RSSTr   z"/analytics/service-level-vs-demandzSmart Inventory - Frontend)r?   tagszCompany ID (required)z Filter by location ID (optional)zFilter by product ID (optional)zCStart month in YYYY-MM format (optional, defaults to 11 months ago)zAEnd month in YYYY-MM format (optional, defaults to current month)
month_frommonth_toc           
         	 t        j                  || ||||      }d|ddS # t        $ rO}t        j	                  dt        |              t        j                  dddd	t        |      i
      cY d}~S d}~wt        $ rO}t        j	                  dt        |              t        j                  dddd	t        |      i
      cY d}~S d}~ww xY w)a  
    Get month-wise service level vs demand analytics.
    
    Returns aggregated monthly data:
    - demand_qty: Total demand quantity for the month (integer)
    - fulfilled_qty: Total fulfilled quantity for the month (integer)
    - lost_sales_qty: Total lost sales quantity for the month (integer)
    - service_level: fulfilled_qty / demand_qty (0.0 - 1.0, or 1.0 if no demand)
    
    Date Range:
    - month_from: Start month (YYYY-MM). Defaults to 11 months ago if not provided
    - month_to: End month (YYYY-MM). Defaults to current month if not provided
    - If neither provided, returns last 12 months of data
    
    Filters:
    - company_id: Required - filters data for specific company
    - location_id: Optional - if provided, only data for that location is included
    - product_id: Optional - if provided, only data for that product is included
    - If both location_id and product_id are omitted, aggregates across all locations and products
    )rF   r_   r   r   r   r   Tz8Service level vs demand analytics retrieved successfullyr'   r,   r*   z8Validation error for service level vs demand analytics: FValidation errorVALIDATION_ERRORr9   r'   r*   
error_codedetailsNz2Error fetching service level vs demand analytics: z&Error fetching service level analyticsDATABASE_ERROR)	r   %get_analytics_service_level_vs_demandrx   r3   r9   r:   r   ErrorResponser8   )r_   r   r   r   r   rF   result_datar<   s           r=   get_service_level_vs_demandr     s    :
 FF!#!!
 Q
 	
  
OPSTUPVxXY$$&)c!f%	
 	
  
I#a&RS$$<'c!f%	
 	

s.    # 	CAA60C6CACCCz/celery/compute-slow-moversc                    	 ddl m} 	 | rddlm} 	  |j
                  | d       |j                  |       }| rd
|  nd}|j                  dd| | dS # t        $ r t        dd      w xY w# t        $ r t        dd	      w xY w# t        $ r3}t        j                  dt        |              t        dd      d}~ww xY w)z0Trigger slow mover computation using Celery taskr   )compute_slow_movers_90drg   zCelery task not available.r.   rp   rq   r-   rr   rs   rt   rh   z#Slow mover computation task startedru   z,Error starting slow mover computation task: rI   z*Error starting slow mover computation taskN)*src.smart_inventory.tasks.slow_movers_taskr   ImportErrorr   r   rw   rx   rk   r$   r8   r3   r9   r:   )rn   r   r   rl   rz   r<   s         r=   trigger_compute_slow_moversr     s    

Vb)c!!!+z:
 ',,[9,7U;-(\ ww<XJG&	
 	
)  
/
 	

  c#<abbc  bCCF8LM4`aabs8   A B A- -B A*-BB 	C.B>>Cz/slow-movers
   zDDate in YYYY-MM-DD format. If not provided, defaults to today's datezFilter by is_slow_mover flagis_slow_moverc           
         	 t        j                  || ||||||      }d|ddS # t        $ r  t        $ rO}	t        j                  dt        |	              t        j                  dddd	t        |	      i
      cY d}	~	S d}	~	wt        $ rO}	t        j                  dt        |	              t        j                  dddd	t        |	      i
      cY d}	~	S d}	~	ww xY w)zmGet slow mover snapshots with pagination and filters. If date is not provided, returns data for today's date.)r]   ra   r   r_   r   r   r   Tz"Slow movers retrieved successfullyr   z%Invalid data format for slow movers: FInvalid data formatINVALID_DATAr9   r   NzError fetching slow movers: zError fetching slow moversr   )
r   get_slow_moversr   rx   r3   r9   r:   r   r   r8   )
r]   ra   r   r_   r   r   r   rF   re   r<   s
             r=   r   r     s    $
++!#!'	
 ;
 	
   
<SVHEF$$)%c!f%	
 	
  
3CF8<=$$0'c!f%	
 	

s.   "% CAB;CCACCCz	/planningzLFilter by status (out_of_stock, low_stock, in_stock, slow_mover, dead_stock)r)   c           	          	 t        j                  || |||||      }|S # t        $ r3}t        j	                  dt        |              t        dd      d}~ww xY w)zP
    Get inventory planning data: stock levels, reorder points, and status.
    )r]   ra   r_   r   r   r)   z#Error fetching inventory planning: rI   z!Error fetching inventory planningr.   N)r   get_inventory_planningr8   r3   r9   r:   r   )	r]   ra   r_   r   r   r)   rF   re   r<   s	            r=   r   r   B  sl    Y22!#!
  Y:3q6(CD4WXXYs     	A.AAz"/celery/compute-inventory-planningzFSnapshot date in YYYY-MM-DD format. If not provided, uses today's datesnapshot_datec                 x   t         st        dd      	 | rddlm} 	  |j                  | d       t        j                  |       }| rd	|  nd
}|j                  dd| | dS # t        $ r t        dd      w xY w# t        $ r3}t        j                  dt        |              t        dd      d}~ww xY w)zATrigger inventory planning snapshot computation using Celery taskrg   zVCelery not available. Inventory planning computation service is currently unavailable.r.   r   rp   rq   r-   rr   rs   rt   rh   z4Inventory planning snapshot computation task started)ri   r)   r*   r   z4Error starting inventory planning computation task: rI   z2Error starting inventory planning computation taskN)#inventory_planning_celery_availabler   r   rw   rx   r   rk   r$   r8   r3   r9   r:   )r   r   rl   rz   r<   s        r=   "trigger_compute_inventory_planningr   _  s    
 /k
 	

j)c!!!-<
 388G.;U=/* wwMhZX*	
 	
  c#<abbc  jKCPQF8TU4hiijr|   z/celery/train-demand-forecastz!Company ID to train the model forc                     t         st        dd      	 t        j                  |       }|j                  dd|  | dS # t
        $ r3}t        j                  dt        |              t        dd	      d
}~ww xY w)z8Trigger demand forecast model training using Celery taskrg   zPCelery not available. Demand forecast training service is currently unavailable.r.   rh   z8Demand forecast model training task started for company )ri   r)   r*   r_   z.Error starting demand forecast training task: rI   z,Error starting demand forecast training taskN)	&train_demand_forecast_celery_availabler   r   rk   r$   r8   r3   r9   r:   )r_   rl   r<   s      r=   trigger_train_demand_forecastr     s    
 2e
 	

d*00< wwQR\Q]^$	
 	
  dEc!fXNO4bccds   (> 	A:.A55A:z/predictpayloadc                    	 | j                   | j                  z
  j                  dz   }t        | j                  | j
                  | j                  |      }	 t        j                   || j                  | j
                  | j                  |d      }t        j#                  d| d       t        j&                  | j                  | j
                  | j                  |j)                         D cg c]9  \  }}t        j*                  |d   j-                         t/        |d               ; c}}      S # t        $ r> t        j                  d| j                          t        dd| j                   d      t        $ rO}t        j                  dt        |              t        j                  d	d
ddt        |      i      cY d}~S d}~ww xY w# t$        $ rO}t        j                  dt        |              t        j                  d	dddt        |      i      cY d}~S d}~wt        $ rO}t        j                  dt        |              t        j                  d	dddt        |      i      cY d}~S d}~ww xY wc c}}w )z
    Generate and store demand forecast predictions.
    Automatically deletes existing forecasts for the same date range to avoid duplicates.
    r   )r_   r   r   horizon_dayszModel not found for company_id=r-   zNo model found for company_id=z. Train it first.r.   zError generating forecast: FzError generating forecastFORECAST_GENERATION_ERRORr9   r   Nv1)rF   r_   r   r   df_predictionsmodel_versionzSuccessfully saved z forecast recordsz#Validation error saving forecasts: zInvalid forecast datar   z$Error saving forecasts to database: z"Error saving forecasts to databaser   r   forecast_qty)r   r   )r_   r   r   	forecasts)end_date
start_datedaysr   r_   r   r   FileNotFoundErrorr3   r9   r   r8   r:   r   r   r   save_demand_forecastr4   rx   ForecastResponseiterrowsForecastResponseItemr   float)r   rF   r   df_predsr<   saved_count_rows           r=   forecast_and_storer     s_   
((7+=+==CCaG #))++))%	
,
 55))++))#
 	)+6GHI& ##%%''%% #++-

 3	 (([%%'"3~#67
	 [  
6w7I7I6JKL3G4F4F3GGXY
 	
  
23q6(;<$$/2c!f%	
 	

*  
:3q6(CD$$+)c!f%	
 	
  
;CF8DE$$8'c!f%	
 	


sY   AD2 AG +>J2AG AG
G
G	J AH%J %J 1AI;5J ;J z/analytics/overviewz
Company IDzLocation ID (optional)zProduct ID (optional)zhDate in YYYY-MM-DD format to get slow movers for specific date if no date is provided, uses today's datec           
      H   	 |s%ddl m} |j                         j                  d      }t	        j
                  ||| ||      }d|ddS # t        $ rO}t        j                  dt        |              t        j                  d	d
ddt        |      i      cY d }~S d }~ww xY w)Nr   )r   rq   )r   r_   r   r   Tz)Analytics overview retrieved successfullyr   z#Error fetching analytics overview: Fz!Error fetching analytics overviewr   r9   r   )r   r   todaystrftimer   get_analytics_overviewr8   r3   r9   r:   r   r   )r_   r   r   r   rF   
date_classre   r<   s           r=   r   r     s    
3##%..z:D22!#!
 B
 	
  
:3q6(CD$$7'c!f%	
 	

s   AA	 		B!ABB!B!z/analytics/kpi-summaryzGDate in YYYY-MM-DD format (optional, defaults to latest available data)c           
         	 t        j                  || ||      }d|ddS # t        $ rO}t        j	                  dt        |              t        j                  dddd	t        |      i
      cY d}~S d}~wt        $ rO}t        j	                  dt        |              t        j                  dddd	t        |      i
      cY d}~S d}~ww xY w)a  
    Get KPI summary for frontend dashboard cards.
    
    Returns aggregated metrics:
    - avg_service_level: Average service level (0.0 - 1.0)
    - stockouts_count: Number of products currently out of stock
    - overstock_count: Number of overstocked products
    - understock_count: Number of understocked products  
    - slow_mover_count: Number of slow-moving products
    - total_products_tracked: Total number of products being tracked
    - avg_days_on_hand: Average days of inventory on hand (stock turns indicator)
    )rF   r_   r   r   Tz"KPI summary retrieved successfullyr   z"Validation error for KPI summary: Fr   r   r9   r   NzError fetching KPI summary: zError fetching KPI summaryr   )	r   get_kpi_summaryrx   r3   r9   r:   r   r   r8   )r_   r   r   rF   re   r<   s         r=   r   r     s    &
++!#	
 ;
 	
  
9#a&BC$$&)c!f%	
 	
  
3CF8<=$$0'c!f%	
 	

s.   ! 	CAA4.C4C AC
C
Cz/analytics/stock-vs-demandzJFilter by location ID (optional, aggregates all locations if not provided)zHFilter by product ID (optional, aggregates all products if not provided)c           
         	 t        j                  || ||||      }d|ddS # t        $ r  t        $ rO}t        j                  dt        |              t        j                  dddd	t        |      i
      cY d}~S d}~wt        $ rO}t        j                  dt        |              t        j                  dddd	t        |      i
      cY d}~S d}~ww xY w)aL  Get month-wise stock vs demand analysis.
    
    Returns aggregated monthly data:
    - avg_daily_demand: Average daily demand across all dates in the month (integer)
    - available_stock: Average available stock across all dates in the month (integer)
    
    Date Range:
    - month_from: Start month (YYYY-MM). Defaults to 11 months ago if not provided
    - month_to: End month (YYYY-MM). Defaults to current month if not provided
    - If neither provided, returns last 12 months of data
    
    Filters:
    - company_id: Required - filters data for specific company
    - location_id: Optional - if provided, only data for that location is included
    - product_id: Optional - if provided, only data for that product is included
    - If both location_id and product_id are omitted, aggregates across all locations and products
    )r_   r   r   r   r   Tz/Stock vs demand analysis retrieved successfullyr   z2Invalid data format for stock vs demand analysis: Fr   r   r9   r   Nz)Error fetching stock vs demand analysis: z'Error fetching stock vs demand analysisr   )
r   get_analytics_stock_vs_demandr   rx   r3   r9   r:   r   r   r8   )r_   r   r   r   r   rF   re   r<   s           r=   r   r   G  s    4"
99!#!!
 H
 	
   
I#a&RS$$)%c!f%	
 	
  
@QIJ$$='c!f%	
 	

s.    # CAA?9C?CACCCz/analytics/fastest-movingz Filter by category ID (optional)z2Number of products to return (default 10, max 100)category_idc                    	 t        j                  || |||      }|S # t        $ r}t        dt	        |            d}~wt
        $ r?}t        j                  dt	        |              t        ddt	        |             d}~ww xY w)z@Get fastest moving products by ads_30d (highest sales velocity).rF   r_   r   r   rE   r-   r.   Nz(Error fetching fastest moving products: rI   )r   get_fastest_moving_productsrx   r   r:   r8   r3   r9   r_   r   r   rE   rF   re   ver<   s           r=   r   r     s    
77!##
  =CG<< 
?AxHI=c!fXF
 	

    	B=B	:BBz/analytics/most-stagnantc                    	 t        j                  || |||      }|S # t        $ r}t        dt	        |            d}~wt
        $ r?}t        j                  dt	        |              t        ddt	        |             d}~ww xY w)z]Get most stagnant products by ads_90d (lowest sales velocity) with excess stock calculations.r   r-   r.   Nz'Error fetching most stagnant products: rI   )r   get_most_stagnant_productsrx   r   r:   r8   r3   r9   r   s           r=   #get_most_stagnant_products_endpointr     s    
66!##
  =CG<< 
>s1vhGH<SVHE
 	

r   z/analytics/most-urgentc                    	 t        j                  || |||      }|S # t        $ r}t        dt	        |            d}~wt
        $ r?}t        j                  dt	        |              t        ddt	        |             d}~ww xY w)zWGet most urgent order requirements based on urgency score (days of cover vs lead time).r   r-   r.   Nz%Error fetching most urgent products: rI   )r   get_most_urgent_productsrx   r   r:   r8   r3   r9   r   s           r=   !get_most_urgent_products_endpointr     s    
44!##
  =CG<< 
<SVHEF:3q6(C
 	

r    zLFilter by status (in_stock, low_stock, out_of_stock, slow_mover, dead_stock)c           
      :   	 t        j                  || |||||      }|t        j                  d       g | |dd}d|ddS # t        $ rO}t        j                  d	t        |              t        j                  d
dddt        |      i      cY d}~S d}~wt        $ ry}t        j                  dt        |              ddl
}	t        j                  d|	j                                 t        j                  d
dddt        |      i      cY d}~S d}~ww xY w)zFGet comprehensive inventory details with joins across multiple tables.)rF   r]   ra   r_   r   r   status_filterNzController returned None resultr   )itemsr]   ra   rb   Tz(Inventory details retrieved successfullyr   z(Validation error for inventory details: Fr   r   r9   r   z"Error fetching inventory details: zTraceback: z Error fetching inventory detailsr   )r   get_inventory_detailsr3   r7   rx   r9   r:   r   r   r8   	traceback
format_exc)
r]   ra   r_   r   r   r)   rF   re   r<   r   s
             r=   r   r     s%   ,
11!#! 
 >NN<="	F A
 	
  
?AxHI$$&)c!f%	
 	
  	
9#a&BC{9#7#7#9":;<$$6'c!f%	
 	
		
s1   ?A 	DABDD!A.DDD)lfastapir   r   r   r   r   sqlalchemy.ormr   
sqlalchemyr	   r
   typingr   r   r   r   loggingr   r   )src.smart_inventory.apps.inventory.modelsr   *src.smart_inventory.core.demand_forecasterr   ,src.smart_inventory.core.prediction_pipeliner   r   r   r   src.utils.dbr   r   utils.db*src.smart_inventory.tasks.daily_sales_taskr   ,src.smart_inventory.tasks.service_level_taskr   rj   rv   r<   	getLogger__name__logger_tempr7   1src.smart_inventory.tasks.inventory_snapshot_taskr   r~   1src.smart_inventory.tasks.inventory_planning_taskr   r   .src.smart_inventory.tasks.demand_forecast_taskr   r   r3   routerpostr:   r>   r2   SalesOrderOutintrJ   SalesOrderLineOutrN   InventoryBatchOutrR   InventoryMovementOutrU   PurchaseOrderOutrX   PurchaseOrderLineOutr[   PaginatedDailySalesResponserd   rm   r{   r   "PaginatedInventorySnapshotResponser   r   PaginatedServiceLevelResponser   ServiceLevelVsDemandResponser   r   SlowMoverResponseboolr   r   r   TrainDemandForecastResponser   r   ForecastRequestr   AnalyticsOverviewResponser   KPISummaryResponser   StockVsDemandResponser   FastestMovingResponser   MostStagnantResponser   MostUrgentResponser   InventoryResponser        r=   <module>r     s   E E " ! , ,  # D N H ! #
+NX#' %)"&\ $0e*.'3Z-1* 
		8	$	  !;
g ;
$sCx. ;
 ";
~ OD1F1F,GHaA+KLsqT7YZ&/S
SS 	S IS  g6O6O1PQaA+PQsqT7^_&/X
XX 	X RX  g6O6O1PQaA+PQsqT7^_&/X
XX 	X RX "48T8T3UVaA+RSsqT7`a&/Z
ZZ 	Z WZ tG4L4L/MNaA+NOsqT7\]&/V
VV 	V OV #D9U9U4VWaA+STsqT7ab&/[
[[ 	[ X[ $W5X5XYaA=9312LMd(hiD.DE&/R
RR R 	R
 	R ZR* *+c ,c. ,-T/uv!e!e .!eH 12T/yz!j!j 3!jH "73]3]^aA=90JKd(fg&/	Z
ZZ Z 		Z _Z( 34aA=9t9STd(fgD.DET/FGD.DE&/c
cc c 	c
 c c 	c 5cB $W5Z5Z[ca];s8RSd(jk&/	T
TT T 		T \T* 0AeAe  nJ  mK  LC-DET/QRD.OPD.st$,op&/;
;
;
 ;
 	;

 ;
 	;
 L;
~ *+T/uv#b#b ,#bL N7+D+DLhKijaA=9/IJd(noD.DET/FGD.DE2PQ&//

/
/
 /
 	/

 /
 /
 /
 	/
 k/
d KaA=90JKD.DET/FGD.DE*xy&/Y
YY Y 	Y
 Y Y 	Y Y8 12t1yz!j!j 3!jH ,W=`=`aC-PQdd bd4 Z(@(@A &/K$$KK BK\ !'2S2S\x[yzC\:T/GHD.EFd  )S  T&/"
"
"
 "
 	"

 	"
 {"
J $W5O5OWsVtuC\:T/GHd(qr&/	/
/
/
 /
 		/
 v/
d (9V9V^z]{|C-DET/{|D.xyD.st$,op&/;
;
;
 ;
 	;

 ;
 	;
 };
| '8U8U]y\z{C-DE!&t9[!\!&t9[!\raC5ij&/

#
 #
 	

 	
 |
8 &w7S7S[wZxyC-DE!&t9[!\!&t9[!\raC5ij&/

#
 #
 	

 	
 z
: $W5O5OWsVtuC-DE!&t9[!\!&t9[!\raC5ij&/

#
 #
 	

 	
 v
` Bw88@\?]^aA=9/IJD.DET/FGD.DE*xy&/6

6
6
 6
 	6

 6
 6
 	6
 _6
I       +#'##H-K9!=>"&#( %*"+  &#'##H-KDQCHI!% %	&  0#'##H-KDQCHI*.'*/'	0  3#'##H-KJ1#NO"&-2*	3sr   c0 d (e 1f  :f= 0c?>c?e .d;;e e=*e88e= f:*f55f:=g7*g22g7