// DocManager.cpp

#include "stdafx.h"
#include <aplXML.h>
#include "dictionary.h"
#include "apl_api.h"
#include "resource.h"
#include "DocCreateDlg.h"
#include "FileLoadDlg.h"
#include "Eraser.h"
//#include "DocumentChangeDlg.h"
#include "DocChanges.h"
#include "ChangeDocVerDlg.h"
#include "SelectAppDlg.h"
#include "choose_inst_dlg.h"
#include "DisAsmStatusDlg.h"
#include "SSCopyDocsDlg.h"
#include "CompareFoldersDlg.h"
#include "HardCopyDlg.h"
#include "DocCopyFilterDlg.h"
#include "ShowDocCopyesDlg.h"
#include "HardCopyHistoryDlg.h"
#include "EntryPropDlg.h"
#include "Helper.h"
#include "ReportApprovalFiledsSetupDlg.h"
#include "aplMPC.h"

CEraser eraser;

#include <list>


//если хочется вложить любое из выражений друг в друга - ставьте фигурные скобки
#define forr(it,ms) for((it)=(ms).begin();(it)!=(ms).end();++(it))
#define ifnend(it,ms,ke) if(((it)=(ms).find(ke))!=(ms).end())
#define ifend(it,ms,ke) if(((it)=(ms).find(ke))==(ms).end())
#define iffindinsertmap(it,ms,ke,pa) ifend(it,ms,ke)(it)=(ms).insert(std::make_pair((ke),(pa))).first;
#define iffindinsertreplacemap(it,ms,ke,pa) iffindinsertmap(it,ms,ke,pa)else(it)=(ms).insert(std::make_pair((ke),(pa))).first;
#define iffindinsertset(it,ms,ke) ifend(it,ms,ke)(it)=(ms).insert(ke).first;
#define iffindinsertreplaceset(it,ms,ke) iffindinsertset(it,ms,ke)else(it)=(ms).insert(ke).first;
#define contains(ms,ke) (ms).find(ke)!=(ms).end()
#define ifcontains(ms,ke) if((ms).find(ke)!=(ms).end())


const TCHAR EnableLog[] =  APL_NO_T("Протоколирование\\Документы\\Включать протоколирование доступа к содержимому документов");
const TCHAR dp_name_options_notification_limit[] = APL_NO_T("Протоколирование\\Документы\\Оповещать если просмотрено документов");
const TCHAR dp_name_options_notification_time[] = APL_NO_T("Протоколирование\\Документы\\Интервал времени для контроля");
const TCHAR dp_name_options_notification_recipient[] = APL_NO_T("Протоколирование\\Документы\\Получатель оповещения");
const TCHAR DocLogName[]	= APL_NO_T("DocAccessLog.log");
const TCHAR SetReadOnlyOnCreate[] = APL_NO_T("Настройка документов\\Устанавливать атрибут для файла \"Только чтение\" при создании документа");

DWORD tick_last_doc_excess = 0;


bool PrepareEnvInPath(CaplAPI *m_api,CString &fpath)
{
	int i=fpath.Find(_T('@'));
	if(i<0) return true;

	int j=fpath.Find(_T('@'),i+1);
	if(j<0) return true;
		
	CString buf,var=fpath.Mid(i+1,j-i-1);
	CString env; env.GetEnvironmentVariable(LPCTSTR(var));
	if(env==_T(""))
	{
		if(m_api!=0)
		{
			if(m_api->m_ModeInteractive)
			{
				buf= APL_T("Указанная в настройках рабочей папки переменная окружения \"");
				buf+=var;
				buf+= APL_T("\" не найдена!");
				AfxMessageBox(buf,MB_ICONSTOP|MB_OK);
			}
			return false;
		}
	}

	buf=fpath.Left(i);
	buf+=env;
	buf+=fpath.Right(fpath.GetLength()-j-1);
	fpath=buf;
	return true;
}


BOOL CaplDocManager::m_bUseAplMarkView=FALSE;

//*************************************************************
bool CaplDocManager::Attach(CaplAPI *api)
{
	m_lastflag = 0;
	if(api==0) {Detach();return false;}
	CaplStepManager::Attach(api);
	m_service_ext_lock=false;

	CHECK_ZERO_ATTR(e_apl_doc_ref, m_data->GetEntityBN(S::apl_document_reference));
	CHECK_ZERO_ATTR(a_apl_doc_ref_item, m_data->GetAttrDefinition(e_apl_doc_ref,S::item));
	CHECK_ZERO_ATTR(a_apl_doc_ref_doc, m_data->GetAttrDefinition(e_apl_doc_ref,S::assigned_document));
	CHECK_ZERO_ATTR(a_doc_rel_frames_of_reference, m_data->GetAttrDefinition(e_apl_doc_ref,_T("apl_frames_of_reference")));
	CHECK_ZERO_ATTR(a_apl_doc_ref_src, m_data->GetAttrDefinition(e_apl_doc_ref,_T("source")));
	CHECK_ZERO_ATTR(a_apl_doc_ref_inner_label, m_data->GetAttrDefinition(e_apl_doc_ref,_T("inner_label")));

	CHECK_ZERO_ATTR(e_doc, m_data->GetEntityBN(S::document));
	CHECK_ZERO_ATTR(a_doc_id, m_data->GetAttrDefinition(e_doc,S::id));
	CHECK_ZERO_ATTR(a_doc_name, m_data->GetAttrDefinition(e_doc,S::name));
	CHECK_ZERO_ATTR(a_doc_descr, m_data->GetAttrDefinition(e_doc,S::description));
	CHECK_ZERO_ATTR(a_doc_code, m_data->GetAttrDefinition(e_doc, _T("code")));
	CHECK_ZERO_ATTR(a_doc_kind, m_data->GetAttrDefinition(e_doc,S::kind));
	CHECK_ZERO_ATTR(a_doc_authentic, m_data->GetAttrDefinition(e_doc, _T("authentic")));
	CHECK_ZERO_ATTR(a_doc_add_dt_code, m_data->GetAttrDefinition(e_doc, _T("add_document_type_code")));
	CHECK_ZERO_ATTR(a_doc_code_depend_desp, m_data->GetAttrDefinition(e_doc, _T("code_doc_in_depending_of_disposition")));
	CHECK_ZERO_ATTR(a_doc_struct_kind, m_data->GetAttrDefinition(e_doc, _T("struct_kind")));
	CHECK_ZERO_ATTR(a_doc_incl_in_doc,m_data->GetAttrDefinition(e_doc, _T("incl_in_doc")));
	CHECK_ZERO_ATTR(a_doc_format , m_data->GetAttrDefinition(e_doc, _T("format")));				
	CHECK_ZERO_ATTR(a_doc_sheets , m_data->GetAttrDefinition(e_doc, _T("sheets")));				
	CHECK_ZERO_ATTR(a_doc_total_sheets_count , m_data->GetAttrDefinition(e_doc, _T("total_sheets_count")));	
	CHECK_ZERO_ATTR(a_doc_total_sheets_count_a4 , m_data->GetAttrDefinition(e_doc, _T("total_sheets_count_a4")));	
	CHECK_ZERO_ATTR(a_doc_litera , m_data->GetAttrDefinition(e_doc, _T("litera")));				
	CHECK_ZERO_ATTR(a_doc_part , m_data->GetAttrDefinition(e_doc, _T("part")));
	CHECK_ZERO_ATTR(a_doc_accept_archive_date , m_data->GetAttrDefinition(e_doc, _T("accept_archive_date")));
	CHECK_ZERO_ATTR(a_doc_released_by , m_data->GetAttrDefinition(e_doc, _T("released_by")));
	CHECK_ZERO_ATTR(a_doc_accept_approval , m_data->GetAttrDefinition(e_doc, _T("accept_approval")));
	CHECK_ZERO_ATTR(a_doc_pdf_code , m_data->GetAttrDefinition(e_doc, _T("pdf_code")));
	CHECK_ZERO_ATTR(a_doc_is_dublicate , m_data->GetAttrDefinition(e_doc, _T("is_dublicate")));
	CHECK_ZERO_ATTR(a_doc_dublicate_inv_num , m_data->GetAttrDefinition(e_doc, _T("dublicate_inv_num")));
	CHECK_ZERO_ATTR(a_doc_subst_inv_num , m_data->GetAttrDefinition(e_doc, _T("subst_inv_num")));
	CHECK_ZERO_ATTR(a_doc_inv_num , m_data->GetAttrDefinition(e_doc, _T("inv_num")));
	CHECK_ZERO_ATTR(a_doc_mail_list , m_data->GetAttrDefinition(e_doc, _T("mail_list")));
	CHECK_ZERO_ATTR(a_doc_src_item , m_data->GetAttrDefinition(e_doc, _T("src_item")));
	CHECK_ZERO_ATTR(a_doc_guid , m_data->GetAttrDefinition(e_doc, _T("guid")));
	CHECK_ZERO_ATTR(a_doc_external_ref , m_data->GetAttrDefinition(e_doc, _T("external_ref")));

	CHECK_ZERO_ATTR(a_doc_from , m_data->GetAttrDefinition(e_doc, _T("from")));
	CHECK_ZERO_ATTR(a_doc_to , m_data->GetAttrDefinition(e_doc, _T("to")));
	CHECK_ZERO_ATTR(a_doc_recipients , m_data->GetAttrDefinition(e_doc, _T("recipients")));
	CHECK_ZERO_ATTR(a_doc_urgency , m_data->GetAttrDefinition(e_doc, _T("urgency")));
	CHECK_ZERO_ATTR(a_doc_date , m_data->GetAttrDefinition(e_doc, _T("date")));
	CHECK_ZERO_ATTR(a_doc_date_of_execution_required , m_data->GetAttrDefinition(e_doc, _T("date_of_execution_required")));
	CHECK_ZERO_ATTR(a_doc_of_execution_planned , m_data->GetAttrDefinition(e_doc, _T("date_of_execution_planned")));
	CHECK_ZERO_ATTR(a_doc_of_execution_fact , m_data->GetAttrDefinition(e_doc, _T("date_of_execution_fact")));

	
	CHECK_ZERO_ATTR(e_dt,m_data->GetEntityBN(S::document_type));
	CHECK_ZERO_ATTR(a_dt_pdt,m_data->GetAttrDefinition(e_dt,_T("product_data_type")));
	CHECK_ZERO_ATTR(a_dt_id,m_data->GetAttrDefinition(e_dt,_T("id")));
	CHECK_ZERO_ATTR(a_dt_entries,m_data->GetAttrDefinition(e_dt,_T("entries")));
	CHECK_ZERO_ATTR(a_dt_sort_num,m_data->GetAttrDefinition(e_dt,_T("sort_num")));
	CHECK_ZERO_ATTR(a_dt_auth_formats,m_data->GetAttrDefinition(e_dt,_T("authorized_format")));	
	CHECK_ZERO_ATTR(a_dt_basis,m_data->GetAttrDefinition(e_dt,_T("basis")));	

	// реквизиты документа
	CHECK_ZERO_ATTR(e_dt_entry,m_data->GetEntityBN(S::apl_document_type_entry));
	CHECK_ZERO_ATTR(a_dt_entry_opt,m_data->GetAttrDefinition(e_dt_entry,_T("optional")));
	CHECK_ZERO_ATTR(a_dt_entry_status,m_data->GetAttrDefinition(e_dt_entry,_T("statuses")));
	CHECK_ZERO_ATTR(a_dt_entry_entry,m_data->GetAttrDefinition(e_dt_entry,_T("entry")));

	// реквизит
	CHECK_ZERO_ATTR(e_entry,m_data->GetEntityBN(S::apl_document_entry));
	CHECK_ZERO_ATTR(a_entry_id,m_data->GetAttrDefinition(e_entry,_T("id")));
	CHECK_ZERO_ATTR(a_entry_name,m_data->GetAttrDefinition(e_entry,_T("name")));
	CHECK_ZERO_ATTR(a_entry_basis,m_data->GetAttrDefinition(e_entry,_T("basis")));
	CHECK_ZERO_ATTR(a_entry_val,m_data->GetAttrDefinition(e_entry,_T("values")));
	CHECK_ZERO_ATTR(a_entry_card_field,m_data->GetAttrDefinition(e_entry,_T("document_card_field")));
	CHECK_ZERO_ATTR(a_entry_descr,m_data->GetAttrDefinition(e_entry, _T("description")));

	// значение реквизита
	CHECK_ZERO_ATTR(e_doc_entry_val,m_data->GetEntityBN(S::apl_document_entry_value));
	CHECK_ZERO_ATTR(a_doc_entry_val_val,m_data->GetAttrDefinition(e_doc_entry_val,_T("value")));
	CHECK_ZERO_ATTR(a_doc_entry_val_prev,m_data->GetAttrDefinition(e_doc_entry_val,_T("prev_value")));
	CHECK_ZERO_ATTR(a_doc_entry_val_entry,m_data->GetAttrDefinition(e_doc_entry_val,_T("entry")));
	CHECK_ZERO_ATTR(a_doc_entry_val_stored,m_data->GetAttrDefinition(e_doc_entry_val,_T("stored")));
	CHECK_ZERO_ATTR(a_doc_entry_val_descr,m_data->GetAttrDefinition(e_doc_entry_val,_T("description")));

	// документ
	CHECK_ZERO_ATTR(e_apl_doc,m_data->GetEntityBN(S::apl_document));
	CHECK_ZERO_ATTR(a_apl_doc_wf_state,m_data->GetAttrDefinition(e_apl_doc,S::state));
	CHECK_ZERO_ATTR(a_apl_doc_active,m_data->GetAttrDefinition(e_apl_doc,S::active));
	CHECK_ZERO_ATTR(a_apl_doc_lock,m_data->GetAttrDefinition(e_apl_doc,_T("locker")));
	CHECK_ZERO_ATTR(a_apl_doc_system,m_data->GetAttrDefinition(e_apl_doc,_T("system")));
	CHECK_ZERO_ATTR(a_apl_doc_inner_label, m_data->GetAttrDefinition(e_apl_doc,_T("inner_label")));
	CHECK_ZERO_ATTR(a_apl_doc_reg_num, m_data->GetAttrDefinition(e_apl_doc,_T("reg_num")));
	CHECK_ZERO_ATTR(a_apl_doc_reg_type, m_data->GetAttrDefinition(e_apl_doc,_T("reg_type")));
	CHECK_ZERO_ATTR(a_ils_doc_type, m_data->GetAttrDefinition(e_apl_doc,_T("ils_type")));	

	// версия документа
	CHECK_ZERO_ATTR(e_apl_doc_rev,m_data->GetEntityBN(S::apl_document_revision));
	CHECK_ZERO_ATTR(a_apl_doc_rev_id,m_data->GetAttrDefinition(e_apl_doc_rev,S::revision_id));
	CHECK_ZERO_ATTR(a_apl_doc_rev_doc,m_data->GetAttrDefinition(e_apl_doc_rev,S::of_document));
	CHECK_ZERO_ATTR(a_apl_doc_rev_label,m_data->GetAttrDefinition(e_apl_doc_rev,S::label_name));
	CHECK_ZERO_ATTR(a_apl_doc_rev_it_needs_work,m_data->GetAttrDefinition(e_apl_doc_rev,_T("it_needs_work")));
	CHECK_ZERO_ATTR(a_apl_doc_rev_format,m_data->GetAttrDefinition(e_apl_doc_rev,_T("format")));
	CHECK_ZERO_ATTR(a_apl_doc_rev_litera,m_data->GetAttrDefinition(e_apl_doc_rev,_T("litera")));
	CHECK_ZERO_ATTR(a_apl_doc_rev_descr,m_data->GetAttrDefinition(e_apl_doc_rev,S::description));
	CHECK_ZERO_ATTR(a_apl_doc_rev_crc,m_data->GetAttrDefinition(e_apl_doc_rev,S::crc));
	CHECK_ZERO_ATTR(a_apl_doc_rev_base,m_data->GetAttrDefinition(e_apl_doc_rev,_T("base_revision")));
	CHECK_ZERO_ATTR(a_apl_doc_rev_start_s,m_data->GetAttrDefinition(e_apl_doc_rev,_T("start_date_s")));
	CHECK_ZERO_ATTR(a_apl_doc_rev_end_s,m_data->GetAttrDefinition(e_apl_doc_rev,_T("end_date_s")));
	CHECK_ZERO_ATTR(a_apl_doc_rev_user,m_data->GetAttrDefinition(e_apl_doc_rev,S::user));
	CHECK_ZERO_ATTR(a_apl_doc_rev_autor,m_data->GetAttrDefinition(e_apl_doc_rev,_T("author")));
	CHECK_ZERO_ATTR(a_apl_doc_rev_edit_path,m_data->GetAttrDefinition(e_apl_doc_rev,_T("edit_path")));
	CHECK_ZERO_ATTR(a_apl_doc_rev_entries,m_data->GetAttrDefinition(e_apl_doc_rev,_T("entries")));
	CHECK_ZERO_ATTR(a_apl_doc_rev_src_doc_ver,m_data->GetAttrDefinition(e_apl_doc_rev,_T("source_doc_ver")));
	CHECK_ZERO_ATTR(a_apl_doc_rev_inner_label, m_data->GetAttrDefinition(e_apl_doc_rev,_T("inner_label")));

	CHECK_ZERO_ATTR(a_apl_doc_rev_sheets , m_data->GetAttrDefinition(e_apl_doc_rev, _T("sheets")));
	CHECK_ZERO_ATTR(a_apl_doc_rev_total_sheets , m_data->GetAttrDefinition(e_apl_doc_rev, _T("total_sheets_count")));
	CHECK_ZERO_ATTR(a_apl_doc_rev_total_sheets_count_a4 , m_data->GetAttrDefinition(e_apl_doc_rev, _T("total_sheets_count_a4")));

	CHECK_ZERO_ATTR(a_apl_doc_rev_src_author,m_data->GetAttrDefinition(e_apl_doc_rev,_T("src_author")));
	CHECK_ZERO_ATTR(a_apl_doc_rev_src_date,m_data->GetAttrDefinition(e_apl_doc_rev,_T("src_date")));
	CHECK_ZERO_ATTR(a_apl_doc_rev_language,m_data->GetAttrDefinition(e_apl_doc_rev,_T("language")));
	CHECK_ZERO_ATTR(a_apl_doc_rev_stored_on,m_data->GetAttrDefinition(e_apl_doc_rev,_T("stored_on")));
	CHECK_ZERO_ATTR(a_apl_doc_rev_char_val_versions,m_data->GetAttrDefinition(e_apl_doc_rev,_T("characteristic_value_versions")));
	CHECK_ZERO_ATTR(a_apl_doc_rev_pictures , m_data->GetAttrDefinition(e_apl_doc_rev, _T("pictures")));

	CHECK_ZERO_ATTR(a_apl_doc_rev_lss_dic_ver,m_data->GetAttrDefinition(e_apl_doc_rev,_T("lss_dictionary_ver")));
	CHECK_ZERO_ATTR(a_apl_doc_rev_gen_by_software , m_data->GetAttrDefinition(e_apl_doc_rev, _T("generated_by_software")));

	CHECK_ZERO_ATTR(e_apl_digital_document,m_data->GetEntityBN(S::apl_digital_document));
	CHECK_ZERO_ATTR(a_apl_doc_rev_access_form,m_data->GetAttrDefinition(e_apl_digital_document,S::access_form));
	CHECK_ZERO_ATTR(e_apl_stored_document,m_data->GetEntityBN(S::apl_stored_document));
	CHECK_ZERO_ATTR(a_apl_stored_document_file_name,m_data->GetAttrDefinition(e_apl_stored_document,S::file_name));
	CHECK_ZERO_ATTR(a_apl_stored_document_source,m_data->GetAttrDefinition(e_apl_stored_document,S::source));
	CHECK_ZERO_ATTR(a_apl_stored_document_code , m_data->GetAttrDefinition(e_apl_stored_document, _T("code")));
	CHECK_ZERO_ATTR(e_apl_assigned_document,m_data->GetEntityBN(S::apl_assigned_document));
	CHECK_ZERO_ATTR(a_apl_assigned_document_location_path,m_data->GetAttrDefinition(e_apl_assigned_document,S::location_path));

	e_apl_doc_change = m_data->GetEntityBN(_T("apl_document_change"));
	a_apl_doc_change_id = m_data->GetAttrDefinition(e_apl_doc_change, _T("id"));
	a_apl_doc_change_name = m_data->GetAttrDefinition(e_apl_doc_change, _T("name"));
	a_apl_doc_change_descr = m_data->GetAttrDefinition(e_apl_doc_change, _T("description"));
	a_apl_doc_change_user = m_data->GetAttrDefinition(e_apl_doc_change, _T("user"));
	a_apl_doc_change_person = m_data->GetAttrDefinition(e_apl_doc_change, _T("author"));
	a_apl_doc_change_doc = m_data->GetAttrDefinition(e_apl_doc_change, _T("document"));
	a_apl_doc_change_old = m_data->GetAttrDefinition(e_apl_doc_change, _T("old_revision"));
	a_apl_doc_change_new = m_data->GetAttrDefinition(e_apl_doc_change, _T("new_revision"));
	a_apl_doc_change_date_s = m_data->GetAttrDefinition(e_apl_doc_change, _T("date_s"));
	a_apl_doc_change_attachment = m_data->GetAttrDefinition(e_apl_doc_change, _T("attachment"));
	a_apl_doc_change_basis = m_data->GetAttrDefinition(e_apl_doc_change, _T("basis"));					

	// Группы типов документов
	CHECK_ZERO_ATTR(e_dt_group, m_data->GetEntityBN(_T("document_type_group")));
	CHECK_ZERO_ATTR(a_dt_group_id, m_data->GetAttrDefinition(e_dt_group,_T("id")));
	CHECK_ZERO_ATTR(a_dt_group_name, m_data->GetAttrDefinition(e_dt_group,_T("name")));
	CHECK_ZERO_ATTR(a_dt_group_descr, m_data->GetAttrDefinition(e_dt_group,_T("description")));
	CHECK_ZERO_ATTR(a_dt_group_par, m_data->GetAttrDefinition(e_dt_group,_T("parent")));
	CHECK_ZERO_ATTR(a_dt_group_content, m_data->GetAttrDefinition(e_dt_group,_T("content")));
	CHECK_ZERO_ATTR(a_apl_doc_ref_type,m_data->GetAttrDefinition(e_apl_doc_ref,_T("type")));
	CHECK_ZERO_ATTR(a_apl_doc_ref_start_date,m_data->GetAttrDefinition(e_apl_doc_ref,_T("start_date")));
	CHECK_ZERO_ATTR(a_apl_doc_ref_end_date,m_data->GetAttrDefinition(e_apl_doc_ref,_T("end_date")));

	CHECK_ZERO_ATTR(e_doc_copy,m_data->GetEntityBN(_T("apl_hard_copy_document")));
	CHECK_ZERO_ATTR(a_doc_copy_id,m_data->GetAttrDefinition(e_doc_copy,_T("id")));
	CHECK_ZERO_ATTR(a_doc_copy_state,m_data->GetAttrDefinition(e_doc_copy,_T("state")));
	CHECK_ZERO_ATTR(a_doc_copy_first_rev,m_data->GetAttrDefinition(e_doc_copy,_T("first_revision")));
	CHECK_ZERO_ATTR(a_doc_copy_cur_rev,m_data->GetAttrDefinition(e_doc_copy,_T("current_revision")));
	CHECK_ZERO_ATTR(a_doc_copy_issue_date,m_data->GetAttrDefinition(e_doc_copy,_T("issue_date")));
	CHECK_ZERO_ATTR(a_doc_copy_last_update,m_data->GetAttrDefinition(e_doc_copy,_T("last_update")));
	CHECK_ZERO_ATTR(a_doc_copy_owner,m_data->GetAttrDefinition(e_doc_copy,_T("owner")));
	CHECK_ZERO_ATTR(a_doc_copy_place_of_use,m_data->GetAttrDefinition(e_doc_copy,_T("place_of_use")));
	CHECK_ZERO_ATTR(a_doc_copy_doc,m_data->GetAttrDefinition(e_doc_copy,_T("document")));
	CHECK_ZERO_ATTR(a_doc_copy_pur_order,m_data->GetAttrDefinition(e_doc_copy,_T("purchase_order")));
	CHECK_ZERO_ATTR(a_doc_copy_real_state,m_data->GetAttrDefinition(e_doc_copy,_T("real_state")));
	CHECK_ZERO_ATTR(a_doc_copy_who,m_data->GetAttrDefinition(e_doc_copy,_T("who")));
	CHECK_ZERO_ATTR(a_doc_copy_destroy_act,m_data->GetAttrDefinition(e_doc_copy,_T("destroy_act")));

	// выдача по заказ-наряду
	CHECK_ZERO_ATTR(e_apl_order_issue,       m_data->GetEntityBN(_T("apl_order_issue")));
	CHECK_ZERO_ATTR(a_apl_order_issue_order, m_data->GetAttrDefinition(e_apl_order_issue, _T("order")));
	CHECK_ZERO_ATTR(a_apl_order_issue_doc_number, m_data->GetAttrDefinition(e_apl_order_issue, _T("document_number")));
	CHECK_ZERO_ATTR(a_apl_order_issue_shop,  m_data->GetAttrDefinition(e_apl_order_issue, _T("shop")));
	CHECK_ZERO_ATTR(a_apl_order_issue_date,  m_data->GetAttrDefinition(e_apl_order_issue, _T("date")));
	CHECK_ZERO_ATTR(a_apl_order_issue_reciever,  m_data->GetAttrDefinition(e_apl_order_issue, _T("reciever")));
	CHECK_ZERO_ATTR(a_apl_order_issue_document,  m_data->GetAttrDefinition(e_apl_order_issue, _T("document")));
		
	// заказ-наряд
	CHECK_ZERO_ATTR(e_doc_copy_order,m_data->GetEntityBN(_T("apl_hardcopy_purchase_order")));
	CHECK_ZERO_ATTR(a_purchase_order_els,m_data->GetAttrDefinition(e_doc_copy_order,_T("elements")));
	CHECK_ZERO_ATTR(a_purchase_order_id,m_data->GetAttrDefinition(e_doc_copy_order,_T("id")));
	CHECK_ZERO_ATTR(a_purchase_order_order,m_data->GetAttrDefinition(e_doc_copy_order,_T("order")));
	CHECK_ZERO_ATTR(a_purchase_order_code,m_data->GetAttrDefinition(e_doc_copy_order,_T("code")));
	CHECK_ZERO_ATTR(a_purchase_order_introd,m_data->GetAttrDefinition(e_doc_copy_order,_T("introd")));
	
	CHECK_ZERO_ATTR(a_purchase_order_descr,m_data->GetAttrDefinition(e_doc_copy_order,_T("description")));
	CHECK_ZERO_ATTR(a_purchase_order_date,m_data->GetAttrDefinition(e_doc_copy_order,_T("date")));
	CHECK_ZERO_ATTR(a_purchase_order_cust,m_data->GetAttrDefinition(e_doc_copy_order,_T("customer")));
	CHECK_ZERO_ATTR(a_purchase_order_type,m_data->GetAttrDefinition(e_doc_copy_order,_T("type")));
	CHECK_ZERO_ATTR(a_purchase_order_hc,m_data->GetAttrDefinition(e_doc_copy_order,_T("hard_copies")));
	CHECK_ZERO_ATTR(a_purchase_order_of_change,m_data->GetAttrDefinition(e_doc_copy_order,_T("of_change")));

	// элемент заказ-наряда
	CHECK_ZERO_ATTR(e_order_elem,m_data->GetEntityBN(_T("apl_document_purchase_order_element")));
	CHECK_ZERO_ATTR(a_order_elem_doc,m_data->GetAttrDefinition(e_order_elem,_T("document")));
	CHECK_ZERO_ATTR(a_order_elem_count,m_data->GetAttrDefinition(e_order_elem,_T("count")));
	CHECK_ZERO_ATTR(a_order_elem_order,m_data->GetAttrDefinition(e_order_elem,_T("order")));

	CHECK_ZERO_ATTR(e_doc_copy_rev_change,m_data->GetEntityBN(_T("apl_doc_copy_rev_change")));	
	CHECK_ZERO_ATTR(a_doc_copy_rev_change_doc_change,m_data->GetAttrDefinition(e_doc_copy_rev_change,_T("document_change")));
	CHECK_ZERO_ATTR(a_doc_copy_rev_change_author,m_data->GetAttrDefinition(e_doc_copy_rev_change,_T("author")));
	CHECK_ZERO_ATTR(a_doc_copy_rev_change_apply_date,m_data->GetAttrDefinition(e_doc_copy_rev_change,_T("apply_date")));
	CHECK_ZERO_ATTR(a_doc_copy_rev_change_hard_copy,m_data->GetAttrDefinition(e_doc_copy_rev_change,_T("hard_copy")));

	CHECK_ZERO_ATTR(e_doc_copy_owner_change,m_data->GetEntityBN(_T("apl_doc_copy_owner_change")));
	CHECK_ZERO_ATTR(a_doc_copy_owner_change_basis,m_data->GetAttrDefinition(e_doc_copy_owner_change,_T("basis")));
	CHECK_ZERO_ATTR(a_doc_copy_owner_change_hand_date,m_data->GetAttrDefinition(e_doc_copy_owner_change,_T("hand_date")));
	CHECK_ZERO_ATTR(a_doc_copy_owner_change_new_owner,m_data->GetAttrDefinition(e_doc_copy_owner_change,_T("new_owner")));
	CHECK_ZERO_ATTR(a_doc_copy_owner_change_new_place_of_use,m_data->GetAttrDefinition(e_doc_copy_owner_change,_T("new_place_of_use")));
	CHECK_ZERO_ATTR(a_doc_copy_owner_change_hard_copy,m_data->GetAttrDefinition(e_doc_copy_owner_change,_T("hard_copy")));

	CHECK_ZERO_ATTR(e_apl_xml_index , m_data->GetEntityBN(	_T("apl_xml_index")	));	
	CHECK_ZERO_ATTR(a_apl_xml_index_cur_doc_rev	, m_data->GetAttrDefinition	(	e_apl_xml_index,	_T("apl_doc_rev")		));
	CHECK_ZERO_ATTR(a_apl_xml_index_lps_system	, m_data->GetAttrDefinition	(	e_apl_xml_index,	_T("lps_system")		));
	CHECK_ZERO_ATTR(a_apl_xml_index_sys_id		, m_data->GetAttrDefinition	(	e_apl_xml_index,	_T("sys_id")			));
	CHECK_ZERO_ATTR(a_apl_xml_index_type		, m_data->GetAttrDefinition	(	e_apl_xml_index,	_T("type")				));
	CHECK_ZERO_ATTR(a_apl_xml_index_type_name	, m_data->GetAttrDefinition	(	e_apl_xml_index,	_T("type_name")			));
	CHECK_ZERO_ATTR(a_apl_xml_index_id			, m_data->GetAttrDefinition	(	e_apl_xml_index,	_T("id")				));
	CHECK_ZERO_ATTR(a_apl_xml_index_name		, m_data->GetAttrDefinition	(	e_apl_xml_index,	_T("name")				));
	CHECK_ZERO_ATTR(a_apl_xml_index_name_eng	, m_data->GetAttrDefinition	(	e_apl_xml_index,	_T("name_eng")			));
	CHECK_ZERO_ATTR(a_apl_xml_index_config_info	, m_data->GetAttrDefinition	(	e_apl_xml_index,	_T("config_info")		));
	CHECK_ZERO_ATTR(a_apl_xml_index_ref_guid	, m_data->GetAttrDefinition	(	e_apl_xml_index,	_T("ref_guid")		));
	CHECK_ZERO_ATTR(a_apl_xml_index_cfg			, m_data->GetAttrDefinition	(	e_apl_xml_index,	_T("configuration")		));

//	e_apl_xml_index_relation = m_data->GetEntityBN(	_T("apl_xml_index_relation")	);	
//	a_apl_xml_index_relation_relating		= m_data->GetAttrDefinition	(	e_apl_xml_index_relation,	_T("relating")	);
//	a_apl_xml_index_relation_related		= m_data->GetAttrDefinition	(	e_apl_xml_index_relation,	_T("related")		);

	CaplLoadData ld(&m_api->m_data, DEF_SOURCE);
	ld.AddQuery(_T('e'), 0, e_entry, 0, true, true);
	ld.LoadEx();

	return m_AllAttrDefined;
}

//*************************************************************
void CaplDocManager::Detach()
{
	m_data=0;

	e_apl_doc_ref=0; a_apl_doc_ref_item=0;	a_apl_doc_ref_doc=0; a_doc_rel_frames_of_reference=0;
	a_apl_doc_ref_src=0;
	a_apl_doc_ref_inner_label = NULL;

	e_doc=0; 	a_doc_id=0; a_doc_name=0; a_doc_descr=0; a_doc_code= 0; a_doc_kind=0;
	e_apl_doc=0; a_apl_doc_wf_state=0; a_apl_doc_active=0; a_apl_doc_lock=0; a_apl_doc_system=0;
	a_apl_doc_inner_label = NULL;
	a_apl_doc_reg_num=0; a_apl_doc_reg_type=0;
	a_ils_doc_type = 0;
	a_doc_total_sheets_count_a4=0; a_doc_total_sheets_count=0;
	a_doc_accept_archive_date = NULL;	
	a_doc_released_by = NULL;			
	a_doc_accept_approval = NULL;		
	a_doc_pdf_code = NULL;				
	a_doc_is_dublicate = NULL;			
	a_doc_dublicate_inv_num = NULL;		
	a_doc_subst_inv_num = NULL;			
	a_doc_inv_num = NULL;				
	a_doc_mail_list = NULL;
	a_doc_src_item = NULL;
	a_doc_guid=NULL;
	a_doc_external_ref=NULL;


	a_doc_from=0;
	a_doc_to=0;
	a_doc_recipients=0;
	a_doc_urgency=0;
	a_doc_date=0;
	a_doc_date_of_execution_required=0;
	a_doc_of_execution_planned=0;
	a_doc_of_execution_fact=0;


	e_dt=0;	a_dt_pdt=0; a_dt_id=0;

	e_apl_doc_rev=0; a_apl_doc_rev_id=0; a_apl_doc_rev_doc=0; a_apl_doc_rev_label=0; a_apl_doc_rev_it_needs_work=0;
	a_apl_doc_rev_descr=0; a_apl_doc_rev_crc=0; a_apl_doc_rev_base=0; a_apl_doc_rev_edit_path=0;
	a_apl_doc_rev_start_s=0; a_apl_doc_rev_end_s=0; a_apl_doc_rev_user=0; a_apl_doc_rev_autor=0;
	a_apl_doc_rev_litera=0;
	a_apl_doc_rev_format=0;
	a_apl_doc_rev_src_doc_ver=0;
	a_apl_doc_rev_inner_label = NULL;

	a_apl_doc_rev_src_author=0;
	a_apl_doc_rev_src_date=0;
	a_apl_doc_rev_language=0;
	a_apl_doc_rev_stored_on=0;
	a_apl_doc_rev_char_val_versions=0;
	a_apl_doc_rev_pictures = 0;

	a_apl_doc_rev_gen_by_software = 0;
	a_apl_doc_rev_lss_dic_ver = 0;

	e_apl_digital_document=0; a_apl_doc_rev_access_form=0;
	e_apl_stored_document=0; a_apl_stored_document_file_name=0; a_apl_stored_document_source=0;
	a_apl_stored_document_code = 0;
	e_apl_assigned_document=0; a_apl_assigned_document_location_path=0;

	e_apl_doc_change=0; 
	a_apl_doc_change_id=0; a_apl_doc_change_name=0; a_apl_doc_change_descr=0; a_apl_doc_change_user=0; a_apl_doc_change_person=0; 
	a_apl_doc_change_doc=0; a_apl_doc_change_old=0; a_apl_doc_change_new=0; a_apl_doc_change_date_s=0; 
	a_apl_doc_change_attachment=0; a_apl_doc_change_basis=0;

	e_dt_group=0;
	a_dt_group_id=0;
	a_dt_group_name=0;
	a_dt_group_descr=0;
	a_dt_group_par=0;
	a_dt_group_content=0;
	a_dt_auth_formats=0;
	a_dt_basis=0;

	e_doc_copy=0;
	a_doc_copy_id=0;
	a_doc_copy_state=0;
	a_doc_copy_first_rev=0;
	a_doc_copy_cur_rev=0;
	a_doc_copy_issue_date=0;
	a_doc_copy_last_update=0;
	a_doc_copy_owner=0;
	a_doc_copy_place_of_use=0;
	a_doc_copy_doc=0;

	e_doc_copy_rev_change=0;
	a_doc_copy_rev_change_doc_change=0;
	a_doc_copy_rev_change_author=0;
	a_doc_copy_rev_change_apply_date=0;
	a_doc_copy_rev_change_hard_copy=0;

	e_doc_copy_owner_change=0;
	a_doc_copy_owner_change_basis=0;
	a_doc_copy_owner_change_hand_date=0;
	a_doc_copy_owner_change_new_owner=0;
	a_doc_copy_owner_change_new_place_of_use=0;
	a_doc_copy_owner_change_hard_copy=0;

	e_apl_xml_index = 0;
	a_apl_xml_index_cur_doc_rev = 0;
	a_apl_xml_index_lps_system = 0;	
	a_apl_xml_index_sys_id = 0;		
	a_apl_xml_index_type = 0;		
	a_apl_xml_index_type_name = 0;	
	a_apl_xml_index_id = 0;			
	a_apl_xml_index_name = 0;	
	a_apl_xml_index_name_eng = 0;	
	a_apl_xml_index_config_info = 0;	
	a_apl_xml_index_ref_guid = 0;	
	a_apl_xml_index_cfg = 0;	

	e_apl_order_issue = 0;
	a_apl_order_issue_order = 0;
	a_apl_order_issue_doc_number = 0;
	a_apl_order_issue_shop = 0;
	a_apl_order_issue_date = 0;
	a_apl_order_issue_reciever = 0;
	a_apl_order_issue_document = 0;

	e_order_elem = 0;
	a_order_elem_doc = 0;
	a_order_elem_count = 0;
	a_order_elem_order = 0;	
}

//*************************************************************

bool CaplDocManager::ChangeEntriesValByDocAttr(CaplInstance *ciRevision)
{
	if(0 == m_api) return false;
	if(false == m_api->m_data.IsConnected()) return false;
	if(0 == ciRevision) return false;

	CString sValue;
	CString sEntryName;
	CString sCardField;
	aplExtent aeDtEnries;
	aplExtent aeEntriesVal;
	CaplInstance *ciEntry = 0;
	CaplInstance *ciDocKind = 0;
	CaplInstance *ciDocument = 0;

	// сначала создаем пустые значения для реквизитов
	m_api->m_data.GetAttr(ciRevision, a_apl_doc_rev_doc, ciDocument);
	if(0==ciDocument) return false;
	m_api->m_data.GetAttr(ciDocument, a_doc_kind, ciDocKind);
	if(0==ciDocKind) return false;
	m_api->m_data.GetAttr(ciDocKind, a_dt_entries, aeDtEnries);
	m_api->LoadExtentInfo(aeDtEnries);

	for(int j=0; j<aeDtEnries.Size; ++j)
	{
		m_api->m_data.GetAttr(aeDtEnries[j], a_dt_entry_entry, ciEntry);
		if(0==ciEntry) continue;
		m_api->m_data.GetAttr(ciEntry, a_entry_card_field, sCardField);
		m_api->m_data.GetAttr(ciEntry, a_entry_name, sEntryName);

		CreateEntryVal(ciRevision, sEntryName, _T(""), true, false);
	}

	// теперь заполняем их из атрибутов документа / версии
	m_api->m_data.GetAttr(ciRevision, a_apl_doc_rev_entries, aeEntriesVal);

	for(int i=0; i<aeEntriesVal.Size; ++i)
	{
		m_api->m_data.GetAttr(aeEntriesVal[i], a_doc_entry_val_entry, ciEntry);
		if(0==ciEntry) continue;
		m_api->m_data.GetAttr(ciEntry, a_entry_card_field, sCardField);

		sValue = GetAttrByCardField(ciRevision, sCardField);
		m_api->m_data.PutAttr(aeEntriesVal[i], a_doc_entry_val_val, sValue);		
	}	

	return true;
}

CString CaplDocManager::GetAttrByCardField(CaplInstance *ciRevision, const CString &name)
{
	if(true == name.IsEmpty())
		return _T("");

	if(0 == ciRevision)
		return _T("");

	CString sValue;
	CaplInstance *ciDocument = 0;
	m_api->m_data.GetAttr(ciRevision, a_apl_doc_rev_doc, ciDocument);

	if(0 == name.CompareNoCase(APL_NO_T("обозначение")))
	{
		m_api->m_data.GetAttr(ciDocument, a_doc_id, sValue);
	}
	else if(0 == name.CompareNoCase(APL_NO_T("наименование"))) 
	{			
		m_api->m_data.GetAttr(ciDocument, a_doc_name, sValue);
	}
	else if(0 == name.CompareNoCase(APL_NO_T("вид документа")))
	{
		CaplInstance *ciDocKind = 0;
		m_api->m_data.GetAttr(ciDocument, a_doc_kind, ciDocKind);
		m_api->m_data.GetAttr(ciDocKind, a_dt_pdt, sValue);
	}
	else if(0 == name.CompareNoCase(APL_NO_T("код вида документа")))
	{
		CaplInstance *ciDocKind = 0;
		m_api->m_data.GetAttr(ciDocument, a_doc_kind, ciDocKind);
		m_api->m_data.GetAttr(ciDocKind, a_dt_id, sValue);
	}
	else if(0 == name.CompareNoCase(APL_NO_T("имя файла"))) 
	{
		
	}
	else if(0 == name.CompareNoCase(APL_NO_T("версия документа"))) 
	{		
		m_api->m_data.GetAttr(ciRevision, a_apl_doc_rev_id, sValue);
	}
	else if(0 == name.CompareNoCase(APL_NO_T("литера"))) 
	{
		m_api->m_data.GetAttr(ciRevision, a_apl_doc_rev_litera, sValue);
	}
	else if(0 == name.CompareNoCase(APL_NO_T("формат"))) 
	{
		m_api->m_data.GetAttr(ciRevision, a_apl_doc_rev_format, sValue);
	}
	else if(0 == name.CompareNoCase(APL_NO_T("Метка"))) 
	{
		m_api->m_data.GetAttr(ciRevision, a_apl_doc_rev_label, sValue);
	}
	else if(0 == name.CompareNoCase(APL_NO_T("лист"))) 
	{
		m_api->m_data.GetAttr(ciRevision, a_apl_doc_rev_sheets, sValue);
	}
	else if(0 == name.CompareNoCase(APL_NO_T("листов"))) 
	{
		m_api->m_data.GetAttr(ciRevision, a_apl_doc_rev_total_sheets, sValue);
	}
	else if(0 == name.CompareNoCase(APL_NO_T("дополнительный код вида документа"))) 
	{
		m_api->m_data.GetAttr(ciDocument, a_doc_add_dt_code, sValue);
	}
	else if(0 == name.CompareNoCase(APL_NO_T("код документа в зависимости от характера использования"))) 
	{		
		m_api->m_data.GetAttr(ciDocument, a_doc_code_depend_desp, sValue);
	}
	else if(0 == name.CompareNoCase(APL_NO_T("инвентарный номер"))) 
	{		
		m_api->m_data.GetAttr(ciDocument, a_doc_inv_num, sValue);
	}
	else if(0 == name.CompareNoCase(APL_NO_T("признак аутентичного документа"))) 
	{		
		m_api->m_data.GetAttr(ciDocument, a_doc_authentic, sValue);
	}

	return sValue;
}

bool CaplDocManager::ChangeDocAttrByEntryVal(CaplInstance *ciRev, CaplInstance *ciEntry, CString sValue)
{
	if(ciRev == 0) return false;
	if(ciEntry == 0) return false;

	CString t_str;
	CaplInstance *ciDoc = 0, *ciDT = 0;

	m_api->m_data.GetAttr(ciRev, m_api->m_doc_mgr.a_apl_doc_rev_doc, ciDoc);
	m_api->m_data.GetAttr(ciEntry, m_api->m_doc_mgr.a_entry_card_field, t_str);
	t_str.MakeLower();

	if(t_str ==  APL_NO_T("обозначение"))
	{
		m_api->m_data.PutAttr(ciDoc, m_api->m_doc_mgr.a_doc_id, sValue);
	}
	else if(t_str ==  APL_NO_T("наименование")) 
	{
		m_api->m_data.PutAttr(ciDoc, m_api->m_doc_mgr.a_doc_name, sValue);
	}
	else if(t_str ==  APL_NO_T("вид документа")) 
	{
		
	}
	else if(t_str ==  APL_NO_T("код вида документа")) 
	{
		
	}
	else if(t_str ==  APL_NO_T("имя файла")) 
	{
		
	}
	else if(t_str ==  APL_NO_T("версия документа")) 
	{
		m_api->m_data.PutAttr(ciRev, m_api->m_doc_mgr.a_apl_doc_rev_id, sValue);
	}
	else if(t_str ==  APL_NO_T("литера")) 
	{
		m_api->m_data.PutAttr(ciRev, m_api->m_doc_mgr.a_apl_doc_rev_litera, sValue);
	}
	else if(t_str ==  APL_NO_T("формат")) 
	{
		m_api->m_data.PutAttr(ciRev, m_api->m_doc_mgr.a_apl_doc_rev_format, sValue);
	}
	else if(t_str ==  APL_NO_T("Метка")) 
	{
		m_api->m_data.PutAttr(ciRev, m_api->m_doc_mgr.a_apl_doc_rev_label, sValue);
	}
	else if(t_str ==  APL_NO_T("лист")) 
	{
		m_api->m_data.PutAttr(ciRev, m_api->m_doc_mgr.a_apl_doc_rev_sheets, sValue);
	}
	else if(t_str ==  APL_NO_T("листов")) 
	{
		m_api->m_data.PutAttr(ciRev, m_api->m_doc_mgr.a_apl_doc_rev_total_sheets, sValue);
	}
	else if(t_str ==  APL_NO_T("дополнительный код вида документа")) 
	{
		m_api->m_data.PutAttr(ciDoc, m_api->m_doc_mgr.a_doc_add_dt_code, sValue);
	}
	else if(t_str ==  APL_NO_T("код документа в зависимости от характера использования")) 
	{
		m_api->m_data.PutAttr(ciDoc, m_api->m_doc_mgr.a_doc_code_depend_desp, sValue);
	}
	else if(t_str ==  APL_NO_T("инвентарный номер")) 
	{
		m_api->m_data.PutAttr(ciDoc, m_api->m_doc_mgr.a_doc_inv_num, sValue);
	}
	else if(t_str ==  APL_NO_T("признак аутентичного документа")) 
	{
		m_api->m_data.PutAttr(ciDoc, m_api->m_doc_mgr.a_doc_authentic, sValue);
	}
	
	return true;
}

//*************************************************************

bool CaplDocManager::CreateEntryVal(CaplInstance *cit, CString sEntryName, CString sValue, bool bShowErrorMsg, bool bCopyToDocAttr, bool bFindPrevValue)
{
	if(!cit) return false;
	if(cit->GetType()==0) return false;
	
	if(m_data->IsKindOf(cit, m_api->m_doc_mgr.e_doc))
		m_data->GetAttr(cit, m_api->m_doc_mgr.a_apl_doc_active, cit);

	bool bStored = false;
	aplExtent aeEntryVal;
	CaplInstance *ciRevToEntry = NULL;
	CaplInstance *ciEntry = NULL, *ciTemp = NULL, *ciEntryVal = NULL;

	// смотрим, а есть ли такой реквизит вообще
	ciRevToEntry = m_api->m_doc_mgr.GetEntryBN(sEntryName);
	if(!ciRevToEntry)
	{
		if(m_api->m_ModeInteractive && bShowErrorMsg)AfxMessageBox( APL_T("Не найден реквизит \"")+sEntryName+_T("\"!"), MB_ICONSTOP);
		return false;
	}

	// смотрим, отвечает ли реквизит за какое-нибудь поле 
	// карточки документа
	if(bCopyToDocAttr)
		ChangeDocAttrByEntryVal(cit, ciRevToEntry, sValue);

	// ищем старое значение реквизита
	if(bFindPrevValue)
		ciTemp = GetEntryValBN(cit, sEntryName);

	if(ciTemp)
	{
		m_data->GetAttr(ciTemp, m_api->m_doc_mgr.a_doc_entry_val_stored, bStored);
		if(!bStored) {m_data->PutAttr(ciTemp, m_api->m_doc_mgr.a_doc_entry_val_val, sValue); return true;}
	}	
	
	// нсоздаем новое значение реквизита
	ciEntryVal = m_api->m_data.CreateInstance(m_api->m_doc_mgr.e_doc_entry_val);				
	
	apidata.PutAttr(ciEntryVal, m_api->m_doc_mgr.a_doc_entry_val_stored, bStored);
	apidata.PutAttr(ciEntryVal, m_api->m_doc_mgr.a_doc_entry_val_val, sValue);
	apidata.PutAttr(ciEntryVal, m_api->m_doc_mgr.a_doc_entry_val_prev, ciTemp);
	apidata.PutAttr(ciEntryVal, m_api->m_doc_mgr.a_doc_entry_val_entry, ciRevToEntry);
			
	apidata.GetAttr(cit, m_api->m_doc_mgr.a_apl_doc_rev_entries, aeEntryVal);
	aeEntryVal.Add(ciEntryVal);
	apidata.PutAttr(cit, m_api->m_doc_mgr.a_apl_doc_rev_entries, aeEntryVal);

	return true;
}

bool CaplDocManager::FindAssociatedDocuments(CaplInstance *inst, aplExtent &out_ext,aplExtent &out_rel, CaplInstance *context,bool from_base)
{
	out_ext.Clear();
	out_rel.Clear();
	if(m_data==0) return false;
	if(inst==0) return false;
	if(inst==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(inst->GetType()==0) return false;
	if(inst->GetAccessmode()>aplRO) return false;
	if(e_doc==0) return false;

	aplExtent ext;
	ext.Add(inst);
	return FindAssociatedDocuments(ext, out_ext, out_rel, context,from_base);

/*	int i,j,k;
	if(inst->GetId()!=0)
	{
		// Чтение из базы
		if(m_data->IsConnected())
		{
			CaplLoadData ld(m_data,DEF_SOURCE);
			// ссылка
			i=ld.AddQuery(_T('b'), inst->GetId(), e_apl_doc_ref,a_apl_doc_ref_item, true);
			  ld.AddQuery(_T('d'), i, 0,a_apl_doc_ref_item, true);
			  ld.AddQuery(_T('d'), i, 0, a_doc_rel_frames_of_reference, true);
			  ld.AddQuery(_T('d'), i, 0,a_apl_doc_ref_src, true);
			i=ld.AddQuery(_T('d'), i, 0,a_apl_doc_ref_doc, true);
			// документ
			  ld.AddQuery(_T('d'), i, 0,a_doc_id, true);
			  ld.AddQuery(_T('d'), i, 0,a_doc_name, true);
			  ld.AddQuery(_T('d'), i, 0,a_doc_code, true);
			  ld.AddQuery(_T('d'), i, 0,a_doc_descr, true);
			  ld.AddQuery(_T('d'), i, 0,a_doc_kind, true);
			  ld.AddQuery(_T('d'), i, 0,a_apl_doc_wf_state, true);
			j=ld.AddQuery(_T('d'), i, 0,a_apl_doc_active, true);
			
			// версия
			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_id, true);
			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_doc, true);
			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_label, true);
			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_litera, true);
			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_descr, true);
			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_base, true);
			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_user, true);
			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_autor, true);
			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_start_s, true);
			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_end_s, true);

			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_src_author, true);
			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_src_date, true);
			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_language, true);

			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_crc, true);
			k=ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_access_form, true);
			  ld.AddQuery(_T('d'), k, 0,a_apl_stored_document_file_name, true);
			  ld.AddQuery(_T('d'), k, 0,a_apl_stored_document_source, true);
			  ld.AddQuery(_T('d'), k, 0,a_apl_assigned_document_location_path, true);
			//lock
			j=ld.AddQuery(_T('d'), i, 0,a_apl_doc_lock, true);
			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_autor, true);
			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_user, true);
			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_descr, true);
			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_edit_path, true);
			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_base, true);
			  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_start_s, true);


			ld.LoadEx();
		}
	}
	aplExtent ext_doc_ref;
	CaplInstance *inst0;
	CaplAggr aggr;
	m_data->GetEntityExtent(e_apl_doc_ref,ext_doc_ref);
	for(i=0;i<ext_doc_ref.Size;i++)
	{
		m_data->GetAttr(ext_doc_ref[i],a_apl_doc_ref_item,inst0);
		if(inst==inst0)
		{
			m_data->GetAttr(ext_doc_ref[i],a_apl_doc_ref_doc,inst0);
			if(inst0!=0)
			{
				if(inst0->GetType()!=0)
				{
					if(inst0->GetAccessmode()<=aplRO)
					{
						bool bAdd=true;
						if(context!=0)
						{
							if(!IsItemInContext(ext_doc_ref[i],context,a_doc_rel_frames_of_reference)) bAdd=false;
						}
						if(bAdd)
						{
							out_rel.Add(ext_doc_ref[i]);
							out_ext.Add(inst0);
						}
					}
				}
			}
		}
	}
	return true;*/
}

bool CaplDocManager::FindAssociatedDocuments(aplExtent &ext, aplExtent &out_ext, aplExtent &out_rel, CaplInstance *context,bool from_base)
{
	out_ext.Clear();
	out_rel.Clear();

	int i;
	if(ext.Size!=0)
	{
		// Чтение из базы
		if(m_data->IsConnected() && from_base)
		{
			CaplLoadData ld(m_data,DEF_SOURCE);
			// ссылка

			for(int _i = 0; _i<ext.Size; _i++)
			{
				if(ext.GetAt(_i)!=0 && ext.GetAt(_i)->GetId()!=0)
				{
					ld.AddQuery(0, ext.GetAt(_i));
				}

				if(ld.m_queries.GetSize()>=m_MaxItemsLoad || (_i>=(ext.Size-1)))
				{
					if(ld.m_queries.GetSize()>0) // На случай, если последние элементы не добавились
					{
						int m=ld.AddQuery(_T('r'), 0, m_api->m_doc_mgr.e_apl_doc_ref, m_api->m_doc_mgr.a_apl_doc_ref_item, true,true);			
						int f=ld.AddQuery(_T('d'), m, 0,m_api->m_doc_mgr.a_apl_doc_ref_doc, true,true);
						int j=ld.AddQuery(_T('d'), f, 0,m_api->m_doc_mgr.a_apl_doc_active, true,true);
						int k=ld.AddQuery(_T('d'), j, 0,m_api->m_doc_mgr.a_apl_doc_rev_access_form, true,true);
						//lock
						int l=ld.AddQuery(_T('d'), f, 0,m_api->m_doc_mgr.a_apl_doc_lock, true,true);
						ld.LoadEx();	
						ld.ClearQuery();
					}
				}
			}
		}
	}
	aplExtent ext_doc_ref;
	CaplInstance *inst0;
	CaplAggr aggr;
	m_api->m_data.GetEntityExtent(m_api->m_doc_mgr.e_apl_doc_ref,ext_doc_ref);
	for(i=0;i<ext_doc_ref.Size;i++)
	{
		if(!ext_doc_ref[i]->GetType()) continue;
		if(ext_doc_ref[i]->GetAccessmode()>aplRO) continue;

		m_api->m_data.GetAttr(ext_doc_ref[i],m_api->m_doc_mgr.a_apl_doc_ref_item,inst0);
		bool find_ = false;
		for(int _m=0; _m<ext.Size; _m++)
			if(ext.GetAt(_m)==inst0) find_=true;
		if(find_)
		{
			m_api->m_data.GetAttr(ext_doc_ref[i],m_api->m_doc_mgr.a_apl_doc_ref_doc,inst0);
			if(inst0!=0)
			{
				if(inst0->GetType()!=0)
				{
					if(inst0->GetAccessmode()<=aplRO)
					{
						bool bAdd=true;
						if(context!=0)
						{
							if(!m_api->m_doc_mgr.IsItemInContext(ext_doc_ref[i],context,m_api->m_doc_mgr.a_doc_rel_frames_of_reference)) bAdd=false;
						}
						if(bAdd)
						{
							out_rel.Add(ext_doc_ref[i]);
							out_ext.Add(inst0);
						}
					}
				}
			}
		}
	}
	return true;
}

bool CaplDocManager::FindAssociatedDocumentsRec(aplExtent &ext, aplExtent &out_ext, aplExtent &out_rel, CaplInstance *context)
{
	aplExtent ext_docs, ext_rels;
	FindAssociatedDocuments(ext, ext_docs, ext_rels, context);
	
	
	if(ext_docs.GetSize())
	{
		aplExtent dmp;	
		for(int i= 0; i<ext_docs.GetSize(); i++)
			if(-1==out_ext.Find(ext_docs[i]))
				dmp.Add(ext_docs[i]);
		
		out_ext.Append(ext_docs);
		out_rel.Append(ext_rels);
		
		if(dmp.GetSize()) FindAssociatedDocumentsRec(dmp, out_ext, out_rel, context);
	}

	return true;
}

bool CaplDocManager::FindAssociatingDocuments(CaplInstance *inst, aplExtent &out_ext,aplExtent &out_rel, CaplInstance *context,bool from_base)
{
	out_ext.Clear();
	out_rel.Clear();
	if(m_data==0) return false;
	if(inst==0) return false;
	if(inst==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(inst->GetType()==0) return false;
	if(inst->GetAccessmode()>aplRO) return false;
	if(e_doc==0) return false;

	aplExtent ext;
	ext.Add(inst);
	return FindAssociatingDocuments(ext, out_ext, out_rel, context, from_base);
}

bool CaplDocManager::FindAssociatingDocuments(aplExtent &ext, aplExtent &out_ext, aplExtent &out_rel, CaplInstance *context,bool from_base)
{
	out_ext.Clear();
	out_rel.Clear();

	int i,j,k,l;
	if(ext.Size!=0)
	{
		// Чтение из базы
		if(m_data->IsConnected() && from_base)
		{
			CaplLoadData ld(m_data,DEF_SOURCE);
			// ссылка

			for(int _i = 0; _i<ext.Size; _i++){
				if(ext.GetAt(_i)!=0 && ext.GetAt(_i)->GetId()!=0){
					ld.AddQuery(0, ext.GetAt(_i));
				}
			}
			if(ld.m_queries.GetSize()>0)
			{
			int m=ld.AddQuery(_T('r'), 0, m_api->m_doc_mgr.e_apl_doc_ref, m_api->m_doc_mgr.a_apl_doc_ref_doc, true,true);			
			/*	  ld.AddQuery(_T('d'), m, 0,m_api->m_doc_mgr.a_apl_doc_ref_item, true);
				  ld.AddQuery(_T('d'), m, 0, m_api->m_doc_mgr.a_doc_rel_frames_of_reference, true);
				  ld.AddQuery(_T('d'), m, 0,m_api->m_doc_mgr.a_apl_doc_ref_src, true);*/
			int f=ld.AddQuery(_T('d'), m, 0,m_api->m_doc_mgr.a_apl_doc_ref_item, true,true);
				// документ
				/*ld.AddQuery(_T('d'), f, 0,m_api->m_doc_mgr.a_doc_id, true);
				  ld.AddQuery(_T('d'), f, 0,m_api->m_doc_mgr.a_doc_name, true);
				  ld.AddQuery(_T('d'), f, 0,m_api->m_doc_mgr.a_doc_code, true);
				  ld.AddQuery(_T('d'), f, 0,m_api->m_doc_mgr.a_doc_descr, true);
				  ld.AddQuery(_T('d'), f, 0,m_api->m_doc_mgr.a_doc_kind, true);
				  ld.AddQuery(_T('d'), f, 0,m_api->m_doc_mgr.a_apl_doc_wf_state, true);*/
				j=ld.AddQuery(_T('d'), f, 0,m_api->m_doc_mgr.a_apl_doc_active, true,true);
				
				// версия
			/*	  ld.AddQuery(_T('d'), j, 0,m_api->m_doc_mgr.a_apl_doc_rev_id, true);
				  ld.AddQuery(_T('d'), j, 0,m_api->m_doc_mgr.a_apl_doc_rev_doc, true);
				  ld.AddQuery(_T('d'), j, 0,m_api->m_doc_mgr.a_apl_doc_rev_label, true);
				  ld.AddQuery(_T('d'), j, 0,m_api->m_doc_mgr.a_apl_doc_rev_litera, true);
				  ld.AddQuery(_T('d'), j, 0,m_api->m_doc_mgr.a_apl_doc_rev_descr, true);
				  ld.AddQuery(_T('d'), j, 0,m_api->m_doc_mgr.a_apl_doc_rev_base, true);
				  ld.AddQuery(_T('d'), j, 0,m_api->m_doc_mgr.a_apl_doc_rev_user, true);
				  ld.AddQuery(_T('d'), j, 0,m_api->m_doc_mgr.a_apl_doc_rev_autor, true);
				  ld.AddQuery(_T('d'), j, 0,m_api->m_doc_mgr.a_apl_doc_rev_start_s, true);
				  ld.AddQuery(_T('d'), j, 0,m_api->m_doc_mgr.a_apl_doc_rev_end_s, true);

				  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_src_author, true);
				  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_src_date, true);
				  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_language, true);

				  ld.AddQuery(_T('d'), j, 0,m_api->m_doc_mgr.a_apl_doc_rev_crc, true);*/
				k=ld.AddQuery(_T('d'), j, 0,m_api->m_doc_mgr.a_apl_doc_rev_access_form, true,true);
			/*	  ld.AddQuery(_T('d'), k, 0,m_api->m_doc_mgr.a_apl_stored_document_file_name, true);
				  ld.AddQuery(_T('d'), k, 0,m_api->m_doc_mgr.a_apl_stored_document_source, true);
				  ld.AddQuery(_T('d'), k, 0,m_api->m_doc_mgr.a_apl_assigned_document_location_path, true);*/
				//lock
				l=ld.AddQuery(_T('d'), f, 0,m_api->m_doc_mgr.a_apl_doc_lock, true,true);
				/*ld.AddQuery(_T('d'), l, 0,m_api->m_doc_mgr.a_apl_doc_rev_autor, true);
				  ld.AddQuery(_T('d'), l, 0,m_api->m_doc_mgr.a_apl_doc_rev_user, true);
				  ld.AddQuery(_T('d'), l, 0,m_api->m_doc_mgr.a_apl_doc_rev_descr, true);
				  ld.AddQuery(_T('d'), l, 0,m_api->m_doc_mgr.a_apl_doc_rev_edit_path, true);
				  ld.AddQuery(_T('d'), l, 0,m_api->m_doc_mgr.a_apl_doc_rev_base, true);
				  ld.AddQuery(_T('d'), l, 0,m_api->m_doc_mgr.a_apl_doc_rev_start_s, true);*/


				ld.LoadEx();			
			}
			  

		}
	}
	aplExtent ext_doc_ref;
	CaplInstance *inst0;
	CaplAggr aggr;
	m_api->m_data.GetEntityExtent(m_api->m_doc_mgr.e_apl_doc_ref,ext_doc_ref);
	for(i=0;i<ext_doc_ref.Size;i++)
	{
		if(!ext_doc_ref[i]->GetType()) continue;
		if(ext_doc_ref[i]->GetAccessmode()>aplRO) continue;

		m_api->m_data.GetAttr(ext_doc_ref[i],m_api->m_doc_mgr.a_apl_doc_ref_doc,inst0);
		bool find_ = false;
		for(int _m=0; _m<ext.Size; _m++)
			if(ext.GetAt(_m)==inst0) find_=true;
		if(find_)
		{
			m_api->m_data.GetAttr(ext_doc_ref[i],m_api->m_doc_mgr.a_apl_doc_ref_item,inst0);
			if(inst0!=0)
			{
				if(inst0->GetType()!=0)
				{
					if(inst0->GetAccessmode()<=aplRO)
					{
						bool bAdd=true;
						if(context!=0)
						{
							if(!m_api->m_doc_mgr.IsItemInContext(ext_doc_ref[i],context,m_api->m_doc_mgr.a_doc_rel_frames_of_reference)) bAdd=false;
						}
						if(bAdd)
						{
							out_rel.Add(ext_doc_ref[i]);
							out_ext.Add(inst0);
						}
					}
				}
			}
		}
	}
	return true;
}

//*************************************************************
CaplInstance *CaplDocManager::FindAssociation(CaplInstance *inst,CaplInstance *doc)
{
	if(m_data==0) return 0;
	if(inst==0) return 0;
	if(inst==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return 0;
	}
	if(inst->GetType()==0) return 0;
	if(doc==0) return 0;
	if(doc==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return 0;
	}
	if(doc->GetType()==0) return 0;
	if(e_doc==0) return 0;

	CaplAttrValue tst_values[2];
	aplExtent ext;

	tst_values[0].value.Set(inst);
	tst_values[0].attr=a_apl_doc_ref_item;

	tst_values[1].value.Set(doc);
	tst_values[1].attr=a_apl_doc_ref_doc;

	m_data->NET_FindInstancesWithAttrValues(e_apl_doc_ref,2,&tst_values[0],ext,true);

	if(ext.Size==0) return 0;
	CaplInstance *rel=ext[0];
	if(rel->GetId()==0) return rel;

	if(m_data->IsConnected())
	{
		CaplLoadData ld(m_data,DEF_SOURCE);
		ld.AddQuery(0,rel,true);
		ld.LoadEx();
	}
	return rel;
}

bool CaplDocManager::FindHardCopyes(aplExtent &out_ext,const TCHAR *id,CaplInstance *document,CaplInstance *owner,CaplInstance *place_of_use,const TCHAR *state,const TCHAR *change_date_begin,const TCHAR *change_date_end,BOOL b_only_out_of_date)
{
	if(m_data==0) return false;
	if(e_doc==0) return false;

	CString buf=id;
	int cond_cnt=0;
	CString doc_id=_T("");
	if(document) doc_id.Format(_T("%d"),document->GetId());
	CString query=_T("SELECT Ext FROM\n");
	CString id_s=id;
	CString state_s=state;
	CString change_date_begin_s=change_date_begin;
	CString change_date_end_s=change_date_end;
	if(b_only_out_of_date)
	{
		query+=_T("Ext0 {apl_document");
		if(document) 
		{
			query+=_T(".#= #")+doc_id+_T("\n");
		}
		else
		{
			query+=_T(".id LIKE ''\n");
		}
		query+=_T("}.active\n");
	}
	if(change_date_begin_s!=_T("") || change_date_end_s!=_T(""))
	{	
		query+=_T("Ext1 {apl_document_change_item(");
		if(document) 
		{
			query+=_T(".#= #")+doc_id+_T("\n");
		}
		else
		{
			query+=_T(".id LIKE ''\n");
		}
		query+=_T("AND .accept_date");
		if(change_date_begin_s!=_T("")) 
		{
			query+=_T(">='");
			query+=change_date_begin;
			query+=_T("'\n");
		}
		if(change_date_end_s!=_T(""))
		{
			if(change_date_begin_s!=_T("")) query+=_T("AND .accept_date");
			query+=_T("<='");
			query+=change_date_end;
			query+=_T("'\n");
		}
		query+=_T(")}.document\n");

	}
	query+=_T("Ext {apl_hard_copy_document(\n");
	if(id_s!=_T(""))        
	{
		query +=_T(".id LIKE '")+buf+_T("'\n");
		cond_cnt++;
	}
	if(document) 
	{
		if(cond_cnt>0) query +=_T("AND ");
		query +=_T(".document= #")+doc_id+_T("\n");
		cond_cnt++;
	}
	if(owner) 
	{
		buf.Format(_T("%d"),owner->GetId());
		if(cond_cnt>0) query +=_T("AND ");
		query +=_T(".owner= #")+buf+_T("\n");
		cond_cnt++;
	}
	if(place_of_use) 
	{
		buf.Format(_T("%d"),place_of_use->GetId());
		if(cond_cnt>0) query +=_T("AND ");
		query +=_T(".place_of_use= #")+buf+_T("\n");
		cond_cnt++;
	}
	if(state_s!=_T("")) 
	{
		buf=state;
		if(cond_cnt>0) query +=_T("AND ");
		query +=_T(".state='")+buf+_T("'\n");
		cond_cnt++;
	}
	if(b_only_out_of_date)
	{
		if(cond_cnt>0) query +=_T("AND ");
		query +=_T(".current_revision NOT_IN #Ext0\n");
		cond_cnt++;
	}
	if(change_date_begin_s!=_T("") || change_date_end_s!=_T(""))
	{	
		if(cond_cnt>0) query +=_T("AND ");
		query +=_T(".document IN #Ext1\n");
		cond_cnt++;
	}
	query +=_T(")} END_SELECT");
	if(m_api->m_data.NET_QueryEditParse(query))
		m_api->m_data.NET_QueryExecute(out_ext, APL_T("Поиск копий документа"));
		
	if(out_ext.Size==0) return false;

	if(m_data->IsConnected())
	{
		LoadDocCopyInfo(out_ext);
	}
	return true;	
}

bool CaplDocManager::LoadDictionary()
{
	if(m_data==0) return false;
	if(e_doc==0) return false;

	if(!m_data->IsConnected()) return true;

	CaplLoadData ld(m_data, DEF_SOURCE);
	int i1 =ld.AddQuery(_T('e'),0,e_dt,0,true,true);
//	ld.AddQuery(_T('d'),i1,0,a_dt_pdt,true);
	
	int i2 =ld.AddQuery(_T('e'),0,e_dt_group,0,true,true);
	int i3 =ld.AddQuery(_T('e'),0,e_entry,0,true,true);
	int i4 =ld.AddQuery(_T('e'),0,e_dt_entry,0,true,true);
	
	if(!ld.LoadEx(true,0, APL_T("Чтение видов документов")))
	{
		if(m_api->m_ModeInteractive)
			AfxMessageBox( APL_T("Ошибка чтения информации о типах документах (MGR)"),MB_OK|MB_ICONSTOP);
		return false;
	}
	return true;
}

//*************************************************************
CaplInstance *CaplDocManager::CreateAssociation(CaplInstance *inst,CaplInstance *doc, aplExtent *contexts, const TCHAR * source, UINT apl_type/*=APL_DOCUMENT_REFERENCE*/, bool bCheckExist)
{
	if(m_data==0) return 0;
	if(inst==0) return 0;
	if(inst==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return 0;
	}
	if(inst->GetType()==0) return 0;
	if(inst->GetAccessmode()>aplRO) return 0;
	if(doc==0) return 0;
	if(doc==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return 0;
	}
	if(doc->GetType()==0) return 0;
	if(e_doc==0) return 0;
	// проверяем уровень доступа на объект, к которому хотим прикрепить документ
	if(inst->GetAccessmode()>aplRO) // Так нужно для АЛП
	{
		if(m_api->m_ModeInteractive)AfxMessageBox(S::NoAccessRightItem());
		return NULL;
	}

	CaplInstance *rel = 0;
	if(bCheckExist) 
		rel = FindAssociation(inst,doc);

	if(rel!=0) return rel;
	
	rel=m_data->CreateInstance(e_apl_doc_ref);
	m_data->PutAttr(rel,a_apl_doc_ref_doc,doc);
	m_data->PutAttr(rel,a_apl_doc_ref_item,inst);
	if(apl_type==APL_DOCUMENT_DEPENDENCE)
		m_data->PutAttr(rel,a_apl_doc_ref_type,APL_DOC_DEPENDENCE);
	else
		m_data->PutAttr(rel,a_apl_doc_ref_type,APL_DOC_RELATION);
	if(source!=0) m_data->PutAttr(rel,a_apl_doc_ref_src,source);
	if(contexts!=0)
	{
		if(contexts->GetSize()>0)
			m_data->PutAttr(rel,a_doc_rel_frames_of_reference,*contexts);
	}
	if(apl_type==APL_DOCUMENT_DEPENDENCE)
	{
		/*Связывание активных версий*/
		CaplInstance* parent_ver;
		CaplInstance* active_ver;
		m_api->m_data.GetAttr(inst, a_apl_doc_active, active_ver);
		m_api->m_data.GetAttr(doc, a_apl_doc_active, parent_ver);
		m_api->m_data.PutAttr(active_ver, a_apl_doc_rev_src_doc_ver, parent_ver);
	}
	if(m_AutoSave) m_data->NET_SaveChanges();
	return rel;
}
// //*************************************************************************
bool CaplDocManager::CreateAssociation(CaplInstance *item, aplExtent &extDocs, aplExtent *contexts, const TCHAR * source)
{
	if(0==extDocs.GetSize()) return true;

	if(0==item) item=m_api->m_change_mgr.SelectInstance(APL_MODE_SELECT_CHANGE|APL_MODE_SELECT_PDF|APL_MODE_SELECT_DOC|APL_MODE_SELECT_PRDINST|APL_MODE_SELECT_LOT|APL_MODE_SELECT_PROJECT,APL_T("Выберите объект"));
	if(0==item) return false;
	if(item->GetAccessmode()>aplRW) {AfxMessageBox(APL_T("Нет прав доступа к объекту !"),MB_ICONSTOP|MB_OK); return false;}

	if(m_api->m_data.IsKindOf(item, m_api->m_change_mgr.e_chng))
	{
		m_api->m_change_mgr.LoadChangeInfo(item);
		
		CString state;
		m_api->m_data.GetAttr(item,m_api->m_change_mgr.a_chng_state,state);

		if( !( state==_T("") || state==_T("not_applied"))) {AfxMessageBox(APL_T("Пакет изменений не редактируетя !"),MB_ICONSTOP|MB_OK); return false;}
	}

	aplExtent ext_exist_docs, ext_exist_docs_ref;

	FindAssociatedDocuments(item,ext_exist_docs,ext_exist_docs_ref);

	int i;
	CaplMap map_docs;

	for(i=0; i<ext_exist_docs.GetSize(); i++) map_docs.Add(ext_exist_docs[i],1);

	int iNotDoc=0;
	int iRefExist=0;
	int iAdded=0;


	long trd0=aplStartWaitDlg( APL_T("Обработка..."));

	for(i=0;i<extDocs.GetSize(); i++)
	{
		CaplInstance *doc=extDocs[i];
		if(!m_api->m_data.IsKindOf(doc, m_api->m_doc_mgr.e_doc)) {iNotDoc++; continue;}
		
		void *aa=map_docs.GetByInP(doc);
		
		if(0!=map_docs.GetByInP(doc)) {iRefExist++; continue;}

		CaplInstance *rel=m_data->CreateInstance(e_apl_doc_ref);
		m_data->PutAttr(rel,a_apl_doc_ref_doc,doc);
		m_data->PutAttr(rel,a_apl_doc_ref_item,item);
		m_data->PutAttr(rel,a_apl_doc_ref_type,APL_DOC_RELATION);
		if(source!=0) m_data->PutAttr(rel,a_apl_doc_ref_src,source);
		if(contexts!=0)
		{
			if(contexts->GetSize()>0)
				m_data->PutAttr(rel,a_doc_rel_frames_of_reference,*contexts);
		}
		iAdded++;
	}
	aplEndWaitDlg(trd0);
	if(m_AutoSave) m_data->NET_SaveChanges();

	CString sBuf;
	sBuf.Format(APL_T("Готово!\n\nДобавлено: %i\nУже было: %i\nНе являются документами: %i"),iAdded, iRefExist, iNotDoc);
	AfxMessageBox(sBuf,MB_OK|MB_ICONINFORMATION);

	return true;
}

//*************************************************************
bool CaplDocManager::LoadDocInfo(CaplInstance *doc)
{
	if (doc==0)return false;
	if (doc==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if (doc->GetType()==0)return false;
	if (doc->GetId()==0)return false;
	if (m_data==0)return false;
	if(e_doc==0) return false;
	aplExtent ext; ext.Unique=false; ext.Add(doc);
	return LoadDocInfo(ext);
}
//*************************************************************
bool CaplDocManager::LoadDocInfo(aplExtent &ext, bool bLoadEntries)
{
	if (m_data==0)return false;
	if(e_doc==0) return false;

	if(!m_data->IsConnected()) return true;
	CaplLoadData ld_doc(m_data,		DEF_SOURCE);
	CaplLoadData ld_rev(m_data,		DEF_SOURCE);
	CaplLoadData ld_ref(m_data,		DEF_SOURCE);
	CaplLoadData ld_file(m_data,	DEF_SOURCE);
	int load_doc_p	= 0;
	int load_rev_p	= 0;
	int load_ref_p	= 0;
	int load_file_p	= 0;

	int i,j;
	int indx_portion=0;

	for (i = 0; i < ext.Size; i++)
	{
		CaplInstance *doc = ext[i];
		if (doc == 0) continue;
		if (doc == (CaplInstance*)-1) {
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
			return false;
		}
		if (doc->GetId() == 0) continue;
		if (doc->GetType() == 0) continue;

		if (m_data->IsKindOf(doc, e_doc))
		{
			load_doc_p++;
			ld_doc.AddQuery(0,doc,true);
		}
		else if(m_data->IsKindOf(doc,e_apl_doc_rev))
		{
			load_rev_p++;
			ld_rev.AddQuery(0,doc,true);
		}
		else if(m_data->IsKindOf(doc,e_apl_doc_ref))
		{
			load_ref_p++;
			ld_ref.AddQuery(0,doc,true);
		}
		else if (m_data->IsKindOf(doc, e_apl_stored_document))
		{
			load_file_p++;
			ld_file.AddQuery(0, doc, true);
		}

		if(load_doc_p==m_MaxItemsLoad || (i==(ext.Size-1) && load_doc_p>0))
		{
			load_doc_p=0;
			j=ld_doc.AddQuery(_T('d'), 0, 0,a_apl_doc_active, true,true);
			ld_doc.AddQuery(_T('d'), j, 0, a_apl_doc_rev_access_form, true,true);
			ld_doc.AddQuery(_T('d'), j, 0, a_apl_doc_rev_pictures, true, true);
			ld_doc.AddQuery(_T('d'), 0, 0, a_apl_doc_lock, true, true);
			
			if(bLoadEntries) ld_doc.AddQuery(_T('d'), j, 0, a_apl_doc_rev_entries, true, true);
			
			j=ld_doc.AddQuery(_T('d'), j, 0, a_apl_doc_rev_src_doc_ver, true, true);
			ld_doc.AddQuery(_T('d'), j, 0, a_apl_doc_rev_doc, true, true);
			
			if(!ld_doc.LoadEx())return false;
		}
		
		if(load_rev_p==m_MaxItemsLoad || (i==(ext.Size-1) && load_rev_p>0))
		{
			load_rev_p=0;
			ld_rev.AddQuery(_T('d'), 0, 0, a_apl_doc_rev_doc, true, true);
			ld_rev.AddQuery(_T('d'), 0, 0, a_apl_doc_rev_access_form, true, true);
			ld_rev.AddQuery(_T('d'), 0, 0, a_apl_doc_rev_pictures, true, true);
			
			if(bLoadEntries) ld_rev.AddQuery(_T('d'), 0, 0, a_apl_doc_rev_entries, true, true);
			
			j=ld_rev.AddQuery(_T('d'), 0, 0, a_apl_doc_rev_src_doc_ver, true, true);
			ld_rev.AddQuery(_T('d'), j, 0, a_apl_doc_rev_doc, true, true);

			if (!ld_rev.LoadEx()) return false;
		}

		if(load_ref_p==m_MaxItemsLoad || (i==(ext.Size-1) && load_ref_p>0))
		{
			load_ref_p=0;
			ld_ref.AddQuery(_T('d'), 0, 0,a_apl_doc_ref_doc, true,true);
			ld_ref.AddQuery(_T('d'), 0, 0,a_apl_doc_ref_item, true,true);
			
			if(!ld_ref.LoadEx())return false;
		}

		if (load_file_p == m_MaxItemsLoad || (i == ext.Size - 1 && load_file_p > 0))
		{
			load_file_p = 0;
			
// 			ld_file.AddQuery(_T('d'), 0, 0, a_apl_stored_document_file_name, true);
// 			ld_file.AddQuery(_T('d'), 0, 0, a_apl_stored_document_code, true);
			ld_file.AddQuery(_T('d'), 0, 0, a_apl_stored_document_source, true, true);

			if (!ld_file.LoadEx()) return false;
		}
	}

	return true;
}

//*************************************************************
bool CaplDocManager::LoadDocCopyInfo(CaplInstance *doc_copy)
{
	if (doc_copy==0)return false;
	if (doc_copy==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if (doc_copy->GetType()==0)return false;
	if (doc_copy->GetId()==0)return false;
	if (m_data==0)return false;
	if(e_doc==0) return false;
	aplExtent ext; ext.Unique=false; ext.Add(doc_copy);
	return LoadDocCopyInfo(ext);
}
//*************************************************************
bool CaplDocManager::LoadDocCopyInfo(aplExtent &ext)
{
	if (m_data==0)return false;
	if(e_doc==0) return false;

	if(!m_data->IsConnected()) return true;
	CaplLoadData ld_doc_copy(m_data,DEF_SOURCE);
	int load_doc_copy_p=0;
	int i,j;

	for(i=0;i<ext.Size;i++)
	{
		CaplInstance *doc_copy=ext[i];
		if (doc_copy==0) continue;
		if (doc_copy==(CaplInstance*)-1) {
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
			return false;
		}
		if (doc_copy->GetId()==0) continue;
		if (doc_copy->GetType()==0) continue;
		load_doc_copy_p++;
		ld_doc_copy.AddQuery(0,doc_copy,true);
		if(load_doc_copy_p==m_MaxItemsLoad || (i==(ext.Size-1) && load_doc_copy_p>0))
		{
			load_doc_copy_p=0;
			ld_doc_copy.AddQuery(_T('d'), 0, 0,a_doc_copy_doc, true,true);
			ld_doc_copy.AddQuery(_T('d'), 0, 0,a_doc_copy_first_rev, true,true);
			ld_doc_copy.AddQuery(_T('d'), 0, 0,a_doc_copy_cur_rev, true,true);
			j=ld_doc_copy.AddQuery(_T('d'), 0, 0,a_doc_copy_doc, true,true);
			ld_doc_copy.AddQuery(_T('d'), j, 0,a_apl_doc_active, true,true);
			
			if(!ld_doc_copy.LoadEx())return false;
		}
	}
	return true;
}
//*************************************************************

CaplInstance *CaplDocManager::FindDocById(const TCHAR *id)
{
	if (id==0)return 0;
	if (m_data==0)return 0;
	if(e_doc==0) return 0;

	aplExtent ext;
	CaplAttrValue tst_value;

	tst_value.value.Set(id);
	tst_value.attr=a_doc_id;;
	m_data->NET_FindInstancesWithAttrValues(e_doc,1,&tst_value,ext,false);
	if(ext.Size==0) return 0;
	
	CaplInstance *doc=ext[0];
	if(0==doc) return 0;
	if(0!=doc->GetId()) LoadDocInfo(doc);
	return doc;
}

CaplInstance *CaplDocManager::FindDocRevById(CaplInstance *doc, const TCHAR *id)
{
	if (id==0)return 0;
	if (m_data==0)return 0;
	if(e_doc==0) return 0;

	if (doc==0)return 0;

	aplExtent ext;
	CaplAttrValue tst_value[2];

	tst_value[0].value.Set(id);
	tst_value[0].attr=a_apl_doc_rev_id;;
	tst_value[1].value.Set(doc);
	tst_value[1].attr=a_apl_doc_rev_doc;

	m_data->NET_FindInstancesWithAttrValues(e_apl_doc_rev,2,&(tst_value[0]),ext,false);
	if(ext.Size==0) return 0;
	
	CaplInstance *rev=ext[0];
	if(0==rev) return 0;
	if(0!=rev->GetId()) LoadDocInfo(rev);
	return rev;

}

CaplInstance *CaplDocManager::FindDocByIdAndType(const TCHAR *id, CaplInstance *doc_type)
{
	if (id==0)return 0;
	if (m_data==0)return 0;
	if(e_doc==0) return 0;

	aplExtent ext;
	CaplAttrValue tst_value[2];

	tst_value[0].value.Set(id);
	tst_value[0].attr=a_doc_id;;
	tst_value[1].value.Set(doc_type);
	tst_value[1].attr=a_doc_kind;;

	m_data->NET_FindInstancesWithAttrValues(e_doc,2,&(tst_value[0]),ext,false);
	if(ext.Size==0) return 0;

	CaplInstance *doc=ext[0];
	if(0==doc) return 0;
	if(0!=doc->GetId()) LoadDocInfo(doc);
	return doc;
}

CaplInstance *CaplDocManager::FindDocByGUID(const TCHAR *s_guid)
{
	if (m_data==0)return 0;
	if(e_doc==0) return 0;
	if(0==s_guid || _T('\0')==s_guid[0]) return 0;

	aplExtent ext;
	CaplAttrValue tst_value;

	tst_value.value.Set(s_guid);
	tst_value.attr=a_doc_guid;;
	m_data->NET_FindInstancesWithAttrValues(e_doc,1,&tst_value,ext,false);
	if(0==ext.Size) return 0;
	return ext[0];
}

//************************************************************
CaplInstance *CaplDocManager::GetLastDocumenrRevision(CaplInstance *doc)
{
	if (m_data==0)return 0;
	if(e_doc==0) return 0;
	if(0==doc)return 0;
	if(!m_data->IsKindOf(doc,e_doc)) return 0;

	CaplLoadData ld(m_data, DEF_SOURCE);
	int i1 =ld.AddQuery(_T('b'),doc->GetId(),e_apl_doc_rev,a_apl_doc_rev_doc,true,true);
	aplExtent ext;
	if(!ld.LoadEx(true,&ext)) return 0;

	int i;
	CString sDate,sMaxDate;
	CaplInstance *inst,*inst2,*maxRev=0;
	for(i=0; i<ext.GetSize();i++)
	{
		inst=ext[i];
		if(0==inst) continue;
		if(inst->IsDeleted()) continue;
		if(inst->GetAccessmode()>aplRO) continue;
		if(!m_data->IsKindOf(inst,e_apl_doc_rev))continue;

		m_data->GetAttr(inst,a_apl_doc_rev_doc,inst2);
		if(inst2!=doc) continue;

		m_data->GetAttr(inst,a_apl_doc_rev_end_s,sDate);
		if(sDate>sMaxDate) {maxRev=inst;  sMaxDate=sDate;}
	}
	return maxRev;
}


//************************************************************
//************************************************************
CaplInstance *CaplDocManager::GetDocumentTypeByID(const TCHAR *id)
{
	if (id==0)return 0;
	if (m_data==0)return 0;
	if(e_doc==0) return 0;

	aplExtent ext;
	CaplAttrValue tst_value;

	tst_value.attr=a_dt_id;
	tst_value.value.Set(id);
	m_data->NET_FindInstancesWithAttrValues(e_dt,1,&tst_value,ext,false);
	if(ext.Size==0) return 0;
	if(ext[0]==0) return 0;

	if(m_data->IsConnected())
	{
		CaplLoadData ld(m_data,DEF_SOURCE);
		ld.AddQuery(0, ext[0], true);
		ld.LoadEx();
	}
	return ext[0];
}
CaplInstance *CaplDocManager::GetDocumentTypeBN(const TCHAR *type)
{
	if (type==0)return 0;
	if (m_data==0)return 0;
	if(e_doc==0) return 0;

	aplExtent ext;
	CaplAttrValue tst_value;

	tst_value.attr=a_dt_pdt;
	tst_value.value.Set(type);
	m_data->NET_FindInstancesWithAttrValues(e_dt,1,&tst_value,ext,false);
	if(ext.Size==0) return 0;
	if(ext[0]==0) return 0;

	if(m_data->IsConnected())
	{
		CaplLoadData ld(m_data,DEF_SOURCE);
		ld.AddQuery(0, ext[0], true);
		ld.LoadEx();
	}
	return ext[0];
}
//*************************************************************
bool CaplDocManager::GetFileName(CaplInstance *doc_or_revision, CString &buf)
{
	buf=_T("");
	if(e_doc==0) return false;
	if(doc_or_revision==0) return false;
	if(doc_or_revision==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(doc_or_revision->GetType()==0) return false;
	if(!GetFullFileName(doc_or_revision,buf)) return false;
	int i=buf.ReverseFind(_T('\\'));
	if(i>=0)
	{
		CString buf1=buf.Right(buf.GetLength()-i-1);
		buf=buf1;
	}
	return true;;
}

//*************************************************************
bool CaplDocManager::GetFullFileName(CaplInstance *doc_or_revision, CString &buf)
{
	buf=_T("");
	if (m_data==0)return false;
	if(e_doc==0) return false;
	if(doc_or_revision==0) return false;
	if(doc_or_revision==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(doc_or_revision->GetType()==0) return false;
	if(doc_or_revision->GetAccessmode()>aplRO) return false;

	CaplInstance *rev=0,*stor;
	bool isFile=false;
	if(m_data->IsKindOf(doc_or_revision,e_apl_doc_rev)) rev=doc_or_revision;
	else if(m_data->IsKindOf(doc_or_revision,e_doc))
		m_data->GetAttr(doc_or_revision,a_apl_doc_active,rev);
	else if(m_data->IsKindOf(doc_or_revision,e_apl_stored_document)) isFile=true;
	else if(m_data->IsKindOf(doc_or_revision,e_apl_assigned_document)) isFile=true;
	
	if(isFile)stor=doc_or_revision;
	else
	{
		if(rev==0) return false;
		m_data->GetAttr(rev,a_apl_doc_rev_access_form,stor);
	}
	if(stor==0) return false;
	if(stor->GetAccessmode()>aplRO) return false;

	if(m_data->IsKindOf(stor,e_apl_stored_document))
		m_data->GetAttr(stor,a_apl_stored_document_file_name,buf);
	else if(m_data->IsKindOf(stor,e_apl_assigned_document))
		m_data->GetAttr(stor,a_apl_assigned_document_location_path,buf);

	return true;
}

//*************************************************************

CaplInstance *CaplDocManager::CreateDocument(const TCHAR *id, const TCHAR *name, const TCHAR *descr,
		CaplInstance *type, const TCHAR *path, bool stored, CaplInstance *item, CaplInstance **created_rel,
		UINT apl_type/* = APL_DOCUMENT_RELATION*/, bool bAlwaysShowDlg, bool bShowCRCCalcDlg, LPCTSTR sFormat)
{
	CaplInstance* dt=type;
	CaplInstance* doc=NULL;
	CaplInstance *stor=NULL,*s_rev=NULL;
	aplExtent m_rel_contexts;

	int n_Autent=0, n_Include=1;
	CString old_file_name = path, sCorrectNewDocId(id), sNameOfNewDocument;
	CString s_id, s_name, s_descr, s_rev_descr, s_path,s_label,s_litera;
	CString s_dkvd=_T(""), s_kdvzohi=_T(""), s_sheets=_T(""), s_total_sheets=_T(""), s_total_sheets_A4=_T(""), s_struct_kind=_T("");
	CString rel_src=_T(""), s_format=_T(""), s_part=_T(""), s_rev_date=_T("");

	// если задан ID документа, то от него необходимо отрезать справа 
	// код вида документа, если он есть (ВСЕ ЭТО, ЕСЛИ item = document)
	bool bDocument = false; 
	bool bRevision = false; 

	if(item)
	{
		// проверяем уровень доступа на объект, к которому хотим прикрепить документ
		if(item->GetAccessmode()>aplRO) // Так нужно для АЛП
		{
			if(m_api->m_ModeInteractive)AfxMessageBox(S::NoAccessRightItem());
			return NULL;
		}
	}

	if(bDocument || bRevision)
	{
		CString sDTid;
		CaplInstance *ciDT = 0, *cit;

		if(bRevision)
		{
			m_api->m_data.GetAttr(item, m_api->m_doc_mgr.a_apl_doc_rev_doc, cit);
			if(cit) m_api->m_data.GetAttr(cit, m_api->m_doc_mgr.a_doc_id, sCorrectNewDocId);
		}
		else if(bDocument)
		{
			cit = item;
		}

		// убираем код вида локумента из обозначения
		if(cit)
		{
			m_api->m_data.GetAttr(cit, m_api->m_doc_mgr.a_doc_kind, ciDT);

			// передаем новому документу также наименование
			if(cit) m_api->m_data.GetAttr(cit, m_api->m_doc_mgr.a_doc_name, sNameOfNewDocument);
			name = sNameOfNewDocument;
		}

		if(ciDT)
		{
			m_api->m_data.GetAttr(ciDT, m_api->m_doc_mgr.a_dt_id, sDTid);
			if(sCorrectNewDocId.Right(sDTid.GetLength()) == sDTid)
			{
				sCorrectNewDocId.Delete( sCorrectNewDocId.GetLength() - sDTid.GetLength(), sDTid.GetLength() );
				id = sCorrectNewDocId;
			}
		}				
	}


	//CString s_doc_litera, s_doc_format, s_doc_sheets, s_doc_total_sheets;

	bool b_stored=true,b_set_ro=true,bShowDlg= false,b_del_from_disk=false;

	CDocCreateDlg CreateDlg;
	CDisAsmStatusDlg DisasmDlg;

	if(created_rel!=0)
		*created_rel=0;
	if(m_data==0)
		return 0;
	if(e_doc==0)
		return 0;

	CString sbufid(id), sbufname(name);
	/*НАМ: чтобы в документе заполнялись наименования/обозначения значениями по умолчанию*/
	if(item)
	{
		if(m_api->m_data.IsKindOf(item, e_doc))
		{
			if(sbufid.IsEmpty()){m_api->m_data.GetAttr(item, a_doc_id, sbufid);id=sbufid;}
			if(sbufname.IsEmpty()){m_api->m_data.GetAttr(item, a_doc_name, sbufname);name=sbufname;}
		}
		else if(m_api->m_data.IsKindOf(item, m_api->m_prd_mgr.e_pdf))
		{
			CaplInstance* prd= NULL;
			m_api->m_data.GetAttr(item, m_api->m_prd_mgr.a_pdf_prd, prd);

			if(prd)
			{
				if(sbufid.IsEmpty()){m_api->m_data.GetAttr(item, m_api->m_prd_mgr.a_prd_id, sbufid);id=sbufid;}
				if(sbufname.IsEmpty()){m_api->m_data.GetAttr(item, m_api->m_prd_mgr.a_prd_name, sbufname);name=sbufname;};
			}
		}
	}
	/**/
	
	if(apl_type==APL_DOCUMENT_DEPENDENCE)
	{
		if(item==IsDependenceDocument(item)) 
		{
			if(m_api->m_ModeInteractive)
				AfxMessageBox( APL_T("Документ является исходным!"));
			return NULL;
		}
	}

	CaplAttrValue tst_values[2];
	tst_values[0].value.Set((LPCTSTR)id);
	tst_values[0].attr=m_api->m_doc_mgr.a_doc_id;
	tst_values[1].value.Set(type);
	tst_values[1].attr=m_api->m_doc_mgr.a_doc_kind;
	
	aplExtent ext_existing;
	m_data->NET_FindInstancesWithAttrValues(e_doc,2,&tst_values[0],ext_existing,false);
	if(m_api->m_ModeInteractive && ext_existing.GetSize())
		bShowDlg= true; //показываем диалог

	// DIV: извращение с проверкой name на пустое значение нужно, т.к. если функцию вызывают с параметром 
	// типа CString то в name помещается ненулевой указатель на буфер с первым нулем и простая 
	// проверка на ноль не работает
	/*if(name!=0){
		if(name[0]==0)bShowDlg=true;
	}
	else */
	// ayatsk быдо обязательно id и name.  Переделал на обязательность id и type
	//if((id==0) || name==0 || (path==0) || bAlwaysShowDlg)

	s_id=id;
	if((s_id==_T("")) || type==0 || (path==0) || bAlwaysShowDlg)
	{
		bShowDlg=true;
	}

	if(path==0) bShowDlg=true;
	
	if( bShowDlg )
	{
		CaplSetResourceHandle setres(module_inst);

		CreateDlg.m_api			=m_api;
		CreateDlg.m_doc_id		=id;
		CreateDlg.m_doc_name	=name;
		CreateDlg.m_doc_descr	=descr;
		CreateDlg.m_dt			=type;
		CreateDlg.m_doc_rev_file=path;
		CreateDlg.m_doc_rev_id	=_T("0");
		if(0!=sFormat) CreateDlg.m_format=sFormat;
		CreateDlg.m_save_to_db	=TRUE;
		CreateDlg.m_set_ro		=TRUE;
		CreateDlg.m_sel_doc_types_names.Append(m_sel_doc_types_names);

		if(item!=0)
			CreateDlg.m_show_contexts=true;

		int iret=CreateDlg.DoModal();
		if(IDOK!=iret)
			return 0;

		doc=CreateDlg.m_doc;
		s_rev=CreateDlg.m_rev;

		s_id		=CreateDlg.m_doc_id;
		s_name		=CreateDlg.m_doc_name;
		s_descr		=CreateDlg.m_doc_descr;
		s_rev_descr	=CreateDlg.m_doc_rev_descr;
		s_dkvd			=CreateDlg.m_sDkvd;
		s_kdvzohi		=CreateDlg.m_sKdvzohi; 

		if(s_kdvzohi == _T(" ")) s_kdvzohi=_T("");
		if(!s_kdvzohi.IsEmpty()) s_kdvzohi = s_kdvzohi[0];

		s_sheets		=CreateDlg.m_sOfList;
		s_total_sheets  =CreateDlg.m_sOfLists;
		s_total_sheets_A4  =CreateDlg.m_sOfListsA4;
		n_Autent		=CreateDlg.m_nAutent;
		s_struct_kind	=CreateDlg.m_sStructKind;
		s_path		=CreateDlg.m_doc_rev_file;
		s_label		=CreateDlg.m_label;
		s_litera	=CreateDlg.m_litera;
		s_format	=CreateDlg.m_format;
		rel_src		=CreateDlg.m_doc_rel_src;
		dt			=CreateDlg.m_dt;
		s_part		=CreateDlg.m_sPart;

		n_Include				= CreateDlg.m_nInclude;
		//s_doc_sheets			= CreateDlg.m_sDocSheets;
		//s_doc_total_sheets		= CreateDlg.m_sDocTotalSheets;
		//s_doc_litera			= CreateDlg.m_sDocLitera;
		//s_doc_format			= CreateDlg.m_sDocFormat;
		
		if (!CreateDlg.m_set_ro)
			b_set_ro = false;

		if (CreateDlg.m_del_from_disk)
			b_del_from_disk = true;

		if (!CreateDlg.m_save_to_db)
			b_stored=false;

		if(CreateDlg.m_save_to_db==TRUE)
			b_stored=true;
		else 
			b_stored=false;

		if(CreateDlg.m_context_changed==true) 
			m_rel_contexts.Append(CreateDlg.m_rel_contexts);

		s_rev_date = CreateDlg.m_sRevDate;
	}
	else
	{
		s_id=id;
		s_name=name;
		s_descr=descr;
		s_path=path;
		b_stored=stored;
		dt= type;

		if (m_api->m_options_mgr.GetIntOptionValueBN(SetReadOnlyOnCreate, 1) != 1)
			b_set_ro = false;
	}

	if(s_path[0]!=_T('*'))
	{
		if(stored)
		{
			CFileFind ff;
			if(0==ff.FindFile(s_path))
			{
				if(old_file_name.IsEmpty() || old_file_name==s_path)
				{
					if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Файл не найден"),MB_OK|MB_ICONSTOP);
					return NULL;
				}
				else
				{
					if(m_api->m_ModeInteractive && AfxMessageBox( APL_T("В новом документе изменено имя файла.\nИспользовать в новом документе файл документа-образца с измененным именем?"),
						MB_YESNO)==IDNO) return NULL;
					CFile::Rename(old_file_name,s_path);
					if(0==ff.FindFile(s_path))
					{
						if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Не удалось скопировать файл."));
						return NULL;
					}
				}
			}
		}
		else
		{
			if(s_path=="")
			{
				if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Сыылка не задана"),MB_OK|MB_ICONSTOP);
				
				return NULL;
			}
		}
	}

	CaplSetResourceHandle setres(module_inst);
	
	if (bShowCRCCalcDlg)
	{
		DisasmDlg.Create(IDD_DISASM_STATUS);
		DisasmDlg.m_name.SetWindowText( APL_T("Расчет контрольной суммы..."));
		DisasmDlg.ShowWindow(TRUE);
		DisasmDlg.ResizeText();	
	}
	
	int crc32=GetFileCRC32(s_path);

	if (bShowCRCCalcDlg)
		DisasmDlg.ShowWindow(FALSE);


	// Создание версии
	
	long code;
	int i;
	CString buf, sVal;
	if(b_stored)
	{
		if(s_path[0]==_T('*')) // Передан используемый Instance
		{
			int inst_i=_atoi((TCHAR*)(LPCTSTR(s_path)+1));
			stor=(CaplInstance*)inst_i;
		}
		else
		{
			stor=m_data->CreateInstance(e_apl_stored_document);
			if(stor==0)
				return NULL;
			i=s_path.ReverseFind(_T('\\'));
			if(i>=0) 
				buf=s_path.Right(s_path.GetLength()-i-1); else buf=s_path;
			i=buf.ReverseFind(_T(':'));
			if(i>=0) 
				buf=buf.Right(buf.GetLength()-i-1); 
			m_data->PutAttr(stor,a_apl_stored_document_file_name,buf);
			if(!m_data->NET_SaveBlob(stor,a_apl_stored_document_source,s_path,code))
				return 0;
		}
	}
	else
	{
		stor=m_data->CreateInstance(e_apl_assigned_document);
		if(stor==0)
			return 0;
		m_data->PutAttr(stor,a_apl_assigned_document_location_path,s_path);
	}
	if(b_del_from_disk && b_stored) // не сохраненные не удаляем
	{
		SetFileAttributes(s_path, FILE_ATTRIBUTE_NORMAL);
		DeleteFile(s_path);
	}
	else if (b_set_ro)
		SetFileAttributes(s_path, FILE_ATTRIBUTE_READONLY);
	
	if(0==s_rev) s_rev=m_data->CreateInstance(e_apl_digital_document);
	m_data->PutAttr(s_rev,a_apl_doc_rev_id,_T("0"));
	m_data->PutAttr(s_rev,a_apl_doc_rev_descr,s_rev_descr);
	m_data->PutAttr(s_rev,m_api->m_doc_mgr.a_apl_doc_rev_litera,s_litera);
	m_data->PutAttr(s_rev,m_api->m_doc_mgr.a_apl_doc_rev_format,s_format);
	m_data->PutAttr(s_rev,m_api->m_doc_mgr.a_apl_doc_rev_label,s_label);
	m_data->PutAttr(s_rev,m_api->m_doc_mgr.a_apl_doc_rev_entries, CreateDlg.m_aeEntryToCreate);
	m_data->PutAttr(s_rev,a_apl_doc_rev_sheets, s_sheets);
	m_data->PutAttr(s_rev,a_apl_doc_rev_total_sheets, s_total_sheets);
	m_data->PutAttr(s_rev,a_apl_doc_rev_total_sheets_count_a4, s_total_sheets_A4);
	m_data->PutAttr(s_rev,a_apl_doc_rev_crc,crc32);
	m_data->PutAttr(s_rev,a_apl_doc_rev_access_form,stor);
	m_data->PutAttr(s_rev,a_apl_doc_rev_user, m_api->m_appr_mgr.GetOperatorName()); // Установка автора
	m_data->PutAttr(s_rev,a_apl_doc_rev_autor, m_api->m_appr_mgr.GetCurrentPerson()); 
	m_data->PutAttr(s_rev,a_apl_doc_rev_src_date,s_rev_date);

	//установка значений принудительных реквизитов
	if(item) CreateDefaultEntries(s_rev, item);

	COleDateTime odt=COleDateTime::GetCurrentTime();
	CString s_date;
	aplDate2String(odt,s_date);		
	m_data->PutAttr(s_rev,a_apl_doc_rev_end_s,s_date);
	
	// Создание документа
	if(0==doc) doc=m_data->CreateInstance(e_apl_doc);
	m_data->PutAttr(doc,a_apl_doc_active,s_rev);
	m_data->PutAttr(doc,a_doc_id, s_id);
	m_data->PutAttr(doc,a_doc_name, s_name);
	m_data->PutAttr(doc,a_doc_descr, s_descr);
	m_data->PutAttr(doc,a_doc_kind, dt);

	m_data->PutAttr(doc,a_doc_add_dt_code, s_dkvd);
	m_data->PutAttr(doc,a_doc_code_depend_desp, s_kdvzohi);
	m_data->PutAttr(doc,a_doc_authentic, n_Autent!=0?true:false);
	m_data->PutAttr(doc,a_doc_incl_in_doc, n_Include!=0?true:false);
	m_data->PutAttr(doc,a_doc_struct_kind, s_struct_kind);
	m_data->PutAttr(doc,a_doc_part, s_part);

// атрибуты пока не используются
/*
	m_data->PutAttr(doc,a_doc_format, s_doc_format);
	m_data->PutAttr(doc,a_doc_litera, s_doc_litera);
	m_data->PutAttr(doc,a_doc_sheets, s_doc_sheets);
	m_data->PutAttr(doc,a_doc_total_sheets_count, s_doc_total_sheets);
*/

	m_data->PutAttr(doc,a_apl_doc_wf_state, _T("working"));
	m_data->PutAttr(s_rev,a_apl_doc_rev_doc,doc);

	if(item!=0)
	{
		CaplInstance* i_created_rel=0;
		i_created_rel = CreateAssociation(item,doc,&m_rel_contexts,rel_src,apl_type);
		if(created_rel!=0)
			*created_rel=i_created_rel;
	}

	if(m_AutoSave) 
		m_api->SaveChanges();

	if(NULL!=doc)
	{
		CString csAccPat;
		aplExtent aet_doc, aet_rev ;

		aet_doc.Add(doc);
		aet_rev.Add(s_rev);

		if(true==bShowDlg && _T("")!=CreateDlg.m_csAccessString)
			apidata.NET_SetAccessFromPattern(&aet_doc,CreateDlg.m_csAccessString);

		SetRevisionAccessOnCreate(s_rev);
	}

	return doc;
}
//*************************************************************
bool CaplDocManager::GetActualEntriesVal(CaplInstance *ciItem, aplExtent &aeResult)
{
	if(!ciItem) return false;
	if(!m_api->m_data.IsKindOf(ciItem, m_api->m_appr_mgr.e_apl_appr_pers_org)
		&& !m_api->m_data.IsKindOf(ciItem, m_api->m_doc_mgr.e_doc)
		&& !m_api->m_data.IsKindOf(ciItem, m_api->m_doc_mgr.e_apl_doc_rev)) return false;

	aeResult.Clear();
	CaplInstance *ciEntry;
	aplExtent aeEntriesValue, aeEntries;

	// получаем весь набор значений реквизитов
	if(m_api->m_data.IsKindOf(ciItem, m_api->m_appr_mgr.e_apl_appr_pers_org))
	{
		m_api->m_data.GetAttr(ciItem, m_api->m_appr_mgr.a_appr_po_entries, aeEntriesValue);
	}
	else if(m_api->m_data.IsKindOf(ciItem, m_api->m_doc_mgr.e_doc))
	{
		CaplInstance *ciActive = 0;
		m_api->m_data.GetAttr(ciItem, m_api->m_doc_mgr.a_apl_doc_active, ciActive);
		m_api->m_data.GetAttr(ciActive, m_api->m_doc_mgr.a_apl_doc_rev_entries, aeEntriesValue);
	}
	else if(m_api->m_data.IsKindOf(ciItem, m_api->m_doc_mgr.e_apl_doc_rev))
	{
		m_api->m_data.GetAttr(ciItem, m_api->m_doc_mgr.a_apl_doc_rev_entries, aeEntriesValue);
	}
	else 
	{
		return false;
	}

	m_api->LoadExtentInfo(aeEntriesValue);	


	// выбираем только актуальные
	for(int i=aeEntriesValue.Size-1; i>=0; i--)
	{
		m_api->m_data.GetAttr(aeEntriesValue[i], m_api->m_doc_mgr.a_doc_entry_val_entry, ciEntry);
		if(ciEntry == 0) continue;

		// каждый реквизит только один раз (а именно последний)
		int size = aeEntries.Size;
		aeEntries.Add(ciEntry);
		//if(size != aeEntries.Size) aeResult.Add(aeEntriesValue[i]);						
		if(size != aeEntries.Size) aeResult.Insert(0, aeEntriesValue[i]);						
	}

	return true;
}

//*************************************************************
bool CaplDocManager::CreateDefaultEntries(CaplInstance *ciActRev, CaplInstance *ciItem /* = NULL */)
{
	if(!ciActRev) return false;
	if(!ciActRev->GetType()) return false;
	if(!m_data) return false;
	if(!m_data->IsConnected()) return false;

	/*********************************************/

	CString sVal;
	CaplInstance *ciDoc = NULL;
	CaplInstance *ciTmp = NULL;
	CaplInstance *ciEntry = NULL;

	if(m_data->IsKindOf(ciActRev, e_doc)) { ciDoc=ciActRev; m_data->GetAttr(ciDoc, a_apl_doc_active, ciActRev); }
	m_data->GetAttr(ciActRev, a_apl_doc_rev_doc, ciDoc);			

	// значения реквизитов по умолчанию:	первичная применямость.
	
	if(ciItem)
	{
		if(m_api->m_data.IsKindOf(ciItem, m_api->m_prd_mgr.e_pdf))
		{					
			// узнаем значение будущего реквизита
			m_api->m_data.GetAttr(ciItem, m_api->m_prd_mgr.a_apl_pdf_first_usage, ciTmp);

			if(ciTmp)
			{
				m_api->LoadItemInfo(ciTmp);
				m_api->m_data.GetAttr(ciTmp, m_api->m_prd_mgr.a_pdf_prd, ciTmp);
				if(ciTmp) m_api->m_data.GetAttr(ciTmp, m_api->m_prd_mgr.a_prd_id, sVal);
				
				CaplInstance *entry=GetEntryBN( APL_T("Обозначение соответствующего документа, в котором впервые записан данный документ"));
				if(0==entry)
				{
					// создаем - пусть будет, но в виде его точно нет
					ciEntry = m_api->m_data.CreateInstance(m_api->m_doc_mgr.e_entry);
					if(ciEntry) m_api->m_data.PutAttr(ciEntry, m_api->m_doc_mgr.a_entry_name,  APL_T("Обозначение соответствующего документа, в котором впервые записан данный документ"));
				}
				else
				{
					// проверяем, есть ли такой реквизит в виде
					CaplInstance *dt=0;
					if(0!=ciDoc)m_data->GetAttr(ciDoc, a_doc_kind, dt);
					if(dt)
					{
						aplExtent ext0;
						m_data->GetAttr(dt, a_dt_entries, ext0);
						int i;
						for(i=0;i<ext0.GetSize();i++)
						{
							if(ext0[i]==entry)
							{
								CreateEntryVal(ciActRev,  APL_T("Обозначение соответствующего документа, в котором впервые записан данный документ"), sVal, false);				
								break;
							}
						}
					}
				}
			}
		}
	}
	
	return true;	
}
//*************************************************************
bool CaplDocManager::HasAllNecessaryDocRevAttr(CaplInstance *ciRev)
{
	if(!m_data) return false;
	if(!m_data->IsConnected()) return false;
	if(!ciRev) return false;
	if(ciRev->GetType()==0) return false;
	if(!m_data->IsKindOf(ciRev, e_apl_doc_rev))return false;

	CString sFormat, sSheets;
	m_data->GetAttr(ciRev, a_apl_doc_rev_total_sheets, sSheets);
	m_data->GetAttr(ciRev, a_apl_doc_rev_format, sFormat);
	if(sFormat!=_T("") && sSheets!=_T("")) return true;

	CString sDocTypeGroups;
	m_api->m_options_mgr.GetOptionValueBN(APL_NO_T("Настройка документов\\Группы видов документов требующие заполнения информации о формате и листах"),sDocTypeGroups);
	if(sDocTypeGroups==_T("")) return true;

	
	CaplInstance *doc,*dt,*dtg;
	m_data->GetAttr(ciRev, a_apl_doc_rev_doc, doc);
	if(0==doc) return false;
	m_data->GetAttr(doc, a_doc_kind, dt);
	if(0==dt) return true;

	aplExtent ext,ext_dt,ext_dtg;
	//CaplAttrValue tst_value;
	//tst_value.attr=a_dt_group_id;
	m_data->GetEntityExtent(e_dt_group,ext_dtg);

	int i=0,j,k;
	CString buf,dt_group;
	sDocTypeGroups.MakeLower();
	while(i<sDocTypeGroups.GetLength())
	{
		j=sDocTypeGroups.Find(_T('|'),i);
		if(j>=0) {dt_group=sDocTypeGroups.Mid(i,j-i); i=j+1;}
		else {dt_group=sDocTypeGroups.Right(sDocTypeGroups.GetLength()-i); i=sDocTypeGroups.GetLength();}
		dt_group.TrimLeft(); dt_group.TrimRight();
		if(dt_group==_T("")) continue;
		//TRACE(_T("\n%s,"),LPCTSTR(dt_group));

		/*tst_value.value.Set(dt_group);
		ext.Clear();
		m_data->NET_FindInstancesWithAttrValues(e_dt_group,1,&tst_value,ext,false);
		if(ext.Size==0) 
		{
			buf.Format(APL_T("Не найдена указанная в настройках группа видов документов '%s'"),LPCTSTR(dt_group));
			AfxMessageBox(buf,MB_ICONSTOP|MB_OK);
			continue;
		}
		if(ext[0]==0)continue;
		dtg=ext[0];*/

		dtg=0;
		for(k=0;k<ext_dtg.GetSize();k++)
		{
			m_data->GetAttr(ext_dtg[k], a_dt_group_id, buf);
			buf.MakeLower();
			if(buf==dt_group) {dtg=ext_dtg[k]; break;}
		}
		if(0==dtg) 
		{
			buf.Format(APL_T("Не найдена указанная в настройках группа видов документов '%s'"),LPCTSTR(dt_group));
			AfxMessageBox(buf,MB_ICONSTOP|MB_OK);
			continue;
		}
		m_data->GetAttr(dtg, a_dt_group_content, ext_dt);
		for(k=0;k<ext_dt.GetSize();k++)
		{
			if(ext_dt[k]==dt) return false;
		}
	}
	return true;
}

//*************************************************************
bool CaplDocManager::HasAllNecessaryEntries(CaplInstance *ciRev, bool bLoadFromBase /* = true */, CString *sMisingEntry)
{
	int i, j;
	CString t_str, sDTid;

	bool bResult = true;
	bool bOptional, bEqualFind;

	aplExtent aeDTEntries;
	aplExtent aeRevEntryVals;

	CaplInstance *ciDT = NULL;
	CaplInstance *ciDoc = NULL;
	CaplInstance *ciEntryFromDT = NULL;
	CaplInstance *ciEntryFromVal = NULL;

	// список разных исключений
	CaplInstance *ciDTcodeEntry = m_api->m_doc_mgr.GetEntryBN( APL_T("Код документа"));

	if(m_data->IsKindOf(ciRev, e_apl_doc_rev)) m_data->GetAttr(ciRev, a_apl_doc_rev_doc, ciDoc);
	else if(m_data->IsKindOf(ciRev, e_doc)) {ciDoc = ciRev; m_data->GetAttr(ciRev, a_apl_doc_active, ciRev);}
	else return false;

	if(!ciDoc) return false;
	m_data->GetAttr(ciDoc, a_doc_kind, ciDT);
	if(!ciDT) return true;

	// берем все значения реквизитов у версии документа

	m_data->GetAttr(ciRev, a_apl_doc_rev_entries, aeRevEntryVals);

	// берем все определенные для типа документа реквизиты

	m_data->GetAttr(ciDT, a_dt_entries, aeDTEntries);

	if(!aeDTEntries.Size)
	{
		/* ayatsk 26.02.2008 Пока считаем что все хорошо - потом надо будет расскоментарить
		if(m_api->m_ModeInteractive) AfxMessageBox(APL_T("Для вида документа не заданы реквизиты!"), MB_ICONINFORMATION);
		*/
		return true;
	}

	/* ayatsk 26.02.2008 Вылетает в случае если все реквизиты необязательные.
	if(!aeRevEntryVals.Size)
	{
		if(m_api->m_ModeInteractive) AfxMessageBox(APL_T("У версии документа не найдено ни одного реквизита!"), MB_ICONINFORMATION);
		return false;
	}*/

	// смотрим, все ли реквизиты, определенные как обязательные, присутствуют у версии документа

	if(bLoadFromBase)
	{
		m_api->LoadExtentInfo(aeDTEntries);
		m_api->LoadExtentInfo(aeRevEntryVals);
	}

	for(i=0; i<aeDTEntries.Size; i++)
	{
		m_data->GetAttr(aeDTEntries[i], a_dt_entry_opt, bOptional);
		if(bOptional) continue;

		m_data->GetAttr(aeDTEntries[i], a_dt_entry_entry, ciEntryFromDT);
		if(!ciEntryFromDT) continue;

		bEqualFind = false;
		for(j=0; j<aeRevEntryVals.Size; j++)
		{
			m_data->GetAttr(aeRevEntryVals[j], a_doc_entry_val_entry, ciEntryFromVal);

			if(ciEntryFromVal == ciEntryFromDT) 
			{	
				m_data->GetAttr(aeRevEntryVals[j], a_doc_entry_val_val, t_str);
				if(!t_str.IsEmpty())
				{
					bEqualFind = true;
					break;			
				}
				else if(t_str.IsEmpty())
				{
					// если код вида документа пустой, то и значение реквизита не требуется
					if(ciEntryFromVal == ciDTcodeEntry)
					{
						m_api->m_data.GetAttr(ciDT, m_api->m_doc_mgr.a_dt_id, sDTid);
						if(sDTid.IsEmpty())
						{
							bEqualFind = true;
							break;
						}
					}
				}
			}
		}

		// мы обошли все значения реквизитов и совпадений не нашлось, значит
		// обязательный реквизит отсутствует
		if(!bEqualFind)
		{
			if(0!=sMisingEntry) m_api->m_data.GetAttr(ciEntryFromDT, m_api->m_doc_mgr.a_entry_name, *sMisingEntry);
			return false;
		}
	}

	return true;
}
//*************************************************************
bool CaplDocManager::ShowDocChanges(CaplInstance *doc)
{
	if(doc==0) return false;
	if(doc==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(doc->GetType()==0) return false;
	if(doc->GetAccessmode()>aplRO) return false;
	if(m_data==0) return false;
	if(e_doc==0) return false;

	if(m_data->IsConnected())
	{
		int i,j;
		CaplLoadData ld(m_data,DEF_SOURCE);
		CaplAttr *a_user=m_data->GetAttrDefinitionBN(_T("apl_user"),_T("name"));
		// ссылка
		i=ld.AddQuery(_T('b'), doc->GetId(), e_apl_doc_change,a_apl_doc_change_doc, true);
		  ld.AddQuery(_T('d'), i, 0,a_apl_doc_change_doc, true);
		  ld.AddQuery(_T('d'), i, 0,a_apl_doc_change_id, true);
		  ld.AddQuery(_T('d'), i, 0,a_apl_doc_change_name, true);
		  ld.AddQuery(_T('d'), i, 0,a_apl_doc_change_basis, true);
		  ld.AddQuery(_T('d'), i, 0,a_apl_doc_change_descr, true);
		  ld.AddQuery(_T('d'), i, 0,a_apl_doc_change_person, true);
		  ld.AddQuery(_T('d'), i, 0,a_apl_doc_active, true);
		j=ld.AddQuery(_T('d'), i, 0,a_apl_doc_change_attachment, true);
		  ld.AddQuery(_T('d'), j, 0,a_apl_stored_document_file_name, true);
		  ld.AddQuery(_T('d'), j, 0,a_apl_stored_document_source, true);
		  ld.AddQuery(_T('d'), j, 0,a_apl_assigned_document_location_path, true);
		j=ld.AddQuery(_T('d'), i, 0,a_apl_doc_change_user, true);
		  ld.AddQuery(_T('d'), j, 0,a_user, true);
		j=ld.AddQuery(_T('d'), i, 0,a_apl_doc_change_old, true);
		  ld.AddQuery(j,_T('d'), i, 0,a_apl_doc_change_new, true);
		  ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_id, true);
		  ld.AddQuery(_T('d'), i, 0,a_apl_doc_change_date_s, true);
		ld.LoadEx();
	}

	CaplSetResourceHandle setres(module_inst);
	
	CDocChanges dlg;
	dlg.m_api= m_api;
	dlg.m_doc=doc;

	dlg.DoModal();
	//if(dlg.DoModal()!=IDOK) {AfxSetResourceHandle(m_hInstOld);return 0;}

	return true;
}
//*************************************************************
CaplInstance *CaplDocManager::CreateChange(CaplInstance *rev, bool make_change,	bool show_dlg, bool bLSS)
{
	int i;
	if(rev==0) return 0;
	if(rev==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return 0;
	}
	if(m_data==0) return 0;
	if(e_doc==0) return 0;
	CaplInstance *doc,*old_active;


	if(!m_data->IsKindOf(rev,e_apl_doc_rev)) return 0;
	m_data->GetAttr(rev, a_apl_doc_rev_doc, doc);
	m_data->GetAttr(doc, a_apl_doc_active, old_active);
	if(old_active==rev)
	{
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Данная версия уже активна"),MB_OK|MB_ICONSTOP);
		return 0;
	}

	if(!TestMakeVersionActive(doc,true)) return 0;

	CaplSetResourceHandle setres(module_inst);

/*	CDocumentChangeDlg dlg;
	dlg.m_doc_mgr=this;
	dlg.m_doc=doc;
	dlg.m_api= m_api;
	dlg.m_make_change=make_change;
	m_data->GetAttr(old_active,a_apl_doc_rev_id,dlg.m_doc_old_rev);
	m_data->GetAttr(rev,a_apl_doc_rev_id,dlg.m_doc_new_rev);*/

	CString buf= m_api->m_change_mgr.GetAVCId(doc);
	
	CDAVCItemInfo info(rev, buf);
	if (show_dlg)
	{
		CChangeDocVerDlg dlg;
		dlg.m_api=m_api;
		dlg.m_newChng= &info;
		dlg.m_bCanSelect= false;

		if(dlg.DoModal()!=IDOK) return 0;
	}

/*	CaplInstance *change=dlg.m_inst;
	if(change==0) return 0;*/
	CaplInstance *change= m_data->CreateInstance(m_api->m_change_mgr.e_avc);
	if(change)
	{
		m_data->PutAttr(change, m_api->m_change_mgr.a_avc_doc, doc);
		m_data->PutAttr(change, m_api->m_change_mgr.a_avc_old_rev, old_active);
		m_data->PutAttr(change, m_api->m_change_mgr.a_avc_new_rev, info.m_newVer);
			
		m_data->PutAttr(change, m_api->m_change_mgr.a_chng_item_id, info.m_sId);
		m_data->PutAttr(change, m_api->m_change_mgr.a_chng_item_dscr, info.m_sDscr);
		m_data->PutAttr(change, m_api->m_change_mgr.a_chng_item_notes, info.m_sNotes);
		m_data->PutAttr(change, m_api->m_change_mgr.a_chng_item_basis, info.m_sBasis);
		m_data->PutAttr(change, m_api->m_change_mgr.a_chng_item_stock, info.m_sStock);
		m_data->PutAttr(change, m_api->m_change_mgr.a_chng_item_replace_state, info.m_sNewState);
		if(show_dlg)
		{
			CaplAggr aggr;
			for(int l= 0; l<info.m_attachment.GetSize(); l++) 
				aggr.Add(info.m_attachment[l]);
			
			m_data->PutAttr(change, m_api->m_change_mgr.a_chng_item_attachment, aggr);
			m_data->PutAttr(change, m_api->m_change_mgr.a_chng_item_accept_date, info.m_sDate);
			m_data->PutAttr(change, m_api->m_change_mgr.a_chng_item_user, info.m_sUser);
			m_data->PutAttr(change, m_api->m_change_mgr.a_chng_item_autor, info.m_person);
		}
		else
		{
			CaplInstance *person=m_api->m_appr_mgr.GetCurrentPerson();
			if(person) m_data->PutAttr(change, m_api->m_change_mgr.a_chng_item_autor, person);
			CaplInstance *user=m_data->GetCurrUser();
			if(user) m_data->PutAttr(change, m_api->m_change_mgr.a_chng_item_user, m_data->GetNameCurrUser());
		}

		if(make_change) 
		{
			m_data->PutAttr(doc, a_apl_doc_active, rev);

			// изменяем поля карточки в соответствии со значеними реквизитов
			FromEntryValToDoc(rev);

			//Изменяем состояние
			CString sState;
			m_api->m_data.GetAttr(change, m_api->m_change_mgr.a_chng_item_replace_state, sState);
			if(sState!=_T("not_change") && sState!=_T("")) 
				ChangeWFState(doc, sState, APL_NOT_TEST_POSSIBLE_STATES);
		}		
 
		//++ Колесников проверка и замена характеристик
		CString sId, sName, sDescr, sCode, sLabel, sCharId;
		CaplInstance* type= NULL, *activeVer= NULL, *charact, *cicharactOld;
		CaplInstance* ciPdf = NULL;
		CaplInstance* ciChar = NULL;
		mymsiMap siMapOptions;
		msiMapIt siIter;
		aplExtent charactOld, charactNew; //характеристики надо проверить
		aplExtent extDocs,extPdfs,extPrds,extRefs; //данные об изделии
		bool bIntercative;
		bIntercative = 	m_api->m_ModeInteractive;
		m_api->m_ModeInteractive = false;
		if(old_active!=0) m_api->m_data.GetAttr(old_active,m_api->m_doc_mgr.a_apl_doc_rev_char_val_versions,charactOld);
		m_api->m_data.GetAttr(rev,m_api->m_doc_mgr.a_apl_doc_rev_char_val_versions,charactNew);
		extDocs.Add(doc);

		if(bLSS == false)
			FindAssociatedPdfs(extDocs,extPdfs,extPrds,extRefs);

		if (extPdfs.Size==1)
		{
			ciPdf = extPdfs.GetAt(0);
			LoadOptions(siMapOptions);
		}
		//отрезаем характеристики 
		for(i= 0; i<charactOld.GetSize(); i++)
		{
			charact= NULL;
			cicharactOld = charactOld.GetAt(i);
			if(cicharactOld && cicharactOld->GetAccessmode()<aplRO)
			{
				m_api->m_data.GetAttr(cicharactOld, m_api->m_charact_mgr.a_apl_charact_val_ver_char_value, charact);
				if(charact)
				{
					m_api->m_data.PutAttr(charact, m_api->m_charact_mgr.a_apl_charact_val_item, (CaplInstance*)NULL);
					m_api->m_data.PutAttr(charact, m_api->m_charact_mgr.a_apl_charact_val_base_item, (CaplInstance*)NULL);
				}
			}
		}
		//проверка, активная ли
		for(i= 0; i<charactNew.GetSize(); i++)
		{
			charact= NULL;
			CaplInstance* charactActVer= NULL;
			m_api->m_data.GetAttr(charactNew[i], m_api->m_charact_mgr.a_apl_charact_val_ver_char_value, charact);
			if(charact)
			{
				m_api->m_data.GetAttr(charact, m_api->m_charact_mgr.a_apl_charact_val_act_ver, charactActVer);
				if(charactActVer && charactActVer!=charactNew[i])
				{
					m_api->m_charact_mgr.MakeCharValVersionActive(charactNew[i]);
				}
				//привязываем новые
				if(charact->GetAccessmode()<aplRO) 
				{
					if (!ciPdf)
					{
						m_api->m_data.PutAttr(charact, m_api->m_charact_mgr.a_apl_charact_val_item, doc);
						m_api->m_data.PutAttr(charact, m_api->m_charact_mgr.a_apl_charact_val_base_item, doc);
						continue;
					}
					
					m_api->m_data.GetAttr(charact,m_api->m_charact_mgr.a_apl_charact_val_charact,ciChar);
					m_api->m_data.GetAttr(ciChar,m_api->m_charact_mgr.a_apl_charact_id,sCharId);
					siIter = siMapOptions.m_data.find(sCharId);
					if (siIter==siMapOptions.m_data.end())
					{
						m_api->m_data.PutAttr(charact, m_api->m_charact_mgr.a_apl_charact_val_item, doc);
						m_api->m_data.PutAttr(charact, m_api->m_charact_mgr.a_apl_charact_val_base_item, doc);
						continue;
					}
					if (!siIter->second)
					{
						m_api->m_data.PutAttr(charact, m_api->m_charact_mgr.a_apl_charact_val_item, doc);
						m_api->m_data.PutAttr(charact, m_api->m_charact_mgr.a_apl_charact_val_base_item, doc);
					}
					else
					{
						m_api->m_data.PutAttr(charact, m_api->m_charact_mgr.a_apl_charact_val_item, ciPdf);
						m_api->m_data.PutAttr(charact, m_api->m_charact_mgr.a_apl_charact_val_base_item, ciPdf);
					}
				}
			}
		}
		m_api->m_ModeInteractive = bIntercative;

		if(m_AutoSave) m_api->SaveChanges();
		
		if(m_AutoUsurpire && change!=0)
		{
			CString csAccPat;
			if(TRUE==m_api->m_options_mgr.GetDefPatern(change->GetType(),csAccPat))
			{
				aplExtent ext; ext.Add(change);
				apidata.NET_SetAccessFromPattern(&ext,csAccPat);
			}
		}

		CString sSubject=  APL_T("Изменение документа "), sContent=  APL_T("Поменялась активная версия документа."),
			sDocName;
		
		m_api->GetItemName(doc, sDocName);
		sSubject+=sDocName;

		aplExtent sbscr_ext;
		m_api->m_message_mgr.GetItemsSubscribers(doc, sbscr_ext);
		if (sbscr_ext.GetSize() > 0)
		{
			aplExtent wo;
			wo.Add(doc);
			m_api->m_message_mgr.SendNotifyMessage(NULL, sbscr_ext,
				sSubject, sContent, wo);
		}

		if(m_AutoSave) m_data->NET_SaveChanges();

	}
	return change;
}

bool CaplDocManager::FromEntryValToDoc(CaplInstance *ciRev)
{
	aplExtent aeExt;
	CString t_str, buf;
	CaplInstance *cit = NULL, *ciDoc = NULL;

	m_data->GetAttr(ciRev, a_apl_doc_rev_entries, aeExt);
	m_api->LoadExtentInfo(aeExt);

	for(int i=0; i<aeExt.GetSize(); i++)
	{
		m_data->GetAttr(aeExt[i], a_doc_entry_val_val, t_str);
		m_data->GetAttr(aeExt[i], a_doc_entry_val_entry, cit);

		m_data->GetAttr(ciRev, a_apl_doc_rev_doc, ciDoc);
		m_data->GetAttr(cit, a_entry_name, buf);
		buf.MakeLower();

		/*if(!buf.CompareNoCase(APL_T("обозначение документа")))
		{
			m_data->PutAttr(ciDoc, a_doc_id, t_str);
		}
		else if(!buf.CompareNoCase(APL_T("наименование изделия")))
		{
			m_data->PutAttr(ciDoc, a_doc_name, t_str);
		}
		else */if(!buf.CompareNoCase( APL_T("литера")))
		{
			m_data->PutAttr(ciRev, a_apl_doc_rev_litera, t_str);
		}
		else if(!buf.CompareNoCase( GetEntryFormatName()))
		{
			m_data->PutAttr(ciRev, a_apl_doc_rev_format, t_str);
		}
		else if(!buf.CompareNoCase( APL_T("порядковый номер листа")))
		{
			m_data->PutAttr(ciRev, a_apl_doc_rev_sheets, t_str);
		}
		else if(!buf.CompareNoCase( APL_T("общее количество листов документа")))
		{	
			m_data->PutAttr(ciRev, a_apl_doc_rev_total_sheets, t_str);
		}
	}

	return true;
}

CString CaplDocManager::GetEntryFormatName() const
{
	return APL_T("Обозначение формата листа");
}

CString CaplDocManager::GetEntryInventoryNumberName() const
{
	return APL_T("Инвентарный номер подлинника");
}

CString CaplDocManager::GetEntryMailListName() const
{
	return APL_T("Список рассылки");
}

CString CaplDocManager::GetEntryTotalListCountName() const
{
	return APL_T("Общее количество листов документа");
}

CString CaplDocManager::GetEntryReleasedByName() const
{
	return APL_T("Кем выпущен");
}

CString CaplDocManager::GetEntryAcceptApprovalName() const
{
	return APL_T("Подпись о приёме в сектор КД");
}

CString CaplDocManager::GetEntryPdfCodeName() const
{
	return APL_T("Шифр изделия");
}

CString CaplDocManager::GetEntrySubstInventoryNumberName() const
{
	return APL_T("Взамен инвентарного номера");
}

CString CaplDocManager::GetEntryDublicateInentoryNumberName() const
{
	return APL_T("Инвентарный номер дубликата");
}

CString CaplDocManager::GetEntryDublicateName() const
{
	return APL_T("Дубликат");
}

CString CaplDocManager::GetEntryArchiveAcceptDateName() const
{
	return APL_T("Дата принятия в архив");
}

bool CaplDocManager::CreateDefaultInventoryBookSearchNumberOption() const
{
	const CString sOptionName = m_api->m_options_mgr.GetInventoryBookOrderFromOptionName();
	if(sOptionName.IsEmpty())
		return false;

	int nValue;
	m_api->m_options_mgr.GetOptionValueBN(sOptionName, nValue, 0);

	if(nValue == 0)
	{
		nValue = 10000;
		m_api->m_options_mgr.CreateOption(sOptionName, nValue);
	}	

	return true;
}

bool CaplDocManager::CreateDefaultPdfSeriesOption() const
{
	const CString sOptionName = m_api->m_options_mgr.GetPdfSeriesOptionName();
	if(sOptionName.IsEmpty())
		return false;

	CString sValue;
	m_api->m_options_mgr.GetOptionValueBN(sOptionName, sValue, _T(""));

	if(sValue.IsEmpty())
	{
		sValue = APL_NO_T(	"17;8;19;56;80;100;140;140;172;184;260;392;777;943;140БТ;	\
							140ПС;17-1В;17-1ВА;172А;172КО;172ПТ;17АК;17АЛ;17В3;17В5;	\
							17ИН;17П;8АТ;8АТ1;8БТ;8ГР;8МА1;8МБ;8МБГ;8МГА;8МД;8МН;8МПБ;	\
							8МТ;8МТВ;8МТВ-1;8МТВ1С;8МТВ-2;8МТВ-3;8МТВ-5;8МТВГА;;8МТВС;	\
							8МТИ;8МТКО;8МТП;8МТПИ;8МТШ-1;8МТШ-2;8МУМ;8П;8Т;8ТБ;8ТВ;АНС;	\
							АПВ;ВМ;8М;90");

		m_api->m_options_mgr.CreateOption(sOptionName, sValue);
	}	

	return true;
}

CString CaplDocManager::GetDefaultMailList(CaplInstance *pDocument) const
{
	if(pDocument == NULL)
		return _T("");

	CString sMailList;
	CaplInstance *pDocType = NULL;
	CString sDocTypeId, sDocTypeName;

	m_api->m_data.GetAttr(pDocument, m_api->m_doc_mgr.a_doc_kind, pDocType);
	if (pDocType)
	{
		m_api->m_data.GetAttr(pDocType, m_api->m_doc_mgr.a_dt_id, sDocTypeId);
		m_api->m_data.GetAttr(pDocType, m_api->m_doc_mgr.a_dt_pdt, sDocTypeName);
	}

	sDocTypeName.MakeLower();
	CString sDrawModel = APL_T("чертёж"), sDrawModelEx = APL_T("чертеж"); 
	
	if (sDocTypeName.Find(APL_T("чертеж"))!=-1||sDocTypeName.Find(APL_T("чертёж"))!=-1)
	{
		sMailList= APL_T("10;12;30;118;СКО;ОКБ");
	}
	else if(sDocTypeName.Find(APL_T("извещение"))!=-1)
	{
		sMailList= APL_T("10;12;30;104;109;118;160;СКО;ОКБ");
	}
	else if(sDocTypeName.Find(APL_T("спецификация"))!=-1)
	{
		sMailList= APL_T("10;12;30;109;118;160;СКО;ОКБ");
	}
	else
	{
		sMailList= APL_T("10;12;30;118;160;СКО;ОКБ");
	}
	return sMailList;

	if (0 == sDocTypeId.CompareNoCase(APL_T("ИИ"))||
		0 == sDocTypeId.CompareNoCase(APL_T("ПИ"))||
		0 == sDocTypeId.CompareNoCase(APL_T("СЗ"))||
		0 == sDocTypeId.CompareNoCase(APL_T("КТС"))||
		0 == sDocTypeId.CompareNoCase(APL_T("ПЧ"))||
		0 == sDocTypeId.CompareNoCase(APL_T("ВС"))
		)
	{
// 		if (sDocTypeName.Find(sDrawModelEx) == -1 && sDocTypeName.Find(sDrawModel) == -1)
// 		{
// 			sMailList= APL_T("10;12;30;104;106;109;118;819;827;СКО;ОКБ");
// 		}
// 		else
// 		{
// 			sMailList = APL_T("10;12;30;104;106;118;819;827;СКО;ОКБ");
// 		}

	}
	else 
	{
		if (sDocTypeName.Find(sDrawModelEx)==-1 && sDocTypeName.Find(sDrawModel) == -1)
		{
			sMailList = APL_T("10;12;30;106;109;118;СКО;ОКБ");
		}
		else
		{
			sMailList = APL_T("10;12;30;106;118;СКО;ОКБ");
		}
	}

	return sMailList;
}

//*************************************************************

bool CaplDocManager::AddEntryToDocType(CaplInstance *ciEntry, CaplInstance *ciDT, bool bOptional)
{	
	if(!ciDT) return false;
	if(ciDT->GetId() == 0) return false;
	if(ciDT->GetType() == 0)	return false;

	if(!ciEntry) return false;
	if(ciEntry->GetId() == 0) return false;
	if(ciEntry->GetType() == 0)	return false;

	aplExtent aeDTEntries;
	CaplInstance *ciDTEntry = 0;

	m_api->m_data.GetAttr(ciDT, m_api->m_doc_mgr.a_dt_entries, aeDTEntries);
	ciDTEntry = m_api->m_data.CreateInstance(m_api->m_doc_mgr.e_dt_entry);
	if(!ciDTEntry) return false;

	m_api->m_data.PutAttr(ciDTEntry, m_api->m_doc_mgr.a_dt_entry_entry, ciEntry);
	m_api->m_data.PutAttr(ciDTEntry, m_api->m_doc_mgr.a_dt_entry_opt, bOptional);
	aeDTEntries.Add(ciDTEntry);

	m_api->m_data.PutAttr(ciDT, m_api->m_doc_mgr.a_dt_entries, aeDTEntries);
	return true;
}	

//*************************************************************
CaplInstance *CaplDocManager::CreateFile(const TCHAR *path, bool stored)
{
	if(m_data==0) return 0;
	if(e_doc==0) return 0;
	if(path==0) return 0;

	CaplInstance *stor=0;
	if(stored)
	{
		stor=m_data->CreateInstance(e_apl_stored_document);
		if(stor==0) return 0;
		long code;
		m_data->PutAttr(stor,a_apl_stored_document_file_name,path);
		if(!m_data->NET_SaveBlob(stor,a_apl_stored_document_source,path,code))
		{
			m_data->DeleteInstance(stor);
			return 0;
		}
	}
	else
	{
		stor=m_data->CreateInstance(e_apl_assigned_document);
		if(stor==0) return 0;
		m_data->PutAttr(stor,a_apl_assigned_document_location_path,path);
	}
	return stor;
}
//*************************************************************
CaplInstance *CaplDocManager::CreateDocumentRevision(CaplInstance *doc,
		const TCHAR *path, bool stored, bool set_active, CaplInstance *base_rev, bool bShowDlg)
{
	if(m_data==0) return 0;
	if(doc==0) return 0;
	if(doc==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return 0;
	}
	if(doc->GetType()==0) return 0;
	if(e_doc==0) return 0;
	if(path==0 && stored==true) return 0; //ЯАИ: будем создавать пустышку

	if(!m_data->IsKindOf(doc,e_doc)) return 0;

	CString s_path=path;
	CString sDescr;
	bool bSetRO=false, b_del_from_disk=false;;

	if(bShowDlg)
	{
		// Проверка состояния
		CString state;
		m_data->GetAttr(doc,a_apl_doc_wf_state,state);

		if(state==_T("approved"))
		{
			int opt_val=0;
			m_api->m_options_mgr.GetOptionValueBN(APL_NO_T("Настройка документов\\Разрешить создание версий в состоянии 'утверждено'"),opt_val,0);
			if(0==opt_val)
			{
				if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Документ находится в состоянии \"")+GetWFStateName(state)+ APL_T("\" и не может быть изменен!"));
				return 0;
			}
		}
		else if(state!=_T("working") && state!=_T("changing") && state!=_T(""))
		{
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Документ находится в состоянии \"")+GetWFStateName(state)+ APL_T("\" и не может быть изменен!"));
			return 0;
		}


		// Диалог параметров
		CaplSetResourceHandle setres(module_inst);

		CString formats;
		CaplInstance *dt;
		m_data->GetAttr(doc,a_doc_kind, dt);
		if(0!=dt)
		{
			m_api->m_data.GetAttr(dt,a_dt_auth_formats, formats);
			formats.MakeLower();
		}

		CFileLoadDlg dlg;
		dlg.m_api= m_api;
		dlg.m_no_set_active= true;
		if(TestMakeVersionActive(doc)) dlg.m_no_set_active=false;
		dlg.m_mode=_T("create_revision");
		dlg.m_path=s_path;
		dlg.m_set_active=set_active;
		dlg.m_descr=_T("");
		dlg.m_b_no_sub_doc=true;
		dlg.m_formats=formats;
		dlg.m_bEnableDelFile=true;
		if(dlg.DoModal()!=IDOK) return false;
		s_path=dlg.m_path;
		sDescr=dlg.m_descr;
		if(dlg.m_set_active) set_active=true; else set_active=false;
		if(dlg.m_set_ro) bSetRO=true; else bSetRO=false;
		if(dlg.m_save_to_db) stored=true; else stored=false;
		if(dlg.m_del_from_disk) b_del_from_disk=true; else b_del_from_disk=false;
		//if(dlg.m_use_sub_doc) bUseSubDoc=true; else bUseSubDoc=false;*/
	}

	int crc32=0; 	
	
	if(s_path!=_T(""))
	{
		CFileFind ff;
		if(0==ff.FindFile(s_path))
		{
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Файл \"") +s_path+  APL_T("\" не найден"),MB_OK|MB_ICONSTOP);
			return 0;
		}
		crc32=GetFileCRC32(s_path);
	}

	// Проверка уникальности версии по CRC32
	aplExtent ext;
	CaplAttrValue tst_value[2];

	tst_value[0].value.Set(doc);
	tst_value[0].attr=a_apl_doc_rev_doc;;
	tst_value[1].value.Set(crc32);
	tst_value[1].attr=a_apl_doc_rev_crc;
	m_data->NET_FindInstancesWithAttrValues2(e_apl_doc_rev,2,&tst_value[0],ext,false,false,NULL,aplSBMiddle,false,DEF_SOURCE);
	if(ext.GetSize()>0)
	{
		if(IDYES!=AfxMessageBox(APL_T("У документа уже есть версия с такой же контрольной суммой!\n\nСоздать новую версию ?"),MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2)) return 0;
	}
	
	// Создание версии
	CaplInstance *stor=0,*s_rev;
	
	int i;
	long code;
	CString buf;
	if(stored)
	{
		stor=m_data->CreateInstance(e_apl_stored_document);
		if(stor==0) return 0;
		i=s_path.ReverseFind(_T('\\'));
		if(i>=0) buf=s_path.Right(s_path.GetLength()-i-1); else buf=s_path;
		i=buf.ReverseFind(_T(':'));
		if(i>=0) buf=buf.Right(buf.GetLength()-i-1); 
		m_data->PutAttr(stor,a_apl_stored_document_file_name,buf);
		if(!m_data->NET_SaveBlob(stor,a_apl_stored_document_source,s_path,code))
			return 0;
	}
	else
	{
		stor=m_data->CreateInstance(e_apl_assigned_document);
		if(stor==0) return 0;
		m_data->PutAttr(stor,a_apl_assigned_document_location_path,s_path);
	}

	if(0==base_rev)
	{
		// По просьбе Созвездия от 18.08.2022 привязываем версию к активной.
		if(m_api->m_options_mgr.CheckInstallCode(_T("Созвездие")))
		{
			m_data->GetAttr(doc,a_apl_doc_active,base_rev);
		}
	}

	// Определение id версии
	int max_id=GetMaxDocRevId(doc);
	if(max_id<0 && base_rev){m_data->GetAttr(base_rev,a_apl_doc_rev_id,buf);max_id=_atoi(buf);}
	if(max_id<0) return 0;
	max_id++;
	buf.Format(_T("%i"),max_id);

	s_rev=m_data->CreateInstance(e_apl_digital_document);
	m_data->PutAttr(s_rev,a_apl_doc_rev_id,buf);
	m_data->PutAttr(s_rev,a_apl_doc_rev_descr,sDescr);
	m_data->PutAttr(s_rev,a_apl_doc_rev_crc,crc32);
	m_data->PutAttr(s_rev,a_apl_doc_rev_access_form,stor);
	m_data->PutAttr(s_rev,a_apl_doc_rev_doc,doc);
	m_data->PutAttr(s_rev,a_apl_doc_rev_user, m_api->m_appr_mgr.GetOperatorName()); // Установка автора
	m_data->PutAttr(s_rev,a_apl_doc_rev_autor, m_api->m_appr_mgr.GetCurrentPerson()); 
	
	if(base_rev) CopyEntryValues(s_rev, base_rev);		
	FromEntryValToDoc(s_rev);

	COleDateTime odt=COleDateTime::GetCurrentTime();
	CString date_time;
	aplDate2String(odt,date_time);		
	m_data->PutAttr(s_rev,a_apl_doc_rev_end_s,date_time);


	if(base_rev!=0)
	{
		if(m_data->IsKindOf(base_rev,e_apl_doc_rev))
		{
			m_data->PutAttr(s_rev,a_apl_doc_rev_base,base_rev);

			// Копирование атрибутов из базовой версии
			// ЯАИ переделал 09.06.2014 
			// Раньше копировалось только при назначении активной и из активной
			//m_api->LoadItemInfo(baserev);
			CopyDocRevAttrsToNewRev(base_rev,s_rev);
		}
	}

	if(set_active)
	{
		if(doc->GetAccessmode()==aplOWN)
		{
			CreateChange(s_rev, true, false, false);
		}
	}

	if(m_AutoSave) m_data->NET_SaveChanges();

	if(b_del_from_disk && stored)
	{
		SetFileAttributes(s_path, FILE_ATTRIBUTE_NORMAL);
		DeleteFile(s_path);
	}
	else if(bSetRO) SetFileAttributes(s_path, FILE_ATTRIBUTE_READONLY);

	SetRevisionAccessOnCreate(s_rev);

	return s_rev;
}


//*************************************************************
//CaplDocManager::
bool CaplDocManager::ShowDocProperties(CaplInstance *doc_or_revision, CaplInstance* item_rel)
{
	if(m_data==0) return false;
	if(doc_or_revision==0) return false;
	if(doc_or_revision->GetType()==0) return false;
	if(doc_or_revision->GetAccessmode()>aplRO) return false;
	if(e_doc==0) return false;

	m_data->ClearLastQuery();
	CaplInstance *doc,*rev,*inst;
	if(m_data->IsKindOf(doc_or_revision,e_doc))
	{
		doc=doc_or_revision;
		LoadDocInfo(doc);
		m_data->GetAttr(doc,a_apl_doc_active, rev);					
	}
	else if(m_data->IsKindOf(doc_or_revision,e_apl_doc_rev))
	{
		rev=doc_or_revision;
		m_data->GetAttr(rev,a_apl_doc_rev_doc, doc);		
	}
	else return false;

	CString doc_rel_src, sState;

	CaplSetResourceHandle setres(module_inst);

	CDocCreateDlg dlg;
	m_api->m_data.GetAttr(doc, m_api->m_doc_mgr.a_apl_doc_wf_state, sState);

	if(sState ==  APL_NO_T("approved")) dlg.m_bWFstateReadOnly = true;
	dlg.m_api= m_api;
	dlg.m_doc=doc;
	dlg.m_rev=rev;

	dlg.m_sel_doc_types_names.Append(m_sel_doc_types_names);
	if(item_rel!=0)
	{
		m_data->GetAttr(item_rel,a_doc_rel_frames_of_reference, dlg.m_rel_contexts);
		m_data->GetAttr(item_rel,a_apl_doc_ref_src, doc_rel_src);
		m_data->GetAttr(item_rel,a_apl_doc_ref_item, inst);
		dlg.m_doc_rel_src=doc_rel_src;
		dlg.m_show_contexts=true;
		
		if(inst->GetAccessmode()>aplRO) dlg.m_doc_ref_ro=true;
	}
	if(dlg.DoModal()!=IDOK) 
	{
		return false;
	}

	if(dlg.m_context_changed==true)
	{
		if(item_rel!=0)
		{
			if(dlg.m_rel_contexts.GetSize()>0)
				m_data->PutAttr(item_rel,a_doc_rel_frames_of_reference,dlg.m_rel_contexts);
			else
			{
				CaplValue empty_val;
				m_data->PutAttr(item_rel,a_doc_rel_frames_of_reference,empty_val);
			}

			if(dlg.m_doc_rel_src!=doc_rel_src)
				m_data->PutAttr(item_rel,a_apl_doc_ref_src,dlg.m_doc_rel_src);
		}
	}

	if(m_AutoSave) m_data->NET_SaveChanges();

	if(doc->GetAccessmode()==aplOWN)
	{
		aplExtent aet;
		aet.Add(doc);
		apidata.NET_SetAccessFromPattern(&aet,dlg.m_csAccessString);
	}

	return true;
}

//*************************************************************
//CaplDocManager::
bool CaplDocManager::ShowEntryValProperties(CString &sValue, CaplInstance *DocTypeEntry_Entry)
{

	if(!DocTypeEntry_Entry) return false;
	
	if(!m_api->m_data.IsKindOf(DocTypeEntry_Entry, m_api->m_doc_mgr.e_dt_entry)
		&& !m_api->m_data.IsKindOf(DocTypeEntry_Entry, m_api->m_doc_mgr.e_entry))
		return false;
	

	CEntryPropDlg dlg(m_api);
	CaplInstance *cit = NULL;
	if(m_api->m_data.IsKindOf(DocTypeEntry_Entry, m_api->m_doc_mgr.e_dt_entry))
		m_api->m_data.GetAttr(DocTypeEntry_Entry, m_api->m_doc_mgr.a_dt_entry_entry, DocTypeEntry_Entry);

	m_api->m_data.GetAttr(DocTypeEntry_Entry, m_api->m_doc_mgr.a_entry_id, dlg.m_sID);
	m_api->m_data.GetAttr(DocTypeEntry_Entry, m_api->m_doc_mgr.a_entry_name, dlg.m_sName);
	dlg.m_ciEntry = DocTypeEntry_Entry;
	dlg.m_sValue = sValue;

	// показывает диалог "Свойства значения реквизита", куда можно записать значение
	if(dlg.DoModal() == IDOK)
	{
		sValue = dlg.m_sValue;
		return true;
	}

	return false;
}

bool CaplDocManager::EntryForDocumentVersion(CaplInstance *ciEntry)
{
	if(!ciEntry) return false;

	CString sCard;
	m_api->m_data.GetAttr(ciEntry, a_entry_card_field, sCard);
		
	return EntryForDocumentVersion(sCard);
}

bool CaplDocManager::EntryForDocumentVersion(const CString &sCardField)
{
	return (0 == sCardField.Compare( APL_T("Формат")) || 0 == sCardField.Compare( APL_T("Метка")) || 0 == sCardField.Compare( APL_T("Литера")) || 0 == sCardField.Compare( APL_T("Листов"))
		|| 0 == sCardField.Compare( APL_T("Версия документа")) || 0 == sCardField.Compare( APL_T("Лист")) || 0 == sCardField.Compare( APL_T("Имя файла")));	
}

//*************************************************************
//CaplDocManager::
bool CaplDocManager::LoadAllDocumentRevision(CaplInstance *doc, aplExtent &rev_ext)
	// Читает из базы все версии документа
	// Возвращает из базы версии документа (rev_ext) и их историю (rel_ext)
{
	rev_ext.Clear();
	if(m_data==0) return false;
	if(doc==0) return false;
	if(doc==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(doc->GetType()==0) return false;
	if(e_doc==0) return false;
	int i,j,n,k;
	if(doc->GetId()!=0)
	{
		// Чтение из базы
		CaplLoadData ld(m_data,DEF_SOURCE);
		// документ
		i=	ld.AddQuery(0,doc, true);
		n=	ld.AddQuery(_T('d'), i, 0,a_apl_doc_lock, true, true);
		j=	ld.AddQuery(_T('b'), doc->GetId(), e_apl_doc_rev,a_apl_doc_rev_doc, true, true);
				ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_access_form, true, true);
		k=		ld.AddQuery(_T('d'), j, 0, a_apl_doc_rev_src_doc_ver, true, true);
					ld.AddQuery(_T('d'), k, 0, a_apl_doc_rev_doc, true, true);
		ld.LoadEx();
	}
	aplExtent z_rev_ext,z_rev_rel_ext;
	CaplInstance *inst;
	// Чтение версий
	m_data->GetEntityExtent(e_apl_doc_rev,z_rev_ext);
	for(i=0;i<z_rev_ext.Size;i++)
	{
		// нет прав - показывать не стоит
		if(z_rev_ext[i]->GetAccessmode() > aplRO) continue;

		m_data->GetAttr(z_rev_ext[i],a_apl_doc_rev_doc,inst);
		if(inst==doc) rev_ext.Add(z_rev_ext[i]);
	}
	return true;
}

//*************************************************************
CaplInstance *CaplDocManager::GetLasRevision(CaplInstance *doc)
{
	if(m_data==0) return 0;
	if(0==doc) return 0;
	if(doc==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return 0;
	}
	if(doc->GetType()==0) return 0;
	if(doc->GetAccessmode()>aplRO) return 0;

	if(!m_data->IsKindOf(doc,e_doc)) return 0;

	aplExtent extRev;
	m_api->m_doc_mgr.LoadAllDocumentRevision(doc,extRev);
	if(0==extRev.GetSize()) return 0;

	CaplInstance *lastRev=extRev[0];
	int j;
	for(j=1; j<extRev.GetSize();j++)
	{
		CaplInstance *rev_j=extRev[j];
		CaplInstance *rev_doc;
		m_api->m_data.GetAttr(rev_j, m_api->m_doc_mgr.a_apl_doc_rev_doc, rev_doc);
		if(0==rev_doc) continue; // Это не новая версия, а блокировка

		if(rev_j->GetId()>lastRev->GetId()) lastRev=rev_j;
	}
	return  lastRev;
}

//*************************************************************
bool CaplDocManager::CheckSubDocument(CaplInstance *doc_or_revision)
{
	int i;
	if(m_data==0) return false;
	if(doc_or_revision==0) return false;
	if(doc_or_revision==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(doc_or_revision->GetType()==0) return false;
	if(doc_or_revision->GetAccessmode()>aplRO) return false;

	if(e_doc==0) return false;

	CaplInstance *doc, *rev;
	if(m_data->IsKindOf(doc_or_revision,e_doc))
	{
		m_data->GetAttr(doc_or_revision,a_apl_doc_active, rev);
		doc=doc_or_revision;
	}
	else if(m_data->IsKindOf(doc_or_revision,e_apl_doc_rev))
	{
		rev=doc_or_revision;
		m_data->GetAttr(doc_or_revision,a_apl_doc_rev_doc, doc);
	}
	else return false;

	aplExtent ext_sub_doc, ext;
	CaplInstance* subDoc;
	CaplAttrValue av[1];
	CString sType;
	av[0].attr=a_apl_doc_ref_item;
	av[0].value.Set(doc); 

	m_data->NET_FindInstancesWithAttrValues(e_apl_doc_ref,1,av,ext_sub_doc,false);
	m_api->LoadExtentInfo(ext_sub_doc);
	for(i= 0; i<ext_sub_doc.GetSize(); i++)
	{
		if(ext_sub_doc[i]->GetAccessmode()>aplRO){ext_sub_doc.Remove(i);i--;continue;}
		m_api->m_data.GetAttr(ext_sub_doc[i], a_apl_doc_ref_doc, subDoc);
		if(!subDoc || subDoc->GetAccessmode()>aplRO){ext_sub_doc.Remove(i);i--;continue;}
		
		/*Alex Чтобы исключить при обработке зависимые документы*/
		/*Они обрабатываются в CheckOutEx*/
		m_data->GetAttr(ext_sub_doc[i],a_apl_doc_ref_type,sType);
		if(sType==APL_DOC_DEPENDENCE) {ext_sub_doc.Remove(i);i--;continue;}
	}
	if(ext_sub_doc.Size>0) return true;
	av[0].value.Set(rev);
	m_data->NET_FindInstancesWithAttrValues(e_apl_doc_ref,1,av,ext_sub_doc,false);
	m_api->LoadExtentInfo(ext_sub_doc);
	for(i= 0; i<ext_sub_doc.GetSize(); i++)
	{
		if(ext_sub_doc[i]->GetAccessmode()>aplRO){ext_sub_doc.Remove(i);i--;continue;}
		m_api->m_data.GetAttr(ext_sub_doc[i], a_apl_doc_ref_doc, subDoc);
		if(!subDoc || subDoc->GetAccessmode()>aplRO){ext_sub_doc.Remove(i);i--;continue;}

		/*Alex Чтобы исключить при обработке зависимые документы*/
		/*Они обрабатываются в CheckOutEx*/
		m_data->GetAttr(ext_sub_doc[i],a_apl_doc_ref_type,sType);
		if(sType==APL_DOC_DEPENDENCE) {ext_sub_doc.Remove(i);i--;continue;}
	}
	if(ext_sub_doc.Size>0) return true;
	return false;
}
//*************************************************************
bool CaplDocManager::CheckSuperDocument(CaplInstance *doc_or_revision)
{
	if(m_data==0) return false;
	if(doc_or_revision==0) return false;
	if(doc_or_revision==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(doc_or_revision->GetType()==0) return false;
	if(e_doc==0) return false;

	CaplInstance *doc, *rev;
	if(m_data->IsKindOf(doc_or_revision,e_doc))
	{
		m_data->GetAttr(doc_or_revision,a_apl_doc_active, rev);
		doc=doc_or_revision;
	}
	else if(m_data->IsKindOf(doc_or_revision,e_apl_doc_rev))
	{
		rev=doc_or_revision;
		m_data->GetAttr(doc_or_revision,a_apl_doc_rev_doc, doc);
	}
	else return false;

	aplExtent ext_sub_doc;
	CaplAttrValue av[1];
	av[0].attr=a_apl_doc_ref_doc;
	av[0].value.Set(doc);

	m_data->NET_FindInstancesWithAttrValues(e_apl_doc_ref,1,av,ext_sub_doc,false);
	if(ext_sub_doc.Size>0) return true;
	av[0].value.Set(rev);
	m_data->NET_FindInstancesWithAttrValues(e_apl_doc_ref,1,av,ext_sub_doc,false);
	if(ext_sub_doc.Size>0) return true;
	return false;
}


bool CaplDocManager::LoadMultyRevisions(aplExtent doc_or_revisions, const TCHAR *path,CStringArray &names, bool bUseSubDoc,bool bSetRO)
{
// 	if(m_data==0) return false;
// 	if(doc_or_revisions.GetSize()==0) return false;
// 	if(e_doc==0) return false;
// 	int i;
// 	CaplInstance *rev= NULL, *stor= NULL, *doc=0;
// 	CaplInstance *doc_or_revision;
// 	CUIntArray blob_id_s;
// 	int blob_id;
// 
// 	for(i=0;i<doc_or_revisions.GetSize();i++)
// 	{
// 		doc_or_revision=doc_or_revisions.GetAt(i);
// 
// 		if(m_data->IsKindOf(doc_or_revision,e_doc))
// 		{
// 			m_data->GetAttr(doc_or_revision,a_apl_doc_active, rev);
// 			doc=doc_or_revision;
// 		}
// 		else if(m_data->IsKindOf(doc_or_revision,e_apl_doc_rev))
// 		{
// 			rev=doc_or_revision;
// 			m_data->GetAttr(doc_or_revision,a_apl_doc_rev_doc, doc);
// 		}
// 		else if(m_data->IsKindOf(doc_or_revision,e_apl_stored_document))
// 		{
// 			
// 		}
// 		else if(m_data->IsKindOf(doc_or_revision,e_apl_assigned_document))
// 		{
// 
// 		}
// 		else 
// 		{
// 
// 		};
// 	}
// 
// 	LoadDocInfo(doc_or_revisions);

	return false;
}


//*************************************************************
bool CaplDocManager::LoadRevision(CaplInstance *doc_or_revision, const TCHAR *path, int iUseSubDoc,bool bSetRO)
{
	bool bIsLock = false ;

	if(m_data==0) return false;
	if(doc_or_revision==0) return false;
	if(doc_or_revision==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(doc_or_revision->GetType()==0) return false;
	if(e_doc==0) return false;
	CString file,buf,fpath=path,doc_name;
	CaplInstance *rev= NULL, *stor= NULL, *doc=0;
	CString tmp_path; 
	aplGetTempPath(tmp_path);

	bool isFile=false;
	LoadDocInfo(doc_or_revision);
	if(m_data->IsKindOf(doc_or_revision,e_doc))
	{
		m_data->GetAttr(doc_or_revision,a_apl_doc_active, rev);
		doc=doc_or_revision;
	}
	else if(m_data->IsKindOf(doc_or_revision,e_apl_doc_rev))
	{
		rev=doc_or_revision;
		m_data->GetAttr(doc_or_revision,a_apl_doc_rev_doc, doc);
	}
	else if(m_data->IsKindOf(doc_or_revision,e_apl_stored_document)) isFile=true;
	else if(m_data->IsKindOf(doc_or_revision,e_apl_assigned_document)) isFile=true;
	else return false;

	if(doc)
	{
		if(doc->GetAccessmode()>aplRO)
		{
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Нет доступа к версии документа!"),MB_OK|MB_ICONSTOP);
			return false;
		}
	}
	//возможно это локер
	else
	{
		//Проверяем, что перед нами локер
		if ( rev )
		{
			CaplInstance* pBaseRev = NULL ;
			CaplInstance* pOfDoc = NULL ;
			m_api->m_data.GetAttr ( rev, m_api->m_doc_mgr.a_apl_doc_rev_base, pBaseRev ) ;

			//Если ревизия есть
			if ( pBaseRev )
			{
				m_api->m_doc_mgr.LoadDocInfo( pBaseRev ) ;
				m_api->m_data.GetAttr ( pBaseRev, m_api->m_doc_mgr.a_apl_doc_rev_doc, pOfDoc ) ;

				//Если у неё есть OfDocument
				if ( pOfDoc )
				{
					CaplInstance* pLock = NULL ;
					m_api->m_data.GetAttr ( pOfDoc, m_api->m_doc_mgr.a_apl_doc_lock, pLock ) ;

					//Если у него есть замок
					if (pLock)
					{
						//Если это и есть инстанс с которого мы начинали
						if ( rev->GetId() == pLock->GetId() )
						{
							bIsLock = true ;
							//Значит документ записываем в doc
							doc = pOfDoc ;
							
							//Не забываем проверить доступ
							if(doc->GetAccessmode()>aplRO)
							{
								if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Нет доступа к версии документа!"),MB_OK|MB_ICONSTOP);
								return false;
							}
						}
					}
				}
			}
		}
	}

	m_api->GetItemName(doc_or_revision,doc_name);
	if(!isFile)
	{
		if(rev==0){
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Версия документа \"")+doc_name+ APL_T("\" была удалена другим пользователем !"),MB_OK|MB_ICONSTOP);
			return false;
		}
		if(rev->GetType()==0){
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Версия документа \"")+doc_name+ APL_T("\" была удалена другим пользователем !"),MB_OK|MB_ICONSTOP);
			return false;
		}
		GetFileName(rev, file);
	} else GetFileName(doc_or_revision, file);

	bool SetRO=bSetRO;
	// Определение пути
	bool showdlg = true;
	if(fpath.IsEmpty())
	{
		fpath=tmp_path+file;
	}
	else
	{
		if(fpath[fpath.GetLength()-1]==_T('\\')) fpath+=file;
		if(fpath[fpath.GetLength()-1]==_T(':')) fpath+=file;
		else showdlg=false;
	}
	
	// Проверка наличия вложенных документов
	bool bHasSubDoc=false;
	if(m_api->m_ModeInteractive) bHasSubDoc=CheckSubDocument(rev);
	else
	{
		if(iUseSubDoc>=0) bHasSubDoc=CheckSubDocument(rev);
	}

	if(showdlg)
	{
		if(m_api->m_ModeInteractive)
		{
			CaplSetResourceHandle setres(module_inst);

			CFileLoadDlg dlg;
			dlg.m_api= m_api;
			dlg.m_mode=_T("export");
			dlg.m_b_no_sub_doc=!bHasSubDoc;
			if(iUseSubDoc>=0) dlg.m_use_sub_doc=TRUE; else dlg.m_use_sub_doc=FALSE;
			dlg.m_path=fpath;
			if(dlg.DoModal()!=IDOK) return false;
			fpath=dlg.m_path;
			if(dlg.m_set_ro) SetRO=true; else SetRO=false;
			if(dlg.m_use_sub_doc) iUseSubDoc=1; else iUseSubDoc=0;
		}
	}
	else
	{
		if(bHasSubDoc)
		{
			if(0==iUseSubDoc)
			{
				if(!m_api->m_ModeInteractive){
					iUseSubDoc=-1;
				}else{
					BOOL b=AfxMessageBox( APL_T("Документ содержит вложенные. Обрабатывать их ?"),
										MB_YESNO|MB_ICONQUESTION)==IDYES;
					
					if (b) iUseSubDoc=1; else iUseSubDoc=-1;
				}
			}
		}
	}

	if(isFile) stor=doc_or_revision;
	else if(rev->GetAccessmode()<aplNO) m_data->GetAttr(rev,a_apl_doc_rev_access_form,stor);
	
	//Нет свойства access_form
	if(stor==0)
	{
			//Если это локер
			if ( bIsLock)
			{
				CaplInstance* pVirtualStor = m_api->m_data.CreateInstance(m_api->m_doc_mgr.e_apl_stored_document, true, true ) ;
				CaplValue* pValue = NULL ;
				m_api->m_data.GetAttrBN ( rev, _T("document_source"), &pValue ) ;
				m_api->m_data.PutAttr (pVirtualStor, m_api->m_doc_mgr.a_apl_stored_document_source, *pValue) ;
				stor = pVirtualStor ;
			}
			else
			{
				if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Тело документа отсутствует !"),  MB_ICONSTOP | MB_OK);
				//if(IDYES==AfxMessageBox(APL_T("Тело документа отсутствует. Игнорировать ?"),  MB_ICONSTOP | MB_YESNO)) return true;
				return false;
			}
	}


	if(m_data->IsKindOf(stor,e_apl_stored_document))
	{
		bool bOldHM = m_data->SetHideMode(true);
		if (!m_data->NET_LoadBlob(stor, a_apl_stored_document_source, fpath))
		{
			if(m_api->m_ModeInteractive)
			{
				CString sMsg=APL_T("Ошибка при копировании blob!");
				if(0==stor) sMsg=APL_T("Ошибка - чтение blob из несуществующего объекта!");
				else
				{
					int id=stor->GetId();
					AplNetErrors err=m_data->GetLastAplError();
					if (err==APL_NET_SRV_BLOB_NOT_FOUND) sMsg.Format(APL_T("Ошибка - не найден Blob!\n\nInstance: %i, attr: %i"),id,a_apl_stored_document_source->id);
				}
				AfxMessageBox(sMsg,  MB_ICONSTOP | MB_OK);
			}
			m_data->SetHideMode(bOldHM);
			return false;
		}
		m_data->SetHideMode(bOldHM);
	}
	else if(m_data->IsKindOf(stor,e_apl_assigned_document))
	{
		m_data->GetAttr(stor,a_apl_assigned_document_location_path,buf);
		SetFileAttributes(fpath, FILE_ATTRIBUTE_NORMAL);
		if(buf!=fpath)
		{
			if(!CopyFile(buf,fpath,FALSE))
			{
				if(GetLastError()==ERROR_FILE_NOT_FOUND){
					if(m_api->m_ModeInteractive)
						AfxMessageBox( APL_T("Не найдено тело документа \"")+doc_name+ APL_T("\", хранимого вне БД !"),MB_ICONSTOP | MB_OK);
				}else{
					if(m_api->m_ModeInteractive){
						AfxMessageBox( APL_T("Ошибка при копировании !"),MB_ICONSTOP | MB_OK);
					}
				}
				return false;
			}
		}
	}

	AfterSaveDocumentFile(doc_or_revision, fpath);
	
	LogDocAccess(rev,_T("LoadRevision"),fpath);

	if(SetRO) SetFileAttributes(fpath, FILE_ATTRIBUTE_READONLY);

	if(bHasSubDoc && iUseSubDoc>0) // обработка входящик документов
	{
		aplExtent ext0,ext1,ext2;
		FindAssociatedDocuments(doc,ext0,ext2);
		FindAssociatedDocuments(rev,ext1,ext2);
		ext0.Append(ext1);
		int i=fpath.ReverseFind(_T('\\'));
		bool i_am_locker=false;
		if(!m_service_ext_lock)
		{
			i_am_locker=true;
			m_service_ext_lock=true;
			m_service_ext.Clear();
			m_service_ext.Add(doc);
		}
		
		if(i>0)
		{
			buf=fpath.Left(i+1);
			for(i=0;i<ext0.Size;i++)
			{
				if(m_service_ext.Find(ext0[i])<0)
				{
					m_service_ext.Add(ext0[i]);
					LoadRevision(ext0[i],buf,iUseSubDoc);
				}
			}
		}
		if(i_am_locker)
		{
			m_service_ext_lock=false;
			m_service_ext.Clear();
		}

	}
	return true;
}
//*************************************************************
// Скопирована из FolderManager-a
bool CaplDocManager::CopyDocsOnDisk(aplExtent &docs, CString &defpath, int mode)
{
	if(m_api==0 || m_data==0) return false;
	if(!m_data->IsConnected()) return false;

	CaplSetResourceHandle setres(module_inst);
	CSSCopyDocsDlg dlg;
	dlg.m_sFolder = defpath;
	if(mode==APL_CHECKOUT_DOCS) dlg.m_title= APL_T("Взять документы на редактирование");
	else if(mode==APL_PRINT_DOCS) dlg.m_title= APL_T("Настройка печати документов из папки");
	if(mode==APL_COPY_DOCS) dlg.m_show_check = true;
	if(dlg.DoModal()==IDOK)
	{
		m_api->m_folder_mgr.CreateFolderOndisk(dlg.m_sFolder);
		bool old = m_api->m_ModeInteractive;
		m_api->m_ModeInteractive = false;
		TCHAR dir[1024];
		GetCurrentDirectory(1024,dir);
		long wdlg = aplStartWaitDlg( APL_T("Идет обработка данных..."));
		defpath = dlg.m_sFolder;
		CString path = dlg.m_sFolder, id=_T("");
		if(path.Right(1)!=_T("\\"))path+=_T("\\");
		for(int i=0; i<docs.Size;i++)
			if(m_data->IsKindOf(docs[i],m_api->m_doc_mgr.e_doc))
			if(docs[i]!=0)
			{
				id=_T("");
				if(docs[i]->GetAccessmode()>aplRO) continue;
				if(mode==APL_CHECKOUT_DOCS)
				{
					CaplInstance *lock=0;
					m_data->GetAttr(docs[i],m_api->m_doc_mgr.a_apl_doc_lock,lock);
					if(lock!=0) continue;
				}
				path += CCompareFoldersDlg::GetDocFileName(docs[i],m_api);
				CaplInstance *active;
				m_data->GetAttrBN(docs[i],_T("active"),active);
				if(active==0)continue;
				CaplInstance *doc;
				m_data->GetAttr(active,m_api->m_doc_mgr.a_apl_doc_rev_access_form,doc);
				if(mode!=APL_CHECKOUT_DOCS)
				{
					LogDocAccess(active,_T("CopyDocsOnDisk"),path);
					CFileStatus fs;
					int crc_1=0, crc_2 = 0;
					if(CFile::GetStatus(path,fs))
					{
						if(fs.m_attribute&CFile::readOnly) fs.m_attribute&=~CFile::readOnly;
						CFile::SetStatus(path,fs);
						crc_2 = GetFileCRC32(path);
					}
					m_data->GetAttrBN(active,_T("crc"),crc_1);
					if(crc_2!=crc_1 || crc_2==0)
					{
						CString source = _T("");
						if(m_data->IsKindOf(doc,m_api->m_doc_mgr.e_apl_stored_document)) source = _T("source");
						else if(m_data->IsKindOf(doc,m_api->m_doc_mgr.e_apl_assigned_document)) source = _T("location_path");
						BOOL rs=0;

						if(mode!=APL_CHECKOUT_DOCS)
							while(!m_data->NET_LoadBlobBN(doc,source,path))
							{
								TRACE( APL_T("Не могу создать файл: ")+path);
								rs = MessageBox(NULL, APL_T("Не могу создать файл ")+path, APL_T("Ошибка."),MB_ABORTRETRYIGNORE|MB_ICONERROR);
								if(rs==IDIGNORE) break;
								if(rs==IDABORT)
								{
									m_api->m_ModeInteractive = old;
									SetCurrentDirectory(dir);
									return true;
								}
							}
						if(rs==IDIGNORE) continue;
						else
						{
							if(dlg.m_bcheck)
							{
								CFile::GetStatus(path,fs);
								fs.m_attribute |=CFile::readOnly;
								CFile::SetStatus(path,fs);
							}
							TRACE( APL_T("Сохранен документ ")+id+_T("\n"));
							if(mode==APL_PRINT_DOCS)
							{
								CString tmp_dir; tmp_dir.GetEnvironmentVariable(_T("temp"));
								aplShellExecute(NULL,_T("print"),path,NULL,tmp_dir,SW_HIDE);
							}
							if(dlg.m_rec_docs) 
								m_api->m_folder_mgr.RecursiveCopyDocs(docs[i],dlg.m_sFolder, mode, (dlg.m_bcheck==TRUE));
						}
					}
					else
					{
						CFileStatus fs;
						if(CFile::GetStatus(path, fs))
						{
							if((dlg.m_bcheck==TRUE) && (!(fs.m_attribute&CFile::readOnly))) fs.m_attribute|=CFile::readOnly;
							else if((dlg.m_bcheck==FALSE) && fs.m_attribute&CFile::readOnly) fs.m_attribute&=~CFile::readOnly;
							CFile::SetStatus(path,fs);
						}
						if(mode==APL_PRINT_DOCS)
						{
							CString tmp_dir; tmp_dir.GetEnvironmentVariable(_T("temp"));
							ShellExecute(NULL,_T("print"),path,NULL,tmp_dir,SW_HIDE);
						}
						if(dlg.m_rec_docs) 
							m_api->m_folder_mgr.RecursiveCopyDocs(docs[i],dlg.m_sFolder, mode, (dlg.m_bcheck==TRUE));
					}
				}
				else 
				{
					m_api->m_doc_mgr.CheckOutEx(active,path,false,false);
					if(dlg.m_rec_docs) 
						m_api->m_folder_mgr.RecursiveCopyDocs(docs[i],dlg.m_sFolder, mode, (dlg.m_bcheck==TRUE));
				}
			}
			else { docs.Remove(i);i--;}
		SetCurrentDirectory(dir);
		aplEndWaitDlg(wdlg);
		if(mode==APL_COPY_DOCS) AfxMessageBox( APL_T("Сохранение документов завершено."));
		else AfxMessageBox( APL_T("Операция завершена."));
		m_api->m_ModeInteractive = old;
		return true;
	}
	return false;
}
//*************************************************************

bool CaplDocManager::View(CaplInstance *doc_or_revision, bool show_app_dlg, int iUseSubDoc)
{
	if(m_data==0) return false;
	if(doc_or_revision==0) return false;
	if(doc_or_revision==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(doc_or_revision->GetType()==0) return false;
	if(doc_or_revision->GetAccessmode()>aplRO) return false;
	if(e_doc==0) return false;

	if(m_bUseAplMarkView)
	{
		if(ViewWithMarkView(doc_or_revision)) return true;
	}
	
	CString file,fpath,app_path,buf;
	CaplInstance *doc=0,*rev=0;
	bool isFile=false, isExtFile=false;
	LoadDocInfo(doc_or_revision);
	if(m_data->IsKindOf(doc_or_revision, e_doc))
	{
		doc=doc_or_revision;
		m_data->GetAttr(doc_or_revision, a_apl_doc_active, rev);
	}
	else if(m_data->IsKindOf(doc_or_revision,e_apl_doc_rev))
	{
		rev=doc_or_revision;
		m_data->GetAttr(doc_or_revision, a_apl_doc_rev_doc, doc);
	}
	else if(m_data->IsKindOf(doc_or_revision,e_apl_stored_document)) isFile=true;
	else if(m_data->IsKindOf(doc_or_revision,e_apl_assigned_document)) isFile=true;
	else return false;

	if(0!=doc)
	{
		m_api->m_data.GetAttr(doc, a_apl_doc_system, buf );
		if(buf==_T("GenerateESI")) return ViewESI(doc_or_revision);
	}
	
	if(!isFile)
	{
		if(rev==0) {
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Версия удалена другим пользователем")); 
			return false;
		}
		if(rev->GetType()==0) {
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Версия удалена другим пользователем")); 
			return false;
		}
		CaplInstance *stor;
		m_data->GetAttr(rev, a_apl_doc_rev_access_form, stor);
		if(m_data->IsKindOf(stor,e_apl_assigned_document))
		{
			//GetFullFileName(rev,file);
			m_data->GetAttr(stor, a_apl_assigned_document_location_path, fpath);
			isExtFile=true;
		}
		else GetFileName(rev,file);
	}
	else GetFileName(doc_or_revision,file);


	// Проверяем расширение - а не надо ли использовать AplMarkView
	int i=file.ReverseFind(_T('.'));
	if(i>=0)
	{
		CString ext=file.Right(file.GetLength()-i);
		ext.MakeLower();
		if(ext==_T(".xmlrep")) if(ViewWithMarkView(doc_or_revision)) return true;
	}
	

	if(!isExtFile) // Это не ссылка, поэтому копируем в temp
	{
		TCHAR lpTempPath[MAX_PATH];
		GetTempPath(MAX_PATH,lpTempPath);

		//убрал ayatsk 24.07.2009, т.к. проблемы с ProE
		//TCHAR lpTempFileName[MAX_PATH];
		//GetTempFileName(lpTempPath,_T("pss"),0,lpTempFileName); 
		//fpath=lpTempFileName+CString(_T("."))+file;
		fpath=lpTempPath;
		if(fpath==_T("")) fpath=_T("c:");
		if(fpath[fpath.GetLength()-1]!=_T('\\')) fpath+=_T('\\');
		
		CString tmp_path=fpath;
		while(1)
		{
			fpath=tmp_path;
			fpath+=file;
			CFileFind ff;
			if(ff.FindFile(fpath))
			{
				SetFileAttributes(LPCTSTR(fpath),FILE_ATTRIBUTE_NORMAL);
				if(!DeleteFile(fpath))
				{
					tmp_path+=_T('~');
					continue;
				}
			}
			break;
		}
		if(!LoadRevision(doc_or_revision,fpath,iUseSubDoc)) return false;
	}
	
	LogDocAccess(rev,_T("View"),fpath);

	//HANDLE hProcess = RunFile(fpath, show_app_dlg);

	if(show_app_dlg) //Открыть с помощью
	{
		/* Не работает в Windows 10
		typedef void (WINAPI *LPOPENWITH)(HWND, DWORD, LPCTSTR, DWORD);

		HMODULE hDll;
		LPOPENWITH pOpenWith;

		hDll = LoadLibrary(_T("SHELL32"));
		if ( hDll )
		{
			pOpenWith = (LPOPENWITH)GetProcAddress(hDll, "OpenAs_RunDLLA");
			if ( pOpenWith )
				pOpenWith(0, 0, LPCTSTR(fpath), 0);

			FreeLibrary(hDll);
		}*/
		CString s1; 
		s1=_T("shell32.dll,OpenAs_RunDLL ");
		s1+=fpath; 
		ShellExecute(0, _T("open"), _T("rundll32.exe"), LPCTSTR(s1), NULL, SW_NORMAL);
	}
	else
	{
		LPTSTR sCmd=_T("open");
		if(show_app_dlg) sCmd=_T("openas");

		HINSTANCE hRes=aplShellExecute(0,sCmd,fpath,0,0,SW_SHOWNORMAL, false);
		if((int)hRes<=32)
		{
			hRes=aplShellExecute(0,_T("view"),fpath,0,0,SW_SHOWNORMAL, false);
			if((int)hRes<=32)
			{
				hRes=aplShellExecute(0,_T("preview"),fpath,0,0,SW_SHOWNORMAL, false);
			}
		}

		if((int)hRes<=32)
		{
			if(m_api->m_ModeInteractive)
			{
				if(SE_ERR_ASSOCINCOMPLETE==(int)hRes || SE_ERR_NOASSOC==(int)hRes) AfxMessageBox( APL_T("Нет ассоциированного приложения")); 
				else AfxMessageBox( APL_T("Ошибка запуска приложения")); 
			}			

			::SetFileAttributes(fpath, FILE_ATTRIBUTE_NORMAL);
			::DeleteFile(fpath);
			return false;
		}

		if(!isExtFile)  eraser.AddFileInfo(fpath,hRes,false);
	}
	return true;
}

bool CaplDocManager::ViewWithMarkView(CaplInstance *doc_or_revision, int bOpenInNewProcess)
{
	if(m_data==0) return false;
	if(doc_or_revision==0) return false;
	if(doc_or_revision==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(doc_or_revision->GetType()==0) return false;
	if(doc_or_revision->GetAccessmode()>aplRO) return false;
	if(e_doc==0) return false;

	if(-1==bOpenInNewProcess)
	{
		if(GetKeyState(VK_SHIFT) < 0) bOpenInNewProcess=1; else bOpenInNewProcess =0;
	}

	CString filename,file_ext;
	GetFileName(doc_or_revision,filename);
	int i=filename.ReverseFind(_T('.'));
	if(i>=0) file_ext=filename.Right(filename.GetLength()-(i+1));
	file_ext.MakeLower();

	if(!( (file_ext==_T("pdf")) || (file_ext==_T("tif"))|| (file_ext==_T("tiff")) || (file_ext==_T("png"))|| (file_ext==_T("bmp"))
		|| (file_ext==_T("jpg")) || (file_ext==_T("jpeg")) || (file_ext==_T("gif"))
		|| (file_ext==_T("svg"))|| (file_ext==_T("xmlrep"))) ) return false;


	static DWORD PID_markView=0;

	if(bOpenInNewProcess>0) PID_markView=0;

	if(0!=PID_markView && CaplMPC::IsPpocessActive(PID_markView))
	{
		CString buf;
		buf.Format(_T("/showdocument=#%i"),doc_or_revision->GetId());
		CaplMPC mpc;
		bool b=mpc.SendCommand(PID_markView,buf);	
		return true;
	}

	CString buf,psw,sCmdLine=_T("* ");
	sCmdLine+=_T("\""); sCmdLine+=_T("/user="); sCmdLine+=m_api->m_data.GetNameCurrUser(); sCmdLine+=_T("\"");
	m_api->m_data.NET_GetString4DupSession(psw);
	sCmdLine+=_T(" \""); sCmdLine+=_T("/password="); sCmdLine+=psw; sCmdLine+=_T("\"");
	sCmdLine+=_T(" \""); sCmdLine+=_T("/db="); sCmdLine+=m_api->m_data.GetNameCurrConnection(); sCmdLine+=_T("\"");
	buf.Format(_T("#%i"),doc_or_revision->GetId());
	sCmdLine+=_T(" "); sCmdLine+=_T("/showdocument="); sCmdLine+=buf;	

	PID_markView=CaplMPC::StartProcess(_T("aplmarkview.exe"),sCmdLine);
	if(0==PID_markView||-1==PID_markView )
	{
		//запустить не удалось - берем путь по настройке
		CString path;
		HKEY key=0;
		const TCHAR CaplDefWindowParam_KeyName[]=_T("Software\\CALS Centre \"Applied Logistic\"");
		RegOpenKeyEx(HKEY_CURRENT_USER,CaplDefWindowParam_KeyName,0, KEY_QUERY_VALUE,&key);
		if(0!=key)
		{
			TCHAR *buf=new TCHAR[1024];
			DWORD size=1024; DWORD type=0;;
			RegQueryValueEx(key,_T("AplMarkViewPath"),0,&type,(BYTE*)buf,&size);
			path=buf;
			delete buf;
			RegCloseKey(key);
		}
		if(path!=_T(""))
		{
			path+=_T("aplmarkview.exe");
			PID_markView=CaplMPC::StartProcess(path,sCmdLine);
		}
	}
	if(0==PID_markView||-1==PID_markView )AfxMessageBox( APL_T("Ошибка запуска aplMarkView.exe!"),MB_ICONSTOP|MB_OK);
	return true;
}
//*************************************************************

bool CaplDocManager::Print(CaplInstance *doc_or_revision, bool show_app_dlg)
{
	if(m_data==0) return false;
	if(doc_or_revision==0) return false;
	if(doc_or_revision==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(doc_or_revision->GetType()==0) return false;
	if(doc_or_revision->GetAccessmode()>aplRO) return false;
	if(e_doc==0) return false;
	CString file,fpath,app_path;
	CaplInstance *rev;
	bool isFile=false;
	if(m_data->IsKindOf(doc_or_revision,e_doc))
	{
		LoadDocInfo(doc_or_revision);
		m_data->GetAttr(doc_or_revision,a_apl_doc_active, rev);
	}
	else if(m_data->IsKindOf(doc_or_revision,e_apl_doc_rev)) rev=doc_or_revision;
	else if(m_data->IsKindOf(doc_or_revision,e_apl_stored_document)) isFile=true;
	else if(m_data->IsKindOf(doc_or_revision,e_apl_assigned_document)) isFile=true;
	else return false;
	
	if(!isFile)
	{
		if(rev==0) {
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Версия удалена другим пользователем")); 
			return false;
		}
		if(rev->GetType()==0) {
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Версия удалена другим пользователем")); 
			return false;
		}
		GetFileName(rev,file);
	}
	else GetFileName(doc_or_revision,file);

	if(file==_T("")) file = _T("~01");
	aplGetTempPath(fpath);
	fpath+=file;

	if(LoadRevision(doc_or_revision,fpath))
	{
		if(show_app_dlg)
		{
			if(!SelectApp(fpath,app_path)) return false;
		}
		if(app_path==_T(""))
		{
			SHELLEXECUTEINFO ExInfo;
			ExInfo.cbSize = sizeof(SHELLEXECUTEINFO);
			ExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
			ExInfo.hwnd = 0;
			ExInfo.lpVerb = _T("print");
			ExInfo.lpFile = fpath;
			ExInfo.lpParameters = 0;
			ExInfo.lpDirectory = 0;
			ExInfo.nShow = SW_SHOWNORMAL;
			ShellExecuteEx(&ExInfo);
			
			if((int)ExInfo.hInstApp==SE_ERR_ASSOCINCOMPLETE) 
			{if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Нет ассоциированного приложения")); return false;}
			if((int)ExInfo.hInstApp<=32) 
			{if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка запуска приложения")); return false;}
			if(ExInfo.hProcess!=0) eraser.AddFileInfo(fpath,ExInfo.hProcess,false);
		}
		else
		{
			CString buf=app_path; buf+=_T(" \"");buf+=fpath;buf+=_T("\"");

			PROCESS_INFORMATION proc_inf;
			STARTUPINFO startin;
			startin.cb = sizeof(STARTUPINFO);
			startin.lpReserved = NULL;
			startin.lpDesktop = NULL;
			startin.lpTitle = NULL;
			startin.dwFlags = STARTF_USESHOWWINDOW;
			startin.cbReserved2 = 0;
			startin.lpReserved2 = NULL;
			startin.wShowWindow = SW_SHOW;

			BOOL res=CreateProcess(NULL, LPTSTR((LPCTSTR)buf), NULL, NULL, FALSE, 0, NULL,NULL,&startin,&proc_inf);
			//long res=WinExec(LPCTSTR(buf),SW_SHOW);
			//long res=aplCreateProcess(app_path,_T("d:\\test.txt"),false,false);
			if(res==0) 
			{if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка запуска приложения")); return false;}
			//if(res!=0) eraser.AddFileInfo(fpath,(HANDLE)res,false);
		}
	}
	return true;
}
/*
CaplInstance *CaplDocManager::CheckMyLock(CaplInstance *doc, bool bShowMessages)
{
	if(doc==0) return 0;
	if(doc==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox(APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	};
	if(doc->GetAccessmode()>aplRO) return 0;
	
	CaplInstance *lock=0;
	m_data->GetAttr(doc,a_apl_doc_lock, lock);
	if(!lock) return 0;

	CaplInstance *user=0;
	if(lock) m_data->GetAttr(lock,a_apl_doc_rev_autor,user);
		
	if(user!=m_data->GetCurrUser())
	{
		if(bShowMessages) AfxMessageBox(APL_T("Документ уже редактируется другим пользователем!"),MB_OK|MB_ICONSTOP);
		return false;
	}
	return lock;
}
*/

int CaplDocManager::CheckForCheckOut(CaplInstance* doc_or_revision)
{
	CaplInstance* rev= NULL, *doc= NULL, *locker= NULL;
	CaplInstance* autor= NULL, *person= NULL;
	CString sState, sName;

	if(!doc_or_revision) return 0;
	if(0==doc_or_revision->GetType()) return 0;
	if(doc_or_revision->GetAccessmode()>aplRO)
	{
		AfxMessageBox( APL_T("Нет доступа к документу !"), MB_OK|MB_ICONSTOP);
		return 1;
	}
	if(m_data->IsKindOf(doc_or_revision, e_doc))
	{
		doc=doc_or_revision;
		m_data->GetAttr(doc_or_revision, a_apl_doc_active, rev);
	}
	else if(m_data->IsKindOf(doc_or_revision, e_apl_doc_rev))
	{
		rev=doc_or_revision;
		m_data->GetAttr(doc_or_revision, a_apl_doc_rev_doc, doc);
	}
	
	if(doc)
		m_api->GetItemName(doc, sName);

	/*Проверка на удаление*/
	if(!doc || !rev)
	{
		if(m_api->m_ModeInteractive)
		{
			if(!rev)
				AfxMessageBox( APL_T("Версия документа \"")+sName+ APL_T("\" была удалена другим пользователем!"),MB_OK|MB_ICONSTOP);
			else if(!doc)
				AfxMessageBox( APL_T("Документ \"")+sName+ APL_T("\" был удален другим пользователем!"),MB_OK|MB_ICONSTOP);
		}
		return 3;
	}

	if(!doc->GetType() || !rev->GetType())
	{
		if(m_api->m_ModeInteractive)
		{
			if(!rev->GetType())
				AfxMessageBox( APL_T("Версия документа \"")+sName+ APL_T("\" была удалена другим пользователем!"),MB_OK|MB_ICONSTOP);
			else if(!doc->GetType())
				AfxMessageBox( APL_T("Документ \"")+sName+ APL_T("\" был удален другим пользователем!"),MB_OK|MB_ICONSTOP);
		}
		return 3;
	}

	/*Проверка доступа*/
	if(doc->GetAccessmode()>=aplRO||rev->GetAccessmode()>aplRO) 
	{
		if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Нет прав на редактирование документа \"")+sName+_T("\"!"), MB_OK|MB_ICONSTOP);
		return 1;
	}

	/*Проверка состояния документа*/
	m_data->GetAttr(doc, a_apl_doc_wf_state, sState);
	if(m_api->m_show.m_auto_wfstate!=TRUE)
	{
		if( ! ((sState==_T("")) || (sState==_T("working"))  || (sState==_T("changing"))) )
		{
			if(m_api->m_ModeInteractive) 
				AfxMessageBox( APL_T("Документ \"")+sName+ APL_T("\" находится в состоянии \"")+GetWFStateName(sState)+ APL_T("\" и не может быть изменен.\n\nДля изменения документ надо перевести в состояние \"В разработке\" или \"На изменении\"."),
				MB_OK|MB_ICONSTOP);
			return 2;
		}
	}
	else
	{
		if(sState==_T("canceled"))
		{
			if(m_api->m_ModeInteractive) 
				AfxMessageBox( APL_T("Документ \"")+sName+ APL_T("\" находится в состоянии \"")+GetWFStateName(_T("canceled"))+ APL_T("\" и не может редактироваться."));
			return 2;
		}
	}

	/*Проверка блокировки документа другим пользователем*/
	m_data->GetAttr(doc, a_apl_doc_lock, locker);
	if(locker!=0)
	{
		m_api->m_data.GetAttr(locker, a_apl_doc_rev_autor, autor);
		person= m_api->m_appr_mgr.GetCurrentPerson();

		if(person!=autor)
		{
			if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Документ \"")+sName+ APL_T("\" уже редактируется !"),MB_OK|MB_ICONSTOP);
			return 4;
		}
	}
	
	return 0;
}
//*************************************************************
bool CaplDocManager::MultiCheckOut(aplExtent &ext, const TCHAR *path, CStringArray& filenames, bool bAllMustCheckOut/*=true*/,aplExtent * pCheckOutExt/*=0*/,  bool bAlwaysShowDlg/* = false*/, bool bUseSubDoc/* = false*/)
{
	for(int i = 0; i<ext.Size; i++)
	{
		if(CheckOut(ext.GetAt(i),path,bAlwaysShowDlg,bUseSubDoc,true,false,true))
		{
			if(pCheckOutExt)
				pCheckOutExt->Add(ext.GetAt(i));
			else if(bAllMustCheckOut)
				continue;
			else 
				return false;
		}
	}
	CUIntArray blob_ids;
	CaplInstance* pInst, *rev; 
	for(int i = 0; i<ext.Size; i++)
	{
		rev = 0;
		pInst = ext.GetAt(i);
		if(m_data->IsKindOf(pInst,e_doc))
			m_data->GetAttr(pInst,a_apl_doc_active, rev);
		else if(m_data->IsKindOf(pInst,e_apl_doc_rev))
			rev=pInst;
		
		if (rev)
		{
			CaplInstance  *accessForm = NULL;
			m_api->m_data.GetAttr(rev, m_api->m_doc_mgr.a_apl_doc_rev_access_form, accessForm );

			CString strBlobId;
			m_api->m_data.GetAttr(accessForm, m_api->m_doc_mgr.a_apl_stored_document_source, strBlobId );

			if ( !strBlobId.IsEmpty())
				if(int blobId = ::_ttoi(strBlobId) )
					blob_ids.Add( blobId );
		}
	}
	if ( blob_ids.GetCount() > 0 )
		m_api->m_data.NET_LoadMultiBlobsFromSrv(blob_ids, path, filenames,  0 );
	return true;
}

//*************************************************************
bool CaplDocManager::CheckOut(CaplInstance *doc_or_revision, const TCHAR *path, bool bAlwaysShowDlg/* = false*/, bool bUseSubDoc/* = false*/, bool bIgnoreState/* = false*/,bool bCharact/* = true*/,bool bGenNewName/* = false*/, bool bLoadInfo /*= true*/)
{
	if(m_data==0) return false;
	if(doc_or_revision==0) return false;
	if(doc_or_revision==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(doc_or_revision->GetType()==0) return false;
	if(e_doc==0) return false;
	CString file,buf,fpath=path,descr;
	if(path==0) bAlwaysShowDlg = true;
	CaplInstance *doc,*rev, *stor, *inst,*dt=0;
	BOOL run_ass_app=false;

	if(!PrepareEnvInPath(m_api,fpath)) return false;

	if(m_data->IsKindOf(doc_or_revision,e_doc))
	{
		doc=doc_or_revision;
		m_data->GetAttr(doc_or_revision,a_apl_doc_active, rev);
	}
	else if(m_data->IsKindOf(doc_or_revision,e_apl_doc_rev))
	{
		rev=doc_or_revision;
		m_data->GetAttr(doc_or_revision,a_apl_doc_rev_doc, doc);
	}
	else return false;

	if(doc==0)return false;
	
	// чтобы данные точно прочитались с сервера!
	m_data->ClearLastQuery();
	if(bLoadInfo) LoadDocInfo(doc);
	
//-----------------Проверка состояния документа-----------------------------
	if(!bIgnoreState)
	{
		CString state;
		m_data->GetAttr(doc,a_apl_doc_wf_state,state);
		
		
		if(state.Compare(_T("must_revision"))==0)
		{
			if(!ChangeWFState(doc, _T("changing"))) return false;
		}
		else if(m_api->m_show.m_auto_wfstate!=TRUE)
		{
			if(state==_T("approved"))
			{
				int opt_val=0;
				m_api->m_options_mgr.GetOptionValueBN(APL_NO_T("Настройка документов\\Разрешить создание версий в состоянии 'утверждено'"),opt_val,0);
				if(0==opt_val)
				{
					if(m_api->m_ModeInteractive) 
					{
						AfxMessageBox( APL_T("Документ находится в состоянии \"")+GetWFStateName(state)+ APL_T("\" и не может быть изменен.\n\nДля изменения документ надо перевести в состояние \"в разработке\" или \"на изменении\"."),
							MB_OK|MB_ICONSTOP);
					}
					else
						TRACE( APL_T("Документ находится в состоянии \"")+GetWFStateName(state)+ APL_T("\" и не может быть изменен."));

					return false;
				}
			}
			else if( ! ((state==_T("")) || (state==_T("working"))  || (state==_T("changing"))) )
			{
				if(m_api->m_ModeInteractive) 
				{
					AfxMessageBox( APL_T("Документ находится в состоянии \"")+GetWFStateName(state)+ APL_T("\" и не может быть изменен.\n\nДля изменения документ надо перевести в состояние \"в разработке\" или \"на изменении\"."),
						MB_OK|MB_ICONSTOP);
				}
				else
					TRACE( APL_T("Документ находится в состоянии \"")+GetWFStateName(state)+ APL_T("\" и не может быть изменен."));
				
				return false;
			}
		}
		else
		{
			if(state==_T("canceled"))
			{
				if(m_api->m_ModeInteractive) 
					AfxMessageBox( APL_T("Документ находится в состоянии \"")+GetWFStateName(_T("canceled"))+ APL_T("\" и не может редактироваться."));
				else
					TRACE( APL_T("Документ находится в состоянии \"")+GetWFStateName(_T("canceled"))+ APL_T("\" и не может редактироваться.\n"));
				return false;
			}
			else if(state==_T("approved"))
			{
				int opt_val=0;
				m_api->m_options_mgr.GetOptionValueBN(APL_NO_T("Настройка документов\\Разрешить создание версий в состоянии 'утверждено'"),opt_val,0);
				if(0==opt_val)
				{
					if(m_api->m_ModeInteractive) 
					{
						if(AfxMessageBox( APL_T("Документ находится в состоянии \"")+GetWFStateName(state)+ APL_T("\". перевести его в состояние \"")+GetWFStateName(_T("changing"))+_T("\"?"),MB_YESNO)==IDNO)
							return false;
					}
					else
						TRACE( APL_T("Документ переведен из состояния \"")+GetWFStateName(state)+ APL_T("\" в состояние \"")+GetWFStateName(_T("changing"))+_T("\"\n"));
		
					if(0==m_api->m_doc_mgr.ChangeWFState(doc,_T("changing"))) return false;
				}
			}
			else if(state==_T("approving_change"))
			{
				if(m_api->m_ModeInteractive) 
				{
					if(AfxMessageBox( APL_T("Документ находится в состоянии \"")+GetWFStateName(state)+ APL_T("\" перевести его в состояние \"")+GetWFStateName(_T("changing"))+_T("\"?"),MB_YESNO)==IDNO)
						return false;
				}
				else
					TRACE( APL_T("Документ переведен из состояния \"")+GetWFStateName(state)+ APL_T("\" в состояние \"")+GetWFStateName(_T("changing"))+_T("\"\n"));

				if(0==m_api->m_doc_mgr.ChangeWFState(doc,_T("changing"))) return false;
			}
			else if(state==_T("approving"))
			{
				if(m_api->m_ModeInteractive) 
				{
					if(AfxMessageBox( APL_T("Документ находится в состоянии \"")+GetWFStateName(state)+ APL_T("\" перевести его в состояние \"")+GetWFStateName(_T("working"))+_T("\"?"),MB_YESNO)==IDNO)
						return false;
				}
				else
					TRACE( APL_T("Документ переведен из состояния \"")+GetWFStateName(state)+ APL_T("\" в состояние \"")+GetWFStateName(_T("working"))+_T("\"\n"));

				if(0==m_api->m_doc_mgr.ChangeWFState(doc,_T("working")))return false;
			}
		}
	}
//-----------------Проверка состояния документа-----------------------------
	
	if(doc->GetAccessmode()>=aplRO) 
	{
		if(m_api->m_ModeInteractive) aplErrorMessage(S::NoAccessRight(),doc);
		else 
		{
			TRACE(S::NoAccessRight());
			TRACE("\n");
		}
		return false;
	}
	
	
	if(rev==0)
	{
		if(m_api->m_ModeInteractive)
		{
			if(IDYES!=AfxMessageBox( APL_T("Версия документа была удалена другим пользователем ! \n\nОтметить документ как редактируемый ?"),
				MB_YESNO|MB_ICONSTOP))
				return false;
		}
		else
		{
			TRACE( APL_T("Версия документа была удалена другим пользователем !\n"));
			return false;
		}
	}
	else
	{
		if(rev->GetType()==0)
		{
			if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Версия документа была удалена другим пользователем !"),MB_OK|MB_ICONSTOP);
			else TRACE( APL_T("Версия документа была удалена другим пользователем !\n"));
			return false;
		}

		if(rev->GetAccessmode()>aplRO) 
		{
			if(m_api->m_ModeInteractive) aplErrorMessage(S::NoAccessRight(),rev);
			else 
			{
				TRACE(S::NoAccessRight());
				TRACE("\n");
			}
			return false;
		}
	}

	// проверка блокировки
	m_data->GetAttr(doc,a_apl_doc_lock, inst);
	if(inst!=0)
	{
		if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Документ уже редактируется !"),MB_OK|MB_ICONSTOP);
		else TRACE( APL_T("Документ уже редактируется !\n"));
		return false;
	}

	bool showdlg=true;

	// Определение пути
	if(rev==0)  fpath=_T(""); 
	else
	{
		GetFileName(rev,file);
		bool SetRO=true;
		if(fpath.Find(_T('\\'))==-1)  // Задано только имя файла 
		{
			CString sMyFolder;
			LPTSTR szPath= sMyFolder.GetBuffer(1024);
			SHGetSpecialFolderPath(NULL, szPath, CSIDL_PERSONAL, FALSE);
			sMyFolder.ReleaseBuffer();
			if(sMyFolder.GetLength()>0) {if(sMyFolder[sMyFolder.GetLength()-1]!=_T('\\')) sMyFolder+=_T("\\");}
			TCHAR *tmp_buf=new TCHAR[_MAX_PATH];
			GetCurrentDirectory(_MAX_PATH,tmp_buf);
			buf=tmp_buf;
			delete []tmp_buf;
			if(buf[buf.GetLength()-1]!=_T('\\'))buf+=_T("\\");
			if(fpath==_T("")) sMyFolder+=file; else sMyFolder+=fpath;
			fpath=sMyFolder;
		}
		else
		{
			if(fpath[fpath.GetLength()-1]==_T('\\')) fpath+=file;
			if(fpath[fpath.GetLength()-1]==_T(':')) fpath+=file;
			else showdlg=false;
		}
	}

	// Проверка наличия вложенных документов
	bool bHasSubDoc=false;
	if(m_api->m_ModeInteractive) bHasSubDoc=CheckSubDocument(rev);
	else
	{
		if(bUseSubDoc) bHasSubDoc=CheckSubDocument(rev);
	}

	if(bAlwaysShowDlg)showdlg=true;
	if(showdlg && rev!=0)
	{
		if(m_api->m_ModeInteractive || bAlwaysShowDlg)
		{
			CaplSetResourceHandle setres(module_inst);

			CFileLoadDlg dlg;
			dlg.m_api= m_api;
			dlg.m_mode=_T("checkout");
			dlg.m_path=fpath;
			dlg.m_b_no_sub_doc=!bHasSubDoc;
			if(dlg.DoModal()!=IDOK) return false;
			fpath=dlg.m_path;
			descr=dlg.m_descr;
			run_ass_app=dlg.m_run_ass_app;
			if(dlg.m_use_sub_doc) bUseSubDoc=true; else bUseSubDoc=false;
		}
	}
	else
	{
		if(bHasSubDoc)
		{
			if(!bUseSubDoc && m_api->m_ModeInteractive)
			{
				if(AfxMessageBox( APL_T("Документ содержит вложенные. Обрабатывать их ?"),
					MB_YESNO|MB_ICONQUESTION)==IDYES) 
					bUseSubDoc=true;
			}
		}
	}
	
	if(rev!=0)
	{
		m_data->GetAttr(rev,a_apl_doc_rev_access_form,stor);
		bool write_file_to_disk = true;
		if(stor==0)
		{
			//AfxMessageBox(APL_T("Ошибка в БД!"),  MB_ICONSTOP | MB_OK);
			if(!m_api->m_ModeInteractive) return false;
			if(IDNO==AfxMessageBox( APL_T("Тело документа отсутствует. Продолжить ?"),  MB_ICONSTOP | MB_YESNO)) return false;
			fpath=_T("");
		}
		else if(m_data->IsKindOf(stor,e_apl_stored_document))
		{
			//проверка на наличие файла на диске...
			int crc1=0, crc2=0;
			{
				crc1 = GetFileCRC32(fpath);
				m_data->GetAttr(rev,a_apl_doc_rev_crc, crc2);
				if (crc1 != crc2 || bGenNewName) // генерим новое имя, если даже у файлов одинаковый CRC
				{
					CFileStatus fs;
					if (CFile::GetStatus(fpath, fs))
					{
						if (bGenNewName)
						{
							CString PathName;
							CString fileName;
							int iNum = fpath.ReverseFind(_T('\\'));

							PathName = fpath.Left(iNum+1);
							fileName = fpath.Right(fpath.GetLength()-iNum-1);
							
							do 
							{
								fileName = _T("_") + fileName;
								fpath.Format(_T("%s%s"),PathName,fileName);
								
							} while (CFile::GetStatus(fpath,fs));
						}
						else if (!(fs.m_attribute&CFile::readOnly))
						{
//							if(!m_api->m_ModeInteractive) return false;
							if (m_api->m_ModeInteractive)
								if (AfxMessageBox( APL_T("Файл ")+fpath+ APL_T(" существует. Заменить его?"),MB_YESNO|MB_ICONQUESTION)==IDNO)
									write_file_to_disk = false;
							fs.m_attribute&=~CFile::readOnly;
							CFile::SetStatus(fpath,fs);
						}
					}
				}
			}
			if(write_file_to_disk)
			{			
				//fs.m_attribute&=~CFile::readOnly;
				//CFile::SetStatus(fpath,fs);

				bool oldHideMode=m_data->SetHideMode(!m_api->m_ModeInteractive);
				if (!m_data->NET_LoadBlob(stor, a_apl_stored_document_source, fpath))
				{
					if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка при копировании файла \"")+fpath+ APL_T("\" ! \nПроверьте правильность указанного пути."),  MB_ICONSTOP | MB_OK);
					return false;
				}
				m_data->SetHideMode(oldHideMode);
			}
			SetFileAttributes(fpath, FILE_ATTRIBUTE_NORMAL);
		}
		else if(m_data->IsKindOf(stor,e_apl_assigned_document))
		{
			m_data->GetAttr(stor,a_apl_assigned_document_location_path,buf);
			SetFileAttributes(fpath, FILE_ATTRIBUTE_NORMAL);
			if(buf!=path)
			{
				//проверка на наличие файла на диске...
				int crc1=0, crc2=0;
				{
					crc1 = GetFileCRC32(fpath);
					m_data->GetAttr(rev,a_apl_doc_rev_crc, crc2);
					if(crc1!=crc2)
					{
						CFileStatus fs;
						if(CFile::GetStatus(fpath,fs))
							if(!(fs.m_attribute&CFile::readOnly))
							{
								if(!m_api->m_ModeInteractive) return false;
								if(AfxMessageBox( APL_T("Файл ")+fpath+ APL_T(" существует. Заменить его?"),MB_YESNO|MB_ICONQUESTION)==IDNO)
									write_file_to_disk = false;
								fs.m_attribute&=~CFile::readOnly;
								CFile::SetStatus(fpath,fs);
							}
					}
				}
				if(write_file_to_disk)
					if(!CopyFile(buf,fpath,FALSE))
					{
						if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка при копировании !"),MB_ICONSTOP | MB_OK);
						return false;
					}
			}
		}
	}
	// определение имени компьютера
	CString name_comp;
	m_data->GetCompName(name_comp);
	
	// Создание объектов
	inst=m_data->CreateInstance(e_apl_digital_document);
	m_data->PutAttr(doc,a_apl_doc_lock,inst);
	m_data->PutAttr(inst,a_apl_doc_rev_base, rev);
	m_data->PutAttr(inst,a_apl_doc_rev_edit_path, LPCTSTR(fpath));
	m_data->PutAttr(inst,a_apl_doc_rev_descr, descr);
	m_data->PutAttr(inst,a_apl_doc_rev_user, m_api->m_appr_mgr.GetOperatorName()); // Установка автора
	m_data->PutAttr(inst,a_apl_doc_rev_autor, m_api->m_appr_mgr.GetCurrentPerson()); 
	m_data->PutAttr(inst,a_apl_doc_rev_stored_on, name_comp);

	COleDateTime odt=COleDateTime::GetCurrentTime();
	CString s_dt;
	aplDate2String(odt,s_dt);
	m_data->PutAttr(inst,a_apl_doc_rev_start_s,s_dt);

	

	if(bUseSubDoc && bHasSubDoc) // обработка входящик документов
	{
		aplExtent ext0,ext1,ext2;
		FindAssociatedDocuments(doc,ext0,ext2);
		FindAssociatedDocuments(rev,ext1,ext2);
		ext0.Append(ext1);
		int i=fpath.ReverseFind(_T('\\'));
		bool i_am_locker=false;
		if(!m_service_ext_lock)
		{
			i_am_locker=true;
			m_service_ext_lock=true;
			m_service_ext.Clear();
			m_service_ext.Add(doc);
		}
		
		if(i>0)
		{
			buf=fpath.Left(i+1);
			bool bMode= m_api->m_ModeInteractive;
			m_api->SetModeInteractive(false);
			for(i=0;i<ext0.Size;i++)
			{
				if(m_service_ext.Find(ext0[i])<0)
				{
					m_service_ext.Add(ext0[i]);
					CheckOut(ext0[i],buf,false,bUseSubDoc,bIgnoreState);
				}
			}
			m_api->SetModeInteractive(bMode);
		}
		if(i_am_locker)
		{
			m_service_ext_lock=false;
			m_service_ext.Clear();
		}

	}

	//++Колесников забор на редактирование вложенных характеристик
	if(bCharact)
	{
		bool bInteractive;
		aplExtent aeCharacteristics;
		aplExtent aeCharacteristicsVersions;
		CaplInstance* ciCharacteristic;
		CaplInstance* ciPdf = NULL;
		CaplInstance* ciChar = NULL;
		CString sEditSystem,sCharId;
		aplExtent extDocs,extPdfs,extPrds,extRefs,extBuf; //данные об изделии
		mymsiMap siMapOptions;
		msiMapIt siIter;
		bInteractive = m_api->m_ModeInteractive;
		m_api->m_ModeInteractive = false;
		extDocs.Add(doc);
		FindAssociatedPdfs(extDocs,extPdfs,extPrds,extRefs);
		if (extPdfs.Size==1)
		{
			ciPdf = extPdfs.GetAt(0);
			LoadOptions(siMapOptions);
		}
		extBuf.Add(doc);
		if (ciPdf)
			extBuf.Add(ciPdf);
		m_api->m_charact_mgr.FindAssociatedCharacteristic(extBuf,aeCharacteristics);
		m_api->m_charact_mgr.LoadCharacteristic(aeCharacteristics);
		for (int iChar = 0; iChar < aeCharacteristics.GetSize(); iChar++)
		{
			ciCharacteristic = aeCharacteristics.GetAt(iChar);
			
			if(ciCharacteristic==0)continue;

			m_api->m_data.GetAttr(ciCharacteristic, m_api->m_charact_mgr.a_apl_charact_val_system, sEditSystem);
			if(!sEditSystem.IsEmpty())
			{
				CaplInstance *rev=0,*act=0,*lock=0;
				m_api->m_data.GetAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_lock_ver,lock);
				if(lock)
					continue;
				lock = 0;
				m_data->GetAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_act_ver,act);
				if(!act)
				{
					CString num;
					num=_T("");
					act=m_api->m_charact_mgr.GetLatestCharValVersion(ciCharacteristic,num,false);
					if(act)
						m_data->PutAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_act_ver,act);
					else
						act=m_api->m_charact_mgr.CreateCharValVersion(ciCharacteristic,_T("0"));
					if(!act) continue;
				}
				if(rev)	
					lock=m_api->m_charact_mgr.CreateCharValVersion(rev,_T("-1"),false);
				else 
					lock=m_api->m_charact_mgr.CreateCharValVersion(act,_T("-1"),false);	
				if(!lock) 
					continue;
				m_data->PutAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_lock_ver,lock);
				aeCharacteristicsVersions.Add(lock);
				if (!ciPdf)
					continue;
				m_api->m_data.GetAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_charact,ciChar);
				if(ciChar==0)continue;
				m_api->m_data.GetAttr(ciChar,m_api->m_charact_mgr.a_apl_charact_id,sCharId);
				siIter = siMapOptions.m_data.find(sCharId);
				if (siIter==siMapOptions.m_data.end())
					continue;
				if (!siIter->second)
				{
					m_api->m_data.PutAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_item,doc);
					m_api->m_data.PutAttr(ciCharacteristic, m_api->m_charact_mgr.a_apl_charact_val_base_item, doc);
				}
				else
				{
					m_api->m_data.PutAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_item,ciPdf);
					m_api->m_data.PutAttr(ciCharacteristic, m_api->m_charact_mgr.a_apl_charact_val_base_item, ciPdf);
				}
			}
		}
		m_api->m_data.PutAttr(inst,m_api->m_doc_mgr.a_apl_doc_rev_char_val_versions,aeCharacteristicsVersions);
		m_api->m_ModeInteractive = bInteractive;
	}//if(bCharact)
	if(m_AutoSave) m_data->NET_SaveChanges();

	LogDocAccess(rev,_T("CheckOut"),fpath);
	
	if(run_ass_app)
	{
		if(fpath!=_T("")) RunFile(fpath);
	}

	return true;
}
//*************************************************************

bool CaplDocManager::UndoCheckOut(CaplInstance *doc, bool bUseSubDoc, bool bIgnoreState/* = false*/,bool bCharact/* = true*/, bool bFromDB /*= true*/)
	// Отменяет редактированиие документа (doc - документ)
{
	if(m_data==0) return false;
	if(doc==0) return false;
	if(doc==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(doc->GetType()==0) return false;
	if(e_doc==0) return false;
	if(!m_data->IsKindOf(doc,e_doc))return false;
	// чтобы данные точно прочитались с сервера!
	m_data->ClearLastQuery();
	if(bFromDB) LoadDocInfo(doc);
	if(doc->GetAccessmode()>=aplRO) 
	{
		if(m_api->m_ModeInteractive)aplErrorMessage(S::NoAccessRight(),doc);
		return false;
	}
	CaplInstance *lock;
	CString buf;
	m_data->GetAttr(doc,a_apl_doc_lock, lock);
	if(lock==0) return false; // Документ не заблокирован
	
/*	m_data->GetAttr(inst,a_apl_doc_rev_user,buf);
	if(buf!=m_data->GetNameCurrUser())
	{
		if(IDNO==AfxMessageBox(APL_T("Документ взят на редактирование другим пользователем !\n\n")
			APL_T("Вы действительно хотите отменить редактирование ?"),
			MB_YESNO|MB_ICONSTOP|MB_DEFBUTTON2))
		return false;
	}
*/
	bool bThisUser=false;
	CaplInstance *pers1=0,*pers;
	m_data->GetAttr(lock,a_apl_doc_rev_autor,pers);
	if(pers!=0)
	{
		// Взято на редактирование не анонимным пользователем
		pers1=m_api->m_appr_mgr.GetCurrentPerson();
		if(pers==pers1) bThisUser=true;
	}
	else
	{
		m_data->GetAttr(lock,a_apl_doc_rev_user,buf);
		buf.MakeLower();
		CString sCurUser=m_data->GetNameCurrUser();
		sCurUser.MakeLower();

		//if(buf!=m_data->GetNameCurrUser()) // Престало работать после унификации записи оператора
		if(buf.Find(sCurUser)>=0) bThisUser=true;
	}

	if(!bThisUser)
	{
		if(doc->GetAccessmode()!=aplOWN)
		{
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Документ взят на редактирование другим пользователем!"),MB_OK|MB_ICONSTOP);
			return false;
		}
		else
		{
			if(!m_data->IsAdmin())
			{
				int v=m_api->m_options_mgr.GetIntOptionValueBN(APL_NO_T("Настройка документов\\Запретить отмену редактирования другим пользователем"),0);
				if(1==v)
				{
					if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("У Вас нет прав для отмены редактирования!"),MB_OK|MB_ICONSTOP);
					return false;
				}	
			}
			if(IDNO==AfxMessageBox( APL_T("Документ взят на редактирование другим пользователем!\n\nВы действительно хотите отменить редактирование?"),
				MB_YESNO|MB_ICONSTOP|MB_DEFBUTTON2))
			return false;
		}
	}

	m_data->PutAttr(doc,a_apl_doc_lock, (CaplInstance*)0);

	// удаляем для анду блоб из локера
	CaplAttr *pBlobAttr = m_data->GetAttrDefinition( lock->GetType(), _T("document_source"));
	CString strBlobId;
	if ( m_api->m_data.GetAttr(lock, pBlobAttr, strBlobId ) )
	{
		if ( !strBlobId.IsEmpty() )
		{
			m_data->NET_DeleteBlob(strBlobId);
		}
	}

	m_data->DeleteInstance(lock);

	// Проверка наличия вложенных документов
	bool bHasSubDoc= false;
	if(m_api->m_ModeInteractive) bHasSubDoc= CheckSubDocument(doc);
	if(bHasSubDoc)
	{
		if(!bUseSubDoc)
		{
			if(m_api->m_ModeInteractive)
			{
				if(AfxMessageBox( APL_T("Документ содержит вложенные. Обрабатывать их?"),
					MB_YESNO|MB_ICONQUESTION)==IDYES) 
					bUseSubDoc=true;
			}
			else
				TRACE( APL_T("Документ содержит вложенные. Не обрабатываются!"));
		}
	}

	if(bUseSubDoc && bHasSubDoc) // обработка входящик документов
	{
		aplExtent ext0,ext1,ext2;
		FindAssociatedDocuments(doc,ext0,ext2);
		CaplInstance *rev;
		m_data->GetAttr(doc,a_apl_doc_active, rev);
		FindAssociatedDocuments(rev,ext1,ext2);
		ext0.Append(ext1);
		bool i_am_locker=false;
		if(!m_service_ext_lock)
		{
			i_am_locker=true;
			m_service_ext_lock=true;
			m_service_ext.Clear();
			m_service_ext.Add(doc);
		}
		
		for(int i=0;i<ext0.Size;i++)
		{
			if(m_service_ext.Find(ext0[i])<0)
			{
				m_service_ext.Add(ext0[i]);
				UndoCheckOut(ext0[i],bUseSubDoc,bIgnoreState);
			}
		}
		if(i_am_locker)
		{
			m_service_ext_lock=false;
			m_service_ext.Clear();
		}
	}
	if(bFromDB && m_AutoSave) m_data->NET_SaveChanges();

	if(0!=m_api->m_options_mgr.GetIntOptionValueBN(EnableLog,0))
	{
		CString doc_id,msg;
		m_api->m_data.GetAttr(doc,m_api->m_doc_mgr.a_doc_id,doc_id);
		msg.Format(_T("Function=UndoCheckOut doc=\"%s\"  inst_rev=%i"),
			LPCTSTR(doc_id),doc->GetId());
		m_api->m_data.NET_WriteLog(DocLogName,msg,true);
	}
	//++отмена редактирования вложенных характеристик
	if(bCharact)
	{

		bool bInteractive;
		aplExtent aeCharacteristics;
		aplExtent extDocs,extPdfs,extPrds,extRefs,extBuf; //данные об изделии
		CaplInstance* ciCharacteristic;
		CaplInstance* ciPdf = NULL;
		CaplInstance* ciChar = NULL;
		CString sEditSystem,sCharId;
		mymsiMap siMapOptions;
		msiMapIt siIter;

		bInteractive = m_api->m_ModeInteractive;
		m_api->m_ModeInteractive = false;
		extDocs.Add(doc);
		FindAssociatedPdfs(extDocs,extPdfs,extPrds,extRefs);
		if (extPdfs.Size==1)
		{
			ciPdf = extPdfs.GetAt(0);
			LoadOptions(siMapOptions);
		}
		extBuf.Add(doc);
		if (ciPdf)
			extBuf.Add(ciPdf);
		m_api->m_charact_mgr.FindAssociatedCharacteristic(extBuf,aeCharacteristics);
		m_api->m_charact_mgr.LoadCharacteristic(aeCharacteristics);
		for(int iChar = 0; iChar < aeCharacteristics.GetSize();iChar++)
		{
			ciCharacteristic = aeCharacteristics.GetAt(iChar);
			m_api->m_data.GetAttr(ciCharacteristic, m_api->m_charact_mgr.a_apl_charact_val_system, sEditSystem);
			if(!sEditSystem.IsEmpty())
			{
				CaplInstance *lock=0;
				m_api->m_data.GetAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_lock_ver,lock);
				if(!lock)
					continue;
				m_data->PutAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_lock_ver,(CaplInstance*)0);
				m_api->m_charact_mgr.DeleteCharacteristic(lock);
				if (!ciPdf)
					continue;
				m_api->m_data.GetAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_charact,ciChar);
				m_api->m_data.GetAttr(ciChar,m_api->m_charact_mgr.a_apl_charact_id,sCharId);
				siIter = siMapOptions.m_data.find(sCharId);
				if (siIter == siMapOptions.m_data.end())
					continue;
				if (!siIter->second)
				{
					m_api->m_data.PutAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_item,doc);
					m_api->m_data.PutAttr(ciCharacteristic, m_api->m_charact_mgr.a_apl_charact_val_base_item, doc);
				}
				else
				{
					m_api->m_data.PutAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_item,ciPdf);
					m_api->m_data.PutAttr(ciCharacteristic, m_api->m_charact_mgr.a_apl_charact_val_base_item, ciPdf);
				}
			}
		}
		
		m_api->m_ModeInteractive = bInteractive;
	}//if(bCharact)

	if(bFromDB)
		m_api->m_data.NET_SaveChanges();

	return true;
}
//*************************************************************
bool CaplDocManager::TestMakeVersionActive(CaplInstance *doc, bool bShowMsg)
{
	if(0==doc) return false;
	if(doc->GetAccessmode()>aplRW)
	{
		if(bShowMsg && m_api->m_ModeInteractive) aplErrorMessage(S::NoAccessRight(),doc);
		return false;
	}

	CString sState;
	m_data->GetAttr(doc,a_apl_doc_wf_state,sState);

	if( (sState==_T("")) || (sState==_T("working"))  ) return true;
	if(sState==_T("changing")) 
	{
		int opt_val=0;
		m_api->m_options_mgr.GetOptionValueBN(APL_NO_T("Настройка документов\\Состояние 'на изменении'\\Запретить делать версию активной"),opt_val,0);
		if(1==opt_val)
		{
			if(bShowMsg && m_api->m_ModeInteractive) 
			{
				AfxMessageBox( APL_T("Документ находится в состоянии \"")+GetWFStateName(sState)+ APL_T("\" и не может изменятся."));
			}
			return false;
		}

		if(doc->GetAccessmode()==aplOWN) return true;	
		m_api->m_options_mgr.GetOptionValueBN(APL_NO_T("Настройка документов\\Состояние 'на изменении'\\Требовать полный доступ для назначения версии активной"),opt_val,0);
		if(1==opt_val)
		{
			if(bShowMsg && m_api->m_ModeInteractive) aplErrorMessage(S::NoAccessRight(),doc);
			return false;
		}
		else return true;
	}
	if(bShowMsg && m_api->m_ModeInteractive) 
	{
		AfxMessageBox( APL_T("Документ находится в состоянии \"")+GetWFStateName(sState)+ APL_T("\" и не может изменятся."));
	}
	return false;
}
//*************************************************************
bool CaplDocManager::CheckIn(CaplInstance *doc, const TCHAR *path,
							 bool set_active, bool bAlwaysShowDlg, 
							 bool bUseSubDoc, 
							 bool bIgnoreState/* = false*/,
							 bool bCharact/* = true*/, 
							 bool bLoadInfo /*= true*/,
							 bool bLSS /*= false*/)
{
	m_lastflag = 0;
	if(m_data==0) return false;
	if(doc==0) return false;
	if(doc==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(doc->GetType()==0) return false;
	if(!m_data->IsKindOf(doc,e_doc)) return false;
	if(e_doc==0) return false;

/*	if(!m_ModeInteractive)
	{
		if(path==0) return false;
		else if(*path==_T('\0'))return false;
	}*/

	CString file,buf,fpath=path,descr;
	CaplInstance *f_rev=0,  *lock=0,*stor=0,*s_rev=0;
	CString s_dt;
	bool b_setActive=set_active, bSetRO=true, bStor=true,m_del_from_disk=false;

	if(!m_data->IsKindOf(doc,e_doc))return false;
	// чтобы данные точно прочитались с сервера!
	m_data->ClearLastQuery();
	if(bLoadInfo) LoadDocInfo(doc);
	if(doc->GetAccessmode()>aplRW) 
	{
		if(m_api->m_ModeInteractive)aplErrorMessage(S::NoAccessRight(),doc);
		return false;
	}

	CString state;
	m_data->GetAttr(doc,a_apl_doc_wf_state,state);

	bool no_set_active = false;
	if (!bIgnoreState)
	{
// 		if(state==_T("canceled"))
// 		{
// 			if(m_api->m_ModeInteractive)AfxMessageBox(APL_T("Документ находится в состоянии\"")+GetWFStateName(_T("canceled"))+APL_T("\" и не может быть изменен!"));
// 			return false;
// 		}
// 		else 

		if(state==_T("approved"))
		{
			int opt_val=0;
			m_api->m_options_mgr.GetOptionValueBN(APL_NO_T("Настройка документов\\Разрешить создание версий в состоянии 'утверждено'"),opt_val,0);
			if(0==opt_val)
			{
				if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Документ находится в состоянии \"")+GetWFStateName(state)+ APL_T("\" и не может быть изменен!"));
				return false;
			}
		}
		else if(state==_T("changing"))
		{
			if(set_active) 
				if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Документ находится в состоянии \"")+GetWFStateName(state)+ APL_T("\" и для него невозможно сделать версию активной!"));
			no_set_active = true;
		}
		else if(state!=_T("working") /*&& state!=_T("changing")*/ && state!=_T(""))
		{
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Документ находится в состоянии \"")+GetWFStateName(state)+ APL_T("\" и не может быть изменен!"));
			return false;
			
			//было
// 			if(set_active) 
// 				if(m_api->m_ModeInteractive)AfxMessageBox(APL_T("Документ находится в состоянии \"")+GetWFStateName(state)+APL_T("\" и для него невозможно сделать версию активной!"));
// 			no_set_active = true;
		}
	}
	
	if(set_active)
	{
		if(doc->GetAccessmode()>aplRW)
		{
			if(!m_api->m_ModeInteractive) return false;
			if(IDYES!=AfxMessageBox( APL_T("Недостаточно прав для назначения новой версии активной!\n Продолжить без назначения версии активной?"),MB_YESNO|MB_ICONSTOP))
				return false;
		}		
	}
	// проверка блокировки
	int i;
	CaplLoadData ld(m_data,DEF_SOURCE);
	long aplError=0;
	m_data->GetAttr(doc,a_apl_doc_lock, lock);
	if(lock==0)
	{
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Редактирование завершено другим пользователем!"),MB_OK|MB_ICONSTOP);
		return false;
	}

	bool bCorrectPath=false;
	
	bool bStoredInDocSource = false; // если в документ соурс находится блоб, в котором документ, то зачекинить может любой
	CaplAttr *pBlobAttr = m_data->GetAttrDefinition( lock->GetType(), _T("document_source"));
	CString strBlobId;

	if(lock!=0)
	{
		CaplInstance *pers1=0,*pers;
		m_data->GetAttr(lock,a_apl_doc_rev_autor,pers);

		if ( m_api->m_data.GetAttr(lock, pBlobAttr, strBlobId ) )
		{
			if ( !strBlobId.IsEmpty() )
			{
				bStoredInDocSource = true;
			}
		}

		if ( !bStoredInDocSource )
		{
			bool bThisUser=false;
		
			if(pers!=0)
			{
				// Взято на редактирование не анонимным пользователем
				pers1=m_api->m_appr_mgr.GetCurrentPerson();
				if(pers==pers1) bThisUser=true;
			}
			else
			{
				m_data->GetAttr(lock,a_apl_doc_rev_user,buf);
				buf.MakeLower();
				CString sCurUser=m_data->GetNameCurrUser();
				sCurUser.MakeLower();
				
				//if(buf!=m_data->GetNameCurrUser()) // Престало работать после унификации записи оператора
				if(buf.Find(sCurUser)>=0)  bThisUser=true;
			}
			if(!bThisUser)
			{
				if(m_api->m_ModeInteractive)
					AfxMessageBox( APL_T("Документ взят на редактирование другим пользователем!"),MB_OK|MB_ICONSTOP);
				return false;
			}
		}

		m_data->GetAttr(lock,a_apl_doc_rev_base,f_rev);
		m_data->GetAttr(lock,a_apl_doc_rev_start_s,s_dt);
		m_data->GetAttr(lock,a_apl_doc_rev_edit_path,buf);
		m_data->GetAttr(lock,a_apl_doc_rev_descr,descr);
		if(fpath.IsEmpty()) 
		{
			fpath = buf;
			bCorrectPath = true;
		}

		if ( bStoredInDocSource )
		{
			// док из соурса файла
			// проверить наличие на диске, иначе взять в темп файл( если из псс )

			DWORD  	fileAttr = GetFileAttributes(fpath);
			if ( 0xFFFFFFFF == fileAttr)
			{
				// нет на диске

				TCHAR szTempFileName[MAX_PATH];  
				TCHAR lpTempPathBuffer[MAX_PATH];

				::GetTempPath(MAX_PATH,   lpTempPathBuffer); // buffer for path 

				::GetTempFileName(lpTempPathBuffer, // directory for tmp files
					_T("DEMO"),     // temp file name prefix 
					0,                // create unique name 
					szTempFileName);  // buffer for name 

				fpath = szTempFileName;

				// читаем из блоба

				/*bCorrectPath = */LoadFileFromLocker( lock, fpath );

				bCorrectPath= true;
			}


		}

	}

	
	// Определение пути
	if(f_rev!=0) 
		GetFileName(f_rev,file);
	if(fpath.IsEmpty()) fpath=buf;
	if(fpath.IsEmpty()) fpath=file;
	if(!bCorrectPath)
	{
		bCorrectPath= true;
		if(fpath[fpath.GetLength()-1]==_T('\\')) fpath+=file;
		else if(fpath[fpath.GetLength()-1]==_T(':')) fpath+=file;
	}
	bool showdlg=false;

	if(!m_api->m_ModeInteractive)
	{
		if(!bCorrectPath) return false;
	}
	else
	{
		if(!bCorrectPath) showdlg=true;
		else
		{
			if(path==0) showdlg=(fpath.IsEmpty()==TRUE);
			else if(*path==_T('\0'))showdlg=true;
		}
	}

	// Проверка наличия вложенных документов
	bool bHasSubDoc=false;
	if(m_api->m_ModeInteractive) bHasSubDoc=CheckSubDocument(f_rev);
	else
	{
		if(bUseSubDoc) bHasSubDoc=CheckSubDocument(f_rev);
	}

	if((showdlg)||(bAlwaysShowDlg))
	{
		if(m_api->m_ModeInteractive || bAlwaysShowDlg)
		{
			CaplSetResourceHandle setres(module_inst);

			CString formats;
			CaplInstance *dt;
			m_data->GetAttr(doc,a_doc_kind, dt);
			if(0!=dt)
			{
				m_api->m_data.GetAttr(dt,a_dt_auth_formats, formats);
				formats.MakeLower();
			}


			CFileLoadDlg dlg;
			dlg.m_api= m_api;
			dlg.m_no_set_active= true;
			if(TestMakeVersionActive(doc)) dlg.m_no_set_active=false;
			dlg.m_mode=_T("checkin");
			dlg.m_path=fpath;
			dlg.m_set_active=b_setActive;
			dlg.m_descr=descr;
			dlg.m_b_no_sub_doc=!bHasSubDoc;
			dlg.m_formats=formats;
			dlg.m_bEnableDelFile=true;
			if(dlg.DoModal()!=IDOK) return false;
			fpath=dlg.m_path;
			descr=dlg.m_descr;
			if(dlg.m_set_active)b_setActive=true; else b_setActive=false;
			if(dlg.m_set_ro)bSetRO=true; else bSetRO=false;
			if(dlg.m_save_to_db)bStor=true; else bStor=false;
			if(dlg.m_del_from_disk)m_del_from_disk=true; else m_del_from_disk=false;
			if(dlg.m_use_sub_doc) bUseSubDoc=true; else bUseSubDoc=false;
		}
	}
	else
	{
		if(bHasSubDoc)
		{
			if(!bUseSubDoc && m_api->m_ModeInteractive)
			{
				if(AfxMessageBox( APL_T("Документ содержит вложенные. Обрабатывать их?"),
					MB_YESNO|MB_ICONQUESTION)==IDYES) 
					bUseSubDoc=true;
			}
		}
	}

	CFileFind ff;
	if(FALSE==ff.FindFile(fpath))
	{
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Файл не найден!"),MB_OK|MB_ICONSTOP);
		return false;
	}
	int crc32_1=0,crc32_2=GetFileCRC32(fpath);
	bool bCreateNewRevision=true;
	if(f_rev!=0)
	{
		m_data->GetAttr(f_rev,a_apl_doc_rev_crc,crc32_1);
		if(crc32_1==crc32_2)
		{
			if(m_api->m_ModeInteractive)
			{
				buf.Format( APL_T("Файл %s не изменился!\n\nОтменить редактирование?"),LPCTSTR(fpath));
				if(AfxMessageBox(buf,MB_YESNO|MB_ICONQUESTION)!=IDYES)
					return false;
			}

			return UndoCheckOut(doc,bUseSubDoc,bIgnoreState,bCharact,bLoadInfo);
// 			bCreateNewRevision=false;
// 			s_rev=f_rev;
		}
	}
	long code;
	if(bCreateNewRevision) 
	{
		if(bStor)
		{
			stor=m_data->CreateInstance(e_apl_stored_document);
			if(stor==0) return false;
			i=fpath.ReverseFind(_T('\\'));
			if(i>=0) buf=fpath.Right(fpath.GetLength()-i-1); else buf=fpath;
			i=buf.ReverseFind(_T(':'));
			if(i>=0) buf=buf.Right(buf.GetLength()-i-1); 
			m_data->PutAttr(stor,a_apl_stored_document_file_name,buf);
			if(!m_data->NET_SaveBlob(stor,a_apl_stored_document_source,fpath,code))
			{
				m_data->DeleteInstance(stor);
				return false;
			}
		}
		else
		{
			stor=m_data->CreateInstance(e_apl_assigned_document);
			if(stor==0) return false;
			m_data->PutAttr(stor,a_apl_assigned_document_location_path,fpath);
		}

		// Определение id версии
		int max_id = -1;
		if(doc->GetId() != 0)
		{
			max_id = GetMaxDocRevId(doc);
			if(max_id<0) return false;
			max_id++;
		}
		else
		{
			max_id = 0;
		}

		// Создание версии
		if(lock!=0)s_rev=lock;
		else s_rev=m_data->CreateInstance(e_apl_digital_document);
		m_data->PutAttr(s_rev,a_apl_doc_rev_doc,doc);
		m_data->PutAttr(s_rev,a_apl_doc_rev_base,f_rev);
		buf.Format(_T("%i"),max_id);
		m_data->PutAttr(s_rev,a_apl_doc_rev_id,buf);
		m_data->PutAttr(s_rev,a_apl_doc_rev_descr,descr);
		m_data->PutAttr(s_rev,a_apl_doc_rev_crc,crc32_2);

		m_data->PutAttr(s_rev,a_apl_doc_rev_user, m_api->m_appr_mgr.GetOperatorName()); // Установка автора
		m_data->PutAttr(s_rev,a_apl_doc_rev_autor, m_api->m_appr_mgr.GetCurrentPerson()); 
		m_data->PutAttr(s_rev,a_apl_doc_rev_start_s,s_dt);

		// Копирование атрибутов из базовой версии
		// ЯАИ переделал 09.06.2014 
		// Раньше копировалось только при назначении активной и из активной
		m_api->LoadItemInfo(f_rev);
		CopyDocRevAttrsToNewRev(f_rev,s_rev);

		// копируем значения реквизитов
		CopyEntryValues(s_rev, f_rev,true);
		FromEntryValToDoc(s_rev);

		COleDateTime odt=COleDateTime::GetCurrentTime();
		aplDate2String(odt,s_dt);		
		m_data->PutAttr(s_rev,a_apl_doc_rev_end_s,s_dt);
		m_data->PutAttr(s_rev,a_apl_doc_rev_access_form,stor);
		m_data->PutAttr(s_rev,a_apl_doc_rev_user, m_api->m_appr_mgr.GetOperatorName()); // Установка автора
		m_data->PutAttr(s_rev,a_apl_doc_rev_autor, m_api->m_appr_mgr.GetCurrentPerson()); 

		//++возврат редактируемых вложенных характеристик
		if(bCharact)
		{
			bool bInteractive;
			aplExtent aeCharacteristics;
			aplExtent aeCharacteristicsNewAssociated;
			CaplInstance* ciCharacteristic;
			CString sCharactValue;
			CString sEditSystem;
			aplExtent extDocs,extPdfs,extPrds,extRefs,extBuf; //данные об изделии
			CaplInstance* ciPdf = NULL;
			CaplInstance* ciChar = NULL;
			CString sCharId;
			mymsiMap siMapOptions;
			msiMapIt siIter;
			
			bInteractive = m_api->m_ModeInteractive;
			m_api->m_ModeInteractive = false;
			extDocs.Add(doc);
			FindAssociatedPdfs(extDocs,extPdfs,extPrds,extRefs);
			if (extPdfs.Size==1)
			{
				ciPdf = extPdfs.GetAt(0);
				LoadOptions(siMapOptions);
			}
			extBuf.Add(doc);
			if (ciPdf)
				extBuf.Add(ciPdf);
			m_api->m_charact_mgr.FindAssociatedCharacteristic(extBuf,aeCharacteristics);

			m_api->m_charact_mgr.LoadCharacteristic(aeCharacteristics);
			for(i= 0; i<aeCharacteristics.GetSize(); i++)
			{
				ciCharacteristic = aeCharacteristics.GetAt(i);
				m_api->m_data.GetAttr(ciCharacteristic, m_api->m_charact_mgr.a_apl_charact_val_system, sEditSystem);
				if(sEditSystem.IsEmpty())
					continue;
				m_api->m_data.GetAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_lock_ver,lock);
				if(!lock)
					continue;
				CString dt_s;
				dt_s=_T("");
				COleDateTime dt=COleDateTime::GetCurrentTime();
				aplDate2String(dt,dt_s);
				m_data->PutAttr(lock,m_api->m_charact_mgr.a_apl_charact_val_ver_end_date,dt_s);
				aeCharacteristicsNewAssociated.Add(lock);
				if(set_active)
				{
					m_api->m_charact_mgr.MakeCharValVersionActive(lock);
				}
				m_data->PutAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_lock_ver,(CaplInstance*)0);
				if (!ciPdf)
					continue;
				m_api->m_data.GetAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_charact,ciChar);
				m_api->m_data.GetAttr(ciChar,m_api->m_charact_mgr.a_apl_charact_id,sCharId);
				siIter = siMapOptions.m_data.find(sCharId);
				if (siIter == siMapOptions.m_data.end())
					continue;
				if (!siIter->second)
				{
					m_api->m_data.PutAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_item,doc);
					m_api->m_data.PutAttr(ciCharacteristic, m_api->m_charact_mgr.a_apl_charact_val_base_item, doc);
				}
				else
				{
					m_api->m_data.PutAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_item,ciPdf);
					m_api->m_data.PutAttr(ciCharacteristic, m_api->m_charact_mgr.a_apl_charact_val_base_item, ciPdf);
				}

			}
			
			m_api->m_data.PutAttr(s_rev,m_api->m_doc_mgr.a_apl_doc_rev_char_val_versions, aeCharacteristicsNewAssociated);
			m_api->m_ModeInteractive = bInteractive;
		}//if(bCharact)


		// Установка активной
		if(b_setActive)
		{
			CreateChange(s_rev, true, false, bLSS);
		}
	}
	// Удаление блокировки
	m_data->PutAttr(doc,a_apl_doc_lock, (CaplInstance*)0);
	if(m_AutoSave) m_api->SaveChanges();

	if(m_del_from_disk && bStor)
	{
		SetFileAttributes(fpath, FILE_ATTRIBUTE_NORMAL);
		DeleteFile(fpath);
	}
	else if(bSetRO) SetFileAttributes(fpath, FILE_ATTRIBUTE_READONLY);


	if(bUseSubDoc && bHasSubDoc) // обработка входящик документов
	{
		aplExtent ext0,ext1,ext2;
		FindAssociatedDocuments(doc,ext0,ext2);
		FindAssociatedDocuments(f_rev,ext1,ext2);
		ext0.Append(ext1);
		int i=fpath.ReverseFind(_T('\\'));
		bool i_am_locker=false;
		if(!m_service_ext_lock)
		{
			i_am_locker=true;
			m_service_ext_lock=true;
			m_service_ext.Clear();
			m_service_ext.Add(doc);
		}
		
		if(i>0)
		{
			buf=fpath.Left(i+1);
			bool bMode= m_api->m_ModeInteractive;
			m_api->SetModeInteractive(false);
			for(i=0;i<ext0.Size;i++)
			{
				if(m_service_ext.Find(ext0[i])<0)
				{
					m_service_ext.Add(ext0[i]);
					CheckIn(ext0[i],buf,b_setActive,false,bUseSubDoc,bIgnoreState);
				}
			}
			m_api->SetModeInteractive(bMode);
		}
		if(i_am_locker)
		{
			m_service_ext_lock=false;
			m_service_ext.Clear();
		}

	}

	if(b_setActive) m_lastflag = APL_SETACTIVEVER;

	if ( bStoredInDocSource )
	{
		m_data->NET_DeleteBlob( strBlobId );
		::DeleteFile( fpath );
	}

	if(m_AutoSave)
	{
		m_api->SaveChanges();
	}

	if(s_rev && s_rev->GetId() && s_rev->GetType())
	{
		SetRevisionAccessOnCreate(s_rev);
	}

	LogDocAccess(s_rev,_T("CheckIn"),fpath);

	return true;
}
//************************************************************************
// Задает доступ созданной версии документа
bool CaplDocManager::SetRevisionAccessOnCreate(CaplInstance *rev)
{
	if(0==rev) return false;
	if(rev->GetAccessmode()>aplOWN) return false;

	aplExtent aet;
	aet.Add(rev);

	int opt=0;
	m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Настройка документов\\При создании версии копировать права доступа с документа"),opt,0);
	if(1==opt)		
	{
		CaplInstance *doc;
		m_api->m_data.GetAttr(rev,m_api->m_doc_mgr.a_apl_doc_rev_doc,doc);
		if(0!=doc) m_api->m_data.NET_CopyGroupeAccess(doc,aet);
		return true;
	}

	if(true==m_AutoUsurpire)
	{
		CString csAccPat;
		if(TRUE==m_api->m_options_mgr.GetDefPatern(rev->GetType(),csAccPat))
			apidata.NET_SetAccessFromPattern(&aet,csAccPat);
	}
	return true;
}

//************************************************************************
//************************************************************************
//************************************************************************
CaplInstance* CaplDocManager::GetEntryVal(CaplInstance *ciRev, CaplInstance *Entry, bool bLoadInfo)
{
	if(0==ciRev) return NULL;
	if(0==Entry) return NULL;

	if(m_api->m_data.IsKindOf(ciRev, m_api->m_doc_mgr.e_doc))
		m_api->m_data.GetAttr(ciRev, m_api->m_doc_mgr.a_apl_doc_active, ciRev);

	CString t_str;
	aplExtent aeEntry;
	aplExtent aeEntryVal;
	CaplInstance *ciResult = NULL, *cit = NULL;

	apidata.GetAttr(ciRev, m_api->m_doc_mgr.a_apl_doc_rev_entries, aeEntryVal);
	if(bLoadInfo)
		m_api->LoadExtentInfo(aeEntryVal);

	for(int i=0; i<aeEntryVal.GetSize(); i++)
	{
		apidata.GetAttr(aeEntryVal[i], m_api->m_doc_mgr.a_doc_entry_val_entry, cit);
		if(cit) aeEntry.Add(cit);		
	}	

	if(bLoadInfo)
		m_api->LoadExtentInfo(aeEntry);

	for(int i=0; i<aeEntryVal.GetSize(); i++) 
	{
		CaplInstance *EntryVal=aeEntryVal[i];
		apidata.GetAttr(EntryVal, m_api->m_doc_mgr.a_doc_entry_val_entry, cit);
		if(Entry==cit) return EntryVal;
	}

	return ciResult;
}
//************************************************************************
CaplInstance* CaplDocManager::GetEntryValBN(CaplInstance *ciRev, LPCTSTR sEntryName, bool bLoadInfo)
{
	if(0==ciRev) return NULL;
	CaplInstance *entry=GetEntryBN(sEntryName);
	if(0==entry) return 0;

	return GetEntryVal(ciRev,entry,bLoadInfo);

	/*if(m_api->m_data.IsKindOf(ciRev, m_api->m_doc_mgr.e_doc))
		m_api->m_data.GetAttr(ciRev, m_api->m_doc_mgr.a_apl_doc_active, ciRev);

	CString t_str;
	aplExtent aeEntry;
	aplExtent aeEntryVal;
	CaplInstance *ciResult = NULL, *cit = NULL;

	apidata.GetAttr(ciRev, m_api->m_doc_mgr.a_apl_doc_rev_entries, aeEntryVal);
	if(bLoadInfo)
		m_api->LoadExtentInfo(aeEntryVal);

	for(int i=0; i<aeEntryVal.GetSize(); i++)
	{
		apidata.GetAttr(aeEntryVal[i], m_api->m_doc_mgr.a_doc_entry_val_entry, cit);
		if(cit) aeEntry.Add(cit);		
	}	

	if(bLoadInfo)
		m_api->LoadExtentInfo(aeEntry);
	for(int i=0; i<aeEntryVal.GetSize(); i++) 
	{
		apidata.GetAttr(aeEntryVal[i], m_api->m_doc_mgr.a_doc_entry_val_entry, cit);
		if(!cit) continue;

		apidata.GetAttr(cit, m_api->m_doc_mgr.a_entry_name, t_str);
		if(!t_str.CompareNoCase(sEntryName))
			ciResult = aeEntryVal[i];
	}

	return ciResult;*/
}
//************************************************************************
bool CaplDocManager::GetEntryVal(CaplInstance *ciRev, CaplInstance *Entry, CString &Value, bool bLoadInfo)
{
	Value=_T("");
	CaplInstance *EntryVal=GetEntryVal(ciRev,Entry,bLoadInfo);
	if(0==EntryVal) return false;
	m_api->m_data.GetAttr(EntryVal, m_api->m_doc_mgr.a_doc_entry_val_val, Value);
	return true;
}
//************************************************************************
bool CaplDocManager::GetEntryValBN(CaplInstance *ciRev, LPCTSTR EntryName, CString &Value, bool bLoadInfo)
{
	return GetEntryVal(ciRev,GetEntryBN(EntryName),Value,bLoadInfo);
}
//************************************************************************
CaplInstance* CaplDocManager::GetEntryBN(LPCTSTR sEntryName)
{
	if(0==sEntryName) return 0;
	CString t_str;
	CString sEntryNameLo=sEntryName;
	sEntryNameLo.MakeLower();

	aplExtent aeEntries;
	m_api->m_data.GetEntityExtent(m_api->m_doc_mgr.e_entry, aeEntries);

	for(int i=0; i<aeEntries.GetSize(); i++)
	{
		m_api->m_data.GetAttr(aeEntries[i], m_api->m_doc_mgr.a_entry_name, t_str);
		t_str.MakeLower();
		if(t_str == sEntryNameLo) 
			return aeEntries[i];
	}

	CString sSql;
	sSql.Format(_T("SELECT Ext_ FROM Ext_{apl_document_entry.name = '%s'} END_SELECT"), sEntryName);
	if(!m_api->m_data.NET_QueryEditParse(sSql, false, &t_str)) return NULL;
	m_data->NET_QueryExecute(aeEntries, APL_T("Загрузка реквизитов..."));

	if(aeEntries.GetSize())
	{
		//если не нашли в кэше, а нашли поиском, значит не зачитаны словари
		m_api->m_doc_mgr.LoadDictionary();
		return aeEntries[0];
	}

	return NULL;
}
//************************************************************************
bool CaplDocManager::UpdateEntryValues(CaplInstance *pSource, CaplInstance *pReciever, const CStringArray &entries) const
{
	// проверки
	if(NULL == pSource || NULL == pReciever || entries.GetSize() == 0)
		return false;

	if(pSource == pReciever)
		return false;

	if(false == m_api->m_data.IsKindOf(pSource, e_apl_doc_rev))
		return false;

	if(false == m_api->m_data.IsKindOf(pReciever, e_apl_doc_rev))
		return false;

	// возьмем существующие реквизиты у версий документов
	aplExtent sourceEntries, recieverEntries;
	m_api->m_data.GetAttr(pSource, a_apl_doc_rev_entries, sourceEntries);
	m_api->m_data.GetAttr(pReciever, a_apl_doc_rev_entries, recieverEntries);

	// начнем копирование / создание
	CString sEntryName;
	CaplInstance *pEntry = NULL;
	aplExtent newEntries;

	for(int i=0; i<sourceEntries.Size; ++i)
	{
		m_api->m_data.GetAttr(sourceEntries[i], a_doc_entry_val_entry, pEntry);
		if(NULL == pEntry)
			continue;

		// посмотрим, нужно ли копировать этот реквизит
		bool bNeedToUpdate = false;
		m_api->m_data.GetAttr(pEntry, a_entry_name, sEntryName);

		for(int j=0; j<entries.GetSize(); ++j)
		{
			if(0 == sEntryName.CompareNoCase(entries[j]))
			{
				bNeedToUpdate = true;
				break;
			}
		}

		if(bNeedToUpdate)	
		{
			// найдем такой же реквизит у приемника
			CaplInstance *pRecieverValue = NULL;
			CaplInstance *pRecieverEntry = NULL;

			for(int j=0; j<recieverEntries.Size; ++j)
			{
				m_api->m_data.GetAttr(recieverEntries[j], a_doc_entry_val_entry, pRecieverEntry);
				if(pRecieverEntry == pEntry)
				{
					pRecieverValue = recieverEntries[j];
					//break;
				}
			}

			// если у приемника нет такого реквизита, то создадим его
			if(NULL == pRecieverValue)
			{
				pRecieverValue = m_api->m_data.CreateInstance(e_doc_entry_val);
				newEntries.Add(pRecieverValue);
			}

			// скопируем атрибуты
			CaplValue value;
			CaplAttr attr;
			
			for(int j=0; j<sourceEntries[i]->GetType()->all_attrs.GetSize(); ++j)
			{
				CaplAttr *pAttr = sourceEntries[i]->GetType()->all_attrs[j];

				if(m_api->m_data.GetAttr(sourceEntries[i], pAttr, value))
					m_api->m_data.PutAttr(pRecieverValue, pAttr, value);
			}
		}
	}

	// дополним приемник реквизитами
	if(newEntries.Size > 0)
	{
		recieverEntries.Append(newEntries);
		m_api->m_data.PutAttr(pReciever, a_apl_doc_rev_entries, recieverEntries);
	}

	return true;
}

bool bFindAttrInList(CaplAttr *attr,const CString &sExcludeAttr)
{
	if(0==attr) return false;
	if(sExcludeAttr==_T("")) return false;
	CString attr_name=_T('|')+attr->name+_T('|');
	if(sExcludeAttr.Find(attr_name)<0) return false;
	return true;
}

bool CaplDocManager::CopyDocRevAttrsToNewRev(CaplInstance *from_rev, CaplInstance *to_rev)
{
	if(0==from_rev || 0==to_rev ) return false;

	CString sExcludeAttr;
	m_api->m_options_mgr.GetOptionValueBN(APL_NO_T("Настройка документов\\При создании новой версии не копировать атрибуты"),sExcludeAttr);
	if(sExcludeAttr!=_T(""))
	{
		sExcludeAttr.MakeLower();
		sExcludeAttr.Insert(0,_T('|'));
		sExcludeAttr+=_T('|');
	}

	CString t_str;

	/* это не нужно, т.к. будет много версий с одинаковыми метками
	if(sExcludeAttr==_T("") || !bFindAttrInList(a_apl_doc_rev_label, sExcludeAttr))
	{
		m_data->GetAttr(from_rev, a_apl_doc_rev_label, t_str);
		m_data->PutAttr(to_rev, a_apl_doc_rev_label, t_str);
	}*/

	if(sExcludeAttr==_T("") ||  !bFindAttrInList(a_apl_doc_rev_format, sExcludeAttr))
	{
		m_data->GetAttr(from_rev, a_apl_doc_rev_format, t_str);
		m_data->PutAttr(to_rev, a_apl_doc_rev_format, t_str);
		//m_data->PutAttr(doc, a_doc_format , t_str);
	}

	if(sExcludeAttr==_T("") || !bFindAttrInList(a_apl_doc_rev_litera, sExcludeAttr))
	{
		m_data->GetAttr(from_rev, a_apl_doc_rev_litera, t_str);
		m_data->PutAttr(to_rev, a_apl_doc_rev_litera, t_str);
		//m_data->PutAttr(doc, a_doc_litera , t_str);
	}

	if(sExcludeAttr==_T("") || !bFindAttrInList(a_apl_doc_rev_sheets, sExcludeAttr))
	{
		m_data->GetAttr(from_rev, a_apl_doc_rev_sheets, t_str);
		m_data->PutAttr(to_rev, a_apl_doc_rev_sheets, t_str);
		//m_data->PutAttr(doc, a_doc_sheets , t_str);
	}

	if(sExcludeAttr==_T("") || !bFindAttrInList(a_apl_doc_rev_total_sheets, sExcludeAttr))
	{

		m_data->GetAttr(from_rev, a_apl_doc_rev_total_sheets, t_str);
		m_data->PutAttr(to_rev, a_apl_doc_rev_total_sheets, t_str);
		//m_data->PutAttr(doc, a_doc_total_sheets_count , t_str);
	}

	if(sExcludeAttr==_T("") ||bFindAttrInList(a_apl_doc_rev_total_sheets_count_a4,sExcludeAttr))
	{
		m_data->GetAttr(from_rev, a_apl_doc_rev_total_sheets_count_a4, t_str);
		m_data->PutAttr(to_rev, a_apl_doc_rev_total_sheets_count_a4, t_str);
	}
	return true;
}

bool CaplDocManager::GetCardValue(CaplInstance *ciRev, LPCTSTR sCardField, CString &sCardValue)
{
	sCardValue=_T("");
	if(0==ciRev) return false;
	if(ciRev->IsDeleted()) return false;
	if(ciRev->GetAccessmode()>aplRO) return false;

	CaplInstance *doc,*rev;
	if(m_api->m_data.IsKindOf(ciRev,e_doc))	{doc=ciRev; rev=0; }
	else if(m_api->m_data.IsKindOf(ciRev,e_apl_doc_rev))
	{
		rev=ciRev;
		m_api->m_data.GetAttr(ciRev,a_apl_doc_rev_doc,doc);
		if(0==doc) return false;
		if(doc->GetAccessmode()>aplRO)  return false;
	}
	else return false;

	CString sCardFieldName=sCardField;
	sCardFieldName.MakeLower();
	if(sCardFieldName==_T(""))  return false;

	if(0!=doc)
	{
		if(sCardFieldName== APL_NO_T("обозначение")) m_api->m_data.GetAttr(doc,a_doc_id,sCardValue);
		else if(sCardFieldName== APL_NO_T("наименование")) m_api->m_data.GetAttr(doc,a_doc_name,sCardValue);
		else if(sCardFieldName== APL_NO_T("вид документа"))
		{
			CaplInstance *dt;
			m_api->m_data.GetAttr(doc, a_doc_kind, dt);
			if(0!=dt)	m_api->m_data.GetAttr(dt, a_dt_pdt, sCardValue);
		}
		else if(sCardFieldName== APL_NO_T("код вида документа"))
		{
			CaplInstance *dt;
			m_api->m_data.GetAttr(doc, a_doc_kind, dt);
			if(0!=dt)	m_api->m_data.GetAttr(dt, a_dt_id, sCardValue);
		}
		else if(sCardFieldName== APL_NO_T("дополнительный код вида документа")) m_api->m_data.GetAttr(doc,a_doc_add_dt_code,sCardValue);
		else if(sCardFieldName== APL_NO_T("код документа в зависимости от характера использования")) m_api->m_data.GetAttr(doc,a_doc_code_depend_desp,sCardValue);
		else if(sCardFieldName== APL_NO_T("инвентарный номер"))m_api->m_data.GetAttr(doc,a_doc_inv_num, sCardValue);
		else if(sCardFieldName== APL_NO_T("признак аутентичного документа"))
		{
			bool b;
			m_api->m_data.GetAttr(doc,a_doc_authentic, b);
			sCardValue= b ? _T("1") : _T("0");
		}
	}
	if(0!=rev)
	{
		if(sCardFieldName== APL_NO_T("версия документа")) m_api->m_data.GetAttr(rev,a_apl_doc_rev_id,sCardValue);
		else if(sCardFieldName== APL_NO_T("литера")) m_api->m_data.GetAttr(rev,a_apl_doc_rev_litera,sCardValue);
		else if(sCardFieldName== APL_NO_T("формат")) m_api->m_data.GetAttr(rev,a_apl_doc_rev_format,sCardValue);
		else if(sCardFieldName== APL_NO_T("метка")) m_api->m_data.GetAttr(rev,a_apl_doc_rev_label,sCardValue);
		else if(sCardFieldName== APL_NO_T("лист")) m_api->m_data.GetAttr(rev,a_apl_doc_rev_sheets,sCardValue);
		else if(sCardFieldName== APL_NO_T("листов")) m_api->m_data.GetAttr(rev,a_apl_doc_rev_total_sheets,sCardValue);
		else if(sCardFieldName== APL_NO_T("дата создания")) m_api->m_data.GetAttr(rev,a_apl_doc_rev_src_date,sCardValue);
		//else if(sCardFieldName== APL_NO_T("имя файла")) m_api->m_data.GetAttr(rev,,sCardValue);
	}
	return true;
}


bool CaplDocManager::CopyEntryValues(CaplInstance *ciRev, CaplInstance *ciSource, bool bLoadInfo)
{
	if(ciSource==0) return false;
	CString t_str, sEntryName;
	aplExtent aeRevEntryVals, aeExt;
	CaplInstance *cit = NULL, *ciNewEntryVal = NULL;

	if(!ciSource->attrs && bLoadInfo)
		m_api->LoadItemInfo(ciSource);
	
	//m_data->GetAttr(ciSource, a_apl_doc_rev_entries, aeRevEntryVals);
	//if(bLoadInfo)
	//	m_api->LoadExtentInfo(aeRevEntryVals);	
	GetActualEntriesVal(ciSource,aeRevEntryVals);
	
	int i,j;

	// ЯАИ 2012.04.17 Убираем повторяющиеся реквизиты (считаем что их мало, поэтому тупым перебором)
	// ЯАИ: 2019.06.19 Этот кусок работал некорректно, если в списке были предыдущие значения реквизитов
	// Необходимость в такой "чистке" отпала ввиду замены чуть выше GetAttr на GetActualEntriesVal 
// 	CaplInstance *cit_i,*cit_j;
// 	for(i=0;i<aeRevEntryVals.GetSize()-1;i++)
// 	{
// 	m_data->GetAttr(aeRevEntryVals[i], a_doc_entry_val_entry, cit_i);
// 		for(j=i+1;j<aeRevEntryVals.GetSize();j++)
// 		{
// 			m_data->GetAttr(aeRevEntryVals[j], a_doc_entry_val_entry, cit_j);
// 			if(cit_i==cit_j)
// 			{
// 				aeRevEntryVals.Remove(j);
// 				j--;
// 			}
// 		}
// 	}

	// ЯАИ 19.08.2011 по просьбе ЦКБА
	CString entrys_4_clear;
	bool bCheck_entrys_4_clear=false;
	m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Настройка документов\\Реквизиты, очищаемые при создании новой версии"),entrys_4_clear,0);
	if(entrys_4_clear!=_T(""))
	{
		bCheck_entrys_4_clear=true;
		entrys_4_clear.MakeLower();
		if(entrys_4_clear[0]!=_T('|')) entrys_4_clear.Insert(0,_T('|'));
		entrys_4_clear+=_T('|'); // Будет 2 подряд - ничего страшного
	}

	// копируем значения реквизитов
	for(int i=0; i<aeRevEntryVals.GetSize(); i++)
	{
		bool bSetEmpty=false;
		if(bCheck_entrys_4_clear)// ЯАИ 19.08.2011 по просьбе ЦКБА
		{
			m_data->GetAttr(aeRevEntryVals[i], a_doc_entry_val_entry, cit);
			if(0==cit) continue;
			m_api->m_data.GetAttr(cit, m_api->m_doc_mgr.a_entry_name, sEntryName);
			if(sEntryName!=_T(""))
			{
				if(sEntryName[0]!=_T('|')) sEntryName.Insert(0,_T('|'));
				sEntryName+=_T('|');
				sEntryName.MakeLower();
				if(entrys_4_clear.Find(sEntryName)>=0)	
				{
					CString card_field_name;
					m_api->m_data.GetAttr(cit, m_api->m_doc_mgr.a_entry_card_field, card_field_name);
					
					if(card_field_name!=_T(""))
					{
						card_field_name.MakeLower();

						/*if(t_str ==  APL_T("обозначение"))
						{
							m_api->m_data.PutAttr(ciDoc, m_api->m_doc_mgr.a_doc_id, sValue);
						}
						else if(t_str ==  APL_T("наименование")) 
						{
							m_api->m_data.PutAttr(ciDoc, m_api->m_doc_mgr.a_doc_name, sValue);
						}
						else if(t_str ==  APL_T("вид документа")) 
						{
						}
						else if(t_str ==  APL_T("код вида документа")) 
						{
						}
						else if(t_str ==  APL_T("имя файла")) 
						{

						}
						else if(t_str ==  APL_T("версия документа")) 
						{
							m_api->m_data.PutAttr(ciRev, m_api->m_doc_mgr.a_apl_doc_rev_id, sValue);
						}*/

						if(card_field_name ==  APL_T("литера")) 
						{
							bSetEmpty=true;
							//m_api->m_data.PutAttr(ciRev, m_api->m_doc_mgr.a_apl_doc_rev_litera, _T(""));
						}
						else if(card_field_name ==  APL_T("формат")) 
						{
							bSetEmpty=true;
							//m_api->m_data.PutAttr(ciRev, m_api->m_doc_mgr.a_apl_doc_rev_format, _T(""));
						}
						else if(card_field_name ==  APL_T("метка")) 
						{
							bSetEmpty=true;
							//m_api->m_data.PutAttr(ciRev, m_api->m_doc_mgr.a_apl_doc_rev_label, _T(""));
						}
						else if(card_field_name ==  APL_T("лист")) 
						{
							bSetEmpty=true;
							//m_api->m_data.PutAttr(ciRev, m_api->m_doc_mgr.a_apl_doc_rev_sheets, _T(""));
						}
						else if(card_field_name ==  APL_T("листов")) 
						{
							bSetEmpty=true;;
							//m_api->m_data.PutAttr(ciRev, m_api->m_doc_mgr.a_apl_doc_rev_total_sheets, _T(""));
						}
						/*else if(card_field_name ==  APL_NO_T("дополнительный код вида документа")) 
						{
							m_api->m_data.PutAttr(ciDoc, m_api->m_doc_mgr.a_doc_add_dt_code, _T(""));
						}
						else if(card_field_name ==  APL_NO_T("код документа в зависимости от характера использования")) 
						{
							m_api->m_data.PutAttr(ciDoc, m_api->m_doc_mgr.a_doc_code_depend_desp, _T(""));
						}
						else if(card_field_name ==  APL_NO_T("признак аутентичного документа")) 
						{
							m_api->m_data.PutAttr(ciDoc, m_api->m_doc_mgr.a_doc_authentic, _T(""));
						}*/
					}
					if(!bSetEmpty)continue;		
				}
			}
		}

		ciNewEntryVal = m_data->CreateInstance(m_api->m_doc_mgr.e_doc_entry_val);		
		if(ciNewEntryVal)
		{			
			{
				m_data->GetAttr(aeRevEntryVals[i], a_doc_entry_val_entry, cit);
				m_data->PutAttr(ciNewEntryVal, a_doc_entry_val_entry, cit);
				
				if(0!=cit) m_api->m_data.GetAttr(cit, m_api->m_doc_mgr.a_entry_name, sEntryName);

				m_data->GetAttr(aeRevEntryVals[i], a_doc_entry_val_descr, t_str);
				m_data->PutAttr(ciNewEntryVal, a_doc_entry_val_descr, t_str);

				m_data->GetAttr(aeRevEntryVals[i], a_doc_entry_val_prev, cit);
				m_data->PutAttr(ciNewEntryVal, a_doc_entry_val_prev, cit);

				if(bSetEmpty) t_str=_T("");
				else
				{
					if(sEntryName !=  APL_T("Версия документа")) m_data->GetAttr(aeRevEntryVals[i], a_doc_entry_val_val, t_str);
					else m_api->m_data.GetAttr(ciRev, m_api->m_doc_mgr.a_apl_doc_rev_id, t_str);
				}
				m_data->PutAttr(ciNewEntryVal, a_doc_entry_val_val, t_str);

				aeExt.Add(ciNewEntryVal);
			}
		}
	}

	// ЯАИ 10.04.2019: Копируем значения атрибутов в реквизиты (если их не было)
	// Это нужно для случая, когда реквизит соответствующий атрибуту добавили виду документов после создания версии 
	
	CaplInstance *doc=0,*dt=0;
	aplExtent dt_entries;
	m_data->GetAttr(ciSource, a_apl_doc_rev_doc, doc);
	if(0!=doc) m_data->GetAttr(doc, a_doc_kind, dt);
	if(0!=dt)  m_data->GetAttr(dt, a_dt_entries, dt_entries);

	if(dt_entries.GetSize()>0)
	{
		CString sCardField,sEntryName;
		for(i=0;i<dt_entries.GetSize();i++)
		{
			CaplInstance *dt_entry=dt_entries[i];
			if(0==dt_entry) continue;

			CaplInstance *entry;
			m_data->GetAttr(dt_entry, a_dt_entry_entry, entry);
			if(0==entry) continue;
			m_data->GetAttr(entry, a_entry_card_field, sCardField);
			if(sCardField==_T("")) continue;
			sCardField.MakeLower();
			if(sCardField==APL_NO_T("имя файла")) continue;
			if(sCardField==APL_NO_T("версия документа")) continue;
			if(sCardField==APL_NO_T("дата создания")) continue;

			if(bCheck_entrys_4_clear)// Проверяем по списку исключений
			{
				m_api->m_data.GetAttr(entry, m_api->m_doc_mgr.a_entry_name, sEntryName);
				if(sEntryName!=_T(""))
				{
					sEntryName.MakeLower();
					if(sEntryName[0]!=_T('|')) sEntryName.Insert(0,_T('|'));
					sEntryName+=_T('|');
					if(entrys_4_clear.Find(sEntryName)>=0) 
						continue;
				}
			}

			//Определяем текущее значение из карточки
			 CString sCurValueFromCard, sEntryVal;
			 if(!GetCardValue(ciSource,sCardField,sCurValueFromCard)) continue;
			 if(sCurValueFromCard==_T("")) continue;  // Если атрибут пустой, то нечего и копировать


			// Ищем такой существующий реквизит
		    CaplInstance *exist_entry_val=0;
			for(j=0; j<aeExt.GetSize();j++)
			{
				CaplInstance *entry_val=aeExt[j];
				CaplInstance *entry_j=0;
				m_data->GetAttr(entry_val, a_doc_entry_val_entry,entry_j);
				if(entry_j==entry) {exist_entry_val=entry_val; break;}
			}

			if(0!=exist_entry_val)
			{
				m_data->GetAttr(exist_entry_val, a_doc_entry_val_val,sEntryVal);
				if(sEntryVal==_T("")) 
					m_data->PutAttr(exist_entry_val, a_doc_entry_val_val,sCurValueFromCard);
			}
			else
			{
				exist_entry_val = m_data->CreateInstance(e_doc_entry_val);		
				m_data->PutAttr(exist_entry_val, a_doc_entry_val_entry, entry);
				m_data->PutAttr(exist_entry_val, a_doc_entry_val_val, sCurValueFromCard);
				aeExt.Add(exist_entry_val);
			}
		}
	}

	return m_data->PutAttr(ciRev, a_apl_doc_rev_entries, aeExt);
}

//*************************************************************
bool CaplDocManager::Edit(CaplInstance *doc_or_revision, const TCHAR *path, bool show_app_dlg, bool bUseSubDoc, bool bIgnoreState/* = false*/)
{
	if(m_data==0) return false;
	if(doc_or_revision==0) return false;
	if(doc_or_revision==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(doc_or_revision->GetType()==0) return false;
	if(e_doc==0) return false;
	CString file,fpath,app_path;
	CaplInstance *rev,*doc=0;
	if(m_data->IsKindOf(doc_or_revision,e_doc))
	{
		doc=doc_or_revision;
		m_data->GetAttr(doc_or_revision,a_apl_doc_active, rev);
	}
	else if(m_data->IsKindOf(doc_or_revision,e_apl_doc_rev))
	{
		rev=doc_or_revision;
		m_data->GetAttr(doc_or_revision,a_apl_doc_rev_doc, doc);	
	}
	else return false;

	LoadDocInfo(doc);


	CaplInstance *lock;
	m_data->GetAttr(doc,a_apl_doc_lock, lock);
	if(lock!=0)
	{
		bool bThisUser=false;
		CaplInstance *pers1=0,*pers;
		m_data->GetAttr(lock,a_apl_doc_rev_autor,pers);
		if(pers!=0)
		{
			// Взято на редактирование не анонимным пользователем
			pers1=m_api->m_appr_mgr.GetCurrentPerson();
			if(pers==pers1) bThisUser=true;
		}
		else
		{
			CString buf;
			m_data->GetAttr(lock,a_apl_doc_rev_user,buf);
			buf.MakeLower();
			CString sCurUser=m_data->GetNameCurrUser();
			sCurUser.MakeLower();

			//if(buf!=m_data->GetNameCurrUser()) // Престало работать после унификации записи оператора
			if(buf.Find(sCurUser)>=0) bThisUser=true;
		}
		if(!bThisUser)
		{
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Документ взят на редактирование другим пользователем!"),MB_OK|MB_ICONSTOP);
			return false;
		}
		else
		{
			m_data->GetAttr(lock,a_apl_doc_rev_edit_path,fpath);
			HANDLE hProcess=RunFile(fpath, show_app_dlg);
			return true;
		}
	}
	
	GetFileName(rev,file);
	if(file.IsEmpty()) file = _T("~01");
	if(path)
	{
		fpath=path;
		if(!PrepareEnvInPath(m_api,fpath)) return false;
	}

	if(fpath.IsEmpty())
	{
		LPTSTR szPath= fpath.GetBuffer(1024);
		SHGetSpecialFolderPath(NULL, szPath, CSIDL_PERSONAL, FALSE);
		fpath.ReleaseBuffer();
		if(fpath.GetLength()>0) {if(fpath[fpath.GetLength()-1]!=_T('\\')) fpath+=_T("\\");}
	}

	if(fpath.IsEmpty()) aplGetTempPath(fpath);
	if(fpath.GetLength()>0) {if(fpath[fpath.GetLength()-1]!=_T('\\')) fpath+=_T("\\");}
	fpath+=file;

	if(CheckOutEx(doc_or_revision,fpath, false, bUseSubDoc,bIgnoreState))
	{
		LogDocAccess(rev,_T("Edit"),fpath);

		if(fpath!=_T(""))
		{
			//HANDLE hProcess=RunFile(fpath, show_app_dlg);

			if(show_app_dlg) //Открыть с помощью
			{
				/* Не работает в Windows 10
				typedef void (WINAPI *LPOPENWITH)(HWND, DWORD, LPCTSTR, DWORD);

				HMODULE hDll;
				LPOPENWITH pOpenWith;

				hDll = LoadLibrary(_T("SHELL32"));
				if ( hDll )
				{
					pOpenWith = (LPOPENWITH)GetProcAddress(hDll, "OpenAs_RunDLLA");
					if ( pOpenWith )
						pOpenWith(0, 0, LPCTSTR(fpath), 0);

					FreeLibrary(hDll);
				}*/
				CString s1; 
				s1=_T("shell32.dll,OpenAs_RunDLL ");
				s1+=fpath; 
				ShellExecute(0, _T("open"), _T("rundll32.exe"), LPCTSTR(s1), NULL, SW_NORMAL);
			}
			else
			{
				LPTSTR sCmd=_T("open");
				if(show_app_dlg) sCmd=_T("openas");

				HINSTANCE hRes=aplShellExecute(0,sCmd,fpath,0,0,SW_SHOWNORMAL, false);
				if((int)hRes<=32)
				{
					hRes=aplShellExecute(0,_T("edit"),fpath,0,0,SW_SHOWNORMAL, false);
				}
				
				if((int)hRes<=32)
				{
					if(m_api->m_ModeInteractive)
					{
						if(SE_ERR_ASSOCINCOMPLETE==(int)hRes || SE_ERR_NOASSOC==(int)hRes) AfxMessageBox( APL_T("Нет ассоциированного приложения")); 
						else AfxMessageBox( APL_T("Ошибка запуска приложения")); 
					}			
				}
			}
		}
	}
	return true;
}
//*************************************************************
HANDLE CaplDocManager::RunFile(const TCHAR *file ,bool bShowAppDlg)
{
	CString fpath=file, app_path;
	if(fpath.IsEmpty()) return 0;
	if(bShowAppDlg)
	{
		if(!SelectApp(fpath, app_path)) return 0;
	}
	if(app_path.IsEmpty())
	{
		HINSTANCE hRes=aplShellExecute(NULL, _T("open"), fpath, NULL, NULL, SW_SHOW);
		if((int)hRes<=32) return 0;
		return hRes;
	}
	else
	{
		CString buf=app_path; buf+=_T(" \"");buf+=fpath;buf+=_T("\"");

		PROCESS_INFORMATION proc_inf;
		STARTUPINFO startin;
		startin.cb = sizeof(STARTUPINFO);
		startin.lpReserved = NULL;
		startin.lpDesktop = NULL;
		startin.lpTitle = NULL;
		startin.dwFlags = STARTF_USESHOWWINDOW;
		startin.cbReserved2 = 0;
		startin.lpReserved2 = NULL;
		startin.wShowWindow = SW_SHOW;

		BOOL res=CreateProcess(NULL, LPTSTR((LPCTSTR)buf), NULL, NULL, FALSE, 0, NULL,NULL,&startin,&proc_inf);
		//long res=WinExec(LPCTSTR(buf),SW_SHOW);
		//long res=aplCreateProcess(app_path,fpath,false,false);
		if(res==0) 
		{if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка запуска приложения!")); return 0;}
		//if(res!=0) eraser.AddFileInfo(fpath,(HANDLE)res,false);
	}
	return 0;
}
//*************************************************************
bool CaplDocManager::DeleteRevision(CaplInstance *rev, bool delete_doc,  bool bLoadInfo /*= true*/, bool bAdditionalCheck /*= true*/)
{
	if(!m_api->m_data.IsDictLoad()) return false;
	if(rev==0) return false;
	if(rev==(CaplInstance*)-1) 
	{
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(rev->GetType()==0)
	{
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Версия документа была удалена другим пользователем!"),MB_OK|MB_ICONSTOP);
		return false;
	}
	if(!m_data->IsKindOf(rev,e_apl_doc_rev)) return false;
	if(rev->GetAccessmode()!=aplOWN) 
	{
		if(m_api->m_ModeInteractive)aplErrorMessage(S::NoAccessRight(),rev);
		return false;
	}
	
	if(bLoadInfo)
		LoadDocInfo(rev);

	CaplInstance *inst, *stor,*b_rev=0;
	int i,k;

	m_data->GetAttr(rev,a_apl_doc_rev_base,b_rev);
	m_data->GetAttr(rev,a_apl_doc_rev_doc,inst);
	if(inst)m_data->GetAttr(inst,a_apl_doc_active,inst);
	if(inst==rev && !delete_doc)
	{
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Активную версию нельзя удалять!"),MB_OK|MB_ICONSTOP);
		return false;
	}

	if(m_api->m_ModeInteractive && !delete_doc)
	{
		if(AfxMessageBox( APL_T("Вы действительно хотите удалить версию документа?"), MB_YESNO|MB_ICONQUESTION)!=IDYES)return false;
	}
	
	// проверяем на использование данной версии документа в событиях LSS
	aplExtent ext_events;
	if(m_api->m_ModeInteractive)
	{
		CaplEntity *pEventRefEnt = m_api->m_data.GetEntityBN(_T("apl_event_relation"));
		CaplAttr *pEventRefRev= m_api->m_data.GetAttrDefinition(pEventRefEnt, _T("obj_rev"));
		CaplAttrValue find_val_e[1];
		find_val_e[0].attr = pEventRefRev;
		find_val_e[0].value.Set(rev);

		apidata.NET_FindInstancesWithAttrValues(pEventRefEnt, 1, &find_val_e[0], ext_events, false);

		if (ext_events.GetSize())
		{
			if(AfxMessageBox( APL_T("Документ используется в событиях LSS. Всё равно удалить?"), MB_YESNO | MB_ICONQUESTION)!=IDYES)
				return false;
		}
	}

	// проверяем на использование данной версии документа в каком-либо изменении
	CaplInstance* doc;
	apidata.GetAttr(rev, m_api->m_doc_mgr.a_apl_doc_rev_doc, doc);
	aplExtent ext_changes;
	CaplAttrValue find_val[1];
	find_val[0].attr = m_api->m_change_mgr.a_avc_doc;
	find_val[0].value.Set(doc);
	
	if(bAdditionalCheck)
		apidata.NET_FindInstancesWithAttrValues(m_api->m_change_mgr.e_avc, 1, &find_val[0], ext_changes, false);
	
	if (ext_changes.GetSize())
	{
		int res;
		if(m_api->m_ModeInteractive){
			res = AfxMessageBox( APL_T("Документ используется в изменении. Всё равно удалить?"), MB_YESNO | MB_ICONQUESTION);
		}else{
			res=IDYES;
		}
		if (res == IDYES)
		{
			for (i = 0; i < ext_changes.GetSize(); i++)
			{
				aplExtent aggr;
				
				apidata.GetAttr(ext_changes[i], m_api->m_change_mgr.a_chng_item_attachment, aggr);
				for (int l = 0; l < aggr.GetSize(); l++)
				{
					apidata.NET_DeleteBlob(aggr[l], m_api->m_doc_mgr.a_apl_stored_document_source);
					apidata.DeleteInstance(aggr[i]);
				}
				
				apidata.DeleteInstance(ext_changes[i]);
			}
		}
		else
			return false;
	}
	
	// удаление основного блоба
	m_data->GetAttr(rev,a_apl_doc_rev_access_form,stor);
	if(stor&&m_data->IsKindOf(stor,e_apl_stored_document))
	{
		if(!m_data->NET_DeleteBlob(stor,a_apl_stored_document_source))
			return false;
	}
	// удаление вспомогательных блобов из публикаций
	aplExtent ext_pictures;
	m_data->GetAttr(rev,a_apl_doc_rev_pictures,ext_pictures);
	for (i = 0; i < ext_pictures.GetSize(); i++){
		if(m_data->IsKindOf(ext_pictures[i],e_apl_stored_document))
		{
			if(!m_data->NET_DeleteBlob(ext_pictures[i],a_apl_stored_document_source))
				return false;
		}else{
			ext_pictures.Remove(i);
			i--;
		}
	}
	

	if(!delete_doc)
	{
		// При удалении всего документа не меняем никакие атриюуты - чтобы потом можн было восстановить дерево из UNDO
		// Чтение последующих 
		if(rev->GetId()!=0)
		{
			CaplLoadData ld(m_data,DEF_SOURCE);
			k=ld.AddQuery(_T('b'), rev->GetId(), e_apl_doc_rev,a_apl_doc_rev_base,true);
			  ld.AddQuery(_T('d'), k, 0,a_apl_doc_rev_base, true);
			ld.LoadEx();
		}
		// замена последующих
		aplExtent ext_rev;
		m_data->GetEntityExtent(e_apl_doc_rev,ext_rev);
		for(i=0;i<ext_rev.Size;i++)
		{
			m_data->GetAttr(ext_rev[i], a_apl_doc_rev_base, inst);
			if(inst==rev)
			{ 
				if(ext_rev[i]->GetAccessmode()<=aplRW)
					m_data->PutAttr(ext_rev[i], a_apl_doc_rev_base, b_rev);
			}
		}
	}
	// удаляем статусы и характеристики объекта
	if(bAdditionalCheck)
	{
		m_api->m_appr_mgr.DeleteAllApproval(rev);
		m_api->m_charact_mgr.DeleteAllAssociatedCharacteristic(rev);
		m_api->m_doc_mgr.DeleteAssociatedEntries(rev);
	}

	// Удаление объектов
	m_data->DeleteInstance(rev);
	if (stor)
		m_data->DeleteInstance(stor);
	for (i = 0; i < ext_pictures.GetSize(); i++){
		m_data->DeleteInstance(ext_pictures[i]);
	}

	ClearAllXmlUsages( rev );
	//удаление из событий LSS
	for( int i = 0; i < ext_events.GetSize(); i++ )
		m_data->DeleteInstance( ext_events[i] );
	
	if(m_AutoSave) m_data->NET_SaveChanges();
	return true;
}
//*************************************************************
bool CaplDocManager::DeleteAssociatedEntries(CaplInstance *ciItem)
{
	int i, j;
	aplExtent aeEntries, aeItems;

	if(m_data->IsKindOf(ciItem, m_api->m_doc_mgr.e_doc))
		m_api->m_doc_mgr.LoadAllDocumentRevision(ciItem, aeItems);
	else if(m_data->IsKindOf(ciItem, m_api->m_doc_mgr.e_apl_doc_rev))
		aeItems.Add(ciItem);

	for(j=0; j<aeItems.GetSize(); j++)
	{
		aeEntries.Clear();
		m_api->m_data.GetAttr(aeItems[j], m_api->m_doc_mgr.a_apl_doc_rev_entries, aeEntries);
		for(i=0; i<aeEntries.GetSize(); i++) m_data->DeleteInstance(aeEntries[i]);
	}

	return true;
}
//*************************************************************
bool CaplDocManager::DeleteDoc(CaplInstance *doc)
{
	if(m_data==0) return false;
	if(doc==0) return false;
	if(doc==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"),MB_ICONSTOP|MB_OK);
		return false;
	}
	if(doc->GetType()==0) return false;
	if(e_doc==0) return false;
	if(!m_data->IsKindOf(doc,e_doc)) return false;

	if(doc->GetAccessmode()!=aplOWN) 
	{
		if(m_api->m_ModeInteractive)aplErrorMessage(S::NoAccessRight(),doc);
		return false;
	}
	
	if(!m_api->m_data.IsAdmin())
	{
		int opt=0;
		m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Настройка документов\\Запретить удаление документов связанных с неразрабатываемыми изделиями"),opt,0);
		if(1==opt)		
		{
			aplExtent ext_rel,ext_items;
			FindAssociatingDocuments(doc,ext_items,ext_rel);
			m_api->LoadExtentInfo(ext_items);

			bool bNoDelete=false;
			int i;
			for(i=0;i<ext_items.GetSize();i++)
			{
				CString sState;
				CaplInstance *inst=ext_items[i];
				if(m_api->m_data.IsKindOf(inst,m_api->m_prd_mgr.e_pdf))
				{
					m_api->m_data.GetAttr(inst,m_api->m_prd_mgr.a_apl_pdf_state,sState);
					if(sState!=_T("working") && sState!=_T("changing")) {bNoDelete=true; break;}
				}
				else if(m_api->m_data.IsKindOf(inst,m_api->m_change_mgr.e_chng))
				{
					m_api->m_data.GetAttr(inst,m_api->m_change_mgr.a_chng_state,sState);
					if(sState!=_T("not_applied"))  {bNoDelete=true; break;}
				}
			}

			if(bNoDelete)
			{
				if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Документ ассоциирован с уже не редактируемым изделием или пакетом изменений!\n\nУдалить документ нельзя!"),MB_ICONSTOP|MB_OK);
				return false;
			}
		}
	}
	
	if(m_api->m_ModeInteractive)
	{
		if(IDYES!=AfxMessageBox( APL_T("Вы уверены что хотите удалить документ ?"), MB_YESNO|MB_ICONQUESTION))
			return false;
	}
	aplExtent ext_rev;
	LoadAllDocumentRevision(doc,ext_rev);
	if(ext_rev.Size>1)
	{
// 		if(m_api->m_ModeInteractive)AfxMessageBox(APL_T("У документа более одной редакции !\n\n"
// 			"Удалите сначала все кроме активной."),MB_OK|MB_ICONSTOP);
		// 		return false;
		if(m_api->m_ModeInteractive)
		{
			CString str;
			GetItemName(doc,str);
			if(AfxMessageBox( APL_T("У документа ")+str+ APL_T(" более одной редакции !\n\nУдалить все редакции документа?"),
				MB_YESNO|MB_ICONQUESTION|MB_SYSTEMMODAL)==IDNO)
				return false;
		}
	}
	
	// При удалении всего документа не меняем никакие атриюуты - чтобы потом можн было восстановить дерево из UNDO
// 	CaplInstance* activeVer= NULL;
// 	m_data->GetAttr(doc, a_apl_doc_active, activeVer);	
// 	m_data->PutAttr(doc, a_apl_doc_active, (CaplInstance*)0);
	CaplInstance* Ver= NULL;
	int i;
	bool prevAutoSave = m_AutoSave;
	m_AutoSave = false;
	
	// информацию о версиях загружаем одним лоадом, а не в цикле для каждой
	LoadDocInfo(ext_rev);

	for(i=0;i<ext_rev.Size;i++)
	{
		Ver = ext_rev.GetAt(i);
		if(Ver!=0)
		{
			m_api->m_doc_mgr.DeleteAssociatedEntries(Ver);
			if(!DeleteRevision(Ver,true,false))
			{
				// При удалении всего документа не меняем никакие атриюуты - чтобы потом можн было восстановить дерево из UNDO
				//m_data->PutAttr(doc, a_apl_doc_active, activeVer);
				m_AutoSave = prevAutoSave;
				return false;
			}
		}
	}
	
	aplExtent ext;
	CaplInstance *lock;
	// Удаление блокировки
	m_data->GetAttr(doc,a_apl_doc_lock, lock);
	if(lock!=0) m_data->DeleteInstance(lock);

	// Удаление связей
	if(doc->GetId()!=0)
	{
		CaplAttrValue tst_values[1];
		aplExtent ext;
		tst_values[0].value.Set(doc);
		tst_values[0].attr=a_apl_doc_ref_doc;
		m_data->NET_FindInstancesWithAttrValues(e_apl_doc_ref,1,&tst_values[0],ext,true);
		for(i=0;i<ext.Size;i++)
			m_data->DeleteInstance(ext[i]);
	}
	//удалим ассоциации со справочником
	m_api->m_classifier_mgr.DeleteClassifierAssociation(doc,0);
	// удаляем статусы и характеристики объекта
	m_api->m_appr_mgr.DeleteAllApproval(doc);
	m_api->m_charact_mgr.DeleteAllAssociatedCharacteristic(doc);	
	// удаляю папку avred, в которой могут быть документы, полученные
	// после использования функции "красного карандаша" 
	// в плагине AutoVue (просмотр 2D/3D чертежей и моделей)
	DeleteAvred(doc);
	m_data->DeleteInstance(doc);
	m_AutoSave = prevAutoSave;
	if(m_AutoSave) m_api->SaveChanges();
	return true;
}

bool CaplDocManager::DeleteAvred(CaplInstance *doc)
{
	ASSERT(m_api);
	if(NULL == m_data) return false;
	if(NULL == doc) return false;

	aplExtent flds, docs, revs;
	if(m_api->m_folder_mgr.GetAllSubFolder(doc, flds))
	{
		CaplInstance *active;
		bool OldModeInter = m_api->m_ModeInteractive;
		m_api->m_ModeInteractive = false;
		CaplInstance* parent;
		for(int i=0; i<flds.GetSize(); i++)
		{
			m_api->m_data.GetAttr(flds[i], m_api->m_folder_mgr.a_folder_parent, parent);
			if(doc == parent)
			{
				m_api->m_folder_mgr.GetFolderContents(flds[i], docs);
				for(int j=0; j<docs.GetSize(); j++)
				{
					if(m_api->m_data.IsKindOf(docs[j], m_api->m_doc_mgr.e_doc))
					{
						m_api->m_data.GetAttr(docs[j], m_api->m_doc_mgr.a_apl_doc_active, active);
						m_api->m_doc_mgr.LoadAllDocumentRevision(docs[j], revs);
						for(int k=0; k<revs.GetSize(); k++)
						{
							if(active != revs[k]) 
								m_api->m_doc_mgr.DeleteRevision(revs[k]);
						}
						m_api->m_doc_mgr.DeleteDoc(docs[j]);
					}
				}
				m_api->m_folder_mgr.DeleteFolder(flds[i]);
			}			
		}
		m_api->m_ModeInteractive = OldModeInter;
		return true;
	}
	else
		return false;
}

bool CaplDocManager::DeleteDocHardCopy(CaplInstance *doc_copy)
{
	int i;
	if(m_data==0) return false;
	if(doc_copy==0) return false;
	if(doc_copy==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(doc_copy->GetType()==0) return false;
	if(e_doc==0) return false;

	if(doc_copy->GetAccessmode()!=aplOWN) 
	{
		if(m_api->m_ModeInteractive)aplErrorMessage(S::NoAccessRight(),doc_copy);
		return false;
	}

	if(m_api->m_ModeInteractive && IDYES!=AfxMessageBox( APL_T("Вы уверены что хотите удалить описание копии документа ?"),
		MB_YESNO|MB_ICONQUESTION)) return false;
	

	// Удаление связей
	if(doc_copy->GetId()!=0)
	{
		CaplAttrValue tst_values[1];
		aplExtent ext;
		tst_values[0].value.Set(doc_copy);
		tst_values[0].attr=a_doc_copy_rev_change_hard_copy;
		m_data->NET_FindInstancesWithAttrValues(e_doc_copy_rev_change,1,&tst_values[0],ext,true);
		for(i=0;i<ext.Size;i++)
			m_data->DeleteInstance(ext[i]);
	
		ext.Clear();
		tst_values[0].value.Set(doc_copy);
		tst_values[0].attr=a_doc_copy_owner_change_hard_copy;
		m_data->NET_FindInstancesWithAttrValues(e_doc_copy_owner_change,1,&tst_values[0],ext,true);
		for(i=0;i<ext.Size;i++)
			m_data->DeleteInstance(ext[i]);
	}
	//удалим ассоциации со справочником
	m_api->m_classifier_mgr.DeleteClassifierAssociation(doc_copy,0);
	// удаляем статусы и характеристики объекта
	m_api->m_appr_mgr.DeleteAllApproval(doc_copy);
	m_api->m_charact_mgr.DeleteAllAssociatedCharacteristic(doc_copy);
	
	m_data->DeleteInstance(doc_copy);
	if(m_AutoSave) m_data->NET_SaveChanges();
	return true;
}

bool CaplDocManager::ApplyHardCopyRevChanges(CaplInstance *doc_copy,CaplInstance *author,CaplInstance *doc_change,const TCHAR *apply_date)
{
	if(m_data==0) return false;
	if(doc_copy==0) return false;
	if(doc_copy==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(doc_copy->GetType()==0) return false;
	if(e_doc==0) return false;

	if(doc_copy->GetAccessmode()>aplRW) 
	{
		if(m_api->m_ModeInteractive)aplErrorMessage(S::NoAccessRight(),doc_copy);
		return false;
	}
	if(!author)
	{
		author=GetCurrentPerson();
		if(!author)
		{
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Для текущего пользователя не указан сотрудник"),MB_OK|MB_ICONSTOP);
			return false;
		}
	}
	CString apply_date_s=apply_date;
	if(apply_date_s==_T(""))
	{
		COleDateTime dt=COleDateTime::GetCurrentTime();
		aplDate2String(dt,apply_date_s);
	}
	CaplInstance *doc=0,*doc_act_ver=0;
	m_api->m_data.GetAttr(doc_copy,a_doc_copy_doc,doc);
	if(doc) 
	{
		m_api->m_data.GetAttr(doc,a_apl_doc_active,doc_act_ver);
		if(!doc_change)
		{
			CaplInstance *doc=0,*doc_act_ver=0;
			m_api->m_data.GetAttr(doc_copy,a_doc_copy_doc,doc);
			if(doc) 
			{
				m_api->m_data.GetAttr(doc,a_apl_doc_active,doc_act_ver);
				aplExtent ext_changes;
				m_api->m_change_mgr.GetAllChanges(doc, ext_changes);
				for(int i=0;ext_changes.GetSize();i++)
				{
					CaplInstance* rev;
					m_api->m_data.GetAttr(ext_changes[i], m_api->m_change_mgr.a_avc_new_rev, rev);
					if(rev==doc_act_ver)
					{
						doc_change=ext_changes[i];
						break;
					}
				}
			}
		}
	}
	m_api->m_data.PutAttr(doc_copy,a_doc_copy_cur_rev,doc_act_ver);
	m_api->m_data.PutAttr(doc_copy,a_doc_copy_last_update,apply_date_s);	
	CaplInstance *doc_copy_rev_change=m_api->m_data.CreateInstance(e_doc_copy_rev_change);
	if(doc_copy_rev_change)
	{
		if(doc_change) m_api->m_data.PutAttr(doc_copy_rev_change,a_doc_copy_rev_change_doc_change,doc_change);
		m_api->m_data.PutAttr(doc_copy_rev_change,a_doc_copy_rev_change_author,author);
		m_api->m_data.PutAttr(doc_copy_rev_change,a_doc_copy_rev_change_apply_date,apply_date_s);
		m_api->m_data.PutAttr(doc_copy_rev_change,a_doc_copy_rev_change_hard_copy,doc_copy);
	}
	if(m_AutoSave) m_data->NET_SaveChanges();
	return true;
}

bool CaplDocManager::SelectApp(const TCHAR *file, CString &app)
{
	app=_T("");
	CSelectAppDlg dlg;
	dlg.m_file_name=file;
	if(dlg.DoModal()!=IDOK) return false;
	app=dlg.m_App;
	return true;
}
//*************************************************************
CaplInstance* CaplDocManager::SelectDocType(CaplInstance *selected_doc_type,CaplInstance *selected_group,bool m_show_all_types, bool b_select_group)
{

	CaplInstance *person = m_api->m_appr_mgr.GetCurrentPerson();
	if(person==0)
	{
		AfxMessageBox( APL_T("С пользователем не ассоциирован сотрудник!\n\n Выбор вида документа невозможен."));
		return 0;
	}
	aplExtent ext;
	m_api->m_data.GetAttrBN(person,_T("apl_person_roles"),ext);
	if(ext.GetSize()==0)
	{
		AfxMessageBox( APL_T("Для текущего сотрудника не задана ни одна роль!\n\n Выбор вида документа невозможен."));
		return 0;
	}

	CaplSetResourceHandle setres(module_inst);
	CChoose_inst_dlg dlg;
	dlg.m_api= m_api;
	dlg.header= APL_T("Выбор вида документа");
	dlg.e_group=e_dt_group;
	dlg.a_group_id=a_dt_group_id;
	dlg.a_group_name=a_dt_group_name;
	dlg.a_group_description=a_dt_group_descr;
	dlg.a_group_content=a_dt_group_content;
	dlg.a_group_parent=a_dt_group_par;
	dlg.e_elem=e_dt;
	dlg.m_show_all_types=m_show_all_types;
	dlg.m_bSelectGroup=b_select_group;

	dlg.selected_element=selected_doc_type;

	static CaplInstance *global_selected_group=0;
	if(selected_group!=0) dlg.selected_group=selected_group;
	else
	{
		if(global_selected_group!=0) dlg.selected_group=global_selected_group;
	}

	dlg.tmp.header= APL_T("Код");
	dlg.tmp.function_type=0;
	dlg.tmp.attr=a_dt_id;
	dlg.tmp.second_attr=0;
	dlg.tmp.width=80;
	dlg.elements.Add(dlg.tmp);

	dlg.tmp.header= APL_T("Наименование");
	dlg.tmp.function_type=0;
	dlg.tmp.attr=a_dt_pdt;
	dlg.tmp.second_attr=0;
	dlg.tmp.width=300;
	dlg.elements.Add(dlg.tmp);
	
	if(m_sel_doc_types_names.GetSize()>0)
	{
		dlg.m_attr_for_def=a_dt_pdt;
		dlg.m_default_names=&m_sel_doc_types_names;
	}

	int ret=dlg.DoModal();

	global_selected_group=dlg.selected_group;

	if(ret!=IDOK)return 0;
	
	if(b_select_group) return dlg.selected_group;
	
	return dlg.GetChosenElement();
	
}

void CaplDocManager_GetAllSubGroup(CaplAPI *m_api, aplExtent &ext_groups, CaplInstance *group, aplExtent &ext_all_subgroup)
{
	if(0==m_api || 0==group) return;
	int i;
	CaplInstance *inst;
	for(i=0;i<ext_groups.GetSize();i++)
	{
		CaplInstance *group_i=ext_groups[i];
		m_api->m_data.GetAttr(group_i,m_api->m_doc_mgr.a_dt_group_par,inst);
		if(inst==group)CaplDocManager_GetAllSubGroup(m_api,ext_groups,group_i,ext_all_subgroup);
	}
	ext_all_subgroup.Add(group);
}
//*************************************************************
bool CaplDocManager::GetAllDocTypeInGroup(CaplInstance *group, aplExtent &ext_dt, bool bRecursive)
{
	ext_dt.Clear();
	if(0==group) return true;
	if(0==m_api) return false;

	aplExtent ext_all_group,ext_group;
	m_api->m_data.GetEntityExtent(m_api->m_doc_mgr.e_dt_group,ext_all_group);
	CaplDocManager_GetAllSubGroup(m_api,ext_all_group,group,ext_group);

	int i;
	aplExtent ext1;
	for(i=0;i<ext_group.GetSize();i++)
	{
		m_api->m_data.GetAttr(ext_group[i],m_api->m_doc_mgr.a_dt_group_content,ext1);
		ext_dt.Append(ext1);
	}
	return true;
}
//*************************************************************
CaplInstance *CaplDocManager::CreateDocumentByDot(CaplInstance *i_doc, CaplInstance *inst)
{
	if(inst==0 || i_doc==0)
	{
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен 0!"));;
		return 0;
	}

	if(inst->GetAccessmode()>aplRW || i_doc->GetAccessmode()>aplRO)
	{
		if(m_api->m_ModeInteractive)aplErrorMessage(S::NoAccessRight(),inst);
		return 0;
	}
	CString tmp_path, tmp; 
	aplGetTempPath(tmp_path);
	CString doc_id= _T(""), name = _T(""), doc_name=_T(""), doc_descr=_T("");
				
	GetFileName(i_doc, name);
	tmp_path+=name;
	LoadRevision(i_doc, tmp_path);
		 		
	CaplInstance *doc_kind=0;
	m_data->GetAttr(i_doc, a_doc_id, doc_id);
	m_data->GetAttr(i_doc, a_doc_name, doc_name);
	m_data->GetAttr(i_doc, a_doc_descr, doc_descr);
	m_data->GetAttr(i_doc, a_doc_kind, doc_kind);

	CString sFormat;
	CaplInstance *doc_rev;
	m_data->GetAttr(i_doc, a_apl_doc_active, doc_rev);
	if(0!=doc_rev)
	{
		m_data->GetAttr(doc_rev, a_apl_doc_rev_format, sFormat);
	}

	if(inst!=0)
	{
		CString buf;
		m_api->GetItemName(inst,buf);
		if(buf!=_T(""))
		{
			doc_id+=_T(" ");
			doc_id+=buf;
		}
	}

	return CreateDocument(doc_id, doc_name, doc_descr, doc_kind, tmp_path, true, inst,0,APL_DOCUMENT_RELATION,true,true,LPCTSTR(sFormat));
}
//*************************************************************
CaplInstance* CaplDocManager::IsDependenceDocument(CaplInstance *doc, aplExtent *docs, aplExtent *ref)
{
	aplExtent trel, tref;
	FindDependenceDocuments(doc, trel, tref);
	CaplInstance *rez = NULL;
	if(tref.Size>0)
		m_data->GetAttr(tref[0],a_apl_doc_ref_doc, rez);
	if(docs!=0)
	{
		docs->Clear();
		docs->Append(trel);
	}
	if(ref!=0)
	{
		ref->Clear();
		ref->Append(tref);
	}
	return rez;
}
//*************************************************************
bool CaplDocManager::FindDependenceDocuments(CaplInstance *doc, aplExtent &docs, aplExtent&ref)
{
	ref.Clear();
	docs.Clear();

	if(m_data==0)return false;
	if(!m_data->IsConnected()) return false;
	CaplLoadData ld(m_data,DEF_SOURCE);
	if(doc==0) return false;
	if(doc==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}

	int a = ld.AddQuery(_T('b'), doc->GetId(), e_apl_doc_ref, a_apl_doc_ref_item,true,true);
	int b = ld.AddQuery(_T('b'), doc->GetId(), e_apl_doc_ref, a_apl_doc_ref_doc,true,true);
//			ld.AddQuery(_T('d'), a, 0, a_apl_doc_ref_item, true);
//			ld.AddQuery(_T('d'), a, 0, a_apl_doc_ref_doc, true);
//			ld.AddQuery(_T('d'), a, 0, a_apl_doc_ref_type, true);

	ld.LoadEx();
	aplExtent ext;
	m_data->GetEntityExtent(e_apl_doc_ref,ext);
	CaplInstance *tmp;
	bool isdoc = true;
	CString type;
	for(int i=0;i<ext.Size;i++)
	{
		m_data->GetAttr(ext[i],a_apl_doc_ref_type,type);
		if(type!=APL_DOC_DEPENDENCE) continue;
		m_data->GetAttr(ext[i],a_apl_doc_ref_item,tmp);
		if(tmp==doc) 
		{
			m_data->GetAttr(ext[i],a_apl_doc_ref_doc,tmp);
			if(!tmp) continue;
			ref.Add(ext[i]);
			docs.Add(tmp);
		}
		else
		{
			m_data->GetAttr(ext[i],a_apl_doc_ref_doc,tmp);
			if(tmp==doc) 
			{
				m_data->GetAttr(ext[i],a_apl_doc_ref_item,tmp);
				if(!tmp) continue;
				ref.Add(ext[i]);
				docs.Add(tmp);
			}
		}
	}
	return true;
}
//*************************************************************
bool CaplDocManager::CheckOutEx(CaplInstance *doc_or_revision, const TCHAR *path, bool bAlwaysShowDlg /* =false */, bool bUseSubDoc /* =false */, bool bIgnoreState/* = false*/)
{
	if(m_data==0) return false;
	if(doc_or_revision==0) return false;
	if(doc_or_revision==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(doc_or_revision->GetType()==0) return false;
	if(e_doc==0) return false;

	CaplInstance *doc=0; CaplInstance* doccc_rev;
	if(m_data->IsKindOf(doc_or_revision,e_doc))
	{
		doc = doc_or_revision;
		m_api->m_data.GetAttr(doc, a_apl_doc_active, doccc_rev);
	}
	else if(m_data->IsKindOf(doc_or_revision, e_apl_doc_rev))
	{
		m_data->GetAttr(doc_or_revision,a_apl_doc_rev_doc, doc);
		doccc_rev= doc_or_revision;
	}
	aplExtent rel, ref;

	if(doc==0) return false;
	if(doccc_rev==0) return false;
	
	/*Определение: зависимый документ или нет*/
	CaplInstance *parent = IsDependenceDocument(doc);/*Всегда возвращает parent и для doc исходного, и для doc зависимого документа*/
	/*Если parent ноль, тогда вызываем обработку для одного документа*/
	if(!parent) return CheckOut(doc_or_revision, path, bAlwaysShowDlg, bUseSubDoc,bIgnoreState);
//	if(parent!=doc) return CheckOut(doc_or_revision, path, bAlwaysShowDlg, bUseSubDoc,bIgnoreState);
	if(m_api->m_ModeInteractive)
	{
		if(parent==doc)//обрабатывается исходный документа
		{
			if(AfxMessageBox( APL_T("Документ является исходным. Взять его и все зависимые документы на редактирование?"),MB_YESNO|MB_ICONQUESTION)==IDNO) return false;
		}
		else //if(parent!=doc)// обрабатывается зависимый документ
		{
			if(parent->GetAccessmode()>aplRW) 	{  AfxMessageBox( APL_T("Нет доступа к зависимому документу!"),MB_OK|MB_ICONSTOP); return false;}
			if(AfxMessageBox( APL_T("Документ является зависимым. Взять его и исходный документ на редактирование?"),MB_YESNO|MB_ICONQUESTION)==IDNO) return false;
		}
	}
	if(!FindDependenceDocuments(parent,rel, ref)) return false;
	
	CaplInstance *active=0, *lock=0;
	/* Нулевой документ должен соответствовать path, иначе жопа 
		Раньше было пихание parent в нулевой индекс*/
	rel.Remove(rel.Find(doc));
	if(rel.GetSize())
		lock = rel.GetAt(0);
	rel.SetAt(0,doc);
	if(lock)
		rel.Add(lock);
	rel.Add(parent);

	LoadDocInfo(rel);
	bool res = true;
	CString edit_path=_T(""), file_name=_T(""), tmp;
	int i;

	/*Проверка можно или нет взять на редактирование все документы*/
	for(i=0; i<rel.GetSize(); i++)
		if(CheckForCheckOut(rel[i]))
			return false;

	CaplInstance* parent_ver;
	CaplAttrValue find_val[2];
	aplExtent extSVer;

	if(parent==doc) parent_ver= doccc_rev;
	else m_api->m_data.GetAttr(doccc_rev, a_apl_doc_rev_src_doc_ver, parent_ver);
	
	if(parent_ver)
	{
		find_val[0].attr= a_apl_doc_rev_src_doc_ver;
		find_val[0].value.Set(parent_ver);
		find_val[1].attr= a_apl_doc_rev_doc;

		m_api->m_data.NET_FindInstancesWithAttrValues(e_apl_digital_document, 1, &find_val[0], extSVer, false);
		if(parent_ver && !parent_ver->attrs)
			extSVer.Add(doccc_rev);
	}

	if(extSVer.GetSize())
		LoadDocInfo(extSVer);

	bool old = m_api->m_ModeInteractive;
	bool bShowDlg;
	
	//В начале передаем путь, который пришел в функцию
	tmp= path;

	for(i=0; i<rel.Size; i++)
	{
		if(rel[i]==NULL) continue;
		m_data->GetAttr(rel[i], a_apl_doc_lock, lock);
		if(lock!=NULL) continue;
		
		//Берем все документы в папку, в которую взяли первый документ
		if(edit_path!=_T(""))
		{
			m_data->GetAttr(rel[i],a_apl_doc_active,active);
			CaplInstance *af=0;
			if(active!=0)
			{
				m_data->GetAttr(active,a_apl_doc_rev_access_form, af);
				if(af!=0)
				{
					if(m_data->IsKindOf(af,e_apl_stored_document))
						m_data->GetAttr(af,a_apl_stored_document_file_name, file_name);
					else if(m_data->IsKindOf(af,e_apl_assigned_document))
						m_data->GetAttr(af,a_apl_assigned_document_location_path, file_name);
					if(file_name!=_T(""))
					{
						file_name = file_name.Right(file_name.GetLength()-file_name.ReverseFind(_T('\\'))-1);
						tmp= edit_path+file_name;
					}
				}
			}
		}

		/*Если обломилось что-то внутри, отменяем редактирование для всех*/
		CaplInstance *ciInstForCheckOut = rel[i];
		if(ciInstForCheckOut == doc) ciInstForCheckOut = doc_or_revision; // ???
		if(parent_ver)
		{
			if(rel[i]!=parent)
			{
				find_val[1].value.Set(rel[i]);
				m_api->m_data.FindInstancesWithAttrValuesInLocalCache(e_apl_digital_document, NULL, 2, &find_val[0], extSVer, false, false, false);
				if(extSVer.GetSize())
					ciInstForCheckOut= extSVer[0];
			}
			else
			{
				ciInstForCheckOut= parent_ver;
			}
		}
		
		/*Первый раз показываем диалог*/
		if(i==0) bShowDlg= bAlwaysShowDlg;
		else bShowDlg= false;

		if(!CheckOut(ciInstForCheckOut, tmp, bShowDlg, false, bIgnoreState))
		{
			CString sName;
			m_api->GetItemName(rel[i], sName);
			
			if(i!=0)
				AfxMessageBox( APL_T("Возникла ошибка при взятии документа \"")+sName+ APL_T("\" на редактирование. Редактирование документов отменено."), MB_OK|MB_ICONERROR);

			for(i=i-1;i>=0;i--)
				UndoCheckOut(rel[i],false,bIgnoreState);

			m_api->m_ModeInteractive = old;
			return false;
		}

		//Определяем путь, куда взяли первый документ
		if(edit_path==_T(""))
		{
			m_data->GetAttr(rel[i],a_apl_doc_lock,lock);
			if(lock==0)
				continue;

			m_data->GetAttr(lock,a_apl_doc_rev_edit_path, edit_path);
			edit_path = edit_path.Left(edit_path.ReverseFind(_T('\\'))+1);
		}

		if(0==i)m_api->m_ModeInteractive = false;
	}	
	m_api->m_ModeInteractive = old;
	return res;
}
//*************************************************************
bool CaplDocManager::CheckInEx(CaplInstance *doc, const TCHAR *path, bool set_active/* =false */, bool bAlwaysShowDlg/* =false */, bool bUseSubDoc/* =false */, bool bIgnoreState/* = false*/)
{
	aplExtent rel, ref;
	CaplInstance *parent = IsDependenceDocument(doc);/*Всегда возвращает parent и для doc исходного, и для doc зависимого документа*/
//	if(parent!=doc) return CheckIn(doc, path, set_active, bAlwaysShowDlg, bUseSubDoc,bIgnoreState);
	if(!parent) return CheckIn(doc, path, set_active, bAlwaysShowDlg, bUseSubDoc,bIgnoreState);
	if(!FindDependenceDocuments(parent,rel, ref)) return false;
	
	CaplInstance *lock=0, *active=0, *inst_rev;
	CString edit_path;
	int crc1, crc2;

	m_data->GetAttr(parent,a_apl_doc_lock, lock);
	if(lock==0) return false;
	m_data->GetAttr(lock,a_apl_doc_rev_edit_path, edit_path);
	if(edit_path.IsEmpty()) return false;
	crc1 = GetFileCRC32(edit_path);
//	m_data->GetAttr(parent,a_apl_doc_active, active);
	m_data->GetAttr(lock, a_apl_doc_rev_base, active);

	inst_rev = rel.GetAt(0);
	rel.SetAt(0,parent);
	rel.Add(inst_rev);
	bool change = TestOnChange(rel);
	
	m_data->GetAttr(active,a_apl_doc_rev_crc, crc2);
	if(crc1==crc2 && !change)
	{
		if(m_api->m_ModeInteractive)
			if(AfxMessageBox( APL_T("Исходный документ не изменился. Отменить редактирование?"),MB_YESNO|MB_ICONQUESTION)==IDNO) return false;
		return UndoCheckOutEx(doc,false,bIgnoreState);
	}
	if(m_api->m_ModeInteractive)
		if(AfxMessageBox( APL_T("Завершить редактирование исходного и всех зависимых документов?"),MB_YESNO|MB_ICONQUESTION)==IDNO) return false;
	if(!change)
	{
		if(m_api->m_ModeInteractive)
			if(AfxMessageBox( APL_T("Один из зависимых документов не изменился. Создать промежуточную версию исходного документа?"),MB_YESNO|MB_ICONQUESTION)==IDNO) return false;

		bool old_ModeInteractive = m_api->m_ModeInteractive;
		m_api->m_ModeInteractive = false;

		CheckIn(parent,edit_path,bIgnoreState);
		CheckOut(lock,edit_path,bIgnoreState);

		m_api->m_ModeInteractive = old_ModeInteractive;
		return true;
	}
	bool old = m_api->m_ModeInteractive;
	m_api->m_ModeInteractive = false;

	LoadDocInfo(rel);

	CaplInstance* parent_rev;//Версия исходного документа
	m_api->m_data.GetAttr(parent, a_apl_doc_lock, parent_rev);
	
	bool bOldAutoSave= m_api->m_AutoSave;
	m_api->SetAutoSave(false);

	bool res = true;
	edit_path = _T("");
	for(int i=0; i<rel.Size; i++)
	{
		m_data->GetAttr(rel[i],a_apl_doc_lock,lock);
		if(lock==0) continue;
		m_data->GetAttr(lock,a_apl_doc_rev_edit_path, edit_path);
		
		if(!CheckIn(rel[i],edit_path,set_active,i==0,bUseSubDoc,bIgnoreState))
		{
			if(i==0)/*В диалоге можно нажать Отмена, тогда ничего не делаем*/
			{
				m_api->m_ModeInteractive = old;
				m_api->SetAutoSave(bOldAutoSave);
				return false;
			}
			else 
			{
				AfxMessageBox( APL_T("Возникли ошибки при сохранении файла \"")+edit_path+_T("\"."), MB_ICONERROR|MB_OK);
			}
		}
		
		/*Связываем версии исходного и зависимого документа*/
		if(lock!=parent_rev)
		{
			if(lock->GetType() && parent_rev->GetType())
				m_api->m_data.PutAttr(lock, a_apl_doc_rev_src_doc_ver, parent_rev);
		}

		set_active = (APL_SETACTIVEVER==GetLastFlag());
	}
	m_api->SetAutoSave(bOldAutoSave);
	m_api->m_ModeInteractive = old;
	m_api->SaveChanges();
	return res;
}
//*************************************************************
bool CaplDocManager::UndoCheckOutEx(CaplInstance *doc, bool bUseSubDoc/* =false */, bool bIgnoreState/* = false*/)
{
	aplExtent rel, ref;
	CaplInstance *parent = IsDependenceDocument(doc);/*Всегда возвращает parent и для doc исходного, и для doc зависимого документа*/
	if(!parent) return UndoCheckOut(doc,bUseSubDoc,bIgnoreState);
//	if(parent!=doc) return UndoCheckOut(doc,bUseSubDoc,bIgnoreState);
	if(m_api->m_ModeInteractive)
	{
		if(doc==parent)
		{	
			if(AfxMessageBox( APL_T("Документ является исходным. Завершить редактирование исходного и всех зависимых документов?"),MB_YESNO|MB_ICONQUESTION)==IDNO) return false;
		}
		else //if(doc!=parent)
		{
			if(AfxMessageBox( APL_T("Документ является зависимым. Завершить редактирование исходного и всех зависимых документов?"),MB_YESNO|MB_ICONQUESTION)==IDNO) return false;
		}
	}
	if(!FindDependenceDocuments(parent,rel, ref)) return false;
	bool old = m_api->m_ModeInteractive;
	m_api->m_ModeInteractive = false;
	rel.Add(parent);
	bool res = true;
	for(int i=0; i<rel.Size; i++)
		UndoCheckOut(rel[i],false,bIgnoreState);
	m_api->m_ModeInteractive = old;
	return res;
}
//*************************************************************
bool CaplDocManager::TestOnChange(aplExtent &deps)
{
	CaplInstance *lock, *base;
	CString path;
	int crc1, crc2;
	bool bChange= true;
	for(int i=0; i<deps.Size && bChange;i++)
	{
		if(deps[i]->GetAccessmode()>aplRO)
			continue;
		m_data->GetAttr(deps[i],a_apl_doc_lock, lock);
		if(lock==0) continue;
		m_data->GetAttr(lock,a_apl_doc_rev_edit_path,path);
		if(path==_T("")) continue;
		crc1 = GetFileCRC32(path);
//		m_data->GetAttr(deps[i],a_apl_doc_active, lock);/*Документ может быть взят на редактирование не с активной версии*/
		m_data->GetAttr(lock, a_apl_doc_rev_base, base);
		m_data->GetAttr(base,a_apl_doc_rev_crc, crc2);
		if(crc2==crc1) bChange&= false;
	}
	return bChange;
}
//*************************************************************
bool CaplDocManager::GetAllPurchaseOrder(aplExtent &subItems, bool bLoadFromBase)
{
	if(!m_data->IsConnected()) return false;
	CString sSql, t_str;
	
	if(bLoadFromBase)
	{
		sSql = _T("SELECT Ext_1 FROM Ext_1 { apl_hardcopy_purchase_order.id LIKE '' } END_SELECT");
		if(m_data->NET_QueryEditParse(sSql, false, &t_str) == false) return false;
		m_data->NET_QueryExecute(subItems);
	}
	else
	{
		m_data->GetEntityExtent(m_api->m_doc_mgr.e_doc_copy_order, subItems);
	}
	
	m_api->LoadExtentInfo(subItems);
	return true;
}
//*************************************************************
BOOL CaplDocManager::GetLastFlag()
{
	BOOL res = m_lastflag;
	m_lastflag=0;
	return res;
}

//*************************************************************
CaplInstance *CaplDocManager::CreateDocumentHardCopy(CaplInstance *doc,const TCHAR *id,CaplInstance *owner,CaplInstance *place_of_use,const TCHAR *basis,const TCHAR *issue_date,bool b_show_dlg)
{
	CaplInstance *created_doc_copy=0;
	if(!b_show_dlg)
	{
		if(id)
		{
			//проверка уникальности id
			CaplAttrValue tst_values[2];               
			tst_values[0].value.Set((LPCTSTR)id); 
			tst_values[0].attr=a_doc_copy_id;      
			tst_values[1].value.Set(doc); 
			tst_values[1].attr=a_doc_copy_doc; 
			aplExtent ext_doc_copy_inst;
			m_data->NET_FindInstancesWithAttrValues(e_doc_copy,2,&tst_values[0],ext_doc_copy_inst,false);
			if(ext_doc_copy_inst.GetSize())
			{
				AfxMessageBox( APL_T("Копия документа с таким номером уже есть в базе !!!"));
				b_show_dlg=true;
			}
		}
		else
		{
			AfxMessageBox( APL_T("Номер копии документа не задан!"));
			b_show_dlg=true;
		}
	}
	if(b_show_dlg)
	{
		CaplSetResourceHandle setres(module_inst);

		CHardCopyDlg dlg;
		dlg.m_api=m_api;
		dlg.m_copy_id=id;
		dlg.m_doc=doc;
		dlg.m_owner=owner;
		dlg.m_place_of_use=place_of_use;
		dlg.m_copy_basis=basis;
		CString buf=issue_date;
		aplString2Date(buf,dlg.m_issue_date);
		if(dlg.DoModal()==IDOK)
		{
			created_doc_copy=dlg.m_doc_copy;
		}
	}
	else
	{
		// создаем копию врчуную
		created_doc_copy=m_api->m_data.CreateInstance(m_api->m_doc_mgr.e_doc_copy);
		CaplInstance *ciActRev = NULL;
		
		if(created_doc_copy && doc)
		{
			m_api->m_data.GetAttr(doc, m_api->m_doc_mgr.a_apl_doc_active ,ciActRev);

			m_api->m_data.PutAttr(created_doc_copy,m_api->m_doc_mgr.a_doc_copy_doc,doc);	
			m_api->m_data.PutAttr(created_doc_copy,m_api->m_doc_mgr.a_doc_copy_first_rev,ciActRev);	
			m_api->m_data.PutAttr(created_doc_copy,m_api->m_doc_mgr.a_doc_copy_issue_date,issue_date);	
						
			m_api->m_data.PutAttr(created_doc_copy,m_api->m_doc_mgr.a_doc_copy_id,id);	
			m_api->m_data.PutAttr(created_doc_copy,m_api->m_doc_mgr.a_doc_copy_state,_T(""));
			
			m_api->m_data.PutAttr(created_doc_copy,m_api->m_doc_mgr.a_doc_copy_cur_rev,ciActRev);
			m_api->m_data.PutAttr(created_doc_copy,m_api->m_doc_mgr.a_doc_copy_last_update,issue_date);											
		}
	}
	if(m_AutoSave) m_api->SaveChanges();
	if(created_doc_copy && m_AutoUsurpire)
	{
		int AutoUzurpire;
		m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Автоматически становиться владельцем\\Автоматически становиться владельцем создаваемых документов"),AutoUzurpire,0);
		if(AutoUzurpire==1) 
		{
			if(!m_AutoSave) m_api->SaveChanges();
			aplExtent ext; ext.Add(created_doc_copy);
			m_data->NET_BecomeInstancesOwner(&ext);
		}
	}
		
	return created_doc_copy;
}

bool CaplDocManager::ShowDocCopyProperties(CaplInstance *doc_copy)
{
	bool b_result=false;

	CaplSetResourceHandle setres(module_inst);

	CHardCopyDlg dlg;
	dlg.m_api=m_api;
	dlg.m_doc_copy=doc_copy;
	if(dlg.DoModal()==IDOK)
	{
		if(m_AutoSave) m_api->SaveChanges();
		b_result=true;
	}
	return b_result;
}

void CaplDocManager::ShowAllDocCopyes(CDocCopyFilter *filter)
{
	CaplSetResourceHandle setres(module_inst);

	CShowDocCopyesDlg dlg;
	dlg.m_api=m_api;
	dlg.m_filter=filter;
	dlg.DoModal();

	if(m_AutoSave) 
		m_api->SaveChanges();
}

bool CaplDocManager::ShowHardCopyRevChanges(CaplInstance *doc_copy)
{
	if(!doc_copy) return false;
	if(!doc_copy->GetType()) return false;
	if(doc_copy->GetAccessmode()>aplRO) 
	{
		if(m_api->m_ModeInteractive)aplErrorMessage(S::NoAccessRight(),doc_copy);
		return false;
	}
	
	CaplSetResourceHandle setres(module_inst);

	CHardCopyHistoryDlg dlg;
	dlg.m_api=m_api;
	dlg.m_doc_copy=doc_copy;
	dlg.m_mode=APL_SHOW_REV_HISTORY;
	dlg.DoModal();

	return true;
}

bool CaplDocManager::ShowCardAccount( CaplInstance *pDocument, bool bReadOnly )
{
	if(NULL == pDocument) return false;
	if(NULL == m_api) return false;
	if(false == m_api->m_data.IsConnected()) return false;

	HINSTANCE hDllKvzArchive = NULL;
	hDllKvzArchive = AfxLoadLibrary(_T("KVZARMArchive.dll"));

	bool (*fnShowCardAccount) (CaplAPI*, CaplInstance*) = NULL;
	if(hDllKvzArchive)
	{
		(FARPROC&)fnShowCardAccount = ::GetProcAddress(hDllKvzArchive, "ShowCardAccountGlobal");
		if (NULL == fnShowCardAccount)
		{
			AfxMessageBox(APL_T("Не найдена библиотека KVZARMArchive.dll!"), MB_ICONWARNING);	
		}
		else
		{
			return fnShowCardAccount(m_api, pDocument);
		}
	}

	return false;
}

bool CaplDocManager::ShowHardCopyOwnerChanges(CaplInstance *doc_copy)
{
	if(!doc_copy) return false;
	if(!doc_copy->GetType()) return false;
	if(doc_copy->GetAccessmode()>aplRO) 
	{
		if(m_api->m_ModeInteractive)aplErrorMessage(S::NoAccessRight(),doc_copy);
		return false;
	}
	
	CaplSetResourceHandle setres(module_inst);

	CHardCopyHistoryDlg dlg;
	dlg.m_api=m_api;
	dlg.m_doc_copy=doc_copy;
	dlg.m_mode=APL_SHOW_OWNER_HISTORY;
	dlg.DoModal();
	return true;
}

int CaplDocManager::GetNextHardCopyNumber(CaplInstance *doc)
{
	if(!doc) return -1;
	if(!doc->GetType()) return -1;
	if(doc->GetAccessmode()>aplRO) 
	{
		if(m_api->m_ModeInteractive)aplErrorMessage(S::NoAccessRight(),doc);
		return -1;
	}
	aplExtent ext_copyes;
	FindHardCopyes(ext_copyes,0,doc);
	int num,max_num=0;
	CString buf;
	for(int i=0;i<ext_copyes.GetSize();i++)
	{
		m_api->m_data.GetAttr(ext_copyes[i],a_doc_copy_id,buf);
		num=_atoi(buf);
		if(num>max_num) max_num=num;
	}
	return max_num+1;
}

bool GetMatch(CStringArray *saArray, CString sValue)
{
	for(int i=0; i<saArray->GetSize(); i++)
		if(saArray->GetAt(i) == sValue) return true;

	return false;
}

void FindAssociationBetweenRoleAndStatus(CString sStatus, CString sRole, CString sDateTime, CString &sStatusName, CString &sTmp)
{
	//					Таблица возможных подписей

	CaplMap caAll;

	CStringArray saArchivAppr, saArchiv;			
	saArchivAppr.Add( APL_T("принято")); 
	saArchiv.Add( APL_T("архивариус")); saArchiv.Add(_T("ApprAndDate"));
	caAll.Add((long)&saArchivAppr, (long)&saArchiv);
	
	CStringArray saArchivApprForChange, saArchivChng;
	saArchivApprForChange.Add( APL_T("выполнено"));
	saArchivChng.Add( APL_T("архивариус")); saArchivChng.Add(_T("Change"));
	caAll.Add((long)&saArchivApprForChange, (long)&saArchivChng);

	CStringArray saArchiveCopyAppr, saArchiveCopy;
	saArchiveCopyAppr.Add( APL_T("выполнено")); 
	saArchiveCopy.Add( APL_T("архивариус копий")); saArchiveCopy.Add(_T("Copy"));
	caAll.Add((long)&saArchiveCopyAppr, (long)&saArchiveCopy);

	CStringArray saTechnologAppr, saTechnolog;
	saTechnologAppr.Add( APL_T("техконтроль проведен")); 
	saTechnolog.Add( APL_T("технолог")); saTechnolog.Add(_T("TekhControl"));
	caAll.Add((long)&saTechnologAppr, (long)&saTechnolog);

	CStringArray saNormoKontrAppr, saNormoKontr;
	saNormoKontrAppr.Add( APL_T("нормоконтроль проведен"));
	saNormoKontr.Add( APL_T("нормоконтролер")); saNormoKontr.Add(_T("NormControl"));
	caAll.Add((long)&saNormoKontrAppr, (long)&saNormoKontr);

	CStringArray saMetrologAppr, saMetrolog;
	saMetrologAppr.Add( APL_T("метрконтроль проведен")); 
	saMetrolog.Add( APL_T("метролог")); saMetrolog.Add(_T("MetrControl"));
	caAll.Add((long)&saMetrologAppr, (long)&saMetrolog);

	CStringArray saKonstruktorAppr, saKonstruktor;
	saKonstruktorAppr.Add( APL_T("разработано"));
	saKonstruktor.Add( APL_T("конструктор")); saKonstruktor.Add( APL_T("разработчик")); saKonstruktor.Add(_T("Develop"));
	caAll.Add((long)&saKonstruktorAppr, (long)&saKonstruktor);

	CStringArray saRukovoditelAppr, saRukovoditel;
	saRukovoditelAppr.Add( APL_T("разработано"));  saRukovoditelAppr.Add( APL_T("утверждено")); saRukovoditelAppr.Add( APL_T("проверено")); 
	saRukovoditel.Add( APL_T("руководитель подразделения")); saRukovoditel.Add( APL_T("ведущий по заказу")); saRukovoditel.Add( APL_T("ведущий конструктор")); saRukovoditel.Add(_T("Approved"));
	caAll.Add((long)&saRukovoditelAppr, (long)&saRukovoditel);
	
	CStringArray saReliabAppr, saReliab;
	saReliabAppr.Add( APL_T("согласовано"));
	saReliab.Add( APL_T("расчетчик надежности")); saReliab.Add(_T("Reliab"));
	caAll.Add((long)&saReliabAppr, (long)&saReliab);

	CStringArray saCheckerAppr, saChecker;
	saCheckerAppr.Add( APL_T("проверено"));
	saChecker.Add( APL_T("проверяющий")); saChecker.Add(_T("Checker"));
	caAll.Add((long)&saCheckerAppr, (long)&saChecker);

	CStringArray saSupplyAppr, saSupply;
	saSupplyAppr.Add( APL_T("согласовано"));
	saSupply.Add( APL_T("руководитель СК")); saSupply.Add(_T("Supply"));
	caAll.Add((long)&saSupplyAppr, (long)&saSupply);

	CStringArray saCustomerAppr, saCustomer;
	saCustomerAppr.Add( APL_T("согласовано"));
	saCustomer.Add( APL_T("представитель заказчика")); saCustomer.Add(_T("Customer"));
	caAll.Add((long)&saCustomerAppr, (long)&saCustomer);

	CStringArray saPlanAppr, saPlan;
	saPlanAppr.Add( APL_T("выполнено"));
	saPlan.Add( APL_T("диспетчер")); saPlan.Add(_T("Plan"));
	caAll.Add((long)&saPlanAppr, (long)&saPlan);

	CStringArray saBPPAppr, saBPP;
	saBPPAppr.Add( APL_T("выполнено"));
	saBPP.Add( APL_T("руководитель БППП")); saBPP.Add(_T("BPP"));
	caAll.Add((long)&saBPPAppr, (long)&saBPP);

	// Сверка подписей
	for(int i=0; i<caAll.Size; i++)
	{
		CStringArray *pArrIn = (CStringArray*)caAll.Data[i].in, *pArrOut = (CStringArray*)caAll.Data[i].out;
		if(GetMatch(pArrIn, sStatus) && GetMatch(pArrOut, sRole))
		{
			sStatusName = pArrOut->GetAt(pArrOut->GetSize()-1);
			sTmp = sStatus + _T(" ") + sDateTime;
		}
	}									
}

bool CaplDocManager::SetupApprovalFieldsInReports()
{
	if(!m_api->m_data.IsAdmin())
	{
		if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Данная настройка доступна только администратору."), MB_ICONINFORMATION);
		return false;
	}

	CReportApprovalFiledsSetupDlg dlg(m_api);

	if(dlg.DoModal() == IDOK) return true;
	else return false;	
}

void FindAssociationBetweenRoleAndStatus(CaplXMLFile &file, CString sRole, CString sStatus, CString &sStatusAbbr)
{
	CString roles, approvals, abbr;

	sStatusAbbr=_T("");
	for(int i=0; i<file.root.subnodes.GetSize(); i++)
	{
		CaplXMLNode *node = file.root.subnodes[i];
		if(!node) continue;

		node->GetParam(_T("Role"), roles);
		node->GetParam(_T("Approval"), approvals);
		node->GetParam(_T("Abbrv"), abbr);
		if(roles.IsEmpty() || approvals.IsEmpty() || abbr.IsEmpty()) continue;

		roles.MakeLower(); approvals.MakeLower();
		if( (roles.Find(sRole)>-1 || roles== APL_T("любая роль")) && (approvals.Find(sStatus)>-1 || approvals== APL_T("любой статус")) )
		{
			sStatusAbbr = abbr;
			return;
		}
	}
}

bool CaplDocManager::AfterSaveDocumentFile(CaplInstance *doc, LPCTSTR lpszFileName)
{
	CString sOption;
	CString sPath = lpszFileName;
	if(sPath.IsEmpty()) return false;
	CString sExt;
	int ind = sPath.ReverseFind(_T('.'));
	if(ind<0) return false;
	sExt = sPath.Right(sPath.GetLength()-ind-1);

	if(sExt.CompareNoCase(_T("aplrep"))==0)
	{
		int i;
		aplExtent approvals;
		aplExtent ext;
		CaplInstance *inst, *ciInv = NULL, *ciRev = NULL;
		CString buf, sDocRevId, sArhAppr, sArhDate, sArhName;
		CString sRole;
		CString sStatusName, sPersonName, sDateTime;
		CStdioFile file;
		
		if(m_api->m_data.IsKindOf(doc, e_doc)) m_api->m_data.GetAttr(doc, a_apl_doc_active, inst);
		else inst = doc;

		ciRev = inst;
		m_api->m_appr_mgr.LoadItemApproval(inst, approvals);
		m_api->m_data.GetAttr(inst, a_apl_doc_rev_id, sDocRevId);

		CString sTmp;
		COleDateTime time;	
		CString sFileName = sPath.Left(ind+1)+_T("aplpar");		

		if(!file.Open(sFileName, CFile::modeCreate|CFile::modeWrite)) return false;
		file.WriteString(sPath+_T("\n"));
		buf.Format(_T("%i\n"), GetFileCRC32(sPath));
		file.WriteString(buf);

		// номер версии
		buf.Format(_T("DocumentVer=%s\n"), sDocRevId);
		file.WriteString(buf);

		// смотрим, а нужно ли вообще показывать подписи
		CWinApp *app=AfxGetApp(); // При вызове из ActiveX возвращает 0

		int nOpenWithoutApproval = 0;
		int nOpenWithoutDates = 0;
		int nOpenWithoutSign  = 0;

		if(0!=app)
		{
			nOpenWithoutApproval = app->GetProfileInt(_T("APLREP_Settings"), _T("OpenWithoutApproval"), 0);
			nOpenWithoutDates = app->GetProfileInt(_T("APLREP_Settings"), _T("OpenWithoutDates"), 0);
			nOpenWithoutSign = app->GetProfileInt(_T("APLREP_Settings"), _T("OpenWithoutSign"), 0);
		}

		if( !(nOpenWithoutDates==1 && nOpenWithoutApproval==1) )
		{
			// динамические подписи
			CaplXMLFile xmlFile;
			m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Таблица ролей и статусов для документов типа aplrep"), sOption, _T(""));
									
			if(xmlFile.LoadFromBuffer(sOption))
			{
				for(i=0; i<approvals.GetSize(); i++)
				{
					sRole=_T("");
					m_api->m_data.GetAttr(approvals[i], m_api->m_appr_mgr.a_appr_status, inst);
					if(inst==NULL) continue;
					m_api->m_data.GetAttr(inst, m_api->m_appr_mgr.a_appr_status_name, buf);
					m_api->m_data.GetAttr(approvals[i], m_api->m_appr_mgr.a_appr_role, sRole);
					m_api->m_data.GetAttr(approvals[i], m_api->m_appr_mgr.a_appr_appr_date_time_s, sDateTime);
					m_api->m_data.GetAttr(approvals[i], m_api->m_appr_mgr.a_appr_pers_org, inst);
					if(!sDateTime.IsEmpty()){aplString2Date(sDateTime, time); sDateTime = time.Format(VAR_DATEVALUEONLY);}

					m_api->GetItemName(inst, sPersonName);
					buf.MakeLower(); sRole.MakeLower(); sTmp=_T("");

					// так было раньше (жестко все прошито)
					//FindAssociationBetweenRoleAndStatus(buf, sRole, sDateTime, sStatusName, sTmp);
					// теперь стали динамические настройки
					FindAssociationBetweenRoleAndStatus(xmlFile, sRole, buf, sStatusName);
					if(sStatusName.IsEmpty()) continue;

					if(nOpenWithoutDates == 0)
					{
						buf.Format(_T("%s=%s\n"), sStatusName, sPersonName);
						file.WriteString(buf);

						buf.Format(_T("%sENADate=%s\n"), sStatusName, sDateTime);
						file.WriteString(buf);
					}

					if(nOpenWithoutSign == 0)
					{
						CString str;
						m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Строка для вывода ЭЦП в отчетах"), str, APL_T("ЭЦП"));

						buf.Format(_T("%sENA=%s\n"), sStatusName, LPCTSTR(str) );
						file.WriteString(buf);
					}					
				}
			}
		}
		
		// инвентарный номер
		ciInv = m_api->m_doc_mgr.GetEntryValBN(ciRev,  APL_T("Инвентарный номер подлинника"));
		if(ciInv)
		{
			m_api->m_data.GetAttr(ciInv, m_api->m_doc_mgr.a_doc_entry_val_val, buf);
			buf = _T("InvNum=") + buf + _T("\n");
			file.WriteString(buf);
		}

		// литера
		m_api->m_data.GetAttr(ciRev, m_api->m_doc_mgr.a_apl_doc_rev_litera, buf);
		buf = _T("Litera=") + buf + _T("\n");
		file.WriteString(buf);

		// берем все изменения
		CString sLastDate;
		COleDateTime ApplyTime;
		aplExtent aeAVCitems;		
		CaplLoadData ld(&m_api->m_data,DEF_SOURCE);
		CaplInstance *ciChng = NULL, *ciAVC = NULL;
		int nLastNotAppliedChng = -1, nLastAppliedChng = -1;

		ld.AddQuery(0, ciRev);
		ld.AddQuery(_T('r'), 0, m_api->m_change_mgr.e_avc, m_api->m_change_mgr.a_avc_new_rev, true, true);
		ld.LoadEx(true, &aeAVCitems,  APL_T("Поиск изменения..."));

		// правило следующее: берем последнее проведенное изменение (по дате проведения)
		// или, если проведенных нет, то берем любое непроведенное
		for(int i=0; i<aeAVCitems.Size; ++i)
		{
			if(!m_api->m_data.IsKindOf(aeAVCitems[i], m_api->m_change_mgr.e_avc)) continue;

			m_api->m_data.GetAttr(aeAVCitems[i], m_api->m_change_mgr.a_chng_item_of_chng, ciChng);
			if(!ciChng) continue;

			m_api->m_data.GetAttr(ciChng, m_api->m_change_mgr.a_chng_state, buf); buf.MakeLower();
			if(buf == _T("applied"))
			{
				m_api->m_data.GetAttr(ciChng, m_api->m_change_mgr.a_chng_apply_date, buf);
				if(sLastDate.IsEmpty()) { sLastDate = buf; nLastAppliedChng = i; }
				if(!buf.IsEmpty() && buf > sLastDate) { sLastDate = buf; nLastAppliedChng = i; }
			}
			else
			{
				nLastNotAppliedChng = i;
			}
		}

		int nIntegerTest = 99999999;

		ciChng = NULL;
		if(nLastNotAppliedChng != -1) { m_api->m_data.GetAttr(aeAVCitems[nLastNotAppliedChng], m_api->m_change_mgr.a_chng_item_of_chng, ciChng); ciAVC = aeAVCitems[nLastNotAppliedChng]; }
		if(nLastAppliedChng != -1) { m_api->m_data.GetAttr(aeAVCitems[nLastAppliedChng], m_api->m_change_mgr.a_chng_item_of_chng, ciChng); ciAVC = aeAVCitems[nLastAppliedChng]; }		

		if(ciChng)
		{
			// номер изменения документа
			m_api->m_data.GetAttr(ciAVC, m_api->m_change_mgr.a_chng_item_id, buf);
			buf = _T("AVCid=") + buf + _T("\n");
			file.WriteString(buf);

			// лист
			buf =  APL_T("AVClist=все\n");
			file.WriteString(buf);

			// of_change.id
			m_api->m_data.GetAttr(ciChng, m_api->m_change_mgr.a_chng_id, buf);
			buf = _T("ChngId=") + buf + _T("\n");
			file.WriteString(buf);

			// of_change.apply_date
			m_api->m_data.GetAttr(ciChng, m_api->m_change_mgr.a_chng_apply_date, buf); aplString2Date(buf, ApplyTime); 
			buf.Format(_T("%.2d.%.2d.%.4d"), ApplyTime.GetDay(), ApplyTime.GetMonth(), ApplyTime.GetYear());
			buf = _T("ChngApplyDate=") + buf + _T("\n");
			file.WriteString(buf);
		}

		file.Close();

		return true;
	}

	return false;
}

bool CaplDocManager::CheckInOut(CaplInstance *doc, const TCHAR *path, bool bSetActive/* =false */, bool bSetRO /* = false */, bool bAlwaysShowDlg/* =false */, bool bUseSubDoc/* =false */, bool bIgnoreState/* = false*/)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(doc==NULL) return false;
	if(doc==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return false;
	}
	if(doc->GetType()==NULL) return false;
	if(!m_api->m_data.IsKindOf(doc, e_doc)) return false;
	

	CString file, buf, fpath=path, descr;
	CaplInstance *f_rev=0, *inst=0, *lock=0,*stor=0,*s_rev=0;
	CString s_dt;
	bool bStor = true;
	aplExtent aeCharacteristicsVersions;

	if(fpath.IsEmpty()) return false;

	// чтобы данные точно прочитались с сервера!
	m_data->ClearLastQuery();
	LoadDocInfo(doc);
	if(doc->GetAccessmode()>=aplRO) 
	{
		if(m_api->m_ModeInteractive) AfxMessageBox(S::NoAccessRight(), MB_OK|MB_ICONSTOP);
		return false;
	}
	if(bIgnoreState)
	{
		CString state;
		m_data->GetAttr(doc, a_apl_doc_wf_state, state);
		bool no_set_active = false;
		if(state==_T("canceled"))
		{
			if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Документ находится в состоянии\"")+GetWFStateName(_T("canceled"))+ APL_T("\" и не может быть изменен!"));
			return false;
		}
		else if(state!=_T("working") && state!=_T("changing") && state!=_T(""))
		{
			if(bSetActive) 
				if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Документ находится в состоянии \"")+GetWFStateName(state)+ APL_T("\" и для него невозможно сделать версию активной!"));
			no_set_active = true;
		}
	}

	
	if(bSetActive)
	{
		if(!TestMakeVersionActive(doc,true)) return false;
	}
	// проверка блокировки
	int i;
	CaplLoadData ld(m_data, DEF_SOURCE);
	m_data->GetAttr(doc, a_apl_doc_lock, lock);
	if(lock==0)
	{
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Редактирование завершено другим пользователем !"),MB_OK|MB_ICONSTOP);
		return false;
	}

	bool bCorrectPath=false;
	
	if(lock!=0)
	{
		CaplInstance *pers1=0,*pers;
		m_data->GetAttr(lock,a_apl_doc_rev_autor,pers);
		if(pers!=0)
		{
			// Взято на редактирование не анонимным пользователем
			pers1=m_api->m_appr_mgr.GetCurrentPerson();
			if(pers!=pers1)
			{
				if(m_api->m_ModeInteractive)
					AfxMessageBox( APL_T("Документ взят на редактирование другим пользователем !"),MB_OK|MB_ICONSTOP);
				return false;
			}
		}
		else
		{
			m_data->GetAttr(lock,a_apl_doc_rev_user,buf);
			if(buf!=m_data->GetNameCurrUser())
			{
				if(m_api->m_ModeInteractive)
					AfxMessageBox( APL_T("Документ взят на редактирование другим пользователем !"),MB_OK|MB_ICONSTOP);
				return false;
			}
		}

		m_data->GetAttr(lock, a_apl_doc_rev_base, f_rev);
		m_data->GetAttr(lock, a_apl_doc_rev_start_s, s_dt);
		m_data->GetAttr(lock, a_apl_doc_rev_edit_path, buf);
		m_data->GetAttr(lock, a_apl_doc_rev_descr, descr);
		if(fpath.IsEmpty()) 
		{
			fpath = buf;
			bCorrectPath = true;
		}		
	}

	
	// Определение пути
	if(f_rev!=0) 
		GetFileName(f_rev, file);
	if(fpath.IsEmpty()) fpath=buf;
	if(fpath.IsEmpty()) fpath=file;
	if(!bCorrectPath)
	{
		bCorrectPath= true;
		if(fpath[fpath.GetLength()-1]==_T('\\')) fpath+=file;
		else if(fpath[fpath.GetLength()-1]==_T(':')) fpath+=file;
	}
	bool showdlg=false;

	if(!m_api->m_ModeInteractive)
	{
		if(!bCorrectPath) return false;
	}
	else
	{
		if(!bCorrectPath) showdlg=true;
		else
		{
			if(path==0) showdlg=(fpath.IsEmpty()==TRUE);
			else if(*path==_T('\0'))showdlg=true;
		}
	}

	// Проверка наличия вложенных документов
	bool bHasSubDoc=false;
	if(m_api->m_ModeInteractive) bHasSubDoc=CheckSubDocument(f_rev);
	else
	{
		if(bUseSubDoc) bHasSubDoc=CheckSubDocument(f_rev);
	}

	if((showdlg)||(bAlwaysShowDlg))
	{
		if(m_api->m_ModeInteractive || bAlwaysShowDlg)
		{
			CaplSetResourceHandle setres(module_inst);

			CFileLoadDlg dlg;
			dlg.m_api= m_api;
			if(doc->GetAccessmode()>=aplRW) dlg.m_no_set_active=true;
			dlg.m_mode=_T("checkin");
			dlg.m_path=fpath;
			dlg.m_set_active=bSetActive;
			dlg.m_descr=descr;
			dlg.m_b_no_sub_doc=!bHasSubDoc;
			dlg.m_bEnableDelFile=true;
			if(dlg.DoModal()!=IDOK) return false;
			fpath=dlg.m_path;
			descr=dlg.m_descr;
			bSetActive = (dlg.m_set_active==TRUE);
			bSetRO = (dlg.m_set_ro==TRUE);
			bStor = (dlg.m_save_to_db==TRUE);
			bUseSubDoc = (dlg.m_use_sub_doc==TRUE);
		}
	}
	else
	{
		if(bHasSubDoc)
		{
			if(!bUseSubDoc && m_api->m_ModeInteractive)
			{
				if(AfxMessageBox( APL_T("Документ содержит вложенные. Обрабатывать их ?"),
					MB_YESNO|MB_ICONQUESTION)==IDYES) 
					bUseSubDoc=true;
			}
		}
	}

	CFileFind ff;
	if(FALSE==ff.FindFile(fpath))
	{
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Файл не найден"),MB_OK|MB_ICONSTOP);
		return false;
	}
	int crc32_1=0, crc32_2=GetFileCRC32(fpath);
	bool bCreateNewRevision=true;
	if(f_rev!=0)
	{
		m_data->GetAttr(f_rev,a_apl_doc_rev_crc,crc32_1);
		if(crc32_1==crc32_2) //Ничего не менялось, функция возвращает true, потомучто логически все хорошо.
			return true;
	}
	long code;
	if(bCreateNewRevision) 
	{
		if(bStor)
		{
			stor=m_data->CreateInstance(e_apl_stored_document);
			if(stor==0) return false;
			i=fpath.ReverseFind(_T('\\'));
			if(i>=0) buf=fpath.Right(fpath.GetLength()-i-1); else buf=fpath;
			i=buf.ReverseFind(_T(':'));
			if(i>=0) buf=buf.Right(buf.GetLength()-i-1); 
			m_data->PutAttr(stor,a_apl_stored_document_file_name,buf);
			if(!m_data->NET_SaveBlob(stor,a_apl_stored_document_source, fpath, code))
			{
				m_data->DeleteInstance(stor);
				return false;
			}
		}
		else
		{
			stor=m_data->CreateInstance(e_apl_assigned_document);
			if(stor==0) return false;
			m_data->PutAttr(stor,a_apl_assigned_document_location_path,fpath);
		}

		// Определение id версии
		int max_id=GetMaxDocRevId(doc);
		if(max_id<0) return false;
		max_id++;

		// Создание версии
		if(lock!=0)s_rev=lock;
		else s_rev=m_data->CreateInstance(e_apl_digital_document);
		m_data->PutAttr(s_rev,a_apl_doc_rev_doc,doc);
		m_data->PutAttr(s_rev,a_apl_doc_rev_base,f_rev);
		buf.Format(_T("%i"),max_id);
		m_data->PutAttr(s_rev,a_apl_doc_rev_id,buf);
		m_data->PutAttr(s_rev,a_apl_doc_rev_descr,descr);
		m_data->PutAttr(s_rev,a_apl_doc_rev_crc,crc32_2);

		m_data->PutAttr(s_rev,a_apl_doc_rev_user, m_api->m_appr_mgr.GetOperatorName());
		m_data->PutAttr(s_rev,a_apl_doc_rev_autor, m_api->m_appr_mgr.GetCurrentPerson()); 
		m_data->PutAttr(s_rev,a_apl_doc_rev_start_s,s_dt);

		CopyEntryValues(s_rev, f_rev);
		
		COleDateTime odt;
		m_api->aplGetCurrentTime(odt);
		aplDate2String(odt,s_dt);		
		m_data->PutAttr(s_rev,a_apl_doc_rev_end_s,s_dt);

		m_data->PutAttr(s_rev,a_apl_doc_rev_access_form,stor);

		
		m_data->PutAttr(s_rev,a_apl_doc_rev_user, m_api->m_appr_mgr.GetOperatorName()); // Установка автора
		m_data->PutAttr(s_rev,a_apl_doc_rev_autor, m_api->m_appr_mgr.GetCurrentPerson()); 


		//++ Делаем CheckInOut для характеристик интеграции 
		bool bInteractive;
		aplExtent aeCharacteristics;
		aplExtent aeCharacteristicsNewAssociated;
		
		CaplInstance* ciCharacteristic;
		CString sCharactValue;
		CString sEditSystem;
		aplExtent extDocs,extPdfs,extPrds,extRefs,extBuf; //данные об изделии
		CaplInstance* ciPdf = NULL;
		CaplInstance* ciChar = NULL;
		CString sCharId;
		mymsiMap siMapOptions;
		msiMapIt siIter;


		bInteractive = m_api->m_ModeInteractive;
		m_api->m_ModeInteractive = false;
		extDocs.Add(doc);
		FindAssociatedPdfs(extDocs,extPdfs,extPrds,extRefs);
		if (extPdfs.Size==1)
		{
			ciPdf = extPdfs.GetAt(0);
			LoadOptions(siMapOptions);
		}
		extBuf.Add(doc);
		if (ciPdf)
			extBuf.Add(ciPdf);
		m_api->m_charact_mgr.FindAssociatedCharacteristic(extBuf,aeCharacteristics);
		for(i= 0; i<aeCharacteristics.GetSize(); i++)
		{
			ciCharacteristic = aeCharacteristics.GetAt(i);
			m_api->m_data.GetAttr(ciCharacteristic, m_api->m_charact_mgr.a_apl_charact_val_system, sEditSystem);
			if(sEditSystem.IsEmpty())
				continue;
			m_api->m_data.GetAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_lock_ver,lock);
			if(!lock)
				continue;
			CString dt_s;
			dt_s=_T("");
			COleDateTime dt;
			m_api->aplGetCurrentTime(dt);
			aplDate2String(dt,dt_s);
			m_data->PutAttr(lock,m_api->m_charact_mgr.a_apl_charact_val_ver_end_date,dt_s);
			aeCharacteristicsNewAssociated.Add(lock);
			if(bSetActive)
				m_api->m_charact_mgr.MakeCharValVersionActive(lock);
			m_data->PutAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_lock_ver,(CaplInstance*)0);
			CaplInstance *rev=0,*act=0,*lock=0;
			m_api->m_data.GetAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_lock_ver,lock);
			if(lock)
				continue;
			lock = 0;
			m_data->GetAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_act_ver,act);
			CString num;
			num=_T("");
			if(!act)
			{
				act=m_api->m_charact_mgr.GetLatestCharValVersion(ciCharacteristic,num,false);
				if(act)
					m_data->PutAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_act_ver,act);
				else
					act=m_api->m_charact_mgr.CreateCharValVersion(ciCharacteristic,_T("0"));
				if(!act) continue;
			}
			if (!num.IsEmpty())
			{
				int num_ver = _atoi(num);
				num_ver++;
				num.Format(_T("%d"),num_ver);
			}
			else
				num.Format(_T("0"));
			if(rev)	
				lock=m_api->m_charact_mgr.CreateCharValVersion(rev,num,false);
			else 
				lock=m_api->m_charact_mgr.CreateCharValVersion(act,num,false);	
			if(!lock) 
				continue;
			m_data->PutAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_lock_ver,lock);
			aeCharacteristicsVersions.Add(lock);
			if (!ciPdf)
				continue;
			m_api->m_data.GetAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_charact,ciChar);
			m_api->m_data.GetAttr(ciChar,m_api->m_charact_mgr.a_apl_charact_id,sCharId);
			siIter = siMapOptions.m_data.find(sCharId);
			if (siIter == siMapOptions.m_data.end())
				continue;
			if (!siIter->second)
			{
				m_api->m_data.PutAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_item,doc);
				m_api->m_data.PutAttr(ciCharacteristic, m_api->m_charact_mgr.a_apl_charact_val_base_item, doc);
			}
			else
			{
				m_api->m_data.PutAttr(ciCharacteristic,m_api->m_charact_mgr.a_apl_charact_val_item,ciPdf);
				m_api->m_data.PutAttr(ciCharacteristic, m_api->m_charact_mgr.a_apl_charact_val_base_item, ciPdf);
			}

		}
		m_api->m_data.PutAttr(s_rev,m_api->m_doc_mgr.a_apl_doc_rev_char_val_versions, aeCharacteristicsNewAssociated);

		m_api->m_ModeInteractive = bInteractive;
		// Установка активной
		if(bSetActive)
			CreateChange(s_rev,true,false);
		inst = s_rev;
	}
	// Удаление блокировки
	m_data->PutAttr(doc,a_apl_doc_lock, (CaplInstance*)0);
	if(m_AutoSave) m_api->SaveChanges();

	SetRevisionAccessOnCreate(s_rev);

	if(bSetRO) 
		SetFileAttributes(fpath, FILE_ATTRIBUTE_READONLY);
	else
		SetFileAttributes(fpath, FILE_ATTRIBUTE_NORMAL);

	if(bUseSubDoc && bHasSubDoc) // обработка входящик документов
	{
		aplExtent ext0,ext1,ext2;
		FindAssociatedDocuments(doc,ext0,ext2);
		FindAssociatedDocuments(f_rev,ext1,ext2);
		ext0.Append(ext1);
		int i=fpath.ReverseFind(_T('\\'));
		bool i_am_locker=false;
		if(!m_service_ext_lock)
		{
			i_am_locker=true;
			m_service_ext_lock=true;
			m_service_ext.Clear();
			m_service_ext.Add(doc);
		}
		
		if(i>0)
		{
			buf=fpath.Left(i+1);
			bool bMode= m_api->m_ModeInteractive;
			m_api->SetModeInteractive(false);
			for(i=0;i<ext0.Size;i++)
			{
				if(m_service_ext.Find(ext0[i])<0)
				{
					m_service_ext.Add(ext0[i]);
					CheckInOut(ext0[i], buf, bSetActive, bSetRO, false, bUseSubDoc,bIgnoreState);
				}
			}
			m_api->SetModeInteractive(bMode);
		}
	}

	//Теперь делаем маленький CheckOut;
	// определение имени компьютера
	CString name_comp;
	m_data->GetCompName(name_comp);
	
	// Создание объектов
	CaplInstance* nInst=m_data->CreateInstance(e_apl_digital_document);
	m_data->PutAttr(doc, a_apl_doc_lock, nInst);
	m_data->PutAttr(nInst, a_apl_doc_rev_base, inst);
	m_data->PutAttr(nInst, a_apl_doc_rev_edit_path, LPCTSTR(fpath));
	m_data->PutAttr(nInst, a_apl_doc_rev_descr, descr);
	m_data->PutAttr(nInst, a_apl_doc_rev_user,  m_api->m_appr_mgr.GetOperatorName()); // Установка автора
	m_data->PutAttr(nInst, a_apl_doc_rev_autor, m_api->m_appr_mgr.GetCurrentPerson()); 
	m_data->PutAttr(nInst, a_apl_doc_rev_stored_on, name_comp);
	m_data->PutAttr(nInst, a_apl_doc_rev_char_val_versions,aeCharacteristicsVersions);
	
	COleDateTime odt;
	m_api->aplGetCurrentTime(odt);
	aplDate2String(odt,s_dt);
	m_data->PutAttr(nInst, a_apl_doc_rev_start_s, s_dt);


	if(m_AutoSave)m_api->SaveChanges();
	LogDocAccess(s_rev,_T("CheckInOut"),fpath);
	return true;
}

bool CaplDocManager::FindAssociatedPdfs(aplExtent& extIn, aplExtent& extPdfs, aplExtent& extPrds, aplExtent& extRefs)
{
	extPdfs.Clear();
	extPrds.Clear();
	extRefs.Clear();
	if (!extIn.Size)
		return false;
	int i;
	aplExtent ext1;
	CaplInstance* ciBufDoc = NULL;
	CaplInstance* ciBufPdf = NULL;
	CaplInstance* ciPrd = NULL;
	CString sBuf;
	CString sDocId,sDocName,sPrdId,sPrdName,sDocIdOnly;
	CSortClass::SortExtentByInst(extIn);
	m_api->LoadByParts(extIn,480,true,AddPdfDocRefInfo,(DWORD)NULL);
	m_api->m_data.GetEntityExtent(e_apl_doc_ref,ext1);
	for (i=0;i<ext1.Size;i++)
	{
		m_api->m_data.GetAttr(ext1[i],a_apl_doc_ref_doc,ciBufDoc);
		if (-1==extIn.Find(ciBufDoc))
			continue;
		m_api->m_data.GetAttr(ext1[i],a_apl_doc_ref_item,ciBufPdf);
		if(!ciBufPdf)
			continue;

		if(ciBufPdf->GetType()==0 || ciBufPdf->GetAccessmode()>aplRO) continue;
		m_api->m_data.GetAttr(ciBufPdf,m_api->m_prd_mgr.a_pdf_prd,ciPrd);
		if (!ciPrd)
			continue;
		m_api->m_data.GetAttr(ciPrd,m_api->m_prd_mgr.a_prd_id,sBuf);
		GetOnlyName(sBuf,sPrdId);
		m_api->m_data.GetAttr(ciBufDoc,a_doc_id,sDocId);
		GetOnlyName(sDocId,sDocIdOnly);
		if (sPrdId.CompareNoCase(sDocIdOnly))
			continue;
		m_api->m_data.GetAttr(ciPrd,m_api->m_prd_mgr.a_prd_name,sPrdName);
		m_api->m_data.GetAttr(ciBufDoc,a_doc_name,sDocName);
		if (sPrdName.CompareNoCase(sDocName))
			continue;
		extRefs.Add(ext1[i]);
		extPdfs.Add(ciBufPdf);
		extPrds.Add(ciPrd);
	}
	if (extRefs.Size)
		return true;
	return false;
}

bool CaplDocManager::GetOnlyName(const CString& sFileName, CString &sOnlyName)
{
	bool res= false;
	CString sExt;
	CString sBuf(sFileName);
	sExt=_T("");
	sOnlyName=_T("");
	if(sBuf.IsEmpty())
		return res;
	int count= sBuf.ReverseFind(_T('\\'));	
	if(count!=-1)
		sBuf= sBuf.Right(sBuf.GetLength()-1 - count);
	count= sBuf.ReverseFind(_T('.'));
	if(count!=-1)
	{
		sExt = sBuf.Right(sBuf.GetLength()-1-count);
		sExt.MakeLower();
		if (!sExt.CompareNoCase(_T("asm"))||
			!sExt.CompareNoCase(_T("prt"))||
			!sExt.CompareNoCase(_T("drw"))||
			!sExt.CompareNoCase(_T("sldasm"))||
			!sExt.CompareNoCase(_T("sldprt"))||
			!sExt.CompareNoCase(_T("slddrw")))
		{
			res= true;
			sOnlyName= sBuf.Left(count);
		}
	}
	else
		sOnlyName = sBuf;
	sOnlyName.MakeLower();
	return res;	
}

void CaplDocManager::AddPdfDocRefInfo(CaplAPI *api, CaplLoadData &ld, DWORD data)
{
	int refs,pdfs;
	refs = ld.AddQuery(_T('r'),0,api->m_doc_mgr.e_apl_doc_ref,api->m_doc_mgr.a_apl_doc_ref_doc,true,true);
	pdfs = ld.AddQuery(_T('d'),refs,0,api->m_doc_mgr.a_apl_doc_ref_item,true,true);
	ld.AddQuery(_T('d'), pdfs, 0, api->m_prd_mgr.a_pdf_prd, true, true);
}

void CaplDocManager::LoadOptions(mymsiMap& siMapOptions)
{
	CString name;
	CString sMyCurDoc,sMyCurDocAll;
	CString buf;
	int ipos;
	msiMapIt siIter;
	mssMapIt ssIter;
	mssMap ssMapOpt;
	msiMap siMapOpt;
	siMapOptions.m_data.clear();
	sMyCurDoc = _T("SW_REFS\\All\\");
	sMyCurDocAll = _T("SW_REFS\\Docs\\");
	int iCharAv;
	for(iCharAv = 0; iCharAv < m_api->m_options_mgr.m_params.GetSize(); iCharAv++)
	{
		CaplStrMap::CaplStrMapItem* item=m_api->m_options_mgr.m_params.GetAt(iCharAv);
		if(item==0) continue;
		CaplInstance *inst=(CaplInstance*)item->val;
		if(inst==0) continue;
		if(0==inst->GetType()) continue;
		if(m_api->m_data.IsKindOf(inst,m_api->m_options_mgr.e_str))
		{
			m_api->m_data.GetAttr(inst,m_api->m_options_mgr.a_str_name,name);
			if(!name.Find(sMyCurDoc))
			{
				name.Delete(0,sMyCurDoc.GetLength());
				m_api->m_data.GetAttr(inst,m_api->m_options_mgr.a_str_value,buf);
				ssMapOpt.insert(std::make_pair(buf,name));
				
			}
		}
		if (m_api->m_data.IsKindOf(inst,m_api->m_options_mgr.e_int))
		{
			m_api->m_data.GetAttr(inst,m_api->m_options_mgr.a_int_name,name);
			if (!name.Find(sMyCurDocAll))
			{
				name.Delete(0,sMyCurDocAll.GetLength());
				m_api->m_data.GetAttr(inst,m_api->m_options_mgr.a_int_value,ipos);
				siMapOpt.insert(std::make_pair(name,ipos));
			}
		}
	}
	forr(ssIter,ssMapOpt)
	{
		siIter = siMapOpt.find(ssIter->second);
		if (siIter!=siMapOpt.end())
			siMapOptions.m_data.insert(std::make_pair(ssIter->first,siIter->second));
		else
			siMapOptions.m_data.insert(std::make_pair(ssIter->first,0));
	}
}

// Очищает информацию об использовании для заданной ревизии
void CaplDocManager::ClearAllXmlUsages( CaplInstance *doc_or_revision )
{
	aplExtent ext;
	CaplAttrValue tst_value;

	tst_value.value.Set( doc_or_revision );
	tst_value.attr = a_apl_xml_index_cur_doc_rev;;

	m_data->NET_FindInstancesWithAttrValues(e_apl_xml_index, 1,&tst_value,ext,false);

	for( int i = 0; i < ext.GetSize(); i++ )
	{
		m_data->DeleteInstance( ext[i], false );
	}

	if( m_AutoSave ) m_data->NET_SaveChanges();
	
}


// Добавляет информацию об использовании обьекта справочника
CaplInstance* CaplDocManager::AddXmlUsedItem( CaplInstance *currentDocRevision, CaplInstance *lpsSystem,
											 const CString& sysId, int type,const CString& typeName, const CString& id, const CString& name, const CString& name_eng,
											 const CString& configInfo,
											 const CString& refGuid,
											 CaplInstance *cfgInst)
{
	CaplInstance *xmlUsedItem = m_data->CreateInstance( e_apl_xml_index );

	m_data->PutAttr( xmlUsedItem, a_apl_xml_index_cur_doc_rev, currentDocRevision );
	m_data->PutAttr( xmlUsedItem, a_apl_xml_index_lps_system, lpsSystem );
	m_data->PutAttr( xmlUsedItem, a_apl_xml_index_sys_id, sysId );
	m_data->PutAttr( xmlUsedItem, a_apl_xml_index_type, type );
	m_data->PutAttr( xmlUsedItem, a_apl_xml_index_type_name, typeName );
	m_data->PutAttr( xmlUsedItem, a_apl_xml_index_id, id );
	m_data->PutAttr( xmlUsedItem, a_apl_xml_index_name, name );
	m_data->PutAttr( xmlUsedItem, a_apl_xml_index_name_eng, name_eng );
	m_data->PutAttr( xmlUsedItem, a_apl_xml_index_config_info, configInfo );
	m_data->PutAttr( xmlUsedItem, a_apl_xml_index_ref_guid, refGuid );
	m_data->PutAttr( xmlUsedItem, a_apl_xml_index_cfg, cfgInst );

	if( m_AutoSave ) m_data->NET_SaveChanges();

	return xmlUsedItem;
}
/*
CaplInstance* CaplDocManager::AddXmlUsedItemRelatedRelation( CaplInstance *doc_or_revision, CaplInstance *relating, CaplInstance* related )
{
	CaplInstance *xmlRelItems = m_data->CreateInstance( e_apl_xml_index_relation );

	m_data->PutAttr( xmlRelItems, a_apl_xml_index_relation_relating, relating );
	m_data->PutAttr( xmlRelItems, a_apl_xml_index_relation_related, related );

	if( m_AutoSave ) m_data->NET_SaveChanges();

	return xmlRelItems;
}
*/
// Проверяет, используется ли элемент справочника с определённым sys id
bool CaplDocManager::IsUsedInXml( const CString& sysId )
{
	aplExtent ext;
	CaplAttrValue tst_value;

	tst_value.value.Set( sysId );
	tst_value.attr = a_apl_xml_index_ref_guid;;

	m_data->NET_FindInstancesWithAttrValues(e_apl_xml_index,1,&tst_value,ext,false);

	return ext.Size > 0 ;
}

bool CaplDocManager::IsUsedInXml( const aplExtent& in_ext, std::map<CaplInstance*, bool>& outMap)
{
	std::map< CaplEntity*, CaplAttr* > entAtrMap;
	std::map< CaplEntity*, CaplAttr* >::iterator searchRes;

	CaplInstance* pInst;
	CaplAttr *pAttr;

	std::map< CaplInstance*, bool > currMap;

	std::list< CString > guidsList;

	std::map< CString, CaplInstance* > guidInstMap;

	for( int ind = 0; ind < in_ext.GetSize(); ind++ )
	{
		pInst = in_ext[ ind ];

		searchRes = entAtrMap.find( pInst->GetType() );

		if ( searchRes == entAtrMap.end() )  
		{
			pAttr = m_data->GetAttrDefinition( pInst->GetType(), _T("guid") );
			entAtrMap.insert( std::make_pair( pInst->GetType(), pAttr) );
		}
		else
		{
			pAttr = searchRes->second;
		}

		CString strGuid;
		if(pAttr)
		{
			if ( m_data->GetAttr( pInst, pAttr, strGuid ) )
			{
				guidsList.push_back( strGuid );
				guidInstMap.insert( std::make_pair(strGuid, pInst) );
			}

			outMap.insert( std::make_pair( pInst, false ) );
		}
	}

	aplExtent out_ext;
	FindXmlUsedRefs(guidsList, out_ext);


	CString sys_id;

	for ( int i = 0; i < out_ext.GetSize(); i++)
	{
		m_api->m_data.GetAttr( out_ext[i], m_api->m_doc_mgr.a_apl_xml_index_ref_guid, sys_id);

		outMap[ guidInstMap[ sys_id ] ] = true;
	}

	return out_ext.GetSize() > 0 ;
}

bool CaplDocManager::FindXmlUsedRefs(const std::list<CString>& in_sysIds, aplExtent& out_ext)
{
	CString query = _T("SELECT Ext_0 ");

	query += _T(" FROM ");

	query += _T(" Ext_0 { apl_xml_index ( ");

	for( std::list< CString >::const_iterator it = in_sysIds.begin(); it != in_sysIds.end() ; it++ )
	{
		query +=  _T(" .ref_guid = \'") + *it +_T("\' OR "); 
	}

	// remove last or
	CString tmp = query.Left( query.GetLength() - 3 );

	query = tmp;

	query += _T( " ) } ") ;

	query += _T( " END_SELECT " );

	if( m_api->m_data.NET_QueryEditParse( query ) )
		m_api->m_data.NET_QueryExecute( out_ext,  APL_T("Поиск ссылок") );

	m_api->LoadByParts(out_ext, m_api->m_MaxItemsLoad, true, NULL, 0);

	return out_ext.GetSize() > 0 ;
}

bool CaplDocManager::FindXmlUsedRefs(const CString& sysId, aplExtent &out_ext)
{
	CString query= _T( "SELECT Ext_0 FROM\n Ext_0  { apl_xml_index ( .ref_guid = \'") + sysId +_T("\' ) } END_SELECT");

	if( m_api->m_data.NET_QueryEditParse( query ) )
		m_api->m_data.NET_QueryExecute( out_ext,  APL_T("Поиск ссылок") );

	m_api->LoadByParts(out_ext, m_api->m_MaxItemsLoad, true, NULL, 0);

	return true;
}

bool CaplDocManager::FindXmlUsedRefs(const aplExtent& in_ext, std::map<CaplInstance*, std::vector<CaplInstance*>>& out_map)
{
	std::map<CaplEntity*, CaplAttr*> entAtrMap;
	std::map<CaplEntity*, CaplAttr*>::iterator searchRes;

	CaplInstance* pInst;
	CaplAttr* pAttr;

	aplExtent out_ext;

	std::list<CString> guidsList;

	for( int ind = 0; ind < in_ext.GetSize(); ind++ )
	{
		pInst = in_ext[ind];

		searchRes = entAtrMap.find(pInst->GetType());

		if( searchRes == entAtrMap.end() )
		{
			pAttr = m_data->GetAttrDefinition(pInst->GetType(), _T("guid"));
			entAtrMap.insert(std::make_pair( pInst->GetType(), pAttr));
		}
		else
		{
			pAttr = searchRes->second;
		}

		CString strGuid;
		std::vector<CaplInstance*> pExt;

		if(pAttr && m_data->GetAttr(pInst, pAttr, strGuid) )
		{
			guidsList.push_back(strGuid);
		}

		// запросы по 100 инстансов
		if( guidsList.size() == 100 )
		{
			aplExtent ext;
			FindXmlUsedRefs(guidsList, ext);
			guidsList.clear();

			for( int i = 0; i < ext.GetSize(); i++ )
				out_ext.Add(ext[i]);
		}
	}
	// запрос остатка
	aplExtent ext;
	FindXmlUsedRefs(guidsList, ext);
	for( int i = 0; i < ext.GetSize(); i++ )
		out_ext.Add(ext[i]);

	/************************************************************************/
	/*                                                                      */
	/************************************************************************/

	CString strGuid, strRefGuid;
	CaplAttr *pRefGuidAttr = m_data->GetAttrDefinitionBN(_T("apl_xml_index"), _T("ref_guid"));

	for(int i=0; i<out_ext.Size; ++i)
	{
		m_data->GetAttr(out_ext[i], pRefGuidAttr, strRefGuid);

		for(int j=0; j<in_ext.Size; ++j)
		{
			searchRes = entAtrMap.find(in_ext[j]->GetType());
			if(searchRes == entAtrMap.end()) continue;

			CaplAttr *pGuidAttr = searchRes->second;
			m_data->GetAttr(in_ext[j], pGuidAttr, strGuid);

			if(0 == strGuid.CompareNoCase(strRefGuid))
				out_map[in_ext[j]].push_back(out_ext[i]);
		}
	}

	/************************************************************************/
	/*                                                                      */
	/************************************************************************/	

	return out_ext.GetSize() > 0;
}

bool CaplDocManager::LoadFileFromLocker( CaplInstance * lockInst, const CString& filename )
{
	CaplInstance* pBlobInst = lockInst;
	
	CaplAttr *pBlobAttr = m_data->GetAttrDefinition( pBlobInst->GetType(), _T("document_source"));

	// проверяем был ли старый блоб
	CString oldBlob ;
	m_data->GetAttr( pBlobInst, pBlobAttr, oldBlob );

	if ( !oldBlob.IsEmpty() )
	{
		// блом матерится на существующий файл
		::DeleteFile( filename );
		if ( m_data->NET_LoadBlob( pBlobInst, pBlobAttr, filename ) )
		{
			return true;
		}
	}

	return false;
}

bool CaplDocManager::SaveFileToLocker( CaplInstance* lock, const CString& filename )
{
	CaplInstance* pBlobInst = lock;
	CaplAttr *pBlobAttr = m_api->m_data.GetAttrDefinition(pBlobInst->GetType(), _T("document_source"));

	// проверяем был ли старый блоб
	CString oldBlob ;
	m_api->m_data.GetAttr( pBlobInst, pBlobAttr, oldBlob );

	long code;

	if ( m_data->NET_SaveBlob( pBlobInst, pBlobAttr, filename, code ) )
	{
		// удаляем старый блоб
		if ( !oldBlob.IsEmpty() )
		{
			m_data->NET_DeleteBlob(oldBlob);
		}
	}

	return TRUE;
}

int aplErrorMessage(const TCHAR* message,CaplInstance* inst)
{
	CString buf=message,buf1;
	if(inst!=0)
	{
		buf1.Format(_T("\n id: %i"),inst->GetId());
		buf+=buf1;
		if(inst->GetType()==0){buf1=_T(" type=0");}
		else{buf1=_T(" type=")+inst->GetType()->name;}
		buf+=buf1;
	}
	return AfxMessageBox(buf,MB_OK|MB_ICONSTOP);
}

int CaplDocManager::GetMaxDocRevId(CaplInstance *doc)
{
	if(m_data==0) return -1;
	if(0==doc) return -1;
	
	if(doc==(CaplInstance*)-1) {
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));
		return -1;
	}
	if(doc->GetType()==0) return -1;
	if(doc->GetAccessmode()>aplRO) return -1;

	// Определение id версии
	int i,j;
	aplExtent ext;
	if(0!=doc->GetId())
	{
		CaplLoadData ld(m_data,DEF_SOURCE);
		j=ld.AddQuery(_T('b'), doc->GetId(), e_apl_doc_rev,a_apl_doc_rev_doc, true);
		ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_doc, true);
		ld.AddQuery(_T('d'), j, 0,a_apl_doc_rev_id, true);
		ld.LoadEx(true,&ext);
	}
	else m_data->GetEntityExtent(e_apl_doc_rev,ext);

	int max_id=0,iLastNoAccessId=-1,iLastMaxId=-1;
	CString buf;
	for(i=0;i<ext.Size;i++)
	{
		CaplInstance *inst=ext[i];
		if(0==inst) continue;
		if(0==inst->GetType()) continue;
		if(!m_data->IsKindOf(inst,e_apl_doc_rev))continue;
		if(inst->GetAccessmode()>aplRO)
		{
			if(inst->GetId()>(apl_id)iLastNoAccessId) iLastNoAccessId=inst->GetId();
			continue;
		}
		CaplInstance *doc1;
		m_data->GetAttr(inst,a_apl_doc_rev_doc,doc1);
		if(doc!=doc1) continue;

		m_data->GetAttr(inst,a_apl_doc_rev_id,buf);
		j=_atoi(buf);
		if(j>max_id)
		{
			max_id=j;
			iLastMaxId=inst->GetId();
		}
	}

	if(iLastNoAccessId>iLastMaxId)
	{
		if(m_api->m_ModeInteractive)
			AfxMessageBox( APL_T("К одной из новых версий документа нет доступа. Возможно некорректное определение номера версии."));
	}
	return max_id;
}


int CaplDocManager::CalcAllSheetsFromMultiFormats(LPCTSTR scOfLists, CString* format_description, int *countA4)
{
	double k;
	DWORD multipl;
	int countAll = 0;
	int pos1=0,pos2,pos3,pos4;
	CString format_str,num_str,multipl_str,tmp;
	CString sOfLists;
	DWORD format;
	DWORD count;
	
	if(format_description!=0)*format_description = _T("");
	if(countA4!=0)*countA4 = 0;
	
	sOfLists = scOfLists;

	countAll = _atoi(sOfLists);
	if(countAll > 0)
	{
		if(format_description!=0)format_description->Format(_T("%i"),countAll);
		if(countA4!=0)*countA4 = countAll;
		return countAll;
	}


	do{
		pos2=sOfLists.Find(_T('='),pos1);
		pos3=sOfLists.Find(_T('*'),pos1);
		pos4=sOfLists.Find(_T(','),pos1);
		if(pos2 > 0)
		{	
			if(pos4==-1) pos4=sOfLists.GetLength();
		}
		else break;
		format_str = sOfLists.Mid(pos1,pos2-pos1);
		if(pos3==-1 || pos3 > pos4)
		{
			num_str = sOfLists.Mid(pos2+1,pos4-pos2-1);
			multipl_str = _T("1");
		}
		else
		{
			num_str = sOfLists.Mid(pos2+1,pos3-pos2-1);
			multipl_str = sOfLists.Mid(pos3+1,pos4-pos3-1);;
		}
		if(format_str[0]!=_T('A')) // A - латинское, как и в InsertFormats()
			break;
		format_str.Remove(_T('A'));
		format = _atoi(format_str);
		count = _atoi(num_str);
		if(format < 0 || format > 5)
			continue;
		
		countAll+=count;

		if(format_description!=0 || countA4!=0)
		{
 			multipl = _atoi(multipl_str);

			switch(format)
			{
			case 0: k=16;break;
			case 1: k=8;break;
			case 2: k=4;break;
			case 3: k=2;break;
			case 4: k=1;break;
			case 5: k=0.5;break;
			default:
				continue;
			}
			if(countA4!=0) *countA4 += (int)(0.5 + count * multipl * k);
			if(format_description!=0 && count>0)
			{
				if(multipl > 1)
					tmp.Format(APL_T("A%ix%i - %i лист"),format,multipl,count);
				else
					tmp.Format(APL_T("A%i - %i лист"),format,count);
				div_t div_res_100 = div(count,100);
				div_t div_res_10 = div(count,10);
				if( div_res_100.rem > 9 && div_res_100.rem < 20 ) tmp += APL_T("ов");
				else if( div_res_10.rem == 0 || div_res_10.rem > 4 ) tmp += APL_T("ов");
				else if( div_res_10.rem > 1 ) tmp += APL_T("а");

				if(*format_description != _T("")) *format_description+=_T(" + ");
				*format_description += tmp;
			}
		}
		pos1=pos4+1;
	}while(pos2 > 0);

	return countAll;
}

int CaplDocManager::GetListFormats(LPCTSTR scOfLists, CString* list_formats)
{
	int countAll = 0;
	int pos1=0,pos2,pos3,pos4;
	CString format_str,num_str;
	CString sOfLists;
	DWORD count;
	
	if(list_formats!=0)*list_formats = _T("");
	
	sOfLists = scOfLists;

	countAll = _atoi(sOfLists);
	if(countAll > 0)
	{
		return countAll;
	}

	do{
		pos2=sOfLists.Find(_T('='),pos1);
		pos3=sOfLists.Find(_T('*'),pos1);
		pos4=sOfLists.Find(_T(','),pos1);
		if(pos2 > 0)
		{	
			if(pos4==-1) pos4=sOfLists.GetLength();
		}
		else break;
		format_str = sOfLists.Mid(pos1,pos2-pos1);
		if(pos3==-1 || pos3 > pos4)
		{
			num_str = sOfLists.Mid(pos2+1,pos4-pos2-1);
		}
		else
		{
			num_str = sOfLists.Mid(pos2+1,pos3-pos2-1);
		}

		if(format_str!=_T("A0") && format_str!=_T("A1") && format_str!=_T("A2") && format_str!=_T("A3") && format_str!=_T("A4") && format_str!=_T("A5")) // A - латинское, как и в InsertFormats()
			break;
		count = _atoi(num_str);
		countAll+=count;

		if(list_formats!=0 && count != 0)
		{
			if(*list_formats != _T("")) *list_formats+=_T(", ");
			*list_formats += format_str;
		}
		pos1=pos4+1;
	}while(pos2 > 0);

	return countAll;
}


bool CaplDocManager::CalcA4SheetsCount(LPCTSTR sFormat, LPCTSTR sSheetsCount, CString &sA4Count)
{
	sA4Count=_T("");

	if(sFormat==0 || sSheetsCount==0) return false;
	if(sFormat[0]==_T('\0') || sSheetsCount[0]==_T('\0'))return false;
	if(sFormat[1]==_T('\0'))return false;

	if(!(sFormat[0]==_T('A') || sFormat[0]!=_T('А'))) return false;  //eng - rus

	TCHAR c=sFormat[1];

	double k;
	if(c==_T('0')) k=16;
	else if(c==_T('1')) k=8;
	else if(c==_T('2')) k=4;
	else if(c==_T('3')) k=2;
	else if(c==_T('4')) k=1;
	else if(c==_T('5')) k=0.5;
	else if(c==_T('6')) k=0.25;
	else if(c==_T('7')) k=0.125;
	else {return false;}

	double sheets_count=__atof(sSheetsCount);
	int count=int(0.5+k*sheets_count);
	sA4Count.Format(_T("%i"),count);
	return true;
}

//***********************************************************************
bool CaplDocManager::GetPrdIdFromDocId(CaplInstance *doc, CString &prd_id, CString &prd_ver)
{
	prd_id=_T(""); prd_ver=_T("");
	if(0==doc) return false;
	if(0==doc->GetType()) return false;
	if(doc->GetAccessmode()>aplRO) return false;
	if(!m_api->m_data.IsKindOf(doc,e_doc)) return false;

	CString doc_id,dt_code;
	CaplInstance *dt;
	m_data->GetAttr(doc,a_doc_id,doc_id);
	doc_id.MakeUpper();
	m_data->GetAttr(doc,a_doc_kind,dt);
	if(0!=dt) m_data->GetAttr(dt,a_dt_id,dt_code);
	if(dt_code==_T("")) // основной документ, обозначения совпадают
	{
		prd_id=doc_id;
		if(prd_id==_T("")) return true;
		int j=prd_id.ReverseFind(_T('-'));
		if(j<0) 
			return true;
		prd_ver=prd_id.Right(prd_id.GetLength()-(j+1));
		if(prd_ver==_T("")) 
			return true;
		CString buf=prd_id.Left(j);
		if(buf==_T("")) {prd_ver=_T(""); return true;} // Это если обозначение начинается с единственного "-"
		prd_id=buf;
		return true;
	}

	dt_code.MakeUpper();

	// Ищем с конца код вида документа
	int i=doc_id.GetLength()-1,j=dt_code.GetLength()-1,k;
	while(i>=j)
	{
		if(doc_id[i]!=dt_code[j]) {i--; continue;} 

		bool bEqu=true;
		for(k=1;k<=j;k++)
		{
			if(doc_id[i-k]!=dt_code[j-k]) {bEqu=false; break;}
		}
		if(bEqu) // Нашлось
		{
			prd_id=doc_id.Left(i-j);
			// отделяем версию
			if(prd_id==_T("")) return true;
			j=prd_id.ReverseFind(_T('-'));
			if(j<0) 
				return true;
			prd_ver=prd_id.Right(prd_id.GetLength()-(j+1));
			if(prd_ver==_T("")) 
				return true;
			CString buf=prd_id.Left(j);
			if(buf==_T("")) {prd_ver=_T(""); return true;} // Это если обозначение начинается с единственного "-"
			prd_id=buf;
			return true;
		}
		i--;
	}
	return false;
}

//***********************************************************************
bool CaplDocManager::AttachDocToPrd(CaplInstance *doc)
{
	if(0==doc) return false;
	if(0==doc->GetType()) return false;
	if(doc->GetAccessmode()>aplRO) return false;
	if(!m_api->m_data.IsKindOf(doc,e_doc)) return false;

	CString prd_id,prd_ver,doc_id;
	GetPrdIdFromDocId(doc,prd_id,prd_ver);
	if(prd_id==_T("")) return true;

	m_data->GetAttr(doc,a_doc_id,doc_id);

	CString buf,buf1;
	CaplInstance *prd, *pdf;
	aplExtent ext_pdf;

	prd=m_api->m_prd_mgr.FindPrdById(prd_id);
	if(0!=prd)
	{
		pdf=m_api->m_prd_mgr.FindPdfById(prd,prd_ver);
		if(0!=pdf)
		{
			CaplInstance *rel=FindAssociation(pdf,doc);
			if(0==rel)
			{
				buf1=prd_id;
				if(prd_ver!=_T(""))  buf1+=APL_T(" вер. ")+ prd_ver;
				buf.Format(APL_T("Ассоциировать документ '%s' с изделием '%s'?"),LPCTSTR(doc_id), LPCTSTR(buf1));
				if(IDYES==AfxMessageBox(buf,MB_YESNO|MB_ICONQUESTION))
				{
					CreateAssociation(pdf,doc,0,0,APL_DOCUMENT_RELATION,false);
				}
			}
		}
	}
	if(prd_ver==_T("")) return true;

	prd_id+=_T('-'); prd_id+=prd_ver;
	prd=m_api->m_prd_mgr.FindPrdById(prd_id);
	if(0!=prd)
	{
		pdf=m_api->m_prd_mgr.FindPdfById(prd,_T(""));
		if(0!=pdf)
		{
			CaplInstance *rel=FindAssociation(pdf,doc);
			if(0==rel)
			{
				buf.Format(APL_T("Ассоциировать документ '%s' с изделием '%s'?"),LPCTSTR(doc_id), LPCTSTR(prd_id));
				if(IDYES==AfxMessageBox(buf,MB_YESNO|MB_ICONQUESTION))
				{
					CreateAssociation(pdf,doc,0,0,APL_DOCUMENT_RELATION,false);
				}
			}
		}
	}
	return true;
}

// Протоколирование
void CaplDocManager::LogDocAccess(CaplInstance *inst, LPCTSTR function, LPCTSTR fpath)
{
	if(0==m_api->m_options_mgr.GetIntOptionValueBN(EnableLog,0)) return;

	int recipient_id,NumDocInClock,m_NumMinutes;
	bool notifi_with_excess = true;

	m_api->m_options_mgr.GetOptionValueBN(dp_name_options_notification_limit,NumDocInClock,0);
	m_api->m_options_mgr.GetOptionValueBN(dp_name_options_notification_time,m_NumMinutes,0);
	m_api->m_options_mgr.GetOptionValueBN(dp_name_options_notification_recipient,recipient_id,0);
	if(recipient_id ==0 || NumDocInClock <=0) notifi_with_excess = false;
	CaplInstance* Recipient = m_api->m_data.GetInstById(recipient_id);
	if(Recipient == 0) notifi_with_excess = false; 


	CaplInstance *doc=0;
	CString doc_id,rev_id,msg,sfunction = function;
	if(inst==0)
	{
		msg.Format(_T("Function=%s doc=UNKNOWN rev=UNKNOWN inst_rev=0 path=\"%s\""),function, fpath);
	}
	else
	{
		if(m_api->m_data.IsKindOf(inst,m_api->m_doc_mgr.e_doc))
		{
			doc = inst;
			rev_id = _T("active");
		}
		else if(m_api->m_data.IsKindOf(inst,m_api->m_doc_mgr.e_apl_doc_rev))
		{
			m_api->m_data.GetAttr(inst,m_api->m_doc_mgr.a_apl_doc_rev_doc,doc);
			m_api->m_data.GetAttr(inst,m_api->m_doc_mgr.a_apl_doc_rev_id,rev_id);
		}
		if(doc!=0)
			m_api->m_data.GetAttr(doc,m_api->m_doc_mgr.a_doc_id,doc_id);
		else
			doc_id=_T("");
		
		msg.Format(_T("Function=%s doc=\"%s\" rev=\"%s\" inst_rev=%i path=\"%s\""),
							function, LPCTSTR(doc_id),LPCTSTR(rev_id),inst==0?0:inst->GetId(),fpath);
	}
	if(doc!= 0 && (sfunction==_T("LoadRevision") || sfunction==_T("CopyDocsOnDisk") || sfunction==_T("CopyDocOnDisk") || 
		sfunction==_T("RecursiveCopyDocs") || sfunction==_T("CCompareFoldersDlg") || sfunction==_T("CaplExchangeManager")))
	{
		CString subj,content,tmp;
		COleDateTime odt;
		CaplInstance *person;
		long num_readed = 0;
		aplExtent items;

		m_api->m_data.NET_ControlAccessDocAndWriteLog(doc,num_readed,DocLogName,msg,true);
		// сообщения посылаем не при каждом превышении, а раз <интервал контроля>. Иначе при выгрузке пакета документов получатель утонет в спаме
		if(notifi_with_excess && (num_readed > NumDocInClock) && (GetTickCount() > tick_last_doc_excess + 1000*60*m_NumMinutes))
		{	
			tick_last_doc_excess = GetTickCount();

			CString sPersonName;
			person = m_api->m_appr_mgr.GetCurrentPerson();
			if(0==person) content +=APL_T("не задан.");
			else
			{	BOOL bOld=m_api->m_show.m_PersonId;
				m_api->m_show.m_PersonId=false;
				m_api->m_appr_mgr.GetPersonName(person,sPersonName,false);
				m_api->m_show.m_PersonId=bOld;
			}

			subj = APL_T("Оповещение: сотрудник ")+ sPersonName + APL_T(" (пользователь БД  \"") + m_api->m_data.GetNameCurrUser() + APL_T("\") превысил лимит просмотра документов");
			m_api->m_data.NET_GetServerDateTime(odt);
			content = odt.Format(_T(" %d.%m.%Y  %H:%M:%S"));
			content += APL_T("\n Пользователь: ") + m_api->m_data.GetNameCurrUser();
			content += APL_T("\n Сотрудник: ");
			content += sPersonName;
			content += APL_T("\n БД: ") + m_api->m_data.GetNameCurrBase();
			tmp.Format(_T("%i"),num_readed);
			content += APL_T("\n Количество взятых документов: ") + tmp;
			m_api->m_data.GetCompName(tmp);
			content += APL_T("\n Компьютер: ") + tmp;

			CaplInstance *msg=m_api->m_message_mgr.CreateMessage((CaplInstance*)(-1),Recipient,subj,content,items,1,_T("sendet"),false,true);
			m_api->SaveChanges();
		}
	}
	else
	{
		m_api->m_data.NET_WriteLog(DocLogName,msg,true);
	}
}


bool CaplDocManager::ViewESI(CaplInstance *doc_or_revision)
{
	if(0==doc_or_revision) return false;
	if(doc_or_revision->GetAccessmode()>aplRO) {AfxMessageBox(S::NoAccessRight(),MB_ICONSTOP|MB_OK); return false;}

	CaplInstance *doc=0, *rev=0, *stor;

	if(m_api->m_data.IsKindOf(doc_or_revision,e_doc))
	{
		doc=doc_or_revision;
		m_api->m_data.GetAttr(doc,a_apl_doc_active,rev);

	}
	else if(m_api->m_data.IsKindOf(doc_or_revision,e_apl_doc_rev))
	{
		rev=doc_or_revision;
		m_api->m_data.GetAttr(rev,a_apl_doc_rev_doc,doc);
	}
	else return false;

	if(doc->GetAccessmode()>aplRO) {AfxMessageBox(APL_T("Нет доступа к документу!"),MB_ICONSTOP|MB_OK); return false;}
	if(rev->GetAccessmode()>aplRO) {AfxMessageBox(APL_T("Нет доступа к версии!"),MB_ICONSTOP|MB_OK); return false;}

	CString buf;
	m_api->m_data.GetAttr(doc, a_apl_doc_system, buf );

	if(buf!=_T("GenerateESI")) {AfxMessageBox(APL_T("Документ не является ЭСИ!"),MB_ICONSTOP|MB_OK); return false;}

	m_data->GetAttr(rev,a_apl_doc_rev_access_form,stor);

	if(!m_data->IsKindOf(stor,e_apl_stored_document)) {AfxMessageBox(APL_T("Документ не сохранен в БД!"),MB_ICONSTOP|MB_OK); return false;}


	long fsize;
	m_api->m_data.NET_GetBlobSize(stor, a_apl_stored_document_source, fsize);

	if(0==fsize) {AfxMessageBox(APL_T("Документ пустой!"),MB_ICONSTOP|MB_OK); return false;}

	BYTE *fbuf=new BYTE[fsize+1];
	if(!m_api->m_data.NET_LoadBlob2Memory(stor, a_apl_stored_document_source, fbuf,fsize))
	{
		delete fbuf; AfxMessageBox(APL_T("Ошибка чтения файла из БД!"),MB_ICONSTOP|MB_OK); return false;
	}
	fbuf[fsize]=_T('\0');

	CaplDataBuf dbuf;  dbuf.SetExternalData(fbuf,fsize);

	CaplStepData std;
	std.ApploadFromDataBuf(dbuf);
	delete fbuf;

	aplP21Header header;
	CString sDataBuf;
	if(!std.SaveP21ToDataBuf(sDataBuf,header,aplWIN,true)) {AfxMessageBox(APL_T("Ошибка сохранения файла!"),MB_ICONSTOP|MB_OK); return true;}
	aplShowBigMsg(sDataBuf,APL_T("Содержание ЭСИ в виде обменного файла"));
	return true;
}


int CaplDocManager::CompareRevisionWithFile(CaplInstance *doc_or_rev, LPCTSTR file_path)
{
	if(0==m_api || 0==doc_or_rev || 0==file_path) return -1;
	if(file_path[0]==_T('\0')) return -1;

	CaplInstance *rev=0;
	if(m_api->m_data.IsKindOf(doc_or_rev,e_apl_doc_rev)) rev=doc_or_rev;
	else if(m_api->m_data.IsKindOf(doc_or_rev,e_doc)) m_api->m_data.GetAttr(doc_or_rev,a_apl_doc_active,rev);
	else return -1;
	if(0==rev) return -1;

	// размер файла версии
	long rev_size;
	CaplInstance *ciSource;
	m_api->m_data.GetAttr(rev, a_apl_doc_rev_access_form, ciSource);
	if(0==ciSource) return -1;
	m_api->m_data.NET_GetBlobSize(ciSource, a_apl_stored_document_source, rev_size);

	// размер файла
	CFile file;
	if(!file.Open(file_path,CFile::modeRead|CFile::shareDenyWrite)) return -1;
	long fsize=(long)file.GetLength();

	if(fsize!=rev_size) {file.Close(); return 1;}


	/*int crc_rev, crc_file;
	m_api->m_data.GetAttr(rev,m_api->m_doc_mgr.a_apl_doc_rev_crc,crc_rev);
	crc_file=GetFileCRC32(file_path);
	if(crc_rev!=crc_file) return 1;*/
	
	// Т.к. вероятность совпадения crc не нулевая - сравниваем фафлы

	char *mem_file=new char[fsize];
	file.Read(mem_file,fsize);
	file.Close();


	char *mem_rev=new char[rev_size];
	m_api->m_data.NET_LoadBlob2Memory(ciSource, a_apl_stored_document_source, (BYTE*)mem_rev,rev_size);

	int i;
	bool bEqu=true;
	for(i=0;i<fsize;i++)
	{
		if(mem_file[i]!=mem_rev[i]) {bEqu=false; break;}
	}

	delete mem_file;
	delete mem_rev;
	
	if(bEqu) return 0;
	return 1;
}

//*************************************************************************************
// Читает реквизиты из файла реквизитов
bool CaplDocManager::LoadRequisiteFromFile(LPCTSTR sFileName, CaplStrStrMap &mapRequisite)
{
	mapRequisite.Clear();
	if(0==sFileName) return false;
	if(_T('\0')==sFileName[0]) return false;

	CaplStringFile reqfile;
	if(!reqfile.Open(sFileName,CaplFile::modeRead)) return false;

	int i;
	CString sBuf,sLine,sWord0,sWord1,sWord2;
	while(reqfile.ReadString(sLine))
	{
		i=0;
		if(!aplGetWord(sLine,i,sWord0)) continue;
		if(sWord0==_T(""))continue;
		if(!aplGetWord(sLine,i,sWord1)) continue;
		if(sWord1!=_T('='))continue;

		sWord0.TrimRight(_T('"'));
		sWord0.TrimLeft(_T('"'));

		sWord2=sLine.Right(sLine.GetLength()-i);
		sWord2.TrimRight();
		sWord2.TrimLeft();

		if(sWord2==_T(""))continue;

		// удаляем кавычки у учетом пропущенной в конце

		if(sWord2[0]==_T('"'))
		{
			sWord2.Delete(0,1);
			bool b=false;
			for(i=0;i<sWord2.GetLength();i++) {if(sWord2[i]==_T('"')) b=!b;}

			if(b && sWord2[sWord2.GetLength()-1]) 
				sWord2.Delete(sWord2.GetLength()-1,1);
		}
			
		sWord2.TrimRight();
		sWord2.TrimLeft();

		if(sWord0!=_T("") && sWord1!=_T("")) 
			mapRequisite.Add(sWord0,sWord2);
	}
	reqfile.Close();
	return true;
}

//*************************************************************************************

bool  CaplDocManager::SaveRequisiteToRevision(CaplInstance *rev, CaplStrStrMap &mapRequisite, bool  bAddNewReqToDocType)
{
	if(0==rev) return false;
	if(rev->GetAccessmode()>aplRW) return false;
	if(!m_api->m_data.IsKindOf(rev,e_apl_doc_rev)) return false;
	if(0==mapRequisite.GetSize()) return true;


	CaplInstance *instDoc=0, *instDocType=0, *instActRev=0;
	if(bAddNewReqToDocType)
	{
		m_api->m_data.GetAttr(rev, a_apl_doc_rev_doc, instDoc);
		if(0!=instDoc)
		{
			m_api->m_data.GetAttr(instDoc, a_doc_kind, instDocType);
			m_api->m_data.GetAttr(instDoc, a_apl_doc_active, instActRev);
		}
	}

	int i;
	CString sName;
	for(i=0;i<mapRequisite.GetSize();i++)
	{
		CaplStrStrMap::CaplStrStrMapItem *mi=mapRequisite.GetAt(i);
		if(mi->str==_T("") || mi->val==_T("")) continue;
		sName=mi->str;
		sName.MakeLower();
		//if(sName==_T("обозначение") || sName==_T("наименование")|| sName==_T("вид")) continue;
		if(sName==_T("версия"))
		{
			m_api->m_data.PutAttr(rev, a_apl_doc_rev_id, mi->val);
			//continue;
		}
		if(sName==_T("литера")) m_api->m_data.PutAttr(rev, a_apl_doc_rev_litera, mi->val);
		else if(sName==_T("формат")) m_api->m_data.PutAttr(rev, a_apl_doc_rev_format, mi->val);
		else if(sName==_T("метка")) m_api->m_data.PutAttr(rev, a_apl_doc_rev_label, mi->val);

		CaplInstance *entry=GetEntryBN(mi->str);
		if(0==entry)
		{
			entry = m_api->m_data.CreateInstance(e_entry);
			m_api->m_data.PutAttr(entry, a_entry_name,  mi->str);	

			if(bAddNewReqToDocType && 0!=instDocType) AddEntryToDocType(entry, instDocType);
		}

		CreateEntryVal(rev,mi->str,mi->val,false);
	}
	if(rev==instActRev)	FromEntryValToDoc(instActRev);

	return true;
}

//*********************************************************************************************
bool CaplDocManager::LoadKdFields(CaplInstance *rev, CaplStrStrMap &map_params)
{
	if(0==rev) return false;
	if(rev->GetAccessmode()>aplRO) return false;
	if(!m_api->m_data.IsKindOf(rev,e_apl_doc_rev)) return false;

	CString sVerId,sLitera;
	m_api->m_data.GetAttr(rev,a_apl_doc_rev_id, sVerId);
	if(sVerId!=_T("")) map_params.Add(_T("ver_id"), sVerId);

	m_api->m_data.GetAttr(rev,a_apl_doc_rev_litera, sLitera);
	if(sLitera!=_T("")) map_params.Add(_T("litera"), sLitera);

	return true;
}