ProjektyKosztorysBase.php 74 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792
  1. <?php
  2. Lib::loadClass('RouteBase');
  3. Lib::loadClass('ProjectKosztorysSchema');
  4. Lib::loadClass('ProjectKosztorysModel');
  5. Lib::loadClass('ProjectKosztorysCennik');
  6. Lib::loadClass('UI');
  7. Lib::loadClass('Response');
  8. class Route_ProjektyKosztorysBase extends RouteBase {// TODO: UrlActionBase @see Route_UrlAction
  9. public $_model = array();
  10. public function handleAuth() {
  11. if (!User::logged()) {
  12. User::authByRequest();
  13. }
  14. }
  15. public function ofertaAdminAction() {
  16. // TODO: check if user is allowed to run this action
  17. UI::gora();
  18. UI::menu();
  19. try {
  20. $idProject = V::get('ID_PROJECT', 0, $_REQUEST, 'int');
  21. $idCompany = V::get('ID_COMPANY', 0, $_REQUEST, 'int');
  22. $admin = true;
  23. $ofertaArgs = compact('idProject', 'idCompany', 'admin');
  24. $this->panel($idProject, $idCompany);
  25. if ($idProject > 0) {
  26. $this->oferta($ofertaArgs);
  27. } else {
  28. $this->defaultOferta();
  29. }
  30. } catch (Exception $e) {
  31. UI::alert('danger', "Error #" . $e->getCode() . "|" . $e->getLine() . ": " . $e->getMessage());
  32. }
  33. UI::dol();
  34. }
  35. public function ofertaCompanyAction() {
  36. // TODO: check if user is allowed to run this action
  37. UI::gora();
  38. UI::menu();
  39. try {
  40. $idProject = V::get('ID_PROJECT', 0, $_REQUEST, 'int');
  41. $idCompany = V::get('ID_COMPANY', 0, $_REQUEST, 'int');// TODO: $idCompany from ADMIN_USERS
  42. $admin = false;
  43. $companyAdmin = true;
  44. $ofertaArgs = compact('idProject', 'idCompany', 'admin', 'companyAdmin');
  45. $this->panel($idProject, $idCompany);
  46. if ($idProject > 0) {
  47. $this->oferta($ofertaArgs);
  48. } else {
  49. $this->defaultOferta();
  50. }
  51. } catch (Exception $e) {
  52. UI::alert('danger', "Error #" . $e->getCode() . "|" . $e->getLine() . ": " . $e->getMessage());
  53. }
  54. UI::dol();
  55. }
  56. public function ofertaDefaultAdminAction() {
  57. // TODO: check if user is allowed to run this action
  58. UI::gora();
  59. UI::menu();
  60. try {
  61. $idProject = 0;
  62. $idCompany = V::get('ID_COMPANY', 0, $_REQUEST, 'int');
  63. $this->panel($idProject, $idCompany);
  64. $this->defaultOferta();
  65. } catch (Exception $e) {
  66. UI::alert('danger', "Error #" . $e->getCode() . "|" . $e->getLine() . ": " . $e->getMessage());
  67. }
  68. UI::dol();
  69. }
  70. public function ofertaAction() {
  71. // TODO: check if user is allowed to run this action
  72. UI::gora();
  73. UI::menu();
  74. try {
  75. $idProject = V::get('ID_PROJECT', 0, $_REQUEST, 'int');
  76. $idCompany = V::get('ID_COMPANY', 0, $_REQUEST, 'int');
  77. $admin = false;
  78. if (!$idProject) throw new Exception("Wrong param in 'ID_PROJECT' - expected integer!");// TODO: show select box if not defined
  79. $ofertaArgs = compact('idProject', 'idCompany', 'admin');
  80. $this->panel($idProject, $idCompany);
  81. $this->oferta($ofertaArgs);
  82. } catch (Exception $e) {
  83. UI::alert('danger', "Error #" . $e->getCode() . "|" . $e->getLine() . ": " . $e->getMessage());
  84. }
  85. UI::dol();
  86. }
  87. public function getArgsList() {// TODO: override UrlActionBase::getArgsList action
  88. $args = array();
  89. $args[] = 'ID_PROJECT';
  90. return $args;
  91. }
  92. public function reinstallAction() {// TODO: mv to UrlActionBase
  93. $jsonData = new stdClass();
  94. $jsonData->type = 'success';
  95. $jsonData->msg = 'Gotowe';
  96. try {
  97. $this->reinstall();
  98. } catch (Exception $e) {
  99. $jsonData->type = 'danger';
  100. $jsonData->msg = $e->getMessage();
  101. }
  102. echo json_encode($jsonData);
  103. }
  104. public function reinstall() {// TODO: mv struct check to UrlActionBase
  105. $pdo = DB::getPDO();
  106. {
  107. $dropGDistanceFuncion = "DROP FUNCTION IF EXISTS `GDistance`";
  108. $pdo->exec($dropGDistanceFuncion);
  109. // Test for GDistance:
  110. // select '' as test, GDistance('') as GDistance, IF(GDistance('') = 0, 1, 0) as test_ok;
  111. // select 'NULL' as test, GDistance(NULL) as GDistance, IF(GDistance(NULL) = 0, 1, 0) as test_ok;
  112. // select 'GeomFromText(POLYGON((18.5573431614953 54.3472831082951,18.5612466579916 54.3460308284799,18.5617610722586 54.346524689865,18.5619728898979 54.3488528136092,18.5609743210268 54.3496376437764,18.5600057772984 54.3494578097971,18.559603951991 54.350742572617,18.5590637025025 54.3507194967965,18.5578575757622 54.349434823939,18.5573431614953 54.3472831082951)))' as test, GDistance(GeomFromText('POLYGON((18.5573431614953 54.3472831082951,18.5612466579916 54.3460308284799,18.5617610722586 54.346524689865,18.5619728898979 54.3488528136092,18.5609743210268 54.3496376437764,18.5600057772984 54.3494578097971,18.559603951991 54.350742572617,18.5590637025025 54.3507194967965,18.5578575757622 54.349434823939,18.5573431614953 54.3472831082951))')) as GDistance, IF(1 = GDistance(GeomFromText('POLYGON((18.5573431614953 54.3472831082951,18.5612466579916 54.3460308284799,18.5617610722586 54.346524689865,18.5619728898979 54.3488528136092,18.5609743210268 54.3496376437764,18.5600057772984 54.3494578097971,18.559603951991 54.350742572617,18.5590637025025 54.3507194967965,18.5578575757622 54.349434823939,18.5573431614953 54.3472831082951))')), 1, 0) as test_ok;
  113. // select 'GeomFromText(LINESTRING(18.5573431614953 54.3472831082951,18.5612466579916 54.3460308284799))' as test, GDistance(GeomFromText('LINESTRING(18.5573431614953 54.3472831082951,18.5612466579916 54.3460308284799)')) as GDistance, IF(GDistance(GeomFromText('LINESTRING(18.5573431614953 54.3472831082951,18.5612466579916 54.3460308284799)')) is not null, 1, 0) as test_ok;
  114. // select 'GeomFromText(POINT(18.5573431614953 54.3472831082951))' as test, GDistance(GeomFromText('POINT(18.5573431614953 54.3472831082951)')) as GDistance, IF(GDistance(GeomFromText('POINT(18.5573431614953 54.3472831082951)')) is not null, 1, 0) as test_ok;
  115. $gDistanceFuncion = <<<SQL_FUN
  116. CREATE DEFINER=`root`@`localhost` FUNCTION `GDistance`(`LS` LINESTRING) RETURNS double NO SQL
  117. BEGIN
  118. DECLARE LON_A, LAT_A, LON_B, LAT_B, R, RESULT DOUBLE;
  119. DECLARE A, B POINT;
  120. DECLARE I, N INT;
  121. -- if LS is not geometry type then return 0
  122. -- if GeometryType is not 'LINESTRING' then return 1
  123. -- if GeometryType is 'LINESTRING' then return length
  124. IF LS is null or GeometryType(LS) is null THEN
  125. RETURN 0;
  126. END IF;
  127. IF 'LINESTRING' != GeometryType(LS) THEN
  128. RETURN 1;
  129. END IF;
  130. SET R = 6372795.477598;
  131. SET N = NUMPOINTS(LS);
  132. IF N is null or N = 1 THEN
  133. RETURN 1;
  134. END IF;
  135. SET RESULT = 0;
  136. SET I = 1;
  137. WHILE I < N DO
  138. SET A = POINTN(LS, I);
  139. SET B = POINTN(LS, I + 1);
  140. SET LON_A = RADIANS(X(A));
  141. SET LAT_A = RADIANS(Y(A));
  142. SET LON_B = RADIANS(X(B));
  143. SET LAT_B = RADIANS(Y(B));
  144. SET RESULT = RESULT + ACOS(SIN(LAT_A) * SIN(LAT_B) + COS(LAT_A) * COS(LAT_B) * COS(LON_A - LON_B));
  145. SET I = I + 1;
  146. END WHILE;
  147. SET RESULT = RESULT * R;
  148. RETURN RESULT;
  149. END
  150. SQL_FUN;
  151. $pdo->exec($gDistanceFuncion);
  152. }
  153. /* required Zasoby tree structure - XML (parent rel in PARENT_ID field):
  154. <zasob:tree>
  155. <zasob:TYPESPECIALS>
  156. <zasob:URL_ACTION zasob:key=":action_id" zasob:desc=":url_action_name">
  157. <zasob:PARAM_IN zasob:key=":action_param_1_id" zasob:desc=":url_action_param_1_name"/>
  158. </zasob:URL_ACTION>
  159. </zasob:TYPESPECIALS>
  160. <zasob:BAZA_DANYCH zasob:key=":main_db_id" altername_types="DATABASE_MYSQL,DATABASE_POSTGRESQL">
  161. <zasob:TABELA zasob:key=":tbl_id" zasob:desc="IN7_MK_BAZA_DYSTRYBUCJI">
  162. <zasob:KOMORKA zasob:key=":cell_id" zasob:desc="ID"/>
  163. <zasob:URL_ACTION zasob:key=":link_action_id" zasob:desc=":url_action_name" zasob:alias_id=":action_id">
  164. <zasob:PARAM_IN zasob:key=":cell_id" zasob:desc="ID_PROJECT" zasob:alias_id=":cell_id"/>
  165. </zasob:URL_ACTION>
  166. </zasob:TABELA>
  167. </zasob:BAZA_DANYCH>
  168. </zasob:tree>
  169. */
  170. /* required Zasoby tree structure:
  171. - required base structure
  172. [:ts_main_id] TYPESPECIALS
  173. [:action_id] URL_ACTION :url_action_name
  174. [:action_param_1_id] PARAM_IN :url_action_param_1_name
  175. - current function from schema
  176. [:main_db_id] (DATABASE_MYSQL, BAZA_DANYCH, DATABASE_POSTGRESQL)
  177. [:tbl_id] TABELA 'IN7_MK_BAZA_DYSTRYBUCJI'
  178. [:cell_id] KOMORKA 'ID'
  179. [:link_action_id] (ALIAS DO :action_id) URL_ACTION :url_action_name
  180. [:link_param_id] (ALIAS DO :cell_id) PARAM_IN :url_action_param_1_name
  181. :url_action_name = 'ProjektyKosztyWstepnychRobot'
  182. :url_action_param_1_name = 'ID_PROJECT'
  183. */
  184. $flatConfig_main = array();
  185. {
  186. $flatConfig_main[] = (object)array(// Zasob::assert(TYPESPECIALS)
  187. 'query' => "
  188. select z.ID from CRM_LISTA_ZASOBOW z
  189. where z.TYPE='TYPESPECIALS'
  190. and z.A_STATUS not in('DELETED')
  191. ",
  192. 'createTable' => 'CRM_LISTA_ZASOBOW',
  193. 'createArgs' => array('TYPE' => 'TYPESPECIALS', 'DESC' => 'Typespecials'),
  194. 'out' => array(':ts_main_id' => 'ID')
  195. );
  196. $flatConfig_main[] = (object)array(// Zasob::assert(TYPESPECIALS/:url_action_name)
  197. 'query' => "
  198. select z.ID from CRM_LISTA_ZASOBOW z
  199. where z.PARENT_ID = :ts_main_id
  200. and z.TYPE = 'URL_ACTION'
  201. and z.DESC = :url_action_name
  202. and z.A_STATUS not in('DELETED')
  203. ",
  204. 'createTable' => 'CRM_LISTA_ZASOBOW',
  205. 'createArgs' => array('TYPE' => 'URL_ACTION', 'PARENT_ID' => ':ts_main_id', 'DESC' => ':url_action_name'),
  206. 'in' => array(':ts_main_id', ':url_action_name'),
  207. 'out' => array(':action_id' => 'ID')
  208. );
  209. $flatConfig_main[] = (object)array(// Zasob::assert(TYPESPECIALS/:url_action_name/:url_action_param_1_name)
  210. 'query' => "
  211. select z.ID from CRM_LISTA_ZASOBOW z
  212. where z.PARENT_ID = :action_id
  213. and z.TYPE = 'PARAM_IN'
  214. and z.DESC = :url_action_param_1_name
  215. and z.A_STATUS not in('DELETED')
  216. ",
  217. 'createTable' => 'CRM_LISTA_ZASOBOW',
  218. 'createArgs' => array('TYPE' => 'PARAM_IN', 'PARENT_ID' => ':action_id', 'DESC' => ':url_action_param_1_name'),
  219. 'in' => array(':action_id', ':url_action_param_1_name'),
  220. 'out' => array(':action_param_1_id' => 'ID')
  221. );
  222. }
  223. //DBG::_('DBG', '>1', "flatConfig_main", $flatConfig_main, __CLASS__, __FUNCTION__, __LINE__);
  224. $flatConfig_link_in_projekt = array();
  225. {
  226. $flatConfig_link_in_projekt[] = (object)array(// Zasob::assert(default_db)
  227. 'query' => "
  228. select z.ID from CRM_LISTA_ZASOBOW z
  229. where z.ID = :main_db_id
  230. and z.TYPE in('DATABASE_MYSQL', 'BAZA_DANYCH', 'DATABASE_POSTGRESQL')
  231. and z.A_STATUS not in('DELETED')
  232. ",
  233. 'createTable' => 'CRM_LISTA_ZASOBOW',
  234. 'createArgs' => array('TYPE' => 'BAZA_DANYCH', 'DESC' => 'Baza danych'),
  235. 'in' => array(':main_db_id'),
  236. 'out' => array(':main_db_id' => 'ID')
  237. );
  238. $flatConfig_link_in_projekt[] = (object)array(// Zasob::assert(default_db/IN7_MK_BAZA_DYSTRYBUCJI)
  239. 'query' => "
  240. select z.ID from CRM_LISTA_ZASOBOW z
  241. where z.PARENT_ID = :main_db_id
  242. and z.TYPE = 'TABELA'
  243. and z.DESC = 'IN7_MK_BAZA_DYSTRYBUCJI'
  244. and z.A_STATUS not in('DELETED')
  245. ",
  246. 'createTable' => 'CRM_LISTA_ZASOBOW',
  247. 'createArgs' => array('TYPE' => 'TABELA', 'PARENT_ID' => ':main_db_id', 'DESC' => 'IN7_MK_BAZA_DYSTRYBUCJI'),
  248. 'in' => array(':main_db_id'),
  249. 'out' => array(':tbl_id' => 'ID')
  250. );
  251. $flatConfig_link_in_projekt[] = (object)array(// Zasob::assert(default_db/IN7_MK_BAZA_DYSTRYBUCJI/ID)
  252. 'query' => "
  253. select z.ID from CRM_LISTA_ZASOBOW z
  254. where z.PARENT_ID = :tbl_id
  255. and z.TYPE = 'KOMORKA'
  256. and z.DESC = 'ID'
  257. and z.A_STATUS not in('DELETED')
  258. ",
  259. 'createTable' => 'CRM_LISTA_ZASOBOW',
  260. 'createArgs' => array('TYPE' => 'KOMORKA', 'PARENT_ID' => ':tbl_id', 'DESC' => 'ID'),
  261. 'in' => array(':tbl_id'),
  262. 'out' => array(':cell_id' => 'ID')
  263. );
  264. $flatConfig_link_in_projekt[] = (object)array(// Zasob::assert(default_db/IN7_MK_BAZA_DYSTRYBUCJI/:url_action_name)
  265. 'query' => "
  266. select z.ID from CRM_LISTA_ZASOBOW z
  267. where z.PARENT_ID = :tbl_id
  268. and z.ALIAS_ID = ':action_id'
  269. and z.TYPE = 'URL_ACTION'
  270. and z.DESC = ':url_action_name'
  271. and z.A_STATUS not in('DELETED')
  272. ",
  273. 'createTable' => 'CRM_LISTA_ZASOBOW',
  274. 'createArgs' => array('TYPE' => 'URL_ACTION', 'PARENT_ID' => ':tbl_id', 'ALIAS_ID' => ':action_id', 'DESC' => ':url_action_name'),
  275. 'in' => array(':tbl_id', ':action_id', ':url_action_name'),
  276. 'out' => array(':link_action_id' => 'ID')
  277. );
  278. // [:link_param_id] (ALIAS DO :cell_id) PARAM_IN :url_action_param_1_name
  279. $flatConfig_link_in_projekt[] = (object)array(// Zasob::assert(default_db/IN7_MK_BAZA_DYSTRYBUCJI/:url_action_name/:url_action_param_1_name)
  280. 'query' => "
  281. select z.ID from CRM_LISTA_ZASOBOW z
  282. where z.PARENT_ID = :link_action_id
  283. and z.ALIAS_ID = ':cell_id'
  284. and z.TYPE = 'PARAM_IN'
  285. and z.DESC = ':url_action_param_1_name'
  286. and z.A_STATUS not in('DELETED')
  287. ",
  288. 'createTable' => 'CRM_LISTA_ZASOBOW',
  289. 'createArgs' => array('TYPE' => 'PARAM_IN', 'PARENT_ID' => ':link_action_id', 'ALIAS_ID' => ':cell_id', 'DESC' => ':url_action_param_1_name'),
  290. 'in' => array(':cell_id', ':link_action_id', ':url_action_param_1_name'),
  291. 'out' => array(':link_action_id' => 'ID')
  292. );
  293. }
  294. //DBG::_('DBG', '>1', "flatConfig_link_in_projekt", $flatConfig_link_in_projekt, __CLASS__, __FUNCTION__, __LINE__);
  295. $flatConf = array_merge($flatConfig_main, $flatConfig_link_in_projekt);
  296. $knownArgs = array();
  297. $knownArgs[':url_action_name'] = 'Test';
  298. $knownArgs[':url_action_param_1_name'] = 'ID_PROJECT';
  299. $knownArgs[':main_db_id'] = '36';// from DB::getDB()->getZasobId(); or DB::getPDO()->getZasobId();
  300. $this->_debugFlatConfig($flatConf, $knownArgs);
  301. $args = $this->getArgsList();
  302. $clsName = __CLASS__;
  303. $urlActionName = str_replace('Route_UrlAction_', '', $clsName);
  304. DBG::_('DBG', '>1', "reinstall class", __CLASS__, __CLASS__, __FUNCTION__, __LINE__);
  305. DBG::_('DBG', '>1', "reinstall funName", $urlActionName, __CLASS__, __FUNCTION__, __LINE__);
  306. DBG::_('DBG', '>1', "reinstall test", $args, __CLASS__, __FUNCTION__, __LINE__);
  307. $dbFunction = $this->fetchZasobInfo();
  308. $usrLogin = User::getLogin();
  309. {// check if URL_ACTION already exists
  310. if (!$dbFunction) throw new Exception("Brak id zasobu typu TYPESPECIALS - TODO: CREATE");// $this->createZasobTypespecials();
  311. DBG::_('DBG', '>1', "dbFunction", $dbFunction, __CLASS__, __FUNCTION__, __LINE__);
  312. if ($dbFunction['action_id_is_null']) {
  313. $sth = $pdo->prepare("
  314. insert into CRM_LISTA_ZASOBOW (
  315. TYPE,
  316. PARENT_ID,
  317. `DESC`,
  318. A_RECORD_CREATE_AUTHOR,
  319. A_RECORD_CREATE_DATE
  320. )
  321. values (
  322. 'URL_ACTION',
  323. :ts_id,
  324. :url_action_name,
  325. 'system-by-{$usrLogin}',
  326. NOW()
  327. )
  328. ");
  329. //$sth->bindValue('ts_id', $dbFunction['ts_id'], PDO::PARAM_INT);
  330. //$sth->bindValue('url_action_name', $urlActionName, PDO::PARAM_STR);
  331. $bindValues = array();
  332. $bindValues['ts_id'] = array($dbFunction['ts_id'], PDO::PARAM_INT);
  333. $bindValues['url_action_name'] = $urlActionName;
  334. $pdo->bindValues($sth, $bindValues);
  335. DBG::_('DBG', '>1', "sql", $pdo->getRawSql($sth), __CLASS__, __FUNCTION__, __LINE__);
  336. $sth->execute();
  337. $dbFunction = $this->fetchZasobInfo();
  338. if (!$dbFunction || $dbFunction['action_id_is_null']) throw new Exception("Brak zasobu typu URL_ACTION, nie udało się go utworzyć!");
  339. }
  340. }
  341. {// check params
  342. if (!empty($args)) {
  343. $todoArgs = array();
  344. foreach ($args as $argName) {
  345. if (empty($dbFunction['url_params'])) {
  346. $todoArgs[$argName] = true;
  347. } else if (!array_key_exists($argName, $dbFunction['url_params'])) {
  348. $todoArgs[$argName] = true;
  349. }
  350. // OK PARAM_IN exists
  351. }
  352. $todoArgs = array_keys($todoArgs);
  353. DBG::_('DBG', '>1', "todoArgs", $todoArgs, __CLASS__, __FUNCTION__, __LINE__);
  354. if (!empty($todoArgs)) {
  355. $sqlValues = array();
  356. foreach ($todoArgs as $argName) {
  357. $sqlValues[] = "(
  358. 'PARAM_IN',
  359. {$dbFunction['action_id']},
  360. '{$argName}',
  361. 'system-by-{$usrLogin}',
  362. NOW()
  363. )
  364. ";
  365. }
  366. $sqlValues = implode(", ", $sqlValues);
  367. $sth = $pdo->prepare("
  368. insert into CRM_LISTA_ZASOBOW (
  369. TYPE,
  370. PARENT_ID,
  371. `DESC`,
  372. A_RECORD_CREATE_AUTHOR,
  373. A_RECORD_CREATE_DATE
  374. )
  375. values {$sqlValues}
  376. ");
  377. DBG::_('DBG', '>1', "sql", $pdo->getRawSql($sth), __CLASS__, __FUNCTION__, __LINE__);
  378. //$sth->execute();
  379. $dbFunction = $this->fetchZasobInfo();
  380. }
  381. if (empty($dbFunction['url_params'])) {
  382. throw new Exception("Brak zdefiniowanych parametrów, nie udało się ich utworzyć!");
  383. }
  384. }
  385. }
  386. {// check links in tables
  387. // $info['links']['IN7_MK_BAZA_DYSTRYBUCJI'] = $linkInfo;
  388. if (empty($dbFunction['links']['IN7_MK_BAZA_DYSTRYBUCJI'])) throw new Exception("Brak poprawne wprowadzonej tabeli 'IN7_MK_BAZA_DYSTRYBUCJI' w drzewie zasobów!");
  389. $projInfo = $dbFunction['links']['IN7_MK_BAZA_DYSTRYBUCJI'];
  390. /*
  391. [link_action_id] =>
  392. [db_id] => 36
  393. [tbl_id] => 636
  394. [cell_id] => 763
  395. [param1_id] =>
  396. */
  397. if (!$projInfo['link_action_id']) {
  398. $sth = $pdo->prepare("
  399. insert into CRM_LISTA_ZASOBOW (
  400. TYPE,
  401. PARENT_ID,
  402. ALIAS_ID,
  403. `DESC`,
  404. A_RECORD_CREATE_AUTHOR,
  405. A_RECORD_CREATE_DATE
  406. )
  407. values (
  408. 'URL_ACTION',
  409. {$projInfo['tbl_id']},
  410. {$dbFunction['action_id']},
  411. '{$urlActionName}',
  412. 'system-by-{$usrLogin}',
  413. NOW()
  414. )
  415. ");
  416. //DBG::_('DBG', '>1', "sql", $pdo->getRawSql($sth), __CLASS__, __FUNCTION__, __LINE__);
  417. $sth->execute();
  418. $dbFunction = $this->fetchZasobInfo();
  419. $projInfo = $dbFunction['links']['IN7_MK_BAZA_DYSTRYBUCJI'];
  420. if (!$projInfo['link_action_id']) throw new Exception("Brak zainstalowanej akcji dla tabeli 'IN7_MK_BAZA_DYSTRYBUCJI' - nie udało się zainstalować");
  421. }
  422. if (!$projInfo['param1_id']) {// TODO: get from params
  423. $sth = $pdo->prepare("
  424. insert into CRM_LISTA_ZASOBOW (
  425. TYPE,
  426. PARENT_ID,
  427. ALIAS_ID,
  428. `DESC`,
  429. A_RECORD_CREATE_AUTHOR,
  430. A_RECORD_CREATE_DATE
  431. )
  432. values (
  433. 'PARAM_IN',
  434. {$projInfo['link_action_id']},
  435. {$projInfo['cell_id']},
  436. 'ID_PROJECT',
  437. 'system-by-{$usrLogin}',
  438. NOW()
  439. )
  440. ");
  441. $sth->execute();
  442. $dbFunction = $this->fetchZasobInfo();
  443. $projInfo = $dbFunction['links']['IN7_MK_BAZA_DYSTRYBUCJI'];
  444. if (!$projInfo['param1_id']) throw new Exception("Brak zainstalowanego parametru 1 w akcji dla tabeli 'IN7_MK_BAZA_DYSTRYBUCJI' - nie udało się zainstalować");
  445. }
  446. }
  447. }
  448. public function _debugFlatConfig($flatConfig, $args = array()) {
  449. //DBG::_('DBG', '>1', "flatConfig", $flatConfig, __CLASS__, __FUNCTION__, __LINE__);
  450. echo '<pre style="border:1px solid green">';
  451. foreach ($flatConfig as $conf) {
  452. /*
  453. [query] => string
  454. [createTable] => srting - eg. CRM_LISTA_ZASOBOW
  455. [createArgs] => array - eg. [ TYPE: 'TYPESPECIALS', DESC: 'Typespecials' ]
  456. [in] => array - eg. [ ':ts_main_id', ':url_action_name' ]
  457. [out] => array - eg. [ ':ts_main_id': 'ID' ]
  458. */
  459. echo "Zasob::assert({$conf->createTable}): " . json_encode($conf->createArgs) . " returns: " . json_encode($conf->out) . "\n";
  460. }
  461. echo '</pre>';
  462. echo '<pre style="border:1px solid green">';
  463. echo "DBG: Simulate iter loop:\n";
  464. $simulateGeneratedId = 1000;
  465. $i = 0; $limit = 10; $todoIdx = array(); $knownArgsMap = array();
  466. foreach ($flatConfig as $idx => $conf) $todoIdx[] = $idx;
  467. foreach ($args as $arg => $val) $knownArgsMap[$arg] = $val;
  468. for ($i = 0; $i < $limit; $i++) {
  469. echo ">> DBG loop({$i}):\n";
  470. $isExecuted = false;
  471. foreach ($todoIdx as $idx) {
  472. $conf = $flatConfig[$idx];
  473. /*
  474. [query] => string
  475. [createTable] => srting - eg. CRM_LISTA_ZASOBOW
  476. [createArgs] => array - eg. [ TYPE: 'TYPESPECIALS', DESC: 'Typespecials' ]
  477. [in] => array - eg. [ ':ts_main_id', ':url_action_name' ]
  478. [out] => array - eg. [ ':ts_main_id': 'ID' ]
  479. */
  480. echo ">>>> Loop({$i}): idx({$idx}) Zasob::assert({$conf->createTable}): " . json_encode($conf->createArgs) . " returns: " . json_encode($conf->out) . "\n";
  481. $canExecute = true;
  482. if (!empty($conf->in)) foreach ($conf->in as $argName) {
  483. if (!array_key_exists($argName, $knownArgsMap)) {
  484. $canExecute = false;
  485. }
  486. }
  487. if ($canExecute) {
  488. // TODO: execute - $r = $this->_assertZasobConf($conf, $knownArgsMap);
  489. // fetch params out to $knownArgsMap
  490. foreach ($conf->out as $argName => $outFieldName) {
  491. $knownArgsMap[$argName] = $simulateGeneratedId++;// TODO: fetch from returned object ($r->{$outFieldName})
  492. }
  493. $todoIdx = array_diff($todoIdx, array($idx));// remove $idx from $todoIdx
  494. echo ">>>> Loop({$i}): knownArgsMap: " . json_encode($knownArgsMap) . " \n";
  495. $isExecuted = true;
  496. } else {
  497. echo ">>>> Loop({$i}): cannot execute conf [{$idx}] missing args: " . json_encode($conf->in) . " \n";
  498. }
  499. }
  500. if (!$isExecuted) {
  501. echo "DBG: Stop";
  502. if (empty($todoIdx)) {
  503. echo " - OK";
  504. } else {
  505. echo " - Error - TODO:\n";
  506. foreach ($todoIdx as $idx) {
  507. $conf = $flatConfig[$idx];
  508. echo "Zasob::assert({$conf->createTable}): " . json_encode($conf->createArgs) . " returns: " . json_encode($conf->out) . "\n";
  509. }
  510. }
  511. break;
  512. }
  513. }
  514. echo '</pre>';
  515. }
  516. public function fetchZasobInfo() {
  517. $pdo = DB::getPDO();
  518. $args = $this->getArgsList();
  519. $clsName = __CLASS__;
  520. $urlActionName = str_replace('Route_UrlAction_', '', $clsName);
  521. $sth = $pdo->prepare("
  522. select zp.ID as ts_id
  523. , IF(z.ID is null, 1, 0) as action_id_is_null
  524. , z.ID as action_id
  525. , z.DESC as action_desc
  526. from CRM_LISTA_ZASOBOW zp
  527. left join CRM_LISTA_ZASOBOW z on(z.PARENT_ID = zp.ID
  528. and z.TYPE = 'URL_ACTION'
  529. and z.DESC = :url_action_name
  530. and z.A_STATUS not in('DELETED')
  531. )
  532. where zp.TYPE = 'TYPESPECIALS'
  533. and zp.A_STATUS not in('DELETED')
  534. ");
  535. $sth->bindValue('url_action_name', $urlActionName);
  536. $sth->execute();
  537. $info = $sth->fetch();
  538. if (!$info) return $info;
  539. $info['url_params'] = array();
  540. $info['links'] = array();// where action is installed - expected `IN7_MK_BAZA_DYSTRYBUCJI`
  541. if ($info['action_id'] > 0) {
  542. $sthParams = $pdo->prepare("
  543. select z.ID as param_id
  544. , z.DESC as param_desc
  545. from CRM_LISTA_ZASOBOW z
  546. where z.TYPE = 'PARAM_IN'
  547. and z.A_STATUS not in('DELETED')
  548. and z.PARENT_ID = :url_action_id
  549. ");
  550. $sthParams->bindValue('url_action_id', $info['action_id']);
  551. $sthParams->execute();
  552. $urlParams = array();
  553. $rawUrlParams = $sthParams->fetchAll();
  554. foreach ($rawUrlParams as $urlParam) {
  555. $urlParams[$urlParam['param_desc']] = $urlParam;
  556. }
  557. $info['url_params'] = $urlParams;
  558. }
  559. {
  560. $main_db_id = $pdo->getZasobId();
  561. $sth_dbInfo = $pdo->prepare("
  562. select za.id as link_action_id
  563. , zd.id as db_id
  564. , zt.id as tbl_id
  565. , zi.id as cell_id
  566. , zp1.id as param1_id -- for every param
  567. from CRM_LISTA_ZASOBOW zt
  568. join CRM_LISTA_ZASOBOW zd on(zd.ID = zt.PARENT_ID
  569. and zd.TYPE in('DATABASE_MYSQL', 'BAZA_DANYCH', 'DATABASE_POSTGRESQL')
  570. and zd.ID = {$main_db_id}
  571. )
  572. join CRM_LISTA_ZASOBOW zi on(zi.PARENT_ID = zt.ID
  573. and zi.TYPE = 'KOMORKA'
  574. and zi.DESC = 'ID'
  575. )
  576. left join CRM_LISTA_ZASOBOW za on(za.PARENT_ID = zt.ID
  577. and za.TYPE = 'URL_ACTION'
  578. and za.ALIAS_ID = {$info['action_id']}
  579. )
  580. -- TODO: for every param:
  581. left join CRM_LISTA_ZASOBOW zp1 on(zp1.PARENT_ID = za.ID
  582. and zp1.TYPE = 'PARAM_IN'
  583. and zp1.ALIAS_ID = zi.id
  584. and zp1.DESC = 'ID_PROJECT'
  585. )
  586. where zt.TYPE = 'TABELA'
  587. and zt.A_STATUS not in('DELETED')
  588. and zt.DESC = 'IN7_MK_BAZA_DYSTRYBUCJI'
  589. ");
  590. DBG::_('DBG', '>1', "dbInfo query", $pdo->getRawSql($sth_dbInfo), __CLASS__, __FUNCTION__, __LINE__);
  591. $sth_dbInfo->execute();
  592. $linkInfo = $sth_dbInfo->fetch();
  593. if ($linkInfo) {
  594. $info['links']['IN7_MK_BAZA_DYSTRYBUCJI'] = $linkInfo;
  595. }
  596. }
  597. return $info;
  598. }
  599. public function kosztorysXmlAction() {// TODO: using old schema fields Agr_*
  600. /*
  601. $idProject = 1921;
  602. $schema = ProjectKosztorysSchema::getSchema();
  603. $data = $this->_fetchKosztorysData($idProject);
  604. //DBG::_('DBG', '>1', "XMLWriter", class_exists('XMLWriter'), __CLASS__, __FUNCTION__, __LINE__);
  605. //header('Content-type: application/xml; charset=utf-8');
  606. header('Content-type: text/plain; charset=utf-8');
  607. $xmlWriter = new XMLWriter();
  608. $xmlWriter->openUri('php://output');
  609. $xmlWriter->setIndent(true);
  610. if ($xmlWriter) {
  611. $xmlWriter->startDocument('1.0','UTF-8');
  612. //$xmlWriter->startElementNS(null, 'kosztorysy', 'https://biuro.biall-net.pl/wfs');// adds @xmlns=...
  613. $xmlWriter->startElement('kosztorysy');
  614. $xmlWriter->writeAttribute('targetNamespace', 'https://biuro.biall-net.pl/wfs');
  615. $xmlWriter->writeAttributeNS('xmlns', 'p5', 'http://www.w3.org/2000/xmlns/', 'https://biuro.biall-net.pl/wfs');
  616. for ($i = 1; $i <= 10; $i++) {
  617. $idProject += 1;
  618. $schema = ProjectKosztorysSchema::getSchema();
  619. $data = $this->_fetchKosztorysData($idProject);
  620. $xmlWriter->startElement('kosztorys');
  621. $xmlWriter->startElement('projekt');
  622. $xmlWriter->writeAttribute('id', $idProject);
  623. $xmlWriter->startElement('projekt');
  624. $xmlWriter->text("TODO L." . __LINE__);
  625. $xmlWriter->endElement();
  626. $xmlWriter->endElement();
  627. $xmlWriter->endElement();
  628. }
  629. // $memXmlWriter = new XMLWriter();
  630. // $memXmlWriter->openMemory();
  631. // $memXmlWriter->setIndent(true);
  632. //
  633. // for ($i = 1; $i <= 10; $i++) {
  634. // $idProject += 1;
  635. // $schema = ProjectKosztorysSchema::getSchema();
  636. // $data = $this->_fetchKosztorysData($idProject);
  637. //
  638. // $memXmlWriter->startElement('kosztorys');
  639. // $memXmlWriter->writeAttribute('id', $idProject);
  640. // $memXmlWriter->writeAttributeNS('p5', 'typeName', 'https://biuro.biall-net.pl/wfs', 'Kosztorys');
  641. // $memXmlWriter->text('book_'.$i);
  642. // $memXmlWriter->endElement();
  643. //
  644. // if ($i % 5 == 0) {
  645. // $batchXmlString = $memXmlWriter->outputMemory(true);
  646. // $xmlWriter->writeRaw($batchXmlString);
  647. // }
  648. // }
  649. // $memXmlWriter->flush();
  650. // unset($memXmlWriter);
  651. $xmlWriter->endElement();
  652. $xmlWriter->endDocument();
  653. }
  654. */
  655. }
  656. public function panel($idProject, $idCompany = 0) {
  657. if (User::get('ADM_ADMIN_LEVEL') > 6 || 'Pracownik' != User::getType()) return;// Only for workers with admin level < 6
  658. if (1 == V::get('_print', '', $_GET)) return;// print mode
  659. $task = V::get('_task', '', $_GET);
  660. UI::startTag('div', ['class'=>'jumbotron', 'style' => "padding-left: 20px; padding-right:20px"]);
  661. UI::startTag('div', ['class'=>'container']);
  662. UI::startTag('div', ['class'=>'btn-group']);
  663. if ($idProject > 0) {
  664. echo UI::h('button', [ 'class' => "btn btn-default disabled" ], "Projekt {$idProject}:");
  665. $activeRoute = V::get('_route', '', $_GET);
  666. $route = 'UrlAction_ProjektyKosztorys'; UI::link('default', "Kosztorys", "index.php?_route={$route}&ID_PROJECT={$idProject}", ['className'=>['active'=>($route == $activeRoute)]]);
  667. $route = 'UrlAction_ProjektyPrzedmiarKosztorys'; UI::link('default', "Przedmiar", "index.php?_route={$route}&ID_PROJECT={$idProject}&_print=1", ['className'=>['active'=>($route == $activeRoute)]]);
  668. $route = 'UrlAction_ProjektyZestawienieSwMikRurKosztorys'; UI::link('default', "Zestawienie (światłowód i mikrorurki)", "index.php?_route={$route}&ID_PROJECT={$idProject}&_print=1", ['className'=>['active'=>($route == $activeRoute)]]);
  669. // UI::link('warning', "oferta", "index.php?_route=UrlAction_ProjektyKosztyWstepnychRobot&ID_PROJECT={$idProject}&_task=oferta", ['target'=>'_blank']);
  670. // UI::link('warning', "oferta (Admin)", "index.php?_route=UrlAction_ProjektyKosztyWstepnychRobot&ID_PROJECT={$idProject}&_task=ofertaAdmin", ['target'=>'_blank']);
  671. // UI::link('warning', "oferta company", "index.php?_route=UrlAction_ProjektyKosztyWstepnychRobot&ID_PROJECT={$idProject}&_task=ofertaCompany", ['target'=>'_blank']);
  672. $route = 'UrlAction_ProjektyZamowieniaKosztorys'; UI::link('default', "Zamówienia", "index.php?_route={$route}&ID_PROJECT={$idProject}", ['className'=>['active'=>($route == $activeRoute)]]);
  673. $route = 'UrlAction_ProjektyOdbiorKosztorys'; UI::link('default', "Odbiory", "index.php?_route={$route}&ID_PROJECT={$idProject}", ['className'=>['active'=>($route == $activeRoute)]]);
  674. $route = 'UrlAction_ProjektyOfertaKosztorys'; UI::link('default disabled', "TODO: Oferty", "index.php?_route={$route}&ID_PROJECT={$idProject}", ['className'=>['active'=>($route == $activeRoute)]]);
  675. }
  676. UI::link('default', "Oferta domyślna", "index.php?_route=UrlAction_ProjektyOfertaAdminKosztorys");
  677. UI::endTag('div');// .btn-group
  678. UI::endTag('div');// .container
  679. $this->additionalPanel($idProject, $idCompany);
  680. UI::endTag('div');// .jumbotron
  681. }
  682. public function additionalPanel($idProject, $idCompany = 0) {
  683. }
  684. public function saveOffer($idProject, $idCompany, $args, $admin = false) {
  685. DBG::_('DBG', '>1', "args", $args, __CLASS__, __FUNCTION__, __LINE__);
  686. if (!$admin) return;
  687. $cennik = ProjectKosztorysCennik::getCennik($idProject, $idCompany);
  688. DBG::_('DBG', '>1', "cennik", $cennik, __CLASS__, __FUNCTION__, __LINE__);
  689. $pdo = DB::getPDO();
  690. {
  691. $add_id_zasob = 0;
  692. $add_unit = '';
  693. $add_price = 0;
  694. $add_quantity = 0;
  695. $add__sth = $pdo->prepare("
  696. insert into CRM_LISTA_ZASOBOW_OFFERS (
  697. CRM_LISTA_ZASOBOW_ID
  698. , COMPANIES_ID
  699. , ID_PROJECT
  700. , OFFER_PRICE_PER_RESOURCE_UNIT
  701. , RESOURCE_UNIT_TYPE
  702. , OFFER_UNIT_TYPE
  703. , REQUIRED_RESOURCE_UNITS
  704. , A_RECORD_CREATE_AUTHOR
  705. , A_RECORD_CREATE_DATE
  706. ) values (
  707. :id_zasob
  708. , :id_company
  709. , :id_project
  710. , :price
  711. , :unit
  712. , :unit
  713. , :quantity
  714. , :author
  715. , NOW()
  716. )
  717. ");
  718. $add__sth->bindValue(':author', User::getLogin(), PDO::PARAM_STR);
  719. $add__sth->bindValue(':id_project', $idProject, PDO::PARAM_INT);
  720. $add__sth->bindValue(':id_company', $idCompany, PDO::PARAM_INT);
  721. $add__sth->bindValue(':quantity', $add_quantity, PDO::PARAM_STR);
  722. $add__sth->bindParam(':id_zasob', $add_id_zasob, PDO::PARAM_INT);
  723. $add__sth->bindParam(':price', $add_price, PDO::PARAM_STR);
  724. $add__sth->bindParam(':unit', $add_unit, PDO::PARAM_STR);
  725. }
  726. {
  727. $edit_id_company = $idCompany;
  728. $edit_id_zasob = 0;
  729. $edit_unit = '';
  730. $edit_price = 0;
  731. $edit_author = 0;
  732. $edit_quantity = 0;
  733. $edit__sth = $pdo->prepare("
  734. update CRM_LISTA_ZASOBOW_OFFERS
  735. set CRM_LISTA_ZASOBOW_ID = :id_zasob
  736. , COMPANIES_ID = :id_company
  737. , ID_PROJECT = :id_project
  738. , OFFER_PRICE_PER_RESOURCE_UNIT = :price
  739. , RESOURCE_UNIT_TYPE = :unit
  740. , OFFER_UNIT_TYPE = :unit
  741. , REQUIRED_RESOURCE_UNITS = :quantity
  742. , A_RECORD_UPDATE_AUTHOR = :author
  743. , A_RECORD_UPDATE_DATE = NOW()
  744. where ID = :id
  745. ");
  746. $edit__sth->bindParam(':id', $edit_id, PDO::PARAM_INT);
  747. $edit__sth->bindValue(':author', User::getLogin(), PDO::PARAM_STR);
  748. $edit__sth->bindValue(':id_project', $idProject, PDO::PARAM_INT);
  749. $edit__sth->bindValue(':id_company', $idCompany, PDO::PARAM_INT);
  750. $edit__sth->bindValue(':quantity', $edit_quantity, PDO::PARAM_STR);
  751. $edit__sth->bindParam(':id_zasob', $edit_id_zasob, PDO::PARAM_INT);
  752. $edit__sth->bindParam(':price', $edit_price, PDO::PARAM_STR);
  753. $edit__sth->bindParam(':unit', $edit_unit, PDO::PARAM_STR);
  754. }
  755. $schema = ProjectKosztorysSchema::getSchema();
  756. foreach ($schema['config']['layer'] as $idLayer => $layData) {
  757. DBG::_('DBG', '>1', "layData", $layData, __CLASS__, __FUNCTION__, __LINE__);
  758. foreach ($layData['type'] as $idType => $typeLabel) {
  759. $edit_id = V::get("edit_price_id_{$idType}", '', $args);
  760. $add_price = V::get("price_{$idType}", '', $args);
  761. DBG::_('DBG', '>1', "typeLabel (edit={$edit_id}, price={$add_price})", $typeLabel, __CLASS__, __FUNCTION__, __LINE__);
  762. if ($edit_id > 0) {
  763. $edit_price = V::get("price_{$idType}", '', $args);
  764. $edit_price = str_replace(',', '.', $edit_price);
  765. if ($edit_id > 0 && $edit_price > 0) {
  766. $edit_id_zasob = $idType;
  767. $edit_unit = $layData['jednostka'];
  768. // TODO: check if anything change
  769. DBG::_('DBG', '>1', "EDIT price for idZasob({$idType}) {price:{$edit_price}, id_offer:{$edit_id}}", $typeLabel, __CLASS__, __FUNCTION__, __LINE__);
  770. $edit__sth->execute();
  771. // TODO: add to hist
  772. }
  773. } else {
  774. $add_price = V::get("price_{$idType}", '', $args);
  775. $add_price = str_replace(',', '.', $add_price);
  776. if ($add_price > 0) {
  777. $add_id_zasob = $idType;
  778. $add_unit = $layData['jednostka'];
  779. DBG::_('DBG', '>1', "ADD price for idZasob({$idType}) {price:{$add_price}}", $typeLabel, __CLASS__, __FUNCTION__, __LINE__);
  780. $add__sth->execute();
  781. }
  782. }
  783. }
  784. }
  785. }
  786. public function saveDefaultOffer($args) {
  787. DBG::_('DBG', '>1', "args", $args, __CLASS__, __FUNCTION__, __LINE__);
  788. $cennik = ProjectKosztorysCennik::getDefaultCennik();
  789. DBG::_('DBG', '>1', "cennik", $cennik, __CLASS__, __FUNCTION__, __LINE__);
  790. $idCompany = 0;
  791. $idProject = 0;
  792. $pdo = DB::getPDO();
  793. {
  794. $add_id_zasob = 0;
  795. $add_unit = '';
  796. $add_price = 0;
  797. $add_quantity = 0;
  798. $add__sth = $pdo->prepare("
  799. insert into CRM_LISTA_ZASOBOW_OFFERS (
  800. CRM_LISTA_ZASOBOW_ID
  801. , COMPANIES_ID
  802. , ID_PROJECT
  803. , OFFER_PRICE_PER_RESOURCE_UNIT
  804. , RESOURCE_UNIT_TYPE
  805. , OFFER_UNIT_TYPE
  806. , REQUIRED_RESOURCE_UNITS
  807. , A_RECORD_CREATE_AUTHOR
  808. , A_RECORD_CREATE_DATE
  809. ) values (
  810. :id_zasob
  811. , :id_company
  812. , :id_project
  813. , :price
  814. , :unit
  815. , :unit
  816. , :quantity
  817. , :author
  818. , NOW()
  819. )
  820. ");
  821. $add__sth->bindValue(':author', User::getLogin(), PDO::PARAM_STR);
  822. $add__sth->bindValue(':id_project', $idProject, PDO::PARAM_INT);
  823. $add__sth->bindValue(':id_company', $idCompany, PDO::PARAM_INT);
  824. $add__sth->bindValue(':quantity', $add_quantity, PDO::PARAM_STR);
  825. $add__sth->bindParam(':id_zasob', $add_id_zasob, PDO::PARAM_INT);
  826. $add__sth->bindParam(':price', $add_price, PDO::PARAM_STR);
  827. $add__sth->bindParam(':unit', $add_unit, PDO::PARAM_STR);
  828. }
  829. {
  830. $edit_id_zasob = 0;
  831. $edit_unit = '';
  832. $edit_price = 0;
  833. $edit_author = 0;
  834. $edit_quantity = 0;
  835. $edit__sth = $pdo->prepare("
  836. update CRM_LISTA_ZASOBOW_OFFERS
  837. set CRM_LISTA_ZASOBOW_ID = :id_zasob
  838. , COMPANIES_ID = :id_company
  839. , ID_PROJECT = :id_project
  840. , OFFER_PRICE_PER_RESOURCE_UNIT = :price
  841. , RESOURCE_UNIT_TYPE = :unit
  842. , OFFER_UNIT_TYPE = :unit
  843. , REQUIRED_RESOURCE_UNITS = :quantity
  844. , A_RECORD_UPDATE_AUTHOR = :author
  845. , A_RECORD_UPDATE_DATE = NOW()
  846. where ID = :id
  847. ");
  848. $edit__sth->bindParam(':id', $edit_id, PDO::PARAM_INT);
  849. $edit__sth->bindValue(':author', User::getLogin(), PDO::PARAM_STR);
  850. $edit__sth->bindValue(':id_project', $idProject, PDO::PARAM_INT);
  851. $edit__sth->bindValue(':id_company', $idCompany, PDO::PARAM_INT);
  852. $edit__sth->bindValue(':quantity', $edit_quantity, PDO::PARAM_STR);
  853. $edit__sth->bindParam(':id_zasob', $edit_id_zasob, PDO::PARAM_INT);
  854. $edit__sth->bindParam(':price', $edit_price, PDO::PARAM_STR);
  855. $edit__sth->bindParam(':unit', $edit_unit, PDO::PARAM_STR);
  856. }
  857. $schema = ProjectKosztorysSchema::getSchema();
  858. foreach ($schema['config']['layer'] as $idLayer => $layData) {
  859. DBG::_('DBG', '>1', "layData", $layData, __CLASS__, __FUNCTION__, __LINE__);
  860. foreach ($layData['type'] as $idType => $typeLabel) {
  861. DBG::_('DBG', '>1', "typeLabel", $typeLabel, __CLASS__, __FUNCTION__, __LINE__);
  862. $edit_id = V::get("edit_price_id_{$idType}", '', $args);
  863. if ($edit_id > 0) {
  864. $edit_price = V::get("price_{$idType}", '', $args);
  865. $edit_price = str_replace(',', '.', $edit_price);
  866. if ($edit_id > 0 && $edit_price > 0) {
  867. $edit_id_zasob = $idType;
  868. $edit_unit = $layData['jednostka'];
  869. // TODO: check if anything change
  870. $edit__sth->execute();
  871. // TODO: add to hist
  872. }
  873. } else {
  874. $add_price = V::get("price_{$idType}", '', $args);
  875. $add_price = str_replace(',', '.', $add_price);
  876. if ($add_price > 0) {
  877. $add_id_zasob = $idType;
  878. $add_unit = $layData['jednostka'];
  879. $add__sth->execute();
  880. }
  881. }
  882. }
  883. }
  884. }
  885. public function defaultOferta($idCompany = 0) {
  886. if ('1' == V::get('save_offer', '', $_POST)) {
  887. $this->saveDefaultOffer($_POST);
  888. }
  889. $schema = ProjectKosztorysSchema::getSchema($showErrors = true);
  890. if (empty($schema['config']['type'])) throw new Exception("Schema error - brak zdefiniowanych typów");
  891. $cennik = ProjectKosztorysCennik::getDefaultCennik($idCompany);
  892. //DBG::_(true, true, "cennik", $cennik, __CLASS__, __FUNCTION__, __LINE__);
  893. UI::setTitleJsTag("Cennik domyślny dla Kosztorysów");
  894. ?>
  895. <div class="container">
  896. <form action="" method="post">
  897. <?php foreach ($schema['config']['layer'] as $idLayer => $layData) : ?>
  898. <h4 style="padding:0 6px"><?php echo $layData['label']; ?></h4>
  899. <table class="tabel table-bordered" style="width:100%">
  900. <tbody>
  901. <tr>
  902. <th style="padding:0 6px">id zasobu</th>
  903. <th style="padding:0 6px">typ</th>
  904. <th style="padding:0 6px">jednostka miary</th>
  905. <th style="padding:0 6px">cena jednostkowa</th>
  906. </tr>
  907. <?php foreach ($layData['type'] as $idType => $typeLabel) : ?>
  908. <tr>
  909. <td style="width:100px; padding:0 6px"><?php echo $idType; ?></td>
  910. <td style="padding:0 6px" title="[<?php echo $idType; ?>] <?php echo $typeLabel; ?>"><?php echo $typeLabel; ?></td>
  911. <td style="padding:0 6px"><?php echo $layData['jednostka']; ?></td>
  912. <td style="padding:3px 6px"><input type="text" class="form-control input-sm" name="price_<?php echo $idType; ?>" value="<?php echo $cennik[$idType]['price']; ?>"/></td>
  913. </tr>
  914. <?php endforeach; ?>
  915. </tbody>
  916. </table>
  917. <?php endforeach; ?>
  918. <br>
  919. <?php foreach ($cennik as $item) : ?>
  920. <input type="hidden" name="edit_price_id_<?php echo $item['id_zasob']; ?>" value="<?php echo $item['ID']; ?>">
  921. <?php endforeach; ?>
  922. <input type="hidden" name="save_offer" value="1">
  923. <input type="submit" value="Zapisz" class="btn btn-primary">
  924. </form>
  925. </div>
  926. <?php
  927. // Fix Zasoby [22444] INNE Kosztorys - zasoby
  928. // SELECT * FROM `CRM_LISTA_ZASOBOW_OFFERS`
  929. // WHERE `CRM_LISTA_ZASOBOW_ID` IN (22801,22445,22446,22447,22448,22449,22450,22451,22452,22453,22454,22455,22456,22457,22458,22459,22552,22517,22514,22481,22484,22515,22516,22518,22519,22520,22521,22550,22551,22617,22618,22638,22639,22640,22641,22642,22643,22644,22645,22646,22724,22725,22797,22798)
  930. // ORDER BY `CRM_LISTA_ZASOBOW_OFFERS`.`CRM_LISTA_ZASOBOW_ID` ASC
  931. // limit 100
  932. // <edittype widgetv2type="ValueMap" name="Typ_kosztu">
  933. // <widgetv2config fieldEditable="1" labelOnTop="0">
  934. // <value zasobID="22643" key="Montaż zapasu w studni" value="Montaż zapasu w studni"/>
  935. // <value zasobID="22638" key="Montaż złączek mikrokanalizacji" value="Montaż złączek mikrokanalizacji"/>
  936. // <value zasobID="22645" key="Mufa z montażem" value="Mufa z montażem"/>
  937. // <value zasobID="22642" key="Pigtail od puszki do terminala" value="Pigtail od puszki do terminala"/>
  938. // <value zasobID="22640" key="Przewiert w budynku z uszczelnieniem" value="Przewiert w budynku z uszczelnieniem"/>
  939. // <value zasobID="22639" key="Puszka abonencka z montażem" value="Puszka abonencka z montażem"/>
  940. // <value zasobID="22641" key="Spaw poza mufą" value="Spaw poza mufą"/>
  941. // <value zasobID="22724" key="Spaw w mufie" value="Spaw w mufie"/>
  942. // <value zasobID="22617" key="Spliter 1/16" value="Spliter 1/16"/>
  943. // <value zasobID="22618" key="Spliter 1/4" value="Spliter 1/4"/>
  944. // <value zasobID="22725" key="Spliter 1/8" value="Spliter 1/8"/>
  945. // <value zasobID="22644" key="Wprowadzenie kabli do mufy" value="Wprowadzenie kabli do mufy"/>
  946. // <value zasobID="22646" key="Zamek PIOCH do studni" value="Zamek PIOCH do studni"/>
  947. // <value zasobID="22515" key="Zapas kabla" value="Zapas kabla"/>
  948. // <value zasobID="22514" key="Złącze" value="Złącze "/>
  949. // </widgetv2config>
  950. // </edittype>
  951. // 22574 ->22515 INNE TYPE Zapas kabla
  952. // 22620 ->22618 INNE TYPE Spliter 1/4
  953. // 22621 ->22617 INNE TYPE Spliter 1/16
  954. // 22647 ->22638 INNE TYPE Montaż złączek mikrokanalizacji
  955. // 22648 ->22639 INNE TYPE Puszka abonencka z montażem
  956. // 22649 ->22640 INNE TYPE Przewiert w budynku z uszczelnieniem
  957. // 22650 ->22641 INNE TYPE Spaw poza mufą
  958. // 22651 ->22642 INNE TYPE Pigtail od puszki do terminala
  959. // 22652 ->22643 INNE TYPE Montaż zapasu w studni
  960. // 22653 ->22644 INNE TYPE Wprowadzenie kabli do mufy
  961. // 22654 ->22645 INNE TYPE Mufa z montażem
  962. // 22655 ->22646 INNE TYPE Zamek PIOCH do studni
  963. // 22881 ->22514 INNE TYPE Złącze
  964. // TODO: ? 22484
  965. }
  966. /**
  967. * @returns [ 'cost_total' => :numeric, 'sub_costs' => [ $id_zasob => 'price' ] ]
  968. */
  969. public function getProjectCostByCennik($idProject, $idCompany = 0) {
  970. $projCost = array();
  971. $projCost['cost_total'] = 0;
  972. $projCost['sub_costs'] = array();
  973. $defCennik = ProjectKosztorysCennik::getDefaultCennik($idCompany);
  974. // $defCennik = [ $id_zasob => [ 'price' => $price, 'ID', 'id_zasob', 'id_company', 'id_project', 'unit', 'quantity' ] ]
  975. $cennik = ProjectKosztorysCennik::getCennik($idProject, $idCompany);
  976. $workCennik = ProjectKosztorysCennik::getWorkCennik($idProject, $idCompany);
  977. $data = $this->getKosztorysData($idProject, $idOrder = 0, $admin = false);
  978. foreach ($data['summary'] as $idLayer => $layData) {
  979. foreach ($layData['data'] as $typeData) {
  980. if (!$typeData['idType']) continue;
  981. $price = (!empty($cennik[$typeData['idType']]['price']))? $cennik[$typeData['idType']]['price'] : 0;
  982. $defPrice = (!empty($defCennik[$typeData['idType']]['price']))? $defCennik[$typeData['idType']]['price'] : 0;
  983. $workPrice = (!empty($workCennik[$typeData['idType']]['price']))? $workCennik[$typeData['idType']]['price'] : 0;
  984. $cost = ($price > 0)? $price : $defPrice;
  985. if ($workPrice > 0) $cost += $workPrice;
  986. $cost = $typeData['ilosc'] * $cost;
  987. $projCost['sub_costs'][$typeData['idType']] = $cost;
  988. $projCost['cost_total'] += $cost;
  989. }
  990. }
  991. // fetch sub costs for sub projects
  992. // $data['by_project'] = array_reduce($data['rawDataByType'], function($result, $row) {
  993. // $idProj = $row['ID_PROJECT'];
  994. // $idLayer = $row['idLayer'];
  995. // $idType = $row['idType'];
  996. // if (!array_key_exists($idProj, $result)) $result[$idProj] = array();
  997. // if (!array_key_exists($idLayer, $result)) $result[$idProj][$idLayer] = array();
  998. // if (!array_key_exists($idType, $result[$idProj][$idLayer])) {
  999. // $result[$idProj][$idLayer][$idType] = $row;
  1000. // } else {
  1001. // $result[$idProj][$idLayer][$idType]['ilosc'] += $row['ilosc'];
  1002. $projCost['sub_proj'] = array();
  1003. foreach ($data['by_project'] as $idSubProj => $subProjData) {
  1004. foreach ($subProjData as $idLayer => $layData) {
  1005. foreach ($layData as $idType => $typeData) {
  1006. $price = (!empty($cennik[$typeData['idType']]['price']))? $cennik[$typeData['idType']]['price'] : 0;
  1007. $defPrice = (!empty($defCennik[$typeData['idType']]['price']))? $defCennik[$typeData['idType']]['price'] : 0;
  1008. $cost = ($price > 0)? $price : $defPrice;
  1009. $cost = $typeData['ilosc'] * $cost;
  1010. $projCost['sub_proj'][$idSubProj][$idType] = $cost;
  1011. }
  1012. }
  1013. }
  1014. return $projCost;
  1015. }
  1016. public function getModel($idProject) {
  1017. if (array_key_exists($idProject, $this->_model)) return $this->_model[$idProject];
  1018. $this->_model[$idProject] = new ProjectKosztorysModel($idProject);
  1019. return $this->_model[$idProject];
  1020. }
  1021. public function oferta($args) {
  1022. $idProject = $args['idProject'];
  1023. $idCompany = V::get('idCompany', 0, $args);
  1024. $admin = V::get('admin', false, $args);
  1025. $companyAdmin = V::get('companyAdmin', false, $args);
  1026. if ($admin && '1' == V::get('save_offer', '', $_POST)) {
  1027. $this->saveOffer($idProject, $idCompany, $_POST, $admin);
  1028. }
  1029. $defCennik = ProjectKosztorysCennik::getDefaultCennik($idCompany);
  1030. $cennik = ProjectKosztorysCennik::getCennik($idProject, $idCompany);
  1031. $viewLayerDataArgs = compact('idProject', 'idCompany', 'admin', 'companyAdmin');
  1032. UI::setTitleJsTag("Oferta " . (($idProject)? " [{$idProject}] " : '') . (($idCompany)? " Kontrahent({$idCompany})" : '') . " - Kosztorysy");
  1033. ?>
  1034. <div class="container">
  1035. <?php if ($admin) : ?>
  1036. <form action="" method="post">
  1037. <?php endif; ?>
  1038. <?php $this->viewLayersData($viewLayerDataArgs); ?>
  1039. <?php if ($admin || $companyAdmin) : ?>
  1040. <?php foreach ($cennik as $item) : ?>
  1041. <input type="hidden" name="edit_price_id_<?php echo $item['id_zasob']; ?>" value="<?php echo $item['ID']; ?>">
  1042. <?php endforeach; ?>
  1043. <input type="hidden" name="save_offer" value="1">
  1044. <hr><input class="btn btn-primary" type="submit" value="Zapisz ofertę">
  1045. </form>
  1046. <?php endif; ?>
  1047. </div>
  1048. <?php
  1049. }
  1050. public function viewLayersData($args) {
  1051. $idProject = $args['idProject'];
  1052. $idCompany = V::get('idCompany', 0, $args);
  1053. $admin = V::get('admin', false, $args);
  1054. $priceEditJs = V::get('priceEditJs', false, $args);
  1055. $companyAdmin = V::get('companyAdmin', false, $args);
  1056. $projCosts = V::get('projCosts', array(), $args);
  1057. $showPrices = ! V::get('hidePrices', 0, $args);
  1058. $schema = ProjectKosztorysSchema::getSchema($showErrors = true);
  1059. $conf = $schema['config'];
  1060. DBG::_('DBG', '>1', "conf", $conf, __CLASS__, __FUNCTION__, __LINE__);
  1061. $summaryTypeCost = V::get('sub_costs', array(), $projCosts);
  1062. $subProjCost = V::get('sub_proj', array(), $projCosts);
  1063. $data = $this->getKosztorysData($idProject, $idOrder = 0, $admin);
  1064. DBG::log($data, 'array', "\$data");
  1065. $dataSummary = $data['summary'];
  1066. $dataSubProj = $data['by_project'];
  1067. // $dataSubProj = array();
  1068. // foreach ($data['by_project'] as $idSubProj => $subProjData) {
  1069. // if ($idProject != $idSubProj) $dataSubProj[$idSubProj] = $subProjData;
  1070. // }
  1071. DBG::_('DBG', '>1', "data", $data, __CLASS__, __FUNCTION__, __LINE__);
  1072. $defCennik = ProjectKosztorysCennik::getDefaultCennik($idCompany);
  1073. $cennik = ProjectKosztorysCennik::getCennik($idProject, $idCompany);
  1074. DBG::_('DBG', '>1', "cennik", $cennik, __CLASS__, __FUNCTION__, __LINE__);
  1075. DBG::_('DBG', '>1', "defCennik", $defCennik, __CLASS__, __FUNCTION__, __LINE__);
  1076. $workCennik = ProjectKosztorysCennik::getWorkCennik($idProject, $idCompany);
  1077. if (!empty($summaryTypeCost)) {
  1078. $additionalCosts = array();
  1079. $additionalCosts[] = array();
  1080. $additionalCosts[] = array();
  1081. $additionalCosts[] = array();
  1082. $additionalSummaryTypeCost = array();
  1083. $additionalSummaryTypeCost[] = 0;
  1084. $additionalSummaryTypeCost[] = 0;
  1085. $additionalSummaryTypeCost[] = 0;
  1086. }
  1087. ?>
  1088. <style type="text/css">
  1089. .type_price-UNDEFINED { color:silver }
  1090. .type_price-UNDEFINED input { color:silver }
  1091. .type_price-GLOBAL { color:red }
  1092. .type_price-GLOBAL input { color:red }
  1093. .type_price-PROJECT { color:green }
  1094. .type_price-PROJECT input { color:green }
  1095. /* Print Styles */
  1096. @media print {
  1097. body { font-size:10px; }
  1098. th, td { font-size:10px; }
  1099. h1 { font-size:2em; }
  1100. h2 { font-size:1.6em; }
  1101. h3 { font-size:1.4em; }
  1102. h4 { font-size:1.2em; }
  1103. }
  1104. </style>
  1105. <?php $tblCols = 6 + ($admin ? 1 : 0) + ((!empty($summaryTypeCost))? 1 : 0); ?>
  1106. <table class="tabel table-bordered table-hover" style="width:100%; margin-bottom:6px; page-break-inside:avoid">
  1107. <tbody>
  1108. <?php foreach ($dataSummary as $idLayer => $layData) : ?>
  1109. <tr>
  1110. <td colspan="<?php echo $tblCols + 1; ?>" style="padding:0 6px; font-size:1.2em; line-height:2em"> &mdash; <?php echo $layData['label']; ?></td>
  1111. </tr>
  1112. <tr>
  1113. <td style="width:24px"></td>
  1114. <td style="color:#888; padding:0 6px">typ</td>
  1115. <td style="color:#888; width:60px; padding:0 6px; text-align:right">ilość</td>
  1116. <td style="color:#888; width:80px; padding:0 6px; text-align:right">jednostka</td>
  1117. <?php if ($showPrices) : ?>
  1118. <td style="color:#888; padding:0 6px; text-align:right">cena jednostkowa
  1119. <?php if ($priceEditJs) : ?>
  1120. <button type="button"
  1121. class="btn btn-xs btn-link"
  1122. data-toggle="popover"
  1123. data-trigger="hover"
  1124. title="Cena jednostkowa"
  1125. data-content="Cena na czerwono oznacza cenę z cennika głównego, cena na zielono to cena dla projektu"><i class="glyphicon glyphicon-question-sign"></i></button>
  1126. <?php endif; ?>
  1127. </td>
  1128. <td style="color:#888; padding:0 6px; text-align:right">cena jedn. (robocizna)</td>
  1129. <?php endif; ?>
  1130. <?php if ($admin) : ?>
  1131. <td style="color:#888; padding:0 6px; text-align:right">cena jedn. (domyślna)</td>
  1132. <?php endif; ?>
  1133. <?php if (!empty($summaryTypeCost)) : ?>
  1134. <td style="color:#888; padding:0 6px; text-align:right">szacowany koszt [zł]</td>
  1135. <?php endif; ?>
  1136. <td style="color:#888; padding:0 6px; text-align:right">uwagi</td>
  1137. </tr>
  1138. <?php foreach ($layData['data'] as $typeData) : ?>
  1139. <?php if (!$typeData['idType']) : ?>
  1140. <tr>
  1141. <td colspan="4">
  1142. <?php if ($admin) {
  1143. $fixLink = 'index.php?MENU_INIT=VIEWTABLE_AJAX&ZASOB_ID=' . $conf['layer'][$idLayer]['tabela_id'];
  1144. $fixLink .= '&f_' . $conf['layer'][$idLayer]['zasob_field'] . '=%3D' . $typeData['type'];
  1145. $fixLink .= '&_hash=' . uniqid();
  1146. $fixProjectLink = '<a target="_blank" href="' . $fixLink . "&f_ID_PROJECT={$idProject}" . '">' . "Popraw" . '</a>' . " (dane dla projektu [{$idProject}])";
  1147. $fixAllLink = '<a target="_blank" href="' . $fixLink . '">' . "Popraw wszystkie" . '</a>';
  1148. UI::alert('danger', "Niezdefiniowany typ: <code>{$typeData['type']}</code> - {$fixProjectLink}, {$fixAllLink}");
  1149. } ?>
  1150. <?php DBG::_('DBG', '>1', "Error conf", $conf, __CLASS__, __FUNCTION__, __LINE__); ?>
  1151. <?php DBG::_('DBG', '>1', "Error", $typeData, __CLASS__, __FUNCTION__, __LINE__); ?>
  1152. </td>
  1153. </tr>
  1154. <?php else : ?>
  1155. <?php $idType = $typeData['idType']; ?>
  1156. <?php $defPrice = (!empty($defCennik[$idType]['price']))? $defCennik[$idType]['price'] : 0; ?>
  1157. <?php $price = (!empty($cennik[$idType]) && array_key_exists('price', $cennik[$idType]))? $cennik[$idType]['price'] : $defPrice; ?>
  1158. <?php
  1159. $typePrice = 'UNDEFINED';
  1160. if (!empty($defCennik[$idType]['price'])) $typePrice = 'GLOBAL';
  1161. if (!empty($cennik[$idType]) && array_key_exists('price', $cennik[$idType])) $typePrice = 'PROJECT';
  1162. ?>
  1163. <?php $workPrice = (!empty($workCennik[$idType]['price']))? $workCennik[$idType]['price'] : 0; ?>
  1164. <?php $uwagi = (!empty($cennik[$idType]['notes']))? $cennik[$idType]['notes'] : '';// TODO: uwagi ?>
  1165. <tr>
  1166. <td style="width:24px"></td>
  1167. <td style="padding:0 6px" title="[<?php echo $idType; ?>] <?php echo $typeData['type']; ?>"> &ndash; <?php echo $typeData['type']; ?></td>
  1168. <td style="padding:0 6px; text-align:right"><?php echo $typeData['ilosc']; ?></td>
  1169. <td style="padding:0 6px; text-align:right"><?= $typeData['jednostka']; ?></td>
  1170. <?php if ($showPrices) : ?>
  1171. <td
  1172. <?php if ($priceEditJs) : ?>
  1173. onClick="return p5UI__ButtonAjax(this, 'p5UIBtnAjax:Kosztorys:updateProjektyOferta', { href: '<?= "{$priceEditJs}&idType={$idType}&unitType=zasob"; ?>' })"
  1174. class="type_price-<?= $typePrice; ?>"
  1175. <?php endif; ?>
  1176. style="<?php if ($priceEditJs) : ?>cursor:pointer; <?php endif; ?>padding:3px 6px; text-align:right">
  1177. <?php if ($admin || $companyAdmin) : ?>
  1178. <input type="text" style="text-align:right" class="form-control input-sm" name="price_<?= $idType; ?>" value="<?= $price; ?>"/>
  1179. <?php else : ?>
  1180. <?php echo number_format($price, 2, ',', ' '); ?>
  1181. <?php endif; ?>
  1182. </td>
  1183. <td
  1184. <?php if ($priceEditJs) : ?>
  1185. onClick="return p5UI__ButtonAjax(this, 'p5UIBtnAjax:Kosztorys:updateProjektyOferta', { href: '<?= "{$priceEditJs}&idType={$idType}&unitType=robocizna"; ?>' })"
  1186. <?php endif; ?>
  1187. style="padding:3px 6px; text-align:right">
  1188. <?php if ($admin || $companyAdmin) : ?>
  1189. <input type="text" style="text-align:right" class="form-control input-sm" name="work_price_<?php echo $idType; ?>" value="<?php echo $workPrice; ?>"/>
  1190. <?php else : ?>
  1191. <?php echo number_format($workPrice, 2, ',', ' '); ?>
  1192. <?php endif; ?>
  1193. </td>
  1194. <?php if ($admin) : ?>
  1195. <td style="padding:3px 6px; text-align:right"><?php echo $defPrice; ?></td>
  1196. <?php endif; ?>
  1197. <?php if (!empty($summaryTypeCost)) : ?>
  1198. <td style="padding:3px 6px; text-align:right"><?php echo number_format(V::get($idType, 0, $summaryTypeCost), 2, ',', ' '); ?></td>
  1199. <?php endif; ?>
  1200. <?php endif; ?>
  1201. <td style="padding:3px 6px; text-align:right">
  1202. <?php if ($admin || $companyAdmin) : ?>
  1203. <input type="text" style="text-align:left" class="form-control input-sm" name="uwagi_<?php echo $idType; ?>" value="<?php echo $uwagi; ?>"/>
  1204. <?php else : ?>
  1205. <?php echo $uwagi; ?>
  1206. <?php endif; ?>
  1207. </td>
  1208. </tr>
  1209. <?php endif; ?>
  1210. <?php endforeach; ?>
  1211. <?php endforeach; ?>
  1212. <?php if (!empty($additionalCosts)) : ?>
  1213. <tr>
  1214. <td colspan="<?php echo $tblCols + 1; ?>" style="padding:0 6px; font-size:1.2em; line-height:2em">Koszty dodatkowe</td>
  1215. </tr>
  1216. <tr>
  1217. <td style="width:24px"></td>
  1218. <td style="color:#888; padding:0 6px">typ</td>
  1219. <td style="color:#888; width:60px; padding:0 6px; text-align:right">ilość</td>
  1220. <td style="color:#888; width:80px; padding:0 6px; text-align:right">jednostka</td>
  1221. <td style="color:#888; padding:0 6px; text-align:right">cena jednostkowa</td>
  1222. <td style="color:#888; padding:0 6px; text-align:right">cena jedn. (robocizna)</td>
  1223. <?php if ($admin) : ?>
  1224. <td style="color:#888; padding:0 6px; text-align:right">cena jedn. (domyślna)</td>
  1225. <?php endif; ?>
  1226. <?php if (!empty($summaryTypeCost)) : ?>
  1227. <td style="color:#888; padding:0 6px; text-align:right">szacowany koszt [zł]</td>
  1228. <?php endif; ?>
  1229. <td style="color:#888; padding:0 6px; text-align:right">uwagi</td>
  1230. </tr>
  1231. <?php foreach ($additionalCosts as $idType => $additionalCost) : ?>
  1232. <?php $additionalPrice = 0;//TODO: get from $additionalCennik or $additionalCost ?>
  1233. <?php $additionalWorkPrice = 0;//TODO: get from $additionalWorkCennik or $additionalCost ?>
  1234. <?php $additionalCount = 0;//TODO: fetch ?>
  1235. <?php $additionalUnit = '';//TODO: fetch ?>
  1236. <?php $jednostka = '';//TODO: fetch ?>
  1237. <?php $ilosc = '';//TODO: fetch ?>
  1238. <?php $typeLabel = '';//TODO: fetch ?>
  1239. <?php $price = 0;//TODO: fetch ?>
  1240. <?php $defPrice = 0;//TODO: fetch ?>
  1241. <?php $workPrice = 0;//TODO: fetch ?>
  1242. <?php $uwagi = '';//TODO: fetch ?>
  1243. <tr>
  1244. <td style="width:24px"></td>
  1245. <td style="padding:0 6px">
  1246. <?php if ($admin || $companyAdmin) : ?>
  1247. <input type="text" style="text-align:right" class="form-control input-sm" name="additional_label_<?php echo $idType; ?>" value="<?php echo $typeLabel; ?>"/>
  1248. <?php else : ?>
  1249. - <?php echo $typeLabel; ?>
  1250. <?php endif; ?>
  1251. </td>
  1252. <td style="padding:0 6px; text-align:right">
  1253. <?php if ($admin || $companyAdmin) : ?>
  1254. <input type="text" style="text-align:right" class="form-control input-sm" name="additional_count_<?php echo $idType; ?>" value="<?php echo $additionalCount; ?>"/>
  1255. <?php else : ?>
  1256. <?php echo $ilosc; ?>
  1257. <?php endif; ?>
  1258. </td>
  1259. <td style="padding:0 6px; text-align:right">
  1260. <?php if ($admin || $companyAdmin) : ?>
  1261. <input type="text" style="text-align:right" class="form-control input-sm" name="additional_unit_<?php echo $idType; ?>" value="<?php echo $additionalUnit; ?>"/>
  1262. <?php else : ?>
  1263. <?php echo $jednostka; ?>
  1264. <?php endif; ?>
  1265. </td>
  1266. <td style="padding:3px 6px; text-align:right">
  1267. <?php if ($admin || $companyAdmin) : ?>
  1268. <input type="text" style="text-align:right" class="form-control input-sm" name="additional_price_<?php echo $idType; ?>" value="<?php echo $additionalPrice; ?>"/>
  1269. <?php else : ?>
  1270. <?php echo number_format($price, 2, ',', ' '); ?>
  1271. <?php endif; ?>
  1272. </td>
  1273. <td style="padding:3px 6px; text-align:right">
  1274. <?php if ($admin || $companyAdmin) : ?>
  1275. <input type="text" style="text-align:right" class="form-control input-sm" name="additional_work_price_<?php echo $idType; ?>" value="<?php echo $additionalWorkPrice; ?>"/>
  1276. <?php else : ?>
  1277. <?php echo number_format($workPrice, 2, ',', ' '); ?>
  1278. <?php endif; ?>
  1279. </td>
  1280. <?php if ($admin) : ?>
  1281. <td style="padding:3px 6px; text-align:right"></td>
  1282. <?php endif; ?>
  1283. <?php if (!empty($additionalSummaryTypeCost)) : ?>
  1284. <td style="padding:3px 6px; text-align:right"><?php echo number_format(V::get($idType, 0, $additionalSummaryTypeCost), 2, ',', ' '); ?></td>
  1285. <?php endif; ?>
  1286. <td style="padding:3px 6px; text-align:right">
  1287. <?php if ($admin || $companyAdmin) : ?>
  1288. <input type="text" style="text-align:left" class="form-control input-sm" name="additional_uwagi_<?php echo $idType; ?>" value="<?php echo $uwagi; ?>"/>
  1289. <?php else : ?>
  1290. <?php echo $uwagi; ?>
  1291. <?php endif; ?>
  1292. </td>
  1293. </tr>
  1294. <?php endforeach; ?>
  1295. <?php endif; ?>
  1296. </tbody>
  1297. </table>
  1298. <?php $tblCols = 4 + ($admin ? 1 : 0) + ((!empty($summaryTypeCost))? 1 : 0); ?>
  1299. <?php if (!empty($dataSubProj)) : ?>
  1300. <p style="page-break-before:always; margin-top:60px"></p>
  1301. <h3>Składowe wg projektów podrzędnych:</h3>
  1302. <?php foreach ($dataSubProj as $idSubProj => $subProjData) : ?>
  1303. <table class="tabel table-bordered table-hover" style="width:100%; margin-bottom:6px; page-break-inside:avoid">
  1304. <tbody>
  1305. <tr>
  1306. <th colspan="<?php echo $tblCols + 1; ?>"
  1307. style="padding:0 6px">
  1308. <h4>Projekt <?php echo $idSubProj; ?>: <i><?php echo $this->getModel($idProject)->getProjectName($idSubProj); ?></i>:</h4>
  1309. </th>
  1310. </tr>
  1311. <?php foreach ($subProjData as $idLayer => $layData) : ?>
  1312. <tr>
  1313. <td colspan="<?php echo $tblCols + 1; ?>"
  1314. style="padding:0 6px; font-size:1.2em; line-height:2em"> &mdash; <?php echo $conf['layer'][$idLayer]['label']; ?></td>
  1315. </tr>
  1316. <tr>
  1317. <td style="width:24px"></td>
  1318. <td style="color:#888; padding:0 6px">typ</td>
  1319. <td style="color:#888; padding:0 6px; text-align:right">ilość</td>
  1320. <td style="color:#888; padding:0 6px; text-align:right">jednostka</td>
  1321. <?php if ($admin) : ?>
  1322. <td style="color:#888; padding:0 6px; text-align:right">cena jednostkowa</td>
  1323. <td style="color:#888; padding:0 6px; text-align:right">cena jedn. (domyślna)</td>
  1324. <?php endif; ?>
  1325. <?php if (!empty($subProjCost)) : ?>
  1326. <td style="color:#888; padding:0 6px; text-align:right">szacowany koszt [zł]</td>
  1327. <?php endif; ?>
  1328. </tr>
  1329. <?php foreach ($layData as $idType => $typeData) : ?>
  1330. <?php if (!$typeData['idType']) : ?>
  1331. <tr>
  1332. <td colspan="4">
  1333. <?php if ($admin) {
  1334. $fixLink = 'index.php?MENU_INIT=VIEWTABLE_AJAX&ZASOB_ID=' . $conf['layer'][$idLayer]['tabela_id'];
  1335. $fixLink .= '&f_' . $conf['layer'][$idLayer]['zasob_field'] . '=%3D' . $typeData['type'];
  1336. $fixLink .= '&_hash=' . uniqid();
  1337. $fixProjectLink = '<a target="_blank" href="' . $fixLink . "&f_ID_PROJECT={$idProject}" . '">' . "Popraw" . '</a>' . " (dane dla projektu [{$idProject}])";
  1338. $fixAllLink = '<a target="_blank" href="' . $fixLink . '">' . "Popraw wszystkie" . '</a>';
  1339. UI::alert('danger', "Niezdefiniowany typ: <code>{$typeData['type']}</code> - {$fixProjectLink}, {$fixAllLink}");
  1340. } ?>
  1341. <?php DBG::_('DBG', '>1', "Error conf", $conf, __CLASS__, __FUNCTION__, __LINE__); ?>
  1342. <?php DBG::_('DBG', '>1', "Error", $typeData, __CLASS__, __FUNCTION__, __LINE__); ?>
  1343. </td>
  1344. </tr>
  1345. <?php else : ?>
  1346. <?php $defPrice = (!empty($defCennik[$typeData['idType']]['price']))? $defCennik[$typeData['idType']]['price'] : 0; ?>
  1347. <?php $price = (!empty($cennik[$typeData['idType']]['price']))? $cennik[$typeData['idType']]['price'] : $defPrice; ?>
  1348. <tr>
  1349. <td style="width:24px"></td>
  1350. <td style="padding:0 6px" title="[<?php echo $typeData['idType']; ?>] <?php echo $typeData['type']; ?>"> &ndash; <?php echo $typeData['type']; ?></td>
  1351. <td style="padding:0 6px; text-align:right"><?php echo $typeData['ilosc']; ?></td>
  1352. <td style="padding:0 6px; text-align:right"><?= $typeData['jednostka']; ?></td>
  1353. <?php if ($admin) : ?>
  1354. <td style="padding:3px 6px; text-align:right">
  1355. <input type="text" style="text-align:right" class="form-control input-sm" name="price_<?php echo $typeData['idType']; ?>" value="<?php echo $price; ?>"/>
  1356. </td>
  1357. <?php endif; ?>
  1358. <?php if ($admin) : ?>
  1359. <td style="padding:3px 6px; text-align:right"><?php echo $defPrice; ?></td>
  1360. <?php endif; ?>
  1361. <?php if (!empty($subProjCost)) : ?>
  1362. <td style="padding:3px 6px; text-align:right"><?php echo number_format(V::get($typeData['idType'], 0, $subProjCost[$idSubProj]), 2, ',', ' '); ?></td>
  1363. <?php endif; ?>
  1364. </tr>
  1365. <?php endif; ?>
  1366. <?php endforeach; ?>
  1367. <?php endforeach; ?>
  1368. <?php endforeach; ?>
  1369. </tbody>
  1370. </table>
  1371. <?php endif; ?>
  1372. <link rel="stylesheet" type="text/css" href="static/sweetalert2.min.css">
  1373. <script src="static/sweetalert2.min.js"></script>
  1374. <?php if ($priceEditJs) : ?>
  1375. <script>
  1376. (function(){
  1377. var _updateProjektyOfertaSaveLink = '<?= $priceEditJs ?>';
  1378. jQuery(document).on('p5UIBtnAjax:Kosztorys:updateProjektyOferta:click', function(e, n, payload) {
  1379. <?php if (DBG::isActive()) : ?>console.log('event p5UIBtnAjax:Kosztorys:updateProjektyOferta:click', n, payload);<?php endif; ?>
  1380. });
  1381. jQuery(document).on('p5UIBtnAjax:Kosztorys:updateProjektyOferta:ajaxLoaded', function(e, n, payload) {
  1382. <?php if (DBG::isActive()) : ?>console.log('event p5UIBtnAjax:Kosztorys:updateProjektyOferta:ajaxLoaded', n, payload);<?php endif; ?>
  1383. if ('success' != payload.type) {
  1384. jQuery.notify(payload.msg, payload.type);
  1385. return;
  1386. }
  1387. if (payload.body && payload.body.id > 0) {
  1388. jQuery(n).text(p5Utils__pricePrintPL(payload.body.price));
  1389. }
  1390. var id = payload.body.id;
  1391. var price = payload.body.price;
  1392. <?php if (DBG::isActive()) : ?>console.log('event p5UIBtnAjax:Kosztorys:updateProjektyOferta:ajaxLoaded price', price, 'PL', p5Utils__pricePrintPL(price));<?php endif; ?>
  1393. var unitType = payload.body.unitType;
  1394. var label = payload.body.label || '['+id+']';
  1395. label += '<br><i style="color:#999">(cena domyślna: ' + p5Utils__pricePrintPL(payload.body.defaultPrice) + ')</i>';
  1396. swal({
  1397. title: 'Cena ' + (('robocizna' == unitType) ? 'robocizny' : 'zasobu') + ' [' + id + ']:',
  1398. html: label,
  1399. animation: false,
  1400. input: 'text',
  1401. inputPlaceholder: '0,00',
  1402. inputValue: (0 === price) ? price : p5Utils__pricePrintPL(price),
  1403. showCancelButton: true,
  1404. confirmButtonText: 'Zapisz',
  1405. showLoaderOnConfirm: true,
  1406. preConfirm: Kosztorys__saveFormUpdateProjectOferta(id, unitType),
  1407. allowOutsideClick: false
  1408. }).then(function(responseBody) {
  1409. <?php if (DBG::isActive()) : ?>console.log('event p5UIBtnAjax:Kosztorys:savedFormUpdateProjectOferta:ajaxLoaded', responseBody);<?php endif; ?>
  1410. if ('success' != responseBody.type) {
  1411. jQuery.notify(responseBody.msg || 'Wystąpiły błędy podczas aktualizacji ceny dla ['+id+']', 'error')
  1412. return;
  1413. }
  1414. jQuery.notify(responseBody.msg || 'Zaktualizowano cenę za ['+id+']', 'success')
  1415. jQuery.notify('Odśwież stronę żeby zobaczyć zmiany', 'info')
  1416. jQuery(n).removeClass('type_price-UNDEFINED')
  1417. jQuery(n).removeClass('type_price-GLOBAL')
  1418. jQuery(n).addClass('type_price-PROJECT')
  1419. jQuery(n).text(p5Utils__pricePrintPL(responseBody.price))
  1420. // TODO: update dom price
  1421. // if (responseBody.update_data) {
  1422. // budget__renderCosts(responseBody.update_data['costs']);
  1423. // }
  1424. }).catch(function(e) {// eg. hit Cancel
  1425. })
  1426. });
  1427. function Kosztorys__saveFormUpdateProjectOferta(idType, type) {
  1428. var idType = idType, type = type;// TODO: zasob / robocizna
  1429. return function(price) {
  1430. return new Promise(function(resolve, reject) {
  1431. price = p5Utils__parseFloatOrZero(price)
  1432. if (price < 0) {
  1433. reject('Kwota musi być nie mniejsza od zera.')
  1434. } else {
  1435. superagent
  1436. .post(_updateProjektyOfertaSaveLink + '&idType=' + idType + '&unitType=' + type)
  1437. .type('json') // header ĺapplication/x-www-form-urlencoded' requires type('form');
  1438. .send({
  1439. price: price
  1440. })
  1441. .set('Accept', 'application/json')
  1442. .end(function(err, res) {
  1443. <?php if (DBG::isActive()) : ?>console.log('#widget::Kosztorys/saveFormUpdateProjectOferta: res:', res, 'res.body:', res.body);<?php endif; ?>
  1444. if (err || !res.ok || 'application/json' !== res.type) reject("Request error")
  1445. if (!res.body.id || res.body.id <= 0) reject(res.body.msg || "Wystąpiły błędy podczas dodawaniu kosztu")
  1446. resolve(res.body)
  1447. })
  1448. }
  1449. })
  1450. }
  1451. }
  1452. $(function () {
  1453. $('[data-toggle="popover"]').popover()
  1454. })
  1455. })();
  1456. </script>
  1457. <?php endif; ?>
  1458. <?php
  1459. }
  1460. public function checkGeomDuplicate() {
  1461. // TODO: for every schema.layer
  1462. $sqlTblName = 'Rozdzielcza_Kabel_Swiatlowodowy_wsg84';
  1463. $sql = "select a.ID, b.ID, aswkt(a.the_geom)
  1464. from `{$sqlTblName}` a
  1465. join `$sqlTblName` b on(b.the_geom = a.the_geom and a.ID != b.ID)
  1466. ";
  1467. }
  1468. public function getKosztorysData($idProject, $korespType = '', $idKoresp = 0, $admin = 0, $fetchAllRows = false) {
  1469. static $_data = null;
  1470. if (null === $_data) {
  1471. $idSubProject = $this->getModel($idProject)->getSubProjectIds();
  1472. $idSubProject[] = $idProject;
  1473. $_data = $this->fetchData($idSubProject, $korespType, $idKoresp, $admin, $fetchAllRows);
  1474. }
  1475. return $_data;
  1476. }
  1477. public function fetchData($idProject, $korespType = '', $idKoresp = 0, $admin = 0, $fetchAllRows = false) {
  1478. DBG::log(null, 'string', "fetchData(\$idProject, {$korespType}, {$idKoresp})");
  1479. $data = array();
  1480. $data['summary'] = array();// [ $idType ] = ['type', 'jednostka', 'ilosc']
  1481. $data['rawDataByType'] = array();
  1482. if (empty($idProject)) return $data;
  1483. $schema = ProjectKosztorysSchema::getSchema();// OK only 'config'
  1484. $conf = $schema['config'];
  1485. foreach ($conf['layer'] as $idLayer => $layer) {
  1486. if (!$layer['tabela_name']) continue;// TODO: throw error in validate
  1487. if ('ZASOB' == $layer['zasob_type']) {
  1488. } else if ('ZASOB_ID' == $layer['zasob_type']) {
  1489. } else if ('ID_ZASOB' == $layer['zasob_type']) {
  1490. } else {
  1491. continue;// TODO: validate config error
  1492. }
  1493. $tblName = $layer['tabela_name'];
  1494. $sqlIloscField = (!empty($layer['ilosc_field']))? $layer['ilosc_field'] : 'ID';
  1495. $sqlIlosc = (!empty($layer['ilosc_field'])) ? "sum(t.{$sqlIloscField})" : "count(1)";
  1496. $sqlZasobField = (!empty($layer['zasob_field']))? $layer['zasob_field'] : 'ID';
  1497. $sqlGroupBy = "group by t.ID_PROJECT" . ((!empty($layer['zasob_field']))? ", t.{$sqlZasobField}" : '');
  1498. if ($fetchAllRows) $sqlGroupBy = "group by t.ID";
  1499. $sqlIdProject = (is_array($idProject))? implode(",", $idProject) : (int)$idProject;
  1500. $cols = [
  1501. "t.{$sqlZasobField}",
  1502. "t.ID_PROJECT",
  1503. "{$sqlIlosc} as ilosc",
  1504. "count(1) as ilosc_sztuk",
  1505. ];
  1506. // if ($fetchAllRows) array_unshift($cols, "t.ID as primaryKey"); // DBG
  1507. if ($fetchAllRows && 'Rozdzielcza_Kabel_Swiatlowodowy_wsg84' === $layer['tabela_name']) { // TODO: to config - additional columns
  1508. $cols[] = "sum(t.ZapasA) as Suma_ZapasA";
  1509. $cols[] = "sum(t.ZapasB) as Suma_ZapasB";
  1510. }
  1511. $sqlCols = implode(", ", $cols);
  1512. $sql = "
  1513. select {$sqlCols}
  1514. from {$tblName} t
  1515. where t.ID_PROJECT in({$sqlIdProject})
  1516. and t.the_geom is not null
  1517. -- WHERE
  1518. {$sqlGroupBy}
  1519. ";
  1520. $data['_DBG_sql'][$idLayer] = $sql;
  1521. // $rawLayData = DB::getPDO()->fetchAll($sql);
  1522. $remoteIdKorespField = '';
  1523. if ($idKoresp > 0) {
  1524. switch ($korespType) {
  1525. case 'ZLECENIE': $remoteIdKorespField = "ID_KORESP_ZLECENIE"; break;
  1526. case 'PROTOK_ODB': $remoteIdKorespField = "ID_KORESP_PROTOK_ODB"; break;
  1527. default: // throw new Exception("Not implemented koresp type '{$korespType}'");
  1528. }
  1529. }
  1530. DBG::log($remoteIdKorespField, 'string', "'{$tblName}' \$remoteIdKorespField");
  1531. try {
  1532. if ($remoteIdKorespField) {
  1533. $sqlWithOrder = str_replace("-- WHERE", "and t.{$remoteIdKorespField} = '{$idKoresp}'", $sql);
  1534. $data['_DBG_sql_idOrder'][$idLayer] = $sqlWithOrder;
  1535. $rawLayData = DB::getPDO()->fetchAll($sqlWithOrder);
  1536. } else {
  1537. $rawLayData = DB::getPDO()->fetchAll($sql);
  1538. }
  1539. } catch (Exception $e) {
  1540. DBG::log($e);
  1541. if (1 != V::get('_print', '', $_GET)) UI::alert('danger', "Brak pola `{$remoteIdKorespField}` w tabeli `$tblName`");
  1542. $rawLayData = DB::getPDO()->fetchAll($sql);
  1543. }
  1544. $rawLayData = array_filter($rawLayData, function($row) {
  1545. return ($row['ilosc'] > 0);
  1546. });
  1547. foreach ($rawLayData as $idx => &$row) {
  1548. if ('ZASOB' == $layer['zasob_type']) {
  1549. $row['type'] = trim($row[$sqlZasobField]);
  1550. $row['idType'] = array_search($row['type'], $conf['type']);
  1551. } else if ('ZASOB_ID' == $layer['zasob_type']) {
  1552. $row['type'] = $layer['zasob_label'];
  1553. $row['idType'] = (array_key_exists($layer['zasob_id'], $conf['type']))? $layer['zasob_id'] : null;
  1554. } else if ('ID_ZASOB' == $layer['zasob_type']) {
  1555. $row['type'] = (array_key_exists($row[$sqlZasobField], $conf['type']))? $conf['type'][ $row[$sqlZasobField] ] : null;
  1556. $row['idType'] = $row[$sqlZasobField];
  1557. }
  1558. $idType = $row['idType'];
  1559. $row['idLayer'] = $idLayer;
  1560. $row['jednostka'] = $conf['layer'][$idLayer]['jednostka'];
  1561. if (!empty($conf['layer'][$idLayer]['jednostka_zasob_id'][$idType])) {
  1562. $row['jednostka'] = $conf['layer'][$idLayer]['jednostka_zasob_id'][$idType];
  1563. if ('SZTUKA' == $row['jednostka']) {
  1564. $row['ilosc'] = $row['ilosc_sztuk'];
  1565. }
  1566. }
  1567. unset($row['ilosc_sztuk']);
  1568. unset($row[$sqlZasobField]);
  1569. $data['rawDataByType'][] = $row;
  1570. }
  1571. }
  1572. //DBG::_(true, true, "data", $data, __CLASS__, __FUNCTION__, __LINE__);
  1573. //DBG::table("data['rawDataByType']", $data['rawDataByType'], __CLASS__, __FUNCTION__, __LINE__);
  1574. if (true) { // $admin) {
  1575. foreach ($data['rawDataByType'] as $row) {
  1576. $layer = $conf['layer'][$row['idLayer']];
  1577. if ($row['idType'] <= 0) {
  1578. echo UI::h('div', [ 'class' => "alert alert-warning" ], [
  1579. "Pomijanie nieznanego oznaczenia '{$row['type']}' w ilości {$row['ilosc']} - warstwa '{$layer['label']}' ({$layer['tabela_name']}), projekt nr {$row['ID_PROJECT']}",
  1580. " - ",
  1581. UI::hButtonPost("dodaj typ '{$row['type']}'", [
  1582. 'class' => "btn btn-warning",
  1583. 'data' => [
  1584. '_postTask' => 'addTypKosztu',
  1585. // {$row['type']}' w ilości {$row['ilosc']} - warstwa '{$layer['label']}' ({$layer['tabela_name']}), projekt nr {$row['ID_PROJECT']}",
  1586. // '1xHDPE 40/3,7' w ilości 10 - warstwa 'Rury osłonowe' (Rozdzielcza_rura_oslonowa_magistralna), projekt nr 6906
  1587. 'koszt' => $row['type'],
  1588. 'idLayer' => $row['idLayer'],
  1589. 'table' => $layer['tabela_name'],
  1590. ]
  1591. ])
  1592. ]);
  1593. }
  1594. }
  1595. }
  1596. $data['rawDataByType'] = array_filter($data['rawDataByType'], function($row) {
  1597. return ($row['idType'] > 0);
  1598. });
  1599. //DBG::table("data['rawDataByType'] - clean", $data['rawDataByType'], __CLASS__, __FUNCTION__, __LINE__);
  1600. $data['by_layer'] = array_reduce($data['rawDataByType'], function($result, $row) use ($fetchAllRows, $conf) {
  1601. $idLayer = $row['idLayer'];
  1602. $idType = $row['idType'];
  1603. if (!array_key_exists($idLayer, $result)) $result[$idLayer] = array();
  1604. // TODO: if $dontGroupByZasobType then $result[$idLayer][] = $row;
  1605. // if ($fetchAllRows) {
  1606. // $result[$idLayer][] = $row;
  1607. // } else {
  1608. if (!array_key_exists($idType, $result[$idLayer])) {
  1609. $result[$idLayer][$idType] = $row;
  1610. } else {
  1611. $result[$idLayer][$idType]['ilosc'] += $row['ilosc'];
  1612. // TODO: sum ZapasA, ZapasB
  1613. $layer = $conf['layer'][$idLayer];
  1614. if ($fetchAllRows && 'Rozdzielcza_Kabel_Swiatlowodowy_wsg84' === $layer['tabela_name']) {
  1615. $result[$idLayer][$idType]['Suma_ZapasA'] += $row['Suma_ZapasA'];
  1616. $result[$idLayer][$idType]['Suma_ZapasB'] += $row['Suma_ZapasB'];
  1617. }
  1618. }
  1619. // }
  1620. return $result;
  1621. }, array());
  1622. //DBG::_(true, true, "data['by_layer']", $data['by_layer'], __CLASS__, __FUNCTION__, __LINE__);
  1623. $data['summary'] = array();
  1624. foreach ($data['by_layer'] as $idLayer => $iloscByType) {
  1625. $layData = array();
  1626. $layData['label'] = $conf['layer'][$idLayer]['label'];
  1627. $layData['data'] = $iloscByType;
  1628. // TODO: ProjektyKosztyWstepnychRobot
  1629. //foreach ($layData['data'] as &$iloscData) {
  1630. // $iloscData['jednostka'] = $conf['layer'][$idLayer]['jednostka'];
  1631. //}
  1632. $data['summary'][$idLayer] = $layData;
  1633. }
  1634. //DBG::_(true, true, "data['summary']", $data['summary'], __CLASS__, __FUNCTION__, __LINE__);
  1635. $data['by_project'] = array_reduce($data['rawDataByType'], function($result, $row) {
  1636. $idProj = $row['ID_PROJECT'];
  1637. $idLayer = $row['idLayer'];
  1638. $idType = $row['idType'];
  1639. if (!array_key_exists($idProj, $result)) $result[$idProj] = array();
  1640. if (!array_key_exists($idLayer, $result[$idProj])) $result[$idProj][$idLayer] = array();
  1641. if (!array_key_exists($idType, $result[$idProj][$idLayer])) {
  1642. $result[$idProj][$idLayer][$idType] = $row;
  1643. } else {
  1644. $result[$idProj][$idLayer][$idType]['ilosc'] += $row['ilosc'];
  1645. }
  1646. return $result;
  1647. }, array());
  1648. //DBG::_(true, true, "data['by_project']", $data['by_project'], __CLASS__, __FUNCTION__, __LINE__);
  1649. return $data;
  1650. }
  1651. function execPostTasks() {
  1652. $postTask = V::get('_postTask', '', $_POST);
  1653. try {
  1654. switch ($postTask) {
  1655. case 'addTypKosztu': return $this->addTypKosztu();
  1656. default: ;
  1657. }
  1658. } catch (AlertSuccessException $e) {
  1659. DBG::log($e);
  1660. UI::alert('success', $e->getMessage());
  1661. } catch (Exception $e) {
  1662. DBG::log($e);
  1663. UI::alert('danger', $e->getMessage());
  1664. }
  1665. }
  1666. function addTypKosztu() {
  1667. $koszt = V::get('koszt', '', $_POST);
  1668. $idLayer = V::get('idLayer', 0, $_POST, 'int');
  1669. $table = V::get('table', '', $_POST);
  1670. $schema = ProjectKosztorysSchema::getSchema();// OK only 'config'
  1671. $conf = $schema['config'];
  1672. DBG::log($conf, 'array', '$conf');
  1673. $idType = array_search($koszt, $conf['type']);
  1674. DBG::log("DBG:addTypKosztu \$idType({$idType})");
  1675. if (!$idType) {
  1676. $row = [
  1677. 'PARENT_ID' => ProjectKosztorysSchema::$ID_ZASOB_KOSZTORYS_CONFIG,
  1678. 'TYPE' => "TYP_KOSZTU",
  1679. 'DESC' => $koszt,
  1680. 'DESC_PL' => $koszt,
  1681. ];
  1682. DBG::log($row, 'array', "insert into CRM_LISTA_ZASOBOW type: '{$koszt}' under ROOT");
  1683. $idType = DB::getPDO()->insert('CRM_LISTA_ZASOBOW', array_merge($row, [
  1684. 'A_RECORD_CREATE_AUTHOR' => User::getLogin(),
  1685. 'A_RECORD_CREATE_DATE' => "NOW()",
  1686. ]));
  1687. if ($idType > 0) {
  1688. DB::getPDO()->insert('CRM_LISTA_ZASOBOW_HIST', array_merge($row, [
  1689. 'A_RECORD_CREATE_AUTHOR' => User::getLogin(),
  1690. 'A_RECORD_CREATE_DATE' => "NOW()",
  1691. ]));
  1692. }
  1693. }
  1694. if (!array_key_exists($idLayer, $conf['layer'])) {
  1695. throw new Exception("Layer id {$idLayer} not exists in schema");
  1696. }
  1697. $layConf = $conf['layer'][$idLayer];
  1698. $layIdType = array_search($koszt, $layConf['type']);
  1699. DBG::log("DBG:addTypKosztu \$layIdType({$layIdType})");
  1700. if (!$layIdType) {
  1701. $row = [
  1702. 'PARENT_ID' => $idLayer,
  1703. 'ALIAS_ID' => $idType,
  1704. 'TYPE' => "INNE",
  1705. 'DESC' => "TYPE",
  1706. ];
  1707. DBG::log($row, 'array', "insert into CRM_LISTA_ZASOBOW type: '{$koszt}' under idLayer({$idLayer})");
  1708. $idType = DB::getPDO()->insert('CRM_LISTA_ZASOBOW', array_merge($row, [
  1709. 'A_RECORD_CREATE_AUTHOR' => User::getLogin(),
  1710. 'A_RECORD_CREATE_DATE' => "NOW()",
  1711. ]));
  1712. if ($idType > 0) {
  1713. DB::getPDO()->insert('CRM_LISTA_ZASOBOW_HIST', array_merge($row, [
  1714. 'A_RECORD_CREATE_AUTHOR' => User::getLogin(),
  1715. 'A_RECORD_CREATE_DATE' => "NOW()",
  1716. ]));
  1717. }
  1718. }
  1719. throw new AlertSuccessException("Dodano typ '{$koszt}'");
  1720. }
  1721. }