From eed702884178baa0d6c3e0d95fe4d68ad6ebac36 Mon Sep 17 00:00:00 2001 From: "sas.fajri" Date: Wed, 15 Apr 2026 15:24:53 +0700 Subject: [PATCH] Batch 6f: application controller leftovers --- application/.htaccess | 6 + application/controllers/Arial_Narrow.ttf | Bin 0 -> 179492 bytes application/controllers/Auth_placeholder.php | 131 ++ .../controllers/Auth_placeholder_v2.php | 92 ++ application/controllers/Diagnosticreport.php | 375 ++++++ application/controllers/Dummy_login.php | 17 + application/controllers/Ext_rspad.php | 237 ++++ application/controllers/File_upload.php | 496 +++++++ application/controllers/Imgtoken.php | 39 + application/controllers/Info.php | 22 + application/controllers/Json_placeholder.php | 233 ++++ application/controllers/Merge_rpt.php | 531 ++++++++ application/controllers/Odoo.php | 644 +++++++++ application/controllers/Or_dummy.php | 26 + application/controllers/PushOrder.http | 100 ++ application/controllers/PushOrder.php | 44 + application/controllers/Random_saran.php | 42 + application/controllers/Search.php | 856 ++++++++++++ application/controllers/Station.php | 479 +++++++ application/controllers/Test_api.php | 18 + application/controllers/Test_rpt.php | 18 + application/controllers/Timesheet.php | 343 +++++ application/controllers/Timesheet_v2.php | 575 +++++++++ application/controllers/Timesheet_v3.php | 189 +++ application/controllers/Ttv_dummy.php | 47 + application/controllers/Wa_webhook.php | 58 + application/controllers/Welcome.php | 25 + application/controllers/Xraw.php | 13 + application/controllers/index.html | 11 + application/controllers/mockup/Subgroup.php | 1145 +++++++++++++++++ 30 files changed, 6812 insertions(+) create mode 100755 application/.htaccess create mode 100644 application/controllers/Arial_Narrow.ttf create mode 100644 application/controllers/Auth_placeholder.php create mode 100644 application/controllers/Auth_placeholder_v2.php create mode 100644 application/controllers/Diagnosticreport.php create mode 100644 application/controllers/Dummy_login.php create mode 100644 application/controllers/Ext_rspad.php create mode 100644 application/controllers/File_upload.php create mode 100644 application/controllers/Imgtoken.php create mode 100644 application/controllers/Info.php create mode 100644 application/controllers/Json_placeholder.php create mode 100644 application/controllers/Merge_rpt.php create mode 100644 application/controllers/Odoo.php create mode 100644 application/controllers/Or_dummy.php create mode 100644 application/controllers/PushOrder.http create mode 100644 application/controllers/PushOrder.php create mode 100644 application/controllers/Random_saran.php create mode 100644 application/controllers/Search.php create mode 100644 application/controllers/Station.php create mode 100644 application/controllers/Test_api.php create mode 100644 application/controllers/Test_rpt.php create mode 100644 application/controllers/Timesheet.php create mode 100644 application/controllers/Timesheet_v2.php create mode 100644 application/controllers/Timesheet_v3.php create mode 100644 application/controllers/Ttv_dummy.php create mode 100644 application/controllers/Wa_webhook.php create mode 100755 application/controllers/Welcome.php create mode 100644 application/controllers/Xraw.php create mode 100755 application/controllers/index.html create mode 100644 application/controllers/mockup/Subgroup.php diff --git a/application/.htaccess b/application/.htaccess new file mode 100755 index 00000000..6c63ed4c --- /dev/null +++ b/application/.htaccess @@ -0,0 +1,6 @@ + + Require all denied + + + Deny from all + \ No newline at end of file diff --git a/application/controllers/Arial_Narrow.ttf b/application/controllers/Arial_Narrow.ttf new file mode 100644 index 0000000000000000000000000000000000000000..9d92f4f54370f017a459b47cb9c73203f2601281 GIT binary patch literal 179492 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

3Qd=ohQqU^h{o zq;7MHQ2!1yy$bmJcJg+=gtmep3ECq4Z6lZ9CkJ8`#fu?|PP^SDSU|VSj5j0!q!MvN z5&)rjB7z1;&I;nKHhqasqLk>Q9C^0@L)~GMU4p~x7RV!S1MP5FI!z8yGE0(3vlvpu zMRIBag`7lz_zEUy>muNY*CYTC%27a>O>kha;Ih>tOEw6V7H@~kPFMpfAY?nuQHLyx zE{9Wwz%h}*cIrWsK6JB)xkl`_S|Lxsgr=K|RIE1LN#G{v4ZDU-HE3kOs@ZOr1qjsQ zpqT~5)8mXr8h}?2L{V@`q7n1M1?ycxP82+V0pT3j!JHu@2Cz1`sHq9c26`1wH=3YP zL;?THQ0fvDQ5CL~)nY1xc`1rslS%MOZivh-I^13XZz>+y3DygCXi=g=@_Ov3WiSYk znI1^P)W zw2PSbqDeHNsnLn|9T*zu#15WApPQX9w*sn@yfYw^Y7*U&wn%^5NETIcpfng%WZCHw zolaS@3VO3lmWznhiHIYT1du|Wh@b(&fyUsX7G^LohkvtilQx9Y>@p&uls!>qb_y<+AMd?>w+AA_ zMD+MY7zJL;0CeF1EQk)b-|O%bHnH`BsSmRSFY>@9ngEe-KnLJi+5{l`+w6b{1-nsl zK-f_KD3N7ZaFZ-ay!Xx3{;dYWIqM$g) z8wi$mhrUE7QA%`Dj=WbAZ3fZd_qYYCS0ax*v?GQslhG`?JyzKx)A9i+8bwhC<|NSx z{o{5SvA}`_n1Yzbcm|dUXhpl^B6+z)4{R!^6~!+*!7zvk`ot+=4F@V9WWu>i^m^T1 zQSwXBtQIHO4*L=Ugu|LI+nsi|EI@%lo(>C?fyn@%!=SU9{Q>NIKwvZ&!e%tCVbkIi zd@j7wSOslnXl96+}6qic`$m{|M3v~rdDTfit4eu`w zlR#@etXvB)=XSYe(uQ!FT}Id}Wlxmh)yM4)SS+r9?1RWKNMFDOlSJ`}00Z)}AOu`4 zIiLsu>~I+Idh60-`NJ{~aRo^!xTsqQ0PuwU-RlG+mQ07qEx16uwx#IxdPP|-X zA&3@qE?~aVMKEI1(n{+f;A?SP(9|Sqc>;+O(?+mKR?JLmBr1{@BR*O--9Fj(ot!&L z4wS~?A-`Yp!07bLc8I`l!yA&@28uu&k>mm?|IfH;*Zc&mUYro=AB)1BIJJH&Oo@{~(Yd$)4cws(x zz<#F#=!U6I)6MS@$U?9Lf-Vvo1SOjAf7vXSFf(8k28D)A8&nnclTSFzGE6RD6M95&O!8z6A2h#u+zp7!=FG=V^!zSqPr~yI6rUbC*bQyq6ClsI2T*4-G3(ZCPp%FE1t5|;_Zo(L<73k$HMcn!|qv92?d^s#?s0W)E3}G`_u3^*WmclZJ8b+BUkOsvo8gT8Ey?$@0 zSM8mF82r^kwD$;`goz!tTIH}m0Fhykfv}91q@e0{qYFv);h&0S*&hx`VVJQdKuI=8 zFsTIzySZ^R0V3h>h5`LRZ~i?_0xaEv8ToL?=;7bW)Cd$csfmmcpvvZ4Y_L zBQHr_`j=~ZUzQcs5l|JFHXcY37sX2g#nLAGeP-E3#tdHaAy9h7vtz}E`Q{^e`Q(7; z1($_rB;W$W@Y3UvgBZOFeV_{r!UtKaL4Q#8Mj&v}2J~aicep&rNKi})OaZ^*_K5<} zE!m))&8DD&y%|jRaLhw8gP`1I6R?@dS{d?ok2~U{mny&kdv+%rMgjmPd_G0-c~r$J z`P?Bz^{L1yzL?KPor!L2*5OqE&44&_h#F(zb4!F$?1W&#Dn3P3N}X!&3`D|-XK0Px zcG;sSahuH-SHqa#Zoem-@WD8ZMm!#y>~s49Zg<@0Q{yo=YMISGkK{9A`I7)Hv#p$z zf{(hz8wSY$uVFpTZHAVVEZ_%-mt~Z~)bprrs}BTX?eW;qxf@fREW0d}TY_6A^DRK~3i!e<1zeWO5+T{E zpuNlIi$ZQP`alMMIvg{rz8{@e-0Ti#F{VrN!);E5bIMg=*5x?dBSLspbH~G z7zLQ_@uZJr20?kObZ%F^O2a1D9aqS{@M0&;`jtg*wPI>}Qi=kJ`$DP}GK{GBM|b2@ zr3`=tr(7Ov*10_pqQ`7@n}H>4+_|kD@DoqBIxt~XMGdK?UQrQM;YwL8ruPVk>L zjYY701RzCRBB~}(=pP^!_B~0`EkR0nh8xx)R(v%?@(L+284Akku1H0_e$oLj{}Vn{ z^`Z}8LiPDWN>GW#!wE%AsUENF^uqM?ctmdirWQJNN1$%Q5$IKSQ1*D7PzF|WJmSIo zncJSK2$0YqD4&MSLamJftAgSySFtxD`n8!wQ%Z9-8`el)MpeUMRf&dekYPL=Rins- z)p7t?4Bgf{YoF&u2Y_|aMoM@bvPp(3in(Y42sDdhAi;c(jN zRMXKifD03`EUm&gO<@M03!fVC`O>NyO_%#n%VGhPRFlu?#B|56kgCu`RjFINVL*S` zVCwcbp9Qe=*up-@&FA-{G#-yDQIcgC-lsUxxeq60(8Xu**?nTz7xqPcVP_bqg!U9D zPayGzp@Uqih?yx=6%_JHb(ufx4~G+x#CLIJ;X*YWD6Of@r&4Mx98gkGSI8`+q%dCI zU7!fW5lJdYAx}im0O7!8)g${XB|3>xqLXsu%fl+}`_g4mMJf-IN8aZPW7u&rn$=jD zlqieaR5b`G;t~&Q0)_sGMQp0#B1yuu^x0$&rXtobh%!R*il_;12we75rW5`E=>Ts~ zO+g|1(FZUQRss>oI#nJ`si8Ck?iKt#)eZIP41f|$4(3^Gr>nU{$0RWz` z?x%j2pm6D5zlqD0BSrPsZ1S-Cq^ zp0pFo)F>{=Xov&~{ZkgVhoP+@8?PGz#WTD(83^W1G*0r0hg1G&82ik9a;ZQt8V=E{ zOsmmoAOuuE$Z9Yij)g1IiF7EMgTVb_K!MGpxC3Fo;)h-9ErTggRu+Ug81qBuJ})fb ziZaCwb5+Pzg-K`-lxnvEn~ei-U<@|D)IcU`!3I|lTP2RKta^t7%TAyw8im9|$+*KG z4OGOF(Ij$lJUtphTW>%N1pGMeC=h^}wN+4S(eDWOx7Y zRVEp7=i=m%4+Ihzc7=$&s%UvePG`y;#IaBumx_3V1R9D)Q)P~5$OB2@B_C44GyJZA z>czrcM)E3)rj@QTMgHTWrOoeDR6psfZKm~*x3YSF_(QGc2jl`?sc;S+Qfv8ti zJ;4|W+VAz3!xTuBW6k%Mk`{s&7s2u2CT}FNFiy% z7EP397Fi}GCkPloq#>ECs7S^uD+Dze$yZb+E0L>6_5}>kHV|>a`i(@;%x+ihd1~oW zg@{@KrH@?(OxTKKMP)^)M^r>rxKdV&smvXTS5(xyT*>;%D&Q+p9;>QP;uXK9Ivz(C zkz_g&sZS;=>-$Df%WhA`)TAZia;a(r+dBP8DI}@e%F0T}0DG#vE@Fq4RGk%(B#4hj zQ4B*bUKtURAh1FW$6e?gyse;1#2yhN-ik;?q%u zK?->yf(8f&E+;W=dx=h>l<1@!`MwoN+>g{(SH``4E65`siByn*i#-KbGFRp6Qhm`OP)f0&XBB6>5$t#nr3YCM)YGZw$Xreq>mJB76 zHL>#YXc2x-m zPE}>4NIG7Vtx8uRmrXaO(OOqHe3IsB6NGaX4q#B4kb;>*fVQd3its)|c# z5QzDmlF@lQi}BzRcg9_De>R@Qw9m>}8BL{>kMb#W63Z2maW(C$NX5Ow+fw9HBkRg? zWw~5!p4RAZ?do%Fr@-ZMxzS@=8yYIAbE#BAm0D@{_6y`xNDvf(I3g(xQpgh#G(b3T z88bEREYV4n5}lMI-vUoZekE>;wcsv%51S2((M6|jlm5)a9F$g^pfd$-9 zh^vu!SRODWqX~=#;{-M*Ou+$fZnr;~YRox&zCZRfX!mqFWT%9l#TQz5T}sHsGjUgS3aeYHq5{QOOf$79tasJ$sf;g|%B89? z9$ZpFN=~WOsp?d1s@hlWLsNG~p?n6NlojgJscwc}NkLe$`nBG@Z%i>ifEL z=`cwWre(^FXT$^aW>Z$^OY-WQYbvV-m*XQ^8!IZS!SS+uZcw_qx&nQmi|R~e-&`R# zu(_@|SKV5jDlbziQu#r-Jo$=fm# z`yM_Y1eI|Mz~;1>9){OxHIr#AII%^O#p|d?+k4X@j|WO9GrCZyt1IN2>O84JW>8&I zp$WOV!tg>NkG6>nHtSLu?Dl0ODJ2ckHttfMOsWpU!QNjMtqXNcb){ZW5mn(zSuIW? z4pinF8rl@4rmblRCU~YcH)K?e5)2L>n$IiQnoLbYCesECv<=UomL%2WQUwP#2vezy zM^eT>%7p@T3xw3w)nU)A*JY$aDxZ?;G6fKy&7yeFph5YjjHdts>r$D#QpglCbr=sW z87bq9-Nrm`ZK%@h)uOf1_slSyY%iPXSUW%+=CeHzNk`=v9PV0jAL#w`Of zu~a6hw4GW*LW7|49tqf-v%trI)lfb^q8@)66Ro0+6tYZ8&ga7#nV(Q!-_%rJXm0YQ z>+>y5&GpU5HPw%EW6wpN;u*i?EuWuedIzK*ut=szQ zbiFgLs_Asz=L(#PCiV5yZF6%o;E6rAUYB>(rweIMQ@$R=SJ7ruOG`_kIq$0nflcXL zK}F|z%s0B^U3q^#+LUj~H|LwwCKXM6g$U&f=p@^JNOiufK2lrAhfkkVAYYg@qN;yY z|Ng@V4*xE0WdAv{;rjRQKX1Xbwzk?KO*MtK=CXcbXjGzq0zaS##1TpLAcZ^;K?8&X zm+LWZSBXxdl<1@!`O!`FxStgyXIMO<2% zY9Y|-LVf*^fxi0cGLmGv3{t`~(vf_h@_c3gK_st1^~1AG_1MdsGGSO%-=_LH%*y&v zg{G#eI-mkVF7zE(KcIeO+u+f4O%s~(eX`-Ie0?gPFRN9ngNxW z0oi;$oJqTUu2Y8Q%hI{DI=;Puga$zsd@f)Uj;C*Nz{%QoHy9USjKi-pONF@7zY0@0 z+2JPsFCBkLkH5{eHRb8m*TU%G( z(66zn|A2vmng^XDi zoiTsG!ZQ~wK5I$W(zBN>KWD|tRjbckv-Z4o=da(e@q$g8FTCjDOSWv?w*Ar_J1_g* z<-4x9@~W$MUvuqs*WYmCo||sI<<{@tcKaQ7-t`0B4}bLIySw-9yXW5f?tftafd_x` z&`%$JIYcpZev~&pi9w^DnR$fA!L@U;fQ+fA`Ao4;}u)kyn}Ca2Q+b>H+ ztD-g0#%TZOz-UYK{OGOG+oL~>8Dj1jEPHG?P*c}%}bs6558E$D55wq{CnKzyq|v@)c+3DZvyp~>Tc0< zdZ+$W{S5ui@cQt_Q8#u{@wyJ`3(X^91!0sK@qF5A~h#IU4oR|AhK+ zC#c_<+>^ZP1ogiJ^}hr4jVGv|n_Bn}98QfBL0D1738whY&T%aDU+lqk0fF&&|Mtf8*Z)E#j2+#4^orL`JG$xU-(S1q=*puHpk(J!@#vPL=e>5$s|#OUee}Vj zm%e((t5+Vm^2p6cwla3)Hfr^%@5s_4rz2N&r1?nAk+Q?X4!0ief4JY_y2CYxs}83R z#}BKA<-^>e4-UO|=ud~aRKeZ(qxPBZE`R8GnR7S}Nubf8+MQ z$ny8{_xIlB_w}a!>8iuogqzrA{xY0+_!dr8ycB0AUXSx-Z^g;aTc7|gz9>sAL9JlyKs`m$2i0EX7)pz==wO$ot?#I<6Ol#IMa15dxAZM^ZuS@&)_`Q zw{a@ji#W^m1)NHI2KxY~F8&(lxW0t*$=<=qsh8kvvIRIncrjaq)5!MVEV89IiR^5) z45vsg$GN~Oao*}GU}7~+j64tLMLvL&a?i(Ek?V2d@4Gm2^#FGzcNNaK)^U2yfRj?c z;I8I&bJuX!;-u8$oRKqeW>(~`W8AIW_qp4+ z+qpZqJGr~KA8%iI=jD|atFXQanS8>|y?{UiQ5uAYg2kt}eBknKUVeVt@uiPixXWTIy zQvY}EbFPy62loZ{C3l?5LccMd!@oY`$PYRMgE#SJ-ojhC9B3w(mB;mi0WpW@5;3O>ze_)45R zypP|)^~E{E_p`^iH*xmxy*L?oBhCxHh<(bvjdPOU$Em^JXW!!nu^rrCZUuK4G}z_b zO17WF*SngV`ZqQ9YpCyAQ>d=$lh0)G6yHP5kZYhqYuv^&+=txqLJjL11{t=!kZ|ucb$8X?;q|IFO0O z&?4IEpWhPg<~pOT-NRPQ-_qLIlFM>?ZPuZQp>wUdEZb|fA!$RZdsw1tFE?x;rzQAd zt&MwmW_DnV-KQj4TDwOk&=lS1lC3l6bdNi=y%h#atRt80=7!Er%<5)|A>BfyR)r1K z9@A|c+HKMv6J5}a;jpdIz1f3Xw(S?$tjeM5*9XoWBnUr!pF5X~1(6tyI#vFxqWN3`xx2 zval1v3T)|S<5$P_1x{%`fJ3=YX^n1~*q(@W4^k5yGh2dtWwvGf>U%~uM@N4BPAlAttcE`zyxsXEXo|e+8Qwmh~vYI1`5+l2tfw9?9P|}|0=93K+&23;?W;Z}0 za2*^tx&Zv^+#)t&blrxen22uq6gs0b@&2E`UNW<%#F!L6WptC^asqPQ+|1r|cV%UF zCPPRu4TWey*+4B{o6D}~ZcB8D(e5^|jE!qYqmITtV0kP?Qr^11nax6`d;O{HrF@jl zQunduK9wEad?(#G*n7t_iSDfLy>p^@X994(S6di8-R9JZAN)C(yLEnJH|PBqx967b zWBRm4_v#JFE#ul#Gq-G2Q=MD3bpX}FFsrw08J36++tRsZ=KkXPS&68a*s`~+ZA(`x zW@Bkc`-=y+s@=`oI_7g=YIjYE8{O`q?K+hwWFp0@I;6gBe-EO+VcR;o#ZIluwh4*0 zQ>V5^Teo!fOs$?05-Yk@e&NrtX4{eicjzbMB8#sZ7kQA6vQ9JG7kR34KV44m9Gu1< z#za_@&x2QexTWkygu4+QL3kD6Lxds%{`3O4@s3w{4OW9b28xeGTu(|43 zU8L$*^RaQqx{j?sw)5DYV+W6!MHDPK_QEkeJ0>2h!oBs!3>NWN=P|zD*umTJxxJkT zdl0%24k8>yFoH7r++Qaj!2JMT4@AU+5Kc!}f^a^<4ul&KUPUmo2x1N&0#n#HgieI@ z2s;t>AaoF?I_4vQv98(o?QM=Z=DTB4RJi@x7Z z%N|R&<)GyS%Tdcm^r!Hqh^dchkZG*xbkh=(so#yJyG@Uno;ST}`p{Iwf2tXB5rd9; z2}CS{E~4wB)AhSicem~l-SfIvbsy@AI@7BCTwC*OZq?=7s`t57=W(k#xK(SoRTpuq zrf?Butinh9WBokC@976A%}N*kWzR4A2l<=*U4DawDID{2=F>epJpAeM4w+~89l;<^ zvq#VHhr)y8W?64x9uA+_Ge5SUQ}-Dnk3Gbx__Bh5dAY~;{a6>-&pm$ck4-vn`+jch zJymAy+U!7r4I2il(&aKY@8>?dk6Aj_3`FId_N|WLa^t?$6C)47CL6?G15u3Gw>pT@ zQTtXm;xcmI>SkPq?^}HYmtk}nEO3J%0IEBXO*j3OdkD|($EI^J){K<7*|EA1`Ed0a zkq=fciM%^~KYz{rk*8KyMIPUPJ6p~TGW6XSS&FvC zW=o^DYx=u=z4NK^1Ce>tAFcGx#+@Pe4EJJU+YNm&g6mm_cD;tJG0fp?pucTj#~G2q zUTy%JqB{u+kutK2v~e5Q6#fpJMegPFNS*P(h2D=kDkAT%IS}|ep6~th zMF;Fx@Ygikyiar-iQL;UF|uolHj2xq?ANh-Zug#7$}V1`l`f)Ovo|uQBNLf6<#>a4 zm~NPUm|+qfHL&w1+>6jHJGmvz157)gG3~s~v~!(l=UmgynWmkSO*lFDj6Z!fyKsC4{sD>p=ox?Et~c}eYiP!GyLD}R+k_!pTlc})tZi1b`?Cp&{hamG zsojRe5U$(R#@Z$h@pm^=wgKehyX!04x=rIwYv0RpmttADShF4Wa|-1*t7JADU>q0U zyj`Vhar5?$4(7!#K)>nyCknW>ajOr2=i~1;MLsq~7MO6SZ32pRQqj(jO*^$Bf2jM) zwh8UscZE8-3zR5^I@-FIOo&cvKLAVlv(}aaFqv`bXg`20lfS|4KsnD~&b004Y+60m z$sI#Iwwf-ehp%IGQa#pbD3t1rF4dck_NaFTT~H6Ydb(C`y0O$Be+|{!yWx!1mc3^n zLLK`Mwn3}2!9GOm%h0z(+aR=U**hH(YWZI025FQH^1Y5)tgX9F>uJgq)agLf(Z2W7 zDX6h`%BR#z_bFf9UZdSUz>Q~A;Q-(_UaRuRS5+=5RnaZ!t)g3kDqI&h@Yf0L`-a7a zwQg+zKXh+XZl;#ox4Ls!>-+?4)_+~?jOpK|+JpFx+aT6clbsOqNeS+x^uI{X9dgf% z=eF)?g@M?aXq}7D*}Zkee1G@)S<&d;t`ge=Mr;Uy0<1;qI+j( z?Y?n)58a-TXxYp5v`%c_yQg_>%f1=SGg=cfTRQHUb>WiTUwhUiC!V$B!vEk|7gA?S z=vlM0cHel`Zn`~-p0%5vwVR$bt9h38EUt9{&9`ywd(CV}$57yiuJ`aZD`rop8tWM1 z6}tv%Q>iKDU#C8(rw;_%V8z*C{5ue6mgNTL2GcEUOVBMRy%+S{@~>-(sSk2@^xP6r zEMYG9FrLj=whTYZm-k-J>2))f&8VzA2Qh`pN~*)1vwYdtf9Uq|Wt9laH0fdKZ=JuN zx3|vkZr%!m8E+RxDsc1^#1k#c@D0ZYnSu~7+|Cqzis9@{d~bpk|3ug03yOcD`*h{M zD1Kmgl)3mn;QAoGTJ;(%g@^I|s&C)Es10_<;G#qQvO*pZ!vns*fM#n-4-qox^OqNv4YhCN z1YMxmU3>)JQdx(RtJ#6#t;PN5!Hp-*#utA6s`Kemx+h^m4P&FQA9EH)bS0j37j{{G ziu04P@`Lu%+2!0R*d_QGzJ7(zMdJ%zgHeAXPBy*@Z}a!FgWP8BMn0q4S6mLt9n6XT z^Q;=XKAW&R^a?(Hx0c(1osHjeA7XFdVf`5FRF>gOTobe%pR=|7r7N%x@O{>e-2(dV z&YSFQZXEVUp46`^4k(T(&H^RWYX)C}Dc~zzldzApMcbvi1>Yb#if^68u{$x1TZG-4 zA906pV31e09{ZkG=w8?R^m zZTP-cJ7h5fv@Zm8%OH#Mw7sTH+P>IMaP@k8wP_Fh&5-V0nm+(eK8SB5{Q~=1hp{VG zIh zI#E}t>#v)t`-|SCAEUoc{~OcB;}eeGdi<&422f8Nb}<#-Cu`K`9gp*;iRRhh$$Zef z2>WImu(xtCcGkAQ?*Pp=f!15F`*yFk_wp?JJvjUx`x0EEZ{%gTI`~%5I+`29P2?tl z-ZR0=&9K>ShunV6y~4eReWcI0e_+qZg1w*8zE74P!ng8m{AhkEKZEb$m+>36LFd=Sb$MO0ZaDl*-I=-#@Q><6y+=PsKUcp=->v@*PL*gej5l<^p#BJ_ z6yg7fjeU(1j5~}Un-iD=_%;?Wcaq~5VrTAJ>^uG%BlsErQ{Xd;J;tfncie;-^`&k; zTg>g^&cPRvi@GBAKcCfAVP5e1c6dHx|xQL_<%vtU4if7p20t@ zH-jGsIr<_y!*}RPej#2eF5s8w8nOG|PmeEh8~PZQ8167UWB9TM*kek z#x}(r@y7Tc5>1KSWwm9GC+kuybyn)d^2HS+E51y>m>HM(W2L_G>dH^Ej%+g9kR6kq zlUnD<#Qehi`uvso zALf7FN8e{bRo|+=SHD@X6xs^Kns@u&j6b9}t#)(m=XFc!8|zpVddARLx+sC8K zqr#)=MvWRZYt*VyJ4f9%>Y-7;8uh19$4ASfGo#NKebwlX$2iAK8?$Q6ugA(`M~_`M z_DAEq<5rH_KJMmm`^P?!hI8c6K70(Xi~+bL6fFTS~BUm zNq?O5`DAf&Vsh=|w#hRmubjMn%77`SO<6kSqAAx;>7Me~lvk$wWy;^%?d_5F+V-~g zne8jvx3=HdzOVhU_E*|J>@akw9W@>cL+0@&nJ~Z{ksmD*dWEz_`f7;vAPoMt43_VuB-KXnLAKiIs=hDv0I`?+I&{>?B zpE-BtIWzB^`SvV+R(RIXS@UPDn6+uvu35Lvx_8#kXZ?28yR*KWEzYi(-GBDD*>h)~ zJA2pcJ7+&K`}eayn4_N)o>Mbt#GF}kR?oS7&b@PJ!kIrxj&x! z!rZ^ki_PmZZ@|1$=1rM5=L~gz*Md71+_&Io3!Y!_hXwB~`1`{0g)IwLE&St|b!Xmu z=Ie`6i>5ESebGyc{<=86c*5fOi#II3eDSr5Z#ir6S+AdUY>8osx}<)|^d-xdT(acG zCHF0PddX``j&(V@5?%ee#&*r^TGMq|*X>?XEAEx|c3p`qa`_mws}#_3X&m zwP&Al_O!FlI(yUEA1vdR$;%cmTfgk`Ww$LmuspJS)ADPUcQ1c@`Qhasp2MBvJ12L} zrgPpor?|qiqH@LH6;oC$Ua@|~0}zH;o!6)U%`ym{sRmCvnwedXU) zIaigfYFssb)xuTlS6#X47pq=by>s=E)yK~bpF8l}8Ru?1_r7xvt&!HG*9>1XZ_R~k zu32;MnrGL%wdR90pRFCUcJkU8Yv-*!Ywe1)Pp*Ao?eET$&Qs1i<-GCd-E!U!&b#Nl zpRAMDtyp*Iy4%)0wC=@qZ?F5}eDC>}p8vu6Ve5CT|8j$2!;B3FHu4*-8`o{TaN}DS z487pI3*O%}cGK&d{=Qk-T)uh0<_Vk6+i*LF32N!>K@$pOE+_G)UOIzOAI&bTpTla1~u=UZcPi=j1>nmGd+cs$1 z&$j(?yKei4?H6u;;nKvVwU=(#Vcc=yj%#+@yfe1*s+|v9X1Ywc>@VNj^1YY7_s->W zFTZP7VAu3rb9Y^_>-t^a-}T0>_paD=#dTLadu8Ct=~wQ#@=sT>tD3L6@9OB)7hk<+ zw|jSb_wL;{?Y?vO!QD?@lfGudHLqRs*|qj-M_hZ>wO3wy>vcn}TXNka*JrOk_4-$C zxZs8>Z@BY@hi-W8hS#tvWw9f(*MMIZ<7HB9wwdtD7<@C@qGx9DH_zgS^{IKb&$HE4 zHTc)$B>q1+%WXb>7gurocl0ZpTKyi{#(}2i+F)@RU}MZ`wszS#^BkjK;0*h@mCb#5 zX0#fZ{vJ+u56^RF8_gR{mW?K66pfD<4;o)E9yNYsH0?0%F?J)X-)ZEG*IUKU&R#mb z|NG+m;wSwPz2C1N8#L(s>Eip3-9C>=`399@t=Hg?D(!{ zp9MXm@FasqkBzNr7I3_r9v@c44LX+Awx3(r+}A><`{{UwQ?YQOf}XR^r(GW2^gaFj zW>_$tSWjNy45xET@Jr<#+>OW>@r$EA%r1Vmbo!T{O@Ci<_3KB04eBqF|5Cf4q>q-U zu5#-@psq%X&q?2rys!L@3f(=N@1u{7zf+1qkWhSEx5Mxftbzy^Xg*6ZC}FJB9)^?R zWM(nod*=9^h{$jNlc?gP8~ky-U=n>!mr=t1^y_4w)608&PKEd2ukLw|Y7OdS)f&>t zen;3S`5h6Xr2aq3-UB|WD(xS?=iD-P`kk3f%cM-oOcDaAgb)nmA_yc31dz}Y2tt5R zB%${rU}!=lAVm}uX$peWfCW?*%UV$E>Rmoull>TpZc_9C?ddReLch>vRs7+b0RDCd6B+u(z#;7Fi>o`KsZ_i%9hLSMG> znzjhS!uvN@L4*6;GSQob36^nWh{cd(dNvZ@aJ^_qx)G z3ibbme2S}(FLbBr|I=J4JkmK*`uAM9qw}Sodd=-c_@486t=--Ea-`?Ho|@LPme9_c z<|of?AQLu_{n`Nbe}lGRgH}bJ)v9P2nZRhjC4pxH-t0DwplBy_dZaoR@}e5VQ|gD zD%&Ri+PcKMN0z+3e(?QuCk79gI_aE zZ>2|mPPQeF*&CgGX0!!A8h-t4aXikK8KfIP7ve(h2h~0f z<&y$qe104Rzq1-E?^Ml}YChiY=SgNYteH;Ln^TQ6rhw1v3%Kq6`26gmo;@p4N9BXo z4`q)^U=PwLHy)1LM{(uthb{4C_ff9)2Gz5_eeS92{`DOUqPKD-az!V3JjUofKhM`~ zw%VT*BJZ+_pol;f=N0e_N34p=P0z0)?ZVkrTwxH;vXbx&Wj?AnB$-!n9??<-Pc|-j zX*pF~+YDR^QZlPZn?zi0+FWkhSr)t6cPK0XB}!?jVUjAj<2;209k2^LDKwJ**^Vj^HxBJIzd8y z2rZHgZL&B{PIS6_nMgNyfs;Y@ay<38d|8~B*Cx?vkTWH>J1=dbmE=vN<^bw;wo7!j z$rQpaG^|&aE)1>>Qbfo2+(=!C_k_=yOzlMX*)k8=<{@?@=~GWD%~Fl+mX?X+9L^wP z>4l7?Uy0P#)!8B$HEbnK4lS{l-LiNY&qFB#}gdbWX6SU5!;=`_(N(!*cMu(gxJZ6 z?vugQq1Y=KJUBl@KQ3u()4WD(dUWsj|HEE&*=IJEDl44pSxU9;cAXdh&<4Z*>`3ax5l1nc$3LLQ_O&85PDc5s4P%29z8G zgSY~Q5EX}!QuYJzg{TOe6yB2o!RP$p2kr0dlk2p8Nf!h7Y!v*1o?y{4a)G^?}aQ&!)VGrbV>zq?NG-raae@(}%)~>ai3frw|V=G!d z@V-@#R192M=*KLpxhwn(;TY!9S2ar)WPXy7UNCcVD;ar2GH(@u8Ahs!998HDIvJLT zMf4msgeCgNzuk<$p0qT4yrfW@O+ zxq13BotrZR+8grlO1u&&;L75!#9zbu6hf{+mSsS~ZQ9eLTUNUq`tG|ko6>vxMhs`) zScE8}U+5%oxm-1Yl1V&Ae~9i*C8DF6IVrj)Ji?!{IDt{p6-+9^PD@dWy9l)4(VXdj8L4pRNVzh=V>Z6W_W%atGhkUI=RspU*IA9n%P~A<=ND&| z$BrQGidKlETtJk|3-f&0{yu`*m{y>*G7pXVlpgjCPecKF3_egRLWTsPp> z0pe+#VIMa}^>&gy^LbI3Z?d`;8!FV{aUjD{OQSc!&WJLk^>> zj-Y;29p@JC%uDeM-l;myX2B&+^3=fyhYPbWN2S>C4Edie2sy+VCAISq`%=bTHU5;Q1 zlQDV|H{$RL1EDXIeb8Ja`20ljnu<6ikt3*S3%=A!b{`@pP-&T}z@?N&RMJ3%bFf>M zn@^H)WIm@)GDaysGRCJfga|kTV@fG$4jVBPfmjOZs;#!Zwsowp?n2eq?iM?h`p86saErRr^p4a5NeSZ1AHu0 zJzPbi?WFy9b6|VmV1Ta;Gz1m}_&_T)9i`<7H+P_>=BmC6R~feg^u7`S1Mq^Fu^lK9 zhI(x-xsDj)%vf*&nFN<@4N_9W&f=T02lTE32x`E5_}z9ve)5YPPw0uhc zfzy?igfpwwy)&p!ui>5kzH7@TWQk9^^xX1ATjQRj4>ydRzhqhPrPH51GkQzgxaut< z-qsKsh4bhF6%By2Ho?aHq>7@(l7*u4gte8Fr~zKUsfQVqH(0O8XtX1UCUlmf0%wq4 zBnC)x6Dd1vK>$iCIjt5NlQ~kd7S{Re9G?vGEQ1?iG6FZ(!hC*!Guq)*&&7|n;g0ta zzlbOp8>Bs$B@{cT4xq2Ar3^pm=KwGuQi>N0@;1!}M#7N*<0gd;sBjM6L1;qcUoDaf^)Eiv z-u)a@P>R*6(s@Y+_r983&(DS{Wh*ZPRZFOwY)rPy4~1NQ@&VgJij}dcZgIX}OrGyT z)lLtN&GFR5_KGa1H$9Ge$}?{+g3iIOGIXr7acGAOOJMFg2PsHQxBAdRC*%lAK4Tph zbf(skq_~7SF5QY}vRA}uQIhMpL^m#Jw$SZtogEmi{QlX;!WkxWhAGra`X3g%Qked%ba{2Ekit=1NqPnY%&>8n0MjKI(ZKLbSpvErtcfaFi>z+*l}`)s#Zli^_nQ zOqV!5twTI1?#-K?*M5rI#7};$LHK3=>OV%ZwXLn>Z{($|kkEHy?}lRUyj&X2*EO|j zs%+r`?Kn%4FEGDdJ7>y#Nz9nHIBNQxbv-p7h6w~jM?IY~e zUXkxx4B>v7KgVCS&HPy^bcBlj``k);4u~mXcA&h2n5YmQ(6T znt+R+2I@GH>uCou&n24h!klfx3#&!voH6!!L(DUsh}_bHBtsGu9;ioQXhyEvxB0f` zBs^r;Z#F#k#^527rvGWrvwxc1cglc%Q>Ir|PR)O`Zp@l>W9lB^1DP8p@BZ+Uz2jT5 zvQMu$^RIus)pCjqn7C-c=&?%{UHi3Z=k|x2c0LnBHf$f5wcs5!bu^s@uCtEf428@+ zWI5T4GvrU6?-0RT0J`;Kbd;a(x616;sCIWnR`ej*ZaY9x@f%^shnZGza&DfU_KE2h zpCEa|A`0xKTT<&d!3VC9g|K?N_6B}`JqtO7&Ur0%MieSgl@ek~vW{>g^d z#!q>D_KH?|@9JSAHmn)-z;ZG``AZ$4`_d7fNiKd(jO(>a+CQ`pwL@E8je9^vZF3VpS|yT+q5Zatq|vH?N_uAviwI|%$+{^1 zuU~Ed-@Y0u-c9WP4cI=8#I0f6R08(I)PNgfx}gjZ_%{Ct?dNp_KGv%p30i?{pd=3P z8;MKe1_>}%;^5c(N(l0AsPs$W%b@rM%4?%*Bdw5yhX_}0i0MD2z1dlfu10R}EAjqF zB;JPy<;oRiHHBo2J+R>sw~@Gq@(Ga@bS7QAhio~lozY%BjFqY;PhmXZN7#|VBRsSe zC@c4?E`u})DkTvOT!m30&F?_oIh z)?CM`9f2k21{RP=IJ5;6Hi%LjOz+%R(pP*?ctaJx-sn=Q_Qokg~-1p+vJ)I8Bi0+5Uw)i#NvlM_sd4<#o};g$wo zl$S1Y6Zb~j*|oY&mFMiFubtS-gF_#@p)B^s*}ifWI6+6*Kk6|14v4*rLF`>ohz*cP zGTI||@CL$W8f6R|GK38}CyQx*>ZFRC)x&BQyEb{=-|@_aUK6X^@f-J$`VNmi(0zK} zQJo&#vgUEmN9X@=pmzI=QB&7w8+HH35UrmyUi=u=fIeh`+Pzerq|R4Ys~fFPsGEE4 zSNHXJSv}FiEM<5ydS(pD5LU@(JLE#9pG~lHs1Z1gvqQ)0fLTOakPhowA z#f@Ps2q$K@V6ussPutzs=k9K~oxLHn90_#{C4_^a_Tlt!UZ@l`2zrN%;ch}#z{leF zcSv$kYAcz1m<#2yN7cu9JIC)L_nGki-BR~mT%aWB9gd_5-JI@`xqyPPr zmY&-~$~IP4KOPymN=Xc@Cgu%?Nbu=*v`Jdzs`l)mohxSle&RW@0Vz(o?kA zee|c({Yc%)jnjWxv3mVD?JD@~b&cbMQP4FEi0t`59hu2x@U=>lZMW^X?VMuZ@btWu zuctttbT)c;vPMs6P$HrYqR}GC=pum1^ah!rM-_d>LTHenkHQF!faIXq3c`q}k-{Rw z03=F7jIb5Gttti;K0Kc1@OuaeQTSKL8P0$GpIks9eEj>gw z&hHfPwh>SM(u2IDb*DqgV=qpB1SyIOsT52teEZZ%o(fpv5wo^S>35m5Z*f67> zZoOkqn8|1zm&L5rm=_>hP2?)3998L~>PQXqL;Bevik=RY52L)Ihe|@oAGU>4P^gJY zp)d-uE&%WLE+EPFv;`z=N?X9AviJf{_KAT7B-NU&0<*G z3Uo}SBQp>@Nh#2oSPmE)-itj?OPNPrU$K46;L7^hla6iEJ|@DL>@M9p*Dd)6$sU#4 zy=V8SbG5&TCkGyxRQGg#`1r%i-WtaDx4B0R>|3At>vm`S%%KCO7D295UjMT&Q|IF6 z)b9THvcz7rm#xBaZ(y)(m}9x)ak|B^Ieu&4Il4D~e?UR@nysxP6ey-0ZKaN)z;g~` zwrszy{N6d&!jtO?KCqR%s)qb?1*3AnzJogu_4YQ9MPxgCzJ@X~f=~r=3nrdc;!~}j z+2>@ECs)c1XoPkGITZ;EG=tTHR=}`sAi4-ll3+(kE+0A_AsyHh_KBX69I7dg}jG2>kY=FtP<-MjbM2Qm}U(tC29Vr?6i=*gu;u=Z3JT6Y7Z6y3yzSvTr z(gWar4WlV<5@E`(lom=U=upfQ#lW_=)&jx7= zPj{G9bFKM1GY^ICqUz=ZOcFr9vT57 zG&4k}xR>#Dkxq1TWGwxocyhm1wokL}$0t1kCeey<8M%pS0vp#_nT-s6%VHxlVpu_h zKD3fN)x^J#Ks|ilB$|$YDz87GsAr=O*j;oZDPkIP5JQ( zM#kbJe$>S~1_`OoERf7N#2%t*W?NqnT}wj#kR_ZfrYrzl4yGg;0wXz}6_=m@o|Irr z8p*|*y^MO;Nn%`{N#WRWDhk2anwFX#J5caO8**+tQpFBTBQpJ$r3bZdo_d-{hnJpR z6kMA)xOwQ3m#6;to8iCdM9cP($fYS$50d^@z9XaeK5*oTym@nbEYz;Ps(qnd7}|xv zKZF=fPRP?~Y@C`Fw3fk=#t(rFm7ukX8RP{74?IiR5vUEy1P7~8b#c^8%(ow`o79D4 z#CGti{(uc+lZsyT1!7_e2ZV*+6gtvyUA&DpZrc`FE1rz(qC)9(78>1+5-C)cdDn?WC@kI`r7PHDIGh;$5%ARY0J z!~8La5Rcw_6zSc+7v|d0Zqj6_h0pyZHJuz7anr6CH6~u-jLghJ2HD-) zUU=$>-b2WC-=2A8d0m(C-(T}<-+wuJ3TDLQ_;7u1KUC*snPx)t%r2W-eK1OSdyGlemv%h(Ma4N)Q8WSm!OFhuZ7 z#wnS@Zq_zPwn|YhCZB1@Fn6FG4LxWt!ytpT&OFXGi_S35vWYy}`nWCe)-uNkM?IbFSnJs4 zIOTZXVOdI77#=o%#D6AUkfineR%yMt*|N?0xJ~jK;>_$<0=A)s`^`gaa_jX9RYiNX zAVR7d1saF_M{lu4!GLGzFemVK1EnafjS{mmMIe_2jhbuG`EP`2t!bO-fJt0yBCuMF zQtb+gm8=!EAx%+Si~1kzXDK#&?Tu4=3R2)EEZmN4OtBd&$)uH{FFHH3{;Q2O_*d#< zcIs#dLyWaBGJ!c>VBrfQ2!%b#X5g2d_L`c;My{rD3U-QkI~2oEpXLC;IOcy#5=-3K zB>2f@?di4JGvdi#zyG}77XI2VJ%r!>S|nWhHF#q;8E-UlO=@?vIF-Be_sUE7N96PT z@6cX~56G4L2w5oRd&zq!FH)1C46RyWlo?@=afVpKT}sipn4(oHnqJoOjCneNm!osn zsf~d+Hdlzhs9=sT#(+ucY^sEvftag-14v^N0oAc7?4YwY?TDAa`|Nf1L`)Y+wyF>DR_1@}mT>h>dv!(t!F1t=~aDSjkD65dD-jb=u22?Q^h^ol~l zY#<@H1r+XvI+zm72d=MTYIjYZdb_<5rra1~`x9j>QKy%EKXVV9Xi2;JtawV}LLQKtO^~ zM9jyroura0jCNrQ5NC)B(hwJLPRYFhb7#|!suh5M%+{OYhe`neh&iV`M1HgVzH#&3 z{z-d>6t^tzHe#Lz1d|Yc@3FJLME3Dy*~5e8Udcnq+FSa?r{l!lFV=qdp00C5yQ?ciunVUUe_H;TgFV{W>i1|`GpK%vU(q<@TC#b>01-Vbv!tUn%PTCgu1)a)9*v#mrgPv1p zed8U%x*yq+gN#NvR;tkk%{IYf-)U~#p?Wt#aWRYE+?weqGUHO$A_TM$_Wcd5|2y3 z;DhRFOcawrPe6qFfnsj9Te>PbXCa1^&!O2U=8_UKv7{`f?%mtQ?BCfft!IZ1-`rj^ zVn}5xscM+k{h>wLQt@Q}Qww&zmynrt|5&Y&#s$Cyr?+Rq{jpRqc2r(WKB~zBq+u@FbLy@)lZmqLlLy zGkM1Rtd+Ky$y75*v4(gt(9S%|ywbeQyw`lfj8Nqs=1;%gmdQ5)lX% z-6&TB$&TZZoz1-IHQ73*XP^WkhKZ6JQF1Iol>H$!jqrO?-S3%0GI9XaVJOpaI`|t4 zaAW(#xB$cP+zjM@g+!HiG^5A21-81LE@g{ zD73Qe94$d;HB6`_x$uBbVPS+!&?4?xmq)tYyrvPlA;NnQs&q`7#-Grph}Ql4fB7dy zv>4K-5F>IyVulm}oj{#O?Z+LWVo!FIx%rR`p^xpS3e&bw`==IOZ0HkF9IZeB)5{io z2Uj5D#&LQ;5&QldXgR7%=&U%NcM7lqIYcPpKp!JHC$Eg;tTHY!DWpSZ$b6=Ur&2$A zrn{*fe9QI$7xw=B%C;_#)IGadJbCSfkF{@~L^-5!eBWz_-Z)fqnt0gy!UQZt;}AYj zvvuQEB}`k*mIIcH7O{z6ZrH?aL~sIHuJ_=}4IcO90u3T7WUIm26QhCe_3=cp1B8I!T)FrA%e@3+h zYsHHqRm4i@Ks*9Hf5Vym3J5no<~q6QK>;gg-~m>{co>~^ki_s2gGWF|3>-1LAhr;e zLGWf^B0|2M(bLn>%cJ@R8OJ%sx@&ziZOuN*D#udK z1?eN>In(bP7n~ot&wJ1b+-wlBB50%T@N*s|&v%cpNnU2MtP>uWwi?#Sj~bgzTP=?} z9(S&HulJZG^dvtgo-+%IsF?eU{mtvdb>?j@L+f>iiYO;f@N1Vr4z^x*skvr{5|q&) zw9zc1HIt0~sxdiWK&!Gw(EtyQ;nwchTCZPK?{dW5MHLq=XoGpz3_9ILU1pK@pg%Lz z9)Mj!Sz9dFJCRjj@Q5w*_79RnIIen?Bm4g?Hw%M_MZfNg>q7#ClpCW5C|8f)~u zMF4MXhi@s@>>1b;0rSefZM$QxwAkk372XE>n$idw01 zd8yJ*|DV+rNa+-^EyJ1T9&4UyZg4ld%^M_wLXK!rYk~=r0OGq)Ez62vRS8x~ zirf%%21Zj<#KM?}0$mBZ8MRtRSa`JkY|5#6NfW7Fg#+{}u7Jesc zS6Fv8;G9y+A6z?u>rxpfVZaA`1ply5HzhP%IJRK7oQ?<;VE!4{(`Ec^l9e+zqM}P< zKPa`GDFqy4ab?gy*%GqFW11+lu_NpD18vO97rG^8bo}Q&Z76x;jP`*)kmb-mq}S*x z+VW{?pCM#fr1!O-skv>3$|Mau5m`zxUSolGucX%2Y};;o-zMbQ2ro%6;>HoiFeRws z#t|kn)N<&Nghxz?z6w|Y$xJZ)Rx`6Y=~J7@ zfoq2&E%=&r$fYkp2NrIw+9l6cX=||Y0^0hGAOf7INKcXl7!4&92w*l`IFL<}0@Kot z26MCdpqZU-bDsGUjG6E17DPlC=W+BqHh$Po^myg@mvJZ>FE{FE0h<}MVcr>}LOgKh|phug)ZwiBUENX6ZIfg z?U|XRIvU1`RmUvG>$4cCb|;tvhA$~RUC$Axf!iwZhg67cuz>qi%d0_B+NdmT<2|$->Mpib~fD&F5P7*7kR;_AsaIK!NhPCGO zMXv;FY(N>r(*zNv1c_@|oIyw3%u9BY8NxvZP3F$CjE#tTz|L$WsWVCH`rpz+e9E

_VhG2@R?I7NqGA9@;NXkpI@PQ=j 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 + $rst = []; + $rst[] = [ + "privilege" => "Admin Lab", + "menus" => [ + ["title" => "Pasien", "path" => "/masterdata/pasien" ], + ["title" => "Pemeriksaan", "path" => "/masterdata/px" ], + ] + ]; + $rst[] = [ + "privilege" => "Keu", + "menus" => [ + ["title" => "Company", "path" => "/masterdata/company" ], + ["title" => "Agreement", "path" => "/masterdata/agreement" ], + ] + ]; + echo json_encode(["status" => "OK", "data" => $rst]); + } + function old_menu() { + //for preflight + $this->corss(); + $rst = [ + ["id"=>1,"icon" => "SendIcon","label" => "Menu 01", "target" => "url:/other_module" , "level" => 1], + ["id"=>2,"icon" => "DrafsIcon","label" => "Menu 02", "target" => "", "level" => 1, + "children" => [ + ["id"=>3,"icon" => "DrafsIcon","label" => "Sub Menu 0201", "target" => "link:/def", "level" => 2,], + ["id"=>4,"icon" => "StarIcon","label" => "Sub Menu 0202", "target" => "link:/def", "level" => 2], + ["id"=>5,"icon" => "InboxIcon","label" => "Sub Menu 0203", "target" => "link:/def", "level" => 2], + ["id"=>6,"icon" => "","label" => "Sub Menu 0204", "target" => "link:/def", "level" => 2, + "children" => [ + ["id"=>7,"icon" => "DrafsIcon","label" => "Sub Menu 020401", "target" => "link:/def", "level" => 3], + ["id"=>8,"icon" => "StarIcon","label" => "Sub Menu 020402", "target" => "link:/def", "level" => 3], + ["id"=>9,"icon" => "InboxIcon","label" => "Sub Menu 020403", "target" => "link:/def", "level" => 3], + ["id"=>10,"icon" => "","label" => "Sub Menu 020404", "target" => "link:/def" , "level" => 3], + ], + ] + ], + ], + ["id"=>11,"icon" => "InboxIcon","label" => "Menu 03", "target" => "url:/other_module", "level" => 1 ], + ["id"=>12,"icon" => "StarIcon","label" => "Menu 04", "target" => "url:/other_module", "level" => 1 ], + ["id"=>13,"icon" => "SendIcon","label" => "Menu 05", "target" => "url:/other_module" , "level" => 1], + ]; + echo json_encode(["status"=>"OK","records" => $rst ]); + } + function check_token() { + $req_headers = $headers = array_change_key_case(getallheaders(), CASE_LOWER); + $isLogin = false; + $user = []; + if (isset($req_headers["authorization"])) { + //have bearer + list($bearer, $token) = explode(" ", trim($req_headers["authorization"])); + $user =JWT::decode($token,$this->SECRET_KEY); + $isLogin = true; + } + return [$isLogin,$user]; + } + function info() { + list($isLogin,$user) = $this->check_token(); + echo json_encode(["isLogin" => $isLogin,"user" => $user]); + } + + function refresh_token () { + list($isLogin,$user) = $this->check_token(); + if (! $isLogin) { + $this->sys_error("Invalid Token"); + } else { + $token_expire = date("Y-m-d H:i:s",strtotime("now + 5 minute")); + $user["token_expire"] = $token_expire; + $token = JWT::encode($user,$this->SECRET_KEY); + $data = array( + "status" => "OK", + "user" => $user, + "token" => $token, + "token_expire" => $token_expire + ); + echo json_encode($data); + } + } + function login() { + $this->corss(); + $prm = json_decode(file_get_contents("php://input"),true); + if ($prm["username"] =="admin" && $prm["password"] == "123") { + $token_expire = date("Y-m-d H:i:s",strtotime("now + 5 minute")); + $user = ["name" => "The Admin" , "level" => "Admin", "expire" => $token_expire]; + $this->load->library("Jwt"); + $token = JWT::encode($user,$this->SECRET_KEY); + echo json_encode([ + "status" => "OK", + "token" => $token, + "token_expire" => $token_expire, + "redirect" => "/xinfo", + "user" => $user + ]); + exit; + } + echo json_encode(["status" => "ERR" , "message" => "Invalid username/password"]); + } + + function logout() + { + echo json_encode(["status" => "OK" , "message" => ""]); + } +} +?> diff --git a/application/controllers/Auth_placeholder_v2.php b/application/controllers/Auth_placeholder_v2.php new file mode 100644 index 00000000..7736adf2 --- /dev/null +++ b/application/controllers/Auth_placeholder_v2.php @@ -0,0 +1,92 @@ +load->library("Jwt"); + } + function chalenge() { + $this->corss(); + $param_chalenge = date("YmdHis"); + $ckey = JWT::encode($param_chalenge,$this->CHALENGE_KEY); + echo json_encode(["status" => "OK", "chalenge" => $ckey]); + } + function get_param() { + $sparam = file_get_contents("php://input"); + $jparam = json_decode($sparam,true); + return $jparam; + } + function auth() { + $param = $this->get_param(); + $username = $param["username"]; + $chalenge = $param["chalenge"]; + $password = $param["password"]; + $date = JWT::decode($chalenge,$this->CHALENGE_KEY); + $xdate = date("YmdHis",strtotime("now - 1 minute")); + $is_expired = $date < $xdate; + echo "chalenge date : $date | last 1 minute $xdate => " . ( $is_expired ? " Valid " : "Expired"); + echo "\n\n"; + $x_pw = hash_hmac("sha512","admin123",$chalenge); + echo "pw : $password | $x_pw => " . ( $password == $x_pw ? " OK " : " Not OK"); + } + function corss() { + global $_SERVER; + if (isset($_SERVER["HTTP_ORIGIN"])) { + header('Access-Control-Allow-Origin: ' . $_SERVER["HTTP_ORIGIN"]); + } else { + header('Access-Control-Allow-Origin: */*' ); + } + header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS'); + header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization'); + if ( isset($_SERVER["REQUEST_METHOD"]) && $_SERVER["REQUEST_METHOD"] == "OPTIONS") { + http_response_code(200); + echo json_encode("OK"); + exit; + } + } + function check_token() { + $req_headers = $headers = array_change_key_case(getallheaders(), CASE_LOWER); + $isLogin = false; + $user = []; + if (isset($req_headers["authorization"])) { + //have bearer + list($bearer, $token) = explode(" ", trim($req_headers["authorization"])); + $user =JWT::decode($token,$this->SECRET_KEY); + $isLogin = true; + } + return [$isLogin,$user]; + } +} + +/* + var enc = new TextEncoder("utf-8"); + +window.crypto.subtle.importKey( + "raw", // raw format of the key - should be Uint8Array + enc.encode("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.IjIwMjIwNDExMDUxOTE1Ig.gn7rkM_UAluoChLQWxJ5ZSqp0mxpekK_5Ex18kEM1fI"), + { // algorithm details + name: "HMAC", + hash: {name: "SHA-512"} + }, + false, // export = false + ["sign", "verify"] // what this key can do +).then( key => { + window.crypto.subtle.sign( + "HMAC", + key, + enc.encode("admin123") + ).then(signature => { + var b = new Uint8Array(signature); + var str = Array.prototype.map.call(b, x => ('00'+x.toString(16)).slice(-2)).join("") + console.log(str); + }); +}); + +*/ +?> diff --git a/application/controllers/Diagnosticreport.php b/application/controllers/Diagnosticreport.php new file mode 100644 index 00000000..32c56376 --- /dev/null +++ b/application/controllers/Diagnosticreport.php @@ -0,0 +1,375 @@ +load->library('Satusehat'); + } + + function index() + { + echo "Satu Sehat Diagnostic Report"; + } + + function getdiagnosticreport() + { + + $prm = $this->sys_input; + $orderheaderID = $prm['orderheaderID']; + + //cek db one_health diagnostic report sudah ada atau belum + + + + // get organization + $sql = "SELECT organizationID + FROM one_health.organization + WHERE organizationIsActive = 'Y'"; + + $qry = $this->db->query($sql, []); + $last_qry = $this->db->last_query(); + + if (!$qry) { + $error = array( + "message" => $this->db->error()["message"], + "sql" => $last_qry + ); + $this->sys_error_db($error); + exit; + } + + $organizationID = $qry->result_array()[0]['organizationID']; + + + + $sql_data_diagnostic_report = "SELECT T_OrderHeaderID,T_OrderHeaderLabNumber, + IFNULL(OHPatientMapIHSNumber,'') as OHPatientMapIHSNumber, + IFNULL(OHDoctorMapIHSNumber,'') as doctor_ihsnumber, + EncounterUUID, T_TestName, + IFNULL(Nat_TestLoincCode,'') as code_loinc, + IFNULL(Nat_TestLoincDisplay,'') as code_display, + ServiceRequestUUID, + ServiceRequestID + FROM one_health.service_request + JOIN t_orderheader ON ServiceRequestT_OrderHeaderID = ? AND + ServiceRequestT_OrderHeaderID = T_OrderHeaderID + JOIN m_patient ON M_PatientID = T_OrderHeaderM_PatientID + JOIN t_orderdetail ON ServiceRequestT_OrderDetailID = T_OrderDetailID + JOIN t_test ON T_OrderDetailT_TestID = T_TestID + JOIN nat_test ON T_TestNat_TestID = Nat_TestID AND Nat_TestIsActive = 'Y' + LEFT JOIN nat_test_loinc ON Nat_TestLoincNat_TestID = T_TestNat_TestID + LEFT JOIN one_health.oh_patient_map ON OHPatientMapM_PatientID = M_PatientID + AND OHPatientMapIsActive = 'Y' + LEFT JOIN one_health.oh_doctor_map ON OHDoctorMapM_DoctorID = T_OrderHeaderPjM_DoctorID + LEFT JOIN one_health.encounter ON EncounterT_orderHeaderID = T_orderHeaderID + AND EncounterIsActive= 'Y' + WHERE + ServiceRequestIsActive = 'Y'"; + + $qry_data_diagnostic_report = $this->db->query($sql_data_diagnostic_report,[$orderheaderID]); + + if (!$qry_data_diagnostic_report) { + $last_qry = $this->db->last_query(); + $error = array( + "message" => $this->db->error()["message"], + "sql" => $last_qry + ); + $this->sys_error_db($error); + exit; + } + + $ddr = $qry_data_diagnostic_report->result_array(); + $results = []; + + foreach ($ddr as $k_sr => $rdr) { + $sql = "SELECT * + FROM one_health.diagnostic_report + WHERE DiagnosticReportT_orderHeaderID = ? + AND DiagnosticReportServiceRequestID = ? + AND DiagnosticReportIsActive = 'Y'"; + + $qry = $this->db->query($sql, [ + $orderheaderID, + $rdr['ServiceRequestID'] + ]); + + + $last_qry = $this->db->last_query(); + + if (!$qry) { + $error = array( + "message" => $this->db->error()["message"], + "sql" => $last_qry + ); + $this->sys_error_db($error); + exit; + } + + $exist_data = $qry->result_array(); + + if(count($exist_data) == 0){ + $diagnosticreport_uuid = $this->satusehat->gen_uuid(); + $result["fullUrl"] = "urn:uuid:".$diagnosticreport_uuid; + $data_result['resourceType'] = "DiagnosticReport"; + $data_result['identifier'] = array( + array( + "system" => "http://sys-ids.kemkes.go.id/observation/".$organizationID, + "value" => $rdr['T_OrderHeaderLabNumber'] + ) + ); + $data_result['status'] = "final"; + $data_result['category'] = array( + array( + "coding" => array( + array( + "system" => "http://terminology.hl7.org/CodeSystem/v2-0074", + "code" => "CH", + "display" => "Chemistry" + ) + ) + ) + ); + + $sql = "SELECT T_OrderDetailValDate + FROM t_orderdetail + WHERE + T_OrderDetailT_OrderHeaderID = $orderheaderID AND + T_OrderDetailIsActive = 'Y' AND + T_OrderDetailT_TestIsResult = 'Y' + ORDER BY T_OrderDetailValDate ASC + LIMIT 1"; + //echo $sql; + $query = $this->db->query($sql); + //echo $this->db->last_query(); + if(!$query){ + echo $this->db->last_query(); + $this->sys_error("error get t_orderdetail"); + exit; + } + + $data_validdate = $query->row()->T_OrderDetailValDate; + $efectiveDate = $data_validdate; + $issuedDate = $data_validdate; + + $coding[] = [ + "system" => "http://loinc.org", + "code" => $rdr['code_loinc'], + "display" => $rdr['T_TestName'] + ]; + + $data_result['code'] = array( + "coding" => $coding + ); + $data_result['subject'] = array( + "reference" => "Patient/".$rdr['OHPatientMapIHSNumber'] + ); + $data_result['encounter'] = array( + 'reference' => "Encounter/".$rdr['EncounterUUID'] + ); + $data_result['effectiveDateTime'] = date('c', strtotime($efectiveDate)); + $data_result['issued'] = date('c', strtotime($issuedDate)); + $data_result['performer'] = array( + array( + 'reference' => "Practitioner/".$rdr['doctor_ihsnumber'] + ), + array( + 'reference' => "Organization/".$organizationID + ) + ); + + $sql = "SELECT IFNULL(OHStaffMapIhsNumber,'') as staff_ihsnumber + FROM t_orderdetail + JOIN m_user ON T_OrderDetailValUserID = M_UserID + JOIN m_staff ON M_UserM_StaffID = M_StaffID + LEFT JOIN one_health.oh_staff_map ON OHStaffMapM_StaffNIK = M_StaffNIK + + WHERE + T_OrderDetailT_OrderHeaderID = $orderheaderID AND + T_OrderDetailIsActive = 'Y' AND + T_OrderDetailT_TestIsResult = 'Y' + ORDER BY T_OrderDetailValDate DESC + LIMIT 1"; + $query = $this->db->query($sql); + if(!$query){ + // echo $this->db->last_query(); + $this->sys_error("error get t_orderdetail"); + exit; + } + + $r_validator = $query->row_array(); + + $data_result['performer'] = array( + array( + 'reference' => "Practitioner/".$r_validator['staff_ihsnumber'] + ), + array( + 'reference' => "Organization/".$organizationID + ) + ); + + $sql = "SELECT observationUUID + FROM t_orderdetail + JOIN one_health.observation ON observationT_OrderHeaderID = T_OrderDetailT_OrderHeaderID AND + observationT_TestID = T_OrderDetailT_TestID AND + observationIsActive = 'Y' + WHERE + T_OrderDetailT_OrderHeaderID = $orderheaderID AND + T_OrderDetailIsActive = 'Y' AND + T_OrderDetailT_TestIsResult = 'Y'"; + $query = $this->db->query($sql); + if(!$query){ + echo $this->db->last_query(); + $this->sys_error("error get t_orderdetail observation"); + exit; + } + + $r_observations = $query->result_array(); + + $rst_result = []; + foreach ($r_observations as $idx => $val) { + $idnew = $idx+1; + $rst_result[] = array( + "id" => "{$idnew}", + "reference" => "Observation/".$val['observationUUID'] + ); + } + $data_result['result'] = $rst_result; + + $sql = "SELECT SpecimenUUID + FROM t_orderdetail + JOIN t_test ON T_OrderDetailT_TestID = T_TestID + JOIN t_ordersample ON T_OrderSampleT_SampleTypeID = T_TestT_SampleTypeID AND + T_OrderSampleT_OrderHeaderID = {$prm['orderheaderID']} AND T_OrderSampleIsActive = 'Y' + JOIN one_health.specimen ON SpecimentT_OrderHeaderID = T_OrderDetailT_OrderHeaderID AND + SpecimentT_OrderSampleID = T_OrderSampleID AND + SpecimenIsActive = 'Y' + WHERE + T_OrderDetailT_OrderHeaderID = {$prm['orderheaderID']} AND + T_OrderDetailIsActive = 'Y' AND + T_OrderDetailT_TestIsResult = 'Y' + GROUP BY T_OrderSampleID"; + $query = $this->db->query($sql); + if(!$query){ + echo $this->db->last_query(); + $this->sys_error("error get specimen uuid"); + exit; + } + + $r_specimens = $query->result_array(); + + $rst_specimen = []; + foreach ($r_specimens as $idxx => $vall) { + $idnew = $idxx+1; + $rst_specimen[] = array( + "id" => "{$idnew}", + "reference" => "Specimen/".$vall['SpecimenUUID'] + ); + } + $data_result['specimen'] = $rst_specimen; + + $data_result['basedOn'] = array( + array( + "reference" => "urn:uuid:".$rdr['ServiceRequestUUID'] + ) + ); + $data_result["conclusion"] = ""; + $result["resource"] = $data_result; + $result["request"] = array("method" => "POST", "url" => "DiagnosticReport"); + + $sql = "INSERT INTO one_health.diagnostic_report + ( + DiagnosticReportUUID, + DiagnosticReportT_orderHeaderID, + DiagnosticReportServiceRequestID, + DiagnosticReportJSON, + DiagnosticReportCreated + ) + VALUES + ( + ?, + ?, + ?, + ?, + NOW() + )"; + $qry = $this->db->query($sql, [ + $diagnosticreport_uuid, + $orderheaderID, + $rdr['ServiceRequestID'], + json_encode($result) + ]); + $last_qry = $this->db->last_query(); + + if (!$qry) { + $error = array( + "message" => $this->db->error()["message"], + "sql" => $last_qry + ); + $this->sys_error_db($error); + exit; + } + + $results[] = $result; + }else{ + //echo "Y"; + //print_r($exist_data); + $results[] = json_decode($exist_data[0]['DiagnosticReportJSON']); + } + + + } + + echo json_encode($results); + } + + function getcategorydiagnosticreport() { + $prm = $this->sys_input; + $orderheaderID = $prm['orderheaderID']; + + $sql_category = "SELECT DiagnosticReportJSON + From one_health.diagnostic_report + WHERE DiagnosticReportT_orderHeaderID = ? + AND DiagnosticReportIsActive = 'Y' + "; + + $sql_category_report = $this->db->query($sql_category,[$orderheaderID]); + if (!$sql_category_report) { + $last_qry = $this->db->last_query(); + $error = array( + "message" => $this->db->error()["message"], + "sql" => $last_qry + ); + $this->sys_error_db($error); + exit; + } + $exist_datas = $sql_category_report->result_array(); + // echo json_encode($exist_data); + + $exist_data = json_decode($exist_datas, true); + + // Loop through each object in the array + foreach ($exist_data as $data) { + // Extract the DiagnosticReportJSON string + $diagnosticReportJSON = $data['DiagnosticReportJSON']; + + // Parse the DiagnosticReportJSON string + $diagnosticReport = json_decode($diagnosticReportJSON, true); + + // Access properties within the DiagnosticReportJSON + $fullUrl = $diagnosticReport['fullUrl']; + $resourceType = $diagnosticReport['resource']['resourceType']; + // ... access other properties as needed + + // Print or use the extracted data + echo "Full URL: $fullUrl, Resource Type: $resourceType
"; + } + // for ($i=0; $i < count($exist_data); $i++) { + // $datas = json_decode(json_encode($exist_data[$i]['DiagnosticReportJSON'])); + // $encode = $datas; + // $referenceValue = $datas['resource']['basedOn']['reference']; + // } + exit; + } + } +?> \ No newline at end of file diff --git a/application/controllers/Dummy_login.php b/application/controllers/Dummy_login.php new file mode 100644 index 00000000..03557435 --- /dev/null +++ b/application/controllers/Dummy_login.php @@ -0,0 +1,17 @@ +sys_input; + if ($prm["companyID"]== 100 && $prm["username"] =="admin" && $prm["password"] == "123" ) { + echo json_encode([ + "status" =>"OK", + "data" => [ + "token"=>"token1231231231321", + "name"=>"Administrator", + "userID"=>121, + ]]); + exit; + } + echo json_encode(["status" => "ERR", "message" => "Invalid Login"]); + } +} diff --git a/application/controllers/Ext_rspad.php b/application/controllers/Ext_rspad.php new file mode 100644 index 00000000..35d3af67 --- /dev/null +++ b/application/controllers/Ext_rspad.php @@ -0,0 +1,237 @@ + 0 or Last_Errno <> 0 + or Last_SQL_Errno <> 0 + ) + and date + interval ? minute > now() + order by id desc"; + $qry = $this->db->query($sql, [$target, $last_minute]); + if (!$qry) { + echo "

"; + print_r($this->db->error()); + echo "

"; + exit; + } + $rows = $qry->result_array(); + if (count($rows) == 0) { + echo "No Error in Last 15 minutes\n"; + exit; + } + $msg = "*Last $last_minute minute Error*:\n"; + if (count($rows) > 0) { + foreach ($rows as $r) { + $msg .= "Date: \t" . $r["date"] . "\n"; + if ($r["Last_IO_Errno"] > 0) { + $msg .= "IO Err: \t" . $r["Last_IO_Error"] . "\n"; + } + if ($r["Last_Errno"] > 0) { + $msg .= "Gen Err: \t" . $r["Last_Error"] . "\n"; + } + if ($r["Last_SQL_Errno"] > 0) { + $msg .= "SQL Err: \t" . $r["Last_SQL_Error"] . "\n"; + } + } + } + $msg .= "Last Status: https://devone.aplikasi.web.id/one-api/ext_rspad/show"; + $this->load->library("Wa_sas"); + $hp = "081339692415"; + $resp = $this->wa_sas->send_message($hp, $msg, false); + echo json_encode($resp); + } + function wa_sum($target = "slave_rspad") + { + $sql = "select * from ext_rspad.slave_log + where + target = ? and + ( + Last_IO_Errno <> 0 or Last_Errno <> 0 + or Last_SQL_Errno <> 0 + ) + and date + interval 3 day > now() + order by id desc limit 0,3"; + $qry = $this->db->query($sql, [$target]); + if (!$qry) { + echo "

"; + print_r($this->db->error()); + echo "

"; + exit; + } + $rows = $qry->result_array(); + $msg = ""; + if (count($rows) > 0) { + $msg = "*Last 3 Error (last 3 day)*:\n"; + foreach ($rows as $r) { + $msg .= "Date: \t" . $r["date"] . "\n"; + if ($r["Last_IO_Errno"] > 0) { + $msg .= "IO Err: \t" . $r["Last_IO_Error"] . "\n"; + } + if ($r["Last_Errno"] > 0) { + $msg .= "Gen Err: \t" . $r["Last_Error"] . "\n"; + } + if ($r["Last_SQL_Errno"] > 0) { + $msg .= "SQL Err: \t" . $r["Last_SQL_Error"] . "\n"; + } + } + } + $sql = "select * from ext_rspad.slave_log + where target = ? + order by id desc limit 0,3"; + $qry = $this->db->query($sql, [$target]); + if (!$qry) { + echo "

"; + print_r($this->db->error()); + echo "

"; + exit; + } + $rows = $qry->result_array(); + $msg .= "*Last 3 status*:\n"; + if (count($rows) > 0) { + foreach ($rows as $r) { + $msg .= "Date: \t" . $r["date"] . "\n"; + if ($r["Last_IO_Errno"] > 0) { + $msg .= "IO Err: \t" . $r["Last_IO_Error"] . "\n"; + } + if ($r["Last_Errno"] > 0) { + $msg .= "Gen Err: \t" . $r["Last_Error"] . "\n"; + } + if ($r["Last_SQL_Errno"] > 0) { + $msg .= "SQL Err: \t" . $r["Last_SQL_Error"] . "\n"; + } + $msg .= "IO State:\t" . $r["Slave_IO_State"] . "\n"; + $msg .= "IO Running:\t" . $r["Slave_IO_Running"] . "\n"; + $msg .= "Sql State:\t" . $r["Slave_SQL_Running_State"] . "\n"; + $msg .= "Sql Running:\t" . $r["Slave_SQL_Running"] . "\n"; + $msg .= "Behind Master:\t" . $r["Seconds_Behind_Master"] . "\n"; + $msg .= "\n"; + } + } else { + $msg .= "Tidak ada\n"; + } + $msg .= "Last Status: https://devone.aplikasi.web.id/one-api/ext_rspad/show"; + $this->load->library("Wa_sas"); + $hp = "081339692415"; + $resp = $this->wa_sas->send_message($hp, $msg, false); + echo json_encode($resp); + } + function show($target = "slave_rspad") + { + $sql = "select + date as TrxDate, Slave_IO_Running, Slave_IO_State, Seconds_Behind_Master, + Last_Errno, Last_Error, Last_SQL_Errno, Last_SQL_Error, + Last_IO_Errno, Last_IO_Error + from ext_rspad.slave_log + where target =? order by id desc limit 0,20"; + $qry = $this->db->query($sql, [$target]); + echo "
Log for $target
"; + if (!$qry) { + echo "

"; + print_r($this->db->error()); + echo "

"; + exit; + } + $rows = $qry->result_array(); + $this->print_table_style(); + $this->print_table($rows, array_keys($rows[0])); + } + function slave() + { + $sql = "INSERT INTO ext_rspad.slave_log ( + target, + `Slave_IO_State`,`Master_Host`,`Master_User`, + `Master_Port`,`Connect_Retry`,`Master_Log_File`, + `Read_Master_Log_Pos`,`Relay_Log_File`,`Relay_Log_Pos`, + `Relay_Master_Log_File`,`Slave_IO_Running`,`Slave_SQL_Running`, + `Replicate_Do_DB`,`Replicate_Ignore_DB`,`Replicate_Do_Table`, + `Replicate_Ignore_Table`,`Replicate_Wild_Do_Table`,`Replicate_Wild_Ignore_Table`, + `Last_Errno`,`Last_Error`,`Skip_Counter`, + `Exec_Master_Log_Pos`,`Relay_Log_Space`,`Until_Condition`, + `Until_Log_File`,`Until_Log_Pos`,`Master_SSL_Allowed`, + `Master_SSL_CA_File`,`Master_SSL_CA_Path`,`Master_SSL_Cert`, + `Master_SSL_Cipher`,`Master_SSL_Key`,`Seconds_Behind_Master`, + `Master_SSL_Verify_Server_Cert`,`Last_IO_Errno`,`Last_IO_Error`, + `Last_SQL_Errno`,`Last_SQL_Error`,`Replicate_Ignore_Server_Ids`, + `Master_Server_Id`,`Master_SSL_Crl`,`Master_SSL_Crlpath`, + `Using_Gtid`,`Gtid_IO_Pos`,`Replicate_Do_Domain_Ids`, + `Replicate_Ignore_Domain_Ids`,`Parallel_Mode`,`SQL_Delay`, + `SQL_Remaining_Delay`,`Slave_SQL_Running_State`,`Slave_DDL_Groups`, + `Slave_Non_Transactional_Groups`,`Slave_Transactional_Groups`) + values(?, ?,?,?, ?,?,?, ?,?,?, ?,?,?, ?,?,?, ?,?,?, ?,?,?, ?,?,?, ?,?,?, ?,?,?, ?,?,?, ?,?,?, ?,?,?, ?,?,?, ?,?,?, ?,?,?, ?,?,?, ?,? ) "; + $body = file_get_contents("php://input"); + $prm = json_decode($body, true, 2048); + $qry = $this->db->query($sql, [ + $prm["target"], + $prm["Slave_IO_State"], $prm["Master_Host"], $prm["Master_User"], + $prm["Master_Port"], $prm["Connect_Retry"], $prm["Master_Log_File"], + $prm["Read_Master_Log_Pos"], $prm["Relay_Log_File"], $prm["Relay_Log_Pos"], + $prm["Relay_Master_Log_File"], $prm["Slave_IO_Running"], $prm["Slave_SQL_Running"], + $prm["Replicate_Do_DB"], $prm["Replicate_Ignore_DB"], $prm["Replicate_Do_Table"], + $prm["Replicate_Ignore_Table"], $prm["Replicate_Wild_Do_Table"], $prm["Replicate_Wild_Ignore_Table"], + $prm["Last_Errno"], $prm["Last_Error"], $prm["Skip_Counter"], + $prm["Exec_Master_Log_Pos"], $prm["Relay_Log_Space"], $prm["Until_Condition"], + $prm["Until_Log_File"], $prm["Until_Log_Pos"], $prm["Master_SSL_Allowed"], + $prm["Master_SSL_CA_File"], $prm["Master_SSL_CA_Path"], $prm["Master_SSL_Cert"], + $prm["Master_SSL_Cipher"], $prm["Master_SSL_Key"], $prm["Seconds_Behind_Master"], + $prm["Master_SSL_Verify_Server_Cert"], $prm["Last_IO_Errno"], $prm["Last_IO_Error"], + $prm["Last_SQL_Errno"], $prm["Last_SQL_Error"], $prm["Replicate_Ignore_Server_Ids"], + $prm["Master_Server_Id"], $prm["Master_SSL_Crl"], $prm["Master_SSL_Crlpath"], + $prm["Using_Gtid"], $prm["Gtid_IO_Pos"], $prm["Replicate_Do_Domain_Ids"], + $prm["Replicate_Ignore_Domain_Ids"], $prm["Parallel_Mode"], $prm["SQL_Delay"], + $prm["SQL_Remaining_Delay"], $prm["Slave_SQL_Running_State"], $prm["Slave_DDL_Groups"], + $prm["Slave_Non_Transactional_Groups"], $prm["Slave_Transactional_Groups"] + ]); + if (!$qry) { + echo json_encode([ + "status" => "ERR", + "error" => $this->db->error() + ]); + exit; + } + echo json_encode(["status" => "OK", "error" => []]); + } + + public function print_table_style() + { + echo " + + "; + } + public function print_table($rows, $keys) + { + echo ""; + echo ""; + foreach ($keys as $k) { + echo ""; + } + echo "\n"; + foreach ($rows as $r) { + echo ""; + foreach ($keys as $k) { + echo ""; + } + echo ""; + } + echo "
$k
" . $r[$k] . "
"; + } +} diff --git a/application/controllers/File_upload.php b/application/controllers/File_upload.php new file mode 100644 index 00000000..0ad400b5 --- /dev/null +++ b/application/controllers/File_upload.php @@ -0,0 +1,496 @@ +corss(); + $param = $this->get_param(); + $param["url"] = $param["url"]; + $userID = $this->sys_user["M_UserID"]; + if ($param["cmd"] == "replace") { + $sql = "update fpp set fppUrl = ?, fppUserID = ? + where fppT_OrderHeaderID = ?"; + $qry = $this->db->query($sql, [ + $param["url"], + $userID, + $param["orderHeaderID"], + ]); + } else { + $sql = + " insert into fpp (fppUrl, fppUserID, fppT_OrderHeaderID) values(?,?,?)"; + $qry = $this->db->query($sql, [ + $param["url"], + $userID, + $param["orderHeaderID"], + ]); + } + if (!$qry) { + echo json_encode([ + "status" => "ERR", + "message" => $this->db->error()["message"], + ]); + exit(); + } + echo json_encode(["status" => "OK", "message" => ""]); + } + function get_fpp($orderHeaderID) + { + $sql = "select fppUrl from fpp + where fppT_OrderHeaderID = ? and fppIsActive = 'Y' "; + $qry = $this->db->query($sql, [$orderHeaderID]); + if (!$qry) { + echo json_encode([ + "status" => "ERR", + "message" => $this->db->error()["message"], + ]); + exit(); + } + $rows = $qry->result_array(); + echo json_encode(["status" => "OK", "rows" => $rows]); + } + function view_fpp($orderHeaderID) + { + $sql = "select fppUrl from fpp + where fppT_OrderHeaderID = ? and fppIsActive = 'Y' "; + $qry = $this->db->query($sql, [$orderHeaderID]); + if (!$qry) { + echo "
Error : " . $this->db->error()["message"] . "
"; + exit(); + } + $rows = $qry->result_array(); + if (count($rows) == 0) { + echo "
Belum ada FPP
"; + exit(); + } + $view = ""; + foreach ($rows as $r) { + $pi = pathinfo($r["fppUrl"]); + if ($pi["extenstion"] != "pdf") { + $view .= + "
"; + } else { + $view .= " View FPP PDF "; + } + } + echo "
$view
"; + } + function upload_v2() + { + $this->corss(); + $file = $_FILES["file"]; + $host = "http://devone.aplikasi.web.id"; + $fpp_folder = "/data-fpp/"; + $param = $this->get_param(); + $userID = $this->sys_user["M_UserID"]; + if (!($userID > 0)) { + echo json_encode([ + "status" => "ERR", + "message" => "Authorization error", + ]); + exit(); + } + $nolab = $_POST["nolab"]; + $orderHeaderID = $_POST["orderHeaderID"]; + $sql = "select fppID from fpp where fppT_OrderHeaderID=? + and fppIsActive = 'Y'"; + $qry = $this->db->query($sql, [$orderHeaderID]); + if (!$qry) { + echo json_encode([ + "status" => "ERR", + "message" => $this->db->error()["message"], + ]); + exit(); + } + $rows = $qry->result_array(); + $fppID = 0; + if (count($rows) > 0) { + $fppID = $rows[0]["fppID"]; + } + if (file_exists($file["tmp_name"])) { + $tmpName = tempnam($fpp_folder, "fpp-") . "-{$nolab}.pdf"; + $xname = substr($tmpName, strlen($fpp_folder)); + $upload_status = file_put_contents( + $tmpName, + file_get_contents($file["tmp_name"]) + ); + if (!$upload_status) { + echo json_encode([ + "status" => "ERR", + "message" => "Error Upload File", + ]); + exit(); + } + $url = $host . "/one-api/file_upload/dlv2/" . $xname; + if ($fppID == 0) { + $sql = "insert into fpp (fppUrl, fppUserID, fppT_OrderHeaderID) values(?,?,?)"; + $qry = $this->db->query($sql, [$url, $userID, $orderHeaderID]); + } else { + $sql = "update fpp set fppUrl = ?, fppUserID = ? + where fppID = ?"; + $qry = $this->db->query($sql, [$url, $userID, $orderHeaderID]); + } + if (!$qry) { + echo json_encode([ + "status" => "ERR", + "message" => $this->db->error()["message"], + ]); + exit(); + } + echo json_encode([ + "status" => "OK", + "url" => $url, + ]); + exit(); + } + echo json_encode([ + "status" => "ERR", + "message" => "Failed upload file", + ]); + } + function index() + { + $this->corss(); + $file = $_FILES["file"]; + $host = ""; + if (file_exists($file["tmp_name"])) { + $tmpName = tempnam("/xtmp/", "fpp-") . $file["name"]; + $xname = substr($tmpName, 6); + file_put_contents($tmpName, file_get_contents($file["tmp_name"])); + $nolab = pathinfo($file["name"])["filename"]; + $order = $this->get_order($nolab); + echo json_encode([ + "status" => "OK", + "order" => $order, + "name" => $file["name"], + "url" => $host . "/one-api/file_upload/dl/" . $xname, + ]); + exit(); + } + echo json_encode([ + "status" => "ERR", + "message" => "Failed upload file", + ]); + } + function get_order_by_id($headerID) + { + $sql = "select T_OrderHeaderID, T_OrderHeaderDate, + T_OrderHeaderLabNumber, T_OrderHeaderLabNumberExt, + T_OrderHeaderM_PatientID, T_OrderHeaderSenderM_DoctorID , + T_OrderHeaderSenderM_DoctorAddressID + from t_orderheader + where T_OrderHeaderID = ? + and T_OrderHeaderIsActive = 'Y'"; + $qry = $this->db->query($sql, [$headerID]); + $result = []; + if (!$qry) { + $result["status"] = "ERR"; + $result["message"] = $this->db->error()["message"]; + echo json_encode($result); + exit(); + } + $rows = $qry->result_array(); + if (count($rows) == 0) { + $result["status"] = "ERR"; + $result["message"] = "Order Lab tidak ada"; + echo json_encode($result); + exit(); + } + $orderHeaderID = $rows[0]["T_OrderHeaderID"]; + $orderDate = $rows[0]["T_OrderHeaderDate"]; + $labNo = $rows[0]["T_OrderHeaderLabNumber"]; + $labNoExt = $rows[0]["T_OrderHeaderLabNumberExt"]; + $doctorID = $rows[0]["T_OrderHeaderSenderM_DoctorID"]; + $patientID = $rows[0]["T_OrderHeaderM_PatientID"]; + $addressID = $rows[0]["T_OrderHeaderSenderM_DoctorAddressID"]; + + $sql = "select fn_get_doctor_fullname(?) doctor, + fn_get_patient_atribute(?) patient, + M_DoctorAddressDescription + from m_doctoraddress + where M_DoctorAddressID = ?"; + $qry = $this->db->query($sql, [$doctorID, $patientID, $addressID]); + if (!$qry) { + $result["status"] = "ERR"; + $result["message"] = $this->db->error()["message"]; + echo json_encode($result); + exit(); + } + $rows = $qry->result_array(); + if (count($rows) == 0) { + $result["status"] = "ERR"; + $result["message"] = "Alamat Dokter pengirim tidak ada"; + echo json_encode($result); + exit(); + } + $doctor = $rows[0]["doctor"]; + $address = $rows[0]["M_DoctorAddressDescrtiption"]; + $jpatient = json_decode($rows[0]["patient"], true); + $patient = $jpatient["patient_fullname"]; + $sql = "select T_TestName + from t_orderdetail + join t_test on T_OrderDetailT_OrderHeaderID = ? + and T_OrderDetailIsActive = 'Y' + and T_OrderDetailT_TestID = T_TestID + and T_TestIsPrice = 'Y' + order by T_TestSasCode "; + $qry = $this->db->query($sql, [$orderHeaderID]); + if (!$qry) { + $result["status"] = "ERR"; + $result["message"] = $this->db->error()["message"]; + echo json_encode($result); + exit(); + } + $tests = $qry->result_array(); + $sql = "select fppUrl from fpp where fppT_OrderHeaderID=?"; + + $qry = $this->db->query($sql, [$orderHeaderID]); + if (!$qry) { + $result["status"] = "ERR"; + $result["message"] = $this->db->error()["message"]; + echo json_encode($result); + exit(); + } + $rows = $qry->result_array(); + $existingFpp = []; + foreach ($rows as $r) { + $existingFpp[] = $r["fppUrl"]; + } + echo json_encode([ + "status" => "OK", + "data" => [ + "orderHeaderID" => $orderHeaderID, + "labNo" => $labNo, + "labNoExt" => $labNoExt, + "date" => $orderDate, + "doctor" => $doctor, + "address" => $address, + "patient" => $patient, + "test" => $tests, + "status" => "OK", + "haveExisting" => count($existingFpp) > 0, + "existing" => $existingFpp, + "message" => "", + ], + ]); + } + function get_order($nolab) + { + $sql = "select T_OrderHeaderID, T_OrderHeaderDate, + T_OrderHeaderLabNumber, T_OrderHeaderLabNumberExt, + T_OrderHeaderM_PatientID, T_OrderHeaderSenderM_DoctorID , + T_OrderHeaderSenderM_DoctorAddressID + from t_orderheader + where T_OrderHeaderLabNumber like ? + or T_OrderHeaderLabNumberExt like ? + and T_OrderHeaderIsActive = 'Y'"; + $param = "%" . $nolab; + $qry = $this->db->query($sql, [$param, $param]); + $result = []; + if (!$qry) { + $result["status"] = "ERR"; + $result["message"] = $this->db->error()["message"]; + return $result; + } + $rows = $qry->result_array(); + if (count($rows) == 0) { + $result["status"] = "ERR"; + $result["message"] = "Order dengan No. Lab $nolab tidak ada"; + return $result; + } + $orderHeaderID = $rows[0]["T_OrderHeaderID"]; + $orderDate = $rows[0]["T_OrderHeaderDate"]; + $labNo = $rows[0]["T_OrderHeaderLabNumber"]; + $labNoExt = $rows[0]["T_OrderHeaderLabNumberExt"]; + $doctorID = $rows[0]["T_OrderHeaderSenderM_DoctorID"]; + $patientID = $rows[0]["T_OrderHeaderM_PatientID"]; + $addressID = $rows[0]["T_OrderHeaderSenderM_DoctorAddressID"]; + + $sql = "select fn_get_doctor_fullname(?) doctor, + fn_get_patient_atribute(?) patient, + M_DoctorAddressDescription + from m_doctoraddress + where M_DoctorAddressID = ?"; + $qry = $this->db->query($sql, [$doctorID, $patientID, $addressID]); + if (!$qry) { + $result["status"] = "ERR"; + $result["message"] = $this->db->error()["message"]; + return $result; + } + $rows = $qry->result_array(); + if (count($rows) == 0) { + $result["status"] = "ERR"; + $result["message"] = "Alamat Dokter pengirim tidak ada"; + return $result; + } + $doctor = $rows[0]["doctor"]; + $address = $rows[0]["M_DoctorAddressDescrtiption"]; + $jpatient = json_decode($rows[0]["patient"], true); + $patient = $jpatient["patient_fullname"]; + $sql = "select T_TestName + from t_orderdetail + join t_test on T_OrderDetailT_OrderHeaderID = ? + and T_OrderDetailIsActive = 'Y' + and T_OrderDetailT_TestID = T_TestID + and T_TestIsPrice = 'Y' + order by T_TestSasCode "; + $qry = $this->db->query($sql, [$orderHeaderID]); + if (!$qry) { + $result["status"] = "ERR"; + $result["message"] = $this->db->error()["message"]; + return $result; + } + $tests = $qry->result_array(); + $sql = "select fppUrl from fpp where fppT_OrderHeaderID=?"; + + $qry = $this->db->query($sql, [$orderHeaderID]); + if (!$qry) { + $result["status"] = "ERR"; + $result["message"] = $this->db->error()["message"]; + return $result; + } + $rows = $qry->result_array(); + $existingFpp = []; + foreach ($rows as $r) { + $existingFpp[] = $r["fppUrl"]; + } + return [ + "orderHeaderID" => $orderHeaderID, + "labNo" => $labNo, + "labNoExt" => $labNoExt, + "date" => $orderDate, + "doctor" => $doctor, + "address" => $address, + "patient" => $patient, + "test" => $tests, + "status" => "OK", + "haveExisting" => count($existingFpp) > 0, + "existing" => $existingFpp, + "message" => "", + ]; + } + function dl($xname) + { + $fpath = "/xtmp/" . $xname; + header("Content-type: " . $this->get_mime_type($fpath)); + echo file_get_contents($fpath); + } + function dlv2($xname) + { + $fpath = "/data-fpp/" . $xname; + header("Content-type: " . $this->get_mime_type($fpath)); + echo file_get_contents($fpath); + } + + function get_mime_type($filename) + { + $idx = explode(".", $filename); + $count_explode = count($idx); + $idx = strtolower($idx[$count_explode - 1]); + + $mimet = [ + "txt" => "text/plain", + "htm" => "text/html", + "html" => "text/html", + "php" => "text/html", + "css" => "text/css", + "js" => "application/javascript", + "json" => "application/json", + "xml" => "application/xml", + "swf" => "application/x-shockwave-flash", + "flv" => "video/x-flv", + + // images + "png" => "image/png", + "jpe" => "image/jpeg", + "jpeg" => "image/jpeg", + "jpg" => "image/jpeg", + "gif" => "image/gif", + "bmp" => "image/bmp", + "ico" => "image/vnd.microsoft.icon", + "tiff" => "image/tiff", + "tif" => "image/tiff", + "svg" => "image/svg+xml", + "svgz" => "image/svg+xml", + + // archives + "zip" => "application/zip", + "rar" => "application/x-rar-compressed", + "exe" => "application/x-msdownload", + "msi" => "application/x-msdownload", + "cab" => "application/vnd.ms-cab-compressed", + + // audio/video + "mp3" => "audio/mpeg", + "qt" => "video/quicktime", + "mov" => "video/quicktime", + + // adobe + "pdf" => "application/pdf", + "psd" => "image/vnd.adobe.photoshop", + "ai" => "application/postscript", + "eps" => "application/postscript", + "ps" => "application/postscript", + + // ms office + "doc" => "application/msword", + "rtf" => "application/rtf", + "xls" => "application/vnd.ms-excel", + "ppt" => "application/vnd.ms-powerpoint", + "docx" => "application/msword", + "xlsx" => "application/vnd.ms-excel", + "pptx" => "application/vnd.ms-powerpoint", + + // open office + "odt" => "application/vnd.oasis.opendocument.text", + "ods" => "application/vnd.oasis.opendocument.spreadsheet", + ]; + + if (isset($mimet[$idx])) { + return $mimet[$idx]; + } else { + return "application/octet-stream"; + } + } +} +?> diff --git a/application/controllers/Imgtoken.php b/application/controllers/Imgtoken.php new file mode 100644 index 00000000..e74535bf --- /dev/null +++ b/application/controllers/Imgtoken.php @@ -0,0 +1,39 @@ +sys_input); + } + function convert() + { + $resp = file_get_contents("php://input"); + echo $resp; + } +} diff --git a/application/controllers/Json_placeholder.php b/application/controllers/Json_placeholder.php new file mode 100644 index 00000000..b3653c2d --- /dev/null +++ b/application/controllers/Json_placeholder.php @@ -0,0 +1,233 @@ +corss(); + $this->load->database("default"); + $max_result = 30; + $param = $this->get_param(); + if ($param["search"] == "") { + $sql = "select * from place_holder.drug_allergy limit 0,$max_result"; + $qry = $this->db->query($sql); + } else { + $param["search"] = "%" . $param["search"] . "%"; + $sql = "select * from place_holder.drug_allergy + where CODE like ? or STR like ? + limit 0,$max_result"; + $qry = $this->db->query($sql,[$param["search"]]); + } + if ($qry) { + echo json_encode(["status"=>"ERR","message" => $this->db->error()["message"]]); + exit; + } + echo json_encode(["status"=>"OK","rows"=>$this->db->result_array()]); + } + function search_location() + { + // metode search : 1. search kelurahan ( limit 20) , jika < 20 search kecamatan limit 20 - hasil kelurahan, jika < 20 search city dst + $max_result = 30; + $param = $this->get_param(); + $param["search"] = "%" . $param["search"] . "%"; + $a_loc = []; + if ($param["queryLoc"] != "") { + $a_loc = explode(",",$param["queryLoc"]); + } + $filter_loc = ""; + if (count($a_loc) > 0) { + if (count($a_loc) == 1) { + $filter_loc = " and M_ProvinceName = '" . $a_loc[0] . "'"; + } + if (count($a_loc) == 2) { + $filter_loc = " and M_CityName = '" . $a_loc[1] . "'"; + } + if (count($a_loc) == 3) { + $filter_loc = " and M_DistrictName= '" . $a_loc[2] . "'"; + } + } + $this->load->database("default"); + $this->corss(); + $sql = "select M_KelurahanID,M_KelurahanName, + M_DistrictID, M_DistrictName, + M_CityID, M_CityName, + M_ProvinceID, M_ProvinceName + from m_kelurahan + join m_district on M_KelurahanName like ? + and M_KelurahanIsActive='Y' + and M_DistrictID = M_KelurahanM_DistrictID + join m_city on M_CityID = M_DistrictM_CityID + and M_CityIsActive = 'Y' + join m_province on M_CityM_ProvinceID = M_ProvinceID + and M_ProvinceIsActive = 'Y' + $filter_loc + limit 0,$max_result"; + $qry = $this->db->query($sql, [$param["search"]]); + if (!$qry) { + echo json_encode(["status"=>"ERR","message"=>$this->db->error()["message"]]); + exit; + } + $rows = $qry->result_array(); + $result = []; + foreach ($rows as $r) { + $result[] = $r; + $idx = count($result) - 1; + $result[$idx]["tag"] = [ + $r["M_ProvinceName"], + $r["M_CityName"], + $r["M_DistrictName"], + $r["M_KelurahanName"], + ]; + $result[$idx]["level"] = 1; + } + if (count($rows) < $max_result) { + $max_result = $max_result - count($rows); + $sql = "select + M_DistrictID, M_DistrictName, + M_CityID, M_CityName, + M_ProvinceID, M_ProvinceName + from m_district + join m_city on M_DistrictName like ? + and M_DistrictIsActive ='Y' + and M_DistrictM_CityID = M_CityID + and M_CityIsActive = 'Y' + join m_province on M_CityM_ProvinceID = M_ProvinceID + and M_ProvinceIsActive = 'Y' + $filter_loc + limit 0,$max_result"; + $qry = $this->db->query($sql, [$param["search"]]); + if (!$qry) { + echo json_encode(["status"=>"ERR","message"=>$this->db->error()["message"]]); + exit; + } + $rows = $qry->result_array(); + foreach ($rows as $r) { + $result[] = $r; + $idx = count($result) - 1; + $result[$idx]["tag"] = [ + $r["M_ProvinceName"], + $r["M_CityName"], + $r["M_DistrictName"], + ]; + $result[$idx]["level"] = 2; + } + + if (count($rows) < $max_result) { + $max_result = $max_result - count($rows); + $x_loc = $filter_loc ; + if(count($a_loc) > 2) $x_loc = ""; + $sql = "select + M_CityID, M_CityName, + M_ProvinceID, M_ProvinceName + from m_city + join m_province on M_CityName like ? + and M_CityIsActive = 'Y' + and M_CityM_ProvinceID= M_ProvinceID + and M_ProvinceIsActive= 'Y' + $x_loc + limit 0,$max_result"; + $qry = $this->db->query($sql, [$param["search"]]); + if (!$qry) { + echo json_encode(["status"=>"ERR","message"=>$this->db->error()["message"]]); + exit; + } + $rows = $qry->result_array(); + foreach ($rows as $r) { + $result[] = $r; + $idx = count($result) - 1; + $result[$idx]["tag"] = [ + $r["M_ProvinceName"], + $r["M_CityName"], + ]; + $result[$idx]["level"] = 3; + } + } + } + echo json_encode([ + "status" => "OK", + "rows" => $result + ]); + } + function get_param() + { + $sbody = file_get_contents("php://input"); + return json_decode($sbody, true); + } + function search_patient() + { + $this->corss(); + $ch = curl_init( + "http://devone.aplikasi.web.id/one-api/mockup/fo/registration_v11/patient/search" + ); + $param = $this->get_param(); + $payload = json_encode([ + "noreg" => "", + "search" => $param["search"], + "current_page" => 1, + ]); + curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); + curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type:application/json"]); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + $resp = curl_exec($ch); + $error = curl_errno($ch); + $error_msg = curl_error($ch); + if ($error != 0) { + echo json_encode(["status" => "ERR", "message" => $error_msg]); + exit(); + } + echo $resp; + } + function lookup($param = "") + { + $this->corss(); + $result = [ + "status" => "OK", + "data" => [ + ["id" => 1, "name" => "Satu"], + ["id" => 2, "name" => "Dua"], + ["id" => 3, "name" => "Tiga"], + ["id" => 4, "name" => "Empat"], + ["id" => 5, "name" => "Lima"], + ["id" => 6, "name" => "Enam"], + ["id" => 7, "name" => "Tujuh"], + ["id" => 8, "name" => "Delapan"], + ["id" => 9, "name" => "Sembilan"], + ], + ]; + if ($param != "") { + $data = array_filter($result["data"], function ($r) use ($param) { + return strpos($r["name"], $param) >= 0; + }); + $result["data"] = $data; + } + echo json_encode($result); + } +} +?> diff --git a/application/controllers/Merge_rpt.php b/application/controllers/Merge_rpt.php new file mode 100644 index 00000000..7e45029d --- /dev/null +++ b/application/controllers/Merge_rpt.php @@ -0,0 +1,531 @@ +corss(); + $sql = "select T_OrderHeaderLabNumber, + T_OrderHeaderAddOnSecondM_LangID, + T_OrderHeaderM_LangID, + fn_get_patient_atribute(T_OrderHeaderM_PatientID) patient + from t_orderheader + join t_orderheaderaddon on T_OrderHeaderID = ? + and T_OrderHeaderID = T_OrderHeaderAddonT_OrderHeaderID"; + $qry = $this->db->query($sql, [$orderID]); + if (!$qry) { + echo json_encode([ + "status" => "ERR", + "message" => $this->db->error()["message"], + ]); + exit(); + } + $reports = []; + $rows = $qry->result_array(); + if (count($rows) == 0) { + echo json_encode([ + "status" => "ERR", + "message" => "Order Not Found", + ]); + exit(); + } + $labNo = $rows[0]["T_OrderHeaderLabNumber"]; + $jpat = json_decode($rows[0]["patient"], true); + $pname = str_replace(" ", "_", $jpat["patient_fullname"]); + $ts = "&ts=" . date("Ymdhis"); + $reports[] = [ + "name" => "Hasil Lab", + "url" => "{$rpt_lab}&__format=pdf&username={$username}&PID={$orderID}&ts={$ts}", + ]; + $haveSecondLang = false; + if ( + $rows[0]["T_OrderHeaderAddOnSecondM_LangID"] > 0 && + $rows[0]["T_OrderHeaderAddOnSecondM_LangID"] != + $rows["T_OrderHeaderM_LangID"] + ) { + $haveSecondLang = true; + $reports[] = [ + "name" => "Hasil Lab (Inggris)", + "url" => "{$rpt_lab_en}&__format=pdf&username={$username}&PID={$orderID}&ts={$ts}", + ]; + } + //Xray + $reports[] = [ + "name" => "Rontgen", + "url" => "{$rpt_xray}&__format=pdf&username={$username}&PID={$orderID}&PLang=1&ts={$ts}", + ]; + $reports[] = [ + "name" => "Rontgen (v2)", + "url" => "{$rpt_xray_v2}&__format=pdf&username={$username}&PID={$orderID}&PLang=1&ts={$ts}", + ]; + + if (false && $haveSecondLang) { + $reports[] = [ + "name" => "Rontgen (Inggris)", + "url" => "{$rpt_xray_en}&__format=pdf&username={$username}&PID={$orderID}&PLang=1&ts={$ts}", + ]; + $reports[] = [ + "name" => "Rontgen (Inggris v2)", + "url" => "{$rpt_xray_v2_en}&__format=pdf&username={$username}&PID={$orderID}&PLang=1&ts={$ts}", + ]; + } + $sql = "select * from so_resultentry where So_ResultEntryT_OrderHeaderID=? and So_ResultEntrySo_TemplateName='ECG' + and So_ResultEntryIsActive='Y'"; + $qry = $this->db->query($sql, [$orderID]); + if (!$qry) { + echo json_encode([ + "status" => "ERR", + "message" => $this->db->error()["messaga"], + ]); + exit(); + } + $rows = $qry->result_array(); + foreach ($rows as $r) { + $soID = $r["So_ResultEntryID"]; + $langID = $r["So_ResultEntryM_LangID"]; + if ($langID == 1) { + $name = "Elektromedik"; + $reports[] = [ + "name" => $name, + "url" => "{$rpt_elmd}&__format=pdf&username={$username}&PID={$soID}&PLang={$langID}&ts={$ts}", + ]; + $reports[] = [ + "name" => "$name (v2)", + "url" => "{$rpt_elmd_v2}&__format=pdf&username={$username}&PID={$soID}&PLang={$langID}&ts={$ts}", + ]; + } else { + continue; + $name = "Elektromedik (Inggris)"; + $reports[] = [ + "name" => $name, + "url" => "{$rpt_elmd_en}&__format=pdf&username={$username}&PID={$soID}&PLang={$langID}&ts={$ts}", + ]; + $reports[] = [ + "name" => "Elektromedik (Inggris v2)", + "url" => "{$rpt_elmd_v2_en}&__format=pdf&username={$username}&PID={$soID}&PLang={$langID}&ts={$ts}", + ]; + } + } + //FISIK UMUM + $sql = "select * from so_resultentry where So_ResultEntryT_OrderHeaderID=? and So_ResultEntrySo_TemplateName='FISIK UMUM' + and So_ResultEntryIsActive='Y'"; + $qry = $this->db->query($sql, [$orderID]); + if (!$qry) { + echo json_encode([ + "status" => "ERR", + "message" => $this->db->error()["messaga"], + ]); + exit(); + } + $rows = $qry->result_array(); + foreach ($rows as $r) { + $soID = $r["So_ResultEntryID"]; + $langID = $r["So_ResultEntryM_LangID"]; + if ($langID == 1) { + $reports[] = [ + "name" => "Fisik (riwayat)", + "url" => "{$rpt_fisik_riwayat}&__format=pdf&PType=riwayat&username={$username}&PID={$soID}&PLang={$langID}&ts={$ts}", + ]; + $reports[] = [ + "name" => "Fisik", + "url" => "{$rpt_fisik}&__format=pdf&PType=fisik&username={$username}&PID={$soID}&PLang={$langID}&ts={$ts}", + ]; + } else { + continue; + $name = "Elektromedik (Inggris)"; + $reports[] = [ + "name" => $name, + "url" => "{$rpt_elmd_en}&__format=pdf&username={$username}&PID={$soID}&PLang={$langID}&ts={$ts}", + ]; + $reports[] = [ + "name" => "Elektromedik (Inggris v2)", + "url" => "{$rpt_elmd_v2_en}&__format=pdf&username={$username}&PID={$soID}&PLang={$langID}&ts={$ts}", + ]; + } + } + //FISIK UMUM + $sql = + "select * from mcu_resume where Mcu_ResumeT_OrderHeaderID=? and Mcu_ResumeIsActive = 'Y'"; + $qry = $this->db->query($sql, [$orderID]); + if (!$qry) { + echo json_encode([ + "status" => "ERR", + "message" => $this->db->error()["messaga"], + ]); + exit(); + } + $rows = $qry->result_array(); + foreach ($rows as $r) { + $mcuResumeID = $r["Mcu_ResumeID"]; + $langID = $r["Mcu_ResumeM_LangID"]; + if ($langID == 1) { + $reports[] = [ + "name" => "MCU Resume", + "url" => "{$rpt_mcu_resume}&__format=pdf&username={$username}&PID={$mcuResumeID}&PLang={$langID}&ts={$ts}", + ]; + $reports[] = [ + "name" => "MCU Resume (v2)", + "url" => "{$rpt_mcu_resume_v2}&__format=pdf&username={$username}&PID={$mcuResumeID}&PLang={$langID}&ts={$ts}", + ]; + $reports[] = [ + "name" => "MCU Resume (v3)", + "url" => "{$rpt_mcu_resume_v3}&__format=pdf&username={$username}&PID={$mcuResumeID}&PLang={$langID}&ts={$ts}", + ]; + $reports[] = [ + "name" => "MCU Resume (v4)", + "url" => "{$rpt_mcu_resume_v4}&__format=pdf&username={$username}&PID={$mcuResumeID}&PLang={$langID}&ts={$ts}", + ]; + $reports[] = [ + "name" => "MCU Resume (v5)", + "url" => "{$rpt_mcu_resume_v5}&__format=pdf&username={$username}&PID={$mcuResumeID}&PLang={$langID}&ts={$ts}", + ]; + $reports[] = [ + "name" => "MCU Resume (v6)", + "url" => "{$rpt_mcu_resume_v6}&__format=pdf&username={$username}&PID={$mcuResumeID}&PLang={$langID}&ts={$ts}", + ]; + $reports[] = [ + "name" => "MCU Resume (v7)", + "url" => "{$rpt_mcu_resume_v7}&__format=pdf&username={$username}&PID={$mcuResumeID}&PLang={$langID}&ts={$ts}", + ]; + $reports[] = [ + "name" => "MCU Resume (v8)", + "url" => "{$rpt_mcu_resume_v8}&__format=pdf&username={$username}&PID={$mcuResumeID}&PLang={$langID}&ts={$ts}", + ]; + $reports[] = [ + "name" => "MCU Resume (v9)", + "url" => "{$rpt_mcu_resume_v9}&__format=pdf&username={$username}&PID={$mcuResumeID}&PLang={$langID}&ts={$ts}", + ]; + $reports[] = [ + "name" => "MCU Resume v10", + "url" => "{$rpt_mcu_resume_v10}&__format=pdf&username={$username}&PID={$mcuResumeID}&PLang={$langID}&ts={$ts}", + ]; + } else { + continue; + } + } + + echo json_encode([ + "status" => "OK", + "data" => $reports, + "labNo" => $labNo, + "name" => $pname, + ]); + } + function download_pdf() + { + $this->corss(); + $orderHeaderID = $this->sys_input["headerId"]; + $output_file_name = $orderHeaderID . "-" . "merge" . ".pdf"; + $urls = $this->sys_input["urls"]; + $target = tempnam("/xtmp", uniqid("target", true)) . ".pdf"; + $merge_cmd = "/usr/bin/pdfunite"; + $base_url = "http://localhost/"; + $fnames_del = []; + foreach ($urls as $url) { + $fname = tempnam("/xtmp", uniqid("src", true)) . ".pdf"; + $rpt_data = file_get_contents($base_url . $url); + file_put_contents($fname, $rpt_data); + $merge_cmd .= " $fname "; + $fnames_del[] = $fname; + } + $merge_cmd .= " $target"; + $output = []; + exec($merge_cmd, $output); + header("Content-type: application/pdf"); + header("Content-Disposition: inline"); + /* + header( + 'Content-Disposition: inline; filename="' . + $output_file_name . + '"' + ); + */ + echo file_get_contents($target); + foreach ($fnames_del as $fdel) { + unlink($fdel); + } + if (file_exists($target)) { + unlink($target); + } + } + function get_pdf($orderID) + { + $sql = "select distinct + Group_ResultID,Group_ResultName, + Group_ResultFlagNonLab,IFNULL(T_EmailNonLabUrl,'-') EmailNonLabUrl, + IF(T_EmailNonLabUrl IS NULL AND Group_ResultFlagNonLab = 'Y',' [Belum Pilih Format Hasil]','') temail + from + t_orderdetail + join group_resultdetail + on Group_ResultDetailT_TestID = T_OrderDetailT_TestID + and T_OrderDetailIsActive = 'Y' and Group_ResultDetailIsActive = 'Y' + and T_OrderDetailT_OrderHeaderID = ? + join group_result + on Group_ResultDetailGroup_ResultID = Group_ResultID + and Group_ResultIsActive = 'Y' + LEFT JOIN t_email_nonlab ON T_EmailNonLabT_OrderHeaderID = T_OrderDetailT_OrderHeaderID AND + T_EmailNonLabType LIKE CONCAT('%',REPLACE(Group_ResultName, 'Elektromedik', 'electromedis'),'%')"; + $query = $this->db->query($sql, [$orderID]); + if ($query) { + $rows = $query->result_array(); + $ts = "&ts=" . date("Ymdhis"); + foreach ($rows as $r) { + $xname = $r["Group_ResultName"]; + $gid = $r["Group_ResultID"]; + $emailnonlaburl = str_replace(" ", "", $r["EmailNonLabUrl"]); + if (strpos($emailnonlaburl, "fisik") > 0) { + continue; + } + $report = ""; + switch ($gid) { + case 1: + $report = + "/birt/frameset?__report=report/one/lab/rpt_test_email.rptdesign&__format=pdf&username=admin&PID=" . + $orderID . + $ts; + break; + case 2: + $report = + "/birt/frameset?__report=report/one/lab/rpt_hasil_papsmear_email.rptdesign&__format=pdf&username=admin&PID=" . + $orderID . + $ts; + break; + case 3: + $report = + "/birt/frameset?__report=report/one/lab/rpt_hasil_fna_email.rptdesign&__format=pdf&username=admin&PID=" . + $orderID . + $ts; + break; + case 4: + $report = $emailnonlaburl; + break; + case 5: + $report = $emailnonlaburl; + break; + case 6: + $report = $emailnonlaburl; + break; + case 7: + $report = $emailnonlaburl; + break; + case 8: + $report = $emailnonlaburl; + break; + case 9: + $report = $emailnonlaburl; + break; + case 10: + $report = $emailnonlaburl; + break; + case 11: + $report = $emailnonlaburl; + break; + case 12: + $report = + "/birt/frameset?__report=report/one/lab/rpt_hasil_lcprep_email.rptdesign&__format=pdf&username=admin&PID=" . + $orderID . + $ts; + break; + case 13: + $report = + "/birt/frameset?__report=report/one/lab/rpt_test_mikro_email.rptdesign&__format=pdf&username=admin&PID=" . + $orderID . + $ts; + break; + case 14: + $report = + "/birt/frameset?__report=report/one/lab/rpt_hasil_cytologi_email.rptdesign&__format=pdf&username=admin&PID=" . + $orderID . + $ts; + break; + case 15: + $report = $emailnonlaburl; + break; + case 16: + $report = $emailnonlaburl; + break; + case 17: + $report = $emailnonlaburl; + break; + case 19: + $report = $emailnonlaburl; + break; + } + if ($report != "-") { + $result[] = [ + "name" => $xname, + "groupID" => $gid, + "url" => $report, + ]; + } + } + } + echo json_encode(["status" => "OK", "data" => $result]); + } + + function merge($orderHeaderID, $lang = 1, $rpt = "lab") + { + $sql = "select T_OrderHeaderLabNumber,T_OrderHeaderLabNumberExt,M_PatientName + from t_orderheader + join m_patient on T_OrderHeaderID = ? + and T_OrderHeaderM_PatientID = M_PatientID"; + $qry = $this->db->query($sql, [$orderHeaderID]); + $output_file_name = $orderHeaderID . "-" . $rpt . ".pdf"; + if ($qry) { + $rows = $qry->result_array(); + if (count($rows) > 0) { + $output_file_name = + $rows[0]["T_OrderHeaderLabNumberExt"] . "-" . $rpt . ".pdf"; + } + } + $fnames = []; + $target = tempnam("/xtmp", uniqid("target", true)) . ".pdf"; + $merge_cmd = "/usr/bin/pdfunite"; + $base_url = "http://localhost/"; + $fnames_del = []; + if (strpos($rpt, "lab") !== false) { + $fname = tempnam("/xtmp", uniqid("src", true)) . ".pdf"; + $url = + $base_url . + "/birt/frameset?__report=report/one/lab/rpt_test_email.rptdesign&__format=pdf&username=Administrator&PID=" . + $orderHeaderID . + "&tm=" . + date("Ymdhnis"); + $rpt_data = file_get_contents($url); + file_put_contents($fname, $rpt_data); + $merge_cmd .= " $fname "; + $fnames_del[] = $fname; + } + if (strpos($rpt, "xray") !== false) { + $fname = tempnam("/xtmp", uniqid("src", true)) . ".pdf"; + $url = + $base_url . + "/birt/run?__report=report/one/lab/rpt_hasil_so_xray_email.rptdesign&__format=pdf&username=Administrator&PID=" . + $orderHeaderID . + "&PLang=" . + $lang . + "&tm=" . + date("Ymdhnis"); + $rpt_data = file_get_contents($url); + file_put_contents($fname, $rpt_data); + $merge_cmd .= " $fname "; + $fnames_del[] = $fname; + } + if (strpos($rpt, "ecg") !== false) { + $ecgID = 0; + $sql = "select * from so_resultentry + where So_ResultEntryT_OrderHeaderID=? + and So_ResultEntryIsActive = 'Y' + and So_ResultEntrySo_TemplateName = 'ECG'"; + $qry = $this->db->query($sql, [$orderHeaderID]); + if ($qry) { + $rows = $qry->result_array(); + if (count($rows) > 0) { + $ecgID = $rows[0]["So_ResultEntryID"]; + } + } + if ($ecgID > 0) { + $fname = tempnam("/xtmp", uniqid("src", true)) . ".pdf"; + $url = + $base_url . + "/birt/run?__report=report/one/lab/rpt_hasil_so_elmd_email.rptdesign&__format=pdf&username=Administrator&PID=" . + $ecgID . + "&PLang=" . + $lang . + "&tm=" . + date("Ymdhnis"); + $rpt_data = file_get_contents($url); + file_put_contents($fname, $rpt_data); + $merge_cmd .= " $fname "; + $fnames_del[] = $fname; + } + } + $merge_cmd .= " $target"; + $output = []; + exec($merge_cmd, $output); + header("Content-type: application/pdf"); + header( + 'Content-Disposition: attachment; filename="' . + $output_file_name . + '"' + ); + echo file_get_contents($target); + foreach ($fnames_del as $fdel) { + unlink($fdel); + } + if (file_exists($target)) { + unlink($target); + } + exit(); + } +} +?> diff --git a/application/controllers/Odoo.php b/application/controllers/Odoo.php new file mode 100644 index 00000000..482ae394 --- /dev/null +++ b/application/controllers/Odoo.php @@ -0,0 +1,644 @@ +url = "https://odoo.sismedika.online"; + $this->db_odoo = "odoo16_sismedika"; + $this->username = "admin@sismedika.com"; + $this->password = "duD#Z36qH5ctmRRD"; + $this->common = ripcord::client("{$this->url}/xmlrpc/2/common"); + $this->uid = $this->common->authenticate($this->db_odoo, $this->username, $this->password, array()); + $this->model = ripcord::client("{$this->url}/xmlrpc/2/object"); + $this->db->query("use one_support"); + } + function update_task($client_id = 2) + { + //last 60 days + $sql = "select TicketingID,TicketingDescription,TicketingCreated,TicketingNumber + from one_support.ticketing + where TicketingClientID = ? + and TicketingCreated + interval 7 day > now() + and ( + TicketingOdooTaskID = 0 + or + TicketingDoneDate is null + ) + "; + $qry = $this->db->query($sql, [$client_id]); + if (!$qry) { + print_r($this->db->error()); + } + $rows = $qry->result_array(); + foreach ($rows as $r) { + $no = $r["TicketingNumber"]; + $id = $r["TicketingID"]; + $desc = $r["TicketingDescription"]; + $taskDate = $r["TicketingCreated"]; + + $taskID = $this->task_by_tag($no); + echo "Get Odoo TaskID $taskDate : $no => $taskID\n"; + // echo "\t$desc\n"; + if ($taskID > 0) { + $sql = "update one_support.ticketing + set TicketingOdooTaskID = ? + where TicketingID = ?"; + } + list($date, $staff) = $this->get_done($taskID); + echo "\tDone by $staff at $date\n"; + if ($date != "") { + $sql = "update one_support.ticketing + set TicketingOdooTaskID = ? + , TicketingDoneDate = ?, + TicketingDoneStaff=? + where TicketingID = ?"; + $qry = $this->db->query($sql, [ + $taskID, + $date, $staff, $id + ]); + } else { + $qry = $this->db->query($sql, [ + $taskID, + $id + ]); + } + if (!$qry) { + echo "\tERR : " . print_r($this->db->error()) . "\n"; + } + sleep(1); + $date = ""; + $staff = ""; + } + } + function task_by_tag($tag, $project_id = 123) + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_URL, "http://odoo.sismedika.online/web/dataset/call_kw/project.task/web_search_read"); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + "Content-Type: application/json", + "Cookie: frontend_lang=en_us; td_id=669b47846b8437b163a9c8d43a16c42cae2bc609; session_id=e1c224f95431fc75271cf484260586408c0757d4; cids=1; tz=asia/jakarta", + "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36" + ]); + $param = [ + "jsonrpc" => "2.0", + "method" => "call", + "params" => [ + "model" => "project.task", + "method" => "web_search_read", + "args" => [], + "kwargs" => [ + "limit" => 80, + "offset" => 0, + "order" => "", + "context" => [ + "lang" => "en_US", + "tz" => "Asia/Jakarta", + "uid" => 39, + // "allowed_company_ids" => [ + // 1 + // ], + "bin_size" => true, + "active_model" => "project.project", + "active_id" => $project_id, + "active_ids" => [ + $project_id + ], + "default_project_id" => $project_id, + "show_project_update" => true, + "create" => true, + "active_test" => true + ], + "count_limit" => 81, + "domain" => [ + "&", + [ + "display_project_id", + "=", + $project_id + ], + "|", + [ + "name", + "ilike", + "$tag" + ], + [ + "id", + "ilike", + "$tag" + ] + ], + "fields" => [ + "name", + "project_id", + "tag_ids" + ] + ] + ] + ]; + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($param)); + $response = curl_exec($ch); + $taskID = 0; + if (curl_errno($ch)) { + echo json_encode(["status" => "ERR", "message" => curl_error($ch)]); + } else { + $resp = json_decode($response, true); + if ($resp["result"]["length"] > 0) { + $taskID = $resp["result"]["records"][0]["id"]; + } + } + curl_close($ch); + return $taskID; + } + function get_done($task_id) + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_URL, "http://odoo.sismedika.online/mail/thread/messages"); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + "Content-Type: application/json", + "Cookie: frontend_lang=en_us; td_id=669b47846b8437b163a9c8d43a16c42cae2bc609; session_id=e1c224f95431fc75271cf484260586408c0757d4; cids=1; tz=asia/jakarta", + "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36" + ]); + $data = [ + "jsonrpc" => "2.0", + "method" => "call", + "params" => [ + "thread_id" => $task_id, + "thread_model" => "project.task", + "limit" => 30 + ] + ]; + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + $response = curl_exec($ch); + if (curl_errno($ch)) { + return ["", ""]; + echo json_encode(["status" => "ERR", "message" => curl_error($ch)]); + } else { + $resp = json_decode($response, true); + $date = ""; + $staff = ""; + foreach ($resp["result"] as $r) { + foreach ($r["trackingValues"] as $t) { + if ($t["changedField"] == "Stage") { + if ($t["newValue"]["value"] == "IMPLEMENTATION") { + $date = $r["date"]; + $staff = $r["email_from"]; + break; + } + } + if ($date != "") break; + } + } + if ($date != "") { + // echo json_encode(["status" => "OK", "date" => $date, "by" => $staff]); + return [$date, $staff]; + exit; + } + return ["", ""]; + echo $response; + } + curl_close($ch); + } + function test_implementation($project_id = 70) + { + $sdate = "2024-07-03 00:00:00"; + $edate = "2024-07-03 23:59:59"; + $arg = array(); + $kwarg = array( + "limit" => 10, + "offset" => 0, + "order" => "", + "count_limit" => 11, + "fields" => [ + "id", + "name", + "description", + ], + //"domain"=>[["stage_id","ilike","implementation"]] + // "domain" + ); + $resp = $this->model->execute_kw( + $this->db_odoo, + $this->uid, + $this->password, + "project.task", + "web_search_read", + array(array( + "&", + ["display_project_id", "=", $project_id], + "&", + ["date_last_stage_update", ">=", $sdate], + "&", + ["date_last_stage_update", "<=", $edate], + ["stage_id", "ilike", "implementation"] + )), + $kwarg + ); + echo "$sdate : $edate\n"; + print_r($resp); + } + function get_implementation_v2($project_id = 70, $stage = "", $date = "") + { + if ($date == "") $date = date("Y-m-d"); + $sdate = $date . " 00:00:00"; + $edate = $date . " 23:59:59"; + if ($stage == "") $date = "x"; + if ($date == "x") { + $sdate = "2024-01-01 00:00:00"; + $edate = "2024-08-07 23:59:59"; + } + $arg = array(); + $kwarg = array( + "limit" => 10, + "offset" => 0, + "order" => "", + "count_limit" => 11, + "fields" => [ + "id", + "name", + "description", + ], + //"domain"=>[["stage_id","ilike","implementation"]] + // "domain" + ); + if ($stage == "") { + echo "$sdate | $edate | $project_id\n"; + $resp = $this->model->execute_kw( + $this->db_odoo, + $this->uid, + $this->password, + "project.task", + "web_search_read", + array(array( + "&", + ["display_project_id", "=", intval($project_id)], + "&", + ["date_last_stage_update", ">=", $sdate], + ["date_last_stage_update", "<=", $edate] + )), + $kwarg + ); + } else { + $resp = $this->model->execute_kw( + $this->db_odoo, + $this->uid, + $this->password, + "project.task", + "web_search_read", + array(array( + "&", + ["display_project_id", "=", intval($project_id)], + "&", + ["date_last_stage_update", ">=", $sdate], + "&", + ["date_last_stage_update", "<=", $edate], + ["stage_id", "ilike", $stage] + )), + $kwarg + ); + } + print_r($resp); + exit; + $arr_ticket = []; + if (isset($resp["records"])) { + foreach ($resp["records"] as $r) { + $desc = $r["description"]; + $name = $r["name"]; + $id = $r["id"]; + $tiket = ""; + if (preg_match("/ No. Tiket : (.+)<\/b>
Cabang/", $desc, $match)) { + $tiket = $match[1]; + if (in_array($tiket, $arr_ticket)) { + echo date("Y-m-d H:i:s") . " Ticket # $tiket duplicate \n"; + continue; + } + $arr_ticket[] = $tiket; + } + if ($tiket != "") { + $rec = $this->get_ticketing($tiket); + if ($rec["TicketingStatus"] != "IMPLEMENTATION") { + $ticketID = $rec["TicketingID"]; + $sender = $rec["TicketingSender"]; + $cabang = $rec["M_BranchName"]; + $hasil = ""; + if (preg_match("/(Hasil.*:.+)/", $desc, $match)) { + $hasil = strip_tags($match[1]); + $hasil = str_replace(" ", "", $hasil); + } + $impl_msg = " +Pengirim : $sender +No. Tiket : $tiket +Issue : $name +Cabang : $cabang +Status : Selesai +$hasil + +Silahkan di cek kembali +Terima Kasih\n"; + echo date("Y-m-d H:i:s") . " Done Ticket # $tiket from $sender \n"; + $this->wa_to_sasone_done($impl_msg, $project_id); + $this->update_ticketing($ticketID, "IMPLEMENTATION", $ticketID); + sleep(2); + } + } + } + } + } + function get_implementation($project_id = 70, $date = "") + { + if ($date == "" || $date = "-") $date = date("Y-m-d"); + $sdate = $date . " 00:00:00"; + $edate = $date . " 23:59:59"; + $arg = array(); + $project_id = intval($project_id); + $kwarg = array( + "limit" => 10, + "offset" => 0, + "order" => "", + "count_limit" => 11, + "fields" => [ + "id", + "name", + "description", + ], + //"domain"=>[["stage_id","ilike","implementation"]] + // "domain" + ); + $resp = $this->model->execute_kw( + $this->db_odoo, + $this->uid, + $this->password, + "project.task", + "web_search_read", + array(array( + "&", + ["display_project_id", "=", $project_id], + "&", + ["date_last_stage_update", ">=", $sdate], + "&", + ["date_last_stage_update", "<=", $edate], + ["stage_id", "ilike", "implementation"] + )), + $kwarg + ); + $arr_ticket = []; + if (isset($resp["records"])) { + foreach ($resp["records"] as $r) { + $desc = $r["description"]; + $name = $r["name"]; + $id = $r["id"]; + $tiket = ""; + if (preg_match("/ No. Tiket : (.+)<\/b>
Cabang/", $desc, $match)) { + $tiket = $match[1]; + if (in_array($tiket, $arr_ticket)) { + echo date("Y-m-d H:i:s") . " Ticket # $tiket duplicate \n"; + continue; + } + $arr_ticket[] = $tiket; + } + if ($tiket != "") { + $rec = $this->get_ticketing($tiket); + if ($rec["TicketingStatus"] != "IMPLEMENTATION") { + $ticketID = $rec["TicketingID"]; + $sender = $rec["TicketingSender"]; + $cabang = $rec["M_BranchName"]; + $hasil = ""; + if (preg_match("/(Hasil.*:.+)/", $desc, $match)) { + $hasil = strip_tags($match[1]); + $hasil = str_replace(" ", "", $hasil); + } + $impl_msg = " +Pengirim : $sender +No. Tiket : $tiket +Issue : $name +Cabang : $cabang +Status : Selesai +$hasil + +Silahkan di cek kembali +Terima Kasih\n"; + echo date("Y-m-d H:i:s") . " Done Ticket # $tiket from $sender \n"; + $this->wa_to_sasone_done($impl_msg, $project_id); + $this->update_ticketing($ticketID, "IMPLEMENTATION", $ticketID); + sleep(2); + } + } + } + } + } + + function get_message($taskID) + { + $arg = [ + "thread_id" => $taskID, + "thread_model" => "project_task", + "limit" => 30 + ]; + $resp = $this->model->execute_kw( + $this->db_odoo, + $this->uid, + $this->password, + "mail.thread", + "read", + array($arg) + ); + print_r($resp); + } + function wa_to_sasone_done( + $msg, + $project_id = 70 + ) { + $this->load->library("Wa_sas"); + //$hp = "6287823783747"; + //$hp="6282113702602-1584412485@g.us"; + //bisone supporter + $hp = "6281328282909-1583223560@g.us"; + if ($project_id != 70) { + //sasone + //6282113702602-1584412485 + $hp = "6282113702602-1584412485@g.us"; + if ($project_id == 123) { + //hore + $hp = "120363280846797029@g.us"; + } + } + $resp = $this->wa_sas->send_message($hp, $msg, true); + // print_r($resp); + } + function update_ticketing($ticketID, $status, $taskID) + { + $sql = "update ticketing set TicketingStatus = ?, + TicketingOdooTaskID=? + where ticketingID = ?"; + $qry = $this->db->query($sql, [$status, $taskID, $taskID]); + if (!$qry) { + echo "Error update ticketing $ticketID\n"; + exit; + } + echo $this->db->last_query() . "\n"; + } + function get_ticketing($tiket) + { + $sql = "select TicketingID,TicketingStatus , + M_BranchName, TicketingSender + from + ticketing + join m_branch on TicketingM_BranchCode = M_BranchCode + and TicketingNumber = ? + "; + $qry = $this->db->query($sql, [$tiket]); + if (!$qry) { + echo "Error get ticketing $tiket\n"; + exit; + } + $rows = $qry->result_array(); + if (count($rows) == 0) { + echo "Error get ticketing $tiket\n"; + exit; + } + return $rows[0]; + } + function create_ts() + { + $prm = $this->sys_input; + $date = $prm["date"]; + $time = $prm["time"]; + $employee_id = $prm["employee_id"]; + $task_id = $prm["task_id"]; + $project_id = $prm["project_id"]; + $description = $prm["description"]; + + $arg = array( + "name" => $description, + "date" => $date, + "unit_amount" => $time, + "user_id" => $this->uid, + "task_id" => $task_id, + "project_id" => $project_id, + "employee_id" => $employee_id + ); + + $resp = $this->model->execute_kw( + $this->db_odoo, + $this->uid, + $this->password, + "account.analytic.line", + "create", + array($arg) + ); + print_r($resp); + if (!is_numeric($resp)) { + echo json_encode(["status" => "ERR", "message" => json_encode($resp)]); + } else { + echo json_encode( + [ + "status" => "OK", + "ts_id" => $resp + ] + ); + } + } + function create_task() + { + $prm = $this->sys_input; + $title = $prm["title"]; + $description = $prm["description"]; + $project_id = $prm["project_id"]; + if ($project_id == "") $project_id = 70; + $images = $prm["images"]; + if (is_array($images)) { + foreach ($images as $img) { + $description .= "
" . + ""; + } + } + $users = $prm["users"]; + if ($users == "") { + $users = [ + 44, + 41, + 42 + ]; + } + $arg = array( + "sun" => $this->bool_day("sun"), + "mon" => $this->bool_day("mon"), + "tue" => $this->bool_day("tue"), + "wed" => $this->bool_day("wed"), + "thu" => $this->bool_day("thu"), + "fri" => $this->bool_day("fri"), + "sat" => $this->bool_day("sat"), + "recurrence_id" => false, + "parent_id" => false, + "company_id" => 1, + "stage_id" => 443, + "personal_stage_type_id" => false, + "recurrence_update" => "this", + "priority" => "0", + "name" => "$title", + "kanban_state" => "normal", + "project_id" => $project_id, + "display_project_id" => false, + "milestone_id" => false, + "user_ids" => [ + [ + 6, + false, + $users + ] + ], + "active" => true, + "partner_id" => false, + "partner_phone" => false, + "date_deadline" => false, + "tag_ids" => [ + [ + 6, + false, + [] + ] + ], + "task_properties" => [], + "description" => $description, + "planned_hours" => 0, + "timesheet_ids" => [], + "child_ids" => [], + ); + $resp = $this->model->execute_kw( + $this->db_odoo, + $this->uid, + $this->password, + "project.task", + "create", + array($arg) + ); + if (!is_numeric($resp)) { + echo json_encode(["status" => "ERR", "message" => json_encode($resp)]); + } else { + echo json_encode( + [ + "status" => "OK", + "task_id" => $resp + ] + ); + } + } + function bool_day($inp_dow) + { + $dow = strtolower(date("D", strtotime("now"))); + if ($inp_dow == $dow) return true; + return false; + } +} diff --git a/application/controllers/Or_dummy.php b/application/controllers/Or_dummy.php new file mode 100644 index 00000000..c63f7ff5 --- /dev/null +++ b/application/controllers/Or_dummy.php @@ -0,0 +1,26 @@ +sys_input; + $param = [ + "IncomingJSONData" => json_encode($data), + "IncomingM_BranchID" => $data["branch_id"], + "IncomingT_OrderHeaderID" => $data["T_OrderHeaderID"], + ]; + $qry = $this->db->insert("or_dummy.incoming", $param); + if (!$qry) { + echo json_encode([ + "status" => "ERR", + "message" => "Err incoming " . $this->db->error()["message"] + ]); + exit; + } + echo json_encode(["status" => "OK", "message" => ""]); + } +} diff --git a/application/controllers/PushOrder.http b/application/controllers/PushOrder.http new file mode 100644 index 00000000..00e08fff --- /dev/null +++ b/application/controllers/PushOrder.http @@ -0,0 +1,100 @@ +POST https://devone.aplikasi.web.id/one-api/PushOrder + +{ + "CorporateID": "46", + "CorporateName": "PT Astra Daihatsu Motor", + "outletId": "I", + "BranchCode": "00000619", + "BranchName": "Westerindo Cikarang", + "PatientCode": "CP2407270280", + "PatientName": "Ibu Adela Nurpadilah ", + "PatientSexCode": "F", + "PatientSexName": "Female", + "PatientDOB": "2001\/08\/05", + "PatientAdress": "CpOne Address", + "OrderNumber": "I2410180003", + "OrderDateTime": "2024\/10\/18 14:40:52", + "DoctorOrderCode": "CpOne001", + "DoctorOrderName": "Dr CpOne", + "GuarantorID": "00000619", + "GuarantorName": "Westerindo Cikarang", + "AgreementID": "Cp001", + "AgreementName": "CpOne", + "ReceivedFlag": false, + "LabRegNo": null, + "ReceivedDateTime": null, + "OrderedItems": [ + { + "itemCode": "00000250", + "itemName": "Glukosa Darah Puasa" + }, + { + "itemCode": "00000506", + "itemName": "Urine Lengkap" + }, + { + "itemCode": "00000686", + "itemName": "Hematologi Lengkap" + }, + { + "itemCode": "00001598", + "itemName": "Panel Creatinin" + } + ] + } + +### Error orderNumber mengandung 3 +POST https://devone.aplikasi.web.id/one-api/PushOrder + +{ + "outletId": "02", + "orderNumber": "131112^02", + "orderDT": "2022/04/14 01:01:01", + "visitNumber": "111111^02", + "patientId": "00-01-02-03", + "patientName": "Tn. COBA", + "sexId": "1", + "sexName": "Male", + "dob": "2019/01/23", + "addressName": "Mid o Nowhere 23, Neverland", + "cityId": "0001", + "cityName": "Neverland", + "mobileNumber": "+6281818181818", + "phoneNumber": "+62212345678", + "faxNumber": "", + "email": "coba@gmail.com", + "idNIK": "31750000000000005", + "idSIM": "", + "idPassport": "", + "physicianId": "02-ZZA", + "physicianName": "Dr. Stein", + "isCito": "0", + "diagnoseId": "Z0101", + "diagnoseName": "Nama Diagnosa", + "guarantorId": "GG", + "guarantorName": "PRIVATE", + "agreementId": "X01", + "agreementName": "InsuranceX VIP", + "serviceUnitId": "OP", + "serviceUnitName": "Out Patient", + "wardPoliId": "P01", + "wardPoliName": "Poli Umum", + "roomId": "R01", + "roomName": "Ruang Alamanda", + "bedId": "B01", + "bedName": "Bed 01", + "classId": "0001", + "className": "VIP Class", + "regUserId": "S1234", + "regUserName": "Rafaela", + "orderItemList": [ + { + "OrderItemId": "2792", + "OrderItemName": "PCR SARS-COV-2 H+1 B2C" + }, + { + "OrderItemId": "2234", + "OrderItemName": "Glukosa sewaktu" + } + ] +} diff --git a/application/controllers/PushOrder.php b/application/controllers/PushOrder.php new file mode 100644 index 00000000..3da49767 --- /dev/null +++ b/application/controllers/PushOrder.php @@ -0,0 +1,44 @@ +db->query($sql, [$body]); + $jbody = json_decode($body, true); + //print_r($jbody); + //exit; + $outletId = $jbody["outletId"]; + $nolab = $jbody["OrderNumber"]; + // echo $nolab; + + + $receivedDT = Date("Y/m/d h:i:s"); + if (strpos($nolab, "3") !== false) { + $resp = [ + "status" => 1, + "message" => "ERROR", + "outletId" => $outletId, + "orderNumber" => $nolab, + "lisRegNo" => "x-lis-" . $nolab, + "receivedDT" => $receivedDT + ]; + } else { + + $resp = [ + "status" => 0, + "message" => "SUCCESS", + "outletId" => $outletId, + "orderNumber" => $nolab, + "lisRegNo" => "x-lis-" . $nolab, + "receivedDT" => $receivedDT + ]; + } + echo json_encode($resp); + } +} diff --git a/application/controllers/Random_saran.php b/application/controllers/Random_saran.php new file mode 100644 index 00000000..2b8facd5 --- /dev/null +++ b/application/controllers/Random_saran.php @@ -0,0 +1,42 @@ + 1) { + $ext = $a_ext[1]; + } + $fname = "$xid.$ext"; + $this->load->library("Sas_s3"); + $resp = $this->sas_s3->upload("audio-sample", "$xid.{$ext}", $type, file_get_contents($tmp_name)); + if ($resp['@metadata']['statusCode'] == 200) { + echo json_encode(["status" => "OK", "result" => "file $name of $type ulded to s3 $xid.ogg "]); + }; + } + function index() + { + $sql = "select concat(Mcu_ResumeKesimpulan, ' Untuk itu disarankan ', + Mcu_ResumeSaran) text + from + mcu_resume + where length(Mcu_ResumeSaran) > 20 + and length(Mcu_ResumeSaran) > 20 + order by rand() + limit 0, 1 "; + $qry = $this->db->query($sql); + $rows = $qry->result_array(); + echo json_encode(["status" => "OK", "data" => $rows]); + } +} diff --git a/application/controllers/Search.php b/application/controllers/Search.php new file mode 100644 index 00000000..d736ca1f --- /dev/null +++ b/application/controllers/Search.php @@ -0,0 +1,856 @@ +db = $this->load->database("onedev", true); + } + function index() + { + echo "Api: Training Playground"; + } + + function instrument_byname() + { + try { + //# cek token valid + if (!$this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $param = $this->sys_input; + $page = $param["page"]; + + // check input parameter + $control = ""; + if (isset($param['control'])) { + $control = trim($param["control"]); + if ($control != "") { + $control = '%' . $param['control'] . '%'; + } + } + $test = ""; + if (isset($param['test'])) { + $test = trim($param["test"]); + if ($test != "") { + $test = '%' . $param['test'] . '%'; + } + } + $instrument = trim($param['instrument']); + $instrument = "%" . $instrument . "%"; + + // hitung start_offset + $ROW_PER_PAGE = 10; + $start_offset = 0; + if (isset($param["page"])) { + if (is_numeric((int)$param["page"]) && $param["page"] > 0) { + $start_offset = ($page - 1) * $ROW_PER_PAGE; + } + } + //query + if ( + $control == "" && $test == "" + ) { + $sql = "select distinct Nat_InstrumentID, Nat_InstrumentName + from + nat_instrument + join t_instrument_local on Nat_InstrumentID = T_InstrumentLocalNat_InstrumentID + and Nat_InstrumentIsActive = 'Y' and T_InstrumentLocalIsActive = 'Y' + and Nat_InstrumentName like ? + join nat_qc on Nat_instrumentID = Nat_QcNat_InstrumentID + and Nat_QcIsActive = 'Y' + limit 10 offset ?"; + $qry = $this->db->query($sql, [$instrument, $start_offset]); + $last_qry = $this->db->last_query(); + $count = "select count(distinct Nat_InstrumentID) as total + from + nat_instrument + join t_instrument_local on Nat_InstrumentID = T_InstrumentLocalNat_InstrumentID + and Nat_InstrumentIsActive = 'Y' and T_InstrumentLocalIsActive = 'Y' + and Nat_InstrumentName like ? + join nat_qc on Nat_instrumentID = Nat_QcNat_InstrumentID + and Nat_QcIsActive = 'Y'"; + $qry_total_filter = $this->db->query($count, [$instrument]); + $last_qry_total_filter = $this->db->last_query(); + } else if ( + $control != "" && $test == "" + ) { + $sql = "select distinct Nat_InstrumentID, Nat_InstrumentName + from nat_instrument + join t_instrument_local on Nat_InstrumentID = T_InstrumentLocalNat_InstrumentID + and Nat_InstrumentIsActive = 'Y' + and T_InstrumentLocalIsActive = 'Y' + and Nat_InstrumentName like ? + join nat_qc on Nat_instrumentID = Nat_QcNat_InstrumentID + and Nat_QcIsActive = 'Y' + join nat_qc_control on Nat_QcNat_QcControlID = Nat_QcControlID + and Nat_QcControlIsActive = 'Y' + and Nat_QcControlName like ? + limit 10 offset ?"; + $qry = $this->db->query($sql, [$instrument, $control, $start_offset]); + $last_qry = $this->db->last_query(); + $count = "select count(distinct Nat_InstrumentID) as total + from nat_instrument + join t_instrument_local on Nat_InstrumentID = T_InstrumentLocalNat_InstrumentID + and Nat_InstrumentIsActive = 'Y' + and T_InstrumentLocalIsActive = 'Y' + and Nat_InstrumentName like ? + join nat_qc on Nat_instrumentID = Nat_QcNat_InstrumentID + and Nat_QcIsActive = 'Y' + join nat_qc_control on Nat_QcNat_QcControlID = Nat_QcControlID + and Nat_QcControlIsActive = 'Y' + and Nat_QcControlName like ? + "; + $qry_total_filter = $this->db->query($count, [$instrument, $control]); + $last_qry_total_filter = $this->db->last_query(); + } else if ( + $control == "" && $test != "" + ) { + $sql = "select distinct Nat_InstrumentID, Nat_InstrumentName + from nat_instrument + join t_instrument_local on Nat_InstrumentID = T_InstrumentLocalNat_InstrumentID + and Nat_InstrumentIsActive = 'Y' + and T_InstrumentLocalIsActive = 'Y' + and Nat_InstrumentName like ? + join nat_qc on Nat_instrumentID = Nat_QcNat_InstrumentID + and Nat_QcIsActive = 'Y' + join nat_test on Nat_TestID = Nat_QcNat_TestID + and Nat_TestName like ? + limit 10 offset ?"; + $qry = + $this->db->query($sql, [$instrument, $test, $start_offset]); + $last_qry = $this->db->last_query(); + $count = "select count(distinct Nat_InstrumentID) as total + from nat_instrument + join t_instrument_local on Nat_InstrumentID = T_InstrumentLocalNat_InstrumentID + and Nat_InstrumentIsActive = 'Y' + and T_InstrumentLocalIsActive = 'Y' + and Nat_InstrumentName like ? + join nat_qc on Nat_instrumentID = Nat_QcNat_InstrumentID + and Nat_QcIsActive = 'Y' + join nat_test on Nat_TestID = Nat_QcNat_TestID + and Nat_TestName like ? + "; + $qry_total_filter = $this->db->query($count, [$instrument, $test]); + $last_qry_total_filter = $this->db->last_query(); + } else { + $sql = "select distinct Nat_InstrumentID, Nat_InstrumentName + from nat_instrument + join t_instrument_local on Nat_InstrumentID = T_InstrumentLocalNat_InstrumentID + and Nat_InstrumentIsActive = 'Y' + and T_InstrumentLocalIsActive = 'Y' + and Nat_InstrumentName like ? + join nat_qc on Nat_instrumentID = Nat_QcNat_InstrumentID + and Nat_QcIsActive = 'Y' + join nat_test on Nat_TestID = Nat_QcNat_TestID + and Nat_TestName like ? + join nat_qc_control on Nat_QcNat_QcControlID = Nat_QcControlID + and Nat_QcControlIsActive = 'Y' + and Nat_QcControlName like ? + limit 10 offset ?"; + $qry = $this->db->query($sql, [$instrument, $test, $control, $start_offset]); + $last_qry = $this->db->last_query(); + $count = "select count(distinct Nat_InstrumentID) as total + from nat_instrument + join t_instrument_local on Nat_InstrumentID = T_InstrumentLocalNat_InstrumentID + and Nat_InstrumentIsActive = 'Y' + and T_InstrumentLocalIsActive = 'Y' + and Nat_InstrumentName like ? + join nat_qc on Nat_instrumentID = Nat_QcNat_InstrumentID + and Nat_QcIsActive = 'Y' + join nat_test on Nat_TestID = Nat_QcNat_TestID + and Nat_TestName like ? + join nat_qc_control on Nat_QcNat_QcControlID = Nat_QcControlID + and Nat_QcControlIsActive = 'Y' + and Nat_QcControlName like ? + "; + + $qry_total_filter = $this->db->query($count, [$instrument, $test, $control]); + $last_qry_total_filter = $this->db->last_query(); + } + if (!$qry) { + $this->db->trans_rollback(); + $error = array( + "message" => $this->db->error()["message"], + "sql" => $last_qry + ); + $this->sys_error_db($error); + exit; + } + if (!$qry_total_filter) { + $this->db->trans_rollback(); + $error = array( + "message" => $this->db->error()["message"], + "sql" => $last_qry_total_filter + ); + $this->sys_error_db($error); + exit; + } + $rows = $qry->result_array(); + $total_filter = (int)$qry_total_filter->result_array()[0]["total"]; + + $total = ceil($total_filter / $ROW_PER_PAGE); + $result = array( + "total" => $total, + "total_filter" => $total_filter, + "records" => $rows, + "sql" => $last_qry, + "count" => $last_qry_total_filter + ); + $this->sys_ok($result); + } catch (Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } + function qc_byname() + { + try { + //# cek token valid + if (!$this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $param = $this->sys_input; + + $page = $param["page"]; + $control = "%%"; + if (isset($param['control'])) { + $control = trim($param["control"]); + + if ($control != "") { + $control = '%' . $param['control'] . '%'; + } + } + $instrument = "%%"; + if (isset($param['instrument'])) { + $instrument = trim($param["instrument"]); + if ($instrument != "") { + $instrument = '%' . $param['instrument'] . '%'; + } + } + $test = "%%"; + if (isset($param['test'])) { + $test = trim($param["test"]); + if ($test != "") { + $test = '%' . $param['test'] . '%'; + } + } + $sdate = ""; + if (isset($param['sdate'])) { + $sdate = trim($param["sdate"]); + if ($sdate != "") { + $sdate = $param['sdate']; + } + } + $ROW_PER_PAGE = 10; + $start_offset = 0; + if (isset($param["page"])) { + if ( + is_numeric($param["page"]) && $param["page"] > 0 + ) { + $start_offset = ($page - 1) * $ROW_PER_PAGE; + } + } + $sql = "select distinct M_QcID, M_QcStatMean, M_QcStatSd, M_QcStatTea, + M_QcResultID, M_QcResultValue, M_QcResultIsInstrument , M_QcResultDate, + Nat_QcControlID , Nat_QcControlName , Nat_InstrumentID, Nat_InstrumentName, Nat_TestID , Nat_TestName + from m_qc_result + join m_qc on M_QcResultM_QcID = M_QcID + and M_QcResultDate = ? + and M_QcResultIsActive ='Y' + join nat_qc on M_QcNat_QcID = Nat_QcID + and Nat_QcIsActive = 'Y' + join nat_qc_control on Nat_QcNat_QcControlID =Nat_QcControlID + and Nat_QcControlName like ? + and Nat_QcControlIsActive = 'Y' + join nat_instrument on Nat_QcNat_InstrumentID = Nat_InstrumentID + and Nat_InstrumentName like ? + and Nat_InstrumentIsActive = 'Y' + join nat_test on Nat_QcNat_TestID = Nat_TestID + and Nat_TestName like ? + and Nat_TestIsActive = 'Y' limit 10 offset ?"; + $qry = $this->db->query($sql, [ + $sdate, $control, $instrument, $test, $start_offset + ]); + $last_qry = $this->db->last_query(); + $count = + "select count(distinct M_QcID) as total + from m_qc_result + join m_qc on M_QcResultM_QcID = M_QcID + and M_QcResultDate = ? + and M_QcResultIsActive ='Y' + join nat_qc on M_QcNat_QcID = Nat_QcID + and Nat_QcIsActive = 'Y' + join nat_qc_control on Nat_QcNat_QcControlID =Nat_QcControlID + and Nat_QcControlName like ? + and Nat_QcControlIsActive = 'Y' + join nat_instrument on Nat_QcNat_InstrumentID = Nat_InstrumentID + and Nat_InstrumentName like ? + and Nat_InstrumentIsActive = 'Y' + join nat_test on Nat_QcNat_TestID = Nat_TestID + and Nat_TestName like ? + and Nat_TestIsActive = 'Y' "; + $qry_total_filter = + $this->db->query($count, [ + $sdate, $control, $instrument, $test + ]); + $last_qry_total_filter = $this->db->last_query(); + if ($sdate == "" or $test == "") { + echo json_encode([ + "status" => "ERR", "message" => 'test and sdate is mandatory', + + ]); + } else { + if (!$qry) { + $this->db->trans_rollback(); + $error = array( + "message" => $this->db->error()["message"], + "sql" => $last_qry + ); + $this->sys_error_db($error); + exit; + } + if (!$qry_total_filter) { + $this->db->trans_rollback(); + $error = array( + "message" => $this->db->error()["message"], + "sql" => $last_qry_total_filter + ); + $this->sys_error_db($error); + exit; + } + $rows = $qry->result_array(); + $total_filter = (int)$qry_total_filter->result_array()[0]["total"]; + + $total = ceil($total_filter / $ROW_PER_PAGE); + $result = array( + "total" => $total, + "total_filter" => $total_filter, + "records" => $rows, + "sql" => $last_qry, + "count" => $last_qry_total_filter + ); + $this->sys_ok($result); + } + } catch (Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } + function qc_byid() + { + try { + //# cek token valid + if (!$this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $param = $this->sys_input; + $page = $param["page"]; + $controlid = ""; + $instrumentid = ""; + $ROW_PER_PAGE = 10; + $start_offset = 0; + if (isset($param["page"])) { + if (is_numeric($param["page"]) && $param["page"] > 0) { + $start_offset = ($page - 1) * $ROW_PER_PAGE; + } + } + if (isset($param["controlid"])) { + if (is_numeric($param["controlid"])) { + $controlid = $param["controlid"]; + } + } + if (isset($param["instrumentid"])) { + if (is_numeric($param["instrumentid"])) { + $instrumentid = $param["instrumentid"]; + } + } + $sdate = ""; + if (isset($param['sdate'])) { + $sdate = trim($param["sdate"]); + if ($sdate != "") { + $sdate = $param['sdate']; + } + } + $test = "%%"; + if (isset($param['test'])) { + $test = trim($param["test"]); + if ($test != "") { + $test = '%' . $param['test'] . '%'; + } + } + $sql = "select distinct M_QcID, M_QcStatMean, M_QcStatSd, M_QcStatTea, + M_QcResultID, M_QcResultValue, M_QcResultIsInstrument , M_QcResultDate, + Nat_QcControlID , Nat_QcControlName , Nat_InstrumentID, Nat_InstrumentName, Nat_TestID , Nat_TestName + from m_qc_result + join m_qc on M_QcResultM_QcID = M_QcID + and M_QcResultDate = ? and M_QcResultIsActive ='Y' + join nat_qc on M_QcNat_QcID = Nat_QcID + and Nat_QcIsActive = 'Y' + join nat_qc_control on Nat_QcNat_QcControlID =Nat_QcControlID + and Nat_QcControlID = ? + and Nat_QcControlIsActive = 'Y' + join nat_instrument on Nat_QcNat_InstrumentID = Nat_InstrumentID + and Nat_InstrumentID = ? + and Nat_InstrumentIsActive = 'Y' + join nat_test on Nat_QcNat_TestID = Nat_TestID + and Nat_TestName like ? + and Nat_TestIsActive = 'Y' limit 10 offset ?"; + $qry = $this->db->query($sql, [$sdate, $controlid, $instrumentid, $test, $start_offset]); + $last_qry = $this->db->last_query(); + $count = "select count(distinct M_QcID) as total + from m_qc_result + join m_qc on M_QcResultM_QcID = M_QcID + and M_QcResultDate = ? and M_QcResultIsActive ='Y' + join nat_qc on M_QcNat_QcID = Nat_QcID + and Nat_QcIsActive = 'Y' + join nat_qc_control on Nat_QcNat_QcControlID =Nat_QcControlID + and Nat_QcControlID = ? + and Nat_QcControlIsActive = 'Y' + join nat_instrument on Nat_QcNat_InstrumentID = Nat_InstrumentID + and Nat_InstrumentID = ? + and Nat_InstrumentIsActive = 'Y' + join nat_test on Nat_QcNat_TestID = Nat_TestID + and Nat_TestName like ? + and Nat_TestIsActive = 'Y'"; + $qry_total_filter = $this->db->query($count, [$sdate, $controlid, $instrumentid, $test]); + $last_qry_total_filter = $this->db->last_query(); + if ($controlid == "" or $instrumentid == "" or $sdate == "") { + echo json_encode([ + "status" => "ERR", "message" => 'control, instrument, and sdate is mandatory', + ]); + } else { + if (!$qry) { + $this->db->trans_rollback(); + $error = array( + "message" => $this->db->error()["message"], + "sql" => $last_qry + ); + $this->sys_error_db($error); + exit; + } + + if (!$qry_total_filter) { + $this->db->trans_rollback(); + $error = array( + "message" => $this->db->error()["message"], + "sql" => $last_qry_total_filter + ); + $this->sys_error_db($error); + exit; + } + $rows = $qry->result_array(); + $total_filter = (int)$qry_total_filter->result_array()[0]["total"]; + + $total = ceil($total_filter / $ROW_PER_PAGE); + $result = array( + "total" => $total, + "total_filter" => $total_filter, + "records" => $rows, + "sql" => $last_qry, + "count" => $last_qry_total_filter + ); + $this->sys_ok($result); + } + } catch (Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } + function control_byname() + { + try { + //# cek token valid + if (!$this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $param = $this->sys_input; + // $page = 0; + $page = $param['page']; + + // check input parameter + + // mandatory + $control = trim($param['control']); + $control = "%" . $control . "%"; + + // tidak mandatory + $instrument = ""; + if (isset($param['instrument'])) { + $instrument = trim($param["instrument"]); + if ($instrument != "") { + $instrument = '%' . $param['instrument'] . '%'; + } + } + $test = ""; + if (isset($param['test'])) { + $test = trim($param["test"]); + if ($test != "") { + $test = '%' . $param['test'] . '%'; + } + } + + // hitung start_offset + $ROW_PER_PAGE = 10; + $start_offset = 0; + if (isset($param["page"])) { + if (is_numeric($param["page"]) && $param['page'] > 0) { + $start_offset = ($page - 1) * $ROW_PER_PAGE; + } + } + + // query + if ($instrument == "" && $test == "") { + $sql = "select + distinct Nat_QcControlID, + Nat_QcControlName, + Nat_QcControlLotNumber, + Nat_QcControlExpired, + Nat_QcLevelID, + Nat_QcLevelName + from nat_qc_control + join nat_qc_level + ON Nat_QcControlNat_QcLevelID = Nat_QcLevelID + AND Nat_QcControlIsActive = 'Y' + AND Nat_QcLevelIsActive = 'Y' + AND Nat_QcControlName like ? + limit 10 offset ?"; + $qry = $this->db->query($sql, [$control, $start_offset]); + $last_query = $this->db->last_query(); + + $sql_total_filter = "select + count(distinct Nat_QcControlID, + Nat_QcControlName, + Nat_QcControlLotNumber, + Nat_QcControlExpired, + Nat_QcLevelID, + Nat_QcLevelName) as total_filter + from nat_qc_control + join nat_qc_level + ON Nat_QcControlNat_QcLevelID = Nat_QcLevelID + AND Nat_QcControlIsActive = 'Y' + AND Nat_QcLevelIsActive = 'Y' + AND Nat_QcControlName like ?"; + $qry_total_filter = $this->db->query($sql_total_filter, [$control]); + $last_query_total_filter = $this->db->last_query(); + } else if ($instrument !== "" && $test == "") { + // instrument terisi dan tes kosong + $sql = "select + distinct Nat_QcControlID, + Nat_QcControlName, + Nat_QcControlLotNumber, + Nat_QcControlExpired, + Nat_QcLevelID, + Nat_QcLevelName + from nat_qc_control + join nat_qc_level + ON Nat_QcControlNat_QcLevelID = Nat_QcLevelID + AND Nat_QcControlIsActive = 'Y' + AND Nat_QcLevelIsActive = 'Y' + AND Nat_QcControlName like ? + join nat_qc + ON Nat_QcControlID = Nat_QcNat_QcControlID + AND Nat_QcIsActive = 'Y' + join nat_instrument + ON Nat_QcNat_InstrumentID = Nat_InstrumentID + AND Nat_InstrumentIsActive = 'Y' + AND Nat_InstrumentName like ? + limit 10 offset ?"; + $qry = $this->db->query($sql, [$control, $instrument, $start_offset]); + $last_query = $this->db->last_query(); + + $sql_total_filter = "select + count(distinct Nat_QcControlID, + Nat_QcControlName, + Nat_QcControlLotNumber, + Nat_QcControlExpired, + Nat_QcLevelID, + Nat_QcLevelName) as total_filter + from nat_qc_control + join nat_qc_level + ON Nat_QcControlNat_QcLevelID = Nat_QcLevelID + AND Nat_QcControlIsActive = 'Y' + AND Nat_QcLevelIsActive = 'Y' + AND Nat_QcControlName like ? + join nat_qc + ON Nat_QcControlID = Nat_QcNat_QcControlID + AND Nat_QcIsActive = 'Y' + join nat_instrument + ON Nat_QcNat_InstrumentID = Nat_InstrumentID + AND Nat_InstrumentIsActive = 'Y' + AND Nat_InstrumentName like ?"; + $qry_total_filter = $this->db->query($sql_total_filter, [$control, $instrument]); + $last_query_total_filter = $this->db->last_query(); + } else if ($instrument == "" && $test !== "") { + // instrument kosong dan tes terisi + $sql = "select + distinct Nat_QcControlID, + Nat_QcControlName, + Nat_QcControlLotNumber, + Nat_QcControlExpired, + Nat_QcLevelID, + Nat_QcLevelName + from nat_qc_control + join nat_qc_level + ON Nat_QcControlNat_QcLevelID = Nat_QcLevelID + AND Nat_QcControlIsActive = 'Y' + AND Nat_QcLevelIsActive = 'Y' + AND Nat_QcControlName like ? + join nat_qc + ON Nat_QcControlID = Nat_QcNat_QcControlID + AND Nat_QcIsActive = 'Y' + join nat_test + ON Nat_QcNat_TestID = Nat_TestID + AND Nat_TestIsActive = 'Y' + AND Nat_TestName like ? + limit 10 offset ?"; + $qry = $this->db->query($sql, [$control, $test, $start_offset]); + $last_query = $this->db->last_query(); + + $sql_total_filter = "select + count(distinct Nat_QcControlID, + Nat_QcControlName, + Nat_QcControlLotNumber, + Nat_QcControlExpired, + Nat_QcLevelID, + Nat_QcLevelName) as total_filter + from nat_qc_control + join nat_qc_level + ON Nat_QcControlNat_QcLevelID = Nat_QcLevelID + AND Nat_QcControlIsActive = 'Y' + AND Nat_QcLevelIsActive = 'Y' + AND Nat_QcControlName like ? + join nat_qc + ON Nat_QcControlID = Nat_QcNat_QcControlID + AND Nat_QcIsActive = 'Y' + join nat_test + ON Nat_QcNat_TestID = Nat_TestID + AND Nat_TestIsActive = 'Y' + AND Nat_TestName like ?"; + $qry_total_filter = $this->db->query($sql_total_filter, [$control, $test]); + $last_query_total_filter = $this->db->last_query(); + } else { + // instrument dan test terisi + $sql = "select + distinct Nat_QcControlID, + Nat_QcControlName, + Nat_QcControlLotNumber, + Nat_QcControlExpired, + Nat_QcLevelID, + Nat_QcLevelName + from nat_qc_control + join nat_qc_level + ON Nat_QcControlNat_QcLevelID = Nat_QcLevelID + AND Nat_QcControlIsActive = 'Y' + AND Nat_QcLevelIsActive = 'Y' + AND Nat_QcControlName like ? + join nat_qc + ON Nat_QcControlID = Nat_QcNat_QcControlID + AND Nat_QcIsActive = 'Y' + join nat_instrument + ON Nat_QcNat_InstrumentID = Nat_InstrumentID + AND Nat_InstrumentIsActive = 'Y' + AND Nat_InstrumentName like ? + join nat_test + ON Nat_QcNat_TestID = Nat_TestID + AND Nat_TestIsActive = 'Y' + AND Nat_TestName like ? + limit 10 offset ?"; + $qry = $this->db->query($sql, [$control, $instrument, $test, $start_offset]); + $last_query = $this->db->last_query(); + + $sql_total_filter = "select + count(distinct Nat_QcControlID, + Nat_QcControlName, + Nat_QcControlLotNumber, + Nat_QcControlExpired, + Nat_QcLevelID, + Nat_QcLevelName) as total_filter + from nat_qc_control + join nat_qc_level + ON Nat_QcControlNat_QcLevelID = Nat_QcLevelID + AND Nat_QcControlIsActive = 'Y' + AND Nat_QcLevelIsActive = 'Y' + AND Nat_QcControlName like ? + join nat_qc + ON Nat_QcControlID = Nat_QcNat_QcControlID + AND Nat_QcIsActive = 'Y' + join nat_instrument + ON Nat_QcNat_InstrumentID = Nat_InstrumentID + AND Nat_InstrumentIsActive = 'Y' + AND Nat_InstrumentName like ? + join nat_test + ON Nat_QcNat_TestID = Nat_TestID + AND Nat_TestIsActive = 'Y' + AND Nat_TestName like ?"; + $qry_total_filter = $this->db->query($sql_total_filter, [$control, $instrument, $test]); + $last_query_total_filter = $this->db->last_query(); + } + + if (!$qry) { + $this->db->trans_rollback(); + $error = array( + "message" => $this->db->error()["message"], + "sql" => $last_query + ); + $this->sys_error_db($error); + exit; + } + + if (!$qry_total_filter) { + $this->db->trans_rollback(); + $error = array( + "message" => $this->db->error()["message"], + "sql" => $last_query_total_filter + ); + $this->sys_error_db($error); + exit; + } + + $rows = $qry->result_array(); + $rows_total_filter = $qry_total_filter->result_array(); + $total = ceil($rows_total_filter[0]["total_filter"] / $ROW_PER_PAGE); + $result = array( + "total" => $total, + "total_filter" => (int)$rows_total_filter[0]["total_filter"], + "records" => $rows, + "sql" => $this->db->last_query() + ); + $this->sys_ok($result); + } catch (Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } + function control_byid() + { + try { + //# cek token valid + if (!$this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $param = $this->sys_input; + $page = $param['page']; + + // check input parameter + + // mandatory + $id = 0; + if (isset($param['id'])) { + if (is_numeric($param['id'])) { + $id = $param['id']; + } + } + + // hitung start_offset + $ROW_PER_PAGE = 10; + $start_offset = 0; + if (isset($param["page"])) { + if (is_numeric($param["page"]) && $param['page'] > 0) { + $start_offset = ($page - 1) * $ROW_PER_PAGE; + } + } + + + $sql = "select + distinct Nat_QcControlID, + Nat_QcControlName, + Nat_QcControlLotNumber, + Nat_QcControlExpired, + Nat_QcLevelID, + Nat_QcLevelName, + Nat_InstrumentID, + Nat_InstrumentName, + Nat_TestID, + Nat_TestName + from nat_qc_control + join nat_qc_level + ON Nat_QcControlNat_QcLevelID = Nat_QcLevelID + AND Nat_QcControlIsActive = 'Y' + AND Nat_QcLevelIsActive = 'Y' + join nat_qc + ON Nat_QcControlID = Nat_QcNat_QcControlID + AND Nat_QcIsActive = 'Y' + join nat_instrument + ON Nat_QcNat_InstrumentID = Nat_InstrumentID + AND Nat_InstrumentIsActive = 'Y' + AND Nat_InstrumentID = ? + join nat_test + ON Nat_QcNat_TestID = Nat_TestID + AND Nat_TestIsActive = 'Y' + limit 10 offset ?"; + $qry = $this->db->query($sql, [$id, $start_offset]); + $last_query = $this->db->last_query(); + + $sql_total_filter = "select + count(distinct Nat_QcControlID, + Nat_QcControlName, + Nat_QcControlLotNumber, + Nat_QcControlExpired, + Nat_QcLevelID, + Nat_QcLevelName, + Nat_InstrumentID, + Nat_InstrumentName, + Nat_TestID, + Nat_TestName) as total_filter + from nat_qc_control + join nat_qc_level + ON Nat_QcControlNat_QcLevelID = Nat_QcLevelID + AND Nat_QcControlIsActive = 'Y' + AND Nat_QcLevelIsActive = 'Y' + join nat_qc + ON Nat_QcControlID = Nat_QcNat_QcControlID + AND Nat_QcIsActive = 'Y' + join nat_instrument + ON Nat_QcNat_InstrumentID = Nat_InstrumentID + AND Nat_InstrumentIsActive = 'Y' + AND Nat_InstrumentID = ? + join nat_test + ON Nat_QcNat_TestID = Nat_TestID + AND Nat_TestIsActive = 'Y'"; + $qry_total_filter = $this->db->query($sql_total_filter, [$id]); + $last_query_total_filter = $this->db->last_query(); + + if (!$qry) { + $this->db->trans_rollback(); + $error = array( + "message" => $this->db->error()["message"], + "sql" => $last_query + ); + $this->sys_error_db($error); + exit; + } + + if (!$qry_total_filter) { + $this->db->trans_rollback(); + $error = array( + "message" => $this->db->error()["message"], + "sql" => $last_query_total_filter + ); + $this->sys_error_db($error); + exit; + } + + $rows = $qry->result_array(); + $rows_total_filter = $qry_total_filter->result_array(); + $total = ceil($rows_total_filter[0]["total_filter"] / $ROW_PER_PAGE); + + $result = array( + "total" => $total, + "total_filter" => (int)$rows_total_filter[0]["total_filter"], + "records" => $rows, + "sql" => $this->db->last_query() + ); + $this->sys_ok($result); + } catch (Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } +} diff --git a/application/controllers/Station.php b/application/controllers/Station.php new file mode 100644 index 00000000..67f35de9 --- /dev/null +++ b/application/controllers/Station.php @@ -0,0 +1,479 @@ +db_onedev = $this->load->database("onedev", true); + } + + + function lookupbahan(){ + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $prm = $this->sys_input; + $id = $prm['id']; + $sql = "select T_BahanID as id, + T_BahanT_SampleStationID as usergroupid, + T_BahanCode as code, + T_BahanName As name, + 'xxx' as action + from t_bahan + join t_samplestation oN T_BahanT_SampleStationID = T_SampleStationID + where + T_BahanT_SampleStationID = {$id} AND T_BahanIsActive = 'Y'"; + //echo $sql; + $rows = $this->db_onedev->query($sql)->result(); + + $result = array ("total" => count($rows), "records" => $rows); + $this->sys_ok($result); + + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } + + public function lookup() + { + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + + $prm = $this->sys_input; + $search = $prm['search']; + $all = $prm['all']; + $limit = ''; + if($all == 'N'){ + $limit = ' LIMIT 10'; + } + $sql = "select COUNT(*) as total + from t_samplestation + where + T_SampleStationIsActive = 'Y'"; + $sql_param = array($search); + $total = $this->db_onedev->query($sql,$sql_param)->row()->total; + + + $sql = "select T_SampleStationID as id, + T_SampleStationCode as code, + T_SampleStationName as name, + T_SampleStationIsNonLab as isnonlab, T_SampleStationName as description , 'xxx' as usergrouptype + from t_samplestation + where + T_SampleStationName LIKE CONCAT('%','{$search}','%') AND + T_SampleStationIsActive = 'Y' $limit"; + $sql_param = array($search); + $query = $this->db_onedev->query($sql); + //echo $this->db_onedev->last_query(); + if ($query) { + $rows = $query->result_array(); + + + } else { + $this->sys_error_db("t_samplestation select",$this->db_onedev); + exit; + } + + + $result = array ("total" => $total, "total_filter"=>count($rows),"records" => $rows); + $this->sys_ok($result); + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } + + + public function addnewstation() + { + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + + //# ambil parameter input + $prm = $this->sys_input; + + $name_station = $prm['name']; + $code_station = $prm['code']; + $isnonlab_station = $prm['isnonlab']; + + + $query = "SELECT COUNT(*) as exist FROM t_samplestation WHERE T_SampleStationIsActive = 'Y' AND T_SampleStationName = '{$name_station}'"; + $exist_name = $this->db_onedev->query($query)->row()->exist; + + + //echo $exist_name; + if($exist_name == 0 ){ + $sql = "insert into t_samplestation( + T_SampleStationCode, + T_SampleStationName, + T_SampleStationIsNonLab, + T_SampleStationCreated, + T_SampleStationLastUpdated + ) + values( ?, ?, ?,now(), now())"; + $query = $this->db_onedev->query($sql, + array( + $name_station, + $code_station, + $isnonlab_station + ) + ); + //echo $query; + if (!$query) { + $this->sys_error_db("t_samplestation insert"); + exit; + } + + $result = array ("total" => 1, "records" => array("xid" => 0)); + $this->sys_ok($result); + } else{ + $errors = array(); + + if($exist_name != 0){ + array_push($errors,array('field'=>'name','msg'=>'Nama sudah ada ')); + } + + $result = array ("total" => -1,"errors" => $errors, "records" => 0); + $this->sys_ok($result); + } + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } + + public function editstation() + { + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + + //# ambil parameter input + $prm = $this->sys_input; + $id_station = $prm['id']; + $code_station = $prm['code']; + $name_station = $prm['name']; + $isnonlab_station = $prm['isnonlab']; + + $query = "SELECT COUNT(*) as exist FROM t_samplestation WHERE T_SampleStationIsActive = 'Y' AND T_SampleStationName = '{$name_station}' + AND T_SampleStationID <> {$id_station} "; +$exist_name = $this->db_onedev->query($query)->row()->exist; + + +if($exist_name == 0){ + + $sql = "update t_samplestation SET + T_SampleStationCode = ?, + T_SampleStationName = ?, + T_SampleStationIsNonLab = ?, + T_SampleStationLastUpdated = now() + where + T_SampleStationID = ? +"; +$query = $this->db_onedev->query($sql, + array( + $code_station, + $name_station, + $isnonlab_station, + $id_station + ) +); +//file_put_contents("/tmp/adi-update-user.sql",$this->db_onedev->last_query()); +//echo $query; +if (!$query) { + $this->sys_error_db("t_samplestation update"); + exit; +} + +$result = array ("total" => 1, "records" => array("xid" => $id_station)); +$this->sys_ok($result); +}else{ + $errors = array(); + + + if($exist_name != 0){ + array_push($errors,array('field'=>'name','msg'=>'Nama sudah ada')); + } + + $result = array ("total" => -1,"errors" => $errors, "records" => 0); + $this->sys_ok($result); +} + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } + + + + public function editbahan() + { + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + + //# ambil parameter input + $prm = $this->sys_input; + $bahanid = $prm['xid']; + $code = $prm['code']; + $name = $prm['name']; + $xstationname = $prm['xstationname']; + + + + $query = "SELECT COUNT(*) as exist FROM t_bahan WHERE T_BahanIsActive = 'Y' AND T_BahanName = '{$name}' + and T_BahanID <> $bahanid "; + $exist_name = $this->db_onedev->query($query)->row()->exist; + + if($exist_name == 0){ + + $sql = "update m_user SET + T_BahanCode = ?, + T_BahanName = ?, + T_BahanT_SampleStationID = ?, + T_BahanLastUpdated = now() + where T_BahanID = ? "; + + $query = $this->db_onedev->query($sql, + array( + $code, + $name, + $xstationname["T_SampleStationID"], + $bahanid + )); + if (!$query) { + $this->sys_error_db("t_bahan update",$this->db_onedev); + exit; + } + $result = array ("total" => 1, "records" => array("xid" => $bahanid)); + $this->sys_ok($result); + } else { + $errors = array(); + + if($exist_name != 0){ + array_push($errors,array('field'=>'name','msg'=>'Nama sudah ada yang pakai dong')); + } + + $result = array ("total" => -1,"errors" => $errors, "records" => 0); + $this->sys_ok($result); + } + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } + + public function addnewbahan() + { + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + + //# ambil parameter input + $prm = $this->sys_input; + $stationid = $prm['stationid']; + $code = $prm['code']; + $name = $prm['name']; + + if($prm['xid'] == 0){ + $query = "SELECT COUNT(*) as exist FROM t_bahan WHERE T_BahanIsActive = 'Y' AND T_BahanName = '{$name}'"; + $exist_name = $this->db_onedev->query($query)->row()->exist; + + if($exist_name == 0){ + $sql = "insert into t_bahan( + T_BahanT_SampleStationID, + T_BahanCode, + T_BahanName, + T_BahanCreated, + T_BahanLastUpdated + ) + values( ?,?,?,now(),now())"; +$query = $this->db_onedev->query($sql, + array( + $stationid, + $code, + $name + ) +); +if (!$query) { + $this->sys_error_db("t_bahan insert",$this->db_onedev); + exit; +} +$result = array ("total" => 1, "records" => array("xid" => 0)); +$this->sys_ok($result); + }else{ + $errors = array(); + if($exist_name != 0){ + array_push($errors,array('field'=>'name','msg'=>'Nama sudah ada yang pakai dong')); + } + + + $result = array ("total" => -1,"errors" => $errors, "records" => 0); + $this->sys_ok($result); + } + }else{ + $query = "SELECT COUNT(*) as exist FROM t_bahan WHERE T_BahanIsActive = 'Y' AND T_BahanName = '{$name}' AND T_BahanID <> {$prm['xid']}"; + $exist_name = $this->db_onedev->query($query)->row()->exist; + //echo $query; + + //echo $query; + if($exist_name == 0 ){ + $sql = "UPDATE t_bahan SET T_BahanName = '{$name}', T_BahanCode = '{$code}' WHERE T_BahanID = '{$prm['xid']}'"; + //echo $sql; + $query = $this->db_onedev->query($sql); + $result = array ("total" => 1, "records" => array("xid" => 0)); + $this->sys_ok($result); + }else{ + $errors = array(); + if($exist_name != 0){ + array_push($errors,array('field'=>'name','msg'=>'name sudah ada yang pakai dong')); + } + + $result = array ("total" => -1,"errors" => $errors, "records" => 0); + $this->sys_ok($result); + } + } + + + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } + + + + public function deletebahan() + { + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + + //# ambil parameter input + $prm = $this->sys_input; + + $sql = "update t_bahan SET + T_BahanIsActive = 'N', + T_BahanLastUpdated = now() + WHERE + T_BahanID = ? + +"; + +$query = $this->db_onedev->query($sql, + array( + $prm['id'] + ) +); +// echo $query; +if (!$query) { + $this->sys_error_db("t_bahan delete"); + exit; +} + + + + + +$result = array ("total" => 1, "records" => array("xid" => 0)); +$this->sys_ok($result); + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } + + public function deleteselect() + { + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + + //# ambil parameter input + $prm = $this->sys_input; + + $sql = "update t_samplestation SET + T_SampleStationIsActive = 'N', + T_SampleStationLastUpdated = now() + WHERE + T_SampleStationID = ? + +"; + +$query = $this->db_onedev->query($sql, + array( + $prm['id'] + ) +); +// echo $query; +if (!$query) { + $this->sys_error_db("t_samplestation delete"); + exit; +} + +$sql = "UPDATE m_user SET + M_UserIsActive = 'N', + M_UserLastUpdated = now() + WHERE + M_UserM_UserGroupID = ? +"; + +$query = $this->db_onedev->query($sql, + array( + $prm['id'] + ) +); +// echo $query; +if (!$query) { + $this->sys_error_db("m_user delete"); + exit; +} + +$result = array ("total" => 1, "records" => array("xid" => 0)); +$this->sys_ok($result); + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } + + } diff --git a/application/controllers/Test_api.php b/application/controllers/Test_api.php new file mode 100644 index 00000000..7fa421be --- /dev/null +++ b/application/controllers/Test_api.php @@ -0,0 +1,18 @@ +get_param()); + echo "header : "; + print_r(getallheaders()); + } +} diff --git a/application/controllers/Test_rpt.php b/application/controllers/Test_rpt.php new file mode 100644 index 00000000..0cef45c6 --- /dev/null +++ b/application/controllers/Test_rpt.php @@ -0,0 +1,18 @@ +url = "http://odoo.sismedika.com:8070"; + $this->db_odoo = "odoo16_sismedika"; + $this->username = "admin@sismedika.com"; + $this->password = "duD#Z36qH5ctmRRD"; + $this->common = ripcord::client("{$this->url}/xmlrpc/2/common"); + $this->uid = $this->common->authenticate($this->db_odoo, $this->username, $this->password, array()); + $this->model = ripcord::client("{$this->url}/xmlrpc/2/object"); + $this->db->query("use one_support"); + $this->teams = [3, 22, 18, 21, 24, 15, 49, 34]; + } + + function external_by_date($date = "") + { + if ($date == "") $date = date("Y-m-d"); + $startDate = "$date 00:00:00"; + $endDate = "$date 23:59:59"; + // Define domain for search + $domain = [ + "&", + ['project_id', '!=', false], + "&", + ['project_id', '!=', "HISv3"], + "&", + ['employee_id', 'in', $this->teams], + "&", + ['date', '>=', $startDate], + ['date', '<=', $endDate] + ]; + $kwarg = array( + "limit" => 1000, + "offset" => 0, + "order" => "user_id", + 'fields' => array( + 'name', 'date', 'project_id', 'task_id', + 'unit_amount', 'user_id' + ) + ); + // Search for timesheet entries + $timesheets = $this->model->execute_kw( + $this->db_odoo, + $this->uid, + $this->password, + 'account.analytic.line', + 'web_search_read', + array($domain), + $kwarg + ); + $total_hours = 0; + $result = []; + foreach ($timesheets["records"] as $r) { + $name = $r["name"]; + $date = $r["date"]; + $project = $r["project_id"][1]; + $hour = $r["unit_amount"]; + $date = $r["date"]; + $user = $r["user_id"][1]; + $total_hours += $hour; + + if (!isset($result[$user])) { + $result[$user] = []; + } + if (!isset($result[$user][$project])) { + $result[$user][$project] = $hour; + } else { + $result[$user][$project] += $hour; + } + } + return $result; + } + + function sas_one($date = "") + { + $sas_teams = [34, 36, 37, 38, 39, 40, 41, 42, 43, 44]; + if ($date == "") $date = date("Y-m-d"); + $startDate = "$date 00:00:00"; + $endDate = "$date 23:59:59"; + // Define domain for search + $domain = [ + "&", + ['project_id', '!=', false], + "&", + ['employee_id', 'in', $sas_teams], + "&", + ['date', '>=', $startDate], + ['date', '<=', $endDate] + ]; + $kwarg = array( + "limit" => 1000, + "offset" => 0, + "order" => "user_id", + 'fields' => array( + 'name', 'date', 'project_id', 'task_id', + 'unit_amount', 'user_id' + ) + ); + // Search for timesheet entries + $timesheets = $this->model->execute_kw( + $this->db_odoo, + $this->uid, + $this->password, + 'account.analytic.line', + 'web_search_read', + array($domain), + $kwarg + ); + $total_hours = 0; + $result = []; + foreach ($timesheets["records"] as $r) { + $name = $r["name"]; + $date = $r["date"]; + $project = $r["project_id"][1]; + $task = $r["task_id"][1]; + $hour = $r["unit_amount"]; + $date = $r["date"]; + $user = $r["user_id"][1]; + $total_hours += $hour; + $total_hours += $hour; + $result[$user][] = [ + "project" => $project, + "task" => $task, + "date" => $date, + "desc" => $name, + "hour" => $hour + ]; + } + $table = "@startuml\n "; + $total_staff = 0; + $prev_user = ""; + $table .= "object Timesheet { \n"; + $table .= "\n"; + foreach ($result as $user => $data) { + if ($prev_user != $user) { + $table .= "$user\n"; + $table .= "<#lightblue,#black>|= Project |= Task |= Desc |= Hour |\n"; + $total_staff++; + $prev_user = $user; + } + foreach ($data as $d) { + $xdesc = $d["desc"]; + if (strlen($xdesc) > 30) { + $xdesc = substr($xdesc, 0, 26) . "..."; + } + $table .= "<#white>| {$d["project"]}| {$d["task"]}| {$xdesc}| {$d["hour"]}|\n"; + } + } + $msg = "Collection Date : " . date("Y-m-d H:i:s") . "\n"; + $msg .= "Total Hour : " . $total_hours . "\n"; + $msg .= "Total Staff: " . $total_staff . "\n"; + $msg .= "---\n"; + $table = str_replace("", $msg, $table); + if ($prev_user != "") { + $table .= "}\n\n"; + } + $table .= "@enduml"; + $img = $this->puml_post($table); + $url = "https://puml.sismedika.online/png/$img"; + $this->wa_to_sasone($url); + } + + function by_project_date($project, $date = "") + { + if ($date == "") $date = date("Y-m-d"); + $startDate = "$date 00:00:00"; + $endDate = "$date 23:59:59"; + // Define domain for search + $domain = [ + "&", + ['project_id', '!=', false], + "&", + ['project_id', 'ilike', "$project"], + "&", + ['date', '>=', $startDate], + ['date', '<=', $endDate] + ]; + + $kwarg = array( + "limit" => 1000, + "offset" => 0, + "order" => "user_id", + 'fields' => array( + 'name', 'date', 'task_id', + 'unit_amount', 'user_id' + ) + ); + // Search for timesheet entries + $timesheets = $this->model->execute_kw( + $this->db_odoo, + $this->uid, + $this->password, + 'account.analytic.line', + 'web_search_read', + array($domain), + $kwarg + ); + $total_hours = 0; + $result = []; + foreach ($timesheets["records"] as $r) { + $name = $r["name"]; + $date = $r["date"]; + $task = $r["task_id"][1]; + $hour = $r["unit_amount"]; + $date = $r["date"]; + $user = $r["user_id"][1]; + $total_hours += $hour; + $result[$user][] = [ + "task" => $task, + "date" => $date, + "desc" => $name, + "hour" => $hour + ]; + } + $table = "@startuml\n "; + $msg = "Collection Date : " . date("Y-m-d H:i:s") . "\n"; + $msg .= "Total Hour : " . $total_hours . "\n"; + $total_staff = 0; + $prev_user = ""; + $table .= "object Timesheet { \n"; + $table .= "\n"; + foreach ($result as $user => $data) { + if ($prev_user != $user) { + $table .= "$user\n"; + $table .= "<#lightblue,#black>|= Date |= Task |= Desc |= Hour |\n"; + $total_staff++; + $prev_user = $user; + } + foreach ($data as $d) { + $xdesc = $d["desc"]; + if (strlen($xdesc) > 50) { + $xdesc = substr($xdesc, 0, 46) . "..."; + } + $table .= "<#white>| {$d["date"]}| {$d["task"]}| {$xdesc}| {$d["hour"]}|\n"; + } + } + $msg .= "Total Staff: " . $total_staff . "\n"; + $msg .= "---\n"; + $table = str_replace("", $msg, $table); + $result = $this->external_by_date($date); + $have_ext = false; + if (count($result) > 0) { + $have_ext = true; + $table .= "\n\n\n"; + $table .= "Non HIS V3\n"; + $table .= "<#lightblue,#black>|= User|= Project|= Hour |\n"; + $total_hours = 0; + foreach ($result as $u => $r) { + foreach ($r as $prj => $hour) { + $table .= "<#white>| {$u}| {$prj}| {$hour}|\n"; + $total_hours += $hour; + } + } + echo "\n"; + $table .= "Total Hour: " . $total_hours . "\n"; + } + if ($prev_user != "" || $have_ext) { + $table .= "}\n\n"; + } + $table .= "@enduml"; + $img = $this->puml_post($table); + $url = "https://puml.sismedika.online/png/$img"; + //echo $url; + $this->wa_to_group($url); + } + function wa_to_sasone( + $url + ) { + $this->load->library("Wa_sas"); + $hp = "6282113702602-1584412485@g.us"; + $resp = $this->wa_sas->send_image( + $hp, + "Timesheet Summary", + $url, + "image/png", + "sasone-status", + "png", + true + ); + print_r($resp); + } + + function wa_to_group( + $url + ) { + $this->load->library("Wa_sas"); + //$hp = "6287823783747"; + //group set to true + $hp = "120363194169273747@g.us"; + //$resp = $this->wa_sas->send_message($hp, $msg,true); + // print_r($resp); + $resp = $this->wa_sas->send_image( + $hp, + "Timesheet Summary", + $url, + "image/png", + "hisv3-status", + "png", + true + ); + print_r($resp); + } + function wa_to_sasone_done( + $msg + ) { + $this->load->library("Wa_sas"); + $hp = "6287823783747"; + //$hp="6282113702602-1584412485@g.us"; + //bisone supporter + //$hp = "6281328282909-1583223560@g.us"; + $resp = $this->wa_sas->send_message($hp, $msg, true); + } + + function puml_post($data) + { + $url = "https://puml.sismedika.online/coder"; + $ch = curl_init($url); + $payload = $data; + curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/plain')); + # Return response instead of printing. + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + # Send request. + $result = curl_exec($ch); + curl_close($ch); + return $result; + } + function bool_day($inp_dow) + { + $dow = strtolower(date("D", strtotime("now"))); + if ($inp_dow == $dow) return true; + return false; + } +} diff --git a/application/controllers/Timesheet_v2.php b/application/controllers/Timesheet_v2.php new file mode 100644 index 00000000..a99530f9 --- /dev/null +++ b/application/controllers/Timesheet_v2.php @@ -0,0 +1,575 @@ +url = "http://odoo.sismedika.com:8070"; + $this->db_odoo = "odoo16_sismedika"; + $this->username = "admin@sismedika.com"; + $this->password = "duD#Z36qH5ctmRRD"; + $this->common = ripcord::client("{$this->url}/xmlrpc/2/common"); + $this->uid = $this->common->authenticate($this->db_odoo, $this->username, $this->password, array()); + $this->model = ripcord::client("{$this->url}/xmlrpc/2/object"); + $this->db->query("use one_support"); + $this->teams = [3, 22, 18, 21, 24, 15, 49, 34]; + } + + // --- v2 + // + function mobile($date = "") + { + $teams = [30, 32, 29, 27, 43]; + if ($date == "") $date = date("Y-m-d"); + $startDate = "$date 00:00:00"; + $endDate = "$date 23:59:59"; + // Define domain for search + $domain = [ + "&", + ['project_id', '!=', false], + "&", + ['employee_id', 'in', $teams], + "&", + ['date', '>=', $startDate], + ['date', '<=', $endDate] + ]; + $kwarg = array( + "limit" => 1000, + "offset" => 0, + "order" => "user_id", + 'fields' => array( + 'name', 'date', 'project_id', 'task_id', + 'unit_amount', 'user_id' + ) + ); + // Search for timesheet entries + $timesheets = $this->model->execute_kw( + $this->db_odoo, + $this->uid, + $this->password, + 'account.analytic.line', + 'web_search_read', + array($domain), + $kwarg + ); + $total_hours = 0; + $result = []; + foreach ($timesheets["records"] as $r) { + $name = $r["name"]; + $date = $r["date"]; + $project = $r["project_id"][1]; + $task = $r["task_id"][1]; + $hour = round($r["unit_amount"], 1); + $date = $r["date"]; + $user = $r["user_id"][1]; + $total_hours += $hour; + $total_hours += $hour; + $result[$user][] = [ + "project" => $project, + "task" => $task, + "date" => $date, + "desc" => $name, + "hour" => $hour + ]; + } + $table = "@startuml\n "; + $total_staff = 0; + $prev_user = ""; + $table .= "object Timesheet { \n"; + $table .= "\n"; + foreach ($result as $user => $data) { + if ($prev_user != $user) { + $table .= "$user\n"; + $table .= "<#lightblue,#black>|= Project |= Task |= Desc |= Hour |\n"; + $total_staff++; + $prev_user = $user; + } + foreach ($data as $d) { + $xdesc = $d["desc"]; + if (strlen($xdesc) > 30) { + $xdesc = substr($xdesc, 0, 26) . "..."; + } + $table .= "<#white>| {$d["project"]}| {$d["task"]}| {$xdesc}| {$d["hour"]}|\n"; + } + } + $msg = "Collection Date : " . date("Y-m-d H:i:s") . "\n"; + $msg .= "Total Hour : " . $total_hours . "\n"; + $msg .= "Total Staff: " . $total_staff . "\n"; + $msg .= "---\n"; + $table = str_replace("", $msg, $table); + if ($prev_user != "") { + $table .= "}\n\n"; + } + $table .= "@enduml"; + $img = $this->puml_post($table); + $url = "https://puml.sismedika.online/png/$img"; + $this->wa_to_mobile($url); + } + function wa_to_mobile( + $url + ) { + $this->load->library("Wa_sas"); + $hp = "120363166799845051@g.us"; + $resp = $this->wa_sas->send_image( + $hp, + "Timesheet Summary", + $url, + "image/png", + "dev.backend-status", + "png", + true + ); + print_r($resp); + } + + function ais($date = "") + { + $teams = [19, 28, 47, 31, 44]; + if ($date == "") $date = date("Y-m-d"); + $startDate = "$date 00:00:00"; + $endDate = "$date 23:59:59"; + // Define domain for search + $domain = [ + "&", + ['project_id', '!=', false], + "&", + ['employee_id', 'in', $teams], + "&", + ['date', '>=', $startDate], + ['date', '<=', $endDate] + ]; + $kwarg = array( + "limit" => 1000, + "offset" => 0, + "order" => "user_id", + 'fields' => array( + 'name', 'date', 'project_id', 'task_id', + 'unit_amount', 'user_id' + ) + ); + // Search for timesheet entries + $timesheets = $this->model->execute_kw( + $this->db_odoo, + $this->uid, + $this->password, + 'account.analytic.line', + 'web_search_read', + array($domain), + $kwarg + ); + $total_hours = 0; + $result = []; + foreach ($timesheets["records"] as $r) { + $name = $r["name"]; + $date = $r["date"]; + $project = $r["project_id"][1]; + $task = $r["task_id"][1]; + $hour = round($r["unit_amount"], 1); + $date = $r["date"]; + $user = $r["user_id"][1]; + $total_hours += $hour; + $total_hours += $hour; + $result[$user][] = [ + "project" => $project, + "task" => $task, + "date" => $date, + "desc" => $name, + "hour" => $hour + ]; + } + $table = "@startuml\n "; + $total_staff = 0; + $prev_user = ""; + $table .= "object Timesheet { \n"; + $table .= "\n"; + foreach ($result as $user => $data) { + if ($prev_user != $user) { + $table .= "$user\n"; + $table .= "<#lightblue,#black>|= Project |= Task |= Desc |= Hour |\n"; + $total_staff++; + $prev_user = $user; + } + foreach ($data as $d) { + $xdesc = $d["desc"]; + if (strlen($xdesc) > 30) { + $xdesc = substr($xdesc, 0, 26) . "..."; + } + $table .= "<#white>| {$d["project"]}| {$d["task"]}| {$xdesc}| {$d["hour"]}|\n"; + } + } + $msg = "Collection Date : " . date("Y-m-d H:i:s") . "\n"; + $msg .= "Total Hour : " . $total_hours . "\n"; + $msg .= "Total Staff: " . $total_staff . "\n"; + $msg .= "---\n"; + $table = str_replace("", $msg, $table); + if ($prev_user != "") { + $table .= "}\n\n"; + } + $table .= "@enduml"; + $img = $this->puml_post($table); + $url = "https://puml.sismedika.online/png/$img"; + $this->wa_to_ais($url); + } + function wa_to_ais( + $url + ) { + $this->load->library("Wa_sas"); + $hp = "120363185074039892@g.us"; + $resp = $this->wa_sas->send_image( + $hp, + "Timesheet Summary", + $url, + "image/png", + "dev.backend-status", + "png", + true + ); + print_r($resp); + } + function wa_to_me( + $url + ) { + $this->load->library("Wa_sas"); + $hp = "6287823783747"; + $resp = $this->wa_sas->send_image( + $hp, + "Timesheet Summary", + $url, + "image/png", + "ais-status", + "png" + ); + print_r($resp); + } + + + + + + + function external_by_date($date = "") + { + if ($date == "") $date = date("Y-m-d"); + $startDate = "$date 00:00:00"; + $endDate = "$date 23:59:59"; + // Define domain for search + $domain = [ + "&", + ['project_id', '!=', false], + "&", + ['project_id', '!=', "HISv3"], + "&", + ['employee_id', 'in', $this->teams], + "&", + ['date', '>=', $startDate], + ['date', '<=', $endDate] + ]; + $kwarg = array( + "limit" => 1000, + "offset" => 0, + "order" => "user_id", + 'fields' => array( + 'name', 'date', 'project_id', 'task_id', + 'unit_amount', 'user_id' + ) + ); + // Search for timesheet entries + $timesheets = $this->model->execute_kw( + $this->db_odoo, + $this->uid, + $this->password, + 'account.analytic.line', + 'web_search_read', + array($domain), + $kwarg + ); + $total_hours = 0; + $result = []; + foreach ($timesheets["records"] as $r) { + $name = $r["name"]; + $date = $r["date"]; + $project = $r["project_id"][1]; + $hour = round($r["unit_amount"], 1); + $date = $r["date"]; + $user = $r["user_id"][1]; + $total_hours += $hour; + + if (!isset($result[$user])) { + $result[$user] = []; + } + if (!isset($result[$user][$project])) { + $result[$user][$project] = $hour; + } else { + $result[$user][$project] += $hour; + } + } + return $result; + } + + function sas_one($date = "") + { + $sas_teams = [34, 36, 37, 38, 39, 40, 41, 42, 43, 44]; + if ($date == "") $date = date("Y-m-d"); + $startDate = "$date 00:00:00"; + $endDate = "$date 23:59:59"; + // Define domain for search + $domain = [ + "&", + ['project_id', '!=', false], + "&", + ['employee_id', 'in', $sas_teams], + "&", + ['date', '>=', $startDate], + ['date', '<=', $endDate] + ]; + $kwarg = array( + "limit" => 1000, + "offset" => 0, + "order" => "user_id", + 'fields' => array( + 'name', 'date', 'project_id', 'task_id', + 'unit_amount', 'user_id' + ) + ); + // Search for timesheet entries + $timesheets = $this->model->execute_kw( + $this->db_odoo, + $this->uid, + $this->password, + 'account.analytic.line', + 'web_search_read', + array($domain), + $kwarg + ); + $total_hours = 0; + $result = []; + foreach ($timesheets["records"] as $r) { + $name = $r["name"]; + $date = $r["date"]; + $project = $r["project_id"][1]; + $task = $r["task_id"][1]; + $hour = round($r["unit_amount"], 1); + $date = $r["date"]; + $user = $r["user_id"][1]; + $total_hours += $hour; + $total_hours += $hour; + $result[$user][] = [ + "project" => $project, + "task" => $task, + "date" => $date, + "desc" => $name, + "hour" => $hour + ]; + } + $table = "@startuml\n "; + $total_staff = 0; + $prev_user = ""; + $table .= "object Timesheet { \n"; + $table .= "\n"; + foreach ($result as $user => $data) { + if ($prev_user != $user) { + $table .= "$user\n"; + $table .= "<#lightblue,#black>|= Project |= Task |= Desc |= Hour |\n"; + $total_staff++; + $prev_user = $user; + } + foreach ($data as $d) { + $xdesc = $d["desc"]; + if (strlen($xdesc) > 30) { + $xdesc = substr($xdesc, 0, 26) . "..."; + } + $table .= "<#white>| {$d["project"]}| {$d["task"]}| {$xdesc}| {$d["hour"]}|\n"; + } + } + $msg = "Collection Date : " . date("Y-m-d H:i:s") . "\n"; + $msg .= "Total Hour : " . $total_hours . "\n"; + $msg .= "Total Staff: " . $total_staff . "\n"; + $msg .= "---\n"; + $table = str_replace("", $msg, $table); + if ($prev_user != "") { + $table .= "}\n\n"; + } + $table .= "@enduml"; + $img = $this->puml_post($table); + $url = "https://puml.sismedika.online/png/$img"; + $this->wa_to_sasone($url); + } + + function by_project_date($project, $date = "") + { + if ($date == "") $date = date("Y-m-d"); + $startDate = "$date 00:00:00"; + $endDate = "$date 23:59:59"; + // Define domain for search + $domain = [ + "&", + ['project_id', '!=', false], + "&", + ['project_id', 'ilike', "$project"], + "&", + ['date', '>=', $startDate], + ['date', '<=', $endDate] + ]; + + $kwarg = array( + "limit" => 1000, + "offset" => 0, + "order" => "user_id", + 'fields' => array( + 'name', 'date', 'task_id', + 'unit_amount', 'user_id' + ) + ); + // Search for timesheet entries + $timesheets = $this->model->execute_kw( + $this->db_odoo, + $this->uid, + $this->password, + 'account.analytic.line', + 'web_search_read', + array($domain), + $kwarg + ); + $total_hours = 0; + $result = []; + foreach ($timesheets["records"] as $r) { + $name = $r["name"]; + $date = $r["date"]; + $task = $r["task_id"][1]; + $hour = round($r["unit_amount"], 1); + $date = $r["date"]; + $user = $r["user_id"][1]; + $total_hours += $hour; + $result[$user][] = [ + "task" => $task, + "date" => $date, + "desc" => $name, + "hour" => $hour + ]; + } + $table = "@startuml\n "; + $msg = "Collection Date : " . date("Y-m-d H:i:s") . "\n"; + $msg .= "Total Hour : " . $total_hours . "\n"; + $total_staff = 0; + $prev_user = ""; + $table .= "object Timesheet { \n"; + $table .= "\n"; + foreach ($result as $user => $data) { + if ($prev_user != $user) { + $table .= "$user\n"; + $table .= "<#lightblue,#black>|= Date |= Task |= Desc |= Hour |\n"; + $total_staff++; + $prev_user = $user; + } + foreach ($data as $d) { + $xdesc = $d["desc"]; + if (strlen($xdesc) > 50) { + $xdesc = substr($xdesc, 0, 46) . "..."; + } + $table .= "<#white>| {$d["date"]}| {$d["task"]}| {$xdesc}| {$d["hour"]}|\n"; + } + } + $msg .= "Total Staff: " . $total_staff . "\n"; + $msg .= "---\n"; + $table = str_replace("", $msg, $table); + $result = $this->external_by_date($date); + $have_ext = false; + if (count($result) > 0) { + $have_ext = true; + $table .= "\n\n\n"; + $table .= "Non HIS V3\n"; + $table .= "<#lightblue,#black>|= User|= Project|= Hour |\n"; + $total_hours = 0; + foreach ($result as $u => $r) { + foreach ($r as $prj => $hour) { + $table .= "<#white>| {$u}| {$prj}| {$hour}|\n"; + $total_hours += $hour; + } + } + echo "\n"; + $table .= "Total Hour: " . $total_hours . "\n"; + } + if ($prev_user != "" || $have_ext) { + $table .= "}\n\n"; + } + $table .= "@enduml"; + $img = $this->puml_post($table); + $url = "https://puml.sismedika.online/png/$img"; + //echo $url; + $this->wa_to_group($url); + } + function wa_to_sasone( + $url + ) { + $this->load->library("Wa_sas"); + $hp = "6282113702602-1584412485@g.us"; + $resp = $this->wa_sas->send_image( + $hp, + "Timesheet Summary", + $url, + "image/png", + "sasone-status", + "png", + true + ); + print_r($resp); + } + + function wa_to_group( + $url + ) { + $this->load->library("Wa_sas"); + //$hp = "6287823783747"; + //group set to true + $hp = "120363194169273747@g.us"; + //$resp = $this->wa_sas->send_message($hp, $msg,true); + // print_r($resp); + $resp = $this->wa_sas->send_image( + $hp, + "Timesheet Summary", + $url, + "image/png", + "hisv3-status", + "png", + true + ); + print_r($resp); + } + function wa_to_sasone_done( + $msg + ) { + $this->load->library("Wa_sas"); + $hp = "6287823783747"; + //$hp="6282113702602-1584412485@g.us"; + //bisone supporter + //$hp = "6281328282909-1583223560@g.us"; + $resp = $this->wa_sas->send_message($hp, $msg, true); + } + + function puml_post($data) + { + $url = "https://puml.sismedika.online/coder"; + $ch = curl_init($url); + $payload = $data; + curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/plain')); + # Return response instead of printing. + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + # Send request. + $result = curl_exec($ch); + curl_close($ch); + return $result; + } + function bool_day($inp_dow) + { + $dow = strtolower(date("D", strtotime("now"))); + if ($inp_dow == $dow) return true; + return false; + } +} diff --git a/application/controllers/Timesheet_v3.php b/application/controllers/Timesheet_v3.php new file mode 100644 index 00000000..5a27bc86 --- /dev/null +++ b/application/controllers/Timesheet_v3.php @@ -0,0 +1,189 @@ +url = "http://odoo.sismedika.com:8070"; + $this->db_odoo = "odoo16_sismedika"; + $this->username = "admin@sismedika.com"; + $this->password = "duD#Z36qH5ctmRRD"; + $this->common = ripcord::client("{$this->url}/xmlrpc/2/common"); + $this->uid = $this->common->authenticate($this->db_odoo, $this->username, $this->password, array()); + $this->model = ripcord::client("{$this->url}/xmlrpc/2/object"); + $this->db->query("use one_support"); + $this->teams = [3, 22, 18, 21, 24, 15, 49, 34]; + } + + + + // sismedika + // 1. Design: Inggrit, Ira, Nana, Zalfa + //2. HIS 2: Heri, Bagas,Febio, Domi, Morris, Putri + //3. App: Tb,Rajif, Pajri, Hanif, Adib + //4. Backoffice: Gifari, Ivan, Moko, Akbar, Stephen + //5. LIS: Fajri, Hanan, Fitri,Andi, Sindhu + //6. HIS 3: Suritno, Ramdhan, Fajar, Rubi + //7. Suppport : Yulius, Jafar, Ahmad fadil, Andreas, Ainun, Indra Waskito + //8. Document : Fardil, Ari Antoni, Heru + function ts_all($date = "") + { + $design_teams = [14, 36, 15, 16]; + $this->ts_team("Design Timesheet", $design_teams, $date); + $hisv2_teams = [17, 24, 26, 25, 23, 11]; + $this->ts_team("HISv2 Timesheet", $hisv2_teams, $date); + $app_teams = [30, 29, 32, 27, 43]; + $this->ts_team("App Timesheet", $app_teams, $date); + $backoffice_teams = [19, 28, 47, 31, 44]; + $this->ts_team("Backoffice Timesheet", $backoffice_teams, $date); + $lis_teams = [37, 39, 40, 41, 42]; + $this->ts_team("LIS Timesheet", $lis_teams, $date); + $hisv3_teams = [18, 21, 20, 22]; + $this->ts_team("HIS v3 Timesheet", $hisv3_teams, $date); + $support_teams = [5, 7, 45, 4, 9, 8, 10]; + $this->ts_team("Support Timesheet", $support_teams, $date); + $doc_teams = [13, 38, 12]; + $this->ts_team("Doc Timesheet", $doc_teams, $date); + } + function ts_team($title, $teams, $date = "") + { + if ($date == "") $date = date("Y-m-d"); + if ($date == "ytd") { + $date = date("Y-m-d", strtotime("now - 1 day")); + } + $startDate = "$date 00:00:00"; + $endDate = "$date 23:59:59"; + // Define domain for search + $domain = [ + "&", + ['project_id', '!=', false], + "&", + ['employee_id', 'in', $teams], + "&", + ['date', '>=', $startDate], + ['date', '<=', $endDate] + ]; + $kwarg = array( + "limit" => 1000, + "offset" => 0, + "order" => "user_id", + 'fields' => array( + 'name', 'date', 'project_id', 'task_id', + 'unit_amount', 'user_id' + ) + ); + // Search for timesheet entries + $timesheets = $this->model->execute_kw( + $this->db_odoo, + $this->uid, + $this->password, + 'account.analytic.line', + 'web_search_read', + array($domain), + $kwarg + ); + $total_hours = 0; + $result = []; + foreach ($timesheets["records"] as $r) { + $name = $r["name"]; + $date = $r["date"]; + $project = $r["project_id"][1]; + $task = $r["task_id"][1]; + $hour = round($r["unit_amount"], 1); + $date = $r["date"]; + $user = $r["user_id"][1]; + $total_hours += $hour; + $total_hours += $hour; + $result[$user][] = [ + "project" => $project, + "task" => $task, + "date" => $date, + "desc" => $name, + "hour" => $hour + ]; + } + $table = "@startuml\n "; + $total_staff = 0; + $prev_user = ""; + $table .= "object Timesheet { \n"; + $table .= "\n"; + foreach ($result as $user => $data) { + if ($prev_user != $user) { + $table .= "$user\n"; + $table .= "<#lightblue,#black>|= Project |= Task |= Desc |= Hour |\n"; + $total_staff++; + $prev_user = $user; + } + foreach ($data as $d) { + $xdesc = $d["desc"]; + if (strlen($xdesc) > 30) { + $xdesc = substr($xdesc, 0, 26) . "..."; + } + $table .= "<#white>| {$d["project"]}| {$d["task"]}| {$xdesc}| {$d["hour"]}|\n"; + } + } + $msg = "Collection Date : " . date("Y-m-d H:i:s") . "\n"; + $msg .= "Timesheet Date : " . $date . "\n"; + $msg .= "Total Hour : " . $total_hours . "\n"; + $msg .= "Total Staff: " . $total_staff . "\n"; + $msg .= "---\n"; + $table = str_replace("", $msg, $table); + if ($prev_user != "") { + $table .= "}\n\n"; + } + $table .= "@enduml"; + $img = $this->puml_post($table); + $url = "https://puml.sismedika.online/png/$img"; + $this->wa_to_me($url, $title); + } + // dev team wa group + // 120363267858371806 + function wa_to_me( + $url, + $title + ) { + $this->load->library("Wa_sas"); + $hp = "120363267858371806@g.us"; + $resp = $this->wa_sas->send_image( + $hp, + "$title", + $url, + "image/png", + "$title", + "png", + true + ); + print_r($resp); + } + + + + + + function puml_post($data) + { + $url = "https://puml.sismedika.online/coder"; + $ch = curl_init($url); + $payload = $data; + curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/plain')); + # Return response instead of printing. + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + # Send request. + $result = curl_exec($ch); + curl_close($ch); + return $result; + } + function bool_day($inp_dow) + { + $dow = strtolower(date("D", strtotime("now"))); + if ($inp_dow == $dow) return true; + return false; + } +} diff --git a/application/controllers/Ttv_dummy.php b/application/controllers/Ttv_dummy.php new file mode 100644 index 00000000..1cf07d48 --- /dev/null +++ b/application/controllers/Ttv_dummy.php @@ -0,0 +1,47 @@ +sys_input; + foreach ($a_data as $d) { + $d["obv_json"] = json_encode($d["obv"]); + unset($d["obv"]); + $qry = $this->db->insert("ttv_dummy.incoming", $d); + if (!$qry) { + echo json_encode([ + "status" => "ERR", + "message" => "Err incoming " . $this->db->error()["message"] + ]); + exit; + } + } + echo json_encode(["status" => "OK", "message" => ""]); + } + function qry() + { + $data = $this->sys_input; + $medrec = $data["medrec"]; + $sql = "select * from ttv_dummy.xorder where medrec = ?"; + $qry = $this->db->query($sql,[$medrec]); + if (!$qry) { + echo json_encode([ + "status" => "ERR", + "message" => "Err incoming " . $this->db->error()["message"] + ]); + } + $rows = $qry->result_array(); + if (count($rows) == 0) { + echo json_encode([ + "status" => "E01", + "message" => "Patient not found" + ]); + exit; + } + echo json_encode(["status"=>"OK", "data"=> $rows[0]]); + } +} diff --git a/application/controllers/Wa_webhook.php b/application/controllers/Wa_webhook.php new file mode 100644 index 00000000..d9b60e36 --- /dev/null +++ b/application/controllers/Wa_webhook.php @@ -0,0 +1,58 @@ +post($json); + } else { + file_put_contents("/xtmp/webhook-raw", "\nno tag : $message\n", FILE_APPEND); + } + } else { + file_put_contents("/xtmp/webhook-raw", "\ninvalid json\n", FILE_APPEND); + } + echo json_encode(["status" => "OK"]); + } + function post($json) + { + //$url = 'http://10.9.10.205:5678/webhook-test/aea7f5ff-f24d-4afe-a52e-8b12d328a3b5'; + $url = "http://10.9.10.205:5678/webhook/428e0945-f0fc-4dce-a043-2f789a0cafda"; + $jsonData = json_encode($json); + + // Initialize cURL + $ch = curl_init($url); + + // Set cURL options + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'Content-Length: ' . strlen($jsonData) + ]); + + // Execute request and capture response + $response = curl_exec($ch); + + // Check for errors + if (curl_errno($ch)) { + $c_msg = 'cURL error: ' . curl_error($ch); + } else { + $c_msg = 'Response: ' . $response; + } + file_put_contents("/xtmp/webhook-raw", "\n$c_msg\n", FILE_APPEND); + // Close cURL + curl_close($ch); + } +} diff --git a/application/controllers/Welcome.php b/application/controllers/Welcome.php new file mode 100755 index 00000000..51094edd --- /dev/null +++ b/application/controllers/Welcome.php @@ -0,0 +1,25 @@ + + * @see https://codeigniter.com/user_guide/general/urls.html + */ + public function index() + { + echo(".:: -- ::."); + } +} diff --git a/application/controllers/Xraw.php b/application/controllers/Xraw.php new file mode 100644 index 00000000..888098a0 --- /dev/null +++ b/application/controllers/Xraw.php @@ -0,0 +1,13 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/application/controllers/mockup/Subgroup.php b/application/controllers/mockup/Subgroup.php new file mode 100644 index 00000000..ae90e8bb --- /dev/null +++ b/application/controllers/mockup/Subgroup.php @@ -0,0 +1,1145 @@ +db_onedev = $this->load->database("onedev", true); + } + + + function lookupsubsubgroup(){ + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $prm = $this->sys_input; + $id = $prm['id']; + $sql = "select Nat_SubSubGroupID as id,Nat_SubGroupID,Nat_SubGroupName, + nat_subsubgroup.* + from nat_subsubgroup + JOIN nat_subgroup ON Nat_SubSubGroupSubGroupID = Nat_SubGroupID + WHERE + Nat_SubSubGroupSubGroupID = {$id} AND Nat_SubSubGroupIsActive = 'Y'"; + // echo $sql; + $query = $this->db_onedev->query($sql, $sql_param); + $rows = $query->result_array(); + if($rows){ + } + + $result = array ("total" => count($rows), "records" => $rows); + $this->sys_ok($result); + + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } + public function lookup() + { + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + + $prm = $this->sys_input; + $search = $prm['search']; + $all = $prm['all']; + $limit = ''; + if($all == 'N'){ + $limit = ' LIMIT 10'; + } + $sql = "select COUNT(*) as total + from nat_subgroup + where + Nat_SubGroupIsActive = 'Y'"; + $sql_param = array($search); + $total = $this->db_onedev->query($sql,$sql_param)->row()->total; + + + $sql = "select Nat_SubGroupID as id, + Nat_SubGroupCode as code, + Nat_SubGroupName as name, + Nat_SubGroupNat_GroupID as groupid, + Nat_SubGroupLangName as namelang, + '' as T_TestIsNonLabName,Nat_GroupName ,Nat_GroupID, + nat_subgroup.* + from nat_subgroup + join nat_group on Nat_SubGroupNat_GroupID = Nat_GroupID + where + ( Nat_SubGroupName LIKE CONCAT('%','{$search}','%') OR + Nat_SubGroupCode LIKE CONCAT('%','{$search}','%') + )AND + Nat_SubGroupIsActive = 'Y' + GROUP BY Nat_SubGroupID + ORDER BY Nat_SubGroupID ASC $limit"; + $sql_param = array($search); + $query = $this->db_onedev->query($sql); + //echo $this->db_onedev->last_query(); + if ($query) { + $rows = $query->result_array(); + + + } else { + $this->sys_error_db("nat_subgroup select"); + exit; + } + + $result = array ("total" => $total, "total_filter"=>count($rows),"records" => $rows); + $this->sys_ok($result); + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } + + + public function addnewsubgroup() + { + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + + //# ambil parameter input + $prm = $this->sys_input; + $name = $prm['name']; + $namelang = $prm['namelang']; + $code = $prm['code']; + $group = $prm['group']; + $query = "SELECT COUNT(*) as exist FROM nat_subgroup WHERE Nat_SubGroupIsActive = 'Y' AND Nat_SubGroupCode = '{$code}'"; + $exist_code = $this->db_onedev->query($query)->row()->exist; + if($exist_code == 0){ + $sql = "insert into nat_subgroup( + Nat_SubGroupCode, + Nat_SubGroupName, + Nat_SubGroupLangName, + Nat_SubGroupNat_GroupID, + Nat_SubGroupCreated, + Nat_SubGroupLastUpdated + ) + values( ?, ?, ?,?, now(), now())"; + $query = $this->db_onedev->query($sql, + array( + $code, + $name, + $namelang, + $group + ) + ); + //echo $query; + if (!$query) { + $this->sys_error_db("nat_subgroup insert"); + exit; + } + + $result = array ("total" => 1, "records" => array("xid" => 0)); + $this->sys_ok($result); + $last_id = $this->db_onedev->insert_id(); + }else{ + $errors = array(); + if($exist_code != 0){ + // array_push($errors,array('field'=>'code','msg'=>'Kode sudah ada yang pakai dong')); + + $sql = "insert into nat_subgroup( + Nat_SubGroupCode, + Nat_SubGroupName, + Nat_SubGroupLangName, + Nat_SubGroupNat_GroupID, + Nat_SubGroupCreated, + Nat_SubGroupLastUpdated + ) + values( ?, ?, ?,?, now(), now())"; + $query = $this->db_onedev->query($sql, + array( + $code, + $name, + $namelang, + $group + ) + ); + //echo $query; + if (!$query) { + $this->sys_error_db("nat_subgroup insert"); + exit; + } + + $result = array ("total" => 1, "records" => array("xid" => 0)); + $this->sys_ok($result); + $last_id = $this->db_onedev->insert_id(); + } + //$result = array ("total" => -1,"errors" => $errors, "records" => 0); + // $this->sys_ok($result); + } + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } + + public function editsubgroup() + { + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + + //# ambil parameter input + $prm = $this->sys_input; + $id = $prm['id']; + $name = $prm['name']; + $namelang = $prm['namelang']; + $code = $prm['code']; + $group = $prm['group']; + $userid = $this->sys_user["M_UserID"]; + $query = "SELECT COUNT(*) as exist FROM nat_subgroup WHERE Nat_SubGroupIsActive = 'Y' AND Nat_SubGroupCode = '{$code}' AND Nat_SubGroupID <> {$prm['id']}"; + $exist_code = $this->db_onedev->query($query)->row()->exist; + if($exist_code == 0){ + $sqlcompany = "update nat_subgroup SET + Nat_SubGroupCode = ?, + Nat_SubGroupName = ?, + Nat_SubGroupLangName = ?, + Nat_SubGroupNat_GroupID = ?, + Nat_SubGroupLastUpdated = now() + where + Nat_SubGroupID = ? + "; + $querycompany = $this->db_onedev->query($sqlcompany, + array( + $code, + $name, + $namelang, + $group, + $id + ) + ); + // echo $query; + if (!$querycompany) { + $this->sys_error_db("nat_subgroup update"); + exit; + } + $result = array ("total" => 1, "records" => array("xid" => $id)); + $this->sys_ok($result); + }else{ + $errors = array(); + if($exist_code != 0){ + + $sqlcompany = "update nat_subgroup SET + Nat_SubGroupCode = ?, + Nat_SubGroupName = ?, + Nat_SubGroupLangName = ?, + Nat_SubGroupNat_GroupID = ?, + Nat_SubGroupLastUpdated = now() + where + Nat_SubGroupID = ? + "; + $querycompany = $this->db_onedev->query($sqlcompany, + array( + $code, + $name, + $namelang, + $group, + $id + ) + ); + // echo $query; + if (!$querycompany) { + $this->sys_error_db("nat_subgroup update"); + exit; + } + $result = array ("total" => 1, "records" => array("xid" => $id)); + $this->sys_ok($result); + } + // $result = array ("total" => -1,"errors" => $errors, "records" => 0); + // $this->sys_ok($result); + } + + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } + public function addnewsubsubgroup() + { + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + + //# ambil parameter input + $prm = $this->sys_input; + $subgroupid = $prm['subgroupid']; + $subsubgroupcode = $prm['subsubgroupcode']; + $subsubgroupname = $prm['subsubgroupname']; + $subsubgroupnamelang = $prm['subsubgroupnamelang']; + + if($prm['xid'] == 0){ + $query = "SELECT COUNT(*) as exist FROM nat_subsubgroup WHERE Nat_SubsubgroupIsActive = 'Y' AND Nat_SubsubgroupName = '{$name}'"; + $exist_name = $this->db_onedev->query($query)->row()->exist; + + if($exist_name == 0){ + $sql = "insert into nat_subsubgroup( + Nat_SubSubGroupSubGroupID, + Nat_SubSubGroupCode, + Nat_SubSubGroupName, + Nat_SubSubGroupLangName, + Nat_SubSubGroupLasUpdated + ) + values( ?,?,?,? ,now())"; +$query = $this->db_onedev->query($sql, + array( + $subgroupid, + $subsubgroupcode , + $subsubgroupname , + $subsubgroupnamelang + ) +); +if (!$query) { + $this->sys_error_db("nat_subsubgroup insert",$this->db_onedev); + exit; +} +$result = array ("total" => 1, "records" => array("xid" => 0)); +$this->sys_ok($result); + }else{ + $errors = array(); + if($exist_name != 0){ + array_push($errors,array('field'=>'name','msg'=>'Nama sudah ada yang pakai dong')); + } + + + $result = array ("total" => -1,"errors" => $errors, "records" => 0); + $this->sys_ok($result); + } + }else{ + $query = "SELECT COUNT(*) as exist FROM nat_subsubgroup WHERE Nat_SubSubGroupIsActive = 'Y' AND Nat_SubSubGroupName = '{$subsubgroupname}' AND Nat_SubSubGroupID <> {$prm['xid']}"; + $exist_name = $this->db_onedev->query($query)->row()->exist; + //echo $query; + + //echo $query; + if($exist_name == 0 ){ + $sql = "UPDATE nat_subsubgroup SET Nat_SubSubGroupName = '{$subsubgroupname}', Nat_SubSubGroupCode = '{$subsubgroupcode}' ,Nat_SubSubGroupLangName = '{$subsubgroupnamelang}' WHERE Nat_SubSubGroupID = '{$prm['xid']}'"; + //echo $sql; + $query = $this->db_onedev->query($sql); + $result = array ("total" => 1, "records" => array("xid" => 0)); + $this->sys_ok($result); + }else{ + $errors = array(); + if($exist_name != 0){ + array_push($errors,array('field'=>'name','msg'=>'name sudah ada yang pakai dong')); + } + + $result = array ("total" => -1,"errors" => $errors, "records" => 0); + $this->sys_ok($result); + } + } + + + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } + + + + public function deletesubgroup() + { + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + + //# ambil parameter input + $prm = $this->sys_input; + $userid = $this->sys_user["M_UserID"]; + $sql = "update nat_subgroup SET + Nat_SubGroupIsActive = 'N', + Nat_SubGroupLastUpdated = now() + WHERE + Nat_SubGroupID = ? + + "; + + $query = $this->db_onedev->query($sql, + array( + $prm['id'] + ) + ); + // echo $query; + if (!$query) { + $this->sys_error_db("nat_subgroup delete"); + exit; + } + $sql = "update nat_subsubgroup SET + Nat_SubSubGroupIsActive = 'N', + Nat_SubSubGroupLastUpdated = now() + WHERE + Nat_SubSubGroupNat_SubGroupID = ? + + "; + + $query = $this->db_onedev->query($sql, + array( + $prm['id'] + ) + ); + // echo $query; + if (!$query) { + $this->sys_error_db("nat_subsubgroup delete"); + exit; + } + $result = array ("total" => 1, "records" => array("xid" => 0)); + $this->sys_ok($result); + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } + public function deletesubsubgroup() + { + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + + //# ambil parameter input + $prm = $this->sys_input; + $userid = $this->sys_user["M_UserID"]; + $sql = "update nat_subsubgroup SET + Nat_SubSubGroupNat_SubGroupID = 0, + Nat_SubSubGroupLastUpdated = now() + WHERE + Nat_SubSubGroupID = ? + + "; + + $query = $this->db_onedev->query($sql, + array( + $prm['id'] + ) + ); + // echo $query; + if (!$query) { + $this->sys_error_db("nat_subsubgroup delete"); + exit; + } + $result = array ("total" => 1, "records" => array("xid" => 0)); + $this->sys_ok($result); + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + } + function selectnonlab(){ + + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $rows = []; + $rows['nonlabs'] = array(array("T_TestIsNonLabID"=>"","T_TestIsNonLabName"=>"LAB"),array("T_TestIsNonLabID"=>"RADIODIAGNOSTIC","T_TestIsNonLabName"=>"RADIODIAGNOSTIC"), array("T_TestIsNonLabID"=>"ELEKTROMEDIS","T_TestIsNonLabName"=>"ELEKTROMEDIS"),array("T_TestIsNonLabID"=>"OTHERS","T_TestIsNonLabName"=>"OTHERS")); + + $result = array( + "total" => count($rows) , + "records" => $rows, + ); + $this->sys_ok($result); + + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + +} + +function selectgroup(){ + + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $rows = []; + $query =" SELECT * + FROM nat_group + WHERE + Nat_GroupIsActive = 'Y' + "; + //echo $query; + $rows['groups'] = $this->db_onedev->query($query)->result_array(); + + + $result = array( + "total" => count($rows) , + "records" => $rows, + ); + $this->sys_ok($result); + + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + +} +function selectcompanybusiness(){ + + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $rows = []; + $query =" SELECT *, COUNT(M_CompanyID) as used + FROM (SELECT m_companybusiness.*,M_CompanyID + FROM + m_companybusiness + LEFT JOIN m_company ON M_CompanyBusinessID = M_CompanyM_CompanyBusinessID AND M_CompanyIsActive = 'Y' + WHERE M_CompanyBusinessIsActive = 'Y') a + GROUP BY M_CompanyBusinessID + "; + //echo $query; + $rows['companybusinesss'] = $this->db_onedev->query($query)->result_array(); + + + $result = array( + "total" => count($rows) , + "records" => $rows, + ); + $this->sys_ok($result); + + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + + } + function selectcompanylevel(){ + + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $prm = $this->sys_input; + $id = $prm['id']; + $rows = []; + $query =" SELECT *,CONCAT(Nat_CompanyLevelName,' [',M_CompanyName,']') as Nat_CompanyLevelName, COUNT(M_CompanyID) as used + FROM (SELECT nat_companylevel.*,M_CompanyID,M_CompanyName + FROM + nat_companylevel + LEFT JOIN m_company ON Nat_CompanyLevelNat_CompanyID = M_CompanyID AND M_CompanyIsActive = 'Y' + WHERE Nat_CompanyLevelIsActive = 'Y') a + GROUP BY Nat_CompanyLevelID + "; + //echo $query; + $rows['companylevels'] = $this->db_onedev->query($query)->result_array(); + + + $result = array( + "total" => count($rows) , + "records" => $rows, + ); + $this->sys_ok($result); + + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + + } + function selecthierarchy(){ + + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $rows = []; + $query =" SELECT *, COUNT(M_CompanyID) as used + FROM (SELECT nat_hierarchy.*,M_CompanyID + FROM + nat_hierarchy + LEFT JOIN m_company ON Nat_HierarchyID = M_CompanyNat_HierarchyID AND M_CompanyIsActive = 'Y' + WHERE Nat_HierarchyIsActive = 'Y') a + GROUP BY Nat_HierarchyID + "; + //echo $query; + $rows['hierarchys'] = $this->db_onedev->query($query)->result_array(); + + + $result = array( + "total" => count($rows) , + "records" => $rows, + ); + $this->sys_ok($result); + + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + + } +function selectdoctor(){ + + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $rows = []; + $query =" SELECT * + FROM m_doctor + WHERE + M_DoctorIsActive = 'Y' + "; + //echo $query; + $rows['doctors'] = $this->db_onedev->query($query)->result_array(); + + + $result = array( + "total" => count($rows) , + "records" => $rows, + ); + $this->sys_ok($result); + + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + + } + function searchdoctor(){ + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $prm = $this->sys_input; + + $max_rst = 12; + $tot_count =0; + + $q = [ + 'search' => '%' + ]; + + if ($prm['search'] != '') + { + $q['search'] = "%{$prm['search']}%"; + } + + // QUERY TOTAL + $sql = "SELECT count(*) as total + FROM + m_doctor + WHERE + M_DoctorName like ? + AND M_DoctorIsActive = 'Y'"; + $query = $this->db_onedev->query($sql,$q['search']); + //echo $query; + if ($query) { + $tot_count = $query->result_array()[0]["total"]; + } + else { + $this->sys_error_db("m_doctor count",$this->db_onedev); + exit; + } + + $sql = " + SELECT * FROM( + SELECT 0 as M_DoctorID, 'Semua Dokter' as M_DoctorName, 'Semua Dokter' as M_DoctorNames + UNION + SELECT M_DoctorID, M_DoctorName, CONCAT(IFNULL(M_DoctorPrefix,''),IFNULL(M_DoctorPrefix2,''),' ',M_DoctorName,' ',IFNULL(M_DoctorSufix,''),IFNULL(M_DoctorSufix2,''),IFNULL(M_DoctorSufix3,'')) as M_DoctorNames + FROM m_doctor + WHERE M_DoctorIsActive = 'Y') a + WHERE + M_DoctorNames like ? + ORDER BY M_DoctorName DESC + "; + $query = $this->db_onedev->query($sql, array($q['search'])); + + if ($query) { + $rows = $query->result_array(); + //echo $this->db_onedev->last_query(); + $result = array("total" => $tot_count, "records" => $rows, "total_display" => sizeof($rows)); + $this->sys_ok($result); + } + else { + $this->sys_error_db("m_doctor rows",$this->db_onedev); + exit; + } + } + function searchsubsubgroup(){ + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $prm = $this->sys_input; + + $max_rst = 12; + $tot_count =0; + + $q = [ + 'search' => '%' + ]; + + if ($prm['search'] != '') + { + $q['search'] = "%{$prm['search']}%"; + } + + // QUERY TOTAL + $sql = "SELECT count(*) as total + FROM nat_subsubgroup + WHERE + Nat_SubSubGroupName like ? + AND Nat_SubSubGroupIsActive = 'Y'"; + $query = $this->db_onedev->query($sql,$q['search']); + //echo $query; + if ($query) { + $tot_count = $query->result_array()[0]["total"]; + } + else { + $this->sys_error_db("nat_subsubgroup count",$this->db_onedev); + exit; + } + + $sql = " + SELECT Nat_SubSubGroupID, Nat_SubSubGroupName + FROM nat_subsubgroup + WHERE + Nat_SubSubGroupName like ? + AND Nat_SubSubGroupIsActive = 'Y' + GROUP BY Nat_SubSubGroupID + ORDER BY Nat_SubSubGroupName ASC + "; + $query = $this->db_onedev->query($sql, array($q['search'])); + + if ($query) { + $rows = $query->result_array(); + //echo $this->db_onedev->last_query(); + $result = array("total" => $tot_count, "records" => $rows, "total_display" => sizeof($rows)); + $this->sys_ok($result); + } + else { + $this->sys_error_db("nat_subsubgroup rows",$this->db_onedev); + exit; + } + } + function searchtemplate(){ + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $prm = $this->sys_input; + + $max_rst = 12; + $tot_count =0; + + $q = [ + 'search' => '%' + ]; + + if ($prm['search'] != '') + { + $q['search'] = "%{$prm['search']}%"; + } + + // QUERY TOTAL + $sql = "SELECT count(*) as total + FROM so_template + WHERE + So_TemplateName like ? + AND So_TemplateIsActive = 'Y'"; + $query = $this->db_onedev->query($sql,$q['search']); + //echo $query; + if ($query) { + $tot_count = $query->result_array()[0]["total"]; + } + else { + $this->sys_error_db("so_template count",$this->db_onedev); + exit; + } + + $sql = " + SELECT So_TemplateID, So_TemplateName + FROM so_template + WHERE + So_TemplateName like ? + AND So_TemplateIsActive = 'Y' + GROUP BY So_TemplateID + ORDER BY So_TemplateName ASC + "; + $query = $this->db_onedev->query($sql, array($q['search'])); + + if ($query) { + $rows = $query->result_array(); + //echo $this->db_onedev->last_query(); + $result = array("total" => $tot_count, "records" => $rows, "total_display" => sizeof($rows)); + $this->sys_ok($result); + } + else { + $this->sys_error_db("so_template rows",$this->db_onedev); + exit; + } + } + function searchcompanylevel(){ + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $prm = $this->sys_input; + + $max_rst = 12; + $tot_count =0; + + + $name = $prm['name']; + $hirarkiid = intval($prm['id']) - 1; + + // QUERY TOTAL + $sql = "SELECT count(*) as total + FROM nat_companylevel + WHERE + Nat_CompanyLevelName like '%{$name}%' + AND + Nat_CompanyLevelNat_HierarchyID = '{$hirarkiid}' + AND Nat_CompanyLevelIsActive = 'Y'"; + $query = $this->db_onedev->query($sql); + //echo $query; + if ($query) { + $tot_count = $query->result_array()[0]["total"]; + } + else { + $this->sys_error_db("nat_companylevel count",$this->db_onedev); + exit; + } + + $sql = " + SELECT * FROM(SELECT *, CONCAT(Nat_CompanyLevelName, ' [',M_CompanyName,']') as Nat_CompanyLevelNames + FROM nat_companylevel + LEFT JOIN m_company ON Nat_CompanyLevelNat_CompanyID = M_CompanyID + WHERE Nat_CompanyLevelIsActive = 'Y') a + WHERE + Nat_CompanyLevelName like '%{$name}%' + AND + Nat_CompanyLevelNat_HierarchyID = '{$hirarkiid}' + AND Nat_CompanyLevelIsActive = 'Y' + ORDER BY Nat_CompanyLevelName DESC + "; + $query = $this->db_onedev->query($sql); + + if ($query) { + $rows = $query->result_array(); + //echo $this->db_onedev->last_query(); + $result = array("total" => $tot_count, "records" => $rows, "total_display" => sizeof($rows)); + $this->sys_ok($result); + } + else { + $this->sys_error_db("nat_companylevel rows",$this->db_onedev); + exit; + } + } +function searchcity(){ + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $prm = $this->sys_input; + + $max_rst = 12; + $tot_count =0; + + $q = [ + 'search' => '%' + ]; + + if ($prm['search'] != '') + { + $q['search'] = "%{$prm['search']}%"; + } + + // QUERY TOTAL + $sql = "SELECT count(*) as total + FROM m_city + WHERE + M_CityName like ? + AND M_CityIsActive = 'Y'"; + $query = $this->db_onedev->query($sql,$q['search']); + //echo $query; + if ($query) { + $tot_count = $query->result_array()[0]["total"]; + } + else { + $this->sys_error_db("m_city count",$this->db_onedev); + exit; + } + + $sql = " + SELECT * + FROM m_city + WHERE + M_CityName like ? + AND M_CityIsActive = 'Y' + ORDER BY M_CityName DESC + "; + $query = $this->db_onedev->query($sql, array($q['search'])); + + if ($query) { + $rows = $query->result_array(); + //echo $this->db_onedev->last_query(); + $result = array("total" => $tot_count, "records" => $rows, "total_display" => sizeof($rows)); + $this->sys_ok($result); + } + else { + $this->sys_error_db("m_city rows",$this->db_onedev); + exit; + } +} +function getstaff(){ + $prm = $this->sys_input; + $query =" SELECT * + FROM m_staff + WHERE + M_StaffIsActive = 'Y' AND M_StaffM_PositionID = 2"; + //echo $query; + $rows = $this->db_onedev->query($query,array($prm['id']))->result_array(); + + $result = array( + "total" => count($rows) , + "records" => $rows, + ); + $this->sys_ok($result); + exit; +} +function getprovince(){ + $prm = $this->sys_input; + $query =" SELECT * + FROM m_province + WHERE + M_ProvinceIsActive = 'Y'"; + //echo $query; + $rows = $this->db_onedev->query($query,array($prm['id']))->result_array(); + + $result = array( + "total" => count($rows) , + "records" => $rows, + ); + $this->sys_ok($result); + exit; +} +function getcity(){ + $prm = $this->sys_input; + $query =" SELECT * + FROM m_city + WHERE + M_CityIsActive = 'Y' AND M_CityM_ProvinceID = ? + "; + //echo $query; + $rows = $this->db_onedev->query($query,array($prm['id']))->result_array(); + + $result = array( + "total" => count($rows) , + "records" => $rows, + ); + $this->sys_ok($result); + exit; +} +function getdistrict(){ + $prm = $this->sys_input; + $query =" SELECT * + FROM m_district + WHERE + M_DistrictIsActive = 'Y' AND M_DistrictM_CityID = ? + "; + //echo $query; + $rows = $this->db_onedev->query($query,array($prm['id']))->result_array(); + + $result = array( + "total" => count($rows) , + "records" => $rows, + ); + $this->sys_ok($result); + exit; +} + +function getkelurahan(){ + $prm = $this->sys_input; + $query =" SELECT * + FROM m_kelurahan + WHERE + M_KelurahanIsActive = 'Y' AND M_KelurahanM_DistrictID = ? + "; + //echo $query; + $rows = $this->db_onedev->query($query,array($prm['id']))->result_array(); + + $result = array( + "total" => count($rows) , + "records" => $rows, + ); + $this->sys_ok($result); + exit; +} +function selectbase(){ + + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $rows = []; + $query =" SELECT 'SPK' as baseid, 'SPK' as basename + UNION SELECT 'MOU' as baseid, 'MOU' as basename + "; + //echo $query; + $rows['bases'] = $this->db_onedev->query($query)->result_array(); + + + $result = array( + "total" => count($rows) , + "records" => $rows, + ); + $this->sys_ok($result); + + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + + } + function selectomzettype(){ + + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $rows = []; + $query =" SELECT * + FROM m_omzettype + WHERE + M_OmzetTypeIsActive = 'Y' + "; + //echo $query; + $rows['omzettypes'] = $this->db_onedev->query($query)->result_array(); + + + $result = array( + "total" => count($rows) , + "records" => $rows, + ); + $this->sys_ok($result); + + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + + } + function selectmoutype(){ + + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $rows = []; + $query =" SELECT * + FROM m_moutype + WHERE + M_MouTypeIsActive = 'Y' + "; + //echo $query; + $rows['moutypes'] = $this->db_onedev->query($query)->result_array(); + + + $result = array( + "total" => count($rows) , + "records" => $rows, + ); + $this->sys_ok($result); + + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + + } + function selectagingtype(){ + + try { + //# cek token valid + if (! $this->isLogin) { + $this->sys_error("Invalid Token"); + exit; + } + $rows = []; + $query =" SELECT * + FROM m_agingtype + WHERE + M_AgingIsActive = 'Y' + "; + //echo $query; + $rows['agingtypes'] = $this->db_onedev->query($query)->result_array(); + + + $result = array( + "total" => count($rows) , + "records" => $rows, + ); + $this->sys_ok($result); + + + } catch(Exception $exc) { + $message = $exc->getMessage(); + $this->sys_error($message); + } + + } + +}