
    H;iT                     `   d dl mZmZmZmZmZmZmZmZm	Z	mZm	Z	m
Z
mZ d dlmZ d dlmZ d dlZ	 d dlmZ d dlmZ  G d deej                        Z G d	 d
eej                        Z G d deej                        Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z  G d de      Z! G d de      Z" G d de      Z# G d de      Z$ G d d e      Z% G d! d"e      Z& G d# d$e      Z' G d% d&e      Z( G d' d(e      Z)y# e$ r d dlmZ d dlmZ Y w xY w))    )ColumnIntegerStringFloatDateTimeDate
ForeignKeyEnumIndexr   r   BooleanUniqueConstraint)relationship)funcN)Base)Companyc                        e Zd ZdZdZdZdZdZy)PurchaseOrderStatusdraftpending_approvalsentreceivedclosedN)__name__
__module____qualname__DRAFTPENDING_APPROVALSENTRECEIVEDCLOSED     H/var/www/html/hubwallet-dev/src/smart_inventory/apps/inventory/models.pyr   r      s    E)DHFr"   r   c                        e Zd ZdZdZdZdZdZy)InventoryBatchStatusactivesold_outexpireddisposeddonatedN)r   r   r   ACTIVESOLD_OUTEXPIREDDISPOSEDDONATEDr!   r"   r#   r%   r%      s    FHGHGr"   r%   c                        e Zd ZdZdZdZdZdZy)MovementTypesalereceipt
adjustmenttransfer_intransfer_outN)r   r   r   SALERECEIPT
ADJUSTMENTTRANSFER_INTRANSFER_OUTr!   r"   r#   r1   r1      s    DGJK!Lr"   r1   c                      e Zd ZdZdZ eeddd      Z ee ed      dd      Z	 ee ed      dd      Z
 e ed	      d
      Z e ed      d
      Z e ed	       ej                                Z e ed	       ej                           ej                                Z ede	g      Z eddd      Z ede
g      Zd Zy)
SalesOrderz2Sales orders table for tracking sales transactionssales_ordersTprimary_keyindexautoincrementcompanies.company_idFnullablerA   locations.location_idtimezonerE   2   server_defaultrL   onupdater   foreign_keysSalesOrderLinesales_orderall, delete-orphanback_populatescascadeLocationc                 V    d| j                    d| j                   d| j                   dS )Nz<SalesOrder(id=, location_id=z, channel='')>)idlocation_idchannelselfs    r#   __repr__zSalesOrder.__repr__9   s1     	8H8H7IUYUaUaTbbeffr"   N)r   r   r   __doc____tablename__r   r   r[   r	   
company_idr\   r   sold_atr   r]   r   now
created_at
updated_atr   companysales_order_lineslocationr`   r!   r"   r#   r=   r=   '   s    <"M	TT	JB,B!Ce[_`J*-D"EPU]abKXt,u=GVBZ%0G$/
KJ$/
U]UYU]U]U_`J 9J<@G$%5m]qrJk]CHgr"   r=   c                      e Zd ZdZdZ eeddd      Z ee ed      dd      Z	 ee ed      d	      Z
 ee ed
      dd      Z eed	      Z eed	      Z eed	      Z e ed       ej$                               Z e ed       ej$                          ej$                               Z ede	g      Z edd      Z edeg      Zd Zy)rQ   zASales order lines table for individual line items in sales ordersri   Tr?   rC   FrD   zsales_orders.idrI   products.product_idrG   rK   rM   r   rO   r=   rU   Productc                 V    d| j                    d| j                   d| j                   dS )Nz<SalesOrderLine(id=z, sales_order_id=, product_id=)>)r[   sales_order_id
product_idr^   s    r#   r`   zSalesOrderLine.__repr__Q   s3    $TWWI->t?R?R>SS`aeapap`qqsttr"   N)r   r   r   ra   rb   r   r   r[   r	   rc   rr   rs   quantityr   
unit_pricepromotion_idr   r   re   rf   rg   r   rh   rR   productr`   r!   r"   r#   rQ   rQ   =   s    K'M	TT	JB,B!Ce[_`JGZ0A%BUSN,A!BUZ^_Jg.H.J'D1L$/
KJ$/
U]UYU]U]U_`J 9J<@G|<OPK9J<@Gur"   rQ   c                   J   e Zd ZdZdZ eeddd      Z ee ed      dd      Z	 ee ed      dd      Z
 ee ed	      dd      Z e ed
      ddd      Z eedd      Z e ed      d      Z e ed      d      Z e ee      dej(                        Z e ed       ej.                               Z e ed       ej.                          ej.                               Z ede	g      Z ede
g      Z edeg      Z eddd      Zd Zy)InventoryBatchzNInventory batches table for LOT-level tracking (perishable & waste management)inventory_batchesTr?   rC   FrD   rl   rF   d   )rE   uniquerA   r   rE   defaultrG   rI   rK   rM   r   rO   rn   rW   InventoryMovementbatchrS   rT   c                 V    d| j                    d| j                   d| j                   dS )Nz<InventoryBatch(id=z, batch_ref='z', quantity=rq   )r[   	batch_refquantity_on_handr^   s    r#   r`   zInventoryBatch.__repr__l   s/    $TWWI]4>>:J,W[WlWlVmmoppr"   N) r   r   r   ra   rb   r   r   r[   r	   rc   rs   r\   r   r   r   r   expiry_datereceived_dater
   r%   r+   statusr   re   rf   rg   r   rh   rw   rj   inventory_movementsr`   r!   r"   r#   ry   ry   U   sD   X'M	TT	JB,B!Ce[_`J,A!BUZ^_J*-D"EPU]abKvc{U4tLIgqA404@K8T2UCMD-.H\HcHcdF$/
KJ$/
U]UYU]U]U_`J 9J<@G9J<@GJk]CH&':7\pqqr"   ry   c                      e Zd ZdZdZ eeddd      Z ee ed      dd      Z	 ee ed      dd      Z
 ee ed	      dd      Z ee ed
      d      Z e ee      d      Z eed      Z e ed      d      Z e ed       ej*                               Z ede	g      Z ede
g      Z edeg      Z edd      Zd Zy)r   zEInventory movements table for real-time tracking of inventory changesr   Tr?   rC   FrD   rl   rF   zinventory_batches.idrI   r{   rG   rK   r   rO   rn   rW   ry   rm   c                 V    d| j                    d| j                   d| j                   dS )Nz<InventoryMovement(id=z, type='z	', delta=rq   )r[   movement_typequantity_deltar^   s    r#   r`   zInventoryMovement.__repr__   s1    'y9K9K8LIVZViViUjjlmmr"   N)r   r   r   ra   rb   r   r   r[   r	   rc   rs   r\   batch_idr
   r1   r   r   r   	referencer   r   re   rf   r   rh   rw   rj   r   r`   r!   r"   r#   r   r   p   s    O)M	TT	JB,B!Ce[_`J,A!BUZ^_J*-D"EPU]abKgz*@ADQH4->MGe4Nvc{T2I$/
