From df46d82fee86fb7ac3f9a62387801b00f53815be Mon Sep 17 00:00:00 2001 From: Adrian Boma Date: Tue, 10 May 2016 22:00:36 -0400 Subject: [PATCH 1/6] Fix issue #380: cascading delete for patient records; delete related records first and then patient record --- app/mixins/.patient-invoices.js.swp | Bin 0 -> 12288 bytes app/mixins/.patient-visits.js.swp | Bin 0 -> 12288 bytes app/mixins/patient-invoices.js | 14 +++++ app/models/.invoice.js.swp | Bin 0 -> 16384 bytes app/patients/delete/.controller.js.swp | Bin 0 -> 12288 bytes app/patients/delete/controller.js | 68 ++++++++++++++++++++++++- app/utils/.pouch-views.js.swp | Bin 0 -> 20480 bytes app/utils/pouch-views.js | 6 +++ 8 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 app/mixins/.patient-invoices.js.swp create mode 100644 app/mixins/.patient-visits.js.swp create mode 100644 app/mixins/patient-invoices.js create mode 100644 app/models/.invoice.js.swp create mode 100644 app/patients/delete/.controller.js.swp create mode 100644 app/utils/.pouch-views.js.swp diff --git a/app/mixins/.patient-invoices.js.swp b/app/mixins/.patient-invoices.js.swp new file mode 100644 index 0000000000000000000000000000000000000000..70046a6c72a20944e8fa97de423b9b7998a96b16 GIT binary patch literal 12288 zcmeI2&2AGh5XT*kl?oN`00tyBLCJ0#kU%M1%7>IgQ9+^{tNoY|m&9JY-YBaoAoUSA zg2aI%61)i#R~~>97kC548wZxEWphKIarBSv@r*tGI9O+zk23ko2G6}*o4aQ1c*Q#f!qu_H&)rz?#8-xy>#&cKX>*~T@1>>e*s zho}g36SaZ*x{7U`N;6Q;|R3BZ42Q2SVL%_xuf!Ucqb}tHU%ce iWk}V|v3`Ecy-G#>&mwvookZT|BCI^Y`GY+Tmwo{G_7lAT literal 0 HcmV?d00001 diff --git a/app/mixins/.patient-visits.js.swp b/app/mixins/.patient-visits.js.swp new file mode 100644 index 0000000000000000000000000000000000000000..fe1a487f45847fb6a0d4b1dfbc201e0c2cfc5d1a GIT binary patch literal 12288 zcmeI2&2AGh5XT*k73HIqIJ+RR8!6e84+)eC3Gs30p;8ne2%)O-W+%jD*IsOINCbsP z;1NKG11Da9D`#GSGbdhxS!c6ERHa-&W9h$k?7wGcez#R7-W+W2@N3akhT{xl>yI`b zu6@`+%qN?a@H8*~ntDiIx0U|&IhyW2F0z`la5CI}U1c(3; zAOim&0g*6vbCt1osPg~+#rOaB(~NyWy+qwdokRUN#n>0rd(<0LA9WJdKz+mepHUxC zA5dkyw8jPnB&KBHKwBy?kGn||AGHX}C% z6&kQQoj{8l*oUF3&pFRT-iM?ZLYD`=p?WW#?NuGtfe-BCwCW}2*pB@aW?lZcvTY|V z3^N^ww7@s~X|=l)#X4c!p*X5Y(-vQTR#^qRzf#b-lUms>e^JFNi;k?*2BK#Lm{~Z# z6trpw=XJ9D#$p{k0T%``32Gh_Vd?_V=i_?QqN<=dPs4yKjN%HO^SfCLChFfC^rD{8 znY0j&3N94ls3<;2h!RL%R8W%#HR6*`K4@O@;)-AWcF%OrX4fah z8u+-kyUsav>N}^Zx=#1t$l3l$^3m`k0ey48<<$_MKBJPf|Bo-`=dNfUYQ?yR<9*<`UAF}XbzTTQ| z@eFtduA6~EjJhAYGx+d_?mr@R-hXg|+;jKi*RAdaJp-Nr&wyvZGvFEU40r}S1D=8Z zeFj8&Ah?WS956$P%-@?<{@!e^H_TtQ(rzyOAJ2eiz%$?(@CQ`~h`)5e|49DK|DZ z^({h%M&y$`7okY-1qj(D%G1vc>10?;(0)eVZZAo4=|G3Hlt!!BTAJ}0wEJ;hWHcVK z8#27Ayrz#BOeQg%{AZoiwAb_!@q8#rzM&CVr8PFou-%Z=Qq9^e!yJy1>;zJx?XssD zGo49GdDPAEl{F)ffi4#fwl7$w=85`@>r^3E zCXBen-Kt?DYgUg&4ejQF;EOQkqG1$xq+9F3X*5-d5|5U~DqSl1XjER3Z=2O^%*{2|uoPT(x0(~pw#~j(-C6ngj#5G8mA%}_ zrCdE03%%8-{7vb6iifft^*Ci7#M&l1O-ze)@lB$qU( zpVoR6U#ul8sB$8j-Gt`zcnB$qr53l{va&^vKNgN@ev-ymZR7xv%3ayqmAfmZ=_QEw z4v8@%*x~q$NB9a@>Fe#6BqKcF$wsvm9O|v_)Q)JmPjlDxWTh~j>F`NqTQ3E&C(}sS z4BX~~3V{a{77>vU8e1R2>u}<9mW=oWF~sl(Y?8!#`I!Wd(iy%=?qZ{pjm9OnW+-8F znYCNmBb`S!D=N)0nRKIE9iIbTgiFp;RhGjAd#v-tW2RxE9nhnSB=vr}823Pwu%ckkIaocR_KVbW5k_i&A5iKTy>K^PY}(7ldIqDwWk9Z?u?t26A?fKUTfpg@?4%D~GqfOK7lK zhf8EN>FUqxso@ko%JcuNI8T2MkmvsmbH;oD=l#pT{lH=1PdMZM5%@arao{1~K0u!P zp9P)(c7fY~U*R181K?}Gmw{8jN#H@?0B{rVI{JGJcoldBcp3OH@Eq`cK>G7t!2di0 zo&nE*XTUSy8So5v20R1*cML4labA~9ZQ(S{Sk6>IN!GP+IwQm!{nWu8M|)e?Zjdx5 zo-JJjaIb{U%u}{AW)!c4YNw~r=r|c^zC1DE2&)SUVKT^BHeQn1MqBDDdv+&!c->HJ zbj_xuXo@nj1YW-K>cAsiR+f=5MQcQ2#*-q)nY3W!uzmG~8lpO->a(V;_2{y{eglJd zch;Ee9fco9aK@ry$jUb{OC5ErT$LiLx~6<2gKI>VN>r6XlC-9z)aie@_F1dR>1wk+ zkuQr@3wtKTngnVVSF3z7!>X^VI=aqW%|_*DhytLj(x0MJS;4VyM?;iSD_2Iy%z}RH zwM8{qTsZ{>E_~pU8N~6jn*|EdtM~iS;)08*n}9~Czx;~AShSv3oU%zFlfK^XN^I-H HNAd69W;&~Z literal 0 HcmV?d00001 diff --git a/app/patients/delete/.controller.js.swp b/app/patients/delete/.controller.js.swp new file mode 100644 index 0000000000000000000000000000000000000000..3ca78cd75c642e572ed4efb7826befc84b04a102 GIT binary patch literal 12288 zcmeI2zi%8x6vrn>5nz&l07Xy$6OhCkgop+yS3~b+86r0l%Ce)--74NiccaS!1~a0h$=Qm_qL;LisM`3j7|8aNKVe}Ir%;3Loj zH^5b}4K9Ng_ycpj18##`;9Kw|cptn8E`q1Q6X0>6wD}NR1J8g{z`vE4>l}=5?9oGFV1+$ws;a{o;Fne;HM1CeYI_Kea*Mm z*sO_ZTcO>mh-J!)Ni%(iCMgwxVL>r^S$`F)MAGj=mc1lf@VbH z+AO89KPvz9AbQi*!}(s+l}v2to26@d2YIb!I=feAGpTOG_AYS`b#z7VOMj9w^Vw(x zSd_e4gxT!W!OiZhi4u00g&pREv*ru5*RM@^!iqGSptLYs%uE=zG)(Dh#7C9ls19Nm z`;amrxKQ;e%P5cIN?>X*z*gN?!#WJv!px4xj;kfLHO}lDQ)pkl~1NJV=L4%Yf5eC-ZEi(11^+hH>xs8*E(1}6is8d-drkXd+O@3Z#x=6 zx6-||SgxJb^{#%)tGK_>vENXB)tO?8+T60|sK0AMM592J(YKlJ&18|cOueWa6)}yJ zkrhan6}4M1@sejOK*d)baT{8R=g}9eaOFC$3W={?{lc6`=8W4P5sD7ahOEwAEEdZL za%2Wyp#`tqP|0hBDNVc7KVwfLJ)p@2l}yubkx|WTb$!iP(UbiHLTc>vQDbsW9Rxak z)p)ZOYQXwDvT-Tv#!4BGG}r5`SAgP1c}_j1P7rUkZrYw&IBPL=3q8!$qL<-7StXsR zZf48OWWgcbjdfcsxH@(B`I*YFqrD7uVQhRX%Hjh&HQS~PQNnfdw~f~ArVXzD1|?Kq AO#lD@ literal 0 HcmV?d00001 diff --git a/app/patients/delete/controller.js b/app/patients/delete/controller.js index 1923a33ddd..e1db10c7c2 100644 --- a/app/patients/delete/controller.js +++ b/app/patients/delete/controller.js @@ -1,4 +1,68 @@ import AbstractDeleteController from 'hospitalrun/controllers/abstract-delete-controller'; -export default AbstractDeleteController.extend({ - title: 'Delete Patient' +import PatientVisitsMixin from 'hospitalrun/mixins/patient-visits'; +import PatientInvoicesMixin from 'hospitalrun/mixins/patient-invoices'; +import PouchDbMixin from 'hospitalrun/mixins/pouchdb'; +import Ember from 'ember'; + +function deleteMany(manyArray) { + if (manyArray.then) { + return manyArray.then(deleteMany); + } + var recordsCount = manyArray.get('length'); + if (!recordsCount) { + // empty array: no records to delete + return Ember.RSVP.resolve(); + } + console.log('deleting ' + recordsCount + ' records'); + return Ember.RSVP.all(manyArray.invoke('destroyRecord', 'async array deletion')); +} + +export default AbstractDeleteController.extend(PatientVisitsMixin, PatientInvoicesMixin, PouchDbMixin, { + title: 'Delete Patient', + + // Override delete action on controller; we must delete + // all related records before deleting patient record + // otherwise errors will occur + deletePatient: function() { + var patient = this.get('model'); + var promises = []; + promises.push(this.deleteVisits(patient)); + promises.push(this.deleteInvoices(patient)); + Ember.RSVP.all(promises) + .then(function() { + patient.destroyRecord(); + }); + this.send(this.get('afterDeleteAction'), patient); + }, + + deleteVisits: function(patient) { + return this.getPatientVisits(patient).then(function(visits) { + var promises = []; + visits.forEach(function(visit) { + promises.push(deleteMany(visit.get('labs'))); + promises.push(deleteMany(visit.get('patientNotes'))); + promises.push(deleteMany(visit.get('vitals'))); + promises.push(deleteMany(visit.get('procedures'))); + promises.push(deleteMany(visit.get('medication'))); + promises.push(deleteMany(visit.get('imaging'))); + }); + return Ember.RSVP.all(promises).then(function(){ + return deleteMany(visits); + }); + }); + }, + + deleteInvoices: function(patient) { + this.getPatientInvoices(patient).then(function(invoices){ + deleteMany(invoices); + }); + }, + + actions: { + // delete related records without modal dialogs + delete: function(patient) { + this.deletePatient(patient); + this.send('closeModal'); + } + } }); diff --git a/app/utils/.pouch-views.js.swp b/app/utils/.pouch-views.js.swp new file mode 100644 index 0000000000000000000000000000000000000000..863fa60473233a06246beb6ace0f2c1118c45696 GIT binary patch literal 20480 zcmeI3dyHIHdBATHLV`_7YG^B}mK<*(GaK*D+9oBz4@B0Ei^dH+h$D z@;tw`B3IY^quk`-Fp9f=W4d)>aPfCiaB5$x7ECR)I_)s_8&S78S&v%HIB3?U{C0b) z8;6a~RJ+x!E=(?k!E&ea8=b)oj_!;!Fw(&KG|-LflUHBjy>aJ`?NZ^F#GxM80l@Qr7yp0%Ri5`v_$+(|?uWbJHnSJD?1&gs;5P^F9D~!!jIz-Eb8=zuEKt7S6)w;8D02 z?u27-J-i;aze?t|Zg!*B!afGMcJ4`1$i--fTjU&1Lk3R5r!KMz}AGrR&W zhJU)y^PYfvp#?{v1Y6)a5;RZ2pTd*yX*dlta2fn337T)f$KX+T5IzXM5ATP&z=t=( zYvA9phqG`7?t|MwY~%p+`BVBYtgG_YCBM-P)E##y^JVYey{c3iS0_CwQtvjaaoB3A zT2S}9jd(Wp<8G&{i<&Z>Ruu12^FcF+{5Y89*8y9n>?)W22{mU*k5A}kOTl6omydK} zKZ^HLZ9?%viTP4%RV&BB+R^ddC0*3DEO!sIqQksoQZ6MG5p>(&VzyCR$cd9mYZ~J{ zmR8t|7lUS867ib;Vz5hSpS?#Cse3ikCsmm|V z3!t_#$75qj<53WIqoyj!&~jqXnM?{BLOE;mSV2QCLDlLrG7OKse zf=;aki{q!ZCwUQTx`jSvX<%GsbR4g=10`#FOeRuFV7@oYMJzNmg;G*f&pZpU(&^51 z;wWs+m$y%-Zdf~!voy-faupjZ%S~%CQc-L0rh0ko*x2~EdW+hg7+gt8I^);+F#=8) z`JFvFZHWA~uDg`joL<72;Y{eU$>>G<+W2g9&XLp(SpQ^9(&`XJb#NEux6j^mW5tX& ztgn<$jzz8I&Y0Sz>%mLr#SW~xKd!R^BYIGZ>ccru2gO$#;$9aFz=ly#%!1~?ayWMoPo;HbUla{Rf*LnHk`EJ?5`d+aA>+I^R>{J7`o+F3P=D4k@x#&@J$*&;Gle^&c1me-v5mYs52b23vkTW3$dI;oJhL6k8z zmi8?TZ0*xmTF;5pr=Go)$k^X%5=U5VEn=a88Cb`Sl>=8{sK$UYQ_NR8_T)ezJFKnN zb4an~Vdo^RoX!f@^uW_r{$FY|#CdSTe zyRpAabi(0<1L84ruA7qcQX-xdkXey_^}w8bLymQH=uKUr<{Pa!zadUDW2)+ksm#6n zTF&2Nj^%>H{|5=^PDxxx{C~;@cV8ive;OqIe-hpYZJ2=@;H|J5UI#xQp8sq32s{k; z!)cIse+DMue2{qm3_Jmk!)d6&n_x4XC8j?EPr&1FFVtZl{0uxt4FAXQ2;2cNwBQ<; zfb-#7#P5F(Ps1nS58!TSz#HHf;XL>-@%)4EJFoz^!L6_l-UK_~HSj#~{5RpN@E33f z9)=aT6>fpI!9FO#g&^_&x8WK1I{XRz9?ZcWxC*X-H^9q5@&FIOyWuXl1AZOe48H(B z2b2lyj+6g~v+f}?OX{4{)#IRDS#Q}7A+ zIGlz6CgB438|>n%@Dw})?6@PAP z8eE-dQQ{0)*3Rk3GM9^X4YT{7J+2f z8hskUa=n^M(yz49k&~95mz;yxS+t*|W7Z*Q<`>hgX+igy_e#G^r>mLMXSn%Wtu1rks*Jq%*b#=&f?Q6M~N1b?%cIxqcvSweWtyb%MHI1-$-V) zw9C^9QMPn&qHv`iM!Axm-CWgY`fOI~x?sg9z?|{zEy+D{I?iOj zDCb(#86DjRt(A0wUK&q*;4HrmtmBErs(Bn?pIpc+;xKYsu}fF!=L-n4BIxm#%L*(b?W?lvE!Qy8;uQ&$Q55h&ak=EBI}-&)m|DZ zZ_oKOF-Lo*9lrkz?{)C8c*v>AErS|cgCq$W0ZSq0V|4s4{~`E#VmXQb@3fKIbHw$} zz!yMr0H213Ac8~icDNFL7Jf)<|6TYn{4SK>V)zs>{ljn%R)l2YJr_Es*E?55NMv9xj6|a0xt5+jTj&l0~s0guBYAkX|`xBLTeuE3`X@WKOE1c*bkA<}xgxQ@ zwHM!v@wbKbM?^~iK+LY4@z9kxWJ$2fOhX5Wx--#4-=#8qTga`dmu^&&4(PMn^^S>r zLC8B28{5nBmDZN}P&Xpz?G&A%os71(PJW-4m0N*mF%EZ#386w$Wlt8-040y*?Xd{K(>qm*Q-nQ%EL|FlTulvo_-} zUMU>tCGsvF`z6FL6ibhmg&Sno-O;Xary8|7otdB>L^>;BB8&fX@j~G^o@PJNJj0+f zb}}CWtxhYtH{-VP6K1&R&y$4_@1H+s3|!9}I9z8MUu)$XF>>QImxk^eL&j^*Uww0` z>k1;+V9dK|R`dZ|<@%D8nRm&uW6WIEub2%#H1_c)HpyV0a$ zma@`zwkfe<{Z5j+@j!-;2h74${tLa2?rQLP<==&atyKfUM(iUsWWHIt7jijW` zWQjz%`Ag+tSo-^2(ad8Xt*Liw7tAd~mXyg7%~ibHTidGTqm;x;v_CtSa! zU^0DLpE5LT)!bwV`IkAP}x+TdiqZsAVRmS|%!Bs#%% zaTH;_?s9YJ*}k6Q>G9}))=URlM>0GW=nAD>iP Date: Wed, 11 May 2016 22:01:05 -0400 Subject: [PATCH 2/6] fix: remove swap files inadverdently checked in --- app/mixins/.patient-invoices.js.swp | Bin 12288 -> 0 bytes app/mixins/.patient-visits.js.swp | Bin 12288 -> 0 bytes app/models/.invoice.js.swp | Bin 16384 -> 0 bytes app/patients/delete/.controller.js.swp | Bin 12288 -> 0 bytes app/utils/.pouch-views.js.swp | Bin 20480 -> 0 bytes 5 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 app/mixins/.patient-invoices.js.swp delete mode 100644 app/mixins/.patient-visits.js.swp delete mode 100644 app/models/.invoice.js.swp delete mode 100644 app/patients/delete/.controller.js.swp delete mode 100644 app/utils/.pouch-views.js.swp diff --git a/app/mixins/.patient-invoices.js.swp b/app/mixins/.patient-invoices.js.swp deleted file mode 100644 index 70046a6c72a20944e8fa97de423b9b7998a96b16..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2&2AGh5XT*kl?oN`00tyBLCJ0#kU%M1%7>IgQ9+^{tNoY|m&9JY-YBaoAoUSA zg2aI%61)i#R~~>97kC548wZxEWphKIarBSv@r*tGI9O+zk23ko2G6}*o4aQ1c*Q#f!qu_H&)rz?#8-xy>#&cKX>*~T@1>>e*s zho}g36SaZ*x{7U`N;6Q;|R3BZ42Q2SVL%_xuf!Ucqb}tHU%ce iWk}V|v3`Ecy-G#>&mwvookZT|BCI^Y`GY+Tmwo{G_7lAT diff --git a/app/mixins/.patient-visits.js.swp b/app/mixins/.patient-visits.js.swp deleted file mode 100644 index fe1a487f45847fb6a0d4b1dfbc201e0c2cfc5d1a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2&2AGh5XT*k73HIqIJ+RR8!6e84+)eC3Gs30p;8ne2%)O-W+%jD*IsOINCbsP z;1NKG11Da9D`#GSGbdhxS!c6ERHa-&W9h$k?7wGcez#R7-W+W2@N3akhT{xl>yI`b zu6@`+%qN?a@H8*~ntDiIx0U|&IhyW2F0z`la5CI}U1c(3; zAOim&0g*6vbCt1osPg~+#rOaB(~NyWy+qwdokRUN#n>0rd(<0LA9WJdKz+mepHUxC zA5dkyw8jPnB&KBHKwBy?kGn||AGHX}C% z6&kQQoj{8l*oUF3&pFRT-iM?ZLYD`=p?WW#?NuGtfe-BCwCW}2*pB@aW?lZcvTY|V z3^N^ww7@s~X|=l)#X4c!p*X5Y(-vQTR#^qRzf#b-lUms>e^JFNi;k?*2BK#Lm{~Z# z6trpw=XJ9D#$p{k0T%``32Gh_Vd?_V=i_?QqN<=dPs4yKjN%HO^SfCLChFfC^rD{8 znY0j&3N94ls3<;2h!RL%R8W%#HR6*`K4@O@;)-AWcF%OrX4fah z8u+-kyUsav>N}^Zx=#1t$l3l$^3m`k0ey48<<$_MKBJPf|Bo-`=dNfUYQ?yR<9*<`UAF}XbzTTQ| z@eFtduA6~EjJhAYGx+d_?mr@R-hXg|+;jKi*RAdaJp-Nr&wyvZGvFEU40r}S1D=8Z zeFj8&Ah?WS956$P%-@?<{@!e^H_TtQ(rzyOAJ2eiz%$?(@CQ`~h`)5e|49DK|DZ z^({h%M&y$`7okY-1qj(D%G1vc>10?;(0)eVZZAo4=|G3Hlt!!BTAJ}0wEJ;hWHcVK z8#27Ayrz#BOeQg%{AZoiwAb_!@q8#rzM&CVr8PFou-%Z=Qq9^e!yJy1>;zJx?XssD zGo49GdDPAEl{F)ffi4#fwl7$w=85`@>r^3E zCXBen-Kt?DYgUg&4ejQF;EOQkqG1$xq+9F3X*5-d5|5U~DqSl1XjER3Z=2O^%*{2|uoPT(x0(~pw#~j(-C6ngj#5G8mA%}_ zrCdE03%%8-{7vb6iifft^*Ci7#M&l1O-ze)@lB$qU( zpVoR6U#ul8sB$8j-Gt`zcnB$qr53l{va&^vKNgN@ev-ymZR7xv%3ayqmAfmZ=_QEw z4v8@%*x~q$NB9a@>Fe#6BqKcF$wsvm9O|v_)Q)JmPjlDxWTh~j>F`NqTQ3E&C(}sS z4BX~~3V{a{77>vU8e1R2>u}<9mW=oWF~sl(Y?8!#`I!Wd(iy%=?qZ{pjm9OnW+-8F znYCNmBb`S!D=N)0nRKIE9iIbTgiFp;RhGjAd#v-tW2RxE9nhnSB=vr}823Pwu%ckkIaocR_KVbW5k_i&A5iKTy>K^PY}(7ldIqDwWk9Z?u?t26A?fKUTfpg@?4%D~GqfOK7lK zhf8EN>FUqxso@ko%JcuNI8T2MkmvsmbH;oD=l#pT{lH=1PdMZM5%@arao{1~K0u!P zp9P)(c7fY~U*R181K?}Gmw{8jN#H@?0B{rVI{JGJcoldBcp3OH@Eq`cK>G7t!2di0 zo&nE*XTUSy8So5v20R1*cML4labA~9ZQ(S{Sk6>IN!GP+IwQm!{nWu8M|)e?Zjdx5 zo-JJjaIb{U%u}{AW)!c4YNw~r=r|c^zC1DE2&)SUVKT^BHeQn1MqBDDdv+&!c->HJ zbj_xuXo@nj1YW-K>cAsiR+f=5MQcQ2#*-q)nY3W!uzmG~8lpO->a(V;_2{y{eglJd zch;Ee9fco9aK@ry$jUb{OC5ErT$LiLx~6<2gKI>VN>r6XlC-9z)aie@_F1dR>1wk+ zkuQr@3wtKTngnVVSF3z7!>X^VI=aqW%|_*DhytLj(x0MJS;4VyM?;iSD_2Iy%z}RH zwM8{qTsZ{>E_~pU8N~6jn*|EdtM~iS;)08*n}9~Czx;~AShSv3oU%zFlfK^XN^I-H HNAd69W;&~Z diff --git a/app/patients/delete/.controller.js.swp b/app/patients/delete/.controller.js.swp deleted file mode 100644 index 3ca78cd75c642e572ed4efb7826befc84b04a102..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2zi%8x6vrn>5nz&l07Xy$6OhCkgop+yS3~b+86r0l%Ce)--74NiccaS!1~a0h$=Qm_qL;LisM`3j7|8aNKVe}Ir%;3Loj zH^5b}4K9Ng_ycpj18##`;9Kw|cptn8E`q1Q6X0>6wD}NR1J8g{z`vE4>l}=5?9oGFV1+$ws;a{o;Fne;HM1CeYI_Kea*Mm z*sO_ZTcO>mh-J!)Ni%(iCMgwxVL>r^S$`F)MAGj=mc1lf@VbH z+AO89KPvz9AbQi*!}(s+l}v2to26@d2YIb!I=feAGpTOG_AYS`b#z7VOMj9w^Vw(x zSd_e4gxT!W!OiZhi4u00g&pREv*ru5*RM@^!iqGSptLYs%uE=zG)(Dh#7C9ls19Nm z`;amrxKQ;e%P5cIN?>X*z*gN?!#WJv!px4xj;kfLHO}lDQ)pkl~1NJV=L4%Yf5eC-ZEi(11^+hH>xs8*E(1}6is8d-drkXd+O@3Z#x=6 zx6-||SgxJb^{#%)tGK_>vENXB)tO?8+T60|sK0AMM592J(YKlJ&18|cOueWa6)}yJ zkrhan6}4M1@sejOK*d)baT{8R=g}9eaOFC$3W={?{lc6`=8W4P5sD7ahOEwAEEdZL za%2Wyp#`tqP|0hBDNVc7KVwfLJ)p@2l}yubkx|WTb$!iP(UbiHLTc>vQDbsW9Rxak z)p)ZOYQXwDvT-Tv#!4BGG}r5`SAgP1c}_j1P7rUkZrYw&IBPL=3q8!$qL<-7StXsR zZf48OWWgcbjdfcsxH@(B`I*YFqrD7uVQhRX%Hjh&HQS~PQNnfdw~f~ArVXzD1|?Kq AO#lD@ diff --git a/app/utils/.pouch-views.js.swp b/app/utils/.pouch-views.js.swp deleted file mode 100644 index 863fa60473233a06246beb6ace0f2c1118c45696..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20480 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 Date: Wed, 11 May 2016 23:19:31 -0400 Subject: [PATCH 3/6] fix: delete payments and line items when deleting invoices --- app/patients/delete/controller.js | 65 ++++++++++++++++++------------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/app/patients/delete/controller.js b/app/patients/delete/controller.js index e1db10c7c2..7514d76317 100644 --- a/app/patients/delete/controller.js +++ b/app/patients/delete/controller.js @@ -5,7 +5,11 @@ import PouchDbMixin from 'hospitalrun/mixins/pouchdb'; import Ember from 'ember'; function deleteMany(manyArray) { + if (!manyArray) { + return Ember.RSVP.resolve(); + } if (manyArray.then) { + // recursive call after resolving async model return manyArray.then(deleteMany); } var recordsCount = manyArray.get('length'); @@ -13,7 +17,6 @@ function deleteMany(manyArray) { // empty array: no records to delete return Ember.RSVP.resolve(); } - console.log('deleting ' + recordsCount + ' records'); return Ember.RSVP.all(manyArray.invoke('destroyRecord', 'async array deletion')); } @@ -24,44 +27,52 @@ export default AbstractDeleteController.extend(PatientVisitsMixin, PatientInvoic // all related records before deleting patient record // otherwise errors will occur deletePatient: function() { + var controller = this; var patient = this.get('model'); - var promises = []; - promises.push(this.deleteVisits(patient)); - promises.push(this.deleteInvoices(patient)); - Ember.RSVP.all(promises) - .then(function() { - patient.destroyRecord(); - }); - this.send(this.get('afterDeleteAction'), patient); + var visits = this.getPatientVisits(patient); + var invoices = this.getPatientInvoices(patient); + // resolve all async models first since they reference each other, then delete + return Ember.RSVP.all([visits, invoices]).then(function(records) { + var promises = []; + promises.push(controller.deleteVisits(records[0])); + promises.push(controller.deleteInvoices(records[1])); + return Ember.RSVP.all(promises) + .then(function() { + return patient.destroyRecord(); + }); + }); }, - deleteVisits: function(patient) { - return this.getPatientVisits(patient).then(function(visits) { - var promises = []; - visits.forEach(function(visit) { - promises.push(deleteMany(visit.get('labs'))); - promises.push(deleteMany(visit.get('patientNotes'))); - promises.push(deleteMany(visit.get('vitals'))); - promises.push(deleteMany(visit.get('procedures'))); - promises.push(deleteMany(visit.get('medication'))); - promises.push(deleteMany(visit.get('imaging'))); - }); - return Ember.RSVP.all(promises).then(function(){ - return deleteMany(visits); - }); + deleteVisits: function(visits) { + var promises = []; + visits.forEach(function(visit) { + promises.push(deleteMany(visit.get('labs'))); + promises.push(deleteMany(visit.get('patientNotes'))); + promises.push(deleteMany(visit.get('vitals'))); + promises.push(deleteMany(visit.get('procedures'))); + promises.push(deleteMany(visit.get('medication'))); + promises.push(deleteMany(visit.get('imaging'))); + }); + return Ember.RSVP.all(promises).then(function() { + return deleteMany(visits); }); }, - deleteInvoices: function(patient) { - this.getPatientInvoices(patient).then(function(invoices){ - deleteMany(invoices); + deleteInvoices: function(invoices) { + var lineItems = invoices.get('lineItems'); + var payments = invoices.get('payments'); + return Ember.RSVP.all([lineItems, payments]).then(function() { + return deleteMany(invoices); }); }, actions: { // delete related records without modal dialogs delete: function(patient) { - this.deletePatient(patient); + var controller = this; + this.deletePatient(patient).then(function() { + controller.send(controller.get('afterDeleteAction'), patient); + }); this.send('closeModal'); } } From 3e14b2b7e3f6521b487169d4c7df19fcb5c4d854 Mon Sep 17 00:00:00 2001 From: Adrian Boma Date: Sun, 22 May 2016 22:18:50 -0400 Subject: [PATCH 4/6] feature: add progress modal to patient delete process because it may take some time to delete all associated records --- app/patients/delete/controller.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/patients/delete/controller.js b/app/patients/delete/controller.js index 7514d76317..cfae08a1d5 100644 --- a/app/patients/delete/controller.js +++ b/app/patients/delete/controller.js @@ -2,6 +2,7 @@ import AbstractDeleteController from 'hospitalrun/controllers/abstract-delete-co import PatientVisitsMixin from 'hospitalrun/mixins/patient-visits'; import PatientInvoicesMixin from 'hospitalrun/mixins/patient-invoices'; import PouchDbMixin from 'hospitalrun/mixins/pouchdb'; +import ProgressDialog from 'hospitalrun/mixins/progress-dialog'; import Ember from 'ember'; function deleteMany(manyArray) { @@ -20,8 +21,10 @@ function deleteMany(manyArray) { return Ember.RSVP.all(manyArray.invoke('destroyRecord', 'async array deletion')); } -export default AbstractDeleteController.extend(PatientVisitsMixin, PatientInvoicesMixin, PouchDbMixin, { +export default AbstractDeleteController.extend(PatientVisitsMixin, PatientInvoicesMixin, PouchDbMixin, ProgressDialog, { title: 'Delete Patient', + progressTitle: 'Delete Patient Record', + progressMessage: 'Deleting patient and all associated records', // Override delete action on controller; we must delete // all related records before deleting patient record @@ -70,10 +73,12 @@ export default AbstractDeleteController.extend(PatientVisitsMixin, PatientInvoic // delete related records without modal dialogs delete: function(patient) { var controller = this; + this.send('closeModal'); + this.showProgressModal(); this.deletePatient(patient).then(function() { + controller.closeProgressModal(); controller.send(controller.get('afterDeleteAction'), patient); }); - this.send('closeModal'); } } }); From 5939a738f3fce786dca84e32246236c4681767f4 Mon Sep 17 00:00:00 2001 From: Adrian Boma Date: Sat, 11 Jun 2016 22:24:15 -0400 Subject: [PATCH 5/6] fix: when deleting patient records, also delete appointsments, payments, invoice line items and proc charges --- app/mixins/patient-appointments.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 app/mixins/patient-appointments.js diff --git a/app/mixins/patient-appointments.js b/app/mixins/patient-appointments.js new file mode 100644 index 0000000000..1c425ded03 --- /dev/null +++ b/app/mixins/patient-appointments.js @@ -0,0 +1,16 @@ +import Ember from 'ember'; +import PouchDbMixin from 'hospitalrun/mixins/pouchdb'; + +export default Ember.Mixin.create(PouchDbMixin, { + getPatientAppointments: function(patient) { + var patientId = patient.get('id'); + var maxValue = this.get('maxValue'); + return this.store.query('appointment', { + options: { + startkey: [patientId, null, null, 'appointment_'], + endkey: [patientId, maxValue, maxValue, maxValue] + }, + mapReduce: 'appointments_by_patient' + }) + } +}); From a00af29f9270a94a71cfc9dd0fc48ddba82071db Mon Sep 17 00:00:00 2001 From: Adrian Boma Date: Sun, 12 Jun 2016 21:52:40 -0400 Subject: [PATCH 6/6] fix last commit and failing tests / add changes to patient delete controller inadverdently not committed --- app/mixins/patient-appointments.js | 2 +- app/patients/delete/controller.js | 48 +++++++++++++++++++++++------- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/app/mixins/patient-appointments.js b/app/mixins/patient-appointments.js index 1c425ded03..c082b857a8 100644 --- a/app/mixins/patient-appointments.js +++ b/app/mixins/patient-appointments.js @@ -11,6 +11,6 @@ export default Ember.Mixin.create(PouchDbMixin, { endkey: [patientId, maxValue, maxValue, maxValue] }, mapReduce: 'appointments_by_patient' - }) + }); } }); diff --git a/app/patients/delete/controller.js b/app/patients/delete/controller.js index cfae08a1d5..778892b1b5 100644 --- a/app/patients/delete/controller.js +++ b/app/patients/delete/controller.js @@ -1,5 +1,6 @@ import AbstractDeleteController from 'hospitalrun/controllers/abstract-delete-controller'; import PatientVisitsMixin from 'hospitalrun/mixins/patient-visits'; +import PatientAppointmentsMixin from 'hospitalrun/mixins/patient-appointments'; import PatientInvoicesMixin from 'hospitalrun/mixins/patient-invoices'; import PouchDbMixin from 'hospitalrun/mixins/pouchdb'; import ProgressDialog from 'hospitalrun/mixins/progress-dialog'; @@ -21,7 +22,7 @@ function deleteMany(manyArray) { return Ember.RSVP.all(manyArray.invoke('destroyRecord', 'async array deletion')); } -export default AbstractDeleteController.extend(PatientVisitsMixin, PatientInvoicesMixin, PouchDbMixin, ProgressDialog, { +export default AbstractDeleteController.extend(PatientVisitsMixin, PatientInvoicesMixin, PouchDbMixin, ProgressDialog, PatientAppointmentsMixin, { title: 'Delete Patient', progressTitle: 'Delete Patient Record', progressMessage: 'Deleting patient and all associated records', @@ -34,11 +35,15 @@ export default AbstractDeleteController.extend(PatientVisitsMixin, PatientInvoic var patient = this.get('model'); var visits = this.getPatientVisits(patient); var invoices = this.getPatientInvoices(patient); + var appointments = this.getPatientAppointments(patient); + var payments = patient.get('payments'); // resolve all async models first since they reference each other, then delete - return Ember.RSVP.all([visits, invoices]).then(function(records) { + return Ember.RSVP.all([visits, invoices, appointments, payments]).then(function(records) { var promises = []; promises.push(controller.deleteVisits(records[0])); promises.push(controller.deleteInvoices(records[1])); + promises.push(deleteMany(records[2])); // appointments + promises.push(deleteMany(records[3])); // payments return Ember.RSVP.all(promises) .then(function() { return patient.destroyRecord(); @@ -49,23 +54,46 @@ export default AbstractDeleteController.extend(PatientVisitsMixin, PatientInvoic deleteVisits: function(visits) { var promises = []; visits.forEach(function(visit) { - promises.push(deleteMany(visit.get('labs'))); + var labs = visit.get('labs'); + var procedures = visit.get('procedures'); + var imaging = visit.get('imaging'); + var procCharges = procedures.then(function(p) { + return p.get('charges'); + }); + var labCharges = labs.then(function(l) { + return l.get('charges'); + }); + var imagingCharges = imaging.then(function(i) { + return i.get('charges'); + }); + var visitCharges = visit.get('charges'); + promises.push(deleteMany(labs)); + promises.push(deleteMany(labCharges)); promises.push(deleteMany(visit.get('patientNotes'))); promises.push(deleteMany(visit.get('vitals'))); - promises.push(deleteMany(visit.get('procedures'))); + promises.push(deleteMany(procedures)); + promises.push(deleteMany(procCharges)); promises.push(deleteMany(visit.get('medication'))); - promises.push(deleteMany(visit.get('imaging'))); + promises.push(deleteMany(imaging)); + promises.push(deleteMany(imagingCharges)); + promises.push(deleteMany(visitCharges)); }); return Ember.RSVP.all(promises).then(function() { return deleteMany(visits); }); }, - deleteInvoices: function(invoices) { - var lineItems = invoices.get('lineItems'); - var payments = invoices.get('payments'); - return Ember.RSVP.all([lineItems, payments]).then(function() { - return deleteMany(invoices); + deleteInvoices: function(patientInvoices) { + return Ember.RSVP.resolve(patientInvoices).then(function(invoices) { + var lineItems = invoices.map(function(i) { + return i.get('lineItems'); + }); + var lineItemDetails = lineItems.map(function(li) { + return li.get('details'); + }); + return Ember.RSVP.all([lineItems, lineItemDetails]).then(function() { + return Ember.RSVP.all([deleteMany(invoices), deleteMany(lineItems), deleteMany(lineItemDetails)]); + }); }); },