
    ]i-                        d Z ddlmZ ddlmZ ddl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mZ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mZmZ ddl m!Z!  eddg      Z"de#e$z  de	fdZ%e"jM                  de'       e
d       e
d       e
dd       e
dd       e
ddd       ee       ee      fde(dedz  de(dz  d edz  d!e(d"e(d#ed$ede'fd%       Z)e"jM                  d&e'       ee       ee      fde(d#ed$ede'fd'       Z*e"jM                  d(e'       e
d)       e
d)       ee       ee      fde(d*e(d+ed#ed$ede'fd,       Z+e"jY                  de'ejZ                  -       ee       ee       e
d.d/0      fde(d1ed#ed$ed2e.de'fd3       Z/e"jM                  d4e'       ee       ee      fde(d5e(d#ed$ede'f
d6       Z0e"jc                  d4e'       ee       ee      fde(d5e(d1ed#ed$ede'fd7       Z2e"jc                  d8e'       ee       ee      fde(d5e(d#ed$ede'f
d9       Z3e"jc                  d:e'       ee       ee      fde(d5e(d#ed$ede'f
d;       Z4e"jc                  d<e'       ee       ee      fde(d5e(d1ed#ed$ede'fd=       Z5e"jc                  d>e'       ee       ee      fde(d5e(d1ed#ed$ede'fd?       Z6e"jY                  d@e'ejZ                  -       e
d)dA0       ed)       ee       ee      fde(d5e(dBe(dCe7dDed#ed$ede'fdE       Z8e"js                  dFe'       ee       ee      fde(d5e(dBe(dGe(d#ed$ede'fdH       Z:e"jM                  dI       ee       ee      fde(d5e(d#ed$efdJ       Z;y)Kz1Router for stock adjustment (sounding) endpoints.    )date)Decimal)	APIRouterDependsFileHTTPExceptionQuery
UploadFilestatus)AsyncSession)get_db)get_current_userget_spbu_access)StatusLaporan)User)StockAdjustmentCreateStockAdjustmentDetailResponseStockAdjustmentResponseStockAdjustmentUpdateStockInitResponseReviewRequestUnlockRequest)stock_servicez!/spbus/{spbu_id}/stock-adjustmentstock)prefixtagsereturnc                     t        | t              r$t        t        j                  t        |             S t        t        j                  t        |             S )uE   Convert service-layer ValueError → 400 and PermissionError → 403.)status_codedetail)
isinstancePermissionErrorr   r   HTTP_403_FORBIDDENstrHTTP_400_BAD_REQUEST)r   s    >/var/www/html/spbu.com/backend/app/routers/stock_adjustment.py_service_errorr(      s:    !_%)B)B3q6RRV%@%@QPP     )response_modelN)defaultr   )r,   alias)r,   ge      d   )r,   r.   lespbu_idtanggalshift_id
adj_statusskiplimitdbcurrent_userc           	         K   	 t        j                  || |||||       d{   \  }}	|D cg c]  }|j                          c}|	||z  dz   |ddS 7 2# t        t        f$ r}
t	        |
      d}
~
ww xY wc c}w w)zh
    List stock adjustments for an SPBU with optional filters.
    Requires: stock:view permission.
    Nr0   )totalpageper_page)datameta)r   list_adjustments
ValueErrorr#   r(   
model_dump)r3   r4   r5   r6   r7   r8   r9   r:   adj_listr<   r   as               r'   rA   rA   %   s       - > >(Je!
 
% *22A2):N 
 (  Q  3sB   A>A AA A>A9A>A A6&A11A66A>z/stock-initc                   K   	 t        j                  ||        d{   }t        j                  |||        d{   }|D cg c]  }|j                          c}|dS 7 D7 '# t        t        f$ r}t        |      d}~ww xY wc c}w w)z
    Return pre-fill data (last known volume/dipstick) for all active tanks of an SPBU.
    Also returns can_approve flag so the frontend can show "Simpan & Approve" vs "Simpan & Submit".
    Requires: stock:view permission.
    N)r?   can_approve)r   get_stock_initcheck_user_can_approverB   r#   r(   rC   )r3   r9   r:   rowsrG   r   rs          r'   rH   rH   @   s      "11"g>>)@@\SZ[[ .22TQ\\^T2;OO	 ?[(  Q 2sT   BA& A"A& A$A& BBB"A& $A& &B5B  BBz/calculate-volume.	tangki_id	height_mmc                    K   	 t        j                  || ||       d{   }ddt        |      iiS 7 # t        t        f$ r}t	        |      d}~ww xY ww)z
    Calculate volume (litres) from a dipstick height (mm) using the tank's calibration table.
    Returns error detail if height is out of calibration range.
    Nr?   volume_liter)r   calculate_volume_for_tankrB   r#   r(   r%   )r3   rL   rM   r9   r:   volumer   s          r'   calculate_volumerR   S   s`      $>>r7IW`aa ^S[122 b(  Q s1   A5 35 A5 AAAA)r+   r    Fz?Dev only: skip auto-approve even if user has approve permission)descriptionr?   force_draftc           	      *  K   	 t        j                  || |j                  |j                  |j                  ||       d{   }|j                  dk(  rdnd}|j                         d| dS 7 -# t
        t        f$ r}t        |      d}~ww xY ww)zh
    Create a new stock adjustment (starts in DRAFT status).
    Requires: stock:create permission.
    )rT   Napprovedzdibuat & disetujuizdisimpan sebagai draftStock adjustment berhasil r?   message)
r   create_adjustmentr5   r4   itemsrB   r#   r(   r   rC   )r3   r?   r9   r:   rT   adjr   actions           r'   rZ   rZ   f   s      !33djj,#
 
 &)ZZ:%=!C[FNN$3MfX1VWW
 (  Q s:   B=A1 A/A1 )B/A1 1B BBBz	/{adj_id}adj_idc                    K   	 t        j                  || |       d{   }d|j                         iS 7 # t        t        f$ r}t	        |      d}~ww xY ww)zx
    Return full detail for a single stock adjustment including all tank rows.
    Requires: stock:view permission.
    Nr?   )r   
get_detailrB   r#   r(   rC   r3   r^   r9   r:   r\   r   s         r'   get_adjustment_detailrb   }   s[      !,,R&AA CNN$%% B(  Q s1   A7 57 A7 AAAAc                    K   	 t        j                  || ||j                         d{   }|j                         ddS 7 # t        t        f$ r}t        |      d}~ww xY ww)z]
    Replace tank rows on a DRAFT stock adjustment.
    Requires: stock:edit permission.
    Nz"Stock adjustment berhasil diupdaterX   )r   update_adjustmentr[   rB   r#   r(   rC   r3   r^   r?   r9   r:   r\   r   s          r'   rd   rd      sb      !33BTT NN$1UVV U(  Q 7   A%%A AA A%A A"AA""A%z/{adj_id}/submitc                    K   	 t        j                  || ||j                         d{   }|j                         ddS 7 # t        t        f$ r}t        |      d}~ww xY ww)z
    Submit a DRAFT stock adjustment for review.
    Validates all active tanks have digital readings before allowing submit.
    Requires: stock:create permission.
    Nz#Stock adjustment berhasil di-submitrX   )r   submit_adjustmentidrB   r#   r(   rC   ra   s         r'   rh   rh      sb      !33BYY NN$1VWW Z(  Q rf   z/{adj_id}/recallc                    K   	 t        j                  || ||j                         d{   }|j                         ddS 7 # t        t        f$ r}t        |      d}~ww xY ww)z
    Recall a SUBMITTED stock adjustment back to DRAFT (operator only).
    Only valid while status is still SUBMITTED (admin has not acted yet).
    Requires: stock:create permission.
    Nz2Stock adjustment berhasil ditarik kembali ke DraftrX   )r   recall_adjustmentri   rB   r#   r(   rC   ra   s         r'   rk   rk      sb      !33BYY NN$1eff Z(  Q rf   z/{adj_id}/reviewc                 &  K   	 t        j                  || ||j                  |j                  |j                         d{   }|j                  dk(  rdnd}|j                         d| dS 7 -# t
        t        f$ r}t        |      d}~ww xY ww)za
    Approve or reject a SUBMITTED stock adjustment.
    Requires: stock:approve permission.
    Napprove	disetujuiditolakrW   rX   )	r   review_adjustmentri   r]   catatanrB   r#   r(   rC   )r3   r^   r?   r9   r:   r\   r   action_labels           r'   rp   rp      s      !33$++t||
 

 #'++":;	LNN$3Ml^1\]]
 (  Q s9   B;A/ A- A/ )B-A/ /B>B		BBz/{adj_id}/unlockc                    K   	 t        j                  || ||j                  |j                         d{   }|j                         ddS 7 # t        t
        f$ r}t        |      d}~ww xY ww)z
    Unlock an APPROVED or LOCKED stock adjustment back to DRAFT, recording the reason.
    Requires: stock:approve permission.
    Nz#Stock adjustment berhasil di-unlockrX   )r   unlock_adjustmentri   alasanrB   r#   r(   rC   re   s          r'   rt   rt      sn      !33$++
 

 NN$1VWW
 (  Q s7   A00A AA A0A A-A((A--A0z/{adj_id}/items/{item_id}/fotosz"Tipe foto: 'manual' atau 'digital'item_idtipefilec           
        K   |j                          d{   }	 t        j                  || |||||j                  xs d       d{   }|j                         ddS 7 I7 # t        t
        f$ r}	t        |	      d}	~	ww xY ww)z
    Upload photo evidence for a tank sounding item (manual stick or digital display).
    Requires: stock:create permission.
    Nzfoto.jpgzFoto berhasil diuploadrX   )readr   upload_item_fotofilenamerB   r#   r(   rC   )
r3   r^   rv   rw   rx   r9   r:   
file_bytesr\   r   s
             r'   r{   r{      s      yy{"J !22$
DMM<WZ
 

 NN$1IJJ #
 (  Q sD   BA B,A$ A"	A$ B"A$ $B3A>>BBz)/{adj_id}/items/{item_id}/fotos/{foto_id}foto_idc                    K   	 t        j                  || |||       d{   }|j                         ddS 7 # t        t        f$ r}t	        |      d}~ww xY ww)zX
    Delete a photo from a tank sounding item.
    Requires: stock:edit permission.
    NzFoto berhasil dihapusrX   )r   delete_item_fotorB   r#   r(   rC   )r3   r^   rv   r~   r9   r:   r\   r   s           r'   r   r     sf      !22'
 

 NN$1HII
 (  Q s1   A: 8: A: A	AAAz/{adj_id}/bast-pdfc                 R  K   ddl m} ddlm} 	 t	        j
                  || |       d{   }|j                  dvrt        dd      dd	lm} dd
lm}	 |j                   |	|      j!                  |j"                  | k(               d{   j%                         }
|
r|
j&                  nd|  }dt)        |j*                        fd|j,                  xs dfdt)        t/        |j0                              fg} |d||t)        |j*                        |j2                  xs d|j4                  |j6                  xs d|j8                  |	      }d|  d|j*                   d|j:                   d} ||ddd| di      S 7 U# t        t        f$ r}t        |      d}~ww xY w7 w)zTDownload BAST PDF for an approved stock adjustment. Requires: stock:view permission.r   )Response)generate_bastN)rV   i  z>BAST hanya tersedia untuk stock adjustment yang sudah Approved)r!   )Spbu)selectzSPBU TanggalShift-zJumlah TangkizStock Adjustment)	modul	record_id	spbu_namer4   submitter_namesubmitter_atapprover_nameapprover_atdetailszBAST-StockAdjustment-z-shiftz.pdfzapplication/pdfzContent-Dispositionzattachment; filename="")content
media_typeheaders)fastapi.responsesr   app.utils.bast_pdfr   r   r`   rB   r#   r(   r   r   app.models.spbur   
sqlalchemyr   executewhereri   scalar_one_or_nonenamer%   r4   
shift_namalenr[   submitted_by_namesubmitted_atreviewed_by_namereviewed_atr5   )r3   r^   r9   r:   FastAPIResponser   r\   r   r   	sa_selectspbur   r   	pdf_bytesr|   s                  r'   download_bast_adjustmentr   !  s     >0 !,,R&AA zz&C(hii$.**Yt_22477g3EFGG[[]D!		wi'8I	C$%	#..'C(	#c#))n-.G
  FS%5,,3%%**1cOOI 'wiqVCLL>QUVH99J26LXJVW4XY[ [1 B(  Q  HsE   F'F E?F AF'F$C2F'?F F!FF!!F')<__doc__datetimer   decimalr   fastapir   r   r   r   r	   r
   r   sqlalchemy.ext.asyncior   app.core.databaser   app.dependenciesr   r   app.models.operationalr   app.models.userr   app.schemas.stockr   r   r   r   r   r   r   app.servicesr   routerrB   r#   r(   getdictintrA   rH   rR   postHTTP_201_CREATEDboolrZ   rb   patchrd   rh   rk   rp   rt   r%   r{   deleter   r    r)   r'   <module>r      s   7   V V V / $ > 0     '	.

Qj?2 Q} Q Bt$ !. .',T'JaA&raC0v 1D[ Dj $	
   	  
 %4 M$/ v 1PPP P 
	P 0P$ 5 3Zsv 1333 3 		3
 3 
3 63$ R&2I2IJ v 1e1rsXX
X 	X 	X
 X 
X KX, K- v 1	&&& 	& 	&
 
& .&" k$/
 v 1WWW  W 		W
 W 
W 0W$  6 v 1	XXX 	X 	X
 
X 7X$  6 v 1	ggg 	g 	g
 
g 7g$  6
 v 1^^^ ^ 		^
 ^ 
^ 7^*  6
 v 1XXX X 		X
 X 
X 7X( .tQWQhQhi
 c'KLCyv 1KKK K 	K
 K 	K K 
K jK. :4P v 1JJJ J 	J
 	J J 
J QJ*  ! v 1	$[$[$[ 	$[ 	$[ "$[r)   