KJ 9J<@G9J<@GJk]CH):OPEnr"   r   c                      e Zd ZdZdZ eeddd      Z ee ed      dd      Z	 eedd      Z
 ee ed      dd      Z e ee      dej                  	      Z e ed
      d      Z e ed
       ej&                               Z e ed
       ej&                          ej&                               Z ede	g      Z eddd      Z edeg      Zd Zy)PurchaseOrderzAPurchase orders table for tracking purchase orders from supplierspurchase_ordersTr?   rC   FrD   rF   r}   rG   rI   rK   rM   r   rO   PurchaseOrderLinepurchase_orderrS   rT   rW   c                 V    d| j                    d| j                   d| j                   dS )Nz<PurchaseOrder(id=z, supplier_id=z
, status='rZ   )r[   supplier_idr   r^   s    r#   r`   zPurchaseOrder.__repr__   s1    #DGG9N4;K;K:LJW[WbWbVccfggr"   N)r   r   r   ra   rb   r   r   r[   r	   rc   r   r\   r
   r   r   r   r   expected_delivery_dater   re   rf   rg   r   rh   purchase_order_linesrj   r`   r!   r"   r#   r   r      s    K%M	TT	JB,B!Ce[_`J5=K*-D"EPU]abKD,-GZG`G`aF#Hd$;dK$/
KJ$/
U]UYU]U]U_`J 9J<@G'(;L\fz{Jk]CHhr"   r   c                      e Zd ZdZdZ eeddd      Z ee ed      dd      Z	 ee ed      d	      Z
 ee ed
      dd      Z eed	      Z eedd      Z eed	      Z e ed       ej$                               Z e ed       ej$                          ej$                               Z ede	g      Z edd      Z edeg      Zd Zy)r   zGPurchase order lines table for individual line items in purchase ordersr   Tr?   rC   FrD   zpurchase_orders.idrI   rl   r   r}   rG   rK   rM   r   rO   r   rm   rn   c                 V    d| j                    d| j                   d| j                   dS )Nz<PurchaseOrderLine(id=z, purchase_order_id=rp   rq   )r[   purchase_order_idrs   r^   s    r#   r`   zPurchaseOrderLine.__repr__   s3    'y0DTE[E[D\\ijnjyjyizz|}}r"   N)r   r   r   ra   rb   r   r   r[   r	   rc   r   rs   ordered_qtyreceived_qtyr   	unit_costr   r   re   rf   rg   r   rh   r   rw   r`   r!   r"   r#   r   r      s    Q*M	TT	JB,B!Ce[_`Jw
