
    /Pi(                        d Z ddlmZ ddlZddlZddlZddlZddlmZmZm	Z	m
Z
mZ ddl ddlmZmZmZmZmZ ddee   fdZd	e
dee   fd
Zd	e
dedee	ee	f      de
fdZd	e
dee   dede	ee
f   fdZd	e
dee   dede
fdZdefdZde	ee
f   ded	e
dedee   deddfdZdddede	eef   dee	ee	f      dedede	ee
f   fdZde	ee
f   de	ee
f   fdZy) uY   
Утилиты для парсинга CSV/XLS/XLSX файлов при импорте.
    )copyN)IteratorListDictAnyType)*)calc_logic_typecalc_prioritycalc_choicescalc_significancecalc_estimate_timereturnc              +     K   | j                   }t        j                  j                  |      d   j	                         }|dk(  rXt        j                  |      }|j                  d      }|j                         D ]  }|D 	cg c]  }	|	j                   c}	   y|dk(  rHt        j                  |d      }|j                  }|j                  d      D ]  }t        |        y|dk(  r<t        |d	|d
      5 }
t!        j"                  |
|      }|D ]  }|  	 ddd       yt%        d|       c c}	w # 1 sw Y   yxY ww)un   
    Парсинг файла (CSV/XLS/XLSX) в итератор списков.
    settings: {"/False}
       z.xlsr   z.xlsxT)	data_only)values_onlyz.csvrreplace)encodingerrors)	delimiterNzUnsupported file format: )full_path_fileospathsplitextlowerxlrdopen_workbooksheet_by_indexget_rowsvalueopenpyxlload_workbookactive	iter_rowslistopencsvreader
ValueError)
attachmentr   r   _	file_pathextworkbook	worksheetrowcellfr*   s               "./common/utils/csv_import_utils.py
parse_filer6      s?    
 ))I
''

9
%a
(
.
.
0C
f}%%i0++A.	%%' 	/C*-.$4::..	/	)))tDOO	&&4&8 	Cs)O		)S8IF 	!ZZY7F 		 	
 4SE:;; /	 	s+   A?E	D8A)E	=#D=!E	=EE	valc                     t        h d      }t        h d      }t        |       j                         j                         }||v ry||v ryy)uz   Парсинг значения в bool с поддержкой русских и английских вариантов.>      да1yestrue+>      нет0nofalse-TFN)	frozensetstrstripr   )r7   _TRUE_VALUES_FALSE_VALUES
normalizeds       r5   _parse_boolrI   *   sL     >?LABMS!'')J\!]"    
field_namevalue_mappingc                 j    |r||vr| dfS ||   }| |v r||    dfS t        |       }||v r||   dfS | dfS )uZ   Применение пользовательского маппинга значений.FT)rD   )r7   rK   rL   val_mapstr_vals        r5   _apply_value_mappingrP   7   sc     Jm;EzJ'G
g~s|T!!#hG'w%%:rJ   field_partsis_custom_with_widgetc                 @    |rd| iS t        |      dkD  r|d   | iS d| iS )ud   Преобразование значения для связанного объекта (FK / M2M).namer   ext_id)len)r7   fieldrQ   rR   s       r5   _convert_relationrX   F   s7     }
;!A$$c?rJ   c                 `   t        |dd      }|dk(  rt        |       dfS |dk(  rt        | t              rt        |       dfS |dk(  rt        | t              rt	        |       dfS |dk(  rt        | t              rt        |       dfS t        |d      rt        | |j                        dfS t        |t              r|n
t        |      }t        |t        j                  j                        rt        |       dfS t        |t        j                  j                        rt!        | |||      d	fS | dfS )
u   
    Преобразование значения в зависимости от типа поля модели.

    Возвращает кортеж (converted_value, is_relation).
    
class_nameNrU   Fprioritysignificanceestimate_timechoicesT)getattrrD   
isinstancer   r   r   hasattrr   r^   type
issubclasscmffieldsCmfBoolrI   
CmfRelBaserX   )r7   rW   rQ   rR   rZ   	field_clss         r5   _convert_by_field_typeri   P   s    d3JX3xZJsC$8S!5((^#
3(< %u,,_$C)=!#&--ui C/66 $E40d5kI)SZZ//03&&)SZZ223 e[:OPRVVV:rJ   c                 d    t        | dd      }t        | dd      }|j                  d      xr |dv S )uV   Проверка: кастомное поле с виджетом M2M / CascadeChoice.rZ    widgetNcf_)CmfM2MCmfCascadeChoice)r_   
startswith)rW   rZ   rl   s      r5   _is_custom_widgetrq   u   s?    b1JUHd+Fe$ 	544rJ   attrs
field_rootis_relationc                    |rMt        |      dkD  r?|s=| j                  |i       }t        |t              r|j	                  |       y|||d   <   y|| v r0| |   }t        |t
              s|g| |<   | |   j                  |       y|| |<   y)uX  
    Сохранение значения в результирующий словарь.

    Мутирует attrs на месте:
    - вложенные ключи для FK-связей (parent_task.ext_id → attrs["parent_task"]["ext_id"])
    - накопление списка для multi-value полей (tags, components)
    r   N)rV   
setdefaultr`   dictupdater'   append)rr   rs   r7   rt   rQ   rR   nestedexistings           r5   _store_valuer|      s     s;'!+4I!!*b1c4 MM# 	 &)F;q>" U$(D)!)
E*j  %jrJ   T)include_rawr2   mapping	model_clsr}   c          	      f   i }|j                         D ]  \  }}|d   |j                  k7  r	 t        |      }|t        |       k\  r4| |   }	|	|	dk(  rA|d   j                  d      }
|
d   }t        |	|d   |      \  }	}d}d}|j                  j                  |      }|r_t        |      }t        |t              r|n
t        |      }t        |t        j                  j                        }|st!        |	||
|      \  }	}t#        |||	||
|        |r|r| |d<   |S # t        t        f$ r Y w xY w)u  
    Маппинг строки импорта в словарь атрибутов модели.

    Параметры
    ---------
    row : list
        Строка данных (список значений ячеек).
    mapping : dict[str, str]
        Соответствие «индекс колонки (строкой)» → «имя поля модели».
        Пример: {"0": {'field_name': 'name', 'model_name': 'CmfTask'}, "1": {'field_name': 'priority', 'model_name': 'CmfTask'}, 
                "3": {'field_name': 'parent_task.ext_id', 'model_name': 'CmfTask'}}
        Ключи — строки, т.к. формат приходит из JSON.
    value_mapping : dict, optional
        Пользовательский маппинг значений по полям.
        Пример: {"priority": {"Высокий": "high", "Низкий": "low"}}
    model_cls : type
        Класс модели CMF для типизации полей.
    include_raw : bool
        Добавлять ли исходную строку в attrs["import_raw_json"].

    Возвращает
    ----------
    dict[str, Any]
        Словарь атрибутов, готовый для создания/обновления объекта модели.
        Пустой словарь, если ни одно поле не было успешно смаппировано.
    
model_namerk   rK   .r   Fimport_raw_json)itemsrZ   intr+   	TypeErrorrV   splitrP   re   getrq   r`   rb   rc   rd   rg   ri   r|   )r2   r~   rL   r   r}   rr   col_idx_str	field_mapcol_idxr7   rQ   rs   mappedrt   rR   rW   rh   s                    r5   map_rowr      sl   D E")--/ '9Y\"i&:&::	+&G c#h'l;#)  -33C8 ^
 +3	,0GWV  %  $$Z0$5e$<!!+E4!8d5kI$Y

0E0EFK#9-B$ [
 	UJ[ "7	9M'9T #& LO I& 		s   DD0/D0c                 x   |j                         D ci c],  \  }}|j                  d      r|j                  d      r*||. }}}d}t        |      j                         D ]  \  }}| j                  j	                  |      }|s$t        |t        j                  j                        rIt        |t              r|D 	cg c]  }	dt        |	      i c}	||<   wt        |t              sd|ig||<   |j                  |v s|j                  d| d| d       ||=  ||d<   ||d	<   ||d
<   |S c c}}w c c}	w )u   
    Подготовка атрибутов для создания объекта.
    Очищает служебные поля и подготавливает M2M поля.
    r-   step_)status
cmf_authorparentprojectcmf_created_atcodecmf_modified_atrT   u    Нельзя загружать =warningr   r   
cmf_import)r   rp   r   re   r   r`   rd   
CmfM2MBaser'   rD   rZ   log)
r   rr   r   
import_objkvclean_attrsPROTECTED_FIELDSrW   items
             r5   prepare_object_attrsr      s:   
 %*KKMiDAqc9JSTS_S_`gSh1a4iKiq[!'') 1  $$Q'eSZZ223!T"BC!D$63t9"5!DAAs#$*A;-Q!11NN=aS!EyQA #K#K	 *K' j "Es   D1D1 D1?D7);zutf-8)__doc__r   r   r)   r   r#   typingr   r   r   r   r   cmf.includecommon.utils.import_utilsr
   r   r   r   r   r6   OptionalboolrI   rD   rP   rX   ri   rq   r|   r   r    rJ   r5   <module>r      s    	 
   2 2  y y<QU <8
S 
Xd^ 
c s (0c4i(AFI3 DI -16:38n" "c "26";>"J  S#X  C  c  " 15c (, 15 F Q	Q#s(^Q DdO,Q 	Q Q 
#s(^Qh4S> RVWZ\_W_R` rJ   