// aplProjectMgr.cpp: implementation of the CaplProjectManager class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "aplProjectMgr.h"
#include "apl_api.h"
#include "ProjectDlg.h"
#include "dictionary.h"
#include "TransactionsReportList.h"
#include "SelectTransactionFilterDlg.h"
#include "PrjMonitorDlg.h"
#include "ShowGanttDlg.h"
#include "CreatePrjCopyDlg.h"
#include "PrjColorLegendDlg.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
bool CaplProjectManager::m_bShowId=true;
bool CaplProjectManager::m_bShowName=true;
bool CaplProjectManager::m_bRecursive=true;

#define APL_PMTT_PLAN	APL_T("План")
#define APL_PMTT_FACT	APL_T("Факт")
#define APL_PMTT_FHELP	APL_T("Для справки")


/*COLORREF  CaplProjectManager::RGB_DEFAULT=RGB(230,244,255);
COLORREF  CaplProjectManager::RGB_POFIG=RGB(171,202,254);
COLORREF  CaplProjectManager::RGB_ENDED=RGB(35,214,57);
COLORREF  CaplProjectManager::RGB_NOTSTART_OVERDUE=RGB(255,155,205);
COLORREF  CaplProjectManager::RGB_NOTSTART_NO_OVERDUE=RGB(255,196,109);
COLORREF  CaplProjectManager::RGB_WORK_GOOD_PROGN=RGB(209,247,230);
COLORREF  CaplProjectManager::RGB_WORK_BAD_PROGN=RGB(255,249,157);
COLORREF  CaplProjectManager::RGB_WORK_OVERDUE=RGB(255,171,171);*/


COLORREF  CaplProjectManager::RGB_DEFAULT=RGB(106,188,255);
COLORREF  CaplProjectManager::RGB_POFIG=RGB(85,148,253);
COLORREF  CaplProjectManager::RGB_ENDED=RGB(30,183,49);
COLORREF  CaplProjectManager::RGB_NOTSTART_OVERDUE=RGB(255,81,168);
COLORREF  CaplProjectManager::RGB_NOTSTART_NO_OVERDUE=RGB(255,159,15);
COLORREF  CaplProjectManager::RGB_WORK_GOOD_PROGN=RGB(56,220,147);
COLORREF  CaplProjectManager::RGB_WORK_BAD_PROGN=RGB(249,236,0);
COLORREF  CaplProjectManager::RGB_WORK_OVERDUE=RGB(255,62,62);



LPCTSTR sDateFormat=_T("%d.%m.%Y");

#define ODT_1SEC 0.0007

CaplProjectManager::CaplProjectManager():CaplPreProjectManager()
{
	m_saMoneyTransactionTypes.Add(APL_T("План"));
	m_saMoneyTransactionTypes.Add(APL_T("Факт"));
	m_saMoneyTransactionTypes.Add(APL_T("Для справки"));

	m_has_role_edit_fact=true;
}

CaplProjectManager::~CaplProjectManager()
{
	m_saMoneyTransactionTypes.RemoveAll();
}

void CaplProjectManager::GetIdPersOrOrg(CaplInstance *item, CString &id)
{
	id=_T("");
	if(0==item) return;

	if(m_api->m_data.IsKindOf(item, m_api->m_appr_mgr.e_person)) {m_api->m_appr_mgr.GetPersonName(item,id); return;}
	else if(m_api->m_data.IsKindOf(item, m_api->m_appr_mgr.e_org))
	{
		CString s0,s1,s00,s10;
		m_api->m_data.GetAttr(item,m_api->m_appr_mgr.a_org_id,s0); 
		m_api->m_data.GetAttr(item,m_api->m_appr_mgr.a_org_name,s1); 

		s00=s0; s00.MakeLower();
		s10=s1; s10.MakeLower();

		if(s10.Find(s00)>=0) {id=s1; return;}
		id=s0; return;
	}
}

CaplInstance *CaplProjectManager::CreateProject(CaplInstance *base_project, LPCTSTR id,bool add_to_base_contents,CaplInstance *item,CaplInstance **rel)
{
	CaplInstance *my_lock=0,*lock=0;
	if(base_project)
	{
		if(base_project->GetAccessmode()>aplRW)
		{
			AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
			return 0;
		}
		if(add_to_base_contents)
		{
			m_data->GetAttr(base_project,a_project_locker_adm_version,lock);
			my_lock=CheckMyLock(base_project,false);
			if(!my_lock && !lock) CheckOut(base_project);
			my_lock=CheckMyLock(base_project,false);
		}
	}

	CaplSetResourceHandle setres(module_inst);

	CProjectDlg dlg;
	dlg.m_project_mgr=this;
	dlg.m_parent=base_project;
	dlg.m_id=id;
	CaplInstance *created_project=0;
	if(dlg.DoModal()==IDOK)
	{
		created_project=dlg.m_project;
		if(created_project)
		{
			if(base_project)
			{
				if(add_to_base_contents && my_lock) AddToParentContent(created_project,base_project);
			}
			if(item) *rel=CreateAssociation(created_project,item);
			if(m_AutoSave) m_data->NET_SaveChanges();
			
			if(m_AutoUsurpire==true && m_api->m_data.IsConnected())
			{
				CaplEntity*	et	=NULL;
				aplExtent	aet;
				CString		csAccPat;
				
				et=e_project;
				aet.Add(created_project);

				if(TRUE==m_api->m_options_mgr.GetDefPatern(et, csAccPat))
					apidata.NET_SetAccessFromPattern(&aet, csAccPat);
			}	
		}
		
	}
	return created_project;
}

bool CaplProjectManager::LoadSubProjects(CaplInstance *project,aplExtent &ext_out)
{
	if(!project) return false;
	if(project->GetAccessmode()>aplRO) return false;

	CaplLoadData ld(m_data,DEF_SOURCE);
	       ld.AddQuery( 0, project);	
		   ld.AddQuery(_T('d'), 0, 0,a_project_parent,true);
		   ld.AddQuery(_T('d'), 0, 0,a_project_content,true);
	int i= ld.AddQuery(_T('d'), 0, 0,a_project_locker_adm_version,true);
			  ld.AddQuery(_T('d'), i, 0,a_project_adm_ver_content,true);
		i= ld.AddQuery(_T('b'), project->GetId(), e_project,a_project_parent, true);
		i= ld.AddQuery(_T('d'), i, 0,a_project_parent, true);	

    ld.LoadEx();

	aplExtent ext_all_projects;
	m_data->GetEntityExtent(e_project,ext_all_projects);
	CaplInstance *inst=0;
	for(i=0;i<ext_all_projects.GetSize();i++)
	{
		if(ext_all_projects[i]->GetAccessmode()>aplRO) continue;
		m_data->GetAttr(ext_all_projects[i],a_project_parent,inst);
		if(inst==project) 
		{
			if(IsProjectInContentOfParent(ext_all_projects[i])) continue;
			ext_out.Add(ext_all_projects[i]);
		}
		
	}
	return true;
	
}

bool CaplProjectManager::GetAllSubProject(CaplInstance *project,aplExtent &ext_out,bool recursive,bool include_associated,bool from_base)
{
	if(!project) return false;
	if(project->GetAccessmode()>aplRO) return false;
	aplExtent ext;
	ext.Add(project);
	GetAllSubProject(ext,ext_out,recursive,include_associated,from_base);
	return true;
}

void CaplProjectManager::GetAllSubProject(aplExtent &project_ext,aplExtent &ext_out,bool recursive,bool include_associated,bool from_base)
{
	int i;
	if(from_base)
	{
		CaplLoadData ld(m_data,DEF_SOURCE);
		bool bLoad=false;
		for(i=0;i<project_ext.GetSize();i++)
		{
			if(project_ext[i]->GetAccessmode()>aplRO) continue;
			ld.AddQuery(0,project_ext[i],true);
			bLoad=true;
		}
		if(bLoad)
		{
				  ld.AddQuery(_T('d'),0,0,a_project_content,true,true);
				  int i1=ld.AddQuery(_T('d'),0,0,a_project_act_adm_version,true,true);
				  ld.AddQuery(_T('d'),i1,0,a_project_adm_ver_content,true,true);
				  if(include_associated)
				  {
					   int k=ld.AddQuery(_T('r'), 0, e_project,a_project_parent, true,true);
							 ld.AddQuery(_T('d'), k, 0,a_project_parent, true,true);	
				  }
				  ld.LoadEx();
		}
	}
	aplExtent ext_rec;
	for(i=0;i<project_ext.GetSize();i++)
	{
		if(project_ext[i]->GetAccessmode()>aplRO) continue;
		CaplAggr aggr;
		CaplInstance *ver=CheckMyLock(project_ext[i],false);
		if(m_data->IsKindOf(project_ext[i],e_project_adm_ver)) ver=project_ext[i];
		if(ver) m_data->GetAttr(ver,a_project_adm_ver_content,aggr);
		else m_data->GetAttr(project_ext[i],a_project_content,aggr);
		CaplInstance *inst=0;
		for(int j=0;j<aggr.GetSize();j++)
		{
			aggr.GetByIndex(j,inst);
			if(inst) 
			{
				ext_out.Add(inst);
				ext_rec.Add(inst);
			}
		}
	}
	if(include_associated)
	{
		aplExtent ext_all_projects;
		m_data->GetEntityExtent(e_project,ext_all_projects);
		for(i=0;i<project_ext.GetSize();i++)
		{
			if(project_ext[i]->GetAccessmode()>aplRO) continue;
			CaplInstance *inst=0;
			for(int j=0;j<ext_all_projects.GetSize();j++)
			{
				m_data->GetAttr(ext_all_projects[j],a_project_parent,inst);
				if(inst==project_ext[i]) 
				{
					bool already_in_list=false;
					for(int k=0;k<ext_rec.GetSize();k++)
					{
						if(ext_rec[k]==ext_all_projects[j]) 
						{
							already_in_list=true;
							break;
						}
					}
					if(!already_in_list) 
					{
						ext_out.Add(ext_all_projects[j]);
						ext_rec.Add(ext_all_projects[j]);
					}
				}
			}
		}
	}
	if(recursive) 
		if(ext_rec.GetSize())
			GetAllSubProject(ext_rec,ext_out,recursive,include_associated,from_base);

}

bool CaplProjectManager::LoadAllSubProjectNlevel(aplExtent &project_ext,aplExtent &ext_out,int nlevel)
{
	ext_out.Clear();
	if(project_ext.GetSize()<1) return false;
	if(nlevel<0) return false;

	CaplLoadData ld(m_data,DEF_SOURCE);
	int i;
	for(i=0;i<project_ext.GetSize();i++)
	{
		if(project_ext[i]->GetAccessmode()>aplRO) continue;
		ld.AddQuery(0,project_ext[i]);
	}
	ld.AddQuery(_T('d'),0,0,a_project_adm_ver_content,true,true);	for(i=1;i<=nlevel;i++)
	{
		ld.AddQuery(_T('d'),(i-1)*2,0,a_project_content,true,true);
		ld.AddQuery(_T('d'),(i-1)*2,0,a_project_adm_ver_content,true,true);
	}
	aplExtent ext1;
	ld.LoadEx(true,&ext1,APL_T("Чтение подпроектов"));

	for(i=0;i<ext1.GetSize();i++)
	{
		if(m_data->IsKindOf(ext1[i],e_project))
			ext_out.Add(ext1[i]);
	}
	return true;
}

bool CaplProjectManager::ShowProjectProperties(CaplInstance *project,bool b_read_only)
{
	if(!project) return false;
	if(project->GetAccessmode()>aplRO)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}
	LoadProjectInfo(project);

	m_api->m_options_mgr.GetOptionValueBN(APL_NO_T("Проекты\\Роль для работы с фактическими платежами"),m_role_to_edit_fact);
	if(m_role_to_edit_fact!=_T("")) m_has_role_edit_fact=m_api->m_appr_mgr.CheckPersonRole(0,m_role_to_edit_fact);

	bool b_read_only_ver=false;//редактирование свойств, поддерживающих версии
	bool b_can_check_out=true; //можно или нет взять проект на редактирование (свойства, поддерживающие версии)
	if(project->GetAccessmode()==aplRO) b_read_only=true; //редактирование всех свойств 
	
	CaplInstance *ver=0;
	CaplInstance *lock=GetLock(project,false);
	CaplInstance *my_lock=CheckMyLock(project,false);
	if(m_data->IsKindOf(project,e_project_adm_ver))	ver=project;
	else ver=my_lock;

	CaplSetResourceHandle setres(module_inst);

	CProjectDlg dlg;
	dlg.m_project_mgr=this;
	if(ver)
	{
		dlg.m_project=ver;
		if(ver!=lock) b_read_only=true;//это не редактируемая 'архивная' версия
	}
	else
	{
		dlg.m_project=project;
		b_read_only_ver=true;
	}
	if(lock && lock!=my_lock) 
	{
		b_can_check_out=false;
		b_read_only_ver=true;
	}
	dlg.m_read_only=b_read_only;		
	dlg.m_read_only_ver=b_read_only_ver;
	dlg.m_can_check_out=b_can_check_out;
	dlg.DoModal(); 

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

bool CaplProjectManager::AddToParentContent(CaplInstance *project,CaplInstance *parent_project)
{
	if(!parent_project) return false;
	if(!project) return false;
	if(parent_project->GetAccessmode()>aplRW)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}
	if(project->GetAccessmode()>aplRO)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}
	CaplInstance *inst=0;
	CaplInstance *lock_parent=0;
	bool just_checked_out=false;
	if(m_data->IsKindOf(parent_project,e_project)) 
	{
		lock_parent=CheckMyLock(parent_project,false);
		if(!lock_parent) 
		{
			CheckOut(parent_project);
			just_checked_out=true;
		}
		lock_parent=CheckMyLock(parent_project,true);
	}
	else if(m_data->IsKindOf(parent_project,e_project_adm_ver))
		lock_parent=parent_project;
	if(!lock_parent) return false;

	CaplInstance *project_ver_project=project;
	if(m_data->IsKindOf(project,e_project_adm_ver))
		m_data->GetAttr(project,a_project_adm_ver_project,project_ver_project);
	if(!project_ver_project) return false;

	CaplAggr aggr;
	if(lock_parent) m_data->GetAttr(lock_parent,a_project_adm_ver_content,aggr);
	else m_data->GetAttr(parent_project,a_project_content,aggr);
	bool found_in_content=false;
	for(int i=0;i<aggr.GetSize();i++)
	{
		aggr.GetByIndex(i,inst);
		if(inst==project_ver_project) {found_in_content=true;break;}
	}
	if(!found_in_content)
	{
		aggr.Add(project_ver_project);
		if(lock_parent) m_data->PutAttr(lock_parent,a_project_adm_ver_content,aggr);
		else m_data->PutAttr(parent_project,a_project_content,aggr);
		RecalcProjectLabor(parent_project);
		if(just_checked_out) CheckIn(parent_project);
		if(m_AutoSave) m_data->NET_SaveChanges();
		return true;
	}
	if(just_checked_out) CheckIn(parent_project);
	return false;
}

