ABACS – биллинговая система
 Главная   Новости   О системе   Статьи   ABACS Inside   Поддержка   Контактная информация   Карта сайта 
Модуль «drmf_process» (функции процесса)

Файл определений "drmf_process.def"



module drmf_process;
import drmf_data;

	void	Processes_Init( TFindInfo &pInfo );
	void	Processes_Done();
	void	Processes_Solution();
	void	Processes_Start( TFindInfo &pInfo );
	void	Processes_Stop();
	bool	Processes_IsStarted();

	bool	Process_WriteToFile( string filename, string msg );
	bool	Process_WriteDetail_String( string msg );
	bool	Process_WriteDetail_Header();
	bool	Process_WriteDetail_Resume();
	void	Process_TrafficDifferent( TTraffic &traf );

	int	Processes_OpenLogins();
	int	Processes_ViewConnects( int hQue, string login );
	bool	Processes_InsertConnects( int pHandleMarker );
	bool	Processes_CopyConnects( string login, string speclogin );
	bool	Processes_ReadConnect( int hQue, TDialupConnectsView &recview );
	bool	Processes_PrintConnect( TDialupConnectsView &recview );

	int	Processes_AddValueSprAbon( string value, int paramcode );
	bool	Processes_AddPin( int pin, TAbonents &recabon );
	bool	Processes_LeavePin( int pin );
	bool	Processes_CopyServices(		int rpin,	int idparent_from,
						int specpin,	int idparent_to );
	bool	Processes_CopyDevice(		int rpin,	string login,
						int specpin,	string speclogin );
	bool	Processes_AddMaleFactor(	int rpin,	string login,
						int specpin,	string speclogin );

	string	Processes_NormalizeCID( string cid );
	int	Processes_OffsetIdConnect();
	int	Processes_OffsetPin();
	string	Processes_GetSpecLogin( string login );
	int	Processes_GetSpecIdConnect( int id );
	int	Processes_GetSpecPin( string cid );
//---------------------- Конец файла --------------------------

Файл кода "drmf_process.src"



module drmf_process;

import system;
import stdio;
import kitcomp;
import QTime;
import QStrings;
import QSet;
import QUtilities;
import QDbCtrl;
import Transact;
import drmf_data;
import drmf_dialog;
import drmf_db;
import drmf_log;

using module system;
using module stdio;
using module kitcomp;
using module QTime;
using module QStrings;
using module QSet;
using module QUtilities;
using module QDbCtrl;
using module Transact;
using module drmf_data;
using module drmf_dialog;
using module drmf_db;
using module drmf_log;
//------------------------------------------------------------
// Переменные
//------------------------------------------------------------
bool		vStateRun;
TFindInfo	vInfo;
int		vCQueOpen,	vCQueExec,	vCQueFree;
int		vAQueOpen,	vAQueExec,	vAQueFree;
float		vTrafOut,	vTrafInLight,	vTrafInNight;
int		vDuration;

class TLogins	{
		string	login;
};
TLogins    	vLogins[ 1 ];
//------------------------------------------------------------
// Функция конструктора и инициализации данных
// Сохраним входные параметры и подготовим переменные модуля
//------------------------------------------------------------
void Processes_Init( TFindInfo &pInfo )
{
	qsetModuleInit();
	vStateRun 		= false;
	vInfo.Login		= pInfo.Login;
	vInfo.CID		= pInfo.CID;
	vInfo.NData		= pInfo.NData;
	vInfo.KData		= pInfo.KData;
	vInfo.ReportFile	= pInfo.ReportFile;
	vInfo.DetailFile	= pInfo.DetailFile;
	vInfo.DbPointer		= pInfo.DbPointer;

	vCQueOpen 		= Dbase_HQuery_COpen();
	vCQueExec 		= Dbase_HQuery_CExec();
	vCQueFree 		= Dbase_HQuery_CFree();
	vAQueOpen 		= Dbase_HQuery_AOpen();
	vAQueExec 		= Dbase_HQuery_AExec();
	vAQueFree 		= Dbase_HQuery_AFree();
	if (	( vCQueOpen == 0 )	||
		( vCQueExec == 0 )	||
		( vCQueFree == 0 )	||
		( vAQueOpen == 0 )	||
		( vAQueExec == 0 )	||
		( vAQueFree == 0 )	) return;
	vDuration		= 0;
	vTrafOut		= 0;
	vTrafInLight		= 0;
	vTrafInNight		= 0;
	vStateRun 		= true;
	Log_SendMsg( "Proccess is started." );
}
//------------------------------------------------------------
// Функция деструктора модуля
//------------------------------------------------------------
void Processes_Done()
{
	vStateRun		= false;
	qsetModuleDone();
	Log_SendMsg( "Process is completed." );
}
//------------------------------------------------------------
// Установка разрядности CID до 6 знаков
//------------------------------------------------------------
string Processes_NormalizeCID( string cid )
{
	int len; string sres;
	len  = _StrLen( cid );
	while ( len < 6 ) {
		cid = "0" + cid;
		len  = _StrLen( cid );
	}
	sres = nomer;
	if ( len > 6 ) sres = _SubStr( cid, len - 5, 6 );
	return( sres );
}
//------------------------------------------------------------
// Возвращает специальный маркер 
// для отличия исходного и сформированного имени (login)
//------------------------------------------------------------
string Processes_GetSpecLabel()
{
	return( "*" );
}
//------------------------------------------------------------
// Преобразование исходного login в [*login*] нарушителя: 
//------------------------------------------------------------
string Processes_GetSpecLogin( string login )
{
	return( Processes_GetSpecLabel()	+
		login				+
		Processes_GetSpecLabel() );
}
//------------------------------------------------------------
// Смещение для номера записи (ID) в базе соединений
//------------------------------------------------------------
int Processes_OffsetIdConnect()
{
	return( 100000000 );
}
//------------------------------------------------------------
// Смещение для PIN
//------------------------------------------------------------
int Processes_OffsetPin()
{
	return( 2000000 );
}
//------------------------------------------------------------
// Преобразование исходных номеров записей в базе соединений
// в номера записей для нарушителя, 
// операция нужна при копировании информации
//------------------------------------------------------------
int Processes_GetSpecIdConnect( int id )
{
	return( id + Processes_OffsetIdConnect() );
}
//------------------------------------------------------------
// Преобразование CID в PIN нарушителя: [2 XXX XXX]
//------------------------------------------------------------
int Processes_GetSpecPin( string cid )
{
	return( _atol( Processes_NormalizeCID( cid ) ) + 
		Processes_OffsetPin() );
}
//------------------------------------------------------------
// Запись строки msg в файл с именем filename
//------------------------------------------------------------
bool Process_WriteToFile( string filename, string msg )
{
	TFile repfile; bool res = false;
	if ( !fopen( repfile, filename, "ab" ) ) return( res );
	res = fputs( msg, repfile );
	return( res && fclose( repfile ) );
}
//------------------------------------------------------------
bool Process_WriteDetail_String( string msg )
{
	return( Process_WriteToFile( vInfo.DetailFile, msg ) );
}
//------------------------------------------------------------
// Удаление соединений по login
//------------------------------------------------------------
bool Processes_KillConnectsByLogin( string login )
{
	string sql; bool bres;
	// удалить коннекты для логина
	_sprintf( sql, "delete from cdr_dialup_ext "		+
	" where id in (select id from cdr_dialup_tbl "		+
	" where (IDUSER=(select iduser from users "		+
	" where login='%s')))", login );
	if ( Dbase_InTransact_IC() ) Dbase_Rollback_IC();
	Dbase_Transact_IC();
	bres = qdbQueryExecute( vCQueFree, sql );
	if ( bres ) {
		_sprintf( sql, "delete from cdr_dialup_tbl "	+
		" where (IDUSER=(select iduser from "		+
		" users_dialup where login='%s'))", login );
		bres = qdbQueryExecute( vCQueFree, sql );
	}
	if ( bres ) Dbase_Commit_IC(); else Dbase_Rollback_IC();
	return( bres );
}
//------------------------------------------------------------
// Возвращает PIN по login
// На выходе: 
// (-1)	- ошибка,
// (0)	- нет PIN с таким логином, 
// (>0)	- PIN
//------------------------------------------------------------
int Processes_PinByRealLogin( string login )
{
	string sql, msg; int res; int deleted, idx; int ndata,kdata;
	_sprintf( msg, "Запрос PIN для login='%s'", login );
	Log_SendMsg( msg );
	_sprintf( sql,	"select sd.*, a.deleted from _____ sd, "        +
			" _____ d, _____ a "				+
			" where (sd.______=%s') and "			+
			" (sd._____=d.id) and (d._____=%ld) and "	+
			" (sd.n_data<=%ld) and (%ld<=sd.k_data) and "	+
			" (a.pin=sd.pin) order by sd.n_data",
			login, cCodeDev_Dialup, 
			qtAbacsByUnix( vInfo.KData ),
			qtAbacsByUnix( vInfo.NData ) );
	if ( !qdbQueryOpen( vAQueFree, sql ) ) {
		_sprintf( msg, "Сбой запроса, sql='%s'", sql );
		Log_SendErr( msg );
		return( -1 );
	}
	res = 0;
	if ( !qdbQueryIsEmpty( vAQueFree ) ) {
		qdbQueryFirst( vAQueFree );
		for( idx = 0; !qdbQueryEof( vAQueFree ); idx = idx + 1 ) {
			deleted = qdbValueAsInteger( vAQueFree, "deleted" );
			if ( ( deleted == 0 )||( idx == 0 ) ) 
				res = qdbValueAsInteger( vAQueFree, "pin" );
			qdbQueryNext( vAQueFree );
		}
	}
	_sprintf( msg, "PIN определен (%ld).", res );
	Log_SendMsg( msg );
	return( res );
}
//------------------------------------------------------------
// Проверка существования номера PIN
// На выходе: 
// ( -1) - ошибка, 
// ( 0 ) - нет такого PIN, 
// ( >0) - PIN есть, возвращается его номер и необходимая информация.
//------------------------------------------------------------
int Processes_ExistsPin( int pin, TAbonents &recabon )
{
	string sql, msg; int res; int idx; int ndata,kdata;
	_sprintf( msg, "Проверка существования договора PIN=%ld", pin );
	Log_SendMsg( msg );
	_sprintf( sql,	"select * from _____ where pin=%ld", pin );
	if ( !qdbQueryOpen( vAQueFree, sql ) ) {
		_sprintf( msg, "Сбой при запросе данных абонентов, " +
		"PIN=%ld, sql='%s'", pin, sql );
		Log_SendErr( msg );
		return( -1 );
	}
	res = 0;
	if ( !qdbQueryIsEmpty( vAQueFree ) ) {
		recabon.deleted	= qdbValueAsInteger( vAQueFree, "deleted" );
		recabon.pin	= qdbValueAsInteger( vAQueFree, "pin"     );
		recabon.cat	= qdbValueAsInteger( vAQueFree, "cat"     );
		res		= recabon.pin;
	}
	if ( res != 0 ) {
		_sprintf( msg, "Договор PIN=%ld уже существует.", pin );
		Log_SendMsg( msg );
	}
	else {
		_sprintf( msg, "Договор PIN=%ld не существует.", pin );
		Log_SendMsg( msg );
	}
	return( res );
}
//------------------------------------------------------------
// Запись заговлока отчета в файл с именем filename
//------------------------------------------------------------
bool Process_WriteDetail_Header()
{
	bool fres; string msg, msgcut;
	Log_SendMsg( "Формирование заголовка детализации..." );
	vDuration		= 0;
	vTrafOut		= 0;
	vTrafInLight	= 0;
	vTrafInNight	= 0;

	_sprintf( msg, "Протокол работы пользователя (CID %s) за период"+
		" с %s по %s %s%s%s%s%s%s%s%s\r\n",
		vInfo.CID, 
		qtUnixToDateAsRuShort( vInfo.NData ), 
		qtUnixToDateAsRuShort( vInfo.KData ),
		cDelimiter,cDelimiter,cDelimiter,cDelimiter,
		cDelimiter,cDelimiter,cDelimiter,cDelimiter );
	fres = Process_WriteDetail_String( msg );
	if ( fres ) {
		_sprintf( msg, "Имя входа%sВремя входа%sВремя выхода%s" +
		"Длительность(сек)%s", cDelimiter,cDelimiter,cDelimiter,cDelimiter );
		_sprintf( msgcut, "Исходящий трафик%sВходящий трафик "  +
		"c 09:00 до 01:00%sВходящий трафик c 01:00 до 09:00%s",
		cDelimiter,cDelimiter,cDelimiter );
		msg = msg + msgcut;
		_sprintf( msgcut, "Информация о сервере доступа%s"    +
		"Информация о CID\r\n", cDelimiter );
		msg = msg + msgcut;
		fres = Process_WriteDetail_String( msg );
	}
	if ( fres )
		Log_SendMsg( "Формирование заголовка детализации завершено." );
	else
		Log_SendErr( "Заголовок не сформирован." );
	return( fres );
}
//------------------------------------------------------------
// Запись итоговой строки в файле отчета с детализацией
//------------------------------------------------------------
bool Process_WriteDetail_Resume()
{
	bool fres; string msg;
	Log_SendMsg( "Запись итогов детализации..." );

	_sprintf( msg, "%s%s%s%ld%sсек%s%1.0f%s%1.0f%sбайт%s\r\n",
		cDelimiter,cDelimiter,cDelimiter,
		vDuration, cDelimiter,cDelimiter,
		vTrafInLight,cDelimiter,vTrafInNight,cDelimiter,
		cDelimiter,cDelimiter );
	fres = Process_WriteDetail_String( msg );

	_sprintf( msg, "%s%s%s%ld%sмин%s%1.3f%s%1.3f%sМб%s\r\n",
		cDelimiter,cDelimiter,cDelimiter,
		vDuration/60, cDelimiter, cDelimiter,
		vTrafInLight/cMB,cDelimiter,
		vTrafInNight/cMB,cDelimiter,
		cDelimiter,cDelimiter );
	if ( fres ) fres = Process_WriteDetail_String( msg );
	_sprintf( msg, "Руководитель отдела Электросвязи <_________>"+
		"%s%s%s_______________%s%s%s%s%s\r\n",
		cDelimiter,cDelimiter,cDelimiter,cDelimiter,
		cDelimiter,cDelimiter,cDelimiter,cDelimiter );
	if ( fres ) fres = Process_WriteDetail_String( msg );
	if ( fres ) 
		Log_SendMsg( "Запись итогов детализации завершена." );
	else
		Log_SendErr( "Запись итогов детализации не выполнена." );
	return( fres );
}
//------------------------------------------------------------
// Функция расчета дневного и ночного трафика, 
// на входе  - структура,
// на выходе - та же структура, но с расчетными данными
//------------------------------------------------------------
void	Process_TrafficDifferent( TTraffic &traf )
{
	int n_night, k_night, l_night, l_light;
	int lpoint, rpoint;
	int i; 
	float trin_speed, trout_speed;
	traf.inb_night = 0; traf.outb_night = 0;
	traf.inb_light = 0; traf.outb_light = 0;
	if ( traf.btime > traf.etime ) { 
		i		= traf.etime; 
		traf.etime	= traf.btime; 
		traf.btime	= i;
	}
	traf.ltime = traf.etime - traf.btime + 1;
	l_night = 0;
	n_night = qtUnixAddHours( qtUnixBeginDay( traf.btime ), 1 );
	k_night = qtUnixAddHours( qtUnixBeginDay( traf.btime ), 9 ) - 1;
	while( n_night <= traf.etime ) {
		if ( k_night >= traf.btime ) {
			// объединение отрезков с посекундной шкалой
			lpoint = traf.btime; 
			if ( lpoint < n_night ) lpoint = n_night;
			rpoint = traf.etime; 
			if ( rpoint > k_night ) rpoint = k_night;
			l_night = l_night + ( rpoint - lpoint ) + 1;
		}
		n_night = qtUnixAddDays( n_night, 1 );
		k_night = qtUnixAddDays( k_night, 1 );
	}
	l_light = traf.ltime - l_night; 
	if ( l_light < 0 ) l_light = 0;
	trin_speed 	= traf.inb/traf.ltime;
	trout_speed	= traf.outb/traf.ltime;
	traf.inb_night	= trin_speed  * l_night;
	traf.inb_light	= trin_speed  * l_light;
	traf.outb_night	= trout_speed * l_night;
	traf.outb_light	= trout_speed * l_light;
}
//------------------------------------------------------------
// Запрос устройств, использованных "нарушителем",
// заполняется массив vLogins[]
// (-1) - ошибка, 
// ( 0) - нет данных,
// (>0) - есть данные
//------------------------------------------------------------
int Processes_OpenLogins()
{
	string sql, errmsg; int idx;
	Log_SendMsg( "формирование списка устройств..." );
	if ( _StrLen( vInfo.Login ) == 0 ) {
		_sprintf( sql, " select distinct(login) from cdr_dialup_view "	+
		" where (cid like '%s') "					+
		" and (start_datetime<='%s') and (stop_datetime>='%s') "	+
		" order by login ",
		"%" + vInfo.CID, 
		qtUnixToDateTimeAsUsFull( vInfo.KData ),
		qtUnixToDateTimeAsUsFull( vInfo.NData ) );
	}
	else {
		_sprintf( sql, " select distinct(login) from cdr_dialup_view "	+
		" where (cid like '%s') and (login='%s') "			+
		" and (start_datetime<='%s') and (stop_datetime>='%s') ",
		"%" + vInfo.CID, 
		vInfo.Login,
		qtUnixToDateTimeAsUsFull( vInfo.KData ),
		qtUnixToDateTimeAsUsFull( vInfo.NData ) );

	}
	vLogins.resize(1);
	if ( !qdbQueryOpen ( vCQueFree, sql ) ) {
		_sprintf( errmsg, "Ошибка запроса: '%s'", sql );
		Log_SendErr( errmsg );
		Log_SendMsg( "Список устройств не сформирован." );
		return( -1 );
	}
	if ( qdbQueryIsEmpty( vCQueFree ) ) {
		_sprintf( errmsg, "Искомых устройств не обнаружено.", sql );
		Log_SendErr( errmsg );
		return( 0 );
	}
	qdbQueryFirst( vCQueFree );
	for( idx = 0; !qdbQueryEof( vCQueFree ); idx = idx + 1 ) {
		if ( idx == vLogins.size ) vLogins.resize( vLogins.size * 2 );
		vLogins[ idx ].login = qdbValueAsString ( vCQueFree, "login" );
		qdbQueryNext( vCQueFree );
		// ограничение на 200.000 логинов
		if ( idx > 200000 ) break;
	}
	qdbQueryClose( vCQueFree );
	if ( idx != 0 ) vLogins.resize( idx );
	Log_SendMsg( "Формирование списка устройств завершено." );
	return( 1 );
}
//------------------------------------------------------------
// Запрос соединений для устройства
// ( 0) - нет данных, 
// (-1) - ошибка, 
// (>0) - есть данные
//------------------------------------------------------------
int Processes_ViewConnects( int hQue, string login )
{
	string sql, msg;
	_sprintf( msg, "Запрос соединений для login='%s'", login );
	Log_SendMsg( msg );
	_sprintf( sql, " select * from cdr_dialup_view "		+
		" where (cid like '%s') and (login='%s') "		+
		" and (start_datetime<='%s') and (stop_datetime>='%s')"	+
		" order by start_datetime",
		"%" + vInfo.CID, login,
		qtUnixToDateTimeAsUsFull( vInfo.KData ),
		qtUnixToDateTimeAsUsFull( vInfo.NData ) );
	if ( !qdbQueryOpen ( hQue, sql ) ) {
		_sprintf( msg, "Сбой запроса соединений, sql='%s'", sql );
		Log_SendErr( msg );
		_sprintf( msg, "Запрос соединений для login='%s' не выполнен.", 
			login );
		Log_SendErr( msg );
		return( -1 );
	}
	_sprintf( msg, "Запрос соединений для login='%s' выполнен успешно.",
		login );
	Log_SendMsg( msg );
	if ( qdbQueryIsEmpty( hQue ) ) return( 0 );
	return( 1 );
}
//------------------------------------------------------------
// Запрос данных из базы соединений для набора ID
// (-1) - ошибка,
// ( 0) - нет данных, 
// (>0) - есть данные
//------------------------------------------------------------
bool Processes_InsertConnects( int pHandleMarker )
{
	string sql, msg, idlist; int cnt; bool bres = true;
	idlist 	= qsetMarkerGetList( pHandleMarker );
	cnt	= qsetMarkerCountItems( pHandleMarker );
	_sprintf( msg, "Добавление соединений, block size=%ld...", cnt );
	Log_SendMsg( msg );
	if ( cnt == 0 ) {
		_sprintf( msg, "Добавление соединений завершено. "+
		"Соединений для вставки нет." );
		Log_SendMsg( msg );
		return( bres );
	}
	_sprintf( sql, "insert into cdr_dialup_tbl select "		+
				"(ID + %ld) ID, "			+
				"_____, _____, _____,"			+
				"(IDUSER + %ld) IDUSER,"		+
				"_____,_____,_____,_____,_____,"	+
				"_____,_____,_____,_____,_____,"	+
				"_____,_____,_____,_____,_____,"	+
				"_____,_____,_____,_____,_____,"	+
				".....,.....,.....,.....,.....,"	+
				" from cdr_dialup_tbl where (id in (%s))",
				Processes_OffsetIdConnect(), 
				Processes_OffsetIdConnect(), 
				idlist );
	if ( Dbase_InTransact_IC() ) Dbase_Rollback_IC();
	Dbase_Transact_IC();
	bres = qdbQueryExecute( vCQueFree, sql );
	if ( bres ) {
		_sprintf( sql, "insert into cdr_dialup_ext select " +
					"(ID + %ld) ID,"		+
					"_____,_____,_____,"		+
					"_____,_____,_____,"		+
					"_____,_____ from "		+
					"cdr_dialup_ext where (id in (%s))",
					Processes_OffsetIdConnect(), 
					idlist );
		bres = qdbQueryExecute( vCQueFree, sql );
	}
	if ( bres ) {
		Dbase_Commit_IC();	
		_sprintf( msg, "Добавление соединений выполнена успешно." );
		Log_SendMsg( msg );
	} 
	else {
		Dbase_Rollback_IC();
		_sprintf( msg, "Добавление соединений не выполнена." );
		Log_SendErr( msg );
	}
	return( bres );
}
//------------------------------------------------------------
// Чтение полей текущей записи в структуру
//------------------------------------------------------------
bool Processes_ReadConnect( int hQue, TDialupConnectsView &recview )
{
	bool res = false;
	qdbClearError();
	recview.id		= qdbValueAsInteger( hQue, "id"			);
	recview.login		= qdbValueAsString ( hQue, "login"		);
	recview.start_datetime	= qdbValueAsString ( hQue, "start_datetime"	);
	recview.stop_datetime	= qdbValueAsString ( hQue, "stop_datetime"	);
	recview.sess_time	= qdbValueAsInteger( hQue, "sess_time"		);
	recview.acctin		= qdbValueAsInteger( hQue, "acctin"		);
	recview.acctout		= qdbValueAsInteger( hQue, "acctout"		);
	recview.callsrv		= qdbValueAsString ( hQue, "callsrv"		);
	recview.cid		= qdbValueAsString ( hQue, "cid"		);
	if ( qdbGetLastErrorCode() == qdbcSuccess ) res = true;
	return( res );
}
//------------------------------------------------------------
// Запись данных в отчет
//------------------------------------------------------------
bool Processes_PrintConnect( TDialupConnectsView &recview )
{
	string msg; bool fres = false;
	string scid;  int lcid; 
	string scall; int lcall; 
	TTraffic traf;
	scid		= Processes_NormalizeCID( recview.cid );
	scall		= Processes_NormalizeCID( recview.callsrv );
	traf.btime	= qtDateTimeAsUsFullToUnix( recview.start_datetime );
	traf.etime	= qtDateTimeAsUsFullToUnix( recview.stop_datetime );
	traf.inb	= recview.acctin;
	traf.outb	= recview.acctout;
	Process_TrafficDifferent( traf );
	_sprintf( msg, "%s%s%s%s%s%s%ld%s%1.0f%s%1.0f%s%1.0f%s%s%s%s\r\n",
		recview.login,		cDelimiter,
		recview.start_datetime,	cDelimiter,
		recview.stop_datetime,	cDelimiter,
		recview.sess_time,	cDelimiter,
		traf.outb,		cDelimiter,
		traf.inb_light,		cDelimiter,
		traf.inb_night,		cDelimiter,
		scall,			cDelimiter,
		scid                             );
	fres = Process_WriteDetail_String( msg );
	if ( fres ) {
		vDuration	= vDuration	+ traf.ltime;
		vTrafOut	= vTrafOut	+ traf.outb;
		vTrafInLight	= vTrafInLight 	+ traf.inb_light;
		vTrafInNight	= vTrafInNight	+ traf.inb_night;
	}
	return( fres );
}
//------------------------------------------------------------
// Добавляет произвольные значения в справочник
// Возвращает: 
// ID != 0, если успешно. 
// ID == 0, если неудача.
//------------------------------------------------------------
int Processes_AddValueSprAbon( string value, int paramcode )
{
	int id = 0; string sql;
	_sprintf( sql, "select id from _____ where (val='%s') and "	+
		" (parent=%ld)", value, paramcode );
	if ( !qdbQueryOpen( vAQueFree, sql ) ) return( id );
	if ( !qdbQueryIsEmpty( vAQueFree ) ) {
		id = qdbValueAsInteger( vAQueFree, "id" );
		return( id );
	}
	id = quGetIdent( false );
	_sprintf( sql, "insert into _____ (id,parent,data,val) values "	+
	" (%ld,%ld,%ld,'%s')", id, paramcode, qtAbacsTimeNow(), value );
	if ( !qdbQueryExecute( vAQueFree, sql ) ) id = 0;
	return( id );
}
//------------------------------------------------------------
// Добавляет договор. На выходе: 
// false	- ошибка, 
// true		- успешно.
//------------------------------------------------------------
bool Processes_AddPin( int pin, TAbonents &recabon )
{
	string	sql, msg;
	int	id[ 10 ];
	bool	res	= false;
	string	fio	= "MaleFactor_"+ _IntToStr( pin );
	string	alias	= "MaleFactor_"+ _IntToStr( pin );

	// Возможно договор уже существует?
	if ( Processes_ExistsPin( specpin, recabon ) != 0 ) return( true ); 

	_sprintf( msg, "Добавление договора PIN=%ld", pin );
	Log_SendMsg( msg );

	// Поправить справочник реквизитов при необходимости
	if ( ( id[ 1 ] = Processes_AddValueSprAbon( fio, 0 ) ) == 0 )
		return( res );
	if ( ( id[ 2 ] = Processes_AddValueSprAbon( "_____", 2 ) ) == 0 )
		return( res );
	if ( ( id[ 3 ] = Processes_AddValueSprAbon( "_____", 5 ) ) == 0 )
		return( res );
	if ( ( id[ 4 ] = Processes_AddValueSprAbon( "_____", 7 ) ) == 0 )
		return( res );
	// Сформировать виртуальный адрес "нарушителя"
	id[ 0 ] = quGetIdent( false );
	_sprintf( sql, 	" insert into _____ "		+
		" (id,pin,_____,data,strana,indexp,"	+
		" _____,city,street,_____,corp,pd,kv,"	+
		" _____,_____) values "			+
		" (%ld,%ld,%ld,%ld,%ld,'%s',%ld,%ld,"	+
		"%ld,'%s','%s','%s','%s',%ld,'%s')",
		id[ 0 ],pin,2,qtAbacsTimeNow(),id[ 4 ],
		"443000",0,id[ 3 ],id[ 2 ],
		"156","","","",0,"" );
	if ( !qdbQueryExecute( vAQueFree, sql ) ) {
		_sprintf( msg, "Сбой при выполнении запроса, sql='%s'", 
			sql );
		Log_SendErr( msg );
		return( res );
	}
	// Добавить pin "нарушителя"
	_sprintf( sql, " insert into _____ "		+
		" (deleted,pin,cat,data,datar,"		+
		" _____,_____,_____,_____,_____,_____,"	+
		" _____,_____,_____,_____) values "	+
		" (%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,"	+
		"%ld,%ld,'%s',%ld,%ld,%ld,%ld)",
		0, pin, 0, 
		qtAbacsTimeNow(), 
		qtAbacsByUnix( qtDateAsRuLongToUnix("01.01.1980") ),
		0, id[ 1 ], 0, 0, 1, alias, 0, 0, 0, 0 );
	res = qdbQueryExecute( vAQueFree, sql );
	if ( res ) 
		res = ( Processes_ExistsPin( specpin, recabon ) != 0 );
	else {
		_sprintf( msg, "Сбой при выполнении запроса, sql='%s'",
			sql );
		Log_SendErr( msg );
	}
	if ( res ) {
		_sprintf( msg, "Добавление договора выполнено, PIN=%ld", 
			pin );
		Log_SendMsg( msg );
	}
	else {
		_sprintf( msg, "Добавление договора не выполнено, PIN=%ld",
			pin );
		Log_SendErr( msg );
	}
	return( res );
}
//------------------------------------------------------------
// Восстановление договора
// На выходе: 
// false	- ошибка, 
// true		- успешно.
//------------------------------------------------------------
bool Processes_LeavePin( int pin )
{
	string sql,msg; bool res = false;
	_sprintf( msg, "Восстановление договора, PIN=%ld...", pin );
	Log_SendMsg( msg );
	_sprintf( sql,"update _____ set deleted=%ld where (pin=%ld)", 
		0, pin );
	res = qdbQueryExecute( vAQueFree, sql );
	if ( res ) {
		_sprintf( msg, "Восстановление договора выполнено, PIN=%ld", 
			pin );
		Log_SendMsg( msg );
	}
	else {
		_sprintf( msg, "Сбой при выполнении запроса, sql='%s'", 
			sql );
		Log_SendMsg( msg );
	}
	return( res );
}
//------------------------------------------------------------
// Удалить существующие услуги на устройстве
//------------------------------------------------------------
bool Processes_DeleteServices( int idparent )
{
	string sql, msg; bool bres = false;
	_sprintf( msg, "Удаление услуг на устройстве id=%ld...", 
		idparent );
	Log_SendMsg( msg );
	_sprintf( sql,	"delete from _____ where parent "	+
		" in (select id from _____ where (idparent=%ld))",
		idparent );
	if ( Dbase_InTransact_Abacs() ) Dbase_Rollback_Abacs();
	Dbase_Transact_Abacs();
	bres = qdbQueryExecute( vAQueFree, sql );
	if ( bres ) {
		_sprintf( sql,	"delete from _____ "		+
			" where (idusl in (select id from "	+
			" _____ where (idparent=%ld)))",  
			idparent );
		bres = qdbQueryExecute( vAQueFree, sql );
		if ( bres ) {
			_sprintf( sql,	"delete from _____ "	+
			" where (idparent=%ld)",
			idparent );
			bres = qdbQueryExecute( vAQueFree, sql );
		}
	}
	if ( bres ) {
		Dbase_Commit_Abacs(); 
		_sprintf( msg, "Услуги на устройстве id=%ld удалены.",
			idparent );
		Log_SendMsg( msg );
	}
	else {
		Dbase_Rollback_Abacs();
		_sprintf( msg, "Услуги на устройстве id=%ld не удалены.", 
			idparent );
		Log_SendErr( msg );
	}
	return( bres );
}
//------------------------------------------------------------
// Удалить установленное устройство 
//------------------------------------------------------------
bool Processes_DeleteDevice( int pin, string login )
{
	string sql,msg; bool res = false;
	_sprintf( msg, "Удаление устройства '%s'с договора PIN=%ld...",
		login, pin );
	Log_SendMsg( msg );
	_sprintf( sql, " delete from _____ where "	+
		" (_____='%s' ) and (pin=%ld) "	+
		" and (iddrive in (select id from _____ where code=%ld))",
		login, pin, cCodeDev_Dialup );
	res = qdbQueryExecute( vAQueFree, sql );
	if ( res ) {
		_sprintf( msg, "Удаление устройства '%s'завершено.", login );
		Log_SendMsg( msg );
	}
	else {
		_sprintf( msg, "Сбой при запросе, sql='%s'", sql );
		Log_SendErr( msg );
	}
	return( res );
}
//------------------------------------------------------------
// Копирование услуг (с одного устройства на другое)
//------------------------------------------------------------
bool Processes_CopyServices(	int rpin,	int idparent_from, 
				int specpin,	int idparent_to )
{
	string	sql, msg; 
	TSetUsl	recusl[ 256 ]; 
	int	idx, idy, newid;
	bool	res = false;
	_sprintf( msg, "Копирование услуг с iddrv1=%ld на iddrv2=%ld...", 
		idparent_from, idparent_to );
	Log_SendMsg( msg );
	if ( !Processes_DeleteServices( idparent_to ) ) return( res );
	// Запросить услуги устройства-источника
	_sprintf( sql, " select 1 tag, su.*, sr.n_data rem_n_data, "	+
		" sr.k_data rem_k_data, sr.flags rem_flags, э		+
		" sr.id rem_id from _____ su, _____ sr where "		+
		" su.id = sr.parent and su.idparent=%ld and "		+
		" su.pin = %ld union "					+
		" select 0 tag, su.*, 0 rem_n_data, 0 rem_k_data, "	+
		" 0 rem_flags, 0 rem_id from _____ su "			+
		" where not exists (select id from _____ where "	+
		" su.id = _____.parent) and "				+
		" su.idparent=%ld and su.pin = %ld order by 7",
		idparent_from, rpin, idparent_from, rpin );
	if ( !qdbQueryOpen( vAQueFree, sql ) ) {
		_sprintf( msg, "Сбой выполнения запроса sql='%s'", sql );
		Log_SendErr( msg );
		_sprintf( msg, "Копирование услуг не выполнено." );
		Log_SendErr( msg );
		return( res );
	}
	res = qdbQueryIsEmpty( vAQueFree );
	if ( res ) {
		_sprintf( msg, "Копирование услуг завершено. Скопировано 0 услуг." );
		Log_SendMsg( msg );
		return( res );
	}
	for( idx = 0; !qdbQueryEof( vAQueFree ); idx = idx + 1 ) {
		qdbClearError();
		recusl[ idx ].tag	= qdbValueAsInteger( vAQueFree,"tag"		);
		recusl[ idx ].id 	= qdbValueAsInteger( vAQueFree,"id"		);
		recusl[ idx ].pin	= qdbValueAsInteger( vAQueFree,"pin"		);
		recusl[ idx ].idparent 	= qdbValueAsInteger( vAQueFree,"idparent"	);
		recusl[ idx ].iddrive	= qdbValueAsInteger( vAQueFree,"iddrive"	);
		recusl[ idx ].idusl	= qdbValueAsInteger( vAQueFree,"idusl"		);
		recusl[ idx ].n_data	= qdbValueAsInteger( vAQueFree,"n_data"		);
		recusl[ idx ].k_data	= qdbValueAsInteger( vAQueFree,"k_data"		);
		recusl[ idx ].iddoc	= qdbValueAsInteger( vAQueFree,"iddoc"		);
		recusl[ idx ].rem	= qdbValueAsString ( vAQueFree,"rem"		);
		recusl[ idx ].idcalc	= qdbValueAsInteger( vAQueFree,"idcalc"		);
		recusl[ idx ].mem.parent= recusl[ idx ].id;
		recusl[ idx ].mem.n_data= qdbValueAsInteger( vAQueFree,"rem_n_data"	);
		recusl[ idx ].mem.k_data= qdbValueAsInteger( vAQueFree,"rem_k_data"	);
		recusl[ idx ].mem.flags	= qdbValueAsInteger( vAQueFree,"rem_flags" 	);
		recusl[ idx ].mem.id	= qdbValueAsInteger( vAQueFree,"rem_id"    	);
		if ( qdbGetLastErrorCode() != qdbcSuccess ) break;
		qdbQueryNext( vAQueFree );
	}
	qdbQueryClose( vAQueFree );
	if ( !trGetTransactState() ) trStartTransact();
	if ( trGetTransactState() ) {
	      	if ( trSetSysLogLs( lsUpdateUslForDrvSpec ) ) {
			// Перенести услуги на второе устройство
			for( idy = 0; idy < idx; idy = idy + 1 ) {
				newid = quGetIdent( false );
				_sprintf( sql,	"insert into _____ "	+
					" (id,pin,idparent,iddrive,"	+
					" idusl,n_data,k_data,iddoc,"	+
					" rem,idcalc) values "		+
					" (%ld,%ld,%ld,%ld,%ld,%ld,"	+
					" %ld,%ld,'%s',%ld)",
					newid, specpin, idparent_to,
					recusl[ idy ].iddrive, 
					recusl[ idy ].idusl,
					recusl[ idy ].n_data, 
					recusl[ idy ].k_data, 
					recusl[ idy ].iddoc,
					recusl[ idy ].rem,
					recusl[ idy ].idcalc );
	      			if ( !trAddTransact( sql ) ) break;
				// перенести историю услуги
				if ( recusl[ idy ].tag == 1 ) {
					recusl[ idy ].mem.parent = newid;
					newid = quGetIdent( false );
					_sprintf( sql, "insert into __"	+
					" (id,parent,n_data,k_data,"	+
					" flags) values(%ld,%ld,%ld,"	+
					" %ld,%ld)",
					newid,
					recusl[ idy ].mem.parent,
					recusl[ idy ].mem.n_data,
					recusl[ idy ].mem.k_data,
					recusl[ idy ].memr.flags );
	      				if ( !trAddTransact( sql ) ) break;
				}
			}
			if ( idy == idx ) res = trExecuteTransact();
		}
	}
	trStopTransact();
	if ( res ) {
		_sprintf( msg, "Копирование услуг завершено."	+
		" Скопировано %ld услуг.", idx );
		Log_SendMsg( msg );
	}
	else {
		_sprintf( msg, "Копирование услуг не выполнено.",  );
		Log_SendErr( msg );
	}
	return( res );
}
//------------------------------------------------------------
// Копирование устройства (с одного договора на другой)
//------------------------------------------------------------
bool Processes_CopyDevice(	int rpin,	string login,
				int specpin,	string speclogin )
{
	string		sql,msg; 
	TSetDrive	recdrv; 
	int		newid;
	bool		res = false;
	_sprintf( msg, "Копирование устройства '%s' с PIN1=%ld на PIN2=%ld...", 
		login, rpin, specpin );
	Log_SendMsg( msg );
	// Удалить существующее устройство
	if ( !Processes_DeleteDevice( specpin, speclogin ) ) {
		Log_SendErr( "Копирование устройств не выполнено." );
		return( res );
	}
	// Запросить устройство с PIN1
	_sprintf( sql, "select sd.* from _____ sd, drive d "	+
		" where (sd._____='%s') and (sd.iddrive=d.id) "	+
		" and (d.code=%ld) and (sd.pin=%ld)", 
		login, cCodeDev_Dialup, rpin );
	if ( !qdbQueryOpen( vAQueFree, sql ) ) {
		_sprintf( msg, "Ошибка чтения устройства, sql='%s'", sql );
		Log_SendErr( msg );
		_sprintf( msg, "Копирование устройства '%s' не выполнено.", 
			login );
		Log_SendErr( msg );
		return( res );
	}
	qdbClearError();
	recdrv.id	= qdbValueAsInteger( vAQueFree, "id"		);
	recdrv.pin	= qdbValueAsInteger( vAQueFree, "pin"		);
	recdrv.iddrive	= qdbValueAsInteger( vAQueFree, "iddrive"	);
	recdrv.n_data	= qdbValueAsInteger( vAQueFree, "n_data"	);
	recdrv.k_data	= qdbValueAsInteger( vAQueFree, "k_data"	);
	recdrv.rem	= qdbValueAsString ( vAQueFree, "rem"		);
	recdrv.numer	= qdbValueAsInteger( vAQueFree, "numer"		);
	recdrv.numer_str= qdbValueAsString ( vAQueFree, "numer_str"	);
	recdrv.col	= qdbValueAsInteger( vAQueFree, "col"		);
	if ( qdbGetLastErrorCode() != qdbcSuccess ) {
		_sprintf( msg, "Ошибка чтения значений , sql='%s'", sql );
		Log_SendErr( msg );
		_sprintf( msg, "Копирование устройства '%s' не выполнено.", 
			login );
		Log_SendErr( msg );
		return( res );
	}
	qdbQueryClose( vAQueFree );
	newid = quGetIdent( false );
	if ( !trGetTransactState() ) trStartTransact();
	if ( trGetTransactState() ) {
	      	if ( trSetSysLogLs( lsUpdateDriveSpec ) ) {
			// Перенести устройство на PIN2
			_sprintf( sql, "insert into ____ "	+
			" (id,pin,iddrive,n_data,k_data,rem,"	+
			" numer,numer_str,col) values "		+
			" (%ld,%ld,%ld,%ld,%ld,"		+
			" '%s',%ld,'%s',%ld)",
			newid, specpin,
			recdrv.iddrive,
			recdrv.n_data,
			recdrv.k_data,
			recdrv.rem,
			recdrv.numer,
			speclogin, recdrv.col );
      			if ( trAddTransact( sql ) ) res = trExecuteTransact();
		}
	}
	trStopTransact();
	if ( res ) res = Processes_CopyServices( rpin, recdrv.id, specpin, newid );
	if ( res ) {
		_sprintf( msg, "Устройство '%s' скопировано. "	+
		"Новое имя '%s', PIN=%ld.", login, rpin, speclogin, specpin );
		Log_SendMsg( msg );
	}
	else {
		_sprintf( msg, "Копирование устройства '%s' не выполнено.",
			login );
		Log_SendErr( msg );
	}
	return( res );
}
//------------------------------------------------------------
// Добавление клиента: 
// договор (PIN), устройство (login) и связанных услуг
//------------------------------------------------------------
bool Processes_AddMaleFactor(	int rpin,	string login,
				int specpin,	string speclogin )
{
	int r; string sql, msg; bool bres = false;
	TAbonents recabon;
	_sprintf( msg, "Добавление договора PIN=%ld, login='%s'",
		specpin, speclogin );
	Log_SendMsg( msg );
	bres = Processes_AddPin( specpin, recabon );
	if ( bres ) {
		// Восстановить договор, если был закрыт
		if ( recabon.deleted != 0 ) {
			bres = Processes_LeavePin( specpin );
			if ( bres ) recabon.deleted = 0;
		}
		bres = ( recabon.deleted == 0 );
		if ( !bres ) return( bres );
		bres = Processes_CopyDevice( rpin, login, specpin, speclogin );
	}
	if ( bres ) {
		_sprintf( msg, "Добавление договора PIN=%ld, "	+
		" login='%s' выполнено успешно.", specpin, speclogin );
		Log_SendMsg( msg );
	}
	else {
		_sprintf( msg, "Добавление договора PIN=%ld, "	+
		"login='%s' не выполнено.", specpin, speclogin );
		Log_SendErr( msg );
	}
	return( bres );
}
//------------------------------------------------------------
// Копирование соединений
//------------------------------------------------------------
bool Processes_CopyConnects( string login, string speclogin )
{
	string sql,msg;
	int num,idx,idy,idz,newid; 
	int hMarker; 
	bool bres;

	_sprintf( msg, "Копирование соединений с login1='%s' на login2='%s'",
		login, speclogin );
	Log_SendMsg( msg );
	// Удалить соединения от прошлой задачи
	if ( !Processes_KillConnectsByLogin( speclogin ) )
		return( false );
	num = Processes_ViewConnects( vCQueOpen, login );
	if ( num < 0 ) {
		_sprintf( msg, "Копирование соединений не выполнено." );
		Log_SendErr( msg );
		return( false );
	}
	if ( num == 0 ) {
		_sprintf( msg, "Копирование соединений выполнено успешно." );
		Log_SendMsg( msg );
		return( true );
	}
	// Создать маркер для множества номеров записей
	hMarker = qsetMarkerCreate();
	if ( hMarker == qsetHandleError ) {
		_sprintf( msg, "Копирование соединений не выполнено. "	+
		"Не создан объект маркера." );
		Log_SendErr( msg );
		return( false );
	}
	qdbQueryFirst( vCQueOpen );
	// Оптимистическое предположение результата
	bres	= true;
	// Основной цикл копирования
	while( !qdbQueryEof( vCQueOpen )&&( bres ) ) {
		// Очистить набор ID
		qsetMarkerClear( hMarker );
		// Создать набор из 256 ID (точнее, не больше это числа)
		for( idx = 0; !qdbQueryEof( vCQueOpen ); idx = idx + 1 ) {
			if ( idx == 256 ) break;
			qsetMarkerCheckItem( hMarker, 
				qdbValueAsInteger( vCQueOpen, "id" ), true );
			qdbQueryNext( vCQueOpen );
		}
		qsetMarkerMove( hMarker, 0 );
		// Запрос записей с набором ID из таблицы соединений
		bres = Processes_InsertConnects( hMarker );
	}
	// Закрыть курсор
	qdbQueryClose( vCQueOpen );
	// Удалить объект маркера
    	qsetMarkerDelete( hMarker );
	if ( bres ) {
		_sprintf( msg, "Копирование соединений выполнено успешно." );
		Log_SendMsg( msg );
	}
	else {
		_sprintf( msg, "Копирование соединений не выполнено." );
		Log_SendErr( msg );
	}
	return( bres );
}
//------------------------------------------------------------
// Построение отчета
//------------------------------------------------------------
void Processes_Solution()
{
	string			sql, msg, lcur, ltot, slogin, slabel; 
	int			idx, idy, rpin, spin, num, nrec;
	int			steplogin, stepstage, stage;
	TDialupConnectsView	recview;
	bool			bres;
	nrec			= 0;
	slabel			= Processes_GetSpecLabel();
	Dialog_OpenProgressBar();
	_sprintf( ltot, "Старт процесса." );
	_sprintf( lcur, "Запрос имен пользователей." );
	Dialog_SetProgressBar( ltot, lcur, 0, 0 );
	// Запрос использованных устройств
	num = Processes_OpenLogins();
	_sprintf( lcur, "Запрос завершен." );
	Dialog_SetProgressBar( "", lcur, 0, 100 );
	// Проверка наличия устройств и печать заголовка отчета
	if ( num <= 0 ) {
		Dialog_CloseProgressBar();
		_printf( "Процесс завершен. Нет искомых устройств." );
		return;
	};
	if ( !Process_WriteDetail_Header() ) {
		Dialog_CloseProgressBar();
		_printf( "Процесс завершен. Ошибка записи заголовка отчета." );
		return;
	}
	spin		= Processes_GetSpecPin( vInfo.CID );
	steplogin	= 100 / vLogins.size;
	stepstage	= steplogin / 4;
	stage		= 100 / 4;
	// Для каждого устройства...
	for( idx = 0; idx < vLogins.size; idx += 1 ) {
		if ( _StrLen( vLogins[ idx ].login ) == 0 ) continue;
		if ( _SubStr( vLogins[ idx ].login, 1,
		_StrLen( Processes_GetSpecLabel() ) ) == Processes_GetSpecLabel() )
			continue;
		rpin	= Processes_PinByRealLogin( vLogins[ idx ].login );
		if( rpin == 0 ) continue;
		slogin	= Processes_GetSpecLogin( vLogins[ idx ].login );

		_sprintf( ltot, "Генерация данных на основе login='%s'...",
			vLogins[ idx ].login );
		_sprintf( lcur, "Добавление договора N%ld для login='%s'...",
			spin, slogin );
		Dialog_SetProgressBar(	ltot, lcur, 
					idx*steplogin + 0*stepstage,
					0*stage );
		// добавить "нарушителя" в список абонентов
		if ( !Processes_AddMaleFactor(	rpin, vLogins[ idx ].login,
						spin, slogin ) ) break;

		_sprintf( lcur, "Копирование соединений с '%s' на '%s'...",
			vLogins[ idx ].login, slogin );
		Dialog_SetProgressBar(	ltot, lcur,
					idx*steplogin + 1*stepstage,
					1*stage );
		// Скопировать соединения "нарушителя"
		if ( !Processes_CopyConnects( vLogins[ idx ].login, slogin ) )
			break;
		
		_sprintf( lcur, "Запрос соединений для '%s'...", slogin );
		Dialog_SetProgressBar(	ltot, lcur,
					idx*steplogin + 2*stepstage,
					2*stage );
		// Сформировать детализацию
		num = Processes_ViewConnects( vCQueOpen, slogin );

		_sprintf( lcur, "Расчет и запись соединений для '%s'...",
			slogin );
		Dialog_SetProgressBar(	ltot, lcur,
					idx*steplogin + 3*stepstage,
					3*stage );
		if ( num > 0 ) {
			qdbQueryFirst( vCQueOpen );
			for( idy = 0; !qdbQueryEof( vCQueOpen ); idy = idy + 1 ) {
				// Чтение данных из текущей записи курсора
				if ( !Processes_ReadConnect( vCQueOpen, recview ) )
					break;
				if ( !Processes_PrintConnect( recview ) )
					break;
				qdbQueryNext( vCQueOpen );
				nrec += 1;
			}
		}
		_sprintf( ltot, "Генерация данных на основе login='%s' завершена.",
			vLogins[ idx ].login );
		_sprintf( lcur, "Запись детализации для '%s'завершена.",
			slogin );
		Dialog_SetProgressBar(	ltot, lcur,
					idx*steplogin + 4*stepstage,
					4*stage );
	}
	if ( nrec > 0 ) {
		_sprintf( ltot, "Запись итоговых данных..." );
		Dialog_SetProgressBar( ltot, "", 99, 99 );
		Process_WriteDetail_Resume();
	}
	_sprintf( ltot, "Процесс завершен." );
	_sprintf( lcur, "Процесс завершен." );
	Dialog_SetProgressBar( ltot, lcur, 100, 100 );

	Dialog_CloseProgressBar();

	if ( idx == vLogins.size )
		_printf("Процесс завершен. Сформирован договор, PIN=%ld",spin);
	else 
		_printf("Процесс формирования договора %ld прошел неудачно.",spin);
}
//------------------------------------------------------------
// Функция внешнего запуска
//------------------------------------------------------------
void Processes_Start( TFindInfo &pInfo )
{
	Processes_Init( pInfo );
	if ( Processes_IsStarted() ) Processes_Solution();
	Processes_Done();
}
//------------------------------------------------------------
// Отложеный останов процессов
//------------------------------------------------------------
void Processes_Stop()
{
	vStateRun = false;
}
//------------------------------------------------------------
// Проверка состояния
//------------------------------------------------------------
bool Processes_IsStarted()
{
	return( vStateRun );
}
//---------------------- Конец файла -------------------------


Список файлов проекта «DRMF»  


Примеры:

 


Подробнее об «ABACS»  


Яндекс.Метрика