o
     ghd                     @   s$  d Z ddlZddlZddlZddlmZmZm	Z	m
Z
 ddlmZ G dd dZdefdd	Zd
ejdedefddZd
ejdedefddZd
ejdedefddZd
ejdedefddZd
ejdefddZdefddZd
ejdefddZd d
ejdedefddZG dd dZe ZdS )!u[   
파일 검증 유틸리티 모듈
Excel 파일의 구조와 데이터를 검증합니다.
    N)DictListTupleAny)clean_dataframe_datac                   @   sF   e Zd ZdZdd ZdefddZdefddZd	ed
efddZ	dS )FileValidationResultu(   파일 검증 결과를 담는 클래스c                 C   s   d| _ g | _g | _i | _d S )NT)is_validerrorswarningsinfo)self r   D/home/skpark/git/infrasmart_work/infrasmart/utils/file_validation.py__init__   s   
zFileValidationResult.__init__messagec                 C   s&   t d|  | j| d| _dS )u   오류 메시지 추가u   검증 오류 추가: FN)consolelogr	   appendr   r   r   r   r   r   	add_error   s   
zFileValidationResult.add_errorc                 C   s    t d|  | j| dS )u   경고 메시지 추가u   검증 경고 추가: N)r   r   r
   r   r   r   r   r   add_warning   s   z FileValidationResult.add_warningkeyvaluec                 C   s$   t d| d|  || j|< dS )u   정보 추가u   검증 정보 추가: z = N)r   r   r   )r   r   r   r   r   r   add_info    s   zFileValidationResult.add_infoN)
__name__
__module____qualname____doc__r   strr   r   r   r   r   r   r   r   r      s    r   returnc           
   
   C   s  t  }ztd t| }t|}tdt| dt|j d g d}|D ]}||jv rD|| t	j	
 ||< t| d q)|dt| |dt|j g d	}g }|D ]}||jvrj|| q^|r{|d
d|  |W S td t||}t||}t||}t|}|d| t||dg }|d| t||}td|j dt|j dt|j  W |S  ty }	 ztdt	|	  |dt	|	  W Y d}	~	|S d}	~	ww )u   
    Excel 파일 검증
    
    Args:
        file_content: 업로드된 파일 내용
        
    Returns:
        FileValidationResult: 검증 결과
    u   Excel 파일 검증 시작u   파일 읽기 완료: u   행, u   열)	   부재명   부재위치   손상내용   단위u    컬럼 공백 제거 완료
total_rowstotal_columnsr    r!   r"      손상물량   개소r#   u(   필수 컬럼이 누락되었습니다: , u   필수 컬럼 검증 통과validation_details
error_rowstable_previewu   검증 완료: valid=z	, errors=z, warnings=   검증 중 오류 발생: u0   파일 처리 중 오류가 발생했습니다: N)r   r   r   pd
read_excelr   lencolumnsastyper   stripr   r   r   joinvalidate_data_typesvalidate_data_valuesvalidate_component_and_damage"perform_damage_quantity_validation(generate_table_preview_with_highlightinggetgenerate_statisticsr   r	   r
   	Exception)
file_contentresultdfstring_columnscolrequired_columnsmissing_columnsdetailed_validationr,   er   r   r   validate_excel_file%   sP   


"







,rF   r?   r>   c              
   C   sP  t d z1tj| d dd}|  }|dkr"|d| d |dk  }|dkr5|d| d W n tyR } z|d	t|  W Y d
}~nd
}~ww z1tj| d dd}|  }|dkrp|d| d |dk  }|dkr|d| d W n ty } z|dt|  W Y d
}~nd
}~ww t d |S )u   데이터 타입 검증u   데이터 타입 검증 시작r'   coercer	   r   u(   손상물량에 숫자가 아닌 값이    개 있습니다.u   손상물량에 음수 값이 u    손상물량 검증 중 오류: Nr(   u"   개소에 숫자가 아닌 값이 u   개소에 음수 값이 u   개소 검증 중 오류: u   데이터 타입 검증 완료)	r   r   r.   
to_numericisnasumr   r<   r   )r?   r>   damage_quantityinvalid_quantity_countnegative_countrE   count_valuesinvalid_count_countr   r   r   r5   q   s:   
  
r5   c                 C   s  t d | d  | d dkB }| d  | d dkB }| d  | d dkB }| dkr:|d|  d | dkrK|d	|  d | dkr\|d
|  d g d}| | d |  d  }t|dkr|dd|  t d |S )u   데이터 값 검증u   데이터 값 검증 시작r     r!   r"   r   u!   부재명이 비어있는 행이 rI   u$   부재위치가 비어있는 행이 u$   손상내용이 비어있는 행이 )mmm   m²   ㎡m2cmeaEAr(      개u   식setr#   u5   지원되지 않는 단위가 사용되었습니다: r)   u   데이터 값 검증 완료)	r   r   rK   rL   r   isinuniquer0   r4   )r?   r>   empty_componentempty_positionempty_damagevalid_unitsinvalid_unitsr   r   r   r6      s    

r6   c                    s   t d g d}| d   }t dt|  g }|D ]-}t|s.t| dkr4|	d qt|  t
 fdd|D }|sL|	  qt d	 |S )
u!   부재명 및 손상내용 검증u(   부재명 및 손상내용 검증 시작)u	   바닥판u   거더u	   가로보u	   세로보u   격벽u   교대u   교각u   기초u   받침u   신축이음u   교면포장u   배수시설u   난간u	   방호벽r    u   유니크 부재명 개수: rR   u   빈값 또는 NaNc                 3       | ]}| v V  qd S Nr   ).0stdcleaned_componentr   r   	<genexpr>       z0validate_component_and_damage.<locals>.<genexpr>u(   부재명 및 손상내용 검증 완료)r   r   dropnar^   r0   r.   rK   r   r3   r   any)r?   r>   standard_componentsunique_componentsnon_standard_components	componentis_standardr   rh   r   r7      s   


r7   c              
   C   sP  t d z{| d  d }|d| | d   }|d| t| }|r9|d|  |d| tj	| d	 d
d
d}|dt|  |dt|  tj	| d d
d
d}|dt|  |dt|  t d W |S  ty } zt dt|  |dt|  W Y d}~|S d}~ww )u   통계 정보 생성u   통계 정보 생성 시작r"   
   damage_countr!   position_countu7   띄어쓰기 차이로 인한 중복 부재명 발견: duplicate_componentsr'   rG   rH   r   total_damage_quantityaverage_damage_quantityr(   total_countaverage_countu   통계 정보 생성 완료u!   통계 정보 생성 중 오류: u7   통계 정보 생성 중 오류가 발생했습니다: N)r   r   value_countsheadto_dictr   check_component_duplicatesr   r.   rJ   fillnafloatrL   meanintr<   r   )r?   r>   damage_statsposition_statscomponent_duplicatesrM   rP   rE   r   r   r   r;      s0   
r;   c                 C   s   i }g }| d    D ]$}t|r0t|dddd}||vr'g ||< || t| q| D ]\}}t|dkrPt	t
|}t|dkrP|| q5|S )u{   
    공백 차이로 인한 중복 부재명 확인
    
    Returns:
        list: 중복 부재명 그룹 리스트
    r     rR   	   )rl   r^   r.   notnar   replacer   itemsr0   listr\   )r?   component_groups
duplicatesrq   
normalizedvariantsunique_variantsr   r   r   r~      s    

r~   r   c                 C   s   dS )uA   JavaScript 스타일 콘솔 로그 (Python에서는 print 사용)Nr   )r   r   r   r   console_log  s    r   c                    s`  t d g }d}g d}fdd|D }|r!g dt|dS g d}g d}g d	}d
}d
}	d
}
jD ] t fdd|D rG } nq6jD ] t fdd|D r\ }	 nqKtd| d|	  jD ] t fdd|D r{ }
 nqj D ]\}}g }zt|d st	|d 
 dkr|d t|d st	|d 
 dkr|d t|d st	|d 
 dkr|d t|d r|d t|d r|d t|d st	|d 
 dkr|d t|d r	t	|d 
 nd}t|d rtj|d ddnd
}t||
 r/tj||
 ddnd
}t|rt|r|rd
}d
}|r^||jv r^t|| r^tj|| dd}|	rx|	|jv rxt||	 rxtj||	 dd}|
r|
|jv rt||
 rtj||
 dd}|d krt|rt|r|| }t|| d!kr|d"| d#|d$d%| d&| d'	 ng }t|r|d( t|r|d |r|d)d*|  n|d+v rZt|r(t|r(t|r(|| | }t|| d!kr'|d,| d#|d$d%| d-| d&| d' nNg }t|r5|d( t|r@|d. t|rK|d |rY|d/d*|  n| d	v rvt|| d!krv|d0| d#| d1 |dk r|d2 |dk r|d3 W n ty } z|d4t	|  W Y d
}~nd
}~ww |r||d5 |t|d rt	|d ndt|d rt	|d ndt|d rt	|d ndt|d rt	|d ndt|d rt	|d ndt|d rt	|d nddd6 q|d77 }qt d8t d9t| d: ||td;S )<u   
    손상물량 계산 검증 수행
    
    Args:
        df: 검증할 DataFrame
        
    Returns:
        dict: 검증 결과
    u!   손상물량 계산 검증 시작r   r&   c                    s   g | ]	}| j vr|qS r   )r1   )rf   rA   )r?   r   r   
<listcomp>.  s    z6perform_damage_quantity_validation.<locals>.<listcomp>)r+   
valid_rowsr$   rC      길이Llengthu   연장)   너비WwidthB)rY   rZ   r[   r(   Nc                 3   rd   re   r   rf   r   rA   r   r   rj   C  rk   z5perform_damage_quantity_validation.<locals>.<genexpr>c                 3   rd   re   r   r   r   r   r   rj   I  rk   u    사용 가능한 길이 컬럼: u   , 너비 컬럼: c                 3   rd   re   r   r   r   r   r   rj   Q  rk   r    rR   u   부재명이 비어있음r!   u   부재위치가 비어있음r"   u   손상내용이 비어있음r'   u   손상물량이 비어있음r(   u   개소가 비어있음r#   u   단위가 비어있음rG   rH   rS   g{Gz?u-   m 단위 손상물량 계산 오류1: 현재 u   , 올바른 값 z.2fu	    (길이 u    × 개소 )r   u,   m 단위 검증을 위한 정보가 없음: r)   )rV   rU   rW   u/   ㎡ 단위 손상물량 계산 오류2: 현재 u    × 너비 r   u/   ㎡ 단위 검증을 위한 정보가 없음2: u2   개수 단위 손상물량 계산 오류3: 현재 u    (개소와 동일해야 함)u   손상물량이 음수임u   개소가 음수임r-      )	row_indexr	   datar   u'   손상물량 계산 검증 완료: 총 u   행 중 u
   개 오류)r+   r   r$   )r   r   r0   r1   rm   printiterrowsr.   rK   r   r3   r   r   rJ   indexabsr4   lowerr<   )r?   r+   r   rB   rC   length_columnswidth_columnscount_columnsavailable_length_colavailable_width_colavailable_count_colidxrow
row_errorsunitrM   countr   r   expected_quantitymissing_inforE   r   )rA   r?   r   r8     s   




"
"
"


"
$&&"""
&


$,






 

 r8   r+   c              
      s  zcd}|  | }g d}g d}g d}g }|D ]  |jv r'|  q|| D ]  |jv r< |vr<|  q,|rC|| }t }|rf|D ]}	|	d d }
d|
  kr^t|k ren qJ||
 qJd}|d	7 }|jD ]  d
v r~|d  d7 }qo|d  d7 }qo|d7 }|d7 }t| D ]\}\}}||v rdnd}d}t }||v r|r|D ]/}	|	d d |krdd	|	d  d}|jD ] t
 fdd|	d D r|  q nq|d| d| d7 }|d|d  d7 }|jD ]L t|  rt|  nd}t|dkr|dd d } d
v r!d }nd}||v r9 |v r9|d!| d"| d#7 }q|d$| d%| d#7 }q|d&7 }q|d'7 }t| |krb|d(t|  d)| d*7 }|W S  ty } ztd+t|  W Y d}~d,S d}~ww )-u   
    전체 테이블 미리보기 생성 (오류 행 하이라이트 포함)
    
    Args:
        df: 미리보기할 DataFrame
        error_rows: 오류 행 정보 리스트
        
    Returns:
        str: HTML 테이블 문자열
    i  )r    r!   r"   r(   r#   r'   r   )u   폭r   u	   너비(m)r   r   r   r   r   r   zj<table class="table table-striped table-bordered table-hover" id="preview-table" style="font-size: 12px;">u_   <thead class="table-dark"><tr><th style="position: sticky; top: 0; z-index: 10;">행번호</th>)r(   r#   zV<th style="position: sticky; top: 0; z-index: 10; min-width: 50px; text-align: left;">z</th>zE<th style="position: sticky; top: 0; z-index: 10; min-width: 100px;">z</tr></thead>z<tbody>ztable-dangerrR   u   title="오류: z | r	   "c                 3   s    | ]} |v V  qd S re   r   )rf   errr   r   r   rj   #  rk   z;generate_table_preview_with_highlighting.<locals>.<genexpr>z<tr class="z" >z<td><strong>z</strong></td>   Nz...z"text-align: left; min-width: 50px;z5<td style="background-color: #f8d7da; color: #721c24;z>"><i class="fas fa-exclamation-triangle text-danger me-1"></i>z</td>z<td style="z">z</tr>z</tbody></table>uT   <div class="alert alert-info mt-2"><small><i class="fas fa-info-circle"></i> 전체 u   행 중 처음 u%   행만 표시됩니다.</small></div>u*   테이블 미리보기 생성 중 오류: u<   <p>테이블 미리보기를 생성할 수 없습니다.</p>)r|   copyr1   r   r\   r0   add	enumerater   r4   rm   r.   r   r   r<   r   r   )r?   r+   max_rows
preview_dfrB   r   r   available_columnserror_row_indices	error_rowdf_indexhtmlr   df_idxr   	row_classerror_title
error_cols
cell_valuestylerE   r   r   r   r9     s   







 

r9   c                   @   s   e Zd ZdefddZdS )Consoler   c                 C   s   t d|  d S )Nz[FILE_VALIDATION] )r   r   r   r   r   r   J  s   zConsole.logN)r   r   r   r   r   r   r   r   r   r   I  s    r   re   )r   pandasr.   renumpynptypingr   r   r   r   utils.commonr   r   rF   	DataFramer5   r6   r7   r;   r   r~   r   r   dictr8   r9   r   r   r   r   r   r   <module>   s&    L' ' Bk
