
    +Ch!                     `   S SK r S SKrS SKJr  S SKJr  S SKJr  S SKJ	r	  S SK
Jr  SrS\4S	 jrS
\S\4S jrS\S\S\4S jrSS\S-  S\4S jjrSS\S-  S\4S jjrSS\S-  S\\\4   4S jjrSS\S\4S jjrS\4S jr SS\S\S-  4S jjrS SKJr  S SKJr  S SKJ r   S SK!r!SS jr"g)     N)Decimal)Iterable)apps)settings)default_storagei   returnc                  ,    [        [        S[        5      $ )u;   Obtém o limite (em MB) a partir do settings, com fallback.HD_LIMIT_MB)getattrr   DEFAULT_LIMITE_MB     (/var/www/html/minhaobra/obras/uploads.py
_limite_mbr      s    8],=>>r   pathc                    Sn[         R                  R                  U 5      (       d  g[         R                  " U 5       Hw  u  p#nU Hk  n[         R                  R	                  X%5      n[         R                  R                  U5      (       d  MH   U[         R                  R                  U5      -  nMm     My     U$ ! [        [        4 a     M  f = f)zFPercorre recursivamente *path* (se existir) somando o tamanho (bytes).r   )	osr   existswalkjoinisfilegetsizeFileNotFoundErrorOSError)r   totaldirpath_	filenamesfnamefps          r   _calcular_tamanho_pastar!      s    E77>>$!#IEg-Bww~~b!!RWW__R00E	  "/ L *73 s   "B;;CCmodel_label
field_namec                 "   [         R                  " U R                  SSS96 nSnUR                  R                  " S0 UD6R                  USS9 H&  nU(       d  M   U[        R                  " U5      -  nM(     U$ ! [        [        4 a     M?  f = f)u   
Soma (em bytes) o tamanho de todos os arquivos `field_name` no queryset
`apps.get_model(model_label).objects.filter(**filters)`.

Usa default_storage.size() → compatível com S3 e afins.
.   )maxsplitr   T)flatr   )
r   	get_modelsplitobjectsfiltervalues_listr   sizer   r   )r"   r#   filtersModelr   r   s         r   _tamanho_arquivos_querysetr1   3   s     NNK--cA->?EE %%00<<Zd<S5--e44 T L ./ s   A::BBbase_media_pathc           	          U=(       d    [         R                  nSnU[        [        R                  R                  USSU R                   35      5      -  n[        U SS5      (       aB  U[        [        R                  R                  USU R                  R                  S5      5      -  nU[        SS	U S
9-  nU[        SS	U S
9-  nU[        SSU S
9-  nU[        SSU S9-  nU[        SSU S
9-  nU[        SSU S
9-  nU$ )u  
Retorna o total de bytes ocupados por *todos* os arquivos do usuário.

Conteúdo incluído:
1. Pasta local  `MEDIA_ROOT/usuarios/uid_<id>/`  (arquivos legados)
2. Comprovantes em `pagamentos/<schema>/comprovantes/`
3. Todos os FileFields nos modelos ligados ao usuário:
   Foto, FotoObra, Pagamento (comprovantes), DocumentoEtapa,
   EtapaObra (documento_orcamento / contrato_servico)
r   usuariosuid_tenantN
pagamentoscomprovantesz
obras.Fotoimagem)obra__usuariozobras.FotoObrazobras.Pagamentocomprovantezobras.DocumentoEtapaarquivo)etapa__obra__usuariozobras.EtapaObradocumento_orcamentocontrato_servico)r   
MEDIA_ROOTr!   r   r   r   idr   r6   schema_namer1   )userr2   base_dirtotal_bytess       r   calcular_uso_total_usuariorF   H   s>    5("5"5HK *
XzT$''+;< K
 tXt$$.GGLL,(?(?
 	
 -hd K -($ K -= K -	 K -0 K --T K r   	limite_mbc                 P    U=(       d
    [        5       n[        U 5      US-  S-  :  $ )u=   
True se o usuário já ultrapassou (ou alcançou) o limite.
i   )r   rF   )rC   rG   s     r   atingiu_limite_hdrI      s*     )Z\I%d+y4/?$/FFFr   c                     U=(       d
    [        5       n[        U 5      n[        US-  S5      n[        SU(       a  [	        X1-  S-  5      OS5      nUUUX1:  S.$ )z
Dados prontos para front-end:
    {
        "uso_mb": 42.13,
        "limite_mb": 800,
        "percentual": 5,
        "bloqueado": False
    }
i      d   r   )uso_mbrG   
percentual	bloqueado)r   rF   roundminint)rC   rG   rE   rM   rN   s        r   uso_hd_formatadorS      sc     )Z\I,T2K;+.2FSY#v1S89ANJ  (	 r   tipoc                      U R                   R                  n[        R                  " SSU5      nSUR
                   SU SU 3$ ! [         a    U R                  n NEf = f)z;
Gera `usuarios/uid_<id>/<tipo>/<arquivo_sanitizado.ext>`.
[^A-Za-z0-9_.-]r   zusuarios/uid_/)obrausuarioAttributeErrorresubrA   )instancefilenamerT   rC   safe_filenames        r   user_file_pathr`      sd     }}$$ FF-sH=M477)1TF!M?;;	    s   A AAc                     U R                   R                  R                  R                  n[        R
                  " SSU5      nSU SU 3$ )z.
`pagamentos/<schema>/comprovantes/<arquivo>`
rV   r   zpagamentos/z/comprovantes/)rX   rY   r6   rB   r[   r\   )r]   r^   schemar_   s       r   pagamento_file_pathrc      sE     ]]""))55FFF-sH=M}o>>r   destino_relativoc                     U=(       d
    [        5       n[        XS9(       a  [        SU S35      e[        R                  " U5      (       a  [        R
                  " U5        [        R                  " X!5        g)u&  
Salva *arquivo_django* em `default_storage` no *destino_relativo*,
desde que o usuário não tenha excedido o limite.

Exemplo de uso:
    salvar_arquivo_com_limite(
        request.user,
        request.FILES["imagem"],
        f"usuarios/uid_{request.user.id}/extras/meu_arquivo.png",
    )
)rG   z
Limite de u6    MB atingido. Apague arquivos ou adquira mais espaço.N)r   rI   	Exceptionr   r   deletesave)rC   arquivo_djangord   rG   s       r   salvar_arquivo_com_limiterj      sd    " )Z\I3#YZ
 	

 .///0):r   )Image)BytesIO)InMemoryUploadedFilec           	          [         R                  " U 5      nUR                  nUR                  X45        [	        5       nUR                  USUSS9  UR                  S5        U R                  R                  SS5      S   S-   n[        US US[        R                  " U5      S 5      $ ! [         a  n[        S	U 35        U s S nA$ S nAff = f)
NJPEGT)formatqualityoptimizer   r%   r&   z.jpgz
image/jpegzErro ao comprimir imagem: )rk   openrp   	thumbnailrl   rh   seeknamersplitrm   sys	getsizeofrf   print)	uploaded_file	max_width
max_height	qualidader9   imagem_formatbuffernome_arquivoes	            r   comprimir_imagemr      s    M* 	)01 F69tLA %))00a8;fD#MM&!
 	
  *1#./s   B&B) )
C3CCC)N)outros)X  r   F   )#r   r[   decimalr   typingr   django.appsr   django.confr   django.core.files.storager   r   rR   r   strr!   r1   rF   boolrI   dictobjectrS   r`   rc   rj   PILrk   iorl   django.core.files.uploadedfilerm   rx   r   r   r   r   <module>r      s   	 	      5  ?C ?# # ,C S PS *1cDj 1C 1pGsTz GT GcDj Df<M 6
<S 
< 
<?s ?" !	; ; Tz	;<   ? 
r   