bool CaplProjectManager::RemoveFromParentContent(CaplInstance *project,CaplInstance *parent_project)
{
	if(!parent_project) return false;
	if(!project) return false;
	if(parent_project->GetAccessmode()>aplRW)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}
	if(project->GetAccessmode()>aplRO)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}
	CaplInstance *inst=0;
	CaplInstance *lock_parent=0;
	bool just_checked_out=false;
	if(m_data->IsKindOf(parent_project,e_project)) 
	{
		lock_parent=CheckMyLock(parent_project,false);
		if(!lock_parent) 
		{
			CheckOut(parent_project,false);
			lock_parent=CheckMyLock(parent_project,true);
			if(!lock_parent) return false;
			just_checked_out=true;
		}
	}
	else if(m_data->IsKindOf(parent_project,e_project_adm_ver))
	{
		lock_parent=parent_project;
	}
	

	CaplInstance *project_ver_project=project;
	if(m_data->IsKindOf(project,e_project_adm_ver))
		m_data->GetAttr(project,a_project_adm_ver_project,project_ver_project);
	if(!project_ver_project) return false;

	CaplAggr aggr;
	if(lock_parent) m_data->GetAttr(lock_parent,a_project_adm_ver_content,aggr);
	else m_data->GetAttr(parent_project,a_project_content,aggr);
	for(int i=0;i<aggr.GetSize();i++)
	{
		aggr.GetByIndex(i,inst);
		if(inst==project_ver_project) 
		{
			aggr.Remove(i);
			if(lock_parent) m_data->PutAttr(lock_parent,a_project_adm_ver_content,aggr);
			else m_data->PutAttr(parent_project,a_project_content,aggr);
			RecalcProjectLabor(parent_project);
			if(just_checked_out) CheckIn(parent_project);
			if(m_AutoSave) m_data->NET_SaveChanges();
			return true;
		}
	}
	return false;
}

bool CaplProjectManager::InsertProjectIntoParent(CaplInstance *project,CaplInstance *parent_project,bool add_to_content,bool remove_from_old_content,bool make_main_parent)
{
	if(!parent_project) return false;
	if(!project) return false;
	if(parent_project->GetAccessmode()>aplRW)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}
	if(project->GetAccessmode()>aplRW)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}
	if(project==parent_project)
	{
		AfxMessageBox(APL_T("Нельзя включать проект сам в себя!"),MB_OK|MB_ICONSTOP);
		return false;
	}
	CaplInstance *par_prj=0;;
	m_data->GetAttr(parent_project,a_project_parent,par_prj);
	while(par_prj)
	{
		if(par_prj==project)
		{
			AfxMessageBox(APL_T("Цикл в структуре проектов недопустим!"));
			return false;
		}
		m_data->GetAttr(par_prj,a_project_parent,par_prj);
	}
	CaplInstance *inst=0;
	m_data->GetAttr(project,a_project_parent,inst);
	if(inst && inst==parent_project)//проект уже связан с родительским, просто добавим его в его состав
	{
		if(add_to_content) 
		{
			AddToParentContent(project,parent_project);
		}
	}
	else
	{
		if(remove_from_old_content) RemoveFromParentContent(project,inst);
		if(add_to_content) 
		{
			if(!inst || remove_from_old_content || make_main_parent) m_data->PutAttr(project,a_project_parent,parent_project);
			AddToParentContent(project,parent_project);
		}
	}
	
	if(m_AutoSave) m_data->NET_SaveChanges();
	return true;
}

bool CaplProjectManager::RemoveProjectFromParent(CaplInstance *project,CaplInstance *parent_project)
{
	if(!parent_project) return false;
	if(!project) return false;
	if(parent_project->GetAccessmode()>aplRW)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}
	if(project->GetAccessmode()>aplRW)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}
	CaplInstance *inst=0;
	m_data->GetAttr(project,a_project_parent,inst);
	if(inst!=parent_project) return false;

	RemoveFromParentContent(project,parent_project);
	m_data->PutAttr(project,a_project_parent,(CaplInstance*)0);
	if(m_AutoSave) m_data->NET_SaveChanges();
	return true;
	
}

bool CaplProjectManager::DeleteProject(CaplInstance *project,bool delete_sub_projects,bool delete_associated_projects,bool recalc_parent_labor)
{
	if(!project) return false;
	if(!project->GetType()) return false;
	if(project->GetAccessmode()>aplOWN)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}
	int i;

	if(m_data->IsKindOf(project,e_project))
	{
		//удаление инстанса трудоемкости
		CaplInstance *labor=0;
		m_data->GetAttr(project,a_project_labor_useness,labor);
		if(labor) m_data->DeleteInstance(labor);
		aplExtent ext;
		if(delete_sub_projects)
		{
			GetAllSubProject(project,ext,true,delete_associated_projects);
			for(i=0;i<ext.GetSize();i++) 
				DeleteProject(ext[i],true,delete_associated_projects,false); 
		}
		//удаление характеристик
		ext.Clear();
		CaplAttrValue tst_values[1];
		tst_values[0].value.Set(project);
		tst_values[0].attr=m_api->m_charact_mgr.a_apl_charact_val_item;
		m_data->NET_FindInstancesWithAttrValues(m_api->m_charact_mgr.e_apl_charact_value,1,&tst_values[0],ext,true);
		for(i=0;i<ext.Size;i++)
		{
			if(!ext[i]) continue;if(ext[i]->GetAccessmode()>aplOWN) continue;
			m_api->m_charact_mgr.DeleteCharacteristic(ext[i]);//чтобы убить и версии характеристик
		}
		//Удаление версий 
		ext.Clear();
		GetAllProjectVersion(project,ext);
		for(i=0;i<ext.GetSize();i++)
		{
			if(ext[i]->GetAccessmode()>aplOWN) continue;
			m_data->DeleteInstance(ext[i]);		
		}
		//удалим напоминания о проекте
		aplExtent alerts;
		m_api->m_message_mgr.FindAlerts(alerts, 0, project);
		for(i=0;i<alerts.GetSize();i++) 
			m_api->m_message_mgr.DeleteAlert(alerts[i]);

		if(recalc_parent_labor)
		{
			CaplInstance *parent=0;
			m_data->GetAttr(project,a_project_parent,parent);
			if(parent)	RecalcProjectLabor(parent);
		}

		m_data->DeleteInstance(project);
	
	}
	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);	
		CaplInstance *act=0;
		if(project_ver_project)
		{
			if(project_ver_project->GetAccessmode()<aplNO)
			{
				m_data->GetAttr(project_ver_project,a_project_act_adm_version,act);
				if(act==project) 
				{
					AfxMessageBox(APL_T("Нельзя удалять активную версию!"));
					return false;
				}
			}
			else 
				return false;
		}
		//удаление инстанса трудоемкости
		CaplInstance *labor=0;
		m_data->GetAttr(project,a_project_adm_ver_labor_useness,labor);
		if(labor) m_data->DeleteInstance(labor);

		m_data->DeleteInstance(project);
	}

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

CaplInstance *CaplProjectManager::FindProjectTypeBN(LPCTSTR name,bool bLoadFromBase)
{
	if(!name) return 0;
	if(bLoadFromBase)
	{
		CaplLoadData ld(m_data,DEF_SOURCE);
		int j=ld.AddQuery(_T('e'),0,e_project_type,0,true);
			  ld.AddQuery(_T('d'),j,0,a_project_type_name,true);
			  ld.LoadEx();
	}
	aplExtent ext;
	m_data->GetEntityExtent(e_project_type,ext);
	CString buf=_T("");
	CString name_s=name;
	name_s.MakeUpper();
	for(int i=0;i<ext.GetSize();i++)
	{
		if(ext[i]->GetAccessmode()>aplRO) continue;
		m_data->GetAttr(ext[i],a_project_type_name,buf);
		buf.MakeUpper();
		if(buf==name_s) return ext[i];
	}
	return 0;
}


CaplInstance *CaplProjectManager::CreateProjectType(LPCTSTR name)
{
	if(!name) return 0;
	CaplInstance *type=FindProjectTypeBN(name);
	if(type)
		return type;
	else
		type=m_data->CreateInstance(e_project_type);
	if(type)
	{
		m_data->PutAttr(type,a_project_type_name,name);
		return type;
	}
	return 0;
}

bool CaplProjectManager::IsProjectIdUnique(LPCTSTR id,CaplInstance *project,bool bShowMessage)
{
	CaplAttrValue tst_values[1];               
	tst_values[0].value.Set(id); 
	tst_values[0].attr=a_project_id;
	if(!m_data->TestUniqueAttrValues(e_project,project,1,&tst_values[0]))
	{
		if(bShowMessage) AfxMessageBox(APL_T("Проект с таким обозначением уже есть в базе !!!"));
		return false;
	}
	return true;
}

bool CaplProjectManager::WhereUsedProject(CaplInstance *project,aplExtent &ext_out)
{
	if(project==0) return false;
	if(project->GetType()==0)return false;
	if(project->GetAccessmode()>aplRO){AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP); return false;}

	CaplInstance *parent=0;
	m_data->GetAttr(project,a_project_parent,parent);
	if(parent) ext_out.Add(parent);
	int i,j,k;
	if((m_data->IsConnected())&&(project->GetId()!=0))
	{
		// чтение из базы
		CaplLoadData ld(m_data,DEF_SOURCE);
		j=	ld.AddQuery(_T('b'), project->GetId(), e_project, a_project_content, true);
	    ld.AddQuery(_T('d'), j, 0,a_project_content, true);
		if (!ld.LoadEx())
		{
			if(m_data->GetLastAplError()!=APL_SOCK_OPERATION_IN_PROGRESS){
				AfxMessageBox(S::ErrorLoadDataMgr,MB_OK|MB_ICONSTOP);
			}
		}
		ld.ClearQuery();
		j=	ld.AddQuery(_T('b'), project->GetId(), e_project_adm_ver, a_project_adm_ver_content, true);
		ld.AddQuery(_T('d'), j, 0,a_project_adm_ver_content, true,true);
		k=ld.AddQuery(_T('d'), j, 0,a_project_adm_ver_project, true,true);
		ld.AddQuery(_T('d'), k, 0,a_project_locker_adm_version, true,true);
	}

	aplExtent ext1;
	CaplAggr aggr0;
	CaplInstance *inst;
	m_data->GetEntityExtent(e_project,ext1);

	for(i=0;i<ext1.Size;i++)
	{
		if(ext1[i]->GetAccessmode()>aplRO) continue;
		m_data->GetAttr(ext1[i],a_project_content,aggr0);	
		for(j=0;j<aggr0.GetSize();j++)
		{
			aggr0.GetByIndex(j,inst);
			if(inst==project) 
			{
				ext_out.Add(ext1[i]);
				break;
			}
		}
	}
	ext1.Clear();
	aggr0.Clear();
	m_data->GetEntityExtent(e_project_adm_ver,ext1);
	for(i=0;i<ext1.Size;i++)
	{
		if(ext1[i]->GetAccessmode()>aplRO) continue;
		CaplInstance *inst0=0;
		m_data->GetAttr(ext1[i],a_project_adm_ver_project,inst0);
		if(!inst0) continue;
		if(inst0->GetAccessmode()>aplRO) continue;
		CaplInstance *lock=CheckMyLock(inst0,false);
		if(!lock) continue;
		m_data->GetAttr(ext1[i],a_project_adm_ver_content,aggr0);	
		for(j=0;j<aggr0.GetSize();j++)
		{
			aggr0.GetByIndex(j,inst);
			if(!inst) continue;
			if(inst->GetAccessmode()>aplRO) continue;
			if(inst==project) 
			{
				ext_out.Add(inst0);
				break;
			}
		}
	}
	LoadProjectInfo(ext_out);

	return true;
}

CaplInstance *CaplProjectManager::FindProjectById(LPCTSTR id,bool bLoadFromBase)
{
	if(!id) return 0;
	if(bLoadFromBase)
	{
		CaplLoadData ld(m_data,DEF_SOURCE);
		int j=ld.AddQuery(_T('e'),0,e_project,0,true);
			  ld.AddQuery(_T('d'),j,0,a_project_id,true);
			  ld.LoadEx();
	}
	aplExtent ext;
	m_data->GetEntityExtent(e_project,ext);
	CString buf=_T("");
	CString id_s=id;
	id_s.MakeUpper();
	for(int i=0;i<ext.GetSize();i++)
	{
		if(ext[i]->GetAccessmode()>aplRO) continue;
		m_data->GetAttr(ext[i],a_project_id,buf);
		buf.MakeUpper();
		if(buf==id_s) return ext[i];
	}
	return 0;
}

CaplInstance *CaplProjectManager::FindProjectBN(LPCTSTR name,bool bLoadFromBase)
{
	if(!name) return 0;
	if(bLoadFromBase)
	{
		CaplLoadData ld(m_data,DEF_SOURCE);
		int j=ld.AddQuery(_T('e'),0,e_project,0,true);
			  ld.AddQuery(_T('d'),j,0,a_project_name,true);
			  ld.LoadEx();
	}
	aplExtent ext;
	m_data->GetEntityExtent(e_project,ext);
	CString buf=_T("");
	CString name_s=name;
	name_s.MakeUpper();
	for(int i=0;i<ext.GetSize();i++)
	{
		if(ext[i]->GetAccessmode()>aplRO) continue;
		m_data->GetAttr(ext[i],a_project_id,buf);
		buf.MakeUpper();
		if(buf==name_s) return ext[i];
	}
	return 0;
}
//*************************************************************************************
bool CaplProjectManager::FindProject(aplExtent &ext_po, bool bCustomer, bool bKurator, bool bExecutor, LPCTSTR sState, aplExtent &ext_prj,bool bLoadFromBase)        // Найти проект по наименованию (первый попавшийся)
{
	ext_prj.Clear();
	if(0==ext_po.GetSize()) return true;

	if(bCustomer==false && bKurator==false && bExecutor==false) return true;

	int i;
	aplExtent ext_po1; // очищенный от мусора
	ext_po1.Unique=false;
	
	for(i=0;i<ext_po.GetSize();i++)
	{
		CaplInstance *po=ext_po[i];
		if(0==po) continue;
		if(0==po->GetType()) continue;
		ext_po1.Add(po);
	}
	if(0==ext_po1.GetSize()) return true;

	CString buf, sCondition,sExt0, sCondExecuor;
	

	if(1==ext_po1.GetSize())
	{
		CString sId; sId.Format(_T("#%i"),ext_po1[0]->GetId());
		if(bCustomer) {sCondition=_T(".customer="); sCondition+=sId;}
		if(bKurator) {if(sCondition!=_T("")) sCondition+=_T(" OR "); sCondition+=_T(".kurator="); sCondition+=sId;}
		if(bExecutor){if(sCondition!=_T("")) sCondition+=_T(" OR "); sCondition+=_T(".executors LIKE "); sCondition+=sId;}
	}
	else
	{
		if(bCustomer||bKurator)
		{
			sExt0=_T("Ext0{");
			bool bNeedCOmma=false;
			for(i=0;i<ext_po1.GetSize();i++)
			{
				buf.Format(_T("#%i"),ext_po1[i]->GetId());
				if(i!=0)sExt0+=_T(",");
				sExt0+=buf;
			}
			sExt0+=_T("} \n");
		}
		if(bCustomer)sCondition=_T(".customer IN #Ext0");
		if(bKurator) {if(sCondition!=_T("")) sCondition+=_T(" OR "); sCondition+=_T(".kurator IN #Ext0");}

		if(bExecutor) 
		{
			for(i=0;i<ext_po1.GetSize();i++)
			{
				if(sCondition!=_T("")) sCondition+=_T(" OR ");
				buf.Format(_T(".executors LIKE #%i"),ext_po1[i]->GetId());
				sCondition+=buf;
			}
		}
	}
	if(sCondition==_T("")) return true;

	if(sState!=0)
	{
		if(sState[0]!=0)
		{
			sCondition.Insert(0,_T("("));
			sCondition+=_T(") AND .state='");
			sCondition+=sState;
			sCondition+=_T("'");
		}
	}

	CString sPrjQuery = _T("SELECT Ext_prj FROM @ext0Ext_prj{apl_project(@cond1)} END_SELECT");
	sPrjQuery.Replace(_T("@ext0"),sExt0);
	sPrjQuery.Replace(_T("@cond1"),sCondition);

	if(!m_api->m_data.NET_QueryEditParse(sPrjQuery,false))
	{
		// Ошибочно составлент запрос
		ASSERT(AfxMessageBox(APL_T("Ошибочно составлент запрос")));
		return false;
	}
	m_api->m_data.NET_QueryExecute(ext_prj);
	if(bLoadFromBase) m_api->m_doc_mgr.LoadExtentInfo(ext_prj);

	return true;
}


