Selaa lähdekoodia

Merge branch 'master' of ssh://biuro.biall-net.pl:2222/plabudda/se

a.binder 6 vuotta sitten
vanhempi
commit
eab4e9a4fe

+ 363 - 242
SE/se-lib/Route/UrlAction/UserContact.php

@@ -1,6 +1,7 @@
 <?php
 
 Lib::loadClass('RouteBase');
+Lib::loadClass('Windykacja_View');
 
 // Tool for Windykacja status table to store contacts with clients
 class Route_UrlAction_UserContact extends RouteBase {
@@ -11,7 +12,7 @@ class Route_UrlAction_UserContact extends RouteBase {
 		if ($idUser <= 0) throw new Exception("Missing id client");
 
 		echo UI::h('h3', [ 'style' => "margin-bottom: 24px; border-bottom: 1px solid #eee" ], "Dodaj notatkę ze spotkania z klientem {$idUser}");
-		$this->viewUserInfo($idUser);
+		Windykacja_View::viewUserInfo($idUser);
 
 		$postTask = V::get('_postTask', '', $_POST);
 		switch ($postTask) {
@@ -23,11 +24,11 @@ class Route_UrlAction_UserContact extends RouteBase {
 
 		echo UI::h('hr');
 
-		$this->viewHistContacts($idUser);
+		$this->viewUserPaymentContactsHistory($idUser);
 	}
 
 	function viewSaveContactForm($idUser) {
-		$windykInfo = $this->getWindykacjaInfo($idUser);
+		$windykInfo = Windykacja_View::getWindykacjaInfo($idUser);
 		$windykStatusInfo = ($windykInfo) ? $windykInfo['A_STATUS_INFO'] : '';
 		$windykReminder = ($windykInfo && (
 			!empty($windykInfo['L_APPOITMENT_USER'])
@@ -81,8 +82,8 @@ class Route_UrlAction_UserContact extends RouteBase {
 			]),
 			UI::h('div', [ 'class' => "row", 'style' => "padding-bottom: 12px" ], [
 				UI::h('div', [ 'class' => "col-md-12" ], [
-					UI::h('label', [], "Notatka"),
-					UI::h('textarea', [ 'class' => "form-control", 'type' => "text", 'name' => 'L_APPOITMENT_INFO' ], $args['L_APPOITMENT_INFO']),
+					UI::h('label', [], "Notatka ze spotkania"),
+					UI::h('textarea', [ 'class' => "form-control", 'type' => "text", 'name' => 'L_APPOITMENT_INFO', 'rows' => 3 ], $args['L_APPOITMENT_INFO']),
 				]),
 			]),
 			UI::h('div', [ 'class' => "row", 'style' => "padding-bottom: 12px" ], [
@@ -197,26 +198,34 @@ class Route_UrlAction_UserContact extends RouteBase {
 				if (empty($args['REMINDER_INFO'])) throw new Exception("Brak adnotacji przypomnienia");
 			}
 
-			$windykInfo = $this->getWindykacjaInfo($idUser);
+			$windykInfo = Windykacja_View::getWindykacjaInfo($idUser);
 
 			// create new record with L_APPOITMENT_* in table `USERS2_CONTACT`
-			DB::getPDO()->insert('USERS2_CONTACT', [
+			$newContactItem = [
 				'ID_BILLING_USERS' => $idUser,
 				'L_APPOITMENT_USER' => $args['L_APPOITMENT_USER'],
 				'L_APPOITMENT_DATE' => $args['L_APPOITMENT_DATE'],
 				'L_APPOITMENT_TYPE' => $args['L_APPOITMENT_TYPE'],
 				'L_APPOITMENT_INFO' => $args['L_APPOITMENT_INFO'],
-				'SALDO' => $windykInfo['SALDO'],
+				'SALDO' => $windykInfo['PAY_SALDO'],
 				'A_RECORD_CREATE_DATE' => "NOW()",
 				'A_RECORD_CREATE_AUTHOR' => User::getLogin(),
-			]);
+			];
+			$idCreated = DB::getPDO()->insert('USERS2_CONTACT', $newContactItem);
+			DB::getPDO()->insert('USERS2_CONTACT_HIST', array_merge($newContactItem, [ 'ID_USERS2' => $idCreated ]));
 			// update A_STATUS_INFO in `USERS2_WINDYKACJA_STATUS` if $args['change_windykacja_status']
 			if ($args['change_windykacja_status']) {
-				DB::getPDO()->update('USERS2_WINDYKACJA_STATUS', 'ID_BILLING_USERS', $idUser, [
-					'A_STATUS_INFO' => $args['A_STATUS_INFO'],
-					'A_RECORD_UPDATE_DATE' => "NOW()",
-					'A_RECORD_UPDATE_AUTHOR' => User::getLogin(),
-				]);
+				if ($windykInfo['A_STATUS_INFO'] != $args['A_STATUS_INFO']) {
+					$toUpdateWindyk = [
+						'A_STATUS_INFO' => $args['A_STATUS_INFO'],
+						'A_RECORD_UPDATE_DATE' => "NOW()",
+						'A_RECORD_UPDATE_AUTHOR' => User::getLogin(),
+					];
+					DB::getPDO()->update('USERS2_WINDYKACJA_STATUS', 'ID_BILLING_USERS', $idUser, $toUpdateWindyk);
+					DB::getPDO()->insert('USERS2_WINDYKACJA_STATUS_HIST', array_merge($toUpdateWindyk, [
+						'ID_USERS2' => $windykInfo['ID'],
+					]));
+				}
 			}
 			// update L_APPOITMENT_* fields using REMINDER_* in `USERS2_WINDYKACJA_STATUS` if $args['add_reminder']
 			if ($args['add_reminder']) {
@@ -237,187 +246,13 @@ class Route_UrlAction_UserContact extends RouteBase {
 		throw new AlertSuccessException("Wprowadzono notatkę ze spotkania z klientem " . UI::h('a', [ 'href' => $this->getLink('', [ 'id_user' => $idUser ]) ], "wróć"));
 	}
 
-	function viewUserInfo($idUser) {
-		$userInfo = $this->getUserInfo($idUser);
-		$windykInfo = $this->getWindykacjaInfo($idUser);
-
-		echo UI::h('details', [ 'style' => "margin-bottom: 24px" ], [
-			UI::h('summary', [ 'style' => "padding: 12px; background: #eee; cursor: pointer; outline: none" ], [
-				($userInfo['is_firma']) ? "Firma" : "Klient",
-				" ",
-				UI::h('b', [], "{$userInfo['P_NAME']} {$userInfo['P_NAME_SECOND']}"),
-				$windykInfo ? UI::h('span', [ 'style' => "padding-left: 24px" ], [
-					"Zapis/Odczyt dla: {$windykInfo['A_ADM_COMPANY']}", // $windykInfo['A_CLASSIFIED'];
-				]) : "",
-				UI::h('span', [ 'style' => "padding-left: 24px" ], [
-					"Status windykacji: ",
-					(!$windykInfo) ? "brak danych" : UI::h('span', [], "{$windykInfo['A_STATUS']} <em>{$windykInfo['A_STATUS_INFO']}</em>"),
-				]),
-				" ...",
-				UI::h('span', [ 'style' => "float:right" ], [
-					UI::h('a', [ 'href' => "index.php?MENU_INIT=USERS2_WINDYKACJA_STATUS&q=&_f=&_user_id={$idUser}" ], "Panel windykacji"),
-				]),
-			]),
-			UI::h('div', [ 'style' => "padding: 12px; background: #eee;" ], [
-				UI::h('table', [], [
-					UI::h('tr', [], [
-						UI::h('td', [ 'style' => "vertical-align:top; padding-right:8px" ], [
-							$this->viewWidgetUserInfo($idUser, $userInfo),
-						]),
-						UI::h('td', [ 'style' => "vertical-align:top; padding-right:8px" ], [
-							$this->viewWidgetUserWindykInfo($idUser, $windykInfo),
-						]),
-					]),
-				]),
-			]),
-		]);
-	}
-	function viewWidgetUserInfo($idUser, $userInfo = []) {
-		if (empty($userInfo)) $userInfo = $this->getUserInfo($idUser);
-
-		$outUserInfo = [
-			'Nr klienta' => $userInfo['ID_BILLING_USERS'],
-			'Firma' => ($userInfo['is_firma']) ? "Tak" : "Nie",
-			'Nip' => $userInfo['P_NIP'],
-			'Pesel' => $userInfo['P_PESEL'],
-			'Tel' => $userInfo['P_PHONE'],
-			'email' => $userInfo['user_mail_contact'],
-			'Adres' => "{$userInfo['P_ADDRESS_POST_CODE']} {$userInfo['P_ADDRESS_CITY']} {$userInfo['P_ADDRESS_STREET']} {$userInfo['P_ADDRESS_HOME']}/{$userInfo['P_ADDRESS_HOUSE']}",
-			'Operator' => "[{$userInfo['BILLING_OWNER']}] {$userInfo['BILLING_OWNER_NAME']}",
-		];
-
-		return UI::h('div', [], [
-			UI::h('p', [ 'style' => "border-left:3px solid #ddd; padding-left:6px; font-weight:bold" ], "Dane klienta"),
-			UI::h('table', [ 'class' => "table table-bordered", 'style' => "width:auto; background:#fff" ],
-				array_map(function ($fieldName) use ($outUserInfo) {
-				return UI::h('tr', [], [
-					UI::h('th', [], $fieldName),
-					UI::h('td', [], $outUserInfo[$fieldName]),
-				]);
-				}, array_keys($outUserInfo))
-			),
-		]);
-	}
-	function viewWidgetUserWindykInfo($idUser, $windykInfo = []) {
-		if (empty($windykInfo)) $windykInfo = $this->getUserInfo($idUser);
-
-		$outWindykInfo = [
-			'Status' => $windykInfo['A_STATUS'],
-
-			// $filter_arr['stan_zero'] = array("stan zerowy");
-			// $filter_arr['10-ego'] = array("termin płatności faktur, saldo na -", 'desc'=>array("10-ego", "10-ego każdego miesiąca - termin płatnosci faktur oraz saldo na minusie"));
-			// $filter_arr['WAITING'] = array("termin płatności faktur", 'desc'=>array("10-ego", "10-ego każdego miesiąca - termin płatnosci faktur"));// z regulaminu
-			// $filter_arr['15'] = array("mail ponaglenie", 'desc'=>array("10-ego + 5", "10-ego + 5 dni roboczych"));
-			// $filter_arr['blokada'] = array("blokada", 'desc'=>array("pn, wt, śr około 25", "najbliższy pn, wt, śr do 25"));// najbliższy pn, wt, śr do 25-ego danego miesiąca
-			// $filter_arr['tel1'] = array("kontakt tel.", 'desc'=>array("", "Ostatni kontakt tel. ponad 3 m-ce temu"));
-			// $filter_arr['bad_address'] = array("błędny adres");
-			// $filter_arr['wezwanie1'] = array("wezwanie do zapłaty", 'desc'=>array("2 x FVat", "2 faktury"));
-			// $filter_arr['waiting-wezwanie2'] = array("oczekiwanie 7 dni od terminu płatności");
-			// $filter_arr['wezwanie2'] = array("ostateczne wezwanie do zapłaty, rozwiązanie umowy", 'desc'=>array("wezwanie + 14", "wezwanie + 14 dni"));
-			// $filter_arr['waiting-krd'] = array("min. 30 dni od ostatecznego wezwania");
-			// $filter_arr['krd'] = array("do przekazania do KRD", 'desc'=>array("wezwanie ost. + 60", "wezwanie ost. + 60 dni"));
-			// $filter_arr['waiting-sad'] = array("przekazano do KRD");
-			// $filter_arr['docs-in-sad'] = array("przekazać sprawę do sądu");// waiting-sad = 30 dni
-			// $filter_arr['sad'] = array("przekazano sprawę do sądu");
-
-			// $filter_arr['3 m-ce przed'] = array("3 m-ce przed przedawnieniem");// 3 m-ce przed przedawnieniem
-			// $filter_arr['po-terminie'] = array("po terminie");// 3 lata po dacie platnosci faktur
-			// $filter_arr['has_nr_sad'] = array("nr sprawy sąd");
-			// $filter_arr['has_nr_komornik'] = array("nr sprawy komornik");
-			// $filter_arr['has_ustalenia'] = array("ustalenia z klientem");
-			// $filter_arr['sad_and_komornik'] = array("sąd z komornik");
-			// $filter_arr['sad_bez_komornik'] = array("sąd bez komornik");
-			// $filter_arr['isMovedToVectra'] = array("przeniesieni do Vectra");
-
-			// if ($filter_selected == 'po-terminie') {
-			// 	$sql_where_and_arr[] = "w.`PAY_SALDO`<=-0.05";
-			// 	$sql_where_and_arr[] = "w.`PAY_DATE`!='0000-00-00'";
-			// 	$sql_where_and_arr[] = "w.`PAY_DATE`<DATE_SUB(NOW(), INTERVAL 36 MONTH)";
-			// }
-			// else if ($filter_selected == '3 m-ce przed') {
-			// 	$sql_where_and_arr[] = "w.`PAY_SALDO`<=-0.05";
-			// 	$sql_where_and_arr[] = "w.`PAY_DATE`!='0000-00-00'";
-			// 	$sql_where_and_arr[] = "w.`PAY_DATE`<DATE_SUB(NOW(), INTERVAL 33 MONTH)";
-			// 	$sql_where_and_arr[] = "w.`PAY_DATE`>DATE_SUB(NOW(), INTERVAL 36 MONTH)";
-			// }
-			// else if ($filter_selected == 'tel1') {
-			// 	$sql_where_and_arr[] = "w.`PAY_SALDO`<=-0.05";
-			// 	$sql_where_and_arr[] = "w.`A_STATUS` in('wezwanie1', 'waiting-wezwanie2', 'wezwanie2', 'waiting-krd')";
-			// 	$sql_where_and_arr[] = "( w.`LAST_PHONE_STATUS_DATE`='0000-00-00'
-			// 		or w.`LAST_PHONE_STATUS_DATE`<DATE_SUB(NOW(), INTERVAL 3 MONTH) )";
-			// }
-			// else if ($filter_selected == 'bad_address') {
-			// 	$sql_where_and_arr[] = "w.`BAD_ADDRESS`>0";
-			// 	$sql_where_and_arr[] = "w.`PAY_SALDO`<=-0.05";
-			// }
-			// else if ($filter_selected == 'stan_zero') {
-			// 	$sql_where_and_arr[] = "w.`A_STATUS`='WAITING'";
-			// 	$sql_where_and_arr[] = "w.`PAY_SALDO`>-0.05";
-			// }
-			// else if ($filter_selected == '10-ego') {
-			// 	$sql_where_and_arr[] = "w.`A_STATUS`='WAITING'";
-			// 	$sql_where_and_arr[] = "w.`PAY_SALDO`<=-0.05";
-			// }
-			// else if ($filter_selected == 'has_nr_sad') {
-			// 	$sql_where_and_arr[] = "w.`NR_SPRAWY_SAD`!=''";
-			// }
-			// else if ($filter_selected == 'has_nr_komornik') {
-			// 	$sql_where_and_arr[] = "w.`NR_SPRAWY_KOMORNIK`!=''";
-			// }
-			// else if ($filter_selected == 'has_ustalenia') {
-			// 	$sql_where_and_arr[] = "w.`L_APPOITMENT_INFO`!=''";
-			// }
-			// else if ($filter_selected == 'sad_and_komornik') {
-			// 	$sql_where_and_arr[] = "w.`A_STATUS`='sad' and w.`NR_SPRAWY_KOMORNIK`!=''";
-			// }
-			// else if ($filter_selected == 'sad_bez_komornik') {
-			// 	$sql_where_and_arr[] = "w.`A_STATUS`='sad' and w.`NR_SPRAWY_KOMORNIK`=''";
-			// }
-			// else if ($filter_selected == 'isMovedToVectra') {
-			// 	$sql_where_and_arr[] = "w.`IS_MOVED_TO_VECTRA`=1";
-			// }
-			// else {
-			// 	$sql_where_and_arr[] = "w.`A_STATUS`='{$filter_selected}'";
-			// }
-
-			'Saldo' => $windykInfo['PAY_SALDO'],
-			'Termin ost. fv' => $windykInfo['PAY_DATE'], // Data wymagalności ostatniej faktury
-			'Zaległe faktury' => $windykInfo['PAY_FVAT'],
-			'Adresy usług' => $windykInfo['SERVICES_STREETS'],
-		];
-
-		return UI::h('div', [], [
-			UI::h('p', [ 'style' => "border-left:3px solid #ddd; padding-left:6px; font-weight:bold" ], [
-				"Informacje o płatnościach",
-				($windykInfo['A_STATUS_UPDATE_DATE'] < date("Y-m-d"))
-				?	UI::h('div', [ 'class' => "text-danger" ], [
-						"Uwaga: Wymagają aktualizacji",
-						" ",
-						UI::h('em', [ 'class' => "text-muted" ], "(dane z {$windykInfo['A_STATUS_UPDATE_DATE']})"),
-						// TODO: btn aktualizuj lub auto aktualizuj przed pokazaniem danych
-					])
-				:	"",
-			]),
-			UI::h('table', [ 'class' => "table table-bordered", 'style' => "width:auto; background:#fff" ],
-				array_map(function ($fieldName) use ($outWindykInfo) {
-				return UI::h('tr', [], [
-					UI::h('th', [], $fieldName),
-					UI::h('td', [], $outWindykInfo[$fieldName]),
-				]);
-				}, array_keys($outWindykInfo))
-			),
-			UI::h('table', [ 'class' => "table table-bordered", 'style' => "width:auto; display:none; background:yellow" ],
-				array_map(function ($fieldName) use ($windykInfo) {
-				return UI::h('tr', [], [
-					UI::h('th', [], $fieldName),
-					UI::h('td', [], $windykInfo[$fieldName]),
-				]);
-				}, array_keys($windykInfo))
-			),
-		]);
-	}
+	function viewUserPaymentContactsHistory($idUser, $params = []) {
+		$markEventsFromSpotkanieNr = V::get('markEventsFromSpotkanieNr', 0, $params, 'int');
+
+		Lib::loadClass('Windykacja_StatsModel');
+		$billDocs = Windykacja_StatsModel::getBillDocsByDate($idUser);
+		// DBG::nicePrint($billDocs, '$billDocs');
 
-	function viewHistContacts($idUser) {
 		$lastHist = DB::getPDO()->fetchAll("
 			select t.ID
 				, t.ID_BILLING_USERS
@@ -428,66 +263,314 @@ class Route_UrlAction_UserContact extends RouteBase {
 				, t.L_APPOITMENT_DATE
 				, t.L_APPOITMENT_TYPE
 				, t.L_APPOITMENT_INFO
+				, IF('0000-00-00 00:00:00' = t.A_RECORD_UPDATE_DATE, t.A_RECORD_CREATE_DATE, t.A_RECORD_UPDATE_DATE) as A_RECORD_UPDATE_DATE
 			from USERS2_CONTACT t
 			where t.ID_BILLING_USERS = :id
 			limit 11
 		", [ ':id' => $idUser ]);
+		// DBG::nicePrint($lastHist, '$lastHist');
+		if (!empty($lastHist)) {
+			foreach ($lastHist as $bill_doc) {
+				$billDocs->add_event(substr($bill_doc['A_RECORD_UPDATE_DATE'], 0, 10), 'HIST_CONTACT', $bill_doc);
+			}
+		}
+
+		// TODO: add zmiania statusu: select h.* from Windyk_HIST where A_STATUS_INFO != 'N/S;'
+
+		$umowy_l2 = Windykacja_StatsModel::getClientUmowy($idUser);
+		//echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;">billDocs ';print_r($billDocs);echo'</pre>';
+		//echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;">billDocs ';print_r(reset($billDocs));echo'</pre>';
+		//echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;">umowy_l2 ';print_r($umowy_l2);echo'</pre>';
+		if (!empty($umowy_l2)) {
+			foreach ($umowy_l2 as $h) {
+				$billDocs->add_event($h['P_DEALDATE'], 'UMOWA', $h);
+
+				if ($h['P_DEALDATE_TERM'] != '0000-00-00') {// < date('Y-m-d')) {
+					$billDocs->add_event($h['P_DEALDATE_TERM'], 'KONIEC UMOWY', $h);
+				}
+			}
+		}
+
+		$user_hist_events = Windykacja_StatsHelper::getUserHistStatusEvents($idUser);
+		if (!empty($user_hist_events)) {
+			foreach ($user_hist_events as $bill_doc) {
+				$billDocs->add_event($bill_doc['A_STATUS_UPDATE_DATE'], 'HIST_STATUS', $bill_doc);
+			}
+		}
 
-		UI::table([ 'caption' => "Historia kontaktów z klientem (TODO: w trakcie prac. Zobacz " .
-			UI::h('a', [ 'href' => "index.php?MENU_INIT=USERS2_WINDYKACJA_STATUS&q=&_f=&_user_id={$idUser}" ], "Panel windykacji") .
-		")", 'rows' => $lastHist ]);
+		$user_hist_events = Windykacja_StatsHelper::getUserHistPhoneEvents($idUser);
+		if (!empty($user_hist_events)) {
+			foreach ($user_hist_events as $bill_doc) {
+				$billDocs->add_event(substr($bill_doc['A_RECORD_UPDATE_DATE'], 0, 10), 'HIST_PHONE', $bill_doc);
+			}
+		}
+
+		$user_hist_events = Windykacja_StatsHelper::getUserBadAddressEvents($user->ID);
+		if (!empty($user_hist_events)) {
+			foreach ($user_hist_events as $bill_doc) {
+				$billDocs->add_event(substr($bill_doc['A_RECORD_UPDATE_DATE'], 0, 10), 'HIST_BAD_ADDRESS', $bill_doc);
+			}
+		}
+
+		// add today
+		$bill_doc = array();
+		$bill_doc['saldo'] = $billDocs->get_saldo();
+		$billDocs->add_event(date('Y-m-d'), 'TODAY', $bill_doc);
+
+		$billDocs->sort_docs();
+		$billDocs->set_saldo_for_all_docs();
+
+		$listBillDocs = $billDocs->get_docs(); // [ day => [ Windykacja_EventDoc, ... ], ... ]
+		// convert to: [ year => [ Windykacja_EventDoc, ... ] ]
+		$groupedByYearBillDocs = array_reduce($listBillDocs, function ($ret, $listDayEvents) {
+			foreach ($listDayEvents as $event) {
+				$year = substr($event->get_date(), 0, 4);
+				if (empty($ret[$year])) $ret[$year] = [];
+				array_unshift($ret[$year], $event);
+			}
+			return $ret;
+		}, []);
+		$groupedByYearBillDocs = array_reverse($groupedByYearBillDocs, true);
+
+		// DBG::nicePrint($listBillDocs, '$listBillDocs');
+		// DBG::nicePrint($groupedByYearBillDocs, '$groupedByYearBillDocs');
+
+		// UI::table([ 'caption' => "Historia kontaktów z klientem (TODO: w trakcie prac. Zobacz " .
+		// 	UI::h('a', [ 'href' => "index.php?MENU_INIT=USERS2_WINDYKACJA_STATUS&q=&_f=&_user_id={$idUser}" ], "Panel windykacji") .
+		// ")", 'rows' => $lastHist ]);
 		// if (count($lastHist) > 10) UI::alert('info', "Przeglądaj wszystkie wpisy TODO: link to view table with ff_ID_BILLING_USERS");
-	}
+		echo UI::h('div', [], array_merge(
+			[
+				UI::h('h3', [], "Historia klienta"),
+			],
+			array_map(function ($listEventDocs, $year) use ($markEventsFromSpotkanieNr) {
+				return UI::h('details', array_merge([ 'style' => "margin:8px 0" ],
+						(date("Y") == $year) ? [ 'open' => "" ] : []
+					), [
+					UI::h('summary', [ 'style' => "height:20px; position:relative; cursor:pointer; outline:none" ], [
+						UI::h('div', [ 'style' => "position:absolute; top:9px; left:20px; width: 100%; border-bottom:2px solid #000" ]),
+						UI::h('span', [ 'style' => "position:absolute; top:0; left:12px; padding:0 12px 0 0; line-height:20px; background-color:#fff; font-weight:bold" ], [
+							"{$year}:",
+						]),
+					]),
+					UI::h('div', [ 'style' => "padding: 8px 0px 8px 54px" ],
+						array_merge(
+							[
+								UI::hTable([
+									'disable_lp' => true,
+									'@class' => 'table table-hover', // table-bordered
+									'cols' => [
+										'data',
+										'winien',
+										'ma',
+										'saldo',
+										'#',
+										'uwagi',
+									],
+									'@style[data]' => "width:80px; text-align:right",
+									'@style[winien]' => "width:90px; text-align:right",
+									'@style[ma]' => "width:90px; text-align:right",
+									'@style[saldo]' => "width:90px; text-align:right; background-color:#f5f5f5",
+									'@style[#]' => "width:140px; padding-left:12px; text-align:left",
+									'rows' => array_map(function ($eventDoc) use ($markEventsFromSpotkanieNr) {
+										$saldo = $eventDoc->get_saldo();
+										$overallSaldo = $eventDoc->get_saldo_overall();
+										$rowClass = "";
+										// $markEventsFromSpotkanieNr
+										if ($markEventsFromSpotkanieNr
+											&& $eventDoc->get_class() == 'EVENT' && $eventDoc->get_type() == 'HIST_CONTACT'
+											&& $eventDoc->get('ID') == $markEventsFromSpotkanieNr
+										) {
+											$rowClass = "info";
+										} else {
+											$rowClass = ('EVENT' === $eventDoc->get_class() && 'TODAY' === $eventDoc->get_type()) ? "warning" : "";
+										}
 
-	function getUserInfo($idUser) {
-		return DB::getPDO()->fetchFirst("
-			select bua.`id_users`
-				, bua.`id_users` as ID_BILLING_USERS
-				, bua.`is_firma`
-				, bua.`P_NAME`
-				, bua.`P_NAME_SECOND`
-				, bua.`P_NIP`
-				, bua.`P_PESEL`
-				, bua.`P_PHONE`
-				, bua.`P_ADDRESS_REGION`
-				, bua.`P_ADDRESS_CITY`
-				, bua.`P_ADDRESS_POST_CODE`
-				, bua.`P_ADDRESS_STREET`
-				, bua.`P_ADDRESS_HOME`
-				, bua.`P_ADDRESS_HOUSE`
-				, bua.`user_mail_contact`
-				, bu.`BILLING_OWNER`
-				, ( select bo.name1 from BILLING_OWNER bo where bo.ID = bu.BILLING_OWNER ) as BILLING_OWNER_NAME
-			from `BILLING_USERS_ADD` as bua
-				left join `BILLING_USERS` as bu on ( bu.`ID` = bua.`id_users` )
-			where bua.`id_users` = :id_user
-		", [ ':id_user' => $idUser ]);
+										return [
+											'data' => $eventDoc->get_date(),
+											'winien' => UI::h('span', [
+													'style' => "color:" . ( (-1 * $saldo > 0) ? "#000" : "#ddd" ),
+												], ($saldo < 0) ? UI::price(-1 * $saldo) : 0
+											),
+											'ma' => UI::h('span', [
+													'style' => "color:" . ( ($saldo > 0) ? "#000" : "#ddd" ),
+												], ($saldo > 0) ? UI::price($saldo) : 0
+											),
+											'saldo' => UI::h('span', [
+													'style' => "color:" . ( ($overallSaldo >= 0) ? "green" : "red" ),
+												], UI::price($overallSaldo)
+											),
+											'#' => $this->viewUserPaymentContactsHistory_eventNr($eventDoc),
+											'uwagi' => $this->viewUserPaymentContactsHistory_eventLabel($eventDoc),
+											'@class' => $rowClass,
+											'@style[data]' => "text-align:right",
+											'@style[winien]' => "text-align:right",
+											'@style[ma]' => "text-align:right",
+											'@style[saldo]' => "text-align:right; background-color:#f5f5f5",
+											'@style[#]' => "padding-left:12px",
+										];
+									}, $listEventDocs),
+								]),
+							],
+							[]
+						)
+					),
+				]);
+			}, $groupedByYearBillDocs, array_keys($groupedByYearBillDocs))
+		));
 	}
-	function getWindykacjaInfo($idUser) {
-		if ($this->_windykInfo) return $this->_windykInfo;
+	function viewUserPaymentContactsHistory_eventNr($v_doc) { // return html (string)
+		/* links fomr l1:
+		 *   FV: https://l1.webone.pl/modules/make_billing/edit.php?mod=make_billing&form=html_faktura&adm=edit&uid=4014&fpos=&dz=&close=0&doc=799413&doctype=1
+		 *   KOR: https://l1.webone.pl/modules/make_billing/edit.php?mod=make_billing&form=html_faktura_korekta&adm=edit&uid=4014&fpos=&dz=&close=0&doc=809557&doctype=3
+		 *        https://biuro.biall-net.pl/dev-pl/se-master/index.php?FUNCTION_INIT=bm_show_document&ARG1_VAL=809557
+		 */
+		if ($v_doc->get_class() == 'BILLING' && 'FVAT' == $v_doc->get_type()) {
+			$nr = $v_doc->get_type();
+			Lib::loadClass('Windykacja_StatsModel');
+			$type_desc = Windykacja_StatsModel::get_billing_type_desc($v_doc->get_type());
+			if ($type_desc) {
+				$type_desc .= "\n Wystawiona: ".$v_doc->get('BILL_DATE')."\n Termin płatności: ".$v_doc->get('PAYMENT_TERM');
+				$nr = '<span title="'.$type_desc.'">'.$nr.'</span>';
+				// TODO: podglad faktury
+				//if ($h['type'] == 'FVAT') $nr .= ' <a href="'."?MENU_INIT=USERS2_WINDYKACJA_STATUS&_user_id=".$user->ID."&task=view_faktura&id=".$h['ID'].'" target="_blank">'.'<img src="'."icon/search.png".'" alt="'."U".'" title="'."Podgląd faktury".'" />'.'</a>';
+			}
+			$docNr = $v_doc->get('nr');
+			$docNrLabel = $v_doc->get('NUMBER') . '/' . $v_doc->get('ID_BILLING_PREFIXES');
+			$nr .= ' <a href="index.php?FUNCTION_INIT=bm_show_document&ARG1_VAL=' . $docNr . '" target="_blank">'."({$docNrLabel})".'</a>';
 
-		$this->_windykInfo = $this->fetchWindykacjaInfo($idUser);
-		if ($this->_windykInfo['A_STATUS_UPDATE_DATE'] < date("Y-m-d")) {
+			return $nr;
+		}
+		if ($v_doc->get_class() == 'BILLING' && 'KORV' == $v_doc->get_type()) {
+			$nr = $v_doc->get_type();
+			Lib::loadClass('Windykacja_StatsModel');
+			$type_desc = Windykacja_StatsModel::get_billing_type_desc($v_doc->get_type());
+			if ($type_desc) {
+				$nr = '<span title="'.$type_desc.'">'.$nr.'</span>';
+			}
+			$docNr = $v_doc->get('nr');
+			$docNrLabel = $v_doc->get('NUMBER') . '/' . $v_doc->get('ID_BILLING_PREFIXES');
+			$remoteFvNum = $v_doc->get('FV_NUMBER');
+			$korNr = $v_doc->get('ID_BILLING_NUMBERS');
+			$korTitle = "Korekta dotycząca faktury nr: {$remoteFvNum}";
+			$nr .= ' <a href="index.php?FUNCTION_INIT=bm_show_document&ARG1_VAL=' . $korNr . '" target="_blank" title="'.$korTitle.'">'."({$docNrLabel})".'</a>';
+
+			return $nr;
+		}
+		if ($v_doc->get_class() == 'BILLING') {
+			$nr = $v_doc->get_type();
 			Lib::loadClass('Windykacja_StatsModel');
-			Lib::loadClass('Windykacja_StatsHelper');
-			$user = Windykacja_StatsModel::get_user_by_id($idUser);
-			if ($user) {
-				$billing_docs = Windykacja_StatsModel::get_bill_dosc_by_date($user);
-				Windykacja_StatsHelper::update_stats($user, $billing_docs);
+			$type_desc = Windykacja_StatsModel::get_billing_type_desc($v_doc->get_type());
+			if ($type_desc) {
+				$nr = '<span title="'.$type_desc.'">'.$nr.'</span>';
 			}
-			$this->_windykInfo = $this->fetchWindykacjaInfo($idUser);
+			$docNr = $v_doc->get('nr');
+			$docNrLabel = $v_doc->get('NUMBER') . '/' . $v_doc->get('ID_BILLING_PREFIXES');
+
+			return $nr;
 		}
-		return $this->_windykInfo;
+		if ($v_doc->get_class() == 'EVENT' && $v_doc->get_type() == 'TODAY') return "";
+		if ($v_doc->get_class() == 'EVENT' && $v_doc->get_type() == 'HIST_STATUS') return "";
+		if ($v_doc->get_class() == 'EVENT' && $v_doc->get_type() == 'HIST_PHONE') return "";
+		if ($v_doc->get_class() == 'EVENT' && $v_doc->get_type() == 'HIST_BAD_ADDRESS') return "";
+		if ($v_doc->get_class() == 'EVENT' && $v_doc->get_type() == 'HIST_CONTACT') return "Spotkanie " . UI::h('a', [
+			'href' => "index.php?_route=ViewTableAjax&namespace=default_db/USERS2_CONTACT#EDIT/" . $v_doc->get('ID'),
+			'target' => "_blank",
+			'title' => "Notatka ze spotkania",
+		], "(" . $v_doc->get('ID') . ")");
+		if ($v_doc->get_class() == 'EVENT') return UI::h('span', [ 'title' => $v_doc->get('ID') ], $v_doc->get_type()); // TODO: dla KP,KW: ID_BILLING_NUMBERS zamiast ID
+
+		return "???";
 	}
-	function fetchWindykacjaInfo($idUser) {
-		return DB::getPDO()->fetchFirst("
-			select t.`ID`
-				, t.A_STATUS
-				, t.A_STATUS_INFO
-				, t.*
-			from `USERS2_WINDYKACJA_STATUS` as t
-			where t.`ID_BILLING_USERS` = :id_user
-		", [ ':id_user' => $idUser ]);
+	function viewUserPaymentContactsHistory_eventLabel($v_doc) { // return html (string)
+		if ($v_doc->get_class() == 'BILLING') return '';
+		if ($v_doc->get_class() == 'EVENT' && $v_doc->get_type() == 'TODAY') return '';
+		if ($v_doc->get_class() == 'EVENT' && $v_doc->get_type() == 'HIST_STATUS') {
+			$id_koresp = intval($v_doc->get('ID_KORESP'));
+			$add = '';
+			if ($id_koresp > 0) {
+				$koresp_edit_link = "index.php?_route=ViewTableAjax&namespace=default_db/IN7_DZIENNIK_KORESP#EDIT/{$id_koresp}";
+				$add = " " . '<a href="' . $koresp_edit_link . '" title="' . "Edycja KORESP. ({$id_koresp})" . '" target="_blank">' . "KOR" . '</a>';
+			}
+			switch ($v_doc->get('A_STATUS')) {
+				case 'WAITING': return "powrót do oczekujących {$add}";
+				case 'waiting-wezwanie2':return "wezwanie do zapłaty (Nr koresp.: ".$v_doc->get('ID_KORESP').") <em>(termin: ".$v_doc->get('PAY_TERM').")</em> {$add}";
+				case 'waiting-krd': return "wezwanie do zapłaty ost. (Nr koresp.: ".$v_doc->get('ID_KORESP').") <em>(termin: ".$v_doc->get('PAY_TERM').")</em> {$add}";
+				case 'N/S;': return "Nr koresp.: ".$v_doc->get('ID_KORESP')." <em>(" . $v_doc->get('K_ZAWARTOS') . ")</em>" .
+					(
+						($v_doc->get('ID_KORESP') > 0 && substr($v_doc->get('params'), 0, strlen('rozwiazanie umowy')) == 'rozwiazanie umowy')
+						?	" " . '<a href="'."?MENU_INIT=USERS2_WINDYKACJA_STATUS&q=".V::get('q','', $_REQUEST)."&task="."bok_rozwiazanie_umowy_print"."&user_id={$user->ID}&id_koresp=".$v_doc->get('ID_KORESP').'" target="_blank" title="' . "Generuj druk rozwiązania umowy" . '">' . "druk" . '</a>'
+						:	""
+					) . " {$add}"
+				;
+				// TODO: get opis from koresp
+				//echo '('.$v_doc->get('ID_KORESP').', '.$v_doc->get('K_ZAWARTOS').'='.substr($v_doc->get('K_ZAWARTOS'), 0, strlen('rozwiazanie umowy')).')';
+				default: return "zmiana statusu na: " . $v_doc->get('A_STATUS') . " ";
+			}
+		}
+		if ($v_doc->get_class() == 'EVENT' && $v_doc->get_type() == 'HIST_PHONE') {
+			$lastUpdateDate = $v_doc->get('A_RECORD_UPDATE_DATE');
+
+			$lastPhoneStatus = ('N/S;' === $v_doc->get('LAST_PHONE_STATUS')) ? '' : $v_doc->get('LAST_PHONE_STATUS');
+			if (!empty($lastPhoneStatus)) {
+				$date = $v_doc->get('PAY_TERM');
+				if ($date == 'N/S;') $date = '';
+				switch ($lastPhoneStatus) {
+					case 'nie_zaplaci': return "nie zapłaci";
+					case 'zaplaci_w_terminie': return "zapłaci w terminie {$date} " . '<em style="font-size:small;">' . "(ustalono {$lastUpdateDate})" . '</em>';
+					case 'zaplaci_za_1mc': return "zapłaci miesiąc później {$date} " . '<em style="font-size:small;">' . "(ustalono {$lastUpdateDate})" . '</em>';
+					case 'zaplaci_za_2mc': return "zapłaci 2 miesiące później {$date} " . '<em style="font-size:small;">' . "(ustalono {$lastUpdateDate})" . '</em>';
+					case 'zaplaci_za_3mc': return "zapłaci 3 miesiące później {$date} " . '<em style="font-size:small;">' . "(ustalono {$lastUpdateDate})" . '</em>';
+					default: return "kontakt z klientem: {$lastPhoneStatus} " . '<em style="font-size:small;">' . "(ustalono {$lastUpdateDate})" . '</em>';
+				}
+			}
+
+			$lastSmsStatus = $v_doc->get('LAST_SMS_STATUS');
+			if ($lastSmsStatus == 'N/S;') $lastSmsStatus = '';
+			if (!empty($lastSmsStatus)) {
+				$lastSmsId = $v_doc->get('LAST_SMS_MSG_ID');
+				return "SMS: {$lastSmsStatus} " . '<em style="font-size:small;" title="' . "(wysłano {$lastUpdateDate}, {$lastSmsId})" . '">' . "(wysłano {$lastUpdateDate})" . '</em>';
+			}
+
+			$lastMailStatus = $v_doc->get('LAST_MAIL_STATUS');
+			if ($lastMailStatus == 'N/S;') $lastMailStatus = '';
+			if (!empty($lastMailStatus)) {
+				$lastMailId = $v_doc->get('LAST_MAIL_MSG_ID');
+				return "MAIL: {$lastMailStatus} " . '<em style="font-size:small;" title="' . "(wysłano {$lastUpdateDate}, {$lastMailId})" . '">' . "(wysłano {$lastUpdateDate})" . '</em>';
+			}
+		}
+
+		if ($v_doc->get_class() == 'EVENT' && $v_doc->get_type() == 'HIST_BAD_ADDRESS') {
+			$koresp_edit_link = "index.php?_route=ViewTableAjax&namespace=default_db/IN7_DZIENNIK_KORESP#EDIT/";
+			$add = ($v_doc->get('ID_KORESP') > 0)
+				?	" - ID Koresp. (" . '<a href="' . $koresp_edit_link . $v_doc->get('ID_KORESP') . '" target="_blank">' . $v_doc->get('ID_KORESP') . '</a>' . ")"
+				:	""
+			;
+
+			return ($v_doc->get('BAD_ADDRESS'))
+				?	"błędny adres zameldowania {$add}"
+				:	"poprawa adresu zameldowania {$add}"
+			;
+		}
+
+		if ($v_doc->get_class() == 'EVENT' && $v_doc->get_type() == 'UMOWA') {
+			return "umowa nr <b>".$v_doc->get('P_DEALNUMBER')."</b> <em>(termin ".$v_doc->get('P_DEALDATE_TERM').")</em>";
+		}
+
+		if ($v_doc->get_class() == 'EVENT' && $v_doc->get_type() == 'KONIEC UMOWY') {
+			return "zakończenie umowy nr <b>".$v_doc->get('P_DEALNUMBER')."</b> <em>(z dnia ".$v_doc->get('P_DEALDATE').")</em>";
+		}
+
+		if ($v_doc->get_class() == 'EVENT' && $v_doc->get_type() == 'HIST_CONTACT') {
+			return implode(" ", [
+				$v_doc->get('L_APPOITMENT_TYPE'),
+				$v_doc->get('L_APPOITMENT_INFO'),
+				UI::h('em', [], "(" . $v_doc->get('L_APPOITMENT_USER') . ")"),
+			]);
+		}
+
+		return "...";
+
 	}
 
 	function prepareTable() {
@@ -560,4 +643,42 @@ class Route_UrlAction_UserContact extends RouteBase {
 			) ENGINE=MyISAM DEFAULT CHARSET=latin2;
 		");
 	}
-}
+}
+
+/*
+insert into USERS2_CONTACT (
+    A_RECORD_CREATE_DATE,
+    A_RECORD_CREATE_AUTHOR,
+    ID_BILLING_USERS,
+    CLIENT_INFO,
+    L_APPOITMENT_TYPE,
+    L_APPOITMENT_DATE,
+    L_APPOITMENT_USER,
+    L_APPOITMENT_INFO
+)
+select
+    h.A_RECORD_UPDATE_DATE as A_RECORD_CREATE_DATE,
+    h.A_RECORD_UPDATE_AUTHOR as A_RECORD_CREATE_AUTHOR,
+    ( select w.ID_BILLING_USERS from USERS2_WINDYKACJA_STATUS w where w.ID = h.ID_USERS2 ) as ID_BILLING_USERS,
+    '' as CLIENT_INFO,
+	'TEL' as L_APPOITMENT_TYPE,
+    IF('N/S;' = h.L_APPOITMENT_DATE and h.LAST_PHONE_STATUS_DATE != 'N/S;', h.LAST_PHONE_STATUS_DATE, h.L_APPOITMENT_DATE) as L_APPOITMENT_DATE,
+    IF('N/S;' = h.L_APPOITMENT_DATE and h.LAST_PHONE_STATUS_DATE != 'N/S;', h.A_RECORD_UPDATE_AUTHOR, h.L_APPOITMENT_USER) as L_APPOITMENT_USER,
+    IF('N/S;' = h.L_APPOITMENT_DATE and h.LAST_PHONE_STATUS_DATE != 'N/S;', h.LAST_PHONE_STATUS, h.L_APPOITMENT_INFO) as L_APPOITMENT_INFO
+
+--    , '===' as X, h.*
+
+from USERS2_WINDYKACJA_STATUS_HIST h
+where
+    h.A_RECORD_UPDATE_DATE like '2019-08-%'
+    and h.A_RECORD_UPDATE_AUTHOR not like '%update%'
+
+
+select sum(ILE_ODZYSKANO) from USERS2_CONTACT;
+
+
+select count(DISTINCT ID_BILLING_USERS) from USERS2_CONTACT;
+
+
+select ID_BILLING_USERS, count(*) as cnt from USERS2_CONTACT group by ID_BILLING_USERS;
+*/

+ 67 - 398
SE/se-lib/Route/UrlAction/UserSaldoAfterContact.php

@@ -1,6 +1,7 @@
 <?php
 
 Lib::loadClass('RouteBase');
+Lib::loadClass('Windykacja_View');
 
 // Windykacja - oblicz ile odzyskano po kontakcie
 class Route_UrlAction_UserSaldoAfterContact extends RouteBase {
@@ -16,11 +17,11 @@ class Route_UrlAction_UserSaldoAfterContact extends RouteBase {
 
 		$idUser = $contactInfo['ID_BILLING_USERS'];
 		if ($idUser <= 0) throw new Exception("Brak numeru klienta");
-		$this->viewUserInfo($idUser);
+		Windykacja_View::viewUserInfo($idUser);
 
 		$postTask = V::get('_postTask', '', $_POST);
 		switch ($postTask) {
-			case 'saveIleOdzyskano': $this->saveIleOdzyskanoPostTask($idUser); break;
+			case 'saveIleOdzyskano': $this->saveIleOdzyskanoPostTask($id, $contactInfo); break;
 			case '': break;
 			default: throw new Exception("Not implemented postTask '{$postTask}'");
 		}
@@ -28,7 +29,7 @@ class Route_UrlAction_UserSaldoAfterContact extends RouteBase {
 
 		echo UI::h('hr');
 
-		$this->viewHistContacts($idUser);
+		Router::getRoute('UrlAction_UserContact')->viewUserPaymentContactsHistory($idUser, [ 'markEventsFromSpotkanieNr' => $id ]);
 	}
 
 	function viewIleOdzyskanoForm($id) {
@@ -42,36 +43,38 @@ class Route_UrlAction_UserSaldoAfterContact extends RouteBase {
 				and A_STATUS != 'DELETED'
 		", [ ':id_user' => $idUser, ':contact_date' => $contactInfo['A_RECORD_CREATE_DATE'] ]);
 		$lastContactId = (!empty($listContactAfter)) ? end($listContactAfter)['ID'] : null;
+		$args = [];
+		$args['ILE_ODZYSKANO'] = V::get('ILE_ODZYSKANO', $contactInfo['ILE_ODZYSKANO'], $_POST);
 
 		echo UI::h('form', [ 'method' => "POST", 'class' => "form-inline" ], [
 			UI::h('input', [ 'type' => "hidden", 'name' => '_postTask', 'value' => "saveIleOdzyskano" ]),
 			UI::h('input', [ 'type' => "hidden", 'name' => 'id', 'value' => $id ]),
 			UI::h('div', [ 'class' => "row", 'style' => "padding-bottom: 12px" ], [
-				"Notatka ze spotkania:",
-				UI::hTable([ 'rows' => [ $contactInfo ] ]),
+				UI::h('div', [ 'class' => "col-md-12" ], [
+					UI::h('h4', [], "Notatka ze spotkania:"),
+					UI::h('div', [ 'style' => "padding-left:32px" ], [
+						$this->viewNotatkaRow($contactInfo),
+					]),
+				]),
 			]),
 			($listContactAfter)
 			?	UI::h('div', [ 'class' => "row", 'style' => "padding-bottom: 12px" ], [
-					UI::h('div', [ 'class' => "alert alert-warning" ], [
-						"Uwaga: Znaleziono późniejsze notatki z klientem",
-						" ",
-						UI::h('a', [ 'href' => $this->getLink('', [ 'ID' => $lastContactId ]) ], "przejdź do najnowszego kontaktu"),
-					]),
-					UI::hTable([
-						'rows' => array_map(function ($item) {
-							return arraY_merge([
-								'ID' => $item['ID'],
-							], $item);
-						}, $listContactAfter)
+					UI::h('div', [ 'class' => "col-md-12" ], [
+						UI::h('div', [ 'class' => "alert alert-warning" ], [
+							"Uwaga: Znaleziono późniejsze notatki z klientem",
+							" ",
+							UI::h('a', [ 'href' => $this->getLink('', [ 'ID' => $lastContactId ]) ], "przejdź do najnowszego kontaktu"),
+						]),
+						UI::h('div', [ 'style' => "padding-left:32px" ], array_map([ $this, 'viewNotatkaRow' ], $listContactAfter)),
 					]),
 				])
 			:	UI::h('div', [], [
 					UI::h('div', [ 'class' => "row", 'style' => "padding-bottom: 12px" ], [
 						UI::h('div', [ 'class' => "col-md-12" ], [
-							UI::h('iframe', [
-								'src' => "https://biuro.biall-net.pl/dev-pl/se-master/index.php?MENU_INIT=USERS2_WINDYKACJA_STATUS&q=&_f=&_user_id={$idUser}",
-								'style' => "width:100%; height:400px; padding:12px; border:1px solid #ddd; border-radius:8px",
-							]),
+							// UI::h('iframe', [
+							// 	'src' => "https://biuro.biall-net.pl/dev-pl/se-master/index.php?MENU_INIT=USERS2_WINDYKACJA_STATUS&q=&_f=&_user_id={$idUser}",
+							// 	'style' => "width:100%; height:400px; padding:12px; border:1px solid #ddd; border-radius:8px",
+							// ]),
 						]),
 						UI::h('div', [ 'class' => "col-md-12" ], [
 							UI::h('label', [], "Ile odzyskano:"),
@@ -85,399 +88,65 @@ class Route_UrlAction_UserSaldoAfterContact extends RouteBase {
 			,
 		]);
 	}
-	function saveContactPostTask($idUser) {
+	function viewNotatkaRow($item) {
+		return UI::h('div', [ 'style' => "margin-bottom:12px" ], array_merge(
+			[
+				UI::h('div', [ 'style' => "font-weight:bold" ], "Notatka nr {$item['ID']}"),
+				UI::h('div', [ 'style' => "color:#333" ], [
+					UI::h('span', [ 'class' => "text-muted" ], "Wykonana przez: "),
+					" {$item['L_APPOITMENT_USER']}",
+				]),
+				UI::h('div', [ 'style' => "color:#333" ], [
+					UI::h('span', [ 'class' => "text-muted" ], "Data: "),
+					" {$item['L_APPOITMENT_DATE']}",
+				]),
+				UI::h('div', [ 'style' => "color:#333" ], [
+					UI::h('span', [ 'class' => "text-muted" ], "Treść: "),
+					" {$item['L_APPOITMENT_INFO']}",
+				]),
+			],
+			($item['ILE_ODZYSKANO'] > 0) ? [
+				UI::h('div', [ 'style' => "color:#333" ], [
+					UI::h('span', [ 'class' => "text-muted" ], "Odzyskano: "),
+					" ",
+					UI::price($item['ILE_ODZYSKANO']),
+				]),
+			] : []
+		));
+	}
+	function saveIleOdzyskanoPostTask($id, $contactInfo) {
 		$args = [];
-		$args['L_APPOITMENT_USER'] = V::get('L_APPOITMENT_USER', '', $_POST);
-		$args['L_APPOITMENT_DATE'] = V::get('L_APPOITMENT_DATE', '', $_POST);
-		$args['L_APPOITMENT_TYPE'] = V::get('L_APPOITMENT_TYPE', '', $_POST);
-		$args['L_APPOITMENT_INFO'] = V::get('L_APPOITMENT_INFO', '', $_POST);
-		$args['change_windykacja_status'] = V::get('change_windykacja_status', '', $_POST);
-		$args['A_STATUS_INFO'] = V::get('A_STATUS_INFO', '', $_POST);
-		$args['add_reminder'] = V::get('add_reminder', '', $_POST);
-		$args['REMINDER_USER'] = V::get('REMINDER_USER', '', $_POST);
-		$args['REMINDER_DATE'] = V::get('REMINDER_DATE', '', $_POST);
-		$args['REMINDER_INFO'] = V::get('REMINDER_INFO', '', $_POST);
+		$args['ILE_ODZYSKANO'] = V::get('ILE_ODZYSKANO', 0, $_POST, 'price');
 
 		try {
-			if (empty($args['L_APPOITMENT_USER'])) throw new Exception("Brak pracownika");
-			if (empty($args['L_APPOITMENT_DATE'])) throw new Exception("Brak daty spotkania");
-			if (empty($args['L_APPOITMENT_TYPE'])) throw new Exception("Brak rodzaju spotkania");
-			if (empty($args['L_APPOITMENT_INFO'])) throw new Exception("Brak treści notatki");
-			if ($args['change_windykacja_status']) {
-				if (empty($args['A_STATUS_INFO'])) throw new Exception("Brak statusu windykacji");
-			}
-			if ($args['add_reminder']) {
-				if (empty($args['REMINDER_USER'])) throw new Exception("Brak pracownika w przypomnieniu");
-				if (empty($args['REMINDER_DATE'])) throw new Exception("Brak daty przypomnienia");
-				if (empty($args['REMINDER_INFO'])) throw new Exception("Brak adnotacji przypomnienia");
-			}
-
-			$windykInfo = $this->getWindykacjaInfo($idUser);
+			if ($contactInfo['ILE_ODZYSKANO'] == $args['ILE_ODZYSKANO']) throw new AlertInfoException("Nie wprowadzono żadnych zmian");
 
-			// create new record with L_APPOITMENT_* in table `USERS2_CONTACT`
-			DB::getPDO()->insert('USERS2_CONTACT', [
-				'ID_BILLING_USERS' => $idUser,
-				'L_APPOITMENT_USER' => $args['L_APPOITMENT_USER'],
-				'L_APPOITMENT_DATE' => $args['L_APPOITMENT_DATE'],
-				'L_APPOITMENT_TYPE' => $args['L_APPOITMENT_TYPE'],
-				'L_APPOITMENT_INFO' => $args['L_APPOITMENT_INFO'],
-				'SALDO' => $windykInfo['SALDO'],
-				'A_RECORD_CREATE_DATE' => "NOW()",
-				'A_RECORD_CREATE_AUTHOR' => User::getLogin(),
+			DB::getPDO()->update('USERS2_CONTACT', 'ID', $id, [
+				'ILE_ODZYSKANO' => $args['ILE_ODZYSKANO'],
+				'A_RECORD_UPDATE_DATE' => "NOW()",
+				'A_RECORD_UPDATE_AUTHOR' => User::getLogin(),
+			]);
+			DB::getPDO()->insert('USERS2_CONTACT_HIST', [
+				'ID_USERS2' => $id,
+				'ILE_ODZYSKANO' => $args['ILE_ODZYSKANO'],
+				'A_RECORD_UPDATE_DATE' => "NOW()",
+				'A_RECORD_UPDATE_AUTHOR' => User::getLogin(),
 			]);
-			// update A_STATUS_INFO in `USERS2_WINDYKACJA_STATUS` if $args['change_windykacja_status']
-			if ($args['change_windykacja_status']) {
-				DB::getPDO()->update('USERS2_WINDYKACJA_STATUS', 'ID_BILLING_USERS', $idUser, [
-					'A_STATUS_INFO' => $args['A_STATUS_INFO'],
-					'A_RECORD_UPDATE_DATE' => "NOW()",
-					'A_RECORD_UPDATE_AUTHOR' => User::getLogin(),
-				]);
-			}
-			// update L_APPOITMENT_* fields using REMINDER_* in `USERS2_WINDYKACJA_STATUS` if $args['add_reminder']
-			if ($args['add_reminder']) {
-				DB::getPDO()->update('USERS2_WINDYKACJA_STATUS', 'ID_BILLING_USERS', $idUser, [
-					'L_APPOITMENT_USER' => $args['REMINDER_USER'],
-					'L_APPOITMENT_DATE' => $args['REMINDER_DATE'],
-					'L_APPOITMENT_INFO' => $args['REMINDER_INFO'],
-					'A_RECORD_UPDATE_DATE' => "NOW()",
-					'A_RECORD_UPDATE_AUTHOR' => User::getLogin(),
-				]);
-			}
+		} catch (AlertInfoException $e) {
+			DBG::log($e);
+			UI::alert('info', $e->getMessage());
+			return;
 		} catch (Exception $e) {
 			DBG::log($e);
 			UI::alert('danger', $e->getMessage());
 			return;
 		}
 
-		throw new AlertSuccessException("Wprowadzono notatkę ze spotkania z klientem " . UI::h('a', [ 'href' => $this->getLink('', [ 'id_user' => $idUser ]) ], "wróć"));
-	}
-
-	function viewUserInfo($idUser) {
-		$userInfo = $this->getUserInfo($idUser);
-		$windykInfo = $this->getWindykacjaInfo($idUser);
-
-		echo UI::h('details', [ 'style' => "margin-bottom: 24px" ], [
-			UI::h('summary', [ 'style' => "padding: 12px; background: #eee; cursor: pointer; outline: none" ], [
-				($userInfo['is_firma']) ? "Firma" : "Klient",
-				" ",
-				UI::h('b', [], "{$userInfo['P_NAME']} {$userInfo['P_NAME_SECOND']}"),
-				$windykInfo ? UI::h('span', [ 'style' => "padding-left: 24px" ], [
-					"Zapis/Odczyt dla: {$windykInfo['A_ADM_COMPANY']}", // $windykInfo['A_CLASSIFIED'];
-				]) : "",
-				UI::h('span', [ 'style' => "padding-left: 24px" ], [
-					"Status windykacji: ",
-					(!$windykInfo) ? "brak danych" : UI::h('span', [], "{$windykInfo['A_STATUS']} <em>{$windykInfo['A_STATUS_INFO']}</em>"),
-				]),
-				" ...",
-				UI::h('span', [ 'style' => "float:right" ], [
-					UI::h('a', [ 'href' => "index.php?MENU_INIT=USERS2_WINDYKACJA_STATUS&q=&_f=&_user_id={$idUser}" ], "Panel windykacji"),
-				]),
-			]),
-			UI::h('div', [ 'style' => "padding: 12px; background: #eee;" ], [
-				UI::h('table', [], [
-					UI::h('tr', [], [
-						UI::h('td', [ 'style' => "vertical-align:top; padding-right:8px" ], [
-							$this->viewWidgetUserInfo($idUser, $userInfo),
-						]),
-						UI::h('td', [ 'style' => "vertical-align:top; padding-right:8px" ], [
-							$this->viewWidgetUserWindykInfo($idUser, $windykInfo),
-						]),
-					]),
-				]),
-			]),
-		]);
-	}
-	function viewWidgetUserInfo($idUser, $userInfo = []) {
-		if (empty($userInfo)) $userInfo = $this->getUserInfo($idUser);
-
-		$outUserInfo = [
-			'Nr klienta' => $userInfo['ID_BILLING_USERS'],
-			'Firma' => ($userInfo['is_firma']) ? "Tak" : "Nie",
-			'Nip' => $userInfo['P_NIP'],
-			'Pesel' => $userInfo['P_PESEL'],
-			'Tel' => $userInfo['P_PHONE'],
-			'email' => $userInfo['user_mail_contact'],
-			'Adres' => "{$userInfo['P_ADDRESS_POST_CODE']} {$userInfo['P_ADDRESS_CITY']} {$userInfo['P_ADDRESS_STREET']} {$userInfo['P_ADDRESS_HOME']}/{$userInfo['P_ADDRESS_HOUSE']}",
-			'Operator' => "[{$userInfo['BILLING_OWNER']}] {$userInfo['BILLING_OWNER_NAME']}",
-		];
-
-		return UI::h('div', [], [
-			UI::h('p', [ 'style' => "border-left:3px solid #ddd; padding-left:6px; font-weight:bold" ], "Dane klienta"),
-			UI::h('table', [ 'class' => "table table-bordered", 'style' => "width:auto; background:#fff" ],
-				array_map(function ($fieldName) use ($outUserInfo) {
-				return UI::h('tr', [], [
-					UI::h('th', [], $fieldName),
-					UI::h('td', [], $outUserInfo[$fieldName]),
-				]);
-				}, array_keys($outUserInfo))
-			),
-		]);
-	}
-	function viewWidgetUserWindykInfo($idUser, $windykInfo = []) {
-		if (empty($windykInfo)) $windykInfo = $this->getUserInfo($idUser);
-
-		$outWindykInfo = [
-			'Status' => $windykInfo['A_STATUS'],
-
-			// $filter_arr['stan_zero'] = array("stan zerowy");
-			// $filter_arr['10-ego'] = array("termin płatności faktur, saldo na -", 'desc'=>array("10-ego", "10-ego każdego miesiąca - termin płatnosci faktur oraz saldo na minusie"));
-			// $filter_arr['WAITING'] = array("termin płatności faktur", 'desc'=>array("10-ego", "10-ego każdego miesiąca - termin płatnosci faktur"));// z regulaminu
-			// $filter_arr['15'] = array("mail ponaglenie", 'desc'=>array("10-ego + 5", "10-ego + 5 dni roboczych"));
-			// $filter_arr['blokada'] = array("blokada", 'desc'=>array("pn, wt, śr około 25", "najbliższy pn, wt, śr do 25"));// najbliższy pn, wt, śr do 25-ego danego miesiąca
-			// $filter_arr['tel1'] = array("kontakt tel.", 'desc'=>array("", "Ostatni kontakt tel. ponad 3 m-ce temu"));
-			// $filter_arr['bad_address'] = array("błędny adres");
-			// $filter_arr['wezwanie1'] = array("wezwanie do zapłaty", 'desc'=>array("2 x FVat", "2 faktury"));
-			// $filter_arr['waiting-wezwanie2'] = array("oczekiwanie 7 dni od terminu płatności");
-			// $filter_arr['wezwanie2'] = array("ostateczne wezwanie do zapłaty, rozwiązanie umowy", 'desc'=>array("wezwanie + 14", "wezwanie + 14 dni"));
-			// $filter_arr['waiting-krd'] = array("min. 30 dni od ostatecznego wezwania");
-			// $filter_arr['krd'] = array("do przekazania do KRD", 'desc'=>array("wezwanie ost. + 60", "wezwanie ost. + 60 dni"));
-			// $filter_arr['waiting-sad'] = array("przekazano do KRD");
-			// $filter_arr['docs-in-sad'] = array("przekazać sprawę do sądu");// waiting-sad = 30 dni
-			// $filter_arr['sad'] = array("przekazano sprawę do sądu");
-
-			// $filter_arr['3 m-ce przed'] = array("3 m-ce przed przedawnieniem");// 3 m-ce przed przedawnieniem
-			// $filter_arr['po-terminie'] = array("po terminie");// 3 lata po dacie platnosci faktur
-			// $filter_arr['has_nr_sad'] = array("nr sprawy sąd");
-			// $filter_arr['has_nr_komornik'] = array("nr sprawy komornik");
-			// $filter_arr['has_ustalenia'] = array("ustalenia z klientem");
-			// $filter_arr['sad_and_komornik'] = array("sąd z komornik");
-			// $filter_arr['sad_bez_komornik'] = array("sąd bez komornik");
-			// $filter_arr['isMovedToVectra'] = array("przeniesieni do Vectra");
-
-			// if ($filter_selected == 'po-terminie') {
-			// 	$sql_where_and_arr[] = "w.`PAY_SALDO`<=-0.05";
-			// 	$sql_where_and_arr[] = "w.`PAY_DATE`!='0000-00-00'";
-			// 	$sql_where_and_arr[] = "w.`PAY_DATE`<DATE_SUB(NOW(), INTERVAL 36 MONTH)";
-			// }
-			// else if ($filter_selected == '3 m-ce przed') {
-			// 	$sql_where_and_arr[] = "w.`PAY_SALDO`<=-0.05";
-			// 	$sql_where_and_arr[] = "w.`PAY_DATE`!='0000-00-00'";
-			// 	$sql_where_and_arr[] = "w.`PAY_DATE`<DATE_SUB(NOW(), INTERVAL 33 MONTH)";
-			// 	$sql_where_and_arr[] = "w.`PAY_DATE`>DATE_SUB(NOW(), INTERVAL 36 MONTH)";
-			// }
-			// else if ($filter_selected == 'tel1') {
-			// 	$sql_where_and_arr[] = "w.`PAY_SALDO`<=-0.05";
-			// 	$sql_where_and_arr[] = "w.`A_STATUS` in('wezwanie1', 'waiting-wezwanie2', 'wezwanie2', 'waiting-krd')";
-			// 	$sql_where_and_arr[] = "( w.`LAST_PHONE_STATUS_DATE`='0000-00-00'
-			// 		or w.`LAST_PHONE_STATUS_DATE`<DATE_SUB(NOW(), INTERVAL 3 MONTH) )";
-			// }
-			// else if ($filter_selected == 'bad_address') {
-			// 	$sql_where_and_arr[] = "w.`BAD_ADDRESS`>0";
-			// 	$sql_where_and_arr[] = "w.`PAY_SALDO`<=-0.05";
-			// }
-			// else if ($filter_selected == 'stan_zero') {
-			// 	$sql_where_and_arr[] = "w.`A_STATUS`='WAITING'";
-			// 	$sql_where_and_arr[] = "w.`PAY_SALDO`>-0.05";
-			// }
-			// else if ($filter_selected == '10-ego') {
-			// 	$sql_where_and_arr[] = "w.`A_STATUS`='WAITING'";
-			// 	$sql_where_and_arr[] = "w.`PAY_SALDO`<=-0.05";
-			// }
-			// else if ($filter_selected == 'has_nr_sad') {
-			// 	$sql_where_and_arr[] = "w.`NR_SPRAWY_SAD`!=''";
-			// }
-			// else if ($filter_selected == 'has_nr_komornik') {
-			// 	$sql_where_and_arr[] = "w.`NR_SPRAWY_KOMORNIK`!=''";
-			// }
-			// else if ($filter_selected == 'has_ustalenia') {
-			// 	$sql_where_and_arr[] = "w.`L_APPOITMENT_INFO`!=''";
-			// }
-			// else if ($filter_selected == 'sad_and_komornik') {
-			// 	$sql_where_and_arr[] = "w.`A_STATUS`='sad' and w.`NR_SPRAWY_KOMORNIK`!=''";
-			// }
-			// else if ($filter_selected == 'sad_bez_komornik') {
-			// 	$sql_where_and_arr[] = "w.`A_STATUS`='sad' and w.`NR_SPRAWY_KOMORNIK`=''";
-			// }
-			// else if ($filter_selected == 'isMovedToVectra') {
-			// 	$sql_where_and_arr[] = "w.`IS_MOVED_TO_VECTRA`=1";
-			// }
-			// else {
-			// 	$sql_where_and_arr[] = "w.`A_STATUS`='{$filter_selected}'";
-			// }
-
-			'Saldo' => $windykInfo['PAY_SALDO'],
-			'Termin ost. fv' => $windykInfo['PAY_DATE'], // Data wymagalności ostatniej faktury
-			'Zaległe faktury' => $windykInfo['PAY_FVAT'],
-			'Adresy usług' => $windykInfo['SERVICES_STREETS'],
-		];
-
-		return UI::h('div', [], [
-			UI::h('p', [ 'style' => "border-left:3px solid #ddd; padding-left:6px; font-weight:bold" ], [
-				"Informacje o płatnościach",
-				($windykInfo['A_STATUS_UPDATE_DATE'] < date("Y-m-d"))
-				?	UI::h('div', [ 'class' => "text-danger" ], [
-						"Uwaga: Wymagają aktualizacji",
-						" ",
-						UI::h('em', [ 'class' => "text-muted" ], "(dane z {$windykInfo['A_STATUS_UPDATE_DATE']})"),
-						// TODO: btn aktualizuj lub auto aktualizuj przed pokazaniem danych
-					])
-				:	"",
-			]),
-			UI::h('table', [ 'class' => "table table-bordered", 'style' => "width:auto; background:#fff" ],
-				array_map(function ($fieldName) use ($outWindykInfo) {
-				return UI::h('tr', [], [
-					UI::h('th', [], $fieldName),
-					UI::h('td', [], $outWindykInfo[$fieldName]),
-				]);
-				}, array_keys($outWindykInfo))
-			),
-			UI::h('table', [ 'class' => "table table-bordered", 'style' => "width:auto; display:none; background:yellow" ],
-				array_map(function ($fieldName) use ($windykInfo) {
-				return UI::h('tr', [], [
-					UI::h('th', [], $fieldName),
-					UI::h('td', [], $windykInfo[$fieldName]),
-				]);
-				}, array_keys($windykInfo))
-			),
-		]);
-	}
-
-	function viewHistContacts($idUser) {
-		$lastHist = DB::getPDO()->fetchAll("
-			select t.ID
-				, t.ID_BILLING_USERS
-		--		, t.CLIENT_INFO
-				, t.A_STATUS
-		--		, t.A_STATUS_INFO
-				, t.L_APPOITMENT_USER
-				, t.L_APPOITMENT_DATE
-				, t.L_APPOITMENT_TYPE
-				, t.L_APPOITMENT_INFO
-			from USERS2_CONTACT t
-			where t.ID_BILLING_USERS = :id
-				and t.A_STATUS != 'DELETED'
-			limit 11
-		", [ ':id' => $idUser ]);
-
-		UI::table([ 'caption' => "Historia kontaktów z klientem (TODO: w trakcie prac. Zobacz " .
-			UI::h('a', [ 'href' => "index.php?MENU_INIT=USERS2_WINDYKACJA_STATUS&q=&_f=&_user_id={$idUser}" ], "Panel windykacji") .
-		")", 'rows' => $lastHist ]);
-		// if (count($lastHist) > 10) UI::alert('info', "Przeglądaj wszystkie wpisy TODO: link to view table with ff_ID_BILLING_USERS");
+		throw new AlertSuccessException("Wprowadzono zmiany " . UI::h('a', [ 'href' => $this->getLink('', [ 'id' => $id ]) ], "wróć"));
 	}
 
 	function getContactInfo($id) {
 		return DB::getPDO()->fetchFirst(" select t.* from USERS2_CONTACT t where t.ID = :id ", [ ':id' => $id ]);
 	}
 
-	function getUserInfo($idUser) {
-		return DB::getPDO()->fetchFirst("
-			select bua.`id_users`
-				, bua.`id_users` as ID_BILLING_USERS
-				, bua.`is_firma`
-				, bua.`P_NAME`
-				, bua.`P_NAME_SECOND`
-				, bua.`P_NIP`
-				, bua.`P_PESEL`
-				, bua.`P_PHONE`
-				, bua.`P_ADDRESS_REGION`
-				, bua.`P_ADDRESS_CITY`
-				, bua.`P_ADDRESS_POST_CODE`
-				, bua.`P_ADDRESS_STREET`
-				, bua.`P_ADDRESS_HOME`
-				, bua.`P_ADDRESS_HOUSE`
-				, bua.`user_mail_contact`
-				, bu.`BILLING_OWNER`
-				, ( select bo.name1 from BILLING_OWNER bo where bo.ID = bu.BILLING_OWNER ) as BILLING_OWNER_NAME
-			from `BILLING_USERS_ADD` as bua
-				left join `BILLING_USERS` as bu on ( bu.`ID` = bua.`id_users` )
-			where bua.`id_users` = :id_user
-		", [ ':id_user' => $idUser ]);
-	}
-	function getWindykacjaInfo($idUser) {
-		if ($this->_windykInfo) return $this->_windykInfo;
-
-		$this->_windykInfo = $this->fetchWindykacjaInfo($idUser);
-		if ($this->_windykInfo['A_STATUS_UPDATE_DATE'] < date("Y-m-d")) {
-			Lib::loadClass('Windykacja_StatsModel');
-			Lib::loadClass('Windykacja_StatsHelper');
-			$user = Windykacja_StatsModel::get_user_by_id($idUser);
-			if ($user) {
-				$billing_docs = Windykacja_StatsModel::get_bill_dosc_by_date($user);
-				Windykacja_StatsHelper::update_stats($user, $billing_docs);
-			}
-			$this->_windykInfo = $this->fetchWindykacjaInfo($idUser);
-		}
-		return $this->_windykInfo;
-	}
-	function fetchWindykacjaInfo($idUser) {
-		return DB::getPDO()->fetchFirst("
-			select t.`ID`
-				, t.A_STATUS
-				, t.A_STATUS_INFO
-				, t.*
-			from `USERS2_WINDYKACJA_STATUS` as t
-			where t.`ID_BILLING_USERS` = :id_user
-		", [ ':id_user' => $idUser ]);
-	}
-
-	function prepareTable() {
-		DB::getPDO()->execSql("
-			CREATE TABLE IF NOT EXISTS `USERS2_CONTACT` (
-				`ID` int(11) NOT NULL AUTO_INCREMENT,
-				`ID_BILLING_USERS` int(11) NOT NULL DEFAULT '0',
-				`CLIENT_INFO` varchar(255) NOT NULL DEFAULT '',
-				`A_STATUS` enum('WAITING','NORMAL','DELETED') NOT NULL DEFAULT 'WAITING',
-				`A_STATUS_INFO` varchar(255) NOT NULL,
-				`L_APPOITMENT_DATE` date NOT NULL DEFAULT '0000-00-00',
-				`L_APPOITMENT_USER` varchar(20) NOT NULL DEFAULT '',
-				`L_APPOITMENT_PERIOD` varchar(4) NOT NULL,
-				`L_APPOITMENT_INFO` varchar(255) NOT NULL,
-				`L_APPOITMENT_TYPE` enum('','LIVE','TEL','MAIL','SMS','INNE') DEFAULT NULL,
-				`A_RECORD_CREATE_DATE` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
-				`A_RECORD_CREATE_AUTHOR` varchar(20) NOT NULL DEFAULT '',
-				`A_RECORD_UPDATE_DATE` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
-				`A_RECORD_UPDATE_AUTHOR` varchar(20) NOT NULL DEFAULT '',
-				`A_PROBLEM` enum('','WARNING','PROBLEM','SERIOUS','UNVERIFIED') DEFAULT NULL,
-				`A_PROBLEM_DESC` varchar(255) NOT NULL DEFAULT '',
-				`A_PROBLEM_DATE` varchar(30) NOT NULL DEFAULT '',
-				`T_WORKPOINTS` varchar(100) NOT NULL DEFAULT '',
-				`T_WORKPOINTS_VALUE` varchar(100) NOT NULL DEFAULT '',
-				`T_WORKPOINTS_TYPE` varchar(100) NOT NULL DEFAULT '',
-				`T_WORKPOINTS_USER` varchar(100) NOT NULL DEFAULT '',
-				`T_WORKPOINTS_DATE` varchar(100) NOT NULL DEFAULT '',
-				`A_CLASSIFIED` varchar(100) NOT NULL DEFAULT '',
-				`A_ADM_COMPANY` varchar(100) NOT NULL DEFAULT '',
-				`ROZLICZ_MONTH` date NOT NULL DEFAULT '0000-00-00',
-				`ROZLICZ_CONFIRM` int(11) NOT NULL DEFAULT '0',
-				`SALDO` decimal(10,2) NOT NULL DEFAULT '0.00',
-				`ILE_ODZYSKANO` decimal(10,2) NOT NULL DEFAULT '0.00',
-				PRIMARY KEY (`ID`)
-			) ENGINE=MyISAM DEFAULT CHARSET=latin2;
-		");
-		DB::getPDO()->execSql("
-			CREATE TABLE IF NOT EXISTS `USERS2_CONTACT_HIST` (
-				`ID` int(11) NOT NULL AUTO_INCREMENT,
-				`ID_USERS2` int(11) NOT NULL,
-				`ID_BILLING_USERS` varchar(11) NOT NULL DEFAULT 'N/S;',
-				`CLIENT_INFO` varchar(255) NOT NULL DEFAULT 'N/S;',
-				`A_STATUS` varchar(32) NOT NULL DEFAULT 'N/S;',
-				`A_STATUS_INFO` varchar(255) NOT NULL DEFAULT 'N/S;',
-				`L_APPOITMENT_DATE` varchar(20) NOT NULL DEFAULT 'N/S;',
-				`L_APPOITMENT_USER` varchar(20) NOT NULL DEFAULT 'N/S;',
-				`L_APPOITMENT_PERIOD` varchar(4) NOT NULL DEFAULT 'N/S;',
-				`L_APPOITMENT_INFO` varchar(255) NOT NULL DEFAULT 'N/S;',
-				`L_APPOITMENT_TYPE` varchar(16) NOT NULL DEFAULT 'N/S;',
-				`A_RECORD_CREATE_DATE` varchar(20) NOT NULL DEFAULT 'N/S;',
-				`A_RECORD_CREATE_AUTHOR` varchar(20) NOT NULL DEFAULT 'N/S;',
-				`A_RECORD_UPDATE_DATE` varchar(20) NOT NULL DEFAULT 'N/S;',
-				`A_RECORD_UPDATE_AUTHOR` varchar(20) NOT NULL DEFAULT 'N/S;',
-				`A_PROBLEM` varchar(16) NOT NULL DEFAULT 'N/S;',
-				`A_PROBLEM_DESC` varchar(255) NOT NULL DEFAULT 'N/S;',
-				`A_PROBLEM_DATE` varchar(30) NOT NULL DEFAULT 'N/S;',
-				`T_WORKPOINTS` varchar(100) NOT NULL DEFAULT 'N/S;',
-				`T_WORKPOINTS_VALUE` varchar(100) NOT NULL DEFAULT 'N/S;',
-				`T_WORKPOINTS_TYPE` varchar(100) NOT NULL DEFAULT 'N/S;',
-				`T_WORKPOINTS_USER` varchar(100) NOT NULL DEFAULT 'N/S;',
-				`T_WORKPOINTS_DATE` varchar(100) NOT NULL DEFAULT 'N/S;',
-				`A_CLASSIFIED` varchar(100) NOT NULL DEFAULT 'N/S;',
-				`A_ADM_COMPANY` varchar(100) NOT NULL DEFAULT 'N/S;',
-				`ROZLICZ_MONTH` varchar(20) NOT NULL DEFAULT 'N/S;',
-				`ROZLICZ_CONFIRM` varchar(11) NOT NULL DEFAULT 'N/S;',
-				`SALDO` varchar(11) NOT NULL DEFAULT 'N/S;',
-				`ILE_ODZYSKANO` varchar(11) NOT NULL DEFAULT 'N/S;',
-				PRIMARY KEY (`ID`),
-				KEY `ID_USERS2` (`ID_USERS2`)
-			) ENGINE=MyISAM DEFAULT CHARSET=latin2;
-		");
-	}
 }

+ 2 - 2
SE/se-lib/Route/UrlAction/WindykacjaUpdateStatus.php

@@ -221,7 +221,7 @@ class Route_UrlAction_WindykacjaUpdateStatus extends RouteBase {
 			]);
 			$user = Windykacja_StatsModel::get_user_by_id($toUpdateClientID);
 			if ($user) {
-				$billing_docs = Windykacja_StatsModel::get_bill_dosc_by_date($user);
+				$billing_docs = Windykacja_StatsModel::getBillDocsByDate($user->ID);
 				Windykacja_StatsHelper::update_stats($user, $billing_docs);
 			}
 		}
@@ -266,7 +266,7 @@ class Route_UrlAction_WindykacjaUpdateStatus extends RouteBase {
 			foreach ($toUpdateClientListIds as $toUpdateClientID) {
 				$user = Windykacja_StatsModel::get_user_by_id($toUpdateClientID);
 				if ($user) {
-					$billing_docs = Windykacja_StatsModel::get_bill_dosc_by_date($user);
+					$billing_docs = Windykacja_StatsModel::getBillDocsByDate($user->ID);
 					Windykacja_StatsHelper::update_stats($user, $billing_docs);
 				} else {
 					DB::getPDO()->update('USERS2_WINDYKACJA_STATUS', 'ID_BILLING_USERS', $toUpdateClientID, [

+ 5 - 2
SE/se-lib/UI.php

@@ -187,7 +187,7 @@ class UI {
 		// if (empty($cols)) return;
 		$hiddenCols = V::get('hidden_cols', array(), $params);
 
-		$tableAttrs = [ 'class' => $cssClassTable ];
+		$tableAttrs = [ 'class' => $cssClassTable, 'style' => V::get('style', '', $params) ];
 		$html_id = V::get('__html_id', '', $params);
 		if ($html_id) $tableAttrs['id'] = $html_id;
 		self::startTag('table', $tableAttrs); echo "\n";
@@ -198,7 +198,10 @@ class UI {
 			if ($showLp) { self::tag('th', [ 'style' => "padding:{$cellPadding}px" ], "Lp.");	echo "\n"; }
 			foreach ($cols as $colName) {
 				if (in_array($colName, $hiddenCols)) continue;
-				echo self::h('th', [ 'style' => "padding:{$cellPadding}px" ], [
+				$attrs = [ 'style' => "padding:{$cellPadding}px" ];
+				if (!empty($params["@class[{$colName}]"])) $attrs['class'] = $params["@class[{$colName}]"];
+				if (!empty($params["@style[{$colName}]"])) $attrs['style'] .= "; " . $params["@style[{$colName}]"];
+				echo self::h('th', $attrs, [
 					$label[$colName],
 					" " . V::get($colName, '', $help)
 				]);

+ 33 - 15
SE/se-lib/Windykacja/BillingListDocs.php

@@ -11,20 +11,20 @@ class Windykacja_BillingListDocs {
 		$this->_saldo = 0;
 	}
 
-	public function add_bill_doc($data, $type, $h) {
-		$bill_doc = new Windykacja_BillingDoc($type, $h);
-		if ('FVAT' == $type && '0000-00-00' == $data) {
-			$data = $h['BILL_DATE'];
+	public function add_bill_doc($date, $type, $item) {
+		$bill_doc = new Windykacja_BillingDoc($date, $type, $item);
+		if ('FVAT' == $type && '0000-00-00' == $date) {
+			$date = $item['BILL_DATE'];
 		}
-		$this->_docs[$data][] = $bill_doc;
-		if ($data <= date("Y-m-d")) {
+		$this->_docs[$date][] = $bill_doc;
+		if ($date <= date("Y-m-d")) {
 			$this->_saldo += $bill_doc->get_saldo();
 		}
 	}
 
-	public function add_event($data, $type, $h) {
-		$event = new Windykacja_EventDoc($type, $h);
-		$this->_docs[$data][] = $event;
+	public function add_event($date, $type, $item) {
+		$event = new Windykacja_EventDoc($date, $type, $item);
+		$this->_docs[$date][] = $event;
 	}
 
 	public function get_saldo() {
@@ -90,6 +90,16 @@ class Windykacja_BillingListDocs {
 		ksort($this->_docs);
 	}
 
+	function set_saldo_for_all_docs() {
+		$saldo = 0;
+		foreach ($this->_docs as $day => $listDayDocs) {
+			foreach ($listDayDocs as $doc) {
+				$saldo += $doc->get_saldo();
+				$doc->set_saldo_overall($saldo);
+			}
+		}
+	}
+
 	public function get_unpaid_fvat() {
 		$today_date = date("Y-m-d");
 		$fvat_arr = array();
@@ -189,25 +199,36 @@ class Windykacja_BillingListDocs {
 class Windykacja_TimelineDoc {
 
 	var $_type;
+	var $_date;
 	var $_data;
 	var $_class;
+	var $_saldo;
+	var $_saldo_overall;
 
 	public function get_type() { return $this->_type; }
+	public function get_date() { return $this->_date; }
 	public function get_data() { return $this->_data; }
 	public function get_class() { return $this->_class; }
+	public function get_saldo() { return $this->_saldo; }
 	public function get($key) {
 		return $this->_data[$key];
 	}
+	public function get_saldo_overall() { return $this->_saldo_overall; }
+	public function set_saldo_overall($overallSaldo) {
+		$this->_saldo_overall = round($overallSaldo, 2);
+	}
 
 }
 
 
 class Windykacja_EventDoc extends Windykacja_TimelineDoc {
 
-	public function __construct($type, &$data) {
+	public function __construct($date, $type, &$data) {
+		$this->_date = $date;
 		$this->_data = $data;
 		$this->_class = 'EVENT';
 		$this->_type = $type;
+		$this->_saldo = 0;
 	}
 
 }
@@ -215,17 +236,14 @@ class Windykacja_EventDoc extends Windykacja_TimelineDoc {
 
 class Windykacja_BillingDoc extends Windykacja_TimelineDoc {
 
-	public function __construct($type, &$data) {
+	public function __construct($date, $type, &$data) {
+		$this->_date = $date;
 		$this->_data = $data;
 		$this->_class = 'BILLING';
 		$this->_convert_type($type);
 		$this->_count_saldo();
 	}
 
-	public function get_saldo() {
-		return $this->_saldo;
-	}
-
 	public function get($key) {
 		return $this->_data[$key];
 	}

+ 29 - 28
SE/se-lib/Windykacja/StatsHelper.php

@@ -92,9 +92,15 @@ class Windykacja_StatsHelper {
 		$data_arr["A_RECORD_UPDATE_DATE"] = date("Y-m-d-H:i");
 		$data_arr["A_RECORD_UPDATE_AUTHOR"] = "stat-update";
 
-		$company = Windykacja_StatsModel::get_company($user);
-		$nr_konta = Windykacja_FunkcjeL1::bankowy_make_nrach($company->NR_RACH_MASS_PAY, $user->ID_BILLING_USERS, 0);
-		$data_arr["ACCOUNT_NUMBER"] = $nr_konta;
+		$company = Windykacja_StatsModel::getOwnerCompany($user->ID_BILLING_USERS);
+		$data_arr["ACCOUNT_NUMBER"] = Windykacja_FunkcjeL1::bankowy_make_nrach($company['NR_RACH_MASS_PAY'], $user->ID_BILLING_USERS, 0);
+		$windykPerms = DB::getPDO()->fetchFirst(" select w.ID, w.A_ADM_COMPANY, w.A_CLASSIFIED from USERS2_WINDYKACJA_STATUS w where w.ID_BILLING_USERS = :id ", [ ':id' => $user->ID_BILLING_USERS ]);
+		$companyPerms = DB::getPDO()->fetchFirst(" select c.ID, c.A_ADM_COMPANY, c.A_CLASSIFIED from COMPANIES c where c.ID = :id ", [ ':id' => $user->ID_BILLING_USERS ]);
+		DBG::log([ 'windykPerms' => $windykPerms, 'companyPerms' => $companyPerms ], 'array', 'TODO:DBG:user perm from COMPANIES table');
+		if ($windykPerms && $companyPerms) {
+			if ($companyPerms['A_ADM_COMPANY'] != $windykPerms['A_ADM_COMPANY']) $data_arr['A_ADM_COMPANY'] = $companyPerms['A_ADM_COMPANY'];
+			if ($companyPerms['A_CLASSIFIED'] != $windykPerms['A_CLASSIFIED']) $data_arr['A_CLASSIFIED'] = $companyPerms['A_CLASSIFIED'];
+		}
 		$data_arr["SERVICES_STREETS"] = Windykacja_StatsModel::getAllServicesStreetsCSV($user);
 		$data_arr["BILLING_USER_NAME"] = DB::getPDO()->fetchValue("
 			select concat(bua.`P_NAME`, ' ', bua.`P_NAME_SECOND`) as P_NAME
@@ -807,41 +813,36 @@ class Windykacja_StatsHelper {
 		return self::_sql_update($user, $data_arr);
 	}
 
-	public static function get_user_hist_events(&$user) {
-		return array_map(function ($item) { return (object)$item; }, DB::getPDO()->fetchAll("
-			select wh.*
-			from `USERS2_WINDYKACJA_STATUS_HIST` as wh
-			where wh.`ID_USERS2` = :id
-		", [ ':id' => $user->WINDYKACJA_ID ]));
-	}
-
-	public static function get_user_hist_status_events(&$user) {
-		return array_map(function ($item) { return (object)$item; }, DB::getPDO()->fetchAll("
+	public static function getUserHistStatusEvents($idUser) { // TODO: convert to idUser. Sql join USERS2_WINDYKACJA_STATUS w where w.ID_BILLING_USERS = :id_user
+		return DB::getPDO()->fetchAll("
 			select wh.*, kor.`K_ZAWARTOS`
-			from `USERS2_WINDYKACJA_STATUS_HIST` as wh
-				left join `IN7_DZIENNIK_KORESP` as kor on(wh.`ID_KORESP`!='N/S;' and kor.`ID`=wh.`ID_KORESP`)
-			where wh.`ID_USERS2` = :id
-				and wh.`A_STATUS_UPDATE_DATE`!='N/S;'
-		", [ ':id' => $user->WINDYKACJA_ID ]));
+			from `USERS2_WINDYKACJA_STATUS` as w
+				join `USERS2_WINDYKACJA_STATUS_HIST` as wh on ( wh.`ID_USERS2` = w.ID )
+				left join `IN7_DZIENNIK_KORESP` as kor on ( wh.`ID_KORESP` != 'N/S;' and kor.`ID` = wh.`ID_KORESP` )
+			where w.`ID_BILLING_USERS` = :id
+				and wh.`A_STATUS_UPDATE_DATE` != 'N/S;'
+		", [ ':id' => $idUser ]);
 	}
 
-	public static function get_user_hist_phone_events(&$user) {
-		return array_map(function ($item) { return (object)$item; }, DB::getPDO()->fetchAll("
+	public static function getUserHistPhoneEvents($idUser) {
+		return DB::getPDO()->fetchAll("
 			select wh.*
-			from `USERS2_WINDYKACJA_STATUS_HIST` as wh
-			where wh.`ID_USERS2` = :id
+			from `USERS2_WINDYKACJA_STATUS` as w
+				join `USERS2_WINDYKACJA_STATUS_HIST` as wh on ( wh.`ID_USERS2` = w.ID )
+			where w.`ID_BILLING_USERS` = :id
 				and wh.`LAST_PHONE_STATUS_DATE` != 'N/S;'
-		", [ ':id' => $user->WINDYKACJA_ID ]));
+		", [ ':id' => $idUser ]);
 	}
 
-	public static function get_user_bad_address_events(&$user) {
-		return array_map(function ($item) { return (object)$item; }, DB::getPDO()->fetchAll("
+	public static function getUserBadAddressEvents($idUser) {
+		return DB::getPDO()->fetchAll("
 			select wh.*
-			from `USERS2_WINDYKACJA_STATUS_HIST` as wh
-			where wh.`ID_USERS2` = :id
+			from `USERS2_WINDYKACJA_STATUS` as w
+				join `USERS2_WINDYKACJA_STATUS_HIST` as wh on ( wh.`ID_USERS2` = w.ID )
+			where w.`ID_BILLING_USERS` = :id
 				and wh.`BAD_ADDRESS` != 'N/S;'
 			order by wh.`ID` ASC
-		", [ ':id' => $user->WINDYKACJA_ID ]));
+		", [ ':id' => $idUser ]);
 	}
 
 	public static function get_status_count() {

+ 55 - 51
SE/se-lib/Windykacja/StatsModel.php

@@ -322,51 +322,52 @@ class Windykacja_StatsModel {
 		// }
 	}
 
-	public static function get_company(&$user) {
-		if (!isset($user->_company)) {
-			$user->_company = DB::getPDO()->fetchFirstAsObject("
-				select
-					bo.`id`
-					, bo.`name1`
-					, bo.`name2`
-					, bo.`kod`
-					, bo.`miasto`
-					, bo.`ulica`
-					, bo.`numer_dom`
-					, bo.`tel`
-					, bo.`fax`
-					, bo.`nip`
-					, bo.`regon`
-					, bo.`bank`
-					, bo.`nr_rach`
-					, bo.`NR_RACH_MASS_PAY`
-					, bo.`BILLING_OWNER_EMAIL`
-				from `BILLING_USERS` as bu
-					left join `BILLING_OWNER` as bo on ( bo.`ID` = bu.`BILLING_OWNER` )
-				where
-					bu.`ID` = :id_user
-			", [ ':id_user' => $user->ID_BILLING_USERS ]);
-			/*
-				id					1 / 2
-				name1				"BIALL-NET" Sp. z o.o. / "NET-DAY" s.c.
-				name2				--- / Adrian i Ewa Wieczorkowscy
-				kod     		80-174 / 80-809
-				miasto			Gdańsk, Otomin / Gdańsk
-				ulica				Słoneczna / Cieszyńskiego
-				numer_dom		43 / 38
-				numer_pos		NULL / NULL
-				uwagi				--- / ---
-				tel					0-58 320-72-92 / 0-58 741 84 54
-				fax					0-58 320-72-96 / 0-58 741 84 56
-				nip					593-22-68-672 / 583-27-54-031
-				regon				192120212 / 192578721
-				bank				Bank Zachodni WBK SA I O/Gdansk / ---
-				nr_rach			46 1090 1098 0000 0001 0253 7156 / 84 1500 1171 1211 7002 9997 0000
-				NR_RACH_MASS_PAY		109000049887 / 109000049669
-				BILLING_OWNER_EMAIL	biall-net@biall.net.pl / netday@netday.pl
-			 */
-		}
-		return $user->_company;
+	public static function getOwnerCompany($idUser) {
+		static $_company;
+		if (!empty($_company)) return $_company;
+		$_company = DB::getPDO()->fetchFirst("
+			select
+				bo.`id`
+				, bo.`name1`
+				, bo.`name2`
+				, bo.`kod`
+				, bo.`miasto`
+				, bo.`ulica`
+				, bo.`numer_dom`
+				, bo.`tel`
+				, bo.`fax`
+				, bo.`nip`
+				, bo.`regon`
+				, bo.`bank`
+				, bo.`nr_rach`
+				, bo.`NR_RACH_MASS_PAY`
+				, bo.`BILLING_OWNER_EMAIL`
+			from `COMPANIES` as c
+				left join `BILLING_OWNER` as bo on ( bo.`ID` = c.`BILLING_OWNER` )
+			where
+				c.`ID` = :id_user
+		", [ ':id_user' => $idUser ]);
+
+		/*
+			id					1 / 2
+			name1				"BIALL-NET" Sp. z o.o. / "NET-DAY" s.c.
+			name2				--- / Adrian i Ewa Wieczorkowscy
+			kod     		80-174 / 80-809
+			miasto			Gdańsk, Otomin / Gdańsk
+			ulica				Słoneczna / Cieszyńskiego
+			numer_dom		43 / 38
+			numer_pos		NULL / NULL
+			uwagi				--- / ---
+			tel					0-58 320-72-92 / 0-58 741 84 54
+			fax					0-58 320-72-96 / 0-58 741 84 56
+			nip					593-22-68-672 / 583-27-54-031
+			regon				192120212 / 192578721
+			bank				Bank Zachodni WBK SA I O/Gdansk / ---
+			nr_rach			46 1090 1098 0000 0001 0253 7156 / 84 1500 1171 1211 7002 9997 0000
+			NR_RACH_MASS_PAY		109000049887 / 109000049669
+			BILLING_OWNER_EMAIL	biall-net@biall.net.pl / netday@netday.pl
+		 */
+		return $_company;
 	}
 
 	public static function get_billing_type($type_id) {
@@ -429,14 +430,14 @@ class Windykacja_StatsModel {
 		return (!empty($streets))? implode(',', array_keys($streets)) : '';
 	}
 
-	public static function get_umowy_from_l2($user) {
+	public static function getClientUmowy($idUser) {
 		return DB::getPDO()->fetchAllByKey("
 			select
 				d.`ID`, d.`P_DEALPREFIX`, d.`P_DEALNUMBER`, d.`P_DEALNUMBER_OLD`, d.`P_DEALDATE`, d.`P_DEALDATE_TERM`, d.`DEALDESC`, d.`ANEX_NEEDED`, d.`ANEX_CONFIRM_DATE`
 			from `DEALS_TABLE` as d
 			where d.`ID_BILLING_USERS` = :id_user
 			order by d.`ID` DESC
-		", $key = 'ID', [ ':id_user' => $user->ID ]);
+		", $key = 'ID', [ ':id_user' => $idUser ]);
 	}
 
 	public static function get_uslugi_from_l2(&$user) {
@@ -505,6 +506,9 @@ class Windykacja_StatsModel {
 	}
 
 	public static function get_bill_dosc_by_date(&$user, $date_limit = null) {
+		return self::getBillDocsByDate($user->ID, $date_limit);
+	}
+	public static function getBillDocsByDate($idUser, $date_limit = null) {
 		// fetch finanse data from remote DB
 		$billing_docs = new Windykacja_BillingListDocs();
 		$pdo_webone = DB::getPDO('931');
@@ -534,7 +538,7 @@ class Windykacja_StatsModel {
 				{$sqlWhereAdd}
 			group by BILLS_FVAT.ID
 			order by BILLS_FVAT.ID_BILLING_NUMBERS ASC
-		", [ ':id_user' => $user->ID ]);
+		", [ ':id_user' => $idUser ]);
 		foreach ($billsFvat as $h) {
 			// if (0){// ? dla kazdej faktury ?
 			// $sql = "select t1.ID_BILLING_NUMBERS AS NR_DOK
@@ -555,7 +559,7 @@ class Windykacja_StatsModel {
 			// 		left join `BILLING_ACCOUNTS_FILES` as t3 on (t1.ID_BILLING_NUMBERS=t3.ID_FIN_MA)
 			// 	where
 			// 		t1.ID_FIN_WINIEN is NULL and t1.ID_FIN_MA is NULL and t1.MA = 0 and  t1.WINIEN > 0
-			// 		and t1.ID_BILLING_NUMBERS={$user->ID}
+			// 		and t1.ID_BILLING_NUMBERS={$idUser}
 			// 	group by t1.ID_BILLING_NUMBERS
 			// 	limit 0,1
 			// ";
@@ -596,7 +600,7 @@ class Windykacja_StatsModel {
 						, {$bill_type['BILLING_NUMBERS_TABLE']}.ID_BILLING_NUMBERS_TYPE
 					from {$bill_type['TABLE']}
 						left join {$bill_type['BILLING_NUMBERS_TABLE']} on ({$bill_type['BILLING_NUMBERS_TABLE']}.ID={$bill_type['TABLE']}.ID_BILLING_NUMBERS)
-					where {$bill_type['TABLE']}.ID_BILLING_USERS='{$user->ID}'
+					where {$bill_type['TABLE']}.ID_BILLING_USERS='{$idUser}'
 						{$sql_where}
 				";
 				$vBillDocs = $pdo_webone->fetchAll($sql);
@@ -627,7 +631,7 @@ class Windykacja_StatsModel {
 						left join `{$bill_type['BILLING_NUMBERS_TABLE']}` t_num on (t_num.`ID`=t.`ID_BILLING_NUMBERS`)
 						left join `{$bill_type['BILLING_NUMBERS_TABLE']}` fv_num on (fv_num.`ID`=t.`REMOTE_ID_BILLING_NUMBERS`)
 						left join `{$bill_type['TABLE']}_POS` t_pos on (t_pos.`ID_BILLS_FVAT`=t.`ID`)
-					where t.`ID_BILLING_USERS`='{$user->ID}'
+					where t.`ID_BILLING_USERS`='{$idUser}'
 						{$sql_where}
 					group by t.`ID`
 					order by t.`ID`

+ 278 - 55
SE/se-lib/Windykacja/View.php

@@ -9,6 +9,238 @@ Lib::loadClass('Windykacja_FunkcjeL1');
 
 class Windykacja_View {
 
+	static function viewUserInfo($idUser) {
+		$userInfo = self::getUserInfo($idUser);
+		$windykInfo = self::getWindykacjaInfo($idUser);
+
+		echo UI::h('details', [ 'style' => "margin-bottom: 24px" ], [
+			UI::h('summary', [ 'style' => "padding: 12px; background: #eee; cursor: pointer; outline: none" ], [
+				($userInfo['is_firma']) ? "Firma" : "Klient",
+				" ",
+				UI::h('b', [], "{$userInfo['P_NAME']} {$userInfo['P_NAME_SECOND']}"),
+				$windykInfo ? UI::h('span', [ 'style' => "padding-left: 24px" ], [
+					"Zapis/Odczyt dla: {$windykInfo['A_ADM_COMPANY']}", // $windykInfo['A_CLASSIFIED'];
+				]) : "",
+				UI::h('span', [ 'style' => "padding-left: 24px" ], [
+					"Status windykacji: ",
+					(!$windykInfo) ? "brak danych" : UI::h('span', [], "{$windykInfo['A_STATUS']} <em>{$windykInfo['A_STATUS_INFO']}</em>"),
+				]),
+				" ...",
+				UI::h('span', [ 'style' => "float:right" ], [
+					UI::h('a', [ 'href' => "index.php?MENU_INIT=USERS2_WINDYKACJA_STATUS&q=&_f=&_user_id={$idUser}" ], "Panel windykacji"),
+				]),
+			]),
+			UI::h('div', [ 'style' => "padding: 12px; background: #eee;" ], [
+				UI::h('table', [], [
+					UI::h('tr', [], [
+						UI::h('td', [ 'style' => "vertical-align:top; padding-right:8px" ], [
+							self::viewWidgetUserInfo($idUser, $userInfo),
+						]),
+						UI::h('td', [ 'style' => "vertical-align:top; padding-right:8px" ], [
+							self::viewWidgetUserWindykInfo($idUser, $windykInfo),
+						]),
+					]),
+				]),
+			]),
+		]);
+	}
+	static function getUserInfo($idUser) {
+		return DB::getPDO()->fetchFirst("
+			select bua.`id_users`
+				, bua.`id_users` as ID_BILLING_USERS
+				, bua.`is_firma`
+				, bua.`P_NAME`
+				, bua.`P_NAME_SECOND`
+				, bua.`P_NIP`
+				, bua.`P_PESEL`
+				, bua.`P_PHONE`
+				, bua.`P_ADDRESS_REGION`
+				, bua.`P_ADDRESS_CITY`
+				, bua.`P_ADDRESS_POST_CODE`
+				, bua.`P_ADDRESS_STREET`
+				, bua.`P_ADDRESS_HOME`
+				, bua.`P_ADDRESS_HOUSE`
+				, bua.`user_mail_contact`
+				, bu.`BILLING_OWNER`
+				, ( select bo.name1 from BILLING_OWNER bo where bo.ID = bu.BILLING_OWNER ) as BILLING_OWNER_NAME
+			from `BILLING_USERS_ADD` as bua
+				left join `BILLING_USERS` as bu on ( bu.`ID` = bua.`id_users` )
+			where bua.`id_users` = :id_user
+		", [ ':id_user' => $idUser ]);
+	}
+	static function getWindykacjaInfo($idUser) {
+		static $_windykInfo;
+		if ($_windykInfo) return $_windykInfo;
+
+		$_windykInfo = self::fetchWindykacjaInfo($idUser);
+		if ($_windykInfo['A_STATUS_UPDATE_DATE'] < date("Y-m-d")) {
+			$user = Windykacja_StatsModel::get_user_by_id($idUser);
+			if ($user) {
+				$billing_docs = Windykacja_StatsModel::getBillDocsByDate($idUser);
+				Windykacja_StatsHelper::update_stats($user, $billing_docs);
+			}
+			$_windykInfo = self::fetchWindykacjaInfo($idUser);
+		}
+		return $_windykInfo;
+	}
+	static function fetchWindykacjaInfo($idUser) {
+		return DB::getPDO()->fetchFirst("
+			select t.`ID`
+				, t.A_STATUS
+				, t.A_STATUS_INFO
+				, t.PAY_SALDO
+				, t.*
+			from `USERS2_WINDYKACJA_STATUS` as t
+			where t.`ID_BILLING_USERS` = :id_user
+		", [ ':id_user' => $idUser ]);
+	}
+	static function viewWidgetUserInfo($idUser, $userInfo = []) {
+		if (empty($userInfo)) $userInfo = self::getUserInfo($idUser);
+
+		$outUserInfo = [
+			'Nr klienta' => $userInfo['ID_BILLING_USERS'],
+			'Firma' => ($userInfo['is_firma']) ? "Tak" : "Nie",
+			'Nip' => $userInfo['P_NIP'],
+			'Pesel' => $userInfo['P_PESEL'],
+			'Tel' => $userInfo['P_PHONE'],
+			'email' => $userInfo['user_mail_contact'],
+			'Adres' => "{$userInfo['P_ADDRESS_POST_CODE']} {$userInfo['P_ADDRESS_CITY']} {$userInfo['P_ADDRESS_STREET']} {$userInfo['P_ADDRESS_HOME']}/{$userInfo['P_ADDRESS_HOUSE']}",
+			'Operator' => "[{$userInfo['BILLING_OWNER']}] {$userInfo['BILLING_OWNER_NAME']}",
+		];
+
+		return UI::h('div', [], [
+			UI::h('p', [ 'style' => "border-left:3px solid #ddd; padding-left:6px; font-weight:bold" ], "Dane klienta"),
+			UI::h('table', [ 'class' => "table table-bordered", 'style' => "width:auto; background:#fff" ],
+				array_map(function ($fieldName) use ($outUserInfo) {
+				return UI::h('tr', [], [
+					UI::h('th', [], $fieldName),
+					UI::h('td', [], $outUserInfo[$fieldName]),
+				]);
+				}, array_keys($outUserInfo))
+			),
+		]);
+	}
+	static function viewWidgetUserWindykInfo($idUser, $windykInfo = []) {
+		if (empty($windykInfo)) $windykInfo = self::getUserInfo($idUser);
+
+		$outWindykInfo = [
+			'Status' => $windykInfo['A_STATUS'],
+
+			// $filter_arr['stan_zero'] = array("stan zerowy");
+			// $filter_arr['10-ego'] = array("termin płatności faktur, saldo na -", 'desc'=>array("10-ego", "10-ego każdego miesiąca - termin płatnosci faktur oraz saldo na minusie"));
+			// $filter_arr['WAITING'] = array("termin płatności faktur", 'desc'=>array("10-ego", "10-ego każdego miesiąca - termin płatnosci faktur"));// z regulaminu
+			// $filter_arr['15'] = array("mail ponaglenie", 'desc'=>array("10-ego + 5", "10-ego + 5 dni roboczych"));
+			// $filter_arr['blokada'] = array("blokada", 'desc'=>array("pn, wt, śr około 25", "najbliższy pn, wt, śr do 25"));// najbliższy pn, wt, śr do 25-ego danego miesiąca
+			// $filter_arr['tel1'] = array("kontakt tel.", 'desc'=>array("", "Ostatni kontakt tel. ponad 3 m-ce temu"));
+			// $filter_arr['bad_address'] = array("błędny adres");
+			// $filter_arr['wezwanie1'] = array("wezwanie do zapłaty", 'desc'=>array("2 x FVat", "2 faktury"));
+			// $filter_arr['waiting-wezwanie2'] = array("oczekiwanie 7 dni od terminu płatności");
+			// $filter_arr['wezwanie2'] = array("ostateczne wezwanie do zapłaty, rozwiązanie umowy", 'desc'=>array("wezwanie + 14", "wezwanie + 14 dni"));
+			// $filter_arr['waiting-krd'] = array("min. 30 dni od ostatecznego wezwania");
+			// $filter_arr['krd'] = array("do przekazania do KRD", 'desc'=>array("wezwanie ost. + 60", "wezwanie ost. + 60 dni"));
+			// $filter_arr['waiting-sad'] = array("przekazano do KRD");
+			// $filter_arr['docs-in-sad'] = array("przekazać sprawę do sądu");// waiting-sad = 30 dni
+			// $filter_arr['sad'] = array("przekazano sprawę do sądu");
+
+			// $filter_arr['3 m-ce przed'] = array("3 m-ce przed przedawnieniem");// 3 m-ce przed przedawnieniem
+			// $filter_arr['po-terminie'] = array("po terminie");// 3 lata po dacie platnosci faktur
+			// $filter_arr['has_nr_sad'] = array("nr sprawy sąd");
+			// $filter_arr['has_nr_komornik'] = array("nr sprawy komornik");
+			// $filter_arr['has_ustalenia'] = array("ustalenia z klientem");
+			// $filter_arr['sad_and_komornik'] = array("sąd z komornik");
+			// $filter_arr['sad_bez_komornik'] = array("sąd bez komornik");
+			// $filter_arr['isMovedToVectra'] = array("przeniesieni do Vectra");
+
+			// if ($filter_selected == 'po-terminie') {
+			// 	$sql_where_and_arr[] = "w.`PAY_SALDO`<=-0.05";
+			// 	$sql_where_and_arr[] = "w.`PAY_DATE`!='0000-00-00'";
+			// 	$sql_where_and_arr[] = "w.`PAY_DATE`<DATE_SUB(NOW(), INTERVAL 36 MONTH)";
+			// }
+			// else if ($filter_selected == '3 m-ce przed') {
+			// 	$sql_where_and_arr[] = "w.`PAY_SALDO`<=-0.05";
+			// 	$sql_where_and_arr[] = "w.`PAY_DATE`!='0000-00-00'";
+			// 	$sql_where_and_arr[] = "w.`PAY_DATE`<DATE_SUB(NOW(), INTERVAL 33 MONTH)";
+			// 	$sql_where_and_arr[] = "w.`PAY_DATE`>DATE_SUB(NOW(), INTERVAL 36 MONTH)";
+			// }
+			// else if ($filter_selected == 'tel1') {
+			// 	$sql_where_and_arr[] = "w.`PAY_SALDO`<=-0.05";
+			// 	$sql_where_and_arr[] = "w.`A_STATUS` in('wezwanie1', 'waiting-wezwanie2', 'wezwanie2', 'waiting-krd')";
+			// 	$sql_where_and_arr[] = "( w.`LAST_PHONE_STATUS_DATE`='0000-00-00'
+			// 		or w.`LAST_PHONE_STATUS_DATE`<DATE_SUB(NOW(), INTERVAL 3 MONTH) )";
+			// }
+			// else if ($filter_selected == 'bad_address') {
+			// 	$sql_where_and_arr[] = "w.`BAD_ADDRESS`>0";
+			// 	$sql_where_and_arr[] = "w.`PAY_SALDO`<=-0.05";
+			// }
+			// else if ($filter_selected == 'stan_zero') {
+			// 	$sql_where_and_arr[] = "w.`A_STATUS`='WAITING'";
+			// 	$sql_where_and_arr[] = "w.`PAY_SALDO`>-0.05";
+			// }
+			// else if ($filter_selected == '10-ego') {
+			// 	$sql_where_and_arr[] = "w.`A_STATUS`='WAITING'";
+			// 	$sql_where_and_arr[] = "w.`PAY_SALDO`<=-0.05";
+			// }
+			// else if ($filter_selected == 'has_nr_sad') {
+			// 	$sql_where_and_arr[] = "w.`NR_SPRAWY_SAD`!=''";
+			// }
+			// else if ($filter_selected == 'has_nr_komornik') {
+			// 	$sql_where_and_arr[] = "w.`NR_SPRAWY_KOMORNIK`!=''";
+			// }
+			// else if ($filter_selected == 'has_ustalenia') {
+			// 	$sql_where_and_arr[] = "w.`L_APPOITMENT_INFO`!=''";
+			// }
+			// else if ($filter_selected == 'sad_and_komornik') {
+			// 	$sql_where_and_arr[] = "w.`A_STATUS`='sad' and w.`NR_SPRAWY_KOMORNIK`!=''";
+			// }
+			// else if ($filter_selected == 'sad_bez_komornik') {
+			// 	$sql_where_and_arr[] = "w.`A_STATUS`='sad' and w.`NR_SPRAWY_KOMORNIK`=''";
+			// }
+			// else if ($filter_selected == 'isMovedToVectra') {
+			// 	$sql_where_and_arr[] = "w.`IS_MOVED_TO_VECTRA`=1";
+			// }
+			// else {
+			// 	$sql_where_and_arr[] = "w.`A_STATUS`='{$filter_selected}'";
+			// }
+
+			'Saldo' => $windykInfo['PAY_SALDO'],
+			'Termin ost. fv' => $windykInfo['PAY_DATE'], // Data wymagalności ostatniej faktury
+			'Zaległe faktury' => $windykInfo['PAY_FVAT'],
+			'Adresy usług' => $windykInfo['SERVICES_STREETS'],
+		];
+
+		return UI::h('div', [], [
+			UI::h('p', [ 'style' => "border-left:3px solid #ddd; padding-left:6px; font-weight:bold" ], [
+				"Informacje o płatnościach",
+				($windykInfo['A_STATUS_UPDATE_DATE'] < date("Y-m-d"))
+				?	UI::h('div', [ 'class' => "text-danger" ], [
+						"Uwaga: Wymagają aktualizacji",
+						" ",
+						UI::h('em', [ 'class' => "text-muted" ], "(dane z {$windykInfo['A_STATUS_UPDATE_DATE']})"),
+						// TODO: btn aktualizuj lub auto aktualizuj przed pokazaniem danych
+					])
+				:	"",
+			]),
+			UI::h('table', [ 'class' => "table table-bordered", 'style' => "width:auto; background:#fff" ],
+				array_map(function ($fieldName) use ($outWindykInfo) {
+				return UI::h('tr', [], [
+					UI::h('th', [], $fieldName),
+					UI::h('td', [], $outWindykInfo[$fieldName]),
+				]);
+				}, array_keys($outWindykInfo))
+			),
+			UI::h('table', [ 'class' => "table table-bordered", 'style' => "width:auto; display:none; background:yellow" ],
+				array_map(function ($fieldName) use ($windykInfo) {
+				return UI::h('tr', [], [
+					UI::h('th', [], $fieldName),
+					UI::h('td', [], $windykInfo[$fieldName]),
+				]);
+				}, array_keys($windykInfo))
+			),
+		]);
+	}
+
+
+
 	public static function user(&$user) {
 
 		$bad_address_task = V::get('bad_address', '', $_POST);
@@ -138,8 +370,8 @@ class Windykacja_View {
 			}
 		}
 
-		$company = Windykacja_StatsModel::get_company($user);
-		$nr_konta = Windykacja_FunkcjeL1::bankowy_formatuj_nrach(Windykacja_FunkcjeL1::bankowy_make_nrach($company->NR_RACH_MASS_PAY, $user->ID_BILLING_USERS, 0));
+		$company = Windykacja_StatsModel::getOwnerCompany($user->ID_BILLING_USERS);
+		$nr_konta = Windykacja_FunkcjeL1::bankowy_formatuj_nrach(Windykacja_FunkcjeL1::bankowy_make_nrach($company['NR_RACH_MASS_PAY'], $user->ID_BILLING_USERS, 0));
 
 		echo'<h3>';
 			echo' <a href="'."?MENU_INIT=USERS2_WINDYKACJA_STATUS&q=".V::get('q','', $_REQUEST)."&_p=".V::get('_p', '', $_REQUEST)."&_f=".V::get('_f', '', $_REQUEST)."&_oby=".V::get('_oby', '', $_REQUEST)."&_odir=".V::get('_odir', '', $_REQUEST).'">'."Klienci".'</a>';
@@ -1412,7 +1644,7 @@ class Windykacja_View {
 		}
 
 		$uslugi_l2 = Windykacja_StatsModel::get_uslugi_from_l2($user);
-		$umowy_l2 = Windykacja_StatsModel::get_umowy_from_l2($user);
+		$umowy_l2 = Windykacja_StatsModel::getClientUmowy($user->ID);
 
 		$uslugi_l2_nieprzypisane = array();
 		foreach ($uslugi_l2 as $k_id => $h) {
@@ -1644,7 +1876,7 @@ class Windykacja_View {
 		Lay_Html_Toggle::end();
 	}
 
-	public static function user_historia_platnosci(&$user) {
+	public static function user_historia_platnosci(&$user) { // TODO: mv to UserContact::viewUserPaymentContactsHistory
 		?>
 		<style type="text/css">
             .hide .to-hide{display:none;}
@@ -1656,10 +1888,10 @@ class Windykacja_View {
 		<?php
 		Lay_Html_Toggle::show_js();
 
-		$billing_docs = Windykacja_StatsModel::get_bill_dosc_by_date($user);
+		$billing_docs = Windykacja_StatsModel::getBillDocsByDate($user->ID);
 
 		// add events
-		$umowy_l2 = Windykacja_StatsModel::get_umowy_from_l2($user);
+		$umowy_l2 = Windykacja_StatsModel::getClientUmowy($user->ID);
 		//echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;">billing_docs ';print_r($billing_docs);echo'</pre>';
 		//echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;">billing_docs ';print_r(reset($billing_docs));echo'</pre>';
 		//echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;">umowy_l2 ';print_r($umowy_l2);echo'</pre>';
@@ -1673,27 +1905,24 @@ class Windykacja_View {
 			}
 		}
 
-		$user_hist_events = Windykacja_StatsHelper::get_user_hist_status_events($user);
+		$user_hist_events = Windykacja_StatsHelper::getUserHistStatusEvents($user->ID);
 		if (!empty($user_hist_events)) {
-			foreach ($user_hist_events as $v_hist) {
-				$bill_doc = (array)$v_hist;
-				$billing_docs->add_event($v_hist->A_STATUS_UPDATE_DATE, 'HIST_STATUS', $bill_doc);
+			foreach ($user_hist_events as $bill_doc) {
+				$billing_docs->add_event($bill_doc['A_STATUS_UPDATE_DATE'], 'HIST_STATUS', $bill_doc);
 			}
 		}
 
-		$user_hist_events = Windykacja_StatsHelper::get_user_hist_phone_events($user);
+		$user_hist_events = Windykacja_StatsHelper::getUserHistPhoneEvents($user->ID);
 		if (!empty($user_hist_events)) {
-			foreach ($user_hist_events as $v_hist) {
-				$bill_doc = (array)$v_hist;
-				$billing_docs->add_event(substr($v_hist->A_RECORD_UPDATE_DATE, 0, 10), 'HIST_PHONE', $bill_doc);
+			foreach ($user_hist_events as $bill_doc) {
+				$billing_docs->add_event(substr($bill_doc['A_RECORD_UPDATE_DATE'], 0, 10), 'HIST_PHONE', $bill_doc);
 			}
 		}
 
-		$user_hist_events = Windykacja_StatsHelper::get_user_bad_address_events($user);
+		$user_hist_events = Windykacja_StatsHelper::getUserBadAddressEvents($user->ID);
 		if (!empty($user_hist_events)) {
-			foreach ($user_hist_events as $v_hist) {
-				$bill_doc = (array)$v_hist;
-				$billing_docs->add_event(substr($v_hist->A_RECORD_UPDATE_DATE, 0, 10), 'HIST_BAD_ADDRESS', $bill_doc);
+			foreach ($user_hist_events as $bill_doc) {
+				$billing_docs->add_event(substr($bill_doc['A_RECORD_UPDATE_DATE'], 0, 10), 'HIST_BAD_ADDRESS', $bill_doc);
 			}
 		}
 
@@ -2247,7 +2476,7 @@ class Windykacja_View {
 		header("Content-Disposition: attachment; filename={$csvFileName}.csv");
 		$showCsvHeader = true;
 		foreach ($usersList as $userId => $user) {
-			$billing_docs = Windykacja_StatsModel::get_bill_dosc_by_date($user, $date_limit);
+			$billing_docs = Windykacja_StatsModel::getBillDocsByDate($user->ID, $date_limit);
 			$billing_docs->sort_docs();
 			$saldo = $billing_docs->get_saldo();
 			if ($saldo <= 0) {
@@ -2403,7 +2632,7 @@ class Windykacja_View {
 		header("Content-Disposition: attachment; filename={$csvFileName}.csv");
 		$showCsvHeader = true;
 		foreach ($usersList as $userId => $user) {
-			$billing_docs = Windykacja_StatsModel::get_bill_dosc_by_date($user, $date_limit);
+			$billing_docs = Windykacja_StatsModel::getBillDocsByDate($user->ID, $date_limit);
 			$billing_docs->sort_docs();
 			$fvat_arr = $billing_docs->get_unpaid_fvat();
 			Windykacja_StatsModel::update_doc_number($fvat_arr);
@@ -2484,7 +2713,7 @@ class Windykacja_View {
 
 	public static function wezwanie(&$user, $wezwanie_termin, $wezwanie_ostateczne = false) {
 		$date_limit = date("Y-m-d");
-		$billing_docs = Windykacja_StatsModel::get_bill_dosc_by_date($user, $date_limit);
+		$billing_docs = Windykacja_StatsModel::getBillDocsByDate($user->ID, $date_limit);
 
 		$billing_docs->sort_docs();
 
@@ -2535,9 +2764,9 @@ class Windykacja_View {
 
 			$razem = $saldo_all;
 
-			$company = Windykacja_StatsModel::get_company($user);
+			$company = Windykacja_StatsModel::getOwnerCompany($user->ID_BILLING_USERS);
 
-			$nr_konta = Windykacja_FunkcjeL1::bankowy_formatuj_nrach(Windykacja_FunkcjeL1::bankowy_make_nrach($company->NR_RACH_MASS_PAY, $user->ID_BILLING_USERS, 0));
+			$nr_konta = Windykacja_FunkcjeL1::bankowy_formatuj_nrach(Windykacja_FunkcjeL1::bankowy_make_nrach($company['NR_RACH_MASS_PAY'], $user->ID_BILLING_USERS, 0));
 
 		?>
 			<style type="text/css">
@@ -2561,7 +2790,7 @@ class Windykacja_View {
 			}
 		}
 		if ($id_koresp > 0) {//$user->ID_KORESP) {// TODO: if $user->LAST_ID_KORESP_WEZWANIE1 or LAST_ID_KORESP_WEZWANIE2
-			$koresp = DB::get_by_id('IN7_DZIENNIK_KORESP', $id_koresp);
+			$koresp = DB::getPDO()->fetchFirstAsObject(" select * from IN7_DZIENNIK_KORESP where ID = :id ", [ ':id' => $id_koresp ]);
 			if ($koresp) {
 				echo '<div style="text-align:right;font-weight:bold;">';
 					echo $koresp->ID_PROJECT . '-' .$koresp->ID . "/" . substr(date("Y"), 2);
@@ -2574,37 +2803,31 @@ class Windykacja_View {
 			<table border=0 cellspacing=0 cellpadding=0 style="width:100%;">
 				<tr>
 					<td style="width:60%;border:none;">
-						<?php echo $company->name1; ?>
-						<br /><?php echo "ul. " . $company->ulica . " " . $company->numer_dom; ?>
-						<br /><?php echo $company->kod . " " . $company->miasto; ?>
+						<?= $company['name1']; ?>
+						<br /><?= "ul. {$company['ulica']} {$company['numer_dom']}"; ?>
+						<br /><?= "{$company['kod']} {$company['miasto']}"; ?>
 					</td>
 					<td style="border:none;text-align:left;vertical-align:top;">
-						Gdańsk, dnia <?php echo date("Y-m-d"); ?>
+						Gdańsk, dnia <?= date("Y-m-d"); ?>
 					</td>
 				</tr>
 				<tr>
 					<td style="border:none;">&nbsp;</td>
 					<td style="border:none;">
 						<p style="margin:50px 0;">
-							Numer klienta: <?php echo $user->ID; ?>
-							<br /><?php echo "{$user->P_NAME} {$user->P_NAME_SECOND}"; ?>
+							Numer klienta: <?= $user->ID; ?>
+							<br /><?= "{$user->P_NAME} {$user->P_NAME_SECOND}"; ?>
                             <?php // TODO: P_ADRESS_KORESP_1282 ?>
-							<br /><?php echo "ul. {$user->P_ADDRESS_STREET} {$user->P_ADDRESS_HOUSE}"; ?>
+							<br /><?= "ul. {$user->P_ADDRESS_STREET} {$user->P_ADDRESS_HOUSE}"; ?>
 							<?php if ($user->P_ADDRESS_HOME) { echo "/{$user->P_ADDRESS_HOME}"; } ?>
-							<br /><?php echo "{$user->P_ADDRESS_POST_CODE} {$user->P_ADDRESS_CITY}"; ?>
+							<br /><?= "{$user->P_ADDRESS_POST_CODE} {$user->P_ADDRESS_CITY}"; ?>
 						</p>
 					</td>
 				</tr>
 			</table>
 
 			<h1 style="text-align:center;margin:20px 10px 10px 10px;font-size:28px;">
-				<?php
-				if ($wezwanie_ostateczne) {
-					echo "OSTATECZNE WEZWANIE DO ZAPŁATY";
-				} else {
-					echo "WEZWANIE DO ZAPŁATY";
-				}
-				?>
+				<?= ($wezwanie_ostateczne) ? "OSTATECZNE WEZWANIE DO ZAPŁATY" : "WEZWANIE DO ZAPŁATY"; ?>
 			</h1>
 			<p style="margin:10px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Na podstawie art. 476 Kodeksu cywilnego (Dz. U. z 1964 r. nr 16, poz. 93, z późn. zmianami) wzywamy do natychmiastowego uregulowania należnej sumy, zgodnie z poniższym zestawieniem.</p>
 
@@ -2624,7 +2847,7 @@ class Windykacja_View {
 				<tr>
 					<td colspan="4" style="border:none;"></td>
 					<th style="border-width:2px;border-color:#333;text-align:right;background:#F3F3F3;">Razem:</th>
-					<td style="border-width:2px;border-color:#333;font-weight:bold;"><?php echo Windykacja_FunkcjeL1::formatuj_grosze($razem); ?></td>
+					<td style="border-width:2px;border-color:#333;font-weight:bold;"><?= Windykacja_FunkcjeL1::formatuj_grosze($razem); ?></td>
 				</tr>
 			</tfoot>
 				<?php foreach ($out_tbl as $out_tr) {
@@ -2637,30 +2860,30 @@ class Windykacja_View {
 					//$file_total['PODSTAWA_DATA'] = date("Y-m-d",$r['BAF_TIMESTAMP']);
 					//$file_total['PAYMENT_TERM'] = date("Y-m-d",$r['TERMIN_PL']);
 					?>
-					<tr<?php echo $cls; ?>>
+					<tr<?= $cls; ?>>
 					<td>
-						<?php echo "Faktura Vat"; ?>
+						<?= "Faktura Vat"; ?>
 					</td>
 					<td>
-						<?php echo $out_tr['nr']; ?>
+						<?= $out_tr['nr']; ?>
 					</td>
 					<td>
-						<?php echo $out_tr['winien']; ?>
+						<?= $out_tr['winien']; ?>
 					</td>
 					<td>
-						<nobr><?php echo $out_tr['data']; ?></nobr>
+						<nobr><?= $out_tr['data']; ?></nobr>
 					</td>
 					<td>
-						<nobr><?php echo $out_tr['termin']; ?></nobr>
+						<nobr><?= $out_tr['termin']; ?></nobr>
 					</td>
 					<td>
-						<?php echo $out_tr['pozostalo']; ?>
+						<?= $out_tr['pozostalo']; ?>
 					</td>
 					</tr>
 				<?php } ?>
 			</table>
-			<p style="margin:10px;">Słownie do zapłaty: <span style="border-bottom:1px dotted #000;padding:0 50px;">&nbsp;&nbsp;<b><?php echo Windykacja_FunkcjeL1::slownie($razem); ?></b>&nbsp;&nbsp;</span></p>
-			<p style="margin:10px;background:#eee;text-align:center;">Wymienioną sumę prosimy przekazać na nasz rachunek bankowy <br /><?php echo $nr_konta; ?> w terminie do dnia <span style="border-bottom:1px dotted #000;padding:0 50px;">&nbsp;&nbsp;<b><?php echo $wezwanie_termin; ?></b>&nbsp;&nbsp;</span></p>
+			<p style="margin:10px;">Słownie do zapłaty: <span style="border-bottom:1px dotted #000;padding:0 50px;">&nbsp;&nbsp;<b><?= Windykacja_FunkcjeL1::slownie($razem); ?></b>&nbsp;&nbsp;</span></p>
+			<p style="margin:10px;background:#eee;text-align:center;">Wymienioną sumę prosimy przekazać na nasz rachunek bankowy <br /><?= $nr_konta; ?> w terminie do dnia <span style="border-bottom:1px dotted #000;padding:0 50px;">&nbsp;&nbsp;<b><?= $wezwanie_termin; ?></b>&nbsp;&nbsp;</span></p>
 			<ul style="margin:10px;font-size:small;padding:0 0 0 40px;">
 				<li style="line-height:16px;">Od nieterminowych płatności mogą zostać naliczone odsetki ustawowe (art.481 § 1 KC).</li>
 				<li style="line-height:16px;">W przypadku nieterminowej zapłaty nabywca zostanie obciążony wszelkimi kosztami windykacji oraz postępowania sądowego, które zostaną poniesione przez sprzedawcę w celu odzyskania należności.</li>
@@ -2742,7 +2965,7 @@ class Windykacja_View {
 				//echo $w->A_STATUS . ' (' . $w->A_STATUS_UPDATE_DATE . ')';
 				$user = Windykacja_StatsModel::get_user_by_id($w->ID_BILLING_USERS);
 				if ($user) {
-					$billing_docs = Windykacja_StatsModel::get_bill_dosc_by_date($user);
+					$billing_docs = Windykacja_StatsModel::getBillDocsByDate($user->ID);
 					Windykacja_StatsHelper::update_stats($user, $billing_docs);
 				}
 			//echo'</div>';// .box-blue
@@ -2792,15 +3015,15 @@ class Windykacja_View {
 	 * @params $id_koresp
 	 */
 	public static function task_bok_rozwiazanie_umowy_print($user, $id_koresp) {
-		$user_hist_events = Windykacja_StatsHelper::get_user_hist_status_events($user);
+		$user_hist_events = Windykacja_StatsHelper::getUserHistStatusEvents($user->ID);
 		if (empty($user_hist_events)) {
 			echo '<p style="color:red">' . "Brak danych HIST" . '</p>';
 			return;
 		}
 		$v_doc = null;
 		foreach ($user_hist_events as $v_hist) {
-			if ($v_hist->ID_KORESP == $id_koresp) {
-				$v_doc = $v_hist;
+			if ($v_hist['ID_KORESP'] == $id_koresp) {
+				$v_doc = (object)$v_hist;
 				break;
 			}
 		}
@@ -2816,7 +3039,7 @@ class Windykacja_View {
 			return;
 		}
 
-		$koresp = DB::get_by_id('IN7_DZIENNIK_KORESP', $id_koresp);
+		$koresp = DB::getPDO()->fetchFirstAsObject(" select * from IN7_DZIENNIK_KORESP where ID = :id ", [ ':id' => $id_koresp ]);
 		if (!$koresp) {
 			echo '<p style="color:red">' . "Koresp not exists!" . '</p>';
 			return;
@@ -2927,7 +3150,7 @@ class Windykacja_View {
             }
 		".'</script>';
 
-		$umowy_l2 = Windykacja_StatsModel::get_umowy_from_l2($user);
+		$umowy_l2 = Windykacja_StatsModel::getClientUmowy($user->ID);
 		if (empty($umowy_l2)) {
 			echo '<p style="color:red">' . "Brak aktualnych umów z klientem" . '</p>';
 			return;