o
    ~/i/                     @   s   d dl mZmZmZ d dlmZ d dlmZ d dlm	Z	 d dl
mZmZ d dlmZ d dlmZmZmZmZ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  d dl!m"Z# G dd dej$Z%dS )    )viewsetsstatusfilters)Response)IsAuthenticated)get_object_or_404)koleksimaster)PermissionDenied)SuratSuratfSuratd	DisposisiSuratVersion)SuratSerializerSuratVersionSerializer   )CustomPageNumberPagination)action)MultiPartParser
FormParser)uploadc                       s   e Zd ZdZeegZej	 Z
eZegZeZejejgZg dZg dZdgZ fddZdd Zd"d
dZdd Zd"ddZd"ddZeddgddd"ddZeddgddd#ddZ eddgddd"ddZ!eddgddd#d d!Z"  Z#S )$SuratViewSetup  
    ViewSet lengkap untuk data Surat.
    
    Fitur:
    - GET /api/surat/ → list (paging, search, ordering, filter kategori)
    - GET /api/surat/{pk}/ → detail lengkap
    - POST /api/surat/ → create
    - PUT /api/surat/{pk}/ → update (dengan versioning)
    - DELETE /api/surat/{pk}/ → delete
    - POST /api/surat/{pk}/upload/ → upload lampiran (multi-file)
    - GET /api/surat/{pk}/versions/ → riwayat versi
    - GET /api/surat/{pk}/versions/{version_pk}/ → detail versi
    
    Semua proses upload lampiran API mengikuti mekanisme upload WEB,
    agar path, penamaan file, dan metadata sama.
    )nomorpengirim_namapengirim_instansipenerima_namapenerima_instansiperihaljenissifat)createdupdatedtanggalr   r   r    -createdc                    sF   t  |}| jjd}|dkr|d}|S |dkr!|d}|S )u   
        Override filter bawaan DRF untuk menambahkan sorting manual:

            ?sort=asc   → created ascending
            ?sort=desc  → created descending

        Ini tidak menggantikan DRF ordering, hanya melengkapinya.
        sortascr!   descr$   )superfilter_querysetrequestquery_paramsgetorder_by)selfqueryset
sort_param	__class__ 9/var/www/html/mfile_papteng_new/webapp/api/surat/views.pyr)   H   s   	

zSuratViewSet.filter_querysetc                 C   s   t j }| jjdd }|dkr|jdd}n
|dkr$|jdd}| jjd}|r3|j|d	}| jjd
}|rB|j|d}|S )z
        Fitur filter tambahan:
            ?kategori=surat masuk
            ?kategori=surat keluar
            ?status=public/private
            ?jenis=surat tugas / lainnya
        kategori zsurat masukmasuk)_typezsurat keluarkeluarr   )status_suratr   )jenis__iexact)r   objectsallr*   r+   r,   lowerfilter)r.   qsr5   r:   r   r3   r3   r4   get_queryset^   s   
zSuratViewSet.get_querysetNc                 C   s"   |   }t|d|idj}t|S )zQ
        Mengambil satu surat dengan relasi lampiran, tujuan, disposisi.
        r*   context)
get_objectr   datar   )r.   r*   pksuratrE   r3   r3   r4   retrieve{   s   zSuratViewSet.retrievec                 O   sl   t |jd}|jdd | }|jd}|r(t||j| t	||j
j t|jt|ddtjdS )N)rE   Traise_exceptionsuratfr!   )iduploadedmessager   )r   rE   is_validsaveFILESgetlistsuratf_uploaddeployrF   save_surat_versionuserr   lenr   HTTP_201_CREATED)r.   r*   argskwargs
serializerrG   filesr3   r3   r4   create   s   zSuratViewSet.createc                 O   s   |   }tjj|j|j|j|j|j|j	|j
|j|j|j|j|j|j|jd t||jdd}|jdd |  t|jddS )z|
        Saat surat di-update:
        - Simpan versi lama ke tabel SuratVersion
        - Lalu update data terbaru
        )pk_suratr   r#   pengirimr   r   penerimar   r   r    r   r   r:   
user_inputT)rE   partialrI   r"   )rL   rN   )rD   r   r<   r^   rF   r   r#   r`   r   r   ra   r   r   r    r   r   r:   rb   r   rE   rP   rQ   r   )r.   r*   rF   rZ   r[   rG   r\   r3   r3   r4   update   s*   zSuratViewSet.updatec                 C   s"   |   }|  tdditjdS )NrN   deletedrO   )rD   deleter   r   HTTP_204_NO_CONTENT)r.   r*   rF   rG   r3   r3   r4   destroy   s   zSuratViewSet.destroyTr,   versions)detailmethodsurl_pathc                 C   s<   t t|d tjj|dd}t|dd|id}t|jS )z\
        Menampilkan seluruh riwayat versi surat (termasuk lampiran di tiap versi).
        rF   )r_   r$   Tr*   )manyrC   )	r   r   r   r<   r?   r-   r   r   rE   )r.   r*   rF   versions_qsr\   r3   r3   r4   ri      s   
zSuratViewSet.versionszversions/(?P<version_pk>[^/.]+)c                 C   s4   t t|d t t||d}t|d|id}t|jS )zQ
        Menampilkan satu versi surat + seluruh lampiran versi tersebut.
        rm   )rF   r_   r*   rB   )r   r   r   r   r   rE   )r.   r*   rF   
version_pkversionr\   r3   r3   r4   version_detail   s   
zSuratViewSet.version_detailpostr   c                 C   s   t t|d}|jdd}|r&dd |dD }|r&tjj|djdd	 t	
||jj |jd
}|s>tddiddS t	||j| tdt||dS )u  
        Upload lampiran surat (multi-file) dari API.
        Mekanisme ini HARUS identik dengan Web:
        
        1. pending_delete_ids → soft delete lampiran tertentu
        2. save_surat_version() → simpan versi lama sebelum upload baru
        3. getlist("suratf") → menerima banyak file sekaligus
        4. deploy() → fungsi upload dari WEB, menangani rename, path, metadata
        rm   pending_delete_idsr6   c                 S   s   g | ]}|  r|qS r3   )strip).0pidr3   r3   r4   
<listcomp>   s    z-SuratViewSet.upload_files.<locals>.<listcomp>,)pk__inT)
is_deletedrK   rN   zNo files uploadedi  rO   zUpload success)rN   rM   re   )r   r   rE   r,   splitr   r<   r?   rd   rT   rV   rW   rF   rR   rS   r   rU   rX   )r.   r*   rF   rG   pending_idsr]   r3   r3   r4   upload_files   s    zSuratViewSet.upload_fileszrollback/(?P<version_id>[^/.]+)c           
   
   C   s*  |}z
t jjj|d}W n t jjy    tdditjd Y S w tj	jj
ddjddd	}t|jdr8|jjn|jd}t|jd
rH|jjn|jd
}||vr[|j|kr[tdz	t||| W n  ty }	 ztddt|	 itjdW  Y d }	~	S d }	~	ww tdd| d||dtjdS )Nrm   rj   zSurat tidak ditemukan.rO   OPERATOR)role__startswithroleT)flatrF   z#Anda tidak memiliki akses rollback.zRollback gagal: z!Berhasil rollback surat ke versi .)successrN   surat_id
version_id)	m_koleksir   r<   r,   DoesNotExistr   r   HTTP_404_NOT_FOUNDm_masterRolesexcludevalues_listhasattrrW   r   sessionrF   rb   r
   rT   rollback_surat	ExceptionstrHTTP_400_BAD_REQUESTHTTP_200_OK)
r.   r*   rF   r   surat_pkrG   allowed_roles	user_roleuser_pker3   r3   r4   r     sH   
  	
zSuratViewSet.rollback_surat)N)NN)$__name__
__module____qualname____doc__r   r   parser_classesr   r<   r=   r/   r   serializer_classr   permission_classesr   pagination_classr   SearchFilterOrderingFilterfilter_backendssearch_fieldsordering_fieldsorderingr)   rA   rH   r^   rd   rh   r   ri   rr   r~   r   __classcell__r3   r3   r1   r4   r      s2    



$)r   N)&rest_frameworkr   r   r   rest_framework.responser   rest_framework.permissionsr   django.shortcutsr   webapp.modelsr   r   r	   r   django.core.exceptionsr
   webapp.models.koleksir   r   r   r   r   webapp.api.surat.serializersr   r   
paginationr   rest_framework.decoratorsr   rest_framework.parsersr   r   webapp.views.suratr   rT   ModelViewSetr   r3   r3   r3   r4   <module>   s    