//*************************************************************************************
CString CaplProjectManager::GetProjectActualDate(CaplInstance *inst/* =NULL */,CaplAttr *attr/*=NULL*/)
{
	if(!m_data->IsConnected()) return _T("");
	if(inst==NULL || attr==NULL) return _T("");
	if(!m_data->IsKindOf(inst,e_project)) return _T("");
	if(attr != a_project_date_actual_end
		&& attr != a_project_date_actual_end2
		&& attr != a_project_date_actual_begin) return _T("");
	aplExtent ext;
	GetAllSubProject(inst,ext,true);
	if(ext.Size==0) return _T("");
	CString val=_T(""), max_date=_T("");
	m_data->GetAttr(inst,attr,max_date);
	for(int i=0; i<ext.Size;i++)
	{
		m_api->m_data.GetAttr(ext[i],attr,val);
		if(val==_T("")) return _T("");
		max_date = val>max_date ? val : max_date;
	}
	return max_date;
}

//Версии
 
bool CaplProjectManager::GetAllProjectVersion(CaplInstance *project,aplExtent &outExt)
{
	outExt.Clear();
	if(project==0) return false;
	if(project->GetAccessmode()>aplRO) return false;
	if(project->GetType()==0) return false;

	int i,j(-1);
	// Чтение из базы
	CaplLoadData ld(m_data,DEF_SOURCE);
	
	if(m_data->IsKindOf(project,e_project))
		j=ld.AddQuery(_T('b'), project->GetId(), e_project_adm_ver,a_project_adm_ver_project, true);
	else if(m_data->IsKindOf(project,e_project_adm_ver))
		j=ld.AddQuery(_T('b'), project->GetId(), e_project_adm_ver,a_project_adm_ver_parent, true);
	if (j>=0)
	{
		ld.AddQuery(_T('d'), j, 0, a_project_adm_ver_project, true);
		ld.AddQuery(_T('d'), j, 0, a_project_adm_ver_parent, true);
		ld.LoadEx();
	}

	CaplInstance *inst(NULL);
	aplExtent ext_hist;
	// Чтение версий
	m_data->GetEntityExtent(e_project_adm_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;
		if(m_data->IsKindOf(project,e_project))
			m_data->GetAttr(ext_hist[i],a_project_adm_ver_project,inst);
		else if(m_data->IsKindOf(project,e_project_adm_ver))
			m_data->GetAttr(ext_hist[i],a_project_adm_ver_parent,inst);
		if(inst==project) 
			outExt.Add(ext_hist[i]);
	}
	LoadProjectInfo(outExt);
	return true;
}

bool CaplProjectManager::CheckOut(CaplInstance *project,bool recursive)
{
	if(project==0) return false;
	if(project->GetAccessmode()>aplRO)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}
	if(m_data->IsKindOf(project,e_project))
		if(project->GetAccessmode()>=aplRO){AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);return false;}
	if(!m_data->IsKindOf(project,e_project))
		if(!m_data->IsKindOf(project,e_project_adm_ver))
			return false;
	// чтобы данные точно прочитались с сервера!
	m_data->ClearLastQuery();
	if(!recursive) LoadProjectInfo(project);
	else
	{

	}

	CaplInstance *lock=0,*rev=0;
	CaplInstance *act=0,*project_to_check_out=0;

	CString project_id=_T("");
	if(m_data->IsKindOf(project,e_project))
		project_to_check_out=project;
	else if(m_data->IsKindOf(project,e_project_adm_ver))
	{
		rev=project;
		m_data->GetAttr(project,a_project_adm_ver_project,project_to_check_out);
		if(!project_to_check_out) return false;
		if(project_to_check_out->GetAccessmode()>=aplRO) 
		{	
			AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
			return false;
		}
	}
	m_data->GetAttr(project_to_check_out,a_project_locker_adm_version,lock);
	m_data->GetAttr(project_to_check_out,a_project_id,project_id);
	m_data->GetAttr(project_to_check_out,a_project_act_adm_version,act);

	if(lock!=0)
	{
		CaplInstance *user=0;
		m_data->GetAttr(lock,a_project_adm_ver_author,user);
		if(user!=m_data->GetCurrUser())
		{
			AfxMessageBox(APL_T("Проект ")+project_id+APL_T(" уже редактируется другим пользователем !"),MB_OK|MB_ICONSTOP);
		}
		return false;
	}
	if(!act)
	{
		CString num=_T("");
		act=GetLatestProjectVersion(project_to_check_out,num);
		if(act)
			m_data->PutAttr(project_to_check_out,a_project_act_adm_version,act);
		else
			act=CreateProjectVersion(project_to_check_out,_T("0"));
	}

	if(rev)	lock=CreateProjectVersion(rev,_T("-1"),false);
	else lock=CreateProjectVersion(act,_T("-1"),false);
	if(!lock) return false;
	m_data->PutAttr(project_to_check_out,a_project_locker_adm_version,lock);
	

	if(m_AutoSave && !recursive) 
		m_data->NET_SaveChanges();

	return true;
}

bool CaplProjectManager::CheckOutWithRequest(CaplInstance *project,bool &recursive)
{
	if(!project) return false;
	if(project->GetAccessmode()>aplRW)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}
	// чтобы данные точно прочитались с сервера!
	m_data->ClearLastQuery();
	if(!recursive) LoadProjectInfo(project);

	CaplAggr aggr;
	if(m_data->IsKindOf(project,e_project)) 
		m_data->GetAttr(project,a_project_content,aggr);
	bool check_out_result=false;
	bool sub_project_choice_result=false;
	bool do_recursive=false;
	if(aggr.GetSize()) 
	{
		if(recursive)
		{
			do_recursive=true;
		}
		else
		{
			if(IDYES==AfxMessageBox(APL_T("Проект содержит подпроекты\n\nВзять подпроекты на редактирование ?"),
				MB_YESNO|MB_ICONQUESTION)) do_recursive=true;
		}
	
	}
	if(do_recursive) 
	{
		aplExtent ext;
		//Вариант, при котором берутся на редактирование и работы, не включенных пока в основной план
		//GetAllSubProject(project,ext,true,true);
		long trd=aplStartWaitDlg(APL_T("Идет обработка данных..."));
		GetAllSubProject(project,ext,true);
		for(int i=0;i<ext.GetSize();i++)
		{
			CheckOut(ext[i],true);
		}
		check_out_result=CheckOut(project,true);
		aplEndWaitDlg(trd);
	}
	else
	{
		check_out_result=CheckOut(project);
	}

	if(m_AutoSave) m_data->NET_SaveChanges();

	return check_out_result;
}

bool CaplProjectManager::CheckIn(CaplInstance *project,bool recursive,bool make_new_version_active)
{
	if(project==0) return false;
	aplExtent ext;

	if(!recursive) 
	{
		m_data->ClearLastQuery();
		LoadProjectInfo(project);
	}
	else
	{

	}


	if(!m_data->IsKindOf(project,e_project))return false;
	if(project->GetAccessmode()>aplRO)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}
	CaplInstance *lock=CheckMyLock(project,false);
	if(recursive)
	{
		CaplInstance *inst=0,*inst0=0;
		CaplAggr aggr,aggr_new;
		m_data->GetAttr(project,a_project_content,aggr);
		for(int i=0;i<aggr.GetSize();i++)
		{
			aggr.GetByIndex(i,inst);
			CheckIn(inst,true,make_new_version_active);
		}
		/*
		//Вариант, при котором завершается редактирование и работ, не включенных пока в основной план
		aplExtent ext_content,ext_content_new;
		GetAllSubProject(project,ext_content,false,false);
		for(int i=0;i<ext_content.GetSize();i++)
		{
			CheckIn(ext_content[i],true,make_new_version_active);
		}
		*/
		if(lock)
		{
			if(lock->GetAccessmode()<aplNO)
			{

				m_data->GetAttr(lock,a_project_adm_ver_content,aggr_new);
				for(int i=0;i<aggr_new.GetSize();i++)
				{
					aggr_new.GetByIndex(i,inst);
					bool found=false;
					for(int j=0;j<aggr.GetSize();j++)
					{
						aggr.GetByIndex(j,inst0);
						if(inst0==inst)	{found=true;break;}
					}
					if(!found) CheckIn(inst,true,make_new_version_active);
				}
			}
		}
	}
	if(project->GetAccessmode()>=aplRO) return false;
	
	if(lock==0) return false;

	CString project_id=_T("");
	m_data->GetAttr(project,a_project_id,project_id);

	CaplInstance *base=0,*act=0;
	m_data->GetAttr(project,a_project_act_adm_version,act);
	m_data->GetAttr(lock,a_project_adm_ver_parent,base);
	
	// Проверка измененности
	
	if(base)
	{

		if(!IsProjectChanged(project,lock))
		{
			// 16.09.2023  Убрано по просьбе Созвездия
			/*if(m_bShowMessages)
			{
				if(IDNO==AfxMessageBox(APL_T("Данные проекта ")+project_id+APL_T(" не изменились !\n\n")+
					APL_T("Отменить редактирование ?"),MB_YESNO|MB_ICONQUESTION)) return false;
			}*/
				
			// Отмена редактирования
			UndoCheckOut(project);

			return true;
		}
	}
	if(!make_new_version_active)
	{
		if(!base && !act) make_new_version_active=true;//если активной и базовой нет, считаем, что проект новый
	}
	m_data->PutAttr(project,a_project_locker_adm_version,(CaplInstance*)0);

	CaplInstance *new_active_version=0;

	CString buf=_T("");
	COleDateTime dt=COleDateTime::GetCurrentTime();
	aplDate2String(dt,buf);
	m_data->PutAttr(lock,a_project_adm_ver_end,buf);

	//определение id версии
	GetLatestProjectVersion(project,buf);
	int max_id=_atoi(buf);
	max_id++;
	buf.Format(_T("%i"),max_id);
	m_data->PutAttr(lock,a_project_adm_ver_num,buf);
	if(make_new_version_active)
	{
		MakeProjectVersionActive(lock);
	}

	
	if(m_AutoSave && !recursive)
		m_data->NET_SaveChanges();
	return true;
}

bool CaplProjectManager::CheckInWithRequest(CaplInstance *project,bool &recursive)
{
	if(!project) return false;
	if(!m_data->IsKindOf(project,e_project)) return false;
	LoadProjectInfo(project);
	CaplInstance *lock=CheckMyLock(project,true);	
	if(!lock) return false;

	// По просьбе Созвездия - Возможность завершить редактирование проекта, к которому нет доступа, но, если взят тобой.
	CaplAdminModeProvider adminmode(&(m_api->m_data),-1, -1,DEF_SOURCE);

	if(project->GetAccessmode()>aplRW) // Осталось от варианта до админмода, но пусть остается
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}

	bool ask_recursive=false,do_recursive=false;
	CaplAggr aggr,aggr1;
	m_data->GetAttr(project,a_project_content,aggr);
	m_data->GetAttr(lock,a_project_adm_ver_content,aggr1);
	if(aggr.GetSize() || aggr1.GetSize()) ask_recursive=true;

	if(ask_recursive) 
	{
		if(recursive)
		{
			do_recursive=true;
		}
		else
		{
			/* 16.09.2023 Убрано по просьбе Созвездия
			if(IDYES==AfxMessageBox(APL_T("Проект содержит подпроекты\n\nЗавершить редактирование подпроектов?"),
				MB_YESNO|MB_ICONQUESTION)) do_recursive=true;
				*/
			do_recursive=true;
		}
	
	}
	bool make_active=false;
	if(IsProjectChanged(project,lock))
	{
		//if(IDYES==AfxMessageBox(APL_T("Сделать версию активной?"),MB_YESNO|MB_ICONQUESTION)) make_active=true;
		// 16.09.2023  Убран запрос по просьбе Созвездия
		make_active=true;
	}
	if(do_recursive) 
	{
		aplExtent ext;
		GetAllSubProject(project,ext,true,true);
		LoadProjectInfo(ext);
	}
	bool check_in_result=CheckIn(project,do_recursive,make_active);

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

bool CaplProjectManager::UndoCheckOut(CaplInstance *project,bool recursive)
{
	if(project==0) return false;
	if(!m_data->IsKindOf(project,e_project))return false;
	if(project->GetAccessmode()>aplRO) return false;
	if(!recursive) LoadProjectInfo(project);
	else
	{

	}
	CaplInstance *lock,*user;
	m_data->GetAttr(project,a_project_locker_adm_version,lock);
	int i;
	if(recursive)
	{
		CaplAggr aggr;
		CaplInstance *inst=0;
		m_data->GetAttr(project,a_project_content,aggr);
		for(i=0;i<aggr.GetSize();i++)
		{
			aggr.GetByIndex(i,inst);
			UndoCheckOut(inst,true);
		}
		if(lock)
		{
			if(lock->GetAccessmode()<aplNO)
			{
				m_data->GetAttr(lock,a_project_adm_ver_content,aggr);
				for(int i=0;i<aggr.GetSize();i++)
				{
					aggr.GetByIndex(i,inst);
					UndoCheckOut(inst,true);
				}
			}
		}

	}
	if(project->GetAccessmode()>aplRW) return false;
	if(!lock) return false;
	m_data->GetAttr(lock,a_project_adm_ver_author,user);
	CString project_id=_T("");
	m_data->GetAttr(project,a_project_id,project_id);
	if(user!=m_data->GetCurrUser())
	{
		if(project->GetAccessmode()>aplOWN) 
		{
			AfxMessageBox(APL_T("Проект ")+project_id+APL_T(" заблокирован другим пользователем !"),MB_OK|MB_ICONSTOP);
			return false;
		}
		if(IDNO==AfxMessageBox(APL_T("Проект ")+project_id+APL_T(" заблокирован другим пользователем!\n\nВсе равно отменить редактирование ?"),
			MB_YESNO|MB_ICONQUESTION)) return false;

	}
	//если это первая еще не утвержденная версия 
	CString l_ver;
	CaplInstance *latest_ver=GetLatestProjectVersion(project,l_ver);
	if(!latest_ver) 
	{
		CheckIn(project);

		return true;
	}
	//если за время редактирования были разорваны связи - нужно их восстановить
	aplExtent ext_sub_prj;
	m_data->GetAttr(project,a_project_content,ext_sub_prj);
	CaplInstance *parent;
	for(i=0;i<ext_sub_prj.GetSize();i++)
	{
		if(!ext_sub_prj[i]) continue;if(!ext_sub_prj[i]->GetType()) continue;
		m_data->GetAttr(ext_sub_prj[i],a_project_parent,parent);
		if(parent!=project) m_data->PutAttr(ext_sub_prj[i],a_project_parent,project);
	}


	m_data->PutAttr(project,a_project_locker_adm_version,(CaplInstance*)0);

	//удаление инстансов трудоемкости
	CaplInstance *labor=0;
	m_data->GetAttr(lock,a_project_adm_ver_labor_useness,labor);
	if(labor) m_data->DeleteInstance(labor);
	m_data->GetAttr(lock,a_project_adm_ver_labor_of_item,labor);
	if(labor) m_data->DeleteInstance(labor);

	m_data->DeleteInstance(lock);

	if(m_AutoSave && !recursive)
		m_data->NET_SaveChanges();
	return true;
}

