// CategoryManager.cpp

#include "stdafx.h"
#include "apl_api.h"
#include "dictionary.h"
#include "SelectInstDlg.h"
#include "ContextsDlg.h"
#include "CategoryDiffDlg.h"
#include "DataTimeDlg.h"
#include "StrValueDlg.h" 
#include "htmlGen.h"
#include "WFSHistoryDlg.h"
#include "SelectWFSDlg.h"
#include "NoteDlg.h"
#include "SelectNoteDlg.h"
#include "SelectPrdInstDlg.h"
#include "SelectInstanceDlgEx.h"
#include "DlgListInstances.h"
#include "AboutKatalitDlg.h"
#include "SelectInstanceView.h"
#include "EditExtentDlg.h"


#define DEFAILT_ID_ADMIN_GROUP 3901
#define DEFAILT_ID_ADMIN		3902


bool CaplStepManager::m_bUseVersions=true;

CaplStepManager::CaplStepManager()
{
	m_api=0;
	m_AutoSave=true;
	m_AutoUsurpire=true;	
	//m_ModeInteractive=true;
	m_AllAttrDefined=true;
	m_TestUnique= true;
	Detach();
	m_old_items.Clear();
	m_MaxItemsLoad=1000;
}

CaplStepManager::~CaplStepManager()
{
	CSelectInstanceView::ClearRestoreData();
}

//*************************************************************
bool CaplStepManager::Attach(CaplAPI *api)
{
	m_AllAttrDefined=true;
	if(api==0) {Detach();return false;}
	m_api=api;
	m_data=&(api->m_data);
	m_old_items.Clear();

	m_bContinue=0;

	CHECK_ZERO_ATTR(e_pd_context,m_data->GetEntityBN(_T("product_definition_context")));
	CHECK_ZERO_ATTR(a_pd_context_name,m_data->GetAttrDefinition(e_pd_context,S::name));
	CHECK_ZERO_ATTR(a_pd_context_life_cycle_stage,m_data->GetAttrDefinition(e_pd_context,_T("life_cycle_stage")));

	CHECK_ZERO_ATTR(e_wf_state_history,m_data->GetEntityBN(_T("apl_workflow_state_history")));
	CHECK_ZERO_ATTR(a_wf_new_state,m_data->GetAttrDefinition(e_wf_state_history,_T("new_state")));
	CHECK_ZERO_ATTR(a_wf_old_state,m_data->GetAttrDefinition(e_wf_state_history,_T("old_state")));
	CHECK_ZERO_ATTR(a_wf_date,m_data->GetAttrDefinition(e_wf_state_history,_T("date")));
	CHECK_ZERO_ATTR(a_wf_item,m_data->GetAttrDefinition(e_wf_state_history,_T("item")));
	CHECK_ZERO_ATTR(a_wf_user,m_data->GetAttrDefinition(e_wf_state_history,_T("user")));
	CHECK_ZERO_ATTR(e_note,m_data->GetEntityBN(_T("apl_note")));
	CHECK_ZERO_ATTR(a_note_item,m_data->GetAttrDefinition(e_note,_T("item")));
	CHECK_ZERO_ATTR(a_note_author,m_data->GetAttrDefinition(e_note,_T("author")));
	CHECK_ZERO_ATTR(a_note_date,m_data->GetAttrDefinition(e_note,_T("date")));
	CHECK_ZERO_ATTR(a_note_date_revocation,m_data->GetAttrDefinition(e_note,_T("date_revocation")));
	CHECK_ZERO_ATTR(a_note_source,m_data->GetAttrDefinition(e_note,_T("source")));
	CHECK_ZERO_ATTR(a_note_descr,m_data->GetAttrDefinition(e_note,_T("description")));
	CHECK_ZERO_ATTR(a_note_parent,m_data->GetAttrDefinition(e_note,_T("parent")));
	CHECK_ZERO_ATTR(a_note_markup,m_data->GetAttrDefinition(e_note,_T("markup")));
	CHECK_ZERO_ATTR(a_note_approval,m_data->GetAttrDefinition(e_note,_T("approval")));
	CHECK_ZERO_ATTR(a_note_nohide,m_data->GetAttrDefinition(e_note,_T("no_hide")));

	CHECK_ZERO_ATTR( e_apl_object_locker, m_data->GetEntityBN(_T("apl_object_locker")) );
	CHECK_ZERO_ATTR( a_apl_object_locker_user, m_data->GetAttrDefinition( e_apl_object_locker, _T("user") ) );
	CHECK_ZERO_ATTR( a_apl_object_locker_item, m_data->GetAttrDefinition( e_apl_object_locker, _T("item") ) );
	CHECK_ZERO_ATTR( a_apl_object_locker_description, m_data->GetAttrDefinition( e_apl_object_locker, _T("description") ) );

	CHECK_ZERO_ATTR(e_alt_bidir, m_data->GetEntityBN(_T("alternate_product_relationship_bidirect")));
	CHECK_ZERO_ATTR(a_alt_bidir_type, m_data->GetAttrDefinition(e_alt_bidir,_T("type")));
	CHECK_ZERO_ATTR(a_alt_bidir_type_descr, m_data->GetAttrDefinition(e_alt_bidir,_T("type_descr")));
	CHECK_ZERO_ATTR(a_alt_bidir_reserved, m_data->GetAttrDefinition(e_alt_bidir,_T("reserved")));
	CHECK_ZERO_ATTR(a_alt_base_pdf, m_data->GetAttrDefinition(e_alt_bidir,_T("base_pdf")));
	CHECK_ZERO_ATTR(a_alt_alt_pdf, m_data->GetAttrDefinition(e_alt_bidir,_T("alt_pdf")));
	CHECK_ZERO_ATTR(a_alt_alt_interchange_type, m_data->GetAttrDefinition(e_alt_bidir, _T("interchange_type")));	

	return true;
}
void CaplStepManager::Detach()
{
	m_data=0;
	e_pd_context=0;
	a_pd_context_name=0; a_pd_context_life_cycle_stage=0;

	m_bContinue=0;

	CSelectInstanceView::ClearRestoreData();
}; 
 
bool CaplStepManager::GetListTopLevelEntities(TUListPEntity &list_entities)
{
	list_entities.Clear();
	if(m_api==0) {return false;}

	list_entities.Add(m_api->m_prd_mgr.e_prd);
	list_entities.Add(m_api->m_prd_mgr.e_pdf);
	list_entities.Add(m_api->m_prd_mgr.e_apl_pdf);
	list_entities.Add(m_api->m_doc_mgr.e_doc);
	list_entities.Add(m_api->m_doc_mgr.e_apl_doc_rev);
	list_entities.Add(m_api->m_prd_inst_mgr.e_lot);
	list_entities.Add(m_api->m_prd_inst_mgr.e_prd_inst);
	list_entities.Add(m_api->m_bp_mgr.e_bp);
	list_entities.Add(m_api->m_bp_mgr.e_apl_bp_ver);
	list_entities.Add(m_api->m_bp_mgr.e_apl_bp_inst);
	list_entities.Add(m_api->m_categ_mgr.e_categ);
	list_entities.Add(m_api->m_folder_mgr.e_folder);
	list_entities.Add(m_api->m_query_mgr.e_apl_query);
	list_entities.Add(m_api->m_query_mgr.e_apl_ct);
	list_entities.Add(m_api->m_change_mgr.e_chng);
	list_entities.Add(m_api->m_charact_mgr.e_apl_charact);
	list_entities.Add(m_api->m_appr_mgr.e_person);
	list_entities.Add(m_api->m_appr_mgr.e_org);
	list_entities.Add(m_api->m_appr_mgr.e_apl_user);
//	list_entities.Add(m_api->m_appr_mgr.e_org);
	list_entities.Add(m_api->m_project_mgr->e_project);
	list_entities.Add(m_api->m_classifier_mgr.e_apl_classifier_system);
	list_entities.Add(m_api->m_classifier_mgr.e_apl_classifier_level);
	list_entities.Add(m_api->m_data.GetEntityBN(_T("apl_action_instance")));
	list_entities.Add(m_api->m_req_mgr.e_requirement);
	list_entities.Add(m_api->m_message_mgr.e_message);
	if (NULL != m_api->m_expl_mgr)
	{
		list_entities.Add(m_api->m_expl_mgr->e_apl_refusal);
	}
	

	// ВНИМАНИЕ! При обновлении списка не забыть поменять 
	// 1) CInstPropertyCtrl::InitAvailableColumns() 
	// 2) CaplAPI::ShowItemProperties
	//	! Или сообщить ДИВ-у
	list_entities.Sort();
	
	return true;
}

CaplInstance* CaplStepManager::GetCurrentPerson()
{
	if(!m_data) return NULL;
	if(!m_api->m_data.IsDictLoad()) return NULL;
	
	CaplInstance* person= NULL;
	CaplInstance* inst= m_data->GetCurrUser();

	if(inst)
	{
		CaplInstance* po= NULL;
		m_data->GetAttr(inst, m_api->m_appr_mgr.a_apl_user_po, po);
		if(po && m_data->IsKindOf(po, m_api->m_appr_mgr.e_pers_org))
		{
			if(po->attrs==NULL)
				m_api->LoadItemInfo(po);
			m_data->GetAttr(po, m_api->m_appr_mgr.a_po_the_pers, person);	
		}
		else if(po && m_data->IsKindOf(po, m_api->m_appr_mgr.e_person))
			person = po;

		if (person && person->attrs == NULL)
			m_api->LoadItemInfo(po);
	}

	return person;
}

bool CaplStepManager::LoadContextInfo()
{
	if(m_data==0) return false;
	if(e_pd_context==0) return false;
	if(!m_data->IsConnected())return false;
	// Чтение категорий
	int i;
	if(m_data->IsConnected())
	{
		CaplLoadData ld(m_data,DEF_SOURCE);
		// ссылка
		i=	ld.AddQuery(_T('e'), 0, e_pd_context, 0, true);
			ld.AddQuery(_T('d'), i, 0, a_pd_context_name, true);
			ld.AddQuery(_T('d'), i, 0, a_pd_context_life_cycle_stage, true);

		if(!ld.LoadEx(true,0, APL_T("Чтение контекстов")))
		{
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка чтения информации о контекстах (APL)"),MB_OK|MB_ICONSTOP);
			return false;
		}
	}
	return true;
}
//*******************************************************************************
bool CaplStepManager::ChangeItemContext(aplExtent &ext)
{
	CaplSetResourceHandle setres(module_inst);
	bool ret=false;
	CContextsDlg dlg;
	dlg.m_aggr=&ext;
	dlg.m_mgr=this;
	if(dlg.DoModal()==IDOK) ret=true;
	return ret;
}

void CaplStepManager::Split(const CString &str, CString devider, std::vector<CString> &result, bool bParseAsCsv /*= false*/)
{
	result.clear();
	
	CString word;
	bool bQuotesBegin = false;

	for(int i=0; i<str.GetLength(); ++i)
	{
		if(str[i] == devider)
		{
			// если кавычки еще не закрывались
			if(bQuotesBegin)
			{
				word += str[i];
				continue;
			}

			result.push_back(word);
			word.Empty();
		}
		else
		{
			if(bParseAsCsv && str[i] == _T('\"'))
			{
				// пришла закрывающая пара кавычек
				if(bQuotesBegin)
				{
					bQuotesBegin = false;
				}
				// кавычки только открываются
				else
				{
					bQuotesBegin = true;
				}				
			}
			else
			{
				word += str[i];
			}			
		}
	}

	result.push_back(word);
}

//*******************************************************************************
bool CaplStepManager::PrintItemContextInString(CaplInstance *item,CString &buf)
{
	buf=_T("");
	if(item==0) return false;
	if(item==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if(item->GetType()==0) return false;
	if(item->GetAccessmode()>aplRW)
	{
		if(m_api->m_ModeInteractive)aplErrorMessage(S::NoAccessRight(),item);
		return false;
	}
	
	aplExtent aggr;
	m_data->GetAttrBN(item,_T("apl_frames_of_reference"),aggr);
	return PrintItemContextInString(aggr,buf);
}

bool CaplStepManager::PrintItemContextInString(aplExtent &ext,CString &buf)
{
	buf=_T("");
	CaplInstance *inst;
	CString buf1;
	bool bFirst=true;

	if(ext.GetSize()>0)
	{
		for(int i=0;i<ext.GetSize();i++)
		{
			inst=ext[i];
			if(inst!=0)
			{
				if(!bFirst) buf+=_T(", ");
				m_data->GetAttr(inst,a_pd_context_name,buf1);
				buf+=buf1;
				bFirst=false;
			}
		}
	}
	else
		buf =  APL_T("Все контексты");
	return true;
}
//*******************************************************************************
bool CaplStepManager::IsItemInContext(CaplInstance *item, CaplInstance *context, CaplAttr *attr)
{
	if(item==0) return false;
	if(item==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if(item->GetType()==0) return false;
	if(item->GetAccessmode()>aplRO)return false;
	if(context==0) return true;

	aplExtent aggr;
	if(attr==0) m_data->GetAttrBN(item,_T("apl_frames_of_reference"),aggr);
	else m_data->GetAttr(item,attr,aggr);
	
	int i,k=aggr.GetSize();
	if(k==0) return true;
	for(i=0;i<k;i++)
	{
		if(aggr[i]==context) return true;
	}
	return false;
}
//*******************************************************************************
bool CaplStepManager::FilterExtentByContext(aplExtent &ext_in, aplExtent &ext_contexts, aplExtent &ext_out, CaplAttr *attr)
{
	ext_out.Clear();
	//все контексты
	if(!ext_contexts.Size)
	{
		ext_out.Append(ext_in);
		return true;
	}
	//все контексты
	if(ext_in.Size<1)return true;

	int i,j,k;
	aplExtent ext0;

	for(i=0;i<ext_in.Size;i++)
	{
		CaplInstance *item=ext_in[i];

		if(attr==0) m_data->GetAttrBN(item,_T("apl_frames_of_reference"),ext0);
		else m_data->GetAttr(item,attr,ext0);

		if(ext0.Size==0) { ext_out.Add(item); continue;}

		for(j=0;j<ext0.Size;j++)
		{
			CaplInstance *context=ext0[j];
			bool bBreak=false;
			
			for(k=0;k<ext_contexts.Size;k++)
			{
				if(	context==ext_contexts[k])
				{
					ext_out.Add(item);
					bBreak=true;
					break;
				}
			}
			if(bBreak) break;
		}
	}
	return true;
}

//*******************************************************************************
CaplInstance *CaplStepManager::SelectInstanceEx(long SelectMode, const TCHAR *title,  aplExtent *base_items, fnValidateInst fn)
{
	if(m_data==0) return 0;

	if((SelectMode&APL_MODE_SELECT_PERSON)>0 &&
		(SelectMode&APL_MODE_SELECT_PERSORG)>0)
	{
		if(m_api->m_ModeInteractive)MessageBox(NULL,  APL_T("Ошибка в исходных данных.\n\nНельзя выбирать сотрудника и сотрудника организации."),  APL_T("Ошибка"), MB_ICONERROR);
		return NULL;
	}

	CaplSetResourceHandle setres(module_inst);

	CSelectInstanceDlgEx  dlg;
	if(title!=0) dlg.m_sTitle=title;
	dlg.m_api=m_api;
	dlg.m_mode=SelectMode;
	dlg.m_oldOpenedItems=&m_old_items;
	dlg.m_BaseItems= base_items;
	dlg.m_fn = fn;
	CaplInstance *res=0;
	
	if(dlg.DoModal()==IDOK)
		res = dlg.m_SelectedInstances[0];

	return res;
}

bool CaplStepManager::SelectInstanceEx(long SelectMode, aplExtent &res, const TCHAR *title, aplExtent *base_items, fnValidateInst fn)
{
	res.Clear();

	if(m_data==NULL) return false;
	
	if((SelectMode&APL_MODE_SELECT_PERSON)>0 &&
		(SelectMode&APL_MODE_SELECT_PERSORG)>0)
	{
		if(m_api->m_ModeInteractive)MessageBox(NULL,  APL_T("Ошибка в исходных данных.\n\nНельзя выбирать сотрудника и сотрудника организации."),  APL_T("Ошибка"), MB_ICONERROR);
		return false;
	}
	
	CaplSetResourceHandle setres(module_inst);
	
	CSelectInstanceDlgEx  dlg;
	if(title!=0) dlg.m_sTitle=title;
	dlg.m_api=m_api;
	dlg.m_mode=SelectMode;
	dlg.m_oldOpenedItems=&m_old_items;
	dlg.m_BaseItems= base_items;
	dlg.m_fn = fn;
	
	if(dlg.DoModal()==IDOK)
	{
		res.Append(dlg.m_SelectedInstances);
	}
	return res.GetSize()>0;
}

//*******************************************************************************
CaplInstance *CaplStepManager::SelectInstanceEx2(long SelectMode, const TCHAR *title,  aplExtent *base_items, fnValidateInst2 fn, DWORD data)
{
	if(m_data==0) return 0;

	if((SelectMode&APL_MODE_SELECT_PERSON)>0 &&
		(SelectMode&APL_MODE_SELECT_PERSORG)>0)
	{
		if(m_api->m_ModeInteractive)MessageBox(NULL,  APL_T("Ошибка в исходных данных.\n\nНельзя выбирать сотрудника и сотрудника организации."),  APL_T("Ошибка"), MB_ICONERROR);
		return NULL;
	}

	CaplSetResourceHandle setres(module_inst);

	CSelectInstanceDlgEx  dlg;
	if(title!=0) dlg.m_sTitle=title;
	dlg.m_api=m_api;
	dlg.m_mode=SelectMode;
	dlg.m_oldOpenedItems=&m_old_items;
	dlg.m_BaseItems= base_items;
	dlg.m_fn2 = fn;
	dlg.m_data = data;
	CaplInstance *res=0;
	
	if(dlg.DoModal()==IDOK)
		res = dlg.m_SelectedInstances[0];
	
	return res;
}

bool CaplStepManager::SelectInstanceEx2(long SelectMode, aplExtent &res, const TCHAR *title, aplExtent *base_items, fnValidateInst2 fn, DWORD data)
{
	res.Clear();

	if(m_data==NULL) return false;
	
	if((SelectMode&APL_MODE_SELECT_PERSON)>0 &&
		(SelectMode&APL_MODE_SELECT_PERSORG)>0)
	{
		if(m_api->m_ModeInteractive)MessageBox(NULL,  APL_T("Ошибка в исходных данных.\n\nНельзя выбирать сотрудника и сотрудника организации."),  APL_T("Ошибка"), MB_ICONERROR);
		return false;
	}
	
	CaplSetResourceHandle setres(module_inst);
	
	CSelectInstanceDlgEx  dlg;
	if(title!=0) dlg.m_sTitle=title;
	dlg.m_api=m_api;
	dlg.m_mode=SelectMode;
	dlg.m_oldOpenedItems=&m_old_items;
	dlg.m_BaseItems= base_items;
	dlg.m_fn2 = fn;
	dlg.m_data = data;
	
	if(dlg.DoModal()==IDOK)
	{
		res.Append(dlg.m_SelectedInstances);
	}
	
	return res.GetSize()>0;
}

CaplInstance *CaplStepManager::SelectInstance(long SelectMode, const TCHAR *title,  aplExtent *base_items, fnValidateInst fn)
{
	return SelectInstanceEx(SelectMode, title, base_items,fn);
	
	if(m_data==0) return 0;

	if((SelectMode&APL_MODE_SELECT_PERSON)>0 &&
		(SelectMode&APL_MODE_SELECT_PERSORG)>0)
	{
//		MessageBox(NULL, APL_T("Ошибка в исходных данных.\n\nНельзя выбирать сотрудника и сотрудника организации."), APL_T("Ошибка"), MB_ICONERROR);
		return NULL;
	}
	
	CaplSetResourceHandle setres(module_inst);

	CSelectInstDlg  dlg;
	if(title!=0) dlg.m_title=title;
	dlg.m_api=m_api;
	dlg.m_mode=SelectMode;
	dlg.m_old_items=&m_old_items;
	dlg.m_base_items=base_items;
	CaplInstance *res=0;
	
	//bool bMode= m_data->GetAutoDownloadMode();
	//	m_data->SetAutoDownloadMode(true);
	if(dlg.DoModal()==IDOK)res=dlg.m_sel_inst;
	//	m_data->SetAutoDownloadMode(bMode);
	
	return res;
}

bool CaplStepManager::EditExtent(long SelectMode, aplExtent &ext, const TCHAR *title, const TCHAR *list_title, CaplInstance *sprav)
{
	CaplSetResourceHandle setres(module_inst);

	CEditExtentDlg  dlg;
	if(title!=0) dlg.m_title=(TCHAR*)title;
	if(list_title!=0) dlg.m_list_title=(TCHAR*)list_title;
	dlg.m_api=m_api;
	dlg.m_SelectMode=SelectMode;
	dlg.m_ext=ext;
	dlg.m_sprav=sprav;

	bool res=false;
	if(dlg.DoModal()==IDOK)
	{
		res=true;
		ext=dlg.m_ext;
	}
	return res;
}


bool CaplStepManager::GetItemName(CaplInstance * item, CString &buf)
{
	buf=_T("");
	if(m_api==0) return false;
	return(m_api->GetItemName(item,buf));
}

bool CaplStepManager::LoadExtentInfo(aplExtent &ext){
	if(m_data==0) return false;
	if(m_api==0) return false;
	return(m_api->LoadExtentInfo(ext));
}

/**	Ищет блокиратор для инстанса
@param pInst проверяемый инстанс
@return NULL если не нашли*/
CaplInstance* CaplStepManager::FindLockInstance(const CaplInstance* pInst)
{
	const int attrCount = 1;

	CaplAttrValue val[ attrCount ];

	val[0].attr = a_apl_object_locker_item ;

	CaplInstance* pInstttt = const_cast<CaplInstance*>( pInst ); // нет константной перегрузки
	val[0].value.Set( pInstttt );

	aplExtent extOut;

	if ( m_data->NET_FindInstancesWithAttrValues(e_apl_object_locker, attrCount, val, extOut, false) )
	{
		ASSERT( extOut.GetSize() < 2 );

		if ( extOut.GetSize() == 0 )
			return NULL;

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

		return extOut[0] ;
	}

	return 0;
}

/**	Проверяет заблокировн ли инстанс для редактирования
@param pInst проверяемый инстанс
@return true при заблокированности*/
bool CaplStepManager::IsInstanceLocked( const CaplInstance* pInst)
{
	if ( FindLockInstance(pInst) != NULL )
		return true;

	return false;
}

/**	Блокирует инстанс
@param pInst блокируемый инстанс
@param pUser пользователь
@param message причина лока
@return Указатель на созданный инстанс при успехе*/
CaplInstance* CaplStepManager::SetInstanceLocked(const CaplInstance* pInst, const CaplInstance* pUser, const CString& description /* = _T("") */ )
{
	if ( !IsInstanceLocked( pInst ) )
	{
		CaplInstance *pNewItem = m_data->CreateInstance( e_apl_object_locker );

		m_data->PutAttr( pNewItem, a_apl_object_locker_item, const_cast<CaplInstance*>( pInst ) );
		m_data->PutAttr( pNewItem, a_apl_object_locker_user, const_cast<CaplInstance*>( pUser ) );
		m_data->PutAttr( pNewItem, a_apl_object_locker_description, description );

		if ( m_AutoSave ) m_data->NET_SaveChanges();

		return pNewItem;
	}
	else
	{
		return NULL;
	}

	return NULL;
}

/**	Получает информацию о заблокированном инстансе
@param pInst инстанс
@param pUser пользователь
@param message причина лока
@return true при успехе*/
bool CaplStepManager::GetLockInfo(const CaplInstance* pInst, CaplInstance** ppUser, CString *pDescription /* = NULL */ )
{
	const int attrCount = 1;

	CaplAttrValue val[ attrCount ];

	val[0].attr = a_apl_object_locker_item ;
	val[0].value.Set( const_cast<CaplInstance*>(pInst) );

	aplExtent extOut;

	if ( m_data->NET_FindInstancesWithAttrValues(e_apl_object_locker, attrCount, val, extOut, false) )
	{
		if ( extOut.GetSize() == 0 )
		{
			return false;
		}

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

		if ( ppUser )
		{
			m_data->GetAttr( extOut[0], a_apl_object_locker_user, *ppUser );
		}

		if ( pDescription )
		{
			m_data->GetAttr( extOut[0], a_apl_object_locker_description, *pDescription );
		}

		return true;
	}

	return false;
}

/**	Разблокирует инстанс
@param pInst блокируемый инстанс
@return Указатель на созданный инстанс при успехе*/
bool CaplStepManager::SetInstanceUnLocked(const CaplInstance* pInst )
{
	const int attrCount = 1;

	CaplAttrValue val[ attrCount ];

	val[0].attr = a_apl_object_locker_item ;

	CaplInstance* pInstttt = const_cast<CaplInstance*>( pInst ); // нет константной перегрузки
	val[0].value.Set( pInstttt );

	aplExtent extOut;

	if ( m_data->NET_FindInstancesWithAttrValues( e_apl_object_locker, attrCount, val, extOut, false) )
	{
		if ( extOut.GetSize() == 0 )
		{
			return false;
		}

		ASSERT( extOut.GetSize() <= 1 );

		m_data->DeleteInstance( extOut[0] );

		if ( m_AutoSave ) m_data->NET_SaveChanges();

		return true;
	}

	return false;
}


//*************************************************************
bool CaplCategoryManager::Attach(CaplAPI *api)
{
	if(api==0) {Detach();return false;}
	//m_data=data;
	CaplStepManager::Attach(api);
	e_categ=m_data->GetEntityBN(S::product_category);
	a_categ_id=m_data->GetAttrDefinition(e_categ,S::id);
	a_categ_name=m_data->GetAttrDefinition(e_categ,S::name);
	a_categ_descr=m_data->GetAttrDefinition(e_categ,S::description);

	e_prd_rel_prd_categ=m_data->GetEntityBN(S::prd_rel_prd_cat);
	a_categ_products=m_data->GetAttrDefinition(e_prd_rel_prd_categ,S::products);
	CHECK_ZERO_ATTR(a_categ_charact,m_data->GetAttrDefinition(e_prd_rel_prd_categ,_T("characteristics")));
	CHECK_ZERO_ATTR(a_categ_all_charact,m_data->GetAttrDefinition(e_prd_rel_prd_categ,_T("all_characteristics")));

	e_categ_rel=m_data->GetEntityBN(S::product_category_relationship);
	a_categ_rel_category=m_data->GetAttrDefinition(e_categ_rel,S::category);
	a_categ_rel_sub_category=m_data->GetAttrDefinition(e_categ_rel,S::sub_category);

	e_apl_product_category_ver=m_data->GetEntityBN(_T("apl_product_category_version"));
	if(e_apl_product_category_ver!=0)
	{
		a_categ_ver_categ=m_data->GetAttrDefinition(e_apl_product_category_ver,_T("category"));
		a_categ_ver_id=m_data->GetAttrDefinition(e_apl_product_category_ver,_T("id"));
		a_categ_ver_name=m_data->GetAttrDefinition(e_apl_product_category_ver,_T("name"));
		a_categ_ver_descr=m_data->GetAttrDefinition(e_apl_product_category_ver,_T("description"));
		a_categ_ver_products=m_data->GetAttrDefinition(e_apl_product_category_ver,_T("products"));
		a_categ_ver_author=m_data->GetAttrDefinition(e_apl_product_category_ver,_T("author"));
		a_categ_ver_start=m_data->GetAttrDefinition(e_apl_product_category_ver,_T("start_date"));
		a_categ_ver_end=m_data->GetAttrDefinition(e_apl_product_category_ver,_T("end_date"));
		a_categ_ver_num=m_data->GetAttrDefinition(e_apl_product_category_ver,_T("number")); 
		a_categ_ver_prev=m_data->GetAttrDefinition(e_apl_product_category_ver,_T("previous")); 
		a_categ_act=m_data->GetAttrDefinition(e_categ,_T("active_version"));
		a_categ_lock=m_data->GetAttrDefinition(e_categ,_T("locker"));
	}

	e_categ_content= m_data->GetEntityBN(_T("apl_aggr_option"));
	if(e_categ_content)
	{
		a_categ_content_id= m_data->GetAttrDefinition(e_categ_content, _T("name"));
		a_categ_content_content= m_data->GetAttrDefinition(e_categ_content, _T("val"));
	}

	e_local_query = m_data->GetEntityBN(_T("apl_local_query"));
	if(e_local_query)
	{
		a_local_query_text= m_data->GetAttrDefinition(e_local_query, _T("text"));
		a_local_query_person= m_data->GetAttrDefinition(e_local_query, _T("person"));
		a_local_query_name= m_data->GetAttrDefinition(e_local_query, _T("name"));
		a_local_query_date= m_data->GetAttrDefinition(e_local_query, _T("date"));
	}

	return true;
}

//*************************************************************
void CaplCategoryManager::Detach()
{
	m_data=0;
	e_categ=0; a_categ_id=0; a_categ_name=0; a_categ_descr=0; 
	e_prd_rel_prd_categ=0; a_categ_products=0;
	e_categ_rel=0; a_categ_rel_category=0; a_categ_rel_sub_category=0;

	e_apl_product_category_ver=0;
	a_categ_ver_categ=0; a_categ_ver_id=0; a_categ_ver_name=0; a_categ_ver_descr=0; a_categ_ver_products=0;
	a_categ_ver_author=0; a_categ_ver_start=0; a_categ_ver_end=0; a_categ_ver_num=0; 
	a_categ_act=0; a_categ_lock=0;

	e_local_query = 0;
	a_local_query_person = 0;
	a_local_query_text = 0;
	a_local_query_name = 0;
	a_local_query_date = 0;
}
//*************************************************************
bool CaplCategoryManager::Load(bool load_products)
{
	if(m_data==0) return false;
	if(e_categ==0) return false;
	if(!m_data->IsConnected())return false;
	// Чтение категорий
	int i;//,j,k;
	if(m_data->IsConnected())
	{
		CaplLoadData ld(m_data,DEF_SOURCE);
		// ссылка
		i=	ld.AddQuery(_T('e'), 0, e_categ, 0, true);
			ld.AddQuery(_T('d'), i, 0, a_categ_id, true);
			ld.AddQuery(_T('d'), i, 0, a_categ_name, true);
			ld.AddQuery(_T('d'), i, 0, a_categ_descr, true);
			if(load_products)
				ld.AddQuery(_T('d'), i, 0, a_categ_products, true);
/*			if(a_categ_lock!=0)
			{
				j=ld.AddQuery(_T('d'), i, 0, a_categ_lock, true);
				  ld.AddQuery(_T('d'), j, 0, a_categ_ver_categ, true);
				  ld.AddQuery(_T('d'), j, 0, a_categ_ver_id, true);
				  ld.AddQuery(_T('d'), j, 0, a_categ_ver_name, true);
				  ld.AddQuery(_T('d'), j, 0, a_categ_ver_descr, true);
				  ld.AddQuery(_T('d'), j, 0, a_categ_ver_products, true);
				  k=ld.AddQuery(_T('d'), j, 0, a_categ_ver_author, true);
				  ld.AddQuery(_T('d'), j, 0, a_categ_ver_start, true);
				  ld.AddQuery(_T('d'), j, 0, a_categ_ver_end, true);
				  ld.AddQuery(_T('d'), j, 0, a_categ_ver_num, true);
				  ld.AddQuery(_T('d'), k, 0, m_api->m_appr_mgr.a_apl_user_name, true);
				  ld.AddQuery(_T('d'), k, 0, m_api->m_appr_mgr.a_apl_user_po, true);
			}*/
		i=	ld.AddQuery(_T('e'), 0, e_categ_rel, 0, true);
			ld.AddQuery(_T('d'), i, 0, a_categ_rel_category, true);
			ld.AddQuery(_T('d'), i, 0, a_categ_rel_sub_category, true);

		if(!ld.LoadEx(true,0, APL_T("Чтение категорий")))
		{
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка чтения информации о категориях (APL)"),MB_OK|MB_ICONSTOP);
			return false;
		}
	}
	return true;
}
//*************************************************************
bool CaplCategoryManager::GetAllCategoryVersion(CaplInstance *categ,aplExtent &outExt)
{
	outExt.Clear();
	if(e_categ==0) return false;
	if(m_data==0) return false;
	if(categ==0) return false;
	if(categ==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if(categ->GetType()==0) return false;
	int i,j,k;
	if(categ->GetId()!=0)
	{
		if(m_data->IsConnected())
		{
			// Чтение из базы
			CaplLoadData ld(m_data,DEF_SOURCE);
			// документ
			j=ld.AddQuery(_T('b'), categ->GetId(), e_apl_product_category_ver,a_categ_ver_categ, true);
			  ld.AddQuery(_T('d'), j, 0, a_categ_ver_categ, true);
			  ld.AddQuery(_T('d'), j, 0, a_categ_ver_id, true);
			  ld.AddQuery(_T('d'), j, 0, a_categ_ver_name, true);
			  ld.AddQuery(_T('d'), j, 0, a_categ_ver_descr, true);
			  ld.AddQuery(_T('d'), j, 0, a_categ_ver_products, true);
			  k=ld.AddQuery(_T('d'), j, 0, a_categ_ver_author, true);
			  ld.AddQuery(_T('d'), j, 0, a_categ_ver_start, true);
			  ld.AddQuery(_T('d'), j, 0, a_categ_ver_end, true);
			  ld.AddQuery(_T('d'), j, 0, a_categ_ver_num, true);
			  ld.AddQuery(_T('d'), j, 0, a_categ_ver_prev, true);
			  ld.AddQuery(_T('d'), k, 0, m_api->m_appr_mgr.a_apl_user_name, true);
			  ld.AddQuery(_T('d'), k, 0, m_api->m_appr_mgr.a_apl_user_po, true);
			ld.LoadEx();
		}
	}
	CaplInstance *inst;
	aplExtent ext_hist;
	// Чтение версий
	m_data->GetEntityExtent(e_apl_product_category_ver,ext_hist);
	for(i=0;i<ext_hist.Size;i++)
	{
		if(ext_hist[i]==0) continue;
		if(ext_hist[i]->GetType()==0) continue;
		if(ext_hist[i]->GetAccessmode()>aplRO) continue;
		m_data->GetAttr(ext_hist[i],a_categ_ver_categ,inst);
		if(inst==categ) outExt.Add(ext_hist[i]);
	}
	return true;
}
//*************************************************************
bool CaplCategoryManager::LoadCategoryInfo(CaplInstance *categ,bool bLoadPrdInfo)
{
	if(m_data==0) return false;
	if(categ==0) return false;
	if(categ==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if(categ->GetId()==0) return true;
	if(categ->GetType()==0) return false;
	if(e_categ==0) return false;

	aplExtent ext; ext.Unique=false; ext.Add(categ);
	return LoadCategoryInfo(ext,bLoadPrdInfo);

}
//*************************************************************
bool CaplCategoryManager::LoadCategoryInfo(aplExtent &ext, bool bLoadPrdInfo)
{
	if(m_data==0) return false;
	if(e_categ==0) return false;

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

	int i,j,k;
	
	CaplLoadData ld_categ(m_data,DEF_SOURCE);
	CaplLoadData ld_ver(m_data,DEF_SOURCE);

	int iLoadCateg=0;
	int iLoadCategVer=0;
	aplExtent ext_categ,ext_categ_ver,ext_items;
	ext_categ.Unique=false; 
	ext_categ_ver.Unique=false; 
	CaplAggr  aggr0;
	CaplInstance *inst,*inst0;

	for(i=0;i<ext.Size;i++)
	{
		CaplInstance *categ=ext[i];
		if(categ==0) continue;
		if(categ->GetId()==0) continue;
		if(categ->GetType()==0) continue;

		if(m_data->IsKindOf(categ,e_categ))
		{
			ld_categ.AddQuery(0,categ,true);
			iLoadCateg++;
			ext_categ.Add(categ);
		}
		else if(m_data->IsKindOf(categ,e_apl_product_category_ver))
		{
			ld_ver.AddQuery(0,categ,true);
			iLoadCategVer++;
			ext_categ_ver.Add(categ);
		}
		if(iLoadCateg==m_MaxItemsLoad || (i==(ext.Size-1) && iLoadCateg>0))
		{
			iLoadCateg=0;
		//j=	ld_categ.AddQuery(_T('d'), 0, 0, a_categ_products, true); запрос не нужен - предыдущий запрос 'a' с флагом "загружать все атрибуты"

			if(a_categ_lock!=0)
			{
				j=ld_categ.AddQuery(_T('d'), 0, 0, a_categ_lock, true,true);
				  ld_categ.AddQuery(_T('d'), j, 0, a_categ_ver_author, true,true);
			}
			if(!ld_categ.LoadEx())
			{
				if(apidata.GetLastAplError()!=APL_SOCK_OPERATION_IN_PROGRESS)
				{
					if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка чтения информации о категориях (APL)"),MB_OK|MB_ICONSTOP);
					return false;
				}
			}
			if(bLoadPrdInfo)
			{
				for(k=0;k<ext_categ.Size;k++)
				{
					m_data->GetAttr(ext_categ[k],a_categ_products,aggr0);
					for(j=0;j<aggr0.GetSize();j++)
					{
						aggr0.GetByIndex(j,inst);
						ext_items.Add(inst);
					}
					if(a_categ_lock!=0)
					{
						m_data->GetAttr(ext[i],a_categ_lock,inst0);
						if(inst0!=0)
						{
							m_data->GetAttr(inst0,a_categ_ver_products,aggr0);
							for(j=0;j<aggr0.GetSize();j++)
							{
								aggr0.GetByIndex(j,inst);
								ext_items.Add(inst);
							}
						}
					}
				}
			}
		}

		if(iLoadCategVer==m_MaxItemsLoad || (i==(ext.Size-1) && iLoadCategVer>0))
		{
			iLoadCategVer=0;
			ld_ver.AddQuery(_T('d'), 0, 0, a_categ_ver_author, true,true);
			
			if(!ld_ver.LoadEx())
			{
				if(apidata.GetLastAplError()!=APL_SOCK_OPERATION_IN_PROGRESS)
				{
					if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка чтения информации о категориях (APL)"),MB_OK|MB_ICONSTOP);
					return false;
				}
			}
			if(bLoadPrdInfo)
			{
				for(k=0;k<ext_categ_ver.Size;k++)
				{
					m_data->GetAttr(ext_categ_ver[i],a_categ_ver_products,aggr0);
					for(j=0;j<aggr0.GetSize();j++)
					{
						aggr0.GetByIndex(j,inst);
						ext_items.Add(inst);
					}
				}
			}
		}
	}

	if(ext_items.Size>0) LoadExtentInfo(ext_items);

	return true;
}

bool CaplCategoryManager::MakeTable(CaplInstance *categ,bool is_hide_move_button,bool *redraw)
{
	if(m_data==0)return false;
	if(categ==0)return false;
	if(categ==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if(redraw!=0){*redraw=false;}

	aplExtent ext_prd,ext_tmp,ext_pdf,ext_categ;
	GetCategoryContents(categ,ext_prd);
	//GetAllSubCategory(categ,ext_categ);
	//ext.Append(ext_categ);
	for(int i=0;i<ext_prd.GetSize();i++){
		if(m_data->IsKindOf(ext_prd[i],m_api->m_prd_mgr.e_prd)){
			ext_tmp.Clear();
			m_api->m_prd_mgr.GetAllProductVersion(ext_prd.GetAt(i),ext_tmp);
			ext_pdf.Append(ext_tmp);
		}else{
			ext_pdf.Add(ext_prd[i]);
		}
	}
	m_api->LoadExtentInfo(ext_pdf);
	
	int res=0;
	CaplSetResourceHandle setres(module_inst);
	CDlgListInstances dlg;
	dlg.m_base_inst=categ;
	dlg.m_content=&ext_pdf;
	dlg.m_api=m_api;
	dlg.m_is_hide_move_button=is_hide_move_button;
	dlg.m_delete_message= APL_T("Вы действительно хотите удалить выделенные объекты из категории?");
	if(categ->GetAccessmode()<=aplRW){
		dlg.m_can_delete=true;
	}
	dlg.m_can_delete=false;
	res=dlg.DoModal();

	/*
	if(dlg.m_changed){
		m_data->PutAttr(categ,a_folder_content,ext);
		if(m_AutoSave) m_data->NET_SaveChanges();
		if(redraw!=0){*redraw=true;}
	}
	*/
	return true;
}
//*************************************************************
CaplInstance *CaplCategoryManager::FindCateg(const TCHAR *id)
{
	if(m_data==0) return 0;
	if(id==0) return 0;
	if(e_categ==0) return 0;
	/*int i;
	aplExtent ext;
	CString str;
	m_data->GetEntityExtent(e_categ,ext);
	for(i=0;i<ext.Size;i++)
	{
		m_data->GetAttr(ext[i],a_categ_id,str);
		if(str==id) return ext[i];
	}
	return 0;*/

	aplExtent ext;
	CaplAttrValue tst_value;

	tst_value.value.Set(id);
	tst_value.attr=a_categ_id;
	m_data->NET_FindInstancesWithAttrValues(e_categ,1,&tst_value,ext,false);
	if(ext.Size==0) return 0;
	
	CaplInstance *cat=ext[0];
	return cat;
}
//*************************************************************
/** Возвращает возвращает в ext все входящие в categ категории
	@param categ исходная категория. Если categ == 0 , то возвращается верхний уровень
	@param ext экстент для записи результата
	@param recursive надо ли возвращать все категории на всех уровнях
	@param load_prd надо ли читать в память список содержащихся в категориях изделий
	@return true при удачном выполнении и false в случае ошибки */
bool CaplCategoryManager::GetAllSubCategory(CaplInstance *categ,
				aplExtent &ext, bool recursive, bool load_prd)
{
	aplExtent rels;
	
	return GetAllSubCategory2(categ, ext, rels, recursive, load_prd);
}
bool CaplCategoryManager::GetAllSubCategory2(CaplInstance *categ,
				aplExtent &ext, aplExtent &rels, bool recursive, bool load_prd)
{
	ext.Clear();
	if(m_data==0) return false;
	if(e_categ==0) return false;
	if(categ!=0)
	{
		if(categ==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
		if(categ->GetAccessmode()>aplRO) return false;
		if(categ->GetType()==0)return false;
	}
	int i,j,k;
	CaplInstance *inst;
	aplExtent ext_categ,ext_rel,has_supertypes;

	if(categ==0)
	{
		if(m_data->IsConnected())
		{
			bool bFind= false;
			aplExtent sub_categs, cont;

			CaplAttrValue find_value[2];
			find_value[0].attr= a_categ_content_id;
			find_value[0].value.Set(_T("Categories"));
			
			m_data->NET_FindInstancesWithAttrValues(e_categ_content, 1, &find_value[0], cont, false);
			
			if(cont.GetSize()>0)
			{
				bFind= true;
				CaplLoadData ld(m_data,DEF_SOURCE);
				ld.AddQuery(-1,cont[0]);
				ld.AddQuery(_T('d'), 0, 0, a_categ_content_id, true);
				ld.AddQuery(_T('d'), 0, 0, a_categ_content_content, true);
				if(!ld.LoadEx())
				{
					if(apidata.GetLastAplError()!=APL_SOCK_OPERATION_IN_PROGRESS)
						if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка чтения информации о категориях (APL)"),MB_OK|MB_ICONSTOP);
				}
				m_api->m_data.GetAttr(cont[0], a_categ_content_content, ext);
			}
			
			if(!bFind)
			{
				bool b0=m_data->NET_QueryEditParse(
				
					CString(_T("SELECT Ext_2 FROM ")
					_T("Ext_1{product_category_relationship}.sub_category->product_category ")
					_T("Ext_2{product_category.# NOT_IN #Ext_1} ")
					_T("END_SELECT")));
				if(!b0) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка разбора запроса")); return false;}
				if(!m_data->NET_QueryExecute(ext))
					{if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка выполнения запроса")); return false;}
				
				CaplInstance* categ_cont= m_api->m_data.CreateInstance(e_categ_content);
				if(categ_cont)
				{
					m_api->m_data.PutAttr(categ_cont, a_categ_content_id, _T("Categories"));
					m_api->m_data.PutAttr(categ_cont, a_categ_content_content, ext);
					if(m_AutoSave) m_api->m_data.NET_SaveChanges();
				}			
			}
		}
		else
		{
			// Если PDR в памяти
			m_data->GetEntityExtent(e_categ_rel,ext_rel);
			for(i=0;i<ext_rel.Size;i++)
			{
				m_data->GetAttr(ext_rel[i],a_categ_rel_sub_category,inst);
				if(inst!=0)has_supertypes.Add(inst);
			}
			m_data->GetEntityExtent(e_categ,ext_categ);
			for(i=0;i<ext_categ.Size;i++)
			{
				if(has_supertypes.Find(ext_categ[i])==-1)
				{
					if(ext_categ[i]->GetAccessmode()<=aplRO)
						ext.Add(ext_categ[i]);
				}
			}
		}
		// Чтение в память данных
		if(m_data->IsConnected())
		{
			if(ext.Size>0)
			{
				CaplLoadData ld(m_data,DEF_SOURCE);
				for(int ii=0;ii<ext.Size;ii++) 
				{
					if(ext[ii]->GetId()!=0)
						i=ld.AddQuery(0,ext[ii]);
				}
				ld.AddQuery(_T('d'), i, 0, a_categ_id, true);
				ld.AddQuery(_T('d'), i, 0, a_categ_name, true);
				ld.AddQuery(_T('d'), i, 0, a_categ_descr, true);
				ld.AddQuery(_T('d'), i, 0, a_categ_charact, true);
				ld.AddQuery(_T('d'), i, 0, a_categ_all_charact, true);
				if(load_prd) ld.AddQuery(_T('d'), i, 0, a_categ_products, true);

				if(a_categ_lock!=0)
				{
					j=ld.AddQuery(_T('d'), i, 0, a_categ_lock, true);
					  ld.AddQuery(_T('d'), j, 0, a_categ_ver_categ, true);
					  ld.AddQuery(_T('d'), j, 0, a_categ_ver_id, true);
					  ld.AddQuery(_T('d'), j, 0, a_categ_ver_name, true);
					  ld.AddQuery(_T('d'), j, 0, a_categ_ver_descr, true);
					  ld.AddQuery(_T('d'), j, 0, a_categ_ver_products, true);
					  ld.AddQuery(_T('d'), j, 0, a_categ_ver_start, true);
					  ld.AddQuery(_T('d'), j, 0, a_categ_ver_end, true);
					  ld.AddQuery(_T('d'), j, 0, a_categ_ver_num, true);
					  ld.AddQuery(_T('d'), j, 0, a_categ_ver_prev, true);
					k=ld.AddQuery(_T('d'), j, 0, a_categ_ver_author, true);
					  ld.AddQuery(_T('d'), k, 0, m_api->m_appr_mgr.a_apl_user_name, true);
					  ld.AddQuery(_T('d'), k, 0, m_api->m_appr_mgr.a_apl_user_po, true);
				}
				if(!ld.LoadEx())
				{
					if(apidata.GetLastAplError()!=APL_SOCK_OPERATION_IN_PROGRESS)
						if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка чтения информации о категориях (APL)"),MB_OK|MB_ICONSTOP);
				}	
			}
		}
	}
	else
	{
		if(m_data->IsConnected())
		{
			if(categ->GetId()!=0)
			{
				CaplLoadData ld(m_data,DEF_SOURCE);
				// ссылка
				i=	ld.AddQuery(_T('b'), categ->GetId(), e_categ_rel, a_categ_rel_category, true,true);
					//ld.AddQuery(_T('d'), i, 0,a_categ_rel_category , true,true);
				i=	ld.AddQuery(_T('d'), i, 0, a_categ_rel_sub_category, true,true);
				
					/*ld.AddQuery(_T('d'), i, 0, a_categ_id, true);
					ld.AddQuery(_T('d'), i, 0, a_categ_name, true);
					ld.AddQuery(_T('d'), i, 0, a_categ_descr, true);
					ld.AddQuery(_T('d'), i, 0, a_categ_charact, true);
					ld.AddQuery(_T('d'), i, 0, a_categ_all_charact, true);*/
					if(load_prd) ld.AddQuery(_T('d'), i, 0, a_categ_products, true);

					if(a_categ_lock!=0)
					{
						j=ld.AddQuery(_T('d'), i, 0, a_categ_lock, true,true);
						  /*ld.AddQuery(_T('d'), j, 0, a_categ_ver_categ, true);
						  ld.AddQuery(_T('d'), j, 0, a_categ_ver_id, true);
						  ld.AddQuery(_T('d'), j, 0, a_categ_ver_name, true);
						  ld.AddQuery(_T('d'), j, 0, a_categ_ver_descr, true);
						  ld.AddQuery(_T('d'), j, 0, a_categ_ver_products, true);
						  ld.AddQuery(_T('d'), j, 0, a_categ_ver_start, true);
						  ld.AddQuery(_T('d'), j, 0, a_categ_ver_end, true);
						  ld.AddQuery(_T('d'), j, 0, a_categ_ver_num, true);
						  ld.AddQuery(_T('d'), j, 0, a_categ_ver_prev, true);*/
						k=ld.AddQuery(_T('d'), j, 0, a_categ_ver_author, true,true);
						  /*ld.AddQuery(_T('d'), k, 0, m_api->m_appr_mgr.a_apl_user_name, true);
						  ld.AddQuery(_T('d'), k, 0, m_api->m_appr_mgr.a_apl_user_po, true);*/
					}

				if(!ld.LoadEx())
				{
					if(apidata.GetLastAplError()!=APL_SOCK_OPERATION_IN_PROGRESS)
						if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка чтения информации о категориях (APL)"),MB_OK|MB_ICONSTOP);
				}
			}
				
			m_data->GetEntityExtent(e_categ_rel,ext_rel);
			for(i=0;i<ext_rel.Size;i++)
			{
				m_data->GetAttr(ext_rel[i],a_categ_rel_category,inst);
				if(inst==categ)
				{
					m_data->GetAttr(ext_rel[i],a_categ_rel_sub_category,inst);
					if(inst!=0 && inst->GetAccessmode()<=aplRO)
					{
						ext.Add(inst);
						rels.Add(ext_rel[i]);
						if(recursive)
						{
							aplExtent ext_sub_items, ext_sub_rels;
							GetAllSubCategory2(inst, ext_sub_items, ext_sub_rels, recursive);
							ext.Append(ext_sub_items);
							rels.Append(ext_sub_rels);
						}
					}
				}
			}
		}
	}
	return true;
}
// возвращает в ext все категории в которые входит categ
bool CaplCategoryManager::GetAllParentCategory(CaplInstance *categ,aplExtent &ext)
{
	ext.Clear();
	if(m_data==0) return false;
	if(categ==0) return false;
	if(categ==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if(categ->GetType()==0) return false;
	if(e_categ==0) return false;
	int i,j,k;
	CaplInstance *inst;
	aplExtent ext_rel;

	if(m_data->IsConnected())
	{
		if(categ->GetId()!=0)
		{
			CaplLoadData ld(m_data,DEF_SOURCE);
			// ссылка
			i=	ld.AddQuery(_T('b'), categ->GetId(), e_categ_rel, a_categ_rel_sub_category, true);
				ld.AddQuery(_T('d'), i, 0,a_categ_rel_sub_category , true);
			i=	ld.AddQuery(_T('d'), i, 0, a_categ_rel_category, true);
				ld.AddQuery(_T('d'), i, 0, a_categ_id, true);
				ld.AddQuery(_T('d'), i, 0, a_categ_name, true);
				ld.AddQuery(_T('d'), i, 0, a_categ_descr, true);
			//j=	ld.AddQuery(_T('d'), i, 0, a_categ_products, true);
				if(a_categ_lock!=0)
				{
					j=ld.AddQuery(_T('d'), i, 0, a_categ_lock, true);
					  ld.AddQuery(_T('d'), j, 0, a_categ_ver_categ, true);
					  ld.AddQuery(_T('d'), j, 0, a_categ_ver_id, true);
					  ld.AddQuery(_T('d'), j, 0, a_categ_ver_name, true);
					  ld.AddQuery(_T('d'), j, 0, a_categ_ver_descr, true);
					  ld.AddQuery(_T('d'), j, 0, a_categ_ver_products, true);
					  ld.AddQuery(_T('d'), j, 0, a_categ_ver_start, true);
					  ld.AddQuery(_T('d'), j, 0, a_categ_ver_end, true);
					  ld.AddQuery(_T('d'), j, 0, a_categ_ver_num, true);
					  ld.AddQuery(_T('d'), j, 0, a_categ_ver_prev, true);
					k=ld.AddQuery(_T('d'), j, 0, a_categ_ver_author, true);
					  ld.AddQuery(_T('d'), k, 0, m_api->m_appr_mgr.a_apl_user_name, true);
					  ld.AddQuery(_T('d'), k, 0, m_api->m_appr_mgr.a_apl_user_po, true);
				}

			if(!ld.LoadEx())
			{
				if(apidata.GetLastAplError()!=APL_SOCK_OPERATION_IN_PROGRESS)
					if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка чтения информации о категориях (APL)"),MB_OK|MB_ICONSTOP);
			}
		}
	}

	m_data->GetEntityExtent(e_categ_rel,ext_rel);

	for(i=0;i<ext_rel.Size;i++)
	{
		m_data->GetAttr(ext_rel[i],a_categ_rel_sub_category,inst);
		if(inst==categ)
		{
			m_data->GetAttr(ext_rel[i],a_categ_rel_category,inst);
			if(inst->GetAccessmode()<=aplRO)ext.Add(inst);
		}
	}
	return true;
}
	// **************************************************
	// Структура категорий
	// **************************************************

// вставляет категорию sub в категорию base
bool CaplCategoryManager::InsertSubCategory(CaplInstance *base, CaplInstance *sub)
{
	if((base==0)||(sub==0)) return false;
	if(base==(CaplInstance*)-1 || sub==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if((base->GetType()==0)||(sub->GetType()==0)) return false;
	if(m_data==0) return false;
	if(e_categ==0) return false;
	if(base->GetAccessmode()>=aplRO)return false;
	int i;
	CaplInstance *inst;
	aplExtent ext_rel;
	m_data->GetEntityExtent(e_categ_rel,ext_rel);

	for(i=0;i<ext_rel.Size;i++)
	{
		m_data->GetAttr(ext_rel[i],a_categ_rel_category,inst);
		if(inst==base)
		{
			m_data->GetAttr(ext_rel[i],a_categ_rel_sub_category,inst);
			if(inst==sub) return true;
		}
	}
	inst=m_data->CreateInstance(e_categ_rel);
	if(inst ==0) return false;
	m_data->PutAttr(inst,a_categ_rel_category,base);
	m_data->PutAttr(inst,a_categ_rel_sub_category,sub);
	return true;
}
// удаляет категорию sub из категории base
bool CaplCategoryManager::RemoveSubCategory(CaplInstance *base, CaplInstance *sub)
{
	if((base==0)||(sub==0)) return false;
	if(base==(CaplInstance*)-1 || sub==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if((base->GetType()==0)||(sub->GetType()==0)) return false;
	if(m_data==0) return false;
	if(e_categ==0) return false;
	if(base->GetAccessmode()>=aplRO)return false;
	int i;
	CaplInstance *inst;
	aplExtent ext_rel;
	m_data->GetEntityExtent(e_categ_rel,ext_rel);

	for(i=0;i<ext_rel.Size;i++)
	{
		m_data->GetAttr(ext_rel[i],a_categ_rel_category,inst);
		if(inst==base)
		{
			m_data->GetAttr(ext_rel[i],a_categ_rel_sub_category,inst);
			if(inst==sub) 
			{
				m_data->DeleteInstance(ext_rel[i]);
				return true;
			}
		}
	}
	return false;
}
// создает категорию
CaplInstance *CaplCategoryManager::CreateCategory(const TCHAR *id, const TCHAR *name, const TCHAR *descr)
{
	if((id==0)||(name==0)) return 0;
	if(m_data==0) return 0;
	if(e_categ==0) return 0;
	int i;
	CString tmp;
	CaplInstance *inst;
	aplExtent ext;
	m_data->GetEntityExtent(e_categ,ext);

	for(i=0;i<ext.Size;i++)
	{
		m_data->GetAttr(ext[i],a_categ_id,tmp);
		if(tmp==id) return ext[i];
	}
	inst=m_data->CreateInstance(e_prd_rel_prd_categ);
	if(inst!=0)
	{
		m_data->PutAttr(inst,a_categ_id,id);
		m_data->PutAttr(inst,a_categ_name,name);
		if(descr!=0)m_data->PutAttr(inst,a_categ_descr,descr);
		
		if(true==m_AutoUsurpire)
		{
			aplExtent	aet;
			CString		csAccPat;

			if(aplOWN==inst->GetAccessmode())
				aet.Add(inst);
			if(TRUE==m_api->m_options_mgr.GetDefPatern(inst->GetType(),csAccPat))
				apidata.NET_SetAccessFromPattern(&aet,csAccPat);
		}
	}

	return inst;
}
// Читает атрибуты категории
bool CaplCategoryManager::GetCategoryAttr(CaplInstance *categ, CString &id, CString &name, CString &descr)
{
	id=_T(""); name=_T("");descr=_T("");
	if(categ==0) return false;
	if(categ==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if(categ->GetType()==0) return false;
	if(e_categ==0) return false;
	if(categ->GetAccessmode()>aplRO)return false;
	if(m_data==0) return false;
	if(!m_data->IsKindOf(categ,e_categ))return false;
	m_data->GetAttr(categ,a_categ_id,id);
	m_data->GetAttr(categ,a_categ_name,name);
	m_data->GetAttr(categ,a_categ_descr,descr);
	return true;
}
// уничтожает категорию и все связи
bool CaplCategoryManager::RemoveCategory(CaplInstance *categ)
{
	if(categ==0) return false;
	if(categ==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if(categ->GetType()==0) return false;
	if(e_categ==0) return false;
	if(categ->GetAccessmode()>aplOWN)return false;
	if(m_data==0) return false;
	if(!m_data->IsKindOf(categ,e_categ))return false;
	int i;
	CaplInstance *inst;
	aplExtent ext_rel;
	m_data->GetEntityExtent(e_categ_rel,ext_rel);

	for(i=0;i<ext_rel.Size;i++)
	{
		m_data->GetAttr(ext_rel[i],a_categ_rel_category,inst);
		if(inst==categ) m_data->DeleteInstance(ext_rel[i]);
		else
		{
			m_data->GetAttr(ext_rel[i],a_categ_rel_sub_category,inst);
			if(inst==categ) m_data->DeleteInstance(ext_rel[i]);
		}
	}
	m_data->DeleteInstance(categ);
	return true;
}
// **************************************************
// Ассоцияция с изделиями
// **************************************************

// Возвращает в ext все изделия входящие в categ
// Если all==true => просматриваются все входящие катгории
bool CaplCategoryManager::GetCategoryContents(CaplInstance *categ, aplExtent &ext, bool all, bool bLoadPrdInfo)
{
	ext.Clear();
	if(categ==0) return false;
	if(categ==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if(categ->GetType()==0) return false;
	if(e_categ==0) return false;
	if(categ->GetAccessmode()>aplRO)return false;
	if(m_data==0) return false;
	if(!m_data->IsKindOf(categ,e_categ))
	{
		if(!m_data->IsKindOf(categ,e_apl_product_category_ver))return false;
	}
	int i;
	CaplAggr aggr;

	LoadCategoryInfo(categ,bLoadPrdInfo);

	if(m_data->IsKindOf(categ,e_categ))
	{
		CaplInstance *lock=CheckMyLock(categ,false);
		if(lock==0) m_data->GetAttr(categ,a_categ_products,ext);
		else m_data->GetAttr(lock,a_categ_ver_products,ext);
	}
	else m_data->GetAttr(categ,a_categ_ver_products,ext);

	/*if(m_data->IsKindOf(categ,e_categ))
	{
		CaplInstance *lock=CheckMyLock(categ,false);
		if(lock==0) m_data->GetAttr(categ,a_categ_products,aggr);
		else m_data->GetAttr(lock,a_categ_ver_products,aggr);
	}
	else m_data->GetAttr(categ,a_categ_ver_products,aggr);
	
	CaplInstance *inst;
	for(i=0;i<aggr.GetSize();i++)
	{
		aggr.GetByIndex(i,inst);
		if(inst!=0)	{if(inst->GetType()!=0){if(inst->GetAccessmode()<=aplRO)	ext.Add(inst);}}
	}*/


	if(all)
	{
		static aplExtent PreparedCateg;
		bool f=false;
		if(PreparedCateg.Size==0) f=true;
		PreparedCateg.Add(categ);
		aplExtent ext0,ext1, ext2;
		GetAllSubCategory2(categ, ext1, ext2);
		for(i=0;i<ext1.Size;i++)
		{
			if(ext1[i]==0) continue;
			if(ext1[i]->GetAccessmode()>aplRO) continue;
			if(PreparedCateg.Find(ext1[i])==-1)
			{
				PreparedCateg.Add(ext1[i]);
				GetCategoryContents(ext1[i],ext0,true);
				ext.Append(ext0);
			}
		}
		if(f)PreparedCateg.Clear();
	}
	return true;
}

// Возвращает true, если prd находится в categ
// Если all==true => просматриваются все входящие катгории
bool CaplCategoryManager::FindProductInCategory(CaplInstance *prd, CaplInstance *categ,bool all)
{
	if((prd==0)||(categ==0)) return false;
	if(prd==(CaplInstance*)-1 || categ==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if((prd->GetType()==0)||(categ->GetType()==0)) return false;
	if(m_data==0) return false;
	if(e_categ==0) return false;
	if(prd->GetAccessmode()>aplRO)return false;
	int i;
	aplExtent ext;
	m_data->GetAttr(categ,a_categ_products,ext);
	for(i=0;i<ext.GetSize();i++)
	{
		if(ext[i]==prd)
			return true;
	}
	if(all)
	{
		aplExtent ext0,ext1,ext2;
		GetAllSubCategory2(categ,ext1,ext2,false,true);
		for(i=0;i<ext1.Size;i++)
		{
			if(FindProductInCategory(prd,ext1[i],all)) 
				return true;
		}
	}
	return false;
}

// добавляет prd в categ
bool CaplCategoryManager::AddPrdToCategory(CaplInstance *prd, CaplInstance *categ,bool bLoadCategInfo)
{
	if((prd==0)||(categ==0)) return false;
	if(prd==(CaplInstance*)-1 || categ==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if((prd->GetType()==0)||(categ->GetType()==0)) return false;
	if(m_data==0) return false;
	if(e_categ==0) return false;
	
	if(bLoadCategInfo) LoadCategoryInfo(categ,false);

	if(categ->GetAccessmode()>=aplRO){if(m_api->m_ModeInteractive)aplErrorMessage(S::NoAccessRight(),categ); return false;}
	if(!m_data->IsKindOf(categ,e_prd_rel_prd_categ))return false;
	
	CaplInstance *lock=CheckMyLock(categ,true);
	if(lock==0) return false;

	int i;
	CaplAggr aggr;
	CaplInstance *inst;
	m_data->GetAttr(lock,a_categ_ver_products,aggr);
	for(i=0;i<aggr.GetSize();i++)
	{
		aggr.GetByIndex(i,inst);
		if(inst==prd) return true;
	}
	aggr.Add(prd);
	m_data->PutAttr(lock,a_categ_ver_products,aggr);
	if(m_AutoSave) m_data->NET_SaveChanges();
	return true;
}

//*********************************************************************************
bool CaplCategoryManager::UndoCheckOut( CaplInstance *categ)
{
	if(categ==0) return false;
	if(categ==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if(categ->GetType()==0) return false;
	if(m_data==0) return false;
	if(e_categ==0) return false;
	if(!m_data->IsKindOf(categ,e_prd_rel_prd_categ))return false;

	// чтобы данные точно прочитались с сервера!
	m_data->ClearLastQuery();
	LoadCategoryInfo(categ,false);
	CaplInstance *lock,*user;
	m_data->GetAttr(categ,a_categ_lock,lock);
	if(lock==0)
	{
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Категория не заблокирована !"),MB_OK|MB_ICONSTOP);
		return false;
	}
	m_data->GetAttr(lock,a_categ_ver_author,user);
	if(user!=m_data->GetCurrUser())
	{
		if(!m_api->m_ModeInteractive)return false;
		if(categ->GetAccessmode()>aplRW)
		{
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Категория заблокирована другим пользователем !"),MB_OK|MB_ICONSTOP);
			return false;
		}
		if(IDYES!=AfxMessageBox( APL_T("Категория заблокирована другим пользователем !\n\nВсе равно отменить редактирование ?"),
			MB_YESNO|MB_ICONQUESTION)) return false;
	}
	if(categ->GetAccessmode()>=aplRO) {if(m_api->m_ModeInteractive)aplErrorMessage(S::NoAccessRight(),categ); return false;}

	if(m_api->m_ModeInteractive && IDNO==AfxMessageBox( APL_T("Вы действительно хотите отменить редактирование ?"), MB_YESNO|MB_ICONQUESTION)) return false;
	
	m_data->PutAttr(categ,a_categ_lock,(CaplInstance*)0);
	m_data->DeleteInstance(lock);
	if(m_AutoSave) m_data->NET_SaveChanges();
	return true;
}

//*********************************************************************************
CaplInstance *CaplCategoryManager::CheckMyLock(CaplInstance *categ, bool bShowMessages)
{
	CaplInstance *lock,*user;
	if(categ==0)return 0;
	if(categ==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return 0;};
	m_data->GetAttr(categ,a_categ_lock,lock);
	if(lock==0)
	{
		if(bShowMessages && m_api->m_ModeInteractive)AfxMessageBox( APL_T("Категория не заблокирована !"),MB_OK|MB_ICONSTOP);
		return 0;
	}
	m_data->GetAttr(lock,a_categ_ver_author,user);
	if(user!=m_data->GetCurrUser())
	{
		if(bShowMessages && m_api->m_ModeInteractive)AfxMessageBox( APL_T("Категория заблокирована другим пользователем !"),MB_OK|MB_ICONSTOP);
		return 0;
	}
	return lock;
}
//*********************************************************************************
// удаляет prd из categ
bool CaplCategoryManager::RemovePrdFromCategory(CaplInstance *prd, CaplInstance *categ,bool bLoadCategInfo)
{
	if((prd==0)||(categ==0)) return false;
	if(prd==(CaplInstance*)-1 || categ==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if((prd->GetType()==0)||(categ->GetType()==0)) return false;
	if(m_data==0) return false;
	if(e_categ==0) return false;

	if(bLoadCategInfo) LoadCategoryInfo(categ,false);

	if(categ->GetAccessmode()>=aplRO) {if(m_api->m_ModeInteractive)aplErrorMessage(S::NoAccessRight(),categ); return false;}
	if(!m_data->IsKindOf(categ,e_prd_rel_prd_categ))return false;

	CaplInstance *lock=CheckMyLock(categ,true);
	if(lock==0) return false;

	int i;
	CaplAggr aggr;
	CaplInstance *inst;
	bool bChanged=false;
	m_data->GetAttr(lock,a_categ_ver_products,aggr);
	for(i=0;i<aggr.GetSize();i++)
	{
		aggr.GetByIndex(i,inst);
		if(inst==prd) 
		{
			aggr.Remove(i);
			i--;
			bChanged=true;
		}
	}
	if(bChanged)
	{
		m_data->PutAttr(lock,a_categ_ver_products,aggr);
		if(m_AutoSave) m_data->NET_SaveChanges();
		return true;
	}
	return false;
}
// возвращает в ext все категории, куда входит prd
bool CaplCategoryManager::GetProductCategories(CaplInstance *prd, aplExtent &ext)
{
	ext.Clear();
	if(prd==0) return false;
	if(prd==(CaplInstance*)-1 ) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if(prd->GetType()==0) return false;
	if(m_data==0) return false;
	if(e_categ==0) return false;
	if(prd->GetAccessmode()>aplRO)return false;
	aplExtent ext_cat;
/*	int i,j;
	aplExtent ext_cat;
	CaplInstance *inst;
	CaplAggr aggr;
	m_data->GetEntityExtent(e_prd_rel_prd_categ,ext_cat);
	for(i=0;i<ext_cat.Size;i++)
	{
		m_data->GetAttr(ext_cat[i],a_categ_products,aggr);
		for(j=0;j<aggr.GetSize();j++)
		{
			aggr.GetByIndex(j,inst);
			if(inst==prd)
			{
				ext.Add(ext_cat[i]);
				break;
			}
		}
	}*/
	CaplAttrValue tst_values[1];
	tst_values[0].value.Set(prd);
	tst_values[0].attr=a_categ_products;
	m_data->NET_FindInstancesWithAttrValues(e_prd_rel_prd_categ,1,&tst_values[0],ext_cat,true);
	for(int i=0;i<ext_cat.Size;i++)
	{
		if(ext_cat[i]->GetAccessmode()<=aplRO) ext.Add(ext_cat[i]);
	}
	return true;
}




int aplState2Ico(LPCTSTR state, int default_ico)
{
	if (state==0) return default_ico;
	if (state[0]==_T('\0')) return default_ico;

	if(0==_strcmp(state,_T("working"))) return ICO_STATE_WORKING;
	if(0==_strcmp(state,_T("approving"))) return ICO_STATE_APPROVING;
	if(0==_strcmp(state,_T("approved"))) return ICO_STATE_APPROVED;
	if(0==_strcmp(state,_T("changing"))) return ICO_STATE_CHANGING;
	if(0==_strcmp(state,_T("approving_change"))) return ICO_STATE_APPROVING_CHANGE;
	if(0==_strcmp(state,_T("canceled"))) return ICO_STATE_CANCELED;
	if(0==_strcmp(state,_T("must_revision"))) return ICO_STATE_MUST_REVISION;
	else return default_ico;
}






/// Выводит диалог выбора точки во времени
bool aplSelectDateTime(COleDateTime &odt,const TCHAR *title)
{
	CaplSetResourceHandle setres(module_inst);
	CDataTimeDlg dlg;
	dlg.m_dt=odt;
	if(title) dlg.m_title=title;
	bool rez=true;
	if(dlg.DoModal()!=IDOK) rez=false;
	odt=dlg.m_dt;
	return rez;
}

bool aplGetStringValue(CString &val)
{
	CStrValueDlg dlg;
	dlg.m_val=val;
	if(dlg.DoModal()==IDOK)
	{
		val=dlg.m_val;
		return true;
	}
	return false;
}

bool aplSortByDate(CaplNetStepData* m_data, aplExtent &ext, int left, int right, CaplAttr* date_attr)
{
	if(!m_data) return false;
	if(!m_data->IsConnected() && !m_data->IsDictLoad()) return false;
	if(!ext.GetSize()) return false;
	if(!date_attr) return false;
	if(left>right) return false;
	
	CaplInstance* test= ext.GetAt((left+right)/2);
	CString sTestDate;

	m_data->GetAttr(test, date_attr, sTestDate);

	CString sLeftDate;
	CString sRightDate;
	int i= left; m_data->GetAttr(ext[i], date_attr, sLeftDate);
	int j= right; m_data->GetAttr(ext[j], date_attr, sRightDate);

	bool bUnique= ext.Unique;
	ext.Unique= false;
 	
	CaplInstance* swap;
	do
	{
		while (sLeftDate<sTestDate)
		{
			i++; if(i<ext.GetSize()) m_data->GetAttr(ext[i], date_attr, sLeftDate);			
		}
		while (sRightDate>sTestDate)
		{
			j--; if(j>-1) m_data->GetAttr(ext[j], date_attr, sRightDate);		
		}

		if(i<=j)
		{		
			swap= ext[i];
			ext.SetAt(i, ext[j]);
			ext.SetAt(j, swap);
			
			i++; if(i<ext.GetSize()) m_data->GetAttr(ext[i], date_attr, sLeftDate);
			j--; if(j>-1) m_data->GetAttr(ext[j], date_attr, sRightDate);
		}
	}while(i<=j);

	if(left < j) aplSortByDate(m_data, ext, left, j, date_attr);
	if(i < right) aplSortByDate(m_data, ext, i, right, date_attr);

	ext.Unique= bUnique;

#ifdef _DEBUG
//	TRACE("После сортировки\n");for(int n= 0; n<ext.GetSize(); n++){CString buf= _T("");m_data->GetAttr(ext[n], date_attr, buf);TRACE(_T("%s\n"), buf);}TRACE(_T("\n"));
#endif
	return true;
}
bool aplSortByDate(CaplNetStepData* m_data, aplExtent &ext, int left, int right, CaplAttr* attr1,CaplAttr *attr2)
{
	if(!m_data) return false;
	if(!m_data->IsConnected() && !m_data->IsDictLoad()) return false;
	if(!ext.GetSize()) return false;
	if(attr1==0) return false;
	if(attr2==0) return false;
	if(left>right) return false;
	
	CaplInstance* test= ext.GetAt((left+right)/2);
	CaplInstance* temp_inst;
	CString sTestDate;
	CString sLeftDate;
	CString sRightDate;

	m_data->GetAttr(test, attr1, temp_inst);m_data->GetAttr(temp_inst, attr2, sTestDate);
	int i= left; m_data->GetAttr(ext[i], attr1, temp_inst);m_data->GetAttr(temp_inst, attr2, sLeftDate);
	int j= right; m_data->GetAttr(ext[j], attr1, temp_inst);m_data->GetAttr(temp_inst, attr2, sRightDate);

	bool bUnique= ext.Unique;
	ext.Unique= false;
 	
	CaplInstance* swap;
	do
	{
		while (sLeftDate<sTestDate)
		{
			i++; if(i<ext.GetSize()){
				m_data->GetAttr(ext[i], attr1, temp_inst);
				m_data->GetAttr(temp_inst, attr2, sLeftDate);			
			}
		}
		while (sRightDate>sTestDate)
		{
			j--; if(j>-1) {
				m_data->GetAttr(ext[i], attr1, temp_inst);
				m_data->GetAttr(temp_inst, attr2, sRightDate);	
			}
		}

		if(i<=j)
		{		
			swap= ext[i];
			ext.SetAt(i, ext[j]);
			ext.SetAt(j, swap);
			
			i++; if(i<ext.GetSize()){
				m_data->GetAttr(ext[i], attr1, temp_inst);
				m_data->GetAttr(ext[i], attr2, sLeftDate);
			}
			j--; if(j>-1){
				m_data->GetAttr(ext[i], attr1, temp_inst);
				m_data->GetAttr(ext[i], attr2, sRightDate);
			} 
		}
	}while(i<=j);

	if(left < j) aplSortByDate(m_data, ext, left, j, attr1, attr2);
	if(i < right) aplSortByDate(m_data, ext, i, right, attr1, attr2);

	ext.Unique= bUnique;

#ifdef _DEBUG
//	TRACE("После сортировки\n");for(int n= 0; n<ext.GetSize(); n++){CString buf= _T("");m_data->GetAttr(ext[n], date_attr, buf);TRACE(_T("%s\n"), buf);}TRACE(_T("\n"));
#endif
	return true;
}


bool aplQSortByAttr(CaplNetStepData* m_data, aplExtent &ext, int left, int right, CaplAttr* attr)
{
	if(!m_data) return false;
	if(!m_data->IsConnected() && !m_data->IsDictLoad()) return false;
	if(!ext.GetSize()) return false;
	if(!attr) return false;
	if(left>right) return false;
	
	CaplInstance* test= ext.GetAt((left+right)/2);
	
	CaplValue LeftVal;
	CaplValue RightVal;
	CaplValue TestVal;
					m_data->GetAttr(test, attr, TestVal);
	int i= left; m_data->GetAttr(ext[i], attr, LeftVal);
	int j= right; m_data->GetAttr(ext[j], attr, RightVal);
	
	bool bUnique= ext.Unique;
	ext.Unique= false;
	
	CaplInstance* swap;
	do
	{
		while (LeftVal<TestVal)
		{
			i++; if(i<ext.GetSize()) m_data->GetAttr(ext[i], attr, LeftVal);
		}
		while (RightVal>TestVal)
		{
			j--; if(j>-1) m_data->GetAttr(ext[j], attr, RightVal);		
		}
		
		if(i<=j)
		{		
			swap= ext[i];
			ext.SetAt(i, ext[j]);
			ext.SetAt(j, swap);
			
			i++; if(i<ext.GetSize()) m_data->GetAttr(ext[i], attr, LeftVal);
			j--; if(j>-1) m_data->GetAttr(ext[j], attr, RightVal);
		}
	}while(i<=j);
	
	if(left < j) aplQSortByAttr(m_data, ext, left, j, attr);
	if(i < right) aplQSortByAttr(m_data, ext, i, right, attr);
	
	ext.Unique= bUnique;
	ext.Sorted_inst	= true;
#ifdef _DEBUG
	//	TRACE("После сортировки\n");for(int n= 0; n<ext.GetSize(); n++){CString buf= _T("");m_data->GetAttr(ext[n], date_attr, buf);TRACE(_T("%s\n"), buf);}TRACE(_T("\n"));
#endif
	return true;
}
bool aplQSortByAttr(CaplNetStepData* m_data, aplExtent &ext,int left, int right,CaplAttr *attr1,CaplAttr *attr2)
{
	if(!m_data) return false;
	if(!m_data->IsConnected() && !m_data->IsDictLoad()) return false;
	if(ext.GetSize()==0) return false;
	if(attr1==0) return false;
	if(attr2==0) return false;
	if(left>right) return false;
	
	CaplInstance* test= ext.GetAt((left+right)/2);
	CaplInstance* temp_inst;
	
	CaplValue LeftVal;
	CaplValue RightVal;
	CaplValue TestVal;
	m_data->GetAttr(test, attr1, temp_inst); if(0!=temp_inst)	m_data->GetAttr(temp_inst, attr2, TestVal);
	int i= left; m_data->GetAttr(ext[i], attr1, temp_inst); if(0!=temp_inst) m_data->GetAttr(temp_inst, attr2, LeftVal);
	int j= right; m_data->GetAttr(ext[j], attr1, temp_inst);if(0!=temp_inst) m_data->GetAttr(temp_inst, attr2, RightVal);
		
	bool bUnique= ext.Unique;
	ext.Unique= false;
	
	CaplInstance* swap;
	do
	{
		while (LeftVal<TestVal)
		{
			i++; if(i<ext.GetSize()){
				m_data->GetAttr(ext[i], attr1, temp_inst);
				if(0!=temp_inst) m_data->GetAttr(temp_inst, attr2, LeftVal);
				else LeftVal.Clear();
			}
		}
		while (RightVal>TestVal)
		{
			j--; if(j>-1){
				m_data->GetAttr(ext[j], attr1, temp_inst);		
				if(0!=temp_inst) m_data->GetAttr(temp_inst, attr2, RightVal);		
				else RightVal.Clear();
			}
		}
		
		if(i<=j)
		{		
			swap= ext[i];
			ext.SetAt(i, ext[j]);
			ext.SetAt(j, swap);
			
			i++; if(i<ext.GetSize()) {
				m_data->GetAttr(ext[i], attr1, temp_inst);
				if(0!=temp_inst)  m_data->GetAttr(temp_inst, attr2, LeftVal);
				else LeftVal.Clear();
			}
			j--; if(j>-1) {
				m_data->GetAttr(ext[j], attr1, temp_inst);		
				if(0!=temp_inst)  m_data->GetAttr(temp_inst, attr2, RightVal);		
				else RightVal.Clear();
			}
		}
	}while(i<=j);
	
	if(left < j) aplQSortByAttr(m_data, ext, left, j, attr1, attr2);
	if(i < right) aplQSortByAttr(m_data, ext, i, right, attr1, attr2);
	
	ext.Unique= bUnique;
	ext.Sorted_inst	= true;
	return true;
}

CRITICAL_SECTION *aplQSortByMultiAttr_crisec=0;
CaplAttr *aplQSortByMultiAttr_attr[5];
CaplNetStepData *aplQSortByMultiAttr_data=0;

int aplQSortByMultiAttr_Compare(const void *arg1, const void *arg2)
{
	if(arg1==arg2) return 0;
	if(0==aplQSortByMultiAttr_data) return 0;
	if(0==arg1 || 0==arg2)return 0;
	CaplInstance *inst1=*(CaplInstance **)arg1;
	CaplInstance *inst2=*(CaplInstance **)arg2;
	if(0==inst1 || 0==inst2)return 0;

	CaplValue *v1,*v2;
	int i;
	for(i=0;i<5;i++)
	{
		CaplAttr *attr=aplQSortByMultiAttr_attr[i];
		if(0==attr) return 0;
		aplQSortByMultiAttr_data->GetAttr(inst1,attr,&v1);
		aplQSortByMultiAttr_data->GetAttr(inst2,attr,&v2);
		if(0==v1 && 0==v2) continue;
		if(0==v1) return -1;
		if(0==v2) return 1;

		if(v1->IsEqu(*v2)) continue;
		if((*v1)<(*v2)) return -1;
		return 1;
	}
	return 0;
}

CString AFX_EXT_API GetMyDocPath()
{
	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("\\");
	}
	return sMyFolder;
}

bool aplQSortByMultiAttr(CaplNetStepData* m_data, aplExtent &ext, CaplAttr* attr1, CaplAttr* attr2, CaplAttr* attr3, CaplAttr* attr4, CaplAttr* attr5)
{
	if(0==m_data) return false;
	if(0==attr1) return false;
	if(ext.GetSize()<2) return true;

	if(0==aplQSortByMultiAttr_crisec)
	{
		aplQSortByMultiAttr_crisec=new CRITICAL_SECTION;
		InitializeCriticalSection(aplQSortByMultiAttr_crisec);
	}
	
	EnterCriticalSection(aplQSortByMultiAttr_crisec);
	aplQSortByMultiAttr_attr[0]=attr1;
	aplQSortByMultiAttr_attr[1]=attr2;
	aplQSortByMultiAttr_attr[2]=attr3;
	aplQSortByMultiAttr_attr[3]=attr4;
	aplQSortByMultiAttr_attr[4]=attr5;

	aplQSortByMultiAttr_data=m_data;

	qsort(ext.GetData(), ext.GetSize(), sizeof(CaplInstance*),aplQSortByMultiAttr_Compare);
	LeaveCriticalSection(aplQSortByMultiAttr_crisec);
	return true;
}


int aplQFindInstInExtentByAttr(CaplNetStepData* m_data, aplExtent &ext, CaplAttr* attr, CaplValue *val, bool full_cycle)
{
	if(ext.Size<1) return -1;

	CaplValue TstVal;
	CaplValue TstVal1;
	CaplValue TstVal2;
	if(ext.Size==1)
	{
		m_data->GetAttr(ext[0], attr, TstVal);
		if(TstVal==*val) return 0;
		return -1;
	}

	bool dir_low_high=true;
	int max_size=ext.Size;
	
	int i=0, i0=0, i1=max_size-1, io=-1;
	if( (ext[0]!=0) && (ext[1]!=0) &&  ext.Sorted_inst)
	{
		m_data->GetAttr(ext[0], attr, TstVal1);
		m_data->GetAttr(ext[1], attr, TstVal2);
		if(TstVal1>TstVal2) dir_low_high=false;
		// поиск упорядоченного значения
		do
		{
			io=i;
			i=(i0+i1)/2;
			if(io==i) break;
			bool end=false;
			while(ext[i]==0)
			{
				i--;
				if(i<0){end=true;break;}
			}
			if(end) break;
			
			m_data->GetAttr(ext[i], attr, TstVal);
			if(TstVal==*val){return i;}
			if(dir_low_high)
			{
				if(*val>TstVal) i0=i;
				else i1=i;
			}
			else
			{
				if(*val>TstVal) i1=i;
				else i0=i;
			}
		} while(1);
	}
	if(ext[i1]!=0)
	{
		m_data->GetAttr(ext[i1], attr, TstVal);
		if(TstVal==*val) return i1;
	}
	if(ext[i0]!=0)
	{
		m_data->GetAttr(ext[i0], attr, TstVal);
		if(TstVal==*val) return i0;
	}
	
	if(!full_cycle)return -1;
	// поиск неупорядоченного значения
	for(i=0;i<max_size;i++)
	{
		if(ext[i]==0) continue;

		m_data->GetAttr(ext[i], attr, TstVal);
		if(TstVal==*val) return i;
	}
	return -1;
}

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

/// Взять категорию на редактирование 
bool CaplCategoryManager::CheckOut( CaplInstance *categ)
{
	if(categ==0) return false;
	if(categ==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if(categ->GetType()==0) return false;
	if(m_data==0) return false;
	if(e_categ==0) return false;
	if(e_apl_product_category_ver==0)return false;

	// чтобы данные точно прочитались с сервера!
	m_data->ClearLastQuery();
	LoadCategoryInfo(categ,false);

	if(!m_data->IsKindOf(categ,e_prd_rel_prd_categ))return false;
	if(categ->GetAccessmode()>=aplRO)
	{
		if(m_api->m_ModeInteractive)aplErrorMessage(S::NoAccessRight(),categ);
		return false;
	}
	CString buf;
	CaplInstance *lock;
	CaplAggr aggr;

	m_data->GetAttr(categ,a_categ_lock,lock);
	if(lock!=0)
	{
		if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Категория уже редактируется !"),MB_OK|MB_ICONSTOP);
		return false;
	}
	CaplInstance *act=0;
	m_data->GetAttr(categ,a_categ_act,act);
	if(!act)
	{
		act=CreateCategoryVersion(categ,_T("0"));
	}

	lock=m_data->CreateInstance(e_apl_product_category_ver);
	m_data->PutAttr(categ,a_categ_lock,lock);
	m_data->PutAttr(lock,a_categ_ver_categ,categ);

	m_data->GetAttr(categ,a_categ_id,buf);
	m_data->PutAttr(lock,a_categ_ver_id,buf);
	m_data->GetAttr(categ,a_categ_name,buf);
	m_data->PutAttr(lock,a_categ_ver_name,buf);
	m_data->GetAttr(categ,a_categ_descr,buf);
	m_data->PutAttr(lock,a_categ_ver_descr,buf);
	m_data->GetAttr(categ,a_categ_products,aggr);
	m_data->PutAttr(lock,a_categ_ver_products,aggr);

	m_data->PutAttr(lock,a_categ_ver_author,m_data->GetCurrUser());
	
	COleDateTime dt=COleDateTime::GetCurrentTime();
	aplDate2String(dt,buf);
	m_data->PutAttr(lock,a_categ_ver_start,buf);

	if(m_AutoSave) m_data->NET_SaveChanges();

	return true;
}

CaplInstance *CaplCategoryManager::GetLock(CaplInstance *categ, bool bShowMessages)
{
	if(!m_bUseVersions) return 0;
	if(categ==0) return 0;
	if(categ==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return 0;};
	if(categ->GetType()==0) return 0;
	if(categ->GetAccessmode()>aplRO) return 0;
	if(!m_data->IsKindOf(categ,e_categ)) 
		if(!m_data->IsKindOf(categ,e_apl_product_category_ver))
			return 0;

	CaplInstance *lock=0,*user=0;
	CaplInstance *categ_ver_categ=0;
	if(m_data->IsKindOf(categ,e_categ))
	{
		categ_ver_categ=categ;
		m_data->GetAttr(categ,a_categ_lock,lock);
	}
	else if(m_data->IsKindOf(categ,e_apl_product_category_ver))
	{
		m_data->GetAttr(categ,a_categ_ver_categ,categ_ver_categ);
		if(!categ_ver_categ) return 0;
		m_data->GetAttr(categ_ver_categ,a_categ_lock,lock);
	}else{
		return 0;
	}
	CString categ_id=_T("");
	m_data->GetAttr(categ_ver_categ,a_categ_id,categ_id);
	if(lock==0)
	{
		if(bShowMessages && m_api->m_ModeInteractive)AfxMessageBox( APL_T("Категория ")+categ_id+ APL_T(" не заблокирована !"),MB_OK|MB_ICONSTOP);
		return 0;
	}
		
	return lock;
	
}

bool CaplCategoryManager::MakeCategoryVersionActive(CaplInstance *categ_ver)
{
	if(!m_bUseVersions) return false;
	if(categ_ver==0) return false;
	if(categ_ver==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if(categ_ver->GetAccessmode()>aplRO) {if(m_api->m_ModeInteractive)aplErrorMessage(S::NoAccessRight(),categ_ver); return false;}
	if(!m_data->IsKindOf(categ_ver,e_apl_product_category_ver))
		return false;

	CaplInstance *categ=0;
	m_data->GetAttr(categ_ver,a_categ_ver_categ,categ);	
	if(!categ) return false;
	if(categ->GetAccessmode()>aplRW) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("У Вас недостаточно прав чтобы сделать версию категории активной!"),MB_OK|MB_ICONSTOP); return false;}

	// чтобы данные точно прочитались с сервера!
	m_data->ClearLastQuery();
	LoadCategoryInfo(categ,false);
	if(categ->GetType()==0)
	{
		return false;
	}

	CaplInstance *lock=CheckMyLock(categ,false);
	if(GetLock(categ,false) && !lock) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Категория заблокирована другим пользователем !"),MB_OK|MB_ICONSTOP);return false;}
	
	CaplInstance *act=0;
	m_data->GetAttr(categ,a_categ_act,act);	
	if(act==categ_ver)
	{
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Версия уже активна!"));
		return false;
	}

	CString id,name,descr,buf;
	CString id0,name0,descr0;
	CaplAggr aggr,aggr0;

	m_data->GetAttr(categ_ver,a_categ_ver_id,id);
	m_data->GetAttr(categ_ver,a_categ_ver_name,name);
	m_data->GetAttr(categ_ver,a_categ_ver_descr,descr);
	m_data->GetAttr(categ_ver,a_categ_ver_products,aggr);

	m_data->PutAttr(categ,a_categ_act,categ_ver);


	m_data->PutAttr(categ,a_categ_id,id);
	m_data->PutAttr(categ,a_categ_name,name);
	m_data->PutAttr(categ,a_categ_descr,descr);
	m_data->PutAttr(categ,a_categ_products,aggr);


	if(m_AutoSave) m_data->NET_SaveChanges();
	m_data->GetAttr(categ,a_categ_products,aggr);

	if(m_AutoSave)
	{
		aplExtent ext; ext.Add(categ_ver);
		m_data->NET_SetInstancesAccess(&ext,(CaplInstance *)-1,aplRO);		
	}

	CString sSubject=  APL_T("Изменение содержимого категории "), sContent=  APL_T("Изменилось содержимое категории."),
		sCategName;
		
	m_api->GetItemName(categ, sCategName);
	sSubject+=sCategName;

	aplExtent sbscr_ext;
	m_api->m_message_mgr.GetItemsSubscribers(categ, sbscr_ext);
	aplExtent wo;
	wo.Add(categ);
	m_api->m_message_mgr.SendNotifyMessage(NULL, sbscr_ext,
	sSubject, sContent, wo);

	return true;
}

CaplInstance *CaplCategoryManager::CreateCategoryVersion(CaplInstance *categ,CString num,bool make_active)
{
	if(!m_bUseVersions) return 0;
	if(categ==0) return 0;
	if(categ==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return 0;};
	if(categ->GetType()==0) return 0;
	if(categ->GetAccessmode()>aplRO) return 0;
	if(!m_data->IsKindOf(categ,e_categ))
		if(!m_data->IsKindOf(categ,e_apl_product_category_ver))
			return 0;

	CString id=_T(""),name=_T(""),descr=_T(""),date_time=_T("");
	CaplInstance *categ_ver_categ=0,*categ_ver_base=0,*act_ver=0;
	CaplAggr products;

	CaplInstance *ver=m_data->CreateInstance(e_apl_product_category_ver);
	if(m_data->IsKindOf(categ,e_categ))
	{
		m_data->GetAttr(categ,a_categ_id,id);	
		m_data->GetAttr(categ,a_categ_name,name);
		m_data->GetAttr(categ,a_categ_descr,descr);
		m_data->GetAttr(categ,a_categ_products,products);
		categ_ver_categ=categ;
	}
	else
	{
		m_data->GetAttr(categ,a_categ_ver_id,id);	
		m_data->GetAttr(categ,a_categ_ver_name,name);
		m_data->GetAttr(categ,a_categ_ver_descr,descr);
		m_data->GetAttr(categ,a_categ_ver_products,products);
		m_data->GetAttr(categ,a_categ_ver_categ,categ_ver_categ);
		categ_ver_base=categ;
	}

	m_data->PutAttr(ver,a_categ_ver_id,id);	
	m_data->PutAttr(ver,a_categ_ver_name,name);
	m_data->PutAttr(ver,a_categ_ver_descr,descr);
	m_data->PutAttr(ver,a_categ_ver_products,products);
	m_data->PutAttr(ver,a_categ_ver_categ,categ_ver_categ);
	
	if(categ_ver_base) m_data->PutAttr(ver,a_categ_ver_prev,categ_ver_base);
	m_data->PutAttr(ver,a_categ_ver_author,m_data->GetCurrUser());
	COleDateTime dt=COleDateTime::GetCurrentTime();
	aplDate2String(dt,date_time);
	m_data->PutAttr(ver,a_categ_ver_start,date_time);
	m_data->PutAttr(ver,a_categ_ver_end,date_time);
	if(make_active)
	{
		m_data->PutAttr(ver,a_categ_ver_num,num);
		MakeCategoryVersionActive(ver);
	}
	
	if(m_AutoSave) 
		m_api->SaveChanges();
	return ver;

}
/// Завершить  редактирование категории  
bool CaplCategoryManager::CheckIn( CaplInstance *categ, bool make_new_version_active)
{
	if(categ==0) return false;
	if(categ==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if(categ->GetType()==0) return false;
	if(m_data==0) return false;
	if(e_categ==0) return false;
	if(e_apl_product_category_ver==0)return false;
	
	// чтобы данные точно прочитались с сервера!
	m_data->ClearLastQuery();
	LoadCategoryInfo(categ,false);
	if(categ->GetType()==0)
	{
		return false;
	}

	if(!m_data->IsKindOf(categ,e_prd_rel_prd_categ))return false;
	if(categ->GetAccessmode()>=aplRO)
	{
		if(m_api->m_ModeInteractive)aplErrorMessage(S::NoAccessRight(),categ);
		return false;
	}
	CaplInstance *lock=CheckMyLock(categ,true);

	if(lock==0)
	{
		return false;
	}

	CaplInstance *act;
	CString id,name,descr,buf;
	CString id0,name0,descr0;
	CaplAggr aggr,aggr0;


	m_data->GetAttr(lock,a_categ_ver_id,id);
	m_data->GetAttr(lock,a_categ_ver_name,name);
	m_data->GetAttr(lock,a_categ_ver_descr,descr);
	m_data->GetAttr(lock,a_categ_ver_products,aggr);
	
	// Проверка изменненности
	{
		m_data->GetAttr(categ,a_categ_id,id0);
		m_data->GetAttr(categ,a_categ_name,name0);
		m_data->GetAttr(categ,a_categ_descr,descr0);
		m_data->GetAttr(categ,a_categ_products,aggr0);

		if((id==id0)&&(name==name0)&&(descr==descr0))
		{
			if(aggr.GetSize()==aggr0.GetSize())
			{
				int i,j;
				CaplInstance *inst,*inst0;
				bool bNotFound=false;
				for(i=0;i<aggr.GetSize();i++)
				{
					bool bFound=false;
					aggr.GetByIndex(i,inst);
					for(j=0;j<aggr.GetSize();j++)
					{
						aggr0.GetByIndex(i,inst0);
						if(inst==inst0) {bFound=true; break;}
					}
					if(!bFound){bNotFound=true;break;}
				}
				if(!bNotFound)
				{
					if(m_api->m_ModeInteractive)
					{
						if(IDNO==AfxMessageBox( APL_T("Данные не изменились !\n\nОтменить редактирование ?"),
							MB_YESNO|MB_ICONQUESTION)) return false;
					}

					// Отмена редактирования
					m_data->PutAttr(categ,a_categ_lock,(CaplInstance*)0);
					m_data->DeleteInstance(lock);
					if(m_AutoSave) m_data->NET_SaveChanges();
					return true;
				}
			}
		}
	}
	
	m_data->PutAttr(categ,a_categ_lock,(CaplInstance*)0);
/*	if(make_new_version_active)
	{
		MakeCategoryVersionActive(lock);
	}*/

	m_data->GetAttr(categ,a_categ_act,act);
	m_data->PutAttr(categ,a_categ_act,lock);

	if(act!=0)m_data->PutAttr(lock,a_categ_ver_prev,act);
	m_data->PutAttr(categ,a_categ_id,id);
	m_data->PutAttr(categ,a_categ_name,name);
	m_data->PutAttr(categ,a_categ_descr,descr);

	m_data->PutAttr(categ,a_categ_products,aggr);

	COleDateTime dt=COleDateTime::GetCurrentTime();
	aplDate2String(dt,buf);
	m_data->PutAttr(lock,a_categ_ver_end,buf);

	int i,j,max_id=0;
	CaplInstance *inst;

	// Определение id версии
	CaplLoadData ld(m_data,DEF_SOURCE);
	j=ld.AddQuery(_T('b'), categ->GetId(), e_apl_product_category_ver,a_categ_ver_categ, true);
	  ld.AddQuery(_T('d'), j, 0,a_categ_ver_categ, true);
	  ld.AddQuery(_T('d'), j, 0,a_categ_ver_num, true);
	  ld.LoadEx();

	aplExtent ext_rev;
	m_data->GetEntityExtent(e_apl_product_category_ver,ext_rev);
	for(i=0;i<ext_rev.Size;i++)
	{
		m_data->GetAttr(ext_rev[i],a_categ_ver_categ,inst);
		if(inst==categ)
		{
			m_data->GetAttr(ext_rev[i],a_categ_ver_num,buf);
			j=_atoi(buf);
			if(j>max_id)max_id=j;
		}
	}
	max_id++;
	buf.Format(_T("%i"),max_id);
	m_data->PutAttr(lock,a_categ_ver_num,buf);

	if(m_AutoSave) m_data->NET_SaveChanges();
	m_data->GetAttr(categ,a_categ_products,aggr);

	if(m_AutoSave)
	{
		aplExtent ext; ext.Add(lock);
		m_data->NET_SetInstancesAccess(&ext,(CaplInstance *)-1,aplRO);		
// 		if(true==m_AutoUsurpire)
// 		{
// 			CString csAccPat;	
// 			if(TRUE==m_api->m_options_mgr.GetDefPatern(categ->GetType(),csAccPat))
// 			{
// 				aplExtent aet;
// 				aet.Add(categ);	
// 				apidata.NET_SetAccessFromPattern(&aet,csAccPat);
// 			}
// 		}
	}

	CString sSubject=  APL_T("Изменение содержимого категории "), sContent=  APL_T("Изменилось содержимое категории."),
		sCategName;
		
	m_api->GetItemName(categ, sCategName);
	sSubject+=sCategName;

	aplExtent sbscr_ext;
	m_api->m_message_mgr.GetItemsSubscribers(categ, sbscr_ext);
	aplExtent wo;
	wo.Add(categ);
	m_api->m_message_mgr.SendNotifyMessage(NULL, sbscr_ext,
	sSubject, sContent, wo);
	return true;
}

bool CaplStepManager::IsAdmin()
{
	if(!m_data || !m_data->IsDictLoad()) return false; 
	
	CaplInstance *pUser=m_data->GetCurrUser();
	return IsAdmin(pUser);
}

bool CaplStepManager::IsAdmin(CaplInstance* pUser, bool* bIsSystemAdmin/*=NULL*/)
{
	if(!m_data || !m_data->IsDictLoad()) return false; 
	if(pUser == NULL)
	{
		return false;
	}

	CaplInstance *inst = NULL;
	if(bIsSystemAdmin!=NULL)
	{
		*bIsSystemAdmin= false;
	}
	if(pUser->GetId()==DEFAILT_ID_ADMIN) 
	{
		if(bIsSystemAdmin!=NULL)
		{
			*bIsSystemAdmin= true;
		}
		return true;
	}
	CaplAggr aggr;
	m_data->GetAttr(pUser, m_api->m_appr_mgr.a_apl_user_groups, aggr);
	for(int i=0;i<aggr.GetSize();i++)
	{
		aggr.GetByIndex(i,inst);
		if(inst!=0) 
			if(inst->GetId()==DEFAILT_ID_ADMIN_GROUP){return true;}

	}

	return false;
}

CaplInstance* CaplStepManager::GetAdminGroup(bool bLoadFromDB/*=false*/)
{
	CaplEntity* pGroupsEntity= m_data->GetEntityBN(_T("apl_workgroup"));
	if(pGroupsEntity==NULL)
	{
		return NULL;
	}
	if(true == bLoadFromDB)
	{
		CaplLoadData ld(m_data,DEF_SOURCE);
		ld.AddQuery(_T('e'), 0, pGroupsEntity, 0, true, true);
		ld.LoadEx();
	}
	aplExtent extGroups;
	m_data->GetEntityExtent(pGroupsEntity, extGroups);
	for(int i=0;i<extGroups.GetSize();i++)
	{
		CaplInstance* pGroup= extGroups[i];
		if(pGroup!=NULL)
		{
			if(pGroup->GetId()==DEFAILT_ID_ADMIN_GROUP)
			{
				return pGroup;
			}
		}
	}
	return NULL;
}

CaplInstance* CaplStepManager::GetAllUsersGroup()
{
	CaplEntity* pGroupsEntity= m_data->GetEntityBN(_T("apl_workgroup"));
	if(pGroupsEntity==NULL)
	{
		return NULL;
	}
	CaplAttr* pGroupIdAttr= m_data->GetAttrDefinition(pGroupsEntity, _T("name"));
	if(pGroupIdAttr==NULL)
	{
		return NULL;
	}

	aplExtent ext;
	CaplAttrValue tst_values[1];

	CString sAllStr= _T("all");

	tst_values[0].value.Set(sAllStr);
	tst_values[0].attr=pGroupIdAttr;

	m_data->NET_FindInstancesWithAttrValues(pGroupsEntity,1,&tst_values[0],ext,true);

	CaplInstance* pGroup= NULL;
	if(ext.GetSize()>0)
	{
		pGroup= ext[0];
	}
	else
	{
		pGroup= m_data->CreateInstance(pGroupsEntity);
		m_data->PutAttr(pGroup, pGroupIdAttr, sAllStr);
		if(m_AutoSave) 
		{
			m_data->NET_SaveChanges();
		}
	}
	return pGroup;
}

bool CaplCategoryManager::CategoryHistory(CaplInstance* categ)
{
	if(categ==0) return false;
	if(categ==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if(categ->GetType()==0) return false;
	if(categ->GetId()==0) return false;
	if(m_data==0) return false;
	if(e_categ==0) return false;
	if(e_apl_product_category_ver==0)return false;
	
	CaplSetResourceHandle setres(module_inst);
	
	CCategoryDiffDlg dlg;
	dlg.m_api= m_api;
	dlg.m_inst= categ;
	
	dlg.DoModal();

	return true;
}

int CaplCategoryManager::IsProductsInCategory(aplExtent &categ, aplExtent &inExt, aplExtent &outExt)
{
	if(inExt.Size<=0) 
	{
		return -1;//Не задан входящий список
	}
	int i;
	aplExtent prd,all_prd;
	int c_cnt = categ.GetSize();
	if(c_cnt<=0) 
	{
		return 0;//категории не определены;
	}
	all_prd.Clear();
	aplExtent cats;
	for(i=0; i<c_cnt;i++)
	{
		GetCategoryContents(categ.GetAt(i), prd);
		aplExtent cat, rels;
		GetAllSubCategory2(categ.GetAt(i), cat, rels);
		cats.Append(cat);
		all_prd.Append(prd);
		prd.Clear();
	}
	//сортировать маленький, искать из большого в маленьком.
	aplExtent *big, *smal;
	bool bin= false;
	big = inExt.Size>=all_prd.Size ? &inExt : &all_prd;
	smal = inExt.Size<all_prd.Size ? &inExt : &all_prd;
	if(big==&inExt) return 1;
	
	if(all_prd.Size>0)
	{
		CSortClass::SortExtentByInst(*smal);
		for(i=0; i<big->Size;i++)
		{
			int ind = aplQuickFind((int*)smal->Data,smal->Size,(int)big->GetAt(i));
			if(ind>-1)
			{
				bool old = outExt.Unique;
				outExt.Unique = false;
				outExt.Add(big->GetAt(ind));
				if(bin) big->Remove(i);
				else smal->Remove(ind);
				outExt.Unique = old;
				if(inExt.Size==0)
				{
					return 1;//Все изделия найдены продолжать смысла нет
				}
				if(bin) i--;
			}
		}
	}

	return IsProductsInCategory(cats,inExt,outExt);
}
//*****************************************************************************
bool CaplStepManager::ChangeWFState(aplExtent &ext)
{
	if(!m_api->m_data.IsConnected()) return false;
	if(!m_api->m_data.IsAdmin())
	{
		aplErrorMessage(APL_T("Для выполнения операции необходимы права администратора!"));
		return false;
	}
	
	CaplInstance *inst;
	CaplAttr *attr = 0;
	CString tstr,old_state,prev_old_state=_T("");
	int i;
	
	if(ext.GetSize()==0) return true;

	for(i=0;i<ext.GetSize();i++)
	{
		inst = ext.GetAt(i);
		if(m_data->IsKindOf(inst,m_api->m_doc_mgr.e_doc)) attr = m_api->m_doc_mgr.a_apl_doc_wf_state;
		else if(m_data->IsKindOf(inst,m_api->m_prd_mgr.e_pdf)) attr = m_api->m_prd_mgr.a_apl_pdf_state;
		else if(m_data->IsKindOf(inst,m_api->m_bp_mgr.e_bp)) attr = m_api->m_bp_mgr.a_bp_state;
		else if(m_api->m_data.IsKindOf(inst,m_api->m_change_mgr.e_chng)) attr = m_api->m_change_mgr.a_chng_state;
		else if(m_api->m_data.IsKindOf(inst,m_api->m_req_mgr.e_requirement)) attr = m_api->m_req_mgr.a_req_wf_state;
		else return false;
	}

	CaplSetResourceHandle setres(module_inst);
	CSelectWFSDlg dlg;
	dlg.m_api = m_api;
	dlg.m_inst = 0;
	dlg.m_bOnlyFreeChange = true;
	INT_PTR res = dlg.DoModal();
	
	if(res != IDOK) return true;

	tstr = dlg.m_new_state;

	for(i=0;i<ext.GetSize();i++)
	{
		inst = ext.GetAt(i);
		if(m_data->IsKindOf(inst,m_api->m_doc_mgr.e_doc)) attr = m_api->m_doc_mgr.a_apl_doc_wf_state;
		else if(m_data->IsKindOf(inst,m_api->m_prd_mgr.e_pdf)) attr = m_api->m_prd_mgr.a_apl_pdf_state;
		else if(m_data->IsKindOf(inst,m_api->m_bp_mgr.e_bp)) attr = m_api->m_bp_mgr.a_bp_state;
		else if(m_api->m_data.IsKindOf(inst,m_api->m_change_mgr.e_chng)) attr = m_api->m_change_mgr.a_chng_state;
		else if(m_api->m_data.IsKindOf(inst,m_api->m_req_mgr.e_requirement)) attr = m_api->m_req_mgr.a_req_wf_state;

		m_api->m_data.GetAttr(inst,attr, old_state);

		CaplInstance *state = m_api->m_data.CreateInstance(e_wf_state_history);
		ASSERT(state);

		m_api->m_data.PutAttr(state,a_wf_new_state,tstr);
		m_api->m_data.PutAttr(state,a_wf_old_state,old_state);
		COleDateTime time = COleDateTime::GetCurrentTime();
		CString sTime;
		aplDate2String(time,sTime);
		m_api->m_data.PutAttr(state,a_wf_date,sTime);
		m_api->m_data.PutAttr(state,a_wf_item,inst);

		CString sUsername;
		CaplInstance *pers=m_api->m_appr_mgr.GetCurrentPerson();
		if(pers!=0) m_api->m_appr_mgr.GetPersonName(pers,sUsername);
		if(pers) sUsername+=_T(" (");
		sUsername+= m_api->m_data.GetNameCurrUser();
		if(pers) sUsername+=_T(")");

		m_api->m_data.PutAttr(state,a_wf_user,sUsername);
		m_api->m_data.PutAttr(inst,attr, tstr);

		//  Удаление подписей при переходе на доработку
		if(m_api->m_data.IsKindOf(inst,m_api->m_prd_mgr.e_pdf))
		{
			if(old_state==_T("approving") && tstr==_T("working"))//При переходе из состояния на согласовании в состояние в разработке
			{
				aplExtent ext;
				CaplInstance *active=inst;
				//if(m_api->m_data.IsKindOf(inst,m_api->m_doc_mgr.e_doc))
				//	m_api->m_data.GetAttr(inst,m_api->m_doc_mgr.a_apl_doc_active,active);
				m_api->m_appr_mgr.LoadItemApproval(active,ext);
				for(int i =0; i<ext.Size;i++)
				{
					if(ext[i]->GetAccessmode()<aplRW)
					{
						m_api->m_data.DeleteInstance(ext[i]);//Удалять все статусы
						ext.Remove(i);
						i--;
					}
				}
			}
		}
	}

	if(m_AutoSave) m_data->NET_SaveChanges();

	return true;
}
//*****************************************************************************
CaplInstance *CaplStepManager::ChangeWFState(CaplInstance *inst, const TCHAR *nState, UINT flag)
{
	if(!m_api->m_data.IsConnected()) return NULL;

	// только для казани. если объект - изменение и оно уже проведено, то ничего делать не надо
	if(m_api->m_options_mgr.CheckInstallCode(_T("KVZ")) && inst && m_api->m_data.IsKindOf(inst, m_api->m_change_mgr.e_chng))
	{
		CString state;
		m_api->m_data.GetAttr(inst, m_api->m_change_mgr.a_chng_state, state);

		if(0 == state.CompareNoCase(_T("applied")))
			return 0;
	}
	
	if(inst==0)
	{
		CaplSetResourceHandle setres(module_inst);
		CSelectWFSDlg dlg;
		dlg.m_api = m_api;
		dlg.m_inst = inst;
		dlg.DoModal();
		return NULL;
	}
	if(inst==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return 0;};
	
	if(m_api->m_data.IsKindOf(inst,m_api->m_bp_mgr.e_apl_bp_ver))
	{
		m_api->m_data.GetAttr(inst,m_api->m_bp_mgr.a_bp_ver_bp,inst);
		if(0==inst)
		{
			 if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! БП равен 0!"));
			 return 0;
		}
	}
	
	if(inst->GetAccessmode()>aplRW)
	{
		if(m_api->m_ModeInteractive)
			aplErrorMessage(S::NoAccessRight(),inst);
		return NULL;
	}

	if(!m_api->m_data.IsKindOf(inst,m_api->m_doc_mgr.e_doc) &&
		!m_api->m_data.IsKindOf(inst,m_api->m_bp_mgr.e_bp) &&
		!m_api->m_data.IsKindOf(inst,m_api->m_prd_mgr.e_pdf) &&
		!m_api->m_data.IsKindOf(inst,m_api->m_req_mgr.e_requirement) &&
		!m_api->m_data.IsKindOf(inst,m_api->m_change_mgr.e_chng) &&

		// Временная затычка (Зборошенко, 2009.08.31)
		!m_api->m_data.IsKindOfBN(inst, _T("apl_appearence_composition"))) return NULL;

	CaplAttr *attr = 0;
	if(m_data->IsKindOf(inst,m_api->m_doc_mgr.e_doc)) attr = m_api->m_doc_mgr.a_apl_doc_wf_state;
	else if(m_data->IsKindOf(inst,m_api->m_prd_mgr.e_pdf)) attr = m_api->m_prd_mgr.a_apl_pdf_state;
	else if(m_data->IsKindOf(inst,m_api->m_bp_mgr.e_bp)) attr = m_api->m_bp_mgr.a_bp_state;
	else if(m_api->m_data.IsKindOf(inst,m_api->m_change_mgr.e_chng)) attr = m_api->m_change_mgr.a_chng_state;
	else if(m_api->m_data.IsKindOf(inst,m_api->m_req_mgr.e_requirement)) attr = m_api->m_req_mgr.a_req_wf_state;

	// Временная затычка (Зборошенко, 2009.08.31)
	else if(m_api->m_data.IsKindOfBN(inst, _T("apl_appearence_composition"))) attr = m_api->m_data.GetAttrDefinitionBN(_T("apl_appearence_composition"), _T("state"));

	if(attr==0) return NULL;
	CString old_state=_T(""), tmp = _T("");
	CString tstr = nState;
	if(tstr.IsEmpty() && !(flag&APL_NOT_TEST_POSSIBLE_STATES && !m_api->m_ModeInteractive))
	{
		CaplSetResourceHandle setres(module_inst);
		CSelectWFSDlg dlg;
		dlg.m_api = m_api;
		dlg.m_inst = inst;
		if(dlg.DoModal()!=IDOK) 
		{
			return NULL;
		}

		tstr = dlg.m_new_state;
		flag=APL_NOT_TEST_POSSIBLE_STATES;
	}
	m_api->m_data.GetAttr(inst,attr,old_state);
	if(tstr==old_state) return NULL;
	
	/*Нельзя переводить объекты из состояния "Утверждено" без роли*/
	if((old_state==_T("canceled") || old_state==_T("approved")) && flag!=APL_NOT_TEST_POSSIBLE_STATES)
	{
		if(!IsAdmin())
		{
			CString role;
			m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Роли\\Роль для перевода объектов из состояния 'утверждено'"),role,_T(""));
			
			bool bCannSet=false;
			if(!role.IsEmpty())
			{
				if(m_api->m_appr_mgr.CheckPersonRole(0,role)) bCannSet=true;
			}
			if(!bCannSet)
			{
				if(inst->GetAccessmode()<=aplRW)
				{
					m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Роли\\Роль для перевода своих объектов из состояния 'утверждено'"),role,_T(""));
					if(!role.IsEmpty())
					{
						if(m_api->m_appr_mgr.CheckPersonRole(0,role)) bCannSet=true;
					}
				}
			}

			if(!bCannSet)
			{
				CString buf=  APL_T("Превести объект из состояния \"")+GetWFStateName(old_state)+ APL_T("\"\n могут только администраторы");
				if(!role.IsEmpty())
				{
					buf+= APL_T("\n или сотрудники с ролью \"");
					buf+=role;
					buf+=_T("\"");
				}
				buf+=_T("!");

				if(m_api->m_ModeInteractive) AfxMessageBox(buf,MB_OK|MB_ICONSTOP);
				return NULL;
			}
		}
	}
	CStringArray states;
	if(!(flag&APL_NOT_TEST_POSSIBLE_STATES))
	{
		if(!GetPossibleWFState(inst,states)) return NULL;
		bool ok = false;
		while(states.GetSize()>0)
		{
			CString str = states.GetAt(0);
			if(str==tstr)
			{
				ok = true;
				break;
			}
			states.RemoveAt(0);
		}
		if(!ok) 
		{
			m_api->GetItemName(inst, tstr);
			if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Для элемента \"") + tstr +  APL_T("\" не может быть установлено заданное состояние."), MB_ICONSTOP);
			return NULL;
		}
	}

	CaplInstance *state = m_api->m_data.CreateInstance(e_wf_state_history);
	ASSERT(state);
	m_api->m_data.PutAttr(state,a_wf_new_state,tstr);
	m_api->m_data.PutAttr(state,a_wf_old_state,old_state);
	COleDateTime time = COleDateTime::GetCurrentTime();
	CString sTime;
	aplDate2String(time,sTime);
	m_api->m_data.PutAttr(state,a_wf_date,sTime);
	m_api->m_data.PutAttr(state,a_wf_item,inst);

	CString sUsername;
	CaplInstance *pers=m_api->m_appr_mgr.GetCurrentPerson();
	if(pers!=0) m_api->m_appr_mgr.GetPersonName(pers,sUsername);
	if(pers) sUsername+=_T(" (");
	sUsername+= m_api->m_data.GetNameCurrUser();
	if(pers) sUsername+=_T(")");

	m_api->m_data.PutAttr(state,a_wf_user,sUsername);
	m_api->m_data.PutAttr(inst,attr, tstr);

	//16.11.2011 ayatsk параллельное изменение версии изделия по просьбе ГРПЗ
	if(m_api->m_data.IsKindOf(inst,m_api->m_doc_mgr.e_doc) )
	{
		if(tstr==_T("working") || tstr==_T("approving") || tstr==_T("approved") ||  tstr==_T("canceled") || tstr==_T("must_revision") )
		{ 
			int option=0;
			m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Состояния\\Изменять состояние версии изделия при изменении состояния документа"),option,0);
			if(0!=option)
			{
				//Ищем изделие
				CString sId,sId1;
				m_api->m_data.GetAttr(inst,m_api->m_doc_mgr.a_doc_id,sId);
				CaplInstance *prd,*pdf=0;
				prd=m_api->m_prd_mgr.FindPrdById(sId);
				if(0!=prd)pdf=m_api->m_prd_mgr.FindPdfById(prd,_T(""));
				if(0==pdf)
				{
					int k=sId.ReverseFind(_T('-'));
					if(k>0)
					{
						sId1=sId.Left(k);
						prd=m_api->m_prd_mgr.FindPrdById(sId1);
						if(0!=prd)
						{	
							sId1=sId.Right(sId.GetLength()-(k+1));
							pdf=m_api->m_prd_mgr.FindPdfById(prd,sId1);
						}
					}
				}
				if(0!=pdf)
				{
					CString sOldState1;
					m_api->m_data.GetAttr(pdf,m_api->m_prd_mgr.a_apl_pdf_state, sOldState1);
					if(sOldState1!=tstr)
					{
						CaplInstance *state = m_api->m_data.CreateInstance(e_wf_state_history);
						ASSERT(state);
						m_api->m_data.PutAttr(state,a_wf_new_state,tstr);
						m_api->m_data.PutAttr(state,a_wf_old_state,sOldState1);
						m_api->m_data.PutAttr(state,a_wf_date,sTime);
						m_api->m_data.PutAttr(state,a_wf_item,pdf);
						m_api->m_data.PutAttr(state,a_wf_user,sUsername);
						m_api->m_data.PutAttr(pdf,m_api->m_prd_mgr.a_apl_pdf_state, tstr);
					}
				}
			}
		}
	}
	
	//  Удаление подписей при переходе на доработку
	if(m_api->m_data.IsKindOf(inst,m_api->m_prd_mgr.e_pdf))
	{
		if(old_state==_T("approving") && tstr==_T("working"))//При переходе из состояния на согласовании в состояние в разработке
		{
			aplExtent ext;
			CaplInstance *active=inst;
			//if(m_api->m_data.IsKindOf(inst,m_api->m_doc_mgr.e_doc))
			//	m_api->m_data.GetAttr(inst,m_api->m_doc_mgr.a_apl_doc_active,active);
			m_api->m_appr_mgr.LoadItemApproval(active,ext);
			for(int i =0; i<ext.Size;i++)
			{
				if(ext[i]->GetAccessmode()<aplRW)
				{
					m_api->m_data.DeleteInstance(ext[i]);//Удалять все статусы
					ext.Remove(i);
					i--;
				}
			}
		}
	}
	if(m_AutoSave) m_data->NET_SaveChanges();
	return state;
}
//*****************************************************************************
CString CaplStepManager::TranslateMkState(const CString &state)
{
	if(state == _T("need_data_input"))
	{
		return APL_T("Заявка на ввод/изменение данных");
	}
	else if(state == _T("need_data_check"))
	{
		return APL_T("Требуется проверка");
	}
	else if(state == _T("need_data_limits"))
	{
		return APL_T("Нормирование");
	}
	
	return _T("");
}

CString CaplStepManager::GetPossibleWFState(CaplInstance *inst, CStringArray &states)
{
	if(inst==0) return _T("");
	if(inst==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return _T("");};
	if(inst->GetType()==0) return _T("");
	if(inst->GetAccessmode()>aplRO) return _T("");

	if(!m_api->m_data.IsKindOf(inst,m_api->m_doc_mgr.e_doc) &&
		!m_api->m_data.IsKindOf(inst,m_api->m_bp_mgr.e_bp) &&
		!m_api->m_data.IsKindOf(inst,m_api->m_req_mgr.e_requirement) &&
		!m_api->m_data.IsKindOf(inst,m_api->m_prd_mgr.e_pdf) &&
		!m_api->m_data.IsKindOfBN(inst, _T("apl_appearence_composition"))) return _T("");

	states.RemoveAll();
	CString val=_T("");
	CaplAttr *attr = 0;

	if(m_data->IsKindOf(inst,m_api->m_doc_mgr.e_doc)) attr = m_api->m_doc_mgr.a_apl_doc_wf_state;
	else if(m_data->IsKindOf(inst,m_api->m_prd_mgr.e_pdf)) attr = m_api->m_prd_mgr.a_apl_pdf_state;
	else if(m_data->IsKindOf(inst,m_api->m_bp_mgr.e_bp)) attr = m_api->m_bp_mgr.a_bp_state;
	else if(m_data->IsKindOf(inst,m_api->m_req_mgr.e_requirement)) attr = m_api->m_req_mgr.a_req_wf_state;

	// Временная затычка (Зборошенко, 2009.08.31)
	else if(m_api->m_data.IsKindOfBN(inst, _T("apl_appearence_composition"))) attr = m_api->m_data.GetAttrDefinitionBN(_T("apl_appearence_composition"), _T("state"));

	m_api->m_data.GetAttr(inst,attr,val);
	if(val==_T("working"))
	{
		states.Add(_T("approving"));
		states.Add(_T("approved"));	
		states.Add(_T("canceled"));			//отклoнено
		return val;
	}
	else if(val==_T("approving"))
	{
		states.Add(_T("working"));			//В разработке
		states.Add(_T("approved"));			//согласовано
		states.Add(_T("canceled"));			//отклoнено
		return val;
	}
	else if(val==_T("approved"))
	{
		states.Add(_T("canceled"));			//отклoнено
		states.Add(_T("changing"));			//на изменении
		states.Add(_T("must_revision"));	//требует пересмотра
		return val;
	}
	else if(val==_T("canceled"))
	{
		states.Add(_T("working"));			//В разработке
		states.Add(_T("approved"));
		return val;
	}
	else if(val==_T("changing"))
	{
		states.Add(_T("approving_change"));	//на согласовании изменения
		return val;
	}
	else if(val==_T("approving_change"))
	{
		states.Add(_T("changing"));
		states.Add(_T("approved"));			//согласовано
		return val;
	}
	else if(val==_T("must_revision"))
	{
		states.Add(_T("approved"));			//согласовано
		states.Add(_T("changing"));			//на изменении
		states.Add(_T("canceled"));			//отклoнено
		return val;
	}
	else if(val==_T(""))
	{
		states.Add(_T("working"));			//В разработке
		states.Add(_T("approving"));
		states.Add(_T("approved"));			//согласовано
		states.Add(_T("changing"));			//на изменении
		states.Add(_T("approving_change"));	//на согласовании изменения
		states.Add(_T("canceled"));			//отклoнено
		states.Add(_T("must_revision"));	//Требует пересмотра
		return val;
	}
	return val;
}
//*****************************************************************************
bool CaplStepManager::ShowWFStateHistory(CaplInstance *inst)
{
	CaplSetResourceHandle setres(module_inst);
	CWFSHistoryDlg dlg;
	dlg.m_inst = inst;
	dlg.m_api = m_api;
	dlg.DoModal();
	return true;
}
//*****************************************************************************
CString CaplStepManager::GetWFStateName(CString state)
{
	if(state==_T("approved")) return  APL_T("Утверждено");
	else if(state==_T("approving")) return  APL_T("На утверждении");
	else if(state==_T("changing")) return  APL_T("На изменении");
	else if(state==_T("working")) return  APL_T("В разработке");
	else if(state==_T("canceled")) return  APL_T("Не используется");
	else if(state==_T("released")) return  APL_T("В использовании");
	else if(state==_T("approving_change")) return  APL_T("На согласовании изменения");
	else if(state==_T("")) return  APL_T("Не определено");
	else if(state==_T("must_revision")) return  APL_T("Требует пересмотра");
	else if(state==_T("not_change")) return  APL_T("Не изменять");
	else return _T("");
}
//*****************************************************************************

CString aplMakeLover(LPCTSTR str)
{
	CString sTmp(str);
	return sTmp.MakeLower();
}
//*****************************************************************************

CString CaplStepManager::GetWFStateNameEng(CString state)
{
	state.MakeLower();

	if(state== aplMakeLover(APL_T("Утверждено"))) return _T("approved");
	else if(state== aplMakeLover(APL_T("На утверждении"))) return _T("approving");
	else if(state== aplMakeLover(APL_T("На изменении"))) return _T("changing");
	else if(state== aplMakeLover(APL_T("В разработке"))) return _T("working");
	else if(state== aplMakeLover(APL_T("Не используется"))) return _T("canceled");
	else if(state== aplMakeLover(APL_T("В использовании"))) return _T("released");
	else if(state== aplMakeLover(APL_T("На согласовании изменения"))) return _T("approving_change");
	else if(state== aplMakeLover(APL_T("Не определено"))) return _T("");
	else if(state== aplMakeLover(APL_T("Требует пересмотра"))) return _T("must_revision");	
	else if(state== aplMakeLover(APL_T("Не изменять"))) return _T("not_change");
	else return _T("");
}
//*****************************************************************************
bool CaplStepManager::CreateNote(CaplInstance *inst, CaplInstance *parent/* = NULL*/, CaplInstance **ciNote/* = NULL*/)
{
	CaplSetResourceHandle setres(module_inst);
	CNoteDlg dlg;
	AfxInitRichEdit2();
	dlg.m_inst = inst;
	dlg.m_api = m_api;
	dlg.m_parent = parent;
	dlg.DoModal();
	if(ciNote) *ciNote = dlg.m_ciNote;
	return true;
}

bool CaplStepManager::DeleteNote(CaplInstance *ciNote)
{
	if(0==ciNote) return false;
	if(ciNote->IsDeleted()) return false;
	if(!m_api->m_data.IsKindOf(ciNote,m_api->m_appr_mgr.e_note))return false;

	CString buf;
	CaplInstance *approval;
	m_api->m_data.GetAttr(ciNote,m_api->m_appr_mgr.a_note_approval,approval);

	if(0!=approval)
	{
		if(m_api->m_data.IsAdmin())
		{
			if(IDYES!=AfxMessageBox(APL_T("Примечание заверено электронной подписью.\nУдалить его можно только всесте с подписью!\n\nДействительно удалить примечание?"),
				MB_YESNO|MB_ICONSTOP))
			{
				return false;
			}

		}
		else
		{
			AfxMessageBox(APL_T("Примечание заверено электронной подписью. Его нельзя удалить!"),MB_ICONSTOP);
			return false;
		}
	}
	if(0!=approval)
	{
		aplExtent ext; ext.Add(approval);
		m_api->m_appr_mgr.LoadApprovalInfo(ext);

		COleDateTime odt=COleDateTime::GetCurrentTime();
		CString sDate;
		aplDate2String(odt,sDate);
		m_api->m_data.PutAttr(approval,m_api->m_appr_mgr.a_appr_revocation_date_time,sDate);

		m_api->m_data.GetAttr(approval,m_api->m_appr_mgr.a_appr_notes,buf);
		if(buf!=_T("")) buf+=_T("   ");
		buf+=APL_T("Подпись отозвана при удалении примечания");
		m_api->m_data.PutAttr(approval,m_api->m_appr_mgr.a_appr_notes,buf);
	}

	// Проверки самого примечания

	CaplInstance *noteItem;
	aplExtent notes;
	m_api->m_data.GetAttr(ciNote,m_api->m_appr_mgr.a_note_item,noteItem);
	if(0!=noteItem)
	{
		m_api->m_appr_mgr.FindAssociatedNotes(noteItem,notes);
		
		bool bHasChild=false;
		CaplInstance *par;
		for(int i=0; i<notes.GetSize();i++)
		{
			m_api->m_data.GetAttr(notes[i],m_api->m_appr_mgr.a_note_parent,par);
			if(par==ciNote) {bHasChild=true; break;}
		}
		if(bHasChild)
		{
			AfxMessageBox( APL_T("Сначала необходимо удалить все ответы на это примечание"));
			return false;
		}
	}

	CaplInstance *p=0,*pers = m_api->m_appr_mgr.GetCurrentPerson();
	m_api->m_data.GetAttr(ciNote,m_api->m_appr_mgr.a_note_author,p);
	if(p!=pers)
	{
		if(!m_api->m_appr_mgr.IsAdmin())
		{
			aplErrorMessage(APL_T("Удалять чужие примечания может только администратор!"));
			return false;
		}
		if(IDYES!=AfxMessageBox( APL_T("Вы хотите удалить чужое примечание!\n\nДействительно удалить примечание?"),MB_YESNO|MB_ICONSTOP|MB_DEFBUTTON2)) return false;
	}

	CString sDate;
	COleDateTime odt,odt1;
	m_api->m_data.GetAttr(ciNote,m_api->m_appr_mgr.a_note_date,sDate);
	aplString2Date(sDate,odt);
	m_api->m_data.NET_GetServerDateTime(odt1);
	COleDateTimeSpan ds=odt1-odt;
	if(ds.GetDays()>=1) {aplErrorMessage(APL_T("Примечание создано более суток назад! Его нельзя удалить!")); 		return false;	}

	
	//Удаление
	m_api->m_data.GetAttr(ciNote,m_api->m_appr_mgr.a_note_markup,buf);
	if(buf!=_T(""))	m_api->m_data.NET_DeleteBlob(ciNote,m_api->m_appr_mgr.a_note_markup);
	m_api->m_data.GetAttr(ciNote,m_api->m_appr_mgr.a_note_source,buf);
	if(buf!=_T(""))	m_api->m_data.NET_DeleteBlob(ciNote,m_api->m_appr_mgr.a_note_source);
	m_api->m_data.DeleteInstance(ciNote);
	m_api->SaveChanges();
	return true;
}


bool CaplStepManager::ShowNote(CaplInstance *ciNote, bool bReadOnly)
{
	if(0==ciNote) return false;
	CaplSetResourceHandle setres(module_inst);
	CNoteDlg dlg;
	AfxInitRichEdit2();
	dlg.m_api = m_api;
	dlg.m_ciNote=ciNote;
	dlg.m_b_read_only=bReadOnly;
	dlg.DoModal();
	return true;
}


//*****************************************************************************
bool CaplStepManager::ShowNotes(CaplInstance *inst, CaplInstance *ciNote, bool bShowTree)
{
	CaplSetResourceHandle setres(module_inst);
	CSelectNoteDlg dlg;
	AfxInitRichEdit2();
	dlg.m_api = m_api;
	dlg.m_inst = inst;
	dlg.mode = APL_DELETE_MODE;
	dlg.m_ciNoteToSelect = ciNote;
	dlg.m_bShowTree=bShowTree;
	dlg.DoModal();
	return true;
}
//*****************************************************************************
bool CaplStepManager::FindAssociatedNotes(CaplInstance *inst, aplExtent &notes)
{
	notes.Clear();
	if(inst==0) return false;
	if(inst==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if(!m_data->IsConnected()) return false;
	if(inst->GetTemporary() == true) return false;
	CaplLoadData ld(m_data,DEF_SOURCE);

		ld.AddQuery(0,inst);
	int a = ld.AddQuery(_T('r'),0,e_note,a_note_item, true,true);
		/*ld.AddQuery(_T('d'), a, 0, a_note_source,true);
		ld.AddQuery(_T('d'), a, 0, a_note_date,true);
		ld.AddQuery(_T('d'), a, 0, a_note_descr,true);
		ld.AddQuery(_T('d'), a, 0, a_note_item,true);
		ld.AddQuery(_T('d'), a, 0, a_note_author,true);
		ld.AddQuery(_T('d'), a, 0, a_note_parent,true);*/

		if(0!=m_api){if(!m_api->m_bLoadedOrgstruct)  ld.AddQuery(_T('d'), a, 0, a_note_author,true,true);}


	ld.LoadEx();
	aplExtent ext;
	m_data->GetEntityExtent(e_note,ext);
	CaplInstance *tmp=0;		
	for(int i=0; i<ext.GetSize();i++)
	{
		m_data->GetAttr(ext[i],a_note_item,tmp);
		if(tmp==inst) notes.Add(ext[i]);
	}
	return true;
}
//*****************************************************************************
bool CaplStepManager::SetRTFToRichEdit(CaplRichEditCtrl *richedit, CaplInstance *inst)
{
	return CSelectNoteDlg::SetRTF(richedit, inst, m_api);
}

//*****************************************************************************
CString GetCommand(TCHAR *rtf)
{
	if(rtf[0]!=_T('\\')) return rtf[0];
	CString str = rtf;
	int pos = str.Find(_T("\\"),1);
//	int t = str.Find(_T(";"),1);
//	if(t>-1) pos = pos>t ? t:pos;
	int t = str.Find(_T("}"),1);
	if(t>-1) pos = pos>t ? t:pos;
	t = str.Find(_T("{"),1);
	if(t>-1) pos = pos>t ? t:pos;
	if(pos<0) return _T("");
	CString rez = str.Mid(1,pos-1);
	rez.TrimLeft();
	rez.TrimRight();
	if(rez==_T("") && str>_T(""))
	{
		str = str.Right(str.GetLength()-1);
		return GetCommand(str.GetBuffer(0));
	}
	else 
		return rez;
}
//*****************************************************************************
bool apl_ConvertRTF2HTML(char *rtf, char *filename)
{
	CString fname=_T("");
	if(filename==0)
	{
		CFileDialog dlg(false,_T("html"),NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, APL_T("Файлы HTML (*.html, *.htm)|*.html,*.htm|"));
		dlg.m_ofn.lpstrTitle =  APL_T("Сохранить текст как");
		if(dlg.DoModal()==IDCANCEL) return false;
		fname = dlg.GetPathName();
	}
	else
		fname = filename;
	CString body = rtf;
	int scob_cnt=0;
	int par_cnt = 0;
	if(body.GetLength()<5) return false;
	if(body.Left(5)!=_T("{\\rtf")) return false;
	int pos_e = body.ReverseFind(_T('}'));
	int pos_b = body.Find(_T("\\"),4);
	if(pos_b==-1 || pos_e==-1) return false;
	body = body.Mid(pos_b,pos_e-5);
	CStdioFile html;
	if(!html.Open(fname,CFile::modeCreate|CFile::modeWrite)) return false;
	html.WriteString(_T("<HEAD>\n"));
	html.WriteString(_T("<TITLE>\n"));
	html.WriteString(fname+_T("\n"));
	html.WriteString(_T("</TITLE>\n"));
	html.WriteString(_T("</HEAD>\n"));
	html.WriteString(_T("<BODY>\n"));
	CString cmd, w_cmd;
	bool sup=false, sub=false, under=false, strike=false, bold=false, ital=false;
	CStringArray fonts;
	CStringArray colors;
	colors.Add(_T("\"#000000\""));
	int cnt = 0;
	while((cmd=GetCommand(body.GetBuffer(0)))>_T(""))
	{
		w_cmd = _T("");
		cnt = cmd.GetLength();
		if(cnt>1) cnt++;
		if(cmd.Find(_T(" "))>0 && cmd.Left(1)!=_T("'")) 
		{
			w_cmd = cmd.Right(cmd.GetLength()-cmd.Find(_T(" ")));
			cmd = cmd.Left(cmd.Find(_T(" ")));
		}
		if(cmd==_T("b") && cnt==1) cnt++;
		else if(cmd==_T("i") && cnt==1) cnt++;

		if(cmd==_T("ansicpg1251")) w_cmd = _T("<META HTTP-EQUIV=\"Content-Type\" content=\"text/html; charset=windows-1251\">\n") + w_cmd; 
		else if(cmd==_T("{")) scob_cnt++; 
		else if(cmd==_T("}")) scob_cnt--; 
		else if(cmd==_T("fonttbl"))//Загрузка шрифтов
		{
			w_cmd = _T("");
			int scob_cnt_tmp = scob_cnt;
			while((cmd=GetCommand(body.GetBuffer(0)))>_T(""))
			{
				if(cmd==_T("{")) scob_cnt++; 
				else if(cmd==_T("}")) scob_cnt--; 
				else if(cmd.Left(8)==_T("fcharset") && cmd.Find(_T(" "))>-1)
				{
					CString name = cmd.Right(cmd.GetLength()-cmd.Find(_T(" "))-1);
					if(name.GetAt(name.GetLength()-1)==_T(';')) name = name.Left(name.GetLength()-1);
					fonts.Add(name);
				}
				int cnt = cmd.GetLength();
				if(cnt>1) cnt++;
				body = body.Right(body.GetLength()-cnt);
				if(scob_cnt<scob_cnt_tmp) break;
			}
			cmd = GetCommand(body.GetBuffer(0));
			cnt = cmd.GetLength();
			if(cnt>1) cnt++;
			if(cmd.Find(_T(" "))>0) 
			{
				w_cmd = cmd.Right(cmd.GetLength()-cmd.Find(_T(" "))-1);
				cmd = cmd.Left(cmd.Find(_T(" ")));
			}
		}
		else if(cmd==_T("colortbl"))//Задание массива палитр
		{
			w_cmd = _T("");
			CString r,g,b;
			body = body.Right(body.GetLength()-cnt);
			while((r = GetCommand(body.GetBuffer(0)))!=_T("}"))
			{
				int cnt = r.GetLength();
				if(cnt>1) cnt++;
				body = body.Right(body.GetLength()-cnt);
				if(r.Left(3)!=_T("red")) continue;
				g = GetCommand(body.GetBuffer(0));
				cnt = g.GetLength();
				if(cnt>1) cnt++;
				body = body.Right(body.GetLength()-cnt);
				b = GetCommand(body.GetBuffer(0));
				cnt = b.GetLength();
				if(cnt>1) cnt++;
				body = body.Right(body.GetLength()-cnt);
				BYTE cr,cg,cb;
				r = r.Right(r.GetLength()-3);g = g.Right(g.GetLength()-5);b = b.Right(b.GetLength()-4);b = b.Left(b.GetLength()-1);
				BYTE tr,tg,tb;
				cr = _atoi(r);cg = _atoi(g);cb = _atoi(b);
				tr = cr/16;tg = cg/16;tb = cb/16;
				cr = cr - tr*16;cg = cg - tg*16;cb = cb - tb*16;
#if _MSC_VER >= 1400
				if(tr>9) r = _T('a') + (CString)( char(tr - 10) ); else r.Format(_T("%d"),tr);
				if(tg>9) g = _T('a') + (CString)( char(tg - 10) ); else g.Format(_T("%d"),tg);
				if(tb>9) b = _T('a') + (CString)( char(tb - 10) ); else b.Format(_T("%d"),tb);
#else
				if(tr>9) r = _T('a') + tr - 10; else r.Format(_T("%d"),tr);
				if(tg>9) g = _T('a') + tg - 10; else g.Format(_T("%d"),tg);
				if(tb>9) b = _T('a') + tb - 10; else b.Format(_T("%d"),tb);
#endif
				CString t;
#if _MSC_VER >= 1400
				if(cr>9) r += _T('a')+(CString)( char(cr - 10) );else {t.Format(_T("%s%d"),r,cr);r=t;}
				if(cg>9) g += _T('a')+(CString)( char(cg - 10) );else {t.Format(_T("%s%d"),g,cg);g=t;}
				if(cb>9) b += _T('a')+(CString)( char(cb - 10) );else {t.Format(_T("%s%d"),b,cb);b=t;}
#else
				if(cr>9) r += _T('a')+cr-10;else {t.Format(_T("%s%d"),r,cr);r=t;}
				if(cg>9) g += _T('a')+cg-10;else {t.Format(_T("%s%d"),g,cg);g=t;}
				if(cb>9) b += _T('a')+cb-10;else {t.Format(_T("%s%d"),b,cb);b=t;}
#endif
				t = _T("\"#")+r+g+b+_T("\"");
				colors.Add(t);
			}
			scob_cnt--;
			cmd = r;
			cnt = cmd.GetLength();
			if(cnt>1) cnt++;
			if(cmd.Find(_T(" "))>0) 
			{
				w_cmd = cmd.Right(cmd.GetLength()-cmd.Find(_T(" "))-1);
				cmd = cmd.Left(cmd.Find(_T(" ")));
			}
		}
		else if(cmd==_T("par")) 
		{
			if(ital) w_cmd = _T("</i>")+w_cmd;ital=false;
			if(bold) w_cmd = _T("</b>")+w_cmd;bold=false;
			if(strike) w_cmd = _T("</strike>")+w_cmd;strike=false;
			if(under) w_cmd = _T("</u>")+w_cmd;under=false;
			w_cmd = _T("<br>\n") + w_cmd;
		}
		else if(cmd==_T("line")) w_cmd = _T("<br>\n") + w_cmd;
		else if(cmd.Left(2)==_T("fs"))
		{
			int s = _atoi(cmd.Mid(2,2));
			if(s<8)		s=1;
			else if(s<10)	s=2;
			else if(s<12)	s=3;
			else if(s<14)	s=4;
			else if(s<18)	s=5;
			else if(s<24)	s=6;
			else if(s<36)	s=7;
			CString size;
			size.Format(_T("%d"),s/2);
			w_cmd = _T("<font size = \"")+size+_T("\">") + w_cmd;			
		}
		else if(cmd[0]==_T('f')) //Если это шрифт то селектим его.
		{
			CString s = _T("");
			for(int i=0;i<fonts.GetSize();i++)
			{
				s.Format(_T("f%d"),i);
				if(s==cmd){w_cmd = _T("<font face = \"")+fonts[i]+_T("\">\n") + w_cmd;break;}
			}
		}
		else if(cmd==_T("b0"))	{w_cmd = _T("</b>")+w_cmd;bold=false;}
		else if(cmd==_T("b"))	{w_cmd = _T("<b>")+w_cmd;bold=true;}
		else if(cmd.Left(1)==_T("'"))
		{
			BYTE b1=0, b2=0;
			CString tmp1 = cmd.Mid(1,1); tmp1.MakeLower();
			CString tmp2 = cmd.Mid(2,1); tmp2.MakeLower();
			if(tmp1.FindOneOf(_T("0123456789"))>-1) b1 = (BYTE)_atoi(tmp1);
			else if(tmp1.FindOneOf(_T("abcdef"))>-1) b1 = (BYTE)(tmp1[0]-_T('a')+10);
			if(tmp2.FindOneOf(_T("0123456789"))>-1) b2 = (BYTE)_atoi(tmp2);
			else if(tmp2.FindOneOf(_T("abcdef"))>-1) b2 = (BYTE)(tmp2[0]-_T('a')+10);
			char rez = b1*16+b2;
			tmp1=_T(""); tmp1+=rez; w_cmd=tmp1+cmd.Right(cmd.GetLength()-3)+w_cmd;
		}
		else if(cmd==_T("qc")) w_cmd = _T("<p align=center>")+w_cmd;
		else if(cmd==_T("qr")) w_cmd = _T("<p align=right>")+w_cmd;
		else if(cmd==_T("ql")) w_cmd = _T("<p align=left>")+w_cmd;
		else if(cmd==_T("pard")) 
		{
			if(sub) w_cmd=_T("</sub>")+w_cmd;if(sup) w_cmd=_T("</sup>")+w_cmd;w_cmd = _T("<p align=left>")+w_cmd;sub=false;sup=false;
			if(ital) w_cmd = _T("</i>")+w_cmd;ital=false;
			if(bold) w_cmd = _T("</b>")+w_cmd;bold=false;
			if(strike) w_cmd = _T("</strike>")+w_cmd;strike=false;
			if(under) w_cmd = _T("</u>")+w_cmd;under=false;
		}
		else if(cmd==_T("strike0")) {w_cmd=_T("</strike>")+w_cmd;strike=false;}
		else if(cmd==_T("strike")) {w_cmd=_T("<strike>")+w_cmd;strike=true;}
		else if(cmd==_T("i0")) w_cmd = _T("</i>")+w_cmd;
		else if(cmd==_T("i")) w_cmd = _T("<i>")+w_cmd;
		else if(cmd==_T("ulnone")) {w_cmd = _T("</u>")+w_cmd;under=false;}
		else if(cmd==_T("ulw")) cmd = _T("ul");
		else if(cmd==_T("uldb")) cmd = _T("ul");
		else if(cmd==_T("ul0"))	{w_cmd = _T("</u>")+w_cmd;under=false;}
		else if(cmd==_T("ul"))	{w_cmd = _T("<u>")+w_cmd;under=true;}
		else if(cmd==_T("up0")) {w_cmd = _T("</sup>")+w_cmd;sup=false;}
		else if(cmd.Left(1)==_T("u") && cmd.GetLength()>5) w_cmd = _T("&#")+cmd.Mid(1,4)+_T(";")+cmd.Mid(6,cmd.GetLength()-6); 
		else if(cmd==_T("dn0")) {w_cmd = _T("</sub>")+w_cmd;sub=false;}
		else if(cmd.Left(2)==_T("up") && !sup){w_cmd = _T("<sup>")+w_cmd;sup=true;if(sub) w_cmd=_T("</sub>")+w_cmd;sub=false;}
		else if(cmd.Left(2)==_T("dn") && !sub){w_cmd = _T("<sub>")+w_cmd;sub=true;if(sup) w_cmd=_T("</sup>")+w_cmd;sup=false;}
		else if(cmd.Left(2)==_T("cf"))
		{
			CString t = cmd.Mid(2,3);
			int i = _atoi(t);
			if(i>-1 && i<colors.GetSize()) 
				w_cmd = _T("<font color=")+colors.GetAt(i)+_T(">")+w_cmd;
		}

		body = body.Right(body.GetLength()-cnt);
		if(cmd==_T(" ")) w_cmd = _T(" ");
		html.WriteString(w_cmd);
	}
	html.WriteString(_T("</BODY>\n"));
	html.Close();
	return true;
}

bool CaplPreProjectManager::Attach(CaplAPI *api)
{
	if(api==0) {Detach();return false;}
	CaplStepManager::Attach(api);

	e_project=m_data->GetEntityBN(_T("apl_project"));
	a_project_id=m_data->GetAttrDefinition(e_project, _T("id"));
	a_project_name=m_data->GetAttrDefinition(e_project, _T("name"));
	a_project_descr=m_data->GetAttrDefinition(e_project, _T("description"));
	a_project_descr2=m_data->GetAttrDefinition(e_project, _T("description2"));
	a_project_owner=m_data->GetAttrDefinition(e_project,_T("owner") );
	a_project_kurator=m_data->GetAttrDefinition(e_project,_T("kurator") );
	a_project_executors=m_data->GetAttrDefinition(e_project,_T("executors"));
	a_project_co_executors=m_data->GetAttrDefinition(e_project,_T("co_executors"));
	a_project_co_customers=m_data->GetAttrDefinition(e_project,_T("co_customers"));
	a_project_prev_sequences=m_data->GetAttrDefinition(e_project,_T("prev_sequences"));
	a_project_customer=m_data->GetAttrDefinition(e_project,_T("customer"));
	a_project_date_planned_begin=m_data->GetAttrDefinition(e_project,_T("date_planned_begin"));
	a_project_date_planned_duration=m_data->GetAttrDefinition(e_project,_T("planed_duration"));
	a_project_date_set_mask=m_data->GetAttrDefinition(e_project,_T("date_set_mask"));
	a_project_date_planned_end=m_data->GetAttrDefinition(e_project,_T("date_planned_end"));
	a_project_date_planned_end2=m_data->GetAttrDefinition(e_project,_T("date_planned_end2"));
	a_project_date_actual_begin=m_data->GetAttrDefinition(e_project, _T("date_actual_begin"));
	a_project_date_actual_end=m_data->GetAttrDefinition(e_project,_T("date_actual_end"));
	a_project_date_actual_end2=m_data->GetAttrDefinition(e_project,_T("date_actual_end2"));
	a_project_labor_useness=m_data->GetAttrDefinition(e_project,_T("labor_useness"));
	a_project_labor_useness_actual=m_data->GetAttrDefinition(e_project,_T("labor_useness_actual"));
	a_project_labor_useness_actual_date=m_data->GetAttrDefinition(e_project,_T("labor_useness_actual_date"));
	a_project_labor_of_item=m_data->GetAttrDefinition(e_project,_T("labor_of_item"));
	a_project_persentage=m_data->GetAttrDefinition(e_project,_T("persentage"));
	a_project_state=m_data->GetAttrDefinition(e_project,_T("state"));
	a_project_parent=m_data->GetAttrDefinition(e_project,_T("parent"));
	a_project_content=m_data->GetAttrDefinition(e_project,_T("content"));
	a_project_type=m_data->GetAttrDefinition(e_project,_T("type"));
	a_project_prototype=m_data->GetAttrDefinition(e_project,_T("prototype"));
	a_project_prd_amount_planned=m_data->GetAttrDefinition(e_project,_T("product_amount_planned"));
	a_project_prd_amount_actual=m_data->GetAttrDefinition(e_project,_T("product_amount_actual"));
	a_project_prd_amount_unit=m_data->GetAttrDefinition(e_project,_T("product_amount_unit"));
	a_project_calc_by_amount=m_data->GetAttrDefinition(e_project,_T("calculate_labor_by_prd_amount"));
	a_project_control_type=m_data->GetAttrDefinition(e_project,_T("control_type"));
	a_project_transactions = m_data->GetAttrDefinition(e_project,_T("transactions"));
	a_project_number = m_data->GetAttrDefinition(e_project,_T("number"));

	a_project_taken_measures = m_data->GetAttrDefinition(e_project,_T("taken_measures"));
	a_project_payment_condition = m_data->GetAttrDefinition(e_project,_T("payment_condition"));
	a_project_note1 = m_data->GetAttrDefinition(e_project,_T("note1"));
	a_project_note2	= m_data->GetAttrDefinition(e_project,_T("note2"));
	a_project_note3 = m_data->GetAttrDefinition(e_project,_T("note3"));

	e_labor_useness_value=m_data->GetEntityBN(_T("labor_useness_value"));
	a_labor_value=m_data->GetAttrDefinition(e_labor_useness_value, _T("value_component"));
	a_labor_unit=m_data->GetAttrDefinition(e_labor_useness_value, _T("unit_component"));

	e_project_type=m_data->GetEntityBN(_T("apl_project_type"));
	a_project_type_name=m_data->GetAttrDefinition(e_project_type,_T("name"));

	//Версии 
	a_project_act_adm_version=m_data->GetAttrDefinition(e_project, _T("active_adm_version"));
	a_project_locker_adm_version=m_data->GetAttrDefinition(e_project, _T("locker_adm_version"));
	a_project_act_cont_version=m_data->GetAttrDefinition(e_project, _T("active_content_version"));
	a_project_locker_cont_version=m_data->GetAttrDefinition(e_project, _T("locker_content_version"));

	e_project_adm_ver=m_data->GetEntityBN(_T("apl_project_administrativ_version"));
	a_project_adm_ver_id=m_data->GetAttrDefinition(e_project_adm_ver, _T("id"));
	a_project_adm_ver_name=m_data->GetAttrDefinition(e_project_adm_ver, _T("name"));
	a_project_adm_ver_number=m_data->GetAttrDefinition(e_project_adm_ver, _T("number"));
	a_project_adm_ver_descr=m_data->GetAttrDefinition(e_project_adm_ver, _T("description"));
	a_project_adm_ver_type=m_data->GetAttrDefinition(e_project_adm_ver, _T("type"));
	a_project_adm_ver_customer=m_data->GetAttrDefinition(e_project_adm_ver, _T("customer"));
	a_project_adm_ver_labor_useness=m_data->GetAttrDefinition(e_project_adm_ver, _T("labor_useness"));
	a_project_adm_ver_kurator=m_data->GetAttrDefinition(e_project_adm_ver, _T("kurator"));
	a_project_adm_ver_executors=m_data->GetAttrDefinition(e_project_adm_ver, _T("executors"));
	a_project_adm_ver_co_executors=m_data->GetAttrDefinition(e_project_adm_ver, _T("co_executors"));
	a_project_adm_ver_co_customers=m_data->GetAttrDefinition(e_project_adm_ver, _T("co_customers"));
	a_project_adm_ver_prev_sequences=m_data->GetAttrDefinition(e_project_adm_ver, _T("prev_sequences"));
	a_project_adm_ver_date_planned_begin=m_data->GetAttrDefinition(e_project_adm_ver, _T("date_planned_begin"));
	a_project_adm_ver_date_planned_end=m_data->GetAttrDefinition(e_project_adm_ver, _T("date_planned_end"));
	a_project_adm_ver_date_planned_end2=m_data->GetAttrDefinition(e_project_adm_ver, _T("date_planned_end2"));
	a_project_adm_ver_date_planned_duration=m_data->GetAttrDefinition(e_project_adm_ver, _T("planed_duration"));
	a_project_adm_ver_date_set_mask=m_data->GetAttrDefinition(e_project_adm_ver, _T("date_set_mask"));
	a_project_adm_ver_project=m_data->GetAttrDefinition(e_project_adm_ver, _T("project"));
	a_project_adm_ver_num=m_data->GetAttrDefinition(e_project_adm_ver, _T("version_id"));
	a_project_adm_ver_author=m_data->GetAttrDefinition(e_project_adm_ver, _T("author"));
	a_project_adm_ver_start=m_data->GetAttrDefinition(e_project_adm_ver, _T("date_of_create"));
	a_project_adm_ver_end=m_data->GetAttrDefinition(e_project_adm_ver, _T("date_of_end"));	
	a_project_adm_ver_content=m_data->GetAttrDefinition(e_project_adm_ver, _T("content"));	
	a_project_adm_ver_parent=m_data->GetAttrDefinition(e_project_adm_ver, _T("parent"));	
	a_project_adm_ver_basis=m_data->GetAttrDefinition(e_project_adm_ver, _T("basis"));
	a_project_adm_ver_labor_of_item=m_data->GetAttrDefinition(e_project_adm_ver, _T("labor_of_item"));
	a_project_adm_ver_persentage=m_data->GetAttrDefinition(e_project_adm_ver, _T("persentage"));
	a_project_adm_ver_prd_amount_planned=m_data->GetAttrDefinition(e_project_adm_ver, _T("product_amount_planned"));
	a_project_adm_ver_prd_amount_unit=m_data->GetAttrDefinition(e_project_adm_ver, _T("product_amount_unit"));
	a_project_adm_ver_calc_by_amount=m_data->GetAttrDefinition(e_project_adm_ver, _T("calculate_labor_by_prd_amount"));
	a_project_adm_ver_control_type=m_data->GetAttrDefinition(e_project_adm_ver,_T("control_type"));

	e_project_cont_ver=m_data->GetEntityBN(_T("apl_project_content_version"));
	a_project_cont_ver_project=m_data->GetAttrDefinition(e_project_cont_ver, _T("project"));
	a_project_cont_ver_num=m_data->GetAttrDefinition(e_project_cont_ver, _T("version_id"));
	a_project_cont_ver_act_content=m_data->GetAttrDefinition(e_project_cont_ver, _T("active_content"));


	e_project_ref=m_data->GetEntityBN(_T("apl_project_reference"));

	a_project_ref_item=m_data->GetAttrDefinition(e_project_ref, _T("item"));
	a_project_ref_project=m_data->GetAttrDefinition(e_project_ref, _T("project"));
	a_project_ref_id=m_data->GetAttrDefinition(e_project_ref, _T("id"));
	a_project_ref_name=m_data->GetAttrDefinition(e_project_ref, _T("name"));
	a_project_ref_control_status=m_data->GetAttrDefinition(e_project_ref, _T("control_status"));

	e_project_seg=m_data->GetEntityBN(_T("apl_project_sequence"));
	a_project_seq_prev=m_data->GetAttrDefinition(e_project_seg, _T("prev"));
	a_project_seq_next=m_data->GetAttrDefinition(e_project_seg, _T("next"));
	a_project_seq_type=m_data->GetAttrDefinition(e_project_seg, _T("type"));
	a_project_seq_offset=m_data->GetAttrDefinition(e_project_seg, _T("offset"));

	e_money_transaction = m_data->GetEntityBN(_T("apl_money_transaction"));
	a_money_transaction_id = m_data->GetAttrDefinition(e_money_transaction, _T("id"));
	a_money_transaction_name = m_data->GetAttrDefinition(e_money_transaction, _T("name"));
	a_money_transaction_descr = m_data->GetAttrDefinition(e_money_transaction, _T("descr"));
	a_money_transaction_type = m_data->GetAttrDefinition(e_money_transaction, _T("type"));
	a_money_transaction_date = m_data->GetAttrDefinition(e_money_transaction, _T("date"));
	a_money_transaction_summ = m_data->GetAttrDefinition(e_money_transaction, _T("summ"));
	a_money_transaction_account = m_data->GetAttrDefinition(e_money_transaction, _T("account"));
	a_money_transaction_nds = m_data->GetAttrDefinition(e_money_transaction, _T("nds"));
	
	m_show_ass_projects=1;

	m_bShowMessages=true;
	return true;
}

void CaplPreProjectManager::Detach()
{
	e_project=0;
	a_project_id=0;
	a_project_name=0;
	a_project_descr=0;
	a_project_descr2=0;
	a_project_owner=0;
	a_project_customer=0;
	a_project_kurator=0;
	a_project_executors=0;
	a_project_co_executors=0;
	a_project_co_customers=0;
	a_project_prev_sequences=0;
	a_project_date_planned_begin=0;
	a_project_date_planned_end=0;
	a_project_date_planned_end2=0;
	a_project_date_planned_duration=0;
	a_project_date_set_mask=0;
	a_project_date_actual_begin=0;
	a_project_date_actual_end=0;
	a_project_date_actual_end2=0;
	a_project_labor_useness=0;
	a_project_labor_useness_actual=0;
	a_project_labor_useness_actual_date=0;
	a_project_labor_of_item=0;
	a_project_persentage=0;
	a_project_state=0;
	a_project_parent=0;
	a_project_content=0;
	a_project_type=0;
	a_project_prototype=0;
	a_project_prd_amount_planned=0;
	a_project_prd_amount_actual=0;
	a_project_prd_amount_unit=0;
	a_project_calc_by_amount=0;
	a_project_control_type=0;
	a_project_number=0;
	a_project_taken_measures =0;
	a_project_payment_condition = 0;
	a_project_note1 =0;
	a_project_note2	=0;
	a_project_note3 =0;

	a_project_transactions = NULL;
	
	e_labor_useness_value=0;
	a_labor_value=0;
	a_labor_unit=0;

	e_project_type=0;
	a_project_type_name=0;

	a_project_act_adm_version=0;
	a_project_locker_adm_version=0;
	a_project_act_cont_version=0;
	a_project_locker_cont_version=0;

	e_project_adm_ver=0;
	a_project_adm_ver_id=0;
	a_project_adm_ver_name=0;
	a_project_adm_ver_number=0;
	a_project_adm_ver_descr=0;
	a_project_adm_ver_kurator=0;
	a_project_adm_ver_executors=0;
	a_project_adm_ver_co_executors=0;
	a_project_adm_ver_co_customers=0;
	a_project_adm_ver_prev_sequences=0;
	a_project_adm_ver_date_planned_begin=0;
	a_project_adm_ver_date_planned_end=0;
	a_project_adm_ver_date_planned_end2=0;
	a_project_adm_ver_date_planned_duration=0;
	a_project_adm_ver_date_set_mask=0;
	a_project_adm_ver_project=0;
	a_project_adm_ver_num=0;
	a_project_adm_ver_author=0;
	a_project_adm_ver_start=0;
	a_project_adm_ver_end=0;
	a_project_adm_ver_content=0;
	a_project_adm_ver_parent=0;
	a_project_adm_ver_basis=0;
	a_project_adm_ver_type=0;
	a_project_adm_ver_customer=0;
	a_project_adm_ver_labor_useness=0;
	a_project_adm_ver_labor_of_item=0;
	a_project_adm_ver_persentage=0;
	a_project_adm_ver_prd_amount_planned=0;
	a_project_adm_ver_calc_by_amount=0;
	a_project_adm_ver_prd_amount_unit=0;
	a_project_adm_ver_prd_amount_unit=0;
	a_project_adm_ver_control_type=0;

	e_project_cont_ver=0;
	a_project_cont_ver_project=0;
	a_project_cont_ver_num=0;
	a_project_cont_ver_act_content=0;



	e_project_ref=0;
	a_project_ref_item=0;
	a_project_ref_project=0;
	a_project_ref_id=0;
	a_project_ref_name=0;
	a_project_ref_control_status=0;

	e_project_seg=0;
	a_project_seq_prev=0;
	a_project_seq_next=0;
	a_project_seq_type=0;
	a_project_seq_offset=0;

	m_show_ass_projects=0;

	e_money_transaction = NULL;
	a_money_transaction_id = NULL;
	a_money_transaction_name = NULL;
	a_money_transaction_descr = NULL;
	a_money_transaction_type = NULL;
	a_money_transaction_date = NULL;
	a_money_transaction_summ = NULL;
	a_money_transaction_account=0;
	a_money_transaction_nds=0;
}

bool CaplPreProjectManager::LoadDictionary()
{
	m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Проекты\\Показывать ассоциированные проекты"),m_show_ass_projects,1);
	if(m_data->IsConnected())
	{
		CaplLoadData ld(m_data,DEF_SOURCE);
		int j=ld.AddQuery(_T('e'),0,e_project_type,0,true,true);
			  //ld.AddQuery(_T('d'),j,0,a_project_type_name,true);
		return ld.LoadEx();
	}
	return true;
}

//*******************************************************************************
bool CaplPreProjectManager::LoadProjectInfo(CaplInstance *project, bool bLoadPrevRelations)
{
	if(project==0) return false;
	if(project==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if(project->GetAccessmode()>aplRO) return false;
	
	aplExtent ext;
	ext.Add(project);
	return LoadProjectInfo(ext,bLoadPrevRelations);
}

bool CaplPreProjectManager::LoadProjectInfo(aplExtent &ext, bool bLoadPrevRelations)
{
	CaplLoadData ld_projects(m_data,DEF_SOURCE);
	CaplLoadData ld_project_vers(m_data,DEF_SOURCE);
	int iLoadProjects=0;
	int iLoadProjectVers=0;
	int a,b, i;

	aplExtent ext_prj4Rel; ext_prj4Rel.Unique=false;

	for(i=0;i<ext.GetSize();i++)
	{
		CaplInstance *inst=ext[i];
		if(!inst) continue;
		if(inst->GetAccessmode()>aplRO) continue; 
		if(inst->GetId()==0) continue;
		if(m_data->IsKindOf(inst,e_project)) {
			iLoadProjects++;
			ld_projects.AddQuery(0,inst,true);
			if(bLoadPrevRelations) ext_prj4Rel.Add(inst);
		}
		if(m_data->IsKindOf(inst,e_project_adm_ver)) {
			iLoadProjectVers++;
			ld_project_vers.AddQuery(0,inst,true);
			if(bLoadPrevRelations)
			{
				CaplInstance *inst1;
				m_data->GetAttr(inst,a_project_adm_ver_project,inst1);
				if(inst1!=0) ext_prj4Rel.Add(inst);
			}
		}
		if(iLoadProjects==m_MaxItemsLoad || (i==(ext.Size-1) && iLoadProjects>0))
		{
			iLoadProjects=0;
			ld_projects.AddQuery(_T('d'), 0, 0,a_project_labor_useness, true,true);
			ld_projects.AddQuery(_T('d'), 0, 0,a_project_labor_useness_actual, true,true);
			ld_projects.AddQuery(_T('d'), 0, 0,a_project_labor_of_item, true,true);
			ld_projects.AddQuery(_T('d'), 0, 0,a_project_transactions, true,true);
			a=ld_projects.AddQuery(_T('d'), 0, 0,a_project_parent, true);
					ld_projects.AddQuery(_T('d'), a, 0,a_project_content, true);
			ld_projects.AddQuery(_T('d'), 0, 0,a_project_type, true,true);
			a=ld_projects.AddQuery(_T('d'), 0, 0,a_project_content, true,true);
					//Подпроцессы
				  ld_projects.AddQuery(_T('d'), a, 0,a_project_labor_useness, true,true);
				  ld_projects.AddQuery(_T('d'), a, 0,a_project_labor_useness_actual, true,true);
				  ld_projects.AddQuery(_T('d'), a, 0,a_project_labor_of_item, true,true);
				  ld_projects.AddQuery(_T('d'), a, 0,a_project_type, true,true);
				  b=ld_projects.AddQuery(_T('d'), a, 0,a_project_parent, true);
						ld_projects.AddQuery(_T('d'), b, 0,a_project_content, true);

			ld_projects.LoadEx();
		}
		if(iLoadProjectVers==m_MaxItemsLoad || (i==(ext.Size-1) && iLoadProjectVers>0))
		{
			iLoadProjectVers=0;
			ld_project_vers.AddQuery(_T('d'), 0, 0,a_project_adm_ver_labor_useness, true,true);
			ld_project_vers.AddQuery(_T('d'), 0, 0,a_project_adm_ver_labor_of_item, true,true);
			ld_project_vers.AddQuery(_T('d'), 0, 0,a_project_adm_ver_type, true,true);
			ld_project_vers.AddQuery(_T('d'), 0, 0,a_project_adm_ver_author, true,true);
			a=ld_project_vers.AddQuery(_T('d'), 0, 0,a_project_adm_ver_content, true,true);
					//Подпроцессы
				  ld_project_vers.AddQuery(_T('d'), a, 0,a_project_labor_useness, true,true);
				  ld_project_vers.AddQuery(_T('d'), a, 0,a_project_labor_useness_actual, true,true);
				  ld_project_vers.AddQuery(_T('d'), a, 0,a_project_labor_of_item, true,true);
				  ld_project_vers.AddQuery(_T('d'), a, 0,a_project_type, true,true);
				  b=ld_project_vers.AddQuery(_T('d'), a, 0,a_project_parent, true);
						ld_project_vers.AddQuery(_T('d'), b, 0,a_project_content, true);

			ld_project_vers.LoadEx();
		}
	}

	if(bLoadPrevRelations && ext_prj4Rel.GetSize()>0)
	{
		CaplLoadData ld_rels(m_data,DEF_SOURCE);
		for(i=0;i<ext_prj4Rel.GetSize();i++) ld_rels.AddQuery(0,ext_prj4Rel[i],true);
		int i = ld_rels.AddQuery(_T('r'),0,e_project_seg,a_project_seq_prev,true,true);
		ld_rels.AddQuery(_T('d'), i, 0, a_project_seq_next , true,true);
		ld_rels.LoadEx();
	}

	aplExtent ext0;
	CaplInstance *act=0,*lock=0,*base=0;
	for(i=0;i<ext.GetSize();i++)
	{
		if(!ext[i]) continue;if(ext[i]->GetAccessmode()>aplRO) continue;
		if(m_data->IsKindOf(ext[i],e_project)) 
		{
			m_data->GetAttr(ext[i],a_project_act_adm_version,act);
			m_data->GetAttr(ext[i],a_project_locker_adm_version,lock);
			if(act){ext0.Add(act);}
			if(lock){ext0.Add(lock);}
		}
	}
	if(ext0.GetSize()) LoadProjectInfo(ext0);
	return true;

}

//*************************************************************************
//******   Ассоциации проекта с объектами  ********************************
//*************************************************************************


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

	aplExtent ext;
	ext.Add(project);
	return LoadProjectReferenceInfo(ext);
}

//*******************************************************************************
bool CaplPreProjectManager::LoadProjectReferenceInfo(aplExtent &ext)
{
	CaplLoadData ld(m_data,DEF_SOURCE);
	int iLoad=0;
	for(int i=0;i<ext.GetSize();i++)
	{
		if(!ext[i]) continue;if(ext[i]->GetAccessmode()>aplRO) continue;if(ext[i]->GetId()==0) continue;
		if(m_data->IsKindOf(ext[i],e_project_ref)) 
		{
			iLoad++;
			ld.AddQuery(0,ext[i],true);
		}
		if(iLoad==m_MaxItemsLoad || (i==(ext.Size-1) && iLoad>0))
		{
			iLoad=0;
			if(!ld.LoadEx()){
				if(apidata.GetLastAplError()!=APL_SOCK_OPERATION_IN_PROGRESS){
					if(m_api->m_ModeInteractive)AfxMessageBox(S::ErrorLoadDataMgr(),MB_OK|MB_ICONSTOP);
				}
			}
		}
	}
	return true;
	
}



CaplInstance *CaplPreProjectManager::CreateAssociation(CaplInstance *project,CaplInstance *item,const TCHAR *id,const TCHAR *name,CaplInstance *control_status)
{
	if(!project) return 0;
	if(!item) return 0;
	if(project->GetAccessmode()>aplRW)
	{
		AfxMessageBox(CaplTranslate::Translate(S::NoAccessRightItem_rus),MB_OK|MB_ICONSTOP);
		return 0;
	}
	if(item->GetAccessmode()>aplRW)
	{
		AfxMessageBox(CaplTranslate::Translate(S::NoAccessRightItem_rus),MB_OK|MB_ICONSTOP);
		return 0;
	}

	CaplInstance *rel=FindAssociation(project,item);
	if(rel!=0) 
	{
		if(m_api->m_ModeInteractive)
			AfxMessageBox(APL_T("Такая связь уже существует!"));
		return 0;
	}

	rel=m_data->CreateInstance(e_project_ref);
	m_data->PutAttr(rel,a_project_ref_project,project);
	m_data->PutAttr(rel,a_project_ref_item,item);
	if(id) m_data->PutAttr(rel,a_project_ref_id,id);
	if(name) m_data->PutAttr(rel,a_project_ref_name,name);
	if(control_status) m_data->PutAttr(rel,a_project_ref_control_status,control_status);

	if(m_AutoSave) 
	{
		m_data->NET_SaveChanges();
	}
	return rel;
}


bool CaplPreProjectManager::DeleteAssociation(CaplInstance *project,CaplInstance *item)
{
	if(!project) return false;
	if(!item) return false;
	if(project->GetAccessmode()>aplOWN)
	{
		AfxMessageBox(CaplTranslate::Translate(S::NoAccessRightItem_rus),MB_OK|MB_ICONSTOP);
		return false;
	}
	if(item->GetAccessmode()>aplOWN)
	{
		AfxMessageBox(CaplTranslate::Translate(S::NoAccessRightItem_rus),MB_OK|MB_ICONSTOP);
		return false;
	}

	CaplInstance *rel=FindAssociation(project,item);
	if(!rel) return false;

	m_data->DeleteInstance(rel);

	if(m_AutoSave) 
	{
		m_data->NET_SaveChanges();
	}
	return true;
}

//*************************************************************
CaplInstance *CaplPreProjectManager::FindAssociation(CaplInstance *project,CaplInstance *item)
{
	if(item==0) return 0;
	if(item->GetType()==0) return 0;
	if(project==0) return 0;
	if(project->GetType()==0) return 0;

	aplExtent ext;
	CaplAttrValue tst_values[2];
	
	tst_values[0].value.Set(item);
	tst_values[0].attr=a_project_ref_item;

	tst_values[1].value.Set(project);
	tst_values[1].attr=a_project_ref_project;

	m_data->NET_FindInstancesWithAttrValues(e_project_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())
	{
		LoadProjectReferenceInfo(rel);
	}
	return rel;
}

//*************************************************************
bool CaplPreProjectManager::FindAssociatedProjects(CaplInstance *item, aplExtent &out_ext, aplExtent &out_rel) 
{
	out_ext.Clear();
	out_rel.Clear();
	if(item==0) return false;
	if(item->GetType()==0) return false;
	if(item->GetAccessmode()>aplRO) return false;

	int i;
	aplExtent ext;
	CaplAttrValue tst_values[1];

	if(m_data->IsKindOf(item, m_api->m_doc_mgr.e_doc))
	{
		m_api->m_doc_mgr.FindAssociatingDocuments(item,out_ext,out_rel);
	}
	else
	{
		tst_values[0].value.Set(item);
		tst_values[0].attr=a_project_ref_item;

		m_data->NET_FindInstancesWithAttrValues(e_project_ref,1,&tst_values[0],ext,true);
		if(ext.GetSize()) LoadProjectReferenceInfo(ext);

		CaplInstance *project;
		for(i=0;i<ext.GetSize();i++)
		{
			m_data->GetAttr(ext[i],a_project_ref_project,project);
			if(project)
			{
				if(project->GetType()!=0)
				{
					if(project->GetAccessmode()<=aplRO)
					{
						out_rel.Add(ext[i]);
						out_ext.Add(project);
					}
				}
			}
		}
	}

	if(out_ext.GetSize()) LoadProjectInfo(out_ext);

	return true;
}




//*************************************************************************
//******   Версии проектов       ******************************************
//*************************************************************************


CaplInstance *CaplPreProjectManager::GetLock(CaplInstance *project, bool bShowMessages)
{
	if(project==0) return 0;
	if(project==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return 0;};
	if(project->GetAccessmode()>aplRO) return 0;
	if(!m_data->IsKindOf(project,e_project)) 
		if(!m_data->IsKindOf(project,e_project_adm_ver))
			return 0;

	CaplInstance *lock=0,*user=0;
	if(m_data->IsKindOf(project,e_project))
	{
		m_data->GetAttr(project,a_project_locker_adm_version,lock);
	}
	else if(m_data->IsKindOf(project,e_project_adm_ver))
	{
		CaplInstance *project_ver_project=0;
		m_data->GetAttr(project,a_project_adm_ver_project,project_ver_project);
		if(!project_ver_project) return 0;
		m_data->GetAttr(project_ver_project,a_project_locker_adm_version,lock);
	}
	if(lock==0)
		if(m_bShowMessages)
			if(bShowMessages && m_api->m_ModeInteractive)AfxMessageBox( APL_T("Проект не заблокирован!"),MB_OK|MB_ICONSTOP);
		
	return lock;
}
CaplInstance *CaplPreProjectManager::CheckMyLock(CaplInstance *project, bool bShowMessages)
{
	if(project==0) return 0;
	if(project==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return 0;};
	if(project->GetType()==0) return 0;
	if(project->GetAccessmode()>aplRO) return 0;
	if(!m_data->IsKindOf(project,e_project)) 
		if(!m_data->IsKindOf(project,e_project_adm_ver))
			return 0;

	CaplInstance *lock=GetLock(project,bShowMessages);
	if(!lock) return 0;

	CaplInstance *user=0;
	m_data->GetAttr(lock,a_project_adm_ver_author,user);
	if(user!=m_data->GetCurrUser())
	{
		if(m_bShowMessages)
			if(bShowMessages && m_api->m_ModeInteractive)AfxMessageBox( APL_T("Проект заблокирован другим пользователем !"),MB_OK|MB_ICONSTOP);
		return 0;
	}
	return lock;
}

bool CaplPreProjectManager::IsProjectInContentOfParent(CaplInstance *project)
{
	if(project==0) return false;
	if(project==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if(project->GetType()==0)return false;
	if(project->GetAccessmode()>aplRO){if(m_api->m_ModeInteractive)aplErrorMessage(S::NoAccessRight(),project); return false;}
	CaplInstance *parent=0;
	m_data->GetAttr(project,a_project_parent,parent);
	if(parent) 
	{
		CaplAggr aggr;
		CaplInstance *lock=CheckMyLock(parent,false);
		if(lock) m_data->GetAttr(lock,a_project_adm_ver_content,aggr);
		else m_data->GetAttr(parent,a_project_content,aggr);
		CaplInstance *inst=0;
		for(int i=0;i<aggr.GetSize();i++)
		{
			aggr.GetByIndex(i,inst);
			if(inst==project) 
				return true;
		}
	}
	return false;
}

bool CaplPreProjectManager::FindAssociatedItems(CaplInstance *project, aplExtent &out_ext, aplExtent &out_rel) 
{
	out_ext.Clear();
	out_rel.Clear();
	if(project==0) return false;
	if(project==(CaplInstance*)-1) {if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка вызывающей программы! instance равен -1!"));return false;};
	if(project->GetType()==0) return false;
	if(project->GetAccessmode()>aplRO) return false;
	
	int i;
	aplExtent ext;
	CaplAttrValue tst_values[1];
	
	tst_values[0].value.Set(project);
	tst_values[0].attr=a_project_ref_project;
	
	m_data->NET_FindInstancesWithAttrValues(e_project_ref,1,&tst_values[0],ext,true);
	if(ext.GetSize()) LoadProjectReferenceInfo(ext);
	
	CaplInstance *item;
	for(i=0;i<ext.GetSize();i++)
	{
		m_data->GetAttr(ext[i],a_project_ref_item,item);
		if(item)
		{
			if(item->GetType()!=0)
			{
				if(item->GetAccessmode()<=aplRO)
				{
					out_rel.Add(ext[i]);
					out_ext.Add(item);
				}
			}
		}
	}
	if(out_ext.GetSize()) m_api->LoadExtentInfo(out_ext);
	
	return true;
}

CaplInstance *CaplPreProjectManager::GetLatestProjectVersion(CaplInstance *project,CString &num)
{
	if(!project) return 0;
	if(project->GetAccessmode()>aplRO) return 0;

	CaplLoadData ld(m_data,DEF_SOURCE);
	int j=ld.AddQuery(_T('b'), project->GetId(), e_project_adm_ver,a_project_adm_ver_project, true);
	ld.AddQuery(_T('d'), j, 0,a_project_adm_ver_project, true);
	ld.AddQuery(_T('d'), j, 0,a_project_adm_ver_num, true);
	ld.LoadEx();

	CaplInstance *latest_ver=0,*inst=0;
	int max_id=-1;
	aplExtent ext_rev;
	CString buf;
	num=_T("-1");
	m_data->GetEntityExtent(e_project_adm_ver,ext_rev);
	for(int i=0;i<ext_rev.Size;i++)
	{
		if(!ext_rev[i]) continue;
		if(!ext_rev[i]->GetId()) continue;
		if(ext_rev[i]->GetAccessmode()>aplRO) continue;
		m_data->GetAttr(ext_rev[i],a_project_adm_ver_project,inst);
		if(inst==project)
		{
			m_data->GetAttr(ext_rev[i],a_project_adm_ver_num,buf);
			j=_atoi(buf);
			if(j>max_id)
			{
				latest_ver=ext_rev[i];
				max_id=j;
				num.Format(_T("%i"),max_id);
			}
		}
	}
	return latest_ver;
}

bool CaplPreProjectManager::MakeProjectVersionActive(CaplInstance *project_ver)
{
	if(!project_ver) return false;
	if(project_ver->GetAccessmode()>aplRO) {AfxMessageBox(S::NoAccessRight(),MB_OK|MB_ICONSTOP); return false;}
	if(!m_data->IsKindOf(project_ver,e_project_adm_ver))
		return false;

	CaplInstance *project_ver_project=0;
	m_data->GetAttr(project_ver,a_project_adm_ver_project,project_ver_project);	
	if(!project_ver_project) return false;
	if(project_ver_project->GetAccessmode()>aplRW) {AfxMessageBox(S::NoAccessRight(),MB_OK|MB_ICONSTOP); return false;}
	CaplInstance *lock=GetLock(project_ver_project,false);
	if(lock) 
	{
		CaplInstance *my_lock=CheckMyLock(project_ver_project,true);
		if(!my_lock) return false;
	}

	CaplInstance *act=0;
	m_data->GetAttr(project_ver_project,a_project_act_adm_version,act);	
	if(act==project_ver)
	{
		AfxMessageBox( APL_T("Версия уже активна!"));
		return false;
	}

	CString id=_T(""),name=_T(""),number=_T(""),descr=_T(""),date_time=_T(""),date_planned_begin=_T(""),date_planned_end=_T(""),date_planned_end2=_T("");
	CaplInstance *kurator=0,*labor=0,*labor_of_item=0,*customer=0,*type=0, *prd_amount_unit=0;
	CaplAggr aggr_content,aggr_executors,aggr_co_executors,aggr_co_customers,aggr_prev_sequences;	
	double prd_amount,persentage,planned_duration;
	bool calc_by_amount;
	int date_set_mask;
	CString control_type;

	m_data->GetAttr(project_ver,a_project_adm_ver_id,id);	
	m_data->GetAttr(project_ver,a_project_adm_ver_name,name);
	m_data->GetAttr(project_ver,a_project_adm_ver_number,number);
	m_data->GetAttr(project_ver,a_project_adm_ver_descr,descr);
	m_data->GetAttr(project_ver,a_project_adm_ver_type,type);
	m_data->GetAttr(project_ver,a_project_adm_ver_customer,customer);
	m_data->GetAttr(project_ver,a_project_adm_ver_labor_useness,labor);
	m_data->GetAttr(project_ver,a_project_adm_ver_labor_of_item,labor_of_item);
	m_data->GetAttr(project_ver,a_project_adm_ver_kurator,kurator);
	m_data->GetAttr(project_ver,a_project_adm_ver_executors,aggr_executors);
	m_data->GetAttr(project_ver,a_project_adm_ver_co_executors,aggr_co_executors);
	m_data->GetAttr(project_ver,a_project_adm_ver_co_customers,aggr_co_customers);
	m_data->GetAttr(project_ver,a_project_adm_ver_prev_sequences,aggr_prev_sequences);
	m_data->GetAttr(project_ver,a_project_adm_ver_control_type,control_type);
	m_data->GetAttr(project_ver,a_project_adm_ver_date_planned_begin,date_planned_begin);
	m_data->GetAttr(project_ver,a_project_adm_ver_date_planned_end,date_planned_end);
	m_data->GetAttr(project_ver,a_project_adm_ver_date_planned_end2,date_planned_end2);
	m_data->GetAttr(project_ver,a_project_adm_ver_date_planned_duration,planned_duration);
	m_data->GetAttr(project_ver,a_project_adm_ver_date_set_mask,date_set_mask);

	m_data->GetAttr(project_ver,a_project_adm_ver_content,aggr_content);
	m_data->GetAttr(project_ver,a_project_adm_ver_prd_amount_planned,prd_amount);
	m_data->GetAttr(project_ver,a_project_adm_ver_prd_amount_unit,prd_amount_unit);
	m_data->GetAttr(project_ver,a_project_adm_ver_calc_by_amount,calc_by_amount);
	m_data->GetAttr(project_ver,a_project_adm_ver_persentage,persentage);

	m_data->PutAttr(project_ver_project,a_project_id,id);	
	m_data->PutAttr(project_ver_project,a_project_name,name);
	m_data->PutAttr(project_ver_project,a_project_number,number);
	m_data->PutAttr(project_ver_project,a_project_descr,descr);
	m_data->PutAttr(project_ver_project,a_project_type,type);
	m_data->PutAttr(project_ver_project,a_project_customer,customer);
	m_data->PutAttr(project_ver_project,a_project_labor_useness,labor);
	m_data->PutAttr(project_ver_project,a_project_labor_of_item,labor_of_item);
	m_data->PutAttr(project_ver_project,a_project_kurator,kurator);
	m_data->PutAttr(project_ver_project,a_project_executors,aggr_executors);
	m_data->PutAttr(project_ver_project,a_project_co_executors,aggr_co_executors);
	m_data->PutAttr(project_ver_project,a_project_co_customers,aggr_co_customers);
	m_data->PutAttr(project_ver_project,a_project_prev_sequences,aggr_prev_sequences);
	m_data->PutAttr(project_ver_project,a_project_control_type,control_type);
	m_data->PutAttr(project_ver_project,a_project_date_planned_begin,date_planned_begin);
	m_data->PutAttr(project_ver_project,a_project_date_planned_end,date_planned_end);
	m_data->PutAttr(project_ver_project,a_project_date_planned_end2,date_planned_end2);
	m_data->PutAttr(project_ver_project,a_project_date_planned_duration,planned_duration);
	m_data->PutAttr(project_ver_project,a_project_date_set_mask,date_set_mask);
	m_data->PutAttr(project_ver_project,a_project_content,aggr_content);
	m_data->PutAttr(project_ver_project,a_project_act_adm_version,project_ver);
	m_data->PutAttr(project_ver_project,a_project_prd_amount_planned,prd_amount);
	m_data->PutAttr(project_ver_project,a_project_prd_amount_unit,prd_amount_unit);
	m_data->PutAttr(project_ver_project,a_project_calc_by_amount,calc_by_amount);
	m_data->PutAttr(project_ver_project,a_project_persentage,persentage);

	return true;
}

CaplInstance *CaplPreProjectManager::CreateProjectVersion(CaplInstance *project,CString num,bool make_active)
{
	if(!project) return 0;
	if(project->GetAccessmode()>aplRO) return 0;
	if(!m_data->IsKindOf(project,e_project))
		if(!m_data->IsKindOf(project,e_project_adm_ver))
			return 0;

	CString id=_T(""),name=_T(""),descr=_T(""),date_time=_T(""),date_planned_begin=_T(""),date_planned_end=_T(""),date_planned_end2=_T(""),number=_T("");
	CaplInstance *project_ver_project=0,*project_ver_base=0,*act_ver=0,*kurator=0,*customer=0,*type=0,*labor=0,*unit=0;
	CaplInstance *labor_of_item=0,*unit_of_item=0, *prd_amount_unit=0;
	double value,value_of_item,prd_amount,persentage,planned_duration;
	CaplAggr aggr_content,aggr_executors,aggr_co_executors,aggr_co_customers,aggr_prev_sequences;
	bool calc_by_amount;
	int date_set_mask=0;
	CString control_type;

	CaplInstance *ver=m_data->CreateInstance(e_project_adm_ver);
	if(m_data->IsKindOf(project,e_project))
	{
		m_data->GetAttr(project,a_project_id,id);	
		m_data->GetAttr(project,a_project_name,name);
		m_data->GetAttr(project,a_project_descr,descr);
		m_data->GetAttr(project,a_project_type,type);
		m_data->GetAttr(project,a_project_number,number);
		m_data->GetAttr(project,a_project_customer,customer);
		m_data->GetAttr(project,a_project_labor_useness,labor);
		if(labor)
		{
			m_data->GetAttr(labor,a_labor_unit,unit);
			m_data->GetAttr(labor,a_labor_value,value);
		}
		m_data->GetAttr(project,a_project_labor_of_item,labor_of_item);
		if(labor_of_item)
		{
			m_data->GetAttr(labor_of_item,a_labor_unit,unit_of_item);
			m_data->GetAttr(labor_of_item,a_labor_value,value_of_item);
		}
		m_data->GetAttr(project,a_project_kurator,kurator);
		m_data->GetAttr(project,a_project_executors,aggr_executors);
		m_data->GetAttr(project,a_project_co_executors,aggr_co_executors);
		m_data->GetAttr(project,a_project_co_customers,aggr_co_customers);
		m_data->GetAttr(project,a_project_prev_sequences,aggr_prev_sequences);
		m_data->GetAttr(project,a_project_date_planned_begin,date_planned_begin);
		m_data->GetAttr(project,a_project_date_planned_end,date_planned_end);
		m_data->GetAttr(project,a_project_date_planned_end2,date_planned_end2);
		m_data->GetAttr(project,a_project_date_planned_duration,planned_duration);
		m_data->GetAttr(project,a_project_date_set_mask,date_set_mask);
		m_data->GetAttr(project,a_project_control_type,control_type);

		m_data->GetAttr(project,a_project_content,aggr_content);
		m_data->GetAttr(project,a_project_prd_amount_planned,prd_amount);
		m_data->GetAttr(project,a_project_prd_amount_unit,prd_amount_unit);
		m_data->GetAttr(project,a_project_calc_by_amount,calc_by_amount);
		m_data->GetAttr(project,a_project_persentage,persentage);
		project_ver_project=project;
	}
	else
	{
		m_data->GetAttr(project,a_project_adm_ver_id,id);	
		m_data->GetAttr(project,a_project_adm_ver_name,name);
		m_data->GetAttr(project,a_project_adm_ver_descr,descr);
		m_data->GetAttr(project,a_project_adm_ver_type,type);
		m_data->GetAttr(project,a_project_adm_ver_number,number);
		m_data->GetAttr(project,a_project_adm_ver_customer,customer);
		m_data->GetAttr(project,a_project_adm_ver_labor_useness,labor);
		if(labor)
		{
			m_data->GetAttr(labor,a_labor_unit,unit);
			m_data->GetAttr(labor,a_labor_value,value);
		}
		m_data->GetAttr(project,a_project_adm_ver_labor_of_item,labor_of_item);
		if(labor_of_item)
		{
			m_data->GetAttr(labor_of_item,a_labor_unit,unit_of_item);
			m_data->GetAttr(labor_of_item,a_labor_value,value_of_item);
		}
		m_data->GetAttr(project,a_project_adm_ver_kurator,kurator);
		m_data->GetAttr(project,a_project_adm_ver_executors,aggr_executors);
		m_data->GetAttr(project,a_project_adm_ver_co_executors,aggr_co_executors);
		m_data->GetAttr(project,a_project_adm_ver_co_customers,aggr_co_customers);
		m_data->GetAttr(project,a_project_adm_ver_prev_sequences,aggr_prev_sequences);
		m_data->GetAttr(project,a_project_adm_ver_control_type,control_type);
		m_data->GetAttr(project,a_project_adm_ver_date_planned_begin,date_planned_begin);
		m_data->GetAttr(project,a_project_adm_ver_date_planned_end,date_planned_end);
		m_data->GetAttr(project,a_project_adm_ver_date_planned_end2,date_planned_end2);
		m_data->GetAttr(project,a_project_adm_ver_date_planned_duration,planned_duration);
		m_data->GetAttr(project,a_project_adm_ver_date_set_mask,date_set_mask);
		m_data->GetAttr(project,a_project_adm_ver_content,aggr_content);
		m_data->GetAttr(project,a_project_adm_ver_project,project_ver_project);
		m_data->GetAttr(project,a_project_adm_ver_prd_amount_planned,prd_amount);
		m_data->GetAttr(project,a_project_adm_ver_prd_amount_unit,prd_amount_unit);
		m_data->GetAttr(project,a_project_adm_ver_calc_by_amount,calc_by_amount);
		m_data->GetAttr(project,a_project_adm_ver_persentage,persentage);
		project_ver_base=project;
	}

	m_data->PutAttr(ver,a_project_adm_ver_id,id);	
	m_data->PutAttr(ver,a_project_adm_ver_name,name);
	m_data->PutAttr(ver,a_project_adm_ver_descr,descr);
	m_data->PutAttr(ver,a_project_adm_ver_type,type);
	m_data->PutAttr(ver,a_project_adm_ver_customer,customer);
	m_data->PutAttr(ver,a_project_adm_ver_number,number);

	if(labor)
	{
		CaplInstance *new_labor=m_data->CreateInstance(e_labor_useness_value);
		if(new_labor)
		{
			m_data->PutAttr(ver,a_project_adm_ver_labor_useness,new_labor);
			if(unit) m_data->PutAttr(new_labor,a_labor_unit,unit);
			m_data->PutAttr(new_labor,a_labor_value,value);
		}
	}
	if(labor_of_item)
	{
		CaplInstance *new_labor=m_data->CreateInstance(e_labor_useness_value);
		if(new_labor)
		{
			m_data->PutAttr(ver,a_project_adm_ver_labor_of_item,new_labor);
			if(unit) m_data->PutAttr(new_labor,a_labor_unit,unit_of_item);
			m_data->PutAttr(new_labor,a_labor_value,value_of_item);
		}
	}

	m_data->PutAttr(ver,a_project_adm_ver_kurator,kurator);
	m_data->PutAttr(ver,a_project_adm_ver_executors,aggr_executors);
	m_data->PutAttr(ver,a_project_adm_ver_co_executors,aggr_co_executors);
	m_data->PutAttr(ver,a_project_adm_ver_co_customers,aggr_co_customers);
	m_data->PutAttr(ver,a_project_adm_ver_prev_sequences,aggr_prev_sequences);
	m_data->PutAttr(ver,a_project_adm_ver_control_type,control_type);
	m_data->PutAttr(ver,a_project_adm_ver_date_planned_begin,date_planned_begin);
	m_data->PutAttr(ver,a_project_adm_ver_date_planned_end,date_planned_end);
	m_data->PutAttr(ver,a_project_adm_ver_date_planned_end2,date_planned_end2);
	m_data->PutAttr(ver,a_project_adm_ver_date_planned_duration,planned_duration);
	m_data->PutAttr(ver,a_project_adm_ver_date_set_mask,date_set_mask);
	m_data->PutAttr(ver,a_project_adm_ver_content,aggr_content);
	m_data->PutAttr(ver,a_project_adm_ver_project,project_ver_project);
	m_data->PutAttr(ver,a_project_adm_ver_parent,project_ver_base);
	m_data->PutAttr(ver,a_project_adm_ver_author,m_data->GetCurrUser());
	m_data->PutAttr(ver,a_project_adm_ver_prd_amount_planned,prd_amount);
	m_data->PutAttr(ver,a_project_adm_ver_prd_amount_unit,prd_amount_unit);
	m_data->PutAttr(ver,a_project_adm_ver_calc_by_amount,calc_by_amount);
	m_data->PutAttr(ver,a_project_adm_ver_persentage,persentage);

	COleDateTime dt=COleDateTime::GetCurrentTime();
	aplDate2String(dt,date_time);
	m_data->PutAttr(ver,a_project_adm_ver_start,date_time);
	if(make_active)
	{
		m_data->PutAttr(ver,a_project_adm_ver_end,date_time);
		if(num==_T("-1")) 
		{
			GetLatestProjectVersion(project_ver_project,num);
			int max_id=_atoi(num);
			max_id++;
			num.Format(_T("%i"),max_id);
		}
		m_data->PutAttr(ver,a_project_adm_ver_num,num);
		if(project_ver_project)
			if(project_ver_project->GetAccessmode()<aplRO)
				m_data->PutAttr(project_ver_project,a_project_act_adm_version,ver);
	}

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


//************************************************
bool CaplCategoryManager::RefreshRootCategories()
{
	if(!m_data->IsConnected()) return false;

	aplExtent sub_categs, cont, ext;

	CaplAttrValue find_value[2];
	find_value[0].attr= a_categ_content_id;
	find_value[0].value.Set(_T("Categories"));
	
	m_data->NET_FindInstancesWithAttrValues(e_categ_content, 1, &find_value[0], cont, false);
	
	CaplInstance* rootObj= NULL;

	if(cont.GetSize()>0)
	{
		rootObj= cont[0];
		
		CaplLoadData ld(m_data,DEF_SOURCE);
		ld.AddQuery(-1,cont[0]);
		ld.AddQuery(_T('d'), 0, 0, a_categ_content_id, true);
		ld.AddQuery(_T('d'), 0, 0, a_categ_content_content, true);
		if(!ld.LoadEx())
		{
			if(apidata.GetLastAplError()!=APL_SOCK_OPERATION_IN_PROGRESS && m_api->m_ModeInteractive)
				AfxMessageBox( APL_T("Ошибка чтения информации"),MB_OK|MB_ICONSTOP);
		}
	}

	if(!rootObj)
	{
		rootObj= m_api->m_data.CreateInstance(e_categ_content);
		if(rootObj)	m_api->m_data.PutAttr(rootObj, a_categ_content_id, _T("Categories"));
	}
	
	if(!m_data->NET_QueryEditParse(
			CString(_T("SELECT Ext_2 FROM ")
			_T("Ext_1{product_category_relationship}.sub_category->product_category ")
			_T("Ext_2{product_category.# NOT_IN #Ext_1} ")
			_T("END_SELECT"))))
	{if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка разбора запроса")); return false;}
	if(!m_data->NET_QueryExecute(ext))
		{if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Ошибка выполнения запроса")); return false;}
	
	m_api->m_data.PutAttr(rootObj, a_categ_content_content, ext);
	if(m_AutoSave) m_api->m_data.NET_SaveChanges();

	return true;
}

void UpdataImageList(CImageList &il,int offset, UINT bmp, int width,
					 COLORREF mask,UINT fullcolorbmp=0)
{
	ASSERT(width!=0);
	if(width==0) return;

	int i;
	if(fullcolorbmp==0)
	{
		CImageList tmp_il;
		tmp_il.Create(bmp,width,100,mask);
		for(i=0;i<tmp_il.GetImageCount();i++)
			InstImageList.Replace(i+offset,tmp_il.ExtractIcon(i));
		tmp_il.DeleteImageList();
	}
	else
	{
		CBitmap bm;
		if(!bm.LoadBitmap(fullcolorbmp)) return;

		CImageList tmp_il_fc;
		tmp_il_fc.Create(width, 16, ILC_COLOR24|ILC_MASK, 0, 100);
		tmp_il_fc.Add(&bm, RGB(255,255,255));
		bm.DeleteObject();

		for(i=0;i<tmp_il_fc.GetImageCount();i++)
			InstImageList.Replace(i+offset,tmp_il_fc.ExtractIcon(i));
		tmp_il_fc.DeleteImageList();
	}
}

void InitImageLists()
{
	if(!InstImageList.m_hImageList)
	{
		bool bUseTrueColor=false;
		UINT colorflag=ILC_COLOR4;

		int fc_ico_folder=0;
		int fc_ico_mail=0;

		if(aplGetBitPerPixel(0)>8)
		{
			colorflag=ILC_COLOR24|ILC_MASK;
		    fc_ico_folder=IDB_ITEM_ICON_FOLDER;
			fc_ico_mail=IDB_ITEM_ICON_MAIL;
		}

		InstImageList.Create(20, 16, colorflag, 500, 100);
		COLORREF bkcolor=::GetSysColor(COLOR_WINDOW);
		if(CaplDefWindowParam::m_win_bk_color!=RGB(0,0,0)) bkcolor=CaplDefWindowParam::m_win_bk_color;
		InstImageList.SetBkColor(bkcolor);
		InstImageList.SetImageCount(500);

		UpdataImageList(InstImageList,ICON_NULL, IDR_ITEM_ICON_FOLDER, 20, RGB(255,0,255), fc_ico_folder);
		UpdataImageList(InstImageList,ICON_APPR_INDEX, IDR_ITEM_ICON_APPR, 20, RGB(255,0,255), IDB_ITEM_ICON_APPR);

		UpdataImageList(InstImageList,ICON_MSG_INDEX, IDR_ITEM_ICON_MAIL, 20, RGB(255,0,255), fc_ico_mail);
		
		UpdataImageList(InstImageList,ICON_DOC_INDEX,IDR_ITEM_ICON_DOC, 20, RGB(255,0,255), IDB_ITEM_ICON_DOC);
		UpdataImageList(InstImageList,ICON_CHARACT_INDEX,IDR_ITEM_ICON_CHARACT, 20, RGB(255,0,255), IDB_ITEM_ICON_CHARACT);
		UpdataImageList(InstImageList,ICON_INST_INDEX,IDR_ITEM_ICON_INST, 20, RGB(255,0,255));
		UpdataImageList(InstImageList,ICON_ORGSTRUCT_INDEX,IDR_ITEM_ICON_ORGSTRUCT, 20, RGB(255,0,255), IDB_ITEM_ICON_ORGSTRUCT);
		UpdataImageList(InstImageList,ICON_ALERT_INDEX,IDR_ITEM_ICON_ALERT, 20, RGB(255,0,255));
		
		UpdataImageList(InstImageList,ICON_PRODUCT_INDEX,  IDR_NAVIGATOR_PRD_ICON, 20, RGB(255,0,255));

		UpdataImageList(InstImageList, ICON_WF_INDEX, IDR_NAVIGATOR_WF_ICON, 20, RGB(255,0,255));
		UpdataImageList(InstImageList, ICON_PRJ_INDEX, IDR_NAVIGATOR_PRJ_ICON, 20, RGB(255,0,255));
		
		UpdataImageList(InstImageList, ICON_QUERY_INDEX, IDR_ITEM_ICON_QUERY, 20, RGB(255,0,255));
		
		UpdataImageList(InstImageList, ICON_CONFIG_INDEX, IDR_ITEM_ICON_CONFIG, 20, RGB(255,0,255), IDB_ITEM_ICON_CONFIG);

		UpdataImageList(InstImageList, ICON_STATICTREEITEMS_INDEX, IDR_ITEM_ICON_STATICTREEITEMS, 20, RGB(255,0,255), IDB_STATICTREEITEM_ICONS);		
	}

	if(!TabCtrlImageList.m_hImageList)
	{
		CBitmap bm;
		bm.LoadBitmap(IDB_SHOW_CMD_TB);

		TabCtrlImageList.Create(20, 16, ILC_COLOR24|ILC_MASK, 0, 100);
		TabCtrlImageList.Add(&bm, RGB(192,192,192));
		bm.DeleteObject();
	}

	if(!RelImageList.m_hImageList)
		RelImageList.Create(IDR_TB_REL_TYPE, 8, 16, RGB(255,0,255));
	if(!StateImageList.m_hImageList)
		StateImageList.Create(IDR_TB_STATE, 7, 16, RGB(255,0,255));
	if(!EffImageList.m_hImageList)
		EffImageList.Create(IDR_TB_EFF, 6, 16, RGB(255,0,255));
	if(!ObjStateImageList.m_hImageList)
		ObjStateImageList.Create(IDR_TB_OBJ_STATE, 8, 16,RGB(255,0,255));
	if(!ItemSubtypeImageList.m_hImageList)
	{
		//ItemSubtypeImageList.Create(IDB_TB_SUBTYPE, 16, 6, RGB(255,0,255));
		CBitmap bm;
		bm.LoadBitmap(IDB_TB_SUBTYPE);
		ItemSubtypeImageList.Create(12, 16, ILC_COLOR24|ILC_MASK, 0, 15);
		ItemSubtypeImageList.Add(&bm, RGB(192,192,192));
		bm.DeleteObject();
	}
}

void DestroyImageLists()
{
	if(InstImageList.m_hImageList)
		InstImageList.DeleteImageList();
	if(!RelImageList.m_hImageList)
		RelImageList.DeleteImageList();
	if(!StateImageList.m_hImageList)
		StateImageList.DeleteImageList();
	if(!EffImageList.m_hImageList)
		EffImageList.DeleteImageList();
	if(!ObjStateImageList.m_hImageList)
		ObjStateImageList.DeleteImageList();
	if(!ItemSubtypeImageList.m_hImageList)
		ItemSubtypeImageList.DeleteImageList();
	if(TabCtrlImageList.m_hImageList)
		TabCtrlImageList.DeleteImageList();
}

CImageList* aplGetRelImageList()
{
	if(!RelImageList.m_hImageList) return NULL;
	return &RelImageList;
}

CImageList* aplGetEffImageList()
{
	if(!EffImageList.m_hImageList) return NULL;
	return &EffImageList;
}

CImageList* aplGetStateImageList()
{
	if(!StateImageList.m_hImageList) return NULL;
	return &StateImageList;
}

CImageList* aplGetObjStateImageList()
{
	if(!ObjStateImageList.m_hImageList) return NULL;
	return &ObjStateImageList;
}

CImageList* aplGetItemSubtypeImageList()
{
	if(!ItemSubtypeImageList.m_hImageList) return NULL;
	return &ItemSubtypeImageList;
}

CImageList* aplGetTabCtrlImageList()
{
	if(!TabCtrlImageList.m_hImageList) return NULL;
	return &TabCtrlImageList;
}

CImageList* aplGetInstImageList()
{
	if(!InstImageList.m_hImageList) return NULL;
	return &InstImageList;
}

CaplInstance* aplSelectPrdInst(CaplInstance* Pdf_or_PrdInst, CaplAPI* api,
							   CStringArray* FName, CStringArray *FId, CStringArray *FVer, CStringArray *FSN,
							   bool bNFN, bool bNFI, bool bNFV, bool bNFS)
{
	if(api==0) return 0;

	CaplInstance* pdf = 0;
	if(Pdf_or_PrdInst)
	{
		if(api->m_data.IsKindOf(Pdf_or_PrdInst, api->m_prd_mgr.e_pdf))
			pdf = Pdf_or_PrdInst;
		else if(api->m_data.IsKindOf(Pdf_or_PrdInst, api->m_prd_inst_mgr.e_prd_inst))
		{
			api->m_data.GetAttr(Pdf_or_PrdInst, api->m_prd_inst_mgr.a_prd_inst_pdf, pdf);
			if(pdf==0) return 0;
		}
	}

	api->LoadItemInfo(pdf);
	
	CaplSetResourceHandle setres(module_inst);

	CSelectPrdInstDlg dlg;
	dlg.m_api = api;
	dlg.m_pdf = pdf;
	dlg.m_bShowCreate = false;
	if(FName)
		dlg.m_FiltersName.Append(*FName);
	if(FId)
		dlg.m_FiltersName.Append(*FId);
	if(FVer)
		dlg.m_FiltersName.Append(*FVer);
	if(FSN)
		dlg.m_FiltersName.Append(*FSN);
	dlg.m_bNOT_Id = bNFI;
	dlg.m_bNOT_Name = bNFN;
	dlg.m_bNOT_Ver = bNFV;
	dlg.m_bNOT_SN = bNFS;
	if(dlg.DoModal()==IDOK)
	{
		return dlg.m_selected_prd_inst;
	}

	return NULL;
}

CaplInstance* CaplStepManager::FindContextByName(LPCTSTR sName)
{
	if(!m_data) return NULL;
	aplExtent ext;
	m_api->m_data.GetEntityExtent(e_pd_context, ext);
	if(ext.Size==0)
	{
		LoadContextInfo();
		m_api->m_data.GetEntityExtent(e_pd_context, ext);
	}
	CString buf;
	for(int i=0; i<ext.Size; i++)
	{
		m_data->GetAttr(ext[i], a_pd_context_name, buf);
		if(buf.CompareNoCase(sName)==0)
			return ext[i];
	}
	return NULL;
}

void AFX_EXT_API aplShowAboutDlg(CaplAPI *api, const TCHAR* text, const TCHAR* title, HICON logo_icon)
{
	CString sTitle(text);
	if(sTitle.IsEmpty())
		sTitle.LoadString(AFX_IDS_APP_TITLE);

	CaplSetResourceHandle setres(module_inst);

	bool bDefault = true;
	CRegKey key;
	if(key.Open(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\CALS Centre \"Applied Logistic\""), KEY_QUERY_VALUE)==ERROR_SUCCESS)
	{
		TCHAR *cBuf = new TCHAR[255];
		DWORD dwLen = 255;
#if _MSC_VER >= 1400
		key.QueryStringValue(_T("ClientName"), cBuf, &dwLen);
#else
		key.QueryValue(cBuf, _T("ClientName"), &dwLen);
#endif
		CString ClientName;
		ClientName += cBuf;
		delete [] cBuf;
		bDefault = ClientName.CompareNoCase(_T("katalit"))!=0;
	}
	
	if(bDefault)
	{
		CAboutDlg aboutDlg(api);
		aboutDlg.SetTitle(title);
		aboutDlg.SetText(sTitle);
		aboutDlg.SetLogoIcon(logo_icon);
		aboutDlg.DoModal();
	}
	else
	{
		CAboutKatalitDlg aboutDlg(api);
		aboutDlg.SetTitle(title);
		aboutDlg.SetText(sTitle);
		aboutDlg.SetLogoIcon(logo_icon);
		aboutDlg.DoModal();
	}
}

/*** для новой архитектуры доступа!*/
CaplInstance AFX_EXT_API *SelectAccessPattern(CaplAPI* m_api,CaplInstance *curr_pattern)
{
	if(m_api==0) return 0;
	return SelectAccessPatternC(&(m_api->m_data),curr_pattern);
}

CaplAPI *temp_api=0;
bool IsUsed(CString &pattern_name, CString &option_used)
{
	if(temp_api==0) return true;
	return temp_api->m_options_mgr.WherePatternUsed(pattern_name,option_used);
}

void AFX_EXT_API EditAccessPattern(CaplAPI* m_api)
{
	if(m_api==0) return;
	temp_api=m_api;
	EditAccessPatternC((LPVOID)&(m_api->m_data),IsUsed);
	temp_api=0;

}
/****/



bool CaplPreProjectManager::GetProjectSequenceRelation(CaplInstance *prj, aplExtent &ext_rel, bool previous_only, bool bLoadFromDB)
{
	ext_rel.Clear();
	if(0==m_api) return false;
	if(0==prj) return false;
	if(prj->GetType()==0) return false;
	if(prj->GetAccessmode()>aplRO)return false;

	int i;
	aplExtent ext_tmp;
	CaplInstance *inst,*inst1;

	if(bLoadFromDB)
	{

		CaplLoadData ld(m_data,DEF_SOURCE);
		i = ld.AddQuery(_T('b'),prj->GetId(),e_project_seg,a_project_seq_next,true,true);
			ld.AddQuery(_T('d'), i, 0, a_project_seq_prev, true,true);

		if(!previous_only)
		{
			i = ld.AddQuery(_T('b'),prj->GetId(),e_project_seg,a_project_seq_prev,true,true);
				ld.AddQuery(_T('d'), i, 0, a_project_seq_next , true,true);
		}
		ld.LoadEx(true,&ext_tmp);
	}
	else m_api->m_data.GetEntityExtent(e_project_seg,ext_tmp);

	bool bOldUnique=ext_rel.Unique;
	ext_rel.Unique=false;

	for(i=0;i<ext_tmp.GetSize();i++)
	{
		inst=ext_tmp[i];
		if(inst->GetType()==0) continue;

		if((!bLoadFromDB) && (!m_api->m_data.IsKindOf(inst,e_project_seg))) continue;
		m_api->m_data.GetAttr(inst,a_project_seq_next,inst1);
		if(inst1==prj) ext_rel.Add(inst);
		else
		{
			if(!previous_only)
			{
				m_api->m_data.GetAttr(inst,a_project_seq_prev,inst1);
				if(inst1==prj) ext_rel.Add(inst);
			}
		}
	}
	ext_rel.Unique=bOldUnique;

	return true;
}
//**************************************************************************************************
bool CaplPreProjectManager::LoadProjectsSequenceRelations(aplExtent &projects, aplExtent &ext_rel, bool previous_only, bool bLoadFromDB)
{
	ext_rel.Clear();
	if(0==m_api) return false;
	if(0==projects.GetSize()) return true;

	aplExtent ext_tmp,ext_sorted_projects;
	int i;

	if(bLoadFromDB)
	{
		CaplLoadData ld(m_data,DEF_SOURCE);

		for(i=0;i<projects.GetSize();i++)
		{
			ld.AddQuery(0,projects[i]);
		}

		i = ld.AddQuery(_T('r'),0,e_project_seg,a_project_seq_prev,true,true);
		ld.AddQuery(_T('d'), i, 0, a_project_seq_next , true,true);

		if(!previous_only)
		{
			i = ld.AddQuery(_T('r'),0,e_project_seg,a_project_seq_prev,true,true);
			ld.AddQuery(_T('d'), i, 0, a_project_seq_next , true,true);
		}
		ld.LoadEx(true,&ext_tmp);
	}
	else
	{
		ext_sorted_projects.Unique=false;
		ext_sorted_projects.Clear();
		ext_sorted_projects.Append(projects);
		ext_sorted_projects.Sort();

		m_data->GetEntityExtent(e_project_seg,ext_tmp);
	}

	CaplInstance *inst;
	for(i=0;i<ext_tmp.GetSize();i++)
	{
		inst=ext_tmp[i];
		if(inst->GetType()==0) continue;

		if(bLoadFromDB)
		{
			if(!m_api->m_data.IsKindOf(inst,e_project_seg)) continue;
		}
		else
		{
			CaplInstance *prev,*next;
			m_api->m_data.GetAttr(inst,a_project_seq_next,next);
			if(0==next) continue;
			if(!aplQFindInstInExtent(ext_sorted_projects,next,false)) continue;
			
			if(!previous_only)
			{
				m_api->m_data.GetAttr(next,a_project_seq_next,prev);
				if(0==prev) continue;
				if(!aplQFindInstInExtent(ext_sorted_projects,prev,false)) continue;
			}
		}
		ext_rel.Add(inst);
	}
	return true;
}

const TCHAR CaplDefWindowParam_KeyName[]=_T("Software\\CALS Centre \"Applied Logistic\"");


void CaplStepManager::LoadGlobalParams()
{
	HKEY key=0;
	if(ERROR_SUCCESS!=RegOpenKeyEx(HKEY_CURRENT_USER,CaplDefWindowParam_KeyName,0, KEY_QUERY_VALUE,&key))return;
	if(0==key) return;
	//char *buf=new char[1024];
	DWORD size=1024; DWORD type=0;;
	//RegQueryValueEx(key,_T("def_font_face"),0,&type,(BYTE*)buf,&size);
	//m_font_face=buf;
	size=sizeof(CaplDocManager::m_bUseAplMarkView);
	RegQueryValueEx(key,_T("m_bUseAplMarkView"),0,&type,(BYTE*)(&CaplDocManager::m_bUseAplMarkView),&size);
	//delete buf;
	RegCloseKey(key);
}

void CaplStepManager::SaveGlobalParams()
{
	HKEY key=0;
	if(ERROR_SUCCESS!=RegOpenKeyEx(HKEY_CURRENT_USER,CaplDefWindowParam_KeyName,0, KEY_ALL_ACCESS,&key))
	{
		DWORD Disp=0;
		if(ERROR_SUCCESS!=RegCreateKeyEx(HKEY_CURRENT_USER,CaplDefWindowParam_KeyName,0,0,0, KEY_ALL_ACCESS,0,&key,&Disp))return;

	}
	if(0==key) return;
	//RegSetValueEx(key,_T("def_font_face"),0,REG_SZ,(BYTE*)(LPCTSTR(m_font_face)),m_font_face.GetLength()+1);
	//RegSetValueEx(key,_T("def_font_size"),0,REG_DWORD,(BYTE*)(&m_font_size),sizeof(DWORD));
	RegSetValueEx(key,_T("m_bUseAplMarkView"),0,REG_DWORD,(BYTE*)(&CaplDocManager::m_bUseAplMarkView),sizeof(&CaplDocManager::m_bUseAplMarkView));
	RegCloseKey(key);
}


// Функция сравнивает 2 строки исходя из предположения, что в начале будет иерархия из цифр (например, в обозначении справочников)
int aplCompare2StringAsClassifier(CString &str1, CString &str2)
{
	if(str1==_T("") || str2==_T("")) return str1.Compare(str2);

	int i01=0;
	int i02=0;

	while(true)
	{
		TCHAR *ch1=(TCHAR*)LPCTSTR(str1)+i01;
		TCHAR *ch2=(TCHAR*)LPCTSTR(str2)+i02;

		if(!(ch1[0]>=_T('0') && ch1[0]<=_T('9') &&  ch2[0]>=_T('0') && ch2[0]<=_T('9')))
		{
			// первый символ не цифра
			CString s1=ch1;
			//CString s2=ch2;
			return s1.Compare(ch2);
		}

		int i1=_atoi(ch1);
		int i2=_atoi(ch2);
		if(i1!=i2) 
		{
			if(i1>i2) return 1; else return -1;
		}

		// Ищем след. цифры
		//i1=str1.Find(_T('.'),i01);
		//i2=str2.Find(_T('.'),i02);
		//if(i1>0 && i2>0) {i01=i1+1; i02=i2+1; continue;}
		//break;

		int i=0;
		while(ch1[i]>=_T('0') && ch1[i]<=_T('9')) i++; // пропускаем цифры
		while(ch1[i]==_T(' ') || ch1[i]==_T('.') || ch1[i]==_T('-') || ch1[i]==_T(':')) i++; // пропускаем разделители
		if(ch1[i]==_T('\0')) break;
		i01+=i;

		i=0;
		while(ch2[i]>=_T('0') && ch2[i]<=_T('9')) i++; // пропускаем цифры
		while(ch2[i]==_T(' ') || ch2[i]==_T('.') || ch2[i]==_T('-')|| ch2[i]==_T(':')) i++; // пропускаем разделители
		if(ch2[i]==_T('\0')) break;
		i02+=i;
	}
	return str1.Compare(str2); 
}