// aplProjectMgr.h: interface for the CaplProjectManager class.
//
//////////////////////////////////////////////////////////////////////

#pragma once

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "aplStepManager.h"


#ifndef APL_RRJ_MGR_NOAUTOLIB
#ifdef _DEBUG
#ifdef UNICODE
#pragma comment (lib,"aplProjectManager_ud.lib")
#else
#pragma comment (lib,"aplProjectManagerD.lib")
#endif
#else
#ifdef UNICODE
#pragma comment (lib,"aplProjectManager_u.lib")
#else
#pragma comment (lib,"aplProjectManager.lib")
#endif
#endif
#endif


#ifdef APL_PROGECT_MGR
#define APL_PM_CLASS_EXPORT		_declspec(dllexport)
#else
#define APL_PM_CLASS_EXPORT		_declspec(dllimport)
#endif


bool AFX_EXT_API isAggrChanged(CaplAggr &aggr,CaplAggr &aggr1);
bool AFX_EXT_API isExtentChanged(aplExtent &ext,aplExtent &ext1);

class CaplProjectManager;

class APL_PM_CLASS_EXPORT CaplProjectManager : public CaplPreProjectManager 
{
public:
	class APL_PM_CLASS_EXPORT CTransaction
	{
	public:
		CaplInstance	*m_inst;
		CaplInstance	*m_project;
		
		CString	m_sId;
		CString	m_sName;
		CString	m_sDescr;
		CString	m_sType;
		CString	m_sDate;
		double	m_dSumm;
		double	m_dNDS;

		CString	m_sProjectId;
		CString	m_sProjectName;

		CTransaction()
		{
			m_dSumm = 0;
			m_dNDS=0;
			m_inst = NULL;
			m_project=0;
		};
		
		CTransaction(CTransaction *trs)
		{
			if(trs!=0)
			{
				m_sId=trs->m_sId;
				m_sName=trs->m_sName;
				m_sDescr=trs->m_sDescr;
				m_sType=trs->m_sType;
				m_sDate=trs->m_sDate;
				m_dSumm=trs->m_dSumm;
				m_dNDS=trs->m_dNDS;

				m_sProjectId=trs->m_sProjectId;
				m_sProjectName=trs->m_sProjectName;

				m_inst =trs->m_inst;
				m_project=trs->m_project;
			}
		};
		CTransaction(CaplProjectManager *pProjectMgr, CaplInstance* inst, CaplInstance *project)
		{
			Load(pProjectMgr, inst, project);
		};


		virtual ~CTransaction(){};

		bool Load(CaplProjectManager *pProjectMgr, CaplInstance* inst, CaplInstance *project);
	};

	struct STransactionFilter
	{
		STransactionFilter()
		{
			bShowFact = true;
			bShowPlan = true;
			bShowFHelp = true;

			sDateMax.Empty();
			sDateMin.Empty();
		};

		bool	bShowFact;
		bool	bShowPlan;
		bool	bShowFHelp;

		CString sDateMin;
		CString sDateMax;
	};

	class CPrjPrognozItem
	{
	public:
		CaplInstance *prj;
		COleDateTime prognoz_begin;
		COleDateTime prognoz_end;
		CaplInstance *prev_progn_prj;
		CaplInstance *first_progn_sub_prj;
		CaplInstance *last_progn_sub_prj;

		CPrjPrognozItem(){prj=0; prev_progn_prj=0; first_progn_sub_prj=0; last_progn_sub_prj=0;};
		CPrjPrognozItem(CaplInstance *inst_prj, COleDateTime &end_odt){prj=inst_prj; prev_progn_prj=0; prognoz_end=end_odt;first_progn_sub_prj=0; last_progn_sub_prj=0;};
	};

	CaplProjectManager();
	virtual ~CaplProjectManager();
	CStringArray	m_saMoneyTransactionTypes;

	static bool m_bShowId;
	static bool m_bShowName;
	static bool m_bRecursive;
	CString m_role_to_edit_fact; //Роль в опции для работы с фактическими платежами
	bool m_has_role_edit_fact;
	//static bool m_bShowMessages;