bool CaplProjectManager::UndoCheckOutWithRequest(CaplInstance *project,bool &recursive)
{
	if(!project) return false;
	if(project->GetAccessmode()>aplRW)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}
	if(!m_data->IsKindOf(project,e_project)) return false;
	LoadProjectInfo(project);
	
	CaplInstance *lock=0;
	if(project->GetAccessmode()>aplOWN)
	{
		lock=CheckMyLock(project,true);	
		if(!lock) return false;
	}
	else
	{
		m_data->GetAttr(project,a_project_locker_adm_version,lock);
		if(!lock)
		{
			AfxMessageBox(APL_T("Бизнес-процесс не заблокирован!"));
			return false;
		}
	}

	bool ask_recursive=false,do_recursive=false;
	CaplAggr aggr,aggr1;
	m_data->GetAttr(project,a_project_content,aggr);
	m_data->GetAttr(lock,a_project_adm_ver_content,aggr1);
	if(aggr.GetSize() || aggr1.GetSize()) ask_recursive=true;

	if(ask_recursive) 
	{
		if(recursive)
		{
			do_recursive=true;
		}
		else
		{
			/* 16.09.2023 Убрано по просьбе Созвездия
			if(IDYES==AfxMessageBox(APL_T("Проект содержит подпроекты\n\nОтменить редактирование подпроектов?"),
				MB_YESNO|MB_ICONQUESTION)) do_recursive=true;
				*/
			do_recursive=true;
		}
	
	}
	if(do_recursive) 
	{
		aplExtent ext;
		GetAllSubProject(project,ext,true,true);
		LoadProjectInfo(ext);
	}
	bool undo_check_out_result=UndoCheckOut(project,do_recursive);
	if(undo_check_out_result) 
	{
		CaplInstance *parent=0;
		m_data->GetAttr(project,a_project_parent,parent);
		if(parent) RecalcProjectLabor(parent,true,false);
	}
	if(m_AutoSave) m_data->NET_SaveChanges();
//	if(m_status_dlg_created) m_status_dlg.ShowWindow(FALSE);
	return undo_check_out_result;
}

bool CaplProjectManager::CheckMyLockAndCheckOut(CaplInstance *project,bool recursive)
{
	if(!project) return false;
	if(project->GetAccessmode()>aplRO) return false;

	CaplInstance *lock=0,*user=0,*project_ver_project=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))
	{
		m_data->GetAttr(project,a_project_adm_ver_project,project_ver_project);
		if(project_ver_project) m_data->GetAttr(project_ver_project,a_project_locker_adm_version,lock);
	}
		
	if(lock==0)
	{
		CString buf,id;
		m_data->GetAttr(project,a_project_id,id);
		buf=APL_T("Проект '")+id;
		buf+=APL_T(" ' не заблокирован !\n\nЗаблокировать ?");
		if(IDNO==AfxMessageBox(buf,MB_YESNO|MB_ICONQUESTION))
			return false;
		if(!CheckOutWithRequest(project,recursive)) 
			return false;
	}
	else
	{
		m_data->GetAttr(lock,a_project_adm_ver_author,user);
		if(user!=m_data->GetCurrUser())
		{
			AfxMessageBox(APL_T("Проект заблокирован другим пользователем !"),MB_OK|MB_ICONSTOP);
			return false;
		}
	}
	return true;
}



bool isAggrChanged(CaplAggr &aggr,CaplAggr &aggr1)
{
	if(aggr.GetSize()!=aggr1.GetSize()) return true;
	CaplInstance *inst=0,*inst1=0;
	for(int i=0;i<aggr.GetSize();i++)
	{
		aggr.GetByIndex(i,inst);
		aggr1.GetByIndex(i,inst1);
		if(inst!=inst1) return true;
	}
	return false;
}

bool isExtentChanged(aplExtent &ext,aplExtent &ext1)
{
	if(ext.GetSize()!=ext1.GetSize()) return true;
	for(int i=0;i<ext.GetSize();i++)
	{
		if(ext[i]!=ext1[i]) return true;
	}
	return false;
}

bool CaplProjectManager::IsProjectChanged(CaplInstance *project,CaplInstance *project_ver)
{
	if(!project) return true;
	if(!project_ver) return true;
	if(project->GetAccessmode()>aplRO) return true;
	if(project_ver->GetAccessmode()>aplRO) return true;

	CaplInstance *project_ver_project=0;
	m_data->GetAttr(project_ver,a_project_adm_ver_project,project_ver_project);
	if(project_ver_project!=project) return true;

	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 *customer=0,*kurator,*type=0,*labor=0,*unit=0,*prd_amount_unit=0;
	CaplInstance *labor_of_item=0,*unit_of_item=0;
	double value=0,value_of_item=0,prd_amount=0;
	CaplAggr aggr_content,aggr_executors;
	bool calc_by_amount;
	double planned_duration,planned_duration0;
	int planed_set_mask,planed_set_mask0;
	CString control_type, control_type0;

	CString id0=_T(""),name0=_T(""),number0=_T(""),descr0=_T(""),date_time0=_T(""),date_planned_begin0=_T(""),date_planned_end0=_T(""),date_planned_end20=_T("");
	CaplInstance *customer0=0,*kurator0=0,*type0=0,*labor0=0,*labor_of_item0=0,*unit0=0,*unit_of_item0=0,*prd_amount_unit0=0;
	double value0=0,value_of_item0=0,prd_amount0=0;
	CaplAggr aggr_content0,aggr_executors0;
	CaplAggr aggr_co_executors,aggr_co_executors0,aggr_co_customers,aggr_co_customers0,aggr_prev_sequences,aggr_prev_sequences0;
	bool calc_by_amount0;

	m_data->GetAttr(project,a_project_id,id);	
	m_data->GetAttr(project,a_project_name,name);
	m_data->GetAttr(project,a_project_number,number);
	m_data->GetAttr(project,a_project_descr,descr);
	m_data->GetAttr(project,a_project_customer,customer);
	m_data->GetAttr(project,a_project_type,type);
	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_control_type,control_type);
	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,planed_set_mask);
	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_ver,a_project_adm_ver_id,id0);	
	m_data->GetAttr(project_ver,a_project_adm_ver_name,name0);
	m_data->GetAttr(project_ver,a_project_adm_ver_number,number0);
	m_data->GetAttr(project_ver,a_project_adm_ver_descr,descr0);
	m_data->GetAttr(project_ver,a_project_adm_ver_customer,customer0);
	m_data->GetAttr(project_ver,a_project_adm_ver_type,type0);
	m_data->GetAttr(project_ver,a_project_adm_ver_labor_useness,labor0);
	if(labor0)
	{
		m_data->GetAttr(labor0,a_labor_unit,unit0);
		m_data->GetAttr(labor0,a_labor_value,value0);
	}
	m_data->GetAttr(project_ver,a_project_adm_ver_labor_of_item,labor_of_item0);
	if(labor_of_item0)
	{
		m_data->GetAttr(labor_of_item0,a_labor_unit,unit_of_item0);
		m_data->GetAttr(labor_of_item0,a_labor_value,value_of_item0);
	}
	m_data->GetAttr(project_ver,a_project_adm_ver_kurator,kurator0);
	m_data->GetAttr(project_ver,a_project_adm_ver_executors,aggr_executors0);
	m_data->GetAttr(project_ver,a_project_adm_ver_co_executors,aggr_co_executors0);
	m_data->GetAttr(project_ver,a_project_adm_ver_co_customers,aggr_co_customers0);
	m_data->GetAttr(project_ver,a_project_adm_ver_prev_sequences,aggr_prev_sequences0);
	m_data->GetAttr(project_ver,a_project_adm_ver_control_type,control_type0);
	m_data->GetAttr(project_ver,a_project_adm_ver_date_planned_begin,date_planned_begin0);
	m_data->GetAttr(project_ver,a_project_adm_ver_date_planned_end,date_planned_end0);
	m_data->GetAttr(project_ver,a_project_adm_ver_date_planned_end2,date_planned_end20);
	m_data->GetAttr(project_ver,a_project_adm_ver_date_planned_duration,planned_duration0);
	m_data->GetAttr(project_ver,a_project_adm_ver_date_set_mask,planed_set_mask0);
	m_data->GetAttr(project_ver,a_project_adm_ver_content,aggr_content0);
	m_data->GetAttr(project_ver,a_project_adm_ver_prd_amount_planned,prd_amount0);
	m_data->GetAttr(project_ver,a_project_adm_ver_prd_amount_unit,prd_amount_unit0);
	m_data->GetAttr(project_ver,a_project_adm_ver_calc_by_amount,calc_by_amount0);


	if(id==id0 && name==name0 && number==number0 && descr==descr0 && kurator==kurator0 && customer==customer0 &&
		date_planned_begin==date_planned_begin0 && date_planned_end==date_planned_end0 && date_planned_end2==date_planned_end20 &&
		planned_duration==planned_duration0 && planed_set_mask==planed_set_mask0 &&
		type==type0 && unit==unit0 && value==value0 &&
		unit_of_item==unit_of_item0 && value_of_item==value_of_item0 && 
		prd_amount==prd_amount0 && prd_amount_unit==prd_amount_unit0 && calc_by_amount==calc_by_amount0 &&
		(!isAggrChanged(aggr_executors,aggr_executors0)) && (!isAggrChanged(aggr_content,aggr_content0))&& 
		(!isAggrChanged(aggr_co_executors,aggr_co_executors0)) && (!isAggrChanged(aggr_co_customers,aggr_co_customers0))&&
		(!isAggrChanged(aggr_prev_sequences,aggr_prev_sequences0)) &&

		(control_type==control_type0))
		return false;

	return true;
}

bool CaplProjectManager::ChangeProjectState(CaplInstance *project,LPCTSTR new_state,bool recursive,COleDateTimeSpan &span)
{
	if(project==0) return false;
	if(project->GetAccessmode()>aplRO)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}
	if(recursive)
	{
		aplExtent ext;
		GetAllSubProject(project,ext,false,true);
		for(int i=0;i<ext.GetSize();i++)
		{
			ChangeProjectState(ext[i],new_state,recursive,span);
		}
		if(project->GetAccessmode()>aplRW) return false;
		CString buf;
		COleDateTime dt=COleDateTime::GetCurrentTime();
		aplDate2String(dt,buf);
		m_api->m_data.PutAttr(project,a_project_state,new_state);
		m_api->m_data.PutAttr(project,a_project_date_planned_end2,buf);
		if(span.GetDays() || span.GetHours() || span.GetMinutes())
		{
			COleDateTime new_dt;
			m_api->m_data.GetAttr(project,a_project_date_planned_end,buf);
			if(!buf.IsEmpty())
			{
				aplString2Date(buf,new_dt);
				if (new_dt.GetStatus() == COleDateTime::valid)
				{
					new_dt+=span;
					aplDate2String(new_dt,buf);
					m_api->m_data.PutAttr(project,a_project_date_planned_end,buf);
				}
			}
		}
	}
		

	return true;
}





bool CaplProjectManager::RecalcProjectLabor(CaplInstance *project,bool recursive,bool load_prj_info)
{
	if(!project) return false;

	CaplAdminModeProvider adminmode;
	if(!(m_api->m_data.IsAdmin() || m_api->m_data.GetAdminMode() ) )
	{
		adminmode.SetData(&(m_api->m_data));
		adminmode.StartAdminMode(-1, -1,DEF_SOURCE);
	}

	if(project->GetAccessmode()>aplRW)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}
	if(load_prj_info) LoadProjectInfo(project);
	CaplInstance *labor,*actual_labor,*labor_of_item;
	CaplInstance *lock=CheckMyLock(project,false);

	aplExtent ext_sub_prj;
	double old_labor_value_planned=0,old_actual_labor_value=0,old_persentage=0,old_labor_of_item_value=0;
	double old_prd_amount_planned=0,old_prd_amount_actual=0;
	CaplInstance *old_unit_planned=0,*old_unit_actual=0,*old_labor_of_item_unit=0;

	if(lock)
	{
		m_data->GetAttr(lock,a_project_adm_ver_content,ext_sub_prj);
		m_data->GetAttr(lock,a_project_adm_ver_labor_useness,labor);
		m_data->GetAttr(lock,a_project_adm_ver_labor_of_item,labor_of_item);
		// m_data->GetAttr(lock,a_project_adm_ver_persentage,old_persentage);
		m_data->GetAttr(lock,a_project_adm_ver_prd_amount_planned,old_prd_amount_planned);
	}
	else
	{
		m_data->GetAttr(project,a_project_content,ext_sub_prj);
		m_data->GetAttr(project,a_project_labor_useness,labor);
		m_data->GetAttr(project,a_project_labor_of_item,labor_of_item);
		// m_data->GetAttr(project,a_project_persentage,old_persentage);
		m_data->GetAttr(project,a_project_prd_amount_planned,old_prd_amount_planned);
	}

	m_data->GetAttr(project,a_project_persentage,old_persentage);
	m_data->GetAttr(project,a_project_labor_useness_actual,actual_labor);
	m_data->GetAttr(project,a_project_prd_amount_actual,old_prd_amount_actual);
	if(!labor) 
	{
		labor=m_data->CreateInstance(e_labor_useness_value);
		if(!labor) return false;
		if(lock) m_data->PutAttr(lock,a_project_adm_ver_labor_useness,labor);
		else m_data->PutAttr(project,a_project_labor_useness,labor);
	}
	if(!actual_labor) 
	{
		actual_labor=m_data->CreateInstance(e_labor_useness_value);
		if(!actual_labor) return false;
		m_data->PutAttr(project,a_project_labor_useness_actual,actual_labor);
	}
	if(!labor_of_item)
	{
		labor_of_item=m_data->CreateInstance(e_labor_useness_value);
		if(!labor_of_item) return false;
		if(lock) m_data->PutAttr(lock,a_project_adm_ver_labor_of_item,labor_of_item);
		else m_data->PutAttr(project,a_project_labor_of_item,labor_of_item);
	}
	m_data->GetAttr(labor,a_labor_value,old_labor_value_planned);
	m_data->GetAttr(labor,a_labor_unit,old_unit_planned);
	m_data->GetAttr(actual_labor,a_labor_value,old_actual_labor_value);
	m_data->GetAttr(actual_labor,a_labor_unit,old_unit_actual);
	m_data->GetAttr(labor_of_item,a_labor_value,old_labor_of_item_value);
	m_data->GetAttr(labor_of_item,a_labor_unit,old_labor_of_item_unit);

	double labor_value=0,actual_labor_value=0,persentage=0,prd_amount_planned=0,prd_amount_actual=0;
	CaplInstance *sub_labor_unit=0,*sub_labor_unit_actual=0;
	for(int i=0;i<ext_sub_prj.GetSize();i++)
	{
		if(!ext_sub_prj[i]) continue;
		if(ext_sub_prj[i]->GetAccessmode()>aplRO) continue;
		double sub_labor_value=0,sub_labor_value_actual=0,sub_prd_amount_planned=0,sub_prd_amount_actual=0;
		CaplInstance *sub_labor=0,*sub_labor_actual=0,*sub_lock=0;
		sub_lock=CheckMyLock(ext_sub_prj[i],false);
		if(sub_lock) 
		{
			m_data->GetAttr(sub_lock,a_project_adm_ver_labor_useness,sub_labor);
			m_data->GetAttr(sub_lock,a_project_adm_ver_prd_amount_planned,sub_prd_amount_planned);
		}
		else
		{
			m_data->GetAttr(ext_sub_prj[i],a_project_labor_useness,sub_labor);
			m_data->GetAttr(ext_sub_prj[i],a_project_prd_amount_planned,sub_prd_amount_planned);
		}
		prd_amount_planned+=sub_prd_amount_planned;
		if(sub_labor) 
		{
			m_data->GetAttr(sub_labor,a_labor_value,sub_labor_value);
			m_data->GetAttr(sub_labor,a_labor_unit,sub_labor_unit);
		}
		labor_value+=sub_labor_value;
		m_data->GetAttr(ext_sub_prj[i],a_project_labor_useness_actual,sub_labor_actual);
		m_data->GetAttr(ext_sub_prj[i],a_project_prd_amount_actual,sub_prd_amount_actual);
		prd_amount_actual+=sub_prd_amount_actual;
		if(sub_labor_actual) 
		{
			m_data->GetAttr(sub_labor_actual,a_labor_value,sub_labor_value_actual);
			m_data->GetAttr(sub_labor_actual,a_labor_unit,sub_labor_unit_actual);
		}
		actual_labor_value+=sub_labor_value_actual;
	}
	bool just_checked_out=false;
	bool plans_changed=false;
	double labor_of_item_value=0;
	if(prd_amount_planned) labor_of_item_value=labor_value/prd_amount_planned;
	if(old_labor_value_planned!=labor_value || prd_amount_planned!=old_prd_amount_planned) 
	{
		if(!lock) 
		{
			CheckOut(project);
			just_checked_out=true;
		}
		lock=CheckMyLock(project,false);
		if(!lock)
		{
			AfxMessageBox(APL_T("Ошибка при расчете трудоемкости проектов-родителей (не удалось заблокировать проект)!"));
			return false;
		}
		m_data->GetAttr(lock,a_project_adm_ver_labor_useness,labor);
		m_data->GetAttr(lock,a_project_adm_ver_labor_of_item,labor_of_item);
		if(old_labor_value_planned!=labor_value) m_data->PutAttr(labor,a_labor_value,labor_value);
		if(old_unit_planned!=sub_labor_unit) m_data->PutAttr(labor,a_labor_unit,sub_labor_unit);
		if(old_prd_amount_planned!=prd_amount_planned) m_data->PutAttr(lock,a_project_adm_ver_prd_amount_planned,prd_amount_planned);
		if(old_labor_of_item_value!=labor_of_item_value) m_data->PutAttr(labor_of_item,a_labor_value,labor_of_item_value);
		if(old_labor_of_item_unit!=sub_labor_unit) m_data->PutAttr(labor_of_item,a_labor_unit,sub_labor_unit);
		plans_changed=true;
	}
	if(old_actual_labor_value!=actual_labor_value) m_data->PutAttr(actual_labor,a_labor_value,actual_labor_value);
	if(old_unit_actual!=sub_labor_unit_actual) m_data->PutAttr(actual_labor,a_labor_unit,sub_labor_unit_actual);
	if(old_prd_amount_actual!=prd_amount_actual) m_data->PutAttr(project,a_project_prd_amount_actual,prd_amount_actual);
	
	if(labor_value) persentage=(actual_labor_value/labor_value)*100;
	
	/* 20.03.2023  Убрано использование a_project_adm_ver_persentage  чтобы не было путаницы
	if(plans_changed)//внесли изменения в плановую трудоемкость, пересчитаем % выполнения и запишем в новую версию
	{
		if(old_persentage!=persentage) m_data->PutAttr(lock,a_project_adm_ver_persentage,persentage);
	}
	else 
	{
		if(old_persentage!=persentage) 
		{
			if(lock) m_data->PutAttr(lock,a_project_adm_ver_persentage,persentage);//если есть локер - то в него!
			else m_data->PutAttr(project,a_project_persentage,persentage);//или запишем прямо в свойства проекта
		}
	}*/

	if(old_persentage!=persentage) m_data->PutAttr(project,a_project_persentage,persentage);


	if(just_checked_out) 
	{
		if(plans_changed)
		{
			//CheckIn(project);//сразу завершим только что начатое редактирование
		}
		else
		{
			UndoCheckOut(project);
		}
	}
	if(recursive)
	{
		CaplInstance *parent=0;
		m_data->GetAttr(project,a_project_parent,parent);
		if(parent) RecalcProjectLabor(parent);
		else if(m_AutoSave) m_data->NET_SaveChanges();
	}
	else if(m_AutoSave) 
	{
		m_data->NET_SaveChanges();
	}
	return true;
}