3G(HSXY,A!BUZ^_J51K'E1=Luu-I$/
KJ$/
U]UYU]U]U_`J 9J<@G!/BXYN9J<@G~r"   r   c                      e Zd ZdZdZ eeddd      Z ee ed      dd      Z	 ee ed      dd      Z
 ee ed	      dd      Z e ed
      dd      Z eedd      Z eedd      Z e ed
       ej$                               Z e ed
       ej$                          ej$                               Z ede	g      Z ede
g      Z edeg      Zd Zy)
DailySaleszPDaily sales table for tracking aggregated sales per product per location per daydaily_salesTr?   rC   FrD   rl   rF   rG   r   r}           rK   rM   r   rO   rn   rW   c           	      p    d| j                    d| j                   d| j                   d| j                   d	S )Nz<DailySales(id=rp   rY   z, date=rq   )r[   rs   r\   	sale_dater^   s    r#   r`   zDailySales.__repr__   sH     	t6G~VZVfVfUggnoso}o}n~  A  B  	Br"   N)r   r   r   ra   rb   r   r   r[   r	   rc   rs   r\   r   r   quantity_soldr   total_amountr   re   rf   rg   r   rh   rw   rj   r`   r!   r"   r#   r   r      s   Z!M	TT	JB,B!Ce[_`J,A!BUZ^_J*-D"EPU]abKx.dKI7UA>M%%=L$/
KJ$/
U]UYU]U]U_`J 9J<@G9J<@GJk]CHBr"   r   c                   ~   e Zd ZdZdZ eedd      Z ee ed      dd      Z	 ee ed      dd      Z
 ee ed	      dd      Z eedd      Z eedd
      Z e ed      d      Z e ed       ej(                               Z eddddd      fZ ede	g      Z ede
g      Z edeg      Zy)StockoutEventz
    Logs of stockouts or lost sales events.
    Each record represents some demand that could NOT be fulfilled
    because there was no stock.
    lost_sales_qty = demand you couldn't serve.
    stockout_eventsTr@   rA   rC   FrA   rE   rF   rl   r   r}      rI   rG   rK   !ix_stockout_company_loc_prod_daterc   r\   rs   dater   rO   rW   rn   N)r   r   r   ra   rb   r   r   r[   r	   rc   r\   rs   r   r   r   lost_sales_qtyr   reasonr   r   re   rf   r   __table_args__r   rh   rj   rw   r!   r"   r#   r   r      s     &M	T	6B,B!C4Z_`J*-D"ET\abK,A!B$Y^_J$dU3D EE3?NF3K$/F$/