	static COLORREF  RGB_DEFAULT;
	static COLORREF  RGB_POFIG;
	static COLORREF  RGB_ENDED;
	static COLORREF  RGB_NOTSTART_OVERDUE;
	static COLORREF  RGB_NOTSTART_NO_OVERDUE;
	static COLORREF  RGB_WORK_GOOD_PROGN;
	static COLORREF  RGB_WORK_BAD_PROGN;
	static COLORREF  RGB_WORK_OVERDUE;


	
	CaplInstance *FindProjectTypeBN(LPCTSTR name,bool bLoadFromBase=false); // Найти тип проекта
	CaplInstance *CreateProjectType(LPCTSTR name);							// Создать тип проекта			

	void GetIdPersOrOrg(CaplInstance *item, CString &id); // универсальный возращатель обозначения для заказчикаЮ исполнителя и т.д.


	virtual CaplInstance *CreateProject(CaplInstance *base_project=0,LPCTSTR id=0,bool add_to_contents=true,CaplInstance *item=0,CaplInstance **rel=0);
	
	bool DeleteProject(CaplInstance *project,bool delete_sub_projects=true,bool delete_associated_projects=true,bool recalc_parent_labor=true);
		
	virtual bool ShowProjectProperties(CaplInstance *project,bool b_read_only=false); // Отображает свойства проекта
	
	bool IsProjectIdUnique(LPCTSTR id,CaplInstance *project=0,bool bShowMessage=true); // Проверяет уникальность обозначения проекта

	CaplInstance *FindProjectById(LPCTSTR id,bool bLoadFromBase=false);  // Найти проект по обозначению
	CaplInstance *FindProjectBN(LPCTSTR name,bool bLoadFromBase=false);        // Найти проект по наименованию (первый попавшийся)

	// Находит и возвращает в ext_prj проекты, у которых хотя бы один из ext_po 
	// есть в заказчиках (если bCustomer==true) или есть в ответственных (если bKurator==true) или есть в исполнителях(если bExecutor==true) 
	// Если  bLoadFromBase==true - данные о проектах зачитываются в кэш
	bool FindProject(aplExtent &ext_po, bool bCustomer, bool bKurator, bool bExecutor, LPCTSTR sState, aplExtent &ext_prj,bool bLoadFromBase=false);        // Найти проект по наименованию (первый попавшийся)



	//*************************************************************
	//******   Вертикальные связи (структура) *********************
	//*************************************************************

	/// Прочитать все подпроекты
	bool GetAllSubProject(CaplInstance *project,aplExtent &ext_out,bool recursive=false,bool include_associated=false, bool from_base=true);
	virtual void GetAllSubProject(aplExtent &project_ext,aplExtent &ext_out,bool recursive=false,bool include_associated=false, bool from_base=true);

	/*Зачитать в кэш все подпроекты на nlevel вниз 
	если nlevel==0 - то обновляется информация о project_ext без зачитывания вглубь*/
	bool LoadAllSubProjectNlevel(aplExtent &project_ext,aplExtent &ext_out,int nlevel);

	// Читает из БД подпроекты
	bool LoadSubProjects(CaplInstance *project,aplExtent &ext_out);

	// Возвращает проекты, в состав котоых входит project
	bool WhereUsedProject(CaplInstance *project,aplExtent &ext_out);
	
	/// Добавляет в состав родителя
	bool AddToParentContent(CaplInstance *project,CaplInstance *parent_project);

	/// Удаляет из состава родителя
	bool RemoveFromParentContent(CaplInstance *project,CaplInstance *parent_project);

	/// Удаляет из состава родителя и делает проект корневым
	bool RemoveProjectFromParent(CaplInstance *project,CaplInstance *parent_project);

	/*Делает проект дочерним
	@param project подпроект
	@param parent_project родительский проект
	@param add_to_content флаг необходимости добавления в состав (аггр) родительского проекта 
	@param remove_from_old_content удалять из состава старого родительского проекта
	@param make_main_parent при добавлении в состав родительского проекта делать его "основным родителем" (ссылка на него используется при пересчете суммарных показателей проекта по подпроектам)
	@return true при удачном выполнении и false в случае ошибки */
	virtual bool InsertProjectIntoParent(CaplInstance *project,CaplInstance *parent_project,bool add_to_content=false,bool remove_from_old_content=true,bool make_main_parent=false);
	
	/// Определяет наличие дочерних проектов
	bool IsProjectHaveChildren(CaplInstance *project,bool include_associated=false);


	//*************************************************************
	//******  Горизонтальные связи ********************************
	//*************************************************************

	CaplInstance* CreateProjectSequence(CaplInstance *prev_prj, CaplInstance *next_prj); // Создает последовательность для проектов


	//*************************************************************
	//******   Состояния ******************************************
	//*************************************************************

	/*Меняет состояние проектов
	@param project проект
	@param new_state состояние, на которое меняем
	@param recursive рекурсивно или нет проводить обработку
	@return true при удачном выполнении и false в случае ошибки */
	bool ChangeProjectState(CaplInstance *project,LPCTSTR new_state,bool recursive,COleDateTimeSpan &span);

	/*Меняет состояние проектов в зависимости от состояния подчиненных (обрабатывет также проекты-родители)
	@param project проект
	@return true при удачном выполнении и false в случае ошибки */
	bool UpdateProjectState(CaplInstance *project);


	//*************************************************************************
	//******   Даты  ******************************************
	//*************************************************************************

	/* Ищет наибольшую дату завершения работы
	@param inst указатель на проект.
	@param attr указатель на атрибут который необходимо проверять (actual_end или actual_end2
	@return строку, содержащую наибольшую дату.*/
	CString GetProjectActualDate(CaplInstance *inst=NULL, CaplAttr *attr=NULL);
	
	/*Пересчитывает трудоемкость проектов в зависимости от трудоемкостей подчиненных (обрабатывет также проекты-родители)
	@param project проект
	@return true при удачном выполнении и false в случае ошибки */
	bool RecalcProjectLabor(CaplInstance *project,bool recursive=true,bool load_prj_info=true);
	bool RecalcParentDates(CaplInstance *project, bool recursive=true,bool load_prj_info=true);

	// Вычисляем прогнозируемую дату завершения для начатой работы
	bool GetWorkedProjectEndPrognoz(CaplInstance *prj, COleDateTime &date_end_prognoz);


	/*typedef CArray <COleDateTime, COleDateTime&> apl_COleDateTime_array;
	// Вычисляем прогнозируемые даты завершения для множества проектов
	bool GetProjectsEndPrognoz(aplExtent &ext_prj, apl_COleDateTime_array &prognoz_dates, aplExtent &ext_prev_prognoz);

	bool GetProjectsEndPrognoz4Recursive(CaplInstance *prj, aplExtent &ext_prj, apl_COleDateTime_array &prognoz_dates, CaplAggrMap &prev_prj_aggr_map, COleDateTime &result_dt, aplExtent &ext_prev_prognoz);*/

	typedef CaplTAggr <CPrjPrognozItem*,CPrjPrognozItem*,APLAGGR_LIST|APLAGGR_AUTOKILLREF> apl_CPrjPrognozItem_array;

	bool CalcProjectsEndPrognoz(aplExtent &ext, CaplMap &map_prj_index, apl_CPrjPrognozItem_array &_array_progn_items, bool bLoadFrobDB);
	CPrjPrognozItem *CalcProjectEndPrognoz(CaplInstance *prj, COleDateTime &prjEndPrognoz, CaplMap &map_prj_index, apl_CPrjPrognozItem_array &_array_progn_items, bool bLoadFrobDB);


	// Вычисляем цвет для отобрадения проекта (в зависимости от завершения в срок)
	bool GetProjectColor(CaplInstance *prj, COleDateTime &endPrognozDate, COLORREF &color);

	// Выводит диалог с описанием смысла цветов
	static void ShowColorLegend();

	//*************************************************************************
	//******   Версии проектов       ******************************************
	//*************************************************************************
	
	/** Возвращает все версии проекта  
		@param project проект
		@param outExt  список версий проекта (результат)
		@return true при удачном выполнении и false в случае ошибки */
	bool GetAllProjectVersion(CaplInstance *project,aplExtent &outExt);
	/** Взять проект на редактирование 
		@param project  проект или его версия */
	bool CheckOut( CaplInstance *project,bool recursive=false);
	/** Взять проект на редактирование c выводом диалога запроса
		@param project  проект или его версия 
		@param recursive брать на редактирование все входящие проекты */
	bool CheckOutWithRequest( CaplInstance *project,bool &recursive=m_bRecursive);

	/** Завершить  редактирование проекта  
		@param project  проект
		@param recursive завершать редактирование всех входящих проектов 
		@param make_new_version_active делать новую версию активной */
	bool CheckIn(CaplInstance *project,bool recursive=false,bool make_new_version_active=true);
	/** Завершить редактирование проекта c выводом диалога запроса
		@param project  проект
		@param recursive завершить редактирование все входящих проектов */
	bool CheckInWithRequest( CaplInstance *project,bool &recursive=m_bRecursive);

	/** Отменить редактирование  */
	bool UndoCheckOut( CaplInstance *project,bool recursive=false);
	/** Отменить редактирование проекта c выводом диалога запроса
		@param project  проект */
	bool UndoCheckOutWithRequest(CaplInstance *project,bool &recursive=m_bRecursive);

	/** Проверяет,взят ли проект на редактирование текущим пользователем
		@param project  проверяемый проект или его версия
		@param recursive брать на редактирование все входящие проекты 
		@return true,если заблокирован текущим пользователем,false - если другим пользователем.Если не заблокирован,выводит запрос на блокировку */
	bool CheckMyLockAndCheckOut(CaplInstance *project,bool recursive=true);

	bool IsProjectChanged(CaplInstance *project,CaplInstance *project_ver);


	//*************************************************************************
	//******   Финансовые транзакции ******************************************
	//*************************************************************************

	typedef CaplTAggr<CTransaction*, CTransaction*, APLAGGR_LIST_OR_AUTOKILLREF> aplTransactionsArray;

	CaplInstance* CreateTransaction(CaplInstance* Project, LPCTSTR lpszId, LPCTSTR lpszName, LPCTSTR lpszDescr, LPCTSTR lpszDate, LPCTSTR lpszType, double summ);
	CaplInstance* CreateTransaction(CaplInstance* Project, LPCTSTR lpszId, LPCTSTR lpszName, LPCTSTR lpszDescr, COleDateTime Date, LPCTSTR lpszType, double summ);

	/** Читаем информацию о транзакциях проекта в кэш */
	bool LoadTransactionsInfo(CaplInstance *inst);
	/** Читаем информацию о транзакциях проекта в кэш */
	bool LoadTransactionsInfo(aplExtent &ext);

	/** Удаляем информацию о транзакциях проекта в кэш */
	bool DeleteTransaction(CaplInstance* Project, CaplInstance* inst);

	/** Выбираем фильтр транзакций */
	bool SelectTransactionFilter(STransactionFilter &Filter);
	
	/** Фильтруем танзакции транзакций */
	bool FilterTransactions(aplTransactionsArray &InTransactions, aplTransactionsArray &OutTransactions, STransactionFilter &Filter);

	/** Формируем отчет по транзакциям проекта  */
	bool ReportTransactions(CaplInstance* Project, STransactionFilter &Filter, bool bShowTable = true, bool bRecursive = true, aplTransactionsArray *pArray = NULL);



	//*************************************************************************
	//******   Дополнительные функции ******************************************
	//*************************************************************************

	// Показывает монитор проектов. ext - список отображаемых проектов
	bool ShowProjectsMonitor(aplExtent &ext, bool bLoadFromBD=true);

	// Показывает диалог с диаграммой Ганта. ext - список отображаемых проектов
	// ext - массив проектов
	// bLoadFromBD - зачитывать или нет информацию о проектах из БД
	// bExpandAll - если true, то вызвать "раскрыть все" сразу после открытия
	// prj4select - проект для выделения после открытия
	bool ShowGanttDlg(aplExtent &ext, bool bLoadFromBD=true, bool bExpandAll=false, CaplInstance *prj4select=0);


	// Создает копию дерева проекта (выводит диалог)
	// prj_src - копируемый проект
	// parent - куда вставить (проект или папка)
	CaplInstance *CreateProjectTreeCopy(CaplInstance *prj_src, CaplInstance *parent=0);


	//*************************************************************************
	//******   Проверки  ******************************************
	//*************************************************************************
	
	// Проверяет ограничения для дат проекта  bPrjIsParent - переденный проект и есть родительский (для создания новых)
	bool GetPrjDateRestrictions(CaplInstance *prj,  COleDateTime &odt_begin,  COleDateTime &odt_end, bool bPrjIsParent);

	// Устанавливает новые плановые даты.  Если одна из дат - null - имеющаяся не меняется
	bool SetProjectNewPlanedDate(CaplInstance *prj, COleDateTime &odtNewBeginDate, COleDateTime &odtNewEndDate);  

	//bool SetProjectPlanedBeginDate(CaplInstance *prj, COleDateTime &odtNewBeginDate);  // Устанавливает новую дату начала


};