bool CaplProjectManager::RecalcParentDates(CaplInstance *project, bool recursive,bool load_prj_info)
{
	if(!project) return false;

	CaplAdminModeProvider adminmode;
	if(!(m_api->m_data.IsAdmin() || m_api->m_data.GetAdminMode() ) )
	{
		adminmode.SetData(&(m_api->m_data));
		adminmode.StartAdminMode(-1, -1,DEF_SOURCE);
	}

	if(project->GetAccessmode()>aplRW)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}
	if(load_prj_info) LoadProjectInfo(project);
	CaplInstance *parent=0;
	m_data->GetAttr(project,a_project_parent,parent);
	if(!parent) return false;
	if(parent->GetAccessmode()>aplRW)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}

	CString parent_control_type;	
	CaplInstance *parent_lock=CheckMyLock(parent,false);
	if(parent_lock) m_data->GetAttr(parent_lock,a_project_adm_ver_control_type,parent_control_type);
	else m_data->GetAttr(parent,a_project_control_type,parent_control_type);
	//m_data->GetAttr(parent,a_project_control_type,parent_control_type);
	if(parent_control_type!=APL_NO_T("Определять по входящим")) return false;


	CString old_planned_begin_date,old_planned_end_date;
	CString old_act_begin_date,old_act_end_date;

	if(parent_lock)
	{
		m_data->GetAttr(parent_lock,a_project_adm_ver_date_planned_begin,old_planned_begin_date);
		m_data->GetAttr(parent_lock,a_project_adm_ver_date_planned_end,old_planned_end_date);
	}
	else
	{
		m_data->GetAttr(parent,a_project_date_planned_begin,old_planned_begin_date);
		m_data->GetAttr(parent,a_project_date_planned_end,old_planned_end_date);
	}
	m_data->GetAttr(parent,a_project_date_actual_begin,old_act_begin_date);
	m_data->GetAttr(parent,a_project_date_actual_end,old_act_end_date);

	int i;
	CString begin_date,end_date;
	CString begin_date_min, end_date_max;
	CString act_date_min, act_date_max;

	aplExtent ext_sub_prj;
	GetAllSubProject(parent,ext_sub_prj);
	ext_sub_prj.Add(project); // для вновь создаваемых, но еще не добавленных
	for(i=0;i<ext_sub_prj.GetSize();i++)
	{
		CaplInstance *subprj=ext_sub_prj[i];
		CaplInstance *lock=CheckMyLock(subprj,false);
		if(lock)
		{
			m_data->GetAttr(lock,a_project_adm_ver_date_planned_begin,begin_date);
			m_data->GetAttr(lock,a_project_adm_ver_date_planned_end,end_date);
		}
		else
		{
			m_data->GetAttr(subprj,a_project_date_planned_begin,begin_date);
			m_data->GetAttr(subprj,a_project_date_planned_end,end_date);
		}

		if(begin_date!=_T("") && (begin_date_min==_T("") || begin_date<begin_date_min)) begin_date_min=begin_date;
		if(end_date!=_T("")   && (end_date_max==_T("")   || end_date>end_date_max)) end_date_max=end_date;

		m_data->GetAttr(subprj,a_project_date_actual_begin,begin_date);
		m_data->GetAttr(subprj,a_project_date_actual_end,end_date);
		if(begin_date!=_T("") && (act_date_min==_T("") || begin_date<act_date_min)) act_date_min=begin_date;
		if(end_date!=_T("")   && (act_date_max==_T("")   || end_date>act_date_max)) act_date_max=end_date;

	}

	if(act_date_min!=old_act_begin_date || act_date_max!=old_act_end_date)
	{
		m_data->PutAttr(parent,a_project_date_actual_begin,old_act_begin_date);
		m_data->PutAttr(parent,a_project_date_actual_end,old_act_end_date);
	}

	if(old_planned_begin_date==begin_date_min && old_planned_end_date==end_date_max	) return true;
	bool bFalse=false;
	if(0==parent_lock)
	{
		if(!CheckOutWithRequest(parent,bFalse))
		{
			AfxMessageBox(APL_T("Ошибка при пересчете дат проекта-родителя (не удалось заблокировать проект)!"));
			return false;
		}
		parent_lock=CheckMyLock(parent,false);
		if(0==parent_lock)return false; // такого не должно быть
	}

		
	m_data->PutAttr(parent_lock,a_project_adm_ver_date_planned_begin,begin_date_min);
	m_data->PutAttr(parent_lock,a_project_adm_ver_date_planned_end,end_date_max);


	m_data->PutAttr(parent,a_project_date_actual_begin,old_act_begin_date);
	m_data->PutAttr(parent,a_project_date_actual_end,old_act_end_date);

	
	/*CaplInstance *lock=CheckMyLock(project,false);
	CString old_planned_begin_date=_T(""),old_planned_end_date=_T("");
	CString old_actual_begin_date=_T(""),old_actual_end_date=_T("");
	CString new_planned_begin_date=_T(""),new_planned_end_date=_T("");
	CString new_actual_begin_date=_T(""),new_actual_end_date=_T("");
	if(lock)
	{
		m_data->GetAttr(lock,a_project_adm_ver_date_planned_begin,new_planned_begin_date);
		m_data->GetAttr(lock,a_project_adm_ver_date_planned_end,new_planned_end_date);
	}
	else
	{
		m_data->GetAttr(project,a_project_date_planned_begin,new_planned_begin_date);
		m_data->GetAttr(project,a_project_date_planned_end,new_planned_end_date);
	}
	m_data->GetAttr(project,a_project_date_actual_begin,new_actual_begin_date);
	m_data->GetAttr(project,a_project_date_actual_end,new_actual_end_date);

	CaplInstance *parent_lock=CheckMyLock(parent,false);
	if(parent_lock)
	{
		m_data->GetAttr(parent_lock,a_project_adm_ver_date_planned_begin,old_planned_begin_date);
		m_data->GetAttr(parent_lock,a_project_adm_ver_date_planned_end,old_planned_end_date);
	}
	else
	{
		m_data->GetAttr(parent,a_project_date_planned_begin,old_planned_begin_date);
		m_data->GetAttr(parent,a_project_date_planned_end,old_planned_end_date);
	}
	m_data->GetAttr(parent,a_project_date_actual_begin,old_actual_begin_date);
	m_data->GetAttr(parent,a_project_date_actual_end,old_actual_end_date);

	bool need_check_out=false;
	bool smth_changed=false;
	if((new_planned_begin_date!=_T("") && new_planned_begin_date<old_planned_begin_date) || (old_planned_begin_date==_T("") && new_planned_begin_date!=_T("")))
	{
		smth_changed=true;
		need_check_out=true;
	}
	if(new_planned_end_date>old_planned_end_date)
	{
		smth_changed=true;
		need_check_out=true;
	}
	if((new_actual_begin_date!=_T("") && new_actual_begin_date<old_actual_begin_date) || (old_actual_begin_date==_T("") && new_actual_begin_date!=_T("")))
		smth_changed=true;
	if(new_actual_end_date>old_actual_end_date)
		smth_changed=true;
	if(!smth_changed) return false;
	if(!parent_lock && need_check_out) 
	{
		CheckOut(parent);
		parent_lock=CheckMyLock(project,false);
		if(!parent_lock)
		{
			AfxMessageBox(APL_T("Ошибка при пересчете дат проекта-родителя (не удалось заблокировать проект)!"));
			return false;
		}
	}
	if((new_planned_begin_date!=_T("") && new_planned_begin_date<old_planned_begin_date) || (old_planned_begin_date==_T("") && new_planned_begin_date!=_T("")))
	{
		m_data->PutAttr(parent_lock,a_project_adm_ver_date_planned_begin,new_planned_begin_date);
	}
	if(new_planned_end_date>old_planned_end_date)
	{
		m_data->PutAttr(parent_lock,a_project_adm_ver_date_planned_end,new_planned_end_date);
	}
	if((new_actual_begin_date!=_T("") && new_actual_begin_date<old_actual_begin_date) || (old_actual_begin_date==_T("") && new_actual_begin_date!=_T("")))
	{
		m_data->PutAttr(parent,a_project_date_actual_begin,new_actual_begin_date);
	}
	if(new_actual_end_date>old_actual_end_date)
	{
		m_data->PutAttr(parent,a_project_date_actual_end,new_actual_end_date);
	}*/

	if(recursive) RecalcParentDates(parent, true, load_prj_info);
	
	return true;
}

bool CaplProjectManager::IsProjectHaveChildren(CaplInstance *project, bool include_associated)
{
	if(!project) return false;
	if(project->GetAccessmode()>aplRW)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}
	aplExtent ext_sub_projects;
	GetAllSubProject(project,ext_sub_projects,false,include_associated,false);
	if(ext_sub_projects.GetSize()) return true;
	return false;
}

bool CaplProjectManager::UpdateProjectState(CaplInstance *project)
{
	if(!project) return false;
	if(project->GetAccessmode()>aplRW)
	{
		AfxMessageBox(S::NoAccessRight,MB_OK|MB_ICONSTOP);
		return false;
	}
	LoadProjectInfo(project);
	CString state;
	m_data->GetAttr(project,a_project_state,state);
	if(state==APL_T("завершен")) return true;

	CaplInstance *lock=CheckMyLock(project,false);
	aplExtent ext_sub_prj;
	if(lock) m_data->GetAttr(lock,a_project_adm_ver_content,ext_sub_prj);
	else m_data->GetAttr(project,a_project_content,ext_sub_prj);

	bool all_sub_projects_complete=true;
	for(int i=0;i<ext_sub_prj.GetSize();i++)
	{
		if(!ext_sub_prj[i]) continue;
		if(ext_sub_prj[i]->GetAccessmode()>aplRO) {all_sub_projects_complete=false;break;}
		m_data->GetAttr(ext_sub_prj[i],a_project_state,state);
		if(state!=APL_T("завершен")) {all_sub_projects_complete=false;break;}
	}
	if(all_sub_projects_complete)
	{
		m_data->PutAttr(project,a_project_state,APL_T("завершен"));
		CaplInstance *parent=0;
		m_data->GetAttr(project,a_project_parent,parent);
		if(parent) 
		{
			UpdateProjectState(parent);
		}
		else if(m_AutoSave) 
		{
			m_data->NET_SaveChanges();
		}
	}
	return true;
}


CaplInstance* CaplProjectManager::CreateTransaction(CaplInstance* Project, LPCTSTR lpszId, LPCTSTR lpszName, LPCTSTR lpszDescr, COleDateTime Date, LPCTSTR lpszType, double summ)
{
	if(m_api==NULL) return NULL;
	if(!m_api->m_data.IsDictLoad()) return NULL;
	if(Project==NULL) return NULL;
	if(lpszId==NULL) return NULL;
	
	CString sDate;
	aplDate2String(Date, sDate);
	
	return CreateTransaction(Project, lpszId, lpszName, lpszDescr, sDate, lpszType, summ);
}

CaplInstance* CaplProjectManager::CreateTransaction(CaplInstance* Project, LPCTSTR lpszId, LPCTSTR lpszName, LPCTSTR lpszDescr, LPCTSTR lpszDate, LPCTSTR lpszType, double summ)
{
	if(m_api==NULL) return NULL;
	if(!m_api->m_data.IsDictLoad()) return NULL;
	if(Project==NULL) return NULL;

	if(m_role_to_edit_fact==_T(""))
	{
		if(Project->GetAccessmode()>aplRW) return NULL;
	}
	else
	{
		CString buf=lpszType;
		if(buf==APL_T("Факт"))
		{
			if(!m_has_role_edit_fact) return NULL;
		}
		else if(Project->GetAccessmode()>aplRW) return NULL;
	}

	if(m_api->m_data.IsKindOf(Project,e_project_adm_ver))
	{
		m_api->m_data.GetAttr(Project, a_project_adm_ver_project, Project);
		if(Project==NULL) return NULL;
		if(Project->GetAccessmode()>aplRW) return NULL;
	}
	
	CString sId(lpszId), sName(lpszName), sDescr(lpszDescr), sDate(lpszDate), sType(lpszType);
	/*if(sId.IsEmpty())
	{
		if(m_api->m_ModeInteractive) AfxMessageBox(APL_T("Необходимо указать ID платежа!"));
		return NULL;
	}*/

	//проверка уникальности
	//Еслинадо вставим

	aplExtent ext;
	CaplInstance *nInst = m_api->m_data.CreateInstance(e_money_transaction);
	m_api->m_data.PutAttr(nInst, a_money_transaction_id, sId);
	m_api->m_data.PutAttr(nInst, a_money_transaction_name, sName);
	m_api->m_data.PutAttr(nInst, a_money_transaction_descr, sDescr);
	m_api->m_data.PutAttr(nInst, a_money_transaction_type, sType);
	m_api->m_data.PutAttr(nInst, a_money_transaction_date, sDate);
	m_api->m_data.PutAttr(nInst, a_money_transaction_summ, summ);

	m_api->m_data.GetAttr(Project, a_project_transactions, ext);
	ext.Add(nInst);

	CaplAdminModeProvider adminmode;

	if(Project->GetAccessmode()>aplRW)
	{
		adminmode.SetData(&(m_api->m_data));
		adminmode.StartAdminMode(-1, -1,DEF_SOURCE);
	}

	m_api->m_data.PutAttr(Project, a_project_transactions, ext);
	
	adminmode.ExitAdminMode();
	if(m_AutoSave) m_api->SaveChanges();
	
	return nInst;
}