KJ 	/-v	
N 9J<@GJk]CH9J<@Gr"   r   c                      e Zd ZdZdZ eedd      Z eedd      Z	 ee e
d      dd      Z ee e
d      dd      Z ee e
d	      dd      Z eedd
      Z eedd
      Z eedd
      Z eedd      Z e ed       ej*                               Z edddddd      fZ edeg      Z edeg      Z edeg      Zy)ServiceLevelDailyz
    Derived table: daily service level per company/location/product.
    service_level = fulfilled_demand / total_demand
                  = qty_sold / (qty_sold + lost_sales_qty)
    service_level_dailyTr   Fr   rC   rF   rl   r   r}   g      ?rG   rK   #ix_servicelvl_company_loc_prod_dater   rc   r\   rs   r|   r   rO   rW   rn   N)r   r   r   ra   rb   r   r   r[   r   r   r	   rc   r\   rs   r   
demand_qtyfulfilled_qtyr   service_levelr   r   re   rf   r   r   r   rh   rj   rw   r!   r"   r#   r   r      s    *M	T	6B$dU3D,B!C4Z_`J*-D"ET\abK,A!B$Y^_Js;J55#>MEE3?N55#>M$/
KJ 	1L-	
N 9J<@GJk]CH9J<@Gr"   r   c                   "   e Zd ZdZdZ eedd      Z eedd      Z	 eedd      Z
 eedd      Z eedd      Z eedd      Z eedd      Z eedd      Z e ed	       ej&                         
      Z edddddd      fZy)InventorySnapshotDailyz
    Snapshot of inventory at end of a given day, per company/location/product.
    Computed by Celery task from previous snapshot + today's movements.
    inventory_snapshot_dailyTr   Fr   r   r}   rG   rK   !ix_snapshot_company_loc_prod_datesnapshot_daterc   r\   rs   r   N)r   r   r   ra   rb   r   r   r[   r   r   rc   r\   rs   r   on_hand_qtyinbound_qtyoutbound_qtyr   r   re   rf   r   r   r!   r"   r#   r   r   *  s    
 /M	T	6B4te<Mte<Ju=Kte<J<K<K%%=L$/
KJ 	/	
	Nr"   r   c                   Z   e Zd ZdZ eedd      Z eedd      Z ee e	d      dd      Z
 ee e	d      dd      Z ee e	d	      dd      Z eed
      Z eedd      Z eedd      Z eed
      Z eedd      Z eedd      Z eed
      Z eed
      Z eed
      Z eedd      Z e ed      d
      Z e ed      d
      Z e ed       ej<                               Z e dddddd      fZ! e"de
g      Z# e"deg      Z$ e"deg      Z%y)SlowMoverSnapshotslow_mover_snapshotTr   FrD   rC   r   rF   rl   rI   r   r}      r   rG   rK   "uq_slow_mover_snapshot_day_sku_locr   rc   r\   rs   r   r   rO   rW   rn   N)&r   r   r   rb   r   r   r[   r   r   r	   rc   r\   rs   r   r   total_sold_7dtotal_sold_30dtotal_sold_90dads_7dads_30dads_90ddoh_90ddays_since_last_saler   is_slow_moverr   slow_mover_severityslow_mover_reasonr   r   re   rf   r   r   r   rh   rj   rw   r!   r"   r#   r   r   L  st   )M	T	6B4%t<M,B!C4Z_`J*-D"ET\abK,A!B$Y^_J/K 55#>MEE3?NEE2NEE37FUUC8GUU+GUU+G!'E:7UEBM d;vc{T:$/
KJ 	0\=,	
N 9J<@GJk]CH9J<@Gr"   r   c                       e Zd ZdZ eedd      Z eed      Z eed      Z eed      Z	 ee
d      Z ee
d      Z eed      Z eed      Z e ed       ej&                               Zy	)
DemandForecastdemand_forecastsTr   )rA   FrI   rG   rK   N)r   r   r   rb   r   r   r[   rc   r\   rs   r   forecast_datetarget_dater   forecast_qtyr   model_versionr   r   re   rf   r!   r"   r#   r   r   y  s    &M	T	6Bt,J-Kt,J4%0M.K%%0L6D1M$/
KJr"   r   c                      e Zd ZdZ eedd      Z eedd      Z ee e	d      dd      Z
 ee e	d      dd      Z ee e	d      dd      Z eedd	
      Z eedd	
      Z eedd
      Z eedd
      Z eedd
      Z eedd	
      Z eedd	
      Z eedd	
      Z eedd	
      Z eedd	
      Z eedd	
      Z eedd	
      Z eedd	
      Z eedd	
      Z eedd	
      Z e ed      d      Z eedd	
      Z ee dd
      Z! eed      Z" eed      Z# ee dd
      Z$ eedd	
      Z% e&de
g      Z' e&deg      Z( e&deg      Z) e*ddddd      fZ+y)InventoryPlanningSnapshotinventory_planning_snapshotTr   Fr   rC   rF   rl   r   r}   r   ffffff?r   rI   r   rO   rW   rn   r   rc   r\   rs   $uq_planning_snapshot_per_day_sku_locnameN),r   r   r   rb   r   r   r[   r   r   r	   rc   r\   rs   r   avg_daily_demandsigma_daily_demandlead_time_daysreview_period_daysservice_level_targetcurrent_safety_stockcurrent_reorder_pointforecast_avg_daily_demand_90dforecast_safety_stock_90dforecasted_reorder_point_90dr   r   available_stock
min_target
max_targetr   stock_statusrecommended_order_qtyr   should_reorderdays_of_coverdays_until_stockout	is_urgenturgency_scorer   rh   rj   rw   r   r   r!   r"   r#   r   r     s   1M	T	6B4te<M,B!C4Z_`J*-D"ET\abK,A!B$Y^_J eeSAsC GeQ?N%C!%%F "%%E"55#F %+55#$N! &uuc J#)%%#M  <K<KUUC@Os;Js;J&*t4L"55#FGeUCN 540M 6w>I55#>M 9J<@GJk]CH9J<@G 	\=,7	
Nr"   r   c                      e Zd ZdZ eedd      Z ee ed      dd      Z ee ed      dd      Z	 ee ed      dd      Z
 eedd	
      Z eedd	
      Z eedd
      Z eedd
      Z eed      Z e ed       ej&                               Z e ed       ej&                          ej&                               Z edeg      Z ede	g      Z ede
g      Z edddd      fZy)ReorderPolicyreorder_policiesTr   rC   Fr   rF   rl      r}   r   r   rI   rG   rK   rM   r   rO   rW   rn   rc   r\   rs   "uq_reorder_policy_company_loc_prodr   N)r   r   r   rb   r   r   r[   r	   rc   r\   rs   r   r   r   r   min_order_qtyr   r   r   re   rf   rg   r   rh   rj   rw   r   r   r!   r"   r#   r   r     s.   &M	T	6B,B!C4Z_`J*-D"ET\abK,A!B$Y^_J GeQ?N%C!%%F 55#>M 40K$/
KJ$/
U]UYU]U]U_`J 9J<@GJk]CH9J<@G 	-5	
Nr"   r   )*
sqlalchemyr   r   r   r   r   r   r	   r
   r   r   r   sqlalchemy.ormr   sqlalchemy.sqlr   enumsrc.utils.dbr   (src.smart_inventory.apps.products.modelsr   ImportErrorutils.db$smart_inventory.apps.products.modelsstrr   r%   r1   r=   rQ   ry   r   r   r   r   r   r   r   r   r   r   r   r!   r"   r#   <module>r     sB   G  G  G  G '  =!@#tyy 3		 "3		 "g g,uT u0qT q6n n2hD h.~ ~2B B0$AD $AN#A #AdT D*A *AZLT L$6 6p!D !u  =<=s   D D-,D-