#include "stdafx.h"
#include <finder.h>
#include "CaplComplectManager.h"

using namespace std;

CaplComplectMgr::CaplComplectMgr(CaplAPI *api) : m_api(api)
{
	
}

CaplComplectMgr::~CaplComplectMgr(void)
{
}

CaplInstance* CaplComplectMgr::FindExistingKomplect(CaplInstance *order)
{
	CaplInstance *complect = 0;
	m_api->m_data.GetAttrBN(order, _T("complect"), complect);

	if(0 == complect)
	{
		CString orderId = GetOrderId(order);

		CString sql;
		sql.Format(_T("SELECT Ext_1 FROM Ext_1  {apl_cnf_komplect.id = '%s'} END_SELECT"), orderId);	

		aplExtent result;
		if(m_api->m_data.NET_QueryEditParse(sql, false) == true) 
		{
			m_api->m_data.NET_QueryExecute(result);
			if(0 != result.Size)
			{
				if(IDYES == AfxMessageBox(APL_T("Комплект с данным обозначением уже существует. Перезаписать?"), MB_ICONINFORMATION|MB_YESNO))
				{
					m_api->LoadItemInfo(result[0]);
					return result[0];				
				}
			}		
		}
	}	

	return complect;
}

CaplInstance* CaplComplectMgr::GenerateComplectByPdf( CaplInstance *order, CaplInstance *pdf )
{
	if(0 == m_api) return 0;	
	if(0 == order || 0 == pdf) return false;
	if(false == m_api->m_data.IsConnected()) return false;

	CaplInstance *komplect = FindExistingKomplect(order);
	long dId = aplStartWaitDlg(APL_T("Генерация комплекта..."));

	// находим связи покупных изделий	
	aplExtent parentPdfs; parentPdfs.Add(pdf);
	Disassembly(parentPdfs);

	// оставляем связи, у которых edItem имеет расцеховку
	std::vector<CString> rascVec;
	rascVec.push_back(_T("115"));
	rascVec.push_back(_T("114"));
	rascVec.push_back(_T("131"));
	FilterByRasc(rascVec);
	
	// поиск цехов потребителей для найденных связей		
	if(false == ShowRelationsWithoutShop())
		return 0;	
	
	// поиск справочников, к которым привязаны ПКИ
	FindClassifiers();

	// создаем комплект и occurence's к нему
	komplect = CreateComplect(order, komplect, pdf);	

	aplEndWaitDlg(dId);
	return komplect;
}

void CaplComplectMgr::Disassembly(aplExtent &parentPdfs)
{
	// для переданных pdf ищем связи, в которых они являются верхушками
	aplExtent tmpParentPdfs;	
	aplExtent tmpRelations; 
	tmpRelations.Unique = false;

	int count = 0; 
	for(int i=0; i<parentPdfs.Size; ++i)
	{
		if(!parentPdfs[i]) 
			continue;
		if(!parentPdfs[i]->GetType())
			continue;

		++count;
		tmpParentPdfs.Add(parentPdfs[i]);

		if(((count == 1000) || (i == parentPdfs.GetSize()-1)))
		{			
			CaplFinder ff(DEF_SOURCE);
			aplExtent subResult;								

			int pdfIndex = ff.CreateExt(tmpParentPdfs, true);
			int relIndex = ff.CreateExt(m_api->m_prd_mgr.e_pdr);
			ff.AddAttr(relIndex, m_api->m_prd_mgr.a_pdr_r_ting, pdfIndex);						

			ff.AddToResult(relIndex);
			ff.Find(m_api->m_data, subResult, true, false, false, false, true);	

			tmpParentPdfs.Clear();
			count = 0;

			// подгрузим дополнительные атрибуты
			CaplLoadData ld(&m_api->m_data, DEF_SOURCE);
			for(int j=0; j<subResult.Size; ++j)
			{
				if(!subResult[j]) 
					continue;
				if(!subResult[j]->GetId())
					continue;
				if(!subResult[j]->GetType())
					continue;
				ld.AddQuery(0, subResult[j], true);
				tmpRelations.Add(subResult[j]);
			}

			if(ld.m_queries.GetSize())
			{
				ld.AddQuery(_T('d'), 0, m_api->m_prd_mgr.e_pdr, m_api->m_prd_mgr.a_pdr_r_ting, true, true);
				ld.AddQuery(_T('d'), 0, m_api->m_prd_mgr.e_pdr, m_api->m_prd_mgr.a_pdr_r_ted, true, true);
				ld.LoadEx();
			}
		}				
	}

	// найдем правила применяемости и отфильтруем по дате
	aplExtent pdfEffectivities;
	if(tmpRelations.Size > 0)
	{
		aplExtent tmpSubRelations;	

		for(int i=0; i<tmpRelations.Size; ++i)
		{
			++count;
			tmpSubRelations.Add(tmpRelations[i]);

			if(((count == 1000) || (i == tmpRelations.GetSize()-1)))
			{
				CaplFinder ff(DEF_SOURCE);
				aplExtent subResult;

				int relIndex = ff.CreateExt(tmpSubRelations, true);
				int pdfEffIndex = ff.CreateExt(m_api->m_prd_mgr.e_pd_eff);
				ff.AddAttr(pdfEffIndex, m_api->m_prd_mgr.a_pde_usage, relIndex);
				ff.AddToResult(pdfEffIndex);
				ff.Find(m_api->m_data, subResult, true, false, false, true, true);

				tmpSubRelations.Clear();
				pdfEffectivities.Append(subResult);
				count = 0;
			}
		}
	}

	aplExtent relations;
	m_api->m_prd_mgr.FilterlByDate(tmpRelations, COleDateTime::GetCurrentTime(), relations);	

	tmpRelations.Clear(); tmpRelations.Append(relations); relations.Clear();
	m_api->m_prd_mgr.FilterlBySN(tmpRelations, _T("09399999"), relations);	
	parentPdfs.Clear();	

	// подготовим данные для следующего поиска
	CString type, source;
	CaplInstance *edItem = NULL, *ingItem = NULL;

	for(int i=0; i<relations.Size; ++i)
	{
		if(!relations[i]->GetType())
			continue;

		m_api->m_data.GetAttr(relations[i], m_api->m_prd_mgr.a_pdr_r_ted, edItem);
		m_api->m_data.GetAttr(relations[i], m_api->m_prd_mgr.a_pdr_r_ting, ingItem);		

		if(edItem && ingItem)
		{			
			// покупное дальше не разузловываем
			m_api->m_data.GetAttr(edItem, m_api->m_prd_mgr.a_pdfwss_source, source);
			if(0 != source.CompareNoCase(_T("bought")))
			{
				parentPdfs.Add(edItem);
			}
			else
			{
				m_relationsByEd[edItem].push_back(relations[i]);			
			}

			m_allPdfs[edItem].push_back(relations[i]);			
		}		
	}	

	if(parentPdfs.Size > 0)
		Disassembly(parentPdfs);
}

void CaplComplectMgr::FilterByRasc( std::vector<CString> &rascVec )
{
	m_pdfsRasc.clear();

	aplExtent items;
	aplExtent charactValues;
	CaplFinder ff(DEF_SOURCE);	
	CaplInstance *rascCharact = m_api->m_charact_mgr.GetCharacteristicBN(APL_T("Расцеховка"));

	// для всех edItem и ingItem первого уровня найдем расцеховку со значением rasc
	int charactValIndex = ff.CreateExt(m_api->m_charact_mgr.e_descr_value);
	ff.AddAttr(charactValIndex, m_api->m_charact_mgr.a_apl_charact_val_charact, rascCharact, CaplFinder::cmpEqual);	
	
	map<CaplInstance*, vector<CaplInstance*>>::iterator it, nextIt;
	for(it=m_relationsByEd.begin(); it!=m_relationsByEd.end(); ++it)	
	{
		nextIt = it;		
		items.Add(it->first);

		vector<CaplInstance*> &vec = it->second;
		for(unsigned int j=0; j<vec.size(); ++j)
		{
			CaplInstance *ingItem = 0;
			m_api->m_data.GetAttr(vec[j], m_api->m_prd_mgr.a_pdr_r_ting, ingItem);

			if(ingItem)
				items.Add(ingItem);
		}		
				
		if(items.Size >= 500 || ++nextIt == m_relationsByEd.end())
		{
			ff.AddAttr(charactValIndex, m_api->m_charact_mgr.a_apl_charact_val_item, ff.CreateExt(items, true));
			ff.AddToResult(charactValIndex);
			ff.Find(m_api->m_data, true, false, false, true, true);
			charactValues.Append(ff.m_innerExtent);			

			items.Clear();
			ff.Clear();

			charactValIndex = ff.CreateExt(m_api->m_charact_mgr.e_descr_value);
			ff.AddAttr(charactValIndex, m_api->m_charact_mgr.a_apl_charact_val_charact, rascCharact, CaplFinder::cmpEqual);			
		}
	}
	aplQSortByAttr(&m_api->m_data, charactValues, 0, charactValues.Size-1, m_api->m_charact_mgr.a_apl_charact_val_item);

	// сделаем карту
	for(int i=0; i<charactValues.Size; ++i)
	{
		CaplInstance *item = 0;
		m_api->m_data.GetAttr(charactValues[i], m_api->m_charact_mgr.a_apl_charact_val_item, item);

		if(item)
			m_pdfsRasc[item] = charactValues[i];
	}

	// оставляем лишь те, у которых нужная расцеховка есть
	for(it=m_relationsByEd.begin(); it!=m_relationsByEd.end();)
	{
		CaplValue val;
		val.Set(it->first);
		int index = aplQFindInstInExtentByAttr(&m_api->m_data, charactValues, m_api->m_charact_mgr.a_apl_charact_val_item, &val);

		if(-1 == index)
		{
			m_relationsByEd.erase(it++);
		}
		else
		{
			CString rasc;
			m_api->m_data.GetAttr(charactValues[index], m_api->m_charact_mgr.a_apl_charact_val_descr_val, rasc);

			bool success = false;
			for(unsigned int i=0; i<rascVec.size(); ++i)
			{
				if(rasc.Find(rascVec[i]) != -1)
				{
					success = true;
					break;
				}
			}

			if(success)
				++it;
			else 
				m_relationsByEd.erase(it++);
		}
	}
}

CString CaplComplectMgr::GetShopChain(map<CString, double> &valueByShop)
{
	CString result, tmp;

	for(map<CString, double>::iterator it=valueByShop.begin(); it!=valueByShop.end(); ++it)
	{
		tmp.Format(_T("%s/%g"), it->first, it->second);

		if(result.IsEmpty() == false)
			result += _T(";");
		result += tmp;
	}

	return result;
}

double CaplComplectMgr::GetTotalPdfCount(CaplInstance *item)
{
	double tempCount = 0.0;
	double totalCount = 0.0;
	CaplInstance *edItem = 0, *ingItem = 0;

	std::map<CaplInstance*, std::vector<CaplInstance*>>::iterator It = m_allPdfs.find(item);
	if(It != m_allPdfs.end())
	{
		std::vector<CaplInstance*> &vec = It->second;

		for(unsigned int i=0; i<vec.size(); ++i)
		{
			m_api->m_data.GetAttr(vec[i], m_api->m_prd_mgr.a_pdr_r_ting, ingItem);
			m_api->m_data.GetAttr(vec[i], m_api->m_prd_mgr.a_apl_qacu_value, tempCount);
			totalCount += (tempCount * GetTotalPdfCount(ingItem));
		}
	}	

	if(totalCount == 0) totalCount = 1;
	return totalCount;
}

CString CaplComplectMgr::GetOrderId(CaplInstance *order)
{
	if(0 == order)
		return _T("");

	CString orderId;
	m_api->m_data.GetAttrBN(order, _T("sn"), orderId);
	if(orderId.IsEmpty())
		m_api->m_data.GetAttrBN(order, _T("en"), orderId);

	return orderId;
}

void CaplComplectMgr::GetExistingOccurrences(	CaplInstance *komplect,
												std::map<CaplInstance*, CaplInstance*> &komplectOccurrences,
												std::map<std::pair<CaplInstance*, CaplInstance*>, CaplInstance*> &bomOccurrences)
{
	CaplFinder ff(DEF_SOURCE);

	CaplEntity *apl_cnf_komplect = m_api->m_data.GetEntityBN(_T("apl_cnf_komplect"));
	CaplEntity *apl_cnf_komplect_occurrence = m_api->m_data.GetEntityBN(_T("apl_cnf_komplect_occurrence"));
	CaplEntity *apl_cnf_bom_occurrence = m_api->m_data.GetEntityBN(_T("apl_cnf_bom_occurrence"));

	CaplAttr *a_komplect = m_api->m_data.GetAttrDefinition(apl_cnf_komplect_occurrence, _T("komplect"));
	CaplAttr *a_item = m_api->m_data.GetAttrDefinition(apl_cnf_komplect_occurrence, _T("item"));
	CaplAttr *a_relation = m_api->m_data.GetAttrDefinition(apl_cnf_bom_occurrence, _T("relation"));
	CaplAttr *a_komplect_occurrence = m_api->m_data.GetAttrDefinition(apl_cnf_bom_occurrence, _T("komplect_occurrence"));

	int komplOccIndex = ff.CreateExt(apl_cnf_komplect_occurrence);
	ff.AddAttr(komplOccIndex, a_komplect, komplect, CaplFinder::cmpEqual);

	int bomOccIndex = ff.CreateExt(apl_cnf_bom_occurrence);
	ff.AddAttr(bomOccIndex, a_komplect_occurrence, komplOccIndex);

	ff.SetResultGrpType(CaplFinder::grpOR);
	ff.AddToResult(komplOccIndex);
	ff.AddToResult(bomOccIndex);
	ff.Find(m_api->m_data, true, false, false, true, true);

	// соберем в кучу
	for(int i=0; i<ff.m_innerExtent.Size; ++i)
	{
		if(ff.m_innerExtent[i]->GetType() == apl_cnf_bom_occurrence)
		{
			CaplInstance *rel = 0, *item = 0;
			m_api->m_data.GetAttr(ff.m_innerExtent[i], a_komplect_occurrence, item);
			m_api->m_data.GetAttr(ff.m_innerExtent[i], a_relation, rel);
			bomOccurrences[std::make_pair(item, rel)] = ff.m_innerExtent[i];
		}
		else if(ff.m_innerExtent[i]->GetType() == apl_cnf_komplect_occurrence)
		{
			CaplInstance *pki = 0;
			m_api->m_data.GetAttr(ff.m_innerExtent[i], a_item, pki);
			komplectOccurrences[pki] = ff.m_innerExtent[i];
		}
	}
}

void CaplComplectMgr::ParseRasc(CString& csInRasc,CString csDepotSep,CString csGrpSep,
							 CStringArray* csapOutDepots,CStringArray* csapOutGrps, bool bErasePokrAndTermo)
{
	CString		csAll,csPart,csDep,csGrp;

	int			iLen4Del=-1;
	if(csInRasc.IsEmpty()) return;

	csAll=csInRasc;

	if(bErasePokrAndTermo)
	{
		int nIndex = csAll.Find(_T('П'));
		if(nIndex != -1)
		{
			csAll = csAll.Left(nIndex - 1);
		}
		else 
		{
			nIndex = csAll.Find(_T('Т'));
			if(nIndex != -1)
			{
				csAll = csAll.Left(nIndex - 1);
			}
		}
	}

	do 
	{
		csPart=_T("");csDep=_T("");csGrp=_T("");

		//	получаем цех (и группу, если есть)
		csPart=csAll.SpanExcluding(csDepotSep);
		//	получаем только цех
		csDep=csPart.SpanExcluding(csGrpSep);

		//	получаем группу
		if(csDep.GetLength()<csPart.GetLength())
			csGrp=csPart.Right(csPart.GetLength()-csDep.GetLength()-1);

		if(NULL!=csapOutDepots)
			csapOutDepots->Add(csDep);

		if(NULL!=csapOutGrps)
			csapOutGrps->Add(csGrp);

		iLen4Del=csPart.GetLength();
		if(csAll.GetLength()>=csPart.GetLength()+1)
			iLen4Del++;
		csAll.Delete(0,iLen4Del);
	} 
	while(_T("")!=csAll);
}

CString CaplComplectMgr::GetShopFromRasc(CaplInstance *ingItem)
{
	map<CaplInstance*, CaplInstance*>::iterator rascIt = m_pdfsRasc.find(ingItem);
	if(rascIt == m_pdfsRasc.end())
		return _T("");

	CString value;
	m_api->m_data.GetAttr(rascIt->second, m_api->m_charact_mgr.a_apl_charact_val_descr_val, value);
	if(value.IsEmpty())
		return _T("");

	CStringArray saDepot, saGrp;
	ParseRasc(value, _T(";"), _T("/"), &saDepot, &saGrp, true);

	if(saDepot.GetSize() > 0)
		return saDepot[0];

	return "";
}

CaplInstance* CaplComplectMgr::CreateComplect( CaplInstance *order, CaplInstance *komplect, CaplInstance *pdf )
{
	CString author;
	CaplInstance *currentPerson = m_api->m_appr_mgr.GetCurrentPerson();
	if(currentPerson)
		m_api->m_appr_mgr.GetPersonName(currentPerson, author);

	// на что нужно домножать
	double koeff = 1.0;
	CaplInstance *charact = m_api->m_charact_mgr.GetCharacteristicBN(APL_T("Коэффициент пересчета"));
	if(charact)
	{
		CaplFinder ff(DEF_SOURCE);
		ff.QuickFind(&m_api->m_data, true, 2, std::make_pair(m_api->m_charact_mgr.a_apl_charact_val_item, pdf),
			std::make_pair(m_api->m_charact_mgr.a_apl_charact_val_charact, charact));

		if(ff.m_innerExtent.Size)
			m_api->m_data.GetAttr(ff.m_innerExtent[0], m_api->m_charact_mgr.a_apl_charact_val_meas_val, koeff);
	}	

	// найдем элементы для существующего комплекта
	std::map<CaplInstance*, CaplInstance*> komplectOccurrences;
	std::map<std::pair<CaplInstance*, CaplInstance*>, CaplInstance*> bomOccurrences;

	CaplEntity *apl_cnf_bom_occurrence = m_api->m_data.GetEntityBN(_T("apl_cnf_bom_occurrence"));
	CaplAttr *komplect_occurrence = m_api->m_data.GetAttrDefinition(apl_cnf_bom_occurrence, _T("komplect_occurrence"));

	if(komplect != 0)
		GetExistingOccurrences(komplect, komplectOccurrences, bomOccurrences);		
	
	// создаем/обновляем комлект
	aplExtent chapters;
	m_api->m_data.GetAttrBN(komplect, _T("chapters"), chapters);

	CString currentDate;
	COleDateTime time;
	CString orderId = GetOrderId(order);
	m_api->m_data.NET_GetServerDateTime(time);
	aplDate2String(time, currentDate);

	// комплект	
	map<CaplInstance*, vector<CaplInstance*>>::iterator it;
	if(0 == komplect)
		komplect = m_api->m_data.CreateInstanceBN(_T("apl_cnf_komplect"));		

	for(it=m_relationsByEd.begin(); it!=m_relationsByEd.end(); ++it)	
	{
		double totalValue = 0.0;
		CaplInstance *pki = it->first;
		vector<CaplInstance*> &vec = it->second;
		map<CString, double> valueByShop;

		// apl_cnf_komplect_occurrence
		CaplInstance *komplectOccurrence = 0;
		std::map<CaplInstance*, CaplInstance*>::iterator komplOccIt = komplectOccurrences.find(pki);
		if(komplOccIt == komplectOccurrences.end())
		{
			komplectOccurrence = m_api->m_data.CreateInstanceBN(_T("apl_cnf_komplect_occurrence"));
			m_api->m_data.PutAttrBN(komplectOccurrence, _T("author"), author);
			m_api->m_data.PutAttrBN(komplectOccurrence, _T("creation_date"), currentDate);
		}
		else
		{
			komplectOccurrence = komplOccIt->second;
			komplectOccurrences.erase(komplOccIt);
		}		

		// apl_cnf_bom_occurrence
		for(unsigned int i=0; i<vec.size(); ++i)
		{
			double value = 0.0;
			m_api->m_data.GetAttr(vec[i], m_api->m_prd_mgr.a_apl_qacu_value, value);

			CaplInstance *ingItem = 0;
			m_api->m_data.GetAttr(vec[i], m_api->m_prd_mgr.a_pdr_r_ting, ingItem);

			CString shop = GetShopFromRasc(ingItem);
			if(shop.IsEmpty())
				int h = 0;
						
			// количество считаем рекурсивно вверх по составу
			value *= GetTotalPdfCount(ingItem);
			value *= koeff;

			CaplInstance *bomOccurrence = 0;
			std::map<std::pair<CaplInstance*, CaplInstance*>, CaplInstance*>::iterator bomIt = 
				bomOccurrences.find(std::make_pair(komplectOccurrence, vec[i]));

			if(bomIt == bomOccurrences.end())
			{
				bomOccurrence = m_api->m_data.CreateInstanceBN(_T("apl_cnf_bom_occurrence"));	
			}			
			else
			{
				bomOccurrence = bomIt->second;
				bomOccurrences.erase(bomIt);
			}

			m_api->m_data.PutAttrBN(bomOccurrence, _T("value"), value);
			m_api->m_data.PutAttrBN(bomOccurrence, _T("relation"), vec[i]);
			m_api->m_data.PutAttrBN(bomOccurrence, _T("komplect_occurrence"), komplectOccurrence);

			valueByShop[shop] += value;
			totalValue += value;
		}

		CaplInstance *chapter = 0;
		CString shopchain = GetShopChain(valueByShop);
		map<CaplInstance*, CaplInstance*>::iterator clssfIt = m_pkiClassifiers.find(pki);

		if(clssfIt != m_pkiClassifiers.end())
		{
			chapter = clssfIt->second;
			chapters.Add(chapter);
		}

		m_api->m_data.PutAttrBN(komplectOccurrence, _T("summ_value"), totalValue);
		m_api->m_data.PutAttrBN(komplectOccurrence, _T("item"), pki);
		m_api->m_data.PutAttrBN(komplectOccurrence, _T("shopchain"), shopchain);
		m_api->m_data.PutAttrBN(komplectOccurrence, _T("komplect"), komplect);
		m_api->m_data.PutAttrBN(komplectOccurrence, _T("chapter"), chapter);
		m_api->m_data.PutAttrBN(komplectOccurrence, _T("user"), m_api->m_data.GetCurrUser());
		m_api->m_data.PutAttrBN(komplectOccurrence, _T("date"), currentDate);

		// элемент лога
		CaplInstance *cnfLog = m_api->m_data.CreateInstanceBN(_T("apl_cnf_log"));
		if(cnfLog)
		{
			m_api->m_data.PutAttrBN(cnfLog, _T("komplect_occurrence"), komplectOccurrence);
			m_api->m_data.PutAttrBN(cnfLog, _T("date"), currentDate);
			m_api->m_data.PutAttrBN(cnfLog, _T("user"), m_api->m_data.GetCurrUser());
			m_api->m_data.PutAttrBN(cnfLog, _T("autor"), author);
			m_api->m_data.PutAttrBN(cnfLog, _T("delta"), totalValue);
			m_api->m_data.PutAttrBN(cnfLog, _T("item"), pki);
			m_api->m_data.PutAttrBN(cnfLog, _T("komplect"), komplect);
		}
	}

	// атрибуты комплекта
	if(komplect->GetId() == 0)
	{
		m_api->m_data.PutAttrBN(komplect, _T("id"), orderId);
		m_api->m_data.PutAttrBN(komplect, _T("is_made"), true);		
		m_api->m_data.PutAttrBN(komplect, _T("close_date"), currentDate);	
		m_api->m_data.PutAttrBN(komplect, _T("opening_date"), currentDate);	
		m_api->m_data.PutAttrBN(komplect, _T("shopchains_date"), currentDate);			
		m_api->m_data.PutAttrBN(komplect, _T("autor"), author);				 
	}

	CaplInstance *orderKS = 0;
	m_api->m_data.GetAttrBN(order, _T("modification"), orderKS);
	if(0 != orderKS)
	{
		CString orderKsName;
		m_api->m_prd_mgr.GetProductId(orderKS, &orderKsName);
		m_api->m_data.PutAttrBN(komplect, _T("name"), orderKsName);	
	}

	m_api->m_data.PutAttrBN(komplect, _T("is_made_shopchains"), true);		
	m_api->m_data.PutAttrBN(komplect, _T("date"), currentDate);	
	m_api->m_data.PutAttrBN(komplect, _T("chapters"), chapters);
	m_api->m_data.PutAttrBN(komplect, _T("user"), m_api->m_data.GetCurrUser());	
	

	// всё что осталось подлежит удалению из комплекта (убрано по просьбе Финохиной)
	/*for(std::map<CaplInstance*, CaplInstance*>::iterator it=komplectOccurrences.begin(); it!=komplectOccurrences.end(); ++it)
		m_api->m_data.DeleteInstance(it->second);

	for(std::map<std::pair<CaplInstance*, CaplInstance*>, CaplInstance*>::iterator it=bomOccurrences.begin(); it!=bomOccurrences.end(); ++it)
		m_api->m_data.DeleteInstance(it->second);*/

	m_api->SaveChanges();
	return komplect;
}

void CaplComplectMgr::FindClassifiers()
{
	aplExtent items;	
	CaplFinder ff(DEF_SOURCE);		
	
	map<CaplInstance*, vector<CaplInstance*>>::iterator it, nextIt;
	int clssfIndex = ff.CreateExt(m_api->m_classifier_mgr.e_apl_classifier_association);
		
	for(it=m_relationsByEd.begin(); it!=m_relationsByEd.end(); ++it)	
	{
		nextIt = it;		
		items.Add(it->first);

		if(items.Size == 500 || ++nextIt == m_relationsByEd.end())
		{
			ff.AddAttr(clssfIndex, m_api->m_classifier_mgr.a_apl_classifier_association_item, ff.CreateExt(items, true));
			ff.AddToResult(clssfIndex);
			ff.Find(m_api->m_data, true, false, false, true, true);

			for(int i=0; i<ff.m_innerExtent.Size; ++i)
			{
				CaplInstance *item = 0, *classifier = 0;
				m_api->m_data.GetAttr(ff.m_innerExtent[i], m_api->m_classifier_mgr.a_apl_classifier_association_item, item);
				m_api->m_data.GetAttr(ff.m_innerExtent[i], m_api->m_classifier_mgr.a_apl_classifier_association_classifier, classifier);
				
				if(item && classifier)
					m_pkiClassifiers[item] = classifier;
			}

			items.Clear();
			ff.Clear();
			clssfIndex = ff.CreateExt(m_api->m_classifier_mgr.e_apl_classifier_association);			
		}
	}
}

bool CaplComplectMgr::ShowRelationsWithoutShop()
{
	std::set<CaplInstance*> emptyShop;
	map<CaplInstance*, vector<CaplInstance*>>::iterator it;

	// находим связи без цеха-потребителя
	for(it=m_relationsByEd.begin(); it!=m_relationsByEd.end(); ++it)	
	{
		vector<CaplInstance*> &vec = it->second;						
		for(unsigned int i=0; i<vec.size(); ++i)
		{
			CaplInstance *ingItem = 0;
			m_api->m_data.GetAttr(vec[i], m_api->m_prd_mgr.a_pdr_r_ting, ingItem);

			map<CaplInstance*, CaplInstance*>::iterator rascIt = m_pdfsRasc.find(ingItem);
			if(rascIt == m_pdfsRasc.end())
			{
				emptyShop.insert(vec[i]);				
			}
			else
			{
				CString rasc;
				m_api->m_data.GetAttr(rascIt->second, m_api->m_charact_mgr.a_apl_charact_val_descr_val, rasc);

				if(rasc.IsEmpty())
					emptyShop.insert(vec[i]);
			}			
		}
	}

	if(emptyShop.size() == 0)
		return true;

	AfxMessageBox(APL_T("Были найдены детали без цеха-потребителя. Будет сформирован лог-файл."), MB_ICONINFORMATION);

	// показываем файл
	CStdioFile file;
	CString currentTime = m_api->m_data.NET_GetServerDateTime();
	CString  tmp_path; tmp_path.GetEnvironmentVariable(_T("temp"));
	CString filePath = tmp_path + CString(_T("\\upload_to_1c_error_") + currentTime + _T(".txt"));

	if(FALSE != file.Open(filePath, CFile::modeCreate|CFile::modeWrite))
	{
		aplExtent items;
		for(std::set<CaplInstance*>::iterator it=emptyShop.begin(); it!=emptyShop.end(); ++it)
		{
			CaplInstance *edItem = 0, *ingItem = 0;
			m_api->m_data.GetAttr(*it, m_api->m_prd_mgr.a_pdr_r_ted, edItem);
			m_api->m_data.GetAttr(*it, m_api->m_prd_mgr.a_pdr_r_ting, ingItem);

			items.Add(edItem);
			items.Add(ingItem);
		}
		m_api->LoadExtentInfo(items);

		for(std::set<CaplInstance*>::iterator it=emptyShop.begin(); it!=emptyShop.end(); ++it)
		{
			CaplInstance *edItem = 0, *ingItem = 0;
			m_api->m_data.GetAttr(*it, m_api->m_prd_mgr.a_pdr_r_ted, edItem);
			m_api->m_data.GetAttr(*it, m_api->m_prd_mgr.a_pdr_r_ting, ingItem);

			file.WriteString(APL_T("Нет цеха-потребителя между \"") + m_api->m_prd_mgr.GetProductId(ingItem) + APL_T("\" и \"") + 
				m_api->m_prd_mgr.GetProductId(edItem) + _T("\"\r\n"));
		}		

		file.Close();
		ShellExecute(0, _T("open"), filePath, 0, 0, SW_SHOW);
	}	

	return false;
}