bool CaplProjectManager::LoadTransactionsInfo(CaplInstance *inst)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(!m_api->m_data.IsConnected()) return true;
	if(inst==NULL) return false;

	aplExtent ext;
	ext.Add(inst);
	return LoadTransactionsInfo(ext);
}

bool CaplProjectManager::LoadTransactionsInfo(aplExtent &ext)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(!m_api->m_data.IsConnected()) return true;

	bool bLoadData = false;
	int i;
	CaplLoadData ld(&m_api->m_data, DEF_SOURCE);
	for(i=0; i<ext.GetSize(); i++)
	{
		if(ext[i]==NULL) continue;
		if(ext[i]->GetId()==0) continue;
		if(ext[i]->GetAccessmode()>aplRO) continue;
		if(ext[i]->GetType()==NULL) continue;

		ld.AddQuery(0, ext[i], true);
		bLoadData = true;
	}

	if(bLoadData)
		ld.LoadEx();

	return true;
}

bool CaplProjectManager::DeleteTransaction(CaplInstance* Project, CaplInstance* inst)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;

	if(Project==NULL) return false;
	if(inst->GetAccessmode()>aplRO) {return false;}
	if(inst==NULL) return false;

	if(m_role_to_edit_fact==_T(""))
	{
		if(Project->GetAccessmode()>aplRW) return false;
	}
	else
	{
		CString buf;
		m_api->m_data.GetAttr(inst, a_money_transaction_type, buf);
		if(buf==APL_T("Факт"))
		{
			if(!m_has_role_edit_fact) return false;
		}
		else if(Project->GetAccessmode()>aplRW) return false;
	}

	if(inst->GetAccessmode()>aplOWN) {return false;}

	aplExtent ext;
	m_api->m_data.GetAttr(Project, a_project_transactions, ext);
	ext.Remove(ext.Find(inst));

	CaplAdminModeProvider adminmode;
	if(Project->GetAccessmode()>aplRW)
	{ 
		adminmode.SetData(&(m_api->m_data));
		adminmode.StartAdminMode(-1, -1,DEF_SOURCE);
	}

	m_api->m_data.PutAttr(Project, a_project_transactions, ext);

	m_api->m_data.DeleteInstance(inst);

	if(m_AutoSave) m_api->SaveChanges();

	adminmode.ExitAdminMode();

	return true;
}

bool CaplProjectManager::SelectTransactionFilter(STransactionFilter &Filter)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;

	CSelectTransactionFilterDlg dlg;

	dlg.m_sDateBegin = Filter.sDateMin;
	dlg.m_sDateEnd = Filter.sDateMax;
	
	if(Filter.bShowFact) dlg.m_bFact = TRUE; else dlg.m_bFact = FALSE;
	if(Filter.bShowFHelp) dlg.m_bFHelp = TRUE; else dlg.m_bFHelp = FALSE;
	if(Filter.bShowPlan) dlg.m_bPlan = TRUE; else dlg.m_bPlan = FALSE;

	if(dlg.DoModal()==IDOK)
	{
		Filter.bShowFact = (dlg.m_bFact==TRUE);
		Filter.bShowPlan = (dlg.m_bPlan==TRUE);
		Filter.bShowFHelp = (dlg.m_bFHelp==TRUE);

		Filter.sDateMin = dlg.m_sDateBegin;
		Filter.sDateMax = dlg.m_sDateEnd;

		return true;
	}
	else return false;
}

bool CaplProjectManager::FilterTransactions(aplTransactionsArray &InTransactions, aplTransactionsArray &OutTransactions, STransactionFilter &Filter)
{
	OutTransactions.Clear();

	// Фильтруем массив транзакций

	for(int i=0; i<InTransactions.Size; i++)
	{
		CTransaction *trs=InTransactions[i];


		if((trs->m_sType.CompareNoCase(APL_PMTT_FACT)==0 && Filter.bShowFact) || 
			(trs->m_sType.CompareNoCase(APL_PMTT_PLAN)==0 && Filter.bShowPlan) ||
			(trs->m_sType.CompareNoCase(APL_PMTT_FHELP)==0 && Filter.bShowFHelp))
		{
			if(!Filter.sDateMax.IsEmpty() && trs->m_sDate>Filter.sDateMax) continue;
			if(!Filter.sDateMin.IsEmpty() && trs->m_sDate<Filter.sDateMin) continue;

			OutTransactions.Add(new CTransaction(trs));
		}
	}
	return true;
}

bool CaplProjectManager::ReportTransactions(CaplInstance* Project, STransactionFilter &Filter, bool bShowTable, bool bRecursive, aplTransactionsArray *pArray)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(Project==NULL) return false;

	if(bShowTable==false && pArray==NULL) return false; //неразумная трата ресурсов и не показываем и не возвращаем на обработку

	aplTransactionsArray	AllTransactionArr, FilteredTransactionsArr;
	int i, j;
	aplExtent items, ext, tmp;
	aplExtent transactions;
	items.Add(Project);
	GetAllSubProject(items, ext, bRecursive, true, true);

	LoadProjectInfo(ext);

	ext.Add(Project);
	for(i=0; i<ext.Size; i++)
	{
		m_api->m_data.GetAttr(ext[i], a_project_transactions, tmp);
		transactions.Append(tmp);
	}

	LoadTransactionsInfo(transactions);

	CString sType;
	CString sDate;

	// Формируем массив транзакций
	for(i=0; i<ext.Size; i++)
	{
		m_api->m_data.GetAttr(ext[i], a_project_transactions, tmp);
		for(j=0; j<tmp.Size; j++)
		{
			AllTransactionArr.Add(new CTransaction(this, tmp[j], ext[i]));
		}
	}

	// Фильтруем массив транзакций

	if(pArray)
		FilterTransactions(AllTransactionArr,*pArray,Filter);
	else
		FilterTransactions(AllTransactionArr,FilteredTransactionsArr,Filter);

	
	if(bShowTable)
	{
		CTransactionsReportList dlg;
		dlg.m_prj_mgr=this;
		dlg.m_AllTransactions=&AllTransactionArr;

		if(pArray)
			dlg.m_FilteredTransactions = pArray;
		else
			dlg.m_FilteredTransactions = &FilteredTransactionsArr;

		dlg.DoModal();
	}

	return true;
}

// Вычисляем прогнозируемую дату завершения
bool CaplProjectManager::GetWorkedProjectEndPrognoz(CaplInstance *prj, COleDateTime &date_end_prognoz)
{
	date_end_prognoz.SetStatus(COleDateTime::null);
	if(0==prj) return false;
	if(prj->GetType()==0) return false;
	if(prj->GetAccessmode()>aplRO)return false;

	CString fakt_start_date_s,fakt_end_date_s;
	m_api->m_data.GetAttr(prj,m_api->m_project_mgr->a_project_date_actual_end, fakt_end_date_s);
	if(fakt_end_date_s!=_T("")) return false;	
	m_api->m_data.GetAttr(prj,m_api->m_project_mgr->a_project_date_actual_begin, fakt_start_date_s);
	if(fakt_start_date_s==_T("")) return false;

	COleDateTime odt_start;
	aplString2Date(fakt_start_date_s,odt_start);

	double persentage;
	m_api->m_data.GetAttr(prj,m_api->m_project_mgr->a_project_persentage,persentage);
	COleDateTime odt_useness_actual;
	CString labor_useness_actual_date_s;
	m_api->m_data.GetAttr(prj,m_api->m_project_mgr->a_project_labor_useness_actual_date,labor_useness_actual_date_s);
	if(labor_useness_actual_date_s==_T("") || labor_useness_actual_date_s<fakt_start_date_s)
	{
		odt_useness_actual=COleDateTime::GetCurrentTime();
	}
	else aplString2Date(labor_useness_actual_date_s,odt_useness_actual);


	if(persentage > 0.01 &&(odt_useness_actual>odt_start))
	{
		// Учитываем скорость
		COleDateTimeSpan ds=odt_useness_actual-odt_start;
		double all_days=(ds.GetTotalDays()*100) / persentage;
		COleDateTimeSpan ds_all(all_days);
		date_end_prognoz=odt_start+ds_all;
	}
	else
	{
		// Просто плюсуем длительность
		double plan_duration;
		m_api->m_data.GetAttr(prj,m_api->m_project_mgr->a_project_date_planned_duration,plan_duration);

		COleDateTimeSpan ds_all(plan_duration-ODT_1SEC); // минус минута чтобы не поднимать паники
		if(0==plan_duration)
		{
			CString s_start_plan_date, s_end_planDate; 
			m_api->m_data.GetAttr(prj,m_api->m_project_mgr->a_project_date_planned_begin, s_start_plan_date);
			m_api->m_data.GetAttr(prj,m_api->m_project_mgr->a_project_date_planned_end, s_end_planDate);

			if(s_start_plan_date==_T("") || s_end_planDate==_T("")) return false;
			COleDateTime odt_start,odt_end;
			aplString2Date(s_start_plan_date,odt_start);
			aplString2Date(s_end_planDate,odt_end);
			ds_all=odt_end-odt_start;
		}
		date_end_prognoz=odt_start+ds_all;
	}
	return true;
}
//***********************************************
/*bool CaplProjectManager::GetProjectsEndPrognoz(aplExtent &ext_prj,apl_COleDateTime_array &prognoz_dates, aplExtent &ext_prev_prognoz)
{
	prognoz_dates.RemoveAll();
	prognoz_dates.SetSize(ext_prj.GetSize());
	ext_prj.Sort();

	ext_prev_prognoz.Clear();
	ext_prev_prognoz.SetSize(ext_prj.GetSize());


	// Готовим связи чтобы потом для всех не перебирать все
	CaplAggrMap prev_prj_aggr_map;
	aplExtent ext_rels;
	LoadProjectsSequenceRelations(ext_prj,ext_rels,true);

	int i;
	CaplInstance *prev, *next;
	for(i=0; i<ext_rels.GetSize(); i++)
	{
		CaplInstance *rel=ext_rels[i];
		m_api->m_data.GetAttr(rel,a_project_seq_next,next);
		if(0==next) continue;
		m_api->m_data.GetAttr(rel,a_project_seq_prev,prev);
		if(0==prev) continue;

		prev_prj_aggr_map.Add((long)next,prev);
	}

	for(i=0; i<ext_prj.GetSize(); i++) prognoz_dates[i].SetStatus(COleDateTime::null);

	//Статусы даты  valid - определено  null - не определено  

	COleDateTime odt;
	for(i=0; i<ext_prj.GetSize(); i++)
	{
		GetProjectsEndPrognoz4Recursive(ext_prj[i],ext_prj,prognoz_dates,prev_prj_aggr_map,odt,ext_prev_prognoz);
	}
	return true;
}

bool CaplProjectManager::GetProjectsEndPrognoz4Recursive(CaplInstance *prj, aplExtent &ext_prj, apl_COleDateTime_array &prognoz_dates, CaplAggrMap &prev_prj_aggr_map, COleDateTime &result_dt, aplExtent &ext_prev_prognoz)
{
	if(0==prj) return false;
	if(prj->GetType()==0) return false;
	if(prj->GetAccessmode()>aplRO)return false;

	result_dt.SetStatus(COleDateTime::null);

	int i, idx=aplQFindInstInExtent(ext_prj,prj,false);
	if(idx>=0) // определена ранее
	{
		if(prognoz_dates[idx].GetStatus()!=COleDateTime::null)
		{
			result_dt=prognoz_dates[idx];
			return true;
		}
	}
	else AfxMessageBox(APL_T("Неизвестный проект!"));

	CString date_s;
	m_api->m_data.GetAttr(prj,a_project_date_actual_end, date_s);
	if(date_s!=_T("")) //уже закончена
	{
		aplString2Date(date_s,result_dt);
		if(idx>=0) prognoz_dates[idx]=result_dt;
		return true; //уже закончена
	}

	m_api->m_data.GetAttr(prj,a_project_date_actual_begin, date_s);

	if(date_s!=_T(""))
	{
		//Уже начата
		GetWorkedProjectEndPrognoz(prj,result_dt);
		if(idx>=0) prognoz_dates[idx]=result_dt;
		return true;
	}

	// Надо смотреть предыдущие
	COleDateTime odt,startDate;
	COleDateTimeSpan duration_odts(0);
	CString begin_date_s;
	m_api->m_data.GetAttr(prj,a_project_date_planned_begin, begin_date_s);
	if(begin_date_s==_T("")) begin_date_s=_T("19000101000000");
	aplString2Date(begin_date_s,startDate);
	double planned_duration;
	m_data->GetAttr(prj,a_project_date_planned_duration,planned_duration);
	if(planned_duration!=0) duration_odts=planned_duration;
	else
	{
		CString end_date_s;
		m_api->m_data.GetAttr(prj,a_project_date_planned_end, end_date_s);
		if(end_date_s!=_T(""))
		{
			aplString2Date(end_date_s,odt);
			duration_odts=odt-startDate;
		}
	}

	CaplInstance *prev_prognoz_prj=0;
	int k=prev_prj_aggr_map.QFindByIn((long)prj);
	if(k>=0)
	{
		CaplAggr &RelAggr=prev_prj_aggr_map.Data[k].out;
		for(i=0;i<RelAggr.GetSize();i++)
		{
			CaplInstance *rel_prj=0;
			RelAggr.GetByIndex(i,rel_prj);
			if(GetProjectsEndPrognoz4Recursive(rel_prj,ext_prj,prognoz_dates,prev_prj_aggr_map,odt,ext_prev_prognoz))
			{
				if(odt>startDate)
				{
					startDate=odt;
					prev_prognoz_prj=rel_prj;
				}
			}
		}
	}
	result_dt=startDate+duration_odts;
	if(idx>=0)
	{
		prognoz_dates[idx]=result_dt;
		ext_prev_prognoz.SetAt(idx,prev_prognoz_prj);
	}
	return true;
}*/


bool CaplProjectManager::CalcProjectsEndPrognoz(aplExtent &ext, CaplMap &map_prj_index, apl_CPrjPrognozItem_array &array_progn_items, bool bLoadFrobDB)
{
	int i;
	long swd=aplStartWaitDlg(APL_T("Расчет прогнозов"));
	COleDateTime odt;
	for(i=0;i<ext.GetSize();i++)
	{
		CalcProjectEndPrognoz(ext[i],odt,map_prj_index, array_progn_items,bLoadFrobDB);
	}
	aplEndWaitDlg(swd);
	return true;
}


CaplProjectManager::CPrjPrognozItem * CaplProjectManager::CalcProjectEndPrognoz(CaplInstance *prj, COleDateTime &prjEndPrognoz, CaplMap &map_prj_index, apl_CPrjPrognozItem_array &array_progn_items, bool bLoadFrobDB)
{
	prjEndPrognoz.SetStatus(COleDateTime::null);
	if(0==prj) return false;
	if(0==prj->GetType())return false;

	int i;
	i=map_prj_index.GetByIn((long)prj);
	if(i>0)
	{
		ASSERT(i<array_progn_items.GetSize());
		prjEndPrognoz=array_progn_items[i]->prognoz_end;
		return array_progn_items[i];
	}

	// прогноза еще нет
	CString s_date;
	m_data->GetAttr(prj,a_project_date_actual_end,s_date);
	if(s_date!=_T(""))
	{
		//уже завершена
		aplString2Date(s_date,prjEndPrognoz);
		CPrjPrognozItem *new_prgn_item=new CPrjPrognozItem(prj,prjEndPrognoz);
		map_prj_index.Add((long)prj, array_progn_items.Add(new_prgn_item));
		m_data->GetAttr(prj,a_project_date_actual_begin,s_date);
		aplString2Date(s_date,new_prgn_item->prognoz_begin);
		return new_prgn_item;
	}

	CaplInstance *first_sub_prj=0, *last_sub_prj=0;
	COleDateTime odt_tmp,odt_last_sub_prj_end,odt_last_sub_prj_begin;
	odt_last_sub_prj_end.SetStatus(COleDateTime::null);
	odt_last_sub_prj_begin.SetStatus(COleDateTime::null);
	
	aplExtent content;
	m_data->GetAttr(prj,a_project_content,content);
	if(content.GetSize()>0)
	{
		if(bLoadFrobDB) LoadProjectInfo(content);
		for(i=0;i<content.GetSize();i++)
		{
			CPrjPrognozItem *sub_prh_item=CalcProjectEndPrognoz(content[i],odt_tmp,map_prj_index,array_progn_items,bLoadFrobDB);
			if(0==sub_prh_item) continue;
			if(odt_tmp.GetStatus()==COleDateTime::valid)
			{
				if((odt_last_sub_prj_end.GetStatus()!=COleDateTime::valid) || (odt_tmp>odt_last_sub_prj_end))
				{
					odt_last_sub_prj_end=odt_tmp;
					last_sub_prj=content[i];
				}
			}
			if(sub_prh_item->prognoz_begin.GetStatus()==COleDateTime::valid)
			{
				if((odt_last_sub_prj_begin.GetStatus()!=COleDateTime::valid) || (sub_prh_item->prognoz_begin < odt_last_sub_prj_begin))
				{
					odt_last_sub_prj_begin=sub_prh_item->prognoz_begin;
					first_sub_prj=content[i];
				}
			}
		}
	}

	COleDateTime odt_start, odt;
	m_data->GetAttr(prj,a_project_date_actual_begin,s_date);
	if(s_date!=_T(""))
	{
		//начата
		aplString2Date(s_date,odt_start);

		if(content.GetSize()==0) GetWorkedProjectEndPrognoz(prj,prjEndPrognoz);
		else
		{
			if(odt_last_sub_prj_end.GetStatus()==COleDateTime::valid) prjEndPrognoz=odt_last_sub_prj_end;
			else
			{
				m_data->GetAttr(prj,a_project_date_planned_end,s_date);
				aplString2Date(s_date,prjEndPrognoz);
			}
		}
		CPrjPrognozItem *new_prgn_item=new CPrjPrognozItem(prj,prjEndPrognoz);
		map_prj_index.Add((long)prj, array_progn_items.Add(new_prgn_item));
		new_prgn_item->prognoz_begin=odt_start;
		return new_prgn_item;
	}


	// еще не начата - определяем прогнозируемую дату начала по предыдущим связям
	aplExtent ext_rel;
	CaplInstance *prev_progn_prj=0;
	COleDateTime odt_last_prev_progn; odt_last_prev_progn.SetStatus(COleDateTime::null);
	COleDateTime odt_progn_by_prev; odt_progn_by_prev.SetStatus(COleDateTime::null);
	GetProjectSequenceRelation(prj,ext_rel,true,bLoadFrobDB);
	if(ext_rel.GetSize()>0)
	{
		for(i=0;i<ext_rel.GetSize();i++)
		{
			CaplInstance *prev_prj;
			m_data->GetAttr(ext_rel[i],a_project_seq_prev,prev_prj);
			if(CalcProjectEndPrognoz(prev_prj,odt_tmp,map_prj_index,array_progn_items,bLoadFrobDB))
			{
				if((odt_last_prev_progn.GetStatus()!=COleDateTime::valid)|| (odt_tmp>odt_last_prev_progn))
				{
					odt_last_prev_progn=odt_tmp;
					prev_progn_prj=prev_prj;
				}
			}
		}
	}

	if(odt_last_prev_progn.GetStatus()==COleDateTime::valid)
	{
		COleDateTimeSpan odts(0);
		double dlit;
		m_data->GetAttr(prj,a_project_date_planned_duration,dlit);
		if(0!=dlit) odts= COleDateTimeSpan(dlit);
		else
		{
			COleDateTime odt_s,odt_e;
			m_data->GetAttr(prj,a_project_date_planned_begin,s_date);
			aplString2Date(s_date,odt_s);
			m_data->GetAttr(prj,a_project_date_planned_end,s_date);
			aplString2Date(s_date,odt_e);
			odts=odt_e-odt_e;
		}
		odt_progn_by_prev=odt_last_prev_progn+odts;
	}
	else
	{
		m_data->GetAttr(prj,a_project_date_planned_end,s_date);
		aplString2Date(s_date,odt_progn_by_prev);
		m_data->GetAttr(prj,a_project_date_planned_begin,s_date);
		aplString2Date(s_date,odt_last_prev_progn);

	}

	if(odt_last_sub_prj_end.GetStatus()==COleDateTime::valid)
	{
		if((odt_last_prev_progn.GetStatus()!=COleDateTime::valid) || (odt_last_sub_prj_end>odt_last_prev_progn))
		{
			odt_last_prev_progn=odt_last_sub_prj_begin;
			prev_progn_prj=0;
			odt_progn_by_prev=odt_last_sub_prj_end;
		}
	}

	prjEndPrognoz=odt_progn_by_prev;
	CPrjPrognozItem *prgnitem=new CPrjPrognozItem(prj,prjEndPrognoz);
	prgnitem->prev_progn_prj=prev_progn_prj;
	prgnitem->prognoz_begin=odt_last_prev_progn;
	prgnitem->first_progn_sub_prj=first_sub_prj;
	prgnitem->last_progn_sub_prj=last_sub_prj;
	map_prj_index.Add((long)prj, array_progn_items.Add(prgnitem));
	return prgnitem;
}



// Вычисляем цвет для отобрадения проекта (в зависимости от завершения в срок)
bool CaplProjectManager::GetProjectColor(CaplInstance *prj, COleDateTime &endPrognozDate, COLORREF &color)
{
	color=RGB(0,0,0);
	if(0==prj) return false;
	if(prj->GetType()==0) return false;
	if(prj->GetAccessmode()>aplRO)return false;

	color=RGB_DEFAULT;

	CString plan_end_date_s, fakt_end_date_s,fakt_start_date_s,cur_time_s;
	m_api->m_data.GetAttr(prj,m_api->m_project_mgr->a_project_date_actual_end, fakt_end_date_s);

	if(fakt_end_date_s!=_T("")) {color= RGB_ENDED; return true;}// Работа закончена

	m_api->m_data.GetAttr(prj,m_api->m_project_mgr->a_project_date_planned_end, plan_end_date_s);
	if(plan_end_date_s==_T("")){color=RGB_POFIG; return true;}// Срок не ограничен

	m_api->m_data.GetAttr(prj,m_api->m_project_mgr->a_project_date_actual_begin, fakt_start_date_s);
	
	// задан срок окончания
	COleDateTime odt_curent=COleDateTime::GetCurrentTime();
	aplDate2String(odt_curent,cur_time_s);

	if(plan_end_date_s<=cur_time_s)// просрочена
	{
		
		if( fakt_start_date_s==_T("")) color=RGB_NOTSTART_OVERDUE;
		else color=RGB_WORK_OVERDUE; 
		return true;
	}

	CString plan_start_date_s;
	m_api->m_data.GetAttr(prj,m_api->m_project_mgr->a_project_date_planned_begin, plan_start_date_s);

	// Не закончена, не просрочена
	if(fakt_start_date_s==_T("")  && plan_start_date_s!=_T("") && plan_start_date_s<cur_time_s) color=RGB_NOTSTART_NO_OVERDUE; // не начата но должна была
	else
	{
		//начата
		COleDateTime prognoz_date;
		if(endPrognozDate.GetStatus()==COleDateTime::valid)
		{
			CString prognoz_date_s;
			aplDate2String(endPrognozDate,prognoz_date_s);
			if(prognoz_date_s>plan_end_date_s)color=RGB_WORK_BAD_PROGN;
			else color=RGB_WORK_GOOD_PROGN;
		}	
		else color=RGB_DEFAULT;
	}

	return true;
}


//**************************************************************************************************
bool CaplProjectManager::ShowProjectsMonitor(aplExtent &ext, bool bLoadFromBD)
{
	if(0==m_api) return false;

	if(ext.GetSize()<1) {AfxMessageBox(APL_T("Нет данных для отображения")); return false;}

	if(bLoadFromBD) LoadProjectInfo(ext);

	CaplSetResourceHandle setres(module_inst);

	CPrjMonitorDlg dlg;
	dlg.m_api=m_api;
	dlg.m_prj_mgr=this;
	dlg.m_ext_projects=ext;
	dlg.DoModal();

	return true;
}


bool CaplProjectManager::ShowGanttDlg(aplExtent &ext, bool bLoadFromBD, bool bExpandAll, CaplInstance *prj4select)
{
	if(0==m_api) return false;
	if(ext.GetSize()<1) {AfxMessageBox(APL_T("Нет данных для отображения")); return false;}
	if(bLoadFromBD) LoadProjectInfo(ext);

	CaplSetResourceHandle setres(module_inst);
	CShowGanttDlg dlg;
	dlg.m_api=m_api;
	dlg.m_project_mgr=this;
	dlg.m_projects=ext;
	dlg.m_bAutoExpand=bExpandAll;
	dlg.m_prj4select=prj4select;

	//dlg.m_bAutoExpand=true;
	//dlg.m_prj4select = FindProjectById(APL_T("2-ЙЦУКЕНЬДЖ-8"));

	dlg.DoModal();

	return true;

}


// Создает копию дерева проекта
CaplInstance *CaplProjectManager::CreateProjectTreeCopy(CaplInstance *prj_src,CaplInstance *parent)
{
	if(0==m_api) return 0;

	if(0!=prj_src) 
	{
		if(prj_src->GetType()==0) return false;
		if(prj_src->GetAccessmode()>aplRO)return false;
	}

	if(0!=parent) 
	{
		if(parent->GetAccessmode()>aplRW){AfxMessageBox(APL_T("Нет прав на изменение родителя!"),MB_OK|MB_ICONSTOP); 	return 0; }
	}

	CaplSetResourceHandle setres(module_inst);

	CCreatePrjCopyDlg dlg;
	dlg.m_api=m_api;
	dlg.m_prj_mgr=this;
	dlg.m_src_prj=prj_src;
	dlg.m_parent=parent;
	int res=dlg.DoModal();

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

void CaplProjectManager::ShowColorLegend()
{
	CaplSetResourceHandle setres(module_inst);
	CPrjColorLegendDlg dlg;
	dlg.DoModal();
};

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

CaplInstance* CaplProjectManager::CreateProjectSequence(CaplInstance *prev_prj, CaplInstance *next_prj)
{
	if(0==prev_prj || 0== next_prj) return false;
	if(0==prev_prj->GetType() || 0== next_prj->GetType()) return 0;
	if(prev_prj==next_prj)
	{
		AfxMessageBox( APL_T("Проект не может быть предыдущим для самого себя!"),MB_OK|MB_ICONSTOP);
		return 0;
	}

	if(next_prj->GetAccessmode()>aplRO)
	{
		AfxMessageBox( APL_T("Недостаточно прав!"),MB_OK|MB_ICONSTOP);
		return false;
	}


	CString buf,name1,name2;
	// Запрос - подтверждение
	m_api->GetItemName(prev_prj,name1);
	m_api->GetItemName(next_prj,name2);
	buf.Format(APL_T("Сделать проект\n'%s'\n предыдущим для\n'%s'?"),LPCTSTR(name1),LPCTSTR(name2));
	if(IDYES!=AfxMessageBox(buf,MB_YESNO|MB_ICONQUESTION)) return 0;
	
	
	//Проверка существования такой связи
	CaplAttrValue tst_values[2];               
	tst_values[0].value.Set(prev_prj); 
	tst_values[0].attr=a_project_seq_prev;
	tst_values[1].value.Set(next_prj); 
	tst_values[1].attr=a_project_seq_next;

	if(!m_data->TestUniqueAttrValues(e_project_seg,0,2,&tst_values[0]))
	{
		AfxMessageBox(APL_T("Такая связь уже есть в базе !!!"),MB_OK|MB_ICONSTOP);
		return 0;
	}

	//Проверка цикла в последовательностях
	if(!m_data->TestCycleInRelation(e_project_seg,a_project_seq_prev,a_project_seq_next,prev_prj,next_prj))
	{
		AfxMessageBox( APL_T("Создание невозможно! Такая связь создаст цикл в последовательности проектов."),MB_OK|MB_ICONSTOP);
		return 0;
	}
	
	// Блокируем
	CaplInstance  *myLock=CheckMyLock(next_prj,false);
	if(0==myLock)
	{
		bool b=true;
		if(!CheckOutWithRequest(next_prj,b)) return false;
		myLock=CheckMyLock(next_prj,false);	
		if(0==myLock)return false; // такого не должно быть
	}


	// Создание связи
	CaplInstance *inst=m_data->CreateInstance(e_project_seg);
	m_data->PutAttr(inst,a_project_seq_prev,prev_prj);
	m_data->PutAttr(inst,a_project_seq_next,next_prj);
	//m_api->m_data.PutAttr(inst,m_project_mgr->a_project_seq_type,);

	aplExtent ext;
	m_data->GetAttr(myLock,a_project_adm_ver_prev_sequences,ext);
	ext.Add(inst);
	m_data->PutAttr(myLock,a_project_adm_ver_prev_sequences,ext);

	m_api->SaveChanges();
	return inst;
}


bool CaplProjectManager::SetProjectNewPlanedDate(CaplInstance *prj, COleDateTime &odtNewBeginDate, COleDateTime &odtNewEndDate)
{
	if(0==prj) return false;
	if(prj->GetType()==0) return false;
	if(prj->GetAccessmode()>aplRO)
	{
		AfxMessageBox( APL_T("Недостаточно прав!"),MB_OK|MB_ICONSTOP);
		return false;
	}
	if(odtNewBeginDate.GetStatus()!=COleDateTime::valid && odtNewEndDate.GetStatus()!=COleDateTime::valid) return false;

	CString buf,name,sDate;
	m_api->GetItemName(prj,name);
	CaplInstance *lock=CheckMyLock(prj,false);

	CString control_type;
	if(lock) m_data->GetAttr(lock,a_project_adm_ver_control_type,control_type);
	else m_data->GetAttr(prj,a_project_control_type,control_type);
	//m_data->GetAttr(prj,a_project_control_type,control_type);
	if(control_type==APL_NO_T("Определять по входящим"))
	{
		AfxMessageBox( APL_T("Операция невозможна! Даты проекта определяются по входящим!"),MB_OK|MB_ICONSTOP);
		return false;
	}
	CString sOldBegin, sOldEnd;
	if(lock)
	{
		m_data->GetAttr(lock,a_project_adm_ver_date_planned_begin,sOldBegin);
		m_data->GetAttr(lock,a_project_adm_ver_date_planned_end,sOldEnd);
	}
	else
	{
		m_data->GetAttr(prj,a_project_date_planned_begin,sOldBegin);
		m_data->GetAttr(prj,a_project_date_planned_end,sOldEnd);
	}
	COleDateTime odtOldBegin,odtOldEnd;
	aplString2Date(sOldBegin,odtOldBegin);
	aplString2Date(sOldEnd,odtOldEnd);

	COleDateTimeSpan odtsOld(0.0);
	if(odtOldBegin.GetStatus()==COleDateTime::valid && odtOldEnd.GetStatus()==COleDateTime::valid) odtsOld=odtOldEnd-odtOldBegin;

	bool bSetNewDlit=false;

	if(odtNewBeginDate.GetStatus()==COleDateTime::valid && odtNewEndDate.GetStatus()==COleDateTime::valid)
	{
		// обе даты
		bSetNewDlit=true;
		CString sDateBeginOld=odtOldBegin.Format(_T("%d.%m.%Y"));
		CString sDateBeginNew=odtNewBeginDate.Format(_T("%d.%m.%Y"));
		CString sDateEndOld=odtOldEnd.Format(_T("%d.%m.%Y"));
		CString sDateEndNew=odtNewEndDate.Format(_T("%d.%m.%Y"));
		buf.Format(APL_T("Установить для проекта\n'%s'\n\nдаты   %s - %s\nвместо %s - %s ?"),
			LPCTSTR(name),LPCTSTR(sDateBeginNew),LPCTSTR(sDateEndNew),LPCTSTR(sDateBeginOld),LPCTSTR(sDateEndOld));
		if(IDYES!=AfxMessageBox(buf,MB_YESNO|MB_ICONQUESTION)) return false;

	}
	else if(odtNewBeginDate.GetStatus()==COleDateTime::valid)
	{
		// дату начала
		CString sDateBeginOld=odtOldBegin.Format(_T("%d.%m.%Y"));
		CString sDateBeginNew=odtNewBeginDate.Format(_T("%d.%m.%Y"));
		buf.Format(APL_T("Установить для проекта\n'%s'\nдату начала %s вместо %s ?"),LPCTSTR(name),LPCTSTR(sDateBeginNew),LPCTSTR(sDateBeginOld));
		if(IDYES!=AfxMessageBox(buf,MB_YESNO|MB_ICONQUESTION)) return false;
		odtNewEndDate=odtOldEnd;
	}
	else 
	{
		// дату окончания
		CString sDateEndOld=odtOldEnd.Format(_T("%d.%m.%Y"));
		CString sDateEndNew=odtNewEndDate.Format(_T("%d.%m.%Y"));
		buf.Format(APL_T("Установить для проекта\n'%s'\nдату окончания %s вместо %s ?"),LPCTSTR(name),LPCTSTR(sDateEndNew),LPCTSTR(sDateEndOld));
		if(IDYES!=AfxMessageBox(buf,MB_YESNO|MB_ICONQUESTION)) return false;
		odtNewBeginDate=odtOldBegin;
	}

	COleDateTimeSpan odtsNew(0.0);
	if(odtNewBeginDate.GetStatus()==COleDateTime::valid && odtNewEndDate.GetStatus()==COleDateTime::valid) odtsNew=odtNewEndDate-odtNewBeginDate;
	
	CaplInstance  *myLock=CheckMyLock(prj,false);
	if(0==myLock)
	{
		bool b=true;
		if(!CheckOutWithRequest(prj,b)) return false;
		myLock=CheckMyLock(prj,false);
		if(0==myLock)return false; // такого не должно быть
	}


	bool bResetStart=false;
	COleDateTime  min_restrict_date, max_restrict_date;
	GetPrjDateRestrictions(prj,min_restrict_date, max_restrict_date,false);


	if(min_restrict_date.GetStatus()==COleDateTime::valid &&  odtNewBeginDate.GetStatus()==COleDateTime::valid && odtNewBeginDate < min_restrict_date)
	{
		if(IDYES!=AfxMessageBox(APL_T("Новая дата начала выходит за ограничения родительского проекта!\n\n Установить минимально возможную дату ?!"),MB_YESNO)) return false;
		odtNewBeginDate=min_restrict_date;
		if(bSetNewDlit) odtNewEndDate=min_restrict_date+odtsNew;
		/*COleDateTime tmpEndDate=min_restrict_date+odtsNew;
		if(max_restrict_date.GetStatus()==COleDateTime::valid  && tmpEndDate > max_restrict_date)
		{
			if(IDYES!=AfxMessageBox(APL_T("Новые даты выходят за ограничения родительского проекта!\n\n Установить крайние возможные даты ?!"),MB_YESNO)) return false;
			odtNewBeginDate=min_restrict_date;
			odtNewEndDate=max_restrict_date;
		}
		else
		{
			if(IDYES!=AfxMessageBox(APL_T("Новая дата начала выходит за ограничения родительского проекта!\n\n Установить минимально возможную дату ?!"),MB_YESNO)) return false;
			odtNewBeginDate=min_restrict_date;
			odtNewEndDate=tmpEndDate;
		}*/
	}
	if(max_restrict_date.GetStatus()==COleDateTime::valid &&  odtNewEndDate.GetStatus()==COleDateTime::valid && odtNewEndDate > max_restrict_date)
	{
		if(IDYES!=AfxMessageBox(APL_T("Новая дата окончания выходит за ограничения родительского проекта!\n\n Установить максимально возможную дату ?!"),MB_YESNO)) return false;
		odtNewEndDate=max_restrict_date;
		if(bSetNewDlit) odtNewBeginDate=max_restrict_date-odtsNew;
		/*COleDateTime tmpStartDate=max_restrict_date-odtsNew;
		if(min_restrict_date.GetStatus()==COleDateTime::valid && tmpStartDate < min_restrict_date)
		{
			if(IDYES!=AfxMessageBox(APL_T("Новые даты выходят за ограничения родительского проекта!\n\n Установить крайние возможные даты ?!"),MB_YESNO)) return false;
			odtNewBeginDate=min_restrict_date;
			odtNewEndDate=max_restrict_date;
		}
		else
		{
			if(IDYES!=AfxMessageBox(APL_T("Новая дата окончания выходит за ограничения родительского проекта!\n\n Установить максимально возможную дату ?!"),MB_YESNO)) return false;
			odtNewBeginDate=tmpStartDate;
			odtNewEndDate=max_restrict_date;
		}*/
	}

	if(odtNewBeginDate.GetStatus()==COleDateTime::valid && odtNewEndDate.GetStatus()==COleDateTime::valid) odtsNew=odtNewEndDate-odtNewBeginDate;

	CString sDateBeginNew,sDateEndNew;
	aplDate2String(odtNewBeginDate,sDateBeginNew);
	aplDate2String(odtNewEndDate,sDateEndNew);

	double duration=(int)(0.5+((double)((int)((100*odtsNew.GetTotalHours())/24)))/100);

	m_data->PutAttr(myLock,a_project_adm_ver_date_planned_begin,sDateBeginNew);
	m_data->PutAttr(myLock,a_project_adm_ver_date_planned_end,sDateEndNew);
	m_data->PutAttr(myLock,a_project_adm_ver_date_planned_duration,duration);

	RecalcParentDates(prj);
	m_api->SaveChanges();
	return true;

	return true;
}

/*bool CaplProjectManager::SetProjectPlanedBeginDate(CaplInstance *prj, COleDateTime &odtNewBeginDate)  // Устанавливает новую дату начала
{
	if(0==prj) return false;
	if(prj->GetType()==0) return false;
	if(prj->GetAccessmode()>aplRO)
	{
		AfxMessageBox( APL_T("Недостаточно прав!"),MB_OK|MB_ICONSTOP);
		return false;
	}
	if(odtNewBeginDate.GetStatus()!=COleDateTime::valid)
	{
		AfxMessageBox( APL_T("Некорректно указана новая дата!"),MB_OK|MB_ICONSTOP);
		return false;
	}	

	CString buf,name,sDate;
	m_api->GetItemName(prj,name);
	CaplInstance *lock=CheckMyLock(prj,false);

	CString control_type;
	if(lock) m_data->GetAttr(lock,a_project_adm_ver_control_type,control_type);
	else m_data->GetAttr(prj,a_project_control_type,control_type);
	//m_data->GetAttr(prj,a_project_control_type,control_type);
	if(control_type==APL_T("Определять по входящим"))
	{
		AfxMessageBox( APL_T("Операция невозможна! Даты проекта определяются по входящим!"),MB_OK|MB_ICONSTOP);
		return false;
	}

	if(lock) m_data->GetAttr(lock,a_project_adm_ver_date_planned_begin,sDate);
	else m_data->GetAttr(prj,a_project_date_planned_begin,sDate);

	if(sDate==_T("")) 
	{
		AfxMessageBox( APL_T("Операция невозможна! Не задана плановая дата начала!"),MB_OK|MB_ICONSTOP);
		return false;
	}
	COleDateTime odt_old;
	aplString2Date(sDate,odt_old);

	CString sDateOld=odt_old.Format(_T("%d.%m.%Y"));
	CString sDateNew=odtNewBeginDate.Format(_T("%d.%m.%Y"));
	buf.Format(APL_T("Сделать для проекта\n'%s' дату начала %s вместо %s ?"),LPCSTR(name),LPCSTR(sDateNew),LPCSTR(sDateOld));
	if(IDYES!=AfxMessageBox(buf,MB_YESNO|MB_ICONQUESTION)) return false;

	CaplInstance  *myLock=CheckMyLock(prj,false);
	if(0==myLock)
	{
		bool b=true;
		if(!CheckOutWithRequest(prj,b)) return false;
		myLock=CheckMyLock(prj,false);
		if(0==myLock)return false; // такого не должно быть
	}


	bool bResetStart=false;
	COleDateTime  min_restrict_date, max_restrict_date;
	GetPrjDateRestrictions(prj,min_restrict_date, max_restrict_date,false);
	if(min_restrict_date.GetStatus()==COleDateTime::valid &&  odtNewBeginDate < min_restrict_date)
	{
		if(IDYES!=AfxMessageBox(APL_T("Новая дата начала выходит за ограничения родительского проекта!\n\n Установить минимально возможную дату ?!"),MB_YESNO)) return false;
		odtNewBeginDate=min_restrict_date;
		bResetStart=true;
	}

	CString date_begin, date_end;
	COleDateTime odt_begin,odt_end;

	m_data->GetAttr(myLock,a_project_adm_ver_date_planned_begin,date_begin);
	m_data->GetAttr(myLock,a_project_adm_ver_date_planned_end,date_end);
	//m_data->GetAttr(myLock,a_project_adm_ver_date_planned_duration,planed_duration);

	aplString2Date(date_begin,odt_begin);
	aplString2Date(date_end,odt_end);

	COleDateTime odts(0.0);
	if(odt_end.GetStatus()==COleDateTime::valid)
	{
		odts=odtNewBeginDate-odt_begin;
		odt_end=odt_end+odts;
	}

	if(max_restrict_date.GetStatus()==COleDateTime::valid &&  odt_end > max_restrict_date)
	{
		if(IDYES!=AfxMessageBox(APL_T("Новая дата окончания выходит за ограничения родительского проекта!\n\n Установить максимально возможную дату ?!"),MB_YESNO)) return false;

		odt_end=max_restrict_date;
		odtNewBeginDate=odt_end-odts;
	}

	aplDate2String(odtNewBeginDate,date_begin);
	aplDate2String(odt_end,date_end);

	m_data->PutAttr(myLock,a_project_adm_ver_date_planned_begin,date_begin);
	m_data->PutAttr(myLock,a_project_adm_ver_date_planned_end,date_end);

	RecalcParentDates(prj);
	m_api->SaveChanges();
	return true;

}*/


bool CaplProjectManager::GetPrjDateRestrictions(CaplInstance *prj, COleDateTime &odt_begin,  COleDateTime &odt_end, bool bPrjIsParent)
{
	odt_begin.SetStatus(COleDateTime::null);
	odt_end.SetStatus(COleDateTime::null);

	if(0==prj) return false;
	if(prj->GetType()==0) return false;
	if(prj->GetAccessmode()>aplRO)
	{
		AfxMessageBox( APL_T("Недостаточно прав!"),MB_OK|MB_ICONSTOP);
		return false;
	}

	bool bReturn=true;
	CaplInstance *parent,*cur_prj=prj;
	CString control_type;
	CString s_begin1,s_end1;
	while(true)
	{
		if(bPrjIsParent)  {parent=cur_prj; bPrjIsParent=false;}
		else 	m_data->GetAttr(cur_prj,a_project_parent,parent);

		if(0==parent) return true;

		m_data->GetAttr(parent,a_project_control_type,control_type);
		if(control_type==APL_NO_T("Ограничивать входящие"))
		{
			CaplInstance  *myLock=CheckMyLock(parent,false);
			if(0==myLock)
			{
				m_data->GetAttr(parent,a_project_date_planned_begin,s_begin1);
				m_data->GetAttr(parent,a_project_date_planned_end,s_end1);
			}
			else
			{
				m_data->GetAttr(myLock,a_project_adm_ver_date_planned_begin,s_begin1);
				m_data->GetAttr(myLock,a_project_adm_ver_date_planned_end,s_end1);
			}

			if(s_begin1!=_T("") && odt_begin.GetStatus()==COleDateTime::null)aplString2Date(s_begin1,odt_begin);
			if(s_end1!=_T("") && odt_end.GetStatus()==COleDateTime::null )aplString2Date(s_end1,odt_end);

			if(	odt_begin.GetStatus()!=COleDateTime::null && 	odt_end.GetStatus()!=COleDateTime::null) return true;
		}
		cur_prj=parent;
		LoadProjectInfo(cur_prj,false);
	}
	return true;
/*
			if(s_begin!=_T("") && s_begin_new!=_T("") && s_begin_new<s_begin)
			{
				s_begin_new=s_begin;
				bReturn=false;
			}
			if(s_end!=_T("") && s_end_new!=_T("") && s_end_new>s_end)
			{
				s_end_new=s_end;
				bReturn=false;
			}
			if(bReturn==false) break;
		}
		else if(control_type==APL_NO_T("Определять по входящим"))
		{
			bool bAdd=false;
			if(s_begin!=_T("") && s_begin_new!=_T("") && s_begin_new<s_begin) bAdd=true;
			if(s_end!=_T("") && s_end_new!=_T("") && s_end_new>s_end)  bAdd=true;
			if(bAdd) ext_prj4ResetDate.Add(parent);
		}
		cur_prj=parent;
		LoadProjectInfo(cur_prj,false);
	}
	return bReturn;*/
}

/*
bool  CaplProjectManager::ResetPlanedDates(aplExtent &ext, LPCSTR s_begin, LPCSTR s_end)
{
	int i;
	aplExtent lockers;

	CString s_begin_new=s_begin; 
	CString s_end_new=s_end; 
	bool bFalse=false;

	for(i=0; i<ext.GetSize();i++)
	{
		CaplInstance *prj=ext[i];
		if(prj->GetType()==0) continue;
		if(prj->GetAccessmode()>aplRW)
		{
			CString buf,msg;
			GetItemName(prj,buf);
			msg.Format(APL_T("Нет прав на изменение проекта\n'%s'!"),LPCSTR(buf));
			AfxMessageBox(msg,MB_OK|MB_ICONSTOP);
			return false;
		}

		CaplInstance  *myLock=CheckMyLock(prj,false);
		if(0==myLock)
		{
			if(!CheckOutWithRequest(prj,bFalse)) return false;
			myLock=CheckMyLock(prj,false);
			if(0==myLock)return false; // такого не должно быть
		}
		lockers.Add(myLock);
	}

	// все заблокировали - можно менять
	/*CString s_begin_cur, s_end_cur

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

		m_data->GetAttr(myLock,a_project_adm_ver_date_planned_begin,s_begin_cur);
		m_data->GetAttr(myLock,a_project_adm_ver_date_planned_end,s_end_cur);

		if(s_begin_new!=_T(""))
		{
			if(s_begin_cur==_T("") || s_begin_cur)

		}
		if(s_begin_cur)
	}
	m_api->SaveChanges();
	return true;
}

*/