api.whsales.php 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886
  1. <?php
  2. /**
  3. * Customizable warehouse items sales report
  4. */
  5. class WHSales {
  6. /**
  7. * Warehouse instance placeholder
  8. *
  9. * @var object
  10. */
  11. protected $warehouse = '';
  12. /**
  13. * System messages helper instance placeholder
  14. *
  15. * @var object
  16. */
  17. protected $messages = '';
  18. /**
  19. * Sub-reports database abstraction layer
  20. *
  21. * @var object
  22. */
  23. protected $reportsDb = '';
  24. /**
  25. * Sub-reports itemtypes abstraction layer
  26. *
  27. * @var object
  28. */
  29. protected $reportItemsDb = '';
  30. /**
  31. * Contains all available warehouse item types as id=>itemtypeData
  32. *
  33. * @var array
  34. */
  35. protected $allItemTypes = array();
  36. /**
  37. * Contains all available item type names as id=>itemTypeName
  38. *
  39. * @var array
  40. */
  41. protected $allItemTypeNames = array();
  42. /**
  43. * Contains all item types categories as itemtypeId=>categoryName
  44. *
  45. * @var array
  46. */
  47. protected $allItemCategories = array();
  48. /**
  49. * Contains all available sales sub-reports as id=>reportItemTypes[itemTypeId]=>recordId
  50. *
  51. * @var array
  52. */
  53. protected $allReports = array();
  54. /**
  55. * Contains all available sales sub-reports names as id=>name
  56. *
  57. * @var array
  58. */
  59. protected $allReportNames = array();
  60. /**
  61. * Contains year to render data
  62. *
  63. * @var int
  64. */
  65. protected $showYear = '';
  66. /**
  67. * Some predefined constants like routes, URLs, etc here
  68. */
  69. const TABLE_SUBREPORTS = 'wh_salesreports';
  70. const TABLE_REPORT_ITEMS = 'wh_salesitems';
  71. const RIGHT_EDIT = 'WAREHOUSEDIR';
  72. const URL_ME = '?module=whsales';
  73. const ROUTE_REPORT_RENDER = 'viewreport';
  74. const ROUTE_REPORT_EDIT = 'editreportid';
  75. const ROUTE_REPORT_DEL = 'deletereportid';
  76. const ROUTE_ITEM_DEL = 'deletereportitemid';
  77. const PROUTE_NEWREPORT = 'newreportname';
  78. const PROUTE_EDITREPORTNAME = 'editreportname';
  79. const PROUTE_NEWREPORTITEM = 'addnewitemtoreportid';
  80. const PROUTE_NEWREPORTITEMID = 'addthisitemtoreport';
  81. const PROUTE_YEAR = 'settargetyear';
  82. public function __construct() {
  83. $this->initMessages();
  84. $this->setYear();
  85. $this->initWarehouse();
  86. $this->initReportsDb();
  87. $this->initReportsItemsDb();
  88. $this->loadItemTypes();
  89. $this->loadReports();
  90. }
  91. /**
  92. * Inits warehouse instance for further usage
  93. *
  94. * @return void
  95. */
  96. protected function initWarehouse() {
  97. $this->warehouse = new Warehouse();
  98. }
  99. /**
  100. * Inits message helper
  101. *
  102. * @return void
  103. */
  104. protected function initMessages() {
  105. $this->messages = new UbillingMessageHelper();
  106. }
  107. /**
  108. * Inits sub-reports database layer
  109. *
  110. * @return void
  111. */
  112. protected function initReportsDb() {
  113. $this->reportsDb = new NyanORM(self::TABLE_SUBREPORTS);
  114. }
  115. /**
  116. * Sets current instance target year
  117. *
  118. * @return void
  119. */
  120. protected function setYear() {
  121. if (ubRouting::checkPost(self::PROUTE_YEAR)) {
  122. $this->showYear = ubRouting::post(self::PROUTE_YEAR, 'int');
  123. } else {
  124. $this->showYear = curyear();
  125. }
  126. }
  127. /**
  128. * Inits sub-reports database layer
  129. *
  130. * @return void
  131. */
  132. protected function initReportsItemsDb() {
  133. $this->reportItemsDb = new NyanORM(self::TABLE_REPORT_ITEMS);
  134. }
  135. /**
  136. * Loads all existing itemtypes and categories from warehouse
  137. *
  138. * @return void
  139. */
  140. protected function loadItemTypes() {
  141. $this->allItemTypes = $this->warehouse->getAllItemTypes();
  142. $categoriesTmp = $this->warehouse->getAllItemCategories();
  143. if (!empty($this->allItemTypes)) {
  144. foreach ($this->allItemTypes as $io => $each) {
  145. $this->allItemTypeNames[$each['id']] = $each['name'];
  146. if (isset($categoriesTmp[$each['categoryid']])) {
  147. $this->allItemCategories[$each['id']] = $categoriesTmp[$each['categoryid']];
  148. }
  149. }
  150. }
  151. }
  152. /**
  153. * Loads all existing reports
  154. *
  155. * @return void
  156. */
  157. protected function loadReports() {
  158. $tmpReportNames = $this->reportsDb->getAll();
  159. if (!empty($tmpReportNames)) {
  160. foreach ($tmpReportNames as $io => $each) {
  161. $this->allReportNames[$each['id']] = $each['name'];
  162. $this->allReports[$each['id']] = array();
  163. }
  164. }
  165. $tmpReportTypes = $this->reportItemsDb->getAll();
  166. if (!empty($tmpReportTypes)) {
  167. foreach ($tmpReportTypes as $io => $each) {
  168. $this->allReports[$each['reportid']][$each['itemtypeid']] = $each['id'];
  169. }
  170. }
  171. }
  172. /**
  173. * Renders available sub-reports list with some controls
  174. *
  175. * @return string
  176. */
  177. public function renderReportsList() {
  178. $result = '';
  179. if (!empty($this->allReportNames)) {
  180. $cells = wf_TableCell(__('Report'));
  181. if (cfr(self::RIGHT_EDIT)) {
  182. $cells .= wf_TableCell(__('Actions'));
  183. }
  184. $rows = wf_TableRow($cells, 'row1');
  185. foreach ($this->allReportNames as $eachId => $eachReportName) {
  186. $cells = wf_TableCell(wf_Link(self::URL_ME . '&' . self::ROUTE_REPORT_RENDER . '=' . $eachId, $eachReportName));
  187. if (cfr(self::RIGHT_EDIT)) {
  188. $delUrl = self::URL_ME . '&' . self::ROUTE_REPORT_DEL . '=' . $eachId;
  189. $editUrl = self::URL_ME . '&' . self::ROUTE_REPORT_EDIT . '=' . $eachId;
  190. $actControls = wf_JSAlert($delUrl, web_delete_icon(), $this->messages->getDeleteAlert()) . ' ';
  191. $actControls .= wf_Link($editUrl, web_edit_icon());
  192. $cells .= wf_TableCell($actControls);
  193. }
  194. $rows .= wf_TableRow($cells, 'row5');
  195. }
  196. $result .= wf_TableBody($rows, '100%', 0, 'sortable');
  197. } else {
  198. $result .= $this->messages->getStyledMessage(__('Nothing to show'), 'warning');
  199. }
  200. return($result);
  201. }
  202. /**
  203. * Creates new sales sub-report in database
  204. *
  205. * @param string $name
  206. *
  207. * @return void/string
  208. */
  209. public function createReport($name) {
  210. $nameF = ubRouting::filters($name, 'mres');
  211. $result = '';
  212. if (!empty($nameF)) {
  213. $this->reportsDb->data('name', $nameF);
  214. $this->reportsDb->create();
  215. $newId = $this->reportsDb->getLastId();
  216. log_register('WHSALES CREATE REPORT `' . $name . '` AS [' . $newId . ']');
  217. } else {
  218. $result .= __('Name') . ' ' . __('is empty');
  219. }
  220. return($result);
  221. }
  222. /**
  223. * Renames sales sub-report in database
  224. *
  225. * @param int $reportId
  226. * @param string $name
  227. *
  228. * @return void/string
  229. */
  230. public function renameReport($reportId, $name) {
  231. $reportId = ubRouting::filters($reportId, 'int');
  232. $nameF = ubRouting::filters($name, 'mres');
  233. $result = '';
  234. if (!empty($nameF) AND ! empty($reportId)) {
  235. $this->reportsDb->where('id', '=', $reportId);
  236. $this->reportsDb->data('name', $nameF);
  237. $this->reportsDb->save();
  238. log_register('WHSALES RENAME REPORT `' . $name . '` AS [' . $reportId . ']');
  239. } else {
  240. $result .= __('Name') . ' ' . __('is empty');
  241. }
  242. return($result);
  243. }
  244. /**
  245. * Deletes existing report from database
  246. *
  247. * @param int $reportId
  248. *
  249. * @return void/error
  250. */
  251. public function deleteReport($reportId) {
  252. $reportId = ubRouting::filters($reportId, 'int');
  253. $result = '';
  254. if (!empty($reportId)) {
  255. if (isset($this->allReportNames[$reportId])) {
  256. $reportName = $this->allReportNames[$reportId];
  257. //flushing report
  258. $this->reportsDb->where('id', '=', $reportId);
  259. $this->reportsDb->delete();
  260. //flushing itemtypes
  261. $this->reportItemsDb->where('reportid', '=', $reportId);
  262. $this->reportItemsDb->delete();
  263. log_register('WHSALES DELETE REPORT `' . $reportName . '` AS [' . $reportId . ']');
  264. } else {
  265. $result .= __('Report') . ' ' . __('ID') . ' [' . $reportId . '] ' . __('Not exists');
  266. }
  267. } else {
  268. $result .= __('Report') . ' ' . __('ID') . ' ' . __('is empty');
  269. }
  270. return($result);
  271. }
  272. /**
  273. * Renders new report creation form
  274. *
  275. * @return string
  276. */
  277. public function renderCreationForm() {
  278. $result = '';
  279. if (cfr(self::RIGHT_EDIT)) {
  280. $inputs = wf_TextInput(self::PROUTE_NEWREPORT, __('Name'), '', false, 20);
  281. $inputs .= wf_Submit(__('Create'));
  282. $form = wf_Form('', 'POST', $inputs, 'glamour');
  283. $result .= wf_modalAuto(web_icon_create(__('Create new report')), __('Create new report'), $form);
  284. }
  285. return($result);
  286. }
  287. /**
  288. * Renders form for addition some new item type to existing report
  289. *
  290. * @param int $reportId
  291. *
  292. * @return string
  293. */
  294. protected function renderItemTypeAddForm($reportId) {
  295. $result = '';
  296. $itemsAvail = $this->allItemTypeNames;
  297. if (isset($this->allReports[$reportId])) {
  298. //report exists?
  299. foreach ($this->allReports[$reportId] as $eachItemTypeId => $eachRecordId) {
  300. if (isset($itemsAvail[$eachItemTypeId])) {
  301. //already in report
  302. unset($itemsAvail[$eachItemTypeId]);
  303. }
  304. }
  305. if (!empty($itemsAvail)) {
  306. $itemsSelector = array();
  307. //appending category to selector
  308. foreach ($itemsAvail as $eachItemTypeId => $eachItemTypeName) {
  309. $itemCategory = (isset($this->allItemCategories[$eachItemTypeId])) ? $this->allItemCategories[$eachItemTypeId] . ' ' : '';
  310. $itemsSelector[$eachItemTypeId] = $itemCategory . $eachItemTypeName;
  311. }
  312. $inputs = wf_HiddenInput(self::PROUTE_NEWREPORTITEM, $reportId);
  313. $inputs .= wf_SelectorSearchable(self::PROUTE_NEWREPORTITEMID, $itemsSelector, __('Warehouse item type'), '', false) . ' ';
  314. $inputs .= wf_Submit(__('Append'));
  315. $result .= wf_Form('', 'POST', $inputs, 'glamour');
  316. }
  317. }
  318. return($result);
  319. }
  320. /**
  321. * Returns item type name by its ID if it exists
  322. *
  323. * @param int $itemTypeId
  324. *
  325. * @return string
  326. */
  327. protected function getItemName($itemTypeId) {
  328. $result = '';
  329. if (isset($this->allItemTypeNames[$itemTypeId])) {
  330. $result = $this->allItemTypeNames[$itemTypeId];
  331. }
  332. return($result);
  333. }
  334. /**
  335. * Deletes some itemtype record ID from database
  336. *
  337. * @param int $reportId
  338. * @param int $itemRecordId
  339. *
  340. * @return void
  341. */
  342. public function deleteReportItem($reportId, $itemRecordId) {
  343. $reportId = ubRouting::filters($reportId, 'int');
  344. $itemRecordId = ubRouting::filters($itemRecordId, 'int');
  345. $this->reportItemsDb->where('id', '=', $itemRecordId);
  346. $this->reportItemsDb->delete();
  347. log_register('WHSALES DELETE REPORT [' . $reportId . '] ITEMRECID [' . $itemRecordId . ']');
  348. }
  349. /**
  350. * Appends some itemtype record to existing report
  351. *
  352. * @param int $reportId
  353. * @param int $itemTypeId
  354. *
  355. * @return void/string on error
  356. */
  357. public function addReportItem($reportId, $itemTypeId) {
  358. $reportId = ubRouting::filters($reportId, 'int');
  359. $itemTypeId = ubRouting::filters($itemTypeId, 'int');
  360. $result = '';
  361. if (isset($this->allReports[$reportId])) {
  362. if (isset($this->allItemTypes[$itemTypeId])) {
  363. $this->reportItemsDb->data('reportid', $reportId);
  364. $this->reportItemsDb->data('itemtypeid', $itemTypeId);
  365. $this->reportItemsDb->create();
  366. $newRecId = $this->reportItemsDb->getLastId();
  367. log_register('WHSALES ADD REPORT [' . $reportId . '] ITEMTYPE [' . $itemTypeId . '] AS ITEMRECID [' . $newRecId . ']');
  368. }
  369. }
  370. return($result);
  371. }
  372. /**
  373. * Renders report rename form
  374. *
  375. * @param int $reportId
  376. *
  377. * @return string
  378. */
  379. protected function renderRenameForm($reportId) {
  380. $result = '';
  381. $reportId = ubRouting::filters($reportId, 'int');
  382. if (isset($this->allReports[$reportId])) {
  383. $inputs = wf_TextInput(self::PROUTE_EDITREPORTNAME, __('Name'), $this->getReportName($reportId), false, 20);
  384. $inputs .= wf_Submit(__('Save'));
  385. $result .= wf_Form('', 'POST', $inputs, 'glamour');
  386. }
  387. return($result);
  388. }
  389. /**
  390. * Renders existing report editing form
  391. *
  392. * @param int $reportId
  393. *
  394. * @return string
  395. */
  396. public function renderEditForm($reportId) {
  397. $reportId = ubRouting::filters($reportId, 'int');
  398. $result = '';
  399. if (isset($this->allReports[$reportId])) {
  400. $reportItemTypes = $this->allReports[$reportId];
  401. //rename form
  402. $result .= $this->renderRenameForm($reportId);
  403. $result .= wf_delimiter(0);
  404. if (!empty($this->allItemTypes)) {
  405. //list of itemtypes in report
  406. if (!empty($reportItemTypes)) {
  407. $cells = wf_TableCell(__('Category'));
  408. $cells .= wf_TableCell(__('Warehouse item type'));
  409. $cells .= wf_TableCell(__('Actions'));
  410. $rows = wf_TableRow($cells, 'row1');
  411. foreach ($reportItemTypes as $eachItemTypeId => $eachItmRecordId) {
  412. $eachItemCategory = (isset($this->allItemCategories[$eachItemTypeId])) ? $this->allItemCategories[$eachItemTypeId] : '';
  413. $cells = wf_TableCell($eachItemCategory);
  414. $cells .= wf_TableCell($this->getItemName($eachItemTypeId));
  415. $delUrl = self::URL_ME . '&' . self::ROUTE_REPORT_EDIT . '=' . $reportId . '&' . self::ROUTE_ITEM_DEL . '=' . $eachItmRecordId;
  416. $actLinks = wf_JSAlert($delUrl, web_delete_icon(), $this->messages->getDeleteAlert());
  417. $cells .= wf_TableCell($actLinks);
  418. $rows .= wf_TableRow($cells, 'row5');
  419. }
  420. $result .= wf_TableBody($rows, '100%', 0, 'sortable');
  421. } else {
  422. $result .= $this->messages->getStyledMessage(__('Report doesnt contain any item types'), 'info');
  423. }
  424. //append form
  425. $result .= wf_delimiter(0);
  426. $result .= $this->renderItemTypeAddForm($reportId);
  427. } else {
  428. $result .= $this->messages->getStyledMessage(__('Warehouse item types') . ' ' . __('Not found'), 'warning');
  429. }
  430. } else {
  431. $result .= $this->messages->getStyledMessage(__('Report') . ' ' . __('ID') . ' [' . $reportId . '] ' . __('Not exists'), 'error');
  432. }
  433. return($result);
  434. }
  435. /**
  436. * Returns existing report name by its ID
  437. *
  438. * @return string
  439. */
  440. public function getReportName($reportId) {
  441. $reportId = ubRouting::filters($reportId, 'int');
  442. $result = '';
  443. if (isset($this->allReportNames[$reportId])) {
  444. $result .= $this->allReportNames[$reportId];
  445. }
  446. return($result);
  447. }
  448. /**
  449. * Removes from outcomes non rendered years, move operations, not report itemtypes, etc
  450. *
  451. * @param array $allOutcomes
  452. * @param array $reportItemIds
  453. *
  454. * @return array
  455. */
  456. protected function filterOutcomes($allOutcomes, $reportItemIds) {
  457. $result = array();
  458. $yearMask = $this->showYear . '-';
  459. if (!empty($allOutcomes)) {
  460. foreach ($allOutcomes as $io => $each) {
  461. if (isset($reportItemIds[$each['itemtypeid']])) {
  462. //ignore storage movements, mistakes or cancellations
  463. if ($each['desttype'] != 'storage' AND
  464. $each['desttype'] != 'mistake' AND
  465. $each['desttype'] != 'cancellation'AND
  466. ispos($each['date'], $yearMask)) {
  467. $result[$io] = $each;
  468. }
  469. }
  470. }
  471. }
  472. return($result);
  473. }
  474. /**
  475. * Renders year selector form
  476. *
  477. * @return string
  478. */
  479. protected function renderYearSelector() {
  480. $result = '';
  481. $inputs = wf_YearSelectorPreset(self::PROUTE_YEAR, __('Year'), false, ubRouting::post(self::PROUTE_YEAR)) . ' ';
  482. $inputs .= wf_Submit(__('Show'));
  483. $result .= wf_Form('', 'POST', $inputs, 'glamour');
  484. return($result);
  485. }
  486. /**
  487. * Returns selling stats by some itemTypeID from outcomes array
  488. *
  489. * @param string $fromDate
  490. * @param string $toDate
  491. * @param int $itemTypeId
  492. * @param array $allOutcomes
  493. *
  494. * @return array
  495. */
  496. protected function getItemTypeStat($fromDate, $toDate, $itemTypeId, $allOutcomes) {
  497. $result = array(
  498. 'count' => 0,
  499. 'price' => 0,
  500. 'summ' => 0
  501. );
  502. if (!empty($allOutcomes)) {
  503. foreach ($allOutcomes as $io => $each) {
  504. if ($each['itemtypeid'] == $itemTypeId) {
  505. if (zb_isDateBetween($fromDate, $toDate, $each['date'])) {
  506. $result['count'] += $each['count'];
  507. $result['price'] = $each['price'];
  508. $result['summ'] += ($each['price'] * $each['count']);
  509. }
  510. }
  511. }
  512. }
  513. return($result);
  514. }
  515. /**
  516. * Render sold items year chart
  517. *
  518. * @param array $allOutcomes
  519. *
  520. * @return string
  521. */
  522. protected function renderChartCount($allOutcomes) {
  523. $result = '';
  524. $chartData = array();
  525. $chartData[] = array(__('Month'), __('Count'));
  526. if (!empty($allOutcomes)) {
  527. $sellStats = array();
  528. $chartOptions = "
  529. 'focusTarget': 'category',
  530. 'hAxis': {
  531. 'color': 'none',
  532. 'baselineColor': 'none',
  533. },
  534. 'vAxis': {
  535. 'color': 'none',
  536. 'baselineColor': 'none',
  537. },
  538. 'curveType': 'function',
  539. 'pointSize': 3,
  540. 'crosshair': {
  541. trigger: 'none'
  542. },";
  543. foreach ($allOutcomes as $io => $each) {
  544. $monthNum = date("Y-m", strtotime($each['date']));
  545. if (isset($sellStats[$monthNum])) {
  546. $sellStats[$monthNum] += $each['count'];
  547. } else {
  548. $sellStats[$monthNum] = $each['count'];
  549. }
  550. }
  551. if (!empty($sellStats)) {
  552. foreach ($sellStats as $eachMonth => $monthStat) {
  553. $chartData[] = array($eachMonth, $monthStat);
  554. }
  555. }
  556. if (sizeof($chartData) > 1) {
  557. $result .= wf_gchartsLine($chartData, __('Count'), '100%;', '300px;', $chartOptions);
  558. }
  559. }
  560. return($result);
  561. }
  562. /**
  563. * Render sold items year profit chart
  564. *
  565. * @param array $allOutcomes
  566. *
  567. * @return string
  568. */
  569. protected function renderChartProfit($allOutcomes) {
  570. $result = '';
  571. $chartData = array();
  572. $chartData[] = array(__('Month'), __('Money'));
  573. if (!empty($allOutcomes)) {
  574. $sellStats = array();
  575. $chartOptions = "
  576. 'focusTarget': 'category',
  577. 'hAxis': {
  578. 'color': 'none',
  579. 'baselineColor': 'none',
  580. },
  581. 'vAxis': {
  582. 'color': 'none',
  583. 'baselineColor': 'none',
  584. },
  585. 'curveType': 'function',
  586. 'pointSize': 3,
  587. 'crosshair': {
  588. trigger: 'none'
  589. },";
  590. foreach ($allOutcomes as $io => $each) {
  591. $monthNum = date("Y-m", strtotime($each['date']));
  592. if (isset($sellStats[$monthNum])) {
  593. $sellStats[$monthNum] += ($each['price'] * $each['count']);
  594. } else {
  595. $sellStats[$monthNum] = ($each['price'] * $each['count']);
  596. }
  597. }
  598. if (!empty($sellStats)) {
  599. foreach ($sellStats as $eachMonth => $monthStat) {
  600. $chartData[] = array($eachMonth, $monthStat);
  601. }
  602. }
  603. if (sizeof($chartData) > 1) {
  604. $result .= wf_gchartsLine($chartData, __('Money'), '100%;', '300px;', $chartOptions);
  605. }
  606. }
  607. return($result);
  608. }
  609. /**
  610. * Renders existing sales report
  611. *
  612. * @param int $reportId
  613. *
  614. * @return string
  615. */
  616. public function renderReport($reportId) {
  617. $reportId = ubRouting::filters($reportId, 'int');
  618. $result = '';
  619. //default date intervals setting
  620. $dateCurrentDay = curdate();
  621. $dateMonthBegin = curmonth() . '-01';
  622. $dateMonthEnd = curmonth() . '-' . date("t");
  623. $dateWeekBegin = date("Y-m-d", strtotime('monday this week'));
  624. $dateWeekEnd = date("Y-m-d", strtotime('sunday this week'));
  625. $dateYearBegin = $this->showYear . '-01-01';
  626. $dateYearEnd = $this->showYear . '-12-31';
  627. //year selector here
  628. $result .= $this->renderYearSelector();
  629. $result .= wf_delimiter(0);
  630. if (isset($this->allReports[$reportId])) {
  631. //here itemtypeId=>midprice
  632. $midPrices = array();
  633. $reportItemIds = $this->allReports[$reportId];
  634. if (!empty($reportItemIds)) {
  635. foreach ($reportItemIds as $eachItemId => $eachRecId) {
  636. $eachItemMidPrice = $this->warehouse->getIncomeMiddlePrice($eachItemId);
  637. $midPrices[$eachItemId] = $eachItemMidPrice;
  638. }
  639. $allOutcomes = $this->warehouse->getAllOutcomes();
  640. $yearOutcomes = $this->filterOutcomes($allOutcomes, $reportItemIds);
  641. if (!empty($yearOutcomes)) {
  642. $sellStats = array(
  643. 'summarycount' => array(
  644. 'day' => 0,
  645. 'week' => 0,
  646. 'month' => 0,
  647. 'year' => 0,
  648. ),
  649. 'summaryprice' => array(
  650. 'day' => 0,
  651. 'week' => 0,
  652. 'month' => 0,
  653. 'year' => 0,
  654. ),
  655. );
  656. //sold item counts
  657. $cells = wf_TableCell(__('Warehouse item type'), '40%');
  658. $cells .= wf_TableCell(__('Day'), '15%');
  659. $cells .= wf_TableCell(__('Week'), '15%');
  660. $cells .= wf_TableCell(__('Month'), '15%');
  661. $cells .= wf_TableCell(__('Year'), '15%');
  662. $rows = wf_TableRow($cells, 'row1');
  663. foreach ($reportItemIds as $eachItemId => $eachRecId) {
  664. $sellStats['day'] = $this->getItemTypeStat($dateCurrentDay, $dateCurrentDay, $eachItemId, $yearOutcomes);
  665. $sellStats['week'] = $this->getItemTypeStat($dateWeekBegin, $dateWeekEnd, $eachItemId, $yearOutcomes);
  666. $sellStats['month'] = $this->getItemTypeStat($dateMonthBegin, $dateMonthEnd, $eachItemId, $yearOutcomes);
  667. $sellStats['year'] = $this->getItemTypeStat($dateYearBegin, $dateYearEnd, $eachItemId, $yearOutcomes);
  668. $sellStats['summarycount']['day'] += $sellStats['day']['count'];
  669. $sellStats['summarycount']['week'] += $sellStats['week']['count'];
  670. $sellStats['summarycount']['month'] += $sellStats['month']['count'];
  671. $sellStats['summarycount']['year'] += $sellStats['year']['count'];
  672. $cells = wf_TableCell($this->allItemTypeNames[$eachItemId]);
  673. $cells .= wf_TableCell($sellStats['day']['count']);
  674. $cells .= wf_TableCell($sellStats['week']['count']);
  675. $cells .= wf_TableCell($sellStats['month']['count']);
  676. $cells .= wf_TableCell($sellStats['year']['count']);
  677. $rows .= wf_TableRow($cells, 'row5');
  678. }
  679. $cells = wf_TableCell(wf_tag('b') . __('Total') . ' ' . __('pieces') . wf_tag('b', true));
  680. $cells .= wf_TableCell($sellStats['summarycount']['day']);
  681. $cells .= wf_TableCell($sellStats['summarycount']['week']);
  682. $cells .= wf_TableCell($sellStats['summarycount']['month']);
  683. $cells .= wf_TableCell($sellStats['summarycount']['year']);
  684. $rows .= wf_TableRow($cells, 'row2');
  685. $result .= wf_tag('h2') . __('Count') . wf_tag('h2', true);
  686. $result .= wf_TableBody($rows, '100%', 0, '');
  687. $result .= wf_delimiter(0);
  688. //sold items prices
  689. $cells = wf_TableCell(__('Warehouse item type'), '40%');
  690. $cells .= wf_TableCell(__('Day'), '15%');
  691. $cells .= wf_TableCell(__('Week'), '15%');
  692. $cells .= wf_TableCell(__('Month'), '15%');
  693. $cells .= wf_TableCell(__('Year'), '15%');
  694. $rows = wf_TableRow($cells, 'row1');
  695. foreach ($reportItemIds as $eachItemId => $eachRecId) {
  696. $sellStats['day'] = $this->getItemTypeStat($dateCurrentDay, $dateCurrentDay, $eachItemId, $yearOutcomes);
  697. $sellStats['week'] = $this->getItemTypeStat($dateWeekBegin, $dateWeekEnd, $eachItemId, $yearOutcomes);
  698. $sellStats['month'] = $this->getItemTypeStat($dateMonthBegin, $dateMonthEnd, $eachItemId, $yearOutcomes);
  699. $sellStats['year'] = $this->getItemTypeStat($dateYearBegin, $dateYearEnd, $eachItemId, $yearOutcomes);
  700. $sellStats['summaryprice']['day'] += $sellStats['day']['summ'];
  701. $sellStats['summaryprice']['week'] += $sellStats['week']['summ'];
  702. $sellStats['summaryprice']['month'] += $sellStats['month']['summ'];
  703. $sellStats['summaryprice']['year'] += $sellStats['year']['summ'];
  704. $cells = wf_TableCell($this->allItemTypeNames[$eachItemId]);
  705. $cells .= wf_TableCell($sellStats['day']['summ']);
  706. $cells .= wf_TableCell($sellStats['week']['summ']);
  707. $cells .= wf_TableCell($sellStats['month']['summ']);
  708. $cells .= wf_TableCell(round($sellStats['year']['summ']));
  709. $rows .= wf_TableRow($cells, 'row5');
  710. }
  711. $cells = wf_TableCell(wf_tag('b') . __('Total') . ' ' . __('money') . wf_tag('b', true));
  712. $cells .= wf_TableCell($sellStats['summaryprice']['day']);
  713. $cells .= wf_TableCell($sellStats['summaryprice']['week']);
  714. $cells .= wf_TableCell($sellStats['summaryprice']['month']);
  715. $cells .= wf_TableCell(zb_CashBigValueFormat(round($sellStats['summaryprice']['year'])));
  716. $rows .= wf_TableRow($cells, 'row2');
  717. $result .= wf_tag('h2') . __('Money') . wf_tag('h2', true);
  718. $result .= wf_TableBody($rows, '100%', 0, '');
  719. $result .= wf_delimiter(0);
  720. //profit prediction
  721. $cells = wf_TableCell(__('Warehouse item type'), '40%');
  722. $cells .= wf_TableCell(__('Day'), '15%');
  723. $cells .= wf_TableCell(__('Week'), '15%');
  724. $cells .= wf_TableCell(__('Month'), '15%');
  725. $cells .= wf_TableCell(__('Year'), '15%');
  726. $rows = wf_TableRow($cells, 'row1');
  727. $sellStats = array(
  728. 'summarycount' => array(
  729. 'day' => 0,
  730. 'week' => 0,
  731. 'month' => 0,
  732. 'year' => 0,
  733. ),
  734. 'summaryprice' => array(
  735. 'day' => 0,
  736. 'week' => 0,
  737. 'month' => 0,
  738. 'year' => 0,
  739. ),
  740. );
  741. $profitStats = array(
  742. 'day' => 0,
  743. 'week' => 0,
  744. 'month' => 0,
  745. 'year' => 0,
  746. 'sumday' => 0,
  747. 'sumweek' => 0,
  748. 'summonth' => 0,
  749. 'sumyear' => 0,
  750. );
  751. foreach ($reportItemIds as $eachItemId => $eachRecId) {
  752. $sellStats['day'] = $this->getItemTypeStat($dateCurrentDay, $dateCurrentDay, $eachItemId, $yearOutcomes);
  753. $sellStats['week'] = $this->getItemTypeStat($dateWeekBegin, $dateWeekEnd, $eachItemId, $yearOutcomes);
  754. $sellStats['month'] = $this->getItemTypeStat($dateMonthBegin, $dateMonthEnd, $eachItemId, $yearOutcomes);
  755. $sellStats['year'] = $this->getItemTypeStat($dateYearBegin, $dateYearEnd, $eachItemId, $yearOutcomes);
  756. $sellStats['summarycount']['day'] += $sellStats['day']['count'];
  757. $sellStats['summarycount']['week'] += $sellStats['week']['count'];
  758. $sellStats['summarycount']['month'] += $sellStats['month']['count'];
  759. $sellStats['summarycount']['year'] += $sellStats['year']['count'];
  760. $sellStats['summaryprice']['day'] += $sellStats['day']['summ'];
  761. $sellStats['summaryprice']['week'] += $sellStats['week']['summ'];
  762. $sellStats['summaryprice']['month'] += $sellStats['month']['summ'];
  763. $sellStats['summaryprice']['year'] += $sellStats['year']['summ'];
  764. $profitStats['day'] = $sellStats['day']['summ'] - ($sellStats['day']['count'] * $midPrices[$eachItemId]);
  765. $profitStats['week'] = $sellStats['week']['summ'] - ($sellStats['week']['count'] * $midPrices[$eachItemId]);
  766. $profitStats['month'] = $sellStats['month']['summ'] - ($sellStats['month']['count'] * $midPrices[$eachItemId]);
  767. $profitStats['year'] = $sellStats['year']['summ'] - ($sellStats['year']['count'] * $midPrices[$eachItemId]);
  768. $profitStats['sumday'] += $profitStats['day'];
  769. $profitStats['sumweek'] += $profitStats['week'];
  770. $profitStats['summonth'] += $profitStats['month'];
  771. $profitStats['sumyear'] += $profitStats['year'];
  772. $cells = wf_TableCell($this->allItemTypeNames[$eachItemId] . ' (' . __('middle price') . ' ' . $midPrices[$eachItemId] . ')');
  773. $cells .= wf_TableCell($profitStats['day']);
  774. $cells .= wf_TableCell($profitStats['week']);
  775. $cells .= wf_TableCell($profitStats['month']);
  776. $cells .= wf_TableCell(round($profitStats['year']));
  777. $rows .= wf_TableRow($cells, 'row5');
  778. }
  779. $cells = wf_TableCell(wf_tag('b') . __('Total') . ' ' . __('Profit') . ' ~' . wf_tag('b', true));
  780. $cells .= wf_TableCell($profitStats['sumday']);
  781. $cells .= wf_TableCell($profitStats['sumweek']);
  782. $cells .= wf_TableCell($profitStats['summonth']);
  783. $cells .= wf_TableCell(zb_CashBigValueFormat(round($profitStats['sumyear'])));
  784. $rows .= wf_TableRow($cells, 'row2');
  785. $result .= wf_tag('h2') . __('Profit') . wf_tag('h2', true);
  786. $result .= wf_TableBody($rows, '100%', 0, '');
  787. $result .= wf_delimiter(0);
  788. //some charts here
  789. $result .= $this->renderChartCount($yearOutcomes);
  790. $result .= $this->renderChartProfit($yearOutcomes);
  791. } else {
  792. $result .= $this->messages->getStyledMessage(__('Nothing to show'), 'info');
  793. }
  794. } else {
  795. $result .= $this->messages->getStyledMessage(__('Report doesnt contain any item types'), 'info');
  796. }
  797. } else {
  798. $result .= $this->messages->getStyledMessage(__('Report') . ' ' . __('ID') . ' [' . $reportId . '] ' . __('Not exists'), 'error');
  799. }
  800. $result .= wf_delimiter(0);
  801. $result .= wf_BackLink(self::URL_ME);
  802. return($result);
  803. }
  804. }