
    ]iB                        d Z ddlmZ ddl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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!jK                  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!jK                  d%e&       e	d&d'(       e	d&d)(       ee       ee      fde'dede'd"ed#ede&fd*       Z)e!jU                  d+e&       ed&       ed       ee       ee      fde'd,e
d-e+dz  d"ed#ede&fd.       Z,e!jU                  de&ejZ                  /       ee       ee       e	d0d1(      fde'd2ed"ed#ed3e.de&fd4       Z/e!jK                  d5e&       ee       ee      fde'd6e'd"ed#ede&f
d7       Z0e!jc                  d5e&       ee       ee      fde'd6e'd2ed"ed#ede&fd8       Z2e!jc                  d9e&       ee       ee      fde'd6e'd"ed#ede&f
d:       Z3e!jc                  d;e&       ee       ee      fde'd6e'd"ed#ede&f
d<       Z4e!jc                  d=e&       ee       ee      fde'd6e'd2ed"ed#ede&fd>       Z5e!jc                  d?e&       ee       ee      fde'd6e'd2ed"ed#ede&fd@       Z6e!jo                  d5ejp                  A       ee       ee      fde'd6e'd"ed#eddf
dB       Z9e!jU                  dCe&       ed&       ee       ee      fde'd6e'd,e
d"ed#ede&fdD       Z:e!jK                  dE       ee       ee      fde'd6e'd"ed#efdF       Z;e!jK                  dGe&       ee       ee      fde'd6e'd"ed#ede&f
dH       Z<e!jK                  dI       ee       ee      fde'd6e'd"ed#efdJ       Z=y)Kz/Router for penjualan / laporan shift endpoints.    date)	APIRouterDependsFileFormHTTPExceptionQuery
UploadFilestatus)AsyncSession)get_db)get_current_userget_spbu_access)StatusLaporan)User)LaporanShiftCreateLaporanShiftDetailResponseLaporanShiftResponseLaporanShiftUpdateReviewRequestTellerInitResponseUnlockRequest)operational_servicez/spbus/{spbu_id}/laporan-shift	penjualan)prefixtagsereturnc                     t        | t              r$t        t        j                  t        |             S t        t        j                  t        |             S )uI   Convert service-layer ValueError → 404/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/laporan_shift.py_service_errorr*      s:    !_%)B)B3q6RRV%@%@QPP     )response_modelN)defaultr   )r.   alias)r.   ge      d   )r.   r0   lespbu_idtanggalshift_idlaporan_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)z
    List laporan shift for an SPBU with optional filters.
    Requires: penjualan:view permission (currently enforced by authentication).
    Nr2   )totalpageper_page)datameta)r   list_laporan
ValueErrorr%   r*   
model_dump)r5   r6   r7   r8   r9   r:   r;   r<   laporan_listr>   r   ls               r)   rC   rC   $   s      $7$D$D(ND%%
 
e *66A6):N 
 (  Q  7sB   A>A AA A>A9A>A A6&A11A66A>z/teller-init.z-Tanggal laporan yang akan dibuat (YYYY-MM-DD))descriptionz!Shift ID laporan yang akan dibuatc                 "  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-filled teller_awal values from the previous shift's submitted laporan.
    Also returns can_approve flag so the frontend can show "Save & Approve" vs "Save & Submit".
    Requires: penjualan:view permission.
    N)rA   can_approve)r   get_teller_initcheck_user_can_approverD   r%   r*   rE   )	r5   r6   r7   r;   r<   rowsrJ   r   rs	            r)   rK   rK   ?   s      (88WgxXX/FFr<Y`aa .22TQ\\^T2;OO	 Ya(  Q 2sT   BA( A$A( A&A( BB
B$A( &A( (B7BBBz/extract-from-imagefileold_foto_urlc                 *  K   ddl m}m}m} ddlm} h d}	|j                  |	vrt        t        j                  d      |j                          d{   }
ddlm} dd	l m} |j                         } |||        d{   } ||d
|      } ||
|j                  xs d|       d{   } ||       d{    d}d}	  ||
|j                         d{   }|||dS 7 7 f7 >7 07 # t         $ r}dt#        |       }Y d}~,d}~ww xY ww)u   
    Upload foto laporan shift → Gemini Vision ekstrak data → return structured JSON.
    Foto juga di-upload ke Google Drive sebagai arsip.
    Jika old_foto_url disertakan, file lama akan dihapus (replace, bukan append).
    r   )save_uploadUploadContextdelete_file)extract_from_image>   	image/jpg	image/png
image/jpeg
image/webpz8Format file tidak didukung. Gunakan JPG, PNG, atau WEBP.r!   Nr   )get_spbu_codelaporanzlaporan.jpgzGagal membaca gambar: )rA   foto_urlextract_error)app.utils.file_uploadrR   rS   rT   app.utils.gemini_visionrU   content_typer	   r   r(   readdatetimer   rZ   todayfilename	Exceptionr'   )r5   rO   rP   r;   r<   rR   rS   rT   gemini_extractALLOWEDimage_bytes_daterZ   rc   	spbu_codectxnew_urlr]   	extractedr   s                       r)   rU   rU   T   s     NMLDG'33M
 	

 		#K '3KKME#B00I
	9e
4CT]]-KmSQQG l
### !%MI:(d6G6GHH	
 & + $ 1Q $ I :0Q9:s   ADC%,D C')D*C)+D:C+;DC/ C-C/ D'D)D+D-C/ /	D8DDDD)r-   r"   Fz?Dev only: skip auto-approve even if user has approve permissionrA   force_draftc                 V  K   	 t        j                  || |j                  |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)zi
    Create a new laporan shift (starts in DRAFT status).
    Requires: penjualan:create permission.
    )source_foto_urlrn   kasNapprovedzdibuat & disetujuizdisimpan sebagai draftLaporan berhasil rA   message)r   create_laporanr7   r6   nozzlesrp   rq   rD   r%   r*   r   rE   )r5   rA   r;   r<   rn   r[   r   actions           r)   rv   rv      s      +::dllL 00#	
 
 &-^^z%A!G_F&&(7H5QRR
 (  Q s;   B)AB BB )B)B B&B!!B&&B)z/{laporan_id}
laporan_idc                    K   	 t        j                  || |       d{   }d|j                         iS 7 # t        t        f$ r}t	        |      d}~ww xY ww)z{
    Return full detail for a single laporan shift including all nozzle rows.
    Requires: penjualan:view permission.
    NrA   )r   get_laporan_detailrD   r%   r*   rE   r5   ry   r;   r<   r[   r   s         r)   r{   r{      s]      +>>r7JWW G&&()) X(  Q s1   A7 57 A7 AAAAc                    K   	 t        j                  || ||j                  |j                  |j                         d{   }|j                         ddS 7 # t
        t        f$ r}t        |      d}~ww xY ww)zZ
    Replace nozzle rows on a DRAFT laporan.
    Requires: penjualan:edit permission.
    )rp   rq   NzLaporan berhasil diupdatert   )	r   update_laporanrw   rp   rq   rD   r%   r*   rE   r5   ry   rA   r;   r<   r[   r   s          r)   r~   r~      sz      +::T\\ 00
 
 &&(5PQQ

 (  Q s:   A<<A  AA A<A A9)A44A99A<z/{laporan_id}/submitc                    K   	 t        j                  || ||j                         d{   }|j                         ddS 7 # t        t        f$ r}t        |      d}~ww xY ww)zW
    Submit a DRAFT laporan for review.
    Requires: penjualan:create permission.
    NzLaporan berhasil di-submitrt   )r   submit_laporanidrD   r%   r*   rE   r|   s         r)   r   r      sj      +::\__
 

 &&(5QRR
 (  Q 7   A%%A AA A%A A"AA""A%z/{laporan_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 laporan back to DRAFT (operator only).
    Only valid while the laporan is still in SUBMITTED status (admin has not acted yet).
    Requires: penjualan:create permission.
    Nz)Laporan berhasil ditarik kembali ke Draftrt   )r   recall_laporanr   rD   r%   r*   rE   r|   s         r)   r   r      sj      +::\__
 

 &&(5`aa
 (  Q r   z/{laporan_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)z\
    Approve or reject a SUBMITTED laporan.
    Requires: penjualan:approve permission.
    Napprove	disetujuiditolakrs   rt   )	r   review_laporanr   rx   catatanrD   r%   r*   rE   )r5   ry   rA   r;   r<   r[   r   action_labels           r)   r   r      s      +::\__dkk4<<
 

 #'++":;	L&&(7H5WXX
 (  Q s9   B;A/ A- A/ )B-A/ /B>B		BBz/{laporan_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 laporan back to DRAFT, recording the reason.
    Requires: penjualan:approve permission.
    NzLaporan berhasil di-unlockrt   )r   unlock_laporanr   alasanrD   r%   r*   rE   r   s          r)   r   r     sp      +::\__dkk
 

 &&(5QRR
 (  Q s7   A00A AA A0A A-A((A--A0)r"   c                    K   	 t        j                  || |       d{    y7 # t        t        f$ r}t	        |      d}~ww xY ww)z
    Hard-delete a DRAFT laporan shift (and its nozzle rows via cascade).
    Only DRAFT status can be deleted. Requires: penjualan:delete permission.
    N)r   delete_laporanrD   r%   r*   )r5   ry   r;   r<   r   s        r)   r   r     sB      !00WjIII(  Q s0   A& $& A& AA  AAz/{laporan_id}/import-csvc                   K   |j                   r|j                   j                  d      st        dd      |j                          d{   }|j	                  d      }ddlm} 	 |j                  || |||j                         d{   }||d	    d
dS 7 N7 # t        $ r}	t        dt        |	            d}	~	ww xY ww)z6Upload a POS CSV file and import per-transaction data.z.csv  zFile harus berformat CSVr!   Nz	utf-8-sigr   )pos_import_serviceinsertedz transaksi berhasil diimporrt   )rd   endswithr	   ra   decodeapp.servicesr   import_pos_csvr   rD   r'   )
r5   ry   rO   r;   r<   contentcsv_textr   resultr   s
             r)   r   r   .  s      == 6 6v >4NOOIIKG~~k*H/<)88X|
 
 &*<)==X'YZZ  

  <CF;;<sH   AC
BC'"B 	B
B CB 	C&B<<CCz/{laporan_id}/ba-pdfc                   K   ddl m} ddlm} ddlm} ddlm} 	 t        j                  || |       d{   }|j                  dvrt        dd	
      |j                   ||      j!                  |j"                  | k(               d{   j%                         }
|
r|
j&                  nd|  }|
r|
j(                  n
t+        |       }|j,                  |j.                  |j0                  |j2                  |j4                  |j6                  |j8                  |j:                  |j<                  |j>                  |j@                  d}|jB                  D cg c]  }|jE                          }} |||t+        |jF                        |jH                  xs d|jJ                  xs d||jL                  |jN                  |	      }|jH                  xs djQ                  dd      jQ                  dd      }|jQ                  dd      }d| d|jF                   d| d} ||ddd| di      S 7 # t        t        f$ r}	t        |	      d}	~	ww xY w7 c c}w w)z]Download Berita Acara PDF for an approved laporan shift. Requires: penjualan:view permission.r   Response)generate_ba_penjualanSpbuselectNrr   lockedr   z3BA hanya tersedia untuk laporan yang sudah Approvedr#   SPBU )kas_100kkas_50kkas_20kkas_10kkas_5kkas_2kkas_1k	kas_logampembayaran_kartupembayaran_qrpembayaran_instansi-)		spbu_namerj   r6   
shift_namaapprover_namerw   total_volumetotal_nilairq   shift _/zBA-Penjualan-.pdfapplication/pdfContent-Dispositionattachment; filename=""r   
media_typeheaders))fastapi.responsesr   app.utils.ba_pdfr   app.models.spbur   
sqlalchemyr   r   r{   rD   r%   r*   r   r	   executewherer   scalar_one_or_nonenamenomor_pertaminar'   r   r   r   r   r   r   r   r   r   r   r   rw   rE   r6   r   reviewed_by_namer   r   replace)r5   ry   r;   r<   FastAPIResponser   r   	sa_selectr[   r   spbur   rj   rq   nnozzle_dicts	pdf_bytes
safe_shift	safe_coderd   s                       r)   download_ba_laporanr   H  s+     >6$. +>>r7JWW ~~33C(]^^**Yt_22477g3EFGG[[]D!		wi'8I(,$$#g,I &..%oo%oo%oo%nn%nn%nn%//%66%33&::C -4OO<OqALLNOL<%GOO$%%,..5#))''
I $$/88cBJJ3PSTJ!!#s+Iyk7??*;1ZLMH$&*@
!(LM W X(  Q  H" =sX   IH. H+H. AIICII,B?I+H. .I=IIIIz/{laporan_id}/activity-logc           	        K   ddl m} ddlm} ddlm} |j                   ||      j                   ||j                              j                  |j                  dk(  |j                  |k(  |j                  | k(        j                  |j                  j                                      d{   }|j!                         j#                         }d|D 	cg c]e  }	|	j$                  |	j                  r|	j                  j&                  nd|	j                  r|	j                  j)                         nd|	j*                  dg c}	iS 7 c c}	w w)	zVReturn full audit trail for a laporan shift (all submit/recall/approve/unlock events).r   r   )AuditLog)selectinloadr   NrA   )aksi	user_name
created_atr#   )r   r   app.models.auditr   sqlalchemy.ormr   r   optionsuserr   modul	object_idr5   order_byr   ascscalarsallr   r   	isoformatr#   )
r5   ry   r;   r<   r   r   r   r   rM   rN   s
             r)   get_activity_logr     s     /)+::(	hmm,	-	NNk)*,'


 
(%%))+	,	 	F >>!D 
  ,-FFQVV[[:;,,all446D((	 

 
	
s%   B+E
-E.'E
A*E?E
E
z/{laporan_id}/bast-pdfc                 V  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|j.                   dfdd|j0                  d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 W# t        t        f$ r}t        |      d}~ww xY w7 w)zUDownload BAST PDF for an approved laporan shift. Requires: penjualan:view permission.r   r   )generate_bastNr   r   z5BAST hanya tersedia untuk laporan yang sudah Approvedr   r   r   r   TanggalShiftr   zTotal Volumez LzTotal NilaizRp z,.0f	Penjualan)	r   	record_idr   r6   submitter_namesubmitter_atr   approver_atdetailszBAST-Penjualan-z-shiftr   r   r   r   r   r   )r   r   app.utils.bast_pdfr   r   r{   rD   r%   r*   r   r	   r   r   r   r   r   r   r   r   r   r'   r6   r   r   r   submitted_by_namesubmitted_atr   reviewed_atr7   )r5   ry   r;   r<   r   r   r[   r   r   r   r   r   r   r   rd   s                  r)   download_bast_laporanr     s     >0 +>>r7JWW ~~33C(_``$.**Yt_22477g3EFGG[[]D!		wi'8I	C()	'$$+,	G00145	#g11$789	G ZS%9007C))..5#''I !	7??*;6'BRBRASSWXH99J26LXJVW4XY[ [3 X(  Q  HsE   F)F FF AF)F&C4F)F F#FF##F))>__doc__rb   r   fastapir   r   r   r   r	   r
   r   r   sqlalchemy.ext.asyncior   app.core.databaser   app.dependenciesr   r   app.models.operationalr   app.models.userr   app.schemas.operationalr   r   r   r   r   r   r   r   r   routerrD   r%   r*   getdictintrC   rK   postr'   rU   HTTP_201_CREATEDboolrv   r{   patchr~   r   r   r   r   deleteHTTP_204_NO_CONTENTr   r   r   r   r    r+   r)   <module>r     s-   5  \ \ \ / $ > 0     -	+

Qj?2 Q} Q Bt$ !. .+0X+NaA&raC0v 1D[ Dj "D(	
   	  
 %4 N40 #+Z[#+NOv 1PPP P 		P
 P 
P 1P( "48 Cy#Dzv 1//
/ */ 		/
 / 
/ 9/d R&2I2IJ v 1e1rsSS
S 	S 	S
 S 
S KS0 OD1 v 1	*** 	* 	*
 
* 2*" od3
 v 1RRR R 		R
 R 
R 4R, $T: v 1	SSS 	S 	S
 
S ;S& $T: v 1	bbb 	b 	b
 
b ;b( $T:
 v 1YYY Y 		Y
 Y 
Y ;Y* $T:
 v 1SSS S 		S
 S 
S ;S( F,F,FG v 1	    	  	 
 
  H   '= Cyv 1[[[ [ 		[
 [ 
[ >[2 "# v 1	<<< 	< 	< $<~ (> v 1	    	  	 
 
  ? D $% v 1	%[%[%[ 	%[ 	%[ &%[r+   