#include <windows.h>
#include <stdio.h> // sprintf ()
#include <string>
#include "\works\h\maelstrom.h"
#include "client.h"
#include "config.h"
#include "expense.h"
#include "main.h" // fnGetToday ()
#include "page_reg.h"
#include "page_sms.h" // fnGetPhone ()
#include "page_tuning.h"
#include "read_ini.h"
#include "s_date.h"
#include "s_file_io.h"
#include "s_forms.h"
#include "s_group.h"
#include "s_org.h"
#include "s_service.h"
#include "s_spec.h"
#include "visit.h"
using namespace std;
// ассоциативные массивы
static std::auto_ptr<A_ARRAY> login_date1 (new A_ARRAY); // "имя входа/дата1"
static std::auto_ptr<A_ARRAY> login_date2 (new A_ARRAY); // "имя входа/дата2"
static std::auto_ptr<A_ARRAY> login_time1 (new A_ARRAY); // "имя входа/время1"
static std::auto_ptr<A_ARRAY> login_time2 (new A_ARRAY); // "имя входа/время2"
static std::auto_ptr<A_ARRAY> login_prefix (new A_ARRAY); // "имя входа/префикс"
static std::auto_ptr<A_ARRAY> login_group (new A_ARRAY); // "имя входа/группа"
static std::auto_ptr<A_ARRAY> login_visitflag (new A_ARRAY); // "имя входа/флажок посещения"
static std::auto_ptr<A_ARRAY> login_org (new A_ARRAY); // "имя входа/организация-плательщик"
// меню выбора флажка посещений для фильтра
static void fnVisitFlagsSelectFilter (QUERY *query,int iId)
{
string s;
if (iId < 0)
s = "<select name=visit_flag><option selected value=\"-1\">Не использовать";
else
s = "<select name=visit_flag><option value=\"-1\">Не использовать";
if (config.bUseVisitFlag1)
{
if (iId == 11)
s += "<option selected value=\"11\">'";
else
s += "<option value=\"11\">'";
s += config.szVisitFlagName1;
s += "' включён";
if (iId == 10)
s += "<option selected value=\"10\">'";
else
s += "<option value=\"10\">'";
s += config.szVisitFlagName1;
s += "' выключен";
}
if (config.bUseVisitFlag2)
{
if (iId == 21)
s += "<option selected value=\"21\">'";
else
s += "<option value=\"21\">'";
s += config.szVisitFlagName2;
s += "' включён";
if (iId == 20)
s += "<option selected value=\"20\">'";
else
s += "<option value=\"20\">'";
s += config.szVisitFlagName2;
s += "' выключен";
}
if (config.bUseVisitFlag3)
{
if (iId == 31)
s += "<option selected value=\"31\">'";
else
s += "<option value=\"31\">'";
s += config.szVisitFlagName3;
s += "' включён";
if (iId == 30)
s += "<option selected value=\"30\">'";
else
s += "<option value=\"30\">'";
s += config.szVisitFlagName3;
s += "' выключен";
}
if (config.bUseVisitFlag4)
{
if (iId == 41)
s += "<option selected value=\"41\">'";
else
s += "<option value=\"41\">'";
s += config.szVisitFlagName4;
s += "' включён";
if (iId == 40)
s += "<option selected value=\"40\">'";
else
s += "<option value=\"40\">'";
s += config.szVisitFlagName4;
s += "' выключен";
}
s += "</select>";
query->dst->fnAddLine (s.c_str ());
}
/*
static string fnGetVisitFlagsDescription (int iId)
{
static string s;
s.clear ();
if (iId >= 0)
{
s += ", флажок: '";
switch (iId)
{
case 10:
case 11:
s += config.szVisitFlagName1;
break;
case 20:
case 21:
s += config.szVisitFlagName2;
break;
case 30:
case 31:
s += config.szVisitFlagName3;
break;
case 40:
case 41:
s += config.szVisitFlagName4;
break;
}
switch (iId)
{
case 10:
case 20:
case 30:
case 40:
s += "' выключен";
break;
case 11:
case 21:
case 31:
case 41:
s += "' включён";
break;
}
}
return s;
}
*/
void fnAppReportPeriod (QUERY *query)
{
string s;
char szTmp [20];
char szDate1 [11];
char szDate2 [11];
char szTime1 [5 +1];
char szTime2 [5 +1];
char szPrefix [WS_MAX_NAME_LEN +1];
char szGroupId [2 +1];
char szVisitFlagId [2 +1];
int iCycle;
int iTuningIconSize = fnGetTuningIconSize (query);
int iOrg = -1;
fnFormContent (query);
query->dst->fnAddLine ("<p>Отчёты за период</p>");
query->dst->fnLoad ("templates/app_help_report_period.tpl");
// загружаем данные из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
if (! login_time1->fnGetValue (szTime1,query->szLogin))
{
strcpy (szTime1,"00:00");
login_time1->fnAdd (query->szLogin,szTime1);
}
if (! login_time2->fnGetValue (szTime2,query->szLogin))
{
strcpy (szTime2,"23:59");
login_time2->fnAdd (query->szLogin,szTime2);
}
if (! login_prefix->fnGetValue (szPrefix,query->szLogin))
{
*szPrefix = 0;
login_prefix->fnAdd (query->szLogin,szPrefix);
}
if (! login_group->fnGetValue (szGroupId,query->szLogin))
{
strcpy (szGroupId,"-1");
login_group->fnAdd (query->szLogin,szGroupId);
}
if (! login_visitflag->fnGetValue (szVisitFlagId,query->szLogin))
{
strcpy (szVisitFlagId,"-1");
login_visitflag->fnAdd (query->szLogin,szVisitFlagId);
}
if (login_org->fnGetValue (szTmp,query->szLogin))
iOrg = atoi (szTmp);
else
login_org->fnAdd (query->szLogin,"-1");
s = "<form action=\"/report_period_accept\" method=post>";
s += "<table border=0><tr><td valign=top>Период:</td><td>";
// время 1
s += "<input type=text name=from_time size=20 maxlength=5 value=\"";
s += szTime1;
s += "\">";
query->dst->fnAddLine (s.c_str ());
// дата 1
fnSelectDate (query,"from_",szDate1);
query->dst->fnAddLine ("—<br>");
// время 2
s = "<input type=text name=to_time size=20 maxlength=5 value=\"";
s += szTime2;
s += "\">";
query->dst->fnAddLine (s.c_str ());
// дата 2
fnSelectDate (query,"to_",szDate2);
query->dst->fnAddLine ("</td></tr>");
// префикс филиала
s = "<tr><td>Префикс филиала:</td><td><input type=text name=prefix size=20 maxlength=";
sprintf (szTmp,"%i",WS_MAX_NAME_LEN);
s += szTmp;
s += " value=\"";
s += szPrefix;
s += "\"></td></tr>";
// группа
s += "<tr><td>Группа:</td><td>";
query->dst->fnAddLine (s.c_str ());
fnServicesGroupsSelectFilter (query,atoi (szGroupId));
s = "</td></tr>";
// флажок посещения
s += "<tr><td>Флажок посещения:</td><td>";
query->dst->fnAddLine (s.c_str ());
fnVisitFlagsSelectFilter (query,atoi (szVisitFlagId));
query->dst->fnAddLine ("</td></tr>");
// организация-плательщик
query->dst->fnAddLine ("<tr><td>Плательщик:</td><td>");
fnSelectOrgPayer (query,iOrg);
query->dst->fnAddLine ("</td></tr>");
// кнопка "Применить"
s = "<tr><td> </td><td><input type=submit value=\"Применить\"></td></tr>";
s += "</table></form>";
query->dst->fnAddLine (s.c_str ());
s = "<p><table border=1 width=\"100%\">";
s += "<tr><td>Наименование</td><td>Время</td><td>Период</td><td>Префикс</td><td>Группа</td>\
<td>Флажки</td><td>Плательщик</td><td>Описание</td><td>Столбцы</td></tr>";
if ((query->uiAccessMap & ACCESS_ANALISE)
|| ((! config.bLimitedClientsInfo) && (query->uiAccessMap & ACCESS_REG)))
{
// сальдо клиентов
s += "<tr><td><a href=\"/report_debts_form\" target=\"_blank\">Сальдо клиентов</a></td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td>Упорядоченный по алфавиту список клиентов, у которых есть долг или переплата.</td>";
s += "<td>ФИО клиента, дата рождения, телефоны, сальдо.</td></tr>";
// отчёт о днях рождения клиентов
s += "<tr><td><a href=\"/report_birthday_form\" target=\"_blank\">Отчёт о днях рождения клиентов</a></td>";
s += "<td> </td>";
if (iTuningIconSize == 16)
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
else
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td>Список именинников за период, упорядоченный по дням рождения.</td>";
s += "<td>Дата рождения, ФИО клиента, адрес, телефоны.</td></tr>";
// реестр амбулаторных карт
s += "<tr><td><a href=\"/report_map_order_form\" target=\"_blank\">Реестр амбулаторных карт</a></td>";
s += "<td> </td>";
if (iTuningIconSize == 16)
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
else
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td>Упорядоченный список амбулаторных карт за период.</td>";
s += "<td>Номер (карты), дата (оформления), ФИО клиента.</td></tr>";
// история посещений
s += "<tr><td><a href=\"/report_visits_history_form\" target=\"_blank\">История посещений, сортировка по фамилиям</a><br>";
s += "<a href=\"/report_visits_history_form?sort=2\" target=\"_blank\">История посещений, сортировка по суммам</a></td>";
if (iTuningIconSize == 16)
{
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
}
else
{
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
}
s += "<td>История посещений за период.</td>";
s += "<td>№, ФИО, дата рождения, телефоны, даты посещений (список), кол-во посещений, сумма.</td></tr>";
// реестр назначений внутренний
s += "<tr><td><a href=\"/report_prescriptions_order_form\" target=\"_blank\">Реестр назначений внутренний</a></td>";
if (iTuningIconSize == 16)
{
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
}
else
{
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
}
s += "<td></td><td></td></tr>";
// реестр назначений лабораторный
s += "<tr><td><a href=\"/report_prescriptions_types_order_form\" target=\"_blank\">Реестр назначений лабораторный</a></td>";
if (iTuningIconSize == 16)
{
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
}
else
{
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
}
s += "<td></td><td></td></tr>";
// сотовые телефоны клиентов
s += "<tr><td><a href=\"/report_cellphones_form\" target=\"_blank\">Сотовые телефоны клиентов</a></td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td></td><td></td></tr>";
// оценка количества SMS для рассылки
s += "<tr><td><a href=\"/report_sms_qty_form\" target=\"_blank\">Оценка количества SMS для рассылки</a></td>";
if (iTuningIconSize == 16)
{
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
}
else
{
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
}
s += "<td>Оценка количества клиентов с федеральными телефонными номерами, прошедших через установленные фильтры.</td><td></td></tr>";
}
if (query->uiAccessMap & ACCESS_ANALISE)
{
// *********************
// * финансовые отчёты *
// *********************
s += "<tr><td colspan=9>Финансовые отчёты:</td></tr>";
// отчёт о доходах
s += "<tr><td><a href=\"/report_income_form\" target=\"_blank\">Отчёт о доходах</a></td>";
if (iTuningIconSize == 16)
{
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
}
else
{
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
}
s += "<td></td><td></td></tr>";
if (config.bInputCons)
{
// отчёт о доходах по организациям
s += "<tr><td><a href=\"/report_orgs_income_form\" target=\"_blank\">Отчёт о доходах по организациям</a></td>";
if (iTuningIconSize == 16)
{
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
}
else
{
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
}
s += "<td></td><td></td></tr>";
// отчёт о доходах по менеджерам
s += "<tr><td><a href=\"/report_managers_income_form\" target=\"_blank\">Отчёт о доходах по менеджерам</a></td>";
if (iTuningIconSize == 16)
{
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
}
else
{
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
}
s += "<td></td><td></td></tr>";
}
// отчёт по видам товаров и услуг
s += "<tr><td><a href=\"/report_services_form\" target=\"_blank\">Отчёт по видам товаров и услуг</a></td>";
if (iTuningIconSize == 16)
{
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
}
else
{
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
}
s += "<td></td><td></td></tr>";
// отчёт по видам товаров и услуг (по филиалам)
s += "<tr><td><a href=\"/report_services_form?prefix=1\" target=\"_blank\">Отчёт по видам товаров и услуг (по филиалам)</a></td>";
if (iTuningIconSize == 16)
{
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
}
else
{
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
}
s += "<td></td><td></td></tr>";
// отчёт о первичных и повторных обращениях
s += "<tr><td><a href=\"/report_primary_visits_form\" target=\"_blank\">Отчёт о первичных и повторных обращениях</a></td>";
if (iTuningIconSize == 16)
{
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
}
else
{
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
}
s += "<td></td><td></td></tr>";
// акт выполненных работ
s += "<tr><td><a href=\"/report_act_work_form\" target=\"_blank\">Акт выполненных работ</a></td>";
if (iTuningIconSize == 16)
{
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
}
else
{
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
}
s += "<td></td><td></td></tr>";
// реестр медицинских услуг для страховой организации
s += "<tr><td><a href=\"/report_insurance_order_form\" target=\"_blank\">Реестр медицинских услуг \
для страховой организации</a></td>";
if (iTuningIconSize == 16)
{
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
}
else
{
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
}
s += "<td></td><td></td></tr>";
// отчёт о расходах
s += "<tr><td><a href=\"/report_expenses_form\" target=\"_blank\">Отчёт о расходах</a></td>";
s += "<td> </td>";
if (iTuningIconSize == 16)
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
else
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td></td><td></td></tr>";
// отчёт о предоставленных скидках
s += "<tr><td><a href=\"/report_discount_form\" target=\"_blank\">Отчёт о предоставленных скидках</a></td>";
if (iTuningIconSize == 16)
{
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
}
else
{
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
}
s += "<td>Отчёт о предоставленных скидках за период, содержащий отдельные таблицы для каждого используемого \
вида скидок. Записи упорядочены по дате оформления. Формула расчёта размера скидки: \"(исходная цена * количество) - сумма\".</td>";
s += "<td>Дата (оформления), № договора, ФИО клиента, услуга, исходная цена, % скидки, цена, кол-во, \
сумма, размер скидки в рублях.</td></tr>";
// **************************
// * отчёты модуля контроля *
// **************************
s += "<tr><td colspan=9>Отчёты модуля контроля:</td></tr>";
// МК2: предоставление единовременной скидки
s += "<tr><td><a href=\"/report_control2_form\" target=\"_blank\">МК2: Предоставленные единовременные скидки более ";
sprintf (szTmp,"%i",config.iCheck2Max);
s += szTmp;
s += "%</a></td>";
s += "<td> </td>";
if (iTuningIconSize == 16)
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
else
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td></td><td></td></tr>";
// отчёт о созданных договорах
s += "<tr><td><a href=\"/report_contracts_form\" target=\"_blank\">Отчёт о созданных договорах</a></td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td>Отчёт о действиях по объединению записей в договоры и формированию документов для печати. \
Эта информация хранится 31 день.</td>";
s += "<td>Дата и время, подтип события, логин пользователя, событие, номер и дата договора, ФИО клиента, \
сумма, номер страницы.</td></tr>";
// отчёт о редактировании прейскуранта в конструкторе видов услуг
s += "<tr><td><a href=\"/report_services_edit_form\" target=\"_blank\">Отчёт о редактировании прейскуранта \
в конструкторе видов услуг</a></td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td>Отчёт о событиях изменения прейскуранта, включающий в себя события создания и удаления услуг \
и разделов, а также о редактировании цен и себестоимости услуг. Эта информация хранится 365 дней.</td>";
s += "<td>Дата и время, подтип события, логин пользователя, событие, уникальный номер, наименование, \
прежнее значение, новое значение.</td></tr>";
// ********************************
// * отчёты о работе специалистов *
// ********************************
s += "<tr><td colspan=9>Отчёты о работе специалистов:</td></tr>";
// ведение амбулаторных карт
if (ini1.bSpecMedical
&& config.bInputSpec)
{
s += "<tr><td><a href=\"/report_map_keeping_form\" target=\"_blank\">Ведение амбулаторных карт</a></td>";
s += "<td> </td>";
if (iTuningIconSize == 16)
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
else
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td></td><td></td></tr>";
}
if (config.bInputSpec)
{
// выполненные работы и заработная плата
s += "<tr><td><a href=\"/report_salary_form\" target=\"_blank\">Выполненные работы и заработная плата</a></td>";
if (iTuningIconSize == 16)
{
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
}
else
{
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
}
s += "<td></td><td></td></tr>";
// заработная плата (итоги)
s += "<tr><td><a href=\"/report_salary_short_form\" target=\"_blank\">Заработная плата (итоги)</a></td>";
if (iTuningIconSize == 16)
{
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
}
else
{
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
}
s += "<td></td><td></td></tr>";
// история посещений по специалистам
s += "<tr><td><a href=\"/report_specs_history_form\" target=\"_blank\">История посещений по специалистам</a><br>";
s += "<a href=\"/report_specs_history_form?primary=1\" target=\"_blank\">История первичных посещений по специалистам</a></td>";
if (iTuningIconSize == 16)
{
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
}
else
{
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
}
s += "<td></td><td></td></tr>";
}
if (config.bInputCons)
{
// начисления консультантам
s += "<tr><td><a href=\"/report_cons_payments_form\" target=\"_blank\">Начисления консультантам</a></td>";
if (iTuningIconSize == 16)
{
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
}
else
{
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
}
s += "<td></td><td></td></tr>";
// начисления консультантам по организациям
s += "<tr><td><a href=\"/report_orgs_payments_form\" target=\"_blank\">Начисления консультантам по организациям</a></td>";
if (iTuningIconSize == 16)
{
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
s += "<td> </td>";
}
else
{
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
}
s += "<td></td><td></td></tr>";
}
// ********************
// * шаблонные отчёты *
// ********************
if (iRepTemplatesQty)
{
s += "<tr><td colspan=5 align=center>Шаблонные отчёты:</td></tr>";
for (iCycle = 0; iCycle < iRepTemplatesQty; iCycle++)
{
s += "<tr><td><a href=\"/report_template_form?num=";
sprintf (szTmp,"%i",iCycle);
s += szTmp;
s += "\" target=\"_blank\">";
s += rep_template [iCycle]->szName;
s += "</a></td>";
s += "<td> </td>";
if (iTuningIconSize == 16)
s += "<td><img src=\"/images/16x16/agt_action_success.png\"></td>";
else
s += "<td><img src=\"/images/24x24/agt_action_success.png\"></td>";
s += "<td> </td>";
s += "<td> </td>";
s += "<td></td><td></td></tr>";
}
}
}
s += "</table></p>";
query->dst->fnAddLine (s.c_str ());
if (query->uiAccessMap & ACCESS_ANALISE)
{
s = "<p><table border=0 width=\"100%\"><tr><td>";
// годовой отчёт
s += "<a href=\"/report_base\">Годовой отчёт</a><br>";
s += "</td><td>";
// графики
s += "</td></tr></table></p>";
query->dst->fnAddLine (s.c_str ());
}
fnFormEnd (query);
} // end of fnAppReportPeriod ()
void fnAppReportPeriodAccept (QUERY *query)
{
char sz [INI_MAX_LEXEM_LEN +1];
int iDay1 = 0;
int iMonth1 = 0;
int iYear1 = 0;
int iDay2 = 0;
int iMonth2 = 0;
int iYear2 = 0;
RING *args = query->args;
char szDate1 [11];
char szDate2 [11];
char szTime1 [5 +1];
char szTime2 [5 +1];
char szPrefix [WS_MAX_NAME_LEN +1];
char szGroupId [2 +1];
char szVisitFlagId [2 +1];
int iOrg = -1;
char szTmp [20];
while (args->fnGetQty ())
{
args->fnPop (sz);
if (! strcmp (sz,"from_day"))
{
args->fnPop (sz);
iDay1 = atoi (sz);
continue;
}
if (! strcmp (sz,"from_month"))
{
args->fnPop (sz);
iMonth1 = atoi (sz);
continue;
}
if (! strcmp (sz,"from_year"))
{
args->fnPop (sz);
iYear1 = atoi (sz);
continue;
}
if (! strcmp (sz,"to_day"))
{
args->fnPop (sz);
iDay2 = atoi (sz);
continue;
}
if (! strcmp (sz,"to_month"))
{
args->fnPop (sz);
iMonth2 = atoi (sz);
continue;
}
if (! strcmp (sz,"to_year"))
{
args->fnPop (sz);
iYear2 = atoi (sz);
continue;
}
if (! strcmp (sz,"from_time"))
{
args->fnPop (szTime1);
continue;
}
if (! strcmp (sz,"to_time"))
{
args->fnPop (szTime2);
continue;
}
if (! strcmp (sz,"prefix"))
{
args->fnPop (szPrefix);
continue;
}
if (! strcmp (sz,"group"))
{
args->fnPop (szGroupId);
continue;
}
if (! strcmp (sz,"visit_flag"))
{
args->fnPop (szVisitFlagId);
continue;
}
if (! strcmp (sz,"org_payer"))
{
args->fnPop (sz);
iOrg = atoi (sz);
continue;
}
}
sprintf (szDate1,"%02u/%02u/%04u",iDay1,iMonth1,iYear1);
sprintf (szDate2,"%02u/%02u/%04u",iDay2,iMonth2,iYear2);
fnNormalizeDate (szDate1);
fnNormalizeDate (szDate2);
if (fnCompareDate (szDate1,szDate2) <= 0)
{
login_date1->fnAdd (query->szLogin,szDate1);
login_date2->fnAdd (query->szLogin,szDate2);
}
// проверяем заполнение времени
if (fnCheckTimeHM (szTime1) && fnCheckTimeHM (szTime2))
{
// если начальная и конечная даты одинаковы
if (fnCompareDate (szDate1,szDate2) == 0)
{
int iTime1;
int iTime2;
iTime1 = fnGetMinutesAfterMidnightHM (szTime1);
iTime2 = fnGetMinutesAfterMidnightHM (szTime2);
if (iTime1 <= iTime2)
{
login_time1->fnAdd (query->szLogin,szTime1);
login_time2->fnAdd (query->szLogin,szTime2);
}
}
else
{
login_time1->fnAdd (query->szLogin,szTime1);
login_time2->fnAdd (query->szLogin,szTime2);
}
}
login_prefix->fnAdd (query->szLogin,szPrefix);
login_group->fnAdd (query->szLogin,szGroupId);
login_visitflag->fnAdd (query->szLogin,szVisitFlagId);
// организация-плательщик
sprintf (szTmp,"%i",iOrg);
login_org->fnAdd (query->szLogin,szTmp);
} // end of fnAppReportPeriodAccept ()
// **********************************
// * отчёт о днях рождения клиентов *
// **********************************
void fnAppReportBirthdayForm (QUERY *query)
{
char szDate1 [11];
char szDate2 [11];
string s;
char szTmp [20];
char szClientFIO [100];
int iCycle;
char szBirthday [11];
int iDay,iMonth;
char szPhones [CLIENT_PHONES_LEN +1];
std::auto_ptr<RING> table (new RING (10 kb));
char *szBuf;
char szAddress [CLIENT_ADDRESS_LEN +1];
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
s = "Отчёт о днях рождения клиентов за период с ";
s += szDate1;
s += " по ";
s += szDate2;
fnReportTitle (query,s.c_str ());
// цикл с единицы, т.к. нулевой клиент - Анонимный
for (iCycle = 1; iCycle < iClientsQty; iCycle++)
{
// пропускаем удалённые записи
if (client [iCycle]->fnGetDelete())
continue;
// пропускаем клиентов с некорректной датой рождения
if (! fnCheckDate (client [iCycle]->fnGetBirthday()))
continue;
// год рождения не должен быть меньше 1900
if (fnGetYear(client [iCycle]->fnGetBirthday()) < 1900)
continue;
// определяем дату дня рождения
iDay = fnGetDay (client [iCycle]->fnGetBirthday());
iMonth = fnGetMonth (client [iCycle]->fnGetBirthday());
sprintf (szBirthday,"%02u/%02u/%04u",iDay,iMonth,
fnGetYear (szDate1)); // год начала периода
// szDate1 более поздняя
if (fnCompareDate (szDate1,szBirthday) == 1)
{
if (fnGetYear (szDate1) == fnGetYear (szDate2))
continue;
else
sprintf (szBirthday,"%02u/%02u/%04u",
iDay,iMonth,
// год окончания периода
fnGetYear (szDate2));
}
if (! fnCheckDateRange (szDate1,szBirthday,szDate2))
continue;
// формируем строку таблицы
// внутри комментария дата рождения и ФИО клиента
// в формате ММ/ДД_ФИО для сортировки
sprintf (szTmp,"<!-- %02u/%02u_",
fnGetMonth (client [iCycle]->fnGetBirthday ()),
fnGetDay (client [iCycle]->fnGetBirthday ()));
s = szTmp;
sprintf (szClientFIO,"%s %s %s",
client [iCycle]->fnGetFamily (),
client [iCycle]->fnGetName (),
client [iCycle]->fnGetName2 ());
s += szClientFIO;
s += " -->";
// видимая информация
s += "<tr><td>";
s += client [iCycle]->fnGetBirthday ();
s += "</td><td>";
s += szClientFIO;
s += "</td><td>";
s += client [iCycle]->fnGetAddress (szAddress);
s += " </td><td>";
s += client [iCycle]->fnGetPhones (szPhones);
s += " </td></tr>";
table->fnPushStr (s.c_str ());
}
if (table->fnGetQty ())
{
table->fnSort (0); // сортировка в кольце
query->dst->fnAddLine (
"<table width=\"100%\" border=1><tr>\
<td align=center>Дата рождения</td>\
<td align=center>ФИО клиента</td>\
<td align=center>Адрес</td>\
<td align=center>Телефоны</td></tr>");
while (table->fnGetQty ())
{
szBuf = new char [table->fnGetLen ()];
table->fnPop (szBuf);
query->dst->fnAddLine (szBuf);
delete [] szBuf;
}
query->dst->fnAddLine ("</table>");
}
fnReportEnd (query);
} // end of fnAppReportBirthdayForm ()
// *****************************
// * сотовые телефоны клиентов *
// *****************************
void fnAppReportCellPhonesForm (QUERY *query)
{
string s;
char szTmp [20];
char szClientFIO [100];
int iCycle;
std::auto_ptr<RING> table (new RING (10 kb));
char *szBuf;
fnReportTitle (query,"Сотовые телефоны клиентов");
// цикл с единицы, т.к. нулевой клиент - Анонимный
for (iCycle = 1; iCycle < iClientsQty; iCycle++)
{
// пропускаем удалённые записи
if (client [iCycle]->fnGetDelete ())
continue;
// если в строке отсутствует федеральный номер
if (! fnGetPhone (szTmp,client [iCycle]->fnGetPhoneCell ()))
continue;
// формируем строку таблицы
// ФИО клиента
s = "<tr><td>";
sprintf (szClientFIO,"%s %s %s",
client [iCycle]->fnGetFamily (),
client [iCycle]->fnGetName (),
client [iCycle]->fnGetName2 ());
s += szClientFIO;
s += "</td>";
// дата рождения
s += "<td>";
s += client [iCycle]->fnGetBirthday ();
s += "</td>";
// сотовые телефоны
s += "<td>";
s += client [iCycle]->fnGetPhoneCell ();
s += "</td></tr>";
table->fnPushStr (s.c_str ());
}
if (table->fnGetQty ())
{
table->fnSort (0); // сортировка в кольце
query->dst->fnAddLine (
"<table width=\"100%\" border=1><tr>\
<td align=center>ФИО клиента</td>\
<td align=center>Дата рождения</td>\
<td align=center>Сотовый телефон</td></tr>");
while (table->fnGetQty ())
{
szBuf = new char [table->fnGetLen ()];
table->fnPop (szBuf);
query->dst->fnAddLine (szBuf);
delete [] szBuf;
}
query->dst->fnAddLine ("</table>");
}
fnReportEnd (query);
} // end of fnAppReportCellPhonesForm ()
// **************************************
// * оценка количества SMS для рассылки *
// **************************************
void fnAppReportSmsQtyForm (QUERY *query)
{
char szDate1 [11];
char szDate2 [11];
char szGroupId [2 +1];
int iGroupId;
string s;
int iCycle;
int iClientNum;
std::auto_ptr<A_KEY_INT> clients_nums (new A_KEY_INT (16 kb));
int iQty;
char szTmp [20];
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
// группа
if (! login_group->fnGetValue (szGroupId,query->szLogin))
{
strcpy (szGroupId,"-1");
login_group->fnAdd (query->szLogin,szGroupId);
}
iGroupId = atoi (szGroupId);
s = "Оценка количества SMS для рассылки (период с ";
s += szDate1;
s += " по ";
s += szDate2;
if (iGroupId >= 0)
{
SERVICES_GROUP s_group;
groups->fnPop ((char *) &s_group,iGroupId);
s += ", группа: ";
s += s_group.szName;
}
s += ")";
fnReportTitle (query,s.c_str ());
// выбираем актуальные посещения
for (iCycle = 0; iCycle < iVisitsQty; iCycle++)
{
if (visit [iCycle]->fnGetDelete ())
continue;
if (! visit [iCycle]->fnGetClientNum()) // анонимный клиент
continue;
if (! fnCheckDateRange (szDate1,visit [iCycle]->fnGetDate (),szDate2))
continue;
if (visit [iCycle]->fnGetPreEntry ())
continue;
// группа
if (iGroupId >= 0)
if (! fnServicesGroupsGetMember (visit [iCycle]->fnGetType (),iGroupId))
continue;
// добавляем уникальный номер клиента в массив clients_found
iClientNum = visit [iCycle]->fnGetClientNum();
if (! clients_nums->fnCheck(iClientNum))
clients_nums->fnAdd(iClientNum);
}
iQty = clients_nums->fnGetQty ();
s = "<table width=\"100%\" border=1>";
s += "<tr><td>Количество клиентов, прошедших через фильтр:</td><td align=right>";
sprintf (szTmp,"%i",iQty);
s += szTmp;
s += "</td></tr>";
if (iQty)
{
RING *buf;
std::auto_ptr<RING> clients_found (new RING (16 kb));
int iClientNum;
int iClient;
buf = new RING (16 kb);
clients_nums->fnCopyBuf (buf);
for (iCycle = 0; iCycle < iQty; iCycle++)
{
buf->fnPop((char *) &iClientNum,iCycle);
iClient = fnClientSearchByNum(iClientNum);
if (iClient == -1)
continue;
// пропускаем удалённые записи
if (client [iCycle]->fnGetDelete ())
continue;
// если в строке отсутствует федеральный номер
if (! fnGetPhone (szTmp,client [iClient]->fnGetPhoneCell ()))
continue;
clients_found->fnPush((char *) &iClientNum,sizeof (iClientNum));
}
delete buf;
s += "<tr><td>Из них с федеральными телефонными номерами:</td><td align=right>";
sprintf (szTmp,"%i",clients_found->fnGetQty());
s += szTmp;
s += "</td></tr>";
}
s += "</table>";
query->dst->fnAddLine (s.c_str());
fnReportEnd (query);
} // end of fnAppReportSmsQtyForm()
// ****************************
// * реестр амбулаторных карт *
// ****************************
void fnAppReportMapOrderForm (QUERY *query)
{
char szDate1 [11];
char szDate2 [11];
string s;
int iCycle;
char szMapOrderDate [11];
char szTmp [20];
char szClientFIO [100]; // для вывода FIO
std::auto_ptr<RING> table (new RING (10 kb));
char *szBuf;
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
s = "Реестр амбулаторных карт за период с ";
s += szDate1;
s += " по ";
s += szDate2;
fnReportTitle (query,s.c_str ());
// цикл с единицы, т.к. нулевой клиент - Анонимный
for (iCycle = 1; iCycle < iClientsQty; iCycle++)
{
if (client [iCycle]->fnGetDelete ())
continue;
if (! client [iCycle]->fnGetMapOrderNum ())
continue;
client [iCycle]->fnMapOrderDate ()->fnGetDate (szMapOrderDate);
if (! fnCheckDateRange (szDate1,szMapOrderDate,szDate2))
continue;
// формируем строку таблицы
s = "<!--";
sprintf (szTmp,"%06i",client [iCycle]->fnGetMapOrderNum ()); // шестизначный номер для сортировки
s += szTmp;
s += "--><tr><td align=right>";
sprintf (szTmp,"%i",client [iCycle]->fnGetMapOrderNum ());
s += szTmp;
s += "</td><td>";
s += szMapOrderDate;
s += "</td><td>";
sprintf (szClientFIO,"%s %s %s",
client [iCycle]->fnGetFamily (),
client [iCycle]->fnGetName (),
client [iCycle]->fnGetName2 ());
s += szClientFIO;
s += "</td></tr>";
table->fnPushStr (s.c_str ());
}
if (table->fnGetQty ())
{
table->fnSort (0); // сортировка в кольце
query->dst->fnAddLine (
"<table width=\"100%\" border=1><tr>\
<td align=center>Номер</td>\
<td align=center>Дата</td>\
<td align=center>ФИО клиента</td></tr>");
while (table->fnGetQty ())
{
szBuf = new char [table->fnGetLen ()];
table->fnPop (szBuf);
query->dst->fnAddLine (szBuf);
delete [] szBuf;
}
query->dst->fnAddLine ("</table>");
}
fnReportEnd (query);
} // end of fnAppReportMapOrderForm ()
// ****************************************************************************
// * *
// * ФИНАНСОВЫЕ ОТЧЁТЫ *
// * *
// ****************************************************************************
// *******************
// * отчёт о доходах *
// *******************
void fnAppReportIncomeForm (QUERY *query)
{
char szDate1 [11];
char szDate2 [11];
char szGroupId [2 +1];
char szVisitFlagId [2 +1];
int iGroupId;
int iVisitFlagId;
string s;
int iCycle;
std::auto_ptr<RING> visits_found (new RING (64 kb));
int iQty;
int iDaysQty;
int iCycleDay;
char szCycleDate [11];
double dSum;
double dSumBank;
double dSumTerminal;
double dSumInsurance;
int iVisit;
double dPayment;
char szTmp [20];
double dSumTotal = 0.0;
double dSumTotalBank = 0.0;
double dSumTotalTerminal = 0.0;
double dSumTotalInsurance = 0.0;
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
// группа
if (! login_group->fnGetValue (szGroupId,query->szLogin))
{
strcpy (szGroupId,"-1");
login_group->fnAdd (query->szLogin,szGroupId);
}
iGroupId = atoi (szGroupId);
// флажок посещения
if (! login_visitflag->fnGetValue (szVisitFlagId,query->szLogin))
{
strcpy (szVisitFlagId,"-1");
login_visitflag->fnAdd (query->szLogin,szVisitFlagId);
}
iVisitFlagId = atoi (szVisitFlagId);
s = "Отчёт о доходах за период с ";
s += szDate1;
s += " по ";
s += szDate2;
if (iGroupId >= 0)
{
SERVICES_GROUP s_group;
groups->fnPop ((char *) &s_group,iGroupId);
s += ", группа: ";
s += s_group.szName;
}
fnReportTitle (query,s.c_str ());
// выбираем актуальные посещения
for (iCycle = 0; iCycle < iVisitsQty; iCycle++)
{
if (visit [iCycle]->fnGetDelete ())
continue;
if (! fnCheckDateRange (szDate1,visit [iCycle]->fnGetPaymentDate (),szDate2))
continue;
if (visit [iCycle]->fnGetPreEntry ())
continue;
// флажок посещения
switch (iVisitFlagId)
{
case 11:
if (visit [iCycle]->fnGetFlag1 () == false)
continue;
break;
case 10:
if (visit [iCycle]->fnGetFlag1 () == true)
continue;
break;
case 21:
if (visit [iCycle]->fnGetFlag2 () == false)
continue;
break;
case 20:
if (visit [iCycle]->fnGetFlag2 () == true)
continue;
break;
case 31:
if (visit [iCycle]->fnGetFlag3 () == false)
continue;
break;
case 30:
if (visit [iCycle]->fnGetFlag3 () == true)
continue;
break;
case 41:
if (visit [iCycle]->fnGetFlag4 () == false)
continue;
break;
case 40:
if (visit [iCycle]->fnGetFlag4 () == true)
continue;
}
// группа
if (iGroupId >= 0)
if (! fnServicesGroupsGetMember (visit [iCycle]->fnGetType (),iGroupId))
continue;
// размещаем номер записи в кольцо visits_found
visits_found->fnPush ((char *) &iCycle,sizeof (iCycle));
}
iQty = visits_found->fnGetQty ();
query->dst->fnAddLine (
"<table width=\"100%\" border=1><tr>\
<td align=center>Дата</td>\
<td width=\"15%\" align=center>Наличные</td>\
<td width=\"15%\" align=center>Ч/банк</td>\
<td width=\"15%\" align=center>Терминал</td>\
<td width=\"15%\" align=center>ОМС</td>\
<td width=\"15%\" align=center>Всего</td></tr>");
// цикл по дням
iDaysQty = fnGetDaysQty (szDate1,szDate2);
for (iCycleDay = 0; iCycleDay < iDaysQty; iCycleDay++)
{
fnCreateDate (szCycleDate,szDate1,iCycleDay);
dSum = 0.0;
dSumBank = 0.0;
dSumTerminal = 0.0;
dSumInsurance = 0.0;
for (iCycle = 0; iCycle < iQty; iCycle++)
{
visits_found->fnPop ((char *) &iVisit,iCycle);
if (fnCompareDate (szCycleDate,visit [iVisit]->fnGetPaymentDate ()))
continue;
dPayment = visit [iVisit]->fnGetPaymentSum ();
// подсчитываем сумму
switch (visit [iVisit]->fnGetPaymentType ())
{
case 0: // оплата наличными
dSum += dPayment;
break;
case 1: // оплата через банк
dSumBank += dPayment;
break;
case 2: // терминал
dSumTerminal += dPayment;
break;
case 3: // ОМС
dSumInsurance += dPayment;
break;
}
}
// формируем строку таблицы
s = "<tr><td>";
s += szCycleDate;
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",dSum);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",dSumBank);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",dSumTerminal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",dSumInsurance);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",dSum+dSumBank+dSumTerminal+dSumInsurance);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr>";
query->dst->fnAddLine (s.c_str ());
dSumTotal += dSum;
dSumTotalBank += dSumBank;
dSumTotalTerminal += dSumTerminal;
dSumTotalInsurance += dSumInsurance;
}
// строка итогов
s = "<tr><td align=right><b>Итого:</b></td><td align=right><b>";
sprintf (szTmp,"%.2f",dSumTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</b></td><td align=right><b>";
sprintf (szTmp,"%.2f",dSumTotalBank);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</b></td><td align=right><b>";
sprintf (szTmp,"%.2f",dSumTotalTerminal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</b></td><td align=right><b>";
sprintf (szTmp,"%.2f",dSumTotalInsurance);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</b></td><td align=right><b>";
sprintf (szTmp,"%.2f",dSumTotal+dSumTotalBank+dSumTotalTerminal+dSumTotalInsurance);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</b></td></tr></table>";
query->dst->fnAddLine (s.c_str ());
fnReportEnd (query);
} // end of fnAppReportIncomeForm ()
// ***********************************
// * отчёт о доходах по организациям *
// ***********************************
void fnAppReportOrgsIncomeForm (QUERY *query)
{
char szDate1 [11];
char szDate2 [11];
char szGroupId [2 +1];
char szVisitFlagId [2 +1];
int iGroupId;
int iVisitFlagId;
string s;
int iOrgsQty;
int iCycleOrg;
ORG s_org;
int iCycleSpec;
int iCycle;
double dConsIncome;
double dOrgTotal;
char szTmp [20];
double dIncomeTotal = 0.0;
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
// группа
if (! login_group->fnGetValue (szGroupId,query->szLogin))
{
strcpy (szGroupId,"-1");
login_group->fnAdd (query->szLogin,szGroupId);
}
iGroupId = atoi (szGroupId);
// флажок посещения
if (! login_visitflag->fnGetValue (szVisitFlagId,query->szLogin))
{
strcpy (szVisitFlagId,"-1");
login_visitflag->fnAdd (query->szLogin,szVisitFlagId);
}
iVisitFlagId = atoi (szVisitFlagId);
s = "Отчёт о доходах по организациям за период с ";
s += szDate1;
s += " по ";
s += szDate2;
if (iGroupId >= 0)
{
SERVICES_GROUP s_group;
groups->fnPop ((char *) &s_group,iGroupId);
s += ", группа: ";
s += s_group.szName;
}
fnReportTitle (query,s.c_str ());
iOrgsQty = orgs->fnGetQty ();
for (iCycleOrg = 0; iCycleOrg < iOrgsQty; iCycleOrg++)
{
dOrgTotal = 0.0;
orgs->fnPop ((char *) &s_org,iCycleOrg); // s_org.iKey
// таблица "организация"
s = "<p><table border=0><tr><td>Наименование:</td><td><b>";
s += s_org.szName;
s += "</b></td></tr><tr><td>Адрес:</td><td>";
s += s_org.szAddress;
s += " </td></tr><tr><td>Телефоны:</td><td>";
s += s_org.szPhones;
s += " </td></tr><tr><td>Менеджер:</td><td>";
s += s_org.szManager;
s += " </td></tr></table>";
// заголовок таблицы "доход"
s += "<table border=1 width=\"100%\"><tr>\
<td width=\"50%\" align=center>Консультант</td>\
<td width=\"50%\" align=center>Доход</td></tr>";
for (iCycleSpec = 0; iCycleSpec < iSpecsQty; iCycleSpec++)
{
// пропускаем специалистов
if (! fnGetSpecCons (fnGetSpecType (iCycleSpec)))
continue;
// пропускаем консультантов из других организаций
if (fnGetConsOrg (fnGetSpecType (iCycleSpec)) != s_org.iKey)
continue;
// рассчитываем доход по консультанту
dConsIncome = 0.0;
for (iCycle = 0; iCycle < iVisitsQty; iCycle++)
{
if (visit [iCycle]->fnGetDelete ())
continue;
if (! fnCheckDateRange (szDate1,visit [iCycle]->fnGetPaymentDate (),szDate2))
continue;
if (visit [iCycle]->fnGetPreEntry ())
continue;
// флажок посещения
switch (iVisitFlagId)
{
case 11:
if (visit [iCycle]->fnGetFlag1 () == false)
continue;
break;
case 10:
if (visit [iCycle]->fnGetFlag1 () == true)
continue;
break;
case 21:
if (visit [iCycle]->fnGetFlag2 () == false)
continue;
break;
case 20:
if (visit [iCycle]->fnGetFlag2 () == true)
continue;
break;
case 31:
if (visit [iCycle]->fnGetFlag3 () == false)
continue;
break;
case 30:
if (visit [iCycle]->fnGetFlag3 () == true)
continue;
break;
case 41:
if (visit [iCycle]->fnGetFlag4 () == false)
continue;
break;
case 40:
if (visit [iCycle]->fnGetFlag4 () == true)
continue;
}
// группа
if (iGroupId >= 0)
if (! fnServicesGroupsGetMember (visit [iCycle]->fnGetType (),iGroupId))
continue;
if (visit [iCycle]->fnGetCons () != fnGetSpecType (iCycleSpec))
continue;
if (visit [iCycle]->fnGetAbsence ())
continue;
dConsIncome += visit [iCycle]->fnGetSum ();
}
if (dConsIncome)
{
dOrgTotal += dConsIncome;
dIncomeTotal += dConsIncome;
// формируем строку таблицы
s += "<tr><td>";
s += fnGetSpecFIO (fnGetSpecType (iCycleSpec));
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",dConsIncome);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr>";
}
}
s += "<table width=\"100%\"><tr><td align=right>Итого: <b>";
sprintf (szTmp,"%.2f",dOrgTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</b></td></tr></table></p>";
query->dst->fnAddLine (s.c_str ());
}
s = "<p align=center>Общая сумма доходов по организациям: <b>";
sprintf (szTmp,"%.2f",dIncomeTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</b></p>";
query->dst->fnAddLine (s.c_str ());
fnReportEnd (query);
} // end of fnAppReportOrgsIncomeForm ()
// *********************************
// * отчёт о доходах по менеджерам *
// *********************************
void fnAppReportManagersIncomeForm (QUERY *query)
{
char szDate1 [11];
char szDate2 [11];
char szGroupId [2 +1];
char szVisitFlagId [2 +1];
int iGroupId;
int iVisitFlagId;
string s;
int iOrgsQty;
int iCycleOrg;
ORG s_org;
int iCycle;
double dOrgTotal;
char szTmp [20];
A_ARRAY *manager_income;
RING *buf;
int iManagersQty;
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
// группа
if (! login_group->fnGetValue (szGroupId,query->szLogin))
{
strcpy (szGroupId,"-1");
login_group->fnAdd (query->szLogin,szGroupId);
}
iGroupId = atoi (szGroupId);
// флажок посещения
if (! login_visitflag->fnGetValue (szVisitFlagId,query->szLogin))
{
strcpy (szVisitFlagId,"-1");
login_visitflag->fnAdd (query->szLogin,szVisitFlagId);
}
iVisitFlagId = atoi (szVisitFlagId);
s = "Отчёт о доходах по менеджерам за период с ";
s += szDate1;
s += " по ";
s += szDate2;
if (iGroupId >= 0)
{
SERVICES_GROUP s_group;
groups->fnPop ((char *) &s_group,iGroupId);
s += ", группа: ";
s += s_group.szName;
}
fnReportTitle (query,s.c_str ());
// таблица "организации"
s = "<p><table border=1 width=\"100%\"><tr>\
<td width=\"25%\" align=center>Наименование</td>\
<td width=\"25%\" align=center>Адрес</td>\
<td width=\"25%\" align=center>Менеджер</td>\
<td width=\"25%\" align=center>Доход</td></tr>";
manager_income = new A_ARRAY ();
iOrgsQty = orgs->fnGetQty ();
for (iCycleOrg = 0; iCycleOrg < iOrgsQty; iCycleOrg++)
{
dOrgTotal = 0.0;
orgs->fnPop ((char *) &s_org,iCycleOrg); // s_org.iKey
if (! strlen (s_org.szManager))
continue; // организация не прикреплена к менеджеру
// рассчитываем доход по организации
for (iCycle = 0; iCycle < iVisitsQty; iCycle++)
{
if (visit [iCycle]->fnGetDelete ())
continue;
if (! fnCheckDateRange (szDate1,visit [iCycle]->fnGetPaymentDate (),szDate2))
continue;
if (visit [iCycle]->fnGetPreEntry ())
continue;
// флажок посещения
switch (iVisitFlagId)
{
case 11:
if (visit [iCycle]->fnGetFlag1 () == false)
continue;
break;
case 10:
if (visit [iCycle]->fnGetFlag1 () == true)
continue;
break;
case 21:
if (visit [iCycle]->fnGetFlag2 () == false)
continue;
break;
case 20:
if (visit [iCycle]->fnGetFlag2 () == true)
continue;
break;
case 31:
if (visit [iCycle]->fnGetFlag3 () == false)
continue;
break;
case 30:
if (visit [iCycle]->fnGetFlag3 () == true)
continue;
break;
case 41:
if (visit [iCycle]->fnGetFlag4 () == false)
continue;
break;
case 40:
if (visit [iCycle]->fnGetFlag4 () == true)
continue;
}
// группа
if (iGroupId >= 0)
if (! fnServicesGroupsGetMember (visit [iCycle]->fnGetType (),iGroupId))
continue;
if (visit [iCycle]->fnGetAbsence ())
continue;
// пропускаем консультантов из других организаций
if (fnGetConsOrg (visit [iCycle]->fnGetCons ()) != s_org.iKey)
continue;
dOrgTotal += visit [iCycle]->fnGetSum ();
}
s += "<tr><td>";
s += s_org.szName;
s += "</td><td>";
s += s_org.szAddress;
s += "</td><td>";
s += s_org.szManager;
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",dOrgTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr>";
// добавляем доход по организации в ассоциативный массив
if (manager_income->fnGetValue (szTmp,s_org.szManager))
dOrgTotal += atof (szTmp);
sprintf (szTmp,"%.2f",dOrgTotal);
manager_income->fnAdd (s_org.szManager,szTmp);
}
s += "</table></p>";
query->dst->fnAddLine (s.c_str ());
// таблица "менеджеры"
s = "<p><table border=1 width=\"100%\"><tr>\
<td width=\"50%\" align=center>Менеджер</td>\
<td width=\"50%\" align=center>Доход</td></tr>";
buf = new RING (1 kb);
manager_income->fnCopyBuf (buf);
delete manager_income;
iManagersQty = buf->fnGetQty ()>>1;
for (iCycle = 0; iCycle < iManagersQty; iCycle++)
{
s += "<tr><td>";
buf->fnPop (s_org.szManager);
s += s_org.szManager;
s += "</td><td align=right>";
buf->fnPop (szTmp);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr>";
}
delete buf;
s += "</table></p>";
query->dst->fnAddLine (s.c_str ());
fnReportEnd (query);
} // end of fnAppReportManagersIncomeForm ()
// **********************************
// * отчёт по видам товаров и услуг *
// **********************************
void fnAppReportServicesForm (QUERY *query)
{
RING *args = query->args;
char sz [INI_MAX_LEXEM_LEN +1];
bool bPrefix = false;
// bool bVisitDate = false;
char szDate1 [11];
char szDate2 [11];
char szTime1 [5 +1];
char szTime2 [5 +1];
char szPrefix [WS_MAX_NAME_LEN +1];
char szGroupId [2 +1];
char szVisitFlagId [2 +1];
int iOrg = -1;
std::auto_ptr<RING> visits_found (new RING (64 kb));
int iQty;
int iVisit;
string s;
int iCycleService,iCycle;
double dPriceSum;
double dQtySum;
double dSumSum;
double dQtyTotal = 0.0;
double dSumTotal = 0.0;
char szTmp [20];
int iTime1;
int iTime2;
int iGroupId;
int iVisitFlagId;
int iPaymentTime;
// int iVisitTime;
bool bOneDay = false;
double dCostSum;
double dCostTotal = 0.0;
A_ARRAY *aa_price_qty;
RING *buf;
char szKeyPrice [20];
char szValueQty [20];
double dKeyPrice;
double dValueQty;
int iPricesQty;
double dTmpPrice;
double dTmpQty;
double dTmpSum;
double dTmpCost;
while (args->fnGetQty ())
{
args->fnPop (sz);
if (! strcmp (sz,"prefix"))
{
args->fnPop (sz);
bPrefix = true;
continue;
}
}
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
if (fnCompareDate (szDate1,szDate2) == 0)
bOneDay = true;
// время
if (! login_time1->fnGetValue (szTime1,query->szLogin))
{
strcpy (szTime1,"00:00");
login_time1->fnAdd (query->szLogin,szTime1);
}
if (! login_time2->fnGetValue (szTime2,query->szLogin))
{
strcpy (szTime2,"23:59");
login_time2->fnAdd (query->szLogin,szTime2);
}
// преобразуем время в формат кол-ва минут после полуночи
iTime1 = fnGetMinutesAfterMidnightHM (szTime1);
iTime2 = fnGetMinutesAfterMidnightHM (szTime2);
// префикс
if (bPrefix)
{
if (! login_prefix->fnGetValue (szPrefix,query->szLogin))
{
*szPrefix = 0;
login_prefix->fnAdd (query->szLogin,szPrefix);
}
}
// группа
if (! login_group->fnGetValue (szGroupId,query->szLogin))
{
strcpy (szGroupId,"-1");
login_group->fnAdd (query->szLogin,szGroupId);
}
iGroupId = atoi (szGroupId);
// флажок посещения
if (! login_visitflag->fnGetValue (szVisitFlagId,query->szLogin))
{
strcpy (szVisitFlagId,"-1");
login_visitflag->fnAdd (query->szLogin,szVisitFlagId);
}
iVisitFlagId = atoi (szVisitFlagId);
// организация-плательщик
if (login_org->fnGetValue (szTmp,query->szLogin))
iOrg = atoi (szTmp);
else
login_org->fnAdd (query->szLogin,"-1");
s = "Отчёт по видам товаров и услуг<br>(период: ";
s += szTime1;
s += " ";
s += szDate1;
s += " — ";
s += szTime2;
s += " ";
s += szDate2;
s += ")";
if (bPrefix)
{
s += ", префикс филиала: \"";
s += szPrefix;
s += "\"";
}
if (iGroupId >= 0)
{
SERVICES_GROUP s_group;
groups->fnPop ((char *) &s_group,iGroupId);
s += ", группа: ";
s += s_group.szName;
}
if (iOrg != -1)
{
char szOrgName [WS_MAX_DESC_LEN +1];
s += ", плательщик: ";
s += fnGetOrgName (szOrgName,iOrg);
}
fnReportTitle (query,s.c_str ());
query->dst->fnAddLine (
"<table width=\"100%\" border=1><tr>\
<td align=center>Вид услуг</td>\
<td align=center>Кол-во</td>\
<td align=center>Цена ср.</td>\
<td align=center>Сумма</td>\
<td align=center>С/с ср.</td>\
<td align=center>Прибыль</td></tr>");
// выбираем актуальные посещения
for (iCycle = 0; iCycle < iVisitsQty; iCycle++)
{
if (visit [iCycle]->fnGetDelete ())
continue;
// префикс
if (bPrefix)
if (strcmp (szPrefix,visit [iCycle]->fnGetPrefix ()))
continue;
if (! fnCheckDateRange (szDate1,visit [iCycle]->fnGetPaymentDate (),szDate2))
continue;
if (visit [iCycle]->fnGetPreEntry ())
continue;
// организация-плательщик
if (iOrg != -1)
if (visit [iCycle]->fnGetOrg () != iOrg)
continue;
// флажок посещения
switch (iVisitFlagId)
{
case 11:
if (visit [iCycle]->fnGetFlag1 () == false)
continue;
break;
case 10:
if (visit [iCycle]->fnGetFlag1 () == true)
continue;
break;
case 21:
if (visit [iCycle]->fnGetFlag2 () == false)
continue;
break;
case 20:
if (visit [iCycle]->fnGetFlag2 () == true)
continue;
break;
case 31:
if (visit [iCycle]->fnGetFlag3 () == false)
continue;
break;
case 30:
if (visit [iCycle]->fnGetFlag3 () == true)
continue;
break;
case 41:
if (visit [iCycle]->fnGetFlag4 () == false)
continue;
break;
case 40:
if (visit [iCycle]->fnGetFlag4 () == true)
continue;
}
// группа
if (iGroupId >= 0)
if (! fnServicesGroupsGetMember (visit [iCycle]->fnGetType (),iGroupId))
continue;
// период
iPaymentTime = fnGetMinutesAfterMidnightHM (visit [iCycle]->fnGetPaymentTime ());
if (bOneDay) // период охватывает только один день
{
if ((iPaymentTime < iTime1) || (iPaymentTime > iTime2))
continue;
}
else // период охватывает несколько дней
{
// первый день периода
if ((fnCompareDate (szDate1,visit [iCycle]->fnGetPaymentDate ()) == 0)
&& (iPaymentTime < iTime1))
continue;
// последний день периода
if ((fnCompareDate (szDate2,visit [iCycle]->fnGetPaymentDate ()) == 0)
&& (iPaymentTime > iTime2))
continue;
}
// размещаем номер записи в кольцо visits_found
visits_found->fnPush ((char *) &iCycle,sizeof (iCycle));
}
iQty = visits_found->fnGetQty ();
aa_price_qty = new A_ARRAY ();
buf = new RING (1 kb);
for (iCycleService = 0; iCycleService < iServicesQty; iCycleService++)
{
dPriceSum = 0.0;
dQtySum = 0.0;
dSumSum = 0.0;
dCostSum = 0.0;
aa_price_qty->fnClear ();
for (iCycle = 0; iCycle < iQty; iCycle++)
{
visits_found->fnPop ((char *) &iVisit,iCycle);
if (visit [iVisit]->fnGetType () != fnGetServiceType (iCycleService))
continue;
// цена
dTmpPrice = visit [iVisit]->fnGetPrice();
dPriceSum += dTmpPrice;
// количество
dTmpQty = visit [iVisit]->fnGetQty();
dQtySum += dTmpQty;
// сумма
dTmpSum = dTmpPrice*dTmpQty;
dSumSum += dTmpSum;
// учёт цены и кол-ва
sprintf(szKeyPrice,"%.2f",dTmpPrice);
dValueQty = dTmpQty;
if (aa_price_qty->fnGetValue(szValueQty,szKeyPrice))
dValueQty += atof (szValueQty);
sprintf(szValueQty,"%.2f",dValueQty);
aa_price_qty->fnAdd(szKeyPrice,szValueQty);
// затраты
dTmpCost = visit [iVisit]->fnGetCost ();
dCostSum += dTmpCost;
}
buf->fnClear ();
aa_price_qty->fnCopyBuf (buf);
iPricesQty = buf->fnGetQty ()>>1;
// выводим дополнительные строки
if ((iPricesQty > 1) // если количество цен за услугу больше 1
&& config.bReportServicesDetailed) // если детализация разрешена
{
for (iCycle = 0; iCycle < iPricesQty; iCycle++)
{
buf->fnPop (szKeyPrice);
buf->fnPop (szValueQty);
dKeyPrice = atof (szKeyPrice);
dValueQty = atof (szValueQty);
s = "<tr><td><div style=\"color:silver;\">";
// наименование
s += fnGetServiceName (fnGetServiceType (iCycleService));
// кол-во
s += "</div></td><td width=\"10%\" align=right><div style=\"color:silver;\">";
if (config.bReportSepComma)
fnCharToComma (szValueQty,'.');
s += szValueQty;
// цена
s += "</div></td><td width=\"10%\" align=right><div style=\"color:silver;\">";
if (config.bReportSepComma)
fnCharToComma (szKeyPrice,'.');
s += szKeyPrice;
// сумма
s += "</div></td><td width=\"10%\" align=right><div style=\"color:silver;\">";
sprintf (szTmp,"%.2f",dKeyPrice*dValueQty);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
// с/с ср.
s += "</div></td><td width=\"10%\"> ";
// прибыль
s += "</td><td width=\"10%\"> ";
s += "</td></tr>";
query->dst->fnAddLine (s.c_str ());
}
}
// раздел
if (! fnGetServiceSelect (fnGetServiceType (iCycleService)))
{
s = "<tr><td><b>";
s += fnGetServiceName (fnGetServiceType (iCycleService));
s += "</b></td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>";
query->dst->fnAddLine (s.c_str ());
}
else // товар или услуга
{
do
{
if (config.bReportServicesBrief
&& dQtySum == 0.0)
continue;
// формируем строку таблицы
s = "<tr><td>";
// наименование
s += fnGetServiceName (fnGetServiceType (iCycleService));
// кол-во
s += "</td><td width=\"10%\" align=right>";
sprintf (szTmp,"%.2f",dQtySum);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
dQtyTotal += dQtySum;
// цена средняя
s += "</td><td width=\"10%\" align=right>";
sprintf (szTmp,"%.2f",dQtySum ? dSumSum/dQtySum : 0.0);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
// сумма
s += "</td><td width=\"10%\" align=right>";
sprintf (szTmp,"%.2f",dSumSum);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
dSumTotal += dSumSum;
// с/с ср.
s += "</td><td width=\"10%\" align=right>";
sprintf (szTmp,"%.2f",dCostSum);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
dCostTotal += dCostSum;
// прибыль
s += "</td><td width=\"10%\" align=right>";
sprintf (szTmp,"%.2f",dSumSum-dCostSum);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr>";
query->dst->fnAddLine (s.c_str ());
} while (false);
}
}
delete buf;
delete aa_price_qty;
s = "</table>";
s += "<table border=0 width=\"100%\"><tr><td align=right>Итого сумма: <b>";
sprintf (szTmp,"%.2f",dSumTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</b>, прибыль: <b>";
sprintf (szTmp,"%.2f",dSumTotal-dCostTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</b>, общее кол-во: ";
sprintf (szTmp,"%.2f",dQtyTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr></table>";
query->dst->fnAddLine (s.c_str ());
fnReportEnd (query);
} // end of fnAppReportServicesForm ()
// ***********************************
// * отчёт о предоставленных скидках *
// ***********************************
void fnAppReportDiscountForm(QUERY *query)
{
char szDate1 [11];
char szDate2 [11];
char szGroupId [2 +1];
int iGroupId;
std::auto_ptr<RING> visits_found (new RING (64 kb));
int iQty;
int iVisit;
string s;
int iCycleDiscount,iCycle;
double dTmp;
double dSum;
// int iClientNum;
int iClient;
char szClientFIO [100]; // для вывода ФИО
char szTmp [20];
std::auto_ptr<RING> table (new RING (512 kb));
char *szBuf;
double dSumTotal = 0.0;
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue(szDate1,query->szLogin))
{
fnGetToday(szDate1);
login_date1->fnAdd(query->szLogin,szDate1);
}
if (! login_date2->fnGetValue(szDate2,query->szLogin))
{
fnGetToday(szDate2);
login_date2->fnAdd(query->szLogin,szDate2);
}
// группа
if (! login_group->fnGetValue(szGroupId,query->szLogin))
{
strcpy(szGroupId,"-1");
login_group->fnAdd(query->szLogin,szGroupId);
}
iGroupId = atoi(szGroupId);
s = "Отчёт о предоставленных скидках<br>(период: ";
s += szDate1;
s += " — ";
s += szDate2;
if (iGroupId >= 0)
{
SERVICES_GROUP s_group;
groups->fnPop((char *) &s_group,iGroupId);
s += ", группа: ";
s += s_group.szName;
}
s += ")";
fnReportTitle(query,s.c_str ());
// выбираем актуальные посещения
for (iCycle = 0; iCycle < iVisitsQty; iCycle++)
{
if (visit [iCycle]->fnGetDelete())
continue;
if (visit [iCycle]->fnGetPreEntry())
continue;
if (! visit [iCycle]->fnGetDiscountType())
continue;
if (! fnCheckDateRange(szDate1,visit [iCycle]->fnGetPaymentDate (),szDate2))
continue;
// группа
if (iGroupId >= 0)
if (! fnServicesGroupsGetMember(visit [iCycle]->fnGetType (),iGroupId))
continue;
// размещаем номер записи в кольцо visits_found
visits_found->fnPush((char *) &iCycle,sizeof (iCycle));
}
iQty = visits_found->fnGetQty ();
for (iCycleDiscount = 1; iCycleDiscount <= 11; iCycleDiscount++)
{
dSum = 0.0;
for (iCycle = 0; iCycle < iQty; iCycle++)
{
visits_found->fnPop((char *) &iVisit,iCycle);
if (visit [iVisit]->fnGetDiscountType() != iCycleDiscount)
continue;
// iClientNum = visit [iVisit]->fnGetClientNum();
iClient = visit [iVisit]->fnGetClientIndex();
if (iClient < 1)
continue;
// формируем строку таблицы
// критерий сортировки
s = "<!--";
if (iCycleDiscount == 11)
{
sprintf (szTmp,"%08u_",visit [iVisit]->fnGetDiscountCardNum());
s += szTmp;
}
sprintf (szTmp,"%4u/%02u/%02u",
fnGetYear(visit [iVisit]->fnGetPaymentDate()),
fnGetMonth(visit [iVisit]->fnGetPaymentDate()),
fnGetDay(visit [iVisit]->fnGetPaymentDate()));
s += szTmp;
s += "-->";
s += "<tr>";
if (iCycleDiscount == 11)
{
s += "<td valign=top align=right>";
sprintf (szTmp,"%i",visit [iVisit]->fnGetDiscountCardNum());
s += szTmp;
s += "</td>";
}
// дата
s += "<td valign=top>";
s += visit [iVisit]->fnGetPaymentDate();
s += "</td>";
// № договора
s += "<td valign=top align=right>";
if (visit [iVisit]->fnGetContractNum())
{
if (strlen(visit [iVisit]->fnGetPrefix()))
{
s += visit [iVisit]->fnGetPrefix();
s += "-";
}
sprintf(szTmp,"%i",visit [iVisit]->fnGetContractNum());
s += szTmp;
}
s += " </td>";
// ФИО клиента
s += "<td valign=top>";
sprintf (szClientFIO,"%s %s %s",
client [iClient]->fnGetFamily(),
client [iClient]->fnGetName(),
client [iClient]->fnGetName2());
s += szClientFIO;
s += "</td>";
// услуга
s += "<td valign=top>";
s += fnGetServiceName (visit [iVisit]->fnGetType());
s += "</td>";
// исходная цена
s += "<td valign=top align=right>";
sprintf (szTmp,"%.2f",visit [iVisit]->fnGetOriginalPrice());
s += szTmp;
s += "</td>";
// % скидки (наценки)
s += "<td valign=top align=right>";
sprintf (szTmp,"%.2f",visit [iVisit]->fnGetDiscountPercent());
s += szTmp;
s += "</td>";
// цена
s += "<td valign=top align=right>";
sprintf (szTmp,"%.2f",visit [iVisit]->fnGetPrice());
s += szTmp;
s += "</td>";
// кол-во
s += "<td valign=top align=right>";
sprintf (szTmp,"%.2f",visit [iVisit]->fnGetQty());
s += szTmp;
s += "</td>";
// сумма
s += "<td valign=top align=right>";
sprintf (szTmp,"%.2f",visit [iVisit]->fnGetSum());
s += szTmp;
s += "</td>";
// размер скидки, руб.
if (iCycleDiscount != 7)
// (исходная цена * количество) - сумма
dTmp = (visit [iVisit]->fnGetOriginalPrice()*visit [iVisit]->fnGetQty())-visit [iVisit]->fnGetSum();
else
// наценка
dTmp = visit [iVisit]->fnGetSum()-(visit [iVisit]->fnGetOriginalPrice()*visit [iVisit]->fnGetQty());
dSum += dTmp;
dSumTotal += dTmp;
s += "<td valign=top align=right>";
sprintf (szTmp,"%.2f",dTmp);
s += szTmp;
s += "</td></tr>";
table->fnPushStr (s.c_str ());
}
if (table->fnGetQty ())
{
table->fnSort (0); // сортировка в кольце
s = "<p>";
switch (iCycleDiscount)
{
case 1: s += "С1 единовременная скидка"; break;
case 2: s += "С2 накопительная скидка"; break;
case 3: s += "С3 скидка пенсионерам"; break;
case 4: s += "С4 скидка детям"; break;
case 5: s += "С5 индивидуальная скидка"; break;
case 6: s += "С6 скидка от консультанта"; break;
case 7: s += "С7 наценка"; break;
case 8: s += "С8 скидка по расписанию"; break;
case 9: s += "С9 скидка от организации-плательщика"; break;
case 10: s += "С10 абонемент"; break;
case 11: s += "С11 скидка по дисконтной карте"; break;
}
s += "<table width=\"100%\" border=1><tr>";
if (iCycleDiscount == 11)
s += "<td align=center>№ карты</td>";
s += "<td align=center>Дата</td>";
s += "<td align=center>№ договора</td>";
s += "<td align=center>ФИО клиента</td>";
s += "<td align=center>Услуга</td>";
s += "<td align=center>Исходная цена</td>";
if (iCycleDiscount != 7)
s += "<td align=center>% скидки</td>";
else
s += "<td align=center>% наценки</td>";
s += "<td align=center>Цена</td>";
s += "<td align=center>Кол-во</td>";
s += "<td align=center>Сумма</td>";
s += "<td align=center>Размер скидки, руб.</td></tr>";
query->dst->fnAddLine(s.c_str());
while (table->fnGetQty ())
{
szBuf = new char [table->fnGetLen ()];
table->fnPop (szBuf);
query->dst->fnAddLine (szBuf);
delete [] szBuf;
}
s = "</table>";
s += "<table border=0 width=\"100%\"><tr><td align=right>Итого, руб.: ";
sprintf (szTmp,"%.2f",dSum);
s += szTmp;
s += "</td></tr></table>";
s += "</p>";
query->dst->fnAddLine(s.c_str());
}
}
s = "<p>Таблица \"Итоги\".";
s += "<table width=\"100%\" border=1>";
s += "<tr><td width=\"50%\" align=center>Итого предоставлено скидок на сумму:</td><td align=right>";
sprintf (szTmp,"%.2f",dSumTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr>";
s += "</table></p>";
query->dst->fnAddLine (s.c_str ());
fnReportEnd (query);
} // end of fnAppReportDiscountForm()
// ********************************************
// * отчёт о первичных и повторных обращениях *
// ********************************************
void fnAppReportPrimaryVisitsForm (QUERY *query)
{
char szDate1 [11];
char szDate2 [11];
char szGroupId [2 +1];
int iOrg = -1;
int iGroupId;
string s;
int iCycle,iCycle2;
std::auto_ptr<RING> primary_visits (new RING (4 kb));
std::auto_ptr<RING> total_visits (new RING (32 kb));
int iClientNum;
int iClient;
char szRegDate [11];
A_KEY_INT *client_nums;
int iQty;
int iVisit;
char szClientFIO [100]; // для вывода FIO
bool bPrev;
double dSum;
char szTmp [20];
std::auto_ptr<RING> table (new RING (10 kb));
char *szBuf;
double dSumTotal = 0.0;
int iPrimaryClientsQty;
int iTotalClientsQty;
A_KEY_INT *referred_client_nums;
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
// группа
if (! login_group->fnGetValue (szGroupId,query->szLogin))
{
strcpy (szGroupId,"-1");
login_group->fnAdd (query->szLogin,szGroupId);
}
iGroupId = atoi (szGroupId);
// организация-плательщик
if (login_org->fnGetValue (szTmp,query->szLogin))
iOrg = atoi (szTmp);
else
login_org->fnAdd (query->szLogin,"-1");
s = "Отчёт о первичных и повторных обращениях за период с ";
s += szDate1;
s += " по ";
s += szDate2;
if (iGroupId >= 0)
{
SERVICES_GROUP s_group;
groups->fnPop ((char *) &s_group,iGroupId);
s += ", группа: ";
s += s_group.szName;
}
if (iOrg != -1)
{
char szOrgName [WS_MAX_DESC_LEN +1];
s += ", плательщик: ";
s += fnGetOrgName (szOrgName,iOrg);
}
fnReportTitle (query,s.c_str ());
// выбираем актуальные посещения
for (iCycle = 0; iCycle < iVisitsQty; iCycle++)
{
if (visit [iCycle]->fnGetDelete ())
continue;
if (! fnCheckDateRange (szDate1,visit [iCycle]->fnGetPaymentDate (),szDate2))
continue;
if (visit [iCycle]->fnGetPreEntry ())
continue;
// организация-плательщик
if (iOrg != -1)
if (visit [iCycle]->fnGetOrg () != iOrg)
continue;
// группа
if (iGroupId >= 0)
if (! fnServicesGroupsGetMember (visit [iCycle]->fnGetType (),iGroupId))
continue;
if (visit [iCycle]->fnGetType () < 0)
continue;
// iClientNum = visit [iCycle]->fnGetClientNum ();
// iClient = fnClientSearchByNum (iClientNum);
iClient = visit [iCycle]->fnGetClientIndex();
if (iClient == -1)
continue;
if (iClient == 0) // Анонимный
continue;
client [iClient]->fnCreationDate ()->fnGetDate (szRegDate);
// размещаем номер записи в кольцо
if (fnCheckDateRange (szDate1,szRegDate,szDate2))
primary_visits->fnPush ((char *) &iCycle,sizeof (iCycle));
total_visits->fnPush ((char *) &iCycle,sizeof (iCycle));
}
// таблица "Первичные обращения"
client_nums = new A_KEY_INT ();
iQty = primary_visits->fnGetQty ();
for (iCycle = 0; iCycle < iQty; iCycle++)
{
primary_visits->fnPop ((char *) &iVisit,iCycle);
iClientNum = visit [iVisit]->fnGetClientNum ();
// если номера клиента в массиве нет
if (! client_nums->fnCheck (iClientNum))
{
client_nums->fnAdd (iClientNum);
// iClient = fnClientSearchByNum (iClientNum);
iClient = visit [iVisit]->fnGetClientIndex();
// дата регистрации
client [iClient]->fnCreationDate ()->fnGetDate (szRegDate);
// дата внутри комментария в формате ГГГГ/ММ/ДД для сортировки
sprintf (szTmp,"<!-- %4u/%02u/%02u -->",
fnGetYear (szRegDate),
fnGetMonth (szRegDate),
fnGetDay (szRegDate));
s = szTmp;
s += "<tr><td>";
s += szRegDate;
s += "</td><td>";
// ФИО клиента
sprintf (szClientFIO,"%s %s %s",
client [iClient]->fnGetFamily (),
client [iClient]->fnGetName (),
client [iClient]->fnGetName2 ());
s += szClientFIO;
s += "</td><td>";
// список предоставленных услуг
bPrev = false;
dSum = 0.0;
for (iCycle2 = iCycle; iCycle2 < iQty; iCycle2++)
{
primary_visits->fnPop ((char *) &iVisit,iCycle2);
if (visit [iVisit]->fnGetClientNum () == iClientNum)
{
if (bPrev)
s += ", "; // разделитель
s += fnGetServiceName (visit [iVisit]->fnGetType ());
bPrev = true;
// сумма к оплате
dSum += visit [iVisit]->fnGetSum ();
}
}
s += "</td><td align=right>";
// на сумму
sprintf (szTmp,"%.2f",dSum);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr>";
table->fnPushStr (s.c_str ());
dSumTotal += dSum;
}
}
// сохраняем кол-во первичных обращений
iPrimaryClientsQty = client_nums->fnGetQty ();
delete client_nums;
query->dst->fnAddLine ("<p>Таблица 1. Первичные обращения.");
query->dst->fnAddLine (
"<table width=\"100%\" border=1><tr>\
<td align=center>Дата регистрации</td>\
<td align=center>ФИО клиента</td>\
<td align=center>Список предоставленных услуг</td>\
<td align=center>Сумма</td></tr>");
if (table->fnGetQty ())
{
table->fnSort (0); // сортировка в кольце
while (table->fnGetQty ())
{
szBuf = new char [table->fnGetLen ()];
table->fnPop (szBuf);
query->dst->fnAddLine (szBuf);
delete [] szBuf;
}
}
query->dst->fnAddLine ("</table></p>");
query->dst->fnAddLine ("<p>Таблица 2. Соотношение.");
query->dst->fnAddLine (
"<table border=1><tr><td> </td>\
<td align=center>Кол-во</td>\
<td align=center>Оказано услуг</td>\
<td align=center>На сумму</td></tr>");
s = "<tr><td>Первичные обращения:</td><td align=right>";
sprintf (szTmp,"%i",iPrimaryClientsQty);
s += szTmp;
s += "</td><td align=right>";
sprintf (szTmp,"%i",primary_visits->fnGetQty ());
s += szTmp;
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",dSumTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr>";
query->dst->fnAddLine (s.c_str ());
// рассчитываем данные для второй строки таблицы соотношения
client_nums = new A_KEY_INT ();
iQty = total_visits->fnGetQty ();
dSumTotal = 0.0;
for (iCycle = 0; iCycle < iQty; iCycle++)
{
total_visits->fnPop ((char *) &iVisit,iCycle);
iClientNum = visit [iVisit]->fnGetClientNum ();
// если номера клиента в массиве нет
if (! client_nums->fnCheck (iClientNum))
client_nums->fnAdd (iClientNum);
// сумма к оплате
dSumTotal += visit [iVisit]->fnGetSum ();
}
// сохраняем кол-во первичных обращений
iTotalClientsQty = client_nums->fnGetQty ();
delete client_nums;
s = "<tr><td>Всего:</td><td align=right>";
sprintf (szTmp,"%i",iTotalClientsQty);
s += szTmp;
s += "</td><td align=right>";
sprintf (szTmp,"%i",total_visits->fnGetQty ());
s += szTmp;
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",dSumTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr>";
query->dst->fnAddLine (s.c_str ());
query->dst->fnAddLine ("</table></p>");
// таблица "Клиенты по направлению"
if (config.bInputCons)
{
referred_client_nums = new A_KEY_INT ();
iQty = primary_visits->fnGetQty ();
for (iCycle = 0; iCycle < iQty; iCycle++)
{
primary_visits->fnPop ((char *) &iVisit,iCycle);
if (visit [iVisit]->fnGetCons () < 0)
continue;
iClientNum = visit [iVisit]->fnGetClientNum ();
// если номера клиента в массиве нет
if (! referred_client_nums->fnCheck (iClientNum))
referred_client_nums->fnAdd (iClientNum);
}
query->dst->fnAddLine ("<p>Таблица 3. Клиенты по направлению.");
query->dst->fnAddLine (
"<table border=1><tr><td> </td>\
<td align=center>Кол-во</td></tr>");
s = "<tr><td>Первичные обращения:</td><td align=right>";
sprintf (szTmp,"%i",iPrimaryClientsQty);
s += szTmp;
s += "</td></tr>";
s += "<tr><td>Из них по направлению:</td><td align=right>";
sprintf (szTmp,"%i",referred_client_nums->fnGetQty ());
s += szTmp;
s += "</td></tr>";
s += "</table></p>";
query->dst->fnAddLine (s.c_str ());
delete referred_client_nums;
}
fnReportEnd (query);
} // end of fnAppReportPrimaryVisitsForm ()
// *********************
// * история посещений *
// *********************
void fnAppReportVisitsHistoryForm (QUERY *query)
{
RING *args = query->args;
char sz [INI_MAX_LEXEM_LEN +1];
int iSort = 1;
char szDate1 [11];
char szDate2 [11];
char szGroupId [2 +1];
int iGroupId;
int iCycle;
char szTmp [20];
string s;
std::auto_ptr<RING> visits_found (new RING (512 kb));
A_KEY_INT *client_nums;
int iQty;
int iClientNum;
int iClient;
char szClientFIO [100]; // для вывода FIO
char szPhones [CLIENT_PHONES_LEN +1];
int iCycle2;
int iVisit;
bool bPrev;
double dSum;
std::auto_ptr<RING> table (new RING (512 kb));
double dSumTotal = 0.0;
int iCounter = 1;
char *szBuf;
A_KEY_SZ *client_visits_dates;
while (args->fnGetQty ())
{
args->fnPop (sz);
if (! strcmp (sz,"sort"))
{
args->fnPop (sz);
iSort = atoi (sz);
continue;
}
}
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
// группа
if (! login_group->fnGetValue (szGroupId,query->szLogin))
{
strcpy (szGroupId,"-1");
login_group->fnAdd (query->szLogin,szGroupId);
}
iGroupId = atoi (szGroupId);
s = "История посещений за период с ";
s += szDate1;
s += " по ";
s += szDate2;
if (iGroupId >= 0)
{
SERVICES_GROUP s_group;
groups->fnPop ((char *) &s_group,iGroupId);
s += ", группа: ";
s += s_group.szName;
}
fnReportTitle (query,s.c_str ());
// очищаем накопительные переменные у всех клиентов
for (iCycle = 0; iCycle < iClientsQty; iCycle++)
client [iCycle]->fnClearTmpSum ();
// выбираем актуальные посещения
for (iCycle = 0; iCycle < iVisitsQty; iCycle++)
{
if (visit [iCycle]->fnGetDelete ())
continue;
if (! fnCheckDateRange (szDate1,visit [iCycle]->fnGetDate (),szDate2))
continue;
if (visit [iCycle]->fnGetPreEntry ())
continue;
if (visit [iCycle]->fnGetType () < 0)
continue;
// группа
if (iGroupId >= 0)
if (! fnServicesGroupsGetMember (visit [iCycle]->fnGetType (),iGroupId))
continue;
// подсчитываем сумму для каждого клиента
client [visit [iCycle]->fnGetClientIndex ()]->fnAddTmpSum (visit [iCycle]->fnGetSum ());
// размещаем номер записи в кольцо visits_found
visits_found->fnPush ((char *) &iCycle,sizeof (iCycle));
}
client_nums = new A_KEY_INT ();
iQty = visits_found->fnGetQty ();
for (iCycle = 0; iCycle < iQty; iCycle++)
{
visits_found->fnPop ((char *) &iVisit,iCycle);
iClientNum = visit [iVisit]->fnGetClientNum ();
iClient = visit [iVisit]->fnGetClientIndex ();
if (iClient == -1)
continue;
dSum = client [iClient]->fnGetTmpSum ();
if (dSum < config.dReportVisitsHistoryMinSum) // сумма меньше минимальной
continue;
// если номера клиента в массиве нет
if (! client_nums->fnCheck (iClientNum))
{
client_nums->fnAdd (iClientNum);
s.clear ();
client_visits_dates = new A_KEY_SZ ();
// начало строки не заполняем! ("<tr><td>№</td>")
// если сортировка по cуммам
if (iSort == 2)
{
s += "<!--";
sprintf (szTmp,"%09.2f",999999.00-dSum);
s += szTmp;
s += "-->";
}
// ФИО клиента
s += "<td>";
sprintf (szClientFIO,"%s %s %s",
client [iClient]->fnGetFamily (),
client [iClient]->fnGetName (),
client [iClient]->fnGetName2 ());
s += szClientFIO;
s += "</td>";
// дата рождения
s += "<td>";
s += client [iClient]->fnGetBirthday ();
s += "</td>";
// телефоны
s += "<td>";
s += client [iClient]->fnGetPhones (szPhones);
s += " </td>";
// даты посещений
s += "<td>";
bPrev = false;
for (iCycle2 = iCycle; iCycle2 < iQty; iCycle2++)
{
visits_found->fnPop ((char *) &iVisit,iCycle2);
if (visit [iVisit]->fnGetClientNum () == iClientNum)
{
// подсчитываем количество посещений (разных дат)
if (! client_visits_dates->fnCheck (visit [iVisit]->fnGetDate ()))
{
if (bPrev)
s += ", "; // разделитель
s += visit [iVisit]->fnGetDate ();
bPrev = true;
client_visits_dates->fnAdd (visit [iVisit]->fnGetDate ());
}
}
}
s += "</td>";
// количество посещений
s += "<td>";
sprintf (szTmp,"%i",client_visits_dates->fnGetQty ());
s += szTmp;
s += "</td>";
// на сумму
s += "<td align=right>";
sprintf (szTmp,"%.2f",dSum);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr>";
table->fnPushStr (s.c_str ());
dSumTotal += dSum;
delete client_visits_dates;
}
}
delete client_nums;
query->dst->fnAddLine (
"<table width=\"100%\" border=1><tr>\
<td align=center>№</td>\
<td align=center>ФИО</td>\
<td align=center>Дата рождения</td>\
<td align=center>Телефоны</td>\
<td align=center>Даты посещений</td>\
<td align=center>Кол-во посещений</td>\
<td align=center>Сумма</td></tr>");
if (table->fnGetQty ())
{
table->fnSort (0); // сортировка в кольце
while (table->fnGetQty ())
{
s = "<tr><td>";
sprintf (szTmp,"%i",iCounter++);
s += szTmp;
s += "</td>";
szBuf = new char [table->fnGetLen ()];
table->fnPop (szBuf);
s += szBuf;
delete [] szBuf;
query->dst->fnAddLine (s.c_str ());
}
}
query->dst->fnAddLine ("</table></p>");
s = "<p align=right>";
sprintf (szTmp,"Итого: %.2f",dSumTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</p>";
query->dst->fnAddLine (s.c_str ());
fnReportEnd (query);
} // end of fnAppReportVisitsHistoryForm ()
// *************************
// * акт выполненных работ *
// *************************
void fnAppReportActWorkForm (QUERY *query)
{
char szDate1 [11];
char szDate2 [11];
int iOrg = -1;
char szVisitFlagId [2 +1];
int iVisitFlagId;
int iCycle;
char szTmp [20];
string s;
char szOrgName [WS_MAX_DESC_LEN +1];
std::auto_ptr<RING> visits_found (new RING (512 kb));
A_KEY_INT *client_nums;
int iQty;
int iClientNum;
int iClient;
char szClientFIO [100]; // для вывода FIO
int iCycle2;
int iVisit;
bool bPrev;
double dSum;
std::auto_ptr<RING> table (new RING (512 kb));
double dSumTotal = 0.0;
int iCounter = 1;
char *szBuf;
char szAddress [CLIENT_ADDRESS_LEN +1];
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
// организация-плательщик
if (login_org->fnGetValue (szTmp,query->szLogin))
iOrg = atoi (szTmp);
else
login_org->fnAdd (query->szLogin,"-1");
// флажок посещения
if (! login_visitflag->fnGetValue (szVisitFlagId,query->szLogin))
{
strcpy (szVisitFlagId,"-1");
login_visitflag->fnAdd (query->szLogin,szVisitFlagId);
}
iVisitFlagId = atoi (szVisitFlagId);
s = "Акт выполненных работ за период с ";
s += szDate1;
s += " по ";
s += szDate2;
s += ", организация: ";
if (iOrg != -1)
s += fnGetOrgName (szOrgName,iOrg);
else
s += "не выбрана";
fnReportTitle (query,s.c_str ());
if (iOrg == -1)
{
fnReportEnd (query);
return;
}
// выбираем актуальные посещения
for (iCycle = 0; iCycle < iVisitsQty; iCycle++)
{
if (visit [iCycle]->fnGetDelete ())
continue;
if (visit [iCycle]->fnGetOrg () != iOrg)
continue;
if (! fnCheckDateRange (szDate1,visit [iCycle]->fnGetPaymentDate (),szDate2))
continue;
if (visit [iCycle]->fnGetPreEntry ())
continue;
// флажок посещения
switch (iVisitFlagId)
{
case 11:
if (visit [iCycle]->fnGetFlag1 () == false)
continue;
break;
case 10:
if (visit [iCycle]->fnGetFlag1 () == true)
continue;
break;
case 21:
if (visit [iCycle]->fnGetFlag2 () == false)
continue;
break;
case 20:
if (visit [iCycle]->fnGetFlag2 () == true)
continue;
break;
case 31:
if (visit [iCycle]->fnGetFlag3 () == false)
continue;
break;
case 30:
if (visit [iCycle]->fnGetFlag3 () == true)
continue;
break;
case 41:
if (visit [iCycle]->fnGetFlag4 () == false)
continue;
break;
case 40:
if (visit [iCycle]->fnGetFlag4 () == true)
continue;
}
if (visit [iCycle]->fnGetType () < 0)
continue;
// размещаем номер записи в кольцо
visits_found->fnPush ((char *) &iCycle,sizeof (iCycle));
}
client_nums = new A_KEY_INT ();
iQty = visits_found->fnGetQty ();
for (iCycle = 0; iCycle < iQty; iCycle++)
{
visits_found->fnPop ((char *) &iVisit,iCycle);
iClientNum = visit [iVisit]->fnGetClientNum ();
// если номера клиента в массиве нет
if (! client_nums->fnCheck (iClientNum))
{
client_nums->fnAdd (iClientNum);
iClient = fnClientSearchByNum (iClientNum);
if (iClient == -1)
continue;
// начало строки не заполняем! ("<tr><td>№</td>")
s = "<td>";
// ФИО клиента
sprintf (szClientFIO,"%s %s %s",
client [iClient]->fnGetFamily (),
client [iClient]->fnGetName (),
client [iClient]->fnGetName2 ());
s += szClientFIO;
s += "</td><td>";
// дата рождения
s += client [iClient]->fnGetBirthday ();
s += "</td><td>";
// адрес
s += client [iClient]->fnGetAddress (szAddress);
s += " </td><td style=\"font-size: 8pt\">";
// список предоставленных услуг
bPrev = false;
dSum = 0.0;
for (iCycle2 = iCycle; iCycle2 < iQty; iCycle2++)
{
visits_found->fnPop ((char *) &iVisit,iCycle2);
if (visit [iVisit]->fnGetClientNum () == iClientNum)
{
if (bPrev)
s += "; "; // разделитель
s += visit [iVisit]->fnGetDate ();
s += " ";
s += visit [iVisit]->fnGetTime ();
s += ": ";
s += fnGetServiceName (visit [iVisit]->fnGetType ());
sprintf (szTmp," %.2f",visit [iVisit]->fnGetPrice ());
s += szTmp;
s += "x";
sprintf (szTmp,"%.2f",visit [iVisit]->fnGetQty ());
s += szTmp;
s += "=<b>";
sprintf (szTmp,"%.2f</b>",visit [iVisit]->fnGetPrice ()*visit [iVisit]->fnGetQty ());
s += szTmp;
bPrev = true;
// сумма к оплате
dSum += visit [iVisit]->fnGetPrice ()*visit [iVisit]->fnGetQty ();
}
}
s += "</td><td align=right>";
// на сумму
sprintf (szTmp,"%.2f",dSum);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr>";
table->fnPushStr (s.c_str ());
dSumTotal += dSum;
}
}
delete client_nums;
query->dst->fnAddLine (
"<table width=\"100%\" border=1><tr>\
<td align=center>№</td>\
<td align=center>ФИО</td>\
<td align=center>Дата рождения</td>\
<td align=center>Адрес</td>\
<td align=center>Список предоставленных услуг</td>\
<td align=center>Сумма</td></tr>");
if (table->fnGetQty ())
{
table->fnSort (0); // сортировка в кольце
while (table->fnGetQty ())
{
s = "<tr><td>";
sprintf (szTmp,"%i",iCounter++);
s += szTmp;
s += "</td>";
szBuf = new char [table->fnGetLen ()];
table->fnPop (szBuf);
s += szBuf;
delete [] szBuf;
query->dst->fnAddLine (s.c_str ());
}
}
query->dst->fnAddLine ("</table></p>");
s = "<p align=right>";
sprintf (szTmp,"Итого: %.2f",dSumTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</p>";
s += "<table border=0 width=\"100%\"><tr><td width=\"50%\">Исполнитель:<br>";
s += fnGetFilialName(query->szPrefix);
s += "<br> <br><img src=\"images/color-dark-gray.gif\" width=\"75%\" height=1><br>";
s += fnGetToday (szTmp);
s += "</td><td>Заказчик:<br>";
s += szOrgName;
s += "<br> <br><img src=\"images/color-dark-gray.gif\" width=\"75%\" height=1><br>";
s += "\"____\"________ 20___</td></tr></table>";
query->dst->fnAddLine (s.c_str ());
fnReportEnd (query);
} // end of fnAppReportActWorkForm ()
// ******************************************************
// * реестр медицинских услуг для страховой организации *
// ******************************************************
void fnAppReportInsuranceOrderForm (QUERY *query)
{
char szDate1 [11];
char szDate2 [11];
int iOrg;
char sz [INI_MAX_LEXEM_LEN +1];
char szInsurerTemplate [WS_MAX_DESC_LEN +1];
VDL_TEXT *tpl;
int iCycle,iCycle2,iCycleVisit;
std::auto_ptr<RING> visits_found (new RING (4 kb));
double dSumTotal = 0.0;
int iQty;
int iClientNum;
int iClient;
const char *psz;
string s;
char szTmp [20];
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
// организация-плательщик
if (login_org->fnGetValue (szTmp,query->szLogin))
iOrg = atoi (szTmp);
else
return;
strcpy (sz,ini0.szBaseDir);
// имя файла шаблона реестра
strcat (sz,fnGetOrgInsurerTemplate (szInsurerTemplate,iOrg));
tpl = new VDL_TEXT;
tpl->fnLoad (sz); // загрузка шаблона договора
// выбираем актуальные посещения
for (iCycle = 0; iCycle < iVisitsQty; iCycle++)
{
if (visit [iCycle]->fnGetDelete ())
continue;
if (visit [iCycle]->fnGetOrg () != iOrg)
continue;
if (visit [iCycle]->fnGetPaymentType () != 3) // ОМС
continue;
if (! fnCheckDateRange (szDate1,visit [iCycle]->fnGetPaymentDate (),szDate2))
continue;
if (visit [iCycle]->fnGetPreEntry ())
continue;
if (visit [iCycle]->fnGetType () < 0)
continue;
// размещаем номер записи в кольцо
visits_found->fnPush ((char *) &iCycle,sizeof (iCycle));
// подготовка переменной dSumTotal
dSumTotal += visit [iCycleVisit]->fnGetSum ();
}
iQty = visits_found->fnGetQty ();
// формирование страницы
for (iCycle = 0; iCycle < (int) tpl->fnGetLinesQty (); iCycle++)
{
psz = tpl->fnGetLine (iCycle);
if (! strcmp (psz,"{n_fio_policy_date_ds_service_price_qty_sum_order}"))
{
for (iCycle2 = 0; iCycle2 < iQty; iCycle2++)
{
visits_found->fnPop ((char *) &iCycleVisit,iCycle2);
iClientNum = visit [iCycleVisit]->fnGetClientNum ();
iClient = fnClientSearchByNum (iClientNum);
if (iClient == -1)
continue;
// № п/п
s = "<tr><td align=right>";
sprintf (szTmp,"%i",iCycle2 +1);
s += szTmp;
// фамилия
s += "</td><td>";
s += client [iClient]->fnGetFamily ();
// имя
s += "</td><td>";
s += client [iClient]->fnGetName ();
// отчество
s += "</td><td>";
s += client [iClient]->fnGetName2 ();
// номер полиса (договора) ОМС/ДМС
s += "</td><td>";
s += visit [iCycleVisit]->fnGetPolicy ();
// дата оказания мед.услуги
s += "</td><td>";
s += visit [iCycleVisit]->fnGetDate ();
// диагноз по МКБ
s += "</td><td> ";
// наименование, код мед.услуги по прейскуранту, № зуба
s += "</td><td>";
s += fnGetServiceName (visit [iCycleVisit]->fnGetType ());
// цена мед.услуги по прейскуранту
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",visit [iCycleVisit]->fnGetPrice ());
s += szTmp;
// кол-во
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",visit [iCycleVisit]->fnGetQty ());
s += szTmp;
// сумма
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",visit [iCycleVisit]->fnGetSum ());
s += szTmp;
s += "</td></tr>";
query->dst->fnAddLine (s.c_str ());
}
continue;
}
// итоговая сумма
if (! strcmp (psz,"{sum_total}"))
{
sprintf (szTmp,"%.2f",dSumTotal);
query->dst->fnAddLine (szTmp);
continue;
}
// итоговая сумма числительными
if (! strcmp (psz,"{sum_total_numeral}"))
{
fnSumToString (sz,dSumTotal,true);
query->dst->fnAddLine (sz);
continue;
}
query->dst->fnAddLine (psz);
}
delete tpl;
} // end of fnAppReportInsuranceOrderForm ()
// ********************************
// * реестр назначений внутренний *
// ********************************
void fnAppReportPrescriptionsOrderForm (QUERY *query)
{
char szDate1 [11];
char szDate2 [11];
char szTime1 [5 +1];
char szTime2 [5 +1];
char szGroupId [2 +1];
int iTime1;
int iTime2;
int iGroupId;
int iTime;
bool bOneDay = false;
int iCycle;
char szTmp [20];
string s;
std::auto_ptr<RING> visits_found (new RING (512 kb));
int iQty;
int iVisit;
std::auto_ptr<A_KEY_SZ> contracts (new A_KEY_SZ (16 kb));
int iCurrentContractNum;
char szCurrentContractDate [11];
int iClientNum;
int iClient;
char szClientFIO [100]; // для вывода ФИО
int iCycle2;
string sCodes;
string sServices;
int iVisit2;
std::auto_ptr<RING> table (new RING (512 kb));
char *szBuf;
string sComments;
EXPORT1_ARGS s_export1_args;
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
if (fnCompareDate (szDate1,szDate2) == 0)
bOneDay = true;
// время
if (! login_time1->fnGetValue (szTime1,query->szLogin))
{
strcpy (szTime1,"00:00");
login_time1->fnAdd (query->szLogin,szTime1);
}
if (! login_time2->fnGetValue (szTime2,query->szLogin))
{
strcpy (szTime2,"23:59");
login_time2->fnAdd (query->szLogin,szTime2);
}
// преобразуем время в формат кол-ва минут после полуночи
iTime1 = fnGetMinutesAfterMidnightHM (szTime1);
iTime2 = fnGetMinutesAfterMidnightHM (szTime2);
// группа
if (! login_group->fnGetValue (szGroupId,query->szLogin))
{
strcpy (szGroupId,"-1");
login_group->fnAdd (query->szLogin,szGroupId);
}
iGroupId = atoi (szGroupId);
s = "Реестр назначений внутренний за период с ";
s += szTime1;
s += " ";
s += szDate1;
s += " по ";
s += szTime2;
s += " ";
s += szDate2;
if (iGroupId >= 0)
{
SERVICES_GROUP s_group;
groups->fnPop ((char *) &s_group,iGroupId);
s += ", группа: ";
s += s_group.szName;
}
fnReportTitle (query,s.c_str ());
// выбираем актуальные посещения
for (iCycle = 0; iCycle < iVisitsQty; iCycle++)
{
if (visit [iCycle]->fnGetDelete ())
continue;
if (! fnCheckDateRange (szDate1,visit [iCycle]->fnGetTakingDate (),szDate2))
continue;
if (visit [iCycle]->fnGetPreEntry ())
continue;
if (visit [iCycle]->fnGetType () < 0)
continue;
// группа
if (iGroupId >= 0)
if (! fnServicesGroupsGetMember (visit [iCycle]->fnGetType (),iGroupId))
continue;
// период
iTime = fnGetMinutesAfterMidnightHM (visit [iCycle]->fnGetTakingTime ());
if (bOneDay) // период охватывает только один день
{
if ((iTime < iTime1) || (iTime > iTime2))
continue;
}
else // период охватывает несколько дней
{
// первый день периода
if ((fnCompareDate (szDate1,visit [iCycle]->fnGetTakingDate ()) == 0)
&& (iTime < iTime1))
continue;
// последний день периода
if ((fnCompareDate (szDate2,visit [iCycle]->fnGetTakingDate ()) == 0)
&& (iTime > iTime2))
continue;
}
// размещаем номер записи в кольцо visits_found
visits_found->fnPush ((char *) &iCycle,sizeof (iCycle));
}
iQty = visits_found->fnGetQty ();
for (iCycle = 0; iCycle < iQty; iCycle++)
{
visits_found->fnPop ((char *) &iVisit,iCycle); // неразрушающее чтение
// формируем строковый ключ в формате "НОМЕР_ДАТА" договора
sprintf (szTmp,"%i_%s",visit [iVisit]->fnGetContractNum (),visit [iVisit]->fnGetContractDate ());
if (contracts->fnCheck (szTmp)) // для этого договора строка таблицы уже сформирована
continue;
contracts->fnAdd (szTmp); // добавляем ключ в массив
iCurrentContractNum = visit [iVisit]->fnGetContractNum ();
strcpy (szCurrentContractDate,visit [iVisit]->fnGetContractDate ());
// формируем строку таблицы
// номер договора
s = "<tr><td valign=top>";
if (strlen (visit [iVisit]->fnGetPrefix ()))
{
s += visit [iVisit]->fnGetPrefix ();
s += "-";
}
sprintf (szTmp,"%i",visit [iVisit]->fnGetContractNum ());
s += szTmp;
s += "</td>";
// ФИО клиента
s += "<td valign=top>";
iClientNum = visit [iVisit]->fnGetClientNum ();
iClient = visit [iVisit]->fnGetClientIndex ();
if (iClient == -1)
continue;
sprintf (szClientFIO,"%s %s %s",
client [iClient]->fnGetFamily (),
client [iClient]->fnGetName (),
client [iClient]->fnGetName2 ());
s += szClientFIO;
// добавляем после запятой дату рождения, если она введена
if (fnCheckDate (client [iClient]->fnGetBirthday ()))
{
s += ", ";
s += client [iClient]->fnGetBirthday ();
}
// добавляем после точки с запятой идентификатор договора
sprintf (szTmp,"; %i_%i_",iClientNum,visit [iVisit]->fnGetContractNum ());
s += szTmp;
sprintf (szTmp,"%02u%02u%02u",
fnGetDay (visit [iVisit]->fnGetContractDate ()),
fnGetMonth (visit [iVisit]->fnGetContractDate ()),
fnGetYear (visit [iVisit]->fnGetContractDate ()) -2000);
s += szTmp;
// добавляем после точки с запятой данные для лаборатории
if (client [iClient]->fnGetSex () == CLIENT_FEMALE)
{
bool bArgsFound = false;
bool bLastArgsFound = false;
/*
struct EXPORT1_ARGS
{
int iClientNum;
char szDate [11];
int iCycleDay;
int iCyclePeriod;
int iPregnancy;
};
void fnAddArgsExport1 (EXPORT1_ARGS *src);
void fnGetArgsExport1 (EXPORT1_ARGS *dst,int iClientNum);
*/
bArgsFound = fnGetArgsExport1(&s_export1_args,iClientNum,visit[iVisit]->fnGetContractDate());
if (! bArgsFound)
{
bArgsFound = fnGetLastArgsExport1 (&s_export1_args,iClientNum);
if (bArgsFound)
{
// если данные достаточно свежие
if (fnGetDayIndex(s_export1_args.szDate,szDate2) <= 31)
bLastArgsFound = true;
else
bArgsFound = false;
}
}
if (bArgsFound)
{
if (s_export1_args.iCycleDay)
{
s += "; день цикла ";
sprintf (szTmp,"%i",s_export1_args.iCycleDay);
s += szTmp;
}
if (s_export1_args.iCyclePeriod)
{
s += "; фаза цикла ";
switch (s_export1_args.iCyclePeriod)
{
case 1: s += "овуляция"; break;
case 2: s += "фолликулиновая"; break;
case 3: s += "лютеиновая"; break;
case 4: s += "менопауза"; break;
}
}
if (s_export1_args.iPregnancy)
{
s += "; срок берем/задержки ";
sprintf (szTmp,"%i",s_export1_args.iPregnancy);
s += szTmp;
}
if (bLastArgsFound)
{
s += " (";
s += s_export1_args.szDate;
s += ")";
}
}
}
s += "</td>";
// пол
s += "<td valign=top>";
if (client [iClient]->fnGetSex () == 1)
s += "М";
else
s += "Ж";
s += "</td>";
// собираем пачки кодов и наименований услуг
sCodes.clear ();
sServices.clear ();
sComments.clear ();
for (iCycle2 = iCycle; iCycle2 < iQty; iCycle2++)
{
visits_found->fnPop ((char *) &iVisit2,iCycle2); // неразрушающее чтение
if (visit [iVisit2]->fnGetContractNum () != iCurrentContractNum)
continue;
if (strcmp (visit [iVisit2]->fnGetContractDate (),szCurrentContractDate))
continue;
sCodes += "<div>";
sCodes += fnGetServiceExtCode (visit [iVisit2]->fnGetType ());
sCodes += "</div>";
sServices += "<div>";
sServices += fnGetServiceName (visit [iVisit2]->fnGetType ());
sServices += "</div>";
if (strlen (visit [iVisit2]->fnGetComments ()))
{
sComments += "<div>";
sComments += visit [iVisit2]->fnGetComments ();
sComments += "</div>";
}
}
// коды услуг
s += "<td valign=top>";
s += sCodes;
s += "</td>";
// виды услуг
s += "<td valign=top>";
s += sServices;
s += "</td>";
// примечания
s += "<td valign=top>";
s += sComments;
s += "</td>";
// штрих код
s += "<td><img src=\"images/color-white.gif\" width=";
sprintf (szTmp,"%i",config.iReportBarcodeWidth);
s += szTmp;
s += " height=";
sprintf (szTmp,"%i",config.iReportBarcodeHeight);
s += szTmp;
s += "></td></tr>";
table->fnPushStr (s.c_str ());
}
query->dst->fnAddLine ("<table width=\"100%\" border=1><tr>\
<td align=center>№ договора</td>\
<td align=center>Клиент</td>\
<td align=center>Пол</td>\
<td align=center>Коды услуг</td>\
<td align=center>Виды услуг</td>\
<td align=center>Примечания</td>\
<td align=center>Штрих-код</td></tr>");
if (table->fnGetQty ())
{
table->fnSort (0); // сортировка в кольце
while (table->fnGetQty ())
{
szBuf = new char [table->fnGetLen ()];
table->fnPop (szBuf);
query->dst->fnAddLine (szBuf);
delete [] szBuf;
}
}
query->dst->fnAddLine ("</table></p>");
fnReportEnd (query);
} // end of fnAppReportPrescriptionsOrderForm ()
// **********************************
// * реестр назначений лабораторный *
// **********************************
void fnAppReportPrescriptionsTypesOrderForm (QUERY *query)
{
char szDate1 [11];
char szDate2 [11];
char szTime1 [5 +1];
char szTime2 [5 +1];
char szGroupId [2 +1];
int iTime1;
int iTime2;
int iGroupId;
int iTime;
bool bOneDay = false;
int iCycle;
char szTmp [20];
string s;
std::auto_ptr<RING> visits_found (new RING (512 kb));
int iQty;
int iVisit;
std::auto_ptr<A_KEY_SZ> contracts (new A_KEY_SZ (16 kb));
int iCurrentContractNum;
char szCurrentContractDate [11];
int iClientNum;
int iClient;
char szClientFIO [100]; // для вывода ФИО
int iCycle2;
string sCodes;
string sServices;
int iVisit2;
std::auto_ptr<RING> table (new RING (512 kb));
char *szBuf;
string sComments;
EXPORT1_ARGS s_export1_args;
int iCycleGroup;
char szName [WS_MAX_NAME_LEN +1];
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
if (fnCompareDate (szDate1,szDate2) == 0)
bOneDay = true;
// время
if (! login_time1->fnGetValue (szTime1,query->szLogin))
{
strcpy (szTime1,"00:00");
login_time1->fnAdd (query->szLogin,szTime1);
}
if (! login_time2->fnGetValue (szTime2,query->szLogin))
{
strcpy (szTime2,"23:59");
login_time2->fnAdd (query->szLogin,szTime2);
}
// преобразуем время в формат кол-ва минут после полуночи
iTime1 = fnGetMinutesAfterMidnightHM (szTime1);
iTime2 = fnGetMinutesAfterMidnightHM (szTime2);
// группа
if (! login_group->fnGetValue (szGroupId,query->szLogin))
{
strcpy (szGroupId,"-1");
login_group->fnAdd (query->szLogin,szGroupId);
}
iGroupId = atoi (szGroupId);
s = "Реестр назначений лабораторный за период с ";
s += szTime1;
s += " ";
s += szDate1;
s += " по ";
s += szTime2;
s += " ";
s += szDate2;
if (iGroupId >= 0)
{
SERVICES_GROUP s_group;
groups->fnPop ((char *) &s_group,iGroupId);
s += ", группа: ";
s += s_group.szName;
}
fnReportTitle (query,s.c_str ());
for (iCycleGroup = 0; iCycleGroup < 52; iCycleGroup++)
{
// если группа не является видом биоматериала, пропускаем
if (! fnServicesGroupsGetBiomaterialType (iCycleGroup))
continue;
// выбираем актуальные посещения
visits_found->fnClear ();
contracts->fnClear ();
for (iCycle = 0; iCycle < iVisitsQty; iCycle++)
{
if (visit [iCycle]->fnGetDelete ())
continue;
// если услуга не включена в группу-вид биоматериала, пропускаем
if (! fnServicesGroupsGetMember (visit [iCycle]->fnGetType (),iCycleGroup))
continue;
if (! fnCheckDateRange (szDate1,visit [iCycle]->fnGetTakingDate (),szDate2))
continue;
if (visit [iCycle]->fnGetPreEntry ())
continue;
if (visit [iCycle]->fnGetType () < 0)
continue;
// группа
if (iGroupId >= 0)
if (! fnServicesGroupsGetMember (visit [iCycle]->fnGetType (),iGroupId))
continue;
// период
iTime = fnGetMinutesAfterMidnightHM (visit [iCycle]->fnGetTakingTime ());
if (bOneDay) // период охватывает только один день
{
if ((iTime < iTime1) || (iTime > iTime2))
continue;
}
else // период охватывает несколько дней
{
// первый день периода
if ((fnCompareDate (szDate1,visit [iCycle]->fnGetTakingDate ()) == 0)
&& (iTime < iTime1))
continue;
// последний день периода
if ((fnCompareDate (szDate2,visit [iCycle]->fnGetTakingDate ()) == 0)
&& (iTime > iTime2))
continue;
}
// размещаем номер записи в кольцо visits_found
visits_found->fnPush ((char *) &iCycle,sizeof (iCycle));
}
iQty = visits_found->fnGetQty ();
if (! iQty) // назначения не найдены
continue;
for (iCycle = 0; iCycle < iQty; iCycle++)
{
visits_found->fnPop ((char *) &iVisit,iCycle); // неразрушающее чтение
// формируем строковый ключ в формате "НОМЕР_ДАТА" договора
sprintf (szTmp,"%i_%s",visit [iVisit]->fnGetContractNum (),visit [iVisit]->fnGetContractDate ());
if (contracts->fnCheck (szTmp)) // для этого договора строка таблицы уже сформирована
continue;
contracts->fnAdd (szTmp); // добавляем ключ в массив
iCurrentContractNum = visit [iVisit]->fnGetContractNum ();
strcpy (szCurrentContractDate,visit [iVisit]->fnGetContractDate ());
// формируем строку таблицы
// номер договора
s = "<tr><td valign=top>";
if (strlen (visit [iVisit]->fnGetPrefix ()))
{
s += visit [iVisit]->fnGetPrefix ();
s += "-";
}
sprintf (szTmp,"%i",visit [iVisit]->fnGetContractNum ());
s += szTmp;
s += "</td>";
// ФИО клиента
s += "<td valign=top>";
iClientNum = visit [iVisit]->fnGetClientNum ();
iClient = visit [iVisit]->fnGetClientIndex ();
if (iClient == -1)
continue;
sprintf (szClientFIO,"%s %s %s",
client [iClient]->fnGetFamily (),
client [iClient]->fnGetName (),
client [iClient]->fnGetName2 ());
s += szClientFIO;
// добавляем после запятой дату рождения, если она введена
if (fnCheckDate (client [iClient]->fnGetBirthday ()))
{
s += ", ";
s += client [iClient]->fnGetBirthday ();
}
// добавляем после точки с запятой идентификатор договора
sprintf (szTmp,"; %i_%i_",iClientNum,visit [iVisit]->fnGetContractNum ());
s += szTmp;
sprintf (szTmp,"%02u%02u%02u",
fnGetDay (visit [iVisit]->fnGetContractDate ()),
fnGetMonth (visit [iVisit]->fnGetContractDate ()),
fnGetYear (visit [iVisit]->fnGetContractDate ()) -2000);
s += szTmp;
// добавляем после точки с запятой данные для лаборатории
if (client [iClient]->fnGetSex () == CLIENT_FEMALE)
{
bool bArgsFound = false;
bool bLastArgsFound = false;
/*
struct EXPORT1_ARGS
{
int iClientNum;
char szDate [11];
int iCycleDay;
int iCyclePeriod;
int iPregnancy;
};
void fnAddArgsExport1 (EXPORT1_ARGS *src);
void fnGetArgsExport1 (EXPORT1_ARGS *dst,int iClientNum);
*/
bArgsFound = fnGetArgsExport1(&s_export1_args,iClientNum,visit[iVisit]->fnGetContractDate());
if (! bArgsFound)
{
bArgsFound = fnGetLastArgsExport1 (&s_export1_args,iClientNum);
if (bArgsFound)
{
// если данные достаточно свежие
if (fnGetDayIndex(s_export1_args.szDate,szDate2) <= 31)
bLastArgsFound = true;
else
bArgsFound = false;
}
}
if (bArgsFound)
{
if (s_export1_args.iCycleDay)
{
s += "; день цикла ";
sprintf (szTmp,"%i",s_export1_args.iCycleDay);
s += szTmp;
}
if (s_export1_args.iCyclePeriod)
{
s += "; фаза цикла ";
switch (s_export1_args.iCyclePeriod)
{
case 1: s += "овуляция"; break;
case 2: s += "фолликулиновая"; break;
case 3: s += "лютеиновая"; break;
case 4: s += "менопауза"; break;
}
}
if (s_export1_args.iPregnancy)
{
s += "; срок берем/задержки ";
sprintf (szTmp,"%i",s_export1_args.iPregnancy);
s += szTmp;
}
if (bLastArgsFound)
{
s += " (";
s += s_export1_args.szDate;
s += ")";
}
}
}
s += "</td>";
// пол
s += "<td valign=top>";
if (client [iClient]->fnGetSex () == 1)
s += "М";
else
s += "Ж";
s += "</td>";
// собираем пачки кодов и наименований услуг
sCodes.clear ();
sServices.clear ();
sComments.clear ();
for (iCycle2 = iCycle; iCycle2 < iQty; iCycle2++)
{
visits_found->fnPop ((char *) &iVisit2,iCycle2); // неразрушающее чтение
if (visit [iVisit2]->fnGetContractNum () != iCurrentContractNum)
continue;
if (strcmp (visit [iVisit2]->fnGetContractDate (),szCurrentContractDate))
continue;
sCodes += "<div>";
sCodes += fnGetServiceExtCode (visit [iVisit2]->fnGetType ());
sCodes += "</div>";
sServices += "<div>";
sServices += fnGetServiceName (visit [iVisit2]->fnGetType ());
sServices += "</div>";
if (strlen (visit [iVisit2]->fnGetComments ()))
{
sComments += "<div>";
sComments += visit [iVisit2]->fnGetComments ();
sComments += "</div>";
}
}
// коды услуг
s += "<td valign=top>";
s += sCodes;
s += "</td>";
// виды услуг
s += "<td valign=top>";
s += sServices;
s += "</td>";
// примечания
s += "<td valign=top>";
s += sComments;
s += "</td>";
// штрих код
s += "<td><img src=\"images/color-white.gif\" width=";
sprintf (szTmp,"%i",config.iReportBarcodeWidth);
s += szTmp;
s += " height=";
sprintf (szTmp,"%i",config.iReportBarcodeHeight);
s += szTmp;
s += "></td></tr>";
table->fnPushStr (s.c_str ());
}
s = "<h1>";
s += fnServicesGroupsGetName (szName,iCycleGroup);
s += "</h1>";
query->dst->fnAddLine (s.c_str ());
query->dst->fnAddLine ("<table width=\"100%\" border=1><tr>\
<td align=center>№ договора</td>\
<td align=center>Клиент</td>\
<td align=center>Пол</td>\
<td align=center>Коды услуг</td>\
<td align=center>Виды услуг</td>\
<td align=center>Примечания</td>\
<td align=center>Штрих-код</td></tr>");
if (table->fnGetQty ())
{
table->fnSort (0); // сортировка в кольце
while (table->fnGetQty ())
{
szBuf = new char [table->fnGetLen ()];
table->fnPop (szBuf);
query->dst->fnAddLine (szBuf);
delete [] szBuf;
}
}
query->dst->fnAddLine ("</table></p>");
}
fnReportEnd (query);
} // end of fnAppReportPrescriptionsTypesOrderForm ()
// ********************
// * отчёт о расходах *
// ********************
void fnAppReportExpensesForm (QUERY *query)
{
char szDate1 [11];
char szDate2 [11];
string s;
int iCycle,iCycleType;
std::auto_ptr<RING> table (new RING (10 kb));
double dSum;
char szTmp [20];
double dSumTotal = 0.0;
char *szBuf;
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
s = "Отчёт о расходах за период с ";
s += szDate1;
s += " по ";
s += szDate2;
fnReportTitle (query,s.c_str ());
// список расходов
for (iCycle = 0; iCycle < iExpensesQty; iCycle++)
{
// пропускаем удалённые записи
if (expense [iCycle]->fnGetDelete ())
continue;
// пропускаем записи вне периода
if (! fnCheckDateRange (szDate1,expense [iCycle]->fnGetDate (),szDate2))
continue;
// формируем строку таблицы
// дата внутри комментария в формате ГГГГ/ММ/ДД для сортировки
sprintf (szTmp,"<!-- %4u/%02u/%02u -->",
fnGetYear (expense [iCycle]->fnGetDate ()),
fnGetMonth (expense [iCycle]->fnGetDate ()),
fnGetDay (expense [iCycle]->fnGetDate ()));
s = szTmp;
s += "<tr><td>";
s += expense [iCycle]->fnGetDate ();
s += "</td><td>";
s += fnGetExpenseName (expense [iCycle]->fnGetType ());
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",expense [iCycle]->fnGetSum ());
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td><td>";
s += expense [iCycle]->fnGetBasis ();
s += "</td></tr>";
table->fnPushStr (s.c_str ());
}
table->fnSort (0);
query->dst->fnAddLine ("Таблица 1. Список расходов.");
query->dst->fnAddLine (
"<p><table width=\"100%\" border=1><tr>\
<td align=center>Дата</td>\
<td align=center>Вид расхода</td>\
<td align=center>Сумма</td>\
<td align=center>Основание</td></tr>");
while (table->fnGetQty ())
{
szBuf = new char [table->fnGetLen ()];
table->fnPop (szBuf);
query->dst->fnAddLine (szBuf);
delete [] szBuf;
}
query->dst->fnAddLine ("</table></p>");
// расходы по видам
query->dst->fnAddLine ("Таблица 2. Расходы по видам.");
query->dst->fnAddLine (
"<p><table width=\"100%\" border=1><tr>\
<td align=center>Вид расходов</td>\
<td align=center>Сумма</td></tr>");
for (iCycleType = 0; iCycleType < iExpenseTypesQty; iCycleType++)
{
dSum = 0.0;
for (iCycle = 0; iCycle < iExpensesQty; iCycle++)
{
if (expense [iCycle]->fnGetDelete ())
continue;
if (expense [iCycle]->fnGetType () != ini4 [iCycleType]->iType)
continue;
if (! fnCheckDateRange (szDate1,expense [iCycle]->fnGetDate (),szDate2))
continue;
dSum += expense [iCycle]->fnGetSum ();
}
// подсчитываем общую сумму
dSumTotal += dSum;
// формируем строку таблицы
s = "<tr><td>";
s += ini4 [iCycleType]->szName;
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",dSum);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr>";
query->dst->fnAddLine (s.c_str ());
}
query->dst->fnAddLine ("</table>");
s = "<table border=0 width=\"100%\"><tr><td align=right>Итого: <b>";
sprintf (szTmp,"%.2f",dSumTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</b></td></tr></table></p>";
query->dst->fnAddLine (s.c_str ());
fnReportEnd (query);
} // end of fnAppReportExpensesForm ()
// ****************************************************************************
// * *
// * ОТЧЁТЫ МОДУЛЯ КОНТРОЛЯ *
// * *
// ****************************************************************************
// ******************************************************
// * отчёт МК2 о предоставленных единовременных скидках *
// ******************************************************
void fnAppReportControl2_Form (QUERY *query)
{
char szDate1 [11];
char szDate2 [11];
string s;
char szTmp [20];
int iCycle;
int iClient;
char szClientFIO [100]; // для вывода FIO
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
s = "МК2: Отчёт о предоставленных единовременных скидках более ";
sprintf (szTmp,"%i",config.iCheck2Max);
s += szTmp;
s += "% за период с ";
s += szDate1;
s += " по ";
s += szDate2;
fnReportTitle (query,s.c_str ());
query->dst->fnAddLine (
"<table width=\"100%\" border=1><tr>\
<td align=center>Дата</td>\
<td align=center>Время</td>\
<td align=center>Клиент</td>\
<td align=center>Услуга</td>\
<td align=center>Цена</td>\
<td align=center>Кол-во</td>\
<td align=center>Сумма к оплате</td>\
<td align=center>Исходная цена</td>\
<td align=center>Скидка, %</td>\
<td align=center>Префикс</td>\
<td align=center>Примечания</td></tr>");
for (iCycle = 0; iCycle < iVisitsQty; iCycle++)
{
if (visit [iCycle]->fnGetDelete ())
continue;
// если дата платежа не входит в период
if (! fnCheckDateRange (szDate1,visit [iCycle]->fnGetPaymentDate (),szDate2))
continue;
if (visit [iCycle]->fnGetDiscountType () != 1)
continue;
if (visit [iCycle]->fnGetDiscountPercent () <= (double) config.iCheck2Max)
continue;
// дата внутри комментария в формате ГГГГ/ММ/ДД для сортировки
sprintf (szTmp,"<!-- %4u/%02u/%02u -->",
fnGetYear (visit [iCycle]->fnGetPaymentDate ()),
fnGetMonth (visit [iCycle]->fnGetPaymentDate ()),
fnGetDay (visit [iCycle]->fnGetPaymentDate ()));
s = szTmp;
s += "<tr><td>";
s += visit [iCycle]->fnGetPaymentDate (); // дата платежа
s += "</td><td>";
s += visit [iCycle]->fnGetPaymentTime (); // время
s += "</td><td>";
// клиент
iClient = fnClientSearchByNum (visit [iCycle]->fnGetClientNum ());
if (iClient == -1)
continue;
sprintf (szClientFIO,"%s %s %s",
client [iClient]->fnGetFamily (),
client [iClient]->fnGetName (),
client [iClient]->fnGetName2 ());
s += szClientFIO;
s += "</td><td>";
// услуга
s += fnGetServiceName (visit [iCycle]->fnGetType ());
s += "</td><td>";
// цена
sprintf (szTmp,"%.2f",visit [iCycle]->fnGetPrice ());
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td><td>";
// кол-во
sprintf (szTmp,"%.2f",visit [iCycle]->fnGetQty ());
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td><td>";
// сумма к оплате
sprintf (szTmp,"%.2f",visit [iCycle]->fnGetSum ());
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td><td>";
// исходная цена
sprintf (szTmp,"%.2f",visit [iCycle]->fnGetOriginalPrice ());
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td><td>";
// скидка
sprintf (szTmp,"%.2f %%",visit [iCycle]->fnGetDiscountPercent ());
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td><td>";
s += visit [iCycle]->fnGetPrefix (); // префикс
s += " </td><td>";
s += visit [iCycle]->fnGetComments (); // примечания
s += " </td></tr>";
query->dst->fnAddLine (s.c_str ());
}
query->dst->fnAddLine ("</table>");
fnReportEnd (query);
} // end of fnAppReportControl2_Form ()
// *******************************
// * отчёт о созданных договорах *
// *******************************
void fnAppReportContractsForm (QUERY *query)
{
std::auto_ptr<RING> contracts (new RING (1024 kb));
string s;
int iQty;
int iCycle;
EVENT_RECORD s_event;
SYSTEMTIME lt;
char szTmp [20];
int iClient;
char szClientFIO [100]; // для вывода FIO
std::auto_ptr<A_ARRAY> contract_sum (new A_ARRAY (64 kb));
// ключ ассоциативного массива в формате "номер договора_дата заключения"
char szKey [20];
double dContractSum;
query->ws_ptr->fnGetEvents(contracts.get(),1);
fnReportTitle(query,"Отчёт о созданных договорах");
s = "<table width=\"100%\" border=1 cellspacing=0><tr>\
<td>FILETIME</td>\
<td>Подтип</td>\
<td>Логин</td>\
<td>Событие</td>\
<td>№ и дата договора</td>\
<td>Клиент</td>\
<td>Сумма</td>\
<td>Страница</td></tr>";
iQty = contracts->fnGetQty();
for (iCycle = 0; iCycle < iQty; iCycle++)
{
contracts->fnPop((char *) &s_event);
s += "<tr";
// ключ ассоциативного массива - строка с номером и датой договора
sprintf(szKey,"%i_%s",s_event.iValue1,s_event.szDate);
if (contract_sum->fnGetValue(szTmp,szKey))
{
dContractSum = atof(szTmp);
// если сумма договора уменьшилась
if (s_event.dValue5 < dContractSum)
{
// окрашиваем строку таблицы в предупредительный цвет
s += " bgcolor=\"";
s += szColorOrange;
s += "\"";
}
else
{
// если сумма договора увеличилась
if (s_event.dValue5 > dContractSum)
{
sprintf(szTmp,"%.2f",s_event.dValue5);
contract_sum->fnAdd(szKey,szTmp);
}
}
}
else
{
sprintf(szTmp,"%.2f",s_event.dValue5);
contract_sum->fnAdd(szKey,szTmp);
}
s += ">";
// FILETIME
s += "<td>";
FileTimeToSystemTime(&s_event.ft,<);
sprintf (szTmp,"%02u/%02u/%4u %02u:%02u:%02u",
lt.wDay,lt.wMonth,lt.wYear,lt.wHour,lt.wMinute,lt.wSecond);
s += szTmp;
s += "</td>";
// подтип
s += "<td>";
sprintf (szTmp,"%i",s_event.iSubType);
s += szTmp;
s += "</td>";
// логин
s += "<td>";
s += s_event.szOwner;
s += "</td>";
// событие
s += "<td>";
s += s_event.szDesc;
s += "</td>";
// номер и дата договора
s += "<td>";
sprintf(szTmp,"%i от ",s_event.iValue1);
s += szTmp;
s += s_event.szDate;
s += "</td>";
// клиент
s += "<td>";
iClient = fnClientSearchByNum(s_event.iValue2);
if (iClient == -1)
continue;
sprintf(szClientFIO,"%s %s %s",
client [iClient]->fnGetFamily(),
client [iClient]->fnGetName(),
client [iClient]->fnGetName2());
s += szClientFIO;
s += "</td>";
// сумма
s += "<td>";
sprintf(szTmp,"%.2f",s_event.dValue5);
s += szTmp;
s += "</td>";
// страница
s += "<td>";
if (s_event.iValue3)
{
sprintf(szTmp,"%i",s_event.iValue3);
s += szTmp;
}
s += " </td></tr>";
}
s += "</table>";
query->dst->fnAddLine(s.c_str ());
fnReportEnd(query);
} // end of fnAppReportContractsForm()
// ******************************************************************
// * отчёт о редактировании прейскуранта в конструкторе видов услуг *
// ******************************************************************
void fnAppReportServicesEditForm (QUERY *query)
{
std::auto_ptr<RING> services_edit (new RING (1024 kb));
string s;
int iQty;
int iCycle;
EVENT_RECORD s_event;
SYSTEMTIME lt;
char szTmp [20];
query->ws_ptr->fnGetEvents(services_edit.get(),2);
fnReportTitle(query,"Отчёт о редактировании прейскуранта в конструкторе видов услуг");
s = "<table width=\"100%\" border=1 cellspacing=0><tr>\
<td>FILETIME</td>\
<td>Подтип</td>\
<td>Логин</td>\
<td>Событие</td>\
<td>№</td>\
<td>Наименование</td>\
<td>Прежнее значение</td>\
<td>Новое значение</td></tr>";
iQty = services_edit->fnGetQty();
for (iCycle = 0; iCycle < iQty; iCycle++)
{
services_edit->fnPop((char *) &s_event);
s += "<tr>";
// FILETIME
s += "<td>";
FileTimeToSystemTime(&s_event.ft,<);
sprintf (szTmp,"%02u/%02u/%4u %02u:%02u:%02u",
lt.wDay,lt.wMonth,lt.wYear,lt.wHour,lt.wMinute,lt.wSecond);
s += szTmp;
s += "</td>";
// подтип
s += "<td>";
sprintf (szTmp,"%i",s_event.iSubType);
s += szTmp;
s += "</td>";
// логин
s += "<td>";
s += s_event.szOwner;
s += "</td>";
// событие
s += "<td>";
s += s_event.szDesc;
s += "</td>";
// уникальный номер
s += "<td>";
sprintf(szTmp,"%i",s_event.iValue1);
s += szTmp;
s += "</td>";
// наименование
s += "<td>";
s += s_event.szValue7;
s += "</td>";
// прежнее значение
s += "<td>";
switch (s_event.iSubType)
{
case 4:
case 5:
case 6:
case 7:
case 8:
sprintf(szTmp,"%.2f",s_event.dValue5);
s += szTmp;
}
s += " </td>";
// новое значение
s += "<td>";
switch (s_event.iSubType)
{
case 4:
case 5:
case 6:
case 7:
case 8:
sprintf(szTmp,"%.2f",s_event.dValue6);
s += szTmp;
}
s += " </td>";
s += "</tr>";
}
s += "</table>";
query->dst->fnAddLine(s.c_str ());
fnReportEnd(query);
} // end of fnAppReportServicesEditForm()
// ****************************************************************************
// * *
// * ОТЧЁТЫ О РАБОТЕ СПЕЦИАЛИСТОВ *
// * *
// ****************************************************************************
// **************************************
// * отчёт по ведению амбулаторных карт *
// **************************************
void fnAppReportMapKeepingForm (QUERY *query)
{
char szDate1 [11];
char szDate2 [11];
string s;
char szTmp [20];
int iCycleSpec,iCycle;
int iQty;
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
s = "Отчёт о работе специалистов за период с ";
s += szDate1;
s += " по ";
s += szDate2;
s += "<br>Ведение амбулаторных карт";
fnReportTitle (query,s.c_str ());
query->dst->fnAddLine (
"<table width=\"100%\" border=1><tr>\
<td align=center>Специалист</td>\
<td align=center>Кол-во новых амбулаторных карт</td></tr>");
for (iCycleSpec = 0; iCycleSpec < iSpecsQty; iCycleSpec++)
{
// пропускаем консультантов
if (fnGetSpecCons (fnGetSpecType (iCycleSpec)))
continue;
iQty = 0;
for (iCycle = 0; iCycle < iMapsQty; iCycle++)
{
if (map [iCycle]->fnGetDelete ())
continue;
if (! fnCheckDateRange (szDate1,map [iCycle]->fnGetDate (),szDate2))
continue;
if (map [iCycle]->fnGetSpec () != fnGetSpecType (iCycleSpec))
continue;
iQty++;
}
// формируем строку таблицы
s = "<tr><td>";
s += fnGetSpecFIO (fnGetSpecType (iCycleSpec));
s += "</td><td align=right>";
sprintf (szTmp,"%i",iQty);
s += szTmp;
s += "</td></tr>";
query->dst->fnAddLine (s.c_str ());
}
query->dst->fnAddLine ("</table>");
fnReportEnd (query);
} // end of fnAppReportMapKeepingForm ()
// *****************************************
// * выполненные работы и заработная плата *
// *****************************************
void fnAppReportSalaryForm (QUERY *query)
{
char szDate1 [11];
char szDate2 [11];
char szGroupId [2 +1];
char szVisitFlagId [2 +1];
int iOrg = -1;
int iGroupId;
int iVisitFlagId;
std::auto_ptr<RING> visits_found (new RING (64 kb));
int iQty;
int iVisit;
string s;
char szTmp [20];
char szClientFIO [100];
int iCycleSpec,iCycle;
// int iClientNum;
int iClient;
double dSumTotal;
double dSalary;
std::auto_ptr<RING> table (new RING (10 kb));
double dSalaryTotal;
int iSpecType;
double dSumOverall = 0.0;
double dSalaryOverall = 0.0;
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
// группа
if (! login_group->fnGetValue (szGroupId,query->szLogin))
{
strcpy (szGroupId,"-1");
login_group->fnAdd (query->szLogin,szGroupId);
}
iGroupId = atoi (szGroupId);
// флажок посещения
if (! login_visitflag->fnGetValue (szVisitFlagId,query->szLogin))
{
strcpy (szVisitFlagId,"-1");
login_visitflag->fnAdd (query->szLogin,szVisitFlagId);
}
iVisitFlagId = atoi (szVisitFlagId);
// организация-плательщик
if (login_org->fnGetValue (szTmp,query->szLogin))
iOrg = atoi (szTmp);
else
login_org->fnAdd (query->szLogin,"-1");
s = "Выполненные работы и заработная плата за период с ";
s += szDate1;
s += " по ";
s += szDate2;
if (iGroupId >= 0)
{
SERVICES_GROUP s_group;
groups->fnPop ((char *) &s_group,iGroupId);
s += ", группа: ";
s += s_group.szName;
}
if (iOrg != -1)
{
char szOrgName [WS_MAX_DESC_LEN +1];
s += ", плательщик: ";
s += fnGetOrgName (szOrgName,iOrg);
}
fnReportTitle (query,s.c_str ());
// выбираем актуальные посещения
for (iCycle = 0; iCycle < iVisitsQty; iCycle++)
{
if (visit [iCycle]->fnGetDelete ())
continue;
if (! fnCheckDateRange (szDate1,visit [iCycle]->fnGetDate (),szDate2))
continue;
if (visit [iCycle]->fnGetPreEntry ())
continue;
// организация-плательщик
if (iOrg != -1)
if (visit [iCycle]->fnGetOrg () != iOrg)
continue;
// флажок посещения
switch (iVisitFlagId)
{
case 11:
if (visit [iCycle]->fnGetFlag1 () == false)
continue;
break;
case 10:
if (visit [iCycle]->fnGetFlag1 () == true)
continue;
break;
case 21:
if (visit [iCycle]->fnGetFlag2 () == false)
continue;
break;
case 20:
if (visit [iCycle]->fnGetFlag2 () == true)
continue;
break;
case 31:
if (visit [iCycle]->fnGetFlag3 () == false)
continue;
break;
case 30:
if (visit [iCycle]->fnGetFlag3 () == true)
continue;
break;
case 41:
if (visit [iCycle]->fnGetFlag4 () == false)
continue;
break;
case 40:
if (visit [iCycle]->fnGetFlag4 () == true)
continue;
}
// группа
if (iGroupId >= 0)
if (! fnServicesGroupsGetMember (visit [iCycle]->fnGetType (),iGroupId))
continue;
if (visit [iCycle]->fnGetAbsence ())
continue;
if (visit [iCycle]->fnGetType () < 0)
continue;
// размещаем номер записи в кольцо visits_found
visits_found->fnPush ((char *) &iCycle,sizeof (iCycle));
}
iQty = visits_found->fnGetQty ();
// цикл по специалистам
for (iCycleSpec = 0; iCycleSpec < iSpecsQty; iCycleSpec++)
{
iSpecType = fnGetSpecType (iCycleSpec);
// пропускаем консультантов
if (fnGetSpecCons (iSpecType))
continue;
dSumTotal = 0.0;
dSalaryTotal = 0.0;
for (iCycle = 0; iCycle < iQty; iCycle++)
{
// выбираем записи для текущего специалиста
visits_found->fnPop ((char *) &iVisit,iCycle);
if (visit [iVisit]->fnGetSpec () != iSpecType)
continue;
dSumTotal += visit [iVisit]->fnGetSum ();
dSalary = visit [iVisit]->fnGetSpecPayment ();
dSalaryTotal += dSalary;
// формируем строку таблицы
// iClientNum = visit [iCycle]->fnGetClientNum ();
// iClient = fnClientSearchByNum (iClientNum);
iClient = visit [iVisit]->fnGetClientIndex ();
if (iClient == -1)
continue;
// дата внутри комментария в формате ГГГГ/ММ/ДД для сортировки
sprintf (szTmp,"<!-- %4u/%02u/%02u -->",
fnGetYear (visit [iVisit]->fnGetDate ()),
fnGetMonth (visit [iVisit]->fnGetDate ()),
fnGetDay (visit [iVisit]->fnGetDate ()));
s = szTmp;
s += "<tr><td>";
s += visit [iVisit]->fnGetDate ();
s += "</td><td>";
sprintf (szClientFIO,"%s %s %s",
client [iClient]->fnGetFamily (),
client [iClient]->fnGetName (),
client [iClient]->fnGetName2 ());
s += szClientFIO;
s += "</td><td>";
s += fnGetServiceName (visit [iVisit]->fnGetType ());
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",visit [iVisit]->fnGetSum ());
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",visit [iVisit]->fnGetConsPayment ());
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",dSalary);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr>";
table->fnPushStr (s.c_str ());
}
if (table->fnGetQty ())
{
char *sz;
table->fnSort (0); // сортировка в кольце
s = "Таблица \"Выполненные работы (используется дата посещения): ";
s += fnGetSpecFIO (iSpecType);
if (*fnGetSpecProfession (iSpecType))
{
s += " - ";
s += fnGetSpecProfession (iSpecType);
}
s += "\".";
query->dst->fnAddLine (s.c_str ());
query->dst->fnAddLine (
"<table width=\"100%\" border=1 style=\"font-family: arial, sans-serif; font-size: 9pt;\"><tr>\
<td width=\"10%\" align=center>Дата</td>\
<td width=\"20%\" align=center>ФИО клиента</td>\
<td width=\"40%\" align=center>Вид услуг</td>\
<td width=\"10%\" align=center>Сумма</td>\
<td width=\"10%\" align=center>Консультанту</td>\
<td width=\"10%\" align=center>Заработная плата</td></tr>");
while (table->fnGetQty ())
{
sz = new char [table->fnGetLen ()];
table->fnPop (sz);
query->dst->fnAddLine (sz);
delete [] sz;
}
query->dst->fnAddLine ("</table>");
s = "<table border=0 width=\"100%\"><tr><td align=right>Итого выполнено работ на сумму: <b>";
sprintf (szTmp,"%.2f",dSumTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</b><br>Итого заработная плата: <b>";
sprintf (szTmp,"%.2f",dSalaryTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</b></td></tr></table>";
query->dst->fnAddLine (s.c_str ());
}
dSumOverall += dSumTotal;
dSalaryOverall += dSalaryTotal;
}
s = "<p>Таблица \"Итоги\".";
s += "<table width=\"100%\" border=1 style=\"font-family: arial, sans-serif; font-size: 9pt;\">\
<tr><td width=\"50%\" align=center>Итого выполнено работ на сумму:</td><td align=center>Итого заработная плата:</td></tr>";
s += "<tr><td align=right>";
sprintf (szTmp,"%.2f",dSumOverall);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",dSalaryOverall);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr></table></p>";
query->dst->fnAddLine (s.c_str ());
fnReportEnd (query);
} // end of fnAppReportSalaryForm ()
// ****************************
// * заработная плата (итоги) *
// ****************************
void fnAppReportSalaryShortForm (QUERY *query)
{
char szDate1 [11];
char szDate2 [11];
char szGroupId [2 +1];
char szVisitFlagId [2 +1];
int iOrg = -1;
int iGroupId;
int iVisitFlagId;
std::auto_ptr<RING> visits_found (new RING (64 kb));
int iQty;
int iVisit;
string s;
char szTmp [20];
int iCycleSpec,iCycle;
double dSumTotal;
double dSalary;
double dSalaryTotal;
int iSpecType;
double dSumOverall = 0.0;
double dSalaryOverall = 0.0;
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
// группа
if (! login_group->fnGetValue (szGroupId,query->szLogin))
{
strcpy (szGroupId,"-1");
login_group->fnAdd (query->szLogin,szGroupId);
}
iGroupId = atoi (szGroupId);
// флажок посещения
if (! login_visitflag->fnGetValue (szVisitFlagId,query->szLogin))
{
strcpy (szVisitFlagId,"-1");
login_visitflag->fnAdd (query->szLogin,szVisitFlagId);
}
iVisitFlagId = atoi (szVisitFlagId);
// организация-плательщик
if (login_org->fnGetValue (szTmp,query->szLogin))
iOrg = atoi (szTmp);
else
login_org->fnAdd (query->szLogin,"-1");
s = "Заработная плата (итоги) за период с ";
s += szDate1;
s += " по ";
s += szDate2;
if (iGroupId >= 0)
{
SERVICES_GROUP s_group;
groups->fnPop ((char *) &s_group,iGroupId);
s += ", группа: ";
s += s_group.szName;
}
if (iOrg != -1)
{
char szOrgName [WS_MAX_DESC_LEN +1];
s += ", плательщик: ";
s += fnGetOrgName (szOrgName,iOrg);
}
fnReportTitle (query,s.c_str ());
// выбираем актуальные посещения
for (iCycle = 0; iCycle < iVisitsQty; iCycle++)
{
if (visit [iCycle]->fnGetDelete ())
continue;
if (! fnCheckDateRange (szDate1,visit [iCycle]->fnGetDate (),szDate2))
continue;
if (visit [iCycle]->fnGetPreEntry ())
continue;
// организация-плательщик
if (iOrg != -1)
if (visit [iCycle]->fnGetOrg () != iOrg)
continue;
// флажок посещения
switch (iVisitFlagId)
{
case 11:
if (visit [iCycle]->fnGetFlag1 () == false)
continue;
break;
case 10:
if (visit [iCycle]->fnGetFlag1 () == true)
continue;
break;
case 21:
if (visit [iCycle]->fnGetFlag2 () == false)
continue;
break;
case 20:
if (visit [iCycle]->fnGetFlag2 () == true)
continue;
break;
case 31:
if (visit [iCycle]->fnGetFlag3 () == false)
continue;
break;
case 30:
if (visit [iCycle]->fnGetFlag3 () == true)
continue;
break;
case 41:
if (visit [iCycle]->fnGetFlag4 () == false)
continue;
break;
case 40:
if (visit [iCycle]->fnGetFlag4 () == true)
continue;
}
// группа
if (iGroupId >= 0)
if (! fnServicesGroupsGetMember (visit [iCycle]->fnGetType (),iGroupId))
continue;
if (visit [iCycle]->fnGetAbsence ())
continue;
if (visit [iCycle]->fnGetType () < 0)
continue;
// размещаем номер записи в кольцо visits_found
visits_found->fnPush ((char *) &iCycle,sizeof (iCycle));
}
iQty = visits_found->fnGetQty ();
// цикл по специалистам
for (iCycleSpec = 0; iCycleSpec < iSpecsQty; iCycleSpec++)
{
iSpecType = fnGetSpecType (iCycleSpec);
// пропускаем консультантов
if (fnGetSpecCons (iSpecType))
continue;
dSumTotal = 0.0;
dSalaryTotal = 0.0;
for (iCycle = 0; iCycle < iQty; iCycle++)
{
// выбираем записи для текущего специалиста
visits_found->fnPop ((char *) &iVisit,iCycle);
if (visit [iVisit]->fnGetSpec () != iSpecType)
continue;
dSumTotal += visit [iVisit]->fnGetSum ();
dSalary = visit [iVisit]->fnGetSpecPayment ();
dSalaryTotal += dSalary;
}
if (dSumTotal != 0)
{
s = "<p>Таблица \"Заработная плата (используется дата посещения): ";
s += fnGetSpecFIO (iSpecType);
if (*fnGetSpecProfession (iSpecType))
{
s += " - ";
s += fnGetSpecProfession (iSpecType);
}
s += "\".";
query->dst->fnAddLine (s.c_str ());
s = "<table width=\"100%\" border=1 style=\"font-family: arial, sans-serif; font-size: 9pt;\">\
<tr><td width=\"50%\" align=center>Выполнены работы на сумму</td><td align=center>Заработная плата</td></tr>";
s += "<tr><td align=right>";
sprintf (szTmp,"%.2f",dSumTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",dSalaryTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr></table></p>";
query->dst->fnAddLine (s.c_str ());
}
dSumOverall += dSumTotal;
dSalaryOverall += dSalaryTotal;
}
s = "<p>Таблица \"Итоги\".";
s += "<table width=\"100%\" border=1 style=\"font-family: arial, sans-serif; font-size: 9pt;\">\
<tr><td width=\"50%\" align=center>Итого выполнено работ на сумму:</td><td align=center>Итого заработная плата:</td></tr>";
s += "<tr><td align=right>";
sprintf (szTmp,"%.2f",dSumOverall);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",dSalaryOverall);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr></table></p>";
query->dst->fnAddLine (s.c_str ());
fnReportEnd (query);
} // end of fnAppReportSalaryShortForm ()
// *************************************
// * история посещений по специалистам *
// *************************************
void fnAppReportSpecsHistoryForm (QUERY *query)
{
RING *args = query->args;
char sz [INI_MAX_LEXEM_LEN +1];
bool bPrimary = false;
char szDate1 [11];
char szDate2 [11];
char szGroupId [2 +1];
int iGroupId;
int iCycle;
char szTmp [20];
string s;
std::auto_ptr<RING> visits_found (new RING (512 kb));
A_KEY_INT *client_nums;
int iQty;
int iClientNum;
int iClient;
char szClientFIO [100]; // для вывода FIO
int iCycle2;
int iVisit;
bool bPrev;
double dSum;
std::auto_ptr<RING> table (new RING (512 kb));
double dSumTotal = 0.0;
int iCounter;
char *szBuf;
std::auto_ptr<A_KEY_SZ> client_visits_dates (new A_KEY_SZ);
int iCycleSpec;
int iSpecType;
double dTmp;
char szRegDate [11];
double dSumOverall = 0.0;
while (args->fnGetQty ())
{
args->fnPop (sz);
if (! strcmp (sz,"primary"))
{
args->fnPop (sz);
bPrimary = true;
continue;
}
}
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
// группа
if (! login_group->fnGetValue (szGroupId,query->szLogin))
{
strcpy (szGroupId,"-1");
login_group->fnAdd (query->szLogin,szGroupId);
}
iGroupId = atoi (szGroupId);
if (bPrimary)
s = "История первичных посещений по специалистам за период с ";
else
s = "История посещений по специалистам за период с ";
s += szDate1;
s += " по ";
s += szDate2;
if (iGroupId >= 0)
{
SERVICES_GROUP s_group;
groups->fnPop ((char *) &s_group,iGroupId);
s += ", группа: ";
s += s_group.szName;
}
fnReportTitle (query,s.c_str ());
// выбираем актуальные посещения
for (iCycle = 0; iCycle < iVisitsQty; iCycle++)
{
if (visit [iCycle]->fnGetDelete ())
continue;
if (! fnCheckDateRange (szDate1,visit [iCycle]->fnGetDate (),szDate2))
continue;
if (visit [iCycle]->fnGetPreEntry ())
continue;
if (visit [iCycle]->fnGetType () < 0)
continue;
// группа
if (iGroupId >= 0)
if (! fnServicesGroupsGetMember (visit [iCycle]->fnGetType (),iGroupId))
continue;
if (bPrimary)
{
iClient = visit [iCycle]->fnGetClientIndex();
if (iClient == -1)
continue;
if (iClient == 0) // Анонимный
continue;
client [iClient]->fnCreationDate ()->fnGetDate (szRegDate);
if (! fnCheckDateRange (szDate1,szRegDate,szDate2))
continue;
}
// размещаем номер записи в кольцо visits_found
visits_found->fnPush ((char *) &iCycle,sizeof (iCycle));
}
client_nums = new A_KEY_INT ();
iQty = visits_found->fnGetQty ();
// цикл по специалистам
for (iCycleSpec = 0; iCycleSpec < iSpecsQty; iCycleSpec++)
{
iSpecType = fnGetSpecType (iCycleSpec);
// пропускаем консультантов
if (fnGetSpecCons (iSpecType))
continue;
client_nums->fnClear();
iCounter = 1;
dSumTotal = 0.0;
for (iCycle = 0; iCycle < iQty; iCycle++)
{
// выбираем записи для текущего специалиста
visits_found->fnPop ((char *) &iVisit,iCycle);
if (visit [iVisit]->fnGetSpec () != iSpecType)
continue;
iClientNum = visit [iVisit]->fnGetClientNum ();
iClient = visit [iVisit]->fnGetClientIndex ();
if (iClient == -1)
continue;
// если номера клиента в массиве нет
if (! client_nums->fnCheck (iClientNum))
{
client_nums->fnAdd (iClientNum);
client_visits_dates->fnClear();
dSum = 0.0;
// начало строки не заполняем! ("<tr><td>№</td>")
// ФИО клиента, дата рождения
s = "<td>";
sprintf (szClientFIO,"%s %s %s",
client [iClient]->fnGetFamily (),
client [iClient]->fnGetName (),
client [iClient]->fnGetName2 ());
s += szClientFIO;
s += ", ";
s += client [iClient]->fnGetBirthday ();
s += "</td>";
// номер амбулаторной карты
if (ini1.bSpecMedical)
{
s += "<td>";
if (client [iClient]->fnGetMapOrderNum())
{
sprintf (szTmp,"%i",client [iClient]->fnGetMapOrderNum());
s += szTmp;
}
s += " </td>";
}
// даты посещений
s += "<td>";
bPrev = false;
for (iCycle2 = iCycle; iCycle2 < iQty; iCycle2++)
{
visits_found->fnPop ((char *) &iVisit,iCycle2);
if (visit [iVisit]->fnGetClientNum () != iClientNum)
continue;
if (visit [iVisit]->fnGetSpec () != iSpecType)
continue;
// подсчитываем количество посещений (разных дат)
if (! client_visits_dates->fnCheck (visit [iVisit]->fnGetDate ()))
{
if (bPrev)
s += ", "; // разделитель
s += visit [iVisit]->fnGetDate ();
bPrev = true;
client_visits_dates->fnAdd (visit [iVisit]->fnGetDate ());
}
// подсчитываем сумму
dTmp = visit [iVisit]->fnGetSum();
dSum += dTmp;
dSumTotal += dTmp;
}
s += "</td>";
// количество посещений
s += "<td>";
sprintf (szTmp,"%i",client_visits_dates->fnGetQty ());
s += szTmp;
s += "</td>";
// на сумму
s += "<td align=right>";
sprintf (szTmp,"%.2f",dSum);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr>";
table->fnPushStr (s.c_str ());
}
}
if (table->fnGetQty ())
{
table->fnSort (0); // сортировка в кольце
s = "Таблица \"";
s += fnGetSpecFIO (iSpecType);
if (*fnGetSpecProfession (iSpecType))
{
s += " - ";
s += fnGetSpecProfession (iSpecType);
}
s += "\".";
s += "<table width=\"100%\" border=1><tr>";
s += "<td align=center width=\"5%\">№</td>";
s += "<td align=center width=\"35%\">ФИО</td>";
if (ini1.bSpecMedical)
s += "<td align=center width=\"10%\">№ амб. карты</td>";
s += "<td align=center width=\"30%\">Даты посещений</td>";
s += "<td align=center width=\"10%\">Кол-во посещений</td>";
s += "<td align=center width=\"10%\">Сумма</td></tr>";
query->dst->fnAddLine (s.c_str ());
while (table->fnGetQty ())
{
s = "<tr><td>";
sprintf (szTmp,"%i",iCounter++);
s += szTmp;
s += "</td>";
szBuf = new char [table->fnGetLen ()];
table->fnPop (szBuf);
s += szBuf;
delete [] szBuf;
query->dst->fnAddLine (s.c_str ());
}
query->dst->fnAddLine ("</table></p>");
s = "<p align=right>";
sprintf (szTmp,"Итого: %.2f",dSumTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</p>";
query->dst->fnAddLine (s.c_str ());
dSumOverall += dSumTotal;
}
}
delete client_nums;
s = "<p>Таблица \"Итоги\".";
s += "<table width=\"100%\" border=1>";
s += "<tr><td width=\"50%\" align=center>Общая сумма:</td><td align=right>";
sprintf (szTmp,"%.2f",dSumOverall);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr>";
s += "</table></p>";
query->dst->fnAddLine (s.c_str ());
fnReportEnd (query);
} // end of fnAppReportSpecsHistoryForm()
// ****************************
// * начисления консультантам *
// ****************************
void fnAppReportConsPaymentsForm (QUERY *query)
{
char szDate1 [11];
char szDate2 [11];
char szGroupId [2 +1];
char szVisitFlagId [2 +1];
int iGroupId;
int iVisitFlagId;
string s;
char szTmp [20];
char szClientFIO [100];
int iCycleSpec,iCycle;
int iClientNum;
int iClient;
double dSalary;
std::auto_ptr<RING> table (new RING (10 kb));
double dSalaryTotal;
double dAllPayments = 0.0;
double dSum;
double dSumTotal;
double dAllSums = 0.0;
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
// группа
if (! login_group->fnGetValue (szGroupId,query->szLogin))
{
strcpy (szGroupId,"-1");
login_group->fnAdd (query->szLogin,szGroupId);
}
iGroupId = atoi (szGroupId);
// флажок посещения
if (! login_visitflag->fnGetValue (szVisitFlagId,query->szLogin))
{
strcpy (szVisitFlagId,"-1");
login_visitflag->fnAdd (query->szLogin,szVisitFlagId);
}
iVisitFlagId = atoi (szVisitFlagId);
s = "Начисления консультантам за период с ";
s += szDate1;
s += " по ";
s += szDate2;
if (iGroupId >= 0)
{
SERVICES_GROUP s_group;
groups->fnPop ((char *) &s_group,iGroupId);
s += ", группа: ";
s += s_group.szName;
}
fnReportTitle (query,s.c_str ());
for (iCycleSpec = 0; iCycleSpec < iSpecsQty; iCycleSpec++)
{
// пропускаем специалистов
if (! fnGetSpecCons (fnGetSpecType (iCycleSpec)))
continue;
dSalaryTotal = 0.0;
dSumTotal = 0.0;
for (iCycle = 0; iCycle < iVisitsQty; iCycle++)
{
if (visit [iCycle]->fnGetDelete ())
continue;
if (! fnCheckDateRange (szDate1,visit [iCycle]->fnGetPaymentDate (),szDate2))
continue;
if (visit [iCycle]->fnGetPreEntry ())
continue;
// флажок посещения
switch (iVisitFlagId)
{
case 11:
if (visit [iCycle]->fnGetFlag1 () == false)
continue;
break;
case 10:
if (visit [iCycle]->fnGetFlag1 () == true)
continue;
break;
case 21:
if (visit [iCycle]->fnGetFlag2 () == false)
continue;
break;
case 20:
if (visit [iCycle]->fnGetFlag2 () == true)
continue;
break;
case 31:
if (visit [iCycle]->fnGetFlag3 () == false)
continue;
break;
case 30:
if (visit [iCycle]->fnGetFlag3 () == true)
continue;
break;
case 41:
if (visit [iCycle]->fnGetFlag4 () == false)
continue;
break;
case 40:
if (visit [iCycle]->fnGetFlag4 () == true)
continue;
}
// группа
if (iGroupId >= 0)
if (! fnServicesGroupsGetMember (visit [iCycle]->fnGetType (),iGroupId))
continue;
if (visit [iCycle]->fnGetCons () != fnGetSpecType (iCycleSpec))
continue;
if (visit [iCycle]->fnGetAbsence ())
continue;
dSalary = visit [iCycle]->fnGetConsPayment ();
if (dSalary == 0.0)
continue;
dSalaryTotal += dSalary;
dAllPayments += dSalary;
dSum = visit [iCycle]->fnGetSum ();
dSumTotal += dSum;
dAllSums += dSum;
// формируем строку таблицы
iClientNum = visit [iCycle]->fnGetClientNum ();
iClient = fnClientSearchByNum (iClientNum);
if (iClient == -1)
continue;
// дата внутри комментария в формате ГГГГ/ММ/ДД для сортировки
sprintf (szTmp,"<!-- %4u/%02u/%02u -->",
fnGetYear (visit [iCycle]->fnGetDate ()),
fnGetMonth (visit [iCycle]->fnGetDate ()),
fnGetDay (visit [iCycle]->fnGetDate ()));
s = szTmp;
s += "<tr><td>";
s += visit [iCycle]->fnGetDate ();
s += "</td><td>";
sprintf (szClientFIO,"%s %s %s",
client [iClient]->fnGetFamily (),
client [iClient]->fnGetName (),
client [iClient]->fnGetName2 ());
s += szClientFIO;
s += "</td><td>";
s += fnGetServiceName (visit [iCycle]->fnGetType ());
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",visit [iCycle]->fnGetSum ());
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",dSalary);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr>";
table->fnPushStr (s.c_str ());
}
if (table->fnGetQty ())
{
char szOrgName [WS_MAX_DESC_LEN +1];
char *sz;
table->fnSort (0); // сортировка в кольце
s = "Таблица \"Направления: ";
s += fnGetSpecFIO (fnGetSpecType (iCycleSpec));
*szOrgName = 0;
fnGetConsOrgName (szOrgName,fnGetSpecType (iCycleSpec));
if (*szOrgName)
{
s += " — ";
s += szOrgName;
}
s += "\".";
query->dst->fnAddLine (s.c_str ());
query->dst->fnAddLine (
"<table width=\"100%\" border=1 style=\"font-family: arial, sans-serif; font-size: 9pt;\"><tr>\
<td width=\"10%\" align=center>Дата</td>\
<td width=\"20%\" align=center>ФИО клиента</td>\
<td width=\"40%\" align=center>Вид услуг</td>\
<td width=\"15%\" align=center>Сумма</td>\
<td width=\"15%\" align=center>Начислено</td></tr>");
while (table->fnGetQty ())
{
sz = new char [table->fnGetLen ()];
table->fnPop (sz);
query->dst->fnAddLine (sz);
delete [] sz;
}
query->dst->fnAddLine ("</table>");
s = "<table border=0 width=\"100%\"><tr><td align=right>Итого сумма: <b>";
sprintf (szTmp,"%.2f",dSumTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</b>, к выплате: <b>";
sprintf (szTmp,"%.2f",dSalaryTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</b></td></tr></table>";
query->dst->fnAddLine (s.c_str ());
}
}
s = "<p align=center>Общая сумма: <b>";
sprintf (szTmp,"%.2f",dAllSums);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</b>, сумма всех начислений: <b>";
sprintf (szTmp,"%.2f",dAllPayments);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</b></p>";
query->dst->fnAddLine (s.c_str ());
fnReportEnd (query);
} // end of fnAppReportConsPaymentsForm ()
// ********************************************
// * начисления консультантам по организациям *
// ********************************************
void fnAppReportOrgsPaymentsForm (QUERY *query)
{
char szDate1 [11];
char szDate2 [11];
char szGroupId [2 +1];
char szVisitFlagId [2 +1];
int iGroupId;
int iVisitFlagId;
string s;
int iOrgsQty;
int iCycleOrg;
ORG s_org;
int iCycleSpec;
int iCycle;
double dSalaryTotal;
double dOrgTotal;
char szTmp [20];
double dAllPayments = 0.0;
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
// группа
if (! login_group->fnGetValue (szGroupId,query->szLogin))
{
strcpy (szGroupId,"-1");
login_group->fnAdd (query->szLogin,szGroupId);
}
iGroupId = atoi (szGroupId);
// флажок посещения
if (! login_visitflag->fnGetValue (szVisitFlagId,query->szLogin))
{
strcpy (szVisitFlagId,"-1");
login_visitflag->fnAdd (query->szLogin,szVisitFlagId);
}
iVisitFlagId = atoi (szVisitFlagId);
s = "Начисления консультантам по организациям за период с ";
s += szDate1;
s += " по ";
s += szDate2;
if (iGroupId >= 0)
{
SERVICES_GROUP s_group;
groups->fnPop ((char *) &s_group,iGroupId);
s += ", группа: ";
s += s_group.szName;
}
fnReportTitle (query,s.c_str ());
iOrgsQty = orgs->fnGetQty ();
for (iCycleOrg = 0; iCycleOrg < iOrgsQty; iCycleOrg++)
{
dOrgTotal = 0.0;
orgs->fnPop ((char *) &s_org,iCycleOrg); // s_org.iKey
// таблица "организация"
s = "<p><table border=0><tr><td>Наименование:</td><td><b>";
s += s_org.szName;
s += "</b></td></tr><tr><td>Адрес:</td><td>";
s += s_org.szAddress;
s += " </td></tr><tr><td>Телефоны:</td><td>";
s += s_org.szPhones;
s += " </td></tr><tr><td>Менеджер:</td><td>";
s += s_org.szManager;
s += " </td></tr></table>";
// заголовок таблицы "к оплате"
s += "<table border=1 width=\"100%\"><tr>\
<td width=\"50%\" align=center>Консультант</td>\
<td width=\"50%\" align=center>Начислено</td></tr>";
for (iCycleSpec = 0; iCycleSpec < iSpecsQty; iCycleSpec++)
{
// пропускаем специалистов
if (! fnGetSpecCons (fnGetSpecType (iCycleSpec)))
continue;
// пропускаем консультантов из других организаций
if (fnGetConsOrg (fnGetSpecType (iCycleSpec)) != s_org.iKey)
continue;
// рассчитываем начисления консультанту
dSalaryTotal = 0.0;
for (iCycle = 0; iCycle < iVisitsQty; iCycle++)
{
if (visit [iCycle]->fnGetDelete ())
continue;
if (! fnCheckDateRange (szDate1,visit [iCycle]->fnGetPaymentDate (),szDate2))
continue;
if (visit [iCycle]->fnGetPreEntry ())
continue;
// флажок посещения
switch (iVisitFlagId)
{
case 11:
if (visit [iCycle]->fnGetFlag1 () == false)
continue;
break;
case 10:
if (visit [iCycle]->fnGetFlag1 () == true)
continue;
break;
case 21:
if (visit [iCycle]->fnGetFlag2 () == false)
continue;
break;
case 20:
if (visit [iCycle]->fnGetFlag2 () == true)
continue;
break;
case 31:
if (visit [iCycle]->fnGetFlag3 () == false)
continue;
break;
case 30:
if (visit [iCycle]->fnGetFlag3 () == true)
continue;
break;
case 41:
if (visit [iCycle]->fnGetFlag4 () == false)
continue;
break;
case 40:
if (visit [iCycle]->fnGetFlag4 () == true)
continue;
}
// группа
if (iGroupId >= 0)
if (! fnServicesGroupsGetMember (visit [iCycle]->fnGetType (),iGroupId))
continue;
if (visit [iCycle]->fnGetCons () != fnGetSpecType (iCycleSpec))
continue;
if (visit [iCycle]->fnGetAbsence ())
continue;
dSalaryTotal += visit [iCycle]->fnGetConsPayment ();
}
if (dSalaryTotal)
{
dOrgTotal += dSalaryTotal;
dAllPayments += dSalaryTotal;
// формируем строку таблицы
s += "<tr><td>";
s += fnGetSpecFIO (fnGetSpecType (iCycleSpec));
s += "</td><td align=right>";
sprintf (szTmp,"%.2f",dSalaryTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</td></tr>";
}
}
s += "<table width=\"100%\"><tr><td align=right>Итого: <b>";
sprintf (szTmp,"%.2f",dOrgTotal);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</b></td></tr></table></p>";
query->dst->fnAddLine (s.c_str ());
}
s = "<p align=center>Общая сумма всех начислений: <b>";
sprintf (szTmp,"%.2f",dAllPayments);
if (config.bReportSepComma)
fnCharToComma (szTmp,'.');
s += szTmp;
s += "</b></p>";
query->dst->fnAddLine (s.c_str ());
fnReportEnd (query);
} // end of fnAppReportOrgsPaymentsForm ()
// ****************************************************************************
// * *
// * ШАБЛОННЫЕ ОТЧЁТЫ *
// * *
// ****************************************************************************
void fnAppReportTemplateForm (QUERY *query)
{
RING *args = query->args;
char sz [INI_MAX_LEXEM_LEN +1];
int iTemplate = 0;
int iCycle,iCycle2;
double dSumTotal [52]; // a..z, A..Z
double dQtyTotal [52];
char szDate1 [11];
char szDate2 [11];
double dSum;
double dQty;
// int iServiceNum;
VDL_TEXT *tpl;
const char *psz;
while (args->fnGetQty ())
{
args->fnPop (sz);
if (! strcmp (sz,"num"))
{
args->fnPop (sz);
iTemplate = atoi (sz);
continue;
}
}
// инициализация
for (iCycle = 0; iCycle < 52; iCycle++)
{
dSumTotal [iCycle] = 0.0;
dQtyTotal [iCycle] = 0.0;
}
// загружаем даты из ассоциативных массивов
if (! login_date1->fnGetValue (szDate1,query->szLogin))
{
fnGetToday (szDate1);
login_date1->fnAdd (query->szLogin,szDate1);
}
if (! login_date2->fnGetValue (szDate2,query->szLogin))
{
fnGetToday (szDate2);
login_date2->fnAdd (query->szLogin,szDate2);
}
for (iCycle = 0; iCycle < iVisitsQty; iCycle++)
{
if (visit [iCycle]->fnGetDelete ())
continue;
if (! fnCheckDateRange (szDate1,visit [iCycle]->fnGetDate (),szDate2))
continue;
dSum = visit [iCycle]->fnGetSum ();
dQty = visit [iCycle]->fnGetQty ();
for (iCycle2 = 0; iCycle2 < 52; iCycle2++)
{
if (strstr (fnGetServiceGroups (visit [iCycle]->fnGetType ()),
fnServicesGroupsGetSymbol (iCycle2)))
{
dSumTotal [iCycle2] += dSum;
dQtyTotal [iCycle2] += dQty;
}
}
}
strcpy (sz,ini0.szBaseDir);
// имя файла шаблона
strcat (sz,rep_template [iTemplate]->szFile);
tpl = new VDL_TEXT;
tpl->fnLoad (sz); // загрузка шаблона
for (iCycle = 0; iCycle < (int) tpl->fnGetLinesQty (); iCycle++)
{
psz = tpl->fnGetLine (iCycle);
if (! strcmp (psz,"{org_name}"))
{
query->dst->fnAddLine (fnGetFilialName(query->szPrefix));
continue;
}
if (! strcmp (psz,"{date1}"))
{
query->dst->fnAddLine (szDate1);
continue;
}
if (! strcmp (psz,"{date2}"))
{
query->dst->fnAddLine (szDate2);
continue;
}
if (! strncmp (psz,"{sum}",5))
{
dSum = 0.0;
for (iCycle2 = 0; iCycle2 < 52; iCycle2++)
{
if (strstr (psz+5,fnServicesGroupsGetSymbol (iCycle2)))
dSum += dSumTotal [iCycle2];
}
sprintf (sz,"%.2f",dSum);
if (config.bReportSepComma)
fnCharToComma (sz,'.');
query->dst->fnAddLine (sz);
continue;
}
if (! strncmp (psz,"{qty}",5))
{
dQty = 0.0;
for (iCycle2 = 0; iCycle2 < 52; iCycle2++)
{
if (strstr (psz+5,fnServicesGroupsGetSymbol (iCycle2)))
dQty += dQtyTotal [iCycle2];
}
sprintf (sz,"%.2f",dQty);
if (config.bReportSepComma)
fnCharToComma (sz,'.');
query->dst->fnAddLine (sz);
continue;
}
query->dst->fnAddLine (psz);
}
delete tpl;
} // end of fnAppReportTemplateForm ()
|