diff --git a/cmd/main-api/config.yml-example b/cmd/main-api/config.yml-example index 3423b5d1..f5f03f10 100644 --- a/cmd/main-api/config.yml-example +++ b/cmd/main-api/config.yml-example @@ -66,9 +66,11 @@ bpjsCfg: baseUrl: syncUrlCfg: - enable: false - host: - prefix: new-to-old + enable: false + targetHost: + prefix: new-to-old + source: old-app + secretKey: new-world-order!! docsCfg: path: ../../assets/docs/ \ No newline at end of file diff --git a/cmd/main-migration/migrations/20251205073858.sql b/cmd/main-migration/migrations/20251205073858.sql new file mode 100644 index 00000000..96f9200a --- /dev/null +++ b/cmd/main-migration/migrations/20251205073858.sql @@ -0,0 +1,23 @@ +-- Modify "Chemo" table +ALTER TABLE "public"."Chemo" ADD COLUMN "Doctor_Code" character varying(20) NULL, ADD COLUMN "NextChemoDate" timestamptz NULL, ADD CONSTRAINT "fk_Chemo_Doctor" FOREIGN KEY ("Doctor_Code") REFERENCES "public"."Doctor" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Rename a column from "Encounter_Id" to "Chemo_Id" +ALTER TABLE "public"."ChemoProtocol" RENAME COLUMN "Encounter_Id" TO "Chemo_Id"; +-- Modify "ChemoProtocol" table +ALTER TABLE "public"."ChemoProtocol" DROP CONSTRAINT "fk_ChemoProtocol_Encounter", ALTER COLUMN "DurationUnit_Code" TYPE text, ADD COLUMN "Interval" bigint NULL, ADD COLUMN "Cycle" bigint NULL, ADD COLUMN "Series" integer NULL, ADD COLUMN "Status_Code" text NULL, ADD CONSTRAINT "fk_ChemoProtocol_Chemo" FOREIGN KEY ("Chemo_Id") REFERENCES "public"."Chemo" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Create "ChemoPlan" table +CREATE TABLE "public"."ChemoPlan" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Parent_Id" bigint NULL, + "Protocol_Id" bigint NULL, + "SeriesNumber" integer NULL, + "CycleNumber" bigint NULL, + "PlanDate" timestamptz NULL, + "RealizationDate" timestamptz NULL, + "Notes" text NULL, + "Status" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_ChemoPlan_Protocol" FOREIGN KEY ("Protocol_Id") REFERENCES "public"."ChemoProtocol" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20251205211957.sql b/cmd/main-migration/migrations/20251205211957.sql new file mode 100644 index 00000000..99677edd --- /dev/null +++ b/cmd/main-migration/migrations/20251205211957.sql @@ -0,0 +1,2 @@ +-- Modify "ChemoPlan" table +ALTER TABLE "public"."ChemoPlan" DROP CONSTRAINT "fk_ChemoPlan_Protocol", ADD CONSTRAINT "fk_ChemoProtocol_ChemoPlans" FOREIGN KEY ("Protocol_Id") REFERENCES "public"."ChemoProtocol" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251205214433.sql b/cmd/main-migration/migrations/20251205214433.sql new file mode 100644 index 00000000..34343308 --- /dev/null +++ b/cmd/main-migration/migrations/20251205214433.sql @@ -0,0 +1,2 @@ +-- Modify "ChemoProtocol" table +ALTER TABLE "public"."ChemoProtocol" ADD COLUMN "Patient_Id" bigint NULL; diff --git a/cmd/main-migration/migrations/20251205221124.sql b/cmd/main-migration/migrations/20251205221124.sql new file mode 100644 index 00000000..3eab115a --- /dev/null +++ b/cmd/main-migration/migrations/20251205221124.sql @@ -0,0 +1,2 @@ +-- Modify "ChemoProtocol" table +ALTER TABLE "public"."ChemoProtocol" ADD COLUMN "VerifiedAt" timestamptz NULL, ADD COLUMN "VerifiedBy_User_Id" bigint NULL, ADD CONSTRAINT "fk_ChemoProtocol_VerifiedBy" FOREIGN KEY ("VerifiedBy_User_Id") REFERENCES "public"."User" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251209022744.sql b/cmd/main-migration/migrations/20251209022744.sql new file mode 100644 index 00000000..a8a18481 --- /dev/null +++ b/cmd/main-migration/migrations/20251209022744.sql @@ -0,0 +1,2 @@ +-- Modify "ChemoPlan" table +ALTER TABLE "public"."ChemoPlan" ADD COLUMN "Encounter_Id" bigint NULL, ADD CONSTRAINT "fk_ChemoPlan_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251209025908.sql b/cmd/main-migration/migrations/20251209025908.sql new file mode 100644 index 00000000..5a8522d7 --- /dev/null +++ b/cmd/main-migration/migrations/20251209025908.sql @@ -0,0 +1,2 @@ +-- Modify "Chemo" table +ALTER TABLE "public"."Chemo" ADD COLUMN "Class_Code" text NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 9a5298f1..ac03c936 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:iGd5sCHeyT0TBFNtV83Ge6PW5BjRp8rpw+tgFigOC4Q= +h1:SSn9Za93bvbyBNVuGwpy9R/E/+1hm802NevovuLsplc= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,76 +75,82 @@ h1:iGd5sCHeyT0TBFNtV83Ge6PW5BjRp8rpw+tgFigOC4Q= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -20251106050412.sql h1:MiEMJ1HCFYnalKuq3Z38xJeogfBAMqsTv2sG4EF8dDw= -20251106063418.sql h1:y3veDJPjKekOWLCZek/LgQwXPRhZtOppTfUXiqoL95s= -20251106071906.sql h1:/TUZA3XpMY23qEJXdkTwlzrNMvSSl6JJniPcgAttBaw= -20251106073157.sql h1:78txeibJ602DMD7huD618ZSMt6phSRzDNPTlo0PGyrc= -20251106074218.sql h1:8Xz7WywrtUnSxOHhlal53gG9rE7r86LFUt5zBFe/mIs= -20251106081846.sql h1:jp91Bf5bxGXMiUB1VIuN6y768vb2iWwow44WfCE5J5k= -20251106082844.sql h1:RHYzRO4G1fSWwf+xc/3QezZ/Iil67cZPIgNpNz3TNhQ= -20251106090021.sql h1:dFDk6mq+zjbYWmfWIrHf9DiKvvoXHjrr0++zssMTWP8= -20251106144745.sql h1:aHcr23iBFqCHer5D/SsPMXBCLjGqUYvWYfRU8jSJgIw= -20251107012049.sql h1:hu/7NHhnAkT4xK0RNtqmMDdH1Bo5EZbl7itDRjiCT+g= -20251107064812.sql h1:sfCXDQYnMf0ddrQ9oYljWJLLSt9NJjJV6o8VS3p7aZE= -20251107064937.sql h1:DlYGJ9LZFwZyR7jBP5zaGB128aIc4HAixBKPYCz9EkY= -20251107071420.sql h1:ynCdZAd2utLl+FhtWZwtahNXgIVOvuk3s/rOq7lfXA4= -20251107074318.sql h1:WE9cPhibWtZ0dbu1VEGirTeY6ijFYGMNhHdBtM32kOc= -20251107075050.sql h1:8tvneruqdynDOaJK1+0z4CH7YXZStZpGdqwIeOMLik4= -20251107080604.sql h1:8c4jd4Tql7tcdhbI9NS0tgvN+ADu9FnCf8wMUbmW7A0= -20251107081830.sql h1:SAAe3lmsm9vGXuSEsDdl7ad0EAxP5CMmFRDEgp9M7yY= -20251107091033.sql h1:JLdX/u7GUdBfjrPrMSNAqc8HtSoj0YA9iW9Vc6FJZdw= -20251107091209.sql h1:CzhYtwAwT+GHrbqcagnJE+v3mbl/rObf1IJaLCKlzrs= -20251107091541.sql h1:+3ZyWJTftDY2JeWThXuIxGWpUBnyMPyOyY4jBjdWYJI= -20251110012217.sql h1:f4Z8TuGc+XMSJ+Ekn4/PeHRE2FlHWkc5gKPJB0hAX7c= -20251110012306.sql h1:ENPyI6Kjdk6qKJQb0yJ6MCTDPAmO1WD/uhKuCSl+jYo= -20251110052049.sql h1:OrQ0acnyoQLKnTitZfnBcVr5jDslF59OFLaqT7SpdVs= -20251110062042.sql h1:9KwldQt0NpVPR86L0T4hlkfHAGau+7CiZYgu5rF+yhg= -20251110063202.sql h1:A117DuZmZ6U0jWHA3DISnr+yvBjKIr1ObrUr047YezQ= -20251110063633.sql h1:qTiC0F19JnhUIXF4LGJQ21jEV6kKGyhTr1x2kimFqPQ= -20251110085551.sql h1:HZcJM0RSC6HBaUSjKBE8MgDG8Vn9f3LmwA/OnT9Cp7I= -20251110091516.sql h1:W3AQhQLgirEWuCObbLl+Prdrbq6k6EEY1xcoWsmbog4= -20251110091948.sql h1:3tsITMrZr/T+L4wqUMz8sHS229jCJl4T0Nu3dMccxH8= -20251110092729.sql h1:uU+k88RH/e0Ns4/SmJl03RVYPscBAPuiLfxR6CJqaf0= -20251110093522.sql h1:O7upSj8VNjzvroL4IU59bfxKATOkAVGBArcUbVNq9aM= -20251110100258.sql h1://JSArUMNI3/gAtYDx2VN94C198SFW0ANjgs+p6eCRM= -20251110100545.sql h1:ENPOqeJYRpMI4e8VCKwaQgaql8se6pIidAhG2cjskBg= -20251110155448.sql h1:VW9KE0jxWy4flZ28sdXmhY6JWd6eKAX/cVL8KWRVii4= -20251111072601.sql h1:99WWzGjcDDFNC2cHRfPu4MBLWNrgPMY5HAYUbmIcVRA= -20251111073546.sql h1:iIGwFNfUgStdczw/PXTH3SD84xAyxrbZICofc3M8TMk= -20251111074148.sql h1:mzkezSKwCV2bTZ/0BHiTCX5qAy4uHpwar1xzwAH15Ko= -20251111074652.sql h1:lYh4/3BHV24pgPC0pP4RUKb+XtL/6AsZGPItRpnzBiQ= -20251111082257.sql h1:+cIZ1lf8HYGSL6t6U88plLKk8nOO1YVdV7h3YOM84ds= -20251111111017.sql h1:xzlhR2xLfOj4ddYlesS+bpEeDrxiAf5ILNOspsbZjBU= -20251113101344.sql h1:vSzThY3p6XYTj0dJ2uFVkHmlytyrFAnGE58CJLx364I= -20251113120533.sql h1:lfjgdqRGo/EohrVw8sWlFbDjh3ASTsfQ6pr3qjafqvc= -20251114062746.sql h1:6DLYjfJ60PkAABZTXvOwSE+xrU25oyoX7gpYlBnA9cw= -20251117005942.sql h1:0XoJKca8IOaB9QKFVF/qPY7jKcIgh6m/LODQuE06SAs= -20251117075427.sql h1:LhY2urosfoSu1/vkHmgsNP4JA4DuWBs9gL59yMqcF8M= -20251118074929.sql h1:3RWBD6BziQVw6WSfthgoVuhTELHER9NrIuZm4hY/F1A= -20251119063438.sql h1:EVTG3ZrHjCmM95YPASZTRPiwHrG6e33A2vO4hLSAaBQ= -20251119065730.sql h1:s98wnZOCW6NbnwDS3H53XIQ60u6B9bDwBLNvy5+Rn64= -20251119072302.sql h1:ZL+VHekLYqgNtOFKlj02WHrAk11dtTxQkmyTKE8IOzY= -20251119072450.sql h1:SiJy2vpSvoPFw4J1SW7HjGSJzrqR62NsjRYAeabV+kc= -20251120005512.sql h1:hJUaWXYJ3HiSquBTw8OKhymjA4O43ehAMGfiOY8W87Q= -20251120074415.sql h1:dNmcqZHqfZwi/wtYvO/pSFgImN2scXL0p/7g0+HLp0s= -20251121033803.sql h1:onlddYGo+tQdGaEdJPqdsx3sncGnwEvqMSCksF6vjjI= -20251124071457.sql h1:ikQLIXFikUbkUd55uJBmEvqLGEC9t0db+Om4TQsWP7M= -20251125125303.sql h1:OLKbNPO36AHtIDursW9AeBvf60sahQKC1iOjHmpx0MA= -20251126064057.sql h1:6al3PTWbw/WGiBcrRrVWppOMLtG+eRaH/qSLbnmh1kQ= -20251201081333.sql h1:dD+jcisoUYnxRYWdtVcnxbDeYjUW12/R/qarYQr+utg= -20251201104439.sql h1:h4tz5uetbCKeOI3agSVmAeh6jUfECYy0LhQ7HooYhzg= -20251201113804.sql h1:DdUzqfLdy4AUpVSRFDrIJXntGmtKgZrtvv8MAT4mMxs= -20251201113858.sql h1:XSpicm4aWjrfeY5EYIiw8Ios9v7BGfzZJxpW/57Qwqs= -20251201114751.sql h1:qx+ShdHLacVFcRwwGrW1zMKFHOjMGdnusk7CEfyV8ig= -20251201114913.sql h1:6l/m2/6fmTIjFmKio0QmB8oTwBDCHTIkbuYTODQ7Gwk= -20251202030445.sql h1:5+6ss5KdN6pll8Qtf0RGGyy/BURNO3dBgIBJOzDb624= -20251202044430.sql h1:nJtlQDGj7ZJtJ07NYcF41JCn9ck50GyDPoitTOe8P/s= -20251202064000.sql h1:yzSMOPZrpvQf+u6CxD6LwNySNH9Ip1u70UEf2vWI5w4= -20251202130629.sql h1:u79EiiYq5irxCcjlOHQcACnCKS05XPDDsL4TzLGrNQA= -20251202160848.sql h1:Aq5rVLbrL4vvNnmfk82V22GTteWVTSq9vk2SYzi3EBo= -20251202180207.sql h1:J0Orufzpi+tNhd5+9eLvonKhYc/WMceVHO1WDVRrHAM= -20251202231005.sql h1:DBunbxmAfPYiO5mHspc4dyTTVFoKrHkZSwk/Ieu5oFA= -20251203205052.sql h1:67NoN6JhDfChBA13dmErBSRDiC1gdVBb2F+8SMzpm4U= -20251207020537.sql h1:SIaioWMbg5W1qJDwoh2r7aGnUTIXs67ZhGEe0XyXVB4= -20251207212015.sql h1:RfXFRdynp6vk5KWFzF2nZc2yFpH9BKP9gqBxuAG/G/Q= -20251207221222.sql h1:6DS9hzcfN3+52WShFeI4f9Gqxd4LCQg1Otn5cRipIWU= +20251106050412.sql h1:1002KYtHd8AwrQTMewbs/PPHDylHDghigE/3S7PVdMA= +20251106063418.sql h1:jPW/gBnbFl4RO39lQ0ZMDtYA6xbhyD6CgQupT50HmaY= +20251106071906.sql h1:leYGKxR3EQn794aOehf0sd/ZPmOnvBMZPy5/anGmRB4= +20251106073157.sql h1:KASMzjjjk5UB7Zj8lCRtM1utc4ZnDjlnpZbtTe3vONE= +20251106074218.sql h1:Z5q5deOvLaZDPhiVTN9st3/s56RepBa2YOyrMXBdj4A= +20251106081846.sql h1:P+VsWwhGt60adDIZuE/Aa38JVp/yX1rnsdpXpxASodw= +20251106082844.sql h1:Dmi5A8i9frQZvdXYPwc7f8CisZtBH8liSXq1rI6z1iM= +20251106090021.sql h1:4JwdKgO8T46YhyWVJUxpRIwudBDlG8QN1brSOYmgQ20= +20251106144745.sql h1:nqnQCzGrVJaq8ilOEOGXeRUL1dolj+OPWKuP8A92FRA= +20251107012049.sql h1:Pff4UqltGS3clSlGr0qq8CQM56L29wyxY0FC/N/YAhU= +20251107064812.sql h1:GB9a0ZfMYTIoGNmKUG+XcYUsTnRMFfT4/dAD71uCPc4= +20251107064937.sql h1:IC5pw1Ifj30hiE6dr5NMHXaSHoQI+vRd40N5ABgBHRI= +20251107071420.sql h1:9NO3iyLEXEtWa2kSRjM/8LyzuVIk6pdFL2SuheWjB08= +20251107074318.sql h1:7fHbSRrdjOmHh/xwnjCLwoiB5cW5zeH+uxLV0vZbkIA= +20251107075050.sql h1:np+3uTOnU9QNtK7Knaw8eRMhkyB9AwrtSNHphOBxbHY= +20251107080604.sql h1:cXDBLPJDVWLTG6yEJqkJsOQ7p7VYxLM2SY+mwO8qSHo= +20251107081830.sql h1:/S7OQZo4ZnK80t28g/JyiOTZtmWG/dP5Wg2zXNMQ/iE= +20251107091033.sql h1:/cbkF1nO/IjNSIfDJJx456KJtQ9rWFXOBFAkR/M2xiE= +20251107091209.sql h1:jrLQOUeV8ji2fg0pnEcs1bw4ANUxzTSMXC/rrHLIY+M= +20251107091541.sql h1:6UqbhQQRmzA2+eKu5lIvkwOkk+lH70QLZC8Pjpjcq68= +20251110012217.sql h1:C9HpX0iyHzKjyNv/5DSAn2MCHj6MX4p5UQ/NrY7QD0w= +20251110012306.sql h1:J54yb27d30LBbYp9n1P66gFVRlxPguKu0kxmWIBBG8g= +20251110052049.sql h1:232T2x8xTczJl9nk4jxJpZXhoOGYthhxjJ7nK8Jd8vg= +20251110062042.sql h1:WnfVUXrzYoj8qdkkjO9/JQQ8agGd4GfSHQdMjo7LDAg= +20251110063202.sql h1:hSzGfwVMWa6q3vwIQZUkxKgBNCzHjB+6GKy54zfV+oQ= +20251110063633.sql h1:/VpofIAqNS1CnazEnpW/+evbzn9Kew3xDW48r57M+Xg= +20251110085551.sql h1:bFZwSmfvVbTUr/enWB82WqjG88gpqcZ6s45btUvO0uo= +20251110091516.sql h1:KkJMwPQuaZQhiqnKrNQrgP12gw9rV8T3P2o3mtGTcvY= +20251110091948.sql h1:I4odAYrJdvNf1jPw6ppDC0XdI7v6vKBACg/ABwUgA7I= +20251110092729.sql h1:l1out8soEmVP6dNjaIOtGYo6QDcoJZRI8X1sjZ5ZGmo= +20251110093522.sql h1:nsz8jCxGjEdr/bz9g+4ozfZzIP803xONjVmucad1GMc= +20251110100258.sql h1:IBqt1VZj5WjQ+l9aAFGHOCCBtzb03KlLLihFLut7itg= +20251110100545.sql h1:6/LV7751iyKxE2xI6vO1zly+aHUwxXD/IBwLcVpKxqM= +20251110155448.sql h1:kFPobJB+cpflsXBAWUwy3lohuWvrb/VRlXnhJWl7i3Y= +20251111072601.sql h1:ch8F+yVhsSM5xY+TwMLY3PxdLa4Wuhtj76oyw79R7Js= +20251111073546.sql h1:cCv0NPscADAOBahRVqtDWFs6G2t7n+4a+RwlF8vk/c4= +20251111074148.sql h1:70TsV83u1gQ5TktI13K7NQiyCCa35Td2aR6CNtKUa4U= +20251111074652.sql h1:ddfQ/sRKMezPM75xBFTGytUQX5AwZ3znrJVpg73gKPA= +20251111082257.sql h1:ZsdLY1ROouos0l3oS0lkeSiuKLEUGbVvBhpcM2AVhkw= +20251111111017.sql h1:qrJ93dNtQwcuAvpsP/lAK/H63C4cinXrsVaPmWsTqkU= +20251113101344.sql h1:xaOZvAUP1fFfnO+syEFOzJUIg5lTfBe5AWHPbBWuCLA= +20251113120533.sql h1:f3/U1Ve2yF2zSMhkt+xtwF8wUYfUKYwgbNeGfE37EW4= +20251114062746.sql h1:FInLaEFQByESEwFJKuKnuUSTKmcDpi3ZXaxkKwz2+D8= +20251117005942.sql h1:wD3BWrUSmo1HlW16V3lkaBkJvbAZ0fNk77te7J9NhOc= +20251117075427.sql h1:TqU9VKZa3I8YNXUGQWY3WVBYN+1FvyyaKy0hB1jgAho= +20251118074929.sql h1:p1KsWqCuR1JXA/jVO5BmOhCcaQ8clT7t0YRszAhPFbg= +20251119063438.sql h1:NVGM0X/LHD37EaPl8SNzkNiZDJ7AB1QR+LLwLh6WRdg= +20251119065730.sql h1:U5lzk1WvMB0bw3kwckou7jkEt4bwdYItwHr2Vxqe7w4= +20251119072302.sql h1:qCuI2WMEMF/XNbjV+RXPjBnuCKLu1Fia+mR9HiLWBIs= +20251119072450.sql h1:Xg+bTwqGyKPNFEQhJylvpz1wifdfmDJvcAq6vmNf0Ng= +20251120005512.sql h1:Ek6qpacAI/qVuTYxKno+uJyzn7s5z9pf3t7VA8gTzm4= +20251120074415.sql h1:NNUeJVA03EeBHJhHqPXEZoDv/PnC6yK1/cRhmukyaJo= +20251121033803.sql h1:/vfvFX/3pzSCIHnSbMUT9EMBDykOpVkvyfeTEle9Vas= +20251124071457.sql h1:qg2dhCL9YwD13xnfJ175lW/p6MGfzFKaBqd908FByRc= +20251125125303.sql h1:4JSFv1Pmhbe9tqpLXgO63OwYnGsalStgUXKVWPyc1YE= +20251126064057.sql h1:vAdhz5Nn/gGJy0UKZAEldeXv8HpHtJU/t8ygDVIbTsU= +20251201081333.sql h1:PoC8ADRdwDuohDTB74yW/DaB42igdYa4B6humbrEJBk= +20251201104439.sql h1:tpqdrOf9d2aGwZshqm62nG6SXnfVaO/g6A7z0efPS14= +20251201113804.sql h1:kIEmVoETJXBkab2Q+b3y/pP84eF8W2BdQ47amHCnc+c= +20251201113858.sql h1:KLXKZO5XTQPoEU0YLHE8Fhg9WPKpSN3wNgYPJ+RGFcg= +20251201114751.sql h1:HM17diiPknfSHAmP+kJGP6GzToaPU9/NT+KQBpf3Jq0= +20251201114913.sql h1:gqucFgHFFLA6n/Rdz486cZH5xkaJuwefESLJMJLDue8= +20251202030445.sql h1:QWBVfTepT7DaXP5E0BYoxNM0JwKIQ2qIMXzI4kbz/qE= +20251202044430.sql h1:4QZH9lz0GrQ9rzP1AJ+hJgGalNpp+8FCRckNK7xaTbU= +20251202064000.sql h1:/EN7sT1ol/91qW1aXWrzX+Mc3XOC/7f/LtfA0JRHpbg= +20251202130629.sql h1:9mvalqfhqGCdkcJepJDzHprU2xb0i5sYys1Htf62ioo= +20251202160848.sql h1:Kd2/TziKSMezrt4XgbjQcYvY/Lo9rX0qw7/Lz0/oyKk= +20251202180207.sql h1:IHmSMIO3ia+YV5GULixbdlV1joaUAWtnjQHPd8+HKiM= +20251202231005.sql h1:lua0KKoeBptSfs/6ehZE6Azo6YUlNkOJwGFyb1HQWkY= +20251203205052.sql h1:nk0VK2Uv4bHE3SBfHo/aevVZxtHzr7zAzvmMU8TCCtk= +20251205073858.sql h1:46qqXnArgJmzGE/WO7v7Ev8Jh7BudDiGbdANexq/5Dk= +20251205211957.sql h1:3fvtZ/mBWsTIXllXMFOuCLJsp4MivVP56dunehlU0yo= +20251205214433.sql h1:rn3++FEfX7ntcJcOmCEuOMnr27TZqH0KMGRppzFwFTc= +20251205221124.sql h1:CRruUvGZqlVDBmbQSVEl4wFm+uq30AurMMDI6sb8jxg= +20251207020537.sql h1:JspoBMoP1Yk854vtNniepvATINUpODQ9idKiMkNL0OU= +20251207212015.sql h1:pEH0+QnQ5WXNizxcToLk+8XYaAb6q6WJ1/MJViRVtNQ= +20251207221222.sql h1:gpl3V4/3AGqO3WLCpWW2GAtwuhpmNuBqXMiP61wVHX0= +20251209022744.sql h1:0WXCKpMDFAe/aVnosMGmCYp3mw+FIu+foX14sYmq750= +20251209025908.sql h1:MgO50it1hj7Jj8BD5yKjW8OLC9qS3FFEdelqIsLT1v8= diff --git a/cmd/simgos-sync-api/config.yml-example b/cmd/simgos-sync-api/config.yml-example index 98544958..96e4a6d2 100644 --- a/cmd/simgos-sync-api/config.yml-example +++ b/cmd/simgos-sync-api/config.yml-example @@ -34,4 +34,12 @@ langCfg: corsCfg: allowedOrigin: - allowedMethod: GET, POST, PUT, PATCH, DELETE, OPTIONS \ No newline at end of file + allowedMethod: GET, POST, PUT, PATCH, DELETE, OPTIONS + +syncPartnerCfg: + oldSource + oldSecretKey + oldHost + newSource + newSecretKey + newHost \ No newline at end of file diff --git a/internal/domain/main-entities/chemo-plan/dto.go b/internal/domain/main-entities/chemo-plan/dto.go new file mode 100644 index 00000000..ffd9803f --- /dev/null +++ b/internal/domain/main-entities/chemo-plan/dto.go @@ -0,0 +1,86 @@ +package chemo_plan + +import ( + // std + "time" + + ere "simrs-vx/internal/domain/references/encounter" + + // internal - domain - main-entities + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type CreateDto struct { + Parent_Id *uint `json:"parent_id"` + SeriesNumber *uint16 `json:"seriesNumber"` + CycleNumber *uint `json:"cycleNumber"` + PlanDate *time.Time `json:"planDate"` + RealizationDate *time.Time `json:"realizationDate"` + Notes *string `json:"notes"` + Status ere.StatusProtocolChemo `json:"status"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Parent_Id *uint `json:"parent-id"` + Protocol_Id *uint `json:"protocol-id"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` + Includes string `json:"includes"` +} + +type UpdateDto struct { + Id uint16 `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint16 `json:"id"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + Parent_Id *uint `json:"parent_id"` // chemo.Id + Protocol_Id *uint `json:"protocol_id"` + SeriesNumber *uint16 `json:"seriesNumber"` // series ke - + CycleNumber *uint `json:"cycleNumber"` // cycle ke - + PlanDate *time.Time `json:"planDate"` + RealizationDate *time.Time `json:"realizationDate"` + Notes *string `json:"notes"` + Status ere.StatusProtocolChemo `json:"status"` +} + +func (d ChemoPlan) ToResponse() ResponseDto { + resp := ResponseDto{ + Parent_Id: d.Parent_Id, + SeriesNumber: d.SeriesNumber, + CycleNumber: d.CycleNumber, + PlanDate: d.PlanDate, + RealizationDate: d.RealizationDate, + Notes: d.Notes, + Status: d.Status, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []ChemoPlan) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/chemo-plan/entity.go b/internal/domain/main-entities/chemo-plan/entity.go new file mode 100644 index 00000000..2dc5a363 --- /dev/null +++ b/internal/domain/main-entities/chemo-plan/entity.go @@ -0,0 +1,24 @@ +package chemo_plan + +import ( + ee "simrs-vx/internal/domain/main-entities/encounter" + "time" + + ecore "simrs-vx/internal/domain/base-entities/core" + + ere "simrs-vx/internal/domain/references/encounter" +) + +type ChemoPlan struct { + ecore.Main + Parent_Id *uint `json:"parent_id"` // chemo.Id + Protocol_Id *uint `json:"protocol_id"` + SeriesNumber *uint16 `json:"seriesNumber"` // series ke - + CycleNumber *uint `json:"cycleNumber"` // cycle ke - + PlanDate *time.Time `json:"planDate"` + RealizationDate *time.Time `json:"realizationDate"` + Notes *string `json:"notes"` + Status ere.StatusProtocolChemo `json:"status"` + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` +} diff --git a/internal/domain/main-entities/chemo-protocol/dto.go b/internal/domain/main-entities/chemo-protocol/dto.go index 04ea0023..03ad0c10 100644 --- a/internal/domain/main-entities/chemo-protocol/dto.go +++ b/internal/domain/main-entities/chemo-protocol/dto.go @@ -9,18 +9,21 @@ import ( // internal - domain - main-entities ecore "simrs-vx/internal/domain/base-entities/core" - ee "simrs-vx/internal/domain/main-entities/encounter" + + ec "simrs-vx/internal/domain/main-entities/chemo" ) type CreateDto struct { - Encounter_Id *uint `json:"encounter_id"` - Patient_Weight *float32 `json:"patient_weight"` - Patient_Height *float32 `json:"patient_height"` - Diagnoses *string `json:"diagnoses"` - Duration *uint `json:"duration"` - DurationUnit_Code *erc.TimeUnitCode `json:"durationUnit_code"` - StartDate *time.Time `json:"startDate"` - EndDate *time.Time `json:"endDate"` + Chemo_Id *uint `json:"chemo_id"` + Patient_Weight *float32 `json:"patient_weight"` + Patient_Height *float32 `json:"patient_height"` + Diagnoses *string `json:"diagnoses"` + Interval *uint `json:"interval"` + Cycle *uint `json:"cycle"` + Series *uint16 `json:"series"` + StartDate *time.Time `json:"startDate"` + EndDate *time.Time `json:"endDate"` + Status_Code erc.DataVerifiedCode `json:"-"` } type ReadListDto struct { @@ -30,7 +33,7 @@ type ReadListDto struct { } type FilterDto struct { - Encounter_Id *uint `json:"encounter-id"` + Chemo_Id *uint `json:"chemo-id"` } type ReadDetailDto struct { @@ -55,28 +58,32 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty"` - Patient_Weight *float32 `json:"patient_weight"` - Patient_Height *float32 `json:"patient_height"` - Diagnoses *string `json:"diagnoses"` - Duration *uint `json:"duration"` - DurationUnit_Code *erc.TimeUnitCode `json:"durationUnit_code"` - StartDate *time.Time `json:"startDate"` - EndDate *time.Time `json:"endDate"` + Chemo_Id *uint `json:"chemo_id"` + Chemo *ec.Chemo `json:"chemo,omitempty"` + Patient_Weight *float32 `json:"patient_weight"` + Patient_Height *float32 `json:"patient_height"` + Diagnoses *string `json:"diagnoses"` + Interval *uint `json:"interval"` + Cycle *uint `json:"cycle"` + Series *uint16 `json:"series"` + StartDate *time.Time `json:"startDate"` + EndDate *time.Time `json:"endDate"` + Status_Code erc.DataVerifiedCode `json:"status_code"` } func (d ChemoProtocol) ToResponse() ResponseDto { resp := ResponseDto{ - Encounter_Id: d.Encounter_Id, - Encounter: d.Encounter, - Patient_Weight: d.Patient_Weight, - Patient_Height: d.Patient_Height, - Diagnoses: d.Diagnoses, - Duration: d.Duration, - DurationUnit_Code: d.DurationUnit_Code, - StartDate: d.StartDate, - EndDate: d.EndDate, + Chemo_Id: d.Chemo_Id, + Chemo: d.Chemo, + Patient_Weight: d.Patient_Weight, + Patient_Height: d.Patient_Height, + Diagnoses: d.Diagnoses, + Interval: d.Interval, + Cycle: d.Cycle, + Series: d.Series, + StartDate: d.StartDate, + EndDate: d.EndDate, + Status_Code: d.Status_Code, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/chemo-protocol/entity.go b/internal/domain/main-entities/chemo-protocol/entity.go index e1508e91..6377c136 100644 --- a/internal/domain/main-entities/chemo-protocol/entity.go +++ b/internal/domain/main-entities/chemo-protocol/entity.go @@ -1,21 +1,34 @@ package chemo_protocol import ( - ecore "simrs-vx/internal/domain/base-entities/core" - ee "simrs-vx/internal/domain/main-entities/encounter" - "simrs-vx/internal/domain/references/common" "time" + + ecore "simrs-vx/internal/domain/base-entities/core" + erc "simrs-vx/internal/domain/references/common" + + ec "simrs-vx/internal/domain/main-entities/chemo" + ecp "simrs-vx/internal/domain/main-entities/chemo-plan" + eus "simrs-vx/internal/domain/main-entities/user" ) type ChemoProtocol struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Patient_Weight *float32 `json:"patient_weight"` - Patient_Height *float32 `json:"patient_height"` - Diagnoses *string `json:"diagnoses"` - Duration *uint `json:"duration"` - DurationUnit_Code *common.TimeUnitCode `json:"durationUnit_code" gorm:"size:10"` - StartDate *time.Time `json:"startDate"` - EndDate *time.Time `json:"endDate"` + Chemo_Id *uint `json:"chemo_id"` + Chemo *ec.Chemo `json:"chemo,omitempty" gorm:"foreignKey:Chemo_Id;references:Id"` + Patient_Weight *float32 `json:"patient_weight"` + Patient_Height *float32 `json:"patient_height"` + Diagnoses *string `json:"diagnoses"` + Duration *uint `json:"duration"` // not used + DurationUnit_Code *erc.TimeUnitCode `json:"durationUnit_code"` // not used + Interval *uint `json:"interval"` + Cycle *uint `json:"cycle"` // total cycle + Series *uint16 `json:"series"` // total series + StartDate *time.Time `json:"startDate"` + EndDate *time.Time `json:"endDate"` + Status_Code erc.DataVerifiedCode `json:"status_code"` + VerifiedAt *time.Time `json:"verifiedAt"` + VerifiedBy_User_Id *uint `json:"verifiedBy_user_id"` + VerifiedBy *eus.User `json:"verifiedBy,omitempty" gorm:"foreignKey:VerifiedBy_User_Id;references:Id"` + ChemoPlans *[]ecp.ChemoPlan `json:"chemoPlans,omitempty" gorm:"foreignKey:Protocol_Id;references:Id"` + Patient_Id *uint `json:"patient_id"` } diff --git a/internal/domain/main-entities/chemo/dto.go b/internal/domain/main-entities/chemo/dto.go index 5d8b9501..461203d2 100644 --- a/internal/domain/main-entities/chemo/dto.go +++ b/internal/domain/main-entities/chemo/dto.go @@ -1,6 +1,7 @@ package chemo import ( + ed "simrs-vx/internal/domain/main-entities/doctor" // std "time" @@ -50,10 +51,12 @@ type DeleteDto struct { } type VerifyDto struct { - Id uint16 `json:"id"` - Status_Code erc.DataVerifiedCode `json:"status_code"` - Bed *string `json:"bed" validate:"required"` - Needs *string `json:"needs" validate:"required"` + Id uint16 `json:"id"` + Status_Code erc.DataVerifiedCode `json:"status_code"` + Bed *string `json:"bed"` + Needs *string `json:"needs"` + Doctor_Code *string `json:"doctor_code" validate:"required"` + NextChemoDate *time.Time `json:"nextChemoDate"` pa.AuthInfo } @@ -74,6 +77,9 @@ type ResponseDto struct { VerifiedBy *eus.User `json:"verifiedBy,omitempty"` SrcUnit_Code *string `json:"srcUnit_code"` SrcUnit *eun.Unit `json:"srcUnit,omitempty"` + Doctor_Code *string `json:"doctor_code"` + Doctor *ed.Doctor `json:"doctor,omitempty"` + NextChemoDate *time.Time `json:"nextChemoDate"` } func (d Chemo) ToResponse() ResponseDto { @@ -86,6 +92,9 @@ func (d Chemo) ToResponse() ResponseDto { VerifiedBy: d.VerifiedBy, SrcUnit_Code: d.SrcUnit_Code, SrcUnit: d.SrcUnit, + Doctor_Code: d.Doctor_Code, + Doctor: d.Doctor, + NextChemoDate: d.NextChemoDate, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/chemo/entity.go b/internal/domain/main-entities/chemo/entity.go index 6f5180aa..cc828835 100644 --- a/internal/domain/main-entities/chemo/entity.go +++ b/internal/domain/main-entities/chemo/entity.go @@ -1,14 +1,16 @@ package chemo import ( + ere "simrs-vx/internal/domain/references/encounter" "time" ecore "simrs-vx/internal/domain/base-entities/core" + erc "simrs-vx/internal/domain/references/common" + + ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/encounter" eun "simrs-vx/internal/domain/main-entities/unit" eus "simrs-vx/internal/domain/main-entities/user" - - erc "simrs-vx/internal/domain/references/common" ) type Chemo struct { @@ -19,8 +21,12 @@ type Chemo struct { VerifiedAt *time.Time `json:"verifiedAt"` VerifiedBy_User_Id *uint `json:"verifiedBy_user_id"` VerifiedBy *eus.User `json:"verifiedBy,omitempty" gorm:"foreignKey:VerifiedBy_User_Id;references:Id"` - SrcUnit_Code *string `json:"src_unit_code"` + SrcUnit_Code *string `json:"src_unit_code"` // klinik asal SrcUnit *eun.Unit `json:"src_unit,omitempty" gorm:"foreignKey:SrcUnit_Code;references:Code"` Bed *string `json:"bed" gorm:"size:1024"` Needs *string `json:"needs" gorm:"size:2048"` + Doctor_Code *string `json:"doctor_code"` + Doctor *ed.Doctor `json:"doctor" gorm:"foreignKey:Doctor_Code;references:Code"` + NextChemoDate *time.Time `json:"nextChemoDate"` + Class_Code ere.ChemoClassCode `json:"class_code"` } diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index c039fc0c..53ffff0e 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -34,28 +34,39 @@ import ( ) type CreateDto struct { - Patient_Id *uint `json:"patient_id"` - RegisteredAt *time.Time `json:"registeredAt"` - Class_Code ere.EncounterClassCode `json:"class_code" validate:"maxLength=10"` - SubClass_Code *string `json:"subClass_code" validate:"maxLength=10"` // for sub - Infra_Code *string `json:"infra_code"` // for inpatient - Unit_Code *string `json:"unit_code"` - Specialist_Code *string `json:"specialist_code"` - Subspecialist_Code *string `json:"subspecialist_code"` - VisitDate time.Time `json:"visitDate"` - PaymentMethod_Code ere.AllPaymentMethodCode `json:"paymentMethod_code" gorm:"size:10"` - InsuranceCompany_Code *string `json:"insuranceCompany_code"` - Member_Number *string `json:"member_number" validate:"maxLength=20"` - Ref_Number *string `json:"ref_number" validate:"maxLength=20"` - Trx_Number *string `json:"trx_number" validate:"maxLength=20"` - Appointment_Doctor_Code *string `json:"appointment_doctor_code"` - Adm_Employee_Id *uint `json:"-"` - Responsible_Doctor_Code *string `json:"responsible_doctor_code"` - RefSource_Name *string `json:"refSource_name" validate:"maxLength=100"` - Appointment_Id *uint `json:"appointment_id"` - RefTypeCode ere.RefTypeCode `json:"refTypeCode"` - NewStatus bool `json:"newStatus"` - VclaimReference *TRujukan `json:"vclaimReference"` + Patient_Id *uint `json:"patient_id"` + RegisteredAt *time.Time `json:"registeredAt"` + Class_Code ere.EncounterClassCode `json:"class_code" validate:"maxLength=10"` + SubClass_Code *string `json:"subClass_code" validate:"maxLength=10"` // for sub + Infra_Code *string `json:"infra_code"` // for inpatient + Unit_Code *string `json:"unit_code"` + Specialist_Code *string `json:"specialist_code"` + Subspecialist_Code *string `json:"subspecialist_code"` + VisitDate time.Time `json:"visitDate"` + StartedAt *time.Time `json:"startedAt"` + FinishedAt *time.Time `json:"finishedAt"` + PaymentMethod_Code ere.AllPaymentMethodCode `json:"paymentMethod_code" gorm:"size:10"` + InsuranceCompany_Code *string `json:"insuranceCompany_code"` + Member_Number *string `json:"member_number" validate:"maxLength=20"` + RefTypeCode ere.RefTypeCode `json:"refTypeCode"` + Ref_Number *string `json:"ref_number" validate:"maxLength=20"` + Trx_Number *string `json:"trx_number" validate:"maxLength=20"` + Appointment_Doctor_Code *string `json:"appointment_doctor_code"` + Adm_Employee_Id *uint `json:"-"` + Responsible_Doctor_Code *string `json:"responsible_doctor_code"` + Responsible_Nurse_Code *string `json:"responsible_nurse_code"` + Discharge_Method_Code *ere.DischargeMethodCode `json:"discharge_method_code" gorm:"size:16"` + RefSource_Name *string `json:"refSource_name" validate:"maxLength=100"` + Appointment_Id *uint `json:"appointment_id"` + EarlyEducation *string `json:"earlyEducation"` + MedicalDischargeEducation *string `json:"medicalDischargeEducation"` + AdmDischargeEducation *string `json:"admDischargeEducation"` + DischargeReason *string `json:"dischargeReason"` + Status_Code erc.DataStatusCode `json:"status_code" gorm:"size:10"` + Discharge_Date *time.Time `json:"discharge_date"` + DeathCause *edc.DeathCause `json:"deathCause"` + NewStatus bool `json:"newStatus"` + VclaimReference *TRujukan `json:"vclaimReference"` Id uint `json:"-"` RecentEncounterAdm *Encounter `json:"-"` // if subClass_Code is rehab diff --git a/internal/domain/main-entities/patient/dto.go b/internal/domain/main-entities/patient/dto.go index 6418c6ac..248a7164 100644 --- a/internal/domain/main-entities/patient/dto.go +++ b/internal/domain/main-entities/patient/dto.go @@ -60,6 +60,7 @@ type UpdateDto struct { type DeleteDto struct { Id uint `json:"id"` + pa.AuthInfo } type SearchDto struct { diff --git a/internal/domain/main-entities/soapi/dto.go b/internal/domain/main-entities/soapi/dto.go index 94094df7..bc847b3b 100644 --- a/internal/domain/main-entities/soapi/dto.go +++ b/internal/domain/main-entities/soapi/dto.go @@ -37,16 +37,19 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` + Includes string `json:"includes"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` CreateDto + pa.AuthInfo } type DeleteDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` + pa.AuthInfo } type MetaDto struct { diff --git a/internal/domain/references/clinical/clinical.go b/internal/domain/references/clinical/clinical.go index 80c451c7..a41f459d 100644 --- a/internal/domain/references/clinical/clinical.go +++ b/internal/domain/references/clinical/clinical.go @@ -400,8 +400,8 @@ type SoapiSrc struct { type EarlyMedicValue struct { Vaccinated bool `json:"vaccinated,omitempty"` - CaseStatus string `json:"case-status,omitempty"` - EncounterStatus string `json:"encounter-status,omitempty"` + CaseStatus int `json:"case-status,omitempty"` + EncounterStatus int `json:"encounter-status,omitempty"` PrimaryComplain string `json:"pri-complain,omitempty"` CurrentDiseaseHistory string `json:"cur-disea-hist,omitempty"` SpO2 int `json:"spo2,omitempty"` diff --git a/internal/domain/references/encounter/encounter.go b/internal/domain/references/encounter/encounter.go index ad6abe05..83ef759b 100644 --- a/internal/domain/references/encounter/encounter.go +++ b/internal/domain/references/encounter/encounter.go @@ -22,6 +22,7 @@ type ( PolySwitchCode string DocTypeCode string EntityTypeCode string + StatusProtocolChemo string ) const ( @@ -128,6 +129,10 @@ const ( ETCPerson EntityTypeCode = "person" ETCEncounter EntityTypeCode = "encounter" ETCMCU EntityTypeCode = "mcu" + + SPCComplete StatusProtocolChemo = "complete" + SPCPlanned StatusProtocolChemo = "planned" + SPCSchedule StatusProtocolChemo = "schedule" ) func (ec EncounterClassCode) Code() string { diff --git a/internal/domain/simgos-entities/m-pasien/dto.go b/internal/domain/simgos-entities/m-pasien/dto.go new file mode 100644 index 00000000..8d2c3368 --- /dev/null +++ b/internal/domain/simgos-entities/m-pasien/dto.go @@ -0,0 +1,273 @@ +package m_pasien + +import ( + "fmt" + ecore "simrs-vx/internal/domain/base-entities/core" + e "simrs-vx/internal/domain/main-entities/patient" + pr "simrs-vx/internal/domain/main-entities/person" + pa "simrs-vx/internal/domain/main-entities/person-address" + pab "simrs-vx/internal/domain/main-entities/person-address/base" + pc "simrs-vx/internal/domain/main-entities/person-contact" + rf "simrs-vx/internal/domain/references/person" + + "time" +) + +type MPasienDto struct { + Id uint `json:"id" gorm:"primaryKey;autoIncrement;column:id"` + Nomr string `json:"nomr" gorm:"uniqueIndex;column:nomr"` + Title string `json:"title" gorm:"column:title"` + Nama string `json:"nama" gorm:"column:nama"` + Tempat string `json:"tempat" gorm:"column:tempat"` + Tgllahir string `json:"tgllahir" gorm:"column:tgllahir"` + Jeniskelamin string `json:"jeniskelamin" gorm:"column:jeniskelamin"` + Alamat string `json:"alamat" gorm:"column:alamat"` + Kelurahan uint64 `json:"kelurahan" gorm:"column:kelurahan"` + Kdkecamatan uint `json:"kdkecamatan" gorm:"column:kdkecamatan"` + Kota uint `json:"kota" gorm:"column:kota"` + Kdprovinsi uint `json:"kdprovinsi" gorm:"column:kdprovinsi"` + Notelp string `json:"notelp" gorm:"column:notelp"` + Noktp string `json:"noktp" gorm:"column:noktp"` + SuamiOrtu *string `json:"suami_ortu" gorm:"column:suami_ortu"` + Pekerjaan string `json:"pekerjaan" gorm:"column:pekerjaan"` + Status uint `json:"status" gorm:"column:status"` + Agama uint `json:"agama" gorm:"column:agama"` + Pendidikan uint `json:"pendidikan" gorm:"column:pendidikan"` + Kdcarabayar *uint `json:"kdcarabayar" gorm:"column:kdcarabayar"` + Nip *string `json:"nip" gorm:"column:nip"` + Tgldaftar string `json:"tgldaftar" gorm:"column:tgldaftar"` + AlamatKtp string `json:"alamat_ktp" gorm:"column:alamat_ktp"` + ParentNomr *string `json:"parent_nomr" gorm:"column:parent_nomr"` + Kepercayaan string `json:"kepercayaan" gorm:"column:kepercayaan"` + PenanggungjawabNama string `json:"penanggungjawab_nama" gorm:"column:penanggungjawab_nama"` + PenanggungjawabHubungan string `json:"penanggungjawab_hubungan" gorm:"column:penanggungjawab_hubungan"` + PenanggungjawabAlamat string `json:"penanggungjawab_alamat" gorm:"column:penanggungjawab_alamat"` + PenanggungjawabPhone string `json:"penanggungjawab_phone" gorm:"column:penanggungjawab_phone"` + NoKartu string `json:"no_kartu" gorm:"column:no_kartu"` + JnsPasien string `json:"jns_pasien" gorm:"column:jns_pasien"` + Nk *string `json:"nk" gorm:"column:nk"` + Kdprovider *string `json:"kdprovider" gorm:"column:kdprovider"` + Nmprovider *string `json:"nmprovider" gorm:"column:nmprovider"` + Kelas *uint `json:"kelas" gorm:"column:kelas"` + Sim *string `json:"sim" gorm:"column:sim"` + Paspor *string `json:"paspor" gorm:"column:paspor"` + Disabilitas *string `json:"disabilitas" gorm:"column:disabilitas"` + Bahasa string `json:"bahasa" gorm:"column:bahasa"` + HambatanKomunikasi string `json:"hambatan_komunikasi" gorm:"column:hambatan_komunikasi"` + Kebangsaan string `json:"kebangsaan" gorm:"column:kebangsaan"` + Notelprumah1 string `json:"notelprumah1" gorm:"column:notelprumah1"` + Notelprumah2 *string `json:"notelprumah2" gorm:"column:notelprumah2"` + Notelpkantor string `json:"notelpkantor" gorm:"column:notelpkantor"` + NoHp *string `json:"no_hp" gorm:"column:no_hp"` + AsalMasuk *string `json:"asal_masuk" gorm:"column:asal_masuk"` + Diagnosa *string `json:"diagnosa" gorm:"column:diagnosa"` + DiagnosaUtama *string `json:"diagnosa_utama" gorm:"column:diagnosa_utama"` + Suku string `json:"suku" gorm:"column:suku"` + AgamaLain string `json:"agama_lain" gorm:"column:agama_lain"` + StDisabilitas uint `json:"stDisabilitas" gorm:"column:st_disabilitas"` + TxtKelurahan string `json:"txt_kelurahan" gorm:"column:txt_kelurahan"` + TxtKecamatan string `json:"txt_kecamatan" gorm:"column:txt_kecamatan"` + TxtKota string `json:"txt_kota" gorm:"column:txt_kota"` + TxtProvinsi string `json:"txt_provinsi" gorm:"column:txt_provinsi"` + TxtStatus string `json:"txt_status" gorm:"column:txt_status"` + TxtAgama string `json:"txt_agama" gorm:"column:txt_agama"` + TxtPendidikan string `json:"txt_pendidikan" gorm:"column:txt_pendidikan"` + NamaAyah string `json:"nama_ayah" gorm:"column:nama_ayah"` + NamaIbu string `json:"nama_ibu" gorm:"column:nama_ibu"` + PendidikanAyah string `json:"pendidikan_ayah" gorm:"column:pendidikan_ayah"` + PendidikanIbu string `json:"pendidikan_ibu" gorm:"column:pendidikan_ibu"` + StIdentitasOrtu int `json:"st_identitas_ortu" gorm:"column:st_identitas_ortu"` + NomrBaru *string `json:"nomr_baru" gorm:"column:nomr_baru"` + KtpFile *string `json:"ktp_file" gorm:"column:ktp_file"` + KkFile *string `json:"kk_file" gorm:"column:kk_file"` + CreatedAt *time.Time `json:"created_at" gorm:"column:created_at"` + UpdatedAt *time.Time `json:"updated_at" gorm:"column:updated_at"` + NoKk *string `json:"no_kk" gorm:"column:no_kk"` + NoktpBaru string `json:"noktp_baru" gorm:"column:noktp_baru"` +} + +func (mp MPasienDto) ToPatient() e.Patient { + + patient := e.Patient{ + Main: ecore.Main{ + Id: mp.Id, + }, + NewBornStatus: mp.ParentNomr != nil, + RegisteredAt: parseTimeDateOnly(mp.Tgldaftar), + RegisteredBy_User_Name: mp.Nip, + Number: &mp.Nomr, + Parent_Number: mp.ParentNomr, + // Status_Code: getActiveStatus(mp.Status), + // mp.Status is marital status + // Parent + } + + // person + gc := getGender(mp.Jeniskelamin) + rc := getReligion(mp.Agama) + ec := getEducation(mp.Pendidikan) + mc := getMaritalStatus(mp.Status) + bc := getBirthRegencyCode(mp.Tempat) + et := getEthnicCode(mp.Suku) + lc := getLanguageCode(mp.Bahasa) + + person := pr.Person{ + Name: mp.Nama, + FrontTitle: &mp.Title, + BirthDate: parseTimeDateOnly(mp.Tgllahir), + BirthRegency_Code: &bc, + Gender_Code: &gc, + ResidentIdentityNumber: nilEmptyString(&mp.Noktp), + PassportNumber: nilEmptyString(mp.Paspor), + DrivingLicenseNumber: nilEmptyString(mp.Sim), + Religion_Code: &rc, + Education_Code: &ec, + Ocupation_Name: &mp.Pekerjaan, + MaritalStatus_Code: &mc, + Nationality: &mp.Kebangsaan, + Ethnic_Code: &et, + Language_Code: &lc, + CommunicationIssueStatus: mp.HambatanKomunikasi == "Y", + Disability: mp.Disabilitas, + ResidentIdentityFileUrl: mp.KtpFile, + FamilyIdentityFileUrl: mp.KkFile, + // EndTitle + // Confidence + // Ocupation_Code + } + var addresses []pa.PersonAddress + if mp.Alamat != "" { + vc := fmt.Sprintf("%d", mp.Kelurahan) + addresses = append(addresses, pa.PersonAddress{ + PersonAddress: pab.PersonAddress{ + Address: mp.Alamat, + LocationType_Code: rf.ALTCDom, + Village_Code: &vc, + }, + }) + } + if mp.AlamatKtp != "" { + addresses = append(addresses, pa.PersonAddress{ + PersonAddress: pab.PersonAddress{ + Address: mp.AlamatKtp, + LocationType_Code: rf.ALTCIdn, + }, + }) + } + + var contacts []pc.PersonContact + + if mp.NoHp != nil { + + } + + person.Addresses = &addresses + person.Contacts = &contacts + patient.Person = &person + return patient +} + +func nilEmptyString(s *string) *string { + if s == nil { + return nil + } + return s +} + +func getGender(g string) rf.GenderCode { + if g == "L" { + return rf.GCMale + } else if g == "P" { + return rf.GCFemale + } + return rf.GCUnknown + +} + +func getReligion(r uint) rf.ReligionCode { + switch r { + case 1: + return rf.RCIslam + case 2: + return rf.RCProtestan + case 3: + return rf.RCKatolik + case 4: + return rf.RCHindu + case 5: + return rf.RCBudha + case 6: + return rf.RCKonghucu + default: + // 9 "Lainnya" + // 0 "Tidak diketahui" + return "" + } +} + +func getEducation(e uint) rf.EducationCode { + switch e { + case 0: + return rf.ECTS + case 1: + return rf.ECSD + case 2: + return rf.ECSLTP + case 3: + return rf.ECSLTA + case 4: + return rf.ECD3 + case 5: + return rf.ECS1 + case 6: + return rf.ECOther + case 7: + return rf.ECUnkown + default: + return rf.ECUnkown + } +} + +func getMaritalStatus(m uint) rf.MaritalStatusCode { + switch m { + case 1: + return rf.MaritalStatusSingle // S + case 2: + return rf.MaritalStatusMarried // M + case 3: + return rf.MaritalStatusWidowed // W + case 4: + return rf.MaritalStatusDivorced // D + default: + return "" // unknown + } +} + +func getBirthRegencyCode(r string) string { + if r != "" { + // TODO get from database + } + return "3574" +} + +func getEthnicCode(s string) string { + if s != "" { + // TODO check database + } + return "jawa" +} + +func getLanguageCode(s string) string { + if s != "" { + // TODO check database + } + return "jawa" +} + +func parseTimeDateOnly(d string) *time.Time { + do, err := time.Parse("2006-01-02", d) + if err == nil { + return &do + } + return nil +} diff --git a/internal/domain/simgos-entities/t-diagnosadanterapi/entity.go b/internal/domain/simgos-entities/t-diagnosadanterapi/entity.go index 2e77d362..9579168c 100644 --- a/internal/domain/simgos-entities/t-diagnosadanterapi/entity.go +++ b/internal/domain/simgos-entities/t-diagnosadanterapi/entity.go @@ -11,29 +11,29 @@ type TDiagnosaDanTerapi struct { GolonganDarah string `json:"golongan_darah" gorm:"column:golongan_darah"` TinggiBadan float64 `json:"tinggi_badan" gorm:"column:tinggi_badan"` BeratBadan float64 `json:"berat_badan" gorm:"column:berat_badan"` - Diagnosa string `json:"diagnosa" gorm:"column:diagnosa"` - Komplikasi string `json:"komplikasi" gorm:"column:komplikasi"` - Terapi string `json:"terapi" gorm:"column:terapi"` - Anamnesa string `json:"anamnesa" gorm:"column:anamnesa"` + Diagnosa *string `json:"diagnosa" gorm:"column:diagnosa"` + Komplikasi *string `json:"komplikasi" gorm:"column:komplikasi"` + Terapi *string `json:"terapi" gorm:"column:terapi"` + Anamnesa *string `json:"anamnesa" gorm:"column:anamnesa"` Kdpoly uint `json:"kdpoly" gorm:"column:kdpoly"` Kddokter uint `json:"kddokter" gorm:"column:kddokter"` - Kdtujuanrujuk uint `json:"kdtujuanrujuk" gorm:"column:kdtujuanrujuk"` + Kdtujuanrujuk *uint `json:"kdtujuanrujuk" gorm:"column:kdtujuanrujuk"` Nip string `json:"nip" gorm:"column:nip"` - IcdCode string `json:"icd_code" gorm:"column:icd_code"` + IcdCode *string `json:"icd_code" gorm:"column:icd_code"` KunjunganBl uint `json:"kunjungan_bl" gorm:"column:kunjungan_bl"` KasusBl uint `json:"kasus_bl" gorm:"column:kasus_bl"` - Icdcm string `json:"icdcm" gorm:"column:icdcm"` - Icd9 string `json:"icd_9" gorm:"column:icd_9"` - Klb uint `json:"klb" gorm:"column:klb"` - Bedah uint `json:"bedah" gorm:"column:bedah"` - Jenis uint `json:"jenis" gorm:"column:jenis"` - Perawat string `json:"perawat" gorm:"column:perawat"` - Status string `json:"status" gorm:"column:status"` - PemeriksaanFisik string `json:"pemeriksaan_fisik" gorm:"column:pemeriksaan_fisik"` - RiwayatPasien string `json:"riwayat_pasien" gorm:"column:riwayat_pasien"` - TindakanMedis string `json:"tindakan_medis" gorm:"column:tindakan_medis"` + Icdcm *string `json:"icdcm" gorm:"column:icdcm"` + Icd9 *string `json:"icd_9" gorm:"column:icd_9"` + Klb *uint `json:"klb" gorm:"column:klb"` + Bedah *uint `json:"bedah" gorm:"column:bedah"` + Jenis *uint `json:"jenis" gorm:"column:jenis"` + Perawat *string `json:"perawat" gorm:"column:perawat"` + Status *string `json:"status" gorm:"column:status"` + PemeriksaanFisik *string `json:"pemeriksaan_fisik" gorm:"column:pemeriksaan_fisik"` + RiwayatPasien *string `json:"riwayat_pasien" gorm:"column:riwayat_pasien"` + TindakanMedis *string `json:"tindakan_medis" gorm:"column:tindakan_medis"` Rajal uint `json:"rajal" gorm:"column:rajal"` - UserBatal string `json:"user_batal" gorm:"column:user_batal"` + UserBatal *string `json:"user_batal" gorm:"column:user_batal"` TglBatal *time.Time `json:"tgl_batal" gorm:"column:tgl_batal"` SudahVaksin string `json:"sudah_vaksin" gorm:"column:sudah_vaksin"` CreatedAt time.Time `json:"created_at" gorm:"column:created_at"` @@ -41,7 +41,7 @@ type TDiagnosaDanTerapi struct { Pernapasan string `json:"pernapasan" gorm:"column:pernapasan"` Suhu string `json:"suhu" gorm:"column:suhu"` Sp02 string `json:"sp02" gorm:"column:sp02"` - TujuanPerawatan string `json:"tujuan_perawatan" gorm:"column:tujuan_perawatan"` + TujuanPerawatan *string `json:"tujuan_perawatan" gorm:"column:tujuan_perawatan"` TargetCapaian string `json:"target_capaian" gorm:"column:target_capaian"` } diff --git a/internal/domain/simgos-entities/t-icd-cm/entity.go b/internal/domain/simgos-entities/t-icd-cm/entity.go index 198b29ea..6ea7f935 100644 --- a/internal/domain/simgos-entities/t-icd-cm/entity.go +++ b/internal/domain/simgos-entities/t-icd-cm/entity.go @@ -7,15 +7,15 @@ type TIcdCm struct { Nomr string `json:"nomr" gorm:"column:nomr"` Idxdaftar uint `json:"idxdaftar" gorm:"column:idxdaftar"` Kddokter uint `json:"kddokter" gorm:"column:kddokter"` - Icd string `json:"icd" gorm:"column:icd"` - IcdVerified string `json:"icd_verified" gorm:"column:icd_verified"` + Icd *string `json:"icd" gorm:"column:icd"` + IcdVerified *string `json:"icd_verified" gorm:"column:icd_verified"` StatusRajal uint16 `json:"status_rajal" gorm:"column:status_rajal"` Tanggal time.Time `json:"tanggal" gorm:"column:tanggal"` - StatusVerif uint16 `json:"status_verif" gorm:"column:status_verif"` - IcdVerifiedOrder uint16 `json:"icd_verified_order" gorm:"column:icd_verified_order"` - IcdVerifBy string `json:"icd_verif_by" gorm:"column:icd_verif_by"` + StatusVerif *uint16 `json:"status_verif" gorm:"column:status_verif"` + IcdVerifiedOrder *uint16 `json:"icd_verified_order" gorm:"column:icd_verified_order"` + IcdVerifBy *string `json:"icd_verif_by" gorm:"column:icd_verif_by"` IcdVerifDate *time.Time `json:"icd_verif_date" gorm:"column:icd_verif_date"` - IcdActive uint16 `json:"icd_active" gorm:"column:icd_active"` + IcdActive *uint16 `json:"icd_active" gorm:"column:icd_active"` } func (TIcdCm) TableName() string { diff --git a/internal/domain/simgos-entities/t-icd/entity.go b/internal/domain/simgos-entities/t-icd/entity.go index f2191ecc..73ee49e1 100644 --- a/internal/domain/simgos-entities/t-icd/entity.go +++ b/internal/domain/simgos-entities/t-icd/entity.go @@ -8,15 +8,15 @@ type TIcd struct { Idxdaftar uint `json:"idxdaftar" gorm:"column:idxdaftar"` Kddokter uint `json:"kddokter" gorm:"column:kddokter"` Icd string `json:"icd" gorm:"column:icd"` - IcdVerified string `json:"icd_verified" gorm:"column:icd_verified"` + IcdVerified *string `json:"icd_verified" gorm:"column:icd_verified"` StatusRajal uint16 `json:"status_rajal" gorm:"column:status_rajal"` Tanggal time.Time `json:"tanggal" gorm:"column:tanggal"` - StatusVerif uint16 `json:"status_verif" gorm:"column:status_verif"` - IcdVerifiedOrder uint16 `json:"icd_verified_order" gorm:"column:icd_verified_order"` - IcdVerifBy string `json:"icd_verif_by" gorm:"column:icd_verif_by"` + StatusVerif *uint16 `json:"status_verif" gorm:"column:status_verif"` + IcdVerifiedOrder *uint16 `json:"icd_verified_order" gorm:"column:icd_verified_order"` + IcdVerifBy *string `json:"icd_verif_by" gorm:"column:icd_verif_by"` IcdVerifDate *time.Time `json:"icd_verif_date" gorm:"column:icd_verif_date"` - IcdActive uint16 `json:"icd_active" gorm:"column:icd_active"` - StSebabMati uint16 `json:"st_sebab_mati" gorm:"column:st_sebab_mati"` + IcdActive *uint16 `json:"icd_active" gorm:"column:icd_active"` + StSebabMati *uint16 `json:"st_sebab_mati" gorm:"column:st_sebab_mati"` } func (TIcd) TableName() string { diff --git a/internal/domain/simgos-entities/t-rekammedik/entity.go b/internal/domain/simgos-entities/t-rekammedik/entity.go index 5df0ec83..84cec1ef 100644 --- a/internal/domain/simgos-entities/t-rekammedik/entity.go +++ b/internal/domain/simgos-entities/t-rekammedik/entity.go @@ -5,16 +5,16 @@ import "time" type TRekammedik struct { TglKirim *time.Time `json:"tgl_kirim" gorm:"column:tgl_kirim"` TglTerima *time.Time `json:"tgl_terima" gorm:"column:tgl_terima"` - Idxdaftar int `json:"idxdaftar" gorm:"column:idxdaftar"` - Kdpoly int `json:"kdpoly" gorm:"column:kdpoly"` + Idxdaftar uint `json:"idxdaftar" gorm:"column:idxdaftar"` + Kdpoly uint `json:"kdpoly" gorm:"column:kdpoly"` Pengirim string `json:"pengirim" gorm:"column:pengirim"` - Penerima string `json:"penerima" gorm:"column:penerima"` - Statusrm int `json:"statusrm" gorm:"column:statusrm"` - PenerimaPoly string `json:"penerima_poly" gorm:"column:penerima_poly"` - JamKirimRm string `json:"jam_kirim_rm" gorm:"column:jam_kirim_rm"` - JamTerimaRm string `json:"jam_terima_rm" gorm:"column:jam_terima_rm"` - PjBerkasRm string `json:"pj_berkas_rm" gorm:"column:pj_berkas_rm"` - StatusFisikBerkas string `json:"status_fisik_berkas" gorm:"column:status_fisik_berkas"` + Penerima *string `json:"penerima" gorm:"column:penerima"` + Statusrm *uint `json:"statusrm" gorm:"column:statusrm"` + PenerimaPoly *string `json:"penerima_poly" gorm:"column:penerima_poly"` + JamKirimRm *time.Time `json:"jam_kirim_rm" gorm:"column:jam_kirim_rm"` + JamTerimaRm *time.Time `json:"jam_terima_rm" gorm:"column:jam_terima_rm"` + PjBerkasRm *string `json:"pj_berkas_rm" gorm:"column:pj_berkas_rm"` + StatusFisikBerkas *string `json:"status_fisik_berkas" gorm:"column:status_fisik_berkas"` } func (TRekammedik) TableName() string { diff --git a/internal/domain/sync-entities/authentication/authentication.go b/internal/domain/sync-entities/authentication/authentication.go new file mode 100644 index 00000000..f2448d9d --- /dev/null +++ b/internal/domain/sync-entities/authentication/authentication.go @@ -0,0 +1,9 @@ +package authentication + +type SyncKey struct{} + +type CredentialDto struct { + Source string `json:"X-Sync-Source"` + SecretKey string `json:"X-Sync-SecretKey"` + UserName string `json:"X-Sync-UserName"` +} diff --git a/internal/infra/sync-cfg/sync-cfg.go b/internal/infra/sync-cfg/sync-cfg.go index a6a5d703..8e0e0f5a 100644 --- a/internal/infra/sync-cfg/sync-cfg.go +++ b/internal/infra/sync-cfg/sync-cfg.go @@ -8,8 +8,8 @@ import ( func SetConfig() { a.ParseSingleCfg(&O) - if O.Host == "" || O.Prefix == "" { - panic("config sync host and prefix empty") + if O.NewSecretKey == "" || O.NewHost == "" || O.OldSecretKey == "" || O.OldHost == "" { + panic("secret key and host of the sync partner config can not be empty") } - lo.I.Println("sync url config loaded, status: DONE!!") + lo.I.Println("sync partner config loaded, status: DONE!!") } diff --git a/internal/infra/sync-cfg/tycovar.go b/internal/infra/sync-cfg/tycovar.go index 6ae230fb..a7534f82 100644 --- a/internal/infra/sync-cfg/tycovar.go +++ b/internal/infra/sync-cfg/tycovar.go @@ -1,9 +1,13 @@ package synccfg -var O SyncUrlCfg = SyncUrlCfg{} +var O SyncPartnerCfg = SyncPartnerCfg{} // old -type SyncUrlCfg struct { - Prefix string `yaml:"prefix"` - Host string `yaml:"host"` - Enable bool `yaml:"enable"` +// Used by sync itself, so any partner should be stated here +type SyncPartnerCfg struct { + OldSource string `yaml:"oldSource"` + OldSecretKey string `yaml:"oldSecretKey"` + OldHost string `yaml:"oldHost"` + NewSource string `yaml:"newSource"` + NewSecretKey string `yaml:"newSecretKey"` + NewHost string `yaml:"newHost"` } diff --git a/internal/infra/sync-consumer-cfg/sync-cfg.go b/internal/infra/sync-consumer-cfg/sync-cfg.go new file mode 100644 index 00000000..8ea63dac --- /dev/null +++ b/internal/infra/sync-consumer-cfg/sync-cfg.go @@ -0,0 +1,15 @@ +package synccfg + +import ( + a "github.com/karincake/apem" + lo "github.com/karincake/apem/loggero" +) + +func SetConfig() { + a.ParseSingleCfg(&O) + + if O.TargetHost == "" || O.Prefix == "" { + panic("config sync host and prefix empty") + } + lo.I.Println("sync url config loaded, status: DONE!!") +} diff --git a/internal/infra/sync-consumer-cfg/tycovar.go b/internal/infra/sync-consumer-cfg/tycovar.go index d2146c2b..23fd0dcf 100644 --- a/internal/infra/sync-consumer-cfg/tycovar.go +++ b/internal/infra/sync-consumer-cfg/tycovar.go @@ -1,6 +1,6 @@ package synccfg -var O SyncConsumerUrlCfg = SyncConsumerUrlCfg{} // old +var O SyncConsumerUrlCfg = SyncConsumerUrlCfg{} // new type SyncConsumerUrlCfg struct { Prefix string `yaml:"prefix"` diff --git a/internal/interface/main-handler/authentication/handler.go b/internal/interface/main-handler/authentication/handler.go index 243ba9cd..4bf5134b 100644 --- a/internal/interface/main-handler/authentication/handler.go +++ b/internal/interface/main-handler/authentication/handler.go @@ -9,9 +9,12 @@ import ( sp "github.com/karincake/semprit" sr "github.com/karincake/serabi" + is "simrs-vx/internal/infra/sync-consumer-cfg" + pa "simrs-vx/internal/lib/auth" + m "simrs-vx/internal/domain/main-entities/user" mf "simrs-vx/internal/domain/main-entities/user-fes" - pa "simrs-vx/internal/lib/auth" + esga "simrs-vx/internal/domain/sync-entities/authentication" s "simrs-vx/internal/use-case/main-use-case/authentication" ) @@ -66,12 +69,37 @@ func Logout(w http.ResponseWriter, r *http.Request) { } func GuardMW(next http.Handler) http.Handler { + var ( + accessDetail *pa.AuthInfo + err error + ) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - accessDetail, err := s.ExtractToken(r, s.AccessToken) - if err != nil { - rw.WriteJSON(w, http.StatusUnauthorized, err.(d.FieldError), nil) - return + // Check if it's from sync + credential := esga.CredentialDto{} + credential.Source = r.Header.Get("X-Sync-Source") + credential.SecretKey = r.Header.Get("X-Sync-SecretKey") + credential.UserName = r.Header.Get("X-Sync-UserName") + if credential.Source != "" || credential.SecretKey != "" || credential.UserName != "" { + // validate secretKey and source + if credential.SecretKey != is.O.SecretKey || credential.Source != is.O.Source { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "invalid consumer credential"}, nil) + return + } + + accessDetail, err = s.GetAuthInfoByUserName(credential.UserName) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, err.(d.FieldError), nil) + return + } + } else { + // Normal flow goes here + accessDetail, err = s.ExtractToken(r, s.AccessToken) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, err.(d.FieldError), nil) + return + } } + ctx := context.WithValue(r.Context(), pa.AuthKey{}, accessDetail) next.ServeHTTP(w, r.WithContext(ctx)) }) diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 0e637137..1e52076a 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -68,7 +68,7 @@ import ( gs "simrs-vx/internal/infra/gorm-setting" minio "simrs-vx/internal/infra/minio" ssdb "simrs-vx/internal/infra/ss-db" - simgossync "simrs-vx/internal/infra/sync-cfg" + sync "simrs-vx/internal/infra/sync-consumer-cfg" /******************** pkg ********************/ cmw "simrs-vx/pkg/cors-manager-mw" @@ -152,7 +152,7 @@ func SetRoutes() http.Handler { a.RegisterExtCall(mh.I.SetClient) a.RegisterExtCall(ibpjs.SetConfig) a.RegisterExtCall(validation.RegisterValidation) - a.RegisterExtCall(simgossync.SetConfig) + a.RegisterExtCall(sync.SetConfig) a.RegisterExtCall(docscfg.ParseCfg) a.RegisterExtCall(ibpjs.SetConfig) diff --git a/internal/interface/main-handler/patient/handler.go b/internal/interface/main-handler/patient/handler.go index 41fca562..653a06cc 100644 --- a/internal/interface/main-handler/patient/handler.go +++ b/internal/interface/main-handler/patient/handler.go @@ -63,7 +63,15 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } + + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + dto.Id = uint(id) + dto.AuthInfo = *authInfo + res, err := u.Update(dto) rw.DataResponse(w, res, err) } @@ -75,7 +83,15 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { } dto := e.DeleteDto{} + + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + dto.Id = uint(id) + dto.AuthInfo = *authInfo + res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/soapi/handler.go b/internal/interface/main-handler/soapi/handler.go index fe50b7d2..3683bb23 100644 --- a/internal/interface/main-handler/soapi/handler.go +++ b/internal/interface/main-handler/soapi/handler.go @@ -47,7 +47,7 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } @@ -62,7 +62,7 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.Update(dto) rw.DataResponse(w, res, err) } @@ -74,7 +74,7 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index d4f596b1..745710a0 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -12,6 +12,7 @@ import ( appointment "simrs-vx/internal/domain/main-entities/appointment" authpartner "simrs-vx/internal/domain/main-entities/auth-partner" chemo "simrs-vx/internal/domain/main-entities/chemo" + chemoplan "simrs-vx/internal/domain/main-entities/chemo-plan" chemoprotocol "simrs-vx/internal/domain/main-entities/chemo-protocol" consultation "simrs-vx/internal/domain/main-entities/consultation" controlletter "simrs-vx/internal/domain/main-entities/control-letter" @@ -249,5 +250,6 @@ func getMainEntities() []any { &vclaimreference.VclaimReference{}, &screening.Screening{}, &actionreport.ActionReport{}, + &chemoplan.ChemoPlan{}, } } diff --git a/internal/interface/simgos-sync-handler/new/soapi/handler.go b/internal/interface/simgos-sync-handler/new/soapi/handler.go new file mode 100644 index 00000000..3a52a581 --- /dev/null +++ b/internal/interface/simgos-sync-handler/new/soapi/handler.go @@ -0,0 +1,58 @@ +package soapi + +import ( + "net/http" + + rw "github.com/karincake/risoles" + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/soapi" + esync "simrs-vx/internal/domain/sync-entities/log" + + u "simrs-vx/internal/use-case/simgos-sync-use-case/new/soapi" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.Soapi{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) CreateLog(w http.ResponseWriter, r *http.Request) { + dto := esync.SimxLogDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.CreateSimxLog(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + dto := e.Soapi{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + + res, err := u.Update(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.DeleteDto{} + dto.Id = uint(id) + + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/simgos-sync-handler/old/.keep b/internal/interface/simgos-sync-handler/old/.keep new file mode 100644 index 00000000..e69de29b diff --git a/internal/interface/simgos-sync-handler/old/authentication/authentication.go b/internal/interface/simgos-sync-handler/old/authentication/authentication.go new file mode 100644 index 00000000..282e1ea6 --- /dev/null +++ b/internal/interface/simgos-sync-handler/old/authentication/authentication.go @@ -0,0 +1,52 @@ +package authentication + +import ( + "context" + "net/http" + + d "github.com/karincake/dodol" + rw "github.com/karincake/risoles" + + sc "simrs-vx/internal/lib/sync-credential" + + e "simrs-vx/internal/domain/sync-entities/authentication" + is "simrs-vx/internal/infra/sync-cfg" +) + +func NewGuardMW(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // check the data format + input := e.CredentialDto{} + if success := sc.CheckCredentialData(&input, r, w); !success { + return + } + + // check the validity + if input.Source != is.O.NewSource || input.SecretKey != is.O.NewSecretKey { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "invalid consumer credential"}, nil) + return + } + + ctx := context.WithValue(r.Context(), e.SyncKey{}, input) + next.ServeHTTP(w, r.WithContext(ctx)) + }) +} + +func OldGuardMW(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // check the data format + input := e.CredentialDto{} + if success := sc.CheckCredentialData(&input, r, w); !success { + return + } + + // check the validity + if input.Source != is.O.OldSource || input.SecretKey != is.O.OldSecretKey { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "invalid consumer credential"}, nil) + return + } + + ctx := context.WithValue(r.Context(), e.SyncKey{}, input) + next.ServeHTTP(w, r.WithContext(ctx)) + }) +} diff --git a/internal/interface/simgos-sync-handler/old/patient/handler.go b/internal/interface/simgos-sync-handler/old/patient/handler.go new file mode 100644 index 00000000..4c697fd4 --- /dev/null +++ b/internal/interface/simgos-sync-handler/old/patient/handler.go @@ -0,0 +1,48 @@ +package patient + +import ( + "net/http" + + p "simrs-vx/internal/domain/simgos-entities/m-pasien" + uo "simrs-vx/internal/use-case/simgos-sync-use-case/old/patient" + + rw "github.com/karincake/risoles" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := p.MPasienDto{} + if !rw.ValidateStructByIOR(w, r.Body, &dto) { + return + } + + // mapping m_patient to patient + patient := dto.ToPatient() + res, err := uo.Create(patient) + rw.DataResponse(w, res, err) + +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + + dto := p.MPasienDto{} + if !rw.ValidateStructByIOR(w, r.Body, &dto) { + return + } + patient := dto.ToPatient() + res, err := uo.Update(patient) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { + dto := p.MPasienDto{} + if !rw.ValidateStructByIOR(w, r.Body, &dto) { + return + } + patient := dto.ToPatient() + res, err := uo.Delete(patient) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/simgos-sync-handler/simgos-sync-handler.go b/internal/interface/simgos-sync-handler/simgos-sync-handler.go index 5d52d40b..a47b38d4 100644 --- a/internal/interface/simgos-sync-handler/simgos-sync-handler.go +++ b/internal/interface/simgos-sync-handler/simgos-sync-handler.go @@ -6,6 +6,7 @@ import ( /******************** infra ********************/ gs "simrs-vx/internal/infra/gorm-setting" simgosdb "simrs-vx/internal/infra/simgos-db" + sync "simrs-vx/internal/infra/sync-cfg" /******************** pkg ********************/ cmw "simrs-vx/pkg/cors-manager-mw" @@ -24,9 +25,14 @@ import ( "simrs-vx/internal/interface/simgos-sync-handler/new/encounter" "simrs-vx/internal/interface/simgos-sync-handler/new/installation" "simrs-vx/internal/interface/simgos-sync-handler/new/patient" + "simrs-vx/internal/interface/simgos-sync-handler/new/soapi" "simrs-vx/internal/interface/simgos-sync-handler/new/specialist" "simrs-vx/internal/interface/simgos-sync-handler/new/subspecialist" "simrs-vx/internal/interface/simgos-sync-handler/new/unit" + + oldpatient "simrs-vx/internal/interface/simgos-sync-handler/old/patient" + + oauth "simrs-vx/internal/interface/simgos-sync-handler/old/authentication" // just a reminder, an openauth ) func SetRoutes() http.Handler { @@ -34,6 +40,7 @@ func SetRoutes() http.Handler { a.RegisterExtCall(gs.Adjust) a.RegisterExtCall(zlc.Adjust) a.RegisterExtCall(lh.Populate) + a.RegisterExtCall(sync.SetConfig) a.RegisterExtCall(simgosdb.SetInstance) r := http.NewServeMux() @@ -67,9 +74,14 @@ func SetRoutes() http.Handler { "PATCH /{id}/approve-switch-unit": encounter.O.ApproveSwitchUnit, "PATCH /{id}/cancel-switch-unit": encounter.O.CancelSwitchUnit, }) + hc.SyncCrud(r, prefixnew+"/v1/soapi", soapi.O) /******************** SvcToNew ******************/ - //prefixold := "/old-to-new" - + prefixold := "/old-to-new" + hk.GroupRoutes(prefixold+"/v1/patient", r, oauth.OldGuardMW, hk.MapHandlerFunc{ + "POST /": oldpatient.O.Create, + "PATCH /{id}": oldpatient.O.Update, + "DELETE /{id}": oldpatient.O.Delete, + }) // FINISH THIS return cmw.SetCors(handlerlogger.SetLog(r)) } diff --git a/internal/lib/auth/tycovar.go b/internal/lib/auth/tycovar.go index 117d0c73..0ce3b0fc 100644 --- a/internal/lib/auth/tycovar.go +++ b/internal/lib/auth/tycovar.go @@ -22,6 +22,7 @@ type AuthInfo struct { Pharmachist_Code *string Intern_Position_Code *string Roles []string + Sync bool // User_DivisionPositions []DivisionPosition } diff --git a/internal/lib/sync-credential/helper.go b/internal/lib/sync-credential/helper.go new file mode 100644 index 00000000..e6c5952f --- /dev/null +++ b/internal/lib/sync-credential/helper.go @@ -0,0 +1,23 @@ +package authentication + +import ( + "net/http" + + d "github.com/karincake/dodol" + rw "github.com/karincake/risoles" + sr "github.com/karincake/serabi" + + e "simrs-vx/internal/domain/sync-entities/authentication" +) + +func CheckCredentialData(input *e.CredentialDto, r *http.Request, w http.ResponseWriter) bool { + input.Source = r.Header.Get("X-Sync-Source") + input.SecretKey = r.Header.Get("X-Sync-SecretKey") + input.UserName = r.Header.Get("X-Sync-UserName") + if err := sr.Validate(input); err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil) + return false + } + return true + +} diff --git a/internal/use-case/main-use-case/authentication/case.go b/internal/use-case/main-use-case/authentication/case.go index db83d315..04a88c9b 100644 --- a/internal/use-case/main-use-case/authentication/case.go +++ b/internal/use-case/main-use-case/authentication/case.go @@ -179,6 +179,10 @@ func VerifyToken(r *http.Request, tokenType TokenType) (data *jwt.Token, errCode return token, "", "" } +func GetAuthInfoByUserName(userName string) (data *pa.AuthInfo, err error) { + return getAuthByUserName(userName) +} + func ExtractToken(r *http.Request, tokenType TokenType) (data *pa.AuthInfo, err error) { token, errCode, errDetail := VerifyToken(r, tokenType) if errCode != "" { diff --git a/internal/use-case/main-use-case/authentication/helper.go b/internal/use-case/main-use-case/authentication/helper.go index 7af3afa5..d8c54751 100644 --- a/internal/use-case/main-use-case/authentication/helper.go +++ b/internal/use-case/main-use-case/authentication/helper.go @@ -2,6 +2,7 @@ package authentication import ( "fmt" + pa "simrs-vx/internal/lib/auth" "strconv" "time" @@ -10,10 +11,13 @@ import ( dg "github.com/karincake/apem/db-gorm-pg" ms "github.com/karincake/apem/ms-redis" d "github.com/karincake/dodol" + gh "github.com/karincake/getuk" l "github.com/karincake/lepet" pl "simrs-vx/pkg/logger" + erg "simrs-vx/internal/domain/references/organization" + edp "simrs-vx/internal/domain/main-entities/division-position" ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/employee" @@ -26,7 +30,6 @@ import ( essp "simrs-vx/internal/domain/main-entities/subspecialist-position" eup "simrs-vx/internal/domain/main-entities/unit-position" eu "simrs-vx/internal/domain/main-entities/user" - erg "simrs-vx/internal/domain/references/organization" udp "simrs-vx/internal/use-case/main-use-case/division-position" uip "simrs-vx/internal/use-case/main-use-case/installation-position" @@ -334,3 +337,71 @@ func populateRoles(user *eu.User, input eu.LoginDto, atClaims jwt.MapClaims, out return nil } + +func getAuthByUserName(username string) (auth *pa.AuthInfo, err error) { + // get employee + emp := ee.Employee{} + if err = dg.I. + Joins(`JOIN "User" u ON u."Id" = "Employee"."User_Id"`). + Where(`u."Name" = ?`, username). + Scopes(gh.Preload("User")). + First(&emp).Error; err != nil { + return nil, err + } + + auth = &pa.AuthInfo{ + User_Id: *emp.User_Id, + User_Name: emp.User.Name, + User_ContractPosition_Code: string(emp.User.ContractPosition_Code), + Employee_Position_Code: strPtr(string(*emp.Position_Code)), + Employee_Id: &emp.Id, + Sync: true, + } + + // set map table + tableMap := map[erg.EmployeePositionCode]string{ + erg.EPCDoc: "Doctor", + erg.EPCNur: "Nurse", + erg.EPCMwi: "Midwife", + erg.EPCNut: "Nutritionist", + erg.EPCLab: "Laborant", + erg.EPCPha: "Pharmachist", + } + + table := tableMap[*emp.Position_Code] + if table == "" { + return + } + + type CodeResult struct { + Code string + } + var result CodeResult + + err = dg.I.Table(table). + Select("Code"). + Where("\"Employee_Id\" = ?", emp.Id). + First(&result).Error + if err != nil { + return nil, err + } + + // set map for code + setterMap := map[erg.EmployeePositionCode]func(string){ + erg.EPCDoc: func(v string) { auth.Doctor_Code = &v }, + erg.EPCNur: func(v string) { auth.Nurse_Code = &v }, + erg.EPCMwi: func(v string) { auth.Midwife_Code = &v }, + erg.EPCNut: func(v string) { auth.Nutritionist_Code = &v }, + erg.EPCLab: func(v string) { auth.Laborant_Code = &v }, + erg.EPCPha: func(v string) { auth.Pharmachist_Code = &v }, + } + + setter := setterMap[*emp.Position_Code] + setter(result.Code) + + return +} + +func strPtr(s string) *string { + return &s +} diff --git a/internal/use-case/main-use-case/chemo-protocol/helper.go b/internal/use-case/main-use-case/chemo-protocol/helper.go index 885e6fbb..66a63dcc 100644 --- a/internal/use-case/main-use-case/chemo-protocol/helper.go +++ b/internal/use-case/main-use-case/chemo-protocol/helper.go @@ -17,12 +17,9 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.ChemoProtocol) { inputSrc = &inputTemp.CreateDto } - data.Encounter_Id = inputSrc.Encounter_Id data.Patient_Weight = inputSrc.Patient_Weight data.Patient_Height = inputSrc.Patient_Height data.Diagnoses = inputSrc.Diagnoses - data.Duration = inputSrc.Duration - data.DurationUnit_Code = inputSrc.DurationUnit_Code data.StartDate = inputSrc.StartDate data.EndDate = inputSrc.EndDate } diff --git a/internal/use-case/main-use-case/division/middleware-runner.go b/internal/use-case/main-use-case/division/middleware-runner.go index 51c90d77..76e1c873 100644 --- a/internal/use-case/main-use-case/division/middleware-runner.go +++ b/internal/use-case/main-use-case/division/middleware-runner.go @@ -6,7 +6,7 @@ import ( "gorm.io/gorm" - sync "simrs-vx/internal/infra/sync-cfg" + sync "simrs-vx/internal/infra/sync-consumer-cfg" e "simrs-vx/internal/domain/main-entities/division" esync "simrs-vx/internal/domain/sync-entities/log" diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 07f055a8..62a7c992 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -94,7 +94,7 @@ func Create(input e.CreateDto) (*d.Data, error) { input.NewStatus, err = identifyPatientStatus(input) input.Adm_Employee_Id = input.AuthInfo.Employee_Id - mwRunner := newMiddlewareRunner(&event) + mwRunner := newMiddlewareRunner(&event, input.Sync) err = dg.I.Transaction(func(tx *gorm.DB) error { // create encounter @@ -124,7 +124,8 @@ func Create(input e.CreateDto) (*d.Data, error) { dataEncounter, err := ReadDetailData(e.ReadDetailDto{ Id: data.Id, - Includes: "Adm_Employee.User,Patient.Person.Relatives," + + Includes: "Adm_Employee.User,Adm_Employee.Person," + + "Patient.Person.Relatives," + "Patient.Person.VclaimMember,VclaimReference," + "Patient.Person.Contacts,Patient.Person.Addresses"}, &event, tx) @@ -158,7 +159,6 @@ func Create(input e.CreateDto) (*d.Data, error) { } func ReadList(input e.ReadListDto) (*d.Data, error) { - var data *e.Encounter var dataList []e.Encounter var metaList *e.MetaDto var err error @@ -172,23 +172,9 @@ func ReadList(input e.ReadListDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readList") err = dg.I.Transaction(func(tx *gorm.DB) error { - mwRunner := newMiddlewareRunner(&event) - mwRunner.setMwType(pu.MWTPre) - // Run pre-middleware - if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { - return err - } - if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { return err } - - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { - return err - } - return nil }) @@ -223,23 +209,9 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readDetail") err = dg.I.Transaction(func(tx *gorm.DB) error { - mwRunner := newMiddlewareRunner(&event) - mwRunner.setMwType(pu.MWTPre) - // Run pre-middleware - if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { - return err - } - if data, err = ReadDetailData(input, &event, tx); err != nil { return err } - - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { - return err - } - return nil }) @@ -277,7 +249,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } input.Adm_Employee_Id = input.AuthInfo.Employee_Id - mwRunner := newMiddlewareRunner(&event) + mwRunner := newMiddlewareRunner(&event, input.Sync) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -352,7 +324,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { return nil, err } - mwRunner := newMiddlewareRunner(&event) + mwRunner := newMiddlewareRunner(&event, input.Sync) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -436,7 +408,7 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) { return nil, err } - mwRunner := newMiddlewareRunner(&event) + mwRunner := newMiddlewareRunner(&event, input.Sync) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -554,14 +526,13 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "update") - // TODO: Only "supervisi pendaftaran" could cancel encounter roleAllowed := []string{string(erg.EPCReg), string(erg.EPCNur), string(erg.EPCDoc)} err = validateAuth(input.AuthInfo, roleAllowed, "update-status-encounter", &event) if err != nil { return nil, err } - mwRunner := newMiddlewareRunner(&event) + mwRunner := newMiddlewareRunner(&event, input.Sync) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -604,9 +575,14 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) { return err } - if input.StatusCode == erc.DSCProcess || input.StatusCode == erc.DSCCancel { - data.Status_Code = input.StatusCode + // get data encounter + if data, err = ReadDetailData(e.ReadDetailDto{ + Id: input.Id, + Includes: "Adm_Employee.User"}, &event, tx); err != nil { + return err + } + if input.StatusCode == erc.DSCProcess || input.StatusCode == erc.DSCCancel { mwRunner.setMwType(pu.MWTPre) // Run pre-middleware if err := mwRunner.RunUpdateStatusMiddleware(updatestatusEncounter, data); err != nil { @@ -664,7 +640,7 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { input.StartedAt = &now } - mwRunner := newMiddlewareRunner(&event) + mwRunner := newMiddlewareRunner(&event, input.Sync) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -767,7 +743,7 @@ func RequestSwitchUnit(input e.SwitchUnitDto) (*d.Data, error) { } input.Src_Nurse_Code = input.AuthInfo.Nurse_Code - mwRunner := newMiddlewareRunner(&event) + mwRunner := newMiddlewareRunner(&event, input.Sync) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -795,7 +771,7 @@ func RequestSwitchUnit(input e.SwitchUnitDto) (*d.Data, error) { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "missing-soapi", - Detail: fmt.Sprintf("Missing soapi from latest responsible doctor"), + Detail: "Missing soapi from latest responsible doctor", } return pl.SetLogError(&event, input) } @@ -861,7 +837,7 @@ func ApproveSwitchUnit(input e.ApproveCancelUnitDto) (*d.Data, error) { return nil, err } - mwRunner := newMiddlewareRunner(&event) + mwRunner := newMiddlewareRunner(&event, input.Sync) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -905,7 +881,7 @@ func ApproveSwitchUnit(input e.ApproveCancelUnitDto) (*d.Data, error) { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "missing-soapi", - Detail: fmt.Sprintf("Missing soapi from latest responsible doctor"), + Detail: "Missing soapi from latest responsible doctor", } return pl.SetLogError(&event, input) } @@ -976,7 +952,7 @@ func CancelSwitchUnit(input e.ApproveCancelUnitDto) (*d.Data, error) { return nil, err } - mwRunner := newMiddlewareRunner(&event) + mwRunner := newMiddlewareRunner(&event, input.Sync) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index b6f24a0b..f606eb7c 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -65,44 +65,71 @@ import ( us "simrs-vx/internal/use-case/main-use-case/soapi" ) -func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Encounter) { - var inputSrc *e.CreateDto - if inputT, ok := any(input).(*e.CreateDto); ok { - inputSrc = inputT - data.Status_Code = erc.DSCNew - } else { - inputTemp := any(input).(*e.UpdateDto) - inputSrc = &inputTemp.CreateDto - } - - data.Patient_Id = inputSrc.Patient_Id - data.RegisteredAt = inputSrc.RegisteredAt - data.Class_Code = inputSrc.Class_Code - data.Unit_Code = inputSrc.Unit_Code - data.Specialist_Code = inputSrc.Specialist_Code - data.Subspecialist_Code = inputSrc.Subspecialist_Code - data.VisitDate = inputSrc.VisitDate - data.PaymentMethod_Code = inputSrc.PaymentMethod_Code - data.InsuranceCompany_Code = inputSrc.InsuranceCompany_Code - data.Member_Number = inputSrc.Member_Number - data.Ref_Number = inputSrc.Ref_Number - data.Trx_Number = inputSrc.Trx_Number - data.Appointment_Doctor_Code = inputSrc.Appointment_Doctor_Code - data.Adm_Employee_Id = inputSrc.Adm_Employee_Id - data.Responsible_Doctor_Code = inputSrc.Responsible_Doctor_Code - data.RefSource_Name = inputSrc.RefSource_Name - data.Appointment_Id = inputSrc.Appointment_Id - data.RefType_Code = &inputSrc.RefTypeCode - data.NewStatus = inputSrc.NewStatus +func setDataCreate(input *e.CreateDto, data *e.Encounter) { + data.Patient_Id = input.Patient_Id + data.RegisteredAt = input.RegisteredAt + data.Class_Code = input.Class_Code + data.Unit_Code = input.Unit_Code + data.Specialist_Code = input.Specialist_Code + data.Subspecialist_Code = input.Subspecialist_Code + data.VisitDate = input.VisitDate + data.PaymentMethod_Code = input.PaymentMethod_Code + data.InsuranceCompany_Code = input.InsuranceCompany_Code + data.Member_Number = input.Member_Number + data.RefType_Code = &input.RefTypeCode + data.Ref_Number = input.Ref_Number + data.Trx_Number = input.Trx_Number + data.Appointment_Doctor_Code = input.Appointment_Doctor_Code + data.Adm_Employee_Id = input.Adm_Employee_Id + data.RefSource_Name = input.RefSource_Name + data.Appointment_Id = input.Appointment_Id + data.Status_Code = erc.DSCNew + data.NewStatus = input.NewStatus } func setDataUpdate(src e.UpdateDto, dst *e.Encounter) { - dst.Appointment_Doctor_Code = src.Appointment_Doctor_Code - dst.Responsible_Doctor_Code = src.Responsible_Doctor_Code dst.Unit_Code = src.Unit_Code dst.Specialist_Code = src.Specialist_Code dst.Subspecialist_Code = src.Subspecialist_Code dst.VisitDate = src.VisitDate + dst.Appointment_Doctor_Code = src.Appointment_Doctor_Code + dst.Adm_Employee_Id = src.Adm_Employee_Id + dst.Appointment_Id = src.Appointment_Id + dst.RefSource_Name = src.RefSource_Name + dst.Trx_Number = src.Trx_Number + dst.Ref_Number = src.Ref_Number + dst.Member_Number = src.Member_Number +} + +func setDataUpdateFromSource(input *e.UpdateDto, data *e.Encounter) { + data.Patient_Id = input.Patient_Id + data.RegisteredAt = input.RegisteredAt + data.Unit_Code = input.Unit_Code + data.Specialist_Code = input.Specialist_Code + data.Subspecialist_Code = input.Subspecialist_Code + data.VisitDate = input.VisitDate + data.StartedAt = input.StartedAt + data.FinishedAt = input.FinishedAt + data.PaymentMethod_Code = input.PaymentMethod_Code + data.InsuranceCompany_Code = input.InsuranceCompany_Code + data.Member_Number = input.Member_Number + data.RefType_Code = &input.RefTypeCode + data.Ref_Number = input.Ref_Number + data.Trx_Number = input.Trx_Number + data.Appointment_Doctor_Code = input.Appointment_Doctor_Code + data.Adm_Employee_Id = input.Adm_Employee_Id + data.Responsible_Doctor_Code = input.Responsible_Doctor_Code + data.Discharge_Method_Code = input.Discharge_Method_Code + data.RefSource_Name = input.RefSource_Name + data.Appointment_Id = input.Appointment_Id + data.EarlyEducation = input.EarlyEducation + data.MedicalDischargeEducation = input.MedicalDischargeEducation + data.AdmDischargeEducation = input.AdmDischargeEducation + data.DischargeReason = input.DischargeReason + data.Status_Code = input.Status_Code + data.Discharge_Date = input.Discharge_Date + data.NewStatus = input.NewStatus + data.Responsible_Nurse_Code = input.Responsible_Nurse_Code } func setDataDischarge(src e.DischargeDto, dst *e.Encounter) { @@ -610,7 +637,7 @@ func getSoapiEncounterAdm(enc e.Encounter, event *pl.Event) (dataSoapi []es.Crea event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "missing-soapi", - Detail: fmt.Sprintf("Missing required Soapi types"), + Detail: "Missing required Soapi types", } return nil, pl.SetLogError(event, enc) } diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index a9a5a307..3a2e424a 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -25,7 +25,7 @@ func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Encount pl.SetLogInfo(event, nil, "started", "DBCreate") data := e.Encounter{} - setData(&input, &data) + setDataCreate(&input, &data) var tx *gorm.DB if len(dbx) > 0 { @@ -122,7 +122,12 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e func UpdateData(input e.UpdateDto, data *e.Encounter, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, data, "started", "DBUpdate") - setDataUpdate(input, data) + + if input.Sync { + setDataUpdateFromSource(&input, data) + } else { + setDataUpdate(input, data) + } var tx *gorm.DB if len(dbx) > 0 { @@ -229,7 +234,10 @@ func UpdateStatusData(input e.UpdateStatusDto, event *pl.Event, dbx ...*gorm.DB) if err := tx.Model(&e.Encounter{}). Where("\"Id\" = ?", input.Id). - Update("Status_Code", input.StatusCode).Error; err != nil { + Updates(map[string]interface{}{ + "Status_Code": input.StatusCode, + "Adm_Employee_Id": input.Employee_Id, + }).Error; err != nil { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "update-fail", diff --git a/internal/use-case/main-use-case/encounter/middleware-runner.go b/internal/use-case/main-use-case/encounter/middleware-runner.go index 59bcfd9d..da62fdb6 100644 --- a/internal/use-case/main-use-case/encounter/middleware-runner.go +++ b/internal/use-case/main-use-case/encounter/middleware-runner.go @@ -6,7 +6,7 @@ import ( "gorm.io/gorm" - sync "simrs-vx/internal/infra/sync-cfg" + sync "simrs-vx/internal/infra/sync-consumer-cfg" e "simrs-vx/internal/domain/main-entities/encounter" esync "simrs-vx/internal/domain/sync-entities/log" @@ -20,10 +20,15 @@ type middlewareRunner struct { } // NewMiddlewareExecutor creates a new middleware executor -func newMiddlewareRunner(event *pl.Event) *middlewareRunner { +func newMiddlewareRunner(event *pl.Event, syncFromOldSource bool) *middlewareRunner { + activateSync := sync.O.Enable + if syncFromOldSource { + activateSync = false + } + return &middlewareRunner{ Event: event, - SyncOn: sync.O.Enable, + SyncOn: activateSync, } } diff --git a/internal/use-case/main-use-case/installation/middleware-runner.go b/internal/use-case/main-use-case/installation/middleware-runner.go index b85e3236..b2ff8cb4 100644 --- a/internal/use-case/main-use-case/installation/middleware-runner.go +++ b/internal/use-case/main-use-case/installation/middleware-runner.go @@ -6,7 +6,7 @@ import ( "gorm.io/gorm" - sync "simrs-vx/internal/infra/sync-cfg" + sync "simrs-vx/internal/infra/sync-consumer-cfg" e "simrs-vx/internal/domain/main-entities/installation" esync "simrs-vx/internal/domain/sync-entities/log" diff --git a/internal/use-case/main-use-case/patient/case.go b/internal/use-case/main-use-case/patient/case.go index 24aa4394..7362bf7a 100644 --- a/internal/use-case/main-use-case/patient/case.go +++ b/internal/use-case/main-use-case/patient/case.go @@ -37,7 +37,7 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - mwRunner := newMiddlewareRunner(&event) + mwRunner := newMiddlewareRunner(&event, input.Sync) // check if user has employee position if !input.AuthInfo.HasEmployeePosition() { @@ -143,7 +143,6 @@ func Create(input e.CreateDto) (*d.Data, error) { } func ReadList(input e.ReadListDto) (*d.Data, error) { - var data *e.Patient var dataList []e.Patient var metaList *e.MetaDto var err error @@ -157,23 +156,9 @@ func ReadList(input e.ReadListDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readList") err = dg.I.Transaction(func(tx *gorm.DB) error { - mwRunner := newMiddlewareRunner(&event) - mwRunner.setMwType(pu.MWTPre) - // Run pre-middleware - if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { - return err - } - if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { return err } - - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { - return err - } - return nil }) @@ -208,23 +193,9 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readDetail") err = dg.I.Transaction(func(tx *gorm.DB) error { - mwRunner := newMiddlewareRunner(&event) - mwRunner.setMwType(pu.MWTPre) - // Run pre-middleware - if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { - return err - } - if data, err = ReadDetailData(input, &event, tx); err != nil { return err } - - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { - return err - } - return nil }) @@ -254,7 +225,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "update") - mwRunner := newMiddlewareRunner(&event) + mwRunner := newMiddlewareRunner(&event, input.Sync) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -343,7 +314,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "delete") - mwRunner := newMiddlewareRunner(&event) + mwRunner := newMiddlewareRunner(&event, input.Sync) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") diff --git a/internal/use-case/main-use-case/patient/middleware-runner.go b/internal/use-case/main-use-case/patient/middleware-runner.go index 1ea1623d..0cc10e27 100644 --- a/internal/use-case/main-use-case/patient/middleware-runner.go +++ b/internal/use-case/main-use-case/patient/middleware-runner.go @@ -6,7 +6,7 @@ import ( "gorm.io/gorm" - sync "simrs-vx/internal/infra/sync-cfg" + sync "simrs-vx/internal/infra/sync-consumer-cfg" e "simrs-vx/internal/domain/main-entities/patient" esync "simrs-vx/internal/domain/sync-entities/log" @@ -20,10 +20,15 @@ type middlewareRunner struct { } // NewMiddlewareExecutor creates a new middleware executor -func newMiddlewareRunner(event *pl.Event) *middlewareRunner { +func newMiddlewareRunner(event *pl.Event, syncFromOldSource bool) *middlewareRunner { + activateSync := sync.O.Enable + if syncFromOldSource { + activateSync = false + } + return &middlewareRunner{ Event: event, - SyncOn: sync.O.Enable, + SyncOn: activateSync, } } diff --git a/internal/use-case/main-use-case/soapi/case.go b/internal/use-case/main-use-case/soapi/case.go index 3dc8e195..ebf1c7d8 100644 --- a/internal/use-case/main-use-case/soapi/case.go +++ b/internal/use-case/main-use-case/soapi/case.go @@ -2,6 +2,8 @@ package soapi import ( "errors" + erc "simrs-vx/internal/domain/references/common" + esync "simrs-vx/internal/domain/sync-entities/log" "strconv" e "simrs-vx/internal/domain/main-entities/soapi" @@ -27,53 +29,50 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") + mwRunner := newMiddlewareRunner(&event, input.Sync) + + if !input.AuthInfo.IsDoctor() && !input.AuthInfo.IsNurse() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "auth-forbidden", + Detail: "user position is not allowed", + Raw: errors.New("authentication failed"), + } + return nil, pl.SetLogError(&event, input) + } err := dg.I.Transaction(func(tx *gorm.DB) error { - mwRunner := newMiddlewareRunner(&event, tx) - mwRunner.setMwType(pu.MWTPre) - // Run pre-middleware - if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { - return err - } - - if !input.AuthInfo.IsDoctor() && !input.AuthInfo.IsNurse() { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "auth-forbidden", - Detail: "user position is not allowed", - Raw: errors.New("authentication failed"), - } - return pl.SetLogError(&event, input) - } - - if input.AuthInfo.Employee_Id != nil { - v := uint(*input.AuthInfo.Employee_Id) - input.Employee_Id = &v - } else { - input.Employee_Id = nil - } - if resData, err := CreateData(input, &event, tx); err != nil { return err } else { data = *resData } - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + // get detail for sync + soapiData, err := ReadDetailData(e.ReadDetailDto{ + Id: data.Id, + Includes: "Encounter,Employee.User"}, &event, tx) + if err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err = mwRunner.ExecuteIfSyncOn(func() error { + return mwRunner.RunCreateMiddleware(createPreMw, soapiData) + }); err != nil { + return err + } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, erc.CCCreate, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.II{ "source": source, @@ -85,7 +84,6 @@ func Create(input e.CreateDto) (*d.Data, error) { } func ReadList(input e.ReadListDto) (*d.Data, error) { - var data *e.Soapi var dataList []e.Soapi var metaList *e.MetaDto var err error @@ -99,23 +97,9 @@ func ReadList(input e.ReadListDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readList") err = dg.I.Transaction(func(tx *gorm.DB) error { - mwRunner := newMiddlewareRunner(&event, tx) - mwRunner.setMwType(pu.MWTPre) - // Run pre-middleware - if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { - return err - } - if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { return err } - - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { - return err - } - return nil }) @@ -150,23 +134,9 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readDetail") err = dg.I.Transaction(func(tx *gorm.DB) error { - mwRunner := newMiddlewareRunner(&event, tx) - mwRunner.setMwType(pu.MWTPre) - // Run pre-middleware - if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { - return err - } - if data, err = ReadDetailData(input, &event, tx); err != nil { return err } - - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { - return err - } - return nil }) @@ -196,6 +166,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "update") + mwRunner := newMiddlewareRunner(&event, input.Sync) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -203,32 +174,35 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } - mwRunner := newMiddlewareRunner(&event, tx) - mwRunner.setMwType(pu.MWTPre) - // Run pre-middleware - if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { - return err - } - if err := UpdateData(input, data, &event, tx); err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") + // get detail for sync + soapiData, err := ReadDetailData(e.ReadDetailDto{ + Id: data.Id, + Includes: "Encounter,Employee"}, &event) + if err != nil { + return err + } - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err = mwRunner.ExecuteIfSyncOn(func() error { + return mwRunner.RunUpdateMiddleware(updatePreMw, soapiData) + }); err != nil { return err } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, erc.CCUpdate, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -252,6 +226,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "delete") + mwRunner := newMiddlewareRunner(&event, input.Sync) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -259,30 +234,27 @@ func Delete(input e.DeleteDto) (*d.Data, error) { return err } - mwRunner := newMiddlewareRunner(&event, tx) - mwRunner.setMwType(pu.MWTPre) - // Run pre-middleware - if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { - return err - } - if err := DeleteData(data, &event, tx); err != nil { return err } - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err = mwRunner.ExecuteIfSyncOn(func() error { + return mwRunner.RunDeleteMiddleware(deletePreMw, &input) + }); err != nil { return err } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, erc.CCDelete, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -293,3 +265,39 @@ func Delete(input e.DeleteDto) (*d.Data, error) { }, nil } + +func runLogMiddleware(err error, input any, method erc.CrudCode, mwRunner *middlewareRunner) error { + var errMsg string + inputLog := esync.SimxLogDto{ + Payload: input, + Method: method, + } + + if err != nil { + // Run log-middleware + errMsg = err.Error() + inputLog.ErrMessage = &errMsg + inputLog.IsSuccess = false + + // create log failed + if errMiddleware := mwRunner.ExecuteIfSyncOn(func() error { + return mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog) + }); errMiddleware != nil { + return errMiddleware + } + + return err + } + + // create log success + inputLog.IsSuccess = true + err = mwRunner.ExecuteIfSyncOn(func() error { + return mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog) + }) + + if err != nil { + return err + } + + return nil +} diff --git a/internal/use-case/main-use-case/soapi/helper.go b/internal/use-case/main-use-case/soapi/helper.go index ae396270..c42b95d0 100644 --- a/internal/use-case/main-use-case/soapi/helper.go +++ b/internal/use-case/main-use-case/soapi/helper.go @@ -18,7 +18,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Soapi) { } data.Encounter_Id = inputSrc.Encounter_Id - data.Employee_Id = inputSrc.Employee_Id + data.Employee_Id = inputSrc.AuthInfo.Employee_Id data.Time = inputSrc.Time data.TypeCode = inputSrc.TypeCode data.Value = inputSrc.Value diff --git a/internal/use-case/main-use-case/soapi/lib.go b/internal/use-case/main-use-case/soapi/lib.go index 57bb5d23..85e94800 100644 --- a/internal/use-case/main-use-case/soapi/lib.go +++ b/internal/use-case/main-use-case/soapi/lib.go @@ -81,7 +81,9 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e tx = dg.I } - if err := tx.First(&data, input.Id).Error; err != nil { + if err := tx. + Scopes(gh.Preload(input.Includes)). + First(&data, input.Id).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { return nil, processedErr } diff --git a/internal/use-case/main-use-case/soapi/middleware-runner.go b/internal/use-case/main-use-case/soapi/middleware-runner.go index a840a33a..fbe18503 100644 --- a/internal/use-case/main-use-case/soapi/middleware-runner.go +++ b/internal/use-case/main-use-case/soapi/middleware-runner.go @@ -2,6 +2,8 @@ package soapi import ( e "simrs-vx/internal/domain/main-entities/soapi" + esync "simrs-vx/internal/domain/sync-entities/log" + sync "simrs-vx/internal/infra/sync-consumer-cfg" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -12,24 +14,45 @@ type middlewareRunner struct { Event *pl.Event Tx *gorm.DB MwType pu.MWType + SyncOn bool } // NewMiddlewareExecutor creates a new middleware executor -func newMiddlewareRunner(event *pl.Event, tx *gorm.DB) *middlewareRunner { +func newMiddlewareRunner(event *pl.Event, syncFromOldSource bool) *middlewareRunner { + activateSync := sync.O.Enable + if syncFromOldSource { + activateSync = false + } + return &middlewareRunner{ - Event: event, - Tx: tx, + Event: event, + SyncOn: activateSync, } } // ExecuteCreateMiddleware executes create middleware -func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.Soapi) error { +func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.Soapi) error { for _, middleware := range middlewares { - logData := pu.GetLogData(input, data) + logData := pu.GetLogData(input, nil) pl.SetLogInfo(me.Event, logData, "started", middleware.Name) - if err := middleware.Func(input, data, me.Tx); err != nil { + if err := middleware.Func(input); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) RunCreateLogMiddleware(middlewares []createLogMw, input *esync.SimxLogDto) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, nil) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input); err != nil { return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) } @@ -68,13 +91,13 @@ func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, return nil } -func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Soapi) error { +func (me *middlewareRunner) RunUpdateMiddleware(middlewares []updateMw, input *e.Soapi) error { for _, middleware := range middlewares { - logData := pu.GetLogData(input, data) + logData := pu.GetLogData(input, nil) pl.SetLogInfo(me.Event, logData, "started", middleware.Name) - if err := middleware.Func(input, data, me.Tx); err != nil { + if err := middleware.Func(input); err != nil { return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) } @@ -83,13 +106,13 @@ func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, inpu return nil } -func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Soapi) error { +func (me *middlewareRunner) RunDeleteMiddleware(middlewares []deleteMw, input *e.DeleteDto) error { for _, middleware := range middlewares { - logData := pu.GetLogData(input, data) + logData := pu.GetLogData(input, nil) pl.SetLogInfo(me.Event, logData, "started", middleware.Name) - if err := middleware.Func(input, data, me.Tx); err != nil { + if err := middleware.Func(input); err != nil { return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) } @@ -101,3 +124,10 @@ func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, inpu func (me *middlewareRunner) setMwType(mwType pu.MWType) { me.MwType = mwType } + +func (me *middlewareRunner) ExecuteIfSyncOn(fn func() error) error { + if !me.SyncOn { + return nil + } + return fn() +} diff --git a/internal/use-case/main-use-case/soapi/middleware.go b/internal/use-case/main-use-case/soapi/middleware.go index f2fecda5..548d27fd 100644 --- a/internal/use-case/main-use-case/soapi/middleware.go +++ b/internal/use-case/main-use-case/soapi/middleware.go @@ -1,9 +1,17 @@ package soapi -// example of middleware -// func init() { -// createPreMw = append(createPreMw, -// CreateMw{Name: "modif-input", Func: pm.ModifInput}, -// CreateMw{Name: "check-data", Func: pm.CheckData}, -// ) -// } +import plugin "simrs-vx/internal/use-case/simgos-sync-plugin/new/soapi" + +func init() { + createPreMw = append(createPreMw, + createMw{Name: "sync-create-soapi", Func: plugin.Create}) + + createSimxLogMw = append(createSimxLogMw, + createLogMw{Name: "create-sync-log", Func: plugin.CreateLog}) + + updatePreMw = append(updatePreMw, + updateMw{Name: "sync-update-soapi", Func: plugin.Update}) + + deletePreMw = append(deletePreMw, + deleteMw{Name: "sync-delete-soapi", Func: plugin.Delete}) +} diff --git a/internal/use-case/main-use-case/soapi/tycovar.go b/internal/use-case/main-use-case/soapi/tycovar.go index 956193a4..aece45a5 100644 --- a/internal/use-case/main-use-case/soapi/tycovar.go +++ b/internal/use-case/main-use-case/soapi/tycovar.go @@ -12,11 +12,27 @@ import ( "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/soapi" + elog "simrs-vx/internal/domain/sync-entities/log" ) type createMw struct { Name string - Func func(input *e.CreateDto, data *e.Soapi, tx *gorm.DB) error + Func func(input *e.Soapi) error +} + +type createLogMw struct { + Name string + Func func(input *elog.SimxLogDto) error +} + +type updateMw struct { + Name string + Func func(input *e.Soapi) error +} + +type deleteMw struct { + Name string + Func func(input *e.DeleteDto) error } type readListMw struct { @@ -29,8 +45,8 @@ type readDetailMw struct { Func func(input *e.ReadDetailDto, data *e.Soapi, tx *gorm.DB) error } -type UpdateMw = readDetailMw -type DeleteMw = readDetailMw +type UpdateMw = updateMw +type DeleteMw = deleteMw var createPreMw []createMw // preprocess middleware var createPostMw []createMw // postprocess middleware @@ -38,7 +54,8 @@ var readListPreMw []readListMw // .. var readListPostMw []readListMw // .. var readDetailPreMw []readDetailMw var readDetailPostMw []readDetailMw -var updatePreMw []readDetailMw +var updatePreMw []updateMw var updatePostMw []readDetailMw -var deletePreMw []readDetailMw +var deletePreMw []deleteMw var deletePostMw []readDetailMw +var createSimxLogMw []createLogMw diff --git a/internal/use-case/main-use-case/specialist/middleware-runner.go b/internal/use-case/main-use-case/specialist/middleware-runner.go index 9a10d624..e2799b61 100644 --- a/internal/use-case/main-use-case/specialist/middleware-runner.go +++ b/internal/use-case/main-use-case/specialist/middleware-runner.go @@ -6,7 +6,7 @@ import ( "gorm.io/gorm" - sync "simrs-vx/internal/infra/sync-cfg" + sync "simrs-vx/internal/infra/sync-consumer-cfg" e "simrs-vx/internal/domain/main-entities/specialist" esync "simrs-vx/internal/domain/sync-entities/log" diff --git a/internal/use-case/main-use-case/subspecialist/middleware-runner.go b/internal/use-case/main-use-case/subspecialist/middleware-runner.go index ad1eba08..3e5c0dce 100644 --- a/internal/use-case/main-use-case/subspecialist/middleware-runner.go +++ b/internal/use-case/main-use-case/subspecialist/middleware-runner.go @@ -6,7 +6,7 @@ import ( "gorm.io/gorm" - sync "simrs-vx/internal/infra/sync-cfg" + sync "simrs-vx/internal/infra/sync-consumer-cfg" e "simrs-vx/internal/domain/main-entities/subspecialist" esync "simrs-vx/internal/domain/sync-entities/log" diff --git a/internal/use-case/main-use-case/unit/middleware-runner.go b/internal/use-case/main-use-case/unit/middleware-runner.go index 979548bc..a02bb9cf 100644 --- a/internal/use-case/main-use-case/unit/middleware-runner.go +++ b/internal/use-case/main-use-case/unit/middleware-runner.go @@ -6,7 +6,7 @@ import ( "gorm.io/gorm" - sync "simrs-vx/internal/infra/sync-cfg" + sync "simrs-vx/internal/infra/sync-consumer-cfg" e "simrs-vx/internal/domain/main-entities/unit" esync "simrs-vx/internal/domain/sync-entities/log" diff --git a/internal/use-case/simgos-sync-plugin/new/division/plugin.go b/internal/use-case/simgos-sync-plugin/new/division/plugin.go index 54c1403c..f4d6a34b 100644 --- a/internal/use-case/simgos-sync-plugin/new/division/plugin.go +++ b/internal/use-case/simgos-sync-plugin/new/division/plugin.go @@ -1,167 +1,37 @@ package division import ( - "bytes" - "encoding/json" "fmt" - "io" - "net/http" + helper "simrs-vx/internal/use-case/simgos-sync-plugin/new" - sync "simrs-vx/internal/infra/sync-cfg" + sync "simrs-vx/internal/infra/sync-consumer-cfg" e "simrs-vx/internal/domain/main-entities/division" elog "simrs-vx/internal/domain/sync-entities/log" - - d "github.com/karincake/dodol" ) func Create(input *e.CreateDto) error { - endpoint := getPrefixEndpoint() - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("POST", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "POST", getPrefixEndpoint()) } func CreateLog(input *elog.SimxLogDto) error { prefixEndpoint := getPrefixEndpoint() endpoint := prefixEndpoint + "/log" - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("POST", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "POST", endpoint) } func Update(input *e.UpdateDto) error { prefixEndpoint := getPrefixEndpoint() endpoint := fmt.Sprintf("%s/%v", prefixEndpoint, *input.Id) - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("PATCH", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "PATCH", endpoint) } func Delete(input *e.DeleteDto) error { prefixEndpoint := getPrefixEndpoint() endpoint := fmt.Sprintf("%s/%v", prefixEndpoint, *input.Id) - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("DELETE", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "DELETE", endpoint) } func getPrefixEndpoint() string { - return fmt.Sprintf("%s%s/v1/division", sync.O.Host, sync.O.Prefix) + return fmt.Sprintf("%s%s/v1/division", sync.O.TargetHost, sync.O.Prefix) } diff --git a/internal/use-case/simgos-sync-plugin/new/encounter/plugin.go b/internal/use-case/simgos-sync-plugin/new/encounter/plugin.go index a6334fdb..2f5e2515 100644 --- a/internal/use-case/simgos-sync-plugin/new/encounter/plugin.go +++ b/internal/use-case/simgos-sync-plugin/new/encounter/plugin.go @@ -2,7 +2,7 @@ package encounter import ( "fmt" - sync "simrs-vx/internal/infra/sync-cfg" + sync "simrs-vx/internal/infra/sync-consumer-cfg" helper "simrs-vx/internal/use-case/simgos-sync-plugin/new" e "simrs-vx/internal/domain/main-entities/encounter" @@ -68,5 +68,5 @@ func CancelSwitchUnit(input *e.ApproveCancelUnitDto) error { } func getPrefixEndpoint() string { - return fmt.Sprintf("%s%s/v1/encounter", sync.O.Host, sync.O.Prefix) + return fmt.Sprintf("%s%s/v1/encounter", sync.O.TargetHost, sync.O.Prefix) } diff --git a/internal/use-case/simgos-sync-plugin/new/installation/plugin.go b/internal/use-case/simgos-sync-plugin/new/installation/plugin.go index f2495139..40f0c153 100644 --- a/internal/use-case/simgos-sync-plugin/new/installation/plugin.go +++ b/internal/use-case/simgos-sync-plugin/new/installation/plugin.go @@ -1,167 +1,37 @@ package installation import ( - "bytes" - "encoding/json" "fmt" - "io" - "net/http" - sync "simrs-vx/internal/infra/sync-cfg" + sync "simrs-vx/internal/infra/sync-consumer-cfg" + helper "simrs-vx/internal/use-case/simgos-sync-plugin/new" e "simrs-vx/internal/domain/main-entities/installation" elog "simrs-vx/internal/domain/sync-entities/log" - - d "github.com/karincake/dodol" ) func Create(input *e.CreateDto) error { - endpoint := getPrefixEndpoint() - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("POST", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "POST", getPrefixEndpoint()) } func CreateLog(input *elog.SimxLogDto) error { prefixEndpoint := getPrefixEndpoint() endpoint := prefixEndpoint + "/log" - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("POST", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "POST", endpoint) } func Update(input *e.UpdateDto) error { prefixEndpoint := getPrefixEndpoint() endpoint := fmt.Sprintf("%s/%v", prefixEndpoint, *input.Id) - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("PATCH", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "PATCH", endpoint) } func Delete(input *e.DeleteDto) error { prefixEndpoint := getPrefixEndpoint() endpoint := fmt.Sprintf("%s/%v", prefixEndpoint, *input.Id) - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("DELETE", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "DELETE", endpoint) } func getPrefixEndpoint() string { - return fmt.Sprintf("%s%s/v1/installation", sync.O.Host, sync.O.Prefix) + return fmt.Sprintf("%s%s/v1/installation", sync.O.TargetHost, sync.O.Prefix) } diff --git a/internal/use-case/simgos-sync-plugin/new/patient/plugin.go b/internal/use-case/simgos-sync-plugin/new/patient/plugin.go index 309e1d18..7678da47 100644 --- a/internal/use-case/simgos-sync-plugin/new/patient/plugin.go +++ b/internal/use-case/simgos-sync-plugin/new/patient/plugin.go @@ -1,165 +1,40 @@ package patient import ( - "bytes" "encoding/json" "fmt" "io" "net/http" + helper "simrs-vx/internal/use-case/simgos-sync-plugin/new" d "github.com/karincake/dodol" - sync "simrs-vx/internal/infra/sync-cfg" + sync "simrs-vx/internal/infra/sync-consumer-cfg" e "simrs-vx/internal/domain/main-entities/patient" elog "simrs-vx/internal/domain/sync-entities/log" ) func Create(input *e.Patient) error { - endpoint := getPrefixEndpoint() - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("POST", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "POST", getPrefixEndpoint()) } func CreateLog(input *elog.SimxLogDto) error { prefixEndpoint := getPrefixEndpoint() endpoint := prefixEndpoint + "/log" - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("POST", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "POST", endpoint) } func Update(input *e.Patient) error { prefixEndpoint := getPrefixEndpoint() endpoint := fmt.Sprintf("%s/%v", prefixEndpoint, input.Id) - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("PATCH", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "PATCH", endpoint) } func Delete(input *e.DeleteDto) error { prefixEndpoint := getPrefixEndpoint() endpoint := fmt.Sprintf("%s/%v", prefixEndpoint, input.Id) - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("DELETE", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "DELETE", endpoint) } func GenerateNomrPatient() (*string, error) { @@ -203,5 +78,5 @@ func GenerateNomrPatient() (*string, error) { } func getPrefixEndpoint() string { - return fmt.Sprintf("%s%s/v1/patient", sync.O.Host, sync.O.Prefix) + return fmt.Sprintf("%s%s/v1/patient", sync.O.TargetHost, sync.O.Prefix) } diff --git a/internal/use-case/simgos-sync-plugin/new/soapi/plugin.go b/internal/use-case/simgos-sync-plugin/new/soapi/plugin.go new file mode 100644 index 00000000..20fabfac --- /dev/null +++ b/internal/use-case/simgos-sync-plugin/new/soapi/plugin.go @@ -0,0 +1,36 @@ +package soapi + +import ( + "fmt" + sync "simrs-vx/internal/infra/sync-consumer-cfg" + helper "simrs-vx/internal/use-case/simgos-sync-plugin/new" + + e "simrs-vx/internal/domain/main-entities/soapi" + elog "simrs-vx/internal/domain/sync-entities/log" +) + +func Create(input *e.Soapi) error { + return helper.DoJsonRequest(input, "POST", getPrefixEndpoint()) +} + +func CreateLog(input *elog.SimxLogDto) error { + prefixEndpoint := getPrefixEndpoint() + endpoint := prefixEndpoint + "/log" + return helper.DoJsonRequest(input, "POST", endpoint) +} + +func Update(input *e.Soapi) error { + prefixEndpoint := getPrefixEndpoint() + endpoint := fmt.Sprintf("%s/%v", prefixEndpoint, input.Id) + return helper.DoJsonRequest(input, "PATCH", endpoint) +} + +func Delete(input *e.DeleteDto) error { + prefixEndpoint := getPrefixEndpoint() + endpoint := fmt.Sprintf("%s/%v", prefixEndpoint, input.Id) + return helper.DoJsonRequest(input, "DELETE", endpoint) +} + +func getPrefixEndpoint() string { + return fmt.Sprintf("%s%s/v1/soapi", sync.O.TargetHost, sync.O.Prefix) +} diff --git a/internal/use-case/simgos-sync-plugin/new/specialist/plugin.go b/internal/use-case/simgos-sync-plugin/new/specialist/plugin.go index 892d7a17..29da9d0a 100644 --- a/internal/use-case/simgos-sync-plugin/new/specialist/plugin.go +++ b/internal/use-case/simgos-sync-plugin/new/specialist/plugin.go @@ -1,167 +1,37 @@ package specialist import ( - "bytes" - "encoding/json" "fmt" - "io" - "net/http" + helper "simrs-vx/internal/use-case/simgos-sync-plugin/new" - sync "simrs-vx/internal/infra/sync-cfg" + sync "simrs-vx/internal/infra/sync-consumer-cfg" e "simrs-vx/internal/domain/main-entities/specialist" elog "simrs-vx/internal/domain/sync-entities/log" - - d "github.com/karincake/dodol" ) func Create(input *e.CreateDto) error { - endpoint := getPrefixEndpoint() - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("POST", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "POST", getPrefixEndpoint()) } func CreateLog(input *elog.SimxLogDto) error { prefixEndpoint := getPrefixEndpoint() endpoint := prefixEndpoint + "/log" - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("POST", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "POST", endpoint) } func Update(input *e.UpdateDto) error { prefixEndpoint := getPrefixEndpoint() endpoint := fmt.Sprintf("%s/%v", prefixEndpoint, *input.Id) - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("PATCH", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "PATCH", endpoint) } func Delete(input *e.DeleteDto) error { prefixEndpoint := getPrefixEndpoint() endpoint := fmt.Sprintf("%s/%v", prefixEndpoint, *input.Id) - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("DELETE", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "DELETE", endpoint) } func getPrefixEndpoint() string { - return fmt.Sprintf("%s%s/v1/specialist", sync.O.Host, sync.O.Prefix) + return fmt.Sprintf("%s%s/v1/specialist", sync.O.TargetHost, sync.O.Prefix) } diff --git a/internal/use-case/simgos-sync-plugin/new/subspecialist/plugin.go b/internal/use-case/simgos-sync-plugin/new/subspecialist/plugin.go index 15d6f650..0167936c 100644 --- a/internal/use-case/simgos-sync-plugin/new/subspecialist/plugin.go +++ b/internal/use-case/simgos-sync-plugin/new/subspecialist/plugin.go @@ -1,167 +1,37 @@ package subspecialist import ( - "bytes" - "encoding/json" "fmt" - "io" - "net/http" + helper "simrs-vx/internal/use-case/simgos-sync-plugin/new" - sync "simrs-vx/internal/infra/sync-cfg" + sync "simrs-vx/internal/infra/sync-consumer-cfg" e "simrs-vx/internal/domain/main-entities/subspecialist" elog "simrs-vx/internal/domain/sync-entities/log" - - d "github.com/karincake/dodol" ) func Create(input *e.CreateDto) error { - endpoint := getPrefixEndpoint() - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("POST", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "POST", getPrefixEndpoint()) } func CreateLog(input *elog.SimxLogDto) error { prefixEndpoint := getPrefixEndpoint() endpoint := prefixEndpoint + "/log" - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("POST", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "POST", endpoint) } func Update(input *e.UpdateDto) error { prefixEndpoint := getPrefixEndpoint() endpoint := fmt.Sprintf("%s/%v", prefixEndpoint, *input.Id) - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("PATCH", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "PATCH", endpoint) } func Delete(input *e.DeleteDto) error { prefixEndpoint := getPrefixEndpoint() endpoint := fmt.Sprintf("%s/%v", prefixEndpoint, *input.Id) - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("DELETE", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "DELETE", endpoint) } func getPrefixEndpoint() string { - return fmt.Sprintf("%s%s/v1/subspecialist", sync.O.Host, sync.O.Prefix) + return fmt.Sprintf("%s%s/v1/subspecialist", sync.O.TargetHost, sync.O.Prefix) } diff --git a/internal/use-case/simgos-sync-plugin/new/unit/plugin.go b/internal/use-case/simgos-sync-plugin/new/unit/plugin.go index e854d898..f646f450 100644 --- a/internal/use-case/simgos-sync-plugin/new/unit/plugin.go +++ b/internal/use-case/simgos-sync-plugin/new/unit/plugin.go @@ -1,167 +1,37 @@ package unit import ( - "bytes" - "encoding/json" "fmt" - "io" - "net/http" + helper "simrs-vx/internal/use-case/simgos-sync-plugin/new" - sync "simrs-vx/internal/infra/sync-cfg" + sync "simrs-vx/internal/infra/sync-consumer-cfg" e "simrs-vx/internal/domain/main-entities/unit" elog "simrs-vx/internal/domain/sync-entities/log" - - d "github.com/karincake/dodol" ) func Create(input *e.CreateDto) error { - endpoint := getPrefixEndpoint() - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("POST", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "POST", getPrefixEndpoint()) } func CreateLog(input *elog.SimxLogDto) error { prefixEndpoint := getPrefixEndpoint() endpoint := prefixEndpoint + "/log" - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("POST", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "POST", endpoint) } func Update(input *e.UpdateDto) error { prefixEndpoint := getPrefixEndpoint() endpoint := fmt.Sprintf("%s/%v", prefixEndpoint, *input.Id) - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("PATCH", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "PATCH", endpoint) } func Delete(input *e.DeleteDto) error { prefixEndpoint := getPrefixEndpoint() endpoint := fmt.Sprintf("%s/%v", prefixEndpoint, *input.Id) - - jsonData, err := json.Marshal(input) - if err != nil { - return fmt.Errorf("failed to encode JSON: %w", err) - } - - req, err := http.NewRequest("DELETE", endpoint, bytes.NewReader(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - errors := d.FieldError{} - _ = json.Unmarshal(bodyBytes, &errors) - - return fmt.Errorf(errors.Message) - } - - return nil + return helper.DoJsonRequest(input, "DELETE", endpoint) } func getPrefixEndpoint() string { - return fmt.Sprintf("%s%s/v1/unit", sync.O.Host, sync.O.Prefix) + return fmt.Sprintf("%s%s/v1/unit", sync.O.TargetHost, sync.O.Prefix) } diff --git a/internal/use-case/simgos-sync-use-case/new/encounter/case.go b/internal/use-case/simgos-sync-use-case/new/encounter/case.go index 59e7e345..05c77915 100644 --- a/internal/use-case/simgos-sync-use-case/new/encounter/case.go +++ b/internal/use-case/simgos-sync-use-case/new/encounter/case.go @@ -1,6 +1,7 @@ package encounter import ( + erc "simrs-vx/internal/domain/references/common" pl "simrs-vx/pkg/logger" d "github.com/karincake/dodol" @@ -9,7 +10,6 @@ import ( db "simrs-vx/pkg/dualtrx-helper" e "simrs-vx/internal/domain/main-entities/encounter" - etp "simrs-vx/internal/domain/simgos-entities/t-pendaftaran" synce "simrs-vx/internal/domain/sync-entities/encounter" syncir "simrs-vx/internal/domain/sync-entities/internal-reference" elog "simrs-vx/internal/domain/sync-entities/log" @@ -21,9 +21,7 @@ const source = "encounter" func Create(input e.Encounter) (*d.Data, error) { var ( - sgData *etp.TPendaftaran syncLink *synce.EncounterLink - err error ) event := pl.Event{ @@ -34,21 +32,27 @@ func Create(input e.Encounter) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - err = db.WithDualTx(func(tx *db.Dualtx) error { - // STEP 1: Insert to simgos - sgData, err = CreateTPendaftaranData(input, &event, tx.Simgos) + err := db.WithDualTx(func(tx *db.Dualtx) error { + // STEP 1: Insert TPendaftaran + tPendaftaran, err := CreateTPendaftaranData(input, &event, tx.Simgos) if err != nil { return err } - // STEP 2: Insert to Link - syncLink, err = CreateLinkData(input.Id, sgData.Idxdaftar, &event, tx.Sync) + // STEP 2: Insert TRekammedik + err = CreateTRekammedik(input, tPendaftaran, &event, tx.Simgos) if err != nil { return err } // STEP 3: Update MPasien - err = updatePatientCaraBayar(*sgData, &event, tx.Simgos) + err = updatePatientCaraBayar(*tPendaftaran, &event, tx.Simgos) + if err != nil { + return err + } + + // STEP 4: Insert to Link + syncLink, err = CreateLinkData(input.Id, tPendaftaran.Idxdaftar, &event, tx.Sync) if err != nil { return err } @@ -131,6 +135,11 @@ func Update(input e.Encounter) (*d.Data, error) { tx := db.NewTx() err = tx.Simgos.Transaction(func(tx *gorm.DB) error { + // SET LOCAL + if err = tx.Exec(`SET LOCAL simx.sync_source = 'new'`).Error; err != nil { + return err + } + // Step 2: Update Simgos if err = UpdateTPendaftaranData(input, simgos, "update", &event, tx); err != nil { return err @@ -234,6 +243,11 @@ func CheckIn(input e.Encounter) (*d.Data, error) { tx := db.NewTx() err = tx.Simgos.Transaction(func(tx *gorm.DB) error { + // SET LOCAL + if err = tx.Exec(`SET LOCAL simx.sync_source = 'new'`).Error; err != nil { + return err + } + // Step 2: Update Simgos if err = UpdateTPendaftaranData(input, simgos, "check-in", &event, tx); err != nil { return err @@ -276,13 +290,16 @@ func CheckOut(input e.Encounter) (*d.Data, error) { tx := db.NewTx() err = tx.Simgos.Transaction(func(tx *gorm.DB) error { + // SET LOCAL + if err = tx.Exec(`SET LOCAL simx.sync_source = 'new'`).Error; err != nil { + return err + } + // Step 2: Update Simgos if err = UpdateTPendaftaranData(input, simgos, "check-out", &event, tx); err != nil { return err } - // TODO: Update TPemeriksaanHistory end_konsul if internal reference exist - return nil }) @@ -299,12 +316,12 @@ func CheckOut(input e.Encounter) (*d.Data, error) { func UpdateStatus(input e.Encounter) (*d.Data, error) { event := pl.Event{ - Feature: "Cancel", + Feature: "Update Status", Source: source, } // Start log - pl.SetLogInfo(&event, input, "started", "cancel") + pl.SetLogInfo(&event, input, "started", "update-status") // STEP 1: Get Link syncLink, err := ReadDetailLinkData(input.Id, &event) @@ -320,11 +337,23 @@ func UpdateStatus(input e.Encounter) (*d.Data, error) { tx := db.NewTx() err = tx.Simgos.Transaction(func(tx *gorm.DB) error { - // Step 2: Update Simgos + // SET LOCAL + if err = tx.Exec(`SET LOCAL simx.sync_source = 'new'`).Error; err != nil { + return err + } + + // Step 2: Update TPendaftaran if err = UpdateTPendaftaranData(input, simgos, "update-status", &event, tx); err != nil { return err } + // Step 3: Update TDiagnosadanterapi + if input.Status_Code == erc.DSCCancel { + if err = updateCancelTDiagnosaTherapy(simgos.Idxdaftar, input, &event, tx); err != nil { + return err + } + } + return nil }) @@ -425,6 +454,11 @@ func ApproveSwitchUnit(input e.ApproveCancelUnitDto) (*d.Data, error) { tx := db.NewTx() err = tx.Simgos.Transaction(func(tx *gorm.DB) error { + // SET LOCAL + if err = tx.Exec(`SET LOCAL simx.sync_source = 'new'`).Error; err != nil { + return err + } + // Step 3: Update TPemeriksaanHist if err := utph.UpdateSimgosData(input, tPemeriksaanHist, "approve", &event, tx); err != nil { return err @@ -467,6 +501,11 @@ func CancelSwitchUnit(input e.ApproveCancelUnitDto) (*d.Data, error) { tx := db.NewTx() err = tx.Simgos.Transaction(func(tx *gorm.DB) error { + // SET LOCAL + if err = tx.Exec(`SET LOCAL simx.sync_source = 'new'`).Error; err != nil { + return err + } + // Step 3: Update TPemeriksaanHist if err := utph.UpdateSimgosData(input, tPemeriksaanHist, "cancel", &event, tx); err != nil { return err diff --git a/internal/use-case/simgos-sync-use-case/new/encounter/helper.go b/internal/use-case/simgos-sync-use-case/new/encounter/helper.go index bbbc8687..97656afe 100644 --- a/internal/use-case/simgos-sync-use-case/new/encounter/helper.go +++ b/internal/use-case/simgos-sync-use-case/new/encounter/helper.go @@ -6,25 +6,29 @@ package encounter import ( "encoding/json" + pl "simrs-vx/pkg/logger" + "strconv" + + dg "github.com/karincake/apem/db-gorm-pg" + "gorm.io/gorm" + "gorm.io/gorm/clause" + erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" erp "simrs-vx/internal/domain/references/person" - pl "simrs-vx/pkg/logger" - "strconv" e "simrs-vx/internal/domain/main-entities/encounter" epa "simrs-vx/internal/domain/main-entities/person-address" epc "simrs-vx/internal/domain/main-entities/person-contact" epr "simrs-vx/internal/domain/main-entities/person-relative" + ep "simrs-vx/internal/domain/simgos-entities/m-pasien" - etph "simrs-vx/internal/domain/simgos-entities/t-pemeriksaan-hist" + etdt "simrs-vx/internal/domain/simgos-entities/t-diagnosadanterapi" etp "simrs-vx/internal/domain/simgos-entities/t-pendaftaran" + etrm "simrs-vx/internal/domain/simgos-entities/t-rekammedik" + esync "simrs-vx/internal/domain/sync-entities/encounter" esyncLog "simrs-vx/internal/domain/sync-entities/log" - - dg "github.com/karincake/apem/db-gorm-pg" - "gorm.io/gorm" - "gorm.io/gorm/clause" ) func setDataCreateTPendaftaran(input *e.Encounter) (data etp.TPendaftaran, err error) { @@ -188,34 +192,6 @@ func setDataCheckOut(input e.Encounter, data *etp.TPendaftaran) { return } -func setDataRequestSwitchUnit(input e.Encounter, data *etp.TPendaftaran) (hist []etph.TPemeriksaanHist) { - if enc := input.InternalReferences; enc != nil { - for i, ref := range *enc { - hist = append(hist, etph.TPemeriksaanHist{ - Idxdaftar: &data.Idxdaftar, - Kdpoly: stringtouint(*ref.Unit_Code), - DokterPengonsul: stringtouint(*ref.SrcDoctor_Code), - DokterPenerima: stringtouint(*ref.Doctor_Code), - StartKonsul: &now, - }) - - // set user konsul - if n := input.Responsible_Nurse; n != nil { - if emp := n.Employee; emp != nil { - if u := emp.User; u != nil { - hist[i].UserKonsul = &u.Name - } - } - } - - // setaktif - aktif := uint16(1) - hist[i].StAktif = &aktif - } - } - return -} - func setKdrujuk(input *ere.RefTypeCode, data *etp.TPendaftaran) { switch *input { case ere.RTCGov: @@ -363,12 +339,6 @@ func generateNoKunjung() (int, error) { return lastNumber + 1, nil } -func stringtouint(v string) *uint { - u, _ := strconv.Atoi(v) - point := uint(u) - return &point -} - func updatePatientCaraBayar(input etp.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, nil, "started", "DBUpdate") @@ -381,9 +351,7 @@ func updatePatientCaraBayar(input etp.TPendaftaran, event *pl.Event, dbx ...*gor if err := tx.Model(&ep.MPasien{}). Where("\"nomr\" = ?", input.Nomr). - Updates(map[string]interface{}{ - "kdcarabayar": input.Kdcarabayar, - }).Error; err != nil { + Update("kdcarabayar", input.Kdcarabayar).Error; err != nil { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "update-fail", @@ -417,3 +385,57 @@ func mapAddress(addresses *[]epa.PersonAddress, data *etp.TPendaftaran) { a := (*addresses)[0] data.PenanggungjawabAlamat = a.Address } + +func setDataTRekammedik(input e.Encounter, tdaftar *etp.TPendaftaran) (data etrm.TRekammedik) { + data.TglKirim = tdaftar.Tglreg + data.Idxdaftar = tdaftar.Idxdaftar + data.Kdpoly = tdaftar.Kdpoly + data.JamKirimRm = tdaftar.Tglreg + + if emp := input.Adm_Employee; emp != nil { + if p := emp.Person; p != nil { + data.Pengirim = p.Name + } + } + + return +} + +func updateCancelTDiagnosaTherapy(idxdaftar uint, enc e.Encounter, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, nil, "started", "DBUpdate") + + var ( + tx *gorm.DB + userBatal string + ) + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.IS["simrs"] + } + + if a := enc.Adm_Employee; a != nil { + if u := a.User; u != nil { + userBatal = u.Name + } + } + + if err := tx.Model(&etdt.TDiagnosaDanTerapi{}). + Where("idxdaftar = ?", idxdaftar). + Updates(map[string]interface{}{ + "status": "BATAL", + "user_batal": userBatal, + "tgl_batal": &now, + }).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "update-fail", + Detail: "Failed to update patient", + Raw: err, + } + return pl.SetLogError(event, idxdaftar) + } + + pl.SetLogInfo(event, idxdaftar, "complete") + return nil +} diff --git a/internal/use-case/simgos-sync-use-case/new/encounter/lib.go b/internal/use-case/simgos-sync-use-case/new/encounter/lib.go index 47d50802..95f86ede 100644 --- a/internal/use-case/simgos-sync-use-case/new/encounter/lib.go +++ b/internal/use-case/simgos-sync-use-case/new/encounter/lib.go @@ -1,7 +1,6 @@ package encounter import ( - etph "simrs-vx/internal/domain/simgos-entities/t-pemeriksaan-hist" plh "simrs-vx/pkg/lib-helper" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -138,25 +137,6 @@ func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*e return &data, nil } -func CreateBulkLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.EncounterLink, error) { - pl.SetLogInfo(event, nil, "started", "DBCreate") - data := setDataSimxLink(simxId, simgosId) - - var tx *gorm.DB - if len(dbx) > 0 { - tx = dbx[0] - } else { - tx = dg.I - } - - if err := tx.Create(&data).Error; err != nil { - return nil, plh.HandleCreateError(data, event, err) - } - - pl.SetLogInfo(event, nil, "complete") - return &data, nil -} - func ReadDetailLinkData(simxId uint, event *pl.Event) (*esync.EncounterLink, error) { pl.SetLogInfo(event, simxId, "started", "DBReadDetail") data := esync.EncounterLink{} @@ -218,10 +198,9 @@ func CreateLogData(input esynclog.SimxLogDto, event *pl.Event, dbx ...*gorm.DB) return nil } -func CreateBulkTPemeriksaanHistData(input e.Encounter, data *etp.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) (hist []etph.TPemeriksaanHist, err error) { +func CreateTRekammedik(input e.Encounter, tpendaftaran *etp.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, nil, "started", "DBCreate") - - hist = setDataRequestSwitchUnit(input, data) + data := setDataTRekammedik(input, tpendaftaran) var tx *gorm.DB if len(dbx) > 0 { @@ -230,32 +209,8 @@ func CreateBulkTPemeriksaanHistData(input e.Encounter, data *etp.TPendaftaran, e tx = dg.IS["simrs"] } - if err := tx.Create(&hist).Error; err != nil { - return nil, plh.HandleCreateError(input, event, err) - } - - pl.SetLogInfo(event, nil, "complete") - return hist, nil -} - -func UpdateTPemeriksaanHistData(input e.ApproveCancelUnitDto, data *etph.TPemeriksaanHist, event *pl.Event, dbx ...*gorm.DB) error { - pl.SetLogInfo(event, input, "started", "DBUpdateTPemeriksaanHist") - - var tx *gorm.DB - if len(dbx) > 0 { - tx = dbx[0] - } else { - tx = dg.IS["simrs"] - } - - if err := tx.Save(&data).Error; err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-update-fail", - Detail: "Database update failed", - Raw: err, - } - return pl.SetLogError(event, input) + if err := tx.Create(&data).Error; err != nil { + return plh.HandleCreateError(input, event, err) } pl.SetLogInfo(event, nil, "complete") diff --git a/internal/use-case/simgos-sync-use-case/new/patient/case.go b/internal/use-case/simgos-sync-use-case/new/patient/case.go index a147524c..03497eed 100644 --- a/internal/use-case/simgos-sync-use-case/new/patient/case.go +++ b/internal/use-case/simgos-sync-use-case/new/patient/case.go @@ -122,6 +122,11 @@ func Update(input e.Patient) (*d.Data, error) { tx := db.NewTx() err = tx.Simgos.Transaction(func(tx *gorm.DB) error { + // SET LOCAL + if err = tx.Exec(`SET LOCAL simx.sync_source = 'new'`).Error; err != nil { + return err + } + // Step 3: Update Simgos if err = UpdateSimgosData(input, patientData, &event, tx); err != nil { return err diff --git a/internal/use-case/simgos-sync-use-case/new/soapi/case.go b/internal/use-case/simgos-sync-use-case/new/soapi/case.go new file mode 100644 index 00000000..d7e9bcc4 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/new/soapi/case.go @@ -0,0 +1,274 @@ +package soapi + +import ( + pl "simrs-vx/pkg/logger" + + d "github.com/karincake/dodol" + "gorm.io/gorm" + + db "simrs-vx/pkg/dualtrx-helper" + + e "simrs-vx/internal/domain/main-entities/soapi" + + elog "simrs-vx/internal/domain/sync-entities/log" + esync "simrs-vx/internal/domain/sync-entities/soapi" + + ue "simrs-vx/internal/use-case/simgos-sync-use-case/new/encounter" +) + +const source = "soapi" + +func Create(input e.Soapi) (*d.Data, error) { + var ( + syncLink *esync.SoapiLink + err error + ) + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + // get encounter Link + eLink, err := ue.ReadDetailLinkData(*input.Encounter_Id, &event) + if err != nil { + return nil, err + } + + // get Tpendaftaran + tPendaftaran, err := ue.ReadTPendaftaranDetailData(eLink.Simgos_Id, &event) + if err != nil { + return nil, err + } + + err = db.WithDualTx(func(tx *db.Dualtx) error { + // STEP 1: Insert to TDiagnosaDanTerapi + tDiagTherapy, err := CreateTDiagnosaDanTerapi(input, tPendaftaran, &event, tx.Simgos) + if err != nil { + return err + } + + // STEP 2: Insert to TICD + _, err = CreateTIcd(input, tPendaftaran, &event, tx.Simgos) + if err != nil { + return err + } + + // STEP 3: Insert to TICD-CM + _, err = CreateTIcdCm(input, tPendaftaran, &event, tx.Simgos) + if err != nil { + return err + } + + // STEP 4: Insert to Link + syncLink, err = CreateLinkData(input.Id, tDiagTherapy.Idxterapi, &event, tx.Sync) + if err != nil { + return err + } + + return nil + }) + + if err != nil { + if syncLink != nil { + go func() { _ = DeleteLinkData(syncLink, &event) }() + } + return nil, err + } + + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + }, nil +} + +func CreateSimxLog(input elog.SimxLogDto) (*d.Data, error) { + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + tx := db.NewTx() + err := tx.Sync.Transaction(func(tx *gorm.DB) error { + // Insert to Log + if err := CreateLogData(input, &event, tx); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + }, nil +} + +func Update(input e.Soapi) (*d.Data, error) { + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + // Get Soapi Link + sLink, err := ReadDetailLinkData(input.Id, &event) + if err != nil { + return nil, err + } + + // Get TDiagnosadanTerapi + tDiagTherapy, err := ReadDetailTDiagnosaDanTerapi(sLink.Simgos_Id, &event) + if err != nil { + return nil, err + } + + // Get Encounter Link + eLink, err := ue.ReadDetailLinkData(*input.Encounter_Id, &event) + if err != nil { + return nil, err + } + + // Get TPendaftaran + tPendaftaran, err := ue.ReadTPendaftaranDetailData(eLink.Simgos_Id, &event) + if err != nil { + return nil, err + } + + tx := db.NewTx() + err = tx.Simgos.Transaction(func(tx *gorm.DB) error { + // SET LOCAL + if err = tx.Exec(`SET LOCAL simx.sync_source = 'new'`).Error; err != nil { + return err + } + + // Step 1: Update TDiagnosaDanTerapi + if err = UpdateTDiagnosaDanTerapi(input, tDiagTherapy, &event, tx); err != nil { + return err + } + + // STEP 2: Delete TIcd + if err = HardDeleteTIcd(tDiagTherapy.Idxdaftar, &event, tx); err != nil { + return err + } + + // STEP 3: Delete TIcdCm + if err = HardDeleteTIcdCm(tDiagTherapy.Idxdaftar, &event, tx); err != nil { + return err + } + + // STEP 4: Insert TIcd + if _, err = CreateTIcd(input, tPendaftaran, &event, tx); err != nil { + return err + } + + // STEP 5: Insert TIcd-cm + if _, err = CreateTIcdCm(input, tPendaftaran, &event, tx); err != nil { + return err + } + + return nil + }) + + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + }, nil +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + var isLinkDeleted bool + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + // Get Soapi Link + syncLink, err := ReadDetailLinkData(input.Id, &event) + if err != nil { + return nil, err + } + + // Get TDiagnosa&Terapi + tDiagTh, err := ReadDetailTDiagnosaDanTerapi(syncLink.Simgos_Id, &event) + if err != nil { + return nil, err + } + + err = db.WithDualTx(func(tx *db.Dualtx) error { + // STEP 1: Delete TDiagnosa&Terapi Simgos + if err = HardDeleteTDiagnosaDanTerapi(tDiagTh, &event, tx.Simgos); err != nil { + return err + } + + // STEP 2: Delete TIcd + if err = HardDeleteTIcd(tDiagTh.Idxdaftar, &event, tx.Simgos); err != nil { + return err + } + + // STEP 3: Delete TIcdCm + if err = HardDeleteTIcdCm(tDiagTh.Idxdaftar, &event, tx.Simgos); err != nil { + return err + } + + // STEP 4: Delete Link + err = DeleteLinkData(syncLink, &event, tx.Sync) + if err != nil { + return err + } + + isLinkDeleted = true + return nil + }) + + if err != nil { + if isLinkDeleted { + go func() { + _, _ = CreateLinkData(input.Id, tDiagTh.Idxterapi, &event) + }() + } + return nil, err + } + + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + }, nil + +} diff --git a/internal/use-case/simgos-sync-use-case/new/soapi/helper.go b/internal/use-case/simgos-sync-use-case/new/soapi/helper.go new file mode 100644 index 00000000..b9d761a1 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/new/soapi/helper.go @@ -0,0 +1,200 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package soapi + +import ( + "encoding/json" + "fmt" + ere "simrs-vx/internal/domain/references/encounter" + "strconv" + "time" + + ercl "simrs-vx/internal/domain/references/clinical" + erc "simrs-vx/internal/domain/references/common" + + es "simrs-vx/internal/domain/main-entities/soapi" + + etdt "simrs-vx/internal/domain/simgos-entities/t-diagnosadanterapi" + eicd "simrs-vx/internal/domain/simgos-entities/t-icd" + eicdcm "simrs-vx/internal/domain/simgos-entities/t-icd-cm" + etp "simrs-vx/internal/domain/simgos-entities/t-pendaftaran" + + esyncLog "simrs-vx/internal/domain/sync-entities/log" + esync "simrs-vx/internal/domain/sync-entities/soapi" +) + +func setDataCreateTDiagnosaDanTerapi(input es.Soapi, enc *etp.TPendaftaran) (data etdt.TDiagnosaDanTerapi) { + switch input.TypeCode { + case ercl.STCEEarlyMedic: + data.Idxdaftar = enc.Idxdaftar + data.Nomr = enc.Nomr + data.Kdpoly = enc.Kdpoly + data.Kddokter = enc.Kddokter + + if e := input.Encounter; e != nil { + data.Tanggal = e.VisitDate + if e.Class_Code == ere.ECAmbulatory { + data.Rajal = 1 + } + + } + + if e := input.Employee; e != nil { + if u := e.User; u != nil { + data.Nip = u.Name + } + } + + setEarlyMedicTDT(input, &data) + return + } + + return +} + +func setEarlyMedicTDT(input es.Soapi, data *etdt.TDiagnosaDanTerapi) { + value := ercl.EarlyMedicValue{} + _ = json.Unmarshal([]byte(*input.Value), &value) + + data.TekananDarah = fmt.Sprintf("%v/%v", value.SystolicBloodPressure, value.DiastolicBloodPressure) + data.GolonganDarah = value.BloodType + if value.BloodType == "" { + data.GolonganDarah = "X" + } + + data.TinggiBadan = float64(value.Height) + data.BeratBadan = float64(value.Weight) + data.Diagnosa = &value.EarlyMedicDiagnose + data.Terapi = &value.Therapy + data.Anamnesa = &value.PrimaryComplain + + // TODO : status, tindakan_mdeis (?) + data.KunjunganBl = uint(value.EncounterStatus) + data.KasusBl = uint(value.CaseStatus) + + data.PemeriksaanFisik = &value.PhysicalExamination + data.RiwayatPasien = &value.CurrentDiseaseHistory + + if value.Vaccinated { + data.SudahVaksin = "YA" + } else { + data.SudahVaksin = "TIDAK" + } + + data.DenyutJantung = strconv.Itoa(value.Pulse) + data.Pernapasan = strconv.Itoa(value.RespiratoryRate) + data.Suhu = strconv.Itoa(value.Temperature) + data.Sp02 = strconv.Itoa(value.SpO2) + + if o := value.ExpectedOutcome; len(o) > 0 { + expectedOutput := []string{} + for _, v := range o { + expectedOutput = append(expectedOutput, v.Name) + } + + jsonData, _ := json.Marshal(expectedOutput) + data.TargetCapaian = string(jsonData) + } + return +} + +func setDataIcd(input es.Soapi, enc *etp.TPendaftaran) (data []eicd.TIcd) { + value := ercl.EarlyMedicValue{} + _ = json.Unmarshal([]byte(*input.Value), &value) + + var ( + visitDate time.Time + ambulatory uint16 + ) + + if e := input.Encounter; e != nil { + visitDate = e.VisitDate + if e.Class_Code == ere.ECAmbulatory { + ambulatory = 1 + } + + } + + if d := value.DiagnoseSrc; len(d) > 0 { + for _, v := range d { + data = append(data, eicd.TIcd{ + Nomr: enc.Nomr, + Idxdaftar: enc.Idxdaftar, + Kddokter: enc.Kddokter, + Icd: v.Code, + StatusRajal: ambulatory, + Tanggal: visitDate, + }) + } + } + + return +} + +func setDataIcdCm(input es.Soapi, enc *etp.TPendaftaran) (data []eicdcm.TIcdCm) { + value := ercl.EarlyMedicValue{} + _ = json.Unmarshal([]byte(*input.Value), &value) + + var ( + visitDate time.Time + ambulatory uint16 + ) + + if e := input.Encounter; e != nil { + visitDate = e.VisitDate + if e.Class_Code == ere.ECAmbulatory { + ambulatory = 1 + } + + } + + if p := value.ProcedureSrc; len(p) > 0 { + for _, v := range p { + data = append(data, eicdcm.TIcdCm{ + Nomr: enc.Nomr, + Idxdaftar: enc.Idxdaftar, + Kddokter: enc.Kddokter, + Icd: &v.Code, + StatusRajal: ambulatory, + Tanggal: visitDate, + }) + } + } + + return +} + +func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.SoapiSimxLog) { + // encode to JSON + jsonData, _ := json.MarshalIndent(input.Payload, "", " ") + jsonString := string(jsonData) + + var status erc.ProcessStatusCode + if input.IsSuccess { + status = erc.PSCSuccess + } else { + status = erc.PSCFailed + if input.ErrMessage != nil { + data.ErrMessage = input.ErrMessage + } + } + + data.Value = &jsonString + data.Date = &now + data.Status = status + + return +} + +func setDataSimxLink(simxId, simgosId uint) (data esync.SoapiLink) { + data.Simx_Id = simxId + data.Simgos_Id = simgosId + return +} + +func stringtouint(v string) uint { + u, _ := strconv.Atoi(v) + return uint(u) +} diff --git a/internal/use-case/simgos-sync-use-case/new/soapi/lib.go b/internal/use-case/simgos-sync-use-case/new/soapi/lib.go new file mode 100644 index 00000000..af27a791 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/new/soapi/lib.go @@ -0,0 +1,334 @@ +package soapi + +import ( + "errors" + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + "time" + + dg "github.com/karincake/apem/db-gorm-pg" + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/soapi" + + etdt "simrs-vx/internal/domain/simgos-entities/t-diagnosadanterapi" + eicd "simrs-vx/internal/domain/simgos-entities/t-icd" + eicdcm "simrs-vx/internal/domain/simgos-entities/t-icd-cm" + ep "simrs-vx/internal/domain/simgos-entities/t-pendaftaran" + + esynclog "simrs-vx/internal/domain/sync-entities/log" + esync "simrs-vx/internal/domain/sync-entities/soapi" +) + +var now = time.Now() + +func CreateTDiagnosaDanTerapi(input e.Soapi, tdaftar *ep.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) (*etdt.TDiagnosaDanTerapi, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + data := setDataCreateTDiagnosaDanTerapi(input, tdaftar) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.IS["simrs"] + } + + if err := tx.Create(&data).Error; err != nil { + return nil, plh.HandleCreateError(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadDetailTDiagnosaDanTerapi(simgosId uint, event *pl.Event) (*etdt.TDiagnosaDanTerapi, error) { + pl.SetLogInfo(event, simgosId, "started", "DBReadDetail") + data := etdt.TDiagnosaDanTerapi{} + + var tx = dg.IS["simrs"] + + if err := tx. + Where("\"idxterapi\" = ?", simgosId). + First(&data).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, simgosId, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateTDiagnosaDanTerapi(input e.Soapi, data *etdt.TDiagnosaDanTerapi, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, input, "started", "DBUpdate") + + setEarlyMedicTDT(input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.IS["simrs"] + } + + if err := tx.Save(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-update-fail", + Detail: "Database update failed", + Raw: err, + } + return pl.SetLogError(event, input) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} + +func HardDeleteTDiagnosaDanTerapi(data *etdt.TDiagnosaDanTerapi, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBDelete") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.IS["simrs"] + } + + if err := tx. + Delete(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-delete-fail", + Detail: "Database delete failed", + Raw: err, + } + return pl.SetLogError(event, data) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} + +func CreateTIcd(input e.Soapi, tdaftar *ep.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) (*[]eicd.TIcd, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + data := setDataIcd(input, tdaftar) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.IS["simrs"] + } + + if err := tx.Create(&data).Error; err != nil { + return nil, plh.HandleCreateError(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListTIcd(idxdaftar string, event *pl.Event, dbx ...*gorm.DB) ([]eicd.TIcd, error) { + pl.SetLogInfo(event, idxdaftar, "started", "DBReadList") + data := []eicd.TIcd{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&eicd.TIcd{}). + Where("idxdaftar = ?", idxdaftar) + + if err := tx.Find(&data).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, plh.HandleListError(idxdaftar, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return data, nil +} + +func HardDeleteTIcd(idxdaftar uint, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, idxdaftar, "started", "DBDelete") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.IS["simrs"] + } + + if err := tx. + Where("idxdaftar = ?", idxdaftar). + Delete(&eicd.TIcd{}).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-delete-fail", + Detail: "Database delete failed", + Raw: err, + } + return pl.SetLogError(event, idxdaftar) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} + +func CreateTIcdCm(input e.Soapi, tdaftar *ep.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) (*[]eicdcm.TIcdCm, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + data := setDataIcdCm(input, tdaftar) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.IS["simrs"] + } + + if err := tx.Create(&data).Error; err != nil { + return nil, plh.HandleCreateError(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListTIcdCm(idxdaftar string, event *pl.Event, dbx ...*gorm.DB) ([]eicdcm.TIcdCm, error) { + pl.SetLogInfo(event, idxdaftar, "started", "DBReadList") + data := []eicdcm.TIcdCm{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&eicdcm.TIcdCm{}). + Where("idxdaftar = ?", idxdaftar) + + if err := tx.Find(&data).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, plh.HandleListError(idxdaftar, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return data, nil +} + +func HardDeleteTIcdCm(idxdaftar uint, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, idxdaftar, "started", "DBDelete") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.IS["simrs"] + } + + if err := tx. + Where("idxdaftar = ?", idxdaftar). + Delete(&eicdcm.TIcdCm{}).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-delete-fail", + Detail: "Database delete failed", + Raw: err, + } + return pl.SetLogError(event, idxdaftar) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} + +func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.SoapiLink, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + data := setDataSimxLink(simxId, simgosId) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.Create(&data).Error; err != nil { + return nil, plh.HandleCreateError(data, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadDetailLinkData(simxId uint, event *pl.Event) (*esync.SoapiLink, error) { + pl.SetLogInfo(event, simxId, "started", "DBReadDetail") + data := esync.SoapiLink{} + + var tx = dg.I + + if err := tx. + Where("\"Simx_Id\" = ?", simxId). + First(&data).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, simxId, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func DeleteLinkData(data *esync.SoapiLink, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBDelete") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.Delete(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-delete-fail", + Detail: "Database delete failed", + Raw: err, + } + return pl.SetLogError(event, data) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} + +func CreateLogData(input esynclog.SimxLogDto, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, nil, "started", "DBCreate") + data := setDataSimxLog(&input) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.Create(&data).Error; err != nil { + return plh.HandleCreateError(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} diff --git a/internal/use-case/simgos-sync-use-case/new/soapi/middleware-runner.go b/internal/use-case/simgos-sync-use-case/new/soapi/middleware-runner.go new file mode 100644 index 00000000..74d8b1a8 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/new/soapi/middleware-runner.go @@ -0,0 +1,104 @@ +package soapi + +import ( + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/soapi" +) + +type middlewareRunner struct { + Event *pl.Event + Tx *gorm.DB + MwType pu.MWType +} + +// NewMiddlewareExecutor creates a new middleware executor +func newMiddlewareRunner(event *pl.Event, tx *gorm.DB) *middlewareRunner { + return &middlewareRunner{ + Event: event, + Tx: tx, + } +} + +// ExecuteCreateMiddleware executes create middleware +func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.Soapi) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.Soapi) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Soapi) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Soapi) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Soapi) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) setMwType(mwType pu.MWType) { + me.MwType = mwType +} diff --git a/internal/use-case/simgos-sync-use-case/new/soapi/middleware.go b/internal/use-case/simgos-sync-use-case/new/soapi/middleware.go new file mode 100644 index 00000000..1fa07628 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/new/soapi/middleware.go @@ -0,0 +1 @@ +package soapi diff --git a/internal/use-case/simgos-sync-use-case/new/soapi/tycovar.go b/internal/use-case/simgos-sync-use-case/new/soapi/tycovar.go new file mode 100644 index 00000000..956193a4 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/new/soapi/tycovar.go @@ -0,0 +1,44 @@ +/* +DESCRIPTION: +A sample, part of the package that contains type, constants, and/or variables. + +In this sample it also provides type and variable regarding the needs of the +middleware to separate from main use-case which has the basic CRUD +functionality. The purpose of this is to make the code more maintainable. +*/ +package soapi + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/soapi" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.Soapi, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Soapi, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Soapi, tx *gorm.DB) error +} + +type UpdateMw = readDetailMw +type DeleteMw = readDetailMw + +var createPreMw []createMw // preprocess middleware +var createPostMw []createMw // postprocess middleware +var readListPreMw []readListMw // .. +var readListPostMw []readListMw // .. +var readDetailPreMw []readDetailMw +var readDetailPostMw []readDetailMw +var updatePreMw []readDetailMw +var updatePostMw []readDetailMw +var deletePreMw []readDetailMw +var deletePostMw []readDetailMw diff --git a/internal/use-case/simgos-sync-use-case/old/patient/case.go b/internal/use-case/simgos-sync-use-case/old/patient/case.go new file mode 100644 index 00000000..09afa2bd --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/old/patient/case.go @@ -0,0 +1,165 @@ +package patient + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + + cfg "simrs-vx/internal/infra/sync-cfg" + pl "simrs-vx/pkg/logger" + + e "simrs-vx/internal/domain/main-entities/patient" + un "simrs-vx/internal/use-case/simgos-sync-use-case/new/patient" + + d "github.com/karincake/dodol" +) + +const source = "old-to-new-patient" + +var path = "patient" + +func Create(input e.Patient) (*d.Data, error) { + evt := pl.Event{ + Feature: "Create", + Source: source, + } + + pl.SetLogInfo(&evt, input, "started", "create") + + // create request body + jsonPatient, err := json.Marshal(input) + if err != nil { + return nil, pl.SetLogError(&evt, input) + } + reqBody := bytes.NewBuffer(jsonPatient) + // send data to main-api + resp, err := send(http.MethodPost, path, reqBody, *input.RegisteredBy_User_Name) + if err != nil { + return nil, pl.SetLogError(&evt, input) + } + // getting response + var data MainApiResp + err = json.Unmarshal(resp, &data) + if err != nil { + return nil, pl.SetLogError(&evt, string(resp)) + } + // create PatientLink + un.CreateLinkData(data.Data.Id, input.Id, &evt) + pl.SetLogInfo(&evt, nil, "complete") + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: input.ToResponse(), + }, nil +} + +func Update(input e.Patient) (*d.Data, error) { + evt := pl.Event{ + Feature: "Update", + Source: source, + } + pl.SetLogInfo(&evt, input, "started", "update") + + // get patient link from database + patientLink, err := ReadDetailLinkData(input.Id) + if err != nil { + return nil, pl.SetLogError(&evt, input) + } + + // get data patient from main-api + resp, err := send(http.MethodGet, fmt.Sprintf("%s%v", "patient/", patientLink.Simx_Id), nil, *input.RegisteredBy_User_Name) + if err != nil { + return nil, pl.SetLogError(&evt, input) + } + // unpack data from resp + var respData MainApiResp + err = json.Unmarshal(resp, &respData) + if err != nil { + return nil, pl.SetLogError(&evt, input) + } + + // copy data from simgos m_patient to simx Patient + preserve := map[string]bool{ + "Main.Id": true, + "Person.Id": true, + } + simxPatient := respData.Data + SetPatient(&simxPatient, &input, preserve) + + jsonPatient, err := json.Marshal(simxPatient) + if err != nil { + return nil, pl.SetLogError(&evt, input) + } + + // send data to main api + url := fmt.Sprintf("%s%v", "patient/", simxPatient.Id) + reqBody := bytes.NewBuffer(jsonPatient) + _, err = send(http.MethodPatch, url, reqBody, *input.RegisteredBy_User_Name) + if err != nil { + return nil, pl.SetLogError(&evt, input) + } + + pl.SetLogInfo(&evt, nil, "complete") + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: input.ToResponse(), + }, nil +} + +func Delete(input e.Patient) (*d.Data, error) { + evt := pl.Event{ + Feature: "Delete", + Source: source, + } + pl.SetLogInfo(&evt, input, "started", "delete") + + // get patient link from database + patientLink, err := ReadDetailLinkData(input.Id) + if err != nil { + return nil, err + } + _, err = send(http.MethodDelete, fmt.Sprintf("%s%v", "patient/", patientLink.Simx_Id), nil, *input.RegisteredBy_User_Name) + if err != nil { + return nil, err + } + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: input.ToResponse(), + }, nil +} + +func send(method string, endpoint string, body *bytes.Buffer, username string) ([]byte, error) { + var url string = cfg.O.NewHost + endpoint + var reader io.Reader = nil + if body != nil { + reader = body + } + req, err := http.NewRequest(method, url, reader) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", "application/json") + req.Header.Set("X-Sync-Source", cfg.O.OldSource) + req.Header.Set("X-Sync-SecretKey", cfg.O.NewSecretKey) + req.Header.Set("X-Sync-UserName", username) + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + respBody, _ := io.ReadAll(resp.Body) + return respBody, nil +} diff --git a/internal/use-case/simgos-sync-use-case/old/patient/helper.go b/internal/use-case/simgos-sync-use-case/old/patient/helper.go new file mode 100644 index 00000000..2d89bff9 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/old/patient/helper.go @@ -0,0 +1,69 @@ +package patient + +import ( + "reflect" + "strings" +) + +func SetPatient(dst, src interface{}, preserve map[string]bool) { + dv := reflect.ValueOf(dst).Elem() + sv := reflect.ValueOf(src).Elem() + + for i := 0; i < dv.NumField(); i++ { + f := dv.Type().Field(i) + fieldName := f.Name + + // skip preserved fields + if preserve[fieldName] { + continue + } + + df := dv.Field(i) + sf := sv.Field(i) + if !df.CanSet() { + // skip unexported skip + continue + } + + switch df.Kind() { + + case reflect.Struct: + nestedPreserve := map[string]bool{} + + for key := range preserve { + if strings.HasPrefix(key, fieldName+".") { + nestedPreserve[strings.TrimPrefix(key, fieldName+".")] = true + } + } + + SetPatient(df.Addr().Interface(), sf.Addr().Interface(), nestedPreserve) + case reflect.Pointer: + // Check if pointer points to a struct + if df.Type().Elem().Kind() == reflect.Struct { + if sf.IsNil() { + break + } + + // If dest pointer is nil, allocate it + if df.IsNil() { + df.Set(reflect.New(df.Type().Elem())) + } + + // Recurse into struct via Elem() + nestedPreserve := map[string]bool{} + for key := range preserve { + if strings.HasPrefix(key, fieldName+".") { + nestedPreserve[strings.TrimPrefix(key, fieldName+".")] = true + } + } + + SetPatient(df.Elem().Addr().Interface(), sf.Elem().Addr().Interface(), nestedPreserve) + } + default: + // Overwrite only when src has non-zero value + if !sf.IsZero() { + df.Set(sf) + } + } + } +} diff --git a/internal/use-case/simgos-sync-use-case/old/patient/lib.go b/internal/use-case/simgos-sync-use-case/old/patient/lib.go new file mode 100644 index 00000000..d6b5f470 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/old/patient/lib.go @@ -0,0 +1,19 @@ +package patient + +import ( + esync "simrs-vx/internal/domain/sync-entities/patient" + + dg "github.com/karincake/apem/db-gorm-pg" +) + +func ReadDetailLinkData(simgosId uint) (*esync.PatientLink, error) { + // log event + var data esync.PatientLink + var tx = dg.I + + if err := tx.Where("\"Simgos_Id\" = ?", simgosId).First(&data).Error; err != nil { + return nil, err + } + // log end event + return &data, nil +} diff --git a/internal/use-case/simgos-sync-use-case/old/patient/tycovar.go b/internal/use-case/simgos-sync-use-case/old/patient/tycovar.go new file mode 100644 index 00000000..15d99d0f --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/old/patient/tycovar.go @@ -0,0 +1,14 @@ +package patient + +import e "simrs-vx/internal/domain/main-entities/patient" + +type MainApiResp struct { + Meta MetaData `json:"meta"` + Data e.Patient `json:"data"` +} + +type MetaData struct { + Source string `json:"source"` + Status string `json:"status"` + Structure string `json:"structure"` +} diff --git a/pkg/dualtrx-helper/dualtrx-helper.go b/pkg/dualtrx-helper/dualtrx-helper.go index 2f16203c..144337c5 100644 --- a/pkg/dualtrx-helper/dualtrx-helper.go +++ b/pkg/dualtrx-helper/dualtrx-helper.go @@ -11,9 +11,12 @@ type Dualtx struct { } func NewDualtx() *Dualtx { + simgosTx := dg.IS["simrs"].Begin() + simgosTx.Exec(`SET LOCAL simx.sync_source = 'new'`) + return &Dualtx{ Sync: dg.I.Begin(), - Simgos: dg.IS["simrs"].Begin(), + Simgos: simgosTx, } }