From 066574e0fea6e22c1a55b59805ea0565d35ac8f1 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 24 Oct 2025 12:16:36 +0700 Subject: [PATCH 001/329] adjustment positions --- cmd/main-migration/migrations/atlas.sum | 118 +++++++++--------- .../division-position/base/entity.go | 18 +++ .../main-entities/division-position/entity.go | 13 +- .../domain/main-entities/division/entity.go | 14 ++- .../installation-position/base/entity.go | 20 +++ .../installation-position/entity.go | 13 +- .../main-entities/installation/entity.go | 10 +- .../specialist-position/base/entity.go | 20 +++ .../specialist-position/entity.go | 13 +- .../domain/main-entities/specialist/entity.go | 12 +- .../subspecialist-position/base/entity.go | 20 +++ .../subspecialist-position/entity.go | 13 +- .../main-entities/subspecialist/entity.go | 12 +- .../unit-position/base/entity.go | 18 +++ .../main-entities/unit-position/entity.go | 13 +- internal/domain/main-entities/unit/entity.go | 2 + 16 files changed, 202 insertions(+), 127 deletions(-) create mode 100644 internal/domain/main-entities/division-position/base/entity.go create mode 100644 internal/domain/main-entities/installation-position/base/entity.go create mode 100644 internal/domain/main-entities/specialist-position/base/entity.go create mode 100644 internal/domain/main-entities/subspecialist-position/base/entity.go create mode 100644 internal/domain/main-entities/unit-position/base/entity.go diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 4a370f6a..a52827a6 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,59 +1,59 @@ -h1:HozaE+KMdV5bp0Z1QR6FiU5dW3npmFwbvxo+noqNuRQ= -20250904105930.sql h1:Vv4vCurl7m7/ZB6TjRpkubHpQ4RYwSUn0QHdzfoGpzY= -20250904141448.sql h1:FYCHH9Os4KkrZMDu/jR8FMP+wLMRW+Mb0PkLU/9BRDg= -20250908062237.sql h1:oanBpKZd+akPu2I/xYhUSbd0G5tAFbXzKLER/Zs8ENI= -20250908062323.sql h1:miNG9COddXkD1jGTgaROMAZ618eT6oiLGiJhXWnQwhE= -20250908073811.sql h1:gOi5cnGG1htlpfizybYmUIT0vYjZTBfXiI0nPSYK2u8= -20250908073839.sql h1:cWNDA4YikjoOteAJuNLFILjQUJPFB6o8Wxreiek4QyI= -20250910055902.sql h1:nxxOGnU0BbH/v3IPgeIOXOwH8d3tKomw7h6FTeMnnBs= -20250915123412.sql h1:mz7SiWfrdf0qE1VTSAAnA/147d6gyp6ry5vZ2bR9SH0= -20250916043819.sql h1:RHXVtmMkB6wfv06HfPyHMBmUfIpFt1xveafNz0kwKnE= -20250917040616.sql h1:MYVDht+akBlzQGKNu2hTTTLPEcH1bxT/Q8MK6WEtuhs= -20250917040751.sql h1:J79YyS2JzWgh5oKXMTgh67uo3gLxKaAsxRiZmSIfjBs= -20250917045138.sql h1:/SM1N4O8X3yxpoJgMEARmS1uOkuLKsTOy4PLsRCOKaQ= -20250917093645.sql h1:PNBTGZ7s10e5b5+Tie8YfVQBN0zKtJ5T34oK1iOUEb4= -20250918073552.sql h1:jG7+g3i8ODYaJdcdZz12v3nbsZ5mB9wG6kWnGyTQIRI= -20250918073742.sql h1:j+rgw7puxE7s+phqPVZHmPk0af3rcaA56Itp86y1suY= -20250918074745.sql h1:rPmP4DXs6OnY4Vp+xO/z9jFpJt/RrJ52SJJjIIxeDvc= -20250923025134.sql h1:2r6pcwnBSU5Y9Czk1OHBoh4yZXiMtEca9X8843fTEX0= -20250924051317.sql h1:iUAk2gsGoEGIPQ0lEEUp8maMSId8emNbP+kP712ABIA= -20250929034321.sql h1:UlpALNVmdi95zOIT0yc6ZyTj9bBjQEIpZhvgrc52M+k= -20250929034428.sql h1:feF+H4nDyHh5bdx48Oiz0A1qecZfi6v3qTTdjzJ45Dg= -20250930025550.sql h1:6XT1kXI3Z3ZIxxmvT7poufZWWCW0QiejZPaFV5wBnjI= -20250930140351.sql h1:HxnmAbh9gCy8jwl/9ycGktiByaUripsjFFvohofY2CY= -20251002085604.sql h1:SjLPi+ZN6qDccK3DaEQCgNsZpPwr5kynWXwbwEsziCI= -20251003032030.sql h1:oHfxNSuqTxU8Zaf9H+h8TuUb1Da03wcyc6hZjDrUQ2s= -20251005060450.sql h1:GIuCcrd4MwjmXpvbzDzPYL18BV3QaZZ+Y2FmEzjvi0E= -20251006041122.sql h1:uNDQbSw0M08lYoMvUNlQtS3iDzpPM1ixT13ugSAoWjE= -20251006045658.sql h1:z+t7yCK54Q4SSiF9kUyUhkYB2F+kzSW9TB7ogxd9wzw= -20251006045928.sql h1:1lATLFLp4BWwGZqAjZdP0Dc6ypNXiYcwjoNkqGa8NFE= -20251007022859.sql h1:HXXwWrkyvzJzJGAt9mGskCRBBV/c1JfPmfjDocmJhQ4= -20251008031337.sql h1:Ln5pCF3Hxa5foHZLcds+z/us2eH6VAhhEj3w0TAGlVs= -20251008031554.sql h1:aB4MUS2lmqG0//4HKUWorcPSpWya0VC4QItvGyskEVI= -20251008052346.sql h1:MI3AZgU5XcwZT2OvvlWAxdRtL0eJ3jjRwt56IY1+pRU= -20251008073620.sql h1:sztWXuSNYwpEraaSapSsYwno75LO5H/N7ob7OJQ8X/A= -20251009042854.sql h1:TnPXj+dCJls3IU//cuqJZymyBzZMKs7ayazfgtAFRxM= -20251009052657.sql h1:leXbs0CP8r5dRilmYyLRk1MICqak3ea1/LWMtFrijqQ= -20251010031743.sql h1:SgHNY/lQ88G2F4nZyMfiOkDntb+gtOR+nEQLqXBTwv4= -20251010070721.sql h1:AnJnhXsMzDvK4AFgYw6B16Kpo/hljrZtcpc9m2VOSHQ= -20251010072711.sql h1:aXPTtNwLcTuw8C/yAxwxvqs0ayEjNzI1uuE0vE3ERa8= -20251013044536.sql h1:7Pq6JcvTpPBYDCW2dz3HdgUwY65HlhEVWy9TiG8iONE= -20251013051438.sql h1:X6t8bkqpUYYokBunSufMQUe5vCg0VyO6dxbm7ngosUc= -20251013081808.sql h1:495pLguXL2Ozh+ycn4UYZgZbn6WbjXNbyZUc3JU8qhI= -20251014060047.sql h1:nCgImMRGHhziiW57O1ofWaXCAPGaCOHN7PldQ3OSmM4= -20251014063537.sql h1:2cLmID79jP6cuQ1YJaWTtghFiM1GtHMC0ZQl30Hpy1M= -20251014063720.sql h1:bzLKKVAjSHgDFoiI/glj7t1ETlSAKx+AlsIAaP0ru2g= -20251015045455.sql h1:S547+UugQhlTRcn1Lm1IfqT5RNPttIWIiD+RTx69YaE= -20251016010845.sql h1:c9DUvxl17pUkf0azdYGM/YDzYxIJkLcfZOcMI4rL+R0= -20251016011023.sql h1:u3ivg83bXgYHBbojbWpemLxPE9Dmmj53B6LXo664jxw= -20251016062912.sql h1:W9n1hWchfYkqNX9LO9uxFxEXAb/iY+Pexjnhmp6PbgI= -20251017060617.sql h1:VU6yZ2+LfHpDZ3+TIH40t3F5YXPCpTppuF9+uSqa4b8= -20251017082207.sql h1:QshZslfedckz7iDpSGmPyY9sP6dy6ckHbs8L1TuXIA4= -20251018032635.sql h1:M1U/9W/F9wlW5YDmVAmHFfUJU7FWFaX0DblpfZcYWrE= -20251018040322.sql h1:Zk/vw0e6AzWFO2ElLOzB+OrSz6k+h1Ynxp0TImAzxwY= -20251019093915.sql h1:3Q0kPiZwJnHn5rAvdh0w1LBdiA7W2xBmZWncoPXb044= -20251020062553.sql h1:mJwC/J8GzPAIXckNMvy1f/Nguk2VVf8roD/Raclhbao= -20251021041042.sql h1:d1BAOGAQhqr+oOwcpAVozUsTh457VSDEk2qQFavGG58= -20251021075552.sql h1:TNChGQ1Zlr/1iQ6qvK4iDTAJpe6L/z/M6e/O0SkQVaM= -20251023044432.sql h1:GA2AdJk2ULyjr6igtu9C/CEi4YUIks8r9jXGGaCvPsk= -20251024034832.sql h1:RXmbEhMkOLK5g1QL6up8iRPcwYfo89oLP26ZHvrUK9o= +h1:fAJxBGCfoMXYDjYBlq6RITZ/dXbqiYtQWwupcBMLHV0= +20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= +20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= +20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= +20250908062323.sql h1:oXl6Z143tOpIl4EfP4B8JNU8LrMvVmHEtCgAfiB4gs8= +20250908073811.sql h1:m2aNXfnGxnLq1+rVWrh4f60q7fhyhV3gEwNu/OIqQlE= +20250908073839.sql h1:cPk54xjLdMs26uY8ZHjNWLuyfAMzV7Zb0/9oJQrsw04= +20250910055902.sql h1:5xwjAV6QbtZT9empTJKfhyAjdknbHzb15B0Ku5dzqtQ= +20250915123412.sql h1:D83xaU2YlDEd21HLup/YQpQ2easMToYCyy/oK6AFgQs= +20250916043819.sql h1:ekoTJsBqQZ8G8n0qJ03d13+eoNoc7sAUEQGA5D/CCxk= +20250917040616.sql h1:zoCnmcXuM7AVv85SmN7RmFglCgJnoDmpRWExH0LAc9Q= +20250917040751.sql h1:J1xyRrh32y1+lezwAyNwPcUQ6ABBSgbvzNLva4SVdQU= +20250917045138.sql h1:jKe1Z0uOLG4SGBYM+S/3P+/zMPztmgoderD5swnMuCg= +20250917093645.sql h1:cNI3Pbz1R3LxvIXLuexafJFCXUXrmuFCgXXJ2sG+FW0= +20250918073552.sql h1:RJ1SvMzP6aeWnoPVD3eVAmIQOkcp6Php8z3QRri6v4g= +20250918073742.sql h1:+cEsnJTJFybe2fR69ZoOiX2R6c6iITl4m6WTZ1hjyzY= +20250918074745.sql h1:2hNVQCXF/dVYXAh+T/7oBFgERGWxzVb2FXJjwkFWGCI= +20250923025134.sql h1:Ykz/qpHiGDXPsCsWTjydQFVSibZP2D+h2fIeb2h2JGA= +20250924051317.sql h1:yQuW6SwJxIOM5fcxeAaie5lSm1oLysU/C2hH2xNCVoQ= +20250929034321.sql h1:101FJ8VH12mrZWlt/X1gvKUGOhoiF8tFbjiapAjnHzg= +20250929034428.sql h1:i+pROD9p+g5dOmmZma6WF/0Hw5g3Ha28NN85iTo1K34= +20250930025550.sql h1:+F+CsCUXD/ql0tHGEow70GhPBX1ZybVn+bh/T4YMh7Y= +20250930140351.sql h1:9AAEG1AnOAH+o0+oHL5G7I8vqlWOhwRlCGyyCpT/y1Q= +20251002085604.sql h1:3xZ68eYp4urXRnvotNH1XvG2mYOSDV/j3zHEZ/txg5E= +20251003032030.sql h1:HB+mQ2lXMNomHDpaRhB/9IwYI9/YiDO5eOJ+nAQH/jw= +20251005060450.sql h1:LbtCE2b+8osM3CvnmQJH1uCPtn+d7WchsslBOz8bL3Q= +20251006041122.sql h1:MlS7f21z06sutnf9dIekt5fuHJr4lgcQ4uCuCXAGsfc= +20251006045658.sql h1:3FmGCPCzjgMPdWDRodZTsx3KVaodd9zB9ilib69aewk= +20251006045928.sql h1:Z5g31PmnzNwk/OKdODcxZGm8fjJQdMFK32Xfnt3bRHg= +20251007022859.sql h1:FO03zEfaNEk/aXwY81d5Lp3MoBB9kPQuXlXJ4BPiSR8= +20251008031337.sql h1:l+sxUAGvcTfj3I6kAFHo+T6AYodC9k9GkR+jaKO2xXc= +20251008031554.sql h1:AqrVfIhSzY3PCy8ZlP5W91wn2iznfIuj5qQfubp6/94= +20251008052346.sql h1:nxnXmooIJ6r1mmzwnw+6efxLfc/k9h2aE6RMptPRons= +20251008073620.sql h1:6YsJp1W4SmQJ1lxpqF27BBlDC1zqhw7Yhc7pLzQTY6M= +20251009042854.sql h1:nkBV+R6j0fg7/JY6wH3eb5Vv0asJLnXmb6lINfT/GLQ= +20251009052657.sql h1:EPvdsib5rzCGPryd10HShGKvFPwM/R5S2lIVwtYxpms= +20251010031743.sql h1:T8IZmx8/btRFKLzTe78MzcBsPJNodnLvB0tby9QkirQ= +20251010070721.sql h1:5NQUk/yOV6sABLCB7swx++YIOyJe6MnU+yt1nRzde5w= +20251010072711.sql h1:ZJNqR2piyu8xJhBvVABSlnGEoKSKae3wuEs+wshPe4k= +20251013044536.sql h1:0Xjw8fNILiT8nnfrJDZgQnPf3dntmIoilbapnih8AE4= +20251013051438.sql h1:lfSuw5mgJnePBJamvhZ81osFIouXeiIEiSZ/evdwo48= +20251013081808.sql h1:ijgjNX08G6GBjA/ks8EKtb7P7Y7Cg7zbhqEOruGnv6M= +20251014060047.sql h1:0jqj49WTtneEIMQDBoo4c095ZGi8sCrA8NnHBrPU6D8= +20251014063537.sql h1:VZLXol0PTsTW21Epg6vBPsztWkDtcxup9F/z88EGgIg= +20251014063720.sql h1:2HVUyCV0ud3BJJDH2GEKZN/+IWLFPCsN1KqhP6csO14= +20251015045455.sql h1:MeLWmMhAOAz8b15Dd7IAQnt6JxjSml02XCXK22C0Lpg= +20251016010845.sql h1:4BncQdDOasRZJkzVJrSJJA7091A9VPNVx/faUCUPhBM= +20251016011023.sql h1:9JB9eFZKURK5RoCVDKR6glSvdJ8NTXrN7K/4q51zkz4= +20251016062912.sql h1:ACNn0fe+EMqUt3hoY+Dr3uqAV/QICBa1+mIW7fUc9Fk= +20251017060617.sql h1:4T3t9ifWrEQTPMSM0XJ98pF7Qdt+UfgtMui17bhrnWI= +20251017082207.sql h1:8vLG1l/saRRMHXkyA4nelJyjaSddhZd6r7R+Uo4JS/c= +20251018032635.sql h1:2xey5gnO3y2XSOrU8MLlIfoylPKbRGDRtHDD07B3MbQ= +20251018040322.sql h1:k/pdNiSoT8zFPqNQ/avOD0vYkNh3BTD64IlHrfVXr7I= +20251019093915.sql h1:hFcQE0y+p5dZiVwePGsRGto9m/q6kJNiUZbVDd5Rnjk= +20251020062553.sql h1:Iw7hulcm5iRQlfW+ygA4iTPxLqkxx6h9vXMXEwUAHKs= +20251021041042.sql h1:wMgSivBV2A0NDcsLmKGIp0kMcVh2IODSG9b4dgzCaOM= +20251021075552.sql h1:8gfSMAglflNO6L0sSzxFNEubYN8/O4thT7OQT+WH+3M= +20251023044432.sql h1:MkvajJs3bfk9+wHvQ43/ccAluJEBARm1gWr1u92ccLA= +20251024034832.sql h1:x3s3VEVYLOSKLAFxJGb2+c1FyTMMvPE+9k4Ew7rKQaI= diff --git a/internal/domain/main-entities/division-position/base/entity.go b/internal/domain/main-entities/division-position/base/entity.go new file mode 100644 index 00000000..d44c0b86 --- /dev/null +++ b/internal/domain/main-entities/division-position/base/entity.go @@ -0,0 +1,18 @@ +package base + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type Basic struct { + ecore.SmallMain // adjust this according to the needs + Division_Id *uint16 `json:"division_id"` + Code string `json:"code" gorm:"unique;size:10"` + Name string `json:"name" gorm:"size:50"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` +} + +func (Basic) TableName() string { + return "DivisionPosition" +} diff --git a/internal/domain/main-entities/division-position/entity.go b/internal/domain/main-entities/division-position/entity.go index c7d70968..79379b52 100644 --- a/internal/domain/main-entities/division-position/entity.go +++ b/internal/domain/main-entities/division-position/entity.go @@ -1,18 +1,13 @@ package divisionposition import ( - ecore "simrs-vx/internal/domain/base-entities/core" ed "simrs-vx/internal/domain/main-entities/division" + eb "simrs-vx/internal/domain/main-entities/division-position/base" ee "simrs-vx/internal/domain/main-entities/employee" ) type DivisionPosition struct { - ecore.SmallMain // adjust this according to the needs - Division_Id *uint16 `json:"division_id"` - Division *ed.Division `json:"division" gorm:"foreignKey:Division_Id;references:Id"` - Code string `json:"code" gorm:"unique;size:10"` - Name string `json:"name" gorm:"size:50"` - HeadStatus bool `json:"headStatus"` - Employee_Id *uint `json:"employee_id"` - Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` + eb.Basic + Division *ed.Division `json:"division" gorm:"foreignKey:Division_Id;references:Id"` + Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` } diff --git a/internal/domain/main-entities/division/entity.go b/internal/domain/main-entities/division/entity.go index 470fab0d..4051c138 100644 --- a/internal/domain/main-entities/division/entity.go +++ b/internal/domain/main-entities/division/entity.go @@ -2,13 +2,15 @@ package division import ( ecore "simrs-vx/internal/domain/base-entities/core" + edpb "simrs-vx/internal/domain/main-entities/division-position/base" ) type Division struct { - ecore.SmallMain // adjust this according to the needs - Code string `json:"code" gorm:"unique;size:10"` - Name string `json:"name" gorm:"size:50"` - Parent_Id *uint16 `json:"parent_id"` - Parent *Division `json:"parent" gorm:"foreignKey:Parent_Id;references:Id"` - Childrens []Division `json:"childrens" gorm:"foreignKey:Parent_Id"` // may need references to self + ecore.SmallMain // adjust this according to the needs + Code string `json:"code" gorm:"unique;size:10"` + Name string `json:"name" gorm:"size:50"` + Parent_Id *uint16 `json:"parent_id"` + Parent *Division `json:"parent" gorm:"foreignKey:Parent_Id;references:Id"` + Childrens []Division `json:"childrens" gorm:"foreignKey:Parent_Id"` // may need references to self + DivisionPositions []edpb.Basic `json:"divisionPositions,omitempty" gorm:"foreignKey:Division_Id;references:Id"` } diff --git a/internal/domain/main-entities/installation-position/base/entity.go b/internal/domain/main-entities/installation-position/base/entity.go new file mode 100644 index 00000000..02fbbe84 --- /dev/null +++ b/internal/domain/main-entities/installation-position/base/entity.go @@ -0,0 +1,20 @@ +package base + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/employee" +) + +type Basic struct { + ecore.SmallMain // adjust this according to the needs + Installation_Id *uint16 `json:"installation_id" gorm:"not null"` + Code string `json:"code" gorm:"unique;size:10;not null"` + Name string `json:"name" gorm:"size:30;not null"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` + Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` +} + +func (Basic) TableName() string { + return "InstallationPosition" +} diff --git a/internal/domain/main-entities/installation-position/entity.go b/internal/domain/main-entities/installation-position/entity.go index 03571326..48e95ac5 100644 --- a/internal/domain/main-entities/installation-position/entity.go +++ b/internal/domain/main-entities/installation-position/entity.go @@ -1,18 +1,11 @@ package installation_position import ( - ecore "simrs-vx/internal/domain/base-entities/core" - ee "simrs-vx/internal/domain/main-entities/employee" ei "simrs-vx/internal/domain/main-entities/installation" + eib "simrs-vx/internal/domain/main-entities/installation-position/base" ) type InstallationPosition struct { - ecore.SmallMain // adjust this according to the needs - Installation_Id *uint16 `json:"installation_id" gorm:"not null"` - Installation *ei.Installation `json:"installation,omitempty" gorm:"foreignKey:Installation_Id;references:Id"` - Code string `json:"code" gorm:"unique;size:10;not null"` - Name string `json:"name" gorm:"size:30;not null"` - HeadStatus bool `json:"headStatus"` - Employee_Id *uint `json:"employee_id"` - Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` + eib.Basic // adjust this according to the needs + Installation *ei.Installation `json:"installation,omitempty" gorm:"foreignKey:Installation_Id;references:Id"` } diff --git a/internal/domain/main-entities/installation/entity.go b/internal/domain/main-entities/installation/entity.go index 0cd5b7dd..dea63a45 100644 --- a/internal/domain/main-entities/installation/entity.go +++ b/internal/domain/main-entities/installation/entity.go @@ -2,12 +2,14 @@ package installation import ( ecore "simrs-vx/internal/domain/base-entities/core" + eipb "simrs-vx/internal/domain/main-entities/installation-position/base" ere "simrs-vx/internal/domain/references/encounter" ) type Installation struct { - ecore.SmallMain // adjust this according to the needs - Code string `json:"code" gorm:"unique;size:10"` - Name string `json:"name" gorm:"size:50"` - EncounterClass_Code ere.EncounterClassCode `json:"encounterClass_code" gorm:"size:10"` + ecore.SmallMain // adjust this according to the needs + Code string `json:"code" gorm:"unique;size:10"` + Name string `json:"name" gorm:"size:50"` + EncounterClass_Code ere.EncounterClassCode `json:"encounterClass_code" gorm:"size:10"` + InstallationPositions []eipb.Basic `json:"installationPositions,omitempty" gorm:"foreignKey:Installation_Id;references:Id"` } diff --git a/internal/domain/main-entities/specialist-position/base/entity.go b/internal/domain/main-entities/specialist-position/base/entity.go new file mode 100644 index 00000000..5910689e --- /dev/null +++ b/internal/domain/main-entities/specialist-position/base/entity.go @@ -0,0 +1,20 @@ +package base + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/employee" +) + +type Basic struct { + ecore.SmallMain // adjust this according to the needs + Specialist_Id *uint16 `json:"specialist_id" gorm:"not null"` + Code string `json:"code" gorm:"unique;size:10;not null"` + Name string `json:"name" gorm:"size:30;not null"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` + Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` +} + +func (Basic) TableName() string { + return "SpecialistPosition" +} diff --git a/internal/domain/main-entities/specialist-position/entity.go b/internal/domain/main-entities/specialist-position/entity.go index 0afa5ba3..26c1d27f 100644 --- a/internal/domain/main-entities/specialist-position/entity.go +++ b/internal/domain/main-entities/specialist-position/entity.go @@ -1,18 +1,11 @@ package specialist_position import ( - ecore "simrs-vx/internal/domain/base-entities/core" - ee "simrs-vx/internal/domain/main-entities/employee" es "simrs-vx/internal/domain/main-entities/specialist" + esb "simrs-vx/internal/domain/main-entities/specialist-position/base" ) type SpecialistPosition struct { - ecore.SmallMain // adjust this according to the needs - Specialist_Id *uint16 `json:"specialist_id" gorm:"not null"` - Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Id;references:Id"` - Code string `json:"code" gorm:"unique;size:10;not null"` - Name string `json:"name" gorm:"size:30;not null"` - HeadStatus bool `json:"headStatus"` - Employee_Id *uint `json:"employee_id"` - Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` + esb.Basic + Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Id;references:Id"` } diff --git a/internal/domain/main-entities/specialist/entity.go b/internal/domain/main-entities/specialist/entity.go index 3cea2ebd..5c2d5b89 100644 --- a/internal/domain/main-entities/specialist/entity.go +++ b/internal/domain/main-entities/specialist/entity.go @@ -2,13 +2,15 @@ package specialist import ( ecore "simrs-vx/internal/domain/base-entities/core" + eub "simrs-vx/internal/domain/main-entities/specialist-position/base" eu "simrs-vx/internal/domain/main-entities/unit" ) type Specialist struct { - ecore.SmallMain // adjust this according to the needs - Code string `json:"code" gorm:"unique;size:10"` - Name string `json:"name" gorm:"size:50"` - Unit_Id *uint16 `json:"unit_id"` - Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id"` + ecore.SmallMain // adjust this according to the needs + Code string `json:"code" gorm:"unique;size:10"` + Name string `json:"name" gorm:"size:50"` + Unit_Id *uint16 `json:"unit_id"` + Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id"` + SpecialistPositions []eub.Basic `json:"specialistPositions,omitempty" gorm:"foreignKey:Specialist_Id;references:Id"` } diff --git a/internal/domain/main-entities/subspecialist-position/base/entity.go b/internal/domain/main-entities/subspecialist-position/base/entity.go new file mode 100644 index 00000000..147fcecb --- /dev/null +++ b/internal/domain/main-entities/subspecialist-position/base/entity.go @@ -0,0 +1,20 @@ +package base + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/employee" +) + +type Basic struct { + ecore.SmallMain // adjust this according to the needs + Subspecialist_Id *uint16 `json:"subspecialist_id" gorm:"not null"` + Code string `json:"code" gorm:"unique;size:10;not null"` + Name string `json:"name" gorm:"size:30;not null"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` + Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` +} + +func (Basic) TableName() string { + return "SubspecialistPosition" +} diff --git a/internal/domain/main-entities/subspecialist-position/entity.go b/internal/domain/main-entities/subspecialist-position/entity.go index 5d4bdcb8..28a205ed 100644 --- a/internal/domain/main-entities/subspecialist-position/entity.go +++ b/internal/domain/main-entities/subspecialist-position/entity.go @@ -1,18 +1,11 @@ package subspecialist_position import ( - ecore "simrs-vx/internal/domain/base-entities/core" - ee "simrs-vx/internal/domain/main-entities/employee" es "simrs-vx/internal/domain/main-entities/subspecialist" + esb "simrs-vx/internal/domain/main-entities/subspecialist-position/base" ) type SubspecialistPosition struct { - ecore.SmallMain // adjust this according to the needs - Subspecialist_Id *uint16 `json:"subspecialist_id" gorm:"not null"` - Subspecialist *es.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Id;references:Id"` - Code string `json:"code" gorm:"unique;size:10;not null"` - Name string `json:"name" gorm:"size:30;not null"` - HeadStatus bool `json:"headStatus"` - Employee_Id *uint `json:"employee_id"` - Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` + esb.Basic + Subspecialist *es.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Id;references:Id"` } diff --git a/internal/domain/main-entities/subspecialist/entity.go b/internal/domain/main-entities/subspecialist/entity.go index 5de27442..a81d6ded 100644 --- a/internal/domain/main-entities/subspecialist/entity.go +++ b/internal/domain/main-entities/subspecialist/entity.go @@ -3,12 +3,14 @@ package subspecialist import ( ecore "simrs-vx/internal/domain/base-entities/core" es "simrs-vx/internal/domain/main-entities/specialist" + espb "simrs-vx/internal/domain/main-entities/subspecialist-position/base" ) type Subspecialist struct { - ecore.SmallMain // adjust this according to the needs - Code string `json:"code" gorm:"unique;size:10"` - Name string `json:"name" gorm:"size:50"` - Specialist_Id *uint16 `json:"specialist_id"` - Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Id"` + ecore.SmallMain // adjust this according to the needs + Code string `json:"code" gorm:"unique;size:10"` + Name string `json:"name" gorm:"size:50"` + Specialist_Id *uint16 `json:"specialist_id"` + Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Id"` + SubspecialistPositions []espb.Basic `json:"subspecialistPositions,omitempty" gorm:"foreignKey:Subspecialist_Id;references:Id"` } diff --git a/internal/domain/main-entities/unit-position/base/entity.go b/internal/domain/main-entities/unit-position/base/entity.go new file mode 100644 index 00000000..3d913d4f --- /dev/null +++ b/internal/domain/main-entities/unit-position/base/entity.go @@ -0,0 +1,18 @@ +package base + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type Basic struct { + ecore.SmallMain // adjust this according to the needs + Unit_Id *uint16 `json:"unit_id" gorm:"not null"` + Code string `json:"code" gorm:"unique;size:10;not null"` + Name string `json:"name" gorm:"size:30;not null"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` +} + +func (Basic) TableName() string { + return "UnitPosition" +} diff --git a/internal/domain/main-entities/unit-position/entity.go b/internal/domain/main-entities/unit-position/entity.go index 3bd10d9e..5450cee2 100644 --- a/internal/domain/main-entities/unit-position/entity.go +++ b/internal/domain/main-entities/unit-position/entity.go @@ -1,18 +1,13 @@ package unit_position import ( - ecore "simrs-vx/internal/domain/base-entities/core" ee "simrs-vx/internal/domain/main-entities/employee" eu "simrs-vx/internal/domain/main-entities/unit" + eub "simrs-vx/internal/domain/main-entities/unit-position/base" ) type UnitPosition struct { - ecore.SmallMain // adjust this according to the needs - Unit_Id *uint16 `json:"unit_id" gorm:"not null"` - Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` - Code string `json:"code" gorm:"unique;size:10;not null"` - Name string `json:"name" gorm:"size:30;not null"` - HeadStatus bool `json:"headStatus"` - Employee_Id *uint `json:"employee_id"` - Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` + eub.Basic + Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` + Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` } diff --git a/internal/domain/main-entities/unit/entity.go b/internal/domain/main-entities/unit/entity.go index c86ad822..2142790f 100644 --- a/internal/domain/main-entities/unit/entity.go +++ b/internal/domain/main-entities/unit/entity.go @@ -3,6 +3,7 @@ package unit import ( ecore "simrs-vx/internal/domain/base-entities/core" ei "simrs-vx/internal/domain/main-entities/installation" + eub "simrs-vx/internal/domain/main-entities/unit-position/base" ero "simrs-vx/internal/domain/references/organization" ) @@ -13,4 +14,5 @@ type Unit struct { Code string `json:"code" gorm:"unique;size:10"` Name string `json:"name" gorm:"size:50"` Type_Code *ero.UnitTypeCode `json:"type_code"` + UnitPositions []eub.Basic `json:"unitPositions,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` } From cdae478152a8b8e6229871fc3f6f9b79a0b142f8 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 24 Oct 2025 14:41:41 +0700 Subject: [PATCH 002/329] adjustment detail division --- internal/domain/main-entities/division/dto.go | 49 +++++++++++++++---- .../domain/main-entities/installation/dto.go | 5 +- internal/domain/main-entities/unit/dto.go | 1 + .../main-handler/division/handler.go | 2 + .../use-case/main-use-case/division/case.go | 46 +++++++++++++++-- .../use-case/main-use-case/division/lib.go | 4 +- 6 files changed, 91 insertions(+), 16 deletions(-) diff --git a/internal/domain/main-entities/division/dto.go b/internal/domain/main-entities/division/dto.go index 95ea9119..d82380a0 100644 --- a/internal/domain/main-entities/division/dto.go +++ b/internal/domain/main-entities/division/dto.go @@ -2,6 +2,10 @@ package division import ( ecore "simrs-vx/internal/domain/base-entities/core" + ep "simrs-vx/internal/domain/main-entities/person" + eu "simrs-vx/internal/domain/main-entities/user" + erc "simrs-vx/internal/domain/references/common" + erg "simrs-vx/internal/domain/references/organization" ) type CreateDto struct { @@ -26,8 +30,9 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` - Code *string `json:"code"` + Id uint16 `json:"id"` + Code *string `json:"code"` + Includes string `json:"includes"` } type UpdateDto struct { @@ -47,14 +52,36 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain - Code string `json:"code"` - Name string `json:"name"` - Parent_Id *uint16 `json:"parent_id"` - Parent *Division `json:"parent,omitempty"` - Childrens []Division `json:"childrens,omitempty"` + Code string `json:"code"` + Name string `json:"name"` + Parent_Id *uint16 `json:"parent_id"` + Parent *Division `json:"parent,omitempty"` + Childrens []Division `json:"childrens,omitempty"` + DivisionPosition []ResponseDivisionPosition `json:"divisionPositions,omitempty"` } -func (d Division) ToResponse() ResponseDto { +type ResponseDivisionPosition struct { + ecore.SmallMain // adjust this according to the needs + Division_Id *uint16 `json:"division_id"` + Code string `json:"code"` + Name string `json:"name"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` + Employee ResponseDivisionEmployee `json:"employee"` +} + +type ResponseDivisionEmployee struct { + ecore.Main // adjust this according to the needs + User_Id *uint `json:"user_id"` + User *eu.User `json:"user,omitempty"` + Person_Id *uint `json:"person_id"` + Person *ep.Person `json:"person,omitempty"` + Position_Code *erg.EmployeePositionCode `json:"position_code"` + Number *string `json:"number"` + Status_Code erc.ActiveStatusCode `json:"status_code"` +} + +func (d Division) ToResponse(divPos []ResponseDivisionPosition) ResponseDto { resp := ResponseDto{ Code: d.Code, Name: d.Name, @@ -63,13 +90,17 @@ func (d Division) ToResponse() ResponseDto { Childrens: d.Childrens, } resp.SmallMain = d.SmallMain + + if divPos != nil { + resp.DivisionPosition = divPos + } return resp } func ToResponseList(data []Division) []ResponseDto { resp := make([]ResponseDto, len(data)) for i, u := range data { - resp[i] = u.ToResponse() + resp[i] = u.ToResponse(nil) } return resp } diff --git a/internal/domain/main-entities/installation/dto.go b/internal/domain/main-entities/installation/dto.go index 55981981..24c75beb 100644 --- a/internal/domain/main-entities/installation/dto.go +++ b/internal/domain/main-entities/installation/dto.go @@ -27,8 +27,9 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` - Code *string `json:"code"` + Id uint16 `json:"id"` + Code *string `json:"code"` + Includes string `json:"includes"` } type UpdateDto struct { diff --git a/internal/domain/main-entities/unit/dto.go b/internal/domain/main-entities/unit/dto.go index 10960609..e294d950 100644 --- a/internal/domain/main-entities/unit/dto.go +++ b/internal/domain/main-entities/unit/dto.go @@ -29,6 +29,7 @@ type ReadDetailDto struct { Id uint16 `json:"id"` Installation_Id *uint16 `json:"installation_id"` Code *string `json:"code"` + Includes string `json:"includes"` } type UpdateDto struct { diff --git a/internal/interface/main-handler/division/handler.go b/internal/interface/main-handler/division/handler.go index 94940f55..ee4cbea5 100644 --- a/internal/interface/main-handler/division/handler.go +++ b/internal/interface/main-handler/division/handler.go @@ -37,7 +37,9 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { if id <= 0 { return } + dto := e.ReadDetailDto{} + sf.UrlQueryParam(&dto, *r.URL) dto.Id = uint16(id) res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) diff --git a/internal/use-case/main-use-case/division/case.go b/internal/use-case/main-use-case/division/case.go index daabd2f8..3f0353ae 100644 --- a/internal/use-case/main-use-case/division/case.go +++ b/internal/use-case/main-use-case/division/case.go @@ -2,8 +2,11 @@ package division import ( e "simrs-vx/internal/domain/main-entities/division" + edp "simrs-vx/internal/domain/main-entities/division-position" "strconv" + udp "simrs-vx/internal/use-case/main-use-case/division-position" + dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -61,7 +64,7 @@ func Create(input e.CreateDto) (*d.Data, error) { "structure": "single-data", "status": "created", }, - Data: data.ToResponse(), + Data: data.ToResponse(nil), }, nil } @@ -121,6 +124,7 @@ func ReadList(input e.ReadListDto) (*d.Data, error) { func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { var data *e.Division var err error + var dataDP []e.ResponseDivisionPosition event := pl.Event{ Feature: "ReadDetail", @@ -142,6 +146,40 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { return err } + // get data divisionPositions + dataDivisionPosition, err := udp.ReadList(edp.ReadListDto{ + FilterDto: edp.FilterDto{ + Division_Id: &input.Id, + }, + Includes: "employee,employee.User", + }) + if err != nil { + return err + } + + list, _ := dataDivisionPosition.Data.([]edp.ResponseDto) + if len(list) > 0 { + for _, dp := range list { + dataDP = append(dataDP, e.ResponseDivisionPosition{ + SmallMain: dp.SmallMain, + Division_Id: &dp.Id, + Code: dp.Code, + Name: dp.Name, + HeadStatus: dp.HeadStatus, + Employee_Id: dp.Employee_Id, + Employee: e.ResponseDivisionEmployee{ + Main: dp.Employee.Main, + User_Id: dp.Employee.User_Id, + User: dp.Employee.User, + Person_Id: dp.Employee.Person_Id, + Person: dp.Employee.Person, + Number: dp.Employee.Number, + Status_Code: dp.Employee.Status_Code, + }, + }) + } + } + mwRunner.setMwType(pu.MWTPost) // Run post-middleware if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { @@ -161,7 +199,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { "structure": "single-data", "status": "fetched", }, - Data: data.ToResponse(), + Data: data.ToResponse(dataDP), }, nil } @@ -216,7 +254,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { "structure": "single-data", "status": "updated", }, - Data: data.ToResponse(), + Data: data.ToResponse(nil), }, nil } @@ -270,7 +308,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { "structure": "single-data", "status": "deleted", }, - Data: data.ToResponse(), + Data: data.ToResponse(nil), }, nil } diff --git a/internal/use-case/main-use-case/division/lib.go b/internal/use-case/main-use-case/division/lib.go index 828395e7..56ce34f7 100644 --- a/internal/use-case/main-use-case/division/lib.go +++ b/internal/use-case/main-use-case/division/lib.go @@ -91,7 +91,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 } From fa1374484a3ea098b361da1a13eaa3bdd6cf7a77 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 24 Oct 2025 14:44:04 +0700 Subject: [PATCH 003/329] remove division in employee --- cmd/main-migration/migrations/20251024074315.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 3 ++- internal/domain/main-entities/employee/dto.go | 14 ++++++-------- internal/domain/main-entities/employee/entity.go | 3 --- 4 files changed, 10 insertions(+), 12 deletions(-) create mode 100644 cmd/main-migration/migrations/20251024074315.sql diff --git a/cmd/main-migration/migrations/20251024074315.sql b/cmd/main-migration/migrations/20251024074315.sql new file mode 100644 index 00000000..99b3b76b --- /dev/null +++ b/cmd/main-migration/migrations/20251024074315.sql @@ -0,0 +1,2 @@ +-- Modify "Employee" table +ALTER TABLE "public"."Employee" DROP COLUMN "Division_Code"; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index a52827a6..9f6394ae 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:fAJxBGCfoMXYDjYBlq6RITZ/dXbqiYtQWwupcBMLHV0= +h1:XE6wCH2XnIm3XpP9itgkMFv8CCrc2SOb51W/bA5h3Uk= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -57,3 +57,4 @@ h1:fAJxBGCfoMXYDjYBlq6RITZ/dXbqiYtQWwupcBMLHV0= 20251021075552.sql h1:8gfSMAglflNO6L0sSzxFNEubYN8/O4thT7OQT+WH+3M= 20251023044432.sql h1:MkvajJs3bfk9+wHvQ43/ccAluJEBARm1gWr1u92ccLA= 20251024034832.sql h1:x3s3VEVYLOSKLAFxJGb2+c1FyTMMvPE+9k4Ew7rKQaI= +20251024074315.sql h1:GkocUmXpU1QiZpjvELK4e6sKASxiS3kZTk+35Iux2ds= diff --git a/internal/domain/main-entities/employee/dto.go b/internal/domain/main-entities/employee/dto.go index 9e0e93d2..ff8f6adf 100644 --- a/internal/domain/main-entities/employee/dto.go +++ b/internal/domain/main-entities/employee/dto.go @@ -68,14 +68,12 @@ type ResponseDto struct { func (d Employee) ToResponse() ResponseDto { resp := ResponseDto{ - User_Id: d.User_Id, - User: d.User, - Person_Id: d.Person_Id, - Person: d.Person, - Division_Code: d.Division_Code, - Division: d.Division, - Number: d.Number, - Status_Code: d.Status_Code, + User_Id: d.User_Id, + User: d.User, + Person_Id: d.Person_Id, + Person: d.Person, + Number: d.Number, + Status_Code: d.Status_Code, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/employee/entity.go b/internal/domain/main-entities/employee/entity.go index 1177abe9..7a770be0 100644 --- a/internal/domain/main-entities/employee/entity.go +++ b/internal/domain/main-entities/employee/entity.go @@ -2,7 +2,6 @@ package employee import ( ecore "simrs-vx/internal/domain/base-entities/core" - ed "simrs-vx/internal/domain/main-entities/division" ep "simrs-vx/internal/domain/main-entities/person" eu "simrs-vx/internal/domain/main-entities/user" erc "simrs-vx/internal/domain/references/common" @@ -16,8 +15,6 @@ type Employee struct { Person_Id *uint `json:"person_id"` Person *ep.Person `json:"person,omitempty" gorm:"foreignKey:Person_Id;references:Id"` Position_Code *erg.EmployeePositionCode `json:"position_code" gorm:"size:20"` - Division_Code *string `json:"division_code"` - Division *ed.Division `json:"division,omitempty" gorm:"foreignKey:Division_Code;references:Code"` Number *string `json:"number" gorm:"size:20"` Status_Code erc.ActiveStatusCode `json:"status_code" gorm:"not null;size:10"` } From 49f0509273fafd5e91861d968109fb4abf98d717 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 24 Oct 2025 14:53:44 +0700 Subject: [PATCH 004/329] adjustment division-position --- .../division-position/base/entity.go | 14 ++++++----- .../main-entities/division-position/entity.go | 2 -- internal/domain/main-entities/employee/dto.go | 25 ++++++++----------- 3 files changed, 18 insertions(+), 23 deletions(-) diff --git a/internal/domain/main-entities/division-position/base/entity.go b/internal/domain/main-entities/division-position/base/entity.go index d44c0b86..ce8f3175 100644 --- a/internal/domain/main-entities/division-position/base/entity.go +++ b/internal/domain/main-entities/division-position/base/entity.go @@ -2,15 +2,17 @@ package base import ( ecore "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/employee" ) type Basic struct { - ecore.SmallMain // adjust this according to the needs - Division_Id *uint16 `json:"division_id"` - Code string `json:"code" gorm:"unique;size:10"` - Name string `json:"name" gorm:"size:50"` - HeadStatus bool `json:"headStatus"` - Employee_Id *uint `json:"employee_id"` + ecore.SmallMain // adjust this according to the needs + Division_Id *uint16 `json:"division_id"` + Code string `json:"code" gorm:"unique;size:10"` + Name string `json:"name" gorm:"size:50"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` + Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` } func (Basic) TableName() string { diff --git a/internal/domain/main-entities/division-position/entity.go b/internal/domain/main-entities/division-position/entity.go index 79379b52..d71ba01c 100644 --- a/internal/domain/main-entities/division-position/entity.go +++ b/internal/domain/main-entities/division-position/entity.go @@ -3,11 +3,9 @@ package divisionposition import ( ed "simrs-vx/internal/domain/main-entities/division" eb "simrs-vx/internal/domain/main-entities/division-position/base" - ee "simrs-vx/internal/domain/main-entities/employee" ) type DivisionPosition struct { eb.Basic Division *ed.Division `json:"division" gorm:"foreignKey:Division_Id;references:Id"` - Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` } diff --git a/internal/domain/main-entities/employee/dto.go b/internal/domain/main-entities/employee/dto.go index ff8f6adf..d11ccae0 100644 --- a/internal/domain/main-entities/employee/dto.go +++ b/internal/domain/main-entities/employee/dto.go @@ -2,7 +2,6 @@ package employee import ( ecore "simrs-vx/internal/domain/base-entities/core" - ed "simrs-vx/internal/domain/main-entities/division" ep "simrs-vx/internal/domain/main-entities/person" eu "simrs-vx/internal/domain/main-entities/user" @@ -10,11 +9,10 @@ import ( ) type CreateDto struct { - User_Id *uint `json:"user_id"` - Person_Id *uint `json:"person_id"` - Division_Code *string `json:"division_code"` - Number *string `json:"number" validate:"maxLength=20"` - Status_Code erc.ActiveStatusCode `json:"status_code" validate:"maxLength=10"` + User_Id *uint `json:"user_id"` + Person_Id *uint `json:"person_id"` + Number *string `json:"number" validate:"maxLength=20"` + Status_Code erc.ActiveStatusCode `json:"status_code" validate:"maxLength=10"` } type ReadListDto struct { @@ -26,7 +24,6 @@ type ReadListDto struct { type FilterDto struct { User_Id *uint `json:"user-id"` Person_Id *uint `json:"person-id"` - Division_Code *string `json:"division-code"` Position_Code *string `json:"position-code"` Number *string `json:"number"` Status_Code erc.ActiveStatusCode `json:"status-code"` @@ -56,14 +53,12 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - User_Id *uint `json:"user_id"` - User *eu.User `json:"user,omitempty"` - Person_Id *uint `json:"person_id"` - Person *ep.Person `json:"person,omitempty"` - Division_Code *string `json:"division_code"` - Division *ed.Division `json:"division,omitempty"` - Number *string `json:"number"` - Status_Code erc.ActiveStatusCode `json:"status_code"` + User_Id *uint `json:"user_id"` + User *eu.User `json:"user,omitempty"` + Person_Id *uint `json:"person_id"` + Person *ep.Person `json:"person,omitempty"` + Number *string `json:"number"` + Status_Code erc.ActiveStatusCode `json:"status_code"` } func (d Employee) ToResponse() ResponseDto { From 69f80b45ef5a496dacc8fefb6580535aa94c26a5 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 24 Oct 2025 15:39:14 +0700 Subject: [PATCH 005/329] adjustment detail installation --- internal/domain/main-entities/employee/dto.go | 10 +++-- .../domain/main-entities/installation/dto.go | 15 ++++--- internal/domain/main-entities/unit/dto.go | 7 ++- .../main-handler/installation/handler.go | 2 + .../interface/main-handler/unit/handler.go | 2 + .../main-use-case/authentication/case.go | 12 ++--- .../use-case/main-use-case/division/case.go | 45 ++----------------- .../use-case/main-use-case/employee/helper.go | 1 - .../main-use-case/installation/lib.go | 4 +- internal/use-case/main-use-case/unit/lib.go | 4 +- .../use-case/main-use-case/user/helper.go | 1 - 11 files changed, 40 insertions(+), 63 deletions(-) diff --git a/internal/domain/main-entities/employee/dto.go b/internal/domain/main-entities/employee/dto.go index d11ccae0..85b7008a 100644 --- a/internal/domain/main-entities/employee/dto.go +++ b/internal/domain/main-entities/employee/dto.go @@ -6,13 +6,15 @@ import ( eu "simrs-vx/internal/domain/main-entities/user" erc "simrs-vx/internal/domain/references/common" + erg "simrs-vx/internal/domain/references/organization" ) type CreateDto struct { - User_Id *uint `json:"user_id"` - Person_Id *uint `json:"person_id"` - Number *string `json:"number" validate:"maxLength=20"` - Status_Code erc.ActiveStatusCode `json:"status_code" validate:"maxLength=10"` + User_Id *uint `json:"user_id"` + Person_Id *uint `json:"person_id"` + Number *string `json:"number" validate:"maxLength=20"` + Status_Code erc.ActiveStatusCode `json:"status_code" validate:"maxLength=10"` + Position_Code *erg.EmployeePositionCode `json:"position_code"` } type ReadListDto struct { diff --git a/internal/domain/main-entities/installation/dto.go b/internal/domain/main-entities/installation/dto.go index 24c75beb..302025d8 100644 --- a/internal/domain/main-entities/installation/dto.go +++ b/internal/domain/main-entities/installation/dto.go @@ -2,6 +2,7 @@ package installation import ( ecore "simrs-vx/internal/domain/base-entities/core" + eipb "simrs-vx/internal/domain/main-entities/installation-position/base" ere "simrs-vx/internal/domain/references/encounter" ) @@ -49,16 +50,18 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain - Code string `json:"code"` - Name string `json:"name"` - EncounterClass_Code ere.EncounterClassCode `json:"encounterClass_code"` + Code string `json:"code"` + Name string `json:"name"` + EncounterClass_Code ere.EncounterClassCode `json:"encounterClass_code"` + InstallationPositions []eipb.Basic `json:"installationPositions,omitempty"` } func (d Installation) ToResponse() ResponseDto { resp := ResponseDto{ - Code: d.Code, - Name: d.Name, - EncounterClass_Code: d.EncounterClass_Code, + Code: d.Code, + Name: d.Name, + EncounterClass_Code: d.EncounterClass_Code, + InstallationPositions: d.InstallationPositions, } resp.SmallMain = d.SmallMain return resp diff --git a/internal/domain/main-entities/unit/dto.go b/internal/domain/main-entities/unit/dto.go index e294d950..ce1dd505 100644 --- a/internal/domain/main-entities/unit/dto.go +++ b/internal/domain/main-entities/unit/dto.go @@ -3,6 +3,7 @@ package unit import ( ecore "simrs-vx/internal/domain/base-entities/core" ei "simrs-vx/internal/domain/main-entities/installation" + eipb "simrs-vx/internal/domain/main-entities/unit-position/base" ) type CreateDto struct { @@ -51,8 +52,9 @@ type ResponseDto struct { ecore.SmallMain Installation_Id *uint16 `json:"installation_id"` Installation *ei.Installation - Code string `json:"code"` - Name string `json:"name"` + Code string `json:"code"` + Name string `json:"name"` + UnitPositions []eipb.Basic `json:"unitPositions,omitempty"` } func (d Unit) ToResponse() ResponseDto { @@ -60,6 +62,7 @@ func (d Unit) ToResponse() ResponseDto { Installation_Id: d.Installation_Id, Code: d.Code, Name: d.Name, + UnitPositions: d.UnitPositions, } resp.SmallMain = d.SmallMain if d.Installation != nil { diff --git a/internal/interface/main-handler/installation/handler.go b/internal/interface/main-handler/installation/handler.go index dd5903f8..26885689 100644 --- a/internal/interface/main-handler/installation/handler.go +++ b/internal/interface/main-handler/installation/handler.go @@ -38,6 +38,8 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { return } dto := e.ReadDetailDto{} + + sf.UrlQueryParam(&dto, *r.URL) dto.Id = uint16(id) res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) diff --git a/internal/interface/main-handler/unit/handler.go b/internal/interface/main-handler/unit/handler.go index 0abc9a21..a94ce74e 100644 --- a/internal/interface/main-handler/unit/handler.go +++ b/internal/interface/main-handler/unit/handler.go @@ -38,6 +38,8 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { return } dto := e.ReadDetailDto{} + + sf.UrlQueryParam(&dto, *r.URL) dto.Id = uint16(id) res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) diff --git a/internal/use-case/main-use-case/authentication/case.go b/internal/use-case/main-use-case/authentication/case.go index da454333..5b9952a3 100644 --- a/internal/use-case/main-use-case/authentication/case.go +++ b/internal/use-case/main-use-case/authentication/case.go @@ -120,10 +120,10 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { outputData["employee_id"] = employee.Id role = append(role, "emp-"+string(*employee.Position_Code)) - if employee.Division_Code != nil { - atClaims["employee_division_code"] = employee.Division_Code - outputData["employee_division_code"] = employee.Division_Code - } + //if employee.Division_Code != nil { + // atClaims["employee_division_code"] = employee.Division_Code + // outputData["employee_division_code"] = employee.Division_Code + //} // employee position if employee.Id > 0 && employee.Position_Code != nil { @@ -159,7 +159,7 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: el.GenMessage("auth-getData-failed")}} // division position - divsionPositions, err := getDivisionPosition(employee.Id) + divisionPositions, err := getDivisionPosition(employee.Id) if err != nil { return nil, errorGetPosition } @@ -188,7 +188,7 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { return nil, errorGetPosition } - role = append(role, divsionPositions...) + role = append(role, divisionPositions...) role = append(role, installationPositions...) role = append(role, unitPositions...) role = append(role, specialistPositions...) diff --git a/internal/use-case/main-use-case/division/case.go b/internal/use-case/main-use-case/division/case.go index 9699e124..daabd2f8 100644 --- a/internal/use-case/main-use-case/division/case.go +++ b/internal/use-case/main-use-case/division/case.go @@ -2,11 +2,8 @@ package division import ( e "simrs-vx/internal/domain/main-entities/division" - edp "simrs-vx/internal/domain/main-entities/division-position" "strconv" - udp "simrs-vx/internal/use-case/main-use-case/division-position" - dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -64,7 +61,7 @@ func Create(input e.CreateDto) (*d.Data, error) { "structure": "single-data", "status": "created", }, - Data: data.ToResponse(nil), + Data: data.ToResponse(), }, nil } @@ -145,40 +142,6 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { return err } - // get data divisionPositions - dataDivisionPosition, err := udp.ReadList(edp.ReadListDto{ - FilterDto: edp.FilterDto{ - Division_Id: &input.Id, - }, - Includes: "employee,employee.User", - }) - if err != nil { - return err - } - - list, _ := dataDivisionPosition.Data.([]edp.ResponseDto) - if len(list) > 0 { - for _, dp := range list { - dataDP = append(dataDP, e.ResponseDivisionPosition{ - SmallMain: dp.SmallMain, - Division_Id: &dp.Id, - Code: dp.Code, - Name: dp.Name, - HeadStatus: dp.HeadStatus, - Employee_Id: dp.Employee_Id, - Employee: e.ResponseDivisionEmployee{ - Main: dp.Employee.Main, - User_Id: dp.Employee.User_Id, - User: dp.Employee.User, - Person_Id: dp.Employee.Person_Id, - Person: dp.Employee.Person, - Number: dp.Employee.Number, - Status_Code: dp.Employee.Status_Code, - }, - }) - } - } - mwRunner.setMwType(pu.MWTPost) // Run post-middleware if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { @@ -198,7 +161,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { "structure": "single-data", "status": "fetched", }, - Data: data.ToResponse(dataDP), + Data: data.ToResponse(), }, nil } @@ -253,7 +216,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { "structure": "single-data", "status": "updated", }, - Data: data.ToResponse(nil), + Data: data.ToResponse(), }, nil } @@ -307,7 +270,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { "structure": "single-data", "status": "deleted", }, - Data: data.ToResponse(nil), + Data: data.ToResponse(), }, nil } diff --git a/internal/use-case/main-use-case/employee/helper.go b/internal/use-case/main-use-case/employee/helper.go index b0202c08..e13ce535 100644 --- a/internal/use-case/main-use-case/employee/helper.go +++ b/internal/use-case/main-use-case/employee/helper.go @@ -19,7 +19,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Employee) { data.User_Id = inputSrc.User_Id data.Person_Id = inputSrc.Person_Id - data.Division_Code = inputSrc.Division_Code data.Number = inputSrc.Number data.Status_Code = inputSrc.Status_Code data.Position_Code = inputSrc.Position_Code diff --git a/internal/use-case/main-use-case/installation/lib.go b/internal/use-case/main-use-case/installation/lib.go index fd0158ee..82130c32 100644 --- a/internal/use-case/main-use-case/installation/lib.go +++ b/internal/use-case/main-use-case/installation/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/unit/lib.go b/internal/use-case/main-use-case/unit/lib.go index c79c1373..1a3e5652 100644 --- a/internal/use-case/main-use-case/unit/lib.go +++ b/internal/use-case/main-use-case/unit/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/user/helper.go b/internal/use-case/main-use-case/user/helper.go index cb640dcb..acb32331 100644 --- a/internal/use-case/main-use-case/user/helper.go +++ b/internal/use-case/main-use-case/user/helper.go @@ -46,7 +46,6 @@ func setDataEmployeeUpdate(src e.EmployeUpdateDto) ee.UpdateDto { CreateDto: ee.CreateDto{ User_Id: src.User_Id, Person_Id: src.Person_Id, - Division_Code: src.Division_Code, Number: src.Number, Status_Code: src.Status_Code, Position_Code: &src.Position_Code, From d70a0a47f3f6d5554ae54395bf7ed04561d720f1 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 24 Oct 2025 15:41:26 +0700 Subject: [PATCH 006/329] adjustment unit-position entity --- cmd/main-migration/migrations/atlas.sum | 4 ++-- .../main-entities/unit-position/base/entity.go | 14 ++++++++------ .../domain/main-entities/unit-position/entity.go | 4 +--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 9f6394ae..9a03ed9b 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:XE6wCH2XnIm3XpP9itgkMFv8CCrc2SOb51W/bA5h3Uk= +h1:ieMeKh35/dro1YBBO11ZP0nZan9aJ5aFSqnEAi+T+WQ= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -57,4 +57,4 @@ h1:XE6wCH2XnIm3XpP9itgkMFv8CCrc2SOb51W/bA5h3Uk= 20251021075552.sql h1:8gfSMAglflNO6L0sSzxFNEubYN8/O4thT7OQT+WH+3M= 20251023044432.sql h1:MkvajJs3bfk9+wHvQ43/ccAluJEBARm1gWr1u92ccLA= 20251024034832.sql h1:x3s3VEVYLOSKLAFxJGb2+c1FyTMMvPE+9k4Ew7rKQaI= -20251024074315.sql h1:GkocUmXpU1QiZpjvELK4e6sKASxiS3kZTk+35Iux2ds= +20251024074315.sql h1:EjAjelgi5qAfcRq/8vPTlGGYHvAKxNTllm8f0SzZDns= diff --git a/internal/domain/main-entities/unit-position/base/entity.go b/internal/domain/main-entities/unit-position/base/entity.go index 3d913d4f..b8e6a63a 100644 --- a/internal/domain/main-entities/unit-position/base/entity.go +++ b/internal/domain/main-entities/unit-position/base/entity.go @@ -2,15 +2,17 @@ package base import ( ecore "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/employee" ) type Basic struct { - ecore.SmallMain // adjust this according to the needs - Unit_Id *uint16 `json:"unit_id" gorm:"not null"` - Code string `json:"code" gorm:"unique;size:10;not null"` - Name string `json:"name" gorm:"size:30;not null"` - HeadStatus bool `json:"headStatus"` - Employee_Id *uint `json:"employee_id"` + ecore.SmallMain // adjust this according to the needs + Unit_Id *uint16 `json:"unit_id" gorm:"not null"` + Code string `json:"code" gorm:"unique;size:10;not null"` + Name string `json:"name" gorm:"size:30;not null"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` + Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` } func (Basic) TableName() string { diff --git a/internal/domain/main-entities/unit-position/entity.go b/internal/domain/main-entities/unit-position/entity.go index 5450cee2..9966cd4a 100644 --- a/internal/domain/main-entities/unit-position/entity.go +++ b/internal/domain/main-entities/unit-position/entity.go @@ -1,13 +1,11 @@ package unit_position import ( - ee "simrs-vx/internal/domain/main-entities/employee" eu "simrs-vx/internal/domain/main-entities/unit" eub "simrs-vx/internal/domain/main-entities/unit-position/base" ) type UnitPosition struct { eub.Basic - Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` - Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` + Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` } From e4093587e761ae048f8c1a37ecac6b1753433cb7 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Fri, 24 Oct 2025 15:50:12 +0700 Subject: [PATCH 007/329] wip --- internal/domain/references/person/person.go | 26 +++++++++++---------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/internal/domain/references/person/person.go b/internal/domain/references/person/person.go index 02d0f97e..a9ee5efb 100644 --- a/internal/domain/references/person/person.go +++ b/internal/domain/references/person/person.go @@ -42,18 +42,20 @@ const ( RCBudha ReligionCode = "budha" RCKonghucu ReligionCode = "konghucu" - ECTS EducationCode = "TS" - ECTK EducationCode = "TK" - ECSD EducationCode = "SD" - ECSLTP EducationCode = "SMP" - ECSLTA EducationCode = "SMA" - ECD1 EducationCode = "D1" - ECD2 EducationCode = "D2" - ECD3 EducationCode = "D3" - ECD4 EducationCode = "D4" - ECS1 EducationCode = "S1" - ECS2 EducationCode = "S2" - ECS3 EducationCode = "S3" + ECTS EducationCode = "TS" + ECTK EducationCode = "TK" + ECSD EducationCode = "SD" + ECSLTP EducationCode = "SMP" + ECSLTA EducationCode = "SMA" + ECD1 EducationCode = "D1" + ECD2 EducationCode = "D2" + ECD3 EducationCode = "D3" + ECD4 EducationCode = "D4" + ECS1 EducationCode = "S1" + ECS2 EducationCode = "S2" + ECS3 EducationCode = "S3" + ECOther EducationCode = "other" + ECUnkown EducationCode = "unknown" OCTidakBekerja OcupationCode = "tidak-bekerja" OCPns OcupationCode = "pns" From bc76f9e98599a2e3c01519b8b9c72967bce3eb4a Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 24 Oct 2025 16:04:09 +0700 Subject: [PATCH 008/329] adjustment detail installation,specialis, subspecialist --- .../domain/main-entities/specialist/dto.go | 20 +++++++++++-------- .../domain/main-entities/subspecialist/dto.go | 14 ++++++++----- .../main-handler/specialist/handler.go | 2 ++ .../main-handler/subspecialist/handler.go | 2 ++ .../use-case/main-use-case/specialist/lib.go | 4 +++- .../main-use-case/subspecialist/lib.go | 4 +++- 6 files changed, 31 insertions(+), 15 deletions(-) diff --git a/internal/domain/main-entities/specialist/dto.go b/internal/domain/main-entities/specialist/dto.go index f1338c19..3fa6bf5e 100644 --- a/internal/domain/main-entities/specialist/dto.go +++ b/internal/domain/main-entities/specialist/dto.go @@ -2,6 +2,7 @@ package specialist import ( ecore "simrs-vx/internal/domain/base-entities/core" + espb "simrs-vx/internal/domain/main-entities/specialist-position/base" ) type CreateDto struct { @@ -25,8 +26,9 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` - Code *string `json:"code"` + Id uint16 `json:"id"` + Code *string `json:"code"` + Includes string `json:"includes"` } type UpdateDto struct { @@ -46,16 +48,18 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain - Code string `json:"code"` - Name string `json:"name"` - Unit_Id *uint16 `json:"unit_id"` + Code string `json:"code"` + Name string `json:"name"` + Unit_Id *uint16 `json:"unit_id"` + SpecialistPositions []espb.Basic `json:"specialistPositions,omitempty"` } func (d Specialist) ToResponse() ResponseDto { resp := ResponseDto{ - Code: d.Code, - Name: d.Name, - Unit_Id: d.Unit_Id, + Code: d.Code, + Name: d.Name, + Unit_Id: d.Unit_Id, + SpecialistPositions: d.SpecialistPositions, } resp.SmallMain = d.SmallMain return resp diff --git a/internal/domain/main-entities/subspecialist/dto.go b/internal/domain/main-entities/subspecialist/dto.go index e28f96ae..ed0c97aa 100644 --- a/internal/domain/main-entities/subspecialist/dto.go +++ b/internal/domain/main-entities/subspecialist/dto.go @@ -2,6 +2,7 @@ package subspecialist import ( ecore "simrs-vx/internal/domain/base-entities/core" + espb "simrs-vx/internal/domain/main-entities/subspecialist-position/base" ) type CreateDto struct { @@ -25,8 +26,9 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` - Code *string `json:"code"` + Id uint16 `json:"id"` + Code *string `json:"code"` + Includes string `json:"includes"` } type UpdateDto struct { @@ -46,9 +48,10 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain - Code string `json:"code"` - Name string `json:"name"` - Specialist_Id *uint16 `json:"specialist_id"` + Code string `json:"code"` + Name string `json:"name"` + Specialist_Id *uint16 `json:"specialist_id"` + Subspecialist []espb.Basic `json:"subspecialistPositions,omitempty"` } func (d Subspecialist) ToResponse() ResponseDto { @@ -56,6 +59,7 @@ func (d Subspecialist) ToResponse() ResponseDto { Code: d.Code, Name: d.Name, Specialist_Id: d.Specialist_Id, + Subspecialist: d.SubspecialistPositions, } resp.SmallMain = d.SmallMain return resp diff --git a/internal/interface/main-handler/specialist/handler.go b/internal/interface/main-handler/specialist/handler.go index 561d07d0..d3a074d8 100644 --- a/internal/interface/main-handler/specialist/handler.go +++ b/internal/interface/main-handler/specialist/handler.go @@ -38,6 +38,8 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { return } dto := e.ReadDetailDto{} + + sf.UrlQueryParam(&dto, *r.URL) dto.Id = uint16(id) res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) diff --git a/internal/interface/main-handler/subspecialist/handler.go b/internal/interface/main-handler/subspecialist/handler.go index d639c115..c4b933b4 100644 --- a/internal/interface/main-handler/subspecialist/handler.go +++ b/internal/interface/main-handler/subspecialist/handler.go @@ -38,6 +38,8 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { return } dto := e.ReadDetailDto{} + + sf.UrlQueryParam(&dto, *r.URL) dto.Id = uint16(id) res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) diff --git a/internal/use-case/main-use-case/specialist/lib.go b/internal/use-case/main-use-case/specialist/lib.go index 10f62ced..3e35d004 100644 --- a/internal/use-case/main-use-case/specialist/lib.go +++ b/internal/use-case/main-use-case/specialist/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/subspecialist/lib.go b/internal/use-case/main-use-case/subspecialist/lib.go index 5843086f..46ec11f2 100644 --- a/internal/use-case/main-use-case/subspecialist/lib.go +++ b/internal/use-case/main-use-case/subspecialist/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 } From 4ebeee02f09c3195a4e8073ec43093f3d2080169 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Fri, 24 Oct 2025 16:21:57 +0700 Subject: [PATCH 009/329] feat (patient): rework search --- internal/domain/main-entities/patient/dto.go | 4 +- .../interface/main-handler/main-handler.go | 2 +- .../interface/main-handler/patient/handler.go | 9 +-- .../use-case/main-use-case/patient/case.go | 46 +++++++++++- .../use-case/main-use-case/patient/lib.go | 71 ++++++++++++++----- 5 files changed, 103 insertions(+), 29 deletions(-) diff --git a/internal/domain/main-entities/patient/dto.go b/internal/domain/main-entities/patient/dto.go index 00134b6e..4927a50e 100644 --- a/internal/domain/main-entities/patient/dto.go +++ b/internal/domain/main-entities/patient/dto.go @@ -57,8 +57,8 @@ type DeleteDto struct { } type SearchDto struct { - Search string `json:"search"` - Mode SearchMode `json:"mode"` + Search string `json:"search"` + Pagination ecore.Pagination } type UploadDto struct { diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 690a830a..6a98487f 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -274,7 +274,7 @@ func SetRoutes() http.Handler { "PATCH /{id}": patient.O.Update, "DELETE /{id}": patient.O.Delete, "GET /search/{keyword}": patient.O.Search, - "GET /by-resident-identity": patient.O.SearchByResidentIdentity, + "GET /by-resident-identity": patient.O.SearchByResidentIdentityNumber, "POST /{id}/upload": patient.O.Upload, }) diff --git a/internal/interface/main-handler/patient/handler.go b/internal/interface/main-handler/patient/handler.go index 2c5fcb5b..1d02d8d7 100644 --- a/internal/interface/main-handler/patient/handler.go +++ b/internal/interface/main-handler/patient/handler.go @@ -76,21 +76,22 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { func (obj myBase) Search(w http.ResponseWriter, r *http.Request) { dto := e.SearchDto{} + + sf.UrlQueryParam(&dto, *r.URL) keyword := rw.ValidateString(w, "keyword", r.PathValue("keyword")) if keyword == "" { rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "keyword is required"}, nil) } - dto.Mode = e.SMIdent + dto.Search = keyword res, err := u.Search(dto) rw.DataResponse(w, res, err) } -func (obj myBase) SearchByResidentIdentity(w http.ResponseWriter, r *http.Request) { +func (obj myBase) SearchByResidentIdentityNumber(w http.ResponseWriter, r *http.Request) { dto := e.SearchDto{} sf.UrlQueryParam(&dto, *r.URL) - dto.Mode = e.SMNik - res, err := u.Search(dto) + res, err := u.SearchByResidentIdentityNumber(dto) rw.DataResponse(w, res, err) } diff --git a/internal/use-case/main-use-case/patient/case.go b/internal/use-case/main-use-case/patient/case.go index fd17d7fb..b52215ac 100644 --- a/internal/use-case/main-use-case/patient/case.go +++ b/internal/use-case/main-use-case/patient/case.go @@ -352,18 +352,18 @@ func Delete(input e.DeleteDto) (*d.Data, error) { } -func Search(input e.SearchDto) (*d.Data, error) { +func SearchByResidentIdentityNumber(input e.SearchDto) (*d.Data, error) { var data *e.Patient var err error event := pl.Event{ - Feature: "Search", + Feature: "Search By Resident Identity Number", Source: source, } // Start log pl.SetLogInfo(&event, input, "started", "search") - if data, err = SearchData(input, &event); err != nil { + if data, err = SearchDataByRIN(input, &event); err != nil { return nil, err } @@ -377,6 +377,46 @@ func Search(input e.SearchDto) (*d.Data, error) { }, nil } +func Search(input e.SearchDto) (*d.Data, error) { + var dataList []e.Patient + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "Search", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readList") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + + if dataList, metaList, err = SearchData(input, &event, tx); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + func Upload(input e.UploadDto) (*d.Data, error) { rdDto := e.ReadDetailDto{Id: uint16(input.Id)} var data *e.Patient diff --git a/internal/use-case/main-use-case/patient/lib.go b/internal/use-case/main-use-case/patient/lib.go index f35e3853..36c9d416 100644 --- a/internal/use-case/main-use-case/patient/lib.go +++ b/internal/use-case/main-use-case/patient/lib.go @@ -154,11 +154,11 @@ func DeleteData(data *e.Patient, event *pl.Event, dbx ...*gorm.DB) error { return nil } -func SearchData(input e.SearchDto, event *pl.Event, dbx ...*gorm.DB) (*e.Patient, error) { +// Search By Resident Identity Number +func SearchDataByRIN(input e.SearchDto, event *pl.Event, dbx ...*gorm.DB) (*e.Patient, error) { pl.SetLogInfo(event, input, "started", "DBSearch") - var patient e.Patient - var err error + var data e.Patient var tx *gorm.DB if len(dbx) > 0 { @@ -174,27 +174,60 @@ func SearchData(input e.SearchDto, event *pl.Event, dbx ...*gorm.DB) (*e.Patient Preload("Person.Relatives"). Preload("Person.Insurances") - switch input.Mode { - case e.SMIdent: - // Search by patient number OR person's resident identity number (exact match) OR person's name (partial match) - err = tx.Joins("JOIN \"Person\" ON \"Patient\".\"Person_Id\" = \"Person\".\"Id\""). - Where("\"Patient\".\"Number\" = ? OR \"Person\".\"ResidentIdentityNumber\" = ? OR \"Person\".\"Name\" ILIKE ?", - input.Search, input.Search, "%"+input.Search+"%"). - First(&patient).Error - case e.SMNik: - // Search by patient person's resident identity number (exact match) - err = tx.Joins("JOIN \"Person\" ON \"Patient\".\"Person_Id\" = \"Person\".\"Id\""). - Where("\"Person\".\"ResidentIdentityNumber\" = ?", - input.Search). - First(&patient).Error - } + // Search by patient person's resident identity number (exact match) + err := tx.Joins("JOIN \"Person\" ON \"Patient\".\"Person_Id\" = \"Person\".\"Id\""). + Where("\"Person\".\"ResidentIdentityNumber\" = ?", + input.Search). + First(&data).Error if err != nil { - if processedErr := pu.HandleSearchError(err, event, source, input.Search, patient); processedErr != nil { + if processedErr := pu.HandleSearchError(err, event, source, input.Search, data); processedErr != nil { return nil, processedErr } } pl.SetLogInfo(event, nil, "complete") - return &patient, nil + return &data, nil +} + +func SearchData(input e.SearchDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Patient, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBSearch") + + var data []e.Patient + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + // Preload associations for complete data + tx = tx.Preload(clause.Associations) + tx = tx.Preload("Person.Addresses"). + Preload("Person.Contacts"). + Preload("Person.Relatives"). + Preload("Person.Insurances") + + // Search by patient number OR person's resident identity number (exact match) OR person's name (partial match) + tx = tx.Joins("JOIN \"Person\" ON \"Patient\".\"Person_Id\" = \"Person\".\"Id\""). + Where("\"Patient\".\"Number\" ILIKE ? OR \"Person\".\"ResidentIdentityNumber\" ILIKE ? OR \"Person\".\"Name\" ILIKE ?", + "%"+input.Search+"%", "%"+input.Search+"%", "%"+input.Search+"%") + err := tx.Scopes(gh.Paginate(input, &pagination)).Find(&data).Error + + if err != nil { + if processedErr := pu.HandleSearchError(err, event, source, input.Search, data); processedErr != nil { + return nil, nil, processedErr + } + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil } From a7ce13c76e74ace50747d8a187f913e11544d4a7 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 24 Oct 2025 16:45:00 +0700 Subject: [PATCH 010/329] add crud responsible doctor hist and adm employee hist --- .../main-entities/adm-employee-hist/dto.go | 78 +++++ .../responsible-doctor-hist/dto.go | 78 +++++ .../main-handler/adm-employee-hist/handler.go | 71 ++++ .../interface/main-handler/main-handler.go | 4 + .../responsible-doctor-hist/handler.go | 71 ++++ .../main-use-case/adm-employee-hist/case.go | 303 ++++++++++++++++++ .../main-use-case/adm-employee-hist/helper.go | 24 ++ .../main-use-case/adm-employee-hist/lib.go | 156 +++++++++ .../adm-employee-hist/middleware-runner.go | 103 ++++++ .../adm-employee-hist/middleware.go | 9 + .../adm-employee-hist/tycovar.go | 44 +++ .../responsible-doctor-hist/case.go | 303 ++++++++++++++++++ .../responsible-doctor-hist/helper.go | 24 ++ .../responsible-doctor-hist/lib.go | 156 +++++++++ .../middleware-runner.go | 103 ++++++ .../responsible-doctor-hist/middleware.go | 9 + .../responsible-doctor-hist/tycovar.go | 44 +++ 17 files changed, 1580 insertions(+) create mode 100644 internal/domain/main-entities/adm-employee-hist/dto.go create mode 100644 internal/domain/main-entities/responsible-doctor-hist/dto.go create mode 100644 internal/interface/main-handler/adm-employee-hist/handler.go create mode 100644 internal/interface/main-handler/responsible-doctor-hist/handler.go create mode 100644 internal/use-case/main-use-case/adm-employee-hist/case.go create mode 100644 internal/use-case/main-use-case/adm-employee-hist/helper.go create mode 100644 internal/use-case/main-use-case/adm-employee-hist/lib.go create mode 100644 internal/use-case/main-use-case/adm-employee-hist/middleware-runner.go create mode 100644 internal/use-case/main-use-case/adm-employee-hist/middleware.go create mode 100644 internal/use-case/main-use-case/adm-employee-hist/tycovar.go create mode 100644 internal/use-case/main-use-case/responsible-doctor-hist/case.go create mode 100644 internal/use-case/main-use-case/responsible-doctor-hist/helper.go create mode 100644 internal/use-case/main-use-case/responsible-doctor-hist/lib.go create mode 100644 internal/use-case/main-use-case/responsible-doctor-hist/middleware-runner.go create mode 100644 internal/use-case/main-use-case/responsible-doctor-hist/middleware.go create mode 100644 internal/use-case/main-use-case/responsible-doctor-hist/tycovar.go diff --git a/internal/domain/main-entities/adm-employee-hist/dto.go b/internal/domain/main-entities/adm-employee-hist/dto.go new file mode 100644 index 00000000..9a5d838f --- /dev/null +++ b/internal/domain/main-entities/adm-employee-hist/dto.go @@ -0,0 +1,78 @@ +package adm_employee_hist + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/employee" + "time" +) + +type CreateDto struct { + Encounter_Id *uint `json:"encounter_id"` + Employee_Id *uint `json:"employee_id"` + StartedAt *time.Time `json:"startedAt"` + FinishedAt *time.Time `json:"finishedAt"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Sort string `json:"sort"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Encounter_Id *uint `json:"encounter-id"` + Employee_Id *uint `json:"employee-id"` + StartedAt *time.Time `json:"startedAt"` + FinishedAt *time.Time `json:"finishedAt"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` + Code *string `json:"code"` + 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 // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Employee_Id *uint `json:"employee_id"` + Employee *ee.Employee `json:"employee,omitempty"` + StartedAt *time.Time `json:"startedAt"` + FinishedAt *time.Time `json:"finishedAt"` +} + +func (d AdmEmployeeHist) ToResponse() ResponseDto { + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Employee_Id: d.Employee_Id, + Employee: d.Employee, + StartedAt: d.StartedAt, + FinishedAt: d.FinishedAt, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []AdmEmployeeHist) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/responsible-doctor-hist/dto.go b/internal/domain/main-entities/responsible-doctor-hist/dto.go new file mode 100644 index 00000000..342faffa --- /dev/null +++ b/internal/domain/main-entities/responsible-doctor-hist/dto.go @@ -0,0 +1,78 @@ +package responsible_doctor_hist + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ed "simrs-vx/internal/domain/main-entities/doctor" + "time" +) + +type CreateDto struct { + Encounter_Id *uint `json:"encounter_id"` + Doctor_Id *uint `json:"doctor_id"` + StartedAt *time.Time `json:"startedAt"` + FinishedAt *time.Time `json:"finishedAt"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Sort string `json:"sort"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Encounter_Id *uint `json:"encounter-id"` + Doctor_Id *uint `json:"doctor-id"` + StartedAt *time.Time `json:"startedAt"` + FinishedAt *time.Time `json:"finishedAt"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` + Code *string `json:"code"` + 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 // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Doctor_Id *uint `json:"doctor_id"` + Doctor *ed.Doctor `json:"doctor,omitempty"` + StartedAt *time.Time `json:"startedAt"` + FinishedAt *time.Time `json:"finishedAt"` +} + +func (d ResponsibleDoctorHist) ToResponse() ResponseDto { + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Doctor_Id: d.Doctor_Id, + Doctor: d.Doctor, + StartedAt: d.StartedAt, + FinishedAt: d.FinishedAt, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []ResponsibleDoctorHist) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/interface/main-handler/adm-employee-hist/handler.go b/internal/interface/main-handler/adm-employee-hist/handler.go new file mode 100644 index 00000000..176d8a68 --- /dev/null +++ b/internal/interface/main-handler/adm-employee-hist/handler.go @@ -0,0 +1,71 @@ +package adm_employee_hist + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/adm-employee-hist" + u "simrs-vx/internal/use-case/main-use-case/adm-employee-hist" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint16(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint16(id) + 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 = uint16(id) + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 690a830a..89b55f26 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -31,6 +31,7 @@ import ( soapi "simrs-vx/internal/interface/main-handler/soapi" /******************** actor ********************/ + admemployeehist "simrs-vx/internal/interface/main-handler/adm-employee-hist" doctor "simrs-vx/internal/interface/main-handler/doctor" employee "simrs-vx/internal/interface/main-handler/employee" nurse "simrs-vx/internal/interface/main-handler/nurse" @@ -41,6 +42,7 @@ import ( personcontact "simrs-vx/internal/interface/main-handler/person-contact" personinsurance "simrs-vx/internal/interface/main-handler/person-insurance" pharmacist "simrs-vx/internal/interface/main-handler/pharmacist" + responsibledoctorhist "simrs-vx/internal/interface/main-handler/responsible-doctor-hist" user "simrs-vx/internal/interface/main-handler/user" /******************** external ********************/ @@ -247,6 +249,8 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/internal-reference", internalreference.O) hc.RegCrud(r, "/v1/ambulance-transport-req", ambulancetransportrequest.O) + hc.RegCrud(r, "/v1/responsible-doctor-hist", responsibledoctorhist.O) + hc.RegCrud(r, "/v1/adm-employee-hist", admemployeehist.O) /******************** actor ********************/ hc.RegCrud(r, "/v1/person", person.O) diff --git a/internal/interface/main-handler/responsible-doctor-hist/handler.go b/internal/interface/main-handler/responsible-doctor-hist/handler.go new file mode 100644 index 00000000..4b07df8a --- /dev/null +++ b/internal/interface/main-handler/responsible-doctor-hist/handler.go @@ -0,0 +1,71 @@ +package responsible_doctor_hist + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" + u "simrs-vx/internal/use-case/main-use-case/responsible-doctor-hist" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint16(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint16(id) + 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 = uint16(id) + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/use-case/main-use-case/adm-employee-hist/case.go b/internal/use-case/main-use-case/adm-employee-hist/case.go new file mode 100644 index 00000000..13e308bf --- /dev/null +++ b/internal/use-case/main-use-case/adm-employee-hist/case.go @@ -0,0 +1,303 @@ +package adm_employee_hist + +import ( + e "simrs-vx/internal/domain/main-entities/adm-employee-hist" + eem "simrs-vx/internal/domain/main-entities/employee" + ee "simrs-vx/internal/domain/main-entities/encounter" + "strconv" + + uem "simrs-vx/internal/use-case/main-use-case/employee" + ue "simrs-vx/internal/use-case/main-use-case/encounter" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "adm-employee-hist" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.AdmEmployeeHist{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 err := validateForeignKey(input); err != nil { + return err + } + + 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.AdmEmployeeHist + var dataList []e.AdmEmployeeHist + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.AdmEmployeeHist + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.AdmEmployeeHist + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 := validateForeignKey(input.CreateDto); err != nil { + return err + } + + if err := UpdateData(input, data, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.AdmEmployeeHist + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} + +func validateForeignKey(input e.CreateDto) error { + // validate encounter_id + if _, err := ue.ReadDetail(ee.ReadDetailDto{Id: uint16(*input.Encounter_Id)}); err != nil { + return err + } + + // validate doctor_id + if _, err := uem.ReadDetail(eem.ReadDetailDto{Id: uint16(*input.Employee_Id)}); err != nil { + return err + } + + return nil +} diff --git a/internal/use-case/main-use-case/adm-employee-hist/helper.go b/internal/use-case/main-use-case/adm-employee-hist/helper.go new file mode 100644 index 00000000..19363f0e --- /dev/null +++ b/internal/use-case/main-use-case/adm-employee-hist/helper.go @@ -0,0 +1,24 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package adm_employee_hist + +import ( + e "simrs-vx/internal/domain/main-entities/adm-employee-hist" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.AdmEmployeeHist) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Encounter_Id = inputSrc.Encounter_Id + data.Employee_Id = inputSrc.Employee_Id + data.StartedAt = inputSrc.StartedAt + data.FinishedAt = inputSrc.FinishedAt +} diff --git a/internal/use-case/main-use-case/adm-employee-hist/lib.go b/internal/use-case/main-use-case/adm-employee-hist/lib.go new file mode 100644 index 00000000..dc03b28a --- /dev/null +++ b/internal/use-case/main-use-case/adm-employee-hist/lib.go @@ -0,0 +1,156 @@ +package adm_employee_hist + +import ( + "errors" + e "simrs-vx/internal/domain/main-entities/adm-employee-hist" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.AdmEmployeeHist, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.AdmEmployeeHist{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.AdmEmployeeHist, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.AdmEmployeeHist{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.AdmEmployeeHist{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.AdmEmployeeHist, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.AdmEmployeeHist{} + + var tx, getData *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + switch { + case input.Id != 0: + getData = tx.First(&data, input.Id) + case input.Code != nil && *input.Code != "": + getData = tx.Where("code = ?", *input.Code).First(&data) + default: + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-read-detail-fail", + Detail: "either Id or Code must be provided", + } + + return nil, pl.SetLogError(event, nil) + } + + if err := getData.Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.AdmEmployeeHist, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.AdmEmployeeHist, 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 +} diff --git a/internal/use-case/main-use-case/adm-employee-hist/middleware-runner.go b/internal/use-case/main-use-case/adm-employee-hist/middleware-runner.go new file mode 100644 index 00000000..45f736b5 --- /dev/null +++ b/internal/use-case/main-use-case/adm-employee-hist/middleware-runner.go @@ -0,0 +1,103 @@ +package adm_employee_hist + +import ( + e "simrs-vx/internal/domain/main-entities/adm-employee-hist" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.AdmEmployeeHist) 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.AdmEmployeeHist) 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.AdmEmployeeHist) 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.AdmEmployeeHist) 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.AdmEmployeeHist) 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/main-use-case/adm-employee-hist/middleware.go b/internal/use-case/main-use-case/adm-employee-hist/middleware.go new file mode 100644 index 00000000..ad6ae298 --- /dev/null +++ b/internal/use-case/main-use-case/adm-employee-hist/middleware.go @@ -0,0 +1,9 @@ +package adm_employee_hist + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/adm-employee-hist/tycovar.go b/internal/use-case/main-use-case/adm-employee-hist/tycovar.go new file mode 100644 index 00000000..0827026d --- /dev/null +++ b/internal/use-case/main-use-case/adm-employee-hist/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 adm_employee_hist + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/adm-employee-hist" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.AdmEmployeeHist, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.AdmEmployeeHist, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.AdmEmployeeHist, 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/main-use-case/responsible-doctor-hist/case.go b/internal/use-case/main-use-case/responsible-doctor-hist/case.go new file mode 100644 index 00000000..591c6dd7 --- /dev/null +++ b/internal/use-case/main-use-case/responsible-doctor-hist/case.go @@ -0,0 +1,303 @@ +package responsible_doctor_hist + +import ( + ed "simrs-vx/internal/domain/main-entities/doctor" + ee "simrs-vx/internal/domain/main-entities/encounter" + e "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" + "strconv" + + ud "simrs-vx/internal/use-case/main-use-case/doctor" + ue "simrs-vx/internal/use-case/main-use-case/encounter" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "responsible-doctor-hist" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.ResponsibleDoctorHist{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 err := validateForeignKey(input); err != nil { + return err + } + + 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.ResponsibleDoctorHist + var dataList []e.ResponsibleDoctorHist + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.ResponsibleDoctorHist + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.ResponsibleDoctorHist + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 := validateForeignKey(input.CreateDto); err != nil { + return err + } + + if err := UpdateData(input, data, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.ResponsibleDoctorHist + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} + +func validateForeignKey(input e.CreateDto) error { + // validate encounter_id + if _, err := ue.ReadDetail(ee.ReadDetailDto{Id: uint16(*input.Encounter_Id)}); err != nil { + return err + } + + // validate doctor_id + if _, err := ud.ReadDetail(ed.ReadDetailDto{Id: uint16(*input.Doctor_Id)}); err != nil { + return err + } + + return nil +} diff --git a/internal/use-case/main-use-case/responsible-doctor-hist/helper.go b/internal/use-case/main-use-case/responsible-doctor-hist/helper.go new file mode 100644 index 00000000..6efd1097 --- /dev/null +++ b/internal/use-case/main-use-case/responsible-doctor-hist/helper.go @@ -0,0 +1,24 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package responsible_doctor_hist + +import ( + e "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.ResponsibleDoctorHist) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Encounter_Id = inputSrc.Encounter_Id + data.Doctor_Id = inputSrc.Doctor_Id + data.StartedAt = inputSrc.StartedAt + data.FinishedAt = inputSrc.FinishedAt +} diff --git a/internal/use-case/main-use-case/responsible-doctor-hist/lib.go b/internal/use-case/main-use-case/responsible-doctor-hist/lib.go new file mode 100644 index 00000000..d91294fe --- /dev/null +++ b/internal/use-case/main-use-case/responsible-doctor-hist/lib.go @@ -0,0 +1,156 @@ +package responsible_doctor_hist + +import ( + "errors" + e "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.ResponsibleDoctorHist, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.ResponsibleDoctorHist{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.ResponsibleDoctorHist, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.ResponsibleDoctorHist{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.ResponsibleDoctorHist{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.ResponsibleDoctorHist, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.ResponsibleDoctorHist{} + + var tx, getData *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + switch { + case input.Id != 0: + getData = tx.First(&data, input.Id) + case input.Code != nil && *input.Code != "": + getData = tx.Where("code = ?", *input.Code).First(&data) + default: + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-read-detail-fail", + Detail: "either Id or Code must be provided", + } + + return nil, pl.SetLogError(event, nil) + } + + if err := getData.Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.ResponsibleDoctorHist, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.ResponsibleDoctorHist, 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 +} diff --git a/internal/use-case/main-use-case/responsible-doctor-hist/middleware-runner.go b/internal/use-case/main-use-case/responsible-doctor-hist/middleware-runner.go new file mode 100644 index 00000000..0b107557 --- /dev/null +++ b/internal/use-case/main-use-case/responsible-doctor-hist/middleware-runner.go @@ -0,0 +1,103 @@ +package responsible_doctor_hist + +import ( + e "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.ResponsibleDoctorHist) 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.ResponsibleDoctorHist) 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.ResponsibleDoctorHist) 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.ResponsibleDoctorHist) 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.ResponsibleDoctorHist) 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/main-use-case/responsible-doctor-hist/middleware.go b/internal/use-case/main-use-case/responsible-doctor-hist/middleware.go new file mode 100644 index 00000000..324938e8 --- /dev/null +++ b/internal/use-case/main-use-case/responsible-doctor-hist/middleware.go @@ -0,0 +1,9 @@ +package responsible_doctor_hist + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/responsible-doctor-hist/tycovar.go b/internal/use-case/main-use-case/responsible-doctor-hist/tycovar.go new file mode 100644 index 00000000..aac1d18c --- /dev/null +++ b/internal/use-case/main-use-case/responsible-doctor-hist/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 responsible_doctor_hist + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.ResponsibleDoctorHist, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.ResponsibleDoctorHist, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.ResponsibleDoctorHist, 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 From 98b26a219ffa7a1376fa8b3e028e6cae135ef1b7 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Sat, 25 Oct 2025 08:37:00 +0700 Subject: [PATCH 011/329] add vclaim member, also marital and confidence in person --- cmd/main-migration/migrations/20251025013451.sql | 4 ++++ cmd/main-migration/migrations/20251025013609.sql | 12 ++++++++++++ cmd/main-migration/migrations/atlas.sum | 4 +++- .../domain/bpjs-entities/vclaim-member/dto.go | 1 + .../domain/bpjs-entities/vclaim-member/entity.go | 9 +++++++++ internal/domain/main-entities/patient/entity.go | 15 ++++++++------- internal/domain/main-entities/person/entity.go | 4 ++++ internal/domain/references/person/person.go | 8 ++++---- internal/interface/migration/main-entities.go | 2 ++ 9 files changed, 47 insertions(+), 12 deletions(-) create mode 100644 cmd/main-migration/migrations/20251025013451.sql create mode 100644 cmd/main-migration/migrations/20251025013609.sql create mode 100644 internal/domain/bpjs-entities/vclaim-member/dto.go create mode 100644 internal/domain/bpjs-entities/vclaim-member/entity.go diff --git a/cmd/main-migration/migrations/20251025013451.sql b/cmd/main-migration/migrations/20251025013451.sql new file mode 100644 index 00000000..0296b0f5 --- /dev/null +++ b/cmd/main-migration/migrations/20251025013451.sql @@ -0,0 +1,4 @@ +-- Modify "Patient" table +ALTER TABLE "public"."Patient" ADD COLUMN "RegisteredBy_User_Name" character varying(100) NULL; +-- Modify "Person" table +ALTER TABLE "public"."Person" ADD COLUMN "Confidence" character varying(512) NULL, ADD COLUMN "MaritalStatus_Code" character varying(10) NULL; diff --git a/cmd/main-migration/migrations/20251025013609.sql b/cmd/main-migration/migrations/20251025013609.sql new file mode 100644 index 00000000..9793d86a --- /dev/null +++ b/cmd/main-migration/migrations/20251025013609.sql @@ -0,0 +1,12 @@ +-- Create "VclaimMember" table +CREATE TABLE "public"."VclaimMember" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "CardNumber" character varying(20) NULL, + "Person_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_VclaimMember_CardNumber" UNIQUE ("CardNumber"), + CONSTRAINT "fk_Person_VclaimMember" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 9a03ed9b..33455810 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:ieMeKh35/dro1YBBO11ZP0nZan9aJ5aFSqnEAi+T+WQ= +h1:BeGFyPoCNw+Am00+prXp3+lNStrspn2VED1Mz+3IWpI= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -58,3 +58,5 @@ h1:ieMeKh35/dro1YBBO11ZP0nZan9aJ5aFSqnEAi+T+WQ= 20251023044432.sql h1:MkvajJs3bfk9+wHvQ43/ccAluJEBARm1gWr1u92ccLA= 20251024034832.sql h1:x3s3VEVYLOSKLAFxJGb2+c1FyTMMvPE+9k4Ew7rKQaI= 20251024074315.sql h1:EjAjelgi5qAfcRq/8vPTlGGYHvAKxNTllm8f0SzZDns= +20251025013451.sql h1:XTkUVKTZsZi9qphqhwXdVtHnhNNyJegbGYg+RKUXXag= +20251025013609.sql h1:Wlqjzsxm5Mb+sJPAyWsIrhwEx8oSSjfjYyHnAdkikzs= diff --git a/internal/domain/bpjs-entities/vclaim-member/dto.go b/internal/domain/bpjs-entities/vclaim-member/dto.go new file mode 100644 index 00000000..5914deb6 --- /dev/null +++ b/internal/domain/bpjs-entities/vclaim-member/dto.go @@ -0,0 +1 @@ +package vclaimmember diff --git a/internal/domain/bpjs-entities/vclaim-member/entity.go b/internal/domain/bpjs-entities/vclaim-member/entity.go new file mode 100644 index 00000000..420b569d --- /dev/null +++ b/internal/domain/bpjs-entities/vclaim-member/entity.go @@ -0,0 +1,9 @@ +package vclaimmember + +import ecore "simrs-vx/internal/domain/base-entities/core" + +type VclaimMember struct { + ecore.Main + CardNumber *string `json:"cardNumber" gorm:"unique;size:20"` + Person_Id *uint `json:"person_id"` +} diff --git a/internal/domain/main-entities/patient/entity.go b/internal/domain/main-entities/patient/entity.go index 491140cd..27d3c8ba 100644 --- a/internal/domain/main-entities/patient/entity.go +++ b/internal/domain/main-entities/patient/entity.go @@ -8,11 +8,12 @@ import ( ) type Patient struct { - ecore.Main // adjust this according to the needs - Person_Id *uint `json:"person_id"` - Person *ep.Person `json:"person,omitempty" gorm:"foreignKey:Person_Id;references:Id"` - NewBornStatus bool `json:"newBornStatus"` - RegisteredAt *time.Time `json:"registeredAt"` - Status_Code erc.ActiveStatusCode `json:"status_code" gorm:"not null;size:10"` - Number *string `json:"number" gorm:"unique;size:15"` + ecore.Main // adjust this according to the needs + Person_Id *uint `json:"person_id"` + Person *ep.Person `json:"person,omitempty" gorm:"foreignKey:Person_Id;references:Id"` + NewBornStatus bool `json:"newBornStatus"` + RegisteredAt *time.Time `json:"registeredAt"` + RegisteredBy_User_Name *string `json:"registeredBy_user_name" gorm:"size:100"` + Status_Code erc.ActiveStatusCode `json:"status_code" gorm:"not null;size:10"` + Number *string `json:"number" gorm:"unique;size:15"` } diff --git a/internal/domain/main-entities/person/entity.go b/internal/domain/main-entities/person/entity.go index 8932ca1b..d6e6744a 100644 --- a/internal/domain/main-entities/person/entity.go +++ b/internal/domain/main-entities/person/entity.go @@ -2,6 +2,7 @@ package person import ( ecore "simrs-vx/internal/domain/base-entities/core" + evm "simrs-vx/internal/domain/bpjs-entities/vclaim-member" ee "simrs-vx/internal/domain/main-entities/ethnic" el "simrs-vx/internal/domain/main-entities/language" epa "simrs-vx/internal/domain/main-entities/person-address" @@ -28,9 +29,11 @@ type Person struct { PassportNumber *string `json:"passportNumber" gorm:"unique;size:20"` DrivingLicenseNumber *string `json:"drivingLicenseNumber" gorm:"unique;size:20"` Religion_Code *erp.ReligionCode `json:"religion_code" gorm:"size:10"` + Confidence *string `json:"confidence" gorm:"size:512"` Education_Code *erp.EducationCode `json:"education_code" gorm:"size:10"` Ocupation_Code *erp.OcupationCode `json:"occupation_code" gorm:"size:15"` Ocupation_Name *string `json:"occupation_name" gorm:"size:50"` + MaritalStatus_Code *erp.MaritalStatusCode `json:"maritalStatus_code" gorm:"size:10"` Nationality *string `json:"nationality": gorm:"size:50"` Ethnic_Code *string `json:"ethnic_code" gorm:"size:20"` Ethnic *ee.Ethnic `json:"ethnic,omitempty" gorm:"foreignKey:Ethnic_Code;references:Code"` @@ -46,6 +49,7 @@ type Person struct { Contacts *[]epc.PersonContact `json:"contacts" gorm:"foreignKey:Person_Id"` Relatives *[]epr.PersonRelative `json:"relatives" gorm:"foreignKey:Person_Id"` Insurances *[]epi.PersonInsurance `json:"insurances" gorm:"foreignKey:Person_Id"` + VclaimMember *evm.VclaimMember `json:"vclaimMember,omitempty" gorm:"foreignKey:Person_Id;references:Id"` } func (d Person) IsSameResidentIdentityNumber(input *string) bool { diff --git a/internal/domain/references/person/person.go b/internal/domain/references/person/person.go index a9ee5efb..1648b578 100644 --- a/internal/domain/references/person/person.go +++ b/internal/domain/references/person/person.go @@ -30,10 +30,10 @@ const ( BTCOPositive BloodTypeCode = "O+" BTCONegative BloodTypeCode = "O-" - MSCBelumKawin MaritalStatusCode = "S" - MSCKawin MaritalStatusCode = "M" - MSCCeraiHidup MaritalStatusCode = "D" - MSCCeraiMati MaritalStatusCode = "W" + MaritalStatusSingle MaritalStatusCode = "S" // Single (Belum Kawin) + MaritalStatusMarried MaritalStatusCode = "M" // Married (Kawin) + MaritalStatusDivorced MaritalStatusCode = "D" // Divorced (Cerai Hidup) + MaritalStatusWidowed MaritalStatusCode = "W" // Widowed (Cerai Mati) RCIslam ReligionCode = "islam" RCProtestan ReligionCode = "protestan" diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index eadae620..6507202e 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -92,6 +92,7 @@ import ( village "simrs-vx/internal/domain/main-entities/village" ///BPJS + vclaimmember "simrs-vx/internal/domain/bpjs-entities/vclaim-member" vclaimsep "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" vclaimsephist "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-hist" vclaimsepprint "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-print" @@ -191,5 +192,6 @@ func getMainEntities() []any { &subspecialistposition.SubspecialistPosition{}, &responsibledoctorhist.ResponsibleDoctorHist{}, &admemployeehist.AdmEmployeeHist{}, + &vclaimmember.VclaimMember{}, } } From de42ab3203033b480524a6f5788331bbea4fbaf1 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Sat, 25 Oct 2025 09:03:00 +0700 Subject: [PATCH 012/329] wip --- internal/domain/bpjs-entities/member/dto.go | 1 - .../domain/bpjs-entities/vclaim-member/dto.go | 60 ++++ internal/domain/main-entities/patient/dto.go | 23 +- internal/domain/main-entities/person/dto.go | 100 +++--- .../bpjs-use-case/vclaim-member/case.go | 334 ++++++++++++++++++ .../bpjs-use-case/vclaim-member/helper.go | 22 ++ .../bpjs-use-case/vclaim-member/lib.go | 147 ++++++++ .../vclaim-member/middleware-runner.go | 103 ++++++ .../bpjs-use-case/vclaim-member/middleware.go | 13 + .../bpjs-use-case/vclaim-member/tycovar.go | 44 +++ .../use-case/main-use-case/person/helper.go | 2 + 11 files changed, 794 insertions(+), 55 deletions(-) create mode 100644 internal/use-case/bpjs-use-case/vclaim-member/case.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-member/helper.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-member/lib.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-member/middleware-runner.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-member/middleware.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-member/tycovar.go diff --git a/internal/domain/bpjs-entities/member/dto.go b/internal/domain/bpjs-entities/member/dto.go index f9c95655..e61a9f74 100644 --- a/internal/domain/bpjs-entities/member/dto.go +++ b/internal/domain/bpjs-entities/member/dto.go @@ -4,7 +4,6 @@ type ReadListDto struct { ReferenceType ReferenceType `json:"-"` PathValue1 string `json:"-"` PathValue2 string `json:"-"` - PathValue3 string `json:"-"` } type ReferenceType string diff --git a/internal/domain/bpjs-entities/vclaim-member/dto.go b/internal/domain/bpjs-entities/vclaim-member/dto.go index 5914deb6..34638abb 100644 --- a/internal/domain/bpjs-entities/vclaim-member/dto.go +++ b/internal/domain/bpjs-entities/vclaim-member/dto.go @@ -1 +1,61 @@ package vclaimmember + +import ecore "simrs-vx/internal/domain/base-entities/core" + +type CreateDto struct { + CardNumber *string `json:"cardNumber" validate:"maxLength=20"` + Person_Id *uint `json:"person_id"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Sort string `json:"sort"` + Pagination ecore.Pagination +} + +type FilterDto struct { + CardNumber *string `json:"cardNumber"` +} + +type ReadDetailDto struct { + Id uint `json:"id"` + CardNumber *string `json:"cardNumber"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` + CardNumber *string `json:"cardNumber"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + CardNumber *string `json:"cardNumber"` +} + +func (d VclaimMember) ToResponse() ResponseDto { + resp := ResponseDto{ + CardNumber: d.CardNumber, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []VclaimMember) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/patient/dto.go b/internal/domain/main-entities/patient/dto.go index 4927a50e..abe3b46b 100644 --- a/internal/domain/main-entities/patient/dto.go +++ b/internal/domain/main-entities/patient/dto.go @@ -13,18 +13,23 @@ import ( erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" + + pa "simrs-vx/pkg/auth-helper" ) type CreateDto struct { - Person_Id *uint `json:"-"` - Person *ep.UpdateDto `json:"person"` - NewBornStatus bool `json:"newBornStatus"` - PersonAddresses []epa.UpdateDto `json:"personAddresses"` - PersonContacts []epc.UpdateDto `json:"personContacts"` - PersonRelatives []epr.UpdateDto `json:"personRelatives"` - PersonInsurances []epi.UpdateDto `json:"personInsurances"` - RegisteredAt *time.Time `json:"registeredAt"` - Status_Code erc.ActiveStatusCode `json:"status_code" validate:"maxLength=10"` + Person_Id *uint `json:"-"` + Person *ep.UpdateDto `json:"person"` + NewBornStatus bool `json:"newBornStatus"` + PersonAddresses []epa.UpdateDto `json:"personAddresses"` + PersonContacts []epc.UpdateDto `json:"personContacts"` + PersonRelatives []epr.UpdateDto `json:"personRelatives"` + PersonInsurances []epi.UpdateDto `json:"personInsurances"` + RegisteredAt *time.Time `json:"registeredAt"` + RegisteredBy_User_Name *string `json:"registeredBy_user_name" validate:"maxLength=100"` + Status_Code erc.ActiveStatusCode `json:"status_code" validate:"maxLength=10"` + + pa.AuthInfo } type ReadListDto struct { diff --git a/internal/domain/main-entities/person/dto.go b/internal/domain/main-entities/person/dto.go index 7fb6a235..588379df 100644 --- a/internal/domain/main-entities/person/dto.go +++ b/internal/domain/main-entities/person/dto.go @@ -4,6 +4,7 @@ import ( "time" ecore "simrs-vx/internal/domain/base-entities/core" + evm "simrs-vx/internal/domain/bpjs-entities/vclaim-member" ee "simrs-vx/internal/domain/main-entities/ethnic" epa "simrs-vx/internal/domain/main-entities/person-address" epc "simrs-vx/internal/domain/main-entities/person-contact" @@ -14,24 +15,27 @@ import ( ) type CreateDto struct { - Name string `json:"name" validate:"maxLength=150"` - FrontTitle *string `json:"frontTitle" validate:"maxLength=50"` - EndTitle *string `json:"endTitle" validate:"maxLength=50"` - BirthDate *time.Time `json:"birthDate,omitempty"` - BirthRegency_Code *string `json:"birthRegency_code" validate:"maxLength=4"` - Gender_Code *erp.GenderCode `json:"gender_code"` - ResidentIdentityNumber *string `json:"residentIdentityNumber" validate:"nik;maxLength=16"` - PassportNumber *string `json:"passportNumber" validate:"maxLength=20"` - DrivingLicenseNumber *string `json:"drivingLicenseNumber" validate:"maxLength=20"` - Religion_Code *erp.ReligionCode `json:"religion_code" validate:"maxLength=10"` - Education_Code *erp.EducationCode `json:"education_code" validate:"maxLength=10"` - Ocupation_Code *erp.OcupationCode `json:"occupation_code" validate:"maxLength=15"` - Ocupation_Name *string `json:"occupation_name" validate:"maxLength=50"` - Nationality *string `json:"nationality" validate:"maxLength=50"` - Ethnic_Code *string `json:"ethnic_code" validate:"maxLength=20"` - Language_Code *string `json:"language_code" validate:"maxLength=10"` - CommunicationIssueStatus bool `json:"communicationIssueStatus"` - Disability *string `json:"disability" validate:"maxLength=100"` + Name string `json:"name" validate:"maxLength=150"` + FrontTitle *string `json:"frontTitle" validate:"maxLength=50"` + EndTitle *string `json:"endTitle" validate:"maxLength=50"` + BirthDate *time.Time `json:"birthDate,omitempty"` + BirthRegency_Code *string `json:"birthRegency_code" validate:"maxLength=4"` + Gender_Code *erp.GenderCode `json:"gender_code"` + ResidentIdentityNumber *string `json:"residentIdentityNumber" validate:"nik;maxLength=16"` + PassportNumber *string `json:"passportNumber" validate:"maxLength=20"` + DrivingLicenseNumber *string `json:"drivingLicenseNumber" validate:"maxLength=20"` + Religion_Code *erp.ReligionCode `json:"religion_code" validate:"maxLength=10"` + Education_Code *erp.EducationCode `json:"education_code" validate:"maxLength=10"` + Ocupation_Code *erp.OcupationCode `json:"occupation_code" validate:"maxLength=15"` + Ocupation_Name *string `json:"occupation_name" validate:"maxLength=50"` + MaritalStatus_Code *erp.MaritalStatusCode `json:"maritalStatus_code" validate:"maxLength=10"` + Confidence *string `json:"confidence" validate:"maxLength=512"` + Nationality *string `json:"nationality" validate:"maxLength=50"` + Ethnic_Code *string `json:"ethnic_code" validate:"maxLength=20"` + Language_Code *string `json:"language_code" validate:"maxLength=10"` + CommunicationIssueStatus bool `json:"communicationIssueStatus"` + Disability *string `json:"disability" validate:"maxLength=100"` + VclaimMember_CardNumber *string `json:"vclaimMember_cardNumber" validate:"maxLength=20"` } type ReadListDto struct { @@ -86,33 +90,36 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Name string `json:"name"` - FrontTitle *string `json:"frontTitle"` - EndTitle *string `json:"endTitle"` - BirthDate *time.Time `json:"birthDate,omitempty"` - BirthRegency_Code *string `json:"birthRegency_code"` - BirthRegency *er.Regency `json:"birthRegency,omitempty"` - Gender_Code *erp.GenderCode `json:"gender_code"` - ResidentIdentityNumber *string `json:"residentIdentityNumber"` - PassportNumber *string `json:"passportNumber"` - DrivingLicenseNumber *string `json:"drivingLicenseNumber"` - Religion_Code *erp.ReligionCode `json:"religion_code"` - Education_Code *erp.EducationCode `json:"education_code"` - Ocupation_Code *erp.OcupationCode `json:"occupation_code"` - Ocupation_Name *string `json:"occupation_name"` - Nationality *string `json:"nationality"` - Ethnic_Code *string `json:"ethnic_code"` - Ethnic *ee.Ethnic `json:"ethnic,omitempty"` - Addresses *[]epa.PersonAddress `json:"addresses,omitempty"` - Contacts *[]epc.PersonContact `json:"contacts,omitempty"` - Relatives *[]epr.PersonRelative `json:"relatives,omitempty"` - Language_Code *string `json:"language_code"` - CommunicationIssueStatus bool `json:"communicationIssueStatus"` - Disability *string `json:"disability"` - ResidentIdentityFileUrl *string `json:"residentIdentityFileUrl"` - PassportFileUrl *string `json:"passportFileUrl"` - DrivingLicenseFileUrl *string `json:"drivingLicenseFileUrl"` - FamilyIdentityFileUrl *string `json:"familyIdentityFileUrl"` + Name string `json:"name"` + FrontTitle *string `json:"frontTitle"` + EndTitle *string `json:"endTitle"` + BirthDate *time.Time `json:"birthDate,omitempty"` + BirthRegency_Code *string `json:"birthRegency_code"` + BirthRegency *er.Regency `json:"birthRegency,omitempty"` + Gender_Code *erp.GenderCode `json:"gender_code"` + ResidentIdentityNumber *string `json:"residentIdentityNumber"` + PassportNumber *string `json:"passportNumber"` + DrivingLicenseNumber *string `json:"drivingLicenseNumber"` + Religion_Code *erp.ReligionCode `json:"religion_code"` + Education_Code *erp.EducationCode `json:"education_code"` + Ocupation_Code *erp.OcupationCode `json:"occupation_code"` + Ocupation_Name *string `json:"occupation_name"` + MaritalStatus_Code *erp.MaritalStatusCode `json:"maritalStatus_code"` + Confidence *string `json:"confidence"` + Nationality *string `json:"nationality"` + Ethnic_Code *string `json:"ethnic_code"` + Ethnic *ee.Ethnic `json:"ethnic,omitempty"` + Addresses *[]epa.PersonAddress `json:"addresses,omitempty"` + Contacts *[]epc.PersonContact `json:"contacts,omitempty"` + Relatives *[]epr.PersonRelative `json:"relatives,omitempty"` + Language_Code *string `json:"language_code"` + CommunicationIssueStatus bool `json:"communicationIssueStatus"` + Disability *string `json:"disability"` + ResidentIdentityFileUrl *string `json:"residentIdentityFileUrl"` + PassportFileUrl *string `json:"passportFileUrl"` + DrivingLicenseFileUrl *string `json:"drivingLicenseFileUrl"` + FamilyIdentityFileUrl *string `json:"familyIdentityFileUrl"` + VclaimMember *evm.VclaimMember `json:"vclaimMember,omitempty"` } func (d *Person) ToResponse() ResponseDto { @@ -131,6 +138,8 @@ func (d *Person) ToResponse() ResponseDto { Education_Code: d.Education_Code, Ocupation_Code: d.Ocupation_Code, Ocupation_Name: d.Ocupation_Name, + MaritalStatus_Code: d.MaritalStatus_Code, + Confidence: d.Confidence, Nationality: d.Nationality, Ethnic_Code: d.Ethnic_Code, Ethnic: d.Ethnic, @@ -144,6 +153,7 @@ func (d *Person) ToResponse() ResponseDto { PassportFileUrl: d.PassportFileUrl, DrivingLicenseFileUrl: d.DrivingLicenseFileUrl, FamilyIdentityFileUrl: d.FamilyIdentityFileUrl, + VclaimMember: d.VclaimMember, } resp.Main = d.Main return resp diff --git a/internal/use-case/bpjs-use-case/vclaim-member/case.go b/internal/use-case/bpjs-use-case/vclaim-member/case.go new file mode 100644 index 00000000..7c572f5e --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-member/case.go @@ -0,0 +1,334 @@ +package vclaimmember + +import ( + "strconv" + + e "simrs-vx/internal/domain/bpjs-entities/vclaim-member" + // evsh "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-hist" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "vclaim-member" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.VclaimMember{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.VclaimMember + var dataList []e.VclaimMember + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.VclaimMember + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{CardNumber: input.CardNumber} + var data *e.VclaimMember + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{CardNumber: input.CardNumber} + var data *e.VclaimMember + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} + +// func CreateOrUpdate(input e.CreateDto) (*d.Data, error) { +// rdDto := e.ReadDetailDto{CardNumber: input.CardNumber} +// var data *e.VclaimMember +// var err error + +// event := pl.Event{ +// Feature: "CreateOrUpdate", +// Source: source, +// } + +// // Start log +// pl.SetLogInfo(&event, input, "started", "createOrUpdate") + +// err = dg.I.Transaction(func(tx *gorm.DB) error { +// pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") +// if data, err = ReadDetailData(rdDto, &event, tx); err != nil { +// return err +// } + +// mwRunner := newMiddlewareRunner(&event, tx) +// mwRunner.setMwType(pu.MWTPre) +// // Run pre-middleware +// if err := mwRunner.RunCreateMiddleware(createPreMw, &input, data); err != nil { +// return err +// } + +// if err := CreateOrUpdateData(input, data, &event, tx); err != nil { +// return err +// } + +// pl.SetLogInfo(&event, nil, "complete") + +// mwRunner.setMwType(pu.MWTPost) +// // Run post-middleware +// if err := mwRunner.RunCreateMiddleware(createPostMw, &input, data); err != nil { +// return err +// } + +// return nil +// }) + +// if err != nil { +// return nil, err +// } + +// return &d.Data{ +// Meta: d.II{ +// "source": source, +// "structure": "single-data", +// "status": "created", +// }, +// Data: data.ToResponse(), +// }, nil + +// } diff --git a/internal/use-case/bpjs-use-case/vclaim-member/helper.go b/internal/use-case/bpjs-use-case/vclaim-member/helper.go new file mode 100644 index 00000000..c2789e58 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-member/helper.go @@ -0,0 +1,22 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package vclaimmember + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-member" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.VclaimMember) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.CardNumber = inputSrc.CardNumber + data.Person_Id = inputSrc.Person_Id +} diff --git a/internal/use-case/bpjs-use-case/vclaim-member/lib.go b/internal/use-case/bpjs-use-case/vclaim-member/lib.go new file mode 100644 index 00000000..9044664d --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-member/lib.go @@ -0,0 +1,147 @@ +package vclaimmember + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-member" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.VclaimMember, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.VclaimMember{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.VclaimMember, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.VclaimMember{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.VclaimMember{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.VclaimMember, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.VclaimMember{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if input.CardNumber != nil { + tx = tx.Where("\"CardNumber\" = ?", *input.CardNumber) + } + if input.Id != 0 { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.VclaimMember, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.VclaimMember, 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 +} diff --git a/internal/use-case/bpjs-use-case/vclaim-member/middleware-runner.go b/internal/use-case/bpjs-use-case/vclaim-member/middleware-runner.go new file mode 100644 index 00000000..452a06e0 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-member/middleware-runner.go @@ -0,0 +1,103 @@ +package vclaimmember + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-member" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.VclaimMember) 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.VclaimMember) 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.VclaimMember) 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.VclaimMember) 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.VclaimMember) 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/bpjs-use-case/vclaim-member/middleware.go b/internal/use-case/bpjs-use-case/vclaim-member/middleware.go new file mode 100644 index 00000000..56404d79 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-member/middleware.go @@ -0,0 +1,13 @@ +package vclaimmember + +// import ( +// pvs "simrs-vx/internal/use-case/bpjs-plugin/vclaim-member" +// ) + +// // example of middleware +// func init() { +// createPreMw = append(createPreMw, +// createMw{Name: "create-sep", Func: pvs.CreateSep}, +// ) + +// } diff --git a/internal/use-case/bpjs-use-case/vclaim-member/tycovar.go b/internal/use-case/bpjs-use-case/vclaim-member/tycovar.go new file mode 100644 index 00000000..dafb1227 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-member/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 vclaimmember + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/bpjs-entities/vclaim-member" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.VclaimMember, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.VclaimMember, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.VclaimMember, 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/main-use-case/person/helper.go b/internal/use-case/main-use-case/person/helper.go index 61a2f18c..3760f3b2 100644 --- a/internal/use-case/main-use-case/person/helper.go +++ b/internal/use-case/main-use-case/person/helper.go @@ -30,6 +30,8 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Person) { data.Education_Code = inputSrc.Education_Code data.Ocupation_Code = inputSrc.Ocupation_Code data.Ocupation_Name = inputSrc.Ocupation_Name + data.MaritalStatus_Code = inputSrc.MaritalStatus_Code + data.Confidence = inputSrc.Confidence data.Nationality = inputSrc.Nationality data.Ethnic_Code = inputSrc.Ethnic_Code data.Language_Code = inputSrc.Language_Code From b5b0a8183d7e50a9fb77f9de5db9f4a2b5e0f3fe Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Sat, 25 Oct 2025 18:01:37 +0700 Subject: [PATCH 013/329] dev: hotfix, added system role --- internal/use-case/main-use-case/authentication/case.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/use-case/main-use-case/authentication/case.go b/internal/use-case/main-use-case/authentication/case.go index 5b9952a3..f38e82d0 100644 --- a/internal/use-case/main-use-case/authentication/case.go +++ b/internal/use-case/main-use-case/authentication/case.go @@ -200,6 +200,8 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { intern := intern.Intern{} dg.I.Where("\"User_Id\" = ?", user.Id).First(&intern) role = append(role, "int-"+string(*intern.Position_Code)) + case erg.CSCSys: + role = append(role, "system") } atClaims["roles"] = role outputData["roles"] = role From 2c432a7bef5f09a80b501fe950d36b8032a439a8 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Sun, 26 Oct 2025 21:29:41 +0700 Subject: [PATCH 014/329] feat/authentication + moved pkg/auth-helper to internal/lib/auth + update AuthInfo + cleaning --- assets/language/id/data.json | 3 +- internal/domain/main-entities/adime/dto.go | 7 +- internal/domain/main-entities/chemo/dto.go | 12 ++- .../domain/main-entities/consultation/dto.go | 9 +- .../domain/main-entities/device-order/dto.go | 13 ++- .../domain/main-entities/encounter/dto.go | 18 +++- .../main-entities/material-order/dto.go | 13 ++- .../domain/main-entities/mcu-order/dto.go | 19 ++-- .../main-entities/medication-item-dist/dto.go | 15 ++- .../domain/main-entities/medication/dto.go | 14 ++- .../domain/main-entities/prescription/dto.go | 4 + internal/domain/main-entities/sbar/dto.go | 9 +- internal/domain/main-entities/soapi/dto.go | 2 +- .../interface/main-handler/adime/handler.go | 2 +- .../main-handler/authentication/handler.go | 2 +- .../interface/main-handler/chemo/handler.go | 2 +- .../main-handler/consultation/handler.go | 2 +- .../main-handler/device-order/handler.go | 2 +- .../main-handler/encounter/handler.go | 7 +- .../interface/main-handler/main-handler.go | 31 +++--- .../main-handler/material-order/handler.go | 2 +- .../main-handler/mcu-order/handler.go | 2 +- .../medication-item-dist/handler.go | 2 +- .../main-handler/medication/handler.go | 2 +- .../main-handler/prescription/handler.go | 8 ++ .../interface/main-handler/sbar/handler.go | 2 +- .../interface/main-handler/soapi/handler.go | 2 +- internal/lib/.keep | 0 .../lib/auth/auth.go | 0 .../lib/auth}/tycovar.go | 13 ++- .../main-use-case/authentication/case.go | 98 +++++++++++-------- .../main-use-case/authentication/helper.go | 4 - .../use-case/main-use-case/encounter/lib.go | 27 +++-- 33 files changed, 227 insertions(+), 121 deletions(-) create mode 100644 internal/lib/.keep rename pkg/auth-helper/auth-helper.go => internal/lib/auth/auth.go (100%) rename {pkg/auth-helper => internal/lib/auth}/tycovar.go (84%) diff --git a/assets/language/id/data.json b/assets/language/id/data.json index 9e064e9a..4f76a8ff 100644 --- a/assets/language/id/data.json +++ b/assets/language/id/data.json @@ -5,7 +5,8 @@ "payload-bad": "struktur data tidak sesuai standar", "auth-required": "butuh autentikasi", - "auth-missingHeader": "Header autentikasi tidak ditemukan", + "auth-getData-failed": "gagal mengambil data user", + "auth-missingHeader": "header autentikasi tidak ditemukan", "auth-forbidden": "tidak diijinkan", "auth-login-success": "login berhasil", "auth-login-incorrect": "Username atau Password Tidak Sesuai", diff --git a/internal/domain/main-entities/adime/dto.go b/internal/domain/main-entities/adime/dto.go index 49257154..cb9b675a 100644 --- a/internal/domain/main-entities/adime/dto.go +++ b/internal/domain/main-entities/adime/dto.go @@ -1,13 +1,16 @@ package adime import ( + // std "time" + // internal - lib + pa "simrs-vx/internal/lib/auth" + + // internal - domain ecore "simrs-vx/internal/domain/base-entities/core" eem "simrs-vx/internal/domain/main-entities/employee" ee "simrs-vx/internal/domain/main-entities/encounter" - - pa "simrs-vx/pkg/auth-helper" ) type CreateDto struct { diff --git a/internal/domain/main-entities/chemo/dto.go b/internal/domain/main-entities/chemo/dto.go index 19e5f803..8317b259 100644 --- a/internal/domain/main-entities/chemo/dto.go +++ b/internal/domain/main-entities/chemo/dto.go @@ -1,16 +1,20 @@ package chemo import ( + // std "time" + // internal - lib + pa "simrs-vx/internal/lib/auth" + + // internal - domain - references + erc "simrs-vx/internal/domain/references/common" + + // internal - domain - main-entities ecore "simrs-vx/internal/domain/base-entities/core" 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" - - pa "simrs-vx/pkg/auth-helper" ) type CreateDto struct { diff --git a/internal/domain/main-entities/consultation/dto.go b/internal/domain/main-entities/consultation/dto.go index 1b0e3cc5..33868dd0 100644 --- a/internal/domain/main-entities/consultation/dto.go +++ b/internal/domain/main-entities/consultation/dto.go @@ -1,14 +1,19 @@ package consultation import ( + // std "time" + // internal - lib + pa "simrs-vx/internal/lib/auth" + + // internal - domain - base-entities ecore "simrs-vx/internal/domain/base-entities/core" + + // internal - domain - main-entities ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/encounter" eu "simrs-vx/internal/domain/main-entities/unit" - - pa "simrs-vx/pkg/auth-helper" ) type CreateDto struct { diff --git a/internal/domain/main-entities/device-order/dto.go b/internal/domain/main-entities/device-order/dto.go index 01ef34b2..3d944941 100644 --- a/internal/domain/main-entities/device-order/dto.go +++ b/internal/domain/main-entities/device-order/dto.go @@ -1,13 +1,18 @@ package deviceorder import ( - ecore "simrs-vx/internal/domain/base-entities/core" - ed "simrs-vx/internal/domain/main-entities/doctor" - ee "simrs-vx/internal/domain/main-entities/encounter" + // internal - lib + pa "simrs-vx/internal/lib/auth" + // internal - domain - base-entities + ecore "simrs-vx/internal/domain/base-entities/core" + + // internal - domain - references erc "simrs-vx/internal/domain/references/common" - pa "simrs-vx/pkg/auth-helper" + // internal - domain - main-entities + ed "simrs-vx/internal/domain/main-entities/doctor" + ee "simrs-vx/internal/domain/main-entities/encounter" ) type CreateDto struct { diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index 4a30281d..684d4bb3 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -1,9 +1,20 @@ package encounter import ( + // std "time" + // internal - lib + pa "simrs-vx/internal/lib/auth" + + // internal - domain - base-entities ecore "simrs-vx/internal/domain/base-entities/core" + + // internal - domain - references + erc "simrs-vx/internal/domain/references/common" + ere "simrs-vx/internal/domain/references/encounter" + + // internal - domain - main-entities evs "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" ea "simrs-vx/internal/domain/main-entities/appointment" ed "simrs-vx/internal/domain/main-entities/doctor" @@ -13,11 +24,6 @@ import ( es "simrs-vx/internal/domain/main-entities/specialist" ess "simrs-vx/internal/domain/main-entities/subspecialist" eu "simrs-vx/internal/domain/main-entities/unit" - - erc "simrs-vx/internal/domain/references/common" - ere "simrs-vx/internal/domain/references/encounter" - - pa "simrs-vx/pkg/auth-helper" ) type CreateDto struct { @@ -48,6 +54,8 @@ type ReadListDto struct { FilterDto Includes string `json:"includes"` Pagination ecore.Pagination + + pa.AuthInfo } type FilterDto struct { diff --git a/internal/domain/main-entities/material-order/dto.go b/internal/domain/main-entities/material-order/dto.go index 5485d2dd..bd4f5c91 100644 --- a/internal/domain/main-entities/material-order/dto.go +++ b/internal/domain/main-entities/material-order/dto.go @@ -1,13 +1,18 @@ package materialorder import ( - ecore "simrs-vx/internal/domain/base-entities/core" - ed "simrs-vx/internal/domain/main-entities/doctor" - ee "simrs-vx/internal/domain/main-entities/encounter" + // internal - lib + pa "simrs-vx/internal/lib/auth" + // internal - domain - base-entities + ecore "simrs-vx/internal/domain/base-entities/core" + + // internal - domain - references erc "simrs-vx/internal/domain/references/common" - pa "simrs-vx/pkg/auth-helper" + // internal - domain - main-entities + ed "simrs-vx/internal/domain/main-entities/doctor" + ee "simrs-vx/internal/domain/main-entities/encounter" ) type CreateDto struct { diff --git a/internal/domain/main-entities/mcu-order/dto.go b/internal/domain/main-entities/mcu-order/dto.go index caf3ef58..a8ce83de 100644 --- a/internal/domain/main-entities/mcu-order/dto.go +++ b/internal/domain/main-entities/mcu-order/dto.go @@ -1,15 +1,22 @@ package mcuorder import ( - ecore "simrs-vx/internal/domain/base-entities/core" - ed "simrs-vx/internal/domain/main-entities/doctor" - ee "simrs-vx/internal/domain/main-entities/encounter" + // std "time" + // internal - lib + pa "simrs-vx/internal/lib/auth" + + // internal - domain - base-entities + ecore "simrs-vx/internal/domain/base-entities/core" + + // internal - domain - references ercl "simrs-vx/internal/domain/references/clinical" erc "simrs-vx/internal/domain/references/common" - pa "simrs-vx/pkg/auth-helper" + // internal - domain - main-entities + ed "simrs-vx/internal/domain/main-entities/doctor" + ee "simrs-vx/internal/domain/main-entities/encounter" ) type CreateDto struct { @@ -20,7 +27,7 @@ type CreateDto struct { ExaminationDate *time.Time `json:"examinationDate"` Number uint8 `json:"number"` Temperature float64 `json:"temperature"` - McuUrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"mcuUrgencyLevel_code""` + McuUrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"mcuUrgencyLevel_code"` pa.AuthInfo } @@ -39,7 +46,7 @@ type FilterDto struct { ExaminationDate *time.Time `json:"examinationDate"` Number uint8 `json:"number"` Temperature float64 `json:"temperature"` - McuUrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"mcuUrgencyLevel-code""` + McuUrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"mcuUrgencyLevel-code"` } type ReadDetailDto struct { Id uint `json:"id"` diff --git a/internal/domain/main-entities/medication-item-dist/dto.go b/internal/domain/main-entities/medication-item-dist/dto.go index 9790895a..6936bdbc 100644 --- a/internal/domain/main-entities/medication-item-dist/dto.go +++ b/internal/domain/main-entities/medication-item-dist/dto.go @@ -1,12 +1,17 @@ package medicationitem import ( - ecore "simrs-vx/internal/domain/base-entities/core" - emi "simrs-vx/internal/domain/main-entities/medication-item" - - pa "simrs-vx/pkg/auth-helper" - + // std "time" + + // internal - lib + pa "simrs-vx/internal/lib/auth" + + // internal - domain - base-entities + ecore "simrs-vx/internal/domain/base-entities/core" + + // internal - domain - main-entities + emi "simrs-vx/internal/domain/main-entities/medication-item" ) type CreateDto struct { diff --git a/internal/domain/main-entities/medication/dto.go b/internal/domain/main-entities/medication/dto.go index c2cf9d14..928b926c 100644 --- a/internal/domain/main-entities/medication/dto.go +++ b/internal/domain/main-entities/medication/dto.go @@ -1,15 +1,21 @@ package medication import ( + // std "time" - ecore "simrs-vx/internal/domain/base-entities/core" - ee "simrs-vx/internal/domain/main-entities/encounter" - ep "simrs-vx/internal/domain/main-entities/pharmacist" + // internal - lib + pa "simrs-vx/internal/lib/auth" + // internal - domain - base-entities + ecore "simrs-vx/internal/domain/base-entities/core" + + // internal - domain - references erc "simrs-vx/internal/domain/references/common" - pa "simrs-vx/pkg/auth-helper" + // internal - domain - main-entities + ee "simrs-vx/internal/domain/main-entities/encounter" + ep "simrs-vx/internal/domain/main-entities/pharmacist" ) type CreateDto struct { diff --git a/internal/domain/main-entities/prescription/dto.go b/internal/domain/main-entities/prescription/dto.go index 431f1e2d..3a3ad7b5 100644 --- a/internal/domain/main-entities/prescription/dto.go +++ b/internal/domain/main-entities/prescription/dto.go @@ -7,6 +7,8 @@ import ( ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/encounter" + pa "simrs-vx/internal/lib/auth" + erc "simrs-vx/internal/domain/references/common" ) @@ -15,6 +17,8 @@ type CreateDto struct { Doctor_Id *uint `json:"doctor_id"` IssuedAt *time.Time `json:"issuedAt"` Status_Code erc.DataStatusCode `json:"status_code"` + + pa.AuthInfo } type ReadListDto struct { diff --git a/internal/domain/main-entities/sbar/dto.go b/internal/domain/main-entities/sbar/dto.go index 46cf69a8..1664fb5f 100644 --- a/internal/domain/main-entities/sbar/dto.go +++ b/internal/domain/main-entities/sbar/dto.go @@ -1,13 +1,18 @@ package sbar import ( + // std "time" + // internal - lib + pa "simrs-vx/internal/lib/auth" + + // internal - domain - base-entities ecore "simrs-vx/internal/domain/base-entities/core" + + // internal - domain - main-entities eem "simrs-vx/internal/domain/main-entities/employee" ee "simrs-vx/internal/domain/main-entities/encounter" - - pa "simrs-vx/pkg/auth-helper" ) type CreateDto struct { diff --git a/internal/domain/main-entities/soapi/dto.go b/internal/domain/main-entities/soapi/dto.go index 418a7fb8..b8f1b827 100644 --- a/internal/domain/main-entities/soapi/dto.go +++ b/internal/domain/main-entities/soapi/dto.go @@ -9,7 +9,7 @@ import ( erc "simrs-vx/internal/domain/references/clinical" - pa "simrs-vx/pkg/auth-helper" + pa "simrs-vx/internal/lib/auth" ) type CreateDto struct { diff --git a/internal/interface/main-handler/adime/handler.go b/internal/interface/main-handler/adime/handler.go index 9eabb0af..715f5faf 100644 --- a/internal/interface/main-handler/adime/handler.go +++ b/internal/interface/main-handler/adime/handler.go @@ -11,7 +11,7 @@ import ( e "simrs-vx/internal/domain/main-entities/adime" u "simrs-vx/internal/use-case/main-use-case/adime" - pa "simrs-vx/pkg/auth-helper" + pa "simrs-vx/internal/lib/auth" d "github.com/karincake/dodol" ) diff --git a/internal/interface/main-handler/authentication/handler.go b/internal/interface/main-handler/authentication/handler.go index 01d4fb89..709f33a3 100644 --- a/internal/interface/main-handler/authentication/handler.go +++ b/internal/interface/main-handler/authentication/handler.go @@ -10,7 +10,7 @@ import ( m "simrs-vx/internal/domain/main-entities/user" s "simrs-vx/internal/use-case/main-use-case/authentication" - pa "simrs-vx/pkg/auth-helper" + pa "simrs-vx/internal/lib/auth" ) func Login(w http.ResponseWriter, r *http.Request) { diff --git a/internal/interface/main-handler/chemo/handler.go b/internal/interface/main-handler/chemo/handler.go index ee8c0435..90552020 100644 --- a/internal/interface/main-handler/chemo/handler.go +++ b/internal/interface/main-handler/chemo/handler.go @@ -14,7 +14,7 @@ import ( u "simrs-vx/internal/use-case/main-use-case/chemo" - pa "simrs-vx/pkg/auth-helper" + pa "simrs-vx/internal/lib/auth" d "github.com/karincake/dodol" ) diff --git a/internal/interface/main-handler/consultation/handler.go b/internal/interface/main-handler/consultation/handler.go index 2be1cbdd..2810d2f3 100644 --- a/internal/interface/main-handler/consultation/handler.go +++ b/internal/interface/main-handler/consultation/handler.go @@ -11,7 +11,7 @@ import ( e "simrs-vx/internal/domain/main-entities/consultation" u "simrs-vx/internal/use-case/main-use-case/consultation" - pa "simrs-vx/pkg/auth-helper" + pa "simrs-vx/internal/lib/auth" d "github.com/karincake/dodol" ) diff --git a/internal/interface/main-handler/device-order/handler.go b/internal/interface/main-handler/device-order/handler.go index 42135e58..12999301 100644 --- a/internal/interface/main-handler/device-order/handler.go +++ b/internal/interface/main-handler/device-order/handler.go @@ -9,7 +9,7 @@ import ( e "simrs-vx/internal/domain/main-entities/device-order" u "simrs-vx/internal/use-case/main-use-case/device-order" - pa "simrs-vx/pkg/auth-helper" + pa "simrs-vx/internal/lib/auth" d "github.com/karincake/dodol" ) diff --git a/internal/interface/main-handler/encounter/handler.go b/internal/interface/main-handler/encounter/handler.go index df3320ef..a35f6ba9 100644 --- a/internal/interface/main-handler/encounter/handler.go +++ b/internal/interface/main-handler/encounter/handler.go @@ -12,7 +12,7 @@ import ( u "simrs-vx/internal/use-case/main-use-case/encounter" erc "simrs-vx/internal/domain/references/common" - pa "simrs-vx/pkg/auth-helper" + pa "simrs-vx/internal/lib/auth" d "github.com/karincake/dodol" ) @@ -36,7 +36,12 @@ func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } dto := e.ReadListDto{} + dto.AuthInfo = *authInfo sf.UrlQueryParam(&dto, *r.URL) res, err := u.ReadList(dto) rw.DataResponse(w, res, err) diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 6a98487f..f4871af2 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -135,6 +135,19 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/prescription-item", prescriptionitem.O) hc.RegCrud(r, "/v1/device-order-item", deviceorderitem.O) hc.RegCrud(r, "/v1/material-order-item", materialorderitem.O) + + hk.GroupRoutes("/v1/encounter", r, auth.GuardMW, hk.MapHandlerFunc{ + "GET /": encounter.O.GetList, + "GET /{id}": encounter.O.GetDetail, + "POST /": encounter.O.Create, + "PATCH /{id}": encounter.O.Update, + "DELETE /{id}": encounter.O.Delete, + "PATCH /{id}/checkout": encounter.O.CheckOut, + "PATCH /{id}/proccess": encounter.O.Process, + "PATCH /{id}/cancel": encounter.O.Cancel, + "PATCH /{id}/reject": encounter.O.Reject, + "PATCH /{id}/skip": encounter.O.Skip, + }) hk.GroupRoutes("/v1/mcu-order", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": mcuorder.O.GetList, "GET /{id}": mcuorder.O.GetDetail, @@ -153,7 +166,7 @@ func SetRoutes() http.Handler { "PATCH /{id}/complete": mcuorderitem.O.Complete, "PATCH /{id}/set-schedule": mcuorderitem.O.SetSchedule, }) - hk.GroupRoutes("/v1/prescription", r, hk.MapHandlerFunc{ + hk.GroupRoutes("/v1/prescription", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": prescription.O.GetList, "GET /{id}": prescription.O.GetDetail, "POST /": prescription.O.Create, @@ -161,7 +174,7 @@ func SetRoutes() http.Handler { "DELETE /{id}": prescription.O.Delete, "PATCH /{id}/approve": prescription.O.Approve, }) - hk.GroupRoutes("/v1/mcu-order-sub-item", r, hk.MapHandlerFunc{ + hk.GroupRoutes("/v1/mcu-order-sub-item", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": mcuordersubitem.O.GetList, "GET /{id}": mcuordersubitem.O.GetDetail, "POST /": mcuordersubitem.O.Create, @@ -169,18 +182,6 @@ func SetRoutes() http.Handler { "DELETE /{id}": mcuordersubitem.O.Delete, "PATCH /{id}/complete": mcuordersubitem.O.Complete, }) - hk.GroupRoutes("/v1/encounter", r, auth.GuardMW, hk.MapHandlerFunc{ - "GET /": encounter.O.GetList, - "GET /{id}": encounter.O.GetDetail, - "POST /": encounter.O.Create, - "PATCH /{id}": encounter.O.Update, - "DELETE /{id}": encounter.O.Delete, - "PATCH /{id}/checkout": encounter.O.CheckOut, - "PATCH /{id}/proccess": encounter.O.Process, - "PATCH /{id}/cancel": encounter.O.Cancel, - "PATCH /{id}/reject": encounter.O.Reject, - "PATCH /{id}/skip": encounter.O.Skip, - }) hk.GroupRoutes("/v1/medication", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": medication.O.GetList, "GET /{id}": medication.O.GetDetail, @@ -190,7 +191,7 @@ func SetRoutes() http.Handler { "PATCH /{id}/complete": medication.O.Complete, }) - hk.GroupRoutes("/v1/medication-item", r, hk.MapHandlerFunc{ + hk.GroupRoutes("/v1/medication-item", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": medicationitem.O.GetList, "GET /{id}": medicationitem.O.GetDetail, "POST /": medicationitem.O.Create, diff --git a/internal/interface/main-handler/material-order/handler.go b/internal/interface/main-handler/material-order/handler.go index ae8777cb..34c2b142 100644 --- a/internal/interface/main-handler/material-order/handler.go +++ b/internal/interface/main-handler/material-order/handler.go @@ -11,7 +11,7 @@ import ( e "simrs-vx/internal/domain/main-entities/material-order" u "simrs-vx/internal/use-case/main-use-case/material-order" - pa "simrs-vx/pkg/auth-helper" + pa "simrs-vx/internal/lib/auth" d "github.com/karincake/dodol" ) diff --git a/internal/interface/main-handler/mcu-order/handler.go b/internal/interface/main-handler/mcu-order/handler.go index bcd07a05..2cdb5c32 100644 --- a/internal/interface/main-handler/mcu-order/handler.go +++ b/internal/interface/main-handler/mcu-order/handler.go @@ -11,7 +11,7 @@ import ( e "simrs-vx/internal/domain/main-entities/mcu-order" u "simrs-vx/internal/use-case/main-use-case/mcu-order" - pa "simrs-vx/pkg/auth-helper" + pa "simrs-vx/internal/lib/auth" d "github.com/karincake/dodol" ) diff --git a/internal/interface/main-handler/medication-item-dist/handler.go b/internal/interface/main-handler/medication-item-dist/handler.go index 6c4b659f..9dd00d2b 100644 --- a/internal/interface/main-handler/medication-item-dist/handler.go +++ b/internal/interface/main-handler/medication-item-dist/handler.go @@ -6,7 +6,7 @@ import ( rw "github.com/karincake/risoles" sf "github.com/karincake/semprit" - pa "simrs-vx/pkg/auth-helper" + pa "simrs-vx/internal/lib/auth" e "simrs-vx/internal/domain/main-entities/medication-item-dist" u "simrs-vx/internal/use-case/main-use-case/medication-item-dist" diff --git a/internal/interface/main-handler/medication/handler.go b/internal/interface/main-handler/medication/handler.go index 272eae56..12fb6c84 100644 --- a/internal/interface/main-handler/medication/handler.go +++ b/internal/interface/main-handler/medication/handler.go @@ -6,7 +6,7 @@ import ( rw "github.com/karincake/risoles" sf "github.com/karincake/semprit" - pa "simrs-vx/pkg/auth-helper" + pa "simrs-vx/internal/lib/auth" e "simrs-vx/internal/domain/main-entities/medication" u "simrs-vx/internal/use-case/main-use-case/medication" diff --git a/internal/interface/main-handler/prescription/handler.go b/internal/interface/main-handler/prescription/handler.go index fe73e3fe..24d73372 100644 --- a/internal/interface/main-handler/prescription/handler.go +++ b/internal/interface/main-handler/prescription/handler.go @@ -7,6 +7,9 @@ import ( sf "github.com/karincake/semprit" // ua "github.com/karincake/tumpeng/auth/svc" + d "github.com/karincake/dodol" + + pa "simrs-vx/internal/lib/auth" e "simrs-vx/internal/domain/main-entities/prescription" u "simrs-vx/internal/use-case/main-use-case/prescription" @@ -21,6 +24,11 @@ func (obj myBase) Create(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.AuthInfo = *authInfo res, err := u.Create(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/sbar/handler.go b/internal/interface/main-handler/sbar/handler.go index 7fac1e00..bcf63c8a 100644 --- a/internal/interface/main-handler/sbar/handler.go +++ b/internal/interface/main-handler/sbar/handler.go @@ -11,7 +11,7 @@ import ( e "simrs-vx/internal/domain/main-entities/sbar" u "simrs-vx/internal/use-case/main-use-case/sbar" - pa "simrs-vx/pkg/auth-helper" + pa "simrs-vx/internal/lib/auth" d "github.com/karincake/dodol" ) diff --git a/internal/interface/main-handler/soapi/handler.go b/internal/interface/main-handler/soapi/handler.go index f5446b82..fe50b7d2 100644 --- a/internal/interface/main-handler/soapi/handler.go +++ b/internal/interface/main-handler/soapi/handler.go @@ -11,7 +11,7 @@ import ( e "simrs-vx/internal/domain/main-entities/soapi" u "simrs-vx/internal/use-case/main-use-case/soapi" - pa "simrs-vx/pkg/auth-helper" + pa "simrs-vx/internal/lib/auth" d "github.com/karincake/dodol" ) diff --git a/internal/lib/.keep b/internal/lib/.keep new file mode 100644 index 00000000..e69de29b diff --git a/pkg/auth-helper/auth-helper.go b/internal/lib/auth/auth.go similarity index 100% rename from pkg/auth-helper/auth-helper.go rename to internal/lib/auth/auth.go diff --git a/pkg/auth-helper/tycovar.go b/internal/lib/auth/tycovar.go similarity index 84% rename from pkg/auth-helper/tycovar.go rename to internal/lib/auth/tycovar.go index 06618350..654115fc 100644 --- a/pkg/auth-helper/tycovar.go +++ b/internal/lib/auth/tycovar.go @@ -6,16 +6,23 @@ import ( type AuthKey struct{} +// const AuthKey = struct{}{} type AuthInfo struct { Uuid string User_Id uint User_Name string User_ContractPosition_code string Employee_Position_Code *string + Employee_Id *int + Doctor_Id *int + Nurse_Id *int + Midwife_Id *int + Nutritionist_Id *int + Laborant_Id *int + Pharmachist_Id *int Intern_Position_Code *string - User_DivisionPositions []DivisionPosition - // User_DivisionPositions []DivisionPosition - // User_Position_Code string + Roles []string + // User_DivisionPositions []DivisionPosition } type DivisionPosition struct { diff --git a/internal/use-case/main-use-case/authentication/case.go b/internal/use-case/main-use-case/authentication/case.go index f38e82d0..18ae9b8a 100644 --- a/internal/use-case/main-use-case/authentication/case.go +++ b/internal/use-case/main-use-case/authentication/case.go @@ -13,12 +13,13 @@ import ( "simrs-vx/internal/domain/main-entities/intern" eu "simrs-vx/internal/domain/main-entities/user" - pa "simrs-vx/pkg/auth-helper" + pa "simrs-vx/internal/lib/auth" el "simrs-vx/pkg/logger" p "simrs-vx/pkg/password" ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/employee" + em "simrs-vx/internal/domain/main-entities/midwife" en "simrs-vx/internal/domain/main-entities/nurse" erc "simrs-vx/internal/domain/references/common" erg "simrs-vx/internal/domain/references/organization" @@ -147,13 +148,21 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { outputData["subspecialist_id"] = doctor.Subspecialist_Id } case erg.EPCNur: - nurse := en.Nurse{} - dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&nurse) - if nurse.Id == 0 { + empData := en.Nurse{} + dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + if empData.Id == 0 { return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: el.GenMessage("auth-noNurse")}} } - atClaims["nurse_id"] = nurse.Id - outputData["nurse_id"] = nurse.Id + atClaims["nurse_id"] = empData.Id + outputData["nurse_id"] = empData.Id + case erg.EPCMwi: + empData := em.Midwife{} + dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + if empData.Id == 0 { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: el.GenMessage("auth-noNurse")}} + } + atClaims["nurse_id"] = empData.Id + outputData["nurse_id"] = empData.Id } errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: el.GenMessage("auth-getData-failed")}} @@ -289,43 +298,22 @@ func ExtractToken(r *http.Request, tokenType TokenType) (data *pa.AuthInfo, err if accessUuidRedis.String() == "" { return nil, d.FieldError{Code: "token-unidentified", Message: el.GenMessage("token-unidentified")} } - user_name := fmt.Sprintf("%v", claims["user_name"]) - // user_email := "" - // if v, exist := claims["user_email"]; exist && v != nil { - // user_email = v.(string) - // } - // ref_id := 0 - // if v, exist := claims["user_ref_id"]; exist && v != nil { - // tmp := v.(float64) - // ref_id = int(tmp) - // } - // position_code := "" - // if v, exist := claims["user_position_code"]; exist && v != nil { - // position_code = v.(string) - // } - // data = &AuthInfo{ - // Uuid: accessUuid, - // User_Id: int(user_id), - // User_Name: user_name, - // User_Email: user_email, - // User_Ref_Id: ref_id, - // User_Position_Code: position_code, - contractPosition_code := "" - if v, exist := claims["contractPosition_code"]; exist && v != nil { - contractPosition_code = v.(string) - } - employee_position_code := "" - if v, exist := claims["employee_position_code"]; exist && v != nil { - employee_position_code = v.(string) - } data = &pa.AuthInfo{ - Uuid: accessUuid, - User_Id: uint(user_id), - User_Name: user_name, - User_ContractPosition_code: contractPosition_code, - Employee_Position_Code: &employee_position_code, + Uuid: accessUuid, + User_Id: uint(user_id), + User_Name: fmt.Sprintf("%v", claims["user_name"]), } + + data.User_ContractPosition_code = checkStrClaims(claims, "contractPosition_code") + data.Employee_Position_Code = checkStrPtrClaims(claims, "employee_position_code") + data.Doctor_Id = checkIntPtrClaims(claims, "doctor_id") + data.Nurse_Id = checkIntPtrClaims(claims, "nurse_id") + data.Midwife_Id = checkIntPtrClaims(claims, "midwife_id") + data.Nutritionist_Id = checkIntPtrClaims(claims, "nutritionist_id") + data.Laborant_Id = checkIntPtrClaims(claims, "laborant_id") + data.Pharmachist_Id = checkIntPtrClaims(claims, "pharmachist_id") + data.Intern_Position_Code = checkStrPtrClaims(claims, "intern_position_code") return } return nil, d.FieldError{Code: "token", Message: "token-invalid"} @@ -334,3 +322,33 @@ func ExtractToken(r *http.Request, tokenType TokenType) (data *pa.AuthInfo, err func GetConfig() { a.ParseCfg(&authCfg) } + +func checkStrClaims(claim map[string]interface{}, key string) string { + if v, exist := claim[key]; exist && v != nil { + return v.(string) + } + return "" +} + +func checkStrPtrClaims(claim map[string]interface{}, key string) *string { + if v, exist := claim[key]; exist && v != nil { + val := v.(string) + return &val + } + return nil +} + +func checkIntClaims(claim map[string]interface{}, key string) int { + if v, exist := claim[key]; exist && v != nil { + return v.(int) + } + return 0 +} + +func checkIntPtrClaims(claim map[string]interface{}, key string) *int { + if v, exist := claim[key]; exist && v != nil { + val := int(v.(float64)) + return &val + } + return nil +} diff --git a/internal/use-case/main-use-case/authentication/helper.go b/internal/use-case/main-use-case/authentication/helper.go index 87473386..bec64518 100644 --- a/internal/use-case/main-use-case/authentication/helper.go +++ b/internal/use-case/main-use-case/authentication/helper.go @@ -28,10 +28,6 @@ func getAndCheck(input, condition any) (eCode string) { return "" } -func getDocName(id uint) string { - return "authentication" -} - func getDivisionPosition(employee_id uint) ([]string, error) { var result []string diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index ccc4b811..fce7db74 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -1,15 +1,21 @@ package encounter import ( - e "simrs-vx/internal/domain/main-entities/encounter" + // std + "errors" + // external + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" + + // pkg plh "simrs-vx/pkg/lib-helper" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" - dg "github.com/karincake/apem/db-gorm-pg" - gh "github.com/karincake/getuk" - "gorm.io/gorm" + // internal + e "simrs-vx/internal/domain/main-entities/encounter" ) func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Encounter, error) { @@ -34,6 +40,10 @@ func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Encount } func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Encounter, *e.MetaDto, error) { + if input.AuthInfo.User_Id == 0 { + return nil, nil, plh.HandleListError(input, event, errors.New("user_id is required")) + } + pl.SetLogInfo(event, input, "started", "DBReadList") data := []e.Encounter{} pagination := gh.Pagination{} @@ -46,10 +56,13 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.En } else { tx = dg.I } + tx = tx.Model(&e.Encounter{}) - tx = tx. - Model(&e.Encounter{}). - Scopes(gh.Preload(input.Includes)). + if input.AuthInfo.Doctor_Id != nil { + tx.Where("\"Responsible_Doctor_Id\" = ?", *input.AuthInfo.Doctor_Id) + } + + tx.Scopes(gh.Preload(input.Includes)). Scopes(gh.Filter(input.FilterDto)). Count(&count). Scopes(gh.Paginate(input, &pagination)). From a2ce9d9357c0fa0a4caafbf183e03ef8ae2b4f52 Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 27 Oct 2025 06:25:12 +0700 Subject: [PATCH 015/329] add encounter-checkin --- .../domain/main-entities/encounter/dto.go | 11 ++ .../main-handler/encounter/handler.go | 21 ++++ .../encounter/request-validation.go | 16 ++- .../interface/main-handler/main-handler.go | 21 ++-- .../main-use-case/adm-employee-hist/case.go | 27 ----- .../use-case/main-use-case/encounter/case.go | 105 ++++++++++++++++++ .../main-use-case/encounter/helper.go | 5 + .../use-case/main-use-case/encounter/lib.go | 25 +++++ .../responsible-doctor-hist/case.go | 27 ----- 9 files changed, 192 insertions(+), 66 deletions(-) diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index 4a30281d..ae8d1c5f 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -105,6 +105,17 @@ type DischargeDto struct { InternalReferences *[]eir.CreateDto `json:"internalReferences,omitempty"` } +type CheckinDto struct { + Id uint `json:"id"` + Responsible_Doctor_Id *uint `json:"responsible_doctor_id"` + Responsible_Doctor_StartedAt *time.Time `json:"responsible_doctor_startedAt"` + Responsible_Doctor_FinishedAt *time.Time `json:"responsible_doctor_finishedAt"` + + Adm_Employee_Id *uint `json:"adm_employee_id"` + Adm_Employee_StartedAt *time.Time `json:"adm_employee_startedAt"` + Adm_Employee_FinishedAt *time.Time `json:"adm_employee_finishedAt"` +} + type ResponseDto struct { ecore.Main Patient_Id *uint `json:"patient_id"` diff --git a/internal/interface/main-handler/encounter/handler.go b/internal/interface/main-handler/encounter/handler.go index df3320ef..85b8746d 100644 --- a/internal/interface/main-handler/encounter/handler.go +++ b/internal/interface/main-handler/encounter/handler.go @@ -102,6 +102,27 @@ func (obj myBase) CheckOut(w http.ResponseWriter, r *http.Request) { rw.DataResponse(w, res, err) } +func (obj myBase) CheckIn(w http.ResponseWriter, r *http.Request) { + dto := e.CheckinDto{} + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + + // validate request body + if valid := validateRequestCheckIn(w, dto); !valid { + return + } + + dto.Id = uint(id) + res, err := u.CheckIn(dto) + rw.DataResponse(w, res, err) +} + func (obj myBase) Process(w http.ResponseWriter, r *http.Request) { id := rw.ValidateInt(w, "id", r.PathValue("id")) if id <= 0 { diff --git a/internal/interface/main-handler/encounter/request-validation.go b/internal/interface/main-handler/encounter/request-validation.go index 182dd12e..9e92ea88 100644 --- a/internal/interface/main-handler/encounter/request-validation.go +++ b/internal/interface/main-handler/encounter/request-validation.go @@ -10,9 +10,9 @@ import ( rw "github.com/karincake/risoles" ) -func validateRequestCheckout(w http.ResponseWriter, i e.DischargeDto) (valid bool) { - const dataValidationFail = "" +const dataValidationFail = "data-validation-fail" +func validateRequestCheckout(w http.ResponseWriter, i e.DischargeDto) (valid bool) { switch *i.Discharge_Method_Code { case ere.DMCDeath: if i.DeathCause == nil { @@ -51,3 +51,15 @@ func validateRequestCheckout(w http.ResponseWriter, i e.DischargeDto) (valid boo } return true } + +func validateRequestCheckIn(w http.ResponseWriter, i e.CheckinDto) (valid bool) { + if i.Responsible_Doctor_Id == nil && i.Adm_Employee_Id == nil { + rw.DataResponse(w, nil, d.FieldError{ + Code: dataValidationFail, + Message: "responsible_doctor_id or adm_employee_id required", + }) + return + } + + return true +} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 89b55f26..23b532c2 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -172,16 +172,17 @@ func SetRoutes() http.Handler { "PATCH /{id}/complete": mcuordersubitem.O.Complete, }) hk.GroupRoutes("/v1/encounter", r, auth.GuardMW, hk.MapHandlerFunc{ - "GET /": encounter.O.GetList, - "GET /{id}": encounter.O.GetDetail, - "POST /": encounter.O.Create, - "PATCH /{id}": encounter.O.Update, - "DELETE /{id}": encounter.O.Delete, - "PATCH /{id}/checkout": encounter.O.CheckOut, - "PATCH /{id}/proccess": encounter.O.Process, - "PATCH /{id}/cancel": encounter.O.Cancel, - "PATCH /{id}/reject": encounter.O.Reject, - "PATCH /{id}/skip": encounter.O.Skip, + "GET /": encounter.O.GetList, + "GET /{id}": encounter.O.GetDetail, + "POST /": encounter.O.Create, + "PATCH /{id}": encounter.O.Update, + "DELETE /{id}": encounter.O.Delete, + "PATCH /{id}/check-out": encounter.O.CheckOut, + "PATCH /{id}/check-in": encounter.O.CheckIn, + "PATCH /{id}/proccess": encounter.O.Process, + "PATCH /{id}/cancel": encounter.O.Cancel, + "PATCH /{id}/reject": encounter.O.Reject, + "PATCH /{id}/skip": encounter.O.Skip, }) hk.GroupRoutes("/v1/medication", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": medication.O.GetList, diff --git a/internal/use-case/main-use-case/adm-employee-hist/case.go b/internal/use-case/main-use-case/adm-employee-hist/case.go index 13e308bf..51851584 100644 --- a/internal/use-case/main-use-case/adm-employee-hist/case.go +++ b/internal/use-case/main-use-case/adm-employee-hist/case.go @@ -2,13 +2,8 @@ package adm_employee_hist import ( e "simrs-vx/internal/domain/main-entities/adm-employee-hist" - eem "simrs-vx/internal/domain/main-entities/employee" - ee "simrs-vx/internal/domain/main-entities/encounter" "strconv" - uem "simrs-vx/internal/use-case/main-use-case/employee" - ue "simrs-vx/internal/use-case/main-use-case/encounter" - dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -39,10 +34,6 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } - if err := validateForeignKey(input); err != nil { - return err - } - if resData, err := CreateData(input, &event, tx); err != nil { return err } else { @@ -200,10 +191,6 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } - if err := validateForeignKey(input.CreateDto); err != nil { - return err - } - if err := UpdateData(input, data, &event, tx); err != nil { return err } @@ -287,17 +274,3 @@ func Delete(input e.DeleteDto) (*d.Data, error) { }, nil } - -func validateForeignKey(input e.CreateDto) error { - // validate encounter_id - if _, err := ue.ReadDetail(ee.ReadDetailDto{Id: uint16(*input.Encounter_Id)}); err != nil { - return err - } - - // validate doctor_id - if _, err := uem.ReadDetail(eem.ReadDetailDto{Id: uint16(*input.Employee_Id)}); err != nil { - return err - } - - return nil -} diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 04eedfff..4e41954e 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -4,20 +4,26 @@ import ( "errors" "strconv" + eaeh "simrs-vx/internal/domain/main-entities/adm-employee-hist" ea "simrs-vx/internal/domain/main-entities/ambulatory" ec "simrs-vx/internal/domain/main-entities/chemo" edc "simrs-vx/internal/domain/main-entities/death-cause" + ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/emergency" eem "simrs-vx/internal/domain/main-entities/employee" e "simrs-vx/internal/domain/main-entities/encounter" ei "simrs-vx/internal/domain/main-entities/inpatient" + erdh "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" + uaeh "simrs-vx/internal/use-case/main-use-case/adm-employee-hist" ua "simrs-vx/internal/use-case/main-use-case/ambulatory" uc "simrs-vx/internal/use-case/main-use-case/chemo" udc "simrs-vx/internal/use-case/main-use-case/death-cause" + ud "simrs-vx/internal/use-case/main-use-case/doctor" ue "simrs-vx/internal/use-case/main-use-case/emergency" uem "simrs-vx/internal/use-case/main-use-case/employee" ui "simrs-vx/internal/use-case/main-use-case/inpatient" + urdh "simrs-vx/internal/use-case/main-use-case/responsible-doctor-hist" erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" @@ -511,3 +517,102 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) { }, nil } + +func CheckIn(input e.CheckinDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + var data *e.Encounter + var err error + + event := pl.Event{ + Feature: "CheckIn", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "checkIn") + + // validate foreign key + if err := validateForeignKey(input); err != nil { + return nil, err + } + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err + } + + if data.IsDone() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-state-mismatch", + Detail: "encounter is done", + Raw: errors.New("encounter is done"), + } + return pl.SetLogError(&event, input) + } + + if err := updateCheckInData(input, data, &event, tx); err != nil { + return err + } + + if input.Responsible_Doctor_Id != nil { + // insert responsible_doctor_hist + if _, err = urdh.Create(erdh.CreateDto{ + Encounter_Id: &input.Id, + Doctor_Id: input.Responsible_Doctor_Id, + StartedAt: input.Responsible_Doctor_StartedAt, + FinishedAt: input.Responsible_Doctor_FinishedAt, + }); err != nil { + return err + } + } + + if input.Adm_Employee_Id != nil { + // insert responsible_doctor_hist + if _, err = uaeh.Create(eaeh.CreateDto{ + Encounter_Id: &input.Id, + Employee_Id: input.Adm_Employee_Id, + StartedAt: input.Adm_Employee_StartedAt, + FinishedAt: input.Adm_Employee_FinishedAt, + }); err != nil { + return err + } + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "checkIn", + }, + Data: data.ToResponse(), + }, nil +} + +func validateForeignKey(input e.CheckinDto) error { + // validate employee_Id + if input.Adm_Employee_Id != nil { + if _, err := uem.ReadDetail(eem.ReadDetailDto{Id: uint16(*input.Adm_Employee_Id)}); err != nil { + return err + } + } + + // validate doctor_id + if input.Responsible_Doctor_Id != nil { + if _, err := ud.ReadDetail(ed.ReadDetailDto{Id: uint16(*input.Responsible_Doctor_Id)}); err != nil { + return err + } + } + + return nil +} diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index 41fd6a51..878a472f 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -327,6 +327,11 @@ func setDataUpdateStatus(src e.UpdateStatusDto, dst *e.Encounter) { dst.Status_Code = src.StatusCode } +func setDataCheckIn(src e.CheckinDto, dst *e.Encounter) { + dst.Responsible_Doctor_Id = src.Responsible_Doctor_Id + dst.Adm_Employee_Id = src.Adm_Employee_Id +} + func createInternalReferences(input e.DischargeDto, event *pl.Event, tx *gorm.DB) error { unitIDs := make(map[uint16]struct{}) doctorIDs := make(map[uint]struct{}) diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index ccc4b811..d1dd1afd 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -212,3 +212,28 @@ func UpdateStatusData(input e.UpdateStatusDto, data *e.Encounter, event *pl.Even pl.SetLogInfo(event, nil, "complete") return nil } + +func updateCheckInData(input e.CheckinDto, data *e.Encounter, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setDataCheckIn(input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 +} diff --git a/internal/use-case/main-use-case/responsible-doctor-hist/case.go b/internal/use-case/main-use-case/responsible-doctor-hist/case.go index 591c6dd7..3451a88f 100644 --- a/internal/use-case/main-use-case/responsible-doctor-hist/case.go +++ b/internal/use-case/main-use-case/responsible-doctor-hist/case.go @@ -1,14 +1,9 @@ package responsible_doctor_hist import ( - ed "simrs-vx/internal/domain/main-entities/doctor" - ee "simrs-vx/internal/domain/main-entities/encounter" e "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" "strconv" - ud "simrs-vx/internal/use-case/main-use-case/doctor" - ue "simrs-vx/internal/use-case/main-use-case/encounter" - dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -39,10 +34,6 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } - if err := validateForeignKey(input); err != nil { - return err - } - if resData, err := CreateData(input, &event, tx); err != nil { return err } else { @@ -200,10 +191,6 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } - if err := validateForeignKey(input.CreateDto); err != nil { - return err - } - if err := UpdateData(input, data, &event, tx); err != nil { return err } @@ -287,17 +274,3 @@ func Delete(input e.DeleteDto) (*d.Data, error) { }, nil } - -func validateForeignKey(input e.CreateDto) error { - // validate encounter_id - if _, err := ue.ReadDetail(ee.ReadDetailDto{Id: uint16(*input.Encounter_Id)}); err != nil { - return err - } - - // validate doctor_id - if _, err := ud.ReadDetail(ed.ReadDetailDto{Id: uint16(*input.Doctor_Id)}); err != nil { - return err - } - - return nil -} From 0aa2ed730ca857c1226824f7ff530ccbbf95945d Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 27 Oct 2025 14:34:52 +0700 Subject: [PATCH 016/329] add checkin --- .../domain/main-entities/encounter/dto.go | 13 ++-- .../main-handler/encounter/handler.go | 8 ++ .../use-case/main-use-case/encounter/case.go | 44 ++++++----- .../main-use-case/encounter/helper.go | 9 ++- .../use-case/main-use-case/encounter/lib.go | 73 +++++++++++++++++++ 5 files changed, 119 insertions(+), 28 deletions(-) diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index d07665f0..b552ba86 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -114,14 +114,11 @@ type DischargeDto struct { } type CheckinDto struct { - Id uint `json:"id"` - Responsible_Doctor_Id *uint `json:"responsible_doctor_id"` - Responsible_Doctor_StartedAt *time.Time `json:"responsible_doctor_startedAt"` - Responsible_Doctor_FinishedAt *time.Time `json:"responsible_doctor_finishedAt"` - - Adm_Employee_Id *uint `json:"adm_employee_id"` - Adm_Employee_StartedAt *time.Time `json:"adm_employee_startedAt"` - Adm_Employee_FinishedAt *time.Time `json:"adm_employee_finishedAt"` + Id uint `json:"id"` + Responsible_Doctor_Id *uint `json:"responsible_doctor_id"` + Adm_Employee_Id *uint `json:"adm_employee_id"` + StartedAt *time.Time `json:"startedAt"` + FinishedAt *time.Time `json:"finishedAt"` } type ResponseDto struct { diff --git a/internal/interface/main-handler/encounter/handler.go b/internal/interface/main-handler/encounter/handler.go index ed8b1fbc..a5e74855 100644 --- a/internal/interface/main-handler/encounter/handler.go +++ b/internal/interface/main-handler/encounter/handler.go @@ -2,6 +2,7 @@ package encounter import ( "net/http" + "time" rw "github.com/karincake/risoles" sf "github.com/karincake/semprit" @@ -124,6 +125,13 @@ func (obj myBase) CheckIn(w http.ResponseWriter, r *http.Request) { } dto.Id = uint(id) + + // validate startedAt + if dto.StartedAt == nil { + now := time.Now() + dto.StartedAt = &now + } + res, err := u.CheckIn(dto) rw.DataResponse(w, res, err) } diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 4e41954e..6786eb51 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -2,9 +2,12 @@ package encounter import ( "errors" + eaeh "simrs-vx/internal/domain/main-entities/adm-employee-hist" + erdh "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" + uaeh "simrs-vx/internal/use-case/main-use-case/adm-employee-hist" + urdh "simrs-vx/internal/use-case/main-use-case/responsible-doctor-hist" "strconv" - eaeh "simrs-vx/internal/domain/main-entities/adm-employee-hist" ea "simrs-vx/internal/domain/main-entities/ambulatory" ec "simrs-vx/internal/domain/main-entities/chemo" edc "simrs-vx/internal/domain/main-entities/death-cause" @@ -13,9 +16,8 @@ import ( eem "simrs-vx/internal/domain/main-entities/employee" e "simrs-vx/internal/domain/main-entities/encounter" ei "simrs-vx/internal/domain/main-entities/inpatient" - erdh "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" - - uaeh "simrs-vx/internal/use-case/main-use-case/adm-employee-hist" + erc "simrs-vx/internal/domain/references/common" + ere "simrs-vx/internal/domain/references/encounter" ua "simrs-vx/internal/use-case/main-use-case/ambulatory" uc "simrs-vx/internal/use-case/main-use-case/chemo" udc "simrs-vx/internal/use-case/main-use-case/death-cause" @@ -23,10 +25,6 @@ import ( ue "simrs-vx/internal/use-case/main-use-case/emergency" uem "simrs-vx/internal/use-case/main-use-case/employee" ui "simrs-vx/internal/use-case/main-use-case/inpatient" - urdh "simrs-vx/internal/use-case/main-use-case/responsible-doctor-hist" - - erc "simrs-vx/internal/domain/references/common" - ere "simrs-vx/internal/domain/references/encounter" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -552,34 +550,44 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - if err := updateCheckInData(input, data, &event, tx); err != nil { - return err - } + // Insert responsible_doctor_hist if responsible_doctor_id has changed && update latest history + if input.Responsible_Doctor_Id != nil && *input.Responsible_Doctor_Id != *data.Responsible_Doctor_Id { + // update finishedAt in latest responsible_doctor_hist + if err = updateLatestResponsibleDoctorHist(input, &event, tx); err != nil { + return err + } - if input.Responsible_Doctor_Id != nil { - // insert responsible_doctor_hist + //insert responsible_doctor_hist if _, err = urdh.Create(erdh.CreateDto{ Encounter_Id: &input.Id, Doctor_Id: input.Responsible_Doctor_Id, - StartedAt: input.Responsible_Doctor_StartedAt, - FinishedAt: input.Responsible_Doctor_FinishedAt, + StartedAt: input.StartedAt, }); err != nil { return err } } - if input.Adm_Employee_Id != nil { + // Insert adm_employee_hist if adm_employee_id has changed && update latest history + if input.Adm_Employee_Id != nil && *input.Adm_Employee_Id != *data.Adm_Employee_Id { + // update finishedAt in latest adm_employee_hist + if err = updateLatestAdmEmployeeHist(input, &event, tx); err != nil { + return err + } + // insert responsible_doctor_hist if _, err = uaeh.Create(eaeh.CreateDto{ Encounter_Id: &input.Id, Employee_Id: input.Adm_Employee_Id, - StartedAt: input.Adm_Employee_StartedAt, - FinishedAt: input.Adm_Employee_FinishedAt, + StartedAt: input.StartedAt, }); err != nil { return err } } + if err := updateCheckInData(input, data, &event, tx); err != nil { + return err + } + pl.SetLogInfo(&event, nil, "complete") return nil diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index 878a472f..2e74eff6 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -328,8 +328,13 @@ func setDataUpdateStatus(src e.UpdateStatusDto, dst *e.Encounter) { } func setDataCheckIn(src e.CheckinDto, dst *e.Encounter) { - dst.Responsible_Doctor_Id = src.Responsible_Doctor_Id - dst.Adm_Employee_Id = src.Adm_Employee_Id + if src.Responsible_Doctor_Id != nil { + dst.Responsible_Doctor_Id = src.Responsible_Doctor_Id + } + + if src.Adm_Employee_Id != nil { + dst.Adm_Employee_Id = src.Adm_Employee_Id + } } func createInternalReferences(input e.DischargeDto, event *pl.Event, tx *gorm.DB) error { diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index f8bee755..6e960e49 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -3,6 +3,7 @@ package encounter import ( // std "errors" + "fmt" // external dg "github.com/karincake/apem/db-gorm-pg" @@ -15,7 +16,9 @@ import ( pu "simrs-vx/pkg/use-case-helper" // internal + eaeh "simrs-vx/internal/domain/main-entities/adm-employee-hist" e "simrs-vx/internal/domain/main-entities/encounter" + erdh "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" ) func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Encounter, error) { @@ -250,3 +253,73 @@ func updateCheckInData(input e.CheckinDto, data *e.Encounter, event *pl.Event, d pl.SetLogInfo(event, nil, "complete") return nil } + +func updateLatestResponsibleDoctorHist(input e.CheckinDto, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, "started", "DBUpdate") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + subQuery := tx. + Select("\"Id\""). + Model(&erdh.ResponsibleDoctorHist{}). + Where("\"Encounter_Id\" = ?", input.Id). + Order("\"CreatedAt\" DESC"). + Limit(1) + + fmt.Println(subQuery) + + if err := tx. + Model(&erdh.ResponsibleDoctorHist{}). + Where("\"Id\" = (?)", subQuery). + Update("\"FinishedAt\"", input.StartedAt).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 updateLatestAdmEmployeeHist(input e.CheckinDto, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, "started", "DBUpdate") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + subQuery := tx. + Select("\"Id\""). + Model(&eaeh.AdmEmployeeHist{}). + Where("\"Encounter_Id\" = ?", input.Id). + Order("\"CreatedAt\" DESC"). + Limit(1) + + if err := tx. + Model(&eaeh.AdmEmployeeHist{}). + Where("\"Id\" = (?)", subQuery). + Update("\"FinishedAt\"", input.StartedAt).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 +} From 17172742ec3adf4fc7ca07c885b21a9e8d5927c8 Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 27 Oct 2025 14:52:55 +0700 Subject: [PATCH 017/329] add column in encounter --- cmd/main-migration/migrations/20251027075128.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 7 ++++--- .../domain/main-entities/encounter/entity.go | 4 ++++ .../domain/references/encounter/encounter.go | 16 ++++++++++++++++ 4 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 cmd/main-migration/migrations/20251027075128.sql diff --git a/cmd/main-migration/migrations/20251027075128.sql b/cmd/main-migration/migrations/20251027075128.sql new file mode 100644 index 00000000..6d583866 --- /dev/null +++ b/cmd/main-migration/migrations/20251027075128.sql @@ -0,0 +1,2 @@ +-- Modify "Encounter" table +ALTER TABLE "public"."Encounter" ADD COLUMN "StartedAt" timestamptz NULL, ADD COLUMN "FinishedAt" timestamptz NULL, ADD COLUMN "RefType_Code" text NULL, ADD COLUMN "NewStatus" boolean NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 33455810..a045414f 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:BeGFyPoCNw+Am00+prXp3+lNStrspn2VED1Mz+3IWpI= +h1:ziMZz2LperFyae6+OgAW10C4nB3cdUxwlYGRyT+L+yU= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -58,5 +58,6 @@ h1:BeGFyPoCNw+Am00+prXp3+lNStrspn2VED1Mz+3IWpI= 20251023044432.sql h1:MkvajJs3bfk9+wHvQ43/ccAluJEBARm1gWr1u92ccLA= 20251024034832.sql h1:x3s3VEVYLOSKLAFxJGb2+c1FyTMMvPE+9k4Ew7rKQaI= 20251024074315.sql h1:EjAjelgi5qAfcRq/8vPTlGGYHvAKxNTllm8f0SzZDns= -20251025013451.sql h1:XTkUVKTZsZi9qphqhwXdVtHnhNNyJegbGYg+RKUXXag= -20251025013609.sql h1:Wlqjzsxm5Mb+sJPAyWsIrhwEx8oSSjfjYyHnAdkikzs= +20251025013451.sql h1:6hnuIiwYiG+6nLhOY/+Yyn+I6ZCFNRZxrJNqBV6HLqE= +20251025013609.sql h1:evPJaTD8WxYRMOJZHkSr7ONLx9PYxT+ankzQt9c/sJ0= +20251027075128.sql h1:bV1FEssEnGHBfBB4huqEHtIllIOJx+/l/WEJIlvKuK0= diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index fccbab41..37779409 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -32,10 +32,13 @@ type Encounter struct { Subspecialist_Id *uint16 `json:"subspecialist_id"` Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Id;references:Id"` VisitDate time.Time `json:"visitDate"` + StartedAt *time.Time `json:"startedAt"` + FinishedAt *time.Time `json:"finishedAt"` PaymentMethod_Code erc.PaymentMethodCode `json:"paymentMethod_code" gorm:"size:10"` InsuranceCompany_Id *uint `json:"insuranceCompany_id"` InsuranceCompany *ei.InsuranceCompany `json:"insuranceCompany,omitempty" gorm:"foreignKey:InsuranceCompany_Id;references:Id"` Member_Number *string `json:"memberNumber" gorm:"unique;size:20"` + RefType_Code *ere.RefTypeCode `json:"refType_code"` Ref_Number *string `json:"refNumber" gorm:"unique;size:20"` Trx_Number *string `json:"trxNumber" gorm:"unique;size:20"` Appointment_Doctor_Id *uint `json:"appointment_doctor_id"` @@ -57,6 +60,7 @@ type Encounter struct { Discharge_Date *time.Time `json:"discharge_date"` InternalReferences *[]eir.InternalReference `json:"internalReferences,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` DeathCause *edc.DeathCause `json:"deathCause,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + NewStatus bool `json:"newStatus"` } func (d Encounter) IsDone() bool { diff --git a/internal/domain/references/encounter/encounter.go b/internal/domain/references/encounter/encounter.go index 5b9515ec..eeccb8fe 100644 --- a/internal/domain/references/encounter/encounter.go +++ b/internal/domain/references/encounter/encounter.go @@ -15,6 +15,9 @@ type ( ChemoClassCode string AmbulanceFacilityCode string AmbulanceNeedsCode string + RefTypeCode string + AllPaymentMethodCode string + SEPRefTypeCode string ) const ( @@ -90,6 +93,19 @@ const ( ANCAssist AmbulanceNeedsCode = "assist" // Dengan Pendampingan ANCNonassist AmbulanceNeedsCode = "non-assist" // Tanpa Pendampingan + + RTCNone RefTypeCode = "none" // Tidak Ada + RTCGov RefTypeCode = "gov" // Pemerintah + RTCPrivate RefTypeCode = "private" // Swasta + RTCBpjs RefTypeCode = "bpjs" // BPJS + + APMCJkn AllPaymentMethodCode = "jkn" // JKN + APMCJkmm AllPaymentMethodCode = "jkmm" // JKMM + APMCSpm AllPaymentMethodCode = "spm" // SPM + APMCPks AllPaymentMethodCode = "pks" // PKS + + SRTCInternal SEPRefTypeCode = "internal" // Rujukan Internal + SRTCExternal SEPRefTypeCode = "external" // Faskes Lain ) func (ec EncounterClassCode) Code() string { From c96ce50824b4e12ac2aec1e889b42f4a6b43e124 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 27 Oct 2025 14:54:04 +0700 Subject: [PATCH 018/329] wip patient + parent number --- internal/domain/main-entities/patient/entity.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/domain/main-entities/patient/entity.go b/internal/domain/main-entities/patient/entity.go index 27d3c8ba..83afa6ce 100644 --- a/internal/domain/main-entities/patient/entity.go +++ b/internal/domain/main-entities/patient/entity.go @@ -16,4 +16,6 @@ type Patient struct { RegisteredBy_User_Name *string `json:"registeredBy_user_name" gorm:"size:100"` Status_Code erc.ActiveStatusCode `json:"status_code" gorm:"not null;size:10"` Number *string `json:"number" gorm:"unique;size:15"` + Parent_Number *string `json:"parent_number"` + Parent *Patient `json:"parent,omitempty" gorm:"foreignKey:Parent_Number;references:Number"` } From 2a66ce8361a479a1412368745be484cd39a0ec04 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 27 Oct 2025 16:20:26 +0700 Subject: [PATCH 019/329] specialist include subspecialist --- cmd/main-migration/migrations/20251027091406.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 5 +++-- internal/domain/main-entities/specialist/dto.go | 3 +++ .../domain/main-entities/specialist/entity.go | 14 ++++++++------ .../main-entities/subspecialist/base/entity.go | 16 ++++++++++++++++ .../domain/main-entities/subspecialist/entity.go | 7 ++----- 6 files changed, 34 insertions(+), 13 deletions(-) create mode 100644 cmd/main-migration/migrations/20251027091406.sql create mode 100644 internal/domain/main-entities/subspecialist/base/entity.go diff --git a/cmd/main-migration/migrations/20251027091406.sql b/cmd/main-migration/migrations/20251027091406.sql new file mode 100644 index 00000000..25df3058 --- /dev/null +++ b/cmd/main-migration/migrations/20251027091406.sql @@ -0,0 +1,2 @@ +-- Modify "Patient" table +ALTER TABLE "public"."Patient" ADD COLUMN "Parent_Number" character varying(15) NULL, ADD CONSTRAINT "fk_Patient_Parent" FOREIGN KEY ("Parent_Number") REFERENCES "public"."Patient" ("Number") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index a045414f..88047e74 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:ziMZz2LperFyae6+OgAW10C4nB3cdUxwlYGRyT+L+yU= +h1:+3BKB3OrRFxkAx+v0jB8Y1tcherlTS2Sfsp+nMCTSDE= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -60,4 +60,5 @@ h1:ziMZz2LperFyae6+OgAW10C4nB3cdUxwlYGRyT+L+yU= 20251024074315.sql h1:EjAjelgi5qAfcRq/8vPTlGGYHvAKxNTllm8f0SzZDns= 20251025013451.sql h1:6hnuIiwYiG+6nLhOY/+Yyn+I6ZCFNRZxrJNqBV6HLqE= 20251025013609.sql h1:evPJaTD8WxYRMOJZHkSr7ONLx9PYxT+ankzQt9c/sJ0= -20251027075128.sql h1:bV1FEssEnGHBfBB4huqEHtIllIOJx+/l/WEJIlvKuK0= +20251027075128.sql h1:/iFQBM1sytjqpyQSOx61q33gnorMgxTiFVSuL6bQqsM= +20251027091406.sql h1:4nzeZ5/kDtgMpWOH39XjnZsdfowaDN+jI7NWdP4Sqbw= diff --git a/internal/domain/main-entities/specialist/dto.go b/internal/domain/main-entities/specialist/dto.go index 3fa6bf5e..2cd4acee 100644 --- a/internal/domain/main-entities/specialist/dto.go +++ b/internal/domain/main-entities/specialist/dto.go @@ -3,6 +3,7 @@ package specialist import ( ecore "simrs-vx/internal/domain/base-entities/core" espb "simrs-vx/internal/domain/main-entities/specialist-position/base" + essb "simrs-vx/internal/domain/main-entities/subspecialist/base" ) type CreateDto struct { @@ -52,6 +53,7 @@ type ResponseDto struct { Name string `json:"name"` Unit_Id *uint16 `json:"unit_id"` SpecialistPositions []espb.Basic `json:"specialistPositions,omitempty"` + Subspecialists []essb.Basic `json:"subspecialists,omitempty"` } func (d Specialist) ToResponse() ResponseDto { @@ -60,6 +62,7 @@ func (d Specialist) ToResponse() ResponseDto { Name: d.Name, Unit_Id: d.Unit_Id, SpecialistPositions: d.SpecialistPositions, + Subspecialists: d.Subspecialists, } resp.SmallMain = d.SmallMain return resp diff --git a/internal/domain/main-entities/specialist/entity.go b/internal/domain/main-entities/specialist/entity.go index 5c2d5b89..9efb83b0 100644 --- a/internal/domain/main-entities/specialist/entity.go +++ b/internal/domain/main-entities/specialist/entity.go @@ -3,14 +3,16 @@ package specialist import ( ecore "simrs-vx/internal/domain/base-entities/core" eub "simrs-vx/internal/domain/main-entities/specialist-position/base" + essb "simrs-vx/internal/domain/main-entities/subspecialist/base" eu "simrs-vx/internal/domain/main-entities/unit" ) type Specialist struct { - ecore.SmallMain // adjust this according to the needs - Code string `json:"code" gorm:"unique;size:10"` - Name string `json:"name" gorm:"size:50"` - Unit_Id *uint16 `json:"unit_id"` - Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id"` - SpecialistPositions []eub.Basic `json:"specialistPositions,omitempty" gorm:"foreignKey:Specialist_Id;references:Id"` + ecore.SmallMain // adjust this according to the needs + Code string `json:"code" gorm:"unique;size:10"` + Name string `json:"name" gorm:"size:50"` + Unit_Id *uint16 `json:"unit_id"` + Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id"` + SpecialistPositions []eub.Basic `json:"specialistPositions,omitempty" gorm:"foreignKey:Specialist_Id;references:Id"` + Subspecialists []essb.Basic `json:"subspecialists,omitempty" gorm:"foreignKey:Specialist_Id;references:Id"` } diff --git a/internal/domain/main-entities/subspecialist/base/entity.go b/internal/domain/main-entities/subspecialist/base/entity.go new file mode 100644 index 00000000..bc516360 --- /dev/null +++ b/internal/domain/main-entities/subspecialist/base/entity.go @@ -0,0 +1,16 @@ +package base + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type Basic struct { + ecore.SmallMain // adjust this according to the needs + Code string `json:"code" gorm:"unique;size:10"` + Name string `json:"name" gorm:"size:50"` + Specialist_Id *uint16 `json:"specialist_id"` +} + +func (Basic) TableName() string { + return "Subspecialist" +} diff --git a/internal/domain/main-entities/subspecialist/entity.go b/internal/domain/main-entities/subspecialist/entity.go index a81d6ded..f2ff5d8e 100644 --- a/internal/domain/main-entities/subspecialist/entity.go +++ b/internal/domain/main-entities/subspecialist/entity.go @@ -1,16 +1,13 @@ package subspecialist import ( - ecore "simrs-vx/internal/domain/base-entities/core" es "simrs-vx/internal/domain/main-entities/specialist" espb "simrs-vx/internal/domain/main-entities/subspecialist-position/base" + esb "simrs-vx/internal/domain/main-entities/subspecialist/base" ) type Subspecialist struct { - ecore.SmallMain // adjust this according to the needs - Code string `json:"code" gorm:"unique;size:10"` - Name string `json:"name" gorm:"size:50"` - Specialist_Id *uint16 `json:"specialist_id"` + esb.Basic Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Id"` SubspecialistPositions []espb.Basic `json:"subspecialistPositions,omitempty" gorm:"foreignKey:Subspecialist_Id;references:Id"` } From 5dca15379018666fc2eef88576408829afc9a275 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 27 Oct 2025 16:25:12 +0700 Subject: [PATCH 020/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 128 ++++++++++++------------ 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 88047e74..a808ecf3 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,64 +1,64 @@ -h1:+3BKB3OrRFxkAx+v0jB8Y1tcherlTS2Sfsp+nMCTSDE= -20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= -20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= -20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= -20250908062323.sql h1:oXl6Z143tOpIl4EfP4B8JNU8LrMvVmHEtCgAfiB4gs8= -20250908073811.sql h1:m2aNXfnGxnLq1+rVWrh4f60q7fhyhV3gEwNu/OIqQlE= -20250908073839.sql h1:cPk54xjLdMs26uY8ZHjNWLuyfAMzV7Zb0/9oJQrsw04= -20250910055902.sql h1:5xwjAV6QbtZT9empTJKfhyAjdknbHzb15B0Ku5dzqtQ= -20250915123412.sql h1:D83xaU2YlDEd21HLup/YQpQ2easMToYCyy/oK6AFgQs= -20250916043819.sql h1:ekoTJsBqQZ8G8n0qJ03d13+eoNoc7sAUEQGA5D/CCxk= -20250917040616.sql h1:zoCnmcXuM7AVv85SmN7RmFglCgJnoDmpRWExH0LAc9Q= -20250917040751.sql h1:J1xyRrh32y1+lezwAyNwPcUQ6ABBSgbvzNLva4SVdQU= -20250917045138.sql h1:jKe1Z0uOLG4SGBYM+S/3P+/zMPztmgoderD5swnMuCg= -20250917093645.sql h1:cNI3Pbz1R3LxvIXLuexafJFCXUXrmuFCgXXJ2sG+FW0= -20250918073552.sql h1:RJ1SvMzP6aeWnoPVD3eVAmIQOkcp6Php8z3QRri6v4g= -20250918073742.sql h1:+cEsnJTJFybe2fR69ZoOiX2R6c6iITl4m6WTZ1hjyzY= -20250918074745.sql h1:2hNVQCXF/dVYXAh+T/7oBFgERGWxzVb2FXJjwkFWGCI= -20250923025134.sql h1:Ykz/qpHiGDXPsCsWTjydQFVSibZP2D+h2fIeb2h2JGA= -20250924051317.sql h1:yQuW6SwJxIOM5fcxeAaie5lSm1oLysU/C2hH2xNCVoQ= -20250929034321.sql h1:101FJ8VH12mrZWlt/X1gvKUGOhoiF8tFbjiapAjnHzg= -20250929034428.sql h1:i+pROD9p+g5dOmmZma6WF/0Hw5g3Ha28NN85iTo1K34= -20250930025550.sql h1:+F+CsCUXD/ql0tHGEow70GhPBX1ZybVn+bh/T4YMh7Y= -20250930140351.sql h1:9AAEG1AnOAH+o0+oHL5G7I8vqlWOhwRlCGyyCpT/y1Q= -20251002085604.sql h1:3xZ68eYp4urXRnvotNH1XvG2mYOSDV/j3zHEZ/txg5E= -20251003032030.sql h1:HB+mQ2lXMNomHDpaRhB/9IwYI9/YiDO5eOJ+nAQH/jw= -20251005060450.sql h1:LbtCE2b+8osM3CvnmQJH1uCPtn+d7WchsslBOz8bL3Q= -20251006041122.sql h1:MlS7f21z06sutnf9dIekt5fuHJr4lgcQ4uCuCXAGsfc= -20251006045658.sql h1:3FmGCPCzjgMPdWDRodZTsx3KVaodd9zB9ilib69aewk= -20251006045928.sql h1:Z5g31PmnzNwk/OKdODcxZGm8fjJQdMFK32Xfnt3bRHg= -20251007022859.sql h1:FO03zEfaNEk/aXwY81d5Lp3MoBB9kPQuXlXJ4BPiSR8= -20251008031337.sql h1:l+sxUAGvcTfj3I6kAFHo+T6AYodC9k9GkR+jaKO2xXc= -20251008031554.sql h1:AqrVfIhSzY3PCy8ZlP5W91wn2iznfIuj5qQfubp6/94= -20251008052346.sql h1:nxnXmooIJ6r1mmzwnw+6efxLfc/k9h2aE6RMptPRons= -20251008073620.sql h1:6YsJp1W4SmQJ1lxpqF27BBlDC1zqhw7Yhc7pLzQTY6M= -20251009042854.sql h1:nkBV+R6j0fg7/JY6wH3eb5Vv0asJLnXmb6lINfT/GLQ= -20251009052657.sql h1:EPvdsib5rzCGPryd10HShGKvFPwM/R5S2lIVwtYxpms= -20251010031743.sql h1:T8IZmx8/btRFKLzTe78MzcBsPJNodnLvB0tby9QkirQ= -20251010070721.sql h1:5NQUk/yOV6sABLCB7swx++YIOyJe6MnU+yt1nRzde5w= -20251010072711.sql h1:ZJNqR2piyu8xJhBvVABSlnGEoKSKae3wuEs+wshPe4k= -20251013044536.sql h1:0Xjw8fNILiT8nnfrJDZgQnPf3dntmIoilbapnih8AE4= -20251013051438.sql h1:lfSuw5mgJnePBJamvhZ81osFIouXeiIEiSZ/evdwo48= -20251013081808.sql h1:ijgjNX08G6GBjA/ks8EKtb7P7Y7Cg7zbhqEOruGnv6M= -20251014060047.sql h1:0jqj49WTtneEIMQDBoo4c095ZGi8sCrA8NnHBrPU6D8= -20251014063537.sql h1:VZLXol0PTsTW21Epg6vBPsztWkDtcxup9F/z88EGgIg= -20251014063720.sql h1:2HVUyCV0ud3BJJDH2GEKZN/+IWLFPCsN1KqhP6csO14= -20251015045455.sql h1:MeLWmMhAOAz8b15Dd7IAQnt6JxjSml02XCXK22C0Lpg= -20251016010845.sql h1:4BncQdDOasRZJkzVJrSJJA7091A9VPNVx/faUCUPhBM= -20251016011023.sql h1:9JB9eFZKURK5RoCVDKR6glSvdJ8NTXrN7K/4q51zkz4= -20251016062912.sql h1:ACNn0fe+EMqUt3hoY+Dr3uqAV/QICBa1+mIW7fUc9Fk= -20251017060617.sql h1:4T3t9ifWrEQTPMSM0XJ98pF7Qdt+UfgtMui17bhrnWI= -20251017082207.sql h1:8vLG1l/saRRMHXkyA4nelJyjaSddhZd6r7R+Uo4JS/c= -20251018032635.sql h1:2xey5gnO3y2XSOrU8MLlIfoylPKbRGDRtHDD07B3MbQ= -20251018040322.sql h1:k/pdNiSoT8zFPqNQ/avOD0vYkNh3BTD64IlHrfVXr7I= -20251019093915.sql h1:hFcQE0y+p5dZiVwePGsRGto9m/q6kJNiUZbVDd5Rnjk= -20251020062553.sql h1:Iw7hulcm5iRQlfW+ygA4iTPxLqkxx6h9vXMXEwUAHKs= -20251021041042.sql h1:wMgSivBV2A0NDcsLmKGIp0kMcVh2IODSG9b4dgzCaOM= -20251021075552.sql h1:8gfSMAglflNO6L0sSzxFNEubYN8/O4thT7OQT+WH+3M= -20251023044432.sql h1:MkvajJs3bfk9+wHvQ43/ccAluJEBARm1gWr1u92ccLA= -20251024034832.sql h1:x3s3VEVYLOSKLAFxJGb2+c1FyTMMvPE+9k4Ew7rKQaI= -20251024074315.sql h1:EjAjelgi5qAfcRq/8vPTlGGYHvAKxNTllm8f0SzZDns= -20251025013451.sql h1:6hnuIiwYiG+6nLhOY/+Yyn+I6ZCFNRZxrJNqBV6HLqE= -20251025013609.sql h1:evPJaTD8WxYRMOJZHkSr7ONLx9PYxT+ankzQt9c/sJ0= -20251027075128.sql h1:/iFQBM1sytjqpyQSOx61q33gnorMgxTiFVSuL6bQqsM= -20251027091406.sql h1:4nzeZ5/kDtgMpWOH39XjnZsdfowaDN+jI7NWdP4Sqbw= +h1:Yqb9JSUhzEc3RNP4eGOax6//4rndgFOUT0Q5zHfojxU= +20250904105930.sql h1:Vv4vCurl7m7/ZB6TjRpkubHpQ4RYwSUn0QHdzfoGpzY= +20250904141448.sql h1:FYCHH9Os4KkrZMDu/jR8FMP+wLMRW+Mb0PkLU/9BRDg= +20250908062237.sql h1:oanBpKZd+akPu2I/xYhUSbd0G5tAFbXzKLER/Zs8ENI= +20250908062323.sql h1:miNG9COddXkD1jGTgaROMAZ618eT6oiLGiJhXWnQwhE= +20250908073811.sql h1:gOi5cnGG1htlpfizybYmUIT0vYjZTBfXiI0nPSYK2u8= +20250908073839.sql h1:cWNDA4YikjoOteAJuNLFILjQUJPFB6o8Wxreiek4QyI= +20250910055902.sql h1:nxxOGnU0BbH/v3IPgeIOXOwH8d3tKomw7h6FTeMnnBs= +20250915123412.sql h1:mz7SiWfrdf0qE1VTSAAnA/147d6gyp6ry5vZ2bR9SH0= +20250916043819.sql h1:RHXVtmMkB6wfv06HfPyHMBmUfIpFt1xveafNz0kwKnE= +20250917040616.sql h1:MYVDht+akBlzQGKNu2hTTTLPEcH1bxT/Q8MK6WEtuhs= +20250917040751.sql h1:J79YyS2JzWgh5oKXMTgh67uo3gLxKaAsxRiZmSIfjBs= +20250917045138.sql h1:/SM1N4O8X3yxpoJgMEARmS1uOkuLKsTOy4PLsRCOKaQ= +20250917093645.sql h1:PNBTGZ7s10e5b5+Tie8YfVQBN0zKtJ5T34oK1iOUEb4= +20250918073552.sql h1:jG7+g3i8ODYaJdcdZz12v3nbsZ5mB9wG6kWnGyTQIRI= +20250918073742.sql h1:j+rgw7puxE7s+phqPVZHmPk0af3rcaA56Itp86y1suY= +20250918074745.sql h1:rPmP4DXs6OnY4Vp+xO/z9jFpJt/RrJ52SJJjIIxeDvc= +20250923025134.sql h1:2r6pcwnBSU5Y9Czk1OHBoh4yZXiMtEca9X8843fTEX0= +20250924051317.sql h1:iUAk2gsGoEGIPQ0lEEUp8maMSId8emNbP+kP712ABIA= +20250929034321.sql h1:UlpALNVmdi95zOIT0yc6ZyTj9bBjQEIpZhvgrc52M+k= +20250929034428.sql h1:feF+H4nDyHh5bdx48Oiz0A1qecZfi6v3qTTdjzJ45Dg= +20250930025550.sql h1:6XT1kXI3Z3ZIxxmvT7poufZWWCW0QiejZPaFV5wBnjI= +20250930140351.sql h1:HxnmAbh9gCy8jwl/9ycGktiByaUripsjFFvohofY2CY= +20251002085604.sql h1:SjLPi+ZN6qDccK3DaEQCgNsZpPwr5kynWXwbwEsziCI= +20251003032030.sql h1:oHfxNSuqTxU8Zaf9H+h8TuUb1Da03wcyc6hZjDrUQ2s= +20251005060450.sql h1:GIuCcrd4MwjmXpvbzDzPYL18BV3QaZZ+Y2FmEzjvi0E= +20251006041122.sql h1:uNDQbSw0M08lYoMvUNlQtS3iDzpPM1ixT13ugSAoWjE= +20251006045658.sql h1:z+t7yCK54Q4SSiF9kUyUhkYB2F+kzSW9TB7ogxd9wzw= +20251006045928.sql h1:1lATLFLp4BWwGZqAjZdP0Dc6ypNXiYcwjoNkqGa8NFE= +20251007022859.sql h1:HXXwWrkyvzJzJGAt9mGskCRBBV/c1JfPmfjDocmJhQ4= +20251008031337.sql h1:Ln5pCF3Hxa5foHZLcds+z/us2eH6VAhhEj3w0TAGlVs= +20251008031554.sql h1:aB4MUS2lmqG0//4HKUWorcPSpWya0VC4QItvGyskEVI= +20251008052346.sql h1:MI3AZgU5XcwZT2OvvlWAxdRtL0eJ3jjRwt56IY1+pRU= +20251008073620.sql h1:sztWXuSNYwpEraaSapSsYwno75LO5H/N7ob7OJQ8X/A= +20251009042854.sql h1:TnPXj+dCJls3IU//cuqJZymyBzZMKs7ayazfgtAFRxM= +20251009052657.sql h1:leXbs0CP8r5dRilmYyLRk1MICqak3ea1/LWMtFrijqQ= +20251010031743.sql h1:SgHNY/lQ88G2F4nZyMfiOkDntb+gtOR+nEQLqXBTwv4= +20251010070721.sql h1:AnJnhXsMzDvK4AFgYw6B16Kpo/hljrZtcpc9m2VOSHQ= +20251010072711.sql h1:aXPTtNwLcTuw8C/yAxwxvqs0ayEjNzI1uuE0vE3ERa8= +20251013044536.sql h1:7Pq6JcvTpPBYDCW2dz3HdgUwY65HlhEVWy9TiG8iONE= +20251013051438.sql h1:X6t8bkqpUYYokBunSufMQUe5vCg0VyO6dxbm7ngosUc= +20251013081808.sql h1:495pLguXL2Ozh+ycn4UYZgZbn6WbjXNbyZUc3JU8qhI= +20251014060047.sql h1:nCgImMRGHhziiW57O1ofWaXCAPGaCOHN7PldQ3OSmM4= +20251014063537.sql h1:2cLmID79jP6cuQ1YJaWTtghFiM1GtHMC0ZQl30Hpy1M= +20251014063720.sql h1:bzLKKVAjSHgDFoiI/glj7t1ETlSAKx+AlsIAaP0ru2g= +20251015045455.sql h1:S547+UugQhlTRcn1Lm1IfqT5RNPttIWIiD+RTx69YaE= +20251016010845.sql h1:c9DUvxl17pUkf0azdYGM/YDzYxIJkLcfZOcMI4rL+R0= +20251016011023.sql h1:u3ivg83bXgYHBbojbWpemLxPE9Dmmj53B6LXo664jxw= +20251016062912.sql h1:W9n1hWchfYkqNX9LO9uxFxEXAb/iY+Pexjnhmp6PbgI= +20251017060617.sql h1:VU6yZ2+LfHpDZ3+TIH40t3F5YXPCpTppuF9+uSqa4b8= +20251017082207.sql h1:QshZslfedckz7iDpSGmPyY9sP6dy6ckHbs8L1TuXIA4= +20251018032635.sql h1:M1U/9W/F9wlW5YDmVAmHFfUJU7FWFaX0DblpfZcYWrE= +20251018040322.sql h1:Zk/vw0e6AzWFO2ElLOzB+OrSz6k+h1Ynxp0TImAzxwY= +20251019093915.sql h1:3Q0kPiZwJnHn5rAvdh0w1LBdiA7W2xBmZWncoPXb044= +20251020062553.sql h1:mJwC/J8GzPAIXckNMvy1f/Nguk2VVf8roD/Raclhbao= +20251021041042.sql h1:d1BAOGAQhqr+oOwcpAVozUsTh457VSDEk2qQFavGG58= +20251021075552.sql h1:TNChGQ1Zlr/1iQ6qvK4iDTAJpe6L/z/M6e/O0SkQVaM= +20251023044432.sql h1:GA2AdJk2ULyjr6igtu9C/CEi4YUIks8r9jXGGaCvPsk= +20251024034832.sql h1:RXmbEhMkOLK5g1QL6up8iRPcwYfo89oLP26ZHvrUK9o= +20251024074315.sql h1:3GnPQSbuAAfMa8oWDyBjhXqn1j1zunY/w0ydX0IGPrA= +20251025013451.sql h1:5eNrA9LDxA4i5CCP7wSyOgFZ6t6jBWVil+oGzJpkJ2E= +20251025013609.sql h1:+N6EHc1kv3hqf16CUhXe+UITPmoxOPfi4MECLmJXNrc= +20251027075128.sql h1:PQflgsjce/p2ClbybLtdehdPNDcMZ9Lb1vd98xd0K8E= +20251027091406.sql h1:bYXV57GvodCMjg0/ox+XKGIAGhrDlVuJ1wO4foNEKtQ= From 88e7f99e6d6e3e1a27e65665d32ee0de6aa67bee Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 27 Oct 2025 17:10:00 +0700 Subject: [PATCH 021/329] improve check-in --- .../domain/main-entities/encounter/dto.go | 2 + .../use-case/main-use-case/encounter/case.go | 113 +++++++++++++----- .../main-use-case/encounter/helper.go | 5 + .../use-case/main-use-case/encounter/lib.go | 30 +++-- 4 files changed, 113 insertions(+), 37 deletions(-) diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index b552ba86..89f12caf 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -46,6 +46,8 @@ type CreateDto struct { Responsible_Doctor_Id *uint `json:"responsible_doctor_id"` RefSource_Name *string `json:"refSource_name" validate:"maxLength=100"` Appointment_Id *uint `json:"appointment_id"` + RefTypeCode ere.RefTypeCode `json:"refTypeCode"` + NewStatus bool `json:"newStatus"` pa.AuthInfo } diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 6786eb51..c55b5b4b 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -2,12 +2,21 @@ package encounter import ( "errors" - eaeh "simrs-vx/internal/domain/main-entities/adm-employee-hist" - erdh "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" - uaeh "simrs-vx/internal/use-case/main-use-case/adm-employee-hist" - urdh "simrs-vx/internal/use-case/main-use-case/responsible-doctor-hist" + authhelper "simrs-vx/internal/lib/auth" "strconv" + "time" + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + "gorm.io/gorm" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + erc "simrs-vx/internal/domain/references/common" + ere "simrs-vx/internal/domain/references/encounter" + + eaeh "simrs-vx/internal/domain/main-entities/adm-employee-hist" ea "simrs-vx/internal/domain/main-entities/ambulatory" ec "simrs-vx/internal/domain/main-entities/chemo" edc "simrs-vx/internal/domain/main-entities/death-cause" @@ -16,8 +25,10 @@ import ( eem "simrs-vx/internal/domain/main-entities/employee" e "simrs-vx/internal/domain/main-entities/encounter" ei "simrs-vx/internal/domain/main-entities/inpatient" - erc "simrs-vx/internal/domain/references/common" - ere "simrs-vx/internal/domain/references/encounter" + erdh "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" + es "simrs-vx/internal/domain/main-entities/soapi" + + uaeh "simrs-vx/internal/use-case/main-use-case/adm-employee-hist" ua "simrs-vx/internal/use-case/main-use-case/ambulatory" uc "simrs-vx/internal/use-case/main-use-case/chemo" udc "simrs-vx/internal/use-case/main-use-case/death-cause" @@ -25,18 +36,14 @@ import ( ue "simrs-vx/internal/use-case/main-use-case/emergency" uem "simrs-vx/internal/use-case/main-use-case/employee" ui "simrs-vx/internal/use-case/main-use-case/inpatient" - - pl "simrs-vx/pkg/logger" - pu "simrs-vx/pkg/use-case-helper" - - dg "github.com/karincake/apem/db-gorm-pg" - d "github.com/karincake/dodol" - - "gorm.io/gorm" + urdh "simrs-vx/internal/use-case/main-use-case/responsible-doctor-hist" + us "simrs-vx/internal/use-case/main-use-case/soapi" ) const source = "encounter" +var now = time.Now() + func Create(input e.CreateDto) (*d.Data, error) { data := e.Encounter{} @@ -48,7 +55,21 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - err := dg.I.Transaction(func(tx *gorm.DB) error { + // check if patient is new in the hospital + dataPatient, err := ReadList(e.ReadListDto{ + FilterDto: e.FilterDto{Patient_Id: input.Patient_Id}, + AuthInfo: authhelper.AuthInfo{User_Id: input.User_Id}}) + if err != nil { + return nil, err + } + + if list, ok := dataPatient.Data.([]e.ResponseDto); ok { + if len(list) < 1 { + input.NewStatus = true + } + } + + err = dg.I.Transaction(func(tx *gorm.DB) error { mwRunner := newMiddlewareRunner(&event, tx) mwRunner.setMwType(pu.MWTPre) // Run pre-middleware @@ -126,6 +147,15 @@ func Create(input e.CreateDto) (*d.Data, error) { return errors.New("invalid encounter class code") } + // insert adm_employee_hist + if _, err := uaeh.Create(eaeh.CreateDto{ + Encounter_Id: &data.Main.Id, + Employee_Id: data.Adm_Employee_Id, + StartedAt: &now, + }); err != nil { + return err + } + mwRunner.setMwType(pu.MWTPost) // Run post-middleware if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { @@ -418,6 +448,16 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) { } } + // update finishedAt in latest responsible_doctor_hist + if err = updateLatestResponsibleDoctorHist(e.CheckinDto{Id: input.Id, StartedAt: &now}, &event, tx); err != nil { + return err + } + + // update finishedAt in latest adm_employee_hist + if err = updateLatestAdmEmployeeHist(e.CheckinDto{Id: input.Id, StartedAt: &now}, &event, tx); err != nil { + return err + } + switch *input.Discharge_Method_Code { case ere.DMCDeath: // insert data death-cause @@ -534,6 +574,22 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { return nil, err } + dataSoapi, err := us.ReadList(es.ReadListDto{FilterDto: es.FilterDto{Encounter_Id: &input.Id}}) + if err != nil { + return nil, err + } + if list, ok := dataSoapi.Data.([]es.ResponseDto); ok { + if len(list) > 0 { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-state-mismatch", + Detail: "soapi already exist", + Raw: errors.New("soapi already exist"), + } + return nil, pl.SetLogError(&event, input) + } + } + err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") if data, err = ReadDetailData(rdDto, &event, tx); err != nil { @@ -551,20 +607,23 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { } // Insert responsible_doctor_hist if responsible_doctor_id has changed && update latest history - if input.Responsible_Doctor_Id != nil && *input.Responsible_Doctor_Id != *data.Responsible_Doctor_Id { - // update finishedAt in latest responsible_doctor_hist - if err = updateLatestResponsibleDoctorHist(input, &event, tx); err != nil { - return err + if input.Responsible_Doctor_Id != nil { + if data.Responsible_Doctor_Id == nil || *input.Responsible_Doctor_Id != *data.Responsible_Doctor_Id { + // update finishedAt in latest responsible_doctor_hist + if err = updateLatestResponsibleDoctorHist(input, &event, tx); err != nil { + return err + } + + //insert responsible_doctor_hist + if _, err = urdh.Create(erdh.CreateDto{ + Encounter_Id: &input.Id, + Doctor_Id: input.Responsible_Doctor_Id, + StartedAt: input.StartedAt, + }); err != nil { + return err + } } - //insert responsible_doctor_hist - if _, err = urdh.Create(erdh.CreateDto{ - Encounter_Id: &input.Id, - Doctor_Id: input.Responsible_Doctor_Id, - StartedAt: input.StartedAt, - }); err != nil { - return err - } } // Insert adm_employee_hist if adm_employee_id has changed && update latest history diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index 2e74eff6..d2647a38 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -69,6 +69,8 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Encounter) { data.RefSource_Name = inputSrc.RefSource_Name data.Appointment_Id = inputSrc.Appointment_Id data.Status_Code = erc.DSCProcess + data.RefType_Code = &inputSrc.RefTypeCode + data.NewStatus = inputSrc.NewStatus } func setDataUpdate(src e.UpdateDto, dst *e.Encounter) { @@ -90,6 +92,7 @@ func setDataDischarge(src e.DischargeDto, dst *e.Encounter) { now := time.Now() dst.Discharge_Date = &now + dst.FinishedAt = &now } func checkSoapiByDocExists(encounter_id uint, event *pl.Event, tx *gorm.DB) error { @@ -335,6 +338,8 @@ func setDataCheckIn(src e.CheckinDto, dst *e.Encounter) { if src.Adm_Employee_Id != nil { dst.Adm_Employee_Id = src.Adm_Employee_Id } + + dst.StartedAt = src.StartedAt } func createInternalReferences(input e.DischargeDto, event *pl.Event, tx *gorm.DB) error { diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index 6e960e49..3327bcfa 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -3,8 +3,6 @@ package encounter import ( // std "errors" - "fmt" - // external dg "github.com/karincake/apem/db-gorm-pg" gh "github.com/karincake/getuk" @@ -271,21 +269,26 @@ func updateLatestResponsibleDoctorHist(input e.CheckinDto, event *pl.Event, dbx Order("\"CreatedAt\" DESC"). Limit(1) - fmt.Println(subQuery) - - if err := tx. + result := tx. Model(&erdh.ResponsibleDoctorHist{}). Where("\"Id\" = (?)", subQuery). - Update("\"FinishedAt\"", input.StartedAt).Error; err != nil { + Update("\"FinishedAt\"", input.StartedAt) + + if result.Error != nil { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "data-update-fail", Detail: "Database update failed", - Raw: err, + Raw: result.Error, } return pl.SetLogError(event, input) } + if result.RowsAffected == 0 { + pl.SetLogInfo(event, input, "no previous data found to update") + return nil + } + pl.SetLogInfo(event, nil, "complete") return nil } @@ -307,19 +310,26 @@ func updateLatestAdmEmployeeHist(input e.CheckinDto, event *pl.Event, dbx ...*go Order("\"CreatedAt\" DESC"). Limit(1) - if err := tx. + result := tx. Model(&eaeh.AdmEmployeeHist{}). Where("\"Id\" = (?)", subQuery). - Update("\"FinishedAt\"", input.StartedAt).Error; err != nil { + Update("\"FinishedAt\"", input.StartedAt) + + if result.Error != nil { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "data-update-fail", Detail: "Database update failed", - Raw: err, + Raw: result.Error, } return pl.SetLogError(event, input) } + if result.RowsAffected == 0 { + pl.SetLogInfo(event, input, "no previous data found to update") + return nil + } + pl.SetLogInfo(event, nil, "complete") return nil } From 159db551ebd51de6b85bebaf0a3414e8b7515906 Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 27 Oct 2025 17:20:46 +0700 Subject: [PATCH 022/329] set responsible doctor to required --- .../encounter/request-validation.go | 4 +-- .../use-case/main-use-case/encounter/case.go | 27 +++++++++---------- .../main-use-case/encounter/helper.go | 5 +--- 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/internal/interface/main-handler/encounter/request-validation.go b/internal/interface/main-handler/encounter/request-validation.go index 9e92ea88..025298fc 100644 --- a/internal/interface/main-handler/encounter/request-validation.go +++ b/internal/interface/main-handler/encounter/request-validation.go @@ -53,10 +53,10 @@ func validateRequestCheckout(w http.ResponseWriter, i e.DischargeDto) (valid boo } func validateRequestCheckIn(w http.ResponseWriter, i e.CheckinDto) (valid bool) { - if i.Responsible_Doctor_Id == nil && i.Adm_Employee_Id == nil { + if i.Responsible_Doctor_Id == nil { rw.DataResponse(w, nil, d.FieldError{ Code: dataValidationFail, - Message: "responsible_doctor_id or adm_employee_id required", + Message: "responsible_doctor_id required", }) return } diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index c55b5b4b..d1124b3e 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -607,23 +607,20 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { } // Insert responsible_doctor_hist if responsible_doctor_id has changed && update latest history - if input.Responsible_Doctor_Id != nil { - if data.Responsible_Doctor_Id == nil || *input.Responsible_Doctor_Id != *data.Responsible_Doctor_Id { - // update finishedAt in latest responsible_doctor_hist - if err = updateLatestResponsibleDoctorHist(input, &event, tx); err != nil { - return err - } - - //insert responsible_doctor_hist - if _, err = urdh.Create(erdh.CreateDto{ - Encounter_Id: &input.Id, - Doctor_Id: input.Responsible_Doctor_Id, - StartedAt: input.StartedAt, - }); err != nil { - return err - } + if data.Responsible_Doctor_Id == nil || *input.Responsible_Doctor_Id != *data.Responsible_Doctor_Id { + // update finishedAt in latest responsible_doctor_hist + if err = updateLatestResponsibleDoctorHist(input, &event, tx); err != nil { + return err } + //insert responsible_doctor_hist + if _, err = urdh.Create(erdh.CreateDto{ + Encounter_Id: &input.Id, + Doctor_Id: input.Responsible_Doctor_Id, + StartedAt: input.StartedAt, + }); err != nil { + return err + } } // Insert adm_employee_hist if adm_employee_id has changed && update latest history diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index d2647a38..c5eb155e 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -331,14 +331,11 @@ func setDataUpdateStatus(src e.UpdateStatusDto, dst *e.Encounter) { } func setDataCheckIn(src e.CheckinDto, dst *e.Encounter) { - if src.Responsible_Doctor_Id != nil { - dst.Responsible_Doctor_Id = src.Responsible_Doctor_Id - } - if src.Adm_Employee_Id != nil { dst.Adm_Employee_Id = src.Adm_Employee_Id } + dst.Responsible_Doctor_Id = src.Responsible_Doctor_Id dst.StartedAt = src.StartedAt } From 15179c746c4caddec4c64a2da3b434a0132a3922 Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 27 Oct 2025 17:28:50 +0700 Subject: [PATCH 023/329] add comment --- internal/interface/main-handler/encounter/handler.go | 8 -------- internal/use-case/main-use-case/encounter/case.go | 8 ++++++++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/internal/interface/main-handler/encounter/handler.go b/internal/interface/main-handler/encounter/handler.go index a5e74855..ed8b1fbc 100644 --- a/internal/interface/main-handler/encounter/handler.go +++ b/internal/interface/main-handler/encounter/handler.go @@ -2,7 +2,6 @@ package encounter import ( "net/http" - "time" rw "github.com/karincake/risoles" sf "github.com/karincake/semprit" @@ -125,13 +124,6 @@ func (obj myBase) CheckIn(w http.ResponseWriter, r *http.Request) { } dto.Id = uint(id) - - // validate startedAt - if dto.StartedAt == nil { - now := time.Now() - dto.StartedAt = &now - } - res, err := u.CheckIn(dto) rw.DataResponse(w, res, err) } diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index d1124b3e..11b17e2b 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -574,10 +574,17 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { return nil, err } + // set startedAt + if input.StartedAt == nil { + input.StartedAt = &now + } + + // validate if soapi exist dataSoapi, err := us.ReadList(es.ReadListDto{FilterDto: es.FilterDto{Encounter_Id: &input.Id}}) if err != nil { return nil, err } + if list, ok := dataSoapi.Data.([]es.ResponseDto); ok { if len(list) > 0 { event.Status = "failed" @@ -640,6 +647,7 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { } } + // update encounter data if err := updateCheckInData(input, data, &event, tx); err != nil { return err } From 43f9c0f4c85448f0535734351f9f6fc588fb3628 Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 30 Oct 2025 13:57:52 +0700 Subject: [PATCH 024/329] add json tag to unit response Dto --- internal/domain/main-entities/unit/dto.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/domain/main-entities/unit/dto.go b/internal/domain/main-entities/unit/dto.go index ce1dd505..eca0594f 100644 --- a/internal/domain/main-entities/unit/dto.go +++ b/internal/domain/main-entities/unit/dto.go @@ -50,11 +50,11 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain - Installation_Id *uint16 `json:"installation_id"` - Installation *ei.Installation - Code string `json:"code"` - Name string `json:"name"` - UnitPositions []eipb.Basic `json:"unitPositions,omitempty"` + Installation_Id *uint16 `json:"installation_id"` + Installation *ei.Installation `json:"installation"` + Code string `json:"code"` + Name string `json:"name"` + UnitPositions []eipb.Basic `json:"unitPositions,omitempty"` } func (d Unit) ToResponse() ResponseDto { From 2ce8ecb1b9add66e8e96e1c8e4250050daa1fc97 Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 30 Oct 2025 13:59:28 +0700 Subject: [PATCH 025/329] add json tag to unit response Dto --- internal/domain/main-entities/unit/dto.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/domain/main-entities/unit/dto.go b/internal/domain/main-entities/unit/dto.go index eca0594f..e47afed9 100644 --- a/internal/domain/main-entities/unit/dto.go +++ b/internal/domain/main-entities/unit/dto.go @@ -51,7 +51,7 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain Installation_Id *uint16 `json:"installation_id"` - Installation *ei.Installation `json:"installation"` + Installation *ei.Installation `json:"installation,omitempty"` Code string `json:"code"` Name string `json:"name"` UnitPositions []eipb.Basic `json:"unitPositions,omitempty"` From 1b7c29dc116ea20b33c1df1966d5c6a26c72115d Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 30 Oct 2025 15:32:36 +0700 Subject: [PATCH 026/329] feat (patient): now also create vclaim member + hit bpjs service --- cmd/main-api/config.yml-example | 5 +- internal/domain/main-entities/patient/dto.go | 2 +- .../interface/main-handler/main-handler.go | 2 + internal/lib/auth/auth.go | 2 +- internal/lib/auth/tycovar.go | 2 +- .../bpjs-use-case/vclaim-member/case.go | 9 ++- .../bpjs-use-case/vclaim-member/lib.go | 32 +++++++++ .../use-case/main-use-case/patient/case.go | 8 +++ .../use-case/main-use-case/patient/helper.go | 11 +++ .../main-use-case/patient/middleware.go | 68 +++++++++++++++++-- .../use-case/main-use-case/patient/tycovar.go | 13 ++++ pkg/use-case-helper/use-case-helper.go | 2 +- 12 files changed, 144 insertions(+), 12 deletions(-) diff --git a/cmd/main-api/config.yml-example b/cmd/main-api/config.yml-example index f131a725..60b1644c 100644 --- a/cmd/main-api/config.yml-example +++ b/cmd/main-api/config.yml-example @@ -63,4 +63,7 @@ bpjsCfg: corsCfg: allowedOrigins: - http://example.com - allowedMethod: \ No newline at end of file + allowedMethod: + +bpjsCfg: + baseUrl: \ No newline at end of file diff --git a/internal/domain/main-entities/patient/dto.go b/internal/domain/main-entities/patient/dto.go index abe3b46b..1190ce22 100644 --- a/internal/domain/main-entities/patient/dto.go +++ b/internal/domain/main-entities/patient/dto.go @@ -14,7 +14,7 @@ import ( erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" - pa "simrs-vx/pkg/auth-helper" + pa "simrs-vx/internal/lib/auth" ) type CreateDto struct { diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index b2c78cb5..bedf3b71 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -50,6 +50,7 @@ import ( hk "github.com/karincake/hongkue" /******************** infra ********************/ + ibpjs "simrs-vx/internal/infra/bpjs" gs "simrs-vx/internal/infra/gorm-setting" minio "simrs-vx/internal/infra/minio" ssdb "simrs-vx/internal/infra/ss-db" @@ -118,6 +119,7 @@ func SetRoutes() http.Handler { a.RegisterExtCall(lh.Populate) a.RegisterExtCall(minio.Connect) a.RegisterExtCall(mh.I.SetClient) + a.RegisterExtCall(ibpjs.SetConfig) a.RegisterExtCall(validation.RegisterValidation) r := http.NewServeMux() diff --git a/internal/lib/auth/auth.go b/internal/lib/auth/auth.go index 934d8d61..3efa980f 100644 --- a/internal/lib/auth/auth.go +++ b/internal/lib/auth/auth.go @@ -1,4 +1,4 @@ -package authhelper +package auth import ( "errors" diff --git a/internal/lib/auth/tycovar.go b/internal/lib/auth/tycovar.go index 654115fc..881a9072 100644 --- a/internal/lib/auth/tycovar.go +++ b/internal/lib/auth/tycovar.go @@ -1,4 +1,4 @@ -package authhelper +package auth import ( ero "simrs-vx/internal/domain/references/organization" diff --git a/internal/use-case/bpjs-use-case/vclaim-member/case.go b/internal/use-case/bpjs-use-case/vclaim-member/case.go index 7c572f5e..14c6aaff 100644 --- a/internal/use-case/bpjs-use-case/vclaim-member/case.go +++ b/internal/use-case/bpjs-use-case/vclaim-member/case.go @@ -303,10 +303,17 @@ func Delete(input e.DeleteDto) (*d.Data, error) { // return err // } -// if err := CreateOrUpdateData(input, data, &event, tx); err != nil { +// if data.Person_Id == input.Person_Id { +// return nil +// } +// if err := UpdateData(e.UpdateDto{CreateDto: input}, data, &event, tx); err != nil { // return err // } +// // if err := CreateOrUpdateData(input, data, &event, tx); err != nil { +// // return err +// // } + // pl.SetLogInfo(&event, nil, "complete") // mwRunner.setMwType(pu.MWTPost) diff --git a/internal/use-case/bpjs-use-case/vclaim-member/lib.go b/internal/use-case/bpjs-use-case/vclaim-member/lib.go index 9044664d..3c477298 100644 --- a/internal/use-case/bpjs-use-case/vclaim-member/lib.go +++ b/internal/use-case/bpjs-use-case/vclaim-member/lib.go @@ -145,3 +145,35 @@ func DeleteData(data *e.VclaimMember, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, nil, "complete") return nil } + +func CreateOrUpdateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, nil, "started", "createOrUpdateData") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + data, err := ReadDetailData(e.ReadDetailDto{CardNumber: input.CardNumber}, event, tx) + if err != nil { + if !pu.IsDataNotFoundError(err) { + return err + } + } + + if data == nil { + if _, err := CreateData(input, event, tx); err != nil { + return err + } + } else { + if err := UpdateData(e.UpdateDto{CreateDto: input}, data, event, tx); err != nil { + return err + } + } + + pl.SetLogInfo(event, nil, "complete") + return nil + +} diff --git a/internal/use-case/main-use-case/patient/case.go b/internal/use-case/main-use-case/patient/case.go index b52215ac..cee92a77 100644 --- a/internal/use-case/main-use-case/patient/case.go +++ b/internal/use-case/main-use-case/patient/case.go @@ -4,8 +4,10 @@ import ( "errors" "strconv" + evm "simrs-vx/internal/domain/bpjs-entities/vclaim-member" e "simrs-vx/internal/domain/main-entities/patient" + uvm "simrs-vx/internal/use-case/bpjs-use-case/vclaim-member" upe "simrs-vx/internal/use-case/main-use-case/person" upa "simrs-vx/internal/use-case/main-use-case/person-address" upc "simrs-vx/internal/use-case/main-use-case/person-contact" @@ -49,6 +51,12 @@ func Create(input e.CreateDto) (*d.Data, error) { input.Person_Id = person_id } + if input.Person.VclaimMember_CardNumber != nil && input.Person.ResidentIdentityNumber != nil { + if err := uvm.CreateOrUpdateData(evm.CreateDto{CardNumber: input.Person.VclaimMember_CardNumber, Person_Id: input.Person_Id}, &event, tx); err != nil { + return err + } + } + for idx := range input.PersonAddresses { input.PersonAddresses[idx].Person_Id = *input.Person_Id } diff --git a/internal/use-case/main-use-case/patient/helper.go b/internal/use-case/main-use-case/patient/helper.go index 8abfeaf3..aac8d677 100644 --- a/internal/use-case/main-use-case/patient/helper.go +++ b/internal/use-case/main-use-case/patient/helper.go @@ -12,6 +12,7 @@ import ( "time" e "simrs-vx/internal/domain/main-entities/patient" + ibpjs "simrs-vx/internal/infra/bpjs" pl "simrs-vx/pkg/logger" pmh "simrs-vx/pkg/minio-helper" @@ -135,3 +136,13 @@ func removeUploadedFile(bucket, fileUrl string, event *pl.Event) error { pl.SetLogInfo(event, nil, "complete") return nil } + +func endpointMapper(noBpjs string) string { + today := getTodayDate() + return fmt.Sprintf("%speserta/nokartu?noKartu=%s&tglpelayanan=%s", ibpjs.O.BaseUrl, noBpjs, today) + +} + +func getTodayDate() string { + return time.Now().Format("2006-01-02") +} diff --git a/internal/use-case/main-use-case/patient/middleware.go b/internal/use-case/main-use-case/patient/middleware.go index 5fe75e0a..6b0175dc 100644 --- a/internal/use-case/main-use-case/patient/middleware.go +++ b/internal/use-case/main-use-case/patient/middleware.go @@ -1,9 +1,65 @@ package patient +import ( + "encoding/json" + "fmt" + "io" + "net/http" + + e "simrs-vx/internal/domain/main-entities/patient" + + "gorm.io/gorm" +) + // example of middleware -// func init() { -// createPreMw = append(createPreMw, -// CreateMw{Name: "modif-input", Func: pm.ModifInput}, -// CreateMw{Name: "check-data", Func: pm.CheckData}, -// ) -// } +func init() { + createPreMw = append(createPreMw, + createMw{Name: "check-vclaim-member", Func: checkVclaimMember}, + ) +} + +func checkVclaimMember(input *e.CreateDto, data *e.Patient, tx *gorm.DB) error { + if input.Person.VclaimMember_CardNumber != nil && input.Person.ResidentIdentityNumber != nil { + return isVclaimMemberMatch(input) + } + return nil +} + +func isVclaimMemberMatch(input *e.CreateDto) error { + endpoint := endpointMapper(*input.Person.VclaimMember_CardNumber) + req, err := http.NewRequest("GET", endpoint, nil) + 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() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + var data BPJSResponse + + if err := json.Unmarshal(body, &data); err != nil { + return fmt.Errorf("failed to parse response JSON: %w", err) + } + + if data.MetaData.Code != "200" { + return fmt.Errorf("failed to get vclaim member: %s", data.MetaData.Message) + } + + if data.Response.Peserta.NoKartu == "" || data.Response.Peserta.NIK == "" { + return fmt.Errorf("failed to get vclaim member: noKartu or nik is empty") + } + + if data.Response.Peserta.NIK != *input.Person.ResidentIdentityNumber { + return fmt.Errorf("nik(residentIdentityNumber) is not match with bpjs number(vclaimMember_cardNumber)") + } + return nil +} diff --git a/internal/use-case/main-use-case/patient/tycovar.go b/internal/use-case/main-use-case/patient/tycovar.go index d7e9abfe..29e5c368 100644 --- a/internal/use-case/main-use-case/patient/tycovar.go +++ b/internal/use-case/main-use-case/patient/tycovar.go @@ -42,3 +42,16 @@ var updatePreMw []readDetailMw var updatePostMw []readDetailMw var deletePreMw []readDetailMw var deletePostMw []readDetailMw + +type BPJSResponse struct { + MetaData struct { + Code string `json:"code"` + Message string `json:"message"` + } `json:"metaData"` + Response *struct { + Peserta struct { + NoKartu string `json:"noKartu"` + NIK string `json:"nik"` + } `json:"peserta"` + } `json:"response"` +} diff --git a/pkg/use-case-helper/use-case-helper.go b/pkg/use-case-helper/use-case-helper.go index 8c41266f..0df8fe3e 100644 --- a/pkg/use-case-helper/use-case-helper.go +++ b/pkg/use-case-helper/use-case-helper.go @@ -97,7 +97,7 @@ func HandleMiddlewareError(event *pl.Event, mwType, mwName string, logData inter event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: GetMiddlewareErrorCode(MWType(mwType)), - Detail: fmt.Sprintf("%s middleware %s failed", mwType, mwName), + Detail: fmt.Sprintf("%s middleware %s failed: %s", mwType, mwName, err.Error()), Raw: err, } return pl.SetLogError(event, logData) From 60f8db982d38670a86a2902d283c88bd8d3c9dd7 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 31 Oct 2025 11:27:44 +0700 Subject: [PATCH 027/329] add response unit in specialist --- internal/domain/main-entities/specialist/dto.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/domain/main-entities/specialist/dto.go b/internal/domain/main-entities/specialist/dto.go index 2cd4acee..8724b9c5 100644 --- a/internal/domain/main-entities/specialist/dto.go +++ b/internal/domain/main-entities/specialist/dto.go @@ -4,6 +4,7 @@ import ( ecore "simrs-vx/internal/domain/base-entities/core" espb "simrs-vx/internal/domain/main-entities/specialist-position/base" essb "simrs-vx/internal/domain/main-entities/subspecialist/base" + eu "simrs-vx/internal/domain/main-entities/unit" ) type CreateDto struct { @@ -52,6 +53,7 @@ type ResponseDto struct { Code string `json:"code"` Name string `json:"name"` Unit_Id *uint16 `json:"unit_id"` + Unit *eu.Unit `json:"unit,omitempty"` SpecialistPositions []espb.Basic `json:"specialistPositions,omitempty"` Subspecialists []essb.Basic `json:"subspecialists,omitempty"` } @@ -60,6 +62,7 @@ func (d Specialist) ToResponse() ResponseDto { resp := ResponseDto{ Code: d.Code, Name: d.Name, + Unit: d.Unit, Unit_Id: d.Unit_Id, SpecialistPositions: d.SpecialistPositions, Subspecialists: d.Subspecialists, From fd2fcec2d63e636d360d780c72959bfd91cffcaa Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 31 Oct 2025 15:14:16 +0700 Subject: [PATCH 028/329] add response in subspecialis --- internal/domain/main-entities/subspecialist/dto.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/internal/domain/main-entities/subspecialist/dto.go b/internal/domain/main-entities/subspecialist/dto.go index ed0c97aa..9a93394d 100644 --- a/internal/domain/main-entities/subspecialist/dto.go +++ b/internal/domain/main-entities/subspecialist/dto.go @@ -2,6 +2,7 @@ package subspecialist import ( ecore "simrs-vx/internal/domain/base-entities/core" + es "simrs-vx/internal/domain/main-entities/specialist" espb "simrs-vx/internal/domain/main-entities/subspecialist-position/base" ) @@ -48,10 +49,11 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain - Code string `json:"code"` - Name string `json:"name"` - Specialist_Id *uint16 `json:"specialist_id"` - Subspecialist []espb.Basic `json:"subspecialistPositions,omitempty"` + Code string `json:"code"` + Name string `json:"name"` + Specialist_Id *uint16 `json:"specialist_id"` + Specialist *es.Specialist `json:"specialist,omitempty"` + Subspecialist []espb.Basic `json:"subspecialistPositions,omitempty"` } func (d Subspecialist) ToResponse() ResponseDto { @@ -59,6 +61,7 @@ func (d Subspecialist) ToResponse() ResponseDto { Code: d.Code, Name: d.Name, Specialist_Id: d.Specialist_Id, + Specialist: d.Specialist, Subspecialist: d.SubspecialistPositions, } resp.SmallMain = d.SmallMain From b27e49954bca7b0ac6cfa3a5b4666557ef12c590 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 31 Oct 2025 15:28:23 +0700 Subject: [PATCH 029/329] update entity --- .../main-entities/ambulatory/base/entity.go | 17 +++++++++++++++++ .../domain/main-entities/ambulatory/entity.go | 10 +++------- .../main-entities/emergency/base/entity.go | 16 ++++++++++++++++ .../domain/main-entities/emergency/entity.go | 10 +++------- .../domain/main-entities/encounter/entity.go | 6 ++++++ .../main-entities/inpatient/base/entity.go | 19 +++++++++++++++++++ .../domain/main-entities/inpatient/entity.go | 13 +++---------- .../domain/main-entities/rehab/base/entity.go | 18 ++++++++++++++++++ internal/domain/main-entities/rehab/entity.go | 11 +++++++++++ .../domain/references/encounter/encounter.go | 4 ++++ 10 files changed, 100 insertions(+), 24 deletions(-) create mode 100644 internal/domain/main-entities/ambulatory/base/entity.go create mode 100644 internal/domain/main-entities/emergency/base/entity.go create mode 100644 internal/domain/main-entities/inpatient/base/entity.go create mode 100644 internal/domain/main-entities/rehab/base/entity.go create mode 100644 internal/domain/main-entities/rehab/entity.go diff --git a/internal/domain/main-entities/ambulatory/base/entity.go b/internal/domain/main-entities/ambulatory/base/entity.go new file mode 100644 index 00000000..2dced5a2 --- /dev/null +++ b/internal/domain/main-entities/ambulatory/base/entity.go @@ -0,0 +1,17 @@ +package base + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ere "simrs-vx/internal/domain/references/encounter" +) + +type Basic struct { + ecore.Main // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Class_Code ere.AmbulatoryClassCode `json:"class_code" gorm:"size:10"` + VisitMode_Code ere.VisitModeCode `json:"visitMode_code"` +} + +func (Basic) TableName() string { + return "Ambulatory" +} diff --git a/internal/domain/main-entities/ambulatory/entity.go b/internal/domain/main-entities/ambulatory/entity.go index 58a9810e..61117c81 100644 --- a/internal/domain/main-entities/ambulatory/entity.go +++ b/internal/domain/main-entities/ambulatory/entity.go @@ -1,15 +1,11 @@ package ambulatory import ( - ecore "simrs-vx/internal/domain/base-entities/core" + ea "simrs-vx/internal/domain/main-entities/ambulatory/base" ee "simrs-vx/internal/domain/main-entities/encounter" - - ere "simrs-vx/internal/domain/references/encounter" ) type Ambulatory struct { - ecore.Main // adjust this according to the needs - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Class_Code ere.AmbulatoryClassCode `json:"class_code" gorm:"size:10"` + ea.Basic + Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` } diff --git a/internal/domain/main-entities/emergency/base/entity.go b/internal/domain/main-entities/emergency/base/entity.go new file mode 100644 index 00000000..3ec85f50 --- /dev/null +++ b/internal/domain/main-entities/emergency/base/entity.go @@ -0,0 +1,16 @@ +package base + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ere "simrs-vx/internal/domain/references/encounter" +) + +type Basic struct { + ecore.Main // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Class_Code ere.EmergencyClassCode `json:"class_code" gorm:"size:10"` +} + +func (Basic) TableName() string { + return "Emergency" +} diff --git a/internal/domain/main-entities/emergency/entity.go b/internal/domain/main-entities/emergency/entity.go index 1e6fb078..475a02ca 100644 --- a/internal/domain/main-entities/emergency/entity.go +++ b/internal/domain/main-entities/emergency/entity.go @@ -1,15 +1,11 @@ package emergency import ( - ecore "simrs-vx/internal/domain/base-entities/core" + eeb "simrs-vx/internal/domain/main-entities/emergency/base" ee "simrs-vx/internal/domain/main-entities/encounter" - - ere "simrs-vx/internal/domain/references/encounter" ) type Emergency struct { - ecore.Main // adjust this according to the needs - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Class_Code ere.EmergencyClassCode `json:"class_code" gorm:"size:10"` + eeb.Basic + Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` } diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index 37779409..423dc3e9 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -3,10 +3,13 @@ package encounter import ( ecore "simrs-vx/internal/domain/base-entities/core" evs "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" + eam "simrs-vx/internal/domain/main-entities/ambulatory/base" ea "simrs-vx/internal/domain/main-entities/appointment" edc "simrs-vx/internal/domain/main-entities/death-cause" ed "simrs-vx/internal/domain/main-entities/doctor" + eem "simrs-vx/internal/domain/main-entities/emergency/base" ee "simrs-vx/internal/domain/main-entities/employee" + eip "simrs-vx/internal/domain/main-entities/inpatient/base" ei "simrs-vx/internal/domain/main-entities/insurance-company" eir "simrs-vx/internal/domain/main-entities/internal-reference" ep "simrs-vx/internal/domain/main-entities/patient" @@ -61,6 +64,9 @@ type Encounter struct { InternalReferences *[]eir.InternalReference `json:"internalReferences,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` DeathCause *edc.DeathCause `json:"deathCause,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` NewStatus bool `json:"newStatus"` + Ambulatory *eam.Basic `json:"ambulatory,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + Emergency *eem.Basic `json:"emergency,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + Inpatient *eip.Basic `json:"inpatient,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` } func (d Encounter) IsDone() bool { diff --git a/internal/domain/main-entities/inpatient/base/entity.go b/internal/domain/main-entities/inpatient/base/entity.go new file mode 100644 index 00000000..1f4a94f4 --- /dev/null +++ b/internal/domain/main-entities/inpatient/base/entity.go @@ -0,0 +1,19 @@ +package base + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ei "simrs-vx/internal/domain/main-entities/infra" + ere "simrs-vx/internal/domain/references/encounter" +) + +type Basic struct { + ecore.Main // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Class_Code ere.InpatientClassCode `json:"class_code" gorm:"size:10"` + Infra_Id *uint16 `json:"infra_id"` + Infra *ei.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Id;references:Id"` +} + +func (Basic) TableName() string { + return "Inpatient" +} diff --git a/internal/domain/main-entities/inpatient/entity.go b/internal/domain/main-entities/inpatient/entity.go index 328f5d12..e88e7fa0 100644 --- a/internal/domain/main-entities/inpatient/entity.go +++ b/internal/domain/main-entities/inpatient/entity.go @@ -1,18 +1,11 @@ package inpatient import ( - ecore "simrs-vx/internal/domain/base-entities/core" ee "simrs-vx/internal/domain/main-entities/encounter" - ei "simrs-vx/internal/domain/main-entities/infra" - - ere "simrs-vx/internal/domain/references/encounter" + eb "simrs-vx/internal/domain/main-entities/inpatient/base" ) type Inpatient struct { - ecore.Main // adjust this according to the needs - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Class_Code ere.InpatientClassCode `json:"class_code" gorm:"size:10"` - Infra_Id *uint16 `json:"infra_id"` - Infra *ei.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Id;references:Id"` + eb.Basic + Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` } diff --git a/internal/domain/main-entities/rehab/base/entity.go b/internal/domain/main-entities/rehab/base/entity.go new file mode 100644 index 00000000..b1713811 --- /dev/null +++ b/internal/domain/main-entities/rehab/base/entity.go @@ -0,0 +1,18 @@ +package base + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ed "simrs-vx/internal/domain/main-entities/doctor" +) + +type Basic struct { + ecore.Main // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Doctor_Id *uint `json:"doctor_id"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` + AllocatedVisitCount *int `json:"allocatedVisitCount"` +} + +func (Basic) TableName() string { + return "Rehab" +} diff --git a/internal/domain/main-entities/rehab/entity.go b/internal/domain/main-entities/rehab/entity.go new file mode 100644 index 00000000..7293ba9f --- /dev/null +++ b/internal/domain/main-entities/rehab/entity.go @@ -0,0 +1,11 @@ +package rehab + +import ( + ee "simrs-vx/internal/domain/main-entities/encounter" + eb "simrs-vx/internal/domain/main-entities/rehab/base" +) + +type Rehab struct { + eb.Basic + Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` +} diff --git a/internal/domain/references/encounter/encounter.go b/internal/domain/references/encounter/encounter.go index eeccb8fe..fb133473 100644 --- a/internal/domain/references/encounter/encounter.go +++ b/internal/domain/references/encounter/encounter.go @@ -18,6 +18,7 @@ type ( RefTypeCode string AllPaymentMethodCode string SEPRefTypeCode string + VisitModeCode string ) const ( @@ -106,6 +107,9 @@ const ( SRTCInternal SEPRefTypeCode = "internal" // Rujukan Internal SRTCExternal SEPRefTypeCode = "external" // Faskes Lain + + VMCAdm VisitModeCode = "adm" + VMCSeries VisitModeCode = "series" ) func (ec EncounterClassCode) Code() string { From cfabd694519b8cdebda8318538753e92c2adc988 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 31 Oct 2025 15:38:27 +0700 Subject: [PATCH 030/329] update entity --- .../migrations/20251031082443.sql | 2 + cmd/main-migration/migrations/atlas.sum | 129 +++++++++--------- .../domain/main-entities/encounter/entity.go | 2 + 3 files changed, 69 insertions(+), 64 deletions(-) create mode 100644 cmd/main-migration/migrations/20251031082443.sql diff --git a/cmd/main-migration/migrations/20251031082443.sql b/cmd/main-migration/migrations/20251031082443.sql new file mode 100644 index 00000000..deec65bb --- /dev/null +++ b/cmd/main-migration/migrations/20251031082443.sql @@ -0,0 +1,2 @@ +-- Modify "Ambulatory" table +ALTER TABLE "public"."Ambulatory" ADD COLUMN "VisitMode_Code" text NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index a808ecf3..ab2219c2 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,64 +1,65 @@ -h1:Yqb9JSUhzEc3RNP4eGOax6//4rndgFOUT0Q5zHfojxU= -20250904105930.sql h1:Vv4vCurl7m7/ZB6TjRpkubHpQ4RYwSUn0QHdzfoGpzY= -20250904141448.sql h1:FYCHH9Os4KkrZMDu/jR8FMP+wLMRW+Mb0PkLU/9BRDg= -20250908062237.sql h1:oanBpKZd+akPu2I/xYhUSbd0G5tAFbXzKLER/Zs8ENI= -20250908062323.sql h1:miNG9COddXkD1jGTgaROMAZ618eT6oiLGiJhXWnQwhE= -20250908073811.sql h1:gOi5cnGG1htlpfizybYmUIT0vYjZTBfXiI0nPSYK2u8= -20250908073839.sql h1:cWNDA4YikjoOteAJuNLFILjQUJPFB6o8Wxreiek4QyI= -20250910055902.sql h1:nxxOGnU0BbH/v3IPgeIOXOwH8d3tKomw7h6FTeMnnBs= -20250915123412.sql h1:mz7SiWfrdf0qE1VTSAAnA/147d6gyp6ry5vZ2bR9SH0= -20250916043819.sql h1:RHXVtmMkB6wfv06HfPyHMBmUfIpFt1xveafNz0kwKnE= -20250917040616.sql h1:MYVDht+akBlzQGKNu2hTTTLPEcH1bxT/Q8MK6WEtuhs= -20250917040751.sql h1:J79YyS2JzWgh5oKXMTgh67uo3gLxKaAsxRiZmSIfjBs= -20250917045138.sql h1:/SM1N4O8X3yxpoJgMEARmS1uOkuLKsTOy4PLsRCOKaQ= -20250917093645.sql h1:PNBTGZ7s10e5b5+Tie8YfVQBN0zKtJ5T34oK1iOUEb4= -20250918073552.sql h1:jG7+g3i8ODYaJdcdZz12v3nbsZ5mB9wG6kWnGyTQIRI= -20250918073742.sql h1:j+rgw7puxE7s+phqPVZHmPk0af3rcaA56Itp86y1suY= -20250918074745.sql h1:rPmP4DXs6OnY4Vp+xO/z9jFpJt/RrJ52SJJjIIxeDvc= -20250923025134.sql h1:2r6pcwnBSU5Y9Czk1OHBoh4yZXiMtEca9X8843fTEX0= -20250924051317.sql h1:iUAk2gsGoEGIPQ0lEEUp8maMSId8emNbP+kP712ABIA= -20250929034321.sql h1:UlpALNVmdi95zOIT0yc6ZyTj9bBjQEIpZhvgrc52M+k= -20250929034428.sql h1:feF+H4nDyHh5bdx48Oiz0A1qecZfi6v3qTTdjzJ45Dg= -20250930025550.sql h1:6XT1kXI3Z3ZIxxmvT7poufZWWCW0QiejZPaFV5wBnjI= -20250930140351.sql h1:HxnmAbh9gCy8jwl/9ycGktiByaUripsjFFvohofY2CY= -20251002085604.sql h1:SjLPi+ZN6qDccK3DaEQCgNsZpPwr5kynWXwbwEsziCI= -20251003032030.sql h1:oHfxNSuqTxU8Zaf9H+h8TuUb1Da03wcyc6hZjDrUQ2s= -20251005060450.sql h1:GIuCcrd4MwjmXpvbzDzPYL18BV3QaZZ+Y2FmEzjvi0E= -20251006041122.sql h1:uNDQbSw0M08lYoMvUNlQtS3iDzpPM1ixT13ugSAoWjE= -20251006045658.sql h1:z+t7yCK54Q4SSiF9kUyUhkYB2F+kzSW9TB7ogxd9wzw= -20251006045928.sql h1:1lATLFLp4BWwGZqAjZdP0Dc6ypNXiYcwjoNkqGa8NFE= -20251007022859.sql h1:HXXwWrkyvzJzJGAt9mGskCRBBV/c1JfPmfjDocmJhQ4= -20251008031337.sql h1:Ln5pCF3Hxa5foHZLcds+z/us2eH6VAhhEj3w0TAGlVs= -20251008031554.sql h1:aB4MUS2lmqG0//4HKUWorcPSpWya0VC4QItvGyskEVI= -20251008052346.sql h1:MI3AZgU5XcwZT2OvvlWAxdRtL0eJ3jjRwt56IY1+pRU= -20251008073620.sql h1:sztWXuSNYwpEraaSapSsYwno75LO5H/N7ob7OJQ8X/A= -20251009042854.sql h1:TnPXj+dCJls3IU//cuqJZymyBzZMKs7ayazfgtAFRxM= -20251009052657.sql h1:leXbs0CP8r5dRilmYyLRk1MICqak3ea1/LWMtFrijqQ= -20251010031743.sql h1:SgHNY/lQ88G2F4nZyMfiOkDntb+gtOR+nEQLqXBTwv4= -20251010070721.sql h1:AnJnhXsMzDvK4AFgYw6B16Kpo/hljrZtcpc9m2VOSHQ= -20251010072711.sql h1:aXPTtNwLcTuw8C/yAxwxvqs0ayEjNzI1uuE0vE3ERa8= -20251013044536.sql h1:7Pq6JcvTpPBYDCW2dz3HdgUwY65HlhEVWy9TiG8iONE= -20251013051438.sql h1:X6t8bkqpUYYokBunSufMQUe5vCg0VyO6dxbm7ngosUc= -20251013081808.sql h1:495pLguXL2Ozh+ycn4UYZgZbn6WbjXNbyZUc3JU8qhI= -20251014060047.sql h1:nCgImMRGHhziiW57O1ofWaXCAPGaCOHN7PldQ3OSmM4= -20251014063537.sql h1:2cLmID79jP6cuQ1YJaWTtghFiM1GtHMC0ZQl30Hpy1M= -20251014063720.sql h1:bzLKKVAjSHgDFoiI/glj7t1ETlSAKx+AlsIAaP0ru2g= -20251015045455.sql h1:S547+UugQhlTRcn1Lm1IfqT5RNPttIWIiD+RTx69YaE= -20251016010845.sql h1:c9DUvxl17pUkf0azdYGM/YDzYxIJkLcfZOcMI4rL+R0= -20251016011023.sql h1:u3ivg83bXgYHBbojbWpemLxPE9Dmmj53B6LXo664jxw= -20251016062912.sql h1:W9n1hWchfYkqNX9LO9uxFxEXAb/iY+Pexjnhmp6PbgI= -20251017060617.sql h1:VU6yZ2+LfHpDZ3+TIH40t3F5YXPCpTppuF9+uSqa4b8= -20251017082207.sql h1:QshZslfedckz7iDpSGmPyY9sP6dy6ckHbs8L1TuXIA4= -20251018032635.sql h1:M1U/9W/F9wlW5YDmVAmHFfUJU7FWFaX0DblpfZcYWrE= -20251018040322.sql h1:Zk/vw0e6AzWFO2ElLOzB+OrSz6k+h1Ynxp0TImAzxwY= -20251019093915.sql h1:3Q0kPiZwJnHn5rAvdh0w1LBdiA7W2xBmZWncoPXb044= -20251020062553.sql h1:mJwC/J8GzPAIXckNMvy1f/Nguk2VVf8roD/Raclhbao= -20251021041042.sql h1:d1BAOGAQhqr+oOwcpAVozUsTh457VSDEk2qQFavGG58= -20251021075552.sql h1:TNChGQ1Zlr/1iQ6qvK4iDTAJpe6L/z/M6e/O0SkQVaM= -20251023044432.sql h1:GA2AdJk2ULyjr6igtu9C/CEi4YUIks8r9jXGGaCvPsk= -20251024034832.sql h1:RXmbEhMkOLK5g1QL6up8iRPcwYfo89oLP26ZHvrUK9o= -20251024074315.sql h1:3GnPQSbuAAfMa8oWDyBjhXqn1j1zunY/w0ydX0IGPrA= -20251025013451.sql h1:5eNrA9LDxA4i5CCP7wSyOgFZ6t6jBWVil+oGzJpkJ2E= -20251025013609.sql h1:+N6EHc1kv3hqf16CUhXe+UITPmoxOPfi4MECLmJXNrc= -20251027075128.sql h1:PQflgsjce/p2ClbybLtdehdPNDcMZ9Lb1vd98xd0K8E= -20251027091406.sql h1:bYXV57GvodCMjg0/ox+XKGIAGhrDlVuJ1wO4foNEKtQ= +h1:kXjsrZJU3k4a8nz9SfvetshAm8PQpUM0zww0P+9BhRU= +20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= +20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= +20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= +20250908062323.sql h1:oXl6Z143tOpIl4EfP4B8JNU8LrMvVmHEtCgAfiB4gs8= +20250908073811.sql h1:m2aNXfnGxnLq1+rVWrh4f60q7fhyhV3gEwNu/OIqQlE= +20250908073839.sql h1:cPk54xjLdMs26uY8ZHjNWLuyfAMzV7Zb0/9oJQrsw04= +20250910055902.sql h1:5xwjAV6QbtZT9empTJKfhyAjdknbHzb15B0Ku5dzqtQ= +20250915123412.sql h1:D83xaU2YlDEd21HLup/YQpQ2easMToYCyy/oK6AFgQs= +20250916043819.sql h1:ekoTJsBqQZ8G8n0qJ03d13+eoNoc7sAUEQGA5D/CCxk= +20250917040616.sql h1:zoCnmcXuM7AVv85SmN7RmFglCgJnoDmpRWExH0LAc9Q= +20250917040751.sql h1:J1xyRrh32y1+lezwAyNwPcUQ6ABBSgbvzNLva4SVdQU= +20250917045138.sql h1:jKe1Z0uOLG4SGBYM+S/3P+/zMPztmgoderD5swnMuCg= +20250917093645.sql h1:cNI3Pbz1R3LxvIXLuexafJFCXUXrmuFCgXXJ2sG+FW0= +20250918073552.sql h1:RJ1SvMzP6aeWnoPVD3eVAmIQOkcp6Php8z3QRri6v4g= +20250918073742.sql h1:+cEsnJTJFybe2fR69ZoOiX2R6c6iITl4m6WTZ1hjyzY= +20250918074745.sql h1:2hNVQCXF/dVYXAh+T/7oBFgERGWxzVb2FXJjwkFWGCI= +20250923025134.sql h1:Ykz/qpHiGDXPsCsWTjydQFVSibZP2D+h2fIeb2h2JGA= +20250924051317.sql h1:yQuW6SwJxIOM5fcxeAaie5lSm1oLysU/C2hH2xNCVoQ= +20250929034321.sql h1:101FJ8VH12mrZWlt/X1gvKUGOhoiF8tFbjiapAjnHzg= +20250929034428.sql h1:i+pROD9p+g5dOmmZma6WF/0Hw5g3Ha28NN85iTo1K34= +20250930025550.sql h1:+F+CsCUXD/ql0tHGEow70GhPBX1ZybVn+bh/T4YMh7Y= +20250930140351.sql h1:9AAEG1AnOAH+o0+oHL5G7I8vqlWOhwRlCGyyCpT/y1Q= +20251002085604.sql h1:3xZ68eYp4urXRnvotNH1XvG2mYOSDV/j3zHEZ/txg5E= +20251003032030.sql h1:HB+mQ2lXMNomHDpaRhB/9IwYI9/YiDO5eOJ+nAQH/jw= +20251005060450.sql h1:LbtCE2b+8osM3CvnmQJH1uCPtn+d7WchsslBOz8bL3Q= +20251006041122.sql h1:MlS7f21z06sutnf9dIekt5fuHJr4lgcQ4uCuCXAGsfc= +20251006045658.sql h1:3FmGCPCzjgMPdWDRodZTsx3KVaodd9zB9ilib69aewk= +20251006045928.sql h1:Z5g31PmnzNwk/OKdODcxZGm8fjJQdMFK32Xfnt3bRHg= +20251007022859.sql h1:FO03zEfaNEk/aXwY81d5Lp3MoBB9kPQuXlXJ4BPiSR8= +20251008031337.sql h1:l+sxUAGvcTfj3I6kAFHo+T6AYodC9k9GkR+jaKO2xXc= +20251008031554.sql h1:AqrVfIhSzY3PCy8ZlP5W91wn2iznfIuj5qQfubp6/94= +20251008052346.sql h1:nxnXmooIJ6r1mmzwnw+6efxLfc/k9h2aE6RMptPRons= +20251008073620.sql h1:6YsJp1W4SmQJ1lxpqF27BBlDC1zqhw7Yhc7pLzQTY6M= +20251009042854.sql h1:nkBV+R6j0fg7/JY6wH3eb5Vv0asJLnXmb6lINfT/GLQ= +20251009052657.sql h1:EPvdsib5rzCGPryd10HShGKvFPwM/R5S2lIVwtYxpms= +20251010031743.sql h1:T8IZmx8/btRFKLzTe78MzcBsPJNodnLvB0tby9QkirQ= +20251010070721.sql h1:5NQUk/yOV6sABLCB7swx++YIOyJe6MnU+yt1nRzde5w= +20251010072711.sql h1:ZJNqR2piyu8xJhBvVABSlnGEoKSKae3wuEs+wshPe4k= +20251013044536.sql h1:0Xjw8fNILiT8nnfrJDZgQnPf3dntmIoilbapnih8AE4= +20251013051438.sql h1:lfSuw5mgJnePBJamvhZ81osFIouXeiIEiSZ/evdwo48= +20251013081808.sql h1:ijgjNX08G6GBjA/ks8EKtb7P7Y7Cg7zbhqEOruGnv6M= +20251014060047.sql h1:0jqj49WTtneEIMQDBoo4c095ZGi8sCrA8NnHBrPU6D8= +20251014063537.sql h1:VZLXol0PTsTW21Epg6vBPsztWkDtcxup9F/z88EGgIg= +20251014063720.sql h1:2HVUyCV0ud3BJJDH2GEKZN/+IWLFPCsN1KqhP6csO14= +20251015045455.sql h1:MeLWmMhAOAz8b15Dd7IAQnt6JxjSml02XCXK22C0Lpg= +20251016010845.sql h1:4BncQdDOasRZJkzVJrSJJA7091A9VPNVx/faUCUPhBM= +20251016011023.sql h1:9JB9eFZKURK5RoCVDKR6glSvdJ8NTXrN7K/4q51zkz4= +20251016062912.sql h1:ACNn0fe+EMqUt3hoY+Dr3uqAV/QICBa1+mIW7fUc9Fk= +20251017060617.sql h1:4T3t9ifWrEQTPMSM0XJ98pF7Qdt+UfgtMui17bhrnWI= +20251017082207.sql h1:8vLG1l/saRRMHXkyA4nelJyjaSddhZd6r7R+Uo4JS/c= +20251018032635.sql h1:2xey5gnO3y2XSOrU8MLlIfoylPKbRGDRtHDD07B3MbQ= +20251018040322.sql h1:k/pdNiSoT8zFPqNQ/avOD0vYkNh3BTD64IlHrfVXr7I= +20251019093915.sql h1:hFcQE0y+p5dZiVwePGsRGto9m/q6kJNiUZbVDd5Rnjk= +20251020062553.sql h1:Iw7hulcm5iRQlfW+ygA4iTPxLqkxx6h9vXMXEwUAHKs= +20251021041042.sql h1:wMgSivBV2A0NDcsLmKGIp0kMcVh2IODSG9b4dgzCaOM= +20251021075552.sql h1:8gfSMAglflNO6L0sSzxFNEubYN8/O4thT7OQT+WH+3M= +20251023044432.sql h1:MkvajJs3bfk9+wHvQ43/ccAluJEBARm1gWr1u92ccLA= +20251024034832.sql h1:x3s3VEVYLOSKLAFxJGb2+c1FyTMMvPE+9k4Ew7rKQaI= +20251024074315.sql h1:EjAjelgi5qAfcRq/8vPTlGGYHvAKxNTllm8f0SzZDns= +20251025013451.sql h1:6hnuIiwYiG+6nLhOY/+Yyn+I6ZCFNRZxrJNqBV6HLqE= +20251025013609.sql h1:evPJaTD8WxYRMOJZHkSr7ONLx9PYxT+ankzQt9c/sJ0= +20251027075128.sql h1:/iFQBM1sytjqpyQSOx61q33gnorMgxTiFVSuL6bQqsM= +20251027091406.sql h1:eCZGtUkxAzEAqpC9UsGpP8Df9mS0DEOqSl885LgqpvM= +20251031082443.sql h1:4CJ16kx1tbtG3ycNTTu7di725Q9zL1FNgEozs+JGlwk= diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index 423dc3e9..44af72aa 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -13,6 +13,7 @@ import ( ei "simrs-vx/internal/domain/main-entities/insurance-company" eir "simrs-vx/internal/domain/main-entities/internal-reference" ep "simrs-vx/internal/domain/main-entities/patient" + er "simrs-vx/internal/domain/main-entities/rehab/base" es "simrs-vx/internal/domain/main-entities/specialist" ess "simrs-vx/internal/domain/main-entities/subspecialist" eu "simrs-vx/internal/domain/main-entities/unit" @@ -67,6 +68,7 @@ type Encounter struct { Ambulatory *eam.Basic `json:"ambulatory,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Emergency *eem.Basic `json:"emergency,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Inpatient *eip.Basic `json:"inpatient,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + Rehab *er.Basic `json:"rehab,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` } func (d Encounter) IsDone() bool { From a70e53f6f6f5bf4e1012fdc969169d8378d2dfdf Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 31 Oct 2025 15:47:18 +0700 Subject: [PATCH 031/329] update entity --- cmd/main-migration/migrations/20251031084657.sql | 13 +++++++++++++ cmd/main-migration/migrations/atlas.sum | 5 +++-- internal/interface/migration/main-entities.go | 2 ++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 cmd/main-migration/migrations/20251031084657.sql diff --git a/cmd/main-migration/migrations/20251031084657.sql b/cmd/main-migration/migrations/20251031084657.sql new file mode 100644 index 00000000..30974d75 --- /dev/null +++ b/cmd/main-migration/migrations/20251031084657.sql @@ -0,0 +1,13 @@ +-- Create "Rehab" table +CREATE TABLE "public"."Rehab" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Doctor_Id" bigint NULL, + "AllocatedVisitCount" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Rehab_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Rehab_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index ab2219c2..a851d5ed 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:kXjsrZJU3k4a8nz9SfvetshAm8PQpUM0zww0P+9BhRU= +h1:llqBiqOQF+QcCuZSeEWKfRzAd9gN8gE4uGgdKWkfGW4= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -62,4 +62,5 @@ h1:kXjsrZJU3k4a8nz9SfvetshAm8PQpUM0zww0P+9BhRU= 20251025013609.sql h1:evPJaTD8WxYRMOJZHkSr7ONLx9PYxT+ankzQt9c/sJ0= 20251027075128.sql h1:/iFQBM1sytjqpyQSOx61q33gnorMgxTiFVSuL6bQqsM= 20251027091406.sql h1:eCZGtUkxAzEAqpC9UsGpP8Df9mS0DEOqSl885LgqpvM= -20251031082443.sql h1:4CJ16kx1tbtG3ycNTTu7di725Q9zL1FNgEozs+JGlwk= +20251031082443.sql h1:ajvi2G8OGvcmB2pJ1SoX/09ALHLWKNh84RSonVhJqAc= +20251031084657.sql h1:rsml3HJP+sXmciMBIkowwkyabKFWuQTci2lDjnf5km0= diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index 6507202e..a46b27dd 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -73,6 +73,7 @@ import ( proceduresrc "simrs-vx/internal/domain/main-entities/procedure-src" province "simrs-vx/internal/domain/main-entities/province" regency "simrs-vx/internal/domain/main-entities/regency" + rehab "simrs-vx/internal/domain/main-entities/rehab" responsibledoctorhist "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" room "simrs-vx/internal/domain/main-entities/room" sbar "simrs-vx/internal/domain/main-entities/sbar" @@ -193,5 +194,6 @@ func getMainEntities() []any { &responsibledoctorhist.ResponsibleDoctorHist{}, &admemployeehist.AdmEmployeeHist{}, &vclaimmember.VclaimMember{}, + &rehab.Rehab{}, } } From ab9f1934fe31a4079010c37709fe1a593b0f83a2 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Fri, 31 Oct 2025 16:06:36 +0700 Subject: [PATCH 032/329] at employee_position_code in claims --- internal/use-case/main-use-case/authentication/case.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/use-case/main-use-case/authentication/case.go b/internal/use-case/main-use-case/authentication/case.go index 18ae9b8a..a32b4253 100644 --- a/internal/use-case/main-use-case/authentication/case.go +++ b/internal/use-case/main-use-case/authentication/case.go @@ -128,6 +128,7 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { // employee position if employee.Id > 0 && employee.Position_Code != nil { + atClaims["employee_position_code"] = *employee.Position_Code switch *employee.Position_Code { case erg.EPCDoc: doctor := ed.Doctor{} From 13e703b31bce692a5f440ec405f88d85733c6bdd Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Fri, 31 Oct 2025 16:27:05 +0700 Subject: [PATCH 033/329] feat (adime,soapi,sbar): no longer get employee id, use employee id from authinfo --- internal/use-case/main-use-case/adime/case.go | 13 ++++++------- .../use-case/main-use-case/authentication/case.go | 1 + internal/use-case/main-use-case/sbar/case.go | 13 ++++++------- internal/use-case/main-use-case/soapi/case.go | 13 ++++++------- 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/internal/use-case/main-use-case/adime/case.go b/internal/use-case/main-use-case/adime/case.go index 01d101ae..bc7d4e98 100644 --- a/internal/use-case/main-use-case/adime/case.go +++ b/internal/use-case/main-use-case/adime/case.go @@ -5,9 +5,6 @@ import ( "strconv" e "simrs-vx/internal/domain/main-entities/adime" - ee "simrs-vx/internal/domain/main-entities/employee" - - ue "simrs-vx/internal/use-case/main-use-case/employee" dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -49,11 +46,13 @@ func Create(input e.CreateDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - employee, err := ue.ReadDetailData(ee.ReadDetailDto{User_Id: &input.AuthInfo.User_Id}, &event, tx) - if err != nil { - return err + if input.AuthInfo.Employee_Id != nil { + v := uint(*input.AuthInfo.Employee_Id) + input.Employee_Id = &v + } else { + input.Employee_Id = nil } - input.Employee_Id = &employee.Id + if resData, err := CreateData(input, &event, tx); err != nil { return err } else { diff --git a/internal/use-case/main-use-case/authentication/case.go b/internal/use-case/main-use-case/authentication/case.go index a32b4253..6c645208 100644 --- a/internal/use-case/main-use-case/authentication/case.go +++ b/internal/use-case/main-use-case/authentication/case.go @@ -315,6 +315,7 @@ func ExtractToken(r *http.Request, tokenType TokenType) (data *pa.AuthInfo, err data.Laborant_Id = checkIntPtrClaims(claims, "laborant_id") data.Pharmachist_Id = checkIntPtrClaims(claims, "pharmachist_id") data.Intern_Position_Code = checkStrPtrClaims(claims, "intern_position_code") + data.Employee_Id = checkIntPtrClaims(claims, "employee_id") return } return nil, d.FieldError{Code: "token", Message: "token-invalid"} diff --git a/internal/use-case/main-use-case/sbar/case.go b/internal/use-case/main-use-case/sbar/case.go index 6c92f2b0..45045e35 100644 --- a/internal/use-case/main-use-case/sbar/case.go +++ b/internal/use-case/main-use-case/sbar/case.go @@ -4,11 +4,8 @@ import ( "errors" "strconv" - ee "simrs-vx/internal/domain/main-entities/employee" e "simrs-vx/internal/domain/main-entities/sbar" - ue "simrs-vx/internal/use-case/main-use-case/employee" - dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -49,11 +46,13 @@ func Create(input e.CreateDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - employee, err := ue.ReadDetailData(ee.ReadDetailDto{User_Id: &input.AuthInfo.User_Id}, &event, tx) - if err != nil { - return err + if input.AuthInfo.Employee_Id != nil { + v := uint(*input.AuthInfo.Employee_Id) + input.Employee_Id = &v + } else { + input.Employee_Id = nil } - input.Employee_Id = &employee.Id + if resData, err := CreateData(input, &event, tx); err != nil { return err } else { diff --git a/internal/use-case/main-use-case/soapi/case.go b/internal/use-case/main-use-case/soapi/case.go index fd06e140..3dc8e195 100644 --- a/internal/use-case/main-use-case/soapi/case.go +++ b/internal/use-case/main-use-case/soapi/case.go @@ -4,11 +4,8 @@ import ( "errors" "strconv" - ee "simrs-vx/internal/domain/main-entities/employee" e "simrs-vx/internal/domain/main-entities/soapi" - ue "simrs-vx/internal/use-case/main-use-case/employee" - dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -49,11 +46,13 @@ func Create(input e.CreateDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - employee, err := ue.ReadDetailData(ee.ReadDetailDto{User_Id: &input.AuthInfo.User_Id}, &event, tx) - if err != nil { - return err + if input.AuthInfo.Employee_Id != nil { + v := uint(*input.AuthInfo.Employee_Id) + input.Employee_Id = &v + } else { + input.Employee_Id = nil } - input.Employee_Id = &employee.Id + if resData, err := CreateData(input, &event, tx); err != nil { return err } else { From e69fe7bbb1aeb3d33b148048bb2b3471e5e1d1ed Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Sat, 1 Nov 2025 16:13:40 +0700 Subject: [PATCH 034/329] feat/trx-order: mcu - added inlcude on the McuOrder - reuse deleted data on the McuOrderItem - added scope on the McuOrder --- internal/domain/main-entities/mcu-order/dto.go | 3 ++- .../domain/main-entities/mcu-order/entity.go | 2 ++ .../main-entities/mcu-src-category/entity.go | 2 +- internal/domain/main-entities/mcu-src/dto.go | 2 +- .../interface/main-handler/mcu-order/handler.go | 1 + .../main-use-case/mcu-order-item/lib.go | 17 ++++++++++++++--- .../use-case/main-use-case/mcu-order/lib.go | 2 +- 7 files changed, 22 insertions(+), 7 deletions(-) diff --git a/internal/domain/main-entities/mcu-order/dto.go b/internal/domain/main-entities/mcu-order/dto.go index a8ce83de..9c540d56 100644 --- a/internal/domain/main-entities/mcu-order/dto.go +++ b/internal/domain/main-entities/mcu-order/dto.go @@ -49,7 +49,8 @@ type FilterDto struct { McuUrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"mcuUrgencyLevel-code"` } type ReadDetailDto struct { - Id uint `json:"id"` + Id uint `json:"id"` + Includes string `json:"includes"` } type UpdateDto struct { diff --git a/internal/domain/main-entities/mcu-order/entity.go b/internal/domain/main-entities/mcu-order/entity.go index 1c72a2ba..38053523 100644 --- a/internal/domain/main-entities/mcu-order/entity.go +++ b/internal/domain/main-entities/mcu-order/entity.go @@ -8,6 +8,7 @@ import ( ercl "simrs-vx/internal/domain/references/clinical" erc "simrs-vx/internal/domain/references/common" + ere "simrs-vx/internal/domain/references/encounter" ) type McuOrder struct { @@ -22,6 +23,7 @@ type McuOrder struct { Number uint8 `json:"number"` Temperature float64 `json:"temperature"` McuUrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"mcuUrgencyLevel_code" gorm:"not null;size:15"` + Scope_Code *ere.CheckupScopeCode `json:"scope_code" gorm:"index;size:10"` } func (d McuOrder) IsCompleted() bool { diff --git a/internal/domain/main-entities/mcu-src-category/entity.go b/internal/domain/main-entities/mcu-src-category/entity.go index 21c266e3..3a0d08ca 100644 --- a/internal/domain/main-entities/mcu-src-category/entity.go +++ b/internal/domain/main-entities/mcu-src-category/entity.go @@ -9,5 +9,5 @@ type McuSrcCategory struct { ecore.SmallMain // adjust this according to the needs Code string `json:"code" gorm:"unique;size:20"` Name string `json:"name" gorm:"size:50"` - Scope_Code *ere.CheckupScopeCode `json:"scope_code" gorm:"size:10"` + Scope_Code *ere.CheckupScopeCode `json:"scope_code" gorm:"index;size:10"` } diff --git a/internal/domain/main-entities/mcu-src/dto.go b/internal/domain/main-entities/mcu-src/dto.go index 96586057..7ab13428 100644 --- a/internal/domain/main-entities/mcu-src/dto.go +++ b/internal/domain/main-entities/mcu-src/dto.go @@ -22,7 +22,7 @@ type ReadListDto struct { type FilterDto struct { Code string `json:"code"` Name string `json:"name"` - McuSrcCategory_Code *string `json:"mcuSrcCategory-code"` + McuSrcCategory_Code *string `json:"mcu-src-category-code"` Search string `json:"search" gormhelper:"searchColumns=Code,Name"` } diff --git a/internal/interface/main-handler/mcu-order/handler.go b/internal/interface/main-handler/mcu-order/handler.go index 2cdb5c32..ac4aca9f 100644 --- a/internal/interface/main-handler/mcu-order/handler.go +++ b/internal/interface/main-handler/mcu-order/handler.go @@ -47,6 +47,7 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { return } dto := e.ReadDetailDto{} + sf.UrlQueryParam(&dto, *r.URL) dto.Id = uint(id) res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) diff --git a/internal/use-case/main-use-case/mcu-order-item/lib.go b/internal/use-case/main-use-case/mcu-order-item/lib.go index e53f1c2f..13030ce8 100644 --- a/internal/use-case/main-use-case/mcu-order-item/lib.go +++ b/internal/use-case/main-use-case/mcu-order-item/lib.go @@ -15,9 +15,6 @@ import ( func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.McuOrderItem, error) { pl.SetLogInfo(event, nil, "started", "DBCreate") - data := e.McuOrderItem{} - setData(&input, &data) - var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -25,6 +22,20 @@ func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.McuOrde tx = dg.I } + deletedData := e.McuOrderItem{} + tx.Unscoped(). + Where("\"McuOrder_Id\" = ? AND \"McuSrc_Id\" = ?", input.McuOrder_Id, input.McuSrc_Id). + First(&deletedData) + if deletedData.Id != 0 { + if err := tx.Model(e.McuOrderItem{}).Where("Id = ?", deletedData.Id).Update("DeletedAt", nil).Error; err != nil { + return nil, plh.HandleCreateError(input, event, err) + } + return &deletedData, nil + } + + data := e.McuOrderItem{} + setData(&input, &data) + if err := tx.Create(&data).Error; err != nil { return nil, plh.HandleCreateError(input, event, err) } diff --git a/internal/use-case/main-use-case/mcu-order/lib.go b/internal/use-case/main-use-case/mcu-order/lib.go index ccb63db9..c659be5b 100644 --- a/internal/use-case/main-use-case/mcu-order/lib.go +++ b/internal/use-case/main-use-case/mcu-order/lib.go @@ -81,7 +81,7 @@ 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 } From 0997537c93d84031b673a91cfbdccc8e322b0053 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Sat, 1 Nov 2025 16:30:34 +0700 Subject: [PATCH 035/329] feat/trx-orders: added includes on prescription --- internal/domain/main-entities/prescription/dto.go | 5 +++-- internal/use-case/main-use-case/prescription/lib.go | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/internal/domain/main-entities/prescription/dto.go b/internal/domain/main-entities/prescription/dto.go index 3a3ad7b5..f0c6901e 100644 --- a/internal/domain/main-entities/prescription/dto.go +++ b/internal/domain/main-entities/prescription/dto.go @@ -34,8 +34,9 @@ type FilterDto struct { Status_Code *erc.DataStatusCode `json:"status-code"` } type ReadDetailDto struct { - Id uint `json:"id"` - Encounter_Id *uint `json:"encounter_id"` + Id uint `json:"id"` + Encounter_Id *uint `json:"encounter_id"` + Includes string `json:"includes"` } type UpdateDto struct { diff --git a/internal/use-case/main-use-case/prescription/lib.go b/internal/use-case/main-use-case/prescription/lib.go index 013952f8..52025c89 100644 --- a/internal/use-case/main-use-case/prescription/lib.go +++ b/internal/use-case/main-use-case/prescription/lib.go @@ -89,7 +89,7 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e tx = tx.Where("\"Id\" = ?", input.Id) } - if err := tx.First(&data).Error; err != nil { + if err := tx.Scopes(gh.Preload(input.Includes)).First(&data).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { return nil, processedErr } From b43c174927d9c71d3e8b9ef8e56f319533d08ea4 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Sun, 2 Nov 2025 07:30:18 +0700 Subject: [PATCH 036/329] feat/trx-orders: applied migration --- .../migrations/20251102002037.sql | 6 + cmd/main-migration/migrations/atlas.sum | 129 +++++++++--------- 2 files changed, 71 insertions(+), 64 deletions(-) create mode 100644 cmd/main-migration/migrations/20251102002037.sql diff --git a/cmd/main-migration/migrations/20251102002037.sql b/cmd/main-migration/migrations/20251102002037.sql new file mode 100644 index 00000000..14a39ae1 --- /dev/null +++ b/cmd/main-migration/migrations/20251102002037.sql @@ -0,0 +1,6 @@ +-- Modify "McuOrder" table +ALTER TABLE "public"."McuOrder" ADD COLUMN "Scope_Code" character varying(10) NULL; +-- Create index "idx_McuOrder_Scope_Code" to table: "McuOrder" +CREATE INDEX "idx_McuOrder_Scope_Code" ON "public"."McuOrder" ("Scope_Code"); +-- Create index "idx_McuSrcCategory_Scope_Code" to table: "McuSrcCategory" +CREATE INDEX "idx_McuSrcCategory_Scope_Code" ON "public"."McuSrcCategory" ("Scope_Code"); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index a808ecf3..73107582 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,64 +1,65 @@ -h1:Yqb9JSUhzEc3RNP4eGOax6//4rndgFOUT0Q5zHfojxU= -20250904105930.sql h1:Vv4vCurl7m7/ZB6TjRpkubHpQ4RYwSUn0QHdzfoGpzY= -20250904141448.sql h1:FYCHH9Os4KkrZMDu/jR8FMP+wLMRW+Mb0PkLU/9BRDg= -20250908062237.sql h1:oanBpKZd+akPu2I/xYhUSbd0G5tAFbXzKLER/Zs8ENI= -20250908062323.sql h1:miNG9COddXkD1jGTgaROMAZ618eT6oiLGiJhXWnQwhE= -20250908073811.sql h1:gOi5cnGG1htlpfizybYmUIT0vYjZTBfXiI0nPSYK2u8= -20250908073839.sql h1:cWNDA4YikjoOteAJuNLFILjQUJPFB6o8Wxreiek4QyI= -20250910055902.sql h1:nxxOGnU0BbH/v3IPgeIOXOwH8d3tKomw7h6FTeMnnBs= -20250915123412.sql h1:mz7SiWfrdf0qE1VTSAAnA/147d6gyp6ry5vZ2bR9SH0= -20250916043819.sql h1:RHXVtmMkB6wfv06HfPyHMBmUfIpFt1xveafNz0kwKnE= -20250917040616.sql h1:MYVDht+akBlzQGKNu2hTTTLPEcH1bxT/Q8MK6WEtuhs= -20250917040751.sql h1:J79YyS2JzWgh5oKXMTgh67uo3gLxKaAsxRiZmSIfjBs= -20250917045138.sql h1:/SM1N4O8X3yxpoJgMEARmS1uOkuLKsTOy4PLsRCOKaQ= -20250917093645.sql h1:PNBTGZ7s10e5b5+Tie8YfVQBN0zKtJ5T34oK1iOUEb4= -20250918073552.sql h1:jG7+g3i8ODYaJdcdZz12v3nbsZ5mB9wG6kWnGyTQIRI= -20250918073742.sql h1:j+rgw7puxE7s+phqPVZHmPk0af3rcaA56Itp86y1suY= -20250918074745.sql h1:rPmP4DXs6OnY4Vp+xO/z9jFpJt/RrJ52SJJjIIxeDvc= -20250923025134.sql h1:2r6pcwnBSU5Y9Czk1OHBoh4yZXiMtEca9X8843fTEX0= -20250924051317.sql h1:iUAk2gsGoEGIPQ0lEEUp8maMSId8emNbP+kP712ABIA= -20250929034321.sql h1:UlpALNVmdi95zOIT0yc6ZyTj9bBjQEIpZhvgrc52M+k= -20250929034428.sql h1:feF+H4nDyHh5bdx48Oiz0A1qecZfi6v3qTTdjzJ45Dg= -20250930025550.sql h1:6XT1kXI3Z3ZIxxmvT7poufZWWCW0QiejZPaFV5wBnjI= -20250930140351.sql h1:HxnmAbh9gCy8jwl/9ycGktiByaUripsjFFvohofY2CY= -20251002085604.sql h1:SjLPi+ZN6qDccK3DaEQCgNsZpPwr5kynWXwbwEsziCI= -20251003032030.sql h1:oHfxNSuqTxU8Zaf9H+h8TuUb1Da03wcyc6hZjDrUQ2s= -20251005060450.sql h1:GIuCcrd4MwjmXpvbzDzPYL18BV3QaZZ+Y2FmEzjvi0E= -20251006041122.sql h1:uNDQbSw0M08lYoMvUNlQtS3iDzpPM1ixT13ugSAoWjE= -20251006045658.sql h1:z+t7yCK54Q4SSiF9kUyUhkYB2F+kzSW9TB7ogxd9wzw= -20251006045928.sql h1:1lATLFLp4BWwGZqAjZdP0Dc6ypNXiYcwjoNkqGa8NFE= -20251007022859.sql h1:HXXwWrkyvzJzJGAt9mGskCRBBV/c1JfPmfjDocmJhQ4= -20251008031337.sql h1:Ln5pCF3Hxa5foHZLcds+z/us2eH6VAhhEj3w0TAGlVs= -20251008031554.sql h1:aB4MUS2lmqG0//4HKUWorcPSpWya0VC4QItvGyskEVI= -20251008052346.sql h1:MI3AZgU5XcwZT2OvvlWAxdRtL0eJ3jjRwt56IY1+pRU= -20251008073620.sql h1:sztWXuSNYwpEraaSapSsYwno75LO5H/N7ob7OJQ8X/A= -20251009042854.sql h1:TnPXj+dCJls3IU//cuqJZymyBzZMKs7ayazfgtAFRxM= -20251009052657.sql h1:leXbs0CP8r5dRilmYyLRk1MICqak3ea1/LWMtFrijqQ= -20251010031743.sql h1:SgHNY/lQ88G2F4nZyMfiOkDntb+gtOR+nEQLqXBTwv4= -20251010070721.sql h1:AnJnhXsMzDvK4AFgYw6B16Kpo/hljrZtcpc9m2VOSHQ= -20251010072711.sql h1:aXPTtNwLcTuw8C/yAxwxvqs0ayEjNzI1uuE0vE3ERa8= -20251013044536.sql h1:7Pq6JcvTpPBYDCW2dz3HdgUwY65HlhEVWy9TiG8iONE= -20251013051438.sql h1:X6t8bkqpUYYokBunSufMQUe5vCg0VyO6dxbm7ngosUc= -20251013081808.sql h1:495pLguXL2Ozh+ycn4UYZgZbn6WbjXNbyZUc3JU8qhI= -20251014060047.sql h1:nCgImMRGHhziiW57O1ofWaXCAPGaCOHN7PldQ3OSmM4= -20251014063537.sql h1:2cLmID79jP6cuQ1YJaWTtghFiM1GtHMC0ZQl30Hpy1M= -20251014063720.sql h1:bzLKKVAjSHgDFoiI/glj7t1ETlSAKx+AlsIAaP0ru2g= -20251015045455.sql h1:S547+UugQhlTRcn1Lm1IfqT5RNPttIWIiD+RTx69YaE= -20251016010845.sql h1:c9DUvxl17pUkf0azdYGM/YDzYxIJkLcfZOcMI4rL+R0= -20251016011023.sql h1:u3ivg83bXgYHBbojbWpemLxPE9Dmmj53B6LXo664jxw= -20251016062912.sql h1:W9n1hWchfYkqNX9LO9uxFxEXAb/iY+Pexjnhmp6PbgI= -20251017060617.sql h1:VU6yZ2+LfHpDZ3+TIH40t3F5YXPCpTppuF9+uSqa4b8= -20251017082207.sql h1:QshZslfedckz7iDpSGmPyY9sP6dy6ckHbs8L1TuXIA4= -20251018032635.sql h1:M1U/9W/F9wlW5YDmVAmHFfUJU7FWFaX0DblpfZcYWrE= -20251018040322.sql h1:Zk/vw0e6AzWFO2ElLOzB+OrSz6k+h1Ynxp0TImAzxwY= -20251019093915.sql h1:3Q0kPiZwJnHn5rAvdh0w1LBdiA7W2xBmZWncoPXb044= -20251020062553.sql h1:mJwC/J8GzPAIXckNMvy1f/Nguk2VVf8roD/Raclhbao= -20251021041042.sql h1:d1BAOGAQhqr+oOwcpAVozUsTh457VSDEk2qQFavGG58= -20251021075552.sql h1:TNChGQ1Zlr/1iQ6qvK4iDTAJpe6L/z/M6e/O0SkQVaM= -20251023044432.sql h1:GA2AdJk2ULyjr6igtu9C/CEi4YUIks8r9jXGGaCvPsk= -20251024034832.sql h1:RXmbEhMkOLK5g1QL6up8iRPcwYfo89oLP26ZHvrUK9o= -20251024074315.sql h1:3GnPQSbuAAfMa8oWDyBjhXqn1j1zunY/w0ydX0IGPrA= -20251025013451.sql h1:5eNrA9LDxA4i5CCP7wSyOgFZ6t6jBWVil+oGzJpkJ2E= -20251025013609.sql h1:+N6EHc1kv3hqf16CUhXe+UITPmoxOPfi4MECLmJXNrc= -20251027075128.sql h1:PQflgsjce/p2ClbybLtdehdPNDcMZ9Lb1vd98xd0K8E= -20251027091406.sql h1:bYXV57GvodCMjg0/ox+XKGIAGhrDlVuJ1wO4foNEKtQ= +h1:ewCVlZr73Pj7qD/A+J5/yF94CncwZCb6s8VSHl0Hawo= +20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= +20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= +20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= +20250908062323.sql h1:oXl6Z143tOpIl4EfP4B8JNU8LrMvVmHEtCgAfiB4gs8= +20250908073811.sql h1:m2aNXfnGxnLq1+rVWrh4f60q7fhyhV3gEwNu/OIqQlE= +20250908073839.sql h1:cPk54xjLdMs26uY8ZHjNWLuyfAMzV7Zb0/9oJQrsw04= +20250910055902.sql h1:5xwjAV6QbtZT9empTJKfhyAjdknbHzb15B0Ku5dzqtQ= +20250915123412.sql h1:D83xaU2YlDEd21HLup/YQpQ2easMToYCyy/oK6AFgQs= +20250916043819.sql h1:ekoTJsBqQZ8G8n0qJ03d13+eoNoc7sAUEQGA5D/CCxk= +20250917040616.sql h1:zoCnmcXuM7AVv85SmN7RmFglCgJnoDmpRWExH0LAc9Q= +20250917040751.sql h1:J1xyRrh32y1+lezwAyNwPcUQ6ABBSgbvzNLva4SVdQU= +20250917045138.sql h1:jKe1Z0uOLG4SGBYM+S/3P+/zMPztmgoderD5swnMuCg= +20250917093645.sql h1:cNI3Pbz1R3LxvIXLuexafJFCXUXrmuFCgXXJ2sG+FW0= +20250918073552.sql h1:RJ1SvMzP6aeWnoPVD3eVAmIQOkcp6Php8z3QRri6v4g= +20250918073742.sql h1:+cEsnJTJFybe2fR69ZoOiX2R6c6iITl4m6WTZ1hjyzY= +20250918074745.sql h1:2hNVQCXF/dVYXAh+T/7oBFgERGWxzVb2FXJjwkFWGCI= +20250923025134.sql h1:Ykz/qpHiGDXPsCsWTjydQFVSibZP2D+h2fIeb2h2JGA= +20250924051317.sql h1:yQuW6SwJxIOM5fcxeAaie5lSm1oLysU/C2hH2xNCVoQ= +20250929034321.sql h1:101FJ8VH12mrZWlt/X1gvKUGOhoiF8tFbjiapAjnHzg= +20250929034428.sql h1:i+pROD9p+g5dOmmZma6WF/0Hw5g3Ha28NN85iTo1K34= +20250930025550.sql h1:+F+CsCUXD/ql0tHGEow70GhPBX1ZybVn+bh/T4YMh7Y= +20250930140351.sql h1:9AAEG1AnOAH+o0+oHL5G7I8vqlWOhwRlCGyyCpT/y1Q= +20251002085604.sql h1:3xZ68eYp4urXRnvotNH1XvG2mYOSDV/j3zHEZ/txg5E= +20251003032030.sql h1:HB+mQ2lXMNomHDpaRhB/9IwYI9/YiDO5eOJ+nAQH/jw= +20251005060450.sql h1:LbtCE2b+8osM3CvnmQJH1uCPtn+d7WchsslBOz8bL3Q= +20251006041122.sql h1:MlS7f21z06sutnf9dIekt5fuHJr4lgcQ4uCuCXAGsfc= +20251006045658.sql h1:3FmGCPCzjgMPdWDRodZTsx3KVaodd9zB9ilib69aewk= +20251006045928.sql h1:Z5g31PmnzNwk/OKdODcxZGm8fjJQdMFK32Xfnt3bRHg= +20251007022859.sql h1:FO03zEfaNEk/aXwY81d5Lp3MoBB9kPQuXlXJ4BPiSR8= +20251008031337.sql h1:l+sxUAGvcTfj3I6kAFHo+T6AYodC9k9GkR+jaKO2xXc= +20251008031554.sql h1:AqrVfIhSzY3PCy8ZlP5W91wn2iznfIuj5qQfubp6/94= +20251008052346.sql h1:nxnXmooIJ6r1mmzwnw+6efxLfc/k9h2aE6RMptPRons= +20251008073620.sql h1:6YsJp1W4SmQJ1lxpqF27BBlDC1zqhw7Yhc7pLzQTY6M= +20251009042854.sql h1:nkBV+R6j0fg7/JY6wH3eb5Vv0asJLnXmb6lINfT/GLQ= +20251009052657.sql h1:EPvdsib5rzCGPryd10HShGKvFPwM/R5S2lIVwtYxpms= +20251010031743.sql h1:T8IZmx8/btRFKLzTe78MzcBsPJNodnLvB0tby9QkirQ= +20251010070721.sql h1:5NQUk/yOV6sABLCB7swx++YIOyJe6MnU+yt1nRzde5w= +20251010072711.sql h1:ZJNqR2piyu8xJhBvVABSlnGEoKSKae3wuEs+wshPe4k= +20251013044536.sql h1:0Xjw8fNILiT8nnfrJDZgQnPf3dntmIoilbapnih8AE4= +20251013051438.sql h1:lfSuw5mgJnePBJamvhZ81osFIouXeiIEiSZ/evdwo48= +20251013081808.sql h1:ijgjNX08G6GBjA/ks8EKtb7P7Y7Cg7zbhqEOruGnv6M= +20251014060047.sql h1:0jqj49WTtneEIMQDBoo4c095ZGi8sCrA8NnHBrPU6D8= +20251014063537.sql h1:VZLXol0PTsTW21Epg6vBPsztWkDtcxup9F/z88EGgIg= +20251014063720.sql h1:2HVUyCV0ud3BJJDH2GEKZN/+IWLFPCsN1KqhP6csO14= +20251015045455.sql h1:MeLWmMhAOAz8b15Dd7IAQnt6JxjSml02XCXK22C0Lpg= +20251016010845.sql h1:4BncQdDOasRZJkzVJrSJJA7091A9VPNVx/faUCUPhBM= +20251016011023.sql h1:9JB9eFZKURK5RoCVDKR6glSvdJ8NTXrN7K/4q51zkz4= +20251016062912.sql h1:ACNn0fe+EMqUt3hoY+Dr3uqAV/QICBa1+mIW7fUc9Fk= +20251017060617.sql h1:4T3t9ifWrEQTPMSM0XJ98pF7Qdt+UfgtMui17bhrnWI= +20251017082207.sql h1:8vLG1l/saRRMHXkyA4nelJyjaSddhZd6r7R+Uo4JS/c= +20251018032635.sql h1:2xey5gnO3y2XSOrU8MLlIfoylPKbRGDRtHDD07B3MbQ= +20251018040322.sql h1:k/pdNiSoT8zFPqNQ/avOD0vYkNh3BTD64IlHrfVXr7I= +20251019093915.sql h1:hFcQE0y+p5dZiVwePGsRGto9m/q6kJNiUZbVDd5Rnjk= +20251020062553.sql h1:Iw7hulcm5iRQlfW+ygA4iTPxLqkxx6h9vXMXEwUAHKs= +20251021041042.sql h1:wMgSivBV2A0NDcsLmKGIp0kMcVh2IODSG9b4dgzCaOM= +20251021075552.sql h1:8gfSMAglflNO6L0sSzxFNEubYN8/O4thT7OQT+WH+3M= +20251023044432.sql h1:MkvajJs3bfk9+wHvQ43/ccAluJEBARm1gWr1u92ccLA= +20251024034832.sql h1:x3s3VEVYLOSKLAFxJGb2+c1FyTMMvPE+9k4Ew7rKQaI= +20251024074315.sql h1:EjAjelgi5qAfcRq/8vPTlGGYHvAKxNTllm8f0SzZDns= +20251025013451.sql h1:6hnuIiwYiG+6nLhOY/+Yyn+I6ZCFNRZxrJNqBV6HLqE= +20251025013609.sql h1:evPJaTD8WxYRMOJZHkSr7ONLx9PYxT+ankzQt9c/sJ0= +20251027075128.sql h1:/iFQBM1sytjqpyQSOx61q33gnorMgxTiFVSuL6bQqsM= +20251027091406.sql h1:eCZGtUkxAzEAqpC9UsGpP8Df9mS0DEOqSl885LgqpvM= +20251102002037.sql h1:FTJ9KdTOhso+wNbDoEtvj3D8XkgT6blu79JucGQoprg= From 3391ee0937c9a8a70c7079957c9778c88075528c Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Sun, 2 Nov 2025 16:18:35 +0700 Subject: [PATCH 037/329] feat/trx-orders: added scope for order filtering --- .../domain/main-entities/mcu-order/dto.go | 73 ++++++++++--------- .../domain/main-entities/mcu-order/entity.go | 24 +++--- .../main-use-case/mcu-order/helper.go | 2 +- 3 files changed, 50 insertions(+), 49 deletions(-) diff --git a/internal/domain/main-entities/mcu-order/dto.go b/internal/domain/main-entities/mcu-order/dto.go index 9c540d56..3d042c2f 100644 --- a/internal/domain/main-entities/mcu-order/dto.go +++ b/internal/domain/main-entities/mcu-order/dto.go @@ -20,14 +20,14 @@ import ( ) type CreateDto struct { - Encounter_Id *uint `json:"encounter_id"` - Status_Code erc.DataStatusCode `json:"status_code" gorm:"not null;size:10"` - Doctor_Id *uint `json:"doctor_id"` - SpecimenPickTime *time.Time `json:"specimenPickTime"` - ExaminationDate *time.Time `json:"examinationDate"` - Number uint8 `json:"number"` - Temperature float64 `json:"temperature"` - McuUrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"mcuUrgencyLevel_code"` + Encounter_Id *uint `json:"encounter_id"` + Status_Code erc.DataStatusCode `json:"status_code" gorm:"not null;size:10"` + Doctor_Id *uint `json:"doctor_id"` + SpecimenPickTime *time.Time `json:"specimenPickTime"` + ExaminationDate *time.Time `json:"examinationDate"` + Number uint8 `json:"number"` + Temperature float64 `json:"temperature"` + UrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"urgencyLevel_code"` pa.AuthInfo } @@ -39,14 +39,15 @@ type ReadListDto struct { } type FilterDto struct { - Encounter_Id *uint `json:"encounter-id"` - Status_Code erc.DataStatusCode `json:"status-code" gorm:"not null;size:10"` - Doctor_Id *uint `json:"doctor-id"` - SpecimenPickTime *time.Time `json:"specimenPickTime"` - ExaminationDate *time.Time `json:"examinationDate"` - Number uint8 `json:"number"` - Temperature float64 `json:"temperature"` - McuUrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"mcuUrgencyLevel-code"` + Encounter_Id *uint `json:"encounter-id"` + Status_Code erc.DataStatusCode `json:"status-code" gorm:"not null;size:10"` + Doctor_Id *uint `json:"doctor-id"` + SpecimenPickTime *time.Time `json:"specimenPickTime"` + ExaminationDate *time.Time `json:"examinationDate"` + Number uint8 `json:"number"` + Temperature float64 `json:"temperature"` + UrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"urgency-level-code"` + Scope_Code ercl.McuUrgencyLevelCode `json:"scope-code"` } type ReadDetailDto struct { Id uint `json:"id"` @@ -74,30 +75,30 @@ type MetaDto struct { } type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty"` - Status_Code erc.DataStatusCode `json:"status_code" gorm:"not null;size:10"` - Doctor_Id *uint `json:"doctor_id"` - Doctor *ed.Doctor `json:"doctor,omitempty"` - SpecimenPickTime *time.Time `json:"specimenPickTime"` - ExaminationDate *time.Time `json:"examinationDate"` - Number uint8 `json:"number"` - Temperature float64 `json:"temperature"` - McuUrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"mcuUrgencyLevel_code""` + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty"` + Status_Code erc.DataStatusCode `json:"status_code" gorm:"not null;size:10"` + Doctor_Id *uint `json:"doctor_id"` + Doctor *ed.Doctor `json:"doctor,omitempty"` + SpecimenPickTime *time.Time `json:"specimenPickTime"` + ExaminationDate *time.Time `json:"examinationDate"` + Number uint8 `json:"number"` + Temperature float64 `json:"temperature"` + UrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"urgencyLevel_code""` } func (d McuOrder) ToResponse() ResponseDto { resp := ResponseDto{ - Encounter_Id: d.Encounter_Id, - Encounter: d.Encounter, - Status_Code: d.Status_Code, - Doctor_Id: d.Doctor_Id, - Doctor: d.Doctor, - SpecimenPickTime: d.SpecimenPickTime, - ExaminationDate: d.ExaminationDate, - Number: d.Number, - Temperature: d.Temperature, - McuUrgencyLevel_Code: d.McuUrgencyLevel_Code, + Encounter_Id: d.Encounter_Id, + Encounter: d.Encounter, + Status_Code: d.Status_Code, + Doctor_Id: d.Doctor_Id, + Doctor: d.Doctor, + SpecimenPickTime: d.SpecimenPickTime, + ExaminationDate: d.ExaminationDate, + Number: d.Number, + Temperature: d.Temperature, + UrgencyLevel_Code: d.UrgencyLevel_Code, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/mcu-order/entity.go b/internal/domain/main-entities/mcu-order/entity.go index 38053523..d2b81e58 100644 --- a/internal/domain/main-entities/mcu-order/entity.go +++ b/internal/domain/main-entities/mcu-order/entity.go @@ -12,18 +12,18 @@ import ( ) type McuOrder struct { - ecore.Main // adjust this according to the needs - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Status_Code erc.DataStatusCode `json:"status_code" gorm:"not null;size:10"` - Doctor_Id *uint `json:"doctor_id"` - Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` - SpecimenPickTime *time.Time `json:"specimenPickTime"` - ExaminationDate *time.Time `json:"examinationDate"` - Number uint8 `json:"number"` - Temperature float64 `json:"temperature"` - McuUrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"mcuUrgencyLevel_code" gorm:"not null;size:15"` - Scope_Code *ere.CheckupScopeCode `json:"scope_code" gorm:"index;size:10"` + ecore.Main // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + Status_Code erc.DataStatusCode `json:"status_code" gorm:"not null;size:10"` + Doctor_Id *uint `json:"doctor_id"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` + SpecimenPickTime *time.Time `json:"specimenPickTime"` + ExaminationDate *time.Time `json:"examinationDate"` + Number uint8 `json:"number"` + Temperature float64 `json:"temperature"` + UrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"urgencyLevel_code" gorm:"not null;size:15"` + Scope_Code *ere.CheckupScopeCode `json:"scope_code" gorm:"index;size:10"` } func (d McuOrder) IsCompleted() bool { diff --git a/internal/use-case/main-use-case/mcu-order/helper.go b/internal/use-case/main-use-case/mcu-order/helper.go index 8c7115b6..c7d6fc6f 100644 --- a/internal/use-case/main-use-case/mcu-order/helper.go +++ b/internal/use-case/main-use-case/mcu-order/helper.go @@ -26,6 +26,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.McuOrder) { data.ExaminationDate = inputSrc.ExaminationDate data.Number = inputSrc.Number data.Temperature = inputSrc.Temperature - data.McuUrgencyLevel_Code = inputSrc.McuUrgencyLevel_Code + data.UrgencyLevel_Code = inputSrc.UrgencyLevel_Code data.Doctor_Id = inputSrc.Doctor_Id } From 7e9914998f86fe7d813febfe7c2f556746ad566b Mon Sep 17 00:00:00 2001 From: vanilia Date: Sun, 2 Nov 2025 18:38:08 +0700 Subject: [PATCH 038/329] add rehab --- .../domain/main-entities/encounter/dto.go | 3 + internal/domain/main-entities/rehab/dto.go | 70 +++++ internal/use-case/main-use-case/rehab/case.go | 275 ++++++++++++++++++ .../use-case/main-use-case/rehab/helper.go | 23 ++ internal/use-case/main-use-case/rehab/lib.go | 144 +++++++++ .../main-use-case/rehab/middleware-runner.go | 103 +++++++ .../main-use-case/rehab/middleware.go | 9 + .../use-case/main-use-case/rehab/tycovar.go | 44 +++ 8 files changed, 671 insertions(+) create mode 100644 internal/domain/main-entities/rehab/dto.go create mode 100644 internal/use-case/main-use-case/rehab/case.go create mode 100644 internal/use-case/main-use-case/rehab/helper.go create mode 100644 internal/use-case/main-use-case/rehab/lib.go create mode 100644 internal/use-case/main-use-case/rehab/middleware-runner.go create mode 100644 internal/use-case/main-use-case/rehab/middleware.go create mode 100644 internal/use-case/main-use-case/rehab/tycovar.go diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index 89f12caf..6a716d6e 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -16,6 +16,7 @@ import ( // internal - domain - main-entities evs "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" + eam "simrs-vx/internal/domain/main-entities/ambulatory" ea "simrs-vx/internal/domain/main-entities/appointment" ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/employee" @@ -48,6 +49,8 @@ type CreateDto struct { Appointment_Id *uint `json:"appointment_id"` RefTypeCode ere.RefTypeCode `json:"refTypeCode"` NewStatus bool `json:"newStatus"` + Ambulatory *eam.CreateDto `json:"ambulatory"` + Re pa.AuthInfo } diff --git a/internal/domain/main-entities/rehab/dto.go b/internal/domain/main-entities/rehab/dto.go new file mode 100644 index 00000000..0cec61d8 --- /dev/null +++ b/internal/domain/main-entities/rehab/dto.go @@ -0,0 +1,70 @@ +package rehab + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ed "simrs-vx/internal/domain/main-entities/doctor" +) + +type CreateDto struct { + Encounter_Id *uint `json:"encounter_id"` + Doctor_Id *uint `json:"doctor_id"` + AllocatedVisitCount *int `json:"allocatedVisitCount"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Encounter_Id *uint `json:"encounter-id"` + Doctor_Id *uint `json:"doctor-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 + Encounter_Id *uint `json:"encounter_id"` + Doctor_Id *uint `json:"doctor_id"` + Doctor *ed.Doctor `json:"doctor,omitempty"` + AllocatedVisitCount *int `json:"allocatedVisitCount"` +} + +func (d Rehab) ToResponse() ResponseDto { + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Doctor_Id: d.Doctor_Id, + Doctor: d.Doctor, + AllocatedVisitCount: d.AllocatedVisitCount, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []Rehab) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/use-case/main-use-case/rehab/case.go b/internal/use-case/main-use-case/rehab/case.go new file mode 100644 index 00000000..0d7a243e --- /dev/null +++ b/internal/use-case/main-use-case/rehab/case.go @@ -0,0 +1,275 @@ +package rehab + +import ( + e "simrs-vx/internal/domain/main-entities/rehab" + "strconv" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + "gorm.io/gorm" +) + +const source = "rehab" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.Rehab{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.Rehab + var dataList []e.Rehab + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.Rehab + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.Rehab + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.Rehab + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/rehab/helper.go b/internal/use-case/main-use-case/rehab/helper.go new file mode 100644 index 00000000..5c06ca0a --- /dev/null +++ b/internal/use-case/main-use-case/rehab/helper.go @@ -0,0 +1,23 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package rehab + +import ( + e "simrs-vx/internal/domain/main-entities/rehab" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Rehab) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Encounter_Id = inputSrc.Encounter_Id + data.Doctor_Id = inputSrc.Doctor_Id + data.AllocatedVisitCount = inputSrc.AllocatedVisitCount +} diff --git a/internal/use-case/main-use-case/rehab/lib.go b/internal/use-case/main-use-case/rehab/lib.go new file mode 100644 index 00000000..faee1b35 --- /dev/null +++ b/internal/use-case/main-use-case/rehab/lib.go @@ -0,0 +1,144 @@ +package rehab + +import ( + "errors" + e "simrs-vx/internal/domain/main-entities/rehab" + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Rehab, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.Rehab{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Rehab, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.Rehab{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.Rehab{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Order("\"CreatedAt\" DESC") + + if err := tx.Find(&data).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.Rehab, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.Rehab{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.Rehab, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.Rehab, 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 +} diff --git a/internal/use-case/main-use-case/rehab/middleware-runner.go b/internal/use-case/main-use-case/rehab/middleware-runner.go new file mode 100644 index 00000000..8c0af77a --- /dev/null +++ b/internal/use-case/main-use-case/rehab/middleware-runner.go @@ -0,0 +1,103 @@ +package rehab + +import ( + e "simrs-vx/internal/domain/main-entities/rehab" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.Rehab) 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.Rehab) 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.Rehab) 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.Rehab) 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.Rehab) 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/main-use-case/rehab/middleware.go b/internal/use-case/main-use-case/rehab/middleware.go new file mode 100644 index 00000000..dadf6b9b --- /dev/null +++ b/internal/use-case/main-use-case/rehab/middleware.go @@ -0,0 +1,9 @@ +package rehab + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/rehab/tycovar.go b/internal/use-case/main-use-case/rehab/tycovar.go new file mode 100644 index 00000000..4899ec44 --- /dev/null +++ b/internal/use-case/main-use-case/rehab/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 rehab + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/rehab" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.Rehab, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Rehab, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Rehab, 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 From 616f90096865b24a0930b17c3e2ade01eb255150 Mon Sep 17 00:00:00 2001 From: vanilia Date: Sun, 2 Nov 2025 18:53:35 +0700 Subject: [PATCH 039/329] add rehab --- internal/domain/main-entities/ambulatory/dto.go | 17 ++++++++++------- internal/domain/main-entities/encounter/dto.go | 3 ++- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/internal/domain/main-entities/ambulatory/dto.go b/internal/domain/main-entities/ambulatory/dto.go index 455f7f02..42ece735 100644 --- a/internal/domain/main-entities/ambulatory/dto.go +++ b/internal/domain/main-entities/ambulatory/dto.go @@ -2,13 +2,13 @@ package ambulatory import ( ecore "simrs-vx/internal/domain/base-entities/core" - ee "simrs-vx/internal/domain/main-entities/encounter" ere "simrs-vx/internal/domain/references/encounter" ) type CreateDto struct { - Encounter_Id *uint `json:"encounter_id"` - Class_Code ere.AmbulatoryClassCode `json:"class_code" validate:"maxLength=10"` + Encounter_Id *uint `json:"encounter_id"` + Class_Code ere.AmbulatoryClassCode `json:"class_code" validate:"maxLength=10"` + VisitMode_Code ere.VisitModeCode `json:"visitMode_code"` } type ReadListDto struct { @@ -43,13 +43,16 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty"` - Class_Code ere.AmbulatoryClassCode `json:"class_code"` + Encounter_Id *uint `json:"encounter_id"` + Class_Code ere.AmbulatoryClassCode `json:"class_code"` + VisitMode_Code ere.VisitModeCode `json:"visitMode_code"` } func (d Ambulatory) ToResponse() ResponseDto { - resp := ResponseDto{} + resp := ResponseDto{ + Class_Code: d.Class_Code, + VisitMode_Code: d.VisitMode_Code, + } resp.Main = d.Main return resp } diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index 6a716d6e..d20d53cf 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -22,6 +22,7 @@ import ( ee "simrs-vx/internal/domain/main-entities/employee" eir "simrs-vx/internal/domain/main-entities/internal-reference" ep "simrs-vx/internal/domain/main-entities/patient" + er "simrs-vx/internal/domain/main-entities/rehab/base" es "simrs-vx/internal/domain/main-entities/specialist" ess "simrs-vx/internal/domain/main-entities/subspecialist" eu "simrs-vx/internal/domain/main-entities/unit" @@ -50,7 +51,7 @@ type CreateDto struct { RefTypeCode ere.RefTypeCode `json:"refTypeCode"` NewStatus bool `json:"newStatus"` Ambulatory *eam.CreateDto `json:"ambulatory"` - Re + Rehab *er.Basic `json:"rehab"` pa.AuthInfo } From 32b2b287aacc79bcf650b393314e59deed53c453 Mon Sep 17 00:00:00 2001 From: vanilia Date: Sun, 2 Nov 2025 18:59:30 +0700 Subject: [PATCH 040/329] adjust entity ambulatory and encounter --- .../migrations/20251102115856.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 5 +++-- .../main-entities/ambulatory/base/entity.go | 17 ----------------- internal/domain/main-entities/ambulatory/dto.go | 2 -- .../domain/main-entities/ambulatory/entity.go | 10 ++++++---- .../domain/main-entities/encounter/entity.go | 4 ++-- 6 files changed, 13 insertions(+), 27 deletions(-) create mode 100644 cmd/main-migration/migrations/20251102115856.sql delete mode 100644 internal/domain/main-entities/ambulatory/base/entity.go diff --git a/cmd/main-migration/migrations/20251102115856.sql b/cmd/main-migration/migrations/20251102115856.sql new file mode 100644 index 00000000..1593eb5a --- /dev/null +++ b/cmd/main-migration/migrations/20251102115856.sql @@ -0,0 +1,2 @@ +-- Modify "Ambulatory" table +ALTER TABLE "public"."Ambulatory" DROP CONSTRAINT "fk_Ambulatory_Encounter", ADD CONSTRAINT "fk_Encounter_Ambulatory" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index a851d5ed..9c52a0fc 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:llqBiqOQF+QcCuZSeEWKfRzAd9gN8gE4uGgdKWkfGW4= +h1:eq9RCCa1ej2Ov+qYjL1Pb0AEE3q+W2sHsG2Gg+Qypeg= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -63,4 +63,5 @@ h1:llqBiqOQF+QcCuZSeEWKfRzAd9gN8gE4uGgdKWkfGW4= 20251027075128.sql h1:/iFQBM1sytjqpyQSOx61q33gnorMgxTiFVSuL6bQqsM= 20251027091406.sql h1:eCZGtUkxAzEAqpC9UsGpP8Df9mS0DEOqSl885LgqpvM= 20251031082443.sql h1:ajvi2G8OGvcmB2pJ1SoX/09ALHLWKNh84RSonVhJqAc= -20251031084657.sql h1:rsml3HJP+sXmciMBIkowwkyabKFWuQTci2lDjnf5km0= +20251031084657.sql h1:86mNMS/oMNhewetTvLMFvEz1J6AANePHkE0fOztqHTM= +20251102115856.sql h1:KPtFqdVIsrJq07q/bmyoNMBiZMC5XsQgxi43XmQj1YI= diff --git a/internal/domain/main-entities/ambulatory/base/entity.go b/internal/domain/main-entities/ambulatory/base/entity.go deleted file mode 100644 index 2dced5a2..00000000 --- a/internal/domain/main-entities/ambulatory/base/entity.go +++ /dev/null @@ -1,17 +0,0 @@ -package base - -import ( - ecore "simrs-vx/internal/domain/base-entities/core" - ere "simrs-vx/internal/domain/references/encounter" -) - -type Basic struct { - ecore.Main // adjust this according to the needs - Encounter_Id *uint `json:"encounter_id"` - Class_Code ere.AmbulatoryClassCode `json:"class_code" gorm:"size:10"` - VisitMode_Code ere.VisitModeCode `json:"visitMode_code"` -} - -func (Basic) TableName() string { - return "Ambulatory" -} diff --git a/internal/domain/main-entities/ambulatory/dto.go b/internal/domain/main-entities/ambulatory/dto.go index 455f7f02..9b6bc314 100644 --- a/internal/domain/main-entities/ambulatory/dto.go +++ b/internal/domain/main-entities/ambulatory/dto.go @@ -2,7 +2,6 @@ package ambulatory import ( ecore "simrs-vx/internal/domain/base-entities/core" - ee "simrs-vx/internal/domain/main-entities/encounter" ere "simrs-vx/internal/domain/references/encounter" ) @@ -44,7 +43,6 @@ type MetaDto struct { type ResponseDto struct { ecore.Main Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty"` Class_Code ere.AmbulatoryClassCode `json:"class_code"` } diff --git a/internal/domain/main-entities/ambulatory/entity.go b/internal/domain/main-entities/ambulatory/entity.go index 61117c81..ecf9915e 100644 --- a/internal/domain/main-entities/ambulatory/entity.go +++ b/internal/domain/main-entities/ambulatory/entity.go @@ -1,11 +1,13 @@ package ambulatory import ( - ea "simrs-vx/internal/domain/main-entities/ambulatory/base" - ee "simrs-vx/internal/domain/main-entities/encounter" + ecore "simrs-vx/internal/domain/base-entities/core" + ere "simrs-vx/internal/domain/references/encounter" ) type Ambulatory struct { - ea.Basic - Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + ecore.Main // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Class_Code ere.AmbulatoryClassCode `json:"class_code" gorm:"size:10"` + VisitMode_Code ere.VisitModeCode `json:"visitMode_code"` } diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index 44af72aa..ff116929 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -3,7 +3,7 @@ package encounter import ( ecore "simrs-vx/internal/domain/base-entities/core" evs "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" - eam "simrs-vx/internal/domain/main-entities/ambulatory/base" + eam "simrs-vx/internal/domain/main-entities/ambulatory" ea "simrs-vx/internal/domain/main-entities/appointment" edc "simrs-vx/internal/domain/main-entities/death-cause" ed "simrs-vx/internal/domain/main-entities/doctor" @@ -65,7 +65,7 @@ type Encounter struct { InternalReferences *[]eir.InternalReference `json:"internalReferences,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` DeathCause *edc.DeathCause `json:"deathCause,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` NewStatus bool `json:"newStatus"` - Ambulatory *eam.Basic `json:"ambulatory,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + Ambulatory *eam.Ambulatory `json:"ambulatory,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Emergency *eem.Basic `json:"emergency,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Inpatient *eip.Basic `json:"inpatient,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Rehab *er.Basic `json:"rehab,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` From 16bb34b8b404a3b947f0513d0df7438cc804bfc3 Mon Sep 17 00:00:00 2001 From: vanilia Date: Sun, 2 Nov 2025 20:58:13 +0700 Subject: [PATCH 041/329] add validation for class_code ambulatory --- .../encounter/request-validation.go | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/internal/interface/main-handler/encounter/request-validation.go b/internal/interface/main-handler/encounter/request-validation.go index 025298fc..5963abcb 100644 --- a/internal/interface/main-handler/encounter/request-validation.go +++ b/internal/interface/main-handler/encounter/request-validation.go @@ -63,3 +63,26 @@ func validateRequestCheckIn(w http.ResponseWriter, i e.CheckinDto) (valid bool) return true } + +func validateRequestCreate(w http.ResponseWriter, i e.CreateDto) (valid bool) { + switch { + case i.Class_Code == ere.ECAmbulatory: + if i.Ambulatory == nil { + rw.DataResponse(w, nil, d.FieldError{ + Code: dataValidationFail, + Message: "ambulatory required", + }) + } + } + + if i.Class_Code == ere.ECAmbulatory && i.Ambulatory.Class_Code == ere.ACCRme && i.Ambulatory.VisitMode_Code == ere.VMCAdm { + if *i.Rehab.AllocatedVisitCount == 0 { + rw.DataResponse(w, nil, d.FieldError{ + Code: dataValidationFail, + Message: "rehab.AllocatedVisitCode required", + }) + return + } + } + return +} From 79f5c2c7dbf9ccadf7283b4fc6c83b99584e3a5d Mon Sep 17 00:00:00 2001 From: vanilia Date: Sun, 2 Nov 2025 21:02:49 +0700 Subject: [PATCH 042/329] update dto encounter --- internal/domain/main-entities/encounter/dto.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index d20d53cf..e4b9a521 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -19,7 +19,9 @@ import ( eam "simrs-vx/internal/domain/main-entities/ambulatory" ea "simrs-vx/internal/domain/main-entities/appointment" ed "simrs-vx/internal/domain/main-entities/doctor" + eem "simrs-vx/internal/domain/main-entities/emergency" ee "simrs-vx/internal/domain/main-entities/employee" + ei "simrs-vx/internal/domain/main-entities/inpatient" eir "simrs-vx/internal/domain/main-entities/internal-reference" ep "simrs-vx/internal/domain/main-entities/patient" er "simrs-vx/internal/domain/main-entities/rehab/base" @@ -51,6 +53,8 @@ type CreateDto struct { RefTypeCode ere.RefTypeCode `json:"refTypeCode"` NewStatus bool `json:"newStatus"` Ambulatory *eam.CreateDto `json:"ambulatory"` + Emergency *eem.CreateDto `json:"emergency"` + Inpatient *ei.Inpatient `json:"inpatient"` Rehab *er.Basic `json:"rehab"` pa.AuthInfo From 5f2a871c10c2c77ef6d344b1c0e770c93b866b08 Mon Sep 17 00:00:00 2001 From: vanilia Date: Sun, 2 Nov 2025 21:12:38 +0700 Subject: [PATCH 043/329] adjustment ambulatory, emergency, inpatient entity --- .../migrations/20251102141135.sql | 4 ++++ cmd/main-migration/migrations/atlas.sum | 5 +++-- .../main-entities/emergency/base/entity.go | 16 ---------------- .../domain/main-entities/emergency/dto.go | 7 ++++--- .../domain/main-entities/emergency/entity.go | 9 +++++---- .../domain/main-entities/encounter/entity.go | 8 ++++---- .../main-entities/inpatient/base/entity.go | 19 ------------------- .../domain/main-entities/inpatient/dto.go | 3 --- .../domain/main-entities/inpatient/entity.go | 12 ++++++++---- 9 files changed, 28 insertions(+), 55 deletions(-) create mode 100644 cmd/main-migration/migrations/20251102141135.sql delete mode 100644 internal/domain/main-entities/emergency/base/entity.go delete mode 100644 internal/domain/main-entities/inpatient/base/entity.go diff --git a/cmd/main-migration/migrations/20251102141135.sql b/cmd/main-migration/migrations/20251102141135.sql new file mode 100644 index 00000000..4dafef17 --- /dev/null +++ b/cmd/main-migration/migrations/20251102141135.sql @@ -0,0 +1,4 @@ +-- Modify "Emergency" table +ALTER TABLE "public"."Emergency" DROP CONSTRAINT "fk_Emergency_Encounter", ADD CONSTRAINT "fk_Encounter_Emergency" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "Inpatient" table +ALTER TABLE "public"."Inpatient" DROP CONSTRAINT "fk_Inpatient_Encounter", ADD CONSTRAINT "fk_Encounter_Inpatient" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 9c52a0fc..2c4fb649 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:eq9RCCa1ej2Ov+qYjL1Pb0AEE3q+W2sHsG2Gg+Qypeg= +h1:fy7zM85i70X6PkLcypubf4GA17KSCQpjrSNRRLdWyjM= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -64,4 +64,5 @@ h1:eq9RCCa1ej2Ov+qYjL1Pb0AEE3q+W2sHsG2Gg+Qypeg= 20251027091406.sql h1:eCZGtUkxAzEAqpC9UsGpP8Df9mS0DEOqSl885LgqpvM= 20251031082443.sql h1:ajvi2G8OGvcmB2pJ1SoX/09ALHLWKNh84RSonVhJqAc= 20251031084657.sql h1:86mNMS/oMNhewetTvLMFvEz1J6AANePHkE0fOztqHTM= -20251102115856.sql h1:KPtFqdVIsrJq07q/bmyoNMBiZMC5XsQgxi43XmQj1YI= +20251102115856.sql h1:H1pqgG/uonIc8iHVZVBR2CLg/iRR4alsvC4Rty/GXH8= +20251102141135.sql h1:icypnR4c5x7v6rKZNyhUREh3udLz5iX2yk7yEfRF7xM= diff --git a/internal/domain/main-entities/emergency/base/entity.go b/internal/domain/main-entities/emergency/base/entity.go deleted file mode 100644 index 3ec85f50..00000000 --- a/internal/domain/main-entities/emergency/base/entity.go +++ /dev/null @@ -1,16 +0,0 @@ -package base - -import ( - ecore "simrs-vx/internal/domain/base-entities/core" - ere "simrs-vx/internal/domain/references/encounter" -) - -type Basic struct { - ecore.Main // adjust this according to the needs - Encounter_Id *uint `json:"encounter_id"` - Class_Code ere.EmergencyClassCode `json:"class_code" gorm:"size:10"` -} - -func (Basic) TableName() string { - return "Emergency" -} diff --git a/internal/domain/main-entities/emergency/dto.go b/internal/domain/main-entities/emergency/dto.go index 99628b88..45aa9955 100644 --- a/internal/domain/main-entities/emergency/dto.go +++ b/internal/domain/main-entities/emergency/dto.go @@ -2,7 +2,6 @@ package emergency import ( ecore "simrs-vx/internal/domain/base-entities/core" - ee "simrs-vx/internal/domain/main-entities/encounter" ere "simrs-vx/internal/domain/references/encounter" ) @@ -44,12 +43,14 @@ type MetaDto struct { type ResponseDto struct { ecore.Main Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty"` Class_Code ere.EmergencyClassCode `json:"class_code"` } func (d Emergency) ToResponse() ResponseDto { - resp := ResponseDto{} + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Class_Code: d.Class_Code, + } resp.Main = d.Main return resp } diff --git a/internal/domain/main-entities/emergency/entity.go b/internal/domain/main-entities/emergency/entity.go index 475a02ca..655a441d 100644 --- a/internal/domain/main-entities/emergency/entity.go +++ b/internal/domain/main-entities/emergency/entity.go @@ -1,11 +1,12 @@ package emergency import ( - eeb "simrs-vx/internal/domain/main-entities/emergency/base" - ee "simrs-vx/internal/domain/main-entities/encounter" + ecore "simrs-vx/internal/domain/base-entities/core" + ere "simrs-vx/internal/domain/references/encounter" ) type Emergency struct { - eeb.Basic - Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + ecore.Main // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Class_Code ere.EmergencyClassCode `json:"class_code" gorm:"size:10"` } diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index ff116929..5e950def 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -7,9 +7,9 @@ import ( ea "simrs-vx/internal/domain/main-entities/appointment" edc "simrs-vx/internal/domain/main-entities/death-cause" ed "simrs-vx/internal/domain/main-entities/doctor" - eem "simrs-vx/internal/domain/main-entities/emergency/base" + eem "simrs-vx/internal/domain/main-entities/emergency" ee "simrs-vx/internal/domain/main-entities/employee" - eip "simrs-vx/internal/domain/main-entities/inpatient/base" + eip "simrs-vx/internal/domain/main-entities/inpatient" ei "simrs-vx/internal/domain/main-entities/insurance-company" eir "simrs-vx/internal/domain/main-entities/internal-reference" ep "simrs-vx/internal/domain/main-entities/patient" @@ -66,8 +66,8 @@ type Encounter struct { DeathCause *edc.DeathCause `json:"deathCause,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` NewStatus bool `json:"newStatus"` Ambulatory *eam.Ambulatory `json:"ambulatory,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Emergency *eem.Basic `json:"emergency,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Inpatient *eip.Basic `json:"inpatient,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + Emergency *eem.Emergency `json:"emergency,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + Inpatient *eip.Inpatient `json:"inpatient,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Rehab *er.Basic `json:"rehab,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` } diff --git a/internal/domain/main-entities/inpatient/base/entity.go b/internal/domain/main-entities/inpatient/base/entity.go deleted file mode 100644 index 1f4a94f4..00000000 --- a/internal/domain/main-entities/inpatient/base/entity.go +++ /dev/null @@ -1,19 +0,0 @@ -package base - -import ( - ecore "simrs-vx/internal/domain/base-entities/core" - ei "simrs-vx/internal/domain/main-entities/infra" - ere "simrs-vx/internal/domain/references/encounter" -) - -type Basic struct { - ecore.Main // adjust this according to the needs - Encounter_Id *uint `json:"encounter_id"` - Class_Code ere.InpatientClassCode `json:"class_code" gorm:"size:10"` - Infra_Id *uint16 `json:"infra_id"` - Infra *ei.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Id;references:Id"` -} - -func (Basic) TableName() string { - return "Inpatient" -} diff --git a/internal/domain/main-entities/inpatient/dto.go b/internal/domain/main-entities/inpatient/dto.go index d92232dd..11a864eb 100644 --- a/internal/domain/main-entities/inpatient/dto.go +++ b/internal/domain/main-entities/inpatient/dto.go @@ -2,7 +2,6 @@ package inpatient import ( ecore "simrs-vx/internal/domain/base-entities/core" - ee "simrs-vx/internal/domain/main-entities/encounter" ei "simrs-vx/internal/domain/main-entities/infra" ere "simrs-vx/internal/domain/references/encounter" @@ -48,7 +47,6 @@ type MetaDto struct { type ResponseDto struct { ecore.Main Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty"` Class_Code ere.InpatientClassCode `json:"class_code"` Infra_Id *uint16 `json:"infra_id"` Infra *ei.Infra `json:"infra,omitempty"` @@ -57,7 +55,6 @@ type ResponseDto struct { func (d Inpatient) ToResponse() ResponseDto { resp := ResponseDto{ Encounter_Id: d.Encounter_Id, - Encounter: d.Encounter, Class_Code: d.Class_Code, Infra_Id: d.Infra_Id, Infra: d.Infra, diff --git a/internal/domain/main-entities/inpatient/entity.go b/internal/domain/main-entities/inpatient/entity.go index e88e7fa0..f88eb2fb 100644 --- a/internal/domain/main-entities/inpatient/entity.go +++ b/internal/domain/main-entities/inpatient/entity.go @@ -1,11 +1,15 @@ package inpatient import ( - ee "simrs-vx/internal/domain/main-entities/encounter" - eb "simrs-vx/internal/domain/main-entities/inpatient/base" + ecore "simrs-vx/internal/domain/base-entities/core" + ei "simrs-vx/internal/domain/main-entities/infra" + ere "simrs-vx/internal/domain/references/encounter" ) type Inpatient struct { - eb.Basic - Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + ecore.Main // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Class_Code ere.InpatientClassCode `json:"class_code" gorm:"size:10"` + Infra_Id *uint16 `json:"infra_id"` + Infra *ei.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Id;references:Id"` } From 149253b00f19507e9319568a89efc80548d13529 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Sun, 2 Nov 2025 22:16:02 +0700 Subject: [PATCH 044/329] feat/trx-orders: fixes + renamed a column on table McuOrderItem +migration --- cmd/main-migration/migrations/20251102091932.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 5 +++-- internal/domain/main-entities/mcu-order-item/dto.go | 4 ++-- internal/use-case/main-use-case/mcu-order-item/lib.go | 4 ++-- 4 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 cmd/main-migration/migrations/20251102091932.sql diff --git a/cmd/main-migration/migrations/20251102091932.sql b/cmd/main-migration/migrations/20251102091932.sql new file mode 100644 index 00000000..f10eadd3 --- /dev/null +++ b/cmd/main-migration/migrations/20251102091932.sql @@ -0,0 +1,2 @@ +-- Rename a column from "McuUrgencyLevel_Code" to "UrgencyLevel_Code" +ALTER TABLE "public"."McuOrder" RENAME COLUMN "McuUrgencyLevel_Code" TO "UrgencyLevel_Code"; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 73107582..5162b628 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:ewCVlZr73Pj7qD/A+J5/yF94CncwZCb6s8VSHl0Hawo= +h1:A+ajQZrPn+BR8s8J5tX9DrfLEzZbstFw0klWQiK5Nao= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -62,4 +62,5 @@ h1:ewCVlZr73Pj7qD/A+J5/yF94CncwZCb6s8VSHl0Hawo= 20251025013609.sql h1:evPJaTD8WxYRMOJZHkSr7ONLx9PYxT+ankzQt9c/sJ0= 20251027075128.sql h1:/iFQBM1sytjqpyQSOx61q33gnorMgxTiFVSuL6bQqsM= 20251027091406.sql h1:eCZGtUkxAzEAqpC9UsGpP8Df9mS0DEOqSl885LgqpvM= -20251102002037.sql h1:FTJ9KdTOhso+wNbDoEtvj3D8XkgT6blu79JucGQoprg= +20251102002037.sql h1:lFJbuoZ2LMQnUNGdcwHVY3Xlfslgzu9t2WByT8yfOZI= +20251102091932.sql h1:QfMos5PVRvCsA427b505VSKxoFERhxx07DcP4WhSd7U= diff --git a/internal/domain/main-entities/mcu-order-item/dto.go b/internal/domain/main-entities/mcu-order-item/dto.go index 64e56a85..75e02184 100644 --- a/internal/domain/main-entities/mcu-order-item/dto.go +++ b/internal/domain/main-entities/mcu-order-item/dto.go @@ -23,8 +23,8 @@ type ReadListDto struct { } type FilterDto struct { - McuOrder_Id *uint `json:"mcuOrder-id"` - McuSrc_Id *uint `json:"mcuSrc-id"` + McuOrder_Id *uint `json:"mcu-order-id"` + McuSrc_Id *uint `json:"mcu-src-id"` Result *string `json:"result"` Status_Code erc.DataStatusCode `json:"status-code"` } diff --git a/internal/use-case/main-use-case/mcu-order-item/lib.go b/internal/use-case/main-use-case/mcu-order-item/lib.go index 13030ce8..4b5bb04f 100644 --- a/internal/use-case/main-use-case/mcu-order-item/lib.go +++ b/internal/use-case/main-use-case/mcu-order-item/lib.go @@ -24,10 +24,10 @@ func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.McuOrde deletedData := e.McuOrderItem{} tx.Unscoped(). - Where("\"McuOrder_Id\" = ? AND \"McuSrc_Id\" = ?", input.McuOrder_Id, input.McuSrc_Id). + Where("\"McuOrder_Id\" = ? AND \"McuSrc_Id\" = ?", *input.McuOrder_Id, input.McuSrc_Id). First(&deletedData) if deletedData.Id != 0 { - if err := tx.Model(e.McuOrderItem{}).Where("Id = ?", deletedData.Id).Update("DeletedAt", nil).Error; err != nil { + if err := tx.Unscoped().Model(e.McuOrderItem{}).Where("\"Id\" = ?", deletedData.Id).Update("\"DeletedAt\"", nil).Error; err != nil { return nil, plh.HandleCreateError(input, event, err) } return &deletedData, nil From 388072ef517e064521afcda4bb3b7701e627a0fe Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Mon, 3 Nov 2025 08:03:09 +0700 Subject: [PATCH 045/329] feat/trx-order: ref changes for MCU --- .../domain/main-entities/mcu-order/dto.go | 1 + .../domain/main-entities/mcu-order/entity.go | 3 +-- .../main-entities/mcu-src-category/dto.go | 22 +++++++++---------- .../main-entities/mcu-src-category/entity.go | 10 ++++----- .../domain/references/clinical/clinical.go | 6 +++++ .../domain/references/encounter/encounter.go | 6 ----- .../main-use-case/mcu-order/helper.go | 1 + 7 files changed, 25 insertions(+), 24 deletions(-) diff --git a/internal/domain/main-entities/mcu-order/dto.go b/internal/domain/main-entities/mcu-order/dto.go index 3d042c2f..e63a3e08 100644 --- a/internal/domain/main-entities/mcu-order/dto.go +++ b/internal/domain/main-entities/mcu-order/dto.go @@ -28,6 +28,7 @@ type CreateDto struct { Number uint8 `json:"number"` Temperature float64 `json:"temperature"` UrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"urgencyLevel_code"` + Scope_Code ercl.McuScopeCode `json:"scope_code"` pa.AuthInfo } diff --git a/internal/domain/main-entities/mcu-order/entity.go b/internal/domain/main-entities/mcu-order/entity.go index d2b81e58..bf4e2e77 100644 --- a/internal/domain/main-entities/mcu-order/entity.go +++ b/internal/domain/main-entities/mcu-order/entity.go @@ -8,7 +8,6 @@ import ( ercl "simrs-vx/internal/domain/references/clinical" erc "simrs-vx/internal/domain/references/common" - ere "simrs-vx/internal/domain/references/encounter" ) type McuOrder struct { @@ -23,7 +22,7 @@ type McuOrder struct { Number uint8 `json:"number"` Temperature float64 `json:"temperature"` UrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"urgencyLevel_code" gorm:"not null;size:15"` - Scope_Code *ere.CheckupScopeCode `json:"scope_code" gorm:"index;size:10"` + Scope_Code ercl.McuScopeCode `json:"scope_code" gorm:"index;size:10"` } func (d McuOrder) IsCompleted() bool { diff --git a/internal/domain/main-entities/mcu-src-category/dto.go b/internal/domain/main-entities/mcu-src-category/dto.go index 278c5e5c..c1988790 100644 --- a/internal/domain/main-entities/mcu-src-category/dto.go +++ b/internal/domain/main-entities/mcu-src-category/dto.go @@ -3,13 +3,13 @@ package division import ( ecore "simrs-vx/internal/domain/base-entities/core" - ere "simrs-vx/internal/domain/references/encounter" + erc "simrs-vx/internal/domain/references/clinical" ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=20"` - Name string `json:"name" validate:"maxLength=50"` - Scope_Code *ere.CheckupScopeCode `json:"scope_code" validate:"maxLength=10"` + Code string `json:"code" validate:"maxLength=20"` + Name string `json:"name" validate:"maxLength=50"` + Scope_Code erc.McuScopeCode `json:"scope_code" validate:"maxLength=10"` } type ReadListDto struct { @@ -20,10 +20,10 @@ type ReadListDto struct { } type FilterDto struct { - Code string `json:"code"` - Name string `json:"name"` - Scope_Code *ere.CheckupScopeCode `json:"scope-code"` - Search string `json:"search" gormhelper:"searchColumns=Code,Name"` + Code string `json:"code"` + Name string `json:"name"` + Scope_Code *erc.McuScopeCode `json:"scope-code"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` } type ReadDetailDto struct { @@ -48,9 +48,9 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain - Code string `json:"code"` - Name string `json:"name"` - Scope_Code *ere.CheckupScopeCode `json:"scope_code"` + Code string `json:"code"` + Name string `json:"name"` + Scope_Code erc.McuScopeCode `json:"scope_code"` } func (d McuSrcCategory) ToResponse() ResponseDto { diff --git a/internal/domain/main-entities/mcu-src-category/entity.go b/internal/domain/main-entities/mcu-src-category/entity.go index 3a0d08ca..8fc801b9 100644 --- a/internal/domain/main-entities/mcu-src-category/entity.go +++ b/internal/domain/main-entities/mcu-src-category/entity.go @@ -2,12 +2,12 @@ package division import ( ecore "simrs-vx/internal/domain/base-entities/core" - ere "simrs-vx/internal/domain/references/encounter" + erc "simrs-vx/internal/domain/references/clinical" ) type McuSrcCategory struct { - ecore.SmallMain // adjust this according to the needs - Code string `json:"code" gorm:"unique;size:20"` - Name string `json:"name" gorm:"size:50"` - Scope_Code *ere.CheckupScopeCode `json:"scope_code" gorm:"index;size:10"` + ecore.SmallMain // adjust this according to the needs + Code string `json:"code" gorm:"unique;size:20"` + Name string `json:"name" gorm:"size:50"` + Scope_Code erc.McuScopeCode `json:"scope_code" gorm:"index;size:10"` } diff --git a/internal/domain/references/clinical/clinical.go b/internal/domain/references/clinical/clinical.go index c0eb3594..9b2af591 100644 --- a/internal/domain/references/clinical/clinical.go +++ b/internal/domain/references/clinical/clinical.go @@ -9,6 +9,7 @@ type ( InstructionCode string HeadToToeCode string McuUrgencyLevelCode string + McuScopeCode string SoapiTypeCode string MedicalAction string VehicleTypeCode string @@ -113,6 +114,11 @@ const ( MULCPF McuUrgencyLevelCode = "priority-form" // Form Prioritas MULCRT McuUrgencyLevelCode = "routine" // Pemeriksaan Rutin + MSCRad McuScopeCode = "rad" // Pemeriksaan Rutin + MSCCpLab McuScopeCode = "cp-lab" // Pemeriksaan Rutin + MSCApLab McuScopeCode = "ap-lab" // Pemeriksaan Rutin + MSCMicLab McuScopeCode = "mic-lab" // Pemeriksaan Rutin + STCEarlyNurse SoapiTypeCode = "early-nurse" // Kajian Awal Medis STCEEarlyMedic SoapiTypeCode = "early-medic" // Kajian Awal Rehab Medis STCEarlyRehab SoapiTypeCode = "early-rehab" // Kajian Awal Rehab Medik diff --git a/internal/domain/references/encounter/encounter.go b/internal/domain/references/encounter/encounter.go index eeccb8fe..c2d150be 100644 --- a/internal/domain/references/encounter/encounter.go +++ b/internal/domain/references/encounter/encounter.go @@ -8,7 +8,6 @@ type ( PersonConditionCode string EmergencyClassCode string OutpatientClassCode string - CheckupScopeCode string AmbulatoryClassCode string InpatientClassCode string UploadCode string @@ -64,11 +63,6 @@ const ( OCCHcu OutpatientClassCode = "hcu" // HCU OCCVk OutpatientClassCode = "vk" // Verlos kamer - CSCLab CheckupScopeCode = "lab" // Laboratorium - CSCMLab CheckupScopeCode = "mic-lab" // Microbacterial Laboratorium - CSCPLab CheckupScopeCode = "pa-lab" // Patology Anatomy Laboratorium - CSCRad CheckupScopeCode = "radiology" // Radiology - ACCReg AmbulatoryClassCode = "reg" // Regular ACCRme AmbulatoryClassCode = "rme" // Rehab Medik ACCCad AmbulatoryClassCode = "chemo-adm" // Chemotherapy diff --git a/internal/use-case/main-use-case/mcu-order/helper.go b/internal/use-case/main-use-case/mcu-order/helper.go index c7d6fc6f..7c21f1f6 100644 --- a/internal/use-case/main-use-case/mcu-order/helper.go +++ b/internal/use-case/main-use-case/mcu-order/helper.go @@ -28,4 +28,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.McuOrder) { data.Temperature = inputSrc.Temperature data.UrgencyLevel_Code = inputSrc.UrgencyLevel_Code data.Doctor_Id = inputSrc.Doctor_Id + data.Scope_Code = inputSrc.Scope_Code } From 9c39966bea1b2d6dac1fa31e6525b638fce021c1 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Mon, 3 Nov 2025 14:57:04 +0700 Subject: [PATCH 046/329] dev: hotfix, adjust auth's attributes --- internal/lib/auth/tycovar.go | 14 ++++++------ .../main-use-case/authentication/case.go | 22 +++++++++++++------ 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/internal/lib/auth/tycovar.go b/internal/lib/auth/tycovar.go index 881a9072..44426d4b 100644 --- a/internal/lib/auth/tycovar.go +++ b/internal/lib/auth/tycovar.go @@ -13,13 +13,13 @@ type AuthInfo struct { User_Name string User_ContractPosition_code string Employee_Position_Code *string - Employee_Id *int - Doctor_Id *int - Nurse_Id *int - Midwife_Id *int - Nutritionist_Id *int - Laborant_Id *int - Pharmachist_Id *int + Employee_Id *uint + Doctor_Id *uint + Nurse_Id *uint + Midwife_Id *uint + Nutritionist_Id *uint + Laborant_Id *uint + Pharmachist_Id *uint Intern_Position_Code *string Roles []string // User_DivisionPositions []DivisionPosition diff --git a/internal/use-case/main-use-case/authentication/case.go b/internal/use-case/main-use-case/authentication/case.go index 6c645208..d00889ee 100644 --- a/internal/use-case/main-use-case/authentication/case.go +++ b/internal/use-case/main-use-case/authentication/case.go @@ -308,14 +308,14 @@ func ExtractToken(r *http.Request, tokenType TokenType) (data *pa.AuthInfo, err data.User_ContractPosition_code = checkStrClaims(claims, "contractPosition_code") data.Employee_Position_Code = checkStrPtrClaims(claims, "employee_position_code") - data.Doctor_Id = checkIntPtrClaims(claims, "doctor_id") - data.Nurse_Id = checkIntPtrClaims(claims, "nurse_id") - data.Midwife_Id = checkIntPtrClaims(claims, "midwife_id") - data.Nutritionist_Id = checkIntPtrClaims(claims, "nutritionist_id") - data.Laborant_Id = checkIntPtrClaims(claims, "laborant_id") - data.Pharmachist_Id = checkIntPtrClaims(claims, "pharmachist_id") + data.Doctor_Id = checkUntPtrClaims(claims, "doctor_id") + data.Nurse_Id = checkUntPtrClaims(claims, "nurse_id") + data.Midwife_Id = checkUntPtrClaims(claims, "midwife_id") + data.Nutritionist_Id = checkUntPtrClaims(claims, "nutritionist_id") + data.Laborant_Id = checkUntPtrClaims(claims, "laborant_id") + data.Pharmachist_Id = checkUntPtrClaims(claims, "pharmachist_id") data.Intern_Position_Code = checkStrPtrClaims(claims, "intern_position_code") - data.Employee_Id = checkIntPtrClaims(claims, "employee_id") + data.Employee_Id = checkUntPtrClaims(claims, "employee_id") return } return nil, d.FieldError{Code: "token", Message: "token-invalid"} @@ -354,3 +354,11 @@ func checkIntPtrClaims(claim map[string]interface{}, key string) *int { } return nil } + +func checkUntPtrClaims(claim map[string]interface{}, key string) *uint { + if v, exist := claim[key]; exist && v != nil { + val := uint(v.(float64)) + return &val + } + return nil +} From 8e35aafca2450e0398b3ec32245374f46ed03d38 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Mon, 3 Nov 2025 14:59:03 +0700 Subject: [PATCH 047/329] feat/trx-orders: changed set value for Doctor_Id and the setData --- internal/use-case/main-use-case/prescription/helper.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/use-case/main-use-case/prescription/helper.go b/internal/use-case/main-use-case/prescription/helper.go index 8b85884a..35c55512 100644 --- a/internal/use-case/main-use-case/prescription/helper.go +++ b/internal/use-case/main-use-case/prescription/helper.go @@ -37,7 +37,8 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Prescription) { } data.Encounter_Id = inputSrc.Encounter_Id - data.Doctor_Id = inputSrc.Doctor_Id + // data.Doctor_Id = inputSrc.Doctor_Id + data.Doctor_Id = inputSrc.AuthInfo.Doctor_Id data.IssuedAt = inputSrc.IssuedAt } From 474939278833d00efa47dc227eb76d882aa45dee Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 3 Nov 2025 15:17:11 +0700 Subject: [PATCH 048/329] add control-letter --- .../migrations/20251103081637.sql | 17 +++ cmd/main-migration/migrations/atlas.sum | 5 +- .../main-entities/control-letter/dto.go | 104 ++++++++++++++++++ .../main-entities/control-letter/entity.go | 24 ++++ internal/interface/migration/main-entities.go | 2 + 5 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 cmd/main-migration/migrations/20251103081637.sql create mode 100644 internal/domain/main-entities/control-letter/dto.go create mode 100644 internal/domain/main-entities/control-letter/entity.go diff --git a/cmd/main-migration/migrations/20251103081637.sql b/cmd/main-migration/migrations/20251103081637.sql new file mode 100644 index 00000000..ca898d90 --- /dev/null +++ b/cmd/main-migration/migrations/20251103081637.sql @@ -0,0 +1,17 @@ +-- Create "ControlLetter" table +CREATE TABLE "public"."ControlLetter" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Unit_Id" bigint NULL, + "Specialist_Id" bigint NULL, + "Subspecialist_Id" bigint NULL, + "Date" timestamptz NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_ControlLetter_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_ControlLetter_Specialist" FOREIGN KEY ("Specialist_Id") REFERENCES "public"."Specialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_ControlLetter_Subspecialist" FOREIGN KEY ("Subspecialist_Id") REFERENCES "public"."Subspecialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_ControlLetter_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 5162b628..b5785611 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:A+ajQZrPn+BR8s8J5tX9DrfLEzZbstFw0klWQiK5Nao= +h1:zJVjtCkiWEF41JV7lzbRtI5mPZGz5bC8FaVruh3fmkY= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -63,4 +63,5 @@ h1:A+ajQZrPn+BR8s8J5tX9DrfLEzZbstFw0klWQiK5Nao= 20251027075128.sql h1:/iFQBM1sytjqpyQSOx61q33gnorMgxTiFVSuL6bQqsM= 20251027091406.sql h1:eCZGtUkxAzEAqpC9UsGpP8Df9mS0DEOqSl885LgqpvM= 20251102002037.sql h1:lFJbuoZ2LMQnUNGdcwHVY3Xlfslgzu9t2WByT8yfOZI= -20251102091932.sql h1:QfMos5PVRvCsA427b505VSKxoFERhxx07DcP4WhSd7U= +20251102091932.sql h1:rmdhb5m+P+fU8jROBZNyeYgZKuQvucsuljXv4ZVzvks= +20251103081637.sql h1:jqpMnygFceOJn0rI30GYWI2CKbOu6RzVqw2/Pji2Ka8= diff --git a/internal/domain/main-entities/control-letter/dto.go b/internal/domain/main-entities/control-letter/dto.go new file mode 100644 index 00000000..270ff7b5 --- /dev/null +++ b/internal/domain/main-entities/control-letter/dto.go @@ -0,0 +1,104 @@ +package controlletter + +import ( + // std + "time" + + // internal - lib + pa "simrs-vx/internal/lib/auth" + + // internal - domain - base-entities + ecore "simrs-vx/internal/domain/base-entities/core" + + // internal - domain - main-entities + + ee "simrs-vx/internal/domain/main-entities/encounter" + es "simrs-vx/internal/domain/main-entities/specialist" + ess "simrs-vx/internal/domain/main-entities/subspecialist" + eu "simrs-vx/internal/domain/main-entities/unit" +) + +type CreateDto struct { + Encounter_Id *uint `json:"encounter_id"` + Unit_Id *uint `json:"unit_id"` + Specialist_Id *uint `json:"specialist_id"` + Subspecialist_Id *uint `json:"subspecialist_id"` + Date *time.Time `json:"date"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Encounter_Id *uint `json:"encounter-id"` + Unit_Id *uint `json:"unit-id"` + Specialist_Id *uint `json:"specialist-id"` + Subspecialist_Id *uint `json:"subspecialist-id"` + Date *time.Time `json:"date"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` +} + +type ReplyDto struct { + Id uint `json:"id"` + Solution *string `json:"solution"` + + pa.AuthInfo +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter" gorm:"foreignKey:Encounter_Id;references:Id"` + Unit_Id *uint `json:"unit_id"` + Unit *eu.Unit `json:"unit" gorm:"foreignKey:Unit_Id;references:Id"` + Specialist_Id *uint `json:"specialist_id"` + Specialist *es.Specialist `json:"specialist" gorm:"foreignKey:Specialist_Id;references:Id"` + Subspecialist_Id *uint `json:"subspecialist_id"` + Subspecialist *ess.Subspecialist `json:"subspecialist" gorm:"foreignKey:Subspecialist_Id;references:Id"` + Date *time.Time `json:"date"` +} + +func (d ControlLetter) ToResponse() ResponseDto { + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Encounter: d.Encounter, + Unit_Id: d.Unit_Id, + Unit: d.Unit, + Specialist_Id: d.Specialist_Id, + Specialist: d.Specialist, + Subspecialist_Id: d.Subspecialist_Id, + Subspecialist: d.Subspecialist, + Date: d.Date, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []ControlLetter) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/control-letter/entity.go b/internal/domain/main-entities/control-letter/entity.go new file mode 100644 index 00000000..9cf74a68 --- /dev/null +++ b/internal/domain/main-entities/control-letter/entity.go @@ -0,0 +1,24 @@ +package controlletter + +import ( + "time" + + ecore "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/encounter" + es "simrs-vx/internal/domain/main-entities/specialist" + ess "simrs-vx/internal/domain/main-entities/subspecialist" + eu "simrs-vx/internal/domain/main-entities/unit" +) + +type ControlLetter struct { + ecore.Main // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter" gorm:"foreignKey:Encounter_Id;references:Id"` + Unit_Id *uint `json:"unit_id"` + Unit *eu.Unit `json:"unit" gorm:"foreignKey:Unit_Id;references:Id"` + Specialist_Id *uint `json:"specialist_id"` + Specialist *es.Specialist `json:"specialist" gorm:"foreignKey:Specialist_Id;references:Id"` + Subspecialist_Id *uint `json:"subspecialist_id"` + Subspecialist *ess.Subspecialist `json:"subspecialist" gorm:"foreignKey:Subspecialist_Id;references:Id"` + Date *time.Time `json:"date"` +} diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index 6507202e..28fd0376 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -8,6 +8,7 @@ import ( appointment "simrs-vx/internal/domain/main-entities/appointment" chemo "simrs-vx/internal/domain/main-entities/chemo" consultation "simrs-vx/internal/domain/main-entities/consultation" + controlletter "simrs-vx/internal/domain/main-entities/control-letter" counter "simrs-vx/internal/domain/main-entities/counter" deathcause "simrs-vx/internal/domain/main-entities/death-cause" device "simrs-vx/internal/domain/main-entities/device" @@ -193,5 +194,6 @@ func getMainEntities() []any { &responsibledoctorhist.ResponsibleDoctorHist{}, &admemployeehist.AdmEmployeeHist{}, &vclaimmember.VclaimMember{}, + &controlletter.ControlLetter{}, } } From ec877d73c23fafd19023c0d90fd310bab5fe42cd Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 3 Nov 2025 15:44:03 +0700 Subject: [PATCH 049/329] feat (control-letter): add crud, renaming sync directory --- .../main-entities/control-letter/dto.go | 11 +- .../main-handler/consultation/handler.go | 2 +- .../main-handler/control-letter/handler.go | 71 +++++ .../interface/main-handler/main-handler.go | 2 + .../.keep | 0 .../main-use-case/control-letter/case.go | 299 ++++++++++++++++++ .../main-use-case/control-letter/helper.go | 25 ++ .../main-use-case/control-letter/lib.go | 144 +++++++++ .../control-letter/middleware-runner.go | 103 ++++++ .../control-letter/middleware.go | 9 + .../main-use-case/control-letter/tycovar.go | 44 +++ .../.keep | 0 pkg/use-case-helper/use-case-helper.go | 7 + 13 files changed, 711 insertions(+), 6 deletions(-) create mode 100644 internal/interface/main-handler/control-letter/handler.go rename internal/use-case/{main-sync-case => main-sync-use-case}/.keep (100%) create mode 100644 internal/use-case/main-use-case/control-letter/case.go create mode 100644 internal/use-case/main-use-case/control-letter/helper.go create mode 100644 internal/use-case/main-use-case/control-letter/lib.go create mode 100644 internal/use-case/main-use-case/control-letter/middleware-runner.go create mode 100644 internal/use-case/main-use-case/control-letter/middleware.go create mode 100644 internal/use-case/main-use-case/control-letter/tycovar.go rename internal/use-case/{simgos-sync-case => simgos-sync-use-case}/.keep (100%) diff --git a/internal/domain/main-entities/control-letter/dto.go b/internal/domain/main-entities/control-letter/dto.go index 270ff7b5..4beadd69 100644 --- a/internal/domain/main-entities/control-letter/dto.go +++ b/internal/domain/main-entities/control-letter/dto.go @@ -41,7 +41,8 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id uint16 `json:"id"` + Includes string `json:"includes"` } type UpdateDto struct { @@ -69,13 +70,13 @@ type MetaDto struct { type ResponseDto struct { ecore.Main Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter" gorm:"foreignKey:Encounter_Id;references:Id"` + Encounter *ee.Encounter `json:"encounter,omitempty"` Unit_Id *uint `json:"unit_id"` - Unit *eu.Unit `json:"unit" gorm:"foreignKey:Unit_Id;references:Id"` + Unit *eu.Unit `json:"unit,omitempty"` Specialist_Id *uint `json:"specialist_id"` - Specialist *es.Specialist `json:"specialist" gorm:"foreignKey:Specialist_Id;references:Id"` + Specialist *es.Specialist `json:"specialist,omitempty"` Subspecialist_Id *uint `json:"subspecialist_id"` - Subspecialist *ess.Subspecialist `json:"subspecialist" gorm:"foreignKey:Subspecialist_Id;references:Id"` + Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty"` Date *time.Time `json:"date"` } diff --git a/internal/interface/main-handler/consultation/handler.go b/internal/interface/main-handler/consultation/handler.go index 2810d2f3..e67accd4 100644 --- a/internal/interface/main-handler/consultation/handler.go +++ b/internal/interface/main-handler/consultation/handler.go @@ -1,4 +1,4 @@ -package device +package consultation import ( "net/http" diff --git a/internal/interface/main-handler/control-letter/handler.go b/internal/interface/main-handler/control-letter/handler.go new file mode 100644 index 00000000..d6a73fe0 --- /dev/null +++ b/internal/interface/main-handler/control-letter/handler.go @@ -0,0 +1,71 @@ +package controlletter + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/control-letter" + u "simrs-vx/internal/use-case/main-use-case/control-letter" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint16(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint(id) + 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/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index bedf3b71..baea92da 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -10,6 +10,7 @@ import ( auth "simrs-vx/internal/interface/main-handler/authentication" chemo "simrs-vx/internal/interface/main-handler/chemo" consultation "simrs-vx/internal/interface/main-handler/consultation" + controlletter "simrs-vx/internal/interface/main-handler/control-letter" counter "simrs-vx/internal/interface/main-handler/counter" deviceorder "simrs-vx/internal/interface/main-handler/device-order" deviceorderitem "simrs-vx/internal/interface/main-handler/device-order-item" @@ -251,6 +252,7 @@ func SetRoutes() http.Handler { "PATCH /{id}/reject": chemo.O.Reject, }) + hc.RegCrud(r, "/v1/control-letter", controlletter.O) hc.RegCrud(r, "/v1/internal-reference", internalreference.O) hc.RegCrud(r, "/v1/ambulance-transport-req", ambulancetransportrequest.O) hc.RegCrud(r, "/v1/responsible-doctor-hist", responsibledoctorhist.O) diff --git a/internal/use-case/main-sync-case/.keep b/internal/use-case/main-sync-use-case/.keep similarity index 100% rename from internal/use-case/main-sync-case/.keep rename to internal/use-case/main-sync-use-case/.keep diff --git a/internal/use-case/main-use-case/control-letter/case.go b/internal/use-case/main-use-case/control-letter/case.go new file mode 100644 index 00000000..7ff38a63 --- /dev/null +++ b/internal/use-case/main-use-case/control-letter/case.go @@ -0,0 +1,299 @@ +package controlletter + +import ( + "errors" + "strconv" + + e "simrs-vx/internal/domain/main-entities/control-letter" + ue "simrs-vx/internal/use-case/main-use-case/encounter" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "control-letter" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.ControlLetter{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 pu.IsDateBeforeNow(input.Date) { + return errors.New("date is in the past") + } + + // check if encounter is done + if ue.IsDone(*input.Encounter_Id, &event, tx) { + return errors.New("encounter is already done") + } + + 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.ControlLetter + var dataList []e.ControlLetter + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.ControlLetter + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + } + + input.Includes = "encounter,unit,specialist,subspecialist" + + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + var data *e.ControlLetter + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 pu.IsDateBeforeNow(input.Date) { + return errors.New("date is in the past") + } + + // check if encounter is done + if ue.IsDone(*input.Encounter_Id, &event, tx) { + return errors.New("encounter is already done") + } + + if err := UpdateData(input, data, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + var data *e.ControlLetter + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/control-letter/helper.go b/internal/use-case/main-use-case/control-letter/helper.go new file mode 100644 index 00000000..9b1d3b23 --- /dev/null +++ b/internal/use-case/main-use-case/control-letter/helper.go @@ -0,0 +1,25 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package controlletter + +import ( + e "simrs-vx/internal/domain/main-entities/control-letter" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.ControlLetter) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Encounter_Id = inputSrc.Encounter_Id + data.Unit_Id = inputSrc.Unit_Id + data.Specialist_Id = inputSrc.Specialist_Id + data.Subspecialist_Id = inputSrc.Subspecialist_Id + data.Date = inputSrc.Date +} diff --git a/internal/use-case/main-use-case/control-letter/lib.go b/internal/use-case/main-use-case/control-letter/lib.go new file mode 100644 index 00000000..5f82a856 --- /dev/null +++ b/internal/use-case/main-use-case/control-letter/lib.go @@ -0,0 +1,144 @@ +package controlletter + +import ( + e "simrs-vx/internal/domain/main-entities/control-letter" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.ControlLetter, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.ControlLetter{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.ControlLetter, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.ControlLetter{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.ControlLetter{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Order("\"CreatedAt\" DESC") + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.ControlLetter, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.ControlLetter{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if input.Includes != "" { + tx = tx.Scopes(gh.Preload(input.Includes)) + } + + if err := tx.First(&data, input.Id).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.ControlLetter, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.ControlLetter, 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 +} diff --git a/internal/use-case/main-use-case/control-letter/middleware-runner.go b/internal/use-case/main-use-case/control-letter/middleware-runner.go new file mode 100644 index 00000000..6335de13 --- /dev/null +++ b/internal/use-case/main-use-case/control-letter/middleware-runner.go @@ -0,0 +1,103 @@ +package controlletter + +import ( + e "simrs-vx/internal/domain/main-entities/control-letter" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.ControlLetter) 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.ControlLetter) 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.ControlLetter) 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.ControlLetter) 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.ControlLetter) 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/main-use-case/control-letter/middleware.go b/internal/use-case/main-use-case/control-letter/middleware.go new file mode 100644 index 00000000..42ae506c --- /dev/null +++ b/internal/use-case/main-use-case/control-letter/middleware.go @@ -0,0 +1,9 @@ +package controlletter + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/control-letter/tycovar.go b/internal/use-case/main-use-case/control-letter/tycovar.go new file mode 100644 index 00000000..1f19c991 --- /dev/null +++ b/internal/use-case/main-use-case/control-letter/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 controlletter + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/control-letter" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.ControlLetter, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.ControlLetter, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.ControlLetter, 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-case/.keep b/internal/use-case/simgos-sync-use-case/.keep similarity index 100% rename from internal/use-case/simgos-sync-case/.keep rename to internal/use-case/simgos-sync-use-case/.keep diff --git a/pkg/use-case-helper/use-case-helper.go b/pkg/use-case-helper/use-case-helper.go index 0df8fe3e..a80595bb 100644 --- a/pkg/use-case-helper/use-case-helper.go +++ b/pkg/use-case-helper/use-case-helper.go @@ -143,3 +143,10 @@ func GetTimeNow() *time.Time { tmp := time.Now() return &tmp } + +func IsDateBeforeNow(t *time.Time) bool { + if t == nil { + return false + } + return t.Before(time.Now()) +} From 21c678b823db787a817d6dfe84675d5e9a0f20bb Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 3 Nov 2025 15:46:44 +0700 Subject: [PATCH 050/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 134 ++++++++++++------------ 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index b5785611..eca39d6d 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,67 +1,67 @@ -h1:zJVjtCkiWEF41JV7lzbRtI5mPZGz5bC8FaVruh3fmkY= -20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= -20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= -20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= -20250908062323.sql h1:oXl6Z143tOpIl4EfP4B8JNU8LrMvVmHEtCgAfiB4gs8= -20250908073811.sql h1:m2aNXfnGxnLq1+rVWrh4f60q7fhyhV3gEwNu/OIqQlE= -20250908073839.sql h1:cPk54xjLdMs26uY8ZHjNWLuyfAMzV7Zb0/9oJQrsw04= -20250910055902.sql h1:5xwjAV6QbtZT9empTJKfhyAjdknbHzb15B0Ku5dzqtQ= -20250915123412.sql h1:D83xaU2YlDEd21HLup/YQpQ2easMToYCyy/oK6AFgQs= -20250916043819.sql h1:ekoTJsBqQZ8G8n0qJ03d13+eoNoc7sAUEQGA5D/CCxk= -20250917040616.sql h1:zoCnmcXuM7AVv85SmN7RmFglCgJnoDmpRWExH0LAc9Q= -20250917040751.sql h1:J1xyRrh32y1+lezwAyNwPcUQ6ABBSgbvzNLva4SVdQU= -20250917045138.sql h1:jKe1Z0uOLG4SGBYM+S/3P+/zMPztmgoderD5swnMuCg= -20250917093645.sql h1:cNI3Pbz1R3LxvIXLuexafJFCXUXrmuFCgXXJ2sG+FW0= -20250918073552.sql h1:RJ1SvMzP6aeWnoPVD3eVAmIQOkcp6Php8z3QRri6v4g= -20250918073742.sql h1:+cEsnJTJFybe2fR69ZoOiX2R6c6iITl4m6WTZ1hjyzY= -20250918074745.sql h1:2hNVQCXF/dVYXAh+T/7oBFgERGWxzVb2FXJjwkFWGCI= -20250923025134.sql h1:Ykz/qpHiGDXPsCsWTjydQFVSibZP2D+h2fIeb2h2JGA= -20250924051317.sql h1:yQuW6SwJxIOM5fcxeAaie5lSm1oLysU/C2hH2xNCVoQ= -20250929034321.sql h1:101FJ8VH12mrZWlt/X1gvKUGOhoiF8tFbjiapAjnHzg= -20250929034428.sql h1:i+pROD9p+g5dOmmZma6WF/0Hw5g3Ha28NN85iTo1K34= -20250930025550.sql h1:+F+CsCUXD/ql0tHGEow70GhPBX1ZybVn+bh/T4YMh7Y= -20250930140351.sql h1:9AAEG1AnOAH+o0+oHL5G7I8vqlWOhwRlCGyyCpT/y1Q= -20251002085604.sql h1:3xZ68eYp4urXRnvotNH1XvG2mYOSDV/j3zHEZ/txg5E= -20251003032030.sql h1:HB+mQ2lXMNomHDpaRhB/9IwYI9/YiDO5eOJ+nAQH/jw= -20251005060450.sql h1:LbtCE2b+8osM3CvnmQJH1uCPtn+d7WchsslBOz8bL3Q= -20251006041122.sql h1:MlS7f21z06sutnf9dIekt5fuHJr4lgcQ4uCuCXAGsfc= -20251006045658.sql h1:3FmGCPCzjgMPdWDRodZTsx3KVaodd9zB9ilib69aewk= -20251006045928.sql h1:Z5g31PmnzNwk/OKdODcxZGm8fjJQdMFK32Xfnt3bRHg= -20251007022859.sql h1:FO03zEfaNEk/aXwY81d5Lp3MoBB9kPQuXlXJ4BPiSR8= -20251008031337.sql h1:l+sxUAGvcTfj3I6kAFHo+T6AYodC9k9GkR+jaKO2xXc= -20251008031554.sql h1:AqrVfIhSzY3PCy8ZlP5W91wn2iznfIuj5qQfubp6/94= -20251008052346.sql h1:nxnXmooIJ6r1mmzwnw+6efxLfc/k9h2aE6RMptPRons= -20251008073620.sql h1:6YsJp1W4SmQJ1lxpqF27BBlDC1zqhw7Yhc7pLzQTY6M= -20251009042854.sql h1:nkBV+R6j0fg7/JY6wH3eb5Vv0asJLnXmb6lINfT/GLQ= -20251009052657.sql h1:EPvdsib5rzCGPryd10HShGKvFPwM/R5S2lIVwtYxpms= -20251010031743.sql h1:T8IZmx8/btRFKLzTe78MzcBsPJNodnLvB0tby9QkirQ= -20251010070721.sql h1:5NQUk/yOV6sABLCB7swx++YIOyJe6MnU+yt1nRzde5w= -20251010072711.sql h1:ZJNqR2piyu8xJhBvVABSlnGEoKSKae3wuEs+wshPe4k= -20251013044536.sql h1:0Xjw8fNILiT8nnfrJDZgQnPf3dntmIoilbapnih8AE4= -20251013051438.sql h1:lfSuw5mgJnePBJamvhZ81osFIouXeiIEiSZ/evdwo48= -20251013081808.sql h1:ijgjNX08G6GBjA/ks8EKtb7P7Y7Cg7zbhqEOruGnv6M= -20251014060047.sql h1:0jqj49WTtneEIMQDBoo4c095ZGi8sCrA8NnHBrPU6D8= -20251014063537.sql h1:VZLXol0PTsTW21Epg6vBPsztWkDtcxup9F/z88EGgIg= -20251014063720.sql h1:2HVUyCV0ud3BJJDH2GEKZN/+IWLFPCsN1KqhP6csO14= -20251015045455.sql h1:MeLWmMhAOAz8b15Dd7IAQnt6JxjSml02XCXK22C0Lpg= -20251016010845.sql h1:4BncQdDOasRZJkzVJrSJJA7091A9VPNVx/faUCUPhBM= -20251016011023.sql h1:9JB9eFZKURK5RoCVDKR6glSvdJ8NTXrN7K/4q51zkz4= -20251016062912.sql h1:ACNn0fe+EMqUt3hoY+Dr3uqAV/QICBa1+mIW7fUc9Fk= -20251017060617.sql h1:4T3t9ifWrEQTPMSM0XJ98pF7Qdt+UfgtMui17bhrnWI= -20251017082207.sql h1:8vLG1l/saRRMHXkyA4nelJyjaSddhZd6r7R+Uo4JS/c= -20251018032635.sql h1:2xey5gnO3y2XSOrU8MLlIfoylPKbRGDRtHDD07B3MbQ= -20251018040322.sql h1:k/pdNiSoT8zFPqNQ/avOD0vYkNh3BTD64IlHrfVXr7I= -20251019093915.sql h1:hFcQE0y+p5dZiVwePGsRGto9m/q6kJNiUZbVDd5Rnjk= -20251020062553.sql h1:Iw7hulcm5iRQlfW+ygA4iTPxLqkxx6h9vXMXEwUAHKs= -20251021041042.sql h1:wMgSivBV2A0NDcsLmKGIp0kMcVh2IODSG9b4dgzCaOM= -20251021075552.sql h1:8gfSMAglflNO6L0sSzxFNEubYN8/O4thT7OQT+WH+3M= -20251023044432.sql h1:MkvajJs3bfk9+wHvQ43/ccAluJEBARm1gWr1u92ccLA= -20251024034832.sql h1:x3s3VEVYLOSKLAFxJGb2+c1FyTMMvPE+9k4Ew7rKQaI= -20251024074315.sql h1:EjAjelgi5qAfcRq/8vPTlGGYHvAKxNTllm8f0SzZDns= -20251025013451.sql h1:6hnuIiwYiG+6nLhOY/+Yyn+I6ZCFNRZxrJNqBV6HLqE= -20251025013609.sql h1:evPJaTD8WxYRMOJZHkSr7ONLx9PYxT+ankzQt9c/sJ0= -20251027075128.sql h1:/iFQBM1sytjqpyQSOx61q33gnorMgxTiFVSuL6bQqsM= -20251027091406.sql h1:eCZGtUkxAzEAqpC9UsGpP8Df9mS0DEOqSl885LgqpvM= -20251102002037.sql h1:lFJbuoZ2LMQnUNGdcwHVY3Xlfslgzu9t2WByT8yfOZI= -20251102091932.sql h1:rmdhb5m+P+fU8jROBZNyeYgZKuQvucsuljXv4ZVzvks= -20251103081637.sql h1:jqpMnygFceOJn0rI30GYWI2CKbOu6RzVqw2/Pji2Ka8= +h1:DcO8hW6ltApCY7bmxeSji280ls5j97uZeEb034pHQqY= +20250904105930.sql h1:Vv4vCurl7m7/ZB6TjRpkubHpQ4RYwSUn0QHdzfoGpzY= +20250904141448.sql h1:FYCHH9Os4KkrZMDu/jR8FMP+wLMRW+Mb0PkLU/9BRDg= +20250908062237.sql h1:oanBpKZd+akPu2I/xYhUSbd0G5tAFbXzKLER/Zs8ENI= +20250908062323.sql h1:miNG9COddXkD1jGTgaROMAZ618eT6oiLGiJhXWnQwhE= +20250908073811.sql h1:gOi5cnGG1htlpfizybYmUIT0vYjZTBfXiI0nPSYK2u8= +20250908073839.sql h1:cWNDA4YikjoOteAJuNLFILjQUJPFB6o8Wxreiek4QyI= +20250910055902.sql h1:nxxOGnU0BbH/v3IPgeIOXOwH8d3tKomw7h6FTeMnnBs= +20250915123412.sql h1:mz7SiWfrdf0qE1VTSAAnA/147d6gyp6ry5vZ2bR9SH0= +20250916043819.sql h1:RHXVtmMkB6wfv06HfPyHMBmUfIpFt1xveafNz0kwKnE= +20250917040616.sql h1:MYVDht+akBlzQGKNu2hTTTLPEcH1bxT/Q8MK6WEtuhs= +20250917040751.sql h1:J79YyS2JzWgh5oKXMTgh67uo3gLxKaAsxRiZmSIfjBs= +20250917045138.sql h1:/SM1N4O8X3yxpoJgMEARmS1uOkuLKsTOy4PLsRCOKaQ= +20250917093645.sql h1:PNBTGZ7s10e5b5+Tie8YfVQBN0zKtJ5T34oK1iOUEb4= +20250918073552.sql h1:jG7+g3i8ODYaJdcdZz12v3nbsZ5mB9wG6kWnGyTQIRI= +20250918073742.sql h1:j+rgw7puxE7s+phqPVZHmPk0af3rcaA56Itp86y1suY= +20250918074745.sql h1:rPmP4DXs6OnY4Vp+xO/z9jFpJt/RrJ52SJJjIIxeDvc= +20250923025134.sql h1:2r6pcwnBSU5Y9Czk1OHBoh4yZXiMtEca9X8843fTEX0= +20250924051317.sql h1:iUAk2gsGoEGIPQ0lEEUp8maMSId8emNbP+kP712ABIA= +20250929034321.sql h1:UlpALNVmdi95zOIT0yc6ZyTj9bBjQEIpZhvgrc52M+k= +20250929034428.sql h1:feF+H4nDyHh5bdx48Oiz0A1qecZfi6v3qTTdjzJ45Dg= +20250930025550.sql h1:6XT1kXI3Z3ZIxxmvT7poufZWWCW0QiejZPaFV5wBnjI= +20250930140351.sql h1:HxnmAbh9gCy8jwl/9ycGktiByaUripsjFFvohofY2CY= +20251002085604.sql h1:SjLPi+ZN6qDccK3DaEQCgNsZpPwr5kynWXwbwEsziCI= +20251003032030.sql h1:oHfxNSuqTxU8Zaf9H+h8TuUb1Da03wcyc6hZjDrUQ2s= +20251005060450.sql h1:GIuCcrd4MwjmXpvbzDzPYL18BV3QaZZ+Y2FmEzjvi0E= +20251006041122.sql h1:uNDQbSw0M08lYoMvUNlQtS3iDzpPM1ixT13ugSAoWjE= +20251006045658.sql h1:z+t7yCK54Q4SSiF9kUyUhkYB2F+kzSW9TB7ogxd9wzw= +20251006045928.sql h1:1lATLFLp4BWwGZqAjZdP0Dc6ypNXiYcwjoNkqGa8NFE= +20251007022859.sql h1:HXXwWrkyvzJzJGAt9mGskCRBBV/c1JfPmfjDocmJhQ4= +20251008031337.sql h1:Ln5pCF3Hxa5foHZLcds+z/us2eH6VAhhEj3w0TAGlVs= +20251008031554.sql h1:aB4MUS2lmqG0//4HKUWorcPSpWya0VC4QItvGyskEVI= +20251008052346.sql h1:MI3AZgU5XcwZT2OvvlWAxdRtL0eJ3jjRwt56IY1+pRU= +20251008073620.sql h1:sztWXuSNYwpEraaSapSsYwno75LO5H/N7ob7OJQ8X/A= +20251009042854.sql h1:TnPXj+dCJls3IU//cuqJZymyBzZMKs7ayazfgtAFRxM= +20251009052657.sql h1:leXbs0CP8r5dRilmYyLRk1MICqak3ea1/LWMtFrijqQ= +20251010031743.sql h1:SgHNY/lQ88G2F4nZyMfiOkDntb+gtOR+nEQLqXBTwv4= +20251010070721.sql h1:AnJnhXsMzDvK4AFgYw6B16Kpo/hljrZtcpc9m2VOSHQ= +20251010072711.sql h1:aXPTtNwLcTuw8C/yAxwxvqs0ayEjNzI1uuE0vE3ERa8= +20251013044536.sql h1:7Pq6JcvTpPBYDCW2dz3HdgUwY65HlhEVWy9TiG8iONE= +20251013051438.sql h1:X6t8bkqpUYYokBunSufMQUe5vCg0VyO6dxbm7ngosUc= +20251013081808.sql h1:495pLguXL2Ozh+ycn4UYZgZbn6WbjXNbyZUc3JU8qhI= +20251014060047.sql h1:nCgImMRGHhziiW57O1ofWaXCAPGaCOHN7PldQ3OSmM4= +20251014063537.sql h1:2cLmID79jP6cuQ1YJaWTtghFiM1GtHMC0ZQl30Hpy1M= +20251014063720.sql h1:bzLKKVAjSHgDFoiI/glj7t1ETlSAKx+AlsIAaP0ru2g= +20251015045455.sql h1:S547+UugQhlTRcn1Lm1IfqT5RNPttIWIiD+RTx69YaE= +20251016010845.sql h1:c9DUvxl17pUkf0azdYGM/YDzYxIJkLcfZOcMI4rL+R0= +20251016011023.sql h1:u3ivg83bXgYHBbojbWpemLxPE9Dmmj53B6LXo664jxw= +20251016062912.sql h1:W9n1hWchfYkqNX9LO9uxFxEXAb/iY+Pexjnhmp6PbgI= +20251017060617.sql h1:VU6yZ2+LfHpDZ3+TIH40t3F5YXPCpTppuF9+uSqa4b8= +20251017082207.sql h1:QshZslfedckz7iDpSGmPyY9sP6dy6ckHbs8L1TuXIA4= +20251018032635.sql h1:M1U/9W/F9wlW5YDmVAmHFfUJU7FWFaX0DblpfZcYWrE= +20251018040322.sql h1:Zk/vw0e6AzWFO2ElLOzB+OrSz6k+h1Ynxp0TImAzxwY= +20251019093915.sql h1:3Q0kPiZwJnHn5rAvdh0w1LBdiA7W2xBmZWncoPXb044= +20251020062553.sql h1:mJwC/J8GzPAIXckNMvy1f/Nguk2VVf8roD/Raclhbao= +20251021041042.sql h1:d1BAOGAQhqr+oOwcpAVozUsTh457VSDEk2qQFavGG58= +20251021075552.sql h1:TNChGQ1Zlr/1iQ6qvK4iDTAJpe6L/z/M6e/O0SkQVaM= +20251023044432.sql h1:GA2AdJk2ULyjr6igtu9C/CEi4YUIks8r9jXGGaCvPsk= +20251024034832.sql h1:RXmbEhMkOLK5g1QL6up8iRPcwYfo89oLP26ZHvrUK9o= +20251024074315.sql h1:3GnPQSbuAAfMa8oWDyBjhXqn1j1zunY/w0ydX0IGPrA= +20251025013451.sql h1:5eNrA9LDxA4i5CCP7wSyOgFZ6t6jBWVil+oGzJpkJ2E= +20251025013609.sql h1:+N6EHc1kv3hqf16CUhXe+UITPmoxOPfi4MECLmJXNrc= +20251027075128.sql h1:PQflgsjce/p2ClbybLtdehdPNDcMZ9Lb1vd98xd0K8E= +20251027091406.sql h1:bYXV57GvodCMjg0/ox+XKGIAGhrDlVuJ1wO4foNEKtQ= +20251102002037.sql h1:ZcwULsJU2lI9t5pX7ukmfAHSx4ZxdxLUX6jzLDc2SrU= +20251102091932.sql h1:A6y9j4wAqm4/HfMDxhpy/ChDn3UNRVN99KGgSCX+e18= +20251103081637.sql h1:RFqJNhJItSwJQaMP5IcQ14mL7eQ3EJjGZua9zLWzwMU= From 8a3a140cdec7772c7925208be5e84b223b9edda3 Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 4 Nov 2025 10:26:11 +0700 Subject: [PATCH 051/329] adjustment encounter --- .../domain/main-entities/encounter/dto.go | 10 +- .../main-handler/encounter/handler.go | 5 + .../encounter/request-validation.go | 25 +- .../main-use-case/ambulatory/helper.go | 1 + .../use-case/main-use-case/encounter/case.go | 148 +++++++---- .../use-case/main-use-case/encounter/lib.go | 245 ++++++++++++++++++ .../use-case/main-use-case/soapi/helper.go | 16 ++ internal/use-case/main-use-case/soapi/lib.go | 20 ++ 8 files changed, 403 insertions(+), 67 deletions(-) diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index e4b9a521..0d5e1aae 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -16,15 +16,11 @@ import ( // internal - domain - main-entities evs "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" - eam "simrs-vx/internal/domain/main-entities/ambulatory" ea "simrs-vx/internal/domain/main-entities/appointment" ed "simrs-vx/internal/domain/main-entities/doctor" - eem "simrs-vx/internal/domain/main-entities/emergency" ee "simrs-vx/internal/domain/main-entities/employee" - ei "simrs-vx/internal/domain/main-entities/inpatient" eir "simrs-vx/internal/domain/main-entities/internal-reference" ep "simrs-vx/internal/domain/main-entities/patient" - er "simrs-vx/internal/domain/main-entities/rehab/base" es "simrs-vx/internal/domain/main-entities/specialist" ess "simrs-vx/internal/domain/main-entities/subspecialist" eu "simrs-vx/internal/domain/main-entities/unit" @@ -52,10 +48,8 @@ type CreateDto struct { Appointment_Id *uint `json:"appointment_id"` RefTypeCode ere.RefTypeCode `json:"refTypeCode"` NewStatus bool `json:"newStatus"` - Ambulatory *eam.CreateDto `json:"ambulatory"` - Emergency *eem.CreateDto `json:"emergency"` - Inpatient *ei.Inpatient `json:"inpatient"` - Rehab *er.Basic `json:"rehab"` + VisitMode_Code *ere.VisitModeCode `json:"visitMode_code"` // if subClass_Code is rehab + AllocatedVisitCount *int `json:"allocatedVisitCount"` pa.AuthInfo } diff --git a/internal/interface/main-handler/encounter/handler.go b/internal/interface/main-handler/encounter/handler.go index ed8b1fbc..b66abe76 100644 --- a/internal/interface/main-handler/encounter/handler.go +++ b/internal/interface/main-handler/encounter/handler.go @@ -26,10 +26,15 @@ func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { if err != nil { rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) } + dto := e.CreateDto{} if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } + if valid := validateRequestCreate(w, dto); !valid { + return + } + dto.AuthInfo = *authInfo res, err := u.Create(dto) rw.DataResponse(w, res, err) diff --git a/internal/interface/main-handler/encounter/request-validation.go b/internal/interface/main-handler/encounter/request-validation.go index 5963abcb..d3a7afe4 100644 --- a/internal/interface/main-handler/encounter/request-validation.go +++ b/internal/interface/main-handler/encounter/request-validation.go @@ -67,22 +67,17 @@ func validateRequestCheckIn(w http.ResponseWriter, i e.CheckinDto) (valid bool) func validateRequestCreate(w http.ResponseWriter, i e.CreateDto) (valid bool) { switch { case i.Class_Code == ere.ECAmbulatory: - if i.Ambulatory == nil { - rw.DataResponse(w, nil, d.FieldError{ - Code: dataValidationFail, - Message: "ambulatory required", - }) + // field allocatedVisitCount required if ambulatory visitMode_Code is adm + if ere.AmbulatoryClassCode(*i.SubClass_Code) == ere.ACCRme && *i.VisitMode_Code == ere.VMCAdm { + if *i.AllocatedVisitCount == 0 { + rw.DataResponse(w, nil, d.FieldError{ + Code: dataValidationFail, + Message: "allocatedVisitCount required", + }) + return + } } } - if i.Class_Code == ere.ECAmbulatory && i.Ambulatory.Class_Code == ere.ACCRme && i.Ambulatory.VisitMode_Code == ere.VMCAdm { - if *i.Rehab.AllocatedVisitCount == 0 { - rw.DataResponse(w, nil, d.FieldError{ - Code: dataValidationFail, - Message: "rehab.AllocatedVisitCode required", - }) - return - } - } - return + return true } diff --git a/internal/use-case/main-use-case/ambulatory/helper.go b/internal/use-case/main-use-case/ambulatory/helper.go index f78f0b65..bdd9b106 100644 --- a/internal/use-case/main-use-case/ambulatory/helper.go +++ b/internal/use-case/main-use-case/ambulatory/helper.go @@ -22,6 +22,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Ambulatory) { data.Encounter_Id = inputSrc.Encounter_Id data.Class_Code = inputSrc.Class_Code + data.VisitMode_Code = inputSrc.VisitMode_Code } func CheckClassCode(input *string) (ere.AmbulatoryClassCode, error) { diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 11b17e2b..cb886eee 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -25,6 +25,7 @@ import ( eem "simrs-vx/internal/domain/main-entities/employee" e "simrs-vx/internal/domain/main-entities/encounter" ei "simrs-vx/internal/domain/main-entities/inpatient" + er "simrs-vx/internal/domain/main-entities/rehab" erdh "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" es "simrs-vx/internal/domain/main-entities/soapi" @@ -36,6 +37,7 @@ import ( ue "simrs-vx/internal/use-case/main-use-case/emergency" uem "simrs-vx/internal/use-case/main-use-case/employee" ui "simrs-vx/internal/use-case/main-use-case/inpatient" + ur "simrs-vx/internal/use-case/main-use-case/rehab" urdh "simrs-vx/internal/use-case/main-use-case/responsible-doctor-hist" us "simrs-vx/internal/use-case/main-use-case/soapi" ) @@ -46,6 +48,7 @@ var now = time.Now() func Create(input e.CreateDto) (*d.Data, error) { data := e.Encounter{} + createSoapi := []es.CreateDto{} event := pl.Event{ Feature: "Create", @@ -55,6 +58,33 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") + // validate SubClass + var subCode interface{} + subCode, err := verifyClassCode(input) + if err != nil { + return nil, err + } + + // verify whether the allocated visit count has not exceeded the limit + if input.Class_Code == ere.ECAmbulatory && subCode.(ere.AmbulatoryClassCode) == ere.ACCRme && + *input.VisitMode_Code == ere.VMCSeries { + + dataEncounter, valid, err := verifyAllocatedVisitCount(input, &event) + if err != nil { + return nil, err + } + + if !valid { + return nil, err + } + + // get data soapi + createSoapi, err = getSoapiEncounterAdm(dataEncounter, &event) + if err != nil { + return nil, err + } + } + // check if patient is new in the hospital dataPatient, err := ReadList(e.ReadListDto{ FilterDto: e.FilterDto{Patient_Id: input.Patient_Id}, @@ -62,7 +92,6 @@ func Create(input e.CreateDto) (*d.Data, error) { if err != nil { return nil, err } - if list, ok := dataPatient.Data.([]e.ResponseDto); ok { if len(list) < 1 { input.NewStatus = true @@ -83,6 +112,7 @@ func Create(input e.CreateDto) (*d.Data, error) { input.Adm_Employee_Id = &emp.Id } + // create encounter if resData, err := CreateData(input, &event, tx); err != nil { return err } else { @@ -91,52 +121,57 @@ func Create(input e.CreateDto) (*d.Data, error) { switch input.Class_Code { case ere.ECAmbulatory: - subCode, err := ua.CheckClassCode(input.SubClass_Code) - if err != nil { - return err - } + subCodeAmbulatory := subCode.(ere.AmbulatoryClassCode) ambCreate := ea.CreateDto{ - Encounter_Id: &data.Id, - Class_Code: subCode, + Encounter_Id: &data.Id, + Class_Code: subCodeAmbulatory, + VisitMode_Code: *input.VisitMode_Code, } _, err = ua.CreateData(ambCreate, &event, tx) if err != nil { return err } - if subCode == ere.ACCCac || subCode == ere.ACCCad { + if subCodeAmbulatory == ere.ACCCac || subCodeAmbulatory == ere.ACCCad { chemoCreate := ec.CreateDto{ Encounter_Id: &data.Id, Status_Code: erc.DVCNew, SrcUnit_Id: input.Unit_Id, } - _, err = uc.CreateData(chemoCreate, &event, tx) if err != nil { return err } } - case ere.ECEmergency: - subCode, err := ue.CheckClassCode(input.SubClass_Code) - if err != nil { - return err + + if subCodeAmbulatory == ere.ACCRme && *input.VisitMode_Code == ere.VMCAdm { + // create data rehab + if _, err = ur.CreateData(er.CreateDto{ + Encounter_Id: &data.Id, + Doctor_Id: input.Appointment_Doctor_Id, + AllocatedVisitCount: input.AllocatedVisitCount}, &event, tx); err != nil { + return err + } + } else if subCodeAmbulatory == ere.ACCRme && *input.VisitMode_Code == ere.VMCSeries { + // Insert Soapi + if err = us.CreateBulkData(createSoapi, data.Id, &event, tx); err != nil { + return err + } } + + case ere.ECEmergency: emerCreate := ee.CreateDto{ Encounter_Id: &data.Id, - Class_Code: subCode, + Class_Code: subCode.(ere.EmergencyClassCode), } _, err = ue.CreateData(emerCreate, &event, tx) if err != nil { return err } case ere.ECInpatient: - subCode, err := ui.CheckClassCode(input.SubClass_Code) - if err != nil { - return err - } inpCreate := ei.CreateDto{ Encounter_Id: &data.Id, - Class_Code: subCode, + Class_Code: subCode.(ere.InpatientClassCode), Infra_Id: input.Infra_Id, } _, err = ui.CreateData(inpCreate, &event, tx) @@ -148,11 +183,10 @@ func Create(input e.CreateDto) (*d.Data, error) { } // insert adm_employee_hist - if _, err := uaeh.Create(eaeh.CreateDto{ + if _, err := uaeh.CreateData(eaeh.CreateDto{ Encounter_Id: &data.Main.Id, Employee_Id: data.Adm_Employee_Id, - StartedAt: &now, - }); err != nil { + StartedAt: &now}, &event, tx); err != nil { return err } @@ -430,8 +464,16 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - if err := checkSoapiByDocExists(data.Id, &event, tx); err != nil { - return err + if data.Class_Code == ere.ECAmbulatory { + // validate if soapi exist + err = getSoapiByTypeCode(input.Id, &event, "check-out") + if err != nil { + return err + } + } else { + if err := checkSoapiByDocExists(data.Id, &event, tx); err != nil { + return err + } } if err := updateDischargeData(input, data, &event, tx); err != nil { @@ -557,7 +599,7 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) { } func CheckIn(input e.CheckinDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Rehab"} var data *e.Encounter var err error @@ -580,23 +622,11 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { } // validate if soapi exist - dataSoapi, err := us.ReadList(es.ReadListDto{FilterDto: es.FilterDto{Encounter_Id: &input.Id}}) + err = getSoapiByTypeCode(input.Id, &event, "check-in") if err != nil { return nil, err } - if list, ok := dataSoapi.Data.([]es.ResponseDto); ok { - if len(list) > 0 { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-state-mismatch", - Detail: "soapi already exist", - Raw: errors.New("soapi already exist"), - } - return nil, pl.SetLogError(&event, input) - } - } - err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") if data, err = ReadDetailData(rdDto, &event, tx); err != nil { @@ -621,11 +651,10 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { } //insert responsible_doctor_hist - if _, err = urdh.Create(erdh.CreateDto{ + if _, err = urdh.CreateData(erdh.CreateDto{ Encounter_Id: &input.Id, Doctor_Id: input.Responsible_Doctor_Id, - StartedAt: input.StartedAt, - }); err != nil { + StartedAt: input.StartedAt}, &event, tx); err != nil { return err } } @@ -638,11 +667,10 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { } // insert responsible_doctor_hist - if _, err = uaeh.Create(eaeh.CreateDto{ + if _, err = uaeh.CreateData(eaeh.CreateDto{ Encounter_Id: &input.Id, Employee_Id: input.Adm_Employee_Id, - StartedAt: input.StartedAt, - }); err != nil { + StartedAt: input.StartedAt}, &event, tx); err != nil { return err } } @@ -652,6 +680,15 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { return err } + if err := updateRehabDoctor(er.UpdateDto{ + CreateDto: er.CreateDto{ + Encounter_Id: &data.Id, + Doctor_Id: input.Responsible_Doctor_Id, + }, + }, &event, tx); err != nil { + return err + } + pl.SetLogInfo(&event, nil, "complete") return nil @@ -688,3 +725,26 @@ func validateForeignKey(input e.CheckinDto) error { return nil } + +func verifyClassCode(input e.CreateDto) (subCode interface{}, err error) { + switch input.Class_Code { + case ere.ECAmbulatory: + subCode, err = ua.CheckClassCode(input.SubClass_Code) + if err != nil { + return nil, err + } + case ere.ECEmergency: + subCode, err = ue.CheckClassCode(input.SubClass_Code) + if err != nil { + return nil, err + } + case ere.ECInpatient: + subCode, err = ui.CheckClassCode(input.SubClass_Code) + if err != nil { + return nil, err + } + default: + return nil, errors.New("invalid encounter class code") + } + return +} diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index 3327bcfa..ed41e15f 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -3,6 +3,12 @@ package encounter import ( // std "errors" + "fmt" + erc "simrs-vx/internal/domain/references/clinical" + ere "simrs-vx/internal/domain/references/encounter" + ero "simrs-vx/internal/domain/references/organization" + "strings" + // external dg "github.com/karincake/apem/db-gorm-pg" gh "github.com/karincake/getuk" @@ -15,8 +21,11 @@ import ( // internal eaeh "simrs-vx/internal/domain/main-entities/adm-employee-hist" + ea "simrs-vx/internal/domain/main-entities/ambulatory" e "simrs-vx/internal/domain/main-entities/encounter" + er "simrs-vx/internal/domain/main-entities/rehab" erdh "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" + es "simrs-vx/internal/domain/main-entities/soapi" ) func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Encounter, error) { @@ -333,3 +342,239 @@ func updateLatestAdmEmployeeHist(input e.CheckinDto, event *pl.Event, dbx ...*go pl.SetLogInfo(event, nil, "complete") return nil } + +func verifyAllocatedVisitCount(i e.CreateDto, event *pl.Event) (e.Encounter, bool, error) { + pl.SetLogInfo(event, nil, "started", "DBGetRecentEncounterAdm") + + var ( + tx = dg.I + recentEncounterAdm e.Encounter + countEncounterSeries int64 + ) + + err := tx. + Scopes(gh.Preload("Rehab,Responsible_Doctor")). + Joins("JOIN \"Ambulatory\" ON \"Ambulatory\".\"Encounter_Id\" = \"Encounter\".\"Id\""). + Where("\"Patient_Id\" = ?", i.Patient_Id). + Where("\"Ambulatory\".\"Class_Code\" = ? AND \"Ambulatory\".\"VisitMode_Code\" = ?", ere.ACCRme, ere.VMCAdm). + Order("\"CreatedAt\" DESC"). + First(&recentEncounterAdm).Error + if err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "read-recentEncounter-fail", + Detail: "Database read failed", + Raw: err, + } + return e.Encounter{}, false, pl.SetLogError(event, i) + } + + err = tx. + Model(&e.Encounter{}). + Joins("JOIN \"Ambulatory\" ON \"Ambulatory\".\"Encounter_Id\" = \"Encounter\".\"Id\""). + Where("\"Patient_Id\" = ?", i.Patient_Id). + Where("\"Ambulatory\".\"Class_Code\" = ? AND \"Ambulatory\".\"VisitMode_Code\" = ?", ere.ECAmbulatory, ere.VMCSeries). + Where("\"CreatedAt\" > ?", recentEncounterAdm.CreatedAt). + Count(&countEncounterSeries).Error + if err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "read-countEncounter-fail", + Detail: "Database read failed", + Raw: err, + } + return e.Encounter{}, false, pl.SetLogError(event, i) + } + + return recentEncounterAdm, countEncounterSeries < int64(*recentEncounterAdm.Rehab.AllocatedVisitCount), nil +} + +func getSoapiEncounterAdm(enc e.Encounter, event *pl.Event) (dataSoapi []es.CreateDto, err error) { + var data []es.Soapi + + pl.SetLogInfo(event, enc, "started", "DBReadList") + + if enc.Responsible_Doctor == nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "no responsible-doctor found", + Detail: "Encounter does not have responsible-doctor", + } + } + + err = dg.I. + Model(&es.Soapi{}). + Joins("JOIN \"Employee\" ON \"Employee\".\"Id\" = \"Soapi\".\"Employee_Id\""). + Where("\"Encounter_Id\" = ?", enc.Id). + Where("\"Employee\".\"Position_Code\" = ?", ero.EPCDoc). + Where("\"Soapi\".\"TypeCode\" IN ?", []erc.SoapiTypeCode{erc.STCEEarlyMedic, erc.STCFunc}). + Where("\"Soapi\".\"Employee_Id\" = ?", *enc.Responsible_Doctor.Employee_Id). + Find(&data).Error + + if err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Raw: err, + } + + if errors.Is(err, gorm.ErrRecordNotFound) { + event.ErrInfo.Code = "data-not-found" + event.ErrInfo.Detail = "Data not found" + return nil, pl.SetLogError(event, enc) + } + + event.ErrInfo.Code = "read-fail" + event.ErrInfo.Detail = "Database read failed" + return nil, pl.SetLogError(event, enc) + } + + pl.SetLogInfo(event, nil, "complete") + + for _, s := range data { + // set data soapi for copy + dataSoapi = append(dataSoapi, es.CreateDto{ + Employee_Id: s.Employee_Id, + Time: s.Time, + TypeCode: s.TypeCode, + Value: s.Value, + }) + } + + if len(dataSoapi) < 2 { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "missing-soapi", + Detail: fmt.Sprintf("Missing required Soapi types"), + } + return nil, pl.SetLogError(event, enc) + } + return +} + +func getSoapiByTypeCode(encounterId uint, event *pl.Event, mode string) (err error) { + pl.SetLogInfo(event, encounterId, "started", "DBReadList") + + var ( + dataAmbulatory ea.Ambulatory + dataSoapi []es.Soapi + ) + + // Get Data Ambulatory + if err = dg.I. + Where("\"Encounter_Id\" = ?", encounterId). + First(&dataAmbulatory).Error; err != nil { + return setDBError(event, err, encounterId) + } + + // Set Query for get data Soapi + tx := dg.I. + Model(&es.Soapi{}). + Joins("JOIN \"Employee\" ON \"Employee\".\"Id\" = \"Soapi\".\"Employee_Id\""). + Where("\"Encounter_Id\" = ?", encounterId). + Where("\"Employee\".\"Position_Code\" = ?", ero.EPCDoc) + + // Set Case + switch { + case dataAmbulatory.Class_Code == ere.ACCReg: + tx = tx.Where("\"Soapi\".\"TypeCode\" = ?", erc.STCEEarlyMedic) + case dataAmbulatory.Class_Code == ere.ACCRme && dataAmbulatory.VisitMode_Code == ere.VMCAdm: + tx = tx.Where("\"Soapi\".\"TypeCode\" IN ?", []erc.SoapiTypeCode{erc.STCEEarlyMedic, erc.STCFunc}) + case dataAmbulatory.Class_Code == ere.ACCRme && dataAmbulatory.VisitMode_Code == ere.VMCSeries: + tx = tx.Where("\"Soapi\".\"TypeCode\" = ?", erc.STCEarlyRehab) + } + + if err = tx.Find(&dataSoapi).Error; err != nil { + return setDBError(event, err, encounterId) + } + + pl.SetLogInfo(event, nil, "complete") + return validateExistedSoapi(dataSoapi, &dataAmbulatory, event, mode) +} + +func validateExistedSoapi(dataSoapi []es.Soapi, dataAmbulatory *ea.Ambulatory, event *pl.Event, mode string) error { + typeExist := make(map[erc.SoapiTypeCode]bool) + for _, s := range dataSoapi { + typeExist[s.TypeCode] = true + } + + required := []erc.SoapiTypeCode{} + + switch { + case dataAmbulatory.Class_Code == ere.ACCReg: + required = []erc.SoapiTypeCode{erc.STCEEarlyMedic} + case dataAmbulatory.Class_Code == ere.ACCRme && dataAmbulatory.VisitMode_Code == ere.VMCAdm: + required = []erc.SoapiTypeCode{erc.STCEEarlyMedic, erc.STCEarlyRehab, erc.STCFunc} + case dataAmbulatory.Class_Code == ere.ACCRme && dataAmbulatory.VisitMode_Code == ere.VMCSeries: + required = []erc.SoapiTypeCode{erc.STCEarlyRehab} + } + + var missing, existing []string + for _, code := range required { + if typeExist[code] { + existing = append(existing, string(code)) + } else { + missing = append(missing, string(code)) + } + } + + switch mode { + case "check-in": + if len(existing) > 0 { + return setSoapiError(event, fmt.Sprintf("Soapi type(s) %s exist, can't check-in", strings.Join(existing, ", "))) + } + case "check-out": + if len(missing) > 0 { + return setSoapiError(event, fmt.Sprintf("Soapi type(s) %s not found, can't check-out", strings.Join(missing, ", "))) + } + } + + return nil +} + +func setSoapiError(event *pl.Event, detail string) error { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "invalid-soapi-state", + Detail: detail, + } + return pl.SetLogError(event, detail) +} + +func setDBError(event *pl.Event, err error, ctx any) error { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Raw: err, + Code: "read-fail", + Detail: "Database read failed", + } + return pl.SetLogError(event, ctx) +} + +func updateRehabDoctor(input er.UpdateDto, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, "started", "DBUpdate") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + result := tx. + Model(&er.Rehab{}). + Where("\"Encounter_Id\" = (?)", input.Encounter_Id). + Update("\"Doctor_Id\"", input.Doctor_Id) + + if result.Error != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-update-fail", + Detail: "Database update failed", + Raw: result.Error, + } + return pl.SetLogError(event, input) + } + + pl.SetLogInfo(event, nil, "complete") + 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 5a94848a..ae396270 100644 --- a/internal/use-case/main-use-case/soapi/helper.go +++ b/internal/use-case/main-use-case/soapi/helper.go @@ -23,3 +23,19 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Soapi) { data.TypeCode = inputSrc.TypeCode data.Value = inputSrc.Value } + +func setBulkData(input []e.CreateDto, encounterId uint) []e.Soapi { + var data []e.Soapi + + for _, v := range input { + data = append(data, e.Soapi{ + Encounter_Id: &encounterId, + Employee_Id: v.Employee_Id, + Time: v.Time, + TypeCode: v.TypeCode, + Value: v.Value, + }) + } + + return data +} diff --git a/internal/use-case/main-use-case/soapi/lib.go b/internal/use-case/main-use-case/soapi/lib.go index 7e551505..57bb5d23 100644 --- a/internal/use-case/main-use-case/soapi/lib.go +++ b/internal/use-case/main-use-case/soapi/lib.go @@ -138,3 +138,23 @@ func DeleteData(data *e.Soapi, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, nil, "complete") return nil } + +func CreateBulkData(input []e.CreateDto, encounterId uint, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := setBulkData(input, encounterId) + + 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 +} From 0f9305427c0f2e5d57bf42797a9c676b98edaf1e Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 4 Nov 2025 11:11:24 +0700 Subject: [PATCH 052/329] encounter-adjustment-finish --- internal/use-case/main-use-case/encounter/case.go | 8 +++++++- internal/use-case/main-use-case/encounter/lib.go | 11 ++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index cb886eee..8cff1e21 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -75,7 +75,13 @@ func Create(input e.CreateDto) (*d.Data, error) { } if !valid { - return nil, err + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "visit-limit-exceeded", + Detail: "Encounter has exceeded the allowed number of visits", + Raw: errors.New("visit count exceeds allowed limit"), + } + return nil, pl.SetLogError(&event, input) } // get data soapi diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index ed41e15f..b840f6e1 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -370,11 +370,12 @@ func verifyAllocatedVisitCount(i e.CreateDto, event *pl.Event) (e.Encounter, boo } err = tx. + Debug(). Model(&e.Encounter{}). Joins("JOIN \"Ambulatory\" ON \"Ambulatory\".\"Encounter_Id\" = \"Encounter\".\"Id\""). Where("\"Patient_Id\" = ?", i.Patient_Id). - Where("\"Ambulatory\".\"Class_Code\" = ? AND \"Ambulatory\".\"VisitMode_Code\" = ?", ere.ECAmbulatory, ere.VMCSeries). - Where("\"CreatedAt\" > ?", recentEncounterAdm.CreatedAt). + Where("\"Ambulatory\".\"Class_Code\" = ? AND \"Ambulatory\".\"VisitMode_Code\" = ?", ere.ACCRme, ere.VMCSeries). + Where("\"Encounter\".\"CreatedAt\" > ?", recentEncounterAdm.CreatedAt). Count(&countEncounterSeries).Error if err != nil { event.Status = "failed" @@ -402,7 +403,7 @@ func getSoapiEncounterAdm(enc e.Encounter, event *pl.Event) (dataSoapi []es.Crea } } - err = dg.I. + err = dg.I.Debug(). Model(&es.Soapi{}). Joins("JOIN \"Employee\" ON \"Employee\".\"Id\" = \"Soapi\".\"Employee_Id\""). Where("\"Encounter_Id\" = ?", enc.Id). @@ -478,7 +479,7 @@ func getSoapiByTypeCode(encounterId uint, event *pl.Event, mode string) (err err case dataAmbulatory.Class_Code == ere.ACCReg: tx = tx.Where("\"Soapi\".\"TypeCode\" = ?", erc.STCEEarlyMedic) case dataAmbulatory.Class_Code == ere.ACCRme && dataAmbulatory.VisitMode_Code == ere.VMCAdm: - tx = tx.Where("\"Soapi\".\"TypeCode\" IN ?", []erc.SoapiTypeCode{erc.STCEEarlyMedic, erc.STCFunc}) + tx = tx.Where("\"Soapi\".\"TypeCode\" IN ?", []erc.SoapiTypeCode{erc.STCEEarlyMedic, erc.STCFunc, erc.STCEarlyRehab}) case dataAmbulatory.Class_Code == ere.ACCRme && dataAmbulatory.VisitMode_Code == ere.VMCSeries: tx = tx.Where("\"Soapi\".\"TypeCode\" = ?", erc.STCEarlyRehab) } @@ -503,7 +504,7 @@ func validateExistedSoapi(dataSoapi []es.Soapi, dataAmbulatory *ea.Ambulatory, e case dataAmbulatory.Class_Code == ere.ACCReg: required = []erc.SoapiTypeCode{erc.STCEEarlyMedic} case dataAmbulatory.Class_Code == ere.ACCRme && dataAmbulatory.VisitMode_Code == ere.VMCAdm: - required = []erc.SoapiTypeCode{erc.STCEEarlyMedic, erc.STCEarlyRehab, erc.STCFunc} + required = []erc.SoapiTypeCode{erc.STCEEarlyMedic, erc.STCFunc, erc.STCEarlyRehab} case dataAmbulatory.Class_Code == ere.ACCRme && dataAmbulatory.VisitMode_Code == ere.VMCSeries: required = []erc.SoapiTypeCode{erc.STCEarlyRehab} } From c5539522871b673abcd5195ddcd494d6a7de51b9 Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 4 Nov 2025 11:36:24 +0700 Subject: [PATCH 053/329] adjustment entity and constlist --- .../migrations/20251031082443.sql | 2 - .../migrations/20251031084657.sql | 13 -- .../migrations/20251102115856.sql | 2 - .../migrations/20251102141135.sql | 4 - .../migrations/20251104042334.sql | 2 + .../migrations/20251104043530.sql | 19 +++ cmd/main-migration/migrations/atlas.sum | 136 +++++++++--------- internal/domain/main-entities/chemo/entity.go | 4 +- .../domain/references/clinical/clinical.go | 3 +- .../domain/references/encounter/encounter.go | 10 +- .../main-use-case/ambulatory/helper.go | 2 +- .../use-case/main-use-case/encounter/case.go | 2 +- 12 files changed, 102 insertions(+), 97 deletions(-) delete mode 100644 cmd/main-migration/migrations/20251031082443.sql delete mode 100644 cmd/main-migration/migrations/20251031084657.sql delete mode 100644 cmd/main-migration/migrations/20251102115856.sql delete mode 100644 cmd/main-migration/migrations/20251102141135.sql create mode 100644 cmd/main-migration/migrations/20251104042334.sql create mode 100644 cmd/main-migration/migrations/20251104043530.sql diff --git a/cmd/main-migration/migrations/20251031082443.sql b/cmd/main-migration/migrations/20251031082443.sql deleted file mode 100644 index deec65bb..00000000 --- a/cmd/main-migration/migrations/20251031082443.sql +++ /dev/null @@ -1,2 +0,0 @@ --- Modify "Ambulatory" table -ALTER TABLE "public"."Ambulatory" ADD COLUMN "VisitMode_Code" text NULL; diff --git a/cmd/main-migration/migrations/20251031084657.sql b/cmd/main-migration/migrations/20251031084657.sql deleted file mode 100644 index 30974d75..00000000 --- a/cmd/main-migration/migrations/20251031084657.sql +++ /dev/null @@ -1,13 +0,0 @@ --- Create "Rehab" table -CREATE TABLE "public"."Rehab" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Doctor_Id" bigint NULL, - "AllocatedVisitCount" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Rehab_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Rehab_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); diff --git a/cmd/main-migration/migrations/20251102115856.sql b/cmd/main-migration/migrations/20251102115856.sql deleted file mode 100644 index 1593eb5a..00000000 --- a/cmd/main-migration/migrations/20251102115856.sql +++ /dev/null @@ -1,2 +0,0 @@ --- Modify "Ambulatory" table -ALTER TABLE "public"."Ambulatory" DROP CONSTRAINT "fk_Ambulatory_Encounter", ADD CONSTRAINT "fk_Encounter_Ambulatory" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251102141135.sql b/cmd/main-migration/migrations/20251102141135.sql deleted file mode 100644 index 4dafef17..00000000 --- a/cmd/main-migration/migrations/20251102141135.sql +++ /dev/null @@ -1,4 +0,0 @@ --- Modify "Emergency" table -ALTER TABLE "public"."Emergency" DROP CONSTRAINT "fk_Emergency_Encounter", ADD CONSTRAINT "fk_Encounter_Emergency" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; --- Modify "Inpatient" table -ALTER TABLE "public"."Inpatient" DROP CONSTRAINT "fk_Inpatient_Encounter", ADD CONSTRAINT "fk_Encounter_Inpatient" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251104042334.sql b/cmd/main-migration/migrations/20251104042334.sql new file mode 100644 index 00000000..7628d821 --- /dev/null +++ b/cmd/main-migration/migrations/20251104042334.sql @@ -0,0 +1,2 @@ +-- Modify "Chemo" table +ALTER TABLE "public"."Chemo" DROP COLUMN "Class_Code", ADD COLUMN "Bed" character varying(1024) NULL, ADD COLUMN "Needs" character varying(2048) NULL; diff --git a/cmd/main-migration/migrations/20251104043530.sql b/cmd/main-migration/migrations/20251104043530.sql new file mode 100644 index 00000000..0d34792a --- /dev/null +++ b/cmd/main-migration/migrations/20251104043530.sql @@ -0,0 +1,19 @@ +-- Modify "Ambulatory" table +ALTER TABLE "public"."Ambulatory" DROP CONSTRAINT "fk_Ambulatory_Encounter", ADD COLUMN "VisitMode_Code" text NULL, ADD CONSTRAINT "fk_Encounter_Ambulatory" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "Emergency" table +ALTER TABLE "public"."Emergency" DROP CONSTRAINT "fk_Emergency_Encounter", ADD CONSTRAINT "fk_Encounter_Emergency" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "Inpatient" table +ALTER TABLE "public"."Inpatient" DROP CONSTRAINT "fk_Inpatient_Encounter", ADD CONSTRAINT "fk_Encounter_Inpatient" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Create "Rehab" table +CREATE TABLE "public"."Rehab" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Doctor_Id" bigint NULL, + "AllocatedVisitCount" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Rehab_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Rehab_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index eca39d6d..c701690e 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,67 +1,69 @@ -h1:DcO8hW6ltApCY7bmxeSji280ls5j97uZeEb034pHQqY= -20250904105930.sql h1:Vv4vCurl7m7/ZB6TjRpkubHpQ4RYwSUn0QHdzfoGpzY= -20250904141448.sql h1:FYCHH9Os4KkrZMDu/jR8FMP+wLMRW+Mb0PkLU/9BRDg= -20250908062237.sql h1:oanBpKZd+akPu2I/xYhUSbd0G5tAFbXzKLER/Zs8ENI= -20250908062323.sql h1:miNG9COddXkD1jGTgaROMAZ618eT6oiLGiJhXWnQwhE= -20250908073811.sql h1:gOi5cnGG1htlpfizybYmUIT0vYjZTBfXiI0nPSYK2u8= -20250908073839.sql h1:cWNDA4YikjoOteAJuNLFILjQUJPFB6o8Wxreiek4QyI= -20250910055902.sql h1:nxxOGnU0BbH/v3IPgeIOXOwH8d3tKomw7h6FTeMnnBs= -20250915123412.sql h1:mz7SiWfrdf0qE1VTSAAnA/147d6gyp6ry5vZ2bR9SH0= -20250916043819.sql h1:RHXVtmMkB6wfv06HfPyHMBmUfIpFt1xveafNz0kwKnE= -20250917040616.sql h1:MYVDht+akBlzQGKNu2hTTTLPEcH1bxT/Q8MK6WEtuhs= -20250917040751.sql h1:J79YyS2JzWgh5oKXMTgh67uo3gLxKaAsxRiZmSIfjBs= -20250917045138.sql h1:/SM1N4O8X3yxpoJgMEARmS1uOkuLKsTOy4PLsRCOKaQ= -20250917093645.sql h1:PNBTGZ7s10e5b5+Tie8YfVQBN0zKtJ5T34oK1iOUEb4= -20250918073552.sql h1:jG7+g3i8ODYaJdcdZz12v3nbsZ5mB9wG6kWnGyTQIRI= -20250918073742.sql h1:j+rgw7puxE7s+phqPVZHmPk0af3rcaA56Itp86y1suY= -20250918074745.sql h1:rPmP4DXs6OnY4Vp+xO/z9jFpJt/RrJ52SJJjIIxeDvc= -20250923025134.sql h1:2r6pcwnBSU5Y9Czk1OHBoh4yZXiMtEca9X8843fTEX0= -20250924051317.sql h1:iUAk2gsGoEGIPQ0lEEUp8maMSId8emNbP+kP712ABIA= -20250929034321.sql h1:UlpALNVmdi95zOIT0yc6ZyTj9bBjQEIpZhvgrc52M+k= -20250929034428.sql h1:feF+H4nDyHh5bdx48Oiz0A1qecZfi6v3qTTdjzJ45Dg= -20250930025550.sql h1:6XT1kXI3Z3ZIxxmvT7poufZWWCW0QiejZPaFV5wBnjI= -20250930140351.sql h1:HxnmAbh9gCy8jwl/9ycGktiByaUripsjFFvohofY2CY= -20251002085604.sql h1:SjLPi+ZN6qDccK3DaEQCgNsZpPwr5kynWXwbwEsziCI= -20251003032030.sql h1:oHfxNSuqTxU8Zaf9H+h8TuUb1Da03wcyc6hZjDrUQ2s= -20251005060450.sql h1:GIuCcrd4MwjmXpvbzDzPYL18BV3QaZZ+Y2FmEzjvi0E= -20251006041122.sql h1:uNDQbSw0M08lYoMvUNlQtS3iDzpPM1ixT13ugSAoWjE= -20251006045658.sql h1:z+t7yCK54Q4SSiF9kUyUhkYB2F+kzSW9TB7ogxd9wzw= -20251006045928.sql h1:1lATLFLp4BWwGZqAjZdP0Dc6ypNXiYcwjoNkqGa8NFE= -20251007022859.sql h1:HXXwWrkyvzJzJGAt9mGskCRBBV/c1JfPmfjDocmJhQ4= -20251008031337.sql h1:Ln5pCF3Hxa5foHZLcds+z/us2eH6VAhhEj3w0TAGlVs= -20251008031554.sql h1:aB4MUS2lmqG0//4HKUWorcPSpWya0VC4QItvGyskEVI= -20251008052346.sql h1:MI3AZgU5XcwZT2OvvlWAxdRtL0eJ3jjRwt56IY1+pRU= -20251008073620.sql h1:sztWXuSNYwpEraaSapSsYwno75LO5H/N7ob7OJQ8X/A= -20251009042854.sql h1:TnPXj+dCJls3IU//cuqJZymyBzZMKs7ayazfgtAFRxM= -20251009052657.sql h1:leXbs0CP8r5dRilmYyLRk1MICqak3ea1/LWMtFrijqQ= -20251010031743.sql h1:SgHNY/lQ88G2F4nZyMfiOkDntb+gtOR+nEQLqXBTwv4= -20251010070721.sql h1:AnJnhXsMzDvK4AFgYw6B16Kpo/hljrZtcpc9m2VOSHQ= -20251010072711.sql h1:aXPTtNwLcTuw8C/yAxwxvqs0ayEjNzI1uuE0vE3ERa8= -20251013044536.sql h1:7Pq6JcvTpPBYDCW2dz3HdgUwY65HlhEVWy9TiG8iONE= -20251013051438.sql h1:X6t8bkqpUYYokBunSufMQUe5vCg0VyO6dxbm7ngosUc= -20251013081808.sql h1:495pLguXL2Ozh+ycn4UYZgZbn6WbjXNbyZUc3JU8qhI= -20251014060047.sql h1:nCgImMRGHhziiW57O1ofWaXCAPGaCOHN7PldQ3OSmM4= -20251014063537.sql h1:2cLmID79jP6cuQ1YJaWTtghFiM1GtHMC0ZQl30Hpy1M= -20251014063720.sql h1:bzLKKVAjSHgDFoiI/glj7t1ETlSAKx+AlsIAaP0ru2g= -20251015045455.sql h1:S547+UugQhlTRcn1Lm1IfqT5RNPttIWIiD+RTx69YaE= -20251016010845.sql h1:c9DUvxl17pUkf0azdYGM/YDzYxIJkLcfZOcMI4rL+R0= -20251016011023.sql h1:u3ivg83bXgYHBbojbWpemLxPE9Dmmj53B6LXo664jxw= -20251016062912.sql h1:W9n1hWchfYkqNX9LO9uxFxEXAb/iY+Pexjnhmp6PbgI= -20251017060617.sql h1:VU6yZ2+LfHpDZ3+TIH40t3F5YXPCpTppuF9+uSqa4b8= -20251017082207.sql h1:QshZslfedckz7iDpSGmPyY9sP6dy6ckHbs8L1TuXIA4= -20251018032635.sql h1:M1U/9W/F9wlW5YDmVAmHFfUJU7FWFaX0DblpfZcYWrE= -20251018040322.sql h1:Zk/vw0e6AzWFO2ElLOzB+OrSz6k+h1Ynxp0TImAzxwY= -20251019093915.sql h1:3Q0kPiZwJnHn5rAvdh0w1LBdiA7W2xBmZWncoPXb044= -20251020062553.sql h1:mJwC/J8GzPAIXckNMvy1f/Nguk2VVf8roD/Raclhbao= -20251021041042.sql h1:d1BAOGAQhqr+oOwcpAVozUsTh457VSDEk2qQFavGG58= -20251021075552.sql h1:TNChGQ1Zlr/1iQ6qvK4iDTAJpe6L/z/M6e/O0SkQVaM= -20251023044432.sql h1:GA2AdJk2ULyjr6igtu9C/CEi4YUIks8r9jXGGaCvPsk= -20251024034832.sql h1:RXmbEhMkOLK5g1QL6up8iRPcwYfo89oLP26ZHvrUK9o= -20251024074315.sql h1:3GnPQSbuAAfMa8oWDyBjhXqn1j1zunY/w0ydX0IGPrA= -20251025013451.sql h1:5eNrA9LDxA4i5CCP7wSyOgFZ6t6jBWVil+oGzJpkJ2E= -20251025013609.sql h1:+N6EHc1kv3hqf16CUhXe+UITPmoxOPfi4MECLmJXNrc= -20251027075128.sql h1:PQflgsjce/p2ClbybLtdehdPNDcMZ9Lb1vd98xd0K8E= -20251027091406.sql h1:bYXV57GvodCMjg0/ox+XKGIAGhrDlVuJ1wO4foNEKtQ= -20251102002037.sql h1:ZcwULsJU2lI9t5pX7ukmfAHSx4ZxdxLUX6jzLDc2SrU= -20251102091932.sql h1:A6y9j4wAqm4/HfMDxhpy/ChDn3UNRVN99KGgSCX+e18= -20251103081637.sql h1:RFqJNhJItSwJQaMP5IcQ14mL7eQ3EJjGZua9zLWzwMU= +h1:DapfqgPn4h3ozXgxIdxW/bzPLHdc//0uHjK+W42/jic= +20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= +20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= +20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= +20250908062323.sql h1:oXl6Z143tOpIl4EfP4B8JNU8LrMvVmHEtCgAfiB4gs8= +20250908073811.sql h1:m2aNXfnGxnLq1+rVWrh4f60q7fhyhV3gEwNu/OIqQlE= +20250908073839.sql h1:cPk54xjLdMs26uY8ZHjNWLuyfAMzV7Zb0/9oJQrsw04= +20250910055902.sql h1:5xwjAV6QbtZT9empTJKfhyAjdknbHzb15B0Ku5dzqtQ= +20250915123412.sql h1:D83xaU2YlDEd21HLup/YQpQ2easMToYCyy/oK6AFgQs= +20250916043819.sql h1:ekoTJsBqQZ8G8n0qJ03d13+eoNoc7sAUEQGA5D/CCxk= +20250917040616.sql h1:zoCnmcXuM7AVv85SmN7RmFglCgJnoDmpRWExH0LAc9Q= +20250917040751.sql h1:J1xyRrh32y1+lezwAyNwPcUQ6ABBSgbvzNLva4SVdQU= +20250917045138.sql h1:jKe1Z0uOLG4SGBYM+S/3P+/zMPztmgoderD5swnMuCg= +20250917093645.sql h1:cNI3Pbz1R3LxvIXLuexafJFCXUXrmuFCgXXJ2sG+FW0= +20250918073552.sql h1:RJ1SvMzP6aeWnoPVD3eVAmIQOkcp6Php8z3QRri6v4g= +20250918073742.sql h1:+cEsnJTJFybe2fR69ZoOiX2R6c6iITl4m6WTZ1hjyzY= +20250918074745.sql h1:2hNVQCXF/dVYXAh+T/7oBFgERGWxzVb2FXJjwkFWGCI= +20250923025134.sql h1:Ykz/qpHiGDXPsCsWTjydQFVSibZP2D+h2fIeb2h2JGA= +20250924051317.sql h1:yQuW6SwJxIOM5fcxeAaie5lSm1oLysU/C2hH2xNCVoQ= +20250929034321.sql h1:101FJ8VH12mrZWlt/X1gvKUGOhoiF8tFbjiapAjnHzg= +20250929034428.sql h1:i+pROD9p+g5dOmmZma6WF/0Hw5g3Ha28NN85iTo1K34= +20250930025550.sql h1:+F+CsCUXD/ql0tHGEow70GhPBX1ZybVn+bh/T4YMh7Y= +20250930140351.sql h1:9AAEG1AnOAH+o0+oHL5G7I8vqlWOhwRlCGyyCpT/y1Q= +20251002085604.sql h1:3xZ68eYp4urXRnvotNH1XvG2mYOSDV/j3zHEZ/txg5E= +20251003032030.sql h1:HB+mQ2lXMNomHDpaRhB/9IwYI9/YiDO5eOJ+nAQH/jw= +20251005060450.sql h1:LbtCE2b+8osM3CvnmQJH1uCPtn+d7WchsslBOz8bL3Q= +20251006041122.sql h1:MlS7f21z06sutnf9dIekt5fuHJr4lgcQ4uCuCXAGsfc= +20251006045658.sql h1:3FmGCPCzjgMPdWDRodZTsx3KVaodd9zB9ilib69aewk= +20251006045928.sql h1:Z5g31PmnzNwk/OKdODcxZGm8fjJQdMFK32Xfnt3bRHg= +20251007022859.sql h1:FO03zEfaNEk/aXwY81d5Lp3MoBB9kPQuXlXJ4BPiSR8= +20251008031337.sql h1:l+sxUAGvcTfj3I6kAFHo+T6AYodC9k9GkR+jaKO2xXc= +20251008031554.sql h1:AqrVfIhSzY3PCy8ZlP5W91wn2iznfIuj5qQfubp6/94= +20251008052346.sql h1:nxnXmooIJ6r1mmzwnw+6efxLfc/k9h2aE6RMptPRons= +20251008073620.sql h1:6YsJp1W4SmQJ1lxpqF27BBlDC1zqhw7Yhc7pLzQTY6M= +20251009042854.sql h1:nkBV+R6j0fg7/JY6wH3eb5Vv0asJLnXmb6lINfT/GLQ= +20251009052657.sql h1:EPvdsib5rzCGPryd10HShGKvFPwM/R5S2lIVwtYxpms= +20251010031743.sql h1:T8IZmx8/btRFKLzTe78MzcBsPJNodnLvB0tby9QkirQ= +20251010070721.sql h1:5NQUk/yOV6sABLCB7swx++YIOyJe6MnU+yt1nRzde5w= +20251010072711.sql h1:ZJNqR2piyu8xJhBvVABSlnGEoKSKae3wuEs+wshPe4k= +20251013044536.sql h1:0Xjw8fNILiT8nnfrJDZgQnPf3dntmIoilbapnih8AE4= +20251013051438.sql h1:lfSuw5mgJnePBJamvhZ81osFIouXeiIEiSZ/evdwo48= +20251013081808.sql h1:ijgjNX08G6GBjA/ks8EKtb7P7Y7Cg7zbhqEOruGnv6M= +20251014060047.sql h1:0jqj49WTtneEIMQDBoo4c095ZGi8sCrA8NnHBrPU6D8= +20251014063537.sql h1:VZLXol0PTsTW21Epg6vBPsztWkDtcxup9F/z88EGgIg= +20251014063720.sql h1:2HVUyCV0ud3BJJDH2GEKZN/+IWLFPCsN1KqhP6csO14= +20251015045455.sql h1:MeLWmMhAOAz8b15Dd7IAQnt6JxjSml02XCXK22C0Lpg= +20251016010845.sql h1:4BncQdDOasRZJkzVJrSJJA7091A9VPNVx/faUCUPhBM= +20251016011023.sql h1:9JB9eFZKURK5RoCVDKR6glSvdJ8NTXrN7K/4q51zkz4= +20251016062912.sql h1:ACNn0fe+EMqUt3hoY+Dr3uqAV/QICBa1+mIW7fUc9Fk= +20251017060617.sql h1:4T3t9ifWrEQTPMSM0XJ98pF7Qdt+UfgtMui17bhrnWI= +20251017082207.sql h1:8vLG1l/saRRMHXkyA4nelJyjaSddhZd6r7R+Uo4JS/c= +20251018032635.sql h1:2xey5gnO3y2XSOrU8MLlIfoylPKbRGDRtHDD07B3MbQ= +20251018040322.sql h1:k/pdNiSoT8zFPqNQ/avOD0vYkNh3BTD64IlHrfVXr7I= +20251019093915.sql h1:hFcQE0y+p5dZiVwePGsRGto9m/q6kJNiUZbVDd5Rnjk= +20251020062553.sql h1:Iw7hulcm5iRQlfW+ygA4iTPxLqkxx6h9vXMXEwUAHKs= +20251021041042.sql h1:wMgSivBV2A0NDcsLmKGIp0kMcVh2IODSG9b4dgzCaOM= +20251021075552.sql h1:8gfSMAglflNO6L0sSzxFNEubYN8/O4thT7OQT+WH+3M= +20251023044432.sql h1:MkvajJs3bfk9+wHvQ43/ccAluJEBARm1gWr1u92ccLA= +20251024034832.sql h1:x3s3VEVYLOSKLAFxJGb2+c1FyTMMvPE+9k4Ew7rKQaI= +20251024074315.sql h1:EjAjelgi5qAfcRq/8vPTlGGYHvAKxNTllm8f0SzZDns= +20251025013451.sql h1:6hnuIiwYiG+6nLhOY/+Yyn+I6ZCFNRZxrJNqBV6HLqE= +20251025013609.sql h1:evPJaTD8WxYRMOJZHkSr7ONLx9PYxT+ankzQt9c/sJ0= +20251027075128.sql h1:/iFQBM1sytjqpyQSOx61q33gnorMgxTiFVSuL6bQqsM= +20251027091406.sql h1:eCZGtUkxAzEAqpC9UsGpP8Df9mS0DEOqSl885LgqpvM= +20251102002037.sql h1:lFJbuoZ2LMQnUNGdcwHVY3Xlfslgzu9t2WByT8yfOZI= +20251102091932.sql h1:rmdhb5m+P+fU8jROBZNyeYgZKuQvucsuljXv4ZVzvks= +20251103081637.sql h1:tf3BcwTeIw+oxMEisKDDfyKnBfalTLs8b0PJA8JWYxY= +20251104042334.sql h1:a76eSmiEVviWWjsfAkiriDxRYGhlg8qIjZ2CVQZDnbA= +20251104043530.sql h1:tGP1AhyYzPZAA05IwfJfWWhNISrud3xCmeRFdZ/28SQ= diff --git a/internal/domain/main-entities/chemo/entity.go b/internal/domain/main-entities/chemo/entity.go index 4052ea72..a56dae76 100644 --- a/internal/domain/main-entities/chemo/entity.go +++ b/internal/domain/main-entities/chemo/entity.go @@ -9,7 +9,6 @@ import ( eus "simrs-vx/internal/domain/main-entities/user" erc "simrs-vx/internal/domain/references/common" - ere "simrs-vx/internal/domain/references/encounter" ) type Chemo struct { @@ -22,5 +21,6 @@ type Chemo struct { VerifiedBy *eus.User `json:"verifiedBy,omitempty" gorm:"foreignKey:VerifiedBy_User_Id;references:Id"` SrcUnit_Id *uint `json:"src_unit_id"` SrcUnit *eun.Unit `json:"src_unit,omitempty" gorm:"foreignKey:SrcUnit_Id;references:Id"` - Class_Code ere.ChemoClassCode `json:"class_code"` + Bed *string `json:"bed" gorm:"size:1024"` + Needs *string `json:"needs" gorm:"size:2048"` } diff --git a/internal/domain/references/clinical/clinical.go b/internal/domain/references/clinical/clinical.go index c0eb3594..8120adb3 100644 --- a/internal/domain/references/clinical/clinical.go +++ b/internal/domain/references/clinical/clinical.go @@ -113,11 +113,12 @@ const ( MULCPF McuUrgencyLevelCode = "priority-form" // Form Prioritas MULCRT McuUrgencyLevelCode = "routine" // Pemeriksaan Rutin - STCEarlyNurse SoapiTypeCode = "early-nurse" // Kajian Awal Medis + //STCEarlyNurse SoapiTypeCode = "early-nurse" // Kajian Awal Medis STCEEarlyMedic SoapiTypeCode = "early-medic" // Kajian Awal Rehab Medis STCEarlyRehab SoapiTypeCode = "early-rehab" // Kajian Awal Rehab Medik STCFunc SoapiTypeCode = "function" // Assessment Fungsi STCProgress SoapiTypeCode = "progress" // CPPT + STCDevRecord SoapiTypeCode = "dev-record" // Catatan Perkembangan MAChemo MedicalAction = "chemo" MAHemo MedicalAction = "hemo" diff --git a/internal/domain/references/encounter/encounter.go b/internal/domain/references/encounter/encounter.go index fb133473..97eae05b 100644 --- a/internal/domain/references/encounter/encounter.go +++ b/internal/domain/references/encounter/encounter.go @@ -70,10 +70,12 @@ const ( CSCPLab CheckupScopeCode = "pa-lab" // Patology Anatomy Laboratorium CSCRad CheckupScopeCode = "radiology" // Radiology - ACCReg AmbulatoryClassCode = "reg" // Regular - ACCRme AmbulatoryClassCode = "rme" // Rehab Medik - ACCCad AmbulatoryClassCode = "chemo-adm" // Chemotherapy - ACCCac AmbulatoryClassCode = "chemo-act" // Chemotherapy + ACCReg AmbulatoryClassCode = "reg" // Regular + // ACCRehab ACCRme AmbulatoryClassCode = "rme" // Rehab Medik + // ACCCad AmbulatoryClassCode = "chemo-adm" // Chemotherapy + // ACCCac AmbulatoryClassCode = "chemo-act" // Chemotherapy + ACCRehab AmbulatoryClassCode = "rehab" // Rehab Medik + ACCChemo AmbulatoryClassCode = "chemo" // Rehab Medik ICCIp InpatientClassCode = "ip" // Regular Rawat Inap ICCICU InpatientClassCode = "icu" // ICU diff --git a/internal/use-case/main-use-case/ambulatory/helper.go b/internal/use-case/main-use-case/ambulatory/helper.go index f78f0b65..912211c0 100644 --- a/internal/use-case/main-use-case/ambulatory/helper.go +++ b/internal/use-case/main-use-case/ambulatory/helper.go @@ -28,7 +28,7 @@ func CheckClassCode(input *string) (ere.AmbulatoryClassCode, error) { if input != nil { subCode := ere.AmbulatoryClassCode(*input) switch subCode { - case ere.ACCReg, ere.ACCRme, ere.ACCCad, ere.ACCCac: + case ere.ACCReg, ere.ACCRehab, ere.ACCChemo: return subCode, nil default: return "", errors.New("unknown sub class code") diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 11b17e2b..829cf86c 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -104,7 +104,7 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } - if subCode == ere.ACCCac || subCode == ere.ACCCad { + if subCode == ere.ACCChemo { chemoCreate := ec.CreateDto{ Encounter_Id: &data.Id, Status_Code: erc.DVCNew, From c6eaaa2c10c0c2ff798c1bc78fe877c23342818d Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 4 Nov 2025 14:05:56 +0700 Subject: [PATCH 054/329] finish adjustment encounter --- .../encounter/request-validation.go | 2 +- .../use-case/main-use-case/encounter/case.go | 66 ++- .../main-use-case/encounter/helper.go | 387 +++++++++++++++++- .../use-case/main-use-case/encounter/lib.go | 288 +------------ 4 files changed, 415 insertions(+), 328 deletions(-) diff --git a/internal/interface/main-handler/encounter/request-validation.go b/internal/interface/main-handler/encounter/request-validation.go index d3a7afe4..b7d31e71 100644 --- a/internal/interface/main-handler/encounter/request-validation.go +++ b/internal/interface/main-handler/encounter/request-validation.go @@ -68,7 +68,7 @@ func validateRequestCreate(w http.ResponseWriter, i e.CreateDto) (valid bool) { switch { case i.Class_Code == ere.ECAmbulatory: // field allocatedVisitCount required if ambulatory visitMode_Code is adm - if ere.AmbulatoryClassCode(*i.SubClass_Code) == ere.ACCRme && *i.VisitMode_Code == ere.VMCAdm { + if ere.AmbulatoryClassCode(*i.SubClass_Code) == ere.ACCRehab && *i.VisitMode_Code == ere.VMCAdm { if *i.AllocatedVisitCount == 0 { rw.DataResponse(w, nil, d.FieldError{ Code: dataValidationFail, diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index fa55f222..ef70d9c2 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -38,7 +38,6 @@ import ( uem "simrs-vx/internal/use-case/main-use-case/employee" ui "simrs-vx/internal/use-case/main-use-case/inpatient" ur "simrs-vx/internal/use-case/main-use-case/rehab" - urdh "simrs-vx/internal/use-case/main-use-case/responsible-doctor-hist" us "simrs-vx/internal/use-case/main-use-case/soapi" ) @@ -66,7 +65,7 @@ func Create(input e.CreateDto) (*d.Data, error) { } // verify whether the allocated visit count has not exceeded the limit - if input.Class_Code == ere.ECAmbulatory && subCode.(ere.AmbulatoryClassCode) == ere.ACCRme && + if input.Class_Code == ere.ECAmbulatory && subCode.(ere.AmbulatoryClassCode) == ere.ACCRehab && *input.VisitMode_Code == ere.VMCSeries { dataEncounter, valid, err := verifyAllocatedVisitCount(input, &event) @@ -150,7 +149,7 @@ func Create(input e.CreateDto) (*d.Data, error) { } } - if subCodeAmbulatory == ere.ACCRme && *input.VisitMode_Code == ere.VMCAdm { + if subCodeAmbulatory == ere.ACCRehab && *input.VisitMode_Code == ere.VMCAdm { // create data rehab if _, err = ur.CreateData(er.CreateDto{ Encounter_Id: &data.Id, @@ -158,7 +157,7 @@ func Create(input e.CreateDto) (*d.Data, error) { AllocatedVisitCount: input.AllocatedVisitCount}, &event, tx); err != nil { return err } - } else if subCodeAmbulatory == ere.ACCRme && *input.VisitMode_Code == ere.VMCSeries { + } else if subCodeAmbulatory == ere.ACCRehab && *input.VisitMode_Code == ere.VMCSeries { // Insert Soapi if err = us.CreateBulkData(createSoapi, data.Id, &event, tx); err != nil { return err @@ -442,7 +441,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { } func CheckOut(input e.DischargeDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Ambulatory"} var data *e.Encounter var err error @@ -470,13 +469,14 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - if data.Class_Code == ere.ECAmbulatory { + if data.Ambulatory != nil && (data.Ambulatory.Class_Code == ere.ACCReg || data.Ambulatory.Class_Code == ere.ACCRehab) { // validate if soapi exist - err = getSoapiByTypeCode(input.Id, &event, "check-out") + err = getSoapiByTypeCode(input.Id, *data.Ambulatory, &event, "check-out") if err != nil { return err } } else { + // chemo TBC if err := checkSoapiByDocExists(data.Id, &event, tx); err != nil { return err } @@ -605,7 +605,7 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) { } func CheckIn(input e.CheckinDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Rehab"} + rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Rehab,Ambulatory"} var data *e.Encounter var err error @@ -627,12 +627,6 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { input.StartedAt = &now } - // validate if soapi exist - err = getSoapiByTypeCode(input.Id, &event, "check-in") - if err != nil { - return nil, err - } - err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") if data, err = ReadDetailData(rdDto, &event, tx); err != nil { @@ -649,34 +643,34 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - // Insert responsible_doctor_hist if responsible_doctor_id has changed && update latest history - if data.Responsible_Doctor_Id == nil || *input.Responsible_Doctor_Id != *data.Responsible_Doctor_Id { - // update finishedAt in latest responsible_doctor_hist - if err = updateLatestResponsibleDoctorHist(input, &event, tx); err != nil { + // validate if soapi exist + if data.Ambulatory != nil && (data.Ambulatory.Class_Code == ere.ACCReg || data.Ambulatory.Class_Code == ere.ACCRehab) { + err = getSoapiByTypeCode(input.Id, *data.Ambulatory, &event, "check-in") + if err != nil { return err } + } - //insert responsible_doctor_hist - if _, err = urdh.CreateData(erdh.CreateDto{ - Encounter_Id: &input.Id, + // Insert responsible_doctor_hist if responsible_doctor_id has changed && update latest history + if data.Responsible_Doctor_Id == nil || *input.Responsible_Doctor_Id != *data.Responsible_Doctor_Id { + // upsert responsibleDoctorHist + if err = upsertResponsibleDoctorHist(erdh.CreateDto{ + Encounter_Id: &data.Id, Doctor_Id: input.Responsible_Doctor_Id, - StartedAt: input.StartedAt}, &event, tx); err != nil { + StartedAt: input.StartedAt, + }, &event, tx); err != nil { return err } } // Insert adm_employee_hist if adm_employee_id has changed && update latest history if input.Adm_Employee_Id != nil && *input.Adm_Employee_Id != *data.Adm_Employee_Id { - // update finishedAt in latest adm_employee_hist - if err = updateLatestAdmEmployeeHist(input, &event, tx); err != nil { - return err - } - - // insert responsible_doctor_hist - if _, err = uaeh.CreateData(eaeh.CreateDto{ - Encounter_Id: &input.Id, + // upsert admEmployeeHist + if err = upsertAdmEmployeeHist(eaeh.CreateDto{ + Encounter_Id: &data.Id, Employee_Id: input.Adm_Employee_Id, - StartedAt: input.StartedAt}, &event, tx); err != nil { + StartedAt: input.StartedAt, + }, &event, tx); err != nil { return err } } @@ -686,13 +680,13 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { return err } - if err := updateRehabDoctor(er.UpdateDto{ - CreateDto: er.CreateDto{ + if data.Ambulatory.Class_Code == ere.ACCRehab { + if err := updateRehabDoctor(er.UpdateDto{CreateDto: er.CreateDto{ Encounter_Id: &data.Id, Doctor_Id: input.Responsible_Doctor_Id, - }, - }, &event, tx); err != nil { - return err + }}, &event, tx); err != nil { + return err + } } pl.SetLogInfo(&event, nil, "complete") diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index c5eb155e..4bf7be60 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -7,17 +7,25 @@ package encounter import ( "errors" "fmt" - uir "simrs-vx/internal/use-case/main-use-case/internal-reference" "strings" "time" + dg "github.com/karincake/apem/db-gorm-pg" "gorm.io/gorm" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" + ercl "simrs-vx/internal/domain/references/clinical" + erc "simrs-vx/internal/domain/references/common" + ere "simrs-vx/internal/domain/references/encounter" + erg "simrs-vx/internal/domain/references/organization" + + eaeh "simrs-vx/internal/domain/main-entities/adm-employee-hist" + ea "simrs-vx/internal/domain/main-entities/ambulatory" edo "simrs-vx/internal/domain/main-entities/device-order" ed "simrs-vx/internal/domain/main-entities/doctor" + e "simrs-vx/internal/domain/main-entities/encounter" emo "simrs-vx/internal/domain/main-entities/material-order" emco "simrs-vx/internal/domain/main-entities/mcu-order" em "simrs-vx/internal/domain/main-entities/medication" @@ -26,20 +34,21 @@ import ( emmi "simrs-vx/internal/domain/main-entities/medicine-mix-item" ep "simrs-vx/internal/domain/main-entities/prescription" epi "simrs-vx/internal/domain/main-entities/prescription-item" + er "simrs-vx/internal/domain/main-entities/rehab" + erdh "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" eu "simrs-vx/internal/domain/main-entities/unit" // udo "simrs-vx/internal/use-case/main-use-case/device-order" es "simrs-vx/internal/domain/main-entities/soapi" + uaeh "simrs-vx/internal/use-case/main-use-case/adm-employee-hist" + uir "simrs-vx/internal/use-case/main-use-case/internal-reference" um "simrs-vx/internal/use-case/main-use-case/medication" umei "simrs-vx/internal/use-case/main-use-case/medication-item" umi "simrs-vx/internal/use-case/main-use-case/medicine-mix" ummi "simrs-vx/internal/use-case/main-use-case/medicine-mix-item" up "simrs-vx/internal/use-case/main-use-case/prescription" upi "simrs-vx/internal/use-case/main-use-case/prescription-item" - - e "simrs-vx/internal/domain/main-entities/encounter" - erc "simrs-vx/internal/domain/references/common" - erg "simrs-vx/internal/domain/references/organization" + urdh "simrs-vx/internal/use-case/main-use-case/responsible-doctor-hist" ) func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Encounter) { @@ -432,3 +441,371 @@ func getDoctors(doctorIds []uint, event *pl.Event, tx *gorm.DB) ([]ed.Doctor, er } return doctors, nil } + +func upsertResponsibleDoctorHist(input erdh.CreateDto, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + var latest erdh.ResponsibleDoctorHist + err := tx. + Where("\"Encounter_Id\" = ?", input.Encounter_Id). + Order("\"CreatedAt\" DESC"). + Limit(1). + First(&latest).Error + + switch { + case errors.Is(err, gorm.ErrRecordNotFound): + // Insert + if _, err = urdh.CreateData(input, event, tx); err != nil { + return err + } + case err != nil: + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "read-fail", + Detail: "Failed to read responsible doctor history", + Raw: err, + } + return pl.SetLogError(event, input) + default: + // Update + if err := tx.Model(&latest).Updates(map[string]interface{}{ + "Doctor_Id": input.Doctor_Id, + "StartedAt": input.StartedAt, + "UpdatedAt": time.Now(), + }).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "update-fail", + Detail: "Failed to update responsible doctor history", + Raw: err, + } + return pl.SetLogError(event, input) + } + } + pl.SetLogInfo(event, input, "complete") + return nil +} + +func upsertAdmEmployeeHist(input eaeh.CreateDto, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + var latest eaeh.AdmEmployeeHist + err := tx. + Where("\"Encounter_Id\" = ?", input.Encounter_Id). + Order("\"CreatedAt\" DESC"). + Limit(1). + First(&latest).Error + + switch { + case errors.Is(err, gorm.ErrRecordNotFound): + // Insert + if _, err = uaeh.CreateData(input, event, tx); err != nil { + return err + } + case err != nil: + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "read-fail", + Detail: "Failed to read responsible doctor history", + Raw: err, + } + return pl.SetLogError(event, input) + + default: + // Update + if err := tx.Model(&latest).Updates(map[string]interface{}{ + "Employee_Id": input.Employee_Id, + "StartedAt": input.StartedAt, + "UpdatedAt": time.Now(), + }).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "update-fail", + Detail: "Failed to update responsible doctor history", + Raw: err, + } + return pl.SetLogError(event, input) + } + } + pl.SetLogInfo(event, input, "complete") + + return nil +} + +func updateLatestResponsibleDoctorHist(input e.CheckinDto, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, "started", "DBUpdate") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + subQuery := tx. + Select("\"Id\""). + Model(&erdh.ResponsibleDoctorHist{}). + Where("\"Encounter_Id\" = ?", input.Id). + Order("\"CreatedAt\" DESC"). + Limit(1) + + result := tx. + Model(&erdh.ResponsibleDoctorHist{}). + Where("\"Id\" = (?)", subQuery). + Update("\"FinishedAt\"", input.StartedAt) + + if result.Error != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-update-fail", + Detail: "Database update failed", + Raw: result.Error, + } + return pl.SetLogError(event, input) + } + + if result.RowsAffected == 0 { + pl.SetLogInfo(event, input, "no previous data found to update") + return nil + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} + +func updateLatestAdmEmployeeHist(input e.CheckinDto, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, "started", "DBUpdate") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + subQuery := tx. + Select("\"Id\""). + Model(&eaeh.AdmEmployeeHist{}). + Where("\"Encounter_Id\" = ?", input.Id). + Order("\"CreatedAt\" DESC"). + Limit(1) + + result := tx. + Model(&eaeh.AdmEmployeeHist{}). + Where("\"Id\" = (?)", subQuery). + Update("\"FinishedAt\"", input.StartedAt) + + if result.Error != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-update-fail", + Detail: "Database update failed", + Raw: result.Error, + } + return pl.SetLogError(event, input) + } + + if result.RowsAffected == 0 { + pl.SetLogInfo(event, input, "no previous data found to update") + return nil + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} + +func getSoapiEncounterAdm(enc e.Encounter, event *pl.Event) (dataSoapi []es.CreateDto, err error) { + var data []es.Soapi + + pl.SetLogInfo(event, enc, "started", "DBReadList") + + if enc.Responsible_Doctor == nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "no responsible-doctor found", + Detail: "Encounter does not have responsible-doctor", + } + } + + err = dg.I.Debug(). + Model(&es.Soapi{}). + Joins("JOIN \"Employee\" ON \"Employee\".\"Id\" = \"Soapi\".\"Employee_Id\""). + Where("\"Encounter_Id\" = ?", enc.Id). + Where("\"Employee\".\"Position_Code\" = ?", erg.EPCDoc). + Where("\"Soapi\".\"TypeCode\" IN ?", []ercl.SoapiTypeCode{ercl.STCEEarlyMedic, ercl.STCFunc}). + Where("\"Soapi\".\"Employee_Id\" = ?", *enc.Responsible_Doctor.Employee_Id). + Find(&data).Error + + if err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Raw: err, + } + + if errors.Is(err, gorm.ErrRecordNotFound) { + event.ErrInfo.Code = "data-not-found" + event.ErrInfo.Detail = "Data not found" + return nil, pl.SetLogError(event, enc) + } + + event.ErrInfo.Code = "read-fail" + event.ErrInfo.Detail = "Database read failed" + return nil, pl.SetLogError(event, enc) + } + + pl.SetLogInfo(event, nil, "complete") + + for _, s := range data { + // set data soapi for copy + dataSoapi = append(dataSoapi, es.CreateDto{ + Employee_Id: s.Employee_Id, + Time: s.Time, + TypeCode: s.TypeCode, + Value: s.Value, + }) + } + + if len(dataSoapi) < 2 { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "missing-soapi", + Detail: fmt.Sprintf("Missing required Soapi types"), + } + return nil, pl.SetLogError(event, enc) + } + return +} + +func getSoapiByTypeCode(encounterId uint, dataAmbulatory ea.Ambulatory, event *pl.Event, mode string) (err error) { + pl.SetLogInfo(event, encounterId, "started", "DBReadList") + + var ( + dataSoapi []es.Soapi + ) + + // Set Query for get data Soapi + tx := dg.I. + Model(&es.Soapi{}). + Joins("JOIN \"Employee\" ON \"Employee\".\"Id\" = \"Soapi\".\"Employee_Id\""). + Where("\"Encounter_Id\" = ?", encounterId). + Where("\"Employee\".\"Position_Code\" = ?", erg.EPCDoc) + + // Set Case + switch { + case dataAmbulatory.Class_Code == ere.ACCReg: + tx = tx.Where("\"Soapi\".\"TypeCode\" = ?", ercl.STCEEarlyMedic) + case dataAmbulatory.Class_Code == ere.ACCRehab && dataAmbulatory.VisitMode_Code == ere.VMCAdm: + tx = tx.Where("\"Soapi\".\"TypeCode\" IN ?", []ercl.SoapiTypeCode{ercl.STCEEarlyMedic, ercl.STCFunc, ercl.STCEarlyRehab}) + case dataAmbulatory.Class_Code == ere.ACCRehab && dataAmbulatory.VisitMode_Code == ere.VMCSeries: + tx = tx.Where("\"Soapi\".\"TypeCode\" = ?", ercl.STCEarlyRehab) + } + + if err = tx.Find(&dataSoapi).Error; err != nil { + return setDBError(event, err, encounterId) + } + + pl.SetLogInfo(event, nil, "complete") + return validateExistedSoapi(dataSoapi, &dataAmbulatory, event, mode) +} + +func validateExistedSoapi(dataSoapi []es.Soapi, dataAmbulatory *ea.Ambulatory, event *pl.Event, mode string) error { + typeExist := make(map[ercl.SoapiTypeCode]bool) + for _, s := range dataSoapi { + typeExist[s.TypeCode] = true + } + + required := []ercl.SoapiTypeCode{} + + switch { + case dataAmbulatory.Class_Code == ere.ACCReg: + required = []ercl.SoapiTypeCode{ercl.STCEEarlyMedic} + case dataAmbulatory.Class_Code == ere.ACCRehab && dataAmbulatory.VisitMode_Code == ere.VMCAdm: + required = []ercl.SoapiTypeCode{ercl.STCEEarlyMedic, ercl.STCFunc, ercl.STCEarlyRehab} + case dataAmbulatory.Class_Code == ere.ACCRehab && dataAmbulatory.VisitMode_Code == ere.VMCSeries: + required = []ercl.SoapiTypeCode{ercl.STCEarlyRehab} + } + + var missing, existing []string + for _, code := range required { + if typeExist[code] { + existing = append(existing, string(code)) + } else { + missing = append(missing, string(code)) + } + } + + switch mode { + case "check-in": + if len(existing) > 0 { + return setSoapiError(event, fmt.Sprintf("Soapi type(s) %s exist, can't check-in", strings.Join(existing, ", "))) + } + case "check-out": + if len(missing) > 0 { + return setSoapiError(event, fmt.Sprintf("Soapi type(s) %s not found, can't check-out", strings.Join(missing, ", "))) + } + } + + return nil +} + +func setSoapiError(event *pl.Event, detail string) error { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "invalid-soapi-state", + Detail: detail, + } + return pl.SetLogError(event, detail) +} + +func setDBError(event *pl.Event, err error, ctx any) error { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Raw: err, + Code: "read-fail", + Detail: "Database read failed", + } + return pl.SetLogError(event, ctx) +} + +func updateRehabDoctor(input er.UpdateDto, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, "started", "DBUpdate") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + result := tx. + Model(&er.Rehab{}). + Where("\"Encounter_Id\" = (?)", input.Encounter_Id). + Update("\"Doctor_Id\"", input.Doctor_Id) + + if result.Error != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-update-fail", + Detail: "Database update failed", + Raw: result.Error, + } + return pl.SetLogError(event, input) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index b840f6e1..d80fd513 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -3,29 +3,17 @@ package encounter import ( // std "errors" - "fmt" - erc "simrs-vx/internal/domain/references/clinical" ere "simrs-vx/internal/domain/references/encounter" - ero "simrs-vx/internal/domain/references/organization" - "strings" - // external dg "github.com/karincake/apem/db-gorm-pg" gh "github.com/karincake/getuk" "gorm.io/gorm" - // pkg plh "simrs-vx/pkg/lib-helper" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" - // internal - eaeh "simrs-vx/internal/domain/main-entities/adm-employee-hist" - ea "simrs-vx/internal/domain/main-entities/ambulatory" e "simrs-vx/internal/domain/main-entities/encounter" - er "simrs-vx/internal/domain/main-entities/rehab" - erdh "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" - es "simrs-vx/internal/domain/main-entities/soapi" ) func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Encounter, error) { @@ -261,88 +249,6 @@ func updateCheckInData(input e.CheckinDto, data *e.Encounter, event *pl.Event, d return nil } -func updateLatestResponsibleDoctorHist(input e.CheckinDto, event *pl.Event, dbx ...*gorm.DB) error { - pl.SetLogInfo(event, "started", "DBUpdate") - - var tx *gorm.DB - if len(dbx) > 0 { - tx = dbx[0] - } else { - tx = dg.I - } - - subQuery := tx. - Select("\"Id\""). - Model(&erdh.ResponsibleDoctorHist{}). - Where("\"Encounter_Id\" = ?", input.Id). - Order("\"CreatedAt\" DESC"). - Limit(1) - - result := tx. - Model(&erdh.ResponsibleDoctorHist{}). - Where("\"Id\" = (?)", subQuery). - Update("\"FinishedAt\"", input.StartedAt) - - if result.Error != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-update-fail", - Detail: "Database update failed", - Raw: result.Error, - } - return pl.SetLogError(event, input) - } - - if result.RowsAffected == 0 { - pl.SetLogInfo(event, input, "no previous data found to update") - return nil - } - - pl.SetLogInfo(event, nil, "complete") - return nil -} - -func updateLatestAdmEmployeeHist(input e.CheckinDto, event *pl.Event, dbx ...*gorm.DB) error { - pl.SetLogInfo(event, "started", "DBUpdate") - - var tx *gorm.DB - if len(dbx) > 0 { - tx = dbx[0] - } else { - tx = dg.I - } - - subQuery := tx. - Select("\"Id\""). - Model(&eaeh.AdmEmployeeHist{}). - Where("\"Encounter_Id\" = ?", input.Id). - Order("\"CreatedAt\" DESC"). - Limit(1) - - result := tx. - Model(&eaeh.AdmEmployeeHist{}). - Where("\"Id\" = (?)", subQuery). - Update("\"FinishedAt\"", input.StartedAt) - - if result.Error != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-update-fail", - Detail: "Database update failed", - Raw: result.Error, - } - return pl.SetLogError(event, input) - } - - if result.RowsAffected == 0 { - pl.SetLogInfo(event, input, "no previous data found to update") - return nil - } - - pl.SetLogInfo(event, nil, "complete") - return nil -} - func verifyAllocatedVisitCount(i e.CreateDto, event *pl.Event) (e.Encounter, bool, error) { pl.SetLogInfo(event, nil, "started", "DBGetRecentEncounterAdm") @@ -356,7 +262,7 @@ func verifyAllocatedVisitCount(i e.CreateDto, event *pl.Event) (e.Encounter, boo Scopes(gh.Preload("Rehab,Responsible_Doctor")). Joins("JOIN \"Ambulatory\" ON \"Ambulatory\".\"Encounter_Id\" = \"Encounter\".\"Id\""). Where("\"Patient_Id\" = ?", i.Patient_Id). - Where("\"Ambulatory\".\"Class_Code\" = ? AND \"Ambulatory\".\"VisitMode_Code\" = ?", ere.ACCRme, ere.VMCAdm). + Where("\"Ambulatory\".\"Class_Code\" = ? AND \"Ambulatory\".\"VisitMode_Code\" = ?", ere.ACCRehab, ere.VMCAdm). Order("\"CreatedAt\" DESC"). First(&recentEncounterAdm).Error if err != nil { @@ -374,7 +280,7 @@ func verifyAllocatedVisitCount(i e.CreateDto, event *pl.Event) (e.Encounter, boo Model(&e.Encounter{}). Joins("JOIN \"Ambulatory\" ON \"Ambulatory\".\"Encounter_Id\" = \"Encounter\".\"Id\""). Where("\"Patient_Id\" = ?", i.Patient_Id). - Where("\"Ambulatory\".\"Class_Code\" = ? AND \"Ambulatory\".\"VisitMode_Code\" = ?", ere.ACCRme, ere.VMCSeries). + Where("\"Ambulatory\".\"Class_Code\" = ? AND \"Ambulatory\".\"VisitMode_Code\" = ?", ere.ACCRehab, ere.VMCSeries). Where("\"Encounter\".\"CreatedAt\" > ?", recentEncounterAdm.CreatedAt). Count(&countEncounterSeries).Error if err != nil { @@ -389,193 +295,3 @@ func verifyAllocatedVisitCount(i e.CreateDto, event *pl.Event) (e.Encounter, boo return recentEncounterAdm, countEncounterSeries < int64(*recentEncounterAdm.Rehab.AllocatedVisitCount), nil } - -func getSoapiEncounterAdm(enc e.Encounter, event *pl.Event) (dataSoapi []es.CreateDto, err error) { - var data []es.Soapi - - pl.SetLogInfo(event, enc, "started", "DBReadList") - - if enc.Responsible_Doctor == nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "no responsible-doctor found", - Detail: "Encounter does not have responsible-doctor", - } - } - - err = dg.I.Debug(). - Model(&es.Soapi{}). - Joins("JOIN \"Employee\" ON \"Employee\".\"Id\" = \"Soapi\".\"Employee_Id\""). - Where("\"Encounter_Id\" = ?", enc.Id). - Where("\"Employee\".\"Position_Code\" = ?", ero.EPCDoc). - Where("\"Soapi\".\"TypeCode\" IN ?", []erc.SoapiTypeCode{erc.STCEEarlyMedic, erc.STCFunc}). - Where("\"Soapi\".\"Employee_Id\" = ?", *enc.Responsible_Doctor.Employee_Id). - Find(&data).Error - - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Raw: err, - } - - if errors.Is(err, gorm.ErrRecordNotFound) { - event.ErrInfo.Code = "data-not-found" - event.ErrInfo.Detail = "Data not found" - return nil, pl.SetLogError(event, enc) - } - - event.ErrInfo.Code = "read-fail" - event.ErrInfo.Detail = "Database read failed" - return nil, pl.SetLogError(event, enc) - } - - pl.SetLogInfo(event, nil, "complete") - - for _, s := range data { - // set data soapi for copy - dataSoapi = append(dataSoapi, es.CreateDto{ - Employee_Id: s.Employee_Id, - Time: s.Time, - TypeCode: s.TypeCode, - Value: s.Value, - }) - } - - if len(dataSoapi) < 2 { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "missing-soapi", - Detail: fmt.Sprintf("Missing required Soapi types"), - } - return nil, pl.SetLogError(event, enc) - } - return -} - -func getSoapiByTypeCode(encounterId uint, event *pl.Event, mode string) (err error) { - pl.SetLogInfo(event, encounterId, "started", "DBReadList") - - var ( - dataAmbulatory ea.Ambulatory - dataSoapi []es.Soapi - ) - - // Get Data Ambulatory - if err = dg.I. - Where("\"Encounter_Id\" = ?", encounterId). - First(&dataAmbulatory).Error; err != nil { - return setDBError(event, err, encounterId) - } - - // Set Query for get data Soapi - tx := dg.I. - Model(&es.Soapi{}). - Joins("JOIN \"Employee\" ON \"Employee\".\"Id\" = \"Soapi\".\"Employee_Id\""). - Where("\"Encounter_Id\" = ?", encounterId). - Where("\"Employee\".\"Position_Code\" = ?", ero.EPCDoc) - - // Set Case - switch { - case dataAmbulatory.Class_Code == ere.ACCReg: - tx = tx.Where("\"Soapi\".\"TypeCode\" = ?", erc.STCEEarlyMedic) - case dataAmbulatory.Class_Code == ere.ACCRme && dataAmbulatory.VisitMode_Code == ere.VMCAdm: - tx = tx.Where("\"Soapi\".\"TypeCode\" IN ?", []erc.SoapiTypeCode{erc.STCEEarlyMedic, erc.STCFunc, erc.STCEarlyRehab}) - case dataAmbulatory.Class_Code == ere.ACCRme && dataAmbulatory.VisitMode_Code == ere.VMCSeries: - tx = tx.Where("\"Soapi\".\"TypeCode\" = ?", erc.STCEarlyRehab) - } - - if err = tx.Find(&dataSoapi).Error; err != nil { - return setDBError(event, err, encounterId) - } - - pl.SetLogInfo(event, nil, "complete") - return validateExistedSoapi(dataSoapi, &dataAmbulatory, event, mode) -} - -func validateExistedSoapi(dataSoapi []es.Soapi, dataAmbulatory *ea.Ambulatory, event *pl.Event, mode string) error { - typeExist := make(map[erc.SoapiTypeCode]bool) - for _, s := range dataSoapi { - typeExist[s.TypeCode] = true - } - - required := []erc.SoapiTypeCode{} - - switch { - case dataAmbulatory.Class_Code == ere.ACCReg: - required = []erc.SoapiTypeCode{erc.STCEEarlyMedic} - case dataAmbulatory.Class_Code == ere.ACCRme && dataAmbulatory.VisitMode_Code == ere.VMCAdm: - required = []erc.SoapiTypeCode{erc.STCEEarlyMedic, erc.STCFunc, erc.STCEarlyRehab} - case dataAmbulatory.Class_Code == ere.ACCRme && dataAmbulatory.VisitMode_Code == ere.VMCSeries: - required = []erc.SoapiTypeCode{erc.STCEarlyRehab} - } - - var missing, existing []string - for _, code := range required { - if typeExist[code] { - existing = append(existing, string(code)) - } else { - missing = append(missing, string(code)) - } - } - - switch mode { - case "check-in": - if len(existing) > 0 { - return setSoapiError(event, fmt.Sprintf("Soapi type(s) %s exist, can't check-in", strings.Join(existing, ", "))) - } - case "check-out": - if len(missing) > 0 { - return setSoapiError(event, fmt.Sprintf("Soapi type(s) %s not found, can't check-out", strings.Join(missing, ", "))) - } - } - - return nil -} - -func setSoapiError(event *pl.Event, detail string) error { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "invalid-soapi-state", - Detail: detail, - } - return pl.SetLogError(event, detail) -} - -func setDBError(event *pl.Event, err error, ctx any) error { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Raw: err, - Code: "read-fail", - Detail: "Database read failed", - } - return pl.SetLogError(event, ctx) -} - -func updateRehabDoctor(input er.UpdateDto, event *pl.Event, dbx ...*gorm.DB) error { - pl.SetLogInfo(event, "started", "DBUpdate") - - var tx *gorm.DB - if len(dbx) > 0 { - tx = dbx[0] - } else { - tx = dg.I - } - - result := tx. - Model(&er.Rehab{}). - Where("\"Encounter_Id\" = (?)", input.Encounter_Id). - Update("\"Doctor_Id\"", input.Doctor_Id) - - if result.Error != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-update-fail", - Detail: "Database update failed", - Raw: result.Error, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(event, nil, "complete") - return nil -} From 98a567a5b3b4ec7fe7f9b0a6c1d7ae05a85c0f11 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 4 Nov 2025 15:10:33 +0700 Subject: [PATCH 055/329] add doctor_id in control-letter --- cmd/main-migration/migrations/20251104080952.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 7 ++++--- internal/domain/main-entities/control-letter/entity.go | 3 +++ 3 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 cmd/main-migration/migrations/20251104080952.sql diff --git a/cmd/main-migration/migrations/20251104080952.sql b/cmd/main-migration/migrations/20251104080952.sql new file mode 100644 index 00000000..24fcc6a5 --- /dev/null +++ b/cmd/main-migration/migrations/20251104080952.sql @@ -0,0 +1,2 @@ +-- Modify "ControlLetter" table +ALTER TABLE "public"."ControlLetter" ADD COLUMN "Doctor_Id" bigint NULL, ADD CONSTRAINT "fk_ControlLetter_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index c701690e..7be07b61 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:DapfqgPn4h3ozXgxIdxW/bzPLHdc//0uHjK+W42/jic= +h1:2J5umJFoWClM/F8kKNyZFoDqrV1aL8PimwTG6Mx6syo= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -65,5 +65,6 @@ h1:DapfqgPn4h3ozXgxIdxW/bzPLHdc//0uHjK+W42/jic= 20251102002037.sql h1:lFJbuoZ2LMQnUNGdcwHVY3Xlfslgzu9t2WByT8yfOZI= 20251102091932.sql h1:rmdhb5m+P+fU8jROBZNyeYgZKuQvucsuljXv4ZVzvks= 20251103081637.sql h1:tf3BcwTeIw+oxMEisKDDfyKnBfalTLs8b0PJA8JWYxY= -20251104042334.sql h1:a76eSmiEVviWWjsfAkiriDxRYGhlg8qIjZ2CVQZDnbA= -20251104043530.sql h1:tGP1AhyYzPZAA05IwfJfWWhNISrud3xCmeRFdZ/28SQ= +20251104042334.sql h1:7PDMWOhmJywolAPKFZ14XaDBeMvcxShaXFN2IemNtzk= +20251104043530.sql h1:qvYVp3ysPf27f1BcoRNCFGovxuVE12lg9d6Xzda6zWU= +20251104080952.sql h1:+SMRSBPjP0qeLlaiIdff7hUnW2+1l1GJOWjP7fWPiGA= diff --git a/internal/domain/main-entities/control-letter/entity.go b/internal/domain/main-entities/control-letter/entity.go index 9cf74a68..abaf4a72 100644 --- a/internal/domain/main-entities/control-letter/entity.go +++ b/internal/domain/main-entities/control-letter/entity.go @@ -4,6 +4,7 @@ import ( "time" ecore "simrs-vx/internal/domain/base-entities/core" + ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/encounter" es "simrs-vx/internal/domain/main-entities/specialist" ess "simrs-vx/internal/domain/main-entities/subspecialist" @@ -20,5 +21,7 @@ type ControlLetter struct { Specialist *es.Specialist `json:"specialist" gorm:"foreignKey:Specialist_Id;references:Id"` Subspecialist_Id *uint `json:"subspecialist_id"` Subspecialist *ess.Subspecialist `json:"subspecialist" gorm:"foreignKey:Subspecialist_Id;references:Id"` + Doctor_Id *uint `json:"doctor_id"` + Doctor *ed.Doctor `json:"doctor" gorm:"foreignKey:Doctor_Id;references:Id"` Date *time.Time `json:"date"` } From 97e6437a4ce8eaa3e8defbd93c161abfd87586f6 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 4 Nov 2025 15:13:09 +0700 Subject: [PATCH 056/329] feat (control-letter): add doctor_id --- internal/domain/main-entities/control-letter/dto.go | 7 +++++++ internal/use-case/main-use-case/control-letter/helper.go | 1 + 2 files changed, 8 insertions(+) diff --git a/internal/domain/main-entities/control-letter/dto.go b/internal/domain/main-entities/control-letter/dto.go index 4beadd69..c2bab776 100644 --- a/internal/domain/main-entities/control-letter/dto.go +++ b/internal/domain/main-entities/control-letter/dto.go @@ -12,6 +12,7 @@ import ( // internal - domain - main-entities + ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/encounter" es "simrs-vx/internal/domain/main-entities/specialist" ess "simrs-vx/internal/domain/main-entities/subspecialist" @@ -23,6 +24,7 @@ type CreateDto struct { Unit_Id *uint `json:"unit_id"` Specialist_Id *uint `json:"specialist_id"` Subspecialist_Id *uint `json:"subspecialist_id"` + Doctor_Id *uint `json:"doctor_id"` Date *time.Time `json:"date"` } @@ -37,6 +39,7 @@ type FilterDto struct { Unit_Id *uint `json:"unit-id"` Specialist_Id *uint `json:"specialist-id"` Subspecialist_Id *uint `json:"subspecialist-id"` + Doctor_Id *uint `json:"doctor-id"` Date *time.Time `json:"date"` } @@ -77,6 +80,8 @@ type ResponseDto struct { Specialist *es.Specialist `json:"specialist,omitempty"` Subspecialist_Id *uint `json:"subspecialist_id"` Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty"` + Doctor_Id *uint `json:"doctor_id"` + Doctor *ed.Doctor `json:"doctor,omitempty"` Date *time.Time `json:"date"` } @@ -90,6 +95,8 @@ func (d ControlLetter) ToResponse() ResponseDto { Specialist: d.Specialist, Subspecialist_Id: d.Subspecialist_Id, Subspecialist: d.Subspecialist, + Doctor_Id: d.Doctor_Id, + Doctor: d.Doctor, Date: d.Date, } resp.Main = d.Main diff --git a/internal/use-case/main-use-case/control-letter/helper.go b/internal/use-case/main-use-case/control-letter/helper.go index 9b1d3b23..5cc943c5 100644 --- a/internal/use-case/main-use-case/control-letter/helper.go +++ b/internal/use-case/main-use-case/control-letter/helper.go @@ -21,5 +21,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.ControlLetter) { data.Unit_Id = inputSrc.Unit_Id data.Specialist_Id = inputSrc.Specialist_Id data.Subspecialist_Id = inputSrc.Subspecialist_Id + data.Doctor_Id = inputSrc.Doctor_Id data.Date = inputSrc.Date } From 64879fced480b11c6e58c5df6e274ebc99cc8b96 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 4 Nov 2025 15:15:25 +0700 Subject: [PATCH 057/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 140 ++++++++++++------------ 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 7be07b61..e0d46a35 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,70 +1,70 @@ -h1:2J5umJFoWClM/F8kKNyZFoDqrV1aL8PimwTG6Mx6syo= -20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= -20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= -20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= -20250908062323.sql h1:oXl6Z143tOpIl4EfP4B8JNU8LrMvVmHEtCgAfiB4gs8= -20250908073811.sql h1:m2aNXfnGxnLq1+rVWrh4f60q7fhyhV3gEwNu/OIqQlE= -20250908073839.sql h1:cPk54xjLdMs26uY8ZHjNWLuyfAMzV7Zb0/9oJQrsw04= -20250910055902.sql h1:5xwjAV6QbtZT9empTJKfhyAjdknbHzb15B0Ku5dzqtQ= -20250915123412.sql h1:D83xaU2YlDEd21HLup/YQpQ2easMToYCyy/oK6AFgQs= -20250916043819.sql h1:ekoTJsBqQZ8G8n0qJ03d13+eoNoc7sAUEQGA5D/CCxk= -20250917040616.sql h1:zoCnmcXuM7AVv85SmN7RmFglCgJnoDmpRWExH0LAc9Q= -20250917040751.sql h1:J1xyRrh32y1+lezwAyNwPcUQ6ABBSgbvzNLva4SVdQU= -20250917045138.sql h1:jKe1Z0uOLG4SGBYM+S/3P+/zMPztmgoderD5swnMuCg= -20250917093645.sql h1:cNI3Pbz1R3LxvIXLuexafJFCXUXrmuFCgXXJ2sG+FW0= -20250918073552.sql h1:RJ1SvMzP6aeWnoPVD3eVAmIQOkcp6Php8z3QRri6v4g= -20250918073742.sql h1:+cEsnJTJFybe2fR69ZoOiX2R6c6iITl4m6WTZ1hjyzY= -20250918074745.sql h1:2hNVQCXF/dVYXAh+T/7oBFgERGWxzVb2FXJjwkFWGCI= -20250923025134.sql h1:Ykz/qpHiGDXPsCsWTjydQFVSibZP2D+h2fIeb2h2JGA= -20250924051317.sql h1:yQuW6SwJxIOM5fcxeAaie5lSm1oLysU/C2hH2xNCVoQ= -20250929034321.sql h1:101FJ8VH12mrZWlt/X1gvKUGOhoiF8tFbjiapAjnHzg= -20250929034428.sql h1:i+pROD9p+g5dOmmZma6WF/0Hw5g3Ha28NN85iTo1K34= -20250930025550.sql h1:+F+CsCUXD/ql0tHGEow70GhPBX1ZybVn+bh/T4YMh7Y= -20250930140351.sql h1:9AAEG1AnOAH+o0+oHL5G7I8vqlWOhwRlCGyyCpT/y1Q= -20251002085604.sql h1:3xZ68eYp4urXRnvotNH1XvG2mYOSDV/j3zHEZ/txg5E= -20251003032030.sql h1:HB+mQ2lXMNomHDpaRhB/9IwYI9/YiDO5eOJ+nAQH/jw= -20251005060450.sql h1:LbtCE2b+8osM3CvnmQJH1uCPtn+d7WchsslBOz8bL3Q= -20251006041122.sql h1:MlS7f21z06sutnf9dIekt5fuHJr4lgcQ4uCuCXAGsfc= -20251006045658.sql h1:3FmGCPCzjgMPdWDRodZTsx3KVaodd9zB9ilib69aewk= -20251006045928.sql h1:Z5g31PmnzNwk/OKdODcxZGm8fjJQdMFK32Xfnt3bRHg= -20251007022859.sql h1:FO03zEfaNEk/aXwY81d5Lp3MoBB9kPQuXlXJ4BPiSR8= -20251008031337.sql h1:l+sxUAGvcTfj3I6kAFHo+T6AYodC9k9GkR+jaKO2xXc= -20251008031554.sql h1:AqrVfIhSzY3PCy8ZlP5W91wn2iznfIuj5qQfubp6/94= -20251008052346.sql h1:nxnXmooIJ6r1mmzwnw+6efxLfc/k9h2aE6RMptPRons= -20251008073620.sql h1:6YsJp1W4SmQJ1lxpqF27BBlDC1zqhw7Yhc7pLzQTY6M= -20251009042854.sql h1:nkBV+R6j0fg7/JY6wH3eb5Vv0asJLnXmb6lINfT/GLQ= -20251009052657.sql h1:EPvdsib5rzCGPryd10HShGKvFPwM/R5S2lIVwtYxpms= -20251010031743.sql h1:T8IZmx8/btRFKLzTe78MzcBsPJNodnLvB0tby9QkirQ= -20251010070721.sql h1:5NQUk/yOV6sABLCB7swx++YIOyJe6MnU+yt1nRzde5w= -20251010072711.sql h1:ZJNqR2piyu8xJhBvVABSlnGEoKSKae3wuEs+wshPe4k= -20251013044536.sql h1:0Xjw8fNILiT8nnfrJDZgQnPf3dntmIoilbapnih8AE4= -20251013051438.sql h1:lfSuw5mgJnePBJamvhZ81osFIouXeiIEiSZ/evdwo48= -20251013081808.sql h1:ijgjNX08G6GBjA/ks8EKtb7P7Y7Cg7zbhqEOruGnv6M= -20251014060047.sql h1:0jqj49WTtneEIMQDBoo4c095ZGi8sCrA8NnHBrPU6D8= -20251014063537.sql h1:VZLXol0PTsTW21Epg6vBPsztWkDtcxup9F/z88EGgIg= -20251014063720.sql h1:2HVUyCV0ud3BJJDH2GEKZN/+IWLFPCsN1KqhP6csO14= -20251015045455.sql h1:MeLWmMhAOAz8b15Dd7IAQnt6JxjSml02XCXK22C0Lpg= -20251016010845.sql h1:4BncQdDOasRZJkzVJrSJJA7091A9VPNVx/faUCUPhBM= -20251016011023.sql h1:9JB9eFZKURK5RoCVDKR6glSvdJ8NTXrN7K/4q51zkz4= -20251016062912.sql h1:ACNn0fe+EMqUt3hoY+Dr3uqAV/QICBa1+mIW7fUc9Fk= -20251017060617.sql h1:4T3t9ifWrEQTPMSM0XJ98pF7Qdt+UfgtMui17bhrnWI= -20251017082207.sql h1:8vLG1l/saRRMHXkyA4nelJyjaSddhZd6r7R+Uo4JS/c= -20251018032635.sql h1:2xey5gnO3y2XSOrU8MLlIfoylPKbRGDRtHDD07B3MbQ= -20251018040322.sql h1:k/pdNiSoT8zFPqNQ/avOD0vYkNh3BTD64IlHrfVXr7I= -20251019093915.sql h1:hFcQE0y+p5dZiVwePGsRGto9m/q6kJNiUZbVDd5Rnjk= -20251020062553.sql h1:Iw7hulcm5iRQlfW+ygA4iTPxLqkxx6h9vXMXEwUAHKs= -20251021041042.sql h1:wMgSivBV2A0NDcsLmKGIp0kMcVh2IODSG9b4dgzCaOM= -20251021075552.sql h1:8gfSMAglflNO6L0sSzxFNEubYN8/O4thT7OQT+WH+3M= -20251023044432.sql h1:MkvajJs3bfk9+wHvQ43/ccAluJEBARm1gWr1u92ccLA= -20251024034832.sql h1:x3s3VEVYLOSKLAFxJGb2+c1FyTMMvPE+9k4Ew7rKQaI= -20251024074315.sql h1:EjAjelgi5qAfcRq/8vPTlGGYHvAKxNTllm8f0SzZDns= -20251025013451.sql h1:6hnuIiwYiG+6nLhOY/+Yyn+I6ZCFNRZxrJNqBV6HLqE= -20251025013609.sql h1:evPJaTD8WxYRMOJZHkSr7ONLx9PYxT+ankzQt9c/sJ0= -20251027075128.sql h1:/iFQBM1sytjqpyQSOx61q33gnorMgxTiFVSuL6bQqsM= -20251027091406.sql h1:eCZGtUkxAzEAqpC9UsGpP8Df9mS0DEOqSl885LgqpvM= -20251102002037.sql h1:lFJbuoZ2LMQnUNGdcwHVY3Xlfslgzu9t2WByT8yfOZI= -20251102091932.sql h1:rmdhb5m+P+fU8jROBZNyeYgZKuQvucsuljXv4ZVzvks= -20251103081637.sql h1:tf3BcwTeIw+oxMEisKDDfyKnBfalTLs8b0PJA8JWYxY= -20251104042334.sql h1:7PDMWOhmJywolAPKFZ14XaDBeMvcxShaXFN2IemNtzk= -20251104043530.sql h1:qvYVp3ysPf27f1BcoRNCFGovxuVE12lg9d6Xzda6zWU= -20251104080952.sql h1:+SMRSBPjP0qeLlaiIdff7hUnW2+1l1GJOWjP7fWPiGA= +h1:fcpOnigzzVgIt+BimD58z3BfW5JzOXIltdMVGabIh/Q= +20250904105930.sql h1:Vv4vCurl7m7/ZB6TjRpkubHpQ4RYwSUn0QHdzfoGpzY= +20250904141448.sql h1:FYCHH9Os4KkrZMDu/jR8FMP+wLMRW+Mb0PkLU/9BRDg= +20250908062237.sql h1:oanBpKZd+akPu2I/xYhUSbd0G5tAFbXzKLER/Zs8ENI= +20250908062323.sql h1:miNG9COddXkD1jGTgaROMAZ618eT6oiLGiJhXWnQwhE= +20250908073811.sql h1:gOi5cnGG1htlpfizybYmUIT0vYjZTBfXiI0nPSYK2u8= +20250908073839.sql h1:cWNDA4YikjoOteAJuNLFILjQUJPFB6o8Wxreiek4QyI= +20250910055902.sql h1:nxxOGnU0BbH/v3IPgeIOXOwH8d3tKomw7h6FTeMnnBs= +20250915123412.sql h1:mz7SiWfrdf0qE1VTSAAnA/147d6gyp6ry5vZ2bR9SH0= +20250916043819.sql h1:RHXVtmMkB6wfv06HfPyHMBmUfIpFt1xveafNz0kwKnE= +20250917040616.sql h1:MYVDht+akBlzQGKNu2hTTTLPEcH1bxT/Q8MK6WEtuhs= +20250917040751.sql h1:J79YyS2JzWgh5oKXMTgh67uo3gLxKaAsxRiZmSIfjBs= +20250917045138.sql h1:/SM1N4O8X3yxpoJgMEARmS1uOkuLKsTOy4PLsRCOKaQ= +20250917093645.sql h1:PNBTGZ7s10e5b5+Tie8YfVQBN0zKtJ5T34oK1iOUEb4= +20250918073552.sql h1:jG7+g3i8ODYaJdcdZz12v3nbsZ5mB9wG6kWnGyTQIRI= +20250918073742.sql h1:j+rgw7puxE7s+phqPVZHmPk0af3rcaA56Itp86y1suY= +20250918074745.sql h1:rPmP4DXs6OnY4Vp+xO/z9jFpJt/RrJ52SJJjIIxeDvc= +20250923025134.sql h1:2r6pcwnBSU5Y9Czk1OHBoh4yZXiMtEca9X8843fTEX0= +20250924051317.sql h1:iUAk2gsGoEGIPQ0lEEUp8maMSId8emNbP+kP712ABIA= +20250929034321.sql h1:UlpALNVmdi95zOIT0yc6ZyTj9bBjQEIpZhvgrc52M+k= +20250929034428.sql h1:feF+H4nDyHh5bdx48Oiz0A1qecZfi6v3qTTdjzJ45Dg= +20250930025550.sql h1:6XT1kXI3Z3ZIxxmvT7poufZWWCW0QiejZPaFV5wBnjI= +20250930140351.sql h1:HxnmAbh9gCy8jwl/9ycGktiByaUripsjFFvohofY2CY= +20251002085604.sql h1:SjLPi+ZN6qDccK3DaEQCgNsZpPwr5kynWXwbwEsziCI= +20251003032030.sql h1:oHfxNSuqTxU8Zaf9H+h8TuUb1Da03wcyc6hZjDrUQ2s= +20251005060450.sql h1:GIuCcrd4MwjmXpvbzDzPYL18BV3QaZZ+Y2FmEzjvi0E= +20251006041122.sql h1:uNDQbSw0M08lYoMvUNlQtS3iDzpPM1ixT13ugSAoWjE= +20251006045658.sql h1:z+t7yCK54Q4SSiF9kUyUhkYB2F+kzSW9TB7ogxd9wzw= +20251006045928.sql h1:1lATLFLp4BWwGZqAjZdP0Dc6ypNXiYcwjoNkqGa8NFE= +20251007022859.sql h1:HXXwWrkyvzJzJGAt9mGskCRBBV/c1JfPmfjDocmJhQ4= +20251008031337.sql h1:Ln5pCF3Hxa5foHZLcds+z/us2eH6VAhhEj3w0TAGlVs= +20251008031554.sql h1:aB4MUS2lmqG0//4HKUWorcPSpWya0VC4QItvGyskEVI= +20251008052346.sql h1:MI3AZgU5XcwZT2OvvlWAxdRtL0eJ3jjRwt56IY1+pRU= +20251008073620.sql h1:sztWXuSNYwpEraaSapSsYwno75LO5H/N7ob7OJQ8X/A= +20251009042854.sql h1:TnPXj+dCJls3IU//cuqJZymyBzZMKs7ayazfgtAFRxM= +20251009052657.sql h1:leXbs0CP8r5dRilmYyLRk1MICqak3ea1/LWMtFrijqQ= +20251010031743.sql h1:SgHNY/lQ88G2F4nZyMfiOkDntb+gtOR+nEQLqXBTwv4= +20251010070721.sql h1:AnJnhXsMzDvK4AFgYw6B16Kpo/hljrZtcpc9m2VOSHQ= +20251010072711.sql h1:aXPTtNwLcTuw8C/yAxwxvqs0ayEjNzI1uuE0vE3ERa8= +20251013044536.sql h1:7Pq6JcvTpPBYDCW2dz3HdgUwY65HlhEVWy9TiG8iONE= +20251013051438.sql h1:X6t8bkqpUYYokBunSufMQUe5vCg0VyO6dxbm7ngosUc= +20251013081808.sql h1:495pLguXL2Ozh+ycn4UYZgZbn6WbjXNbyZUc3JU8qhI= +20251014060047.sql h1:nCgImMRGHhziiW57O1ofWaXCAPGaCOHN7PldQ3OSmM4= +20251014063537.sql h1:2cLmID79jP6cuQ1YJaWTtghFiM1GtHMC0ZQl30Hpy1M= +20251014063720.sql h1:bzLKKVAjSHgDFoiI/glj7t1ETlSAKx+AlsIAaP0ru2g= +20251015045455.sql h1:S547+UugQhlTRcn1Lm1IfqT5RNPttIWIiD+RTx69YaE= +20251016010845.sql h1:c9DUvxl17pUkf0azdYGM/YDzYxIJkLcfZOcMI4rL+R0= +20251016011023.sql h1:u3ivg83bXgYHBbojbWpemLxPE9Dmmj53B6LXo664jxw= +20251016062912.sql h1:W9n1hWchfYkqNX9LO9uxFxEXAb/iY+Pexjnhmp6PbgI= +20251017060617.sql h1:VU6yZ2+LfHpDZ3+TIH40t3F5YXPCpTppuF9+uSqa4b8= +20251017082207.sql h1:QshZslfedckz7iDpSGmPyY9sP6dy6ckHbs8L1TuXIA4= +20251018032635.sql h1:M1U/9W/F9wlW5YDmVAmHFfUJU7FWFaX0DblpfZcYWrE= +20251018040322.sql h1:Zk/vw0e6AzWFO2ElLOzB+OrSz6k+h1Ynxp0TImAzxwY= +20251019093915.sql h1:3Q0kPiZwJnHn5rAvdh0w1LBdiA7W2xBmZWncoPXb044= +20251020062553.sql h1:mJwC/J8GzPAIXckNMvy1f/Nguk2VVf8roD/Raclhbao= +20251021041042.sql h1:d1BAOGAQhqr+oOwcpAVozUsTh457VSDEk2qQFavGG58= +20251021075552.sql h1:TNChGQ1Zlr/1iQ6qvK4iDTAJpe6L/z/M6e/O0SkQVaM= +20251023044432.sql h1:GA2AdJk2ULyjr6igtu9C/CEi4YUIks8r9jXGGaCvPsk= +20251024034832.sql h1:RXmbEhMkOLK5g1QL6up8iRPcwYfo89oLP26ZHvrUK9o= +20251024074315.sql h1:3GnPQSbuAAfMa8oWDyBjhXqn1j1zunY/w0ydX0IGPrA= +20251025013451.sql h1:5eNrA9LDxA4i5CCP7wSyOgFZ6t6jBWVil+oGzJpkJ2E= +20251025013609.sql h1:+N6EHc1kv3hqf16CUhXe+UITPmoxOPfi4MECLmJXNrc= +20251027075128.sql h1:PQflgsjce/p2ClbybLtdehdPNDcMZ9Lb1vd98xd0K8E= +20251027091406.sql h1:bYXV57GvodCMjg0/ox+XKGIAGhrDlVuJ1wO4foNEKtQ= +20251102002037.sql h1:ZcwULsJU2lI9t5pX7ukmfAHSx4ZxdxLUX6jzLDc2SrU= +20251102091932.sql h1:A6y9j4wAqm4/HfMDxhpy/ChDn3UNRVN99KGgSCX+e18= +20251103081637.sql h1:RFqJNhJItSwJQaMP5IcQ14mL7eQ3EJjGZua9zLWzwMU= +20251104042334.sql h1:BbjLAwImggvI6489FQgD+S/AaafeiZut8k19TdH7XUE= +20251104043530.sql h1:Y0sOQqgnHxd5vKPA4+4fAGGdWCv6duKAYgHnjRJZUIc= +20251104080952.sql h1:hDHzFs/k+NhPYJ64ifbVp+nTJLMCG5MIMJU1zBMP0V0= From 66ee63a9b65e6b71554d81e63086c2d1f1c82d13 Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 4 Nov 2025 15:29:57 +0700 Subject: [PATCH 058/329] add therapy protocol --- internal/domain/main-entities/chemo/dto.go | 2 + .../main-entities/therapy-protocol/dto.go | 107 ++++++ .../interface/main-handler/chemo/handler.go | 5 + .../interface/main-handler/main-handler.go | 2 + .../main-handler/therapy-protocol/handler.go | 73 +++++ internal/use-case/main-use-case/chemo/case.go | 2 + .../main-use-case/therapy-protocol/case.go | 310 ++++++++++++++++++ .../main-use-case/therapy-protocol/helper.go | 34 ++ .../main-use-case/therapy-protocol/lib.go | 145 ++++++++ .../therapy-protocol/middleware-runner.go | 103 ++++++ .../therapy-protocol/middleware.go | 9 + .../main-use-case/therapy-protocol/tycovar.go | 44 +++ 12 files changed, 836 insertions(+) create mode 100644 internal/domain/main-entities/therapy-protocol/dto.go create mode 100644 internal/interface/main-handler/therapy-protocol/handler.go create mode 100644 internal/use-case/main-use-case/therapy-protocol/case.go create mode 100644 internal/use-case/main-use-case/therapy-protocol/helper.go create mode 100644 internal/use-case/main-use-case/therapy-protocol/lib.go create mode 100644 internal/use-case/main-use-case/therapy-protocol/middleware-runner.go create mode 100644 internal/use-case/main-use-case/therapy-protocol/middleware.go create mode 100644 internal/use-case/main-use-case/therapy-protocol/tycovar.go diff --git a/internal/domain/main-entities/chemo/dto.go b/internal/domain/main-entities/chemo/dto.go index 8317b259..653b5409 100644 --- a/internal/domain/main-entities/chemo/dto.go +++ b/internal/domain/main-entities/chemo/dto.go @@ -52,6 +52,8 @@ 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"` pa.AuthInfo } diff --git a/internal/domain/main-entities/therapy-protocol/dto.go b/internal/domain/main-entities/therapy-protocol/dto.go new file mode 100644 index 00000000..f7a5f2e4 --- /dev/null +++ b/internal/domain/main-entities/therapy-protocol/dto.go @@ -0,0 +1,107 @@ +package therapy_protocol + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ed "simrs-vx/internal/domain/main-entities/doctor" + ee "simrs-vx/internal/domain/main-entities/encounter" + "simrs-vx/internal/domain/references/common" +) + +type CreateDto struct { + Encounter_Id *uint `json:"encounter_id"` + Doctor_Id *uint `json:"doctor_id"` + Anamnesis *string `json:"anamnesis" validate:"maxLength=2048"` + MedicalDiagnoses *string `json:"medicalDiagnoses"` + FunctionDiagnoses *string `json:"functionDiagnoses"` + Procedures *string `json:"procedures"` + SupportingExams *string `json:"supportingExams" validate:"maxLength=2048"` + Instruction *string `json:"instruction" validate:"maxLength=2048"` + Evaluation *string `json:"evaluation" validate:"maxLength=2048"` + WorkCauseStatus *string `json:"workCauseStatus"` + Frequency *uint `json:"frequency"` + IntervalUnit_Code *common.TimeUnitCode `json:"intervalUnit_code" validate:"maxLength=10"` + Duration *uint `json:"duration"` + DurationUnit_Code *common.TimeUnitCode `json:"durationUnit_code" validate:"maxLength=10"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Encounter_Id *uint `json:"encounter-id"` + Doctor_Id *uint `json:"doctor-id"` +} + +type ReadDetailDto struct { + Id uint `json:"id"` + Includes string `json:"includes"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty"` + Doctor_Id *uint `json:"doctor_id"` + Doctor *ed.Doctor `json:"doctor,omitempty"` + Anamnesis *string `json:"anamnesis"` + MedicalDiagnoses *string `json:"medicalDiagnoses"` + FunctionDiagnoses *string `json:"functionDiagnoses"` + Procedures *string `json:"procedures"` + SupportingExams *string `json:"supportingExams"` + Instruction *string `json:"instruction"` + Evaluation *string `json:"evaluation"` + WorkCauseStatus *string `json:"workCauseStatus"` + Frequency *uint `json:"frequency"` + IntervalUnit_Code *common.TimeUnitCode `json:"intervalUnit_code"` + Duration *uint `json:"duration"` + DurationUnit_Code *common.TimeUnitCode `json:"durationUnit_code"` +} + +func (d TherapyProtocol) ToResponse() ResponseDto { + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Encounter: d.Encounter, + Doctor_Id: d.Doctor_Id, + Doctor: d.Doctor, + Anamnesis: d.Anamnesis, + MedicalDiagnoses: d.MedicalDiagnoses, + FunctionDiagnoses: d.FunctionDiagnoses, + Procedures: d.Procedures, + SupportingExams: d.SupportingExams, + Instruction: d.Instruction, + Evaluation: d.Evaluation, + WorkCauseStatus: d.WorkCauseStatus, + Frequency: d.Frequency, + IntervalUnit_Code: d.IntervalUnit_Code, + Duration: d.Duration, + DurationUnit_Code: d.DurationUnit_Code, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []TherapyProtocol) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/interface/main-handler/chemo/handler.go b/internal/interface/main-handler/chemo/handler.go index 90552020..18435479 100644 --- a/internal/interface/main-handler/chemo/handler.go +++ b/internal/interface/main-handler/chemo/handler.go @@ -84,11 +84,16 @@ func (obj myBase) Verify(w http.ResponseWriter, r *http.Request) { } dto := e.VerifyDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint16(id) authInfo, err := pa.GetAuthInfo(r) if err != nil { rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) } + dto.AuthInfo = *authInfo dto.Status_Code = erc.DVCVerified res, err := u.Verify(dto) diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index baea92da..554de761 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -94,6 +94,7 @@ import ( specialistposition "simrs-vx/internal/interface/main-handler/specialist-position" subspecialist "simrs-vx/internal/interface/main-handler/subspecialist" subspecialistposition "simrs-vx/internal/interface/main-handler/subspecialist-position" + therapyprotocol "simrs-vx/internal/interface/main-handler/therapy-protocol" unit "simrs-vx/internal/interface/main-handler/unit" unitposition "simrs-vx/internal/interface/main-handler/unit-position" uom "simrs-vx/internal/interface/main-handler/uom" @@ -257,6 +258,7 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/ambulance-transport-req", ambulancetransportrequest.O) hc.RegCrud(r, "/v1/responsible-doctor-hist", responsibledoctorhist.O) hc.RegCrud(r, "/v1/adm-employee-hist", admemployeehist.O) + hc.RegCrud(r, "/v1/therapy-protocol", therapyprotocol.O) /******************** actor ********************/ hc.RegCrud(r, "/v1/person", person.O) diff --git a/internal/interface/main-handler/therapy-protocol/handler.go b/internal/interface/main-handler/therapy-protocol/handler.go new file mode 100644 index 00000000..2d9efc3b --- /dev/null +++ b/internal/interface/main-handler/therapy-protocol/handler.go @@ -0,0 +1,73 @@ +package therapy_protocol + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/therapy-protocol" + u "simrs-vx/internal/use-case/main-use-case/therapy-protocol" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + + sf.UrlQueryParam(&dto, *r.URL) + dto.Id = uint(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint(id) + 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/use-case/main-use-case/chemo/case.go b/internal/use-case/main-use-case/chemo/case.go index 541faa04..f7b3c7d3 100644 --- a/internal/use-case/main-use-case/chemo/case.go +++ b/internal/use-case/main-use-case/chemo/case.go @@ -311,6 +311,8 @@ func Verify(input e.VerifyDto) (*d.Data, error) { data.VerifiedAt = pu.GetTimeNow() data.Status_Code = input.Status_Code data.VerifiedBy_User_Id = &input.AuthInfo.User_Id + data.Bed = input.Bed + data.Needs = input.Needs err = tx.Save(&data).Error if err != nil { diff --git a/internal/use-case/main-use-case/therapy-protocol/case.go b/internal/use-case/main-use-case/therapy-protocol/case.go new file mode 100644 index 00000000..93cf05a4 --- /dev/null +++ b/internal/use-case/main-use-case/therapy-protocol/case.go @@ -0,0 +1,310 @@ +package therapy_protocol + +import ( + "strconv" + + "gorm.io/gorm" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + ed "simrs-vx/internal/domain/main-entities/doctor" + ee "simrs-vx/internal/domain/main-entities/encounter" + e "simrs-vx/internal/domain/main-entities/therapy-protocol" + + ud "simrs-vx/internal/use-case/main-use-case/doctor" + ue "simrs-vx/internal/use-case/main-use-case/encounter" +) + +const source = "therapy-protocol" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.TherapyProtocol{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + // validate foreign key + if err := validateForeignKey(input); err != nil { + return nil, err + } + + 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 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.TherapyProtocol + var dataList []e.TherapyProtocol + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.TherapyProtocol + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.TherapyProtocol + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + // validate foreign key + if err := validateForeignKey(input.CreateDto); err != nil { + return nil, err + } + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.TherapyProtocol + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} + +func validateForeignKey(input e.CreateDto) error { + // validate encounter + if input.Encounter_Id != nil { + if _, err := ue.ReadDetail(ee.ReadDetailDto{Id: uint16(*input.Encounter_Id)}); err != nil { + return err + } + } + + // validate doctor_id + if input.Doctor_Id != nil { + if _, err := ud.ReadDetail(ed.ReadDetailDto{Id: uint16(*input.Doctor_Id)}); err != nil { + return err + } + } + + return nil +} diff --git a/internal/use-case/main-use-case/therapy-protocol/helper.go b/internal/use-case/main-use-case/therapy-protocol/helper.go new file mode 100644 index 00000000..12e48747 --- /dev/null +++ b/internal/use-case/main-use-case/therapy-protocol/helper.go @@ -0,0 +1,34 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package therapy_protocol + +import ( + e "simrs-vx/internal/domain/main-entities/therapy-protocol" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.TherapyProtocol) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Encounter_Id = inputSrc.Encounter_Id + data.Doctor_Id = inputSrc.Doctor_Id + data.Anamnesis = inputSrc.Anamnesis + data.MedicalDiagnoses = inputSrc.MedicalDiagnoses + data.FunctionDiagnoses = inputSrc.FunctionDiagnoses + data.Procedures = inputSrc.Procedures + data.SupportingExams = inputSrc.SupportingExams + data.Instruction = inputSrc.Instruction + data.Evaluation = inputSrc.Evaluation + data.WorkCauseStatus = inputSrc.WorkCauseStatus + data.Frequency = inputSrc.Frequency + data.IntervalUnit_Code = inputSrc.IntervalUnit_Code + data.Duration = inputSrc.Duration + data.DurationUnit_Code = inputSrc.DurationUnit_Code +} diff --git a/internal/use-case/main-use-case/therapy-protocol/lib.go b/internal/use-case/main-use-case/therapy-protocol/lib.go new file mode 100644 index 00000000..550ef327 --- /dev/null +++ b/internal/use-case/main-use-case/therapy-protocol/lib.go @@ -0,0 +1,145 @@ +package therapy_protocol + +import ( + "errors" + e "simrs-vx/internal/domain/main-entities/therapy-protocol" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.TherapyProtocol, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.TherapyProtocol{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.TherapyProtocol, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.TherapyProtocol{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.TherapyProtocol{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Order("\"CreatedAt\" DESC") + + if err := tx.Find(&data).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.TherapyProtocol, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.TherapyProtocol{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.TherapyProtocol, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.TherapyProtocol, 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 +} diff --git a/internal/use-case/main-use-case/therapy-protocol/middleware-runner.go b/internal/use-case/main-use-case/therapy-protocol/middleware-runner.go new file mode 100644 index 00000000..4391b63a --- /dev/null +++ b/internal/use-case/main-use-case/therapy-protocol/middleware-runner.go @@ -0,0 +1,103 @@ +package therapy_protocol + +import ( + e "simrs-vx/internal/domain/main-entities/therapy-protocol" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.TherapyProtocol) 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.TherapyProtocol) 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.TherapyProtocol) 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.TherapyProtocol) 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.TherapyProtocol) 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/main-use-case/therapy-protocol/middleware.go b/internal/use-case/main-use-case/therapy-protocol/middleware.go new file mode 100644 index 00000000..a2f3626f --- /dev/null +++ b/internal/use-case/main-use-case/therapy-protocol/middleware.go @@ -0,0 +1,9 @@ +package therapy_protocol + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/therapy-protocol/tycovar.go b/internal/use-case/main-use-case/therapy-protocol/tycovar.go new file mode 100644 index 00000000..a027e334 --- /dev/null +++ b/internal/use-case/main-use-case/therapy-protocol/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 therapy_protocol + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/therapy-protocol" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.TherapyProtocol, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.TherapyProtocol, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.TherapyProtocol, 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 From c53082fd260c1031191f318c3b9953090db911a5 Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 4 Nov 2025 15:43:10 +0700 Subject: [PATCH 059/329] add chemo protocol entity --- .../migrations/20251104084135.sql | 17 +++ cmd/main-migration/migrations/atlas.sum | 141 +++++++++--------- .../main-entities/chemo-protocol/entity.go | 21 +++ .../main-entities/therapy-protocol/entity.go | 4 +- internal/interface/migration/main-entities.go | 2 + 5 files changed, 113 insertions(+), 72 deletions(-) create mode 100644 cmd/main-migration/migrations/20251104084135.sql create mode 100644 internal/domain/main-entities/chemo-protocol/entity.go diff --git a/cmd/main-migration/migrations/20251104084135.sql b/cmd/main-migration/migrations/20251104084135.sql new file mode 100644 index 00000000..8c50d914 --- /dev/null +++ b/cmd/main-migration/migrations/20251104084135.sql @@ -0,0 +1,17 @@ +-- Create "ChemoProtocol" table +CREATE TABLE "public"."ChemoProtocol" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Patient_Weight" numeric NULL, + "Patient_Height" numeric NULL, + "Diagnoses" text NULL, + "Duration" bigint NULL, + "DurationUnit_Code" character varying(10) NULL, + "StartDate" timestamptz NULL, + "EndDate" timestamptz NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_ChemoProtocol_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index e0d46a35..40b66b02 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,70 +1,71 @@ -h1:fcpOnigzzVgIt+BimD58z3BfW5JzOXIltdMVGabIh/Q= -20250904105930.sql h1:Vv4vCurl7m7/ZB6TjRpkubHpQ4RYwSUn0QHdzfoGpzY= -20250904141448.sql h1:FYCHH9Os4KkrZMDu/jR8FMP+wLMRW+Mb0PkLU/9BRDg= -20250908062237.sql h1:oanBpKZd+akPu2I/xYhUSbd0G5tAFbXzKLER/Zs8ENI= -20250908062323.sql h1:miNG9COddXkD1jGTgaROMAZ618eT6oiLGiJhXWnQwhE= -20250908073811.sql h1:gOi5cnGG1htlpfizybYmUIT0vYjZTBfXiI0nPSYK2u8= -20250908073839.sql h1:cWNDA4YikjoOteAJuNLFILjQUJPFB6o8Wxreiek4QyI= -20250910055902.sql h1:nxxOGnU0BbH/v3IPgeIOXOwH8d3tKomw7h6FTeMnnBs= -20250915123412.sql h1:mz7SiWfrdf0qE1VTSAAnA/147d6gyp6ry5vZ2bR9SH0= -20250916043819.sql h1:RHXVtmMkB6wfv06HfPyHMBmUfIpFt1xveafNz0kwKnE= -20250917040616.sql h1:MYVDht+akBlzQGKNu2hTTTLPEcH1bxT/Q8MK6WEtuhs= -20250917040751.sql h1:J79YyS2JzWgh5oKXMTgh67uo3gLxKaAsxRiZmSIfjBs= -20250917045138.sql h1:/SM1N4O8X3yxpoJgMEARmS1uOkuLKsTOy4PLsRCOKaQ= -20250917093645.sql h1:PNBTGZ7s10e5b5+Tie8YfVQBN0zKtJ5T34oK1iOUEb4= -20250918073552.sql h1:jG7+g3i8ODYaJdcdZz12v3nbsZ5mB9wG6kWnGyTQIRI= -20250918073742.sql h1:j+rgw7puxE7s+phqPVZHmPk0af3rcaA56Itp86y1suY= -20250918074745.sql h1:rPmP4DXs6OnY4Vp+xO/z9jFpJt/RrJ52SJJjIIxeDvc= -20250923025134.sql h1:2r6pcwnBSU5Y9Czk1OHBoh4yZXiMtEca9X8843fTEX0= -20250924051317.sql h1:iUAk2gsGoEGIPQ0lEEUp8maMSId8emNbP+kP712ABIA= -20250929034321.sql h1:UlpALNVmdi95zOIT0yc6ZyTj9bBjQEIpZhvgrc52M+k= -20250929034428.sql h1:feF+H4nDyHh5bdx48Oiz0A1qecZfi6v3qTTdjzJ45Dg= -20250930025550.sql h1:6XT1kXI3Z3ZIxxmvT7poufZWWCW0QiejZPaFV5wBnjI= -20250930140351.sql h1:HxnmAbh9gCy8jwl/9ycGktiByaUripsjFFvohofY2CY= -20251002085604.sql h1:SjLPi+ZN6qDccK3DaEQCgNsZpPwr5kynWXwbwEsziCI= -20251003032030.sql h1:oHfxNSuqTxU8Zaf9H+h8TuUb1Da03wcyc6hZjDrUQ2s= -20251005060450.sql h1:GIuCcrd4MwjmXpvbzDzPYL18BV3QaZZ+Y2FmEzjvi0E= -20251006041122.sql h1:uNDQbSw0M08lYoMvUNlQtS3iDzpPM1ixT13ugSAoWjE= -20251006045658.sql h1:z+t7yCK54Q4SSiF9kUyUhkYB2F+kzSW9TB7ogxd9wzw= -20251006045928.sql h1:1lATLFLp4BWwGZqAjZdP0Dc6ypNXiYcwjoNkqGa8NFE= -20251007022859.sql h1:HXXwWrkyvzJzJGAt9mGskCRBBV/c1JfPmfjDocmJhQ4= -20251008031337.sql h1:Ln5pCF3Hxa5foHZLcds+z/us2eH6VAhhEj3w0TAGlVs= -20251008031554.sql h1:aB4MUS2lmqG0//4HKUWorcPSpWya0VC4QItvGyskEVI= -20251008052346.sql h1:MI3AZgU5XcwZT2OvvlWAxdRtL0eJ3jjRwt56IY1+pRU= -20251008073620.sql h1:sztWXuSNYwpEraaSapSsYwno75LO5H/N7ob7OJQ8X/A= -20251009042854.sql h1:TnPXj+dCJls3IU//cuqJZymyBzZMKs7ayazfgtAFRxM= -20251009052657.sql h1:leXbs0CP8r5dRilmYyLRk1MICqak3ea1/LWMtFrijqQ= -20251010031743.sql h1:SgHNY/lQ88G2F4nZyMfiOkDntb+gtOR+nEQLqXBTwv4= -20251010070721.sql h1:AnJnhXsMzDvK4AFgYw6B16Kpo/hljrZtcpc9m2VOSHQ= -20251010072711.sql h1:aXPTtNwLcTuw8C/yAxwxvqs0ayEjNzI1uuE0vE3ERa8= -20251013044536.sql h1:7Pq6JcvTpPBYDCW2dz3HdgUwY65HlhEVWy9TiG8iONE= -20251013051438.sql h1:X6t8bkqpUYYokBunSufMQUe5vCg0VyO6dxbm7ngosUc= -20251013081808.sql h1:495pLguXL2Ozh+ycn4UYZgZbn6WbjXNbyZUc3JU8qhI= -20251014060047.sql h1:nCgImMRGHhziiW57O1ofWaXCAPGaCOHN7PldQ3OSmM4= -20251014063537.sql h1:2cLmID79jP6cuQ1YJaWTtghFiM1GtHMC0ZQl30Hpy1M= -20251014063720.sql h1:bzLKKVAjSHgDFoiI/glj7t1ETlSAKx+AlsIAaP0ru2g= -20251015045455.sql h1:S547+UugQhlTRcn1Lm1IfqT5RNPttIWIiD+RTx69YaE= -20251016010845.sql h1:c9DUvxl17pUkf0azdYGM/YDzYxIJkLcfZOcMI4rL+R0= -20251016011023.sql h1:u3ivg83bXgYHBbojbWpemLxPE9Dmmj53B6LXo664jxw= -20251016062912.sql h1:W9n1hWchfYkqNX9LO9uxFxEXAb/iY+Pexjnhmp6PbgI= -20251017060617.sql h1:VU6yZ2+LfHpDZ3+TIH40t3F5YXPCpTppuF9+uSqa4b8= -20251017082207.sql h1:QshZslfedckz7iDpSGmPyY9sP6dy6ckHbs8L1TuXIA4= -20251018032635.sql h1:M1U/9W/F9wlW5YDmVAmHFfUJU7FWFaX0DblpfZcYWrE= -20251018040322.sql h1:Zk/vw0e6AzWFO2ElLOzB+OrSz6k+h1Ynxp0TImAzxwY= -20251019093915.sql h1:3Q0kPiZwJnHn5rAvdh0w1LBdiA7W2xBmZWncoPXb044= -20251020062553.sql h1:mJwC/J8GzPAIXckNMvy1f/Nguk2VVf8roD/Raclhbao= -20251021041042.sql h1:d1BAOGAQhqr+oOwcpAVozUsTh457VSDEk2qQFavGG58= -20251021075552.sql h1:TNChGQ1Zlr/1iQ6qvK4iDTAJpe6L/z/M6e/O0SkQVaM= -20251023044432.sql h1:GA2AdJk2ULyjr6igtu9C/CEi4YUIks8r9jXGGaCvPsk= -20251024034832.sql h1:RXmbEhMkOLK5g1QL6up8iRPcwYfo89oLP26ZHvrUK9o= -20251024074315.sql h1:3GnPQSbuAAfMa8oWDyBjhXqn1j1zunY/w0ydX0IGPrA= -20251025013451.sql h1:5eNrA9LDxA4i5CCP7wSyOgFZ6t6jBWVil+oGzJpkJ2E= -20251025013609.sql h1:+N6EHc1kv3hqf16CUhXe+UITPmoxOPfi4MECLmJXNrc= -20251027075128.sql h1:PQflgsjce/p2ClbybLtdehdPNDcMZ9Lb1vd98xd0K8E= -20251027091406.sql h1:bYXV57GvodCMjg0/ox+XKGIAGhrDlVuJ1wO4foNEKtQ= -20251102002037.sql h1:ZcwULsJU2lI9t5pX7ukmfAHSx4ZxdxLUX6jzLDc2SrU= -20251102091932.sql h1:A6y9j4wAqm4/HfMDxhpy/ChDn3UNRVN99KGgSCX+e18= -20251103081637.sql h1:RFqJNhJItSwJQaMP5IcQ14mL7eQ3EJjGZua9zLWzwMU= -20251104042334.sql h1:BbjLAwImggvI6489FQgD+S/AaafeiZut8k19TdH7XUE= -20251104043530.sql h1:Y0sOQqgnHxd5vKPA4+4fAGGdWCv6duKAYgHnjRJZUIc= -20251104080952.sql h1:hDHzFs/k+NhPYJ64ifbVp+nTJLMCG5MIMJU1zBMP0V0= +h1:drtrRtMhlNYK0c9wV3CUkJvXwWgrD8xGPPJy9wlcvNA= +20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= +20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= +20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= +20250908062323.sql h1:oXl6Z143tOpIl4EfP4B8JNU8LrMvVmHEtCgAfiB4gs8= +20250908073811.sql h1:m2aNXfnGxnLq1+rVWrh4f60q7fhyhV3gEwNu/OIqQlE= +20250908073839.sql h1:cPk54xjLdMs26uY8ZHjNWLuyfAMzV7Zb0/9oJQrsw04= +20250910055902.sql h1:5xwjAV6QbtZT9empTJKfhyAjdknbHzb15B0Ku5dzqtQ= +20250915123412.sql h1:D83xaU2YlDEd21HLup/YQpQ2easMToYCyy/oK6AFgQs= +20250916043819.sql h1:ekoTJsBqQZ8G8n0qJ03d13+eoNoc7sAUEQGA5D/CCxk= +20250917040616.sql h1:zoCnmcXuM7AVv85SmN7RmFglCgJnoDmpRWExH0LAc9Q= +20250917040751.sql h1:J1xyRrh32y1+lezwAyNwPcUQ6ABBSgbvzNLva4SVdQU= +20250917045138.sql h1:jKe1Z0uOLG4SGBYM+S/3P+/zMPztmgoderD5swnMuCg= +20250917093645.sql h1:cNI3Pbz1R3LxvIXLuexafJFCXUXrmuFCgXXJ2sG+FW0= +20250918073552.sql h1:RJ1SvMzP6aeWnoPVD3eVAmIQOkcp6Php8z3QRri6v4g= +20250918073742.sql h1:+cEsnJTJFybe2fR69ZoOiX2R6c6iITl4m6WTZ1hjyzY= +20250918074745.sql h1:2hNVQCXF/dVYXAh+T/7oBFgERGWxzVb2FXJjwkFWGCI= +20250923025134.sql h1:Ykz/qpHiGDXPsCsWTjydQFVSibZP2D+h2fIeb2h2JGA= +20250924051317.sql h1:yQuW6SwJxIOM5fcxeAaie5lSm1oLysU/C2hH2xNCVoQ= +20250929034321.sql h1:101FJ8VH12mrZWlt/X1gvKUGOhoiF8tFbjiapAjnHzg= +20250929034428.sql h1:i+pROD9p+g5dOmmZma6WF/0Hw5g3Ha28NN85iTo1K34= +20250930025550.sql h1:+F+CsCUXD/ql0tHGEow70GhPBX1ZybVn+bh/T4YMh7Y= +20250930140351.sql h1:9AAEG1AnOAH+o0+oHL5G7I8vqlWOhwRlCGyyCpT/y1Q= +20251002085604.sql h1:3xZ68eYp4urXRnvotNH1XvG2mYOSDV/j3zHEZ/txg5E= +20251003032030.sql h1:HB+mQ2lXMNomHDpaRhB/9IwYI9/YiDO5eOJ+nAQH/jw= +20251005060450.sql h1:LbtCE2b+8osM3CvnmQJH1uCPtn+d7WchsslBOz8bL3Q= +20251006041122.sql h1:MlS7f21z06sutnf9dIekt5fuHJr4lgcQ4uCuCXAGsfc= +20251006045658.sql h1:3FmGCPCzjgMPdWDRodZTsx3KVaodd9zB9ilib69aewk= +20251006045928.sql h1:Z5g31PmnzNwk/OKdODcxZGm8fjJQdMFK32Xfnt3bRHg= +20251007022859.sql h1:FO03zEfaNEk/aXwY81d5Lp3MoBB9kPQuXlXJ4BPiSR8= +20251008031337.sql h1:l+sxUAGvcTfj3I6kAFHo+T6AYodC9k9GkR+jaKO2xXc= +20251008031554.sql h1:AqrVfIhSzY3PCy8ZlP5W91wn2iznfIuj5qQfubp6/94= +20251008052346.sql h1:nxnXmooIJ6r1mmzwnw+6efxLfc/k9h2aE6RMptPRons= +20251008073620.sql h1:6YsJp1W4SmQJ1lxpqF27BBlDC1zqhw7Yhc7pLzQTY6M= +20251009042854.sql h1:nkBV+R6j0fg7/JY6wH3eb5Vv0asJLnXmb6lINfT/GLQ= +20251009052657.sql h1:EPvdsib5rzCGPryd10HShGKvFPwM/R5S2lIVwtYxpms= +20251010031743.sql h1:T8IZmx8/btRFKLzTe78MzcBsPJNodnLvB0tby9QkirQ= +20251010070721.sql h1:5NQUk/yOV6sABLCB7swx++YIOyJe6MnU+yt1nRzde5w= +20251010072711.sql h1:ZJNqR2piyu8xJhBvVABSlnGEoKSKae3wuEs+wshPe4k= +20251013044536.sql h1:0Xjw8fNILiT8nnfrJDZgQnPf3dntmIoilbapnih8AE4= +20251013051438.sql h1:lfSuw5mgJnePBJamvhZ81osFIouXeiIEiSZ/evdwo48= +20251013081808.sql h1:ijgjNX08G6GBjA/ks8EKtb7P7Y7Cg7zbhqEOruGnv6M= +20251014060047.sql h1:0jqj49WTtneEIMQDBoo4c095ZGi8sCrA8NnHBrPU6D8= +20251014063537.sql h1:VZLXol0PTsTW21Epg6vBPsztWkDtcxup9F/z88EGgIg= +20251014063720.sql h1:2HVUyCV0ud3BJJDH2GEKZN/+IWLFPCsN1KqhP6csO14= +20251015045455.sql h1:MeLWmMhAOAz8b15Dd7IAQnt6JxjSml02XCXK22C0Lpg= +20251016010845.sql h1:4BncQdDOasRZJkzVJrSJJA7091A9VPNVx/faUCUPhBM= +20251016011023.sql h1:9JB9eFZKURK5RoCVDKR6glSvdJ8NTXrN7K/4q51zkz4= +20251016062912.sql h1:ACNn0fe+EMqUt3hoY+Dr3uqAV/QICBa1+mIW7fUc9Fk= +20251017060617.sql h1:4T3t9ifWrEQTPMSM0XJ98pF7Qdt+UfgtMui17bhrnWI= +20251017082207.sql h1:8vLG1l/saRRMHXkyA4nelJyjaSddhZd6r7R+Uo4JS/c= +20251018032635.sql h1:2xey5gnO3y2XSOrU8MLlIfoylPKbRGDRtHDD07B3MbQ= +20251018040322.sql h1:k/pdNiSoT8zFPqNQ/avOD0vYkNh3BTD64IlHrfVXr7I= +20251019093915.sql h1:hFcQE0y+p5dZiVwePGsRGto9m/q6kJNiUZbVDd5Rnjk= +20251020062553.sql h1:Iw7hulcm5iRQlfW+ygA4iTPxLqkxx6h9vXMXEwUAHKs= +20251021041042.sql h1:wMgSivBV2A0NDcsLmKGIp0kMcVh2IODSG9b4dgzCaOM= +20251021075552.sql h1:8gfSMAglflNO6L0sSzxFNEubYN8/O4thT7OQT+WH+3M= +20251023044432.sql h1:MkvajJs3bfk9+wHvQ43/ccAluJEBARm1gWr1u92ccLA= +20251024034832.sql h1:x3s3VEVYLOSKLAFxJGb2+c1FyTMMvPE+9k4Ew7rKQaI= +20251024074315.sql h1:EjAjelgi5qAfcRq/8vPTlGGYHvAKxNTllm8f0SzZDns= +20251025013451.sql h1:6hnuIiwYiG+6nLhOY/+Yyn+I6ZCFNRZxrJNqBV6HLqE= +20251025013609.sql h1:evPJaTD8WxYRMOJZHkSr7ONLx9PYxT+ankzQt9c/sJ0= +20251027075128.sql h1:/iFQBM1sytjqpyQSOx61q33gnorMgxTiFVSuL6bQqsM= +20251027091406.sql h1:eCZGtUkxAzEAqpC9UsGpP8Df9mS0DEOqSl885LgqpvM= +20251102002037.sql h1:lFJbuoZ2LMQnUNGdcwHVY3Xlfslgzu9t2WByT8yfOZI= +20251102091932.sql h1:rmdhb5m+P+fU8jROBZNyeYgZKuQvucsuljXv4ZVzvks= +20251103081637.sql h1:tf3BcwTeIw+oxMEisKDDfyKnBfalTLs8b0PJA8JWYxY= +20251104042334.sql h1:7PDMWOhmJywolAPKFZ14XaDBeMvcxShaXFN2IemNtzk= +20251104043530.sql h1:qvYVp3ysPf27f1BcoRNCFGovxuVE12lg9d6Xzda6zWU= +20251104080952.sql h1:avghpv1n3yaCDR/TA0X+hgxDGoLBQGu/GJUwj4VT/Ic= +20251104084135.sql h1:Y4coFrHgDXd/DM8ihEy+qMkOSrO8M4SI4shRCJIiBBA= diff --git a/internal/domain/main-entities/chemo-protocol/entity.go b/internal/domain/main-entities/chemo-protocol/entity.go new file mode 100644 index 00000000..e1508e91 --- /dev/null +++ b/internal/domain/main-entities/chemo-protocol/entity.go @@ -0,0 +1,21 @@ +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" +) + +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"` +} diff --git a/internal/domain/main-entities/therapy-protocol/entity.go b/internal/domain/main-entities/therapy-protocol/entity.go index 99b5b59d..f5ec318a 100644 --- a/internal/domain/main-entities/therapy-protocol/entity.go +++ b/internal/domain/main-entities/therapy-protocol/entity.go @@ -25,7 +25,7 @@ type TherapyProtocol struct { Evaluation *string `json:"evaluation" gorm:"size:2048"` WorkCauseStatus *string `json:"workCauseStatus" gorm:"size:2048"` Frequency *uint `json:"frequency"` - IntervalUnit_Code *common.TimeUnitCode `json:"intervalUnit_Code" gorm:"size:10"` + IntervalUnit_Code *common.TimeUnitCode `json:"intervalUnit_code" gorm:"size:10"` Duration *uint `json:"duration"` - DurationUnit_Code *common.TimeUnitCode `json:"durationUnit_Code" gorm:"size:10"` + DurationUnit_Code *common.TimeUnitCode `json:"durationUnit_code" gorm:"size:10"` } diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index fac22ea6..0b3a9970 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -7,6 +7,7 @@ import ( ambulatory "simrs-vx/internal/domain/main-entities/ambulatory" appointment "simrs-vx/internal/domain/main-entities/appointment" chemo "simrs-vx/internal/domain/main-entities/chemo" + 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" counter "simrs-vx/internal/domain/main-entities/counter" @@ -197,5 +198,6 @@ func getMainEntities() []any { &vclaimmember.VclaimMember{}, &controlletter.ControlLetter{}, &rehab.Rehab{}, + &chemoprotocol.ChemoProtocol{}, } } From 28927d4c8b3d5d979ef78edf053d14bc1b60824b Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 4 Nov 2025 16:13:19 +0700 Subject: [PATCH 060/329] add chemo protocol --- .../main-entities/adm-employee-hist/dto.go | 5 +- .../main-entities/chemo-protocol/dto.go | 91 ++++++ .../responsible-doctor-hist/dto.go | 5 +- .../main-handler/chemo-protocol/handler.go | 72 +++++ .../interface/main-handler/main-handler.go | 2 + .../main-use-case/adm-employee-hist/lib.go | 21 +- .../main-use-case/chemo-protocol/case.go | 277 ++++++++++++++++++ .../main-use-case/chemo-protocol/helper.go | 28 ++ .../main-use-case/chemo-protocol/lib.go | 147 ++++++++++ .../chemo-protocol/middleware-runner.go | 103 +++++++ .../chemo-protocol/middleware.go | 9 + .../main-use-case/chemo-protocol/tycovar.go | 44 +++ .../responsible-doctor-hist/lib.go | 21 +- 13 files changed, 787 insertions(+), 38 deletions(-) create mode 100644 internal/domain/main-entities/chemo-protocol/dto.go create mode 100644 internal/interface/main-handler/chemo-protocol/handler.go create mode 100644 internal/use-case/main-use-case/chemo-protocol/case.go create mode 100644 internal/use-case/main-use-case/chemo-protocol/helper.go create mode 100644 internal/use-case/main-use-case/chemo-protocol/lib.go create mode 100644 internal/use-case/main-use-case/chemo-protocol/middleware-runner.go create mode 100644 internal/use-case/main-use-case/chemo-protocol/middleware.go create mode 100644 internal/use-case/main-use-case/chemo-protocol/tycovar.go diff --git a/internal/domain/main-entities/adm-employee-hist/dto.go b/internal/domain/main-entities/adm-employee-hist/dto.go index 9a5d838f..a3500060 100644 --- a/internal/domain/main-entities/adm-employee-hist/dto.go +++ b/internal/domain/main-entities/adm-employee-hist/dto.go @@ -28,9 +28,8 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` - Code *string `json:"code"` - Includes string `json:"includes"` + Id uint16 `json:"id"` + Includes string `json:"includes"` } type UpdateDto struct { diff --git a/internal/domain/main-entities/chemo-protocol/dto.go b/internal/domain/main-entities/chemo-protocol/dto.go new file mode 100644 index 00000000..04ea0023 --- /dev/null +++ b/internal/domain/main-entities/chemo-protocol/dto.go @@ -0,0 +1,91 @@ +package chemo_protocol + +import ( + // std + "time" + + // internal - domain - references + erc "simrs-vx/internal/domain/references/common" + + // internal - domain - main-entities + ecore "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/encounter" +) + +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"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Encounter_Id *uint `json:"encounter-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 + 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"` +} + +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, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []ChemoProtocol) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/responsible-doctor-hist/dto.go b/internal/domain/main-entities/responsible-doctor-hist/dto.go index 342faffa..68c8dd21 100644 --- a/internal/domain/main-entities/responsible-doctor-hist/dto.go +++ b/internal/domain/main-entities/responsible-doctor-hist/dto.go @@ -28,9 +28,8 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` - Code *string `json:"code"` - Includes string `json:"includes"` + Id uint16 `json:"id"` + Includes string `json:"includes"` } type UpdateDto struct { diff --git a/internal/interface/main-handler/chemo-protocol/handler.go b/internal/interface/main-handler/chemo-protocol/handler.go new file mode 100644 index 00000000..60d9db4d --- /dev/null +++ b/internal/interface/main-handler/chemo-protocol/handler.go @@ -0,0 +1,72 @@ +package chemo_protocol + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + e "simrs-vx/internal/domain/main-entities/chemo-protocol" + u "simrs-vx/internal/use-case/main-use-case/chemo-protocol" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + sf.UrlQueryParam(&dto, *r.URL) + + dto.Id = uint16(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint16(id) + 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 = uint16(id) + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 554de761..1c703b64 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -9,6 +9,7 @@ import ( ambulancetransportrequest "simrs-vx/internal/interface/main-handler/ambulance-transport-req" auth "simrs-vx/internal/interface/main-handler/authentication" chemo "simrs-vx/internal/interface/main-handler/chemo" + chemoprotocol "simrs-vx/internal/interface/main-handler/chemo-protocol" consultation "simrs-vx/internal/interface/main-handler/consultation" controlletter "simrs-vx/internal/interface/main-handler/control-letter" counter "simrs-vx/internal/interface/main-handler/counter" @@ -259,6 +260,7 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/responsible-doctor-hist", responsibledoctorhist.O) hc.RegCrud(r, "/v1/adm-employee-hist", admemployeehist.O) hc.RegCrud(r, "/v1/therapy-protocol", therapyprotocol.O) + hc.RegCrud(r, "/v1/chemo-protocol", chemoprotocol.O) /******************** actor ********************/ hc.RegCrud(r, "/v1/person", person.O) diff --git a/internal/use-case/main-use-case/adm-employee-hist/lib.go b/internal/use-case/main-use-case/adm-employee-hist/lib.go index dc03b28a..6bdcbe22 100644 --- a/internal/use-case/main-use-case/adm-employee-hist/lib.go +++ b/internal/use-case/main-use-case/adm-employee-hist/lib.go @@ -75,29 +75,18 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e pl.SetLogInfo(event, input, "started", "DBReadDetail") data := e.AdmEmployeeHist{} - var tx, getData *gorm.DB + var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] } else { tx = dg.I } - switch { - case input.Id != 0: - getData = tx.First(&data, input.Id) - case input.Code != nil && *input.Code != "": - getData = tx.Where("code = ?", *input.Code).First(&data) - default: - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-read-detail-fail", - Detail: "either Id or Code must be provided", - } + if err := tx. + Scopes(gh.Preload(input.Includes)). + First(&data, input.Id). + Error; err != nil { - return nil, pl.SetLogError(event, nil) - } - - if err := getData.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/chemo-protocol/case.go b/internal/use-case/main-use-case/chemo-protocol/case.go new file mode 100644 index 00000000..4e007d28 --- /dev/null +++ b/internal/use-case/main-use-case/chemo-protocol/case.go @@ -0,0 +1,277 @@ +package chemo_protocol + +import ( + "strconv" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/chemo-protocol" +) + +const source = "chemo-protocol" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.ChemoProtocol{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.ChemoProtocol + var dataList []e.ChemoProtocol + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.ChemoProtocol + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.ChemoProtocol + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.ChemoProtocol + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/chemo-protocol/helper.go b/internal/use-case/main-use-case/chemo-protocol/helper.go new file mode 100644 index 00000000..885e6fbb --- /dev/null +++ b/internal/use-case/main-use-case/chemo-protocol/helper.go @@ -0,0 +1,28 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package chemo_protocol + +import ( + e "simrs-vx/internal/domain/main-entities/chemo-protocol" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.ChemoProtocol) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + 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/chemo-protocol/lib.go b/internal/use-case/main-use-case/chemo-protocol/lib.go new file mode 100644 index 00000000..22e8808c --- /dev/null +++ b/internal/use-case/main-use-case/chemo-protocol/lib.go @@ -0,0 +1,147 @@ +package chemo_protocol + +import ( + "errors" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + + e "simrs-vx/internal/domain/main-entities/chemo-protocol" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.ChemoProtocol, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.ChemoProtocol{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.ChemoProtocol, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.ChemoProtocol{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.ChemoProtocol{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Order("\"CreatedAt\" DESC") + + if err := tx.Find(&data).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.ChemoProtocol, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.ChemoProtocol{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.ChemoProtocol, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.ChemoProtocol, 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 +} diff --git a/internal/use-case/main-use-case/chemo-protocol/middleware-runner.go b/internal/use-case/main-use-case/chemo-protocol/middleware-runner.go new file mode 100644 index 00000000..7c932d7b --- /dev/null +++ b/internal/use-case/main-use-case/chemo-protocol/middleware-runner.go @@ -0,0 +1,103 @@ +package chemo_protocol + +import ( + e "simrs-vx/internal/domain/main-entities/chemo-protocol" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.ChemoProtocol) 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.ChemoProtocol) 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.ChemoProtocol) 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.ChemoProtocol) 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.ChemoProtocol) 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/main-use-case/chemo-protocol/middleware.go b/internal/use-case/main-use-case/chemo-protocol/middleware.go new file mode 100644 index 00000000..a438fd1c --- /dev/null +++ b/internal/use-case/main-use-case/chemo-protocol/middleware.go @@ -0,0 +1,9 @@ +package chemo_protocol + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/chemo-protocol/tycovar.go b/internal/use-case/main-use-case/chemo-protocol/tycovar.go new file mode 100644 index 00000000..f4822996 --- /dev/null +++ b/internal/use-case/main-use-case/chemo-protocol/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 chemo_protocol + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/chemo-protocol" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.ChemoProtocol, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.ChemoProtocol, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.ChemoProtocol, 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/main-use-case/responsible-doctor-hist/lib.go b/internal/use-case/main-use-case/responsible-doctor-hist/lib.go index d91294fe..3f035d5e 100644 --- a/internal/use-case/main-use-case/responsible-doctor-hist/lib.go +++ b/internal/use-case/main-use-case/responsible-doctor-hist/lib.go @@ -75,29 +75,18 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e pl.SetLogInfo(event, input, "started", "DBReadDetail") data := e.ResponsibleDoctorHist{} - var tx, getData *gorm.DB + var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] } else { tx = dg.I } - switch { - case input.Id != 0: - getData = tx.First(&data, input.Id) - case input.Code != nil && *input.Code != "": - getData = tx.Where("code = ?", *input.Code).First(&data) - default: - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-read-detail-fail", - Detail: "either Id or Code must be provided", - } + if err := tx. + Scopes(gh.Preload(input.Includes)). + First(&data, input.Id). + Error; err != nil { - return nil, pl.SetLogError(event, nil) - } - - if err := getData.Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { return nil, processedErr } From 4173b20165db8f1377f9e75023c71201452a351d Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 4 Nov 2025 16:27:47 +0700 Subject: [PATCH 061/329] delete debug --- internal/domain/main-entities/ambulatory/dto.go | 1 + internal/domain/main-entities/encounter/dto.go | 4 ++-- internal/use-case/main-use-case/encounter/helper.go | 2 +- internal/use-case/main-use-case/encounter/lib.go | 1 - 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/domain/main-entities/ambulatory/dto.go b/internal/domain/main-entities/ambulatory/dto.go index 42ece735..f580467a 100644 --- a/internal/domain/main-entities/ambulatory/dto.go +++ b/internal/domain/main-entities/ambulatory/dto.go @@ -50,6 +50,7 @@ type ResponseDto struct { func (d Ambulatory) ToResponse() ResponseDto { resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, Class_Code: d.Class_Code, VisitMode_Code: d.VisitMode_Code, } diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index 0d5e1aae..6782b18c 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -48,8 +48,8 @@ type CreateDto struct { Appointment_Id *uint `json:"appointment_id"` RefTypeCode ere.RefTypeCode `json:"refTypeCode"` NewStatus bool `json:"newStatus"` - VisitMode_Code *ere.VisitModeCode `json:"visitMode_code"` // if subClass_Code is rehab - AllocatedVisitCount *int `json:"allocatedVisitCount"` + VisitMode_Code *ere.VisitModeCode `json:"visitMode_code"` // if subClass_Code is rehab + AllocatedVisitCount *int `json:"allocatedVisitCount"` // if subClass_Code is rehab and VisitMode_Code is "adm" pa.AuthInfo } diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index 4bf7be60..67cef58b 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -641,7 +641,7 @@ func getSoapiEncounterAdm(enc e.Encounter, event *pl.Event) (dataSoapi []es.Crea } } - err = dg.I.Debug(). + err = dg.I. Model(&es.Soapi{}). Joins("JOIN \"Employee\" ON \"Employee\".\"Id\" = \"Soapi\".\"Employee_Id\""). Where("\"Encounter_Id\" = ?", enc.Id). diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index d80fd513..0c51a8d6 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -276,7 +276,6 @@ func verifyAllocatedVisitCount(i e.CreateDto, event *pl.Event) (e.Encounter, boo } err = tx. - Debug(). Model(&e.Encounter{}). Joins("JOIN \"Ambulatory\" ON \"Ambulatory\".\"Encounter_Id\" = \"Encounter\".\"Id\""). Where("\"Patient_Id\" = ?", i.Patient_Id). From 5c8c5511d9c51c65257136d22fc2d28ed4bf8a28 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Wed, 5 Nov 2025 11:18:38 +0700 Subject: [PATCH 062/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 142 ++++++++++++------------ 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 40b66b02..d2c79b63 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,71 +1,71 @@ -h1:drtrRtMhlNYK0c9wV3CUkJvXwWgrD8xGPPJy9wlcvNA= -20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= -20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= -20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= -20250908062323.sql h1:oXl6Z143tOpIl4EfP4B8JNU8LrMvVmHEtCgAfiB4gs8= -20250908073811.sql h1:m2aNXfnGxnLq1+rVWrh4f60q7fhyhV3gEwNu/OIqQlE= -20250908073839.sql h1:cPk54xjLdMs26uY8ZHjNWLuyfAMzV7Zb0/9oJQrsw04= -20250910055902.sql h1:5xwjAV6QbtZT9empTJKfhyAjdknbHzb15B0Ku5dzqtQ= -20250915123412.sql h1:D83xaU2YlDEd21HLup/YQpQ2easMToYCyy/oK6AFgQs= -20250916043819.sql h1:ekoTJsBqQZ8G8n0qJ03d13+eoNoc7sAUEQGA5D/CCxk= -20250917040616.sql h1:zoCnmcXuM7AVv85SmN7RmFglCgJnoDmpRWExH0LAc9Q= -20250917040751.sql h1:J1xyRrh32y1+lezwAyNwPcUQ6ABBSgbvzNLva4SVdQU= -20250917045138.sql h1:jKe1Z0uOLG4SGBYM+S/3P+/zMPztmgoderD5swnMuCg= -20250917093645.sql h1:cNI3Pbz1R3LxvIXLuexafJFCXUXrmuFCgXXJ2sG+FW0= -20250918073552.sql h1:RJ1SvMzP6aeWnoPVD3eVAmIQOkcp6Php8z3QRri6v4g= -20250918073742.sql h1:+cEsnJTJFybe2fR69ZoOiX2R6c6iITl4m6WTZ1hjyzY= -20250918074745.sql h1:2hNVQCXF/dVYXAh+T/7oBFgERGWxzVb2FXJjwkFWGCI= -20250923025134.sql h1:Ykz/qpHiGDXPsCsWTjydQFVSibZP2D+h2fIeb2h2JGA= -20250924051317.sql h1:yQuW6SwJxIOM5fcxeAaie5lSm1oLysU/C2hH2xNCVoQ= -20250929034321.sql h1:101FJ8VH12mrZWlt/X1gvKUGOhoiF8tFbjiapAjnHzg= -20250929034428.sql h1:i+pROD9p+g5dOmmZma6WF/0Hw5g3Ha28NN85iTo1K34= -20250930025550.sql h1:+F+CsCUXD/ql0tHGEow70GhPBX1ZybVn+bh/T4YMh7Y= -20250930140351.sql h1:9AAEG1AnOAH+o0+oHL5G7I8vqlWOhwRlCGyyCpT/y1Q= -20251002085604.sql h1:3xZ68eYp4urXRnvotNH1XvG2mYOSDV/j3zHEZ/txg5E= -20251003032030.sql h1:HB+mQ2lXMNomHDpaRhB/9IwYI9/YiDO5eOJ+nAQH/jw= -20251005060450.sql h1:LbtCE2b+8osM3CvnmQJH1uCPtn+d7WchsslBOz8bL3Q= -20251006041122.sql h1:MlS7f21z06sutnf9dIekt5fuHJr4lgcQ4uCuCXAGsfc= -20251006045658.sql h1:3FmGCPCzjgMPdWDRodZTsx3KVaodd9zB9ilib69aewk= -20251006045928.sql h1:Z5g31PmnzNwk/OKdODcxZGm8fjJQdMFK32Xfnt3bRHg= -20251007022859.sql h1:FO03zEfaNEk/aXwY81d5Lp3MoBB9kPQuXlXJ4BPiSR8= -20251008031337.sql h1:l+sxUAGvcTfj3I6kAFHo+T6AYodC9k9GkR+jaKO2xXc= -20251008031554.sql h1:AqrVfIhSzY3PCy8ZlP5W91wn2iznfIuj5qQfubp6/94= -20251008052346.sql h1:nxnXmooIJ6r1mmzwnw+6efxLfc/k9h2aE6RMptPRons= -20251008073620.sql h1:6YsJp1W4SmQJ1lxpqF27BBlDC1zqhw7Yhc7pLzQTY6M= -20251009042854.sql h1:nkBV+R6j0fg7/JY6wH3eb5Vv0asJLnXmb6lINfT/GLQ= -20251009052657.sql h1:EPvdsib5rzCGPryd10HShGKvFPwM/R5S2lIVwtYxpms= -20251010031743.sql h1:T8IZmx8/btRFKLzTe78MzcBsPJNodnLvB0tby9QkirQ= -20251010070721.sql h1:5NQUk/yOV6sABLCB7swx++YIOyJe6MnU+yt1nRzde5w= -20251010072711.sql h1:ZJNqR2piyu8xJhBvVABSlnGEoKSKae3wuEs+wshPe4k= -20251013044536.sql h1:0Xjw8fNILiT8nnfrJDZgQnPf3dntmIoilbapnih8AE4= -20251013051438.sql h1:lfSuw5mgJnePBJamvhZ81osFIouXeiIEiSZ/evdwo48= -20251013081808.sql h1:ijgjNX08G6GBjA/ks8EKtb7P7Y7Cg7zbhqEOruGnv6M= -20251014060047.sql h1:0jqj49WTtneEIMQDBoo4c095ZGi8sCrA8NnHBrPU6D8= -20251014063537.sql h1:VZLXol0PTsTW21Epg6vBPsztWkDtcxup9F/z88EGgIg= -20251014063720.sql h1:2HVUyCV0ud3BJJDH2GEKZN/+IWLFPCsN1KqhP6csO14= -20251015045455.sql h1:MeLWmMhAOAz8b15Dd7IAQnt6JxjSml02XCXK22C0Lpg= -20251016010845.sql h1:4BncQdDOasRZJkzVJrSJJA7091A9VPNVx/faUCUPhBM= -20251016011023.sql h1:9JB9eFZKURK5RoCVDKR6glSvdJ8NTXrN7K/4q51zkz4= -20251016062912.sql h1:ACNn0fe+EMqUt3hoY+Dr3uqAV/QICBa1+mIW7fUc9Fk= -20251017060617.sql h1:4T3t9ifWrEQTPMSM0XJ98pF7Qdt+UfgtMui17bhrnWI= -20251017082207.sql h1:8vLG1l/saRRMHXkyA4nelJyjaSddhZd6r7R+Uo4JS/c= -20251018032635.sql h1:2xey5gnO3y2XSOrU8MLlIfoylPKbRGDRtHDD07B3MbQ= -20251018040322.sql h1:k/pdNiSoT8zFPqNQ/avOD0vYkNh3BTD64IlHrfVXr7I= -20251019093915.sql h1:hFcQE0y+p5dZiVwePGsRGto9m/q6kJNiUZbVDd5Rnjk= -20251020062553.sql h1:Iw7hulcm5iRQlfW+ygA4iTPxLqkxx6h9vXMXEwUAHKs= -20251021041042.sql h1:wMgSivBV2A0NDcsLmKGIp0kMcVh2IODSG9b4dgzCaOM= -20251021075552.sql h1:8gfSMAglflNO6L0sSzxFNEubYN8/O4thT7OQT+WH+3M= -20251023044432.sql h1:MkvajJs3bfk9+wHvQ43/ccAluJEBARm1gWr1u92ccLA= -20251024034832.sql h1:x3s3VEVYLOSKLAFxJGb2+c1FyTMMvPE+9k4Ew7rKQaI= -20251024074315.sql h1:EjAjelgi5qAfcRq/8vPTlGGYHvAKxNTllm8f0SzZDns= -20251025013451.sql h1:6hnuIiwYiG+6nLhOY/+Yyn+I6ZCFNRZxrJNqBV6HLqE= -20251025013609.sql h1:evPJaTD8WxYRMOJZHkSr7ONLx9PYxT+ankzQt9c/sJ0= -20251027075128.sql h1:/iFQBM1sytjqpyQSOx61q33gnorMgxTiFVSuL6bQqsM= -20251027091406.sql h1:eCZGtUkxAzEAqpC9UsGpP8Df9mS0DEOqSl885LgqpvM= -20251102002037.sql h1:lFJbuoZ2LMQnUNGdcwHVY3Xlfslgzu9t2WByT8yfOZI= -20251102091932.sql h1:rmdhb5m+P+fU8jROBZNyeYgZKuQvucsuljXv4ZVzvks= -20251103081637.sql h1:tf3BcwTeIw+oxMEisKDDfyKnBfalTLs8b0PJA8JWYxY= -20251104042334.sql h1:7PDMWOhmJywolAPKFZ14XaDBeMvcxShaXFN2IemNtzk= -20251104043530.sql h1:qvYVp3ysPf27f1BcoRNCFGovxuVE12lg9d6Xzda6zWU= -20251104080952.sql h1:avghpv1n3yaCDR/TA0X+hgxDGoLBQGu/GJUwj4VT/Ic= -20251104084135.sql h1:Y4coFrHgDXd/DM8ihEy+qMkOSrO8M4SI4shRCJIiBBA= +h1:XcM4BDP+DX+wOQ5ldDbxOZWeqFBrXyFHkmVIlIdlfBs= +20250904105930.sql h1:Vv4vCurl7m7/ZB6TjRpkubHpQ4RYwSUn0QHdzfoGpzY= +20250904141448.sql h1:FYCHH9Os4KkrZMDu/jR8FMP+wLMRW+Mb0PkLU/9BRDg= +20250908062237.sql h1:oanBpKZd+akPu2I/xYhUSbd0G5tAFbXzKLER/Zs8ENI= +20250908062323.sql h1:miNG9COddXkD1jGTgaROMAZ618eT6oiLGiJhXWnQwhE= +20250908073811.sql h1:gOi5cnGG1htlpfizybYmUIT0vYjZTBfXiI0nPSYK2u8= +20250908073839.sql h1:cWNDA4YikjoOteAJuNLFILjQUJPFB6o8Wxreiek4QyI= +20250910055902.sql h1:nxxOGnU0BbH/v3IPgeIOXOwH8d3tKomw7h6FTeMnnBs= +20250915123412.sql h1:mz7SiWfrdf0qE1VTSAAnA/147d6gyp6ry5vZ2bR9SH0= +20250916043819.sql h1:RHXVtmMkB6wfv06HfPyHMBmUfIpFt1xveafNz0kwKnE= +20250917040616.sql h1:MYVDht+akBlzQGKNu2hTTTLPEcH1bxT/Q8MK6WEtuhs= +20250917040751.sql h1:J79YyS2JzWgh5oKXMTgh67uo3gLxKaAsxRiZmSIfjBs= +20250917045138.sql h1:/SM1N4O8X3yxpoJgMEARmS1uOkuLKsTOy4PLsRCOKaQ= +20250917093645.sql h1:PNBTGZ7s10e5b5+Tie8YfVQBN0zKtJ5T34oK1iOUEb4= +20250918073552.sql h1:jG7+g3i8ODYaJdcdZz12v3nbsZ5mB9wG6kWnGyTQIRI= +20250918073742.sql h1:j+rgw7puxE7s+phqPVZHmPk0af3rcaA56Itp86y1suY= +20250918074745.sql h1:rPmP4DXs6OnY4Vp+xO/z9jFpJt/RrJ52SJJjIIxeDvc= +20250923025134.sql h1:2r6pcwnBSU5Y9Czk1OHBoh4yZXiMtEca9X8843fTEX0= +20250924051317.sql h1:iUAk2gsGoEGIPQ0lEEUp8maMSId8emNbP+kP712ABIA= +20250929034321.sql h1:UlpALNVmdi95zOIT0yc6ZyTj9bBjQEIpZhvgrc52M+k= +20250929034428.sql h1:feF+H4nDyHh5bdx48Oiz0A1qecZfi6v3qTTdjzJ45Dg= +20250930025550.sql h1:6XT1kXI3Z3ZIxxmvT7poufZWWCW0QiejZPaFV5wBnjI= +20250930140351.sql h1:HxnmAbh9gCy8jwl/9ycGktiByaUripsjFFvohofY2CY= +20251002085604.sql h1:SjLPi+ZN6qDccK3DaEQCgNsZpPwr5kynWXwbwEsziCI= +20251003032030.sql h1:oHfxNSuqTxU8Zaf9H+h8TuUb1Da03wcyc6hZjDrUQ2s= +20251005060450.sql h1:GIuCcrd4MwjmXpvbzDzPYL18BV3QaZZ+Y2FmEzjvi0E= +20251006041122.sql h1:uNDQbSw0M08lYoMvUNlQtS3iDzpPM1ixT13ugSAoWjE= +20251006045658.sql h1:z+t7yCK54Q4SSiF9kUyUhkYB2F+kzSW9TB7ogxd9wzw= +20251006045928.sql h1:1lATLFLp4BWwGZqAjZdP0Dc6ypNXiYcwjoNkqGa8NFE= +20251007022859.sql h1:HXXwWrkyvzJzJGAt9mGskCRBBV/c1JfPmfjDocmJhQ4= +20251008031337.sql h1:Ln5pCF3Hxa5foHZLcds+z/us2eH6VAhhEj3w0TAGlVs= +20251008031554.sql h1:aB4MUS2lmqG0//4HKUWorcPSpWya0VC4QItvGyskEVI= +20251008052346.sql h1:MI3AZgU5XcwZT2OvvlWAxdRtL0eJ3jjRwt56IY1+pRU= +20251008073620.sql h1:sztWXuSNYwpEraaSapSsYwno75LO5H/N7ob7OJQ8X/A= +20251009042854.sql h1:TnPXj+dCJls3IU//cuqJZymyBzZMKs7ayazfgtAFRxM= +20251009052657.sql h1:leXbs0CP8r5dRilmYyLRk1MICqak3ea1/LWMtFrijqQ= +20251010031743.sql h1:SgHNY/lQ88G2F4nZyMfiOkDntb+gtOR+nEQLqXBTwv4= +20251010070721.sql h1:AnJnhXsMzDvK4AFgYw6B16Kpo/hljrZtcpc9m2VOSHQ= +20251010072711.sql h1:aXPTtNwLcTuw8C/yAxwxvqs0ayEjNzI1uuE0vE3ERa8= +20251013044536.sql h1:7Pq6JcvTpPBYDCW2dz3HdgUwY65HlhEVWy9TiG8iONE= +20251013051438.sql h1:X6t8bkqpUYYokBunSufMQUe5vCg0VyO6dxbm7ngosUc= +20251013081808.sql h1:495pLguXL2Ozh+ycn4UYZgZbn6WbjXNbyZUc3JU8qhI= +20251014060047.sql h1:nCgImMRGHhziiW57O1ofWaXCAPGaCOHN7PldQ3OSmM4= +20251014063537.sql h1:2cLmID79jP6cuQ1YJaWTtghFiM1GtHMC0ZQl30Hpy1M= +20251014063720.sql h1:bzLKKVAjSHgDFoiI/glj7t1ETlSAKx+AlsIAaP0ru2g= +20251015045455.sql h1:S547+UugQhlTRcn1Lm1IfqT5RNPttIWIiD+RTx69YaE= +20251016010845.sql h1:c9DUvxl17pUkf0azdYGM/YDzYxIJkLcfZOcMI4rL+R0= +20251016011023.sql h1:u3ivg83bXgYHBbojbWpemLxPE9Dmmj53B6LXo664jxw= +20251016062912.sql h1:W9n1hWchfYkqNX9LO9uxFxEXAb/iY+Pexjnhmp6PbgI= +20251017060617.sql h1:VU6yZ2+LfHpDZ3+TIH40t3F5YXPCpTppuF9+uSqa4b8= +20251017082207.sql h1:QshZslfedckz7iDpSGmPyY9sP6dy6ckHbs8L1TuXIA4= +20251018032635.sql h1:M1U/9W/F9wlW5YDmVAmHFfUJU7FWFaX0DblpfZcYWrE= +20251018040322.sql h1:Zk/vw0e6AzWFO2ElLOzB+OrSz6k+h1Ynxp0TImAzxwY= +20251019093915.sql h1:3Q0kPiZwJnHn5rAvdh0w1LBdiA7W2xBmZWncoPXb044= +20251020062553.sql h1:mJwC/J8GzPAIXckNMvy1f/Nguk2VVf8roD/Raclhbao= +20251021041042.sql h1:d1BAOGAQhqr+oOwcpAVozUsTh457VSDEk2qQFavGG58= +20251021075552.sql h1:TNChGQ1Zlr/1iQ6qvK4iDTAJpe6L/z/M6e/O0SkQVaM= +20251023044432.sql h1:GA2AdJk2ULyjr6igtu9C/CEi4YUIks8r9jXGGaCvPsk= +20251024034832.sql h1:RXmbEhMkOLK5g1QL6up8iRPcwYfo89oLP26ZHvrUK9o= +20251024074315.sql h1:3GnPQSbuAAfMa8oWDyBjhXqn1j1zunY/w0ydX0IGPrA= +20251025013451.sql h1:5eNrA9LDxA4i5CCP7wSyOgFZ6t6jBWVil+oGzJpkJ2E= +20251025013609.sql h1:+N6EHc1kv3hqf16CUhXe+UITPmoxOPfi4MECLmJXNrc= +20251027075128.sql h1:PQflgsjce/p2ClbybLtdehdPNDcMZ9Lb1vd98xd0K8E= +20251027091406.sql h1:bYXV57GvodCMjg0/ox+XKGIAGhrDlVuJ1wO4foNEKtQ= +20251102002037.sql h1:ZcwULsJU2lI9t5pX7ukmfAHSx4ZxdxLUX6jzLDc2SrU= +20251102091932.sql h1:A6y9j4wAqm4/HfMDxhpy/ChDn3UNRVN99KGgSCX+e18= +20251103081637.sql h1:RFqJNhJItSwJQaMP5IcQ14mL7eQ3EJjGZua9zLWzwMU= +20251104042334.sql h1:BbjLAwImggvI6489FQgD+S/AaafeiZut8k19TdH7XUE= +20251104043530.sql h1:Y0sOQqgnHxd5vKPA4+4fAGGdWCv6duKAYgHnjRJZUIc= +20251104080952.sql h1:hDHzFs/k+NhPYJ64ifbVp+nTJLMCG5MIMJU1zBMP0V0= +20251104084135.sql h1:p97mW1MPtPrMWJKy/KZqvymMO/vlelnXp43N9bZVCTI= From cd775e33664151e7ac11d8c652511a20fa56567e Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Wed, 5 Nov 2025 11:03:47 +0700 Subject: [PATCH 063/329] feat/trx-order: added entities for antibiotic --- .../main-entities/antibiotic-in-use/dto.go | 76 +++++++++++++++++++ .../main-entities/antibiotic-in-use/entity.go | 15 ++++ .../antibiotic-src-category/dto.go | 66 ++++++++++++++++ .../antibiotic-src-category/entity.go | 11 +++ .../main-entities/antibiotic-src/dto.go | 76 +++++++++++++++++++ .../main-entities/antibiotic-src/entity.go | 17 +++++ internal/interface/migration/main-entities.go | 4 + 7 files changed, 265 insertions(+) create mode 100644 internal/domain/main-entities/antibiotic-in-use/dto.go create mode 100644 internal/domain/main-entities/antibiotic-in-use/entity.go create mode 100644 internal/domain/main-entities/antibiotic-src-category/dto.go create mode 100644 internal/domain/main-entities/antibiotic-src-category/entity.go create mode 100644 internal/domain/main-entities/antibiotic-src/dto.go create mode 100644 internal/domain/main-entities/antibiotic-src/entity.go diff --git a/internal/domain/main-entities/antibiotic-in-use/dto.go b/internal/domain/main-entities/antibiotic-in-use/dto.go new file mode 100644 index 00000000..7fbce2dd --- /dev/null +++ b/internal/domain/main-entities/antibiotic-in-use/dto.go @@ -0,0 +1,76 @@ +package antibioticinuse + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + eas "simrs-vx/internal/domain/main-entities/antibiotic-src" + emo "simrs-vx/internal/domain/main-entities/mcu-order" + erc "simrs-vx/internal/domain/references/common" + "time" +) + +type CreateDto struct { + McuOrder_Id *uint `json:"mcuOrder_id"` + AntibioticSrc_Id *uint `json:"antibioticSrc_id"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + McuOrder_Id *uint `json:"mcu-order-id"` + AntibioticSrc_Id *uint `json:"mcu-src-id"` + Result *string `json:"result"` + Status_Code erc.DataStatusCode `json:"status-code"` +} +type ReadDetailDto struct { + Id uint `json:"id"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` +} + +type SetScheduleDto struct { + Id uint `json:"id"` + ExaminationDate *time.Time `json:"examinationDate"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + McuOrder_Id *uint `json:"mcuOrder_id"` + McuOrder *emo.McuOrder `json:"mcuOrder,omitempty"` + AntibioticSrc_Id *uint `json:"antibioticSrc_id"` + Antibiotic *eas.CreateDto `json:"mcuSrc,omitempty"` +} + +func (d AntibioticInUse) ToResponse() ResponseDto { + resp := ResponseDto{ + McuOrder_Id: d.McuOrder_Id, + McuOrder: d.McuOrder, + AntibioticSrc_Id: d.AntibioticSrc_Id, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []AntibioticInUse) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/antibiotic-in-use/entity.go b/internal/domain/main-entities/antibiotic-in-use/entity.go new file mode 100644 index 00000000..6d924d4f --- /dev/null +++ b/internal/domain/main-entities/antibiotic-in-use/entity.go @@ -0,0 +1,15 @@ +package antibioticinuse + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + eas "simrs-vx/internal/domain/main-entities/antibiotic-src" + emo "simrs-vx/internal/domain/main-entities/mcu-order" +) + +type AntibioticInUse struct { + ecore.Main // adjust this according to the needs + McuOrder_Id *uint `json:"mcuOrder_id" gorm:"uniqueIndex:idx_order_src"` + McuOrder *emo.McuOrder `json:"mcuOrder,omitempty" gorm:"foreignKey:McuOrder_Id;references:Id"` + AntibioticSrc_Id *uint `json:"antibioticSrcSrc_id" gorm:"uniqueIndex:idx_order_src"` + AntibioticSrc *eas.AntibioticSrc `json:"antibioticSrc,omitempty" gorm:"foreignKey:AntibioticSrc_Id;references:Id"` +} diff --git a/internal/domain/main-entities/antibiotic-src-category/dto.go b/internal/domain/main-entities/antibiotic-src-category/dto.go new file mode 100644 index 00000000..90f420fb --- /dev/null +++ b/internal/domain/main-entities/antibiotic-src-category/dto.go @@ -0,0 +1,66 @@ +package antibioticsrccategory + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type CreateDto struct { + Code string `json:"code" validate:"maxLength=20"` + Name string `json:"name" validate:"maxLength=50"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Sort string `json:"sort"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Code string `json:"code"` + Name string `json:"name"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` + Code *string `json:"code"` +} + +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.SmallMain + Code string `json:"code"` + Name string `json:"name"` +} + +func (d AntibioticSrcCategory) ToResponse() ResponseDto { + resp := ResponseDto{ + Code: d.Code, + Name: d.Name, + } + resp.SmallMain = d.SmallMain + return resp +} + +func ToResponseList(data []AntibioticSrcCategory) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/antibiotic-src-category/entity.go b/internal/domain/main-entities/antibiotic-src-category/entity.go new file mode 100644 index 00000000..31169d9d --- /dev/null +++ b/internal/domain/main-entities/antibiotic-src-category/entity.go @@ -0,0 +1,11 @@ +package antibioticsrccategory + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type AntibioticSrcCategory struct { + ecore.SmallMain // adjust this according to the needs + Code string `json:"code" gorm:"unique;size:20"` + Name string `json:"name" gorm:"size:50"` +} diff --git a/internal/domain/main-entities/antibiotic-src/dto.go b/internal/domain/main-entities/antibiotic-src/dto.go new file mode 100644 index 00000000..9a7a2846 --- /dev/null +++ b/internal/domain/main-entities/antibiotic-src/dto.go @@ -0,0 +1,76 @@ +package antibioticsrc + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ei "simrs-vx/internal/domain/main-entities/item" +) + +type CreateDto struct { + Code string `json:"code" validate:"maxLength=20"` + Name string `json:"name" validate:"maxLength=50"` + AntibioticSrcCategory_Code *string `json:"antibioticSrcCategory_code" validate:"maxLength=20"` + Item_Id *uint `json:"item_id"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Sort string `json:"sort"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Code string `json:"code"` + Name string `json:"name"` + AntibioticSrcCategory_Code *string `json:"antibiotic-src-category-code"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` + Code *string `json:"code"` +} + +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 + Code string `json:"code"` + Name string `json:"name"` + AntibioticSrcCategory_Code *string `json:"antibioticSrcCategory_code"` + Item_Id *uint `json:"item_id"` + Item *ei.Item `json:"item,omitempty"` +} + +func (d AntibioticSrc) ToResponse() ResponseDto { + resp := ResponseDto{ + Code: d.Code, + Name: d.Name, + AntibioticSrcCategory_Code: d.AntibioticSrcCategory_Code, + Item_Id: d.Item_Id, + Item: d.Item, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []AntibioticSrc) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/antibiotic-src/entity.go b/internal/domain/main-entities/antibiotic-src/entity.go new file mode 100644 index 00000000..83089e07 --- /dev/null +++ b/internal/domain/main-entities/antibiotic-src/entity.go @@ -0,0 +1,17 @@ +package antibioticsrc + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + easc "simrs-vx/internal/domain/main-entities/antibiotic-src-category" + ei "simrs-vx/internal/domain/main-entities/item" +) + +type AntibioticSrc struct { + ecore.Main // adjust this according to the needs + Code string `json:"code" gorm:"unique;size:20"` + Name string `json:"name" gorm:"size:50"` + AntibioticSrcCategory_Code *string `json:"antibioticSrcCategory_code" gorm:"size:20"` + AntibioticSrcCategory *easc.AntibioticSrcCategory `json:"antibioticSrcCategory,omitempty" gorm:"foreignKey:AntibioticSrcCategory_Code;references:Code"` + Item_Id *uint `json:"item_id"` + Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` +} diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index 6507202e..0248a0d1 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -5,6 +5,8 @@ import ( admemployeehist "simrs-vx/internal/domain/main-entities/adm-employee-hist" ambulancetransportreq "simrs-vx/internal/domain/main-entities/ambulance-transport-req" ambulatory "simrs-vx/internal/domain/main-entities/ambulatory" + antibioticinuse "simrs-vx/internal/domain/main-entities/antibiotic-in-use" + antibioticsrccategory "simrs-vx/internal/domain/main-entities/antibiotic-src-category" appointment "simrs-vx/internal/domain/main-entities/appointment" chemo "simrs-vx/internal/domain/main-entities/chemo" consultation "simrs-vx/internal/domain/main-entities/consultation" @@ -172,6 +174,8 @@ func getMainEntities() []any { &mcuorderitem.McuOrderItem{}, &mcusubsrc.McuSubSrc{}, &mcuordersubitem.McuOrderSubItem{}, + &antibioticsrccategory.AntibioticSrcCategory{}, + &antibioticinuse.AntibioticInUse{}, &consultation.Consultation{}, &chemo.Chemo{}, &midwife.Midwife{}, From c5643420f117e91b4dab1e8b2ebfb7fe86482ab1 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Wed, 5 Nov 2025 11:50:07 +0700 Subject: [PATCH 064/329] feat/tex-orders: updated migration --- .../migrations/20251105044629.sql | 38 +++++ cmd/main-migration/migrations/atlas.sum | 143 +++++++++--------- 2 files changed, 110 insertions(+), 71 deletions(-) create mode 100644 cmd/main-migration/migrations/20251105044629.sql diff --git a/cmd/main-migration/migrations/20251105044629.sql b/cmd/main-migration/migrations/20251105044629.sql new file mode 100644 index 00000000..24ba9d05 --- /dev/null +++ b/cmd/main-migration/migrations/20251105044629.sql @@ -0,0 +1,38 @@ +-- Create "AntibioticSrcCategory" table +CREATE TABLE "public"."AntibioticSrcCategory" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(20) NULL, + "Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_AntibioticSrcCategory_Code" UNIQUE ("Code") +); +-- Create "AntibioticSrc" table +CREATE TABLE "public"."AntibioticSrc" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(20) NULL, + "Name" character varying(50) NULL, + "AntibioticSrcCategory_Code" character varying(20) NULL, + "Item_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_AntibioticSrc_Code" UNIQUE ("Code"), + CONSTRAINT "fk_AntibioticSrc_AntibioticSrcCategory" FOREIGN KEY ("AntibioticSrcCategory_Code") REFERENCES "public"."AntibioticSrcCategory" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_AntibioticSrc_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "AntibioticInUse" table +CREATE TABLE "public"."AntibioticInUse" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "McuOrder_Id" bigint NULL, + "AntibioticSrc_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_AntibioticInUse_AntibioticSrc" FOREIGN KEY ("AntibioticSrc_Id") REFERENCES "public"."AntibioticSrc" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_AntibioticInUse_McuOrder" FOREIGN KEY ("McuOrder_Id") REFERENCES "public"."McuOrder" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index d2c79b63..b51ad522 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,71 +1,72 @@ -h1:XcM4BDP+DX+wOQ5ldDbxOZWeqFBrXyFHkmVIlIdlfBs= -20250904105930.sql h1:Vv4vCurl7m7/ZB6TjRpkubHpQ4RYwSUn0QHdzfoGpzY= -20250904141448.sql h1:FYCHH9Os4KkrZMDu/jR8FMP+wLMRW+Mb0PkLU/9BRDg= -20250908062237.sql h1:oanBpKZd+akPu2I/xYhUSbd0G5tAFbXzKLER/Zs8ENI= -20250908062323.sql h1:miNG9COddXkD1jGTgaROMAZ618eT6oiLGiJhXWnQwhE= -20250908073811.sql h1:gOi5cnGG1htlpfizybYmUIT0vYjZTBfXiI0nPSYK2u8= -20250908073839.sql h1:cWNDA4YikjoOteAJuNLFILjQUJPFB6o8Wxreiek4QyI= -20250910055902.sql h1:nxxOGnU0BbH/v3IPgeIOXOwH8d3tKomw7h6FTeMnnBs= -20250915123412.sql h1:mz7SiWfrdf0qE1VTSAAnA/147d6gyp6ry5vZ2bR9SH0= -20250916043819.sql h1:RHXVtmMkB6wfv06HfPyHMBmUfIpFt1xveafNz0kwKnE= -20250917040616.sql h1:MYVDht+akBlzQGKNu2hTTTLPEcH1bxT/Q8MK6WEtuhs= -20250917040751.sql h1:J79YyS2JzWgh5oKXMTgh67uo3gLxKaAsxRiZmSIfjBs= -20250917045138.sql h1:/SM1N4O8X3yxpoJgMEARmS1uOkuLKsTOy4PLsRCOKaQ= -20250917093645.sql h1:PNBTGZ7s10e5b5+Tie8YfVQBN0zKtJ5T34oK1iOUEb4= -20250918073552.sql h1:jG7+g3i8ODYaJdcdZz12v3nbsZ5mB9wG6kWnGyTQIRI= -20250918073742.sql h1:j+rgw7puxE7s+phqPVZHmPk0af3rcaA56Itp86y1suY= -20250918074745.sql h1:rPmP4DXs6OnY4Vp+xO/z9jFpJt/RrJ52SJJjIIxeDvc= -20250923025134.sql h1:2r6pcwnBSU5Y9Czk1OHBoh4yZXiMtEca9X8843fTEX0= -20250924051317.sql h1:iUAk2gsGoEGIPQ0lEEUp8maMSId8emNbP+kP712ABIA= -20250929034321.sql h1:UlpALNVmdi95zOIT0yc6ZyTj9bBjQEIpZhvgrc52M+k= -20250929034428.sql h1:feF+H4nDyHh5bdx48Oiz0A1qecZfi6v3qTTdjzJ45Dg= -20250930025550.sql h1:6XT1kXI3Z3ZIxxmvT7poufZWWCW0QiejZPaFV5wBnjI= -20250930140351.sql h1:HxnmAbh9gCy8jwl/9ycGktiByaUripsjFFvohofY2CY= -20251002085604.sql h1:SjLPi+ZN6qDccK3DaEQCgNsZpPwr5kynWXwbwEsziCI= -20251003032030.sql h1:oHfxNSuqTxU8Zaf9H+h8TuUb1Da03wcyc6hZjDrUQ2s= -20251005060450.sql h1:GIuCcrd4MwjmXpvbzDzPYL18BV3QaZZ+Y2FmEzjvi0E= -20251006041122.sql h1:uNDQbSw0M08lYoMvUNlQtS3iDzpPM1ixT13ugSAoWjE= -20251006045658.sql h1:z+t7yCK54Q4SSiF9kUyUhkYB2F+kzSW9TB7ogxd9wzw= -20251006045928.sql h1:1lATLFLp4BWwGZqAjZdP0Dc6ypNXiYcwjoNkqGa8NFE= -20251007022859.sql h1:HXXwWrkyvzJzJGAt9mGskCRBBV/c1JfPmfjDocmJhQ4= -20251008031337.sql h1:Ln5pCF3Hxa5foHZLcds+z/us2eH6VAhhEj3w0TAGlVs= -20251008031554.sql h1:aB4MUS2lmqG0//4HKUWorcPSpWya0VC4QItvGyskEVI= -20251008052346.sql h1:MI3AZgU5XcwZT2OvvlWAxdRtL0eJ3jjRwt56IY1+pRU= -20251008073620.sql h1:sztWXuSNYwpEraaSapSsYwno75LO5H/N7ob7OJQ8X/A= -20251009042854.sql h1:TnPXj+dCJls3IU//cuqJZymyBzZMKs7ayazfgtAFRxM= -20251009052657.sql h1:leXbs0CP8r5dRilmYyLRk1MICqak3ea1/LWMtFrijqQ= -20251010031743.sql h1:SgHNY/lQ88G2F4nZyMfiOkDntb+gtOR+nEQLqXBTwv4= -20251010070721.sql h1:AnJnhXsMzDvK4AFgYw6B16Kpo/hljrZtcpc9m2VOSHQ= -20251010072711.sql h1:aXPTtNwLcTuw8C/yAxwxvqs0ayEjNzI1uuE0vE3ERa8= -20251013044536.sql h1:7Pq6JcvTpPBYDCW2dz3HdgUwY65HlhEVWy9TiG8iONE= -20251013051438.sql h1:X6t8bkqpUYYokBunSufMQUe5vCg0VyO6dxbm7ngosUc= -20251013081808.sql h1:495pLguXL2Ozh+ycn4UYZgZbn6WbjXNbyZUc3JU8qhI= -20251014060047.sql h1:nCgImMRGHhziiW57O1ofWaXCAPGaCOHN7PldQ3OSmM4= -20251014063537.sql h1:2cLmID79jP6cuQ1YJaWTtghFiM1GtHMC0ZQl30Hpy1M= -20251014063720.sql h1:bzLKKVAjSHgDFoiI/glj7t1ETlSAKx+AlsIAaP0ru2g= -20251015045455.sql h1:S547+UugQhlTRcn1Lm1IfqT5RNPttIWIiD+RTx69YaE= -20251016010845.sql h1:c9DUvxl17pUkf0azdYGM/YDzYxIJkLcfZOcMI4rL+R0= -20251016011023.sql h1:u3ivg83bXgYHBbojbWpemLxPE9Dmmj53B6LXo664jxw= -20251016062912.sql h1:W9n1hWchfYkqNX9LO9uxFxEXAb/iY+Pexjnhmp6PbgI= -20251017060617.sql h1:VU6yZ2+LfHpDZ3+TIH40t3F5YXPCpTppuF9+uSqa4b8= -20251017082207.sql h1:QshZslfedckz7iDpSGmPyY9sP6dy6ckHbs8L1TuXIA4= -20251018032635.sql h1:M1U/9W/F9wlW5YDmVAmHFfUJU7FWFaX0DblpfZcYWrE= -20251018040322.sql h1:Zk/vw0e6AzWFO2ElLOzB+OrSz6k+h1Ynxp0TImAzxwY= -20251019093915.sql h1:3Q0kPiZwJnHn5rAvdh0w1LBdiA7W2xBmZWncoPXb044= -20251020062553.sql h1:mJwC/J8GzPAIXckNMvy1f/Nguk2VVf8roD/Raclhbao= -20251021041042.sql h1:d1BAOGAQhqr+oOwcpAVozUsTh457VSDEk2qQFavGG58= -20251021075552.sql h1:TNChGQ1Zlr/1iQ6qvK4iDTAJpe6L/z/M6e/O0SkQVaM= -20251023044432.sql h1:GA2AdJk2ULyjr6igtu9C/CEi4YUIks8r9jXGGaCvPsk= -20251024034832.sql h1:RXmbEhMkOLK5g1QL6up8iRPcwYfo89oLP26ZHvrUK9o= -20251024074315.sql h1:3GnPQSbuAAfMa8oWDyBjhXqn1j1zunY/w0ydX0IGPrA= -20251025013451.sql h1:5eNrA9LDxA4i5CCP7wSyOgFZ6t6jBWVil+oGzJpkJ2E= -20251025013609.sql h1:+N6EHc1kv3hqf16CUhXe+UITPmoxOPfi4MECLmJXNrc= -20251027075128.sql h1:PQflgsjce/p2ClbybLtdehdPNDcMZ9Lb1vd98xd0K8E= -20251027091406.sql h1:bYXV57GvodCMjg0/ox+XKGIAGhrDlVuJ1wO4foNEKtQ= -20251102002037.sql h1:ZcwULsJU2lI9t5pX7ukmfAHSx4ZxdxLUX6jzLDc2SrU= -20251102091932.sql h1:A6y9j4wAqm4/HfMDxhpy/ChDn3UNRVN99KGgSCX+e18= -20251103081637.sql h1:RFqJNhJItSwJQaMP5IcQ14mL7eQ3EJjGZua9zLWzwMU= -20251104042334.sql h1:BbjLAwImggvI6489FQgD+S/AaafeiZut8k19TdH7XUE= -20251104043530.sql h1:Y0sOQqgnHxd5vKPA4+4fAGGdWCv6duKAYgHnjRJZUIc= -20251104080952.sql h1:hDHzFs/k+NhPYJ64ifbVp+nTJLMCG5MIMJU1zBMP0V0= -20251104084135.sql h1:p97mW1MPtPrMWJKy/KZqvymMO/vlelnXp43N9bZVCTI= +h1:6MaKjqJ77v0HFibPPeCdp8Bwg2qOZlEKNgHWc2zq6T0= +20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= +20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= +20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= +20250908062323.sql h1:oXl6Z143tOpIl4EfP4B8JNU8LrMvVmHEtCgAfiB4gs8= +20250908073811.sql h1:m2aNXfnGxnLq1+rVWrh4f60q7fhyhV3gEwNu/OIqQlE= +20250908073839.sql h1:cPk54xjLdMs26uY8ZHjNWLuyfAMzV7Zb0/9oJQrsw04= +20250910055902.sql h1:5xwjAV6QbtZT9empTJKfhyAjdknbHzb15B0Ku5dzqtQ= +20250915123412.sql h1:D83xaU2YlDEd21HLup/YQpQ2easMToYCyy/oK6AFgQs= +20250916043819.sql h1:ekoTJsBqQZ8G8n0qJ03d13+eoNoc7sAUEQGA5D/CCxk= +20250917040616.sql h1:zoCnmcXuM7AVv85SmN7RmFglCgJnoDmpRWExH0LAc9Q= +20250917040751.sql h1:J1xyRrh32y1+lezwAyNwPcUQ6ABBSgbvzNLva4SVdQU= +20250917045138.sql h1:jKe1Z0uOLG4SGBYM+S/3P+/zMPztmgoderD5swnMuCg= +20250917093645.sql h1:cNI3Pbz1R3LxvIXLuexafJFCXUXrmuFCgXXJ2sG+FW0= +20250918073552.sql h1:RJ1SvMzP6aeWnoPVD3eVAmIQOkcp6Php8z3QRri6v4g= +20250918073742.sql h1:+cEsnJTJFybe2fR69ZoOiX2R6c6iITl4m6WTZ1hjyzY= +20250918074745.sql h1:2hNVQCXF/dVYXAh+T/7oBFgERGWxzVb2FXJjwkFWGCI= +20250923025134.sql h1:Ykz/qpHiGDXPsCsWTjydQFVSibZP2D+h2fIeb2h2JGA= +20250924051317.sql h1:yQuW6SwJxIOM5fcxeAaie5lSm1oLysU/C2hH2xNCVoQ= +20250929034321.sql h1:101FJ8VH12mrZWlt/X1gvKUGOhoiF8tFbjiapAjnHzg= +20250929034428.sql h1:i+pROD9p+g5dOmmZma6WF/0Hw5g3Ha28NN85iTo1K34= +20250930025550.sql h1:+F+CsCUXD/ql0tHGEow70GhPBX1ZybVn+bh/T4YMh7Y= +20250930140351.sql h1:9AAEG1AnOAH+o0+oHL5G7I8vqlWOhwRlCGyyCpT/y1Q= +20251002085604.sql h1:3xZ68eYp4urXRnvotNH1XvG2mYOSDV/j3zHEZ/txg5E= +20251003032030.sql h1:HB+mQ2lXMNomHDpaRhB/9IwYI9/YiDO5eOJ+nAQH/jw= +20251005060450.sql h1:LbtCE2b+8osM3CvnmQJH1uCPtn+d7WchsslBOz8bL3Q= +20251006041122.sql h1:MlS7f21z06sutnf9dIekt5fuHJr4lgcQ4uCuCXAGsfc= +20251006045658.sql h1:3FmGCPCzjgMPdWDRodZTsx3KVaodd9zB9ilib69aewk= +20251006045928.sql h1:Z5g31PmnzNwk/OKdODcxZGm8fjJQdMFK32Xfnt3bRHg= +20251007022859.sql h1:FO03zEfaNEk/aXwY81d5Lp3MoBB9kPQuXlXJ4BPiSR8= +20251008031337.sql h1:l+sxUAGvcTfj3I6kAFHo+T6AYodC9k9GkR+jaKO2xXc= +20251008031554.sql h1:AqrVfIhSzY3PCy8ZlP5W91wn2iznfIuj5qQfubp6/94= +20251008052346.sql h1:nxnXmooIJ6r1mmzwnw+6efxLfc/k9h2aE6RMptPRons= +20251008073620.sql h1:6YsJp1W4SmQJ1lxpqF27BBlDC1zqhw7Yhc7pLzQTY6M= +20251009042854.sql h1:nkBV+R6j0fg7/JY6wH3eb5Vv0asJLnXmb6lINfT/GLQ= +20251009052657.sql h1:EPvdsib5rzCGPryd10HShGKvFPwM/R5S2lIVwtYxpms= +20251010031743.sql h1:T8IZmx8/btRFKLzTe78MzcBsPJNodnLvB0tby9QkirQ= +20251010070721.sql h1:5NQUk/yOV6sABLCB7swx++YIOyJe6MnU+yt1nRzde5w= +20251010072711.sql h1:ZJNqR2piyu8xJhBvVABSlnGEoKSKae3wuEs+wshPe4k= +20251013044536.sql h1:0Xjw8fNILiT8nnfrJDZgQnPf3dntmIoilbapnih8AE4= +20251013051438.sql h1:lfSuw5mgJnePBJamvhZ81osFIouXeiIEiSZ/evdwo48= +20251013081808.sql h1:ijgjNX08G6GBjA/ks8EKtb7P7Y7Cg7zbhqEOruGnv6M= +20251014060047.sql h1:0jqj49WTtneEIMQDBoo4c095ZGi8sCrA8NnHBrPU6D8= +20251014063537.sql h1:VZLXol0PTsTW21Epg6vBPsztWkDtcxup9F/z88EGgIg= +20251014063720.sql h1:2HVUyCV0ud3BJJDH2GEKZN/+IWLFPCsN1KqhP6csO14= +20251015045455.sql h1:MeLWmMhAOAz8b15Dd7IAQnt6JxjSml02XCXK22C0Lpg= +20251016010845.sql h1:4BncQdDOasRZJkzVJrSJJA7091A9VPNVx/faUCUPhBM= +20251016011023.sql h1:9JB9eFZKURK5RoCVDKR6glSvdJ8NTXrN7K/4q51zkz4= +20251016062912.sql h1:ACNn0fe+EMqUt3hoY+Dr3uqAV/QICBa1+mIW7fUc9Fk= +20251017060617.sql h1:4T3t9ifWrEQTPMSM0XJ98pF7Qdt+UfgtMui17bhrnWI= +20251017082207.sql h1:8vLG1l/saRRMHXkyA4nelJyjaSddhZd6r7R+Uo4JS/c= +20251018032635.sql h1:2xey5gnO3y2XSOrU8MLlIfoylPKbRGDRtHDD07B3MbQ= +20251018040322.sql h1:k/pdNiSoT8zFPqNQ/avOD0vYkNh3BTD64IlHrfVXr7I= +20251019093915.sql h1:hFcQE0y+p5dZiVwePGsRGto9m/q6kJNiUZbVDd5Rnjk= +20251020062553.sql h1:Iw7hulcm5iRQlfW+ygA4iTPxLqkxx6h9vXMXEwUAHKs= +20251021041042.sql h1:wMgSivBV2A0NDcsLmKGIp0kMcVh2IODSG9b4dgzCaOM= +20251021075552.sql h1:8gfSMAglflNO6L0sSzxFNEubYN8/O4thT7OQT+WH+3M= +20251023044432.sql h1:MkvajJs3bfk9+wHvQ43/ccAluJEBARm1gWr1u92ccLA= +20251024034832.sql h1:x3s3VEVYLOSKLAFxJGb2+c1FyTMMvPE+9k4Ew7rKQaI= +20251024074315.sql h1:EjAjelgi5qAfcRq/8vPTlGGYHvAKxNTllm8f0SzZDns= +20251025013451.sql h1:6hnuIiwYiG+6nLhOY/+Yyn+I6ZCFNRZxrJNqBV6HLqE= +20251025013609.sql h1:evPJaTD8WxYRMOJZHkSr7ONLx9PYxT+ankzQt9c/sJ0= +20251027075128.sql h1:/iFQBM1sytjqpyQSOx61q33gnorMgxTiFVSuL6bQqsM= +20251027091406.sql h1:eCZGtUkxAzEAqpC9UsGpP8Df9mS0DEOqSl885LgqpvM= +20251102002037.sql h1:lFJbuoZ2LMQnUNGdcwHVY3Xlfslgzu9t2WByT8yfOZI= +20251102091932.sql h1:rmdhb5m+P+fU8jROBZNyeYgZKuQvucsuljXv4ZVzvks= +20251103081637.sql h1:tf3BcwTeIw+oxMEisKDDfyKnBfalTLs8b0PJA8JWYxY= +20251104042334.sql h1:7PDMWOhmJywolAPKFZ14XaDBeMvcxShaXFN2IemNtzk= +20251104043530.sql h1:qvYVp3ysPf27f1BcoRNCFGovxuVE12lg9d6Xzda6zWU= +20251104080952.sql h1:avghpv1n3yaCDR/TA0X+hgxDGoLBQGu/GJUwj4VT/Ic= +20251104084135.sql h1:rg+eRE5/5sYWR7z+Xyn0zKw8rr8P/oWxF0xhcNVnNec= +20251105044629.sql h1:aS4nm+7hPU3krzm5qouyEf1+d+aAPtlkQ2zgxgV9rXs= From 34af55c1521fe1d6d5380cc0ba2699b2f92ad082 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Wed, 5 Nov 2025 13:10:06 +0700 Subject: [PATCH 065/329] feat (control-letter): remove includes value on read detail --- internal/use-case/main-use-case/control-letter/case.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/use-case/main-use-case/control-letter/case.go b/internal/use-case/main-use-case/control-letter/case.go index 7ff38a63..6f28c43e 100644 --- a/internal/use-case/main-use-case/control-letter/case.go +++ b/internal/use-case/main-use-case/control-letter/case.go @@ -150,8 +150,6 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { return err } - input.Includes = "encounter,unit,specialist,subspecialist" - if data, err = ReadDetailData(input, &event, tx); err != nil { return err } From c94a9e47fb2e952b69b7ff4988498cf80d9b4c5a Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Wed, 5 Nov 2025 13:14:24 +0700 Subject: [PATCH 066/329] feat (control-letter): add query param --- internal/interface/main-handler/control-letter/handler.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/interface/main-handler/control-letter/handler.go b/internal/interface/main-handler/control-letter/handler.go index d6a73fe0..b0714b25 100644 --- a/internal/interface/main-handler/control-letter/handler.go +++ b/internal/interface/main-handler/control-letter/handler.go @@ -38,6 +38,7 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { return } dto := e.ReadDetailDto{} + sf.UrlQueryParam(&dto, *r.URL) dto.Id = uint16(id) res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) From d1d63b7bb397da34842f4370dd8053b944c7a3ca Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Wed, 5 Nov 2025 19:17:45 +0700 Subject: [PATCH 067/329] feat/trx-orders: removed Item from AntibioticSrc --- cmd/main-migration/migrations/20251105121808.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 5 +++-- internal/domain/main-entities/antibiotic-src/dto.go | 4 ++-- internal/domain/main-entities/antibiotic-src/entity.go | 5 ++--- 4 files changed, 9 insertions(+), 7 deletions(-) create mode 100644 cmd/main-migration/migrations/20251105121808.sql diff --git a/cmd/main-migration/migrations/20251105121808.sql b/cmd/main-migration/migrations/20251105121808.sql new file mode 100644 index 00000000..41c1edf0 --- /dev/null +++ b/cmd/main-migration/migrations/20251105121808.sql @@ -0,0 +1,2 @@ +-- Modify "AntibioticSrc" table +ALTER TABLE "public"."AntibioticSrc" DROP COLUMN "Item_Id"; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index b51ad522..88a3f39c 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:6MaKjqJ77v0HFibPPeCdp8Bwg2qOZlEKNgHWc2zq6T0= +h1:c6psxONIBPkfVLCpAnWAm81SgT25UQT6hgO8KAG6O5M= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -69,4 +69,5 @@ h1:6MaKjqJ77v0HFibPPeCdp8Bwg2qOZlEKNgHWc2zq6T0= 20251104043530.sql h1:qvYVp3ysPf27f1BcoRNCFGovxuVE12lg9d6Xzda6zWU= 20251104080952.sql h1:avghpv1n3yaCDR/TA0X+hgxDGoLBQGu/GJUwj4VT/Ic= 20251104084135.sql h1:rg+eRE5/5sYWR7z+Xyn0zKw8rr8P/oWxF0xhcNVnNec= -20251105044629.sql h1:aS4nm+7hPU3krzm5qouyEf1+d+aAPtlkQ2zgxgV9rXs= +20251105044629.sql h1:4NU27HeKUNFsV82LacnwmnCSAH0pSbZR9J9/ZESRs6M= +20251105121808.sql h1:uPFEHJ6pZbuo8+3giskNg4I91MrNRgrR1dMIe7kL+4g= diff --git a/internal/domain/main-entities/antibiotic-src/dto.go b/internal/domain/main-entities/antibiotic-src/dto.go index 9a7a2846..dd453ae3 100644 --- a/internal/domain/main-entities/antibiotic-src/dto.go +++ b/internal/domain/main-entities/antibiotic-src/dto.go @@ -60,8 +60,8 @@ func (d AntibioticSrc) ToResponse() ResponseDto { Code: d.Code, Name: d.Name, AntibioticSrcCategory_Code: d.AntibioticSrcCategory_Code, - Item_Id: d.Item_Id, - Item: d.Item, + // Item_Id: d.Item_Id, + // Item: d.Item, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/antibiotic-src/entity.go b/internal/domain/main-entities/antibiotic-src/entity.go index 83089e07..6cb8cc85 100644 --- a/internal/domain/main-entities/antibiotic-src/entity.go +++ b/internal/domain/main-entities/antibiotic-src/entity.go @@ -3,7 +3,6 @@ package antibioticsrc import ( ecore "simrs-vx/internal/domain/base-entities/core" easc "simrs-vx/internal/domain/main-entities/antibiotic-src-category" - ei "simrs-vx/internal/domain/main-entities/item" ) type AntibioticSrc struct { @@ -12,6 +11,6 @@ type AntibioticSrc struct { Name string `json:"name" gorm:"size:50"` AntibioticSrcCategory_Code *string `json:"antibioticSrcCategory_code" gorm:"size:20"` AntibioticSrcCategory *easc.AntibioticSrcCategory `json:"antibioticSrcCategory,omitempty" gorm:"foreignKey:AntibioticSrcCategory_Code;references:Code"` - Item_Id *uint `json:"item_id"` - Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` + // Item_Id *uint `json:"item_id"` + // Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` } From 0e982d8ab4f67d9fe4b9e755e306b2276098e88f Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Wed, 5 Nov 2025 20:54:16 +0700 Subject: [PATCH 068/329] feat/trx-orders: added AntibioticSrcCategory flow --- .../antibiotic-src-category/handler.go | 71 +++++ .../interface/main-handler/main-handler.go | 3 + .../antibiotic-src-category/case.go | 276 ++++++++++++++++++ .../antibiotic-src-category/helper.go | 22 ++ .../antibiotic-src-category/lib.go | 140 +++++++++ .../middleware-runner.go | 103 +++++++ .../antibiotic-src-category/middleware.go | 9 + .../antibiotic-src-category/tycovar.go | 44 +++ 8 files changed, 668 insertions(+) create mode 100644 internal/interface/main-handler/antibiotic-src-category/handler.go create mode 100644 internal/use-case/main-use-case/antibiotic-src-category/case.go create mode 100644 internal/use-case/main-use-case/antibiotic-src-category/helper.go create mode 100644 internal/use-case/main-use-case/antibiotic-src-category/lib.go create mode 100644 internal/use-case/main-use-case/antibiotic-src-category/middleware-runner.go create mode 100644 internal/use-case/main-use-case/antibiotic-src-category/middleware.go create mode 100644 internal/use-case/main-use-case/antibiotic-src-category/tycovar.go diff --git a/internal/interface/main-handler/antibiotic-src-category/handler.go b/internal/interface/main-handler/antibiotic-src-category/handler.go new file mode 100644 index 00000000..7dde9c66 --- /dev/null +++ b/internal/interface/main-handler/antibiotic-src-category/handler.go @@ -0,0 +1,71 @@ +package mcusrccategory + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/mcu-src-category" + u "simrs-vx/internal/use-case/main-use-case/mcu-src-category" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint16(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint16(id) + 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 = uint16(id) + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index bedf3b71..ffbdd9ab 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -64,6 +64,7 @@ import ( zlc "simrs-vx/pkg/zerolog-ctx" /******************** sources ********************/ + antibioticsrccat "simrs-vx/internal/interface/main-handler/antibiotic-src-category" device "simrs-vx/internal/interface/main-handler/device" diagnosesrc "simrs-vx/internal/interface/main-handler/diagnose-src" division "simrs-vx/internal/interface/main-handler/division" @@ -133,11 +134,13 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/counter", counter.O) hc.RegCrud(r, "/v1/medicine-mix", medicicinemix.O) hc.RegCrud(r, "/v1/medicine-mix-item", medicicinemixitem.O) + hc.RegCrud(r, "/v1/antibiotic-src-category", antibioticsrccat.O) hc.RegCrud(r, "/v1/soapi", auth.GuardMW, soapi.O) hc.RegCrud(r, "/v1/adime", auth.GuardMW, adime.O) hc.RegCrud(r, "/v1/sbar", auth.GuardMW, sbar.O) hc.RegCrud(r, "/v1/prescription-item", prescriptionitem.O) hc.RegCrud(r, "/v1/device-order-item", deviceorderitem.O) + hc.RegCrud(r, "/v1/material-order-item", materialorderitem.O) hk.GroupRoutes("/v1/encounter", r, auth.GuardMW, hk.MapHandlerFunc{ diff --git a/internal/use-case/main-use-case/antibiotic-src-category/case.go b/internal/use-case/main-use-case/antibiotic-src-category/case.go new file mode 100644 index 00000000..2eaceb0c --- /dev/null +++ b/internal/use-case/main-use-case/antibiotic-src-category/case.go @@ -0,0 +1,276 @@ +package antibioticsrccategory + +import ( + e "simrs-vx/internal/domain/main-entities/antibiotic-src-category" + "strconv" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "antibiotic-src-category" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.AntibioticSrcCategory{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.AntibioticSrcCategory + var dataList []e.AntibioticSrcCategory + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.AntibioticSrcCategory + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.AntibioticSrcCategory + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.AntibioticSrcCategory + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/antibiotic-src-category/helper.go b/internal/use-case/main-use-case/antibiotic-src-category/helper.go new file mode 100644 index 00000000..7bbe8d80 --- /dev/null +++ b/internal/use-case/main-use-case/antibiotic-src-category/helper.go @@ -0,0 +1,22 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package antibioticsrccategory + +import ( + e "simrs-vx/internal/domain/main-entities/antibiotic-src-category" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.AntibioticSrcCategory) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Code = inputSrc.Code + data.Name = inputSrc.Name +} diff --git a/internal/use-case/main-use-case/antibiotic-src-category/lib.go b/internal/use-case/main-use-case/antibiotic-src-category/lib.go new file mode 100644 index 00000000..31f2eee1 --- /dev/null +++ b/internal/use-case/main-use-case/antibiotic-src-category/lib.go @@ -0,0 +1,140 @@ +package antibioticsrccategory + +import ( + e "simrs-vx/internal/domain/main-entities/antibiotic-src-category" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.AntibioticSrcCategory, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.AntibioticSrcCategory{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.AntibioticSrcCategory, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.AntibioticSrcCategory{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.AntibioticSrcCategory{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.AntibioticSrcCategory, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.AntibioticSrcCategory{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.First(&data, input.Id).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.AntibioticSrcCategory, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.AntibioticSrcCategory, 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 +} diff --git a/internal/use-case/main-use-case/antibiotic-src-category/middleware-runner.go b/internal/use-case/main-use-case/antibiotic-src-category/middleware-runner.go new file mode 100644 index 00000000..6ab4e880 --- /dev/null +++ b/internal/use-case/main-use-case/antibiotic-src-category/middleware-runner.go @@ -0,0 +1,103 @@ +package antibioticsrccategory + +import ( + e "simrs-vx/internal/domain/main-entities/antibiotic-src-category" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.AntibioticSrcCategory) 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.AntibioticSrcCategory) 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.AntibioticSrcCategory) 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.AntibioticSrcCategory) 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.AntibioticSrcCategory) 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/main-use-case/antibiotic-src-category/middleware.go b/internal/use-case/main-use-case/antibiotic-src-category/middleware.go new file mode 100644 index 00000000..55091880 --- /dev/null +++ b/internal/use-case/main-use-case/antibiotic-src-category/middleware.go @@ -0,0 +1,9 @@ +package antibioticsrccategory + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/antibiotic-src-category/tycovar.go b/internal/use-case/main-use-case/antibiotic-src-category/tycovar.go new file mode 100644 index 00000000..0980e65a --- /dev/null +++ b/internal/use-case/main-use-case/antibiotic-src-category/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 antibioticsrccategory + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/antibiotic-src-category" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.AntibioticSrcCategory, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.AntibioticSrcCategory, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.AntibioticSrcCategory, 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 From 42265e95f747fb7756870f82a525e780ee47c997 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 11:04:40 +0700 Subject: [PATCH 069/329] doctor all ids into code --- .../migrations/20251106035305.sql | 4 +++ .../migrations/20251106040137.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 6 ++-- .../domain/main-entities/doctor/entity.go | 30 +++++++++++-------- .../domain/main-entities/employee/entity.go | 18 ++++++----- .../domain/references/encounter/encounter.go | 1 + 6 files changed, 39 insertions(+), 22 deletions(-) create mode 100644 cmd/main-migration/migrations/20251106035305.sql create mode 100644 cmd/main-migration/migrations/20251106040137.sql diff --git a/cmd/main-migration/migrations/20251106035305.sql b/cmd/main-migration/migrations/20251106035305.sql new file mode 100644 index 00000000..d2ab1e94 --- /dev/null +++ b/cmd/main-migration/migrations/20251106035305.sql @@ -0,0 +1,4 @@ +-- Modify "Doctor" table +ALTER TABLE "public"."Doctor" ADD COLUMN "SIP_ExpiredDate" timestamptz NULL, ADD COLUMN "Unit_Code" character varying(10) NULL, ADD COLUMN "Specialist_Code" character varying(10) NULL, ADD COLUMN "Subspecialist_Code" character varying(10) NULL, ADD CONSTRAINT "uni_Doctor_Specialist_Code" UNIQUE ("Specialist_Code"), ADD CONSTRAINT "uni_Doctor_Subspecialist_Code" UNIQUE ("Subspecialist_Code"), ADD CONSTRAINT "uni_Doctor_Unit_Code" UNIQUE ("Unit_Code"); +-- Modify "Employee" table +ALTER TABLE "public"."Employee" ADD COLUMN "Contract_ExpiredDate" timestamptz NULL; diff --git a/cmd/main-migration/migrations/20251106040137.sql b/cmd/main-migration/migrations/20251106040137.sql new file mode 100644 index 00000000..f9cb71cc --- /dev/null +++ b/cmd/main-migration/migrations/20251106040137.sql @@ -0,0 +1,2 @@ +-- Modify "Doctor" table +ALTER TABLE "public"."Doctor" DROP CONSTRAINT "uni_Doctor_Specialist_Code", DROP CONSTRAINT "uni_Doctor_Subspecialist_Code", DROP CONSTRAINT "uni_Doctor_Unit_Code"; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 88a3f39c..d6b62389 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:c6psxONIBPkfVLCpAnWAm81SgT25UQT6hgO8KAG6O5M= +h1:yLtZj2e+mxp2L0eRUjFUIrC1GID4BB3/8x6LaHS+v10= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -70,4 +70,6 @@ h1:c6psxONIBPkfVLCpAnWAm81SgT25UQT6hgO8KAG6O5M= 20251104080952.sql h1:avghpv1n3yaCDR/TA0X+hgxDGoLBQGu/GJUwj4VT/Ic= 20251104084135.sql h1:rg+eRE5/5sYWR7z+Xyn0zKw8rr8P/oWxF0xhcNVnNec= 20251105044629.sql h1:4NU27HeKUNFsV82LacnwmnCSAH0pSbZR9J9/ZESRs6M= -20251105121808.sql h1:uPFEHJ6pZbuo8+3giskNg4I91MrNRgrR1dMIe7kL+4g= +20251105121808.sql h1:fii6LjqWYjrm/pEIqttfvJI6QEUL49gque8wYHh1+yI= +20251106035305.sql h1:hRkWZYLQvjmROqlu9xvuXrPQcBKf6yUGTTbSd0lKbmI= +20251106040137.sql h1:ifT65MV7h0sws5EGBOGefRqxSaZqapEeupuhHMJipyw= diff --git a/internal/domain/main-entities/doctor/entity.go b/internal/domain/main-entities/doctor/entity.go index ec882838..014c6c17 100644 --- a/internal/domain/main-entities/doctor/entity.go +++ b/internal/domain/main-entities/doctor/entity.go @@ -6,19 +6,25 @@ import ( es "simrs-vx/internal/domain/main-entities/specialist" ess "simrs-vx/internal/domain/main-entities/subspecialist" eu "simrs-vx/internal/domain/main-entities/unit" + "time" ) type Doctor struct { - ecore.Main // adjust this according to the needs - Code *string `json:"code" gorm:"unique;size:20"` - Employee_Id *uint `json:"employee_id"` - Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` - IHS_Number *string `json:"ihs_number" gorm:"unique;size:20"` - SIP_Number *string `json:"sip_number" gorm:"unique;size:20"` - Unit_Id *uint16 `json:"unit_id"` - Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` - Specialist_Id *uint16 `json:"specialist_id"` - Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Id"` - Subspecialist_Id *uint16 `json:"subspecialist_id"` - Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Id"` + ecore.Main // adjust this according to the needs + Code *string `json:"code" gorm:"unique;size:20"` + Employee_Id *uint `json:"employee_id"` + Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` + IHS_Number *string `json:"ihs_number" gorm:"unique;size:20"` + SIP_Number *string `json:"sip_number" gorm:"unique;size:20"` + SIP_ExpiredDate *time.Time `json:"sip_expiredDate"` + Unit_Id *uint16 `json:"unit_id"` + Unit_Code *string `json:"unit_code" gorm:"size:10"` + Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` + // Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` + Specialist_Id *uint16 `json:"specialist_id"` + Specialist_Code *string `json:"specialist_code" gorm:"size:10"` + Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Id"` + Subspecialist_Id *uint16 `json:"subspecialist_id"` + Subspecialist_Code *string `json:"subspecialist_code" gorm:"size:10"` + Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Id"` } diff --git a/internal/domain/main-entities/employee/entity.go b/internal/domain/main-entities/employee/entity.go index 7a770be0..299ae021 100644 --- a/internal/domain/main-entities/employee/entity.go +++ b/internal/domain/main-entities/employee/entity.go @@ -6,15 +6,17 @@ import ( eu "simrs-vx/internal/domain/main-entities/user" erc "simrs-vx/internal/domain/references/common" erg "simrs-vx/internal/domain/references/organization" + "time" ) type Employee struct { - ecore.Main // adjust this according to the needs - User_Id *uint `json:"user_id"` - User *eu.User `json:"user,omitempty" gorm:"foreignKey:User_Id;references:Id"` - Person_Id *uint `json:"person_id"` - Person *ep.Person `json:"person,omitempty" gorm:"foreignKey:Person_Id;references:Id"` - Position_Code *erg.EmployeePositionCode `json:"position_code" gorm:"size:20"` - Number *string `json:"number" gorm:"size:20"` - Status_Code erc.ActiveStatusCode `json:"status_code" gorm:"not null;size:10"` + ecore.Main // adjust this according to the needs + User_Id *uint `json:"user_id"` + User *eu.User `json:"user,omitempty" gorm:"foreignKey:User_Id;references:Id"` + Person_Id *uint `json:"person_id"` + Person *ep.Person `json:"person,omitempty" gorm:"foreignKey:Person_Id;references:Id"` + Position_Code *erg.EmployeePositionCode `json:"position_code" gorm:"size:20"` + Number *string `json:"number" gorm:"size:20"` + Contract_ExpiredDate *time.Time `json:"contract_expiredDate"` + Status_Code erc.ActiveStatusCode `json:"status_code" gorm:"not null;size:10"` } diff --git a/internal/domain/references/encounter/encounter.go b/internal/domain/references/encounter/encounter.go index f7c8fdc8..45ee8c89 100644 --- a/internal/domain/references/encounter/encounter.go +++ b/internal/domain/references/encounter/encounter.go @@ -43,6 +43,7 @@ const ( DMCExtRef DischargeMethodCode = "external" // Rujuk Faskes Lain DMCDeath DischargeMethodCode = "death" // Meninggal DMCDeathOnArrival DischargeMethodCode = "death-on-arrival" // Meninggal Saat Tiba + DMCRunAway DischargeMethodCode = "run-away" // Melarikan Diri TCAmbulance TransportationCode = "ambulance" // Ambulans TCCar TransportationCode = "car" // Mobil From 9ebcb604c60a77ce08eb985d90bcbe267420929e Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 11:12:28 +0700 Subject: [PATCH 070/329] wip --- internal/domain/main-entities/doctor/dto.go | 75 ++++++++++--------- internal/domain/main-entities/user/dto.go | 8 +- .../use-case/main-use-case/doctor/helper.go | 6 +- internal/use-case/main-use-case/user/case.go | 14 ++-- 4 files changed, 53 insertions(+), 50 deletions(-) diff --git a/internal/domain/main-entities/doctor/dto.go b/internal/domain/main-entities/doctor/dto.go index 0abcd99b..67290551 100644 --- a/internal/domain/main-entities/doctor/dto.go +++ b/internal/domain/main-entities/doctor/dto.go @@ -6,16 +6,18 @@ import ( es "simrs-vx/internal/domain/main-entities/specialist" ess "simrs-vx/internal/domain/main-entities/subspecialist" eu "simrs-vx/internal/domain/main-entities/unit" + "time" ) type CreateDto struct { - Code *string `json:"code" validate:"maxLength=20"` - Employee_Id *uint `json:"employee_id"` - IHS_Number *string `json:"ihs_number"` - SIP_Number *string `json:"sip_number"` - Unit_Id *uint16 `json:"unit_id"` - Specialist_Id *uint16 `json:"specialist_id"` - Subspecialist_Id *uint16 `json:"subspecialist_id"` + Code *string `json:"code" validate:"maxLength=20"` + Employee_Id *uint `json:"employee_id"` + IHS_Number *string `json:"ihs_number"` + SIP_Number *string `json:"sip_number"` + SIP_ExpiredDate *time.Time `json:"sip_expiredDate"` + Unit_Code *string `json:"unit_code"` + Specialist_Code *string `json:"specialist_code"` + Subspecialist_Code *string `json:"subspecialist_code"` } type ReadListDto struct { @@ -25,13 +27,14 @@ type ReadListDto struct { } type FilterDto struct { - Code *string `json:"code"` - Employee_Id *uint `json:"employee-id"` - IHS_Number *string `json:"ihs-number" validate:"maxLength=20"` - SIP_Number *string `json:"sip-number" validate:"maxLength=20"` - Unit_Id *uint `json:"unit-id"` - Specialist_Id *uint16 `json:"specialist-id"` - Subspecialist_Id *uint16 `json:"subspecialist-id"` + Code *string `json:"code"` + Employee_Id *uint `json:"employee-id"` + IHS_Number *string `json:"ihs-number" validate:"maxLength=20"` + SIP_Number *string `json:"sip-number" validate:"maxLength=20"` + SIP_ExpiredDate *string `json:"sip-expiredDate"` + Unit_Code *string `json:"unit-code"` + Specialist_Code *string `json:"specialist-code"` + Subspecialist_Code *string `json:"subspecialist-code"` } type ReadDetailDto struct { @@ -59,32 +62,32 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Code *string `json:"code"` - Employee_Id *uint `json:"employee_id"` - Employee *ee.Employee `json:"employee,omitempty"` - IHS_Number *string `json:"ihs_number"` - SIP_Number *string `json:"sip_number"` - Unit_Id *uint16 `json:"unit_id"` - Unit *eu.Unit `json:"unit,omitempty"` - Specialist_Id *uint16 `json:"specialist_id"` - Specialist *es.Specialist `json:"specialist,omitempty" ` - Subspecialist_Id *uint16 `json:"subspecialist_id"` - Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty"` + Code *string `json:"code"` + Employee_Id *uint `json:"employee_id"` + Employee *ee.Employee `json:"employee,omitempty"` + IHS_Number *string `json:"ihs_number"` + SIP_Number *string `json:"sip_number"` + Unit_Code *string `json:"unit_code"` + Unit *eu.Unit `json:"unit,omitempty"` + Specialist_Code *string `json:"specialist_code"` + Specialist *es.Specialist `json:"specialist,omitempty" ` + Subspecialist_Code *string `json:"subspecialist_code"` + Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty"` } func (d Doctor) ToResponse() ResponseDto { resp := ResponseDto{ - Code: d.Code, - Employee_Id: d.Employee_Id, - Employee: d.Employee, - IHS_Number: d.IHS_Number, - SIP_Number: d.SIP_Number, - Unit_Id: d.Unit_Id, - Unit: d.Unit, - Specialist_Id: d.Specialist_Id, - Specialist: d.Specialist, - Subspecialist_Id: d.Subspecialist_Id, - Subspecialist: d.Subspecialist, + Code: d.Code, + Employee_Id: d.Employee_Id, + Employee: d.Employee, + IHS_Number: d.IHS_Number, + SIP_Number: d.SIP_Number, + Unit_Code: d.Unit_Code, + Unit: d.Unit, + Specialist_Code: d.Specialist_Code, + Specialist: d.Specialist, + Subspecialist_Code: d.Subspecialist_Code, + Subspecialist: d.Subspecialist, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/user/dto.go b/internal/domain/main-entities/user/dto.go index c3a84737..fd4b3f2c 100644 --- a/internal/domain/main-entities/user/dto.go +++ b/internal/domain/main-entities/user/dto.go @@ -24,10 +24,10 @@ type CreateDto struct { Employee *EmployeUpdateDto `json:"employee"` IHS_Number *string `json:"ihs_number" validate:"maxLength=20"` SIP_Number *string `json:"sip_number" validate:"maxLength=20"` - Unit_Id *uint16 `json:"unit_id"` - Infra_Id *uint16 `json:"infra_id"` - Specialist_Id *uint16 `json:"specialist_id"` - Subspecialist_Id *uint16 `json:"subspecialist_id"` + Unit_Code *string `json:"unit_code"` + Infra_Code *string `json:"infra_code"` + Specialist_Code *string `json:"specialist_code"` + Subspecialist_Code *string `json:"subspecialist_code"` ContractPosition_Code erg.ContractPositionCode `json:"contractPosition_code" gorm:"not null;size:20"` } diff --git a/internal/use-case/main-use-case/doctor/helper.go b/internal/use-case/main-use-case/doctor/helper.go index b62045c7..344d1c0e 100644 --- a/internal/use-case/main-use-case/doctor/helper.go +++ b/internal/use-case/main-use-case/doctor/helper.go @@ -21,7 +21,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Doctor) { data.Employee_Id = inputSrc.Employee_Id data.IHS_Number = inputSrc.IHS_Number data.SIP_Number = inputSrc.SIP_Number - data.Unit_Id = inputSrc.Unit_Id - data.Specialist_Id = inputSrc.Specialist_Id - data.Subspecialist_Id = inputSrc.Subspecialist_Id + data.Unit_Code = inputSrc.Unit_Code + data.Specialist_Code = inputSrc.Code + data.Subspecialist_Code = inputSrc.Code } diff --git a/internal/use-case/main-use-case/user/case.go b/internal/use-case/main-use-case/user/case.go index 8e452e62..a1df7e25 100644 --- a/internal/use-case/main-use-case/user/case.go +++ b/internal/use-case/main-use-case/user/case.go @@ -108,13 +108,13 @@ func Create(input e.CreateDto) (*d.Data, error) { switch input.Employee.Position_Code { case ero.EPCDoc: createDoc := ed.CreateDto{ - Code: input.Code, - Employee_Id: &employeeData.Id, - IHS_Number: input.IHS_Number, - SIP_Number: input.SIP_Number, - Unit_Id: input.Unit_Id, - Specialist_Id: input.Specialist_Id, - Subspecialist_Id: input.Subspecialist_Id, + Code: input.Code, + Employee_Id: &employeeData.Id, + IHS_Number: input.IHS_Number, + SIP_Number: input.SIP_Number, + Unit_Code: input.Unit_Code, + Specialist_Code: input.Specialist_Code, + Subspecialist_Code: input.Subspecialist_Code, } if _, err := ud.CreateData(createDoc, &event, tx); err != nil { return err From 867a68ac26b57a79b50cb677188004a1f0cc4801 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 11:14:34 +0700 Subject: [PATCH 071/329] nurse ids into codes --- cmd/main-migration/migrations/20251106041333.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 7 ++++--- internal/domain/main-entities/nurse/entity.go | 2 ++ 3 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 cmd/main-migration/migrations/20251106041333.sql diff --git a/cmd/main-migration/migrations/20251106041333.sql b/cmd/main-migration/migrations/20251106041333.sql new file mode 100644 index 00000000..0e4cc5c0 --- /dev/null +++ b/cmd/main-migration/migrations/20251106041333.sql @@ -0,0 +1,2 @@ +-- Modify "Nurse" table +ALTER TABLE "public"."Nurse" ADD COLUMN "Unit_Code" character varying(10) NULL, ADD COLUMN "Infra_Code" character varying(10) NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index d6b62389..f53af38c 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:yLtZj2e+mxp2L0eRUjFUIrC1GID4BB3/8x6LaHS+v10= +h1:NYYeyYMn4chXAE9qYJ8cipPYeNoXL7Ukmc/Y1w4d+wo= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -71,5 +71,6 @@ h1:yLtZj2e+mxp2L0eRUjFUIrC1GID4BB3/8x6LaHS+v10= 20251104084135.sql h1:rg+eRE5/5sYWR7z+Xyn0zKw8rr8P/oWxF0xhcNVnNec= 20251105044629.sql h1:4NU27HeKUNFsV82LacnwmnCSAH0pSbZR9J9/ZESRs6M= 20251105121808.sql h1:fii6LjqWYjrm/pEIqttfvJI6QEUL49gque8wYHh1+yI= -20251106035305.sql h1:hRkWZYLQvjmROqlu9xvuXrPQcBKf6yUGTTbSd0lKbmI= -20251106040137.sql h1:ifT65MV7h0sws5EGBOGefRqxSaZqapEeupuhHMJipyw= +20251106035305.sql h1:oQ7BwnxPuwY2q98adIVc+lNwL/Sz1OceLJeClDo9/TI= +20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= +20251106041333.sql h1:gIxxRLcPtsGRH6whsDFG8BDZu9G4XAiQj5WPcXb/5gU= diff --git a/internal/domain/main-entities/nurse/entity.go b/internal/domain/main-entities/nurse/entity.go index 9768c622..54f06fd1 100644 --- a/internal/domain/main-entities/nurse/entity.go +++ b/internal/domain/main-entities/nurse/entity.go @@ -14,7 +14,9 @@ type Nurse struct { Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` IHS_Number *string `json:"ihs_number" gorm:"unique;size:20"` Unit_Id *uint16 `json:"unit_id"` + Unit_Code *string `json:"unit_code" gorm:"size:10"` Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` Infra_Id *uint16 `json:"infra_id"` + Infra_Code *string `json:"infra_code" gorm:"size:10"` Infra *ei.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Id;references:Id"` } From 379b34d5baa79995c8a2f8d8fbb598c4f4656f53 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 11:18:37 +0700 Subject: [PATCH 072/329] wip --- internal/domain/main-entities/nurse/dto.go | 16 ++++++++-------- .../use-case/main-use-case/nurse/helper.go | 4 ++-- internal/use-case/main-use-case/user/case.go | 18 +++++++++++------- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/internal/domain/main-entities/nurse/dto.go b/internal/domain/main-entities/nurse/dto.go index 7b7b283c..f48014dd 100644 --- a/internal/domain/main-entities/nurse/dto.go +++ b/internal/domain/main-entities/nurse/dto.go @@ -11,8 +11,8 @@ type CreateDto struct { Code *string `json:"code" validate:"maxLength=20"` Employee_Id *uint `json:"employee_id"` IHS_Number *string `json:"ihs_number" validate:"maxLength=20"` - Unit_Id *uint16 `json:"unit_id"` - Infra_Id *uint16 `json:"infra_id"` + Unit_Code *string `json:"unit_code"` + Infra_Code *string `json:"infra_code"` } type ReadListDto struct { @@ -25,8 +25,8 @@ type FilterDto struct { Code *string `json:"code"` Employee_Id *uint `json:"employee-id"` IHS_Number *string `json:"ihs-number"` - Unit_Id *uint16 `json:"unit-id"` - Infra_Id *uint16 `json:"infra-id"` + Unit_Code *string `json:"unit-code"` + Infra_Code *string `json:"infra-code"` } type ReadDetailDto struct { Id uint16 `json:"id"` @@ -56,9 +56,9 @@ type ResponseDto struct { Employee_Id *uint `json:"employee_id"` Employee *ee.Employee `json:"employee,omitempty"` IHS_Number *string `json:"ihs_number"` - Unit_Id *uint16 `json:"unit_id"` + Unit_Code *string `json:"unit_code"` Unit *eu.Unit `json:"unit,omitempty"` - Infra_Id *uint16 `json:"infra_id"` + Infra_Code *string `json:"infra_code"` Infra *ei.Infra `json:"infra,omitempty"` } @@ -68,9 +68,9 @@ func (d Nurse) ToResponse() ResponseDto { Employee_Id: d.Employee_Id, Employee: d.Employee, IHS_Number: d.IHS_Number, - Unit_Id: d.Unit_Id, + Unit_Code: d.Unit_Code, Unit: d.Unit, - Infra_Id: d.Infra_Id, + Infra_Code: d.Infra_Code, Infra: d.Infra, } resp.Main = d.Main diff --git a/internal/use-case/main-use-case/nurse/helper.go b/internal/use-case/main-use-case/nurse/helper.go index 003230b3..49078088 100644 --- a/internal/use-case/main-use-case/nurse/helper.go +++ b/internal/use-case/main-use-case/nurse/helper.go @@ -20,6 +20,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Nurse) { data.Code = inputSrc.Code data.Employee_Id = inputSrc.Employee_Id data.IHS_Number = inputSrc.IHS_Number - data.Unit_Id = inputSrc.Unit_Id - data.Infra_Id = inputSrc.Infra_Id + data.Unit_Code = inputSrc.Unit_Code + data.Infra_Code = inputSrc.Infra_Code } diff --git a/internal/use-case/main-use-case/user/case.go b/internal/use-case/main-use-case/user/case.go index a1df7e25..94ee6801 100644 --- a/internal/use-case/main-use-case/user/case.go +++ b/internal/use-case/main-use-case/user/case.go @@ -124,8 +124,8 @@ func Create(input e.CreateDto) (*d.Data, error) { Code: input.Code, Employee_Id: &employeeData.Id, IHS_Number: input.IHS_Number, - Unit_Id: input.Unit_Id, - Infra_Id: input.Infra_Id, + Unit_Code: input.Unit_Code, + Infra_Code: input.Infra_Code, } if _, err := un.CreateData(createNurse, &event, tx); err != nil { return err @@ -396,11 +396,13 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } createDoc := ed.CreateDto{ - Code: input.Code, - Employee_Id: &employeeData.Id, - IHS_Number: input.IHS_Number, - SIP_Number: input.SIP_Number, - Unit_Id: input.Unit_Id, + Code: input.Code, + Employee_Id: &employeeData.Id, + IHS_Number: input.IHS_Number, + SIP_Number: input.SIP_Number, + Unit_Code: input.Unit_Code, + Specialist_Code: input.Specialist_Code, + Subspecialist_Code: input.Subspecialist_Code, } if readDocData != nil { if err := ud.UpdateData(ed.UpdateDto{CreateDto: createDoc}, readDocData, &event, tx); err != nil { @@ -422,6 +424,8 @@ func Update(input e.UpdateDto) (*d.Data, error) { Code: input.Code, Employee_Id: &employeeData.Id, IHS_Number: input.IHS_Number, + Unit_Code: input.Unit_Code, + Infra_Code: input.Infra_Code, } if readNurData != nil { if err := un.UpdateData(en.UpdateDto{CreateDto: createNur}, readNurData, &event, tx); err != nil { From 2580d38b723bf7b9fe572708134743b09e726ec6 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 11:21:45 +0700 Subject: [PATCH 073/329] specialist intern ids into codes --- .../migrations/20251106042006.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 5 +++-- .../main-entities/specialist-intern/entity.go | 20 ++++++++++--------- 3 files changed, 16 insertions(+), 11 deletions(-) create mode 100644 cmd/main-migration/migrations/20251106042006.sql diff --git a/cmd/main-migration/migrations/20251106042006.sql b/cmd/main-migration/migrations/20251106042006.sql new file mode 100644 index 00000000..a3f2f609 --- /dev/null +++ b/cmd/main-migration/migrations/20251106042006.sql @@ -0,0 +1,2 @@ +-- Modify "SpecialistIntern" table +ALTER TABLE "public"."SpecialistIntern" ADD COLUMN "Specialist_Code" character varying(10) NULL, ADD COLUMN "Subspecialist_Code" character varying(10) NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index f53af38c..8922bef3 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:NYYeyYMn4chXAE9qYJ8cipPYeNoXL7Ukmc/Y1w4d+wo= +h1:Ke31uEMAxNobMdza6/1rFlWnbE7Z1dHVAAfRi+oXi4E= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -73,4 +73,5 @@ h1:NYYeyYMn4chXAE9qYJ8cipPYeNoXL7Ukmc/Y1w4d+wo= 20251105121808.sql h1:fii6LjqWYjrm/pEIqttfvJI6QEUL49gque8wYHh1+yI= 20251106035305.sql h1:oQ7BwnxPuwY2q98adIVc+lNwL/Sz1OceLJeClDo9/TI= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= -20251106041333.sql h1:gIxxRLcPtsGRH6whsDFG8BDZu9G4XAiQj5WPcXb/5gU= +20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= +20251106042006.sql h1:sVi3ilQnUapkKBzNi/z495eK4ivCF9ssU/D3oEldokM= diff --git a/internal/domain/main-entities/specialist-intern/entity.go b/internal/domain/main-entities/specialist-intern/entity.go index 9df0ed53..482c9b5a 100644 --- a/internal/domain/main-entities/specialist-intern/entity.go +++ b/internal/domain/main-entities/specialist-intern/entity.go @@ -9,13 +9,15 @@ import ( ) type SpecialistIntern struct { - ecore.Main // adjust this according to the needs - Person_Id *uint `json:"person_id"` - Person *ep.Person `json:"person,omitempty" gorm:"foreignKey:Person_Id"` - Specialist_Id *uint16 `json:"specialist_id"` - Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Id"` - Subspecialist_Id *uint16 `json:"subspecialist_id"` - Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Id"` - User_Id *uint `json:"user_id"` - User *eu.User `json:"user,omitempty" gorm:"foreignKey:User_Id"` + ecore.Main // adjust this according to the needs + Person_Id *uint `json:"person_id"` + Person *ep.Person `json:"person,omitempty" gorm:"foreignKey:Person_Id"` + Specialist_Id *uint16 `json:"specialist_id"` + Specialist_Code *string `json:"specialist_code" gorm:"size:10"` + Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Id"` + Subspecialist_Id *uint16 `json:"subspecialist_id"` + Subspecialist_Code *string `json:"subspecialist_code" gorm:"size:10"` + Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Id"` + User_Id *uint `json:"user_id"` + User *eu.User `json:"user,omitempty" gorm:"foreignKey:User_Id"` } From 3126230f3e2e15200fd6e709298f7e7991e8bf41 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 11:28:55 +0700 Subject: [PATCH 074/329] refactor (doctor,nurse,specialist-intern): done --- .../main-entities/specialist-intern/dto.go | 48 +++++++++---------- .../interface/main-handler/doctor/handler.go | 6 +-- .../interface/main-handler/main-handler.go | 5 +- .../interface/main-handler/nurse/handler.go | 6 +-- .../main-use-case/specialist-intern/helper.go | 4 +- internal/use-case/main-use-case/user/case.go | 16 +++---- 6 files changed, 41 insertions(+), 44 deletions(-) diff --git a/internal/domain/main-entities/specialist-intern/dto.go b/internal/domain/main-entities/specialist-intern/dto.go index 2d01c861..bf87b00e 100644 --- a/internal/domain/main-entities/specialist-intern/dto.go +++ b/internal/domain/main-entities/specialist-intern/dto.go @@ -9,10 +9,10 @@ import ( ) type CreateDto struct { - Person_Id *uint `json:"person_id"` - Specialist_Id *uint16 `json:"specialist_id"` - Subspecialist_Id *uint16 `json:"subspecialist_id"` - User_Id *uint `json:"user_id"` + Person_Id *uint `json:"person_id"` + Specialist_Code *string `json:"specialist_code"` + Subspecialist_Code *string `json:"subspecialist_code"` + User_Id *uint `json:"user_id"` } type ReadListDto struct { @@ -22,10 +22,10 @@ type ReadListDto struct { } type FilterDto struct { - Person_Id *uint `json:"person-id"` - Specialist_Id *uint16 `json:"specialist-id"` - Subspecialist_Id *uint16 `json:"subspecialist-id"` - User_Id *uint `json:"user-id"` + Person_Id *uint `json:"person-id"` + Specialist_Code *string `json:"specialist-code"` + Subspecialist_Code *string `json:"subspecialist-code"` + User_Id *uint `json:"user-id"` } type ReadDetailDto struct { @@ -50,26 +50,26 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Person_Id *uint `json:"person_id"` - Person *ep.Person `json:"person,omitempty"` - Specialist_Id *uint16 `json:"specialist_id"` - Specialist *es.Specialist `json:"specialist,omitempty"` - Subspecialist_Id *uint16 `json:"subspecialist_id"` - Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty"` - User_Id *uint `json:"user_id"` - User *eu.User `json:"user,omitempty"` + Person_Id *uint `json:"person_id"` + Person *ep.Person `json:"person,omitempty"` + Specialist_Code *string `json:"specialist_code"` + Specialist *es.Specialist `json:"specialist,omitempty"` + Subspecialist_Code *string `json:"subspecialist_code"` + Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty"` + User_Id *uint `json:"user_id"` + User *eu.User `json:"user,omitempty"` } func (d SpecialistIntern) ToResponse() ResponseDto { resp := ResponseDto{ - Person_Id: d.Person_Id, - Person: d.Person, - Specialist_Id: d.Specialist_Id, - Specialist: d.Specialist, - Subspecialist_Id: d.Subspecialist_Id, - Subspecialist: d.Subspecialist, - User_Id: d.User_Id, - User: d.User, + Person_Id: d.Person_Id, + Person: d.Person, + Specialist_Code: d.Specialist_Code, + Specialist: d.Specialist, + Subspecialist_Code: d.Subspecialist_Code, + Subspecialist: d.Subspecialist, + User_Id: d.User_Id, + User: d.User, } resp.Main = d.Main return resp diff --git a/internal/interface/main-handler/doctor/handler.go b/internal/interface/main-handler/doctor/handler.go index 27281884..ee1252ad 100644 --- a/internal/interface/main-handler/doctor/handler.go +++ b/internal/interface/main-handler/doctor/handler.go @@ -33,7 +33,7 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) + id := rw.ValidateInt(w, "code", r.PathValue("code")) if id <= 0 { return } @@ -44,7 +44,7 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) + id := rw.ValidateInt(w, "code", r.PathValue("code")) if id <= 0 { return } @@ -59,7 +59,7 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { } func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) + id := rw.ValidateInt(w, "code", r.PathValue("code")) if id <= 0 { return } diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 1c703b64..0a6a917a 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -35,9 +35,8 @@ import ( soapi "simrs-vx/internal/interface/main-handler/soapi" /******************** actor ********************/ - doctor "simrs-vx/internal/interface/main-handler/doctor" + employee "simrs-vx/internal/interface/main-handler/employee" - nurse "simrs-vx/internal/interface/main-handler/nurse" nutritionist "simrs-vx/internal/interface/main-handler/nutritionist" patient "simrs-vx/internal/interface/main-handler/patient" person "simrs-vx/internal/interface/main-handler/person" @@ -268,8 +267,6 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/person-contact", personcontact.O) hc.RegCrud(r, "/v1/person-insurance", personinsurance.O) hc.RegCrud(r, "/v1/employee", employee.O) - hc.RegCrud(r, "/v1/doctor", doctor.O) - hc.RegCrud(r, "/v1/nurse", nurse.O) hc.RegCrud(r, "/v1/nutritionist", nutritionist.O) hc.RegCrud(r, "/v1/pharmacist", pharmacist.O) hk.GroupRoutes("/v1/user", r, hk.MapHandlerFunc{ diff --git a/internal/interface/main-handler/nurse/handler.go b/internal/interface/main-handler/nurse/handler.go index 6df7a18e..8817ae14 100644 --- a/internal/interface/main-handler/nurse/handler.go +++ b/internal/interface/main-handler/nurse/handler.go @@ -33,7 +33,7 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) + id := rw.ValidateInt(w, "code", r.PathValue("code")) if id <= 0 { return } @@ -44,7 +44,7 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) + id := rw.ValidateInt(w, "code", r.PathValue("code")) if id <= 0 { return } @@ -59,7 +59,7 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { } func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) + id := rw.ValidateInt(w, "code", r.PathValue("code")) if id <= 0 { return } diff --git a/internal/use-case/main-use-case/specialist-intern/helper.go b/internal/use-case/main-use-case/specialist-intern/helper.go index 36b989d8..91bd2afc 100644 --- a/internal/use-case/main-use-case/specialist-intern/helper.go +++ b/internal/use-case/main-use-case/specialist-intern/helper.go @@ -18,7 +18,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.SpecialistIntern) { } data.Person_Id = inputSrc.Person_Id - data.Specialist_Id = inputSrc.Specialist_Id - data.Subspecialist_Id = inputSrc.Subspecialist_Id + data.Specialist_Code = inputSrc.Specialist_Code + data.Subspecialist_Code = inputSrc.Subspecialist_Code data.User_Id = inputSrc.User_Id } diff --git a/internal/use-case/main-use-case/user/case.go b/internal/use-case/main-use-case/user/case.go index 94ee6801..7c66b153 100644 --- a/internal/use-case/main-use-case/user/case.go +++ b/internal/use-case/main-use-case/user/case.go @@ -87,10 +87,10 @@ func Create(input e.CreateDto) (*d.Data, error) { if input.ContractPosition_Code == ero.CSCInt { createInt := esi.CreateDto{ - Person_Id: input.Person_Id, - Specialist_Id: input.Specialist_Id, - Subspecialist_Id: input.Subspecialist_Id, - User_Id: &data.Id, + Person_Id: input.Person_Id, + Specialist_Code: input.Specialist_Code, + Subspecialist_Code: input.Subspecialist_Code, + User_Id: &data.Id, } if _, err := usi.CreateData(createInt, &event, tx); err != nil { return err @@ -359,10 +359,10 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } createInt := esi.CreateDto{ - User_Id: &data.Id, - Person_Id: input.Person_Id, - Specialist_Id: input.Specialist_Id, - Subspecialist_Id: input.Subspecialist_Id, + User_Id: &data.Id, + Person_Id: input.Person_Id, + Specialist_Code: input.Specialist_Code, + Subspecialist_Code: input.Subspecialist_Code, } if readIntData != nil { if err := usi.UpdateData(esi.UpdateDto{CreateDto: createInt}, readIntData, &event, tx); err != nil { From 9fb919229b4a5c32240b5cac32f3203e97fbd6f9 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 11:39:36 +0700 Subject: [PATCH 075/329] remove ids --- internal/domain/main-entities/nurse/dto.go | 8 ++++---- internal/domain/main-entities/nurse/entity.go | 6 ++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/internal/domain/main-entities/nurse/dto.go b/internal/domain/main-entities/nurse/dto.go index 7b7b283c..11047235 100644 --- a/internal/domain/main-entities/nurse/dto.go +++ b/internal/domain/main-entities/nurse/dto.go @@ -56,9 +56,9 @@ type ResponseDto struct { Employee_Id *uint `json:"employee_id"` Employee *ee.Employee `json:"employee,omitempty"` IHS_Number *string `json:"ihs_number"` - Unit_Id *uint16 `json:"unit_id"` + Unit_Code *string `json:"unit_code"` Unit *eu.Unit `json:"unit,omitempty"` - Infra_Id *uint16 `json:"infra_id"` + Infra_Code *string `json:"infra_code"` Infra *ei.Infra `json:"infra,omitempty"` } @@ -68,9 +68,9 @@ func (d Nurse) ToResponse() ResponseDto { Employee_Id: d.Employee_Id, Employee: d.Employee, IHS_Number: d.IHS_Number, - Unit_Id: d.Unit_Id, + Unit_Code: d.Unit_Code, Unit: d.Unit, - Infra_Id: d.Infra_Id, + Infra_Code: d.Infra_Code, Infra: d.Infra, } resp.Main = d.Main diff --git a/internal/domain/main-entities/nurse/entity.go b/internal/domain/main-entities/nurse/entity.go index 54f06fd1..cb1df0a8 100644 --- a/internal/domain/main-entities/nurse/entity.go +++ b/internal/domain/main-entities/nurse/entity.go @@ -13,10 +13,8 @@ type Nurse struct { Employee_Id *uint `json:"employee_id"` Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` IHS_Number *string `json:"ihs_number" gorm:"unique;size:20"` - Unit_Id *uint16 `json:"unit_id"` Unit_Code *string `json:"unit_code" gorm:"size:10"` - Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` - Infra_Id *uint16 `json:"infra_id"` + Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` Infra_Code *string `json:"infra_code" gorm:"size:10"` - Infra *ei.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Id;references:Id"` + Infra *ei.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Code;references:Code"` } From a2015a5c7e405ddcab254ef97f92d0d6ec0454b0 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 12:08:36 +0700 Subject: [PATCH 076/329] removes ids on doctor,nurse,specialist-intern --- .../migrations/20251106050412.sql | 8 ++++ cmd/main-migration/migrations/atlas.sum | 5 ++- .../domain/main-entities/doctor/entity.go | 26 ++++++------- .../main-entities/prescription/entity.go | 1 + .../main-entities/specialist-intern/entity.go | 6 +-- internal/lib/auth/tycovar.go | 12 +++--- .../main-use-case/authentication/case.go | 38 +++++++++---------- .../use-case/main-use-case/encounter/lib.go | 6 ++- .../main-use-case/prescription/helper.go | 2 +- 9 files changed, 55 insertions(+), 49 deletions(-) create mode 100644 cmd/main-migration/migrations/20251106050412.sql diff --git a/cmd/main-migration/migrations/20251106050412.sql b/cmd/main-migration/migrations/20251106050412.sql new file mode 100644 index 00000000..11ef2a96 --- /dev/null +++ b/cmd/main-migration/migrations/20251106050412.sql @@ -0,0 +1,8 @@ +-- Modify "Prescription" table +ALTER TABLE "public"."Prescription" ADD COLUMN "Doctor_Code" character varying(20) NULL; +-- Modify "Doctor" table +ALTER TABLE "public"."Doctor" DROP CONSTRAINT "fk_Doctor_Specialist", DROP CONSTRAINT "fk_Doctor_Subspecialist", DROP CONSTRAINT "fk_Doctor_Unit", DROP COLUMN "Unit_Id", DROP COLUMN "Specialist_Id", DROP COLUMN "Subspecialist_Id", ADD CONSTRAINT "fk_Doctor_Specialist" FOREIGN KEY ("Specialist_Code") REFERENCES "public"."Specialist" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_Doctor_Subspecialist" FOREIGN KEY ("Subspecialist_Code") REFERENCES "public"."Subspecialist" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_Doctor_Unit" FOREIGN KEY ("Unit_Code") REFERENCES "public"."Unit" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "Nurse" table +ALTER TABLE "public"."Nurse" DROP CONSTRAINT "fk_Nurse_Infra", DROP CONSTRAINT "fk_Nurse_Unit", DROP COLUMN "Unit_Id", DROP COLUMN "Infra_Id", ADD CONSTRAINT "fk_Nurse_Infra" FOREIGN KEY ("Infra_Code") REFERENCES "public"."Infra" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_Nurse_Unit" FOREIGN KEY ("Unit_Code") REFERENCES "public"."Unit" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "SpecialistIntern" table +ALTER TABLE "public"."SpecialistIntern" DROP CONSTRAINT "fk_SpecialistIntern_Specialist", DROP CONSTRAINT "fk_SpecialistIntern_Subspecialist", DROP COLUMN "Specialist_Id", DROP COLUMN "Subspecialist_Id", ADD CONSTRAINT "fk_SpecialistIntern_Specialist" FOREIGN KEY ("Specialist_Code") REFERENCES "public"."Specialist" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_SpecialistIntern_Subspecialist" FOREIGN KEY ("Subspecialist_Code") REFERENCES "public"."Subspecialist" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 8922bef3..79b67fa2 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:Ke31uEMAxNobMdza6/1rFlWnbE7Z1dHVAAfRi+oXi4E= +h1:97IUzyfSecffgKmYYs+a+HW5thHnIY3OuWDTQYy3hGQ= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -74,4 +74,5 @@ h1:Ke31uEMAxNobMdza6/1rFlWnbE7Z1dHVAAfRi+oXi4E= 20251106035305.sql h1:oQ7BwnxPuwY2q98adIVc+lNwL/Sz1OceLJeClDo9/TI= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= -20251106042006.sql h1:sVi3ilQnUapkKBzNi/z495eK4ivCF9ssU/D3oEldokM= +20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= +20251106050412.sql h1:MiEMJ1HCFYnalKuq3Z38xJeogfBAMqsTv2sG4EF8dDw= diff --git a/internal/domain/main-entities/doctor/entity.go b/internal/domain/main-entities/doctor/entity.go index 014c6c17..506271a2 100644 --- a/internal/domain/main-entities/doctor/entity.go +++ b/internal/domain/main-entities/doctor/entity.go @@ -10,21 +10,17 @@ import ( ) type Doctor struct { - ecore.Main // adjust this according to the needs - Code *string `json:"code" gorm:"unique;size:20"` - Employee_Id *uint `json:"employee_id"` - Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` - IHS_Number *string `json:"ihs_number" gorm:"unique;size:20"` - SIP_Number *string `json:"sip_number" gorm:"unique;size:20"` - SIP_ExpiredDate *time.Time `json:"sip_expiredDate"` - Unit_Id *uint16 `json:"unit_id"` - Unit_Code *string `json:"unit_code" gorm:"size:10"` - Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` - // Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` - Specialist_Id *uint16 `json:"specialist_id"` + ecore.Main // adjust this according to the needs + Code *string `json:"code" gorm:"unique;size:20"` + Employee_Id *uint `json:"employee_id"` + Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` + IHS_Number *string `json:"ihs_number" gorm:"unique;size:20"` + SIP_Number *string `json:"sip_number" gorm:"unique;size:20"` + SIP_ExpiredDate *time.Time `json:"sip_expiredDate"` + Unit_Code *string `json:"unit_code" gorm:"size:10"` + Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` Specialist_Code *string `json:"specialist_code" gorm:"size:10"` - Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Id"` - Subspecialist_Id *uint16 `json:"subspecialist_id"` + Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Code;references:Code"` Subspecialist_Code *string `json:"subspecialist_code" gorm:"size:10"` - Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Id"` + Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Code;references:Code"` } diff --git a/internal/domain/main-entities/prescription/entity.go b/internal/domain/main-entities/prescription/entity.go index bdc2d2fb..c32c9d9e 100644 --- a/internal/domain/main-entities/prescription/entity.go +++ b/internal/domain/main-entities/prescription/entity.go @@ -15,6 +15,7 @@ type Prescription struct { Encounter_Id *uint `json:"encounter_id"` Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code" gorm:"size:20"` Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` IssuedAt *time.Time `json:"issuedAt"` Status_Code erc.DataStatusCode `json:"status_code"` diff --git a/internal/domain/main-entities/specialist-intern/entity.go b/internal/domain/main-entities/specialist-intern/entity.go index 482c9b5a..5d87e1a7 100644 --- a/internal/domain/main-entities/specialist-intern/entity.go +++ b/internal/domain/main-entities/specialist-intern/entity.go @@ -12,12 +12,10 @@ type SpecialistIntern struct { ecore.Main // adjust this according to the needs Person_Id *uint `json:"person_id"` Person *ep.Person `json:"person,omitempty" gorm:"foreignKey:Person_Id"` - Specialist_Id *uint16 `json:"specialist_id"` Specialist_Code *string `json:"specialist_code" gorm:"size:10"` - Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Id"` - Subspecialist_Id *uint16 `json:"subspecialist_id"` + Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Code;references:Code"` Subspecialist_Code *string `json:"subspecialist_code" gorm:"size:10"` - Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Id"` + Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Code;references:Code"` User_Id *uint `json:"user_id"` User *eu.User `json:"user,omitempty" gorm:"foreignKey:User_Id"` } diff --git a/internal/lib/auth/tycovar.go b/internal/lib/auth/tycovar.go index 44426d4b..467bd1b6 100644 --- a/internal/lib/auth/tycovar.go +++ b/internal/lib/auth/tycovar.go @@ -14,12 +14,12 @@ type AuthInfo struct { User_ContractPosition_code string Employee_Position_Code *string Employee_Id *uint - Doctor_Id *uint - Nurse_Id *uint - Midwife_Id *uint - Nutritionist_Id *uint - Laborant_Id *uint - Pharmachist_Id *uint + Doctor_Code *string + Nurse_Code *string + Midwife_Code *string + Nutritionist_Code *string + Laborant_Code *string + Pharmachist_Code *string Intern_Position_Code *string Roles []string // User_DivisionPositions []DivisionPosition diff --git a/internal/use-case/main-use-case/authentication/case.go b/internal/use-case/main-use-case/authentication/case.go index d00889ee..6a980d71 100644 --- a/internal/use-case/main-use-case/authentication/case.go +++ b/internal/use-case/main-use-case/authentication/case.go @@ -136,17 +136,17 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { if doctor.Id == 0 { return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noDoctor", Message: el.GenMessage("auth-noDoctor")}} } - atClaims["doctor_id"] = doctor.Id - outputData["doctor_id"] = doctor.Id + atClaims["doctor_code"] = doctor.Code + outputData["doctor_code"] = doctor.Code // specialist - if doctor.Specialist_Id != nil { - atClaims["specialist_id"] = doctor.Specialist_Id - outputData["specialist_id"] = doctor.Specialist_Id + if doctor.Specialist_Code != nil { + atClaims["specialist_code"] = doctor.Specialist_Code + outputData["specialist_code"] = doctor.Specialist_Code } - if doctor.Subspecialist_Id != nil { - atClaims["subspecialist_id"] = doctor.Subspecialist_Id - outputData["subspecialist_id"] = doctor.Subspecialist_Id + if doctor.Subspecialist_Code != nil { + atClaims["subspecialist_code"] = doctor.Subspecialist_Code + outputData["subspecialist_code"] = doctor.Subspecialist_Code } case erg.EPCNur: empData := en.Nurse{} @@ -154,16 +154,16 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { if empData.Id == 0 { return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: el.GenMessage("auth-noNurse")}} } - atClaims["nurse_id"] = empData.Id - outputData["nurse_id"] = empData.Id + atClaims["nurse_code"] = empData.Code + outputData["nurse_code"] = empData.Code case erg.EPCMwi: empData := em.Midwife{} dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) if empData.Id == 0 { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: el.GenMessage("auth-noNurse")}} + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noMidwife", Message: el.GenMessage("auth-noMidwife")}} } - atClaims["nurse_id"] = empData.Id - outputData["nurse_id"] = empData.Id + atClaims["midwife_code"] = empData.Code + outputData["midwife_code"] = empData.Code } errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: el.GenMessage("auth-getData-failed")}} @@ -308,12 +308,12 @@ func ExtractToken(r *http.Request, tokenType TokenType) (data *pa.AuthInfo, err data.User_ContractPosition_code = checkStrClaims(claims, "contractPosition_code") data.Employee_Position_Code = checkStrPtrClaims(claims, "employee_position_code") - data.Doctor_Id = checkUntPtrClaims(claims, "doctor_id") - data.Nurse_Id = checkUntPtrClaims(claims, "nurse_id") - data.Midwife_Id = checkUntPtrClaims(claims, "midwife_id") - data.Nutritionist_Id = checkUntPtrClaims(claims, "nutritionist_id") - data.Laborant_Id = checkUntPtrClaims(claims, "laborant_id") - data.Pharmachist_Id = checkUntPtrClaims(claims, "pharmachist_id") + data.Doctor_Code = checkStrPtrClaims(claims, "doctor_string") + data.Nurse_Code = checkStrPtrClaims(claims, "nurse_string") + data.Midwife_Code = checkStrPtrClaims(claims, "midwife_string") + data.Nutritionist_Code = checkStrPtrClaims(claims, "nutritionist_string") + data.Laborant_Code = checkStrPtrClaims(claims, "laborant_string") + data.Pharmachist_Code = checkStrPtrClaims(claims, "pharmachist_string") data.Intern_Position_Code = checkStrPtrClaims(claims, "intern_position_code") data.Employee_Id = checkUntPtrClaims(claims, "employee_id") return diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index 0c51a8d6..18a632c3 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -4,10 +4,12 @@ import ( // std "errors" ere "simrs-vx/internal/domain/references/encounter" + // external dg "github.com/karincake/apem/db-gorm-pg" gh "github.com/karincake/getuk" "gorm.io/gorm" + // pkg plh "simrs-vx/pkg/lib-helper" pl "simrs-vx/pkg/logger" @@ -56,8 +58,8 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.En } tx = tx.Model(&e.Encounter{}) - if input.AuthInfo.Doctor_Id != nil { - tx.Where("\"Responsible_Doctor_Id\" = ?", *input.AuthInfo.Doctor_Id) + if input.AuthInfo.Doctor_Code != nil { + tx.Where("\"Responsible_Doctor_Id\" = ?", *input.AuthInfo.Doctor_Code) // TODO: fix this } tx.Scopes(gh.Preload(input.Includes)). diff --git a/internal/use-case/main-use-case/prescription/helper.go b/internal/use-case/main-use-case/prescription/helper.go index 35c55512..92fd4531 100644 --- a/internal/use-case/main-use-case/prescription/helper.go +++ b/internal/use-case/main-use-case/prescription/helper.go @@ -38,7 +38,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Prescription) { data.Encounter_Id = inputSrc.Encounter_Id // data.Doctor_Id = inputSrc.Doctor_Id - data.Doctor_Id = inputSrc.AuthInfo.Doctor_Id + data.Doctor_Code = inputSrc.AuthInfo.Doctor_Code data.IssuedAt = inputSrc.IssuedAt } From 03aceaac0b8ebbb5044267e9e9150209bf84370f Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 6 Nov 2025 12:09:32 +0700 Subject: [PATCH 077/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 154 ++++++++++++------------ 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 8922bef3..90d23a8a 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,77 +1,77 @@ -h1:Ke31uEMAxNobMdza6/1rFlWnbE7Z1dHVAAfRi+oXi4E= -20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= -20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= -20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= -20250908062323.sql h1:oXl6Z143tOpIl4EfP4B8JNU8LrMvVmHEtCgAfiB4gs8= -20250908073811.sql h1:m2aNXfnGxnLq1+rVWrh4f60q7fhyhV3gEwNu/OIqQlE= -20250908073839.sql h1:cPk54xjLdMs26uY8ZHjNWLuyfAMzV7Zb0/9oJQrsw04= -20250910055902.sql h1:5xwjAV6QbtZT9empTJKfhyAjdknbHzb15B0Ku5dzqtQ= -20250915123412.sql h1:D83xaU2YlDEd21HLup/YQpQ2easMToYCyy/oK6AFgQs= -20250916043819.sql h1:ekoTJsBqQZ8G8n0qJ03d13+eoNoc7sAUEQGA5D/CCxk= -20250917040616.sql h1:zoCnmcXuM7AVv85SmN7RmFglCgJnoDmpRWExH0LAc9Q= -20250917040751.sql h1:J1xyRrh32y1+lezwAyNwPcUQ6ABBSgbvzNLva4SVdQU= -20250917045138.sql h1:jKe1Z0uOLG4SGBYM+S/3P+/zMPztmgoderD5swnMuCg= -20250917093645.sql h1:cNI3Pbz1R3LxvIXLuexafJFCXUXrmuFCgXXJ2sG+FW0= -20250918073552.sql h1:RJ1SvMzP6aeWnoPVD3eVAmIQOkcp6Php8z3QRri6v4g= -20250918073742.sql h1:+cEsnJTJFybe2fR69ZoOiX2R6c6iITl4m6WTZ1hjyzY= -20250918074745.sql h1:2hNVQCXF/dVYXAh+T/7oBFgERGWxzVb2FXJjwkFWGCI= -20250923025134.sql h1:Ykz/qpHiGDXPsCsWTjydQFVSibZP2D+h2fIeb2h2JGA= -20250924051317.sql h1:yQuW6SwJxIOM5fcxeAaie5lSm1oLysU/C2hH2xNCVoQ= -20250929034321.sql h1:101FJ8VH12mrZWlt/X1gvKUGOhoiF8tFbjiapAjnHzg= -20250929034428.sql h1:i+pROD9p+g5dOmmZma6WF/0Hw5g3Ha28NN85iTo1K34= -20250930025550.sql h1:+F+CsCUXD/ql0tHGEow70GhPBX1ZybVn+bh/T4YMh7Y= -20250930140351.sql h1:9AAEG1AnOAH+o0+oHL5G7I8vqlWOhwRlCGyyCpT/y1Q= -20251002085604.sql h1:3xZ68eYp4urXRnvotNH1XvG2mYOSDV/j3zHEZ/txg5E= -20251003032030.sql h1:HB+mQ2lXMNomHDpaRhB/9IwYI9/YiDO5eOJ+nAQH/jw= -20251005060450.sql h1:LbtCE2b+8osM3CvnmQJH1uCPtn+d7WchsslBOz8bL3Q= -20251006041122.sql h1:MlS7f21z06sutnf9dIekt5fuHJr4lgcQ4uCuCXAGsfc= -20251006045658.sql h1:3FmGCPCzjgMPdWDRodZTsx3KVaodd9zB9ilib69aewk= -20251006045928.sql h1:Z5g31PmnzNwk/OKdODcxZGm8fjJQdMFK32Xfnt3bRHg= -20251007022859.sql h1:FO03zEfaNEk/aXwY81d5Lp3MoBB9kPQuXlXJ4BPiSR8= -20251008031337.sql h1:l+sxUAGvcTfj3I6kAFHo+T6AYodC9k9GkR+jaKO2xXc= -20251008031554.sql h1:AqrVfIhSzY3PCy8ZlP5W91wn2iznfIuj5qQfubp6/94= -20251008052346.sql h1:nxnXmooIJ6r1mmzwnw+6efxLfc/k9h2aE6RMptPRons= -20251008073620.sql h1:6YsJp1W4SmQJ1lxpqF27BBlDC1zqhw7Yhc7pLzQTY6M= -20251009042854.sql h1:nkBV+R6j0fg7/JY6wH3eb5Vv0asJLnXmb6lINfT/GLQ= -20251009052657.sql h1:EPvdsib5rzCGPryd10HShGKvFPwM/R5S2lIVwtYxpms= -20251010031743.sql h1:T8IZmx8/btRFKLzTe78MzcBsPJNodnLvB0tby9QkirQ= -20251010070721.sql h1:5NQUk/yOV6sABLCB7swx++YIOyJe6MnU+yt1nRzde5w= -20251010072711.sql h1:ZJNqR2piyu8xJhBvVABSlnGEoKSKae3wuEs+wshPe4k= -20251013044536.sql h1:0Xjw8fNILiT8nnfrJDZgQnPf3dntmIoilbapnih8AE4= -20251013051438.sql h1:lfSuw5mgJnePBJamvhZ81osFIouXeiIEiSZ/evdwo48= -20251013081808.sql h1:ijgjNX08G6GBjA/ks8EKtb7P7Y7Cg7zbhqEOruGnv6M= -20251014060047.sql h1:0jqj49WTtneEIMQDBoo4c095ZGi8sCrA8NnHBrPU6D8= -20251014063537.sql h1:VZLXol0PTsTW21Epg6vBPsztWkDtcxup9F/z88EGgIg= -20251014063720.sql h1:2HVUyCV0ud3BJJDH2GEKZN/+IWLFPCsN1KqhP6csO14= -20251015045455.sql h1:MeLWmMhAOAz8b15Dd7IAQnt6JxjSml02XCXK22C0Lpg= -20251016010845.sql h1:4BncQdDOasRZJkzVJrSJJA7091A9VPNVx/faUCUPhBM= -20251016011023.sql h1:9JB9eFZKURK5RoCVDKR6glSvdJ8NTXrN7K/4q51zkz4= -20251016062912.sql h1:ACNn0fe+EMqUt3hoY+Dr3uqAV/QICBa1+mIW7fUc9Fk= -20251017060617.sql h1:4T3t9ifWrEQTPMSM0XJ98pF7Qdt+UfgtMui17bhrnWI= -20251017082207.sql h1:8vLG1l/saRRMHXkyA4nelJyjaSddhZd6r7R+Uo4JS/c= -20251018032635.sql h1:2xey5gnO3y2XSOrU8MLlIfoylPKbRGDRtHDD07B3MbQ= -20251018040322.sql h1:k/pdNiSoT8zFPqNQ/avOD0vYkNh3BTD64IlHrfVXr7I= -20251019093915.sql h1:hFcQE0y+p5dZiVwePGsRGto9m/q6kJNiUZbVDd5Rnjk= -20251020062553.sql h1:Iw7hulcm5iRQlfW+ygA4iTPxLqkxx6h9vXMXEwUAHKs= -20251021041042.sql h1:wMgSivBV2A0NDcsLmKGIp0kMcVh2IODSG9b4dgzCaOM= -20251021075552.sql h1:8gfSMAglflNO6L0sSzxFNEubYN8/O4thT7OQT+WH+3M= -20251023044432.sql h1:MkvajJs3bfk9+wHvQ43/ccAluJEBARm1gWr1u92ccLA= -20251024034832.sql h1:x3s3VEVYLOSKLAFxJGb2+c1FyTMMvPE+9k4Ew7rKQaI= -20251024074315.sql h1:EjAjelgi5qAfcRq/8vPTlGGYHvAKxNTllm8f0SzZDns= -20251025013451.sql h1:6hnuIiwYiG+6nLhOY/+Yyn+I6ZCFNRZxrJNqBV6HLqE= -20251025013609.sql h1:evPJaTD8WxYRMOJZHkSr7ONLx9PYxT+ankzQt9c/sJ0= -20251027075128.sql h1:/iFQBM1sytjqpyQSOx61q33gnorMgxTiFVSuL6bQqsM= -20251027091406.sql h1:eCZGtUkxAzEAqpC9UsGpP8Df9mS0DEOqSl885LgqpvM= -20251102002037.sql h1:lFJbuoZ2LMQnUNGdcwHVY3Xlfslgzu9t2WByT8yfOZI= -20251102091932.sql h1:rmdhb5m+P+fU8jROBZNyeYgZKuQvucsuljXv4ZVzvks= -20251103081637.sql h1:tf3BcwTeIw+oxMEisKDDfyKnBfalTLs8b0PJA8JWYxY= -20251104042334.sql h1:7PDMWOhmJywolAPKFZ14XaDBeMvcxShaXFN2IemNtzk= -20251104043530.sql h1:qvYVp3ysPf27f1BcoRNCFGovxuVE12lg9d6Xzda6zWU= -20251104080952.sql h1:avghpv1n3yaCDR/TA0X+hgxDGoLBQGu/GJUwj4VT/Ic= -20251104084135.sql h1:rg+eRE5/5sYWR7z+Xyn0zKw8rr8P/oWxF0xhcNVnNec= -20251105044629.sql h1:4NU27HeKUNFsV82LacnwmnCSAH0pSbZR9J9/ZESRs6M= -20251105121808.sql h1:fii6LjqWYjrm/pEIqttfvJI6QEUL49gque8wYHh1+yI= -20251106035305.sql h1:oQ7BwnxPuwY2q98adIVc+lNwL/Sz1OceLJeClDo9/TI= -20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= -20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= -20251106042006.sql h1:sVi3ilQnUapkKBzNi/z495eK4ivCF9ssU/D3oEldokM= +h1:lDfnkzBVHYhHwd5okbIRgBk5zo9kmeAK9Ideg1SsSw4= +20250904105930.sql h1:Vv4vCurl7m7/ZB6TjRpkubHpQ4RYwSUn0QHdzfoGpzY= +20250904141448.sql h1:FYCHH9Os4KkrZMDu/jR8FMP+wLMRW+Mb0PkLU/9BRDg= +20250908062237.sql h1:oanBpKZd+akPu2I/xYhUSbd0G5tAFbXzKLER/Zs8ENI= +20250908062323.sql h1:miNG9COddXkD1jGTgaROMAZ618eT6oiLGiJhXWnQwhE= +20250908073811.sql h1:gOi5cnGG1htlpfizybYmUIT0vYjZTBfXiI0nPSYK2u8= +20250908073839.sql h1:cWNDA4YikjoOteAJuNLFILjQUJPFB6o8Wxreiek4QyI= +20250910055902.sql h1:nxxOGnU0BbH/v3IPgeIOXOwH8d3tKomw7h6FTeMnnBs= +20250915123412.sql h1:mz7SiWfrdf0qE1VTSAAnA/147d6gyp6ry5vZ2bR9SH0= +20250916043819.sql h1:RHXVtmMkB6wfv06HfPyHMBmUfIpFt1xveafNz0kwKnE= +20250917040616.sql h1:MYVDht+akBlzQGKNu2hTTTLPEcH1bxT/Q8MK6WEtuhs= +20250917040751.sql h1:J79YyS2JzWgh5oKXMTgh67uo3gLxKaAsxRiZmSIfjBs= +20250917045138.sql h1:/SM1N4O8X3yxpoJgMEARmS1uOkuLKsTOy4PLsRCOKaQ= +20250917093645.sql h1:PNBTGZ7s10e5b5+Tie8YfVQBN0zKtJ5T34oK1iOUEb4= +20250918073552.sql h1:jG7+g3i8ODYaJdcdZz12v3nbsZ5mB9wG6kWnGyTQIRI= +20250918073742.sql h1:j+rgw7puxE7s+phqPVZHmPk0af3rcaA56Itp86y1suY= +20250918074745.sql h1:rPmP4DXs6OnY4Vp+xO/z9jFpJt/RrJ52SJJjIIxeDvc= +20250923025134.sql h1:2r6pcwnBSU5Y9Czk1OHBoh4yZXiMtEca9X8843fTEX0= +20250924051317.sql h1:iUAk2gsGoEGIPQ0lEEUp8maMSId8emNbP+kP712ABIA= +20250929034321.sql h1:UlpALNVmdi95zOIT0yc6ZyTj9bBjQEIpZhvgrc52M+k= +20250929034428.sql h1:feF+H4nDyHh5bdx48Oiz0A1qecZfi6v3qTTdjzJ45Dg= +20250930025550.sql h1:6XT1kXI3Z3ZIxxmvT7poufZWWCW0QiejZPaFV5wBnjI= +20250930140351.sql h1:HxnmAbh9gCy8jwl/9ycGktiByaUripsjFFvohofY2CY= +20251002085604.sql h1:SjLPi+ZN6qDccK3DaEQCgNsZpPwr5kynWXwbwEsziCI= +20251003032030.sql h1:oHfxNSuqTxU8Zaf9H+h8TuUb1Da03wcyc6hZjDrUQ2s= +20251005060450.sql h1:GIuCcrd4MwjmXpvbzDzPYL18BV3QaZZ+Y2FmEzjvi0E= +20251006041122.sql h1:uNDQbSw0M08lYoMvUNlQtS3iDzpPM1ixT13ugSAoWjE= +20251006045658.sql h1:z+t7yCK54Q4SSiF9kUyUhkYB2F+kzSW9TB7ogxd9wzw= +20251006045928.sql h1:1lATLFLp4BWwGZqAjZdP0Dc6ypNXiYcwjoNkqGa8NFE= +20251007022859.sql h1:HXXwWrkyvzJzJGAt9mGskCRBBV/c1JfPmfjDocmJhQ4= +20251008031337.sql h1:Ln5pCF3Hxa5foHZLcds+z/us2eH6VAhhEj3w0TAGlVs= +20251008031554.sql h1:aB4MUS2lmqG0//4HKUWorcPSpWya0VC4QItvGyskEVI= +20251008052346.sql h1:MI3AZgU5XcwZT2OvvlWAxdRtL0eJ3jjRwt56IY1+pRU= +20251008073620.sql h1:sztWXuSNYwpEraaSapSsYwno75LO5H/N7ob7OJQ8X/A= +20251009042854.sql h1:TnPXj+dCJls3IU//cuqJZymyBzZMKs7ayazfgtAFRxM= +20251009052657.sql h1:leXbs0CP8r5dRilmYyLRk1MICqak3ea1/LWMtFrijqQ= +20251010031743.sql h1:SgHNY/lQ88G2F4nZyMfiOkDntb+gtOR+nEQLqXBTwv4= +20251010070721.sql h1:AnJnhXsMzDvK4AFgYw6B16Kpo/hljrZtcpc9m2VOSHQ= +20251010072711.sql h1:aXPTtNwLcTuw8C/yAxwxvqs0ayEjNzI1uuE0vE3ERa8= +20251013044536.sql h1:7Pq6JcvTpPBYDCW2dz3HdgUwY65HlhEVWy9TiG8iONE= +20251013051438.sql h1:X6t8bkqpUYYokBunSufMQUe5vCg0VyO6dxbm7ngosUc= +20251013081808.sql h1:495pLguXL2Ozh+ycn4UYZgZbn6WbjXNbyZUc3JU8qhI= +20251014060047.sql h1:nCgImMRGHhziiW57O1ofWaXCAPGaCOHN7PldQ3OSmM4= +20251014063537.sql h1:2cLmID79jP6cuQ1YJaWTtghFiM1GtHMC0ZQl30Hpy1M= +20251014063720.sql h1:bzLKKVAjSHgDFoiI/glj7t1ETlSAKx+AlsIAaP0ru2g= +20251015045455.sql h1:S547+UugQhlTRcn1Lm1IfqT5RNPttIWIiD+RTx69YaE= +20251016010845.sql h1:c9DUvxl17pUkf0azdYGM/YDzYxIJkLcfZOcMI4rL+R0= +20251016011023.sql h1:u3ivg83bXgYHBbojbWpemLxPE9Dmmj53B6LXo664jxw= +20251016062912.sql h1:W9n1hWchfYkqNX9LO9uxFxEXAb/iY+Pexjnhmp6PbgI= +20251017060617.sql h1:VU6yZ2+LfHpDZ3+TIH40t3F5YXPCpTppuF9+uSqa4b8= +20251017082207.sql h1:QshZslfedckz7iDpSGmPyY9sP6dy6ckHbs8L1TuXIA4= +20251018032635.sql h1:M1U/9W/F9wlW5YDmVAmHFfUJU7FWFaX0DblpfZcYWrE= +20251018040322.sql h1:Zk/vw0e6AzWFO2ElLOzB+OrSz6k+h1Ynxp0TImAzxwY= +20251019093915.sql h1:3Q0kPiZwJnHn5rAvdh0w1LBdiA7W2xBmZWncoPXb044= +20251020062553.sql h1:mJwC/J8GzPAIXckNMvy1f/Nguk2VVf8roD/Raclhbao= +20251021041042.sql h1:d1BAOGAQhqr+oOwcpAVozUsTh457VSDEk2qQFavGG58= +20251021075552.sql h1:TNChGQ1Zlr/1iQ6qvK4iDTAJpe6L/z/M6e/O0SkQVaM= +20251023044432.sql h1:GA2AdJk2ULyjr6igtu9C/CEi4YUIks8r9jXGGaCvPsk= +20251024034832.sql h1:RXmbEhMkOLK5g1QL6up8iRPcwYfo89oLP26ZHvrUK9o= +20251024074315.sql h1:3GnPQSbuAAfMa8oWDyBjhXqn1j1zunY/w0ydX0IGPrA= +20251025013451.sql h1:5eNrA9LDxA4i5CCP7wSyOgFZ6t6jBWVil+oGzJpkJ2E= +20251025013609.sql h1:+N6EHc1kv3hqf16CUhXe+UITPmoxOPfi4MECLmJXNrc= +20251027075128.sql h1:PQflgsjce/p2ClbybLtdehdPNDcMZ9Lb1vd98xd0K8E= +20251027091406.sql h1:bYXV57GvodCMjg0/ox+XKGIAGhrDlVuJ1wO4foNEKtQ= +20251102002037.sql h1:ZcwULsJU2lI9t5pX7ukmfAHSx4ZxdxLUX6jzLDc2SrU= +20251102091932.sql h1:A6y9j4wAqm4/HfMDxhpy/ChDn3UNRVN99KGgSCX+e18= +20251103081637.sql h1:RFqJNhJItSwJQaMP5IcQ14mL7eQ3EJjGZua9zLWzwMU= +20251104042334.sql h1:BbjLAwImggvI6489FQgD+S/AaafeiZut8k19TdH7XUE= +20251104043530.sql h1:Y0sOQqgnHxd5vKPA4+4fAGGdWCv6duKAYgHnjRJZUIc= +20251104080952.sql h1:hDHzFs/k+NhPYJ64ifbVp+nTJLMCG5MIMJU1zBMP0V0= +20251104084135.sql h1:p97mW1MPtPrMWJKy/KZqvymMO/vlelnXp43N9bZVCTI= +20251105044629.sql h1:E4BkVD3YyWvd0D18jA57EwTmkeoAMUWrdTCEwdPHA1U= +20251105121808.sql h1:kyMNzaJLyVtS1QpkX7cnVvhQmrrIE8m3GxUWwrMeyUo= +20251106035305.sql h1:VInVWBP1xpEhVIm1+ymuPzu0joxV2oS4qkNIyQvmTSU= +20251106040137.sql h1:7glRO1VAgq89H6zhM6M50iLwMT0w2sb96DUGrvfXZo4= +20251106041333.sql h1:/2wLmx8awSYhVpusDPAI+VeYJOLeLCWsNaF79gl1lg8= +20251106042006.sql h1:05AZyIbRJi1W08ETScADyAhI3elW0bXaWizlCpDfFCI= From 4e001555bb0e02a4c46b30486427806a3bba34b3 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 12:17:49 +0700 Subject: [PATCH 078/329] migration from server --- cmd/main-migration/Makefile | 36 +- cmd/main-migration/README-ATLAS.MD | 116 +- cmd/main-migration/atlas.hcl.example | 42 +- cmd/main-migration/migration.go | 18 +- .../migrations/20250904105930.sql | 1370 ++++++++--------- .../migrations/20250904141448.sql | 20 +- .../migrations/20250908062237.sql | 192 +-- .../migrations/20250908062323.sql | 4 +- .../migrations/20250908073811.sql | 4 +- .../migrations/20250908073839.sql | 4 +- .../migrations/20250910055902.sql | 4 +- .../migrations/20250915123412.sql | 292 ++-- .../migrations/20250916043819.sql | 28 +- .../migrations/20250917040616.sql | 16 +- .../migrations/20250917040751.sql | 4 +- .../migrations/20250917045138.sql | 4 +- .../migrations/20250917093645.sql | 8 +- .../migrations/20250918073552.sql | 20 +- .../migrations/20250918073742.sql | 62 +- .../migrations/20250918074745.sql | 4 +- .../migrations/20250923025134.sql | 34 +- .../migrations/20250924051317.sql | 4 +- .../migrations/20250929034321.sql | 4 +- .../migrations/20250929034428.sql | 4 +- .../migrations/20250930025550.sql | 12 +- .../migrations/20250930140351.sql | 8 +- .../migrations/20251002085604.sql | 4 +- .../migrations/20251003032030.sql | 12 +- .../migrations/20251005060450.sql | 48 +- .../migrations/20251006041122.sql | 4 +- .../migrations/20251006045658.sql | 4 +- .../migrations/20251006045928.sql | 4 +- .../migrations/20251007022859.sql | 4 +- .../migrations/20251008031337.sql | 4 +- .../migrations/20251008031554.sql | 24 +- .../migrations/20251008052346.sql | 4 +- .../migrations/20251008073620.sql | 4 +- .../migrations/20251009042854.sql | 18 +- .../migrations/20251009052657.sql | 16 +- .../migrations/20251010031743.sql | 12 +- .../migrations/20251010070721.sql | 30 +- .../migrations/20251010072711.sql | 4 +- .../migrations/20251013044536.sql | 28 +- .../migrations/20251013051438.sql | 4 +- .../migrations/20251013081808.sql | 32 +- .../migrations/20251014060047.sql | 72 +- .../migrations/20251014063537.sql | 32 +- .../migrations/20251014063720.sql | 52 +- .../migrations/20251015045455.sql | 4 +- .../migrations/20251016010845.sql | 4 +- .../migrations/20251016011023.sql | 34 +- .../migrations/20251016062912.sql | 108 +- .../migrations/20251017060617.sql | 4 +- .../migrations/20251017082207.sql | 4 +- .../migrations/20251018032635.sql | 8 +- .../migrations/20251018040322.sql | 26 +- .../migrations/20251019093915.sql | 30 +- .../migrations/20251020062553.sql | 4 +- .../migrations/20251021041042.sql | 120 +- .../migrations/20251021075552.sql | 16 +- .../migrations/20251023044432.sql | 180 +-- .../migrations/20251024034832.sql | 24 +- .../migrations/20251024074315.sql | 4 +- .../migrations/20251025013451.sql | 8 +- .../migrations/20251025013609.sql | 24 +- .../migrations/20251027075128.sql | 4 +- .../migrations/20251027091406.sql | 4 +- .../migrations/20251102002037.sql | 12 +- .../migrations/20251102091932.sql | 4 +- .../migrations/20251103081637.sql | 34 +- .../migrations/20251104042334.sql | 4 +- .../migrations/20251104043530.sql | 38 +- .../migrations/20251104080952.sql | 4 +- .../migrations/20251104084135.sql | 34 +- .../migrations/20251105044629.sql | 76 +- .../migrations/20251105121808.sql | 4 +- .../migrations/20251106035305.sql | 8 +- .../migrations/20251106040137.sql | 4 +- .../migrations/20251106041333.sql | 4 +- .../migrations/20251106042006.sql | 4 +- 80 files changed, 1785 insertions(+), 1785 deletions(-) diff --git a/cmd/main-migration/Makefile b/cmd/main-migration/Makefile index e83356e5..f445a815 100644 --- a/cmd/main-migration/Makefile +++ b/cmd/main-migration/Makefile @@ -1,18 +1,18 @@ -# Makefile for Atlas migrations - -# Default environment -ENV ?= gorm - -.PHONY: diff apply hash - -## Generate a new migration diff -diff: - atlas migrate diff --env $(ENV) - -## Apply migrations to the database -apply: - atlas migrate apply --env $(ENV) - -## Calculate the schema hash -hash: - atlas migrate hash +# Makefile for Atlas migrations + +# Default environment +ENV ?= gorm + +.PHONY: diff apply hash + +## Generate a new migration diff +diff: + atlas migrate diff --env $(ENV) + +## Apply migrations to the database +apply: + atlas migrate apply --env $(ENV) + +## Calculate the schema hash +hash: + atlas migrate hash diff --git a/cmd/main-migration/README-ATLAS.MD b/cmd/main-migration/README-ATLAS.MD index da249823..ec2869ef 100644 --- a/cmd/main-migration/README-ATLAS.MD +++ b/cmd/main-migration/README-ATLAS.MD @@ -1,59 +1,59 @@ -# Database Migration with Atlas - -This project uses [Atlas](https://atlasgo.io/) for database schema management and migrations. - -## 📋 Prerequisites - -1. **Download and Install Atlas CLI** - Run the following command in PowerShell or Git Bash: - - ```sh - curl -sSf https://atlasgo.sh | sh - ``` - Verify installation: - - ```sh - atlas version - ``` - -2. Install GORM Provider - Run inside your Go project: - - ```sh - go get -u ariga.io/atlas-provider-gorm - ``` - -3. Create atlas.hcl configuration file - Just create an atlas.hcl file in your project root as example given at atlas.hcl.example -4. Create migrations folder - ```sh - mkdir migrations - ``` -5. Usage -You can use the provided Makefile for common commands: - - Generate a migration diff - ```sh - make diff - ``` - - Apply migrations - ```sh - make apply - ``` - - Compute schema hash - ```sh - make hash - ``` - - If you don’t have make installed, you can run the Atlas commands directly: - ```sh - atlas migrate diff --env gorm - ``` - ```sh - atlas migrate apply --env gorm - ``` - ```sh - atlas migrate hash +# Database Migration with Atlas + +This project uses [Atlas](https://atlasgo.io/) for database schema management and migrations. + +## 📋 Prerequisites + +1. **Download and Install Atlas CLI** + Run the following command in PowerShell or Git Bash: + + ```sh + curl -sSf https://atlasgo.sh | sh + ``` + Verify installation: + + ```sh + atlas version + ``` + +2. Install GORM Provider + Run inside your Go project: + + ```sh + go get -u ariga.io/atlas-provider-gorm + ``` + +3. Create atlas.hcl configuration file + Just create an atlas.hcl file in your project root as example given at atlas.hcl.example +4. Create migrations folder + ```sh + mkdir migrations + ``` +5. Usage +You can use the provided Makefile for common commands: + + Generate a migration diff + ```sh + make diff + ``` + + Apply migrations + ```sh + make apply + ``` + + Compute schema hash + ```sh + make hash + ``` + + If you don’t have make installed, you can run the Atlas commands directly: + ```sh + atlas migrate diff --env gorm + ``` + ```sh + atlas migrate apply --env gorm + ``` + ```sh + atlas migrate hash ``` \ No newline at end of file diff --git a/cmd/main-migration/atlas.hcl.example b/cmd/main-migration/atlas.hcl.example index 857d1352..3d02232d 100644 --- a/cmd/main-migration/atlas.hcl.example +++ b/cmd/main-migration/atlas.hcl.example @@ -1,22 +1,22 @@ -data "external_schema" "gorm" { - program = [ - "go", - "run", - "-mod=mod", - ".", - ] -} - -env "gorm" { - src = data.external_schema.gorm.url - dev = "" // dsn db to check the diff - migration { - dir = "file://migrations" - } - url = "" // dsn db to apply - format { - migrate { - diff = "{{ sql . \" \" }}" - } - } +data "external_schema" "gorm" { + program = [ + "go", + "run", + "-mod=mod", + ".", + ] +} + +env "gorm" { + src = data.external_schema.gorm.url + dev = "" // dsn db to check the diff + migration { + dir = "file://migrations" + } + url = "" // dsn db to apply + format { + migrate { + diff = "{{ sql . \" \" }}" + } + } } \ No newline at end of file diff --git a/cmd/main-migration/migration.go b/cmd/main-migration/migration.go index dd28a55f..c0c1283c 100644 --- a/cmd/main-migration/migration.go +++ b/cmd/main-migration/migration.go @@ -1,9 +1,9 @@ -package main - -import ( - m "simrs-vx/internal/interface/migration" -) - -func main() { - m.Migrate(m.Main) -} +package main + +import ( + m "simrs-vx/internal/interface/migration" +) + +func main() { + m.Migrate(m.Main) +} diff --git a/cmd/main-migration/migrations/20250904105930.sql b/cmd/main-migration/migrations/20250904105930.sql index 39175bfb..ae541404 100644 --- a/cmd/main-migration/migrations/20250904105930.sql +++ b/cmd/main-migration/migrations/20250904105930.sql @@ -1,685 +1,685 @@ --- Create "DiagnoseSrc" table -CREATE TABLE "public"."DiagnoseSrc" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(10) NULL, - "Name" character varying(2048) NULL, - "IndName" character varying(2048) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_DiagnoseSrc_Code" UNIQUE ("Code") -); --- Create "PharmacyCompany" table -CREATE TABLE "public"."PharmacyCompany" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(20) NULL, - "Name" character varying(100) NULL, - "Regency_Code" character varying(4) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_PharmacyCompany_Code" UNIQUE ("Code") -); --- Create "Uom" table -CREATE TABLE "public"."Uom" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(10) NULL, - "Name" character varying(50) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Uom_Code" UNIQUE ("Code") -); --- Create "Counter" table -CREATE TABLE "public"."Counter" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(10) NULL, - "Name" character varying(30) NULL, - "Number" smallint NULL, - "Parent_Id" integer NULL, - "Type_Code" text NULL, - "Queue_Code" character varying(5) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Counter_Code" UNIQUE ("Code") -); --- Create "Item" table -CREATE TABLE "public"."Item" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(50) NULL, - "Name" character varying(100) NULL, - "ItemGroup_Code" character varying(10) NULL, - "Uom_Code" character varying(10) NULL, - "Infra_Id" integer NULL, - "Stock" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Item_Code" UNIQUE ("Code"), - CONSTRAINT "fk_Item_Uom" FOREIGN KEY ("Uom_Code") REFERENCES "public"."Uom" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Infra" table -CREATE TABLE "public"."Infra" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(10) NULL, - "Name" character varying(50) NULL, - "InfraGroup_Code" character varying(10) NULL, - "Parent_Id" integer NULL, - "Item_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Infra_Code" UNIQUE ("Code"), - CONSTRAINT "fk_Infra_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Device" table -CREATE TABLE "public"."Device" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(10) NULL, - "Name" character varying(50) NOT NULL, - "Uom_Code" character varying(10) NULL, - "Infra_Id" integer NULL, - "Item_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Device_Code" UNIQUE ("Code"), - CONSTRAINT "fk_Device_Infra" FOREIGN KEY ("Infra_Id") REFERENCES "public"."Infra" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Device_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Device_Uom" FOREIGN KEY ("Uom_Code") REFERENCES "public"."Uom" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Province" table -CREATE TABLE "public"."Province" ( - "Id" smallserial NOT NULL, - "Code" character varying(2) NULL, - "Name" character varying(50) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Province_Code" UNIQUE ("Code") -); --- Create "Regency" table -CREATE TABLE "public"."Regency" ( - "Id" serial NOT NULL, - "Province_Code" character varying(2) NULL, - "Code" character varying(4) NULL, - "Name" character varying(50) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Regency_Code" UNIQUE ("Code"), - CONSTRAINT "fk_Province_Regencies" FOREIGN KEY ("Province_Code") REFERENCES "public"."Province" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "District" table -CREATE TABLE "public"."District" ( - "Id" bigserial NOT NULL, - "Regency_Code" character varying(4) NULL, - "Code" character varying(6) NULL, - "Name" character varying(50) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_District_Code" UNIQUE ("Code"), - CONSTRAINT "fk_Regency_Districts" FOREIGN KEY ("Regency_Code") REFERENCES "public"."Regency" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Division" table -CREATE TABLE "public"."Division" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(10) NULL, - "Name" character varying(50) NULL, - "Parent_Id" smallint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Division_Code" UNIQUE ("Code") -); --- Create "DivisionPosition" table -CREATE TABLE "public"."DivisionPosition" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Division_Id" integer NULL, - "Code" character varying(10) NULL, - "Name" character varying(50) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_DivisionPosition_Code" UNIQUE ("Code"), - CONSTRAINT "fk_DivisionPosition_Division" FOREIGN KEY ("Division_Id") REFERENCES "public"."Division" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Ethnic" table -CREATE TABLE "public"."Ethnic" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(20) NULL, - "Name" character varying(50) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Ethnic_Code" UNIQUE ("Code") -); --- Create "Language" table -CREATE TABLE "public"."Language" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(10) NULL, - "Name" character varying(50) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Language_Code" UNIQUE ("Code") -); --- Create "Person" table -CREATE TABLE "public"."Person" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Name" character varying(150) NOT NULL, - "FrontTitle" character varying(50) NULL, - "EndTitle" character varying(50) NULL, - "BirthDate" timestamptz NULL, - "BirthRegency_Code" character varying(4) NULL, - "Gender_Code" character varying(10) NULL, - "ResidentIdentityNumber" character varying(16) NULL, - "PassportNumber" character varying(20) NULL, - "DrivingLicenseNumber" character varying(20) NULL, - "Religion_Code" character varying(10) NULL, - "Education_Code" character varying(10) NULL, - "Ocupation_Code" character varying(15) NULL, - "Ocupation_Name" character varying(50) NULL, - "Ethnic_Code" character varying(20) NULL, - "Language_Code" character varying(10) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Person_DrivingLicenseNumber" UNIQUE ("DrivingLicenseNumber"), - CONSTRAINT "uni_Person_PassportNumber" UNIQUE ("PassportNumber"), - CONSTRAINT "uni_Person_ResidentIdentityNumber" UNIQUE ("ResidentIdentityNumber"), - CONSTRAINT "fk_Person_Ethnic" FOREIGN KEY ("Ethnic_Code") REFERENCES "public"."Ethnic" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Person_Language" FOREIGN KEY ("Language_Code") REFERENCES "public"."Language" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "User" table -CREATE TABLE "public"."User" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Name" character varying(25) NOT NULL, - "Password" character varying(255) NOT NULL, - "Status_Code" character varying(10) NOT NULL, - "FailedLoginCount" smallint NULL, - "Position_Code" character varying(20) NOT NULL, - "LoginAttemptCount" bigint NULL, - "LastSuccessLogin" timestamptz NULL, - "LastAllowdLogin" timestamptz NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_User_Name" UNIQUE ("Name") -); --- Create "Employee" table -CREATE TABLE "public"."Employee" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "User_Id" bigint NULL, - "Person_Id" bigint NULL, - "Division_Code" character varying(10) NULL, - "Number" character varying(20) NULL, - "Status_Code" character varying(10) NOT NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Employee_Division" FOREIGN KEY ("Division_Code") REFERENCES "public"."Division" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Employee_Person" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Employee_User" FOREIGN KEY ("User_Id") REFERENCES "public"."User" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Installation" table -CREATE TABLE "public"."Installation" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(10) NULL, - "Name" character varying(50) NULL, - "EncounterClass_Code" character varying(10) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Installation_Code" UNIQUE ("Code") -); --- Create "Unit" table -CREATE TABLE "public"."Unit" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Installation_Id" integer NULL, - "Code" character varying(10) NULL, - "Name" character varying(50) NULL, - "Type_Code" text NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Unit_Code" UNIQUE ("Code"), - CONSTRAINT "fk_Unit_Installation" FOREIGN KEY ("Installation_Id") REFERENCES "public"."Installation" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Specialist" table -CREATE TABLE "public"."Specialist" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(10) NULL, - "Name" character varying(50) NULL, - "Unit_Id" integer NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Specialist_Code" UNIQUE ("Code"), - CONSTRAINT "fk_Specialist_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Subspecialist" table -CREATE TABLE "public"."Subspecialist" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(10) NULL, - "Name" character varying(50) NULL, - "Specialist_Id" integer NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Subspecialist_Code" UNIQUE ("Code"), - CONSTRAINT "fk_Subspecialist_Specialist" FOREIGN KEY ("Specialist_Id") REFERENCES "public"."Specialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Doctor" table -CREATE TABLE "public"."Doctor" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Employee_Id" bigint NULL, - "IHS_Number" character varying(20) NULL, - "SIP_Number" character varying(20) NULL, - "Unit_Id" integer NULL, - "Specialist_Id" integer NULL, - "Subspecialist_Id" integer NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Doctor_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Doctor_Specialist" FOREIGN KEY ("Specialist_Id") REFERENCES "public"."Specialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Doctor_Subspecialist" FOREIGN KEY ("Subspecialist_Id") REFERENCES "public"."Subspecialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Doctor_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "DoctorFee" table -CREATE TABLE "public"."DoctorFee" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Doctor_Id" bigint NULL, - "FeeType_Code" character varying(11) NULL, - "Price" numeric NULL, - "Item_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_DoctorFee_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_DoctorFee_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Patient" table -CREATE TABLE "public"."Patient" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Person_Id" bigint NULL, - "RegisteredAt" timestamptz NULL, - "Status_Code" character varying(10) NOT NULL, - "Number" character varying(15) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Patient_Number" UNIQUE ("Number"), - CONSTRAINT "fk_Patient_Person" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Encounter" table -CREATE TABLE "public"."Encounter" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Patient_Id" bigint NULL, - "RegisteredAt" timestamptz NULL, - "Class_Code" character varying(10) NOT NULL, - "Unit_Id" bigint NULL, - "Specialist_Id" integer NULL, - "Subspecialist_Id" integer NULL, - "VisitDate" timestamptz NULL, - "Assignment_Doctor_Id" bigint NULL, - "Responsible_Doctor_Id" bigint NULL, - "DischardeMethod_Code" character varying(10) NULL, - "RefSource_Name" character varying(100) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Encounter_Assignment_Doctor" FOREIGN KEY ("Assignment_Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Encounter_Patient" FOREIGN KEY ("Patient_Id") REFERENCES "public"."Patient" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Encounter_Responsible_Doctor" FOREIGN KEY ("Responsible_Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Encounter_Specialist" FOREIGN KEY ("Specialist_Id") REFERENCES "public"."Specialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Encounter_Subspecialist" FOREIGN KEY ("Subspecialist_Id") REFERENCES "public"."Subspecialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Encounter_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "InsuranceCompany" table -CREATE TABLE "public"."InsuranceCompany" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(20) NULL, - "Name" character varying(50) NULL, - "Regency_Code" character varying(4) NULL, - "Address" character varying(100) NULL, - "PhoneNumber" character varying(20) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_InsuranceCompany_Code" UNIQUE ("Code"), - CONSTRAINT "fk_InsuranceCompany_Regency" FOREIGN KEY ("Regency_Code") REFERENCES "public"."Regency" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "ItemPrice" table -CREATE TABLE "public"."ItemPrice" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Item_Id" bigint NULL, - "Price" numeric NULL, - "InsuranceCompany_Code" character varying(20) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_ItemPrice_InsuranceCompany" FOREIGN KEY ("InsuranceCompany_Code") REFERENCES "public"."InsuranceCompany" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_ItemPrice_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Laborant" table -CREATE TABLE "public"."Laborant" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Employee_Id" bigint NULL, - "IHS_Number" character varying(20) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Laborant_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Material" table -CREATE TABLE "public"."Material" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(10) NULL, - "Name" character varying(50) NULL, - "Uom_Code" character varying(10) NULL, - "Infra_Id" integer NULL, - "Stock" bigint NULL, - "Item_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Material_Code" UNIQUE ("Code"), - CONSTRAINT "fk_Material_Infra" FOREIGN KEY ("Infra_Id") REFERENCES "public"."Infra" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Material_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Material_Uom" FOREIGN KEY ("Uom_Code") REFERENCES "public"."Uom" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "McuSrcCategory" table -CREATE TABLE "public"."McuSrcCategory" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(20) NULL, - "Name" character varying(50) NULL, - "Scope_Code" character varying(10) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_McuSrcCategory_Code" UNIQUE ("Code") -); --- Create "McuSrc" table -CREATE TABLE "public"."McuSrc" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(20) NULL, - "Name" character varying(50) NULL, - "CheckupCategory_Code" character varying(20) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_McuSrc_Code" UNIQUE ("Code"), - CONSTRAINT "fk_McuSrc_CheckupCategory" FOREIGN KEY ("CheckupCategory_Code") REFERENCES "public"."McuSrcCategory" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "MedicalActionSrc" table -CREATE TABLE "public"."MedicalActionSrc" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(20) NULL, - "Name" character varying(50) NULL, - "Item_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_MedicalActionSrc_Code" UNIQUE ("Code"), - CONSTRAINT "fk_MedicalActionSrc_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "ProcedureSrc" table -CREATE TABLE "public"."ProcedureSrc" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(10) NULL, - "Name" character varying(2048) NULL, - "IndName" character varying(2048) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_ProcedureSrc_Code" UNIQUE ("Code") -); --- Create "MedicalActionSrcItem" table -CREATE TABLE "public"."MedicalActionSrcItem" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "MedicalActionSrc_Id" bigint NULL, - "ProcedureSrc_Id" bigint NULL, - "Item_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_MedicalActionSrcItem_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_MedicalActionSrcItem_MedicalActionSrc" FOREIGN KEY ("MedicalActionSrc_Id") REFERENCES "public"."MedicalActionSrc" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_MedicalActionSrcItem_ProcedureSrc" FOREIGN KEY ("ProcedureSrc_Id") REFERENCES "public"."ProcedureSrc" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "MedicineGroup" table -CREATE TABLE "public"."MedicineGroup" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(10) NULL, - "Name" character varying(50) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_MedicineGroup_Code" UNIQUE ("Code") -); --- Create "MedicineMethod" table -CREATE TABLE "public"."MedicineMethod" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(10) NULL, - "Name" character varying(50) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_MedicineMethod_Code" UNIQUE ("Code") -); --- Create "Medicine" table -CREATE TABLE "public"."Medicine" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(10) NULL, - "Name" character varying(50) NULL, - "MedicineGroup_Code" character varying(10) NULL, - "MedicineMethod_Code" character varying(10) NULL, - "Uom_Code" character varying(10) NULL, - "Dose" smallint NULL, - "Infra_Id" integer NULL, - "Stock" bigint NULL, - "Item_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Medicine_Code" UNIQUE ("Code"), - CONSTRAINT "fk_Medicine_Infra" FOREIGN KEY ("Infra_Id") REFERENCES "public"."Infra" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Medicine_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Medicine_MedicineGroup" FOREIGN KEY ("MedicineGroup_Code") REFERENCES "public"."MedicineGroup" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Medicine_MedicineMethod" FOREIGN KEY ("MedicineMethod_Code") REFERENCES "public"."MedicineMethod" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Medicine_Uom" FOREIGN KEY ("Uom_Code") REFERENCES "public"."Uom" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "MedicineMix" table -CREATE TABLE "public"."MedicineMix" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Name" character varying(50) NULL, - PRIMARY KEY ("Id") -); --- Create "MedicineMixItem" table -CREATE TABLE "public"."MedicineMixItem" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "MedicineMix_Id" bigint NULL, - "Medicine_Id" bigint NULL, - "Dose" smallint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_MedicineMixItem_Medicine" FOREIGN KEY ("Medicine_Id") REFERENCES "public"."Medicine" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_MedicineMixItem_MedicineMix" FOREIGN KEY ("MedicineMix_Id") REFERENCES "public"."MedicineMix" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Nurse" table -CREATE TABLE "public"."Nurse" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Employee_Id" bigint NULL, - "IHS_Number" character varying(20) NULL, - "Unit_Id" integer NULL, - "Infra_Id" integer NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Nurse_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Nurse_Infra" FOREIGN KEY ("Infra_Id") REFERENCES "public"."Infra" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Nurse_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Nutritionist" table -CREATE TABLE "public"."Nutritionist" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Employee_Id" bigint NULL, - "IHS_Number" character varying(20) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Nutritionist_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "PersonAddress" table -CREATE TABLE "public"."PersonAddress" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Person_Id" bigint NULL, - "Address" character varying(150) NULL, - "Rt" character varying(2) NULL, - "Rw" character varying(2) NULL, - "Village_Code" character varying(10) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Person_Addresses" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "PersonContact" table -CREATE TABLE "public"."PersonContact" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Person_Id" bigint NULL, - "Type_Code" character varying(15) NULL, - "Value" character varying(100) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Person_Contacts" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Village" table -CREATE TABLE "public"."Village" ( - "Id" bigserial NOT NULL, - "District_Code" character varying(6) NULL, - "Code" character varying(10) NULL, - "Name" character varying(50) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Village_Code" UNIQUE ("Code"), - CONSTRAINT "fk_District_Villages" FOREIGN KEY ("District_Code") REFERENCES "public"."District" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "PersonRelative" table -CREATE TABLE "public"."PersonRelative" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Person_Id" bigint NULL, - "Relationship_Code" character varying(100) NOT NULL, - "Name" character varying(100) NULL, - "Address" character varying(100) NULL, - "Village_Code" character varying(10) NULL, - "Gender_Code" character varying(10) NULL, - "PhoneNumber" character varying(30) NULL, - "Education_Code" character varying(10) NULL, - "Occupation_Code" character varying(10) NULL, - "Occupation_Name" character varying(50) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_PersonRelative_Village" FOREIGN KEY ("Village_Code") REFERENCES "public"."Village" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Person_Relatives" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Pharmacist" table -CREATE TABLE "public"."Pharmacist" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Employee_Id" bigint NULL, - "IHS_Number" character varying(20) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Pharmacist_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "PracticeSchedule" table -CREATE TABLE "public"."PracticeSchedule" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Doctor_Id" bigint NULL, - "Unit_Code" character varying(10) NULL, - "Day_Code" smallint NULL, - "StartTime" character varying(5) NULL, - "EndTime" character varying(5) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_PracticeSchedule_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_PracticeSchedule_Unit" FOREIGN KEY ("Unit_Code") REFERENCES "public"."Unit" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Room" table -CREATE TABLE "public"."Room" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Infra_Id" integer NULL, - "Unit_Id" integer NULL, - "Specialist_Id" integer NULL, - "Subspecialist_Id" integer NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Room_Infra" FOREIGN KEY ("Infra_Id") REFERENCES "public"."Infra" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Room_Specialist" FOREIGN KEY ("Specialist_Id") REFERENCES "public"."Specialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Room_Subspecialist" FOREIGN KEY ("Subspecialist_Id") REFERENCES "public"."Subspecialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Room_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "SpecialistIntern" table -CREATE TABLE "public"."SpecialistIntern" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Person_Id" bigint NULL, - "Specialist_Id" integer NULL, - "Subspecialist_Id" integer NULL, - "User_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_SpecialistIntern_Person" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_SpecialistIntern_Specialist" FOREIGN KEY ("Specialist_Id") REFERENCES "public"."Specialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_SpecialistIntern_Subspecialist" FOREIGN KEY ("Subspecialist_Id") REFERENCES "public"."Subspecialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_SpecialistIntern_User" FOREIGN KEY ("User_Id") REFERENCES "public"."User" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); +-- Create "DiagnoseSrc" table +CREATE TABLE "public"."DiagnoseSrc" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(10) NULL, + "Name" character varying(2048) NULL, + "IndName" character varying(2048) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_DiagnoseSrc_Code" UNIQUE ("Code") +); +-- Create "PharmacyCompany" table +CREATE TABLE "public"."PharmacyCompany" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(20) NULL, + "Name" character varying(100) NULL, + "Regency_Code" character varying(4) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_PharmacyCompany_Code" UNIQUE ("Code") +); +-- Create "Uom" table +CREATE TABLE "public"."Uom" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(10) NULL, + "Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Uom_Code" UNIQUE ("Code") +); +-- Create "Counter" table +CREATE TABLE "public"."Counter" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(10) NULL, + "Name" character varying(30) NULL, + "Number" smallint NULL, + "Parent_Id" integer NULL, + "Type_Code" text NULL, + "Queue_Code" character varying(5) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Counter_Code" UNIQUE ("Code") +); +-- Create "Item" table +CREATE TABLE "public"."Item" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(50) NULL, + "Name" character varying(100) NULL, + "ItemGroup_Code" character varying(10) NULL, + "Uom_Code" character varying(10) NULL, + "Infra_Id" integer NULL, + "Stock" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Item_Code" UNIQUE ("Code"), + CONSTRAINT "fk_Item_Uom" FOREIGN KEY ("Uom_Code") REFERENCES "public"."Uom" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Infra" table +CREATE TABLE "public"."Infra" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(10) NULL, + "Name" character varying(50) NULL, + "InfraGroup_Code" character varying(10) NULL, + "Parent_Id" integer NULL, + "Item_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Infra_Code" UNIQUE ("Code"), + CONSTRAINT "fk_Infra_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Device" table +CREATE TABLE "public"."Device" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(10) NULL, + "Name" character varying(50) NOT NULL, + "Uom_Code" character varying(10) NULL, + "Infra_Id" integer NULL, + "Item_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Device_Code" UNIQUE ("Code"), + CONSTRAINT "fk_Device_Infra" FOREIGN KEY ("Infra_Id") REFERENCES "public"."Infra" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Device_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Device_Uom" FOREIGN KEY ("Uom_Code") REFERENCES "public"."Uom" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Province" table +CREATE TABLE "public"."Province" ( + "Id" smallserial NOT NULL, + "Code" character varying(2) NULL, + "Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Province_Code" UNIQUE ("Code") +); +-- Create "Regency" table +CREATE TABLE "public"."Regency" ( + "Id" serial NOT NULL, + "Province_Code" character varying(2) NULL, + "Code" character varying(4) NULL, + "Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Regency_Code" UNIQUE ("Code"), + CONSTRAINT "fk_Province_Regencies" FOREIGN KEY ("Province_Code") REFERENCES "public"."Province" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "District" table +CREATE TABLE "public"."District" ( + "Id" bigserial NOT NULL, + "Regency_Code" character varying(4) NULL, + "Code" character varying(6) NULL, + "Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_District_Code" UNIQUE ("Code"), + CONSTRAINT "fk_Regency_Districts" FOREIGN KEY ("Regency_Code") REFERENCES "public"."Regency" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Division" table +CREATE TABLE "public"."Division" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(10) NULL, + "Name" character varying(50) NULL, + "Parent_Id" smallint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Division_Code" UNIQUE ("Code") +); +-- Create "DivisionPosition" table +CREATE TABLE "public"."DivisionPosition" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Division_Id" integer NULL, + "Code" character varying(10) NULL, + "Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_DivisionPosition_Code" UNIQUE ("Code"), + CONSTRAINT "fk_DivisionPosition_Division" FOREIGN KEY ("Division_Id") REFERENCES "public"."Division" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Ethnic" table +CREATE TABLE "public"."Ethnic" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(20) NULL, + "Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Ethnic_Code" UNIQUE ("Code") +); +-- Create "Language" table +CREATE TABLE "public"."Language" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(10) NULL, + "Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Language_Code" UNIQUE ("Code") +); +-- Create "Person" table +CREATE TABLE "public"."Person" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Name" character varying(150) NOT NULL, + "FrontTitle" character varying(50) NULL, + "EndTitle" character varying(50) NULL, + "BirthDate" timestamptz NULL, + "BirthRegency_Code" character varying(4) NULL, + "Gender_Code" character varying(10) NULL, + "ResidentIdentityNumber" character varying(16) NULL, + "PassportNumber" character varying(20) NULL, + "DrivingLicenseNumber" character varying(20) NULL, + "Religion_Code" character varying(10) NULL, + "Education_Code" character varying(10) NULL, + "Ocupation_Code" character varying(15) NULL, + "Ocupation_Name" character varying(50) NULL, + "Ethnic_Code" character varying(20) NULL, + "Language_Code" character varying(10) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Person_DrivingLicenseNumber" UNIQUE ("DrivingLicenseNumber"), + CONSTRAINT "uni_Person_PassportNumber" UNIQUE ("PassportNumber"), + CONSTRAINT "uni_Person_ResidentIdentityNumber" UNIQUE ("ResidentIdentityNumber"), + CONSTRAINT "fk_Person_Ethnic" FOREIGN KEY ("Ethnic_Code") REFERENCES "public"."Ethnic" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Person_Language" FOREIGN KEY ("Language_Code") REFERENCES "public"."Language" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "User" table +CREATE TABLE "public"."User" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Name" character varying(25) NOT NULL, + "Password" character varying(255) NOT NULL, + "Status_Code" character varying(10) NOT NULL, + "FailedLoginCount" smallint NULL, + "Position_Code" character varying(20) NOT NULL, + "LoginAttemptCount" bigint NULL, + "LastSuccessLogin" timestamptz NULL, + "LastAllowdLogin" timestamptz NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_User_Name" UNIQUE ("Name") +); +-- Create "Employee" table +CREATE TABLE "public"."Employee" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "User_Id" bigint NULL, + "Person_Id" bigint NULL, + "Division_Code" character varying(10) NULL, + "Number" character varying(20) NULL, + "Status_Code" character varying(10) NOT NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Employee_Division" FOREIGN KEY ("Division_Code") REFERENCES "public"."Division" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Employee_Person" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Employee_User" FOREIGN KEY ("User_Id") REFERENCES "public"."User" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Installation" table +CREATE TABLE "public"."Installation" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(10) NULL, + "Name" character varying(50) NULL, + "EncounterClass_Code" character varying(10) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Installation_Code" UNIQUE ("Code") +); +-- Create "Unit" table +CREATE TABLE "public"."Unit" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Installation_Id" integer NULL, + "Code" character varying(10) NULL, + "Name" character varying(50) NULL, + "Type_Code" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Unit_Code" UNIQUE ("Code"), + CONSTRAINT "fk_Unit_Installation" FOREIGN KEY ("Installation_Id") REFERENCES "public"."Installation" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Specialist" table +CREATE TABLE "public"."Specialist" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(10) NULL, + "Name" character varying(50) NULL, + "Unit_Id" integer NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Specialist_Code" UNIQUE ("Code"), + CONSTRAINT "fk_Specialist_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Subspecialist" table +CREATE TABLE "public"."Subspecialist" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(10) NULL, + "Name" character varying(50) NULL, + "Specialist_Id" integer NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Subspecialist_Code" UNIQUE ("Code"), + CONSTRAINT "fk_Subspecialist_Specialist" FOREIGN KEY ("Specialist_Id") REFERENCES "public"."Specialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Doctor" table +CREATE TABLE "public"."Doctor" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Employee_Id" bigint NULL, + "IHS_Number" character varying(20) NULL, + "SIP_Number" character varying(20) NULL, + "Unit_Id" integer NULL, + "Specialist_Id" integer NULL, + "Subspecialist_Id" integer NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Doctor_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Doctor_Specialist" FOREIGN KEY ("Specialist_Id") REFERENCES "public"."Specialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Doctor_Subspecialist" FOREIGN KEY ("Subspecialist_Id") REFERENCES "public"."Subspecialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Doctor_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "DoctorFee" table +CREATE TABLE "public"."DoctorFee" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Doctor_Id" bigint NULL, + "FeeType_Code" character varying(11) NULL, + "Price" numeric NULL, + "Item_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_DoctorFee_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_DoctorFee_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Patient" table +CREATE TABLE "public"."Patient" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Person_Id" bigint NULL, + "RegisteredAt" timestamptz NULL, + "Status_Code" character varying(10) NOT NULL, + "Number" character varying(15) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Patient_Number" UNIQUE ("Number"), + CONSTRAINT "fk_Patient_Person" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Encounter" table +CREATE TABLE "public"."Encounter" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Patient_Id" bigint NULL, + "RegisteredAt" timestamptz NULL, + "Class_Code" character varying(10) NOT NULL, + "Unit_Id" bigint NULL, + "Specialist_Id" integer NULL, + "Subspecialist_Id" integer NULL, + "VisitDate" timestamptz NULL, + "Assignment_Doctor_Id" bigint NULL, + "Responsible_Doctor_Id" bigint NULL, + "DischardeMethod_Code" character varying(10) NULL, + "RefSource_Name" character varying(100) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Encounter_Assignment_Doctor" FOREIGN KEY ("Assignment_Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Encounter_Patient" FOREIGN KEY ("Patient_Id") REFERENCES "public"."Patient" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Encounter_Responsible_Doctor" FOREIGN KEY ("Responsible_Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Encounter_Specialist" FOREIGN KEY ("Specialist_Id") REFERENCES "public"."Specialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Encounter_Subspecialist" FOREIGN KEY ("Subspecialist_Id") REFERENCES "public"."Subspecialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Encounter_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "InsuranceCompany" table +CREATE TABLE "public"."InsuranceCompany" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(20) NULL, + "Name" character varying(50) NULL, + "Regency_Code" character varying(4) NULL, + "Address" character varying(100) NULL, + "PhoneNumber" character varying(20) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_InsuranceCompany_Code" UNIQUE ("Code"), + CONSTRAINT "fk_InsuranceCompany_Regency" FOREIGN KEY ("Regency_Code") REFERENCES "public"."Regency" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "ItemPrice" table +CREATE TABLE "public"."ItemPrice" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Item_Id" bigint NULL, + "Price" numeric NULL, + "InsuranceCompany_Code" character varying(20) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_ItemPrice_InsuranceCompany" FOREIGN KEY ("InsuranceCompany_Code") REFERENCES "public"."InsuranceCompany" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_ItemPrice_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Laborant" table +CREATE TABLE "public"."Laborant" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Employee_Id" bigint NULL, + "IHS_Number" character varying(20) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Laborant_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Material" table +CREATE TABLE "public"."Material" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(10) NULL, + "Name" character varying(50) NULL, + "Uom_Code" character varying(10) NULL, + "Infra_Id" integer NULL, + "Stock" bigint NULL, + "Item_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Material_Code" UNIQUE ("Code"), + CONSTRAINT "fk_Material_Infra" FOREIGN KEY ("Infra_Id") REFERENCES "public"."Infra" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Material_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Material_Uom" FOREIGN KEY ("Uom_Code") REFERENCES "public"."Uom" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "McuSrcCategory" table +CREATE TABLE "public"."McuSrcCategory" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(20) NULL, + "Name" character varying(50) NULL, + "Scope_Code" character varying(10) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_McuSrcCategory_Code" UNIQUE ("Code") +); +-- Create "McuSrc" table +CREATE TABLE "public"."McuSrc" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(20) NULL, + "Name" character varying(50) NULL, + "CheckupCategory_Code" character varying(20) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_McuSrc_Code" UNIQUE ("Code"), + CONSTRAINT "fk_McuSrc_CheckupCategory" FOREIGN KEY ("CheckupCategory_Code") REFERENCES "public"."McuSrcCategory" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "MedicalActionSrc" table +CREATE TABLE "public"."MedicalActionSrc" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(20) NULL, + "Name" character varying(50) NULL, + "Item_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_MedicalActionSrc_Code" UNIQUE ("Code"), + CONSTRAINT "fk_MedicalActionSrc_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "ProcedureSrc" table +CREATE TABLE "public"."ProcedureSrc" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(10) NULL, + "Name" character varying(2048) NULL, + "IndName" character varying(2048) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_ProcedureSrc_Code" UNIQUE ("Code") +); +-- Create "MedicalActionSrcItem" table +CREATE TABLE "public"."MedicalActionSrcItem" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "MedicalActionSrc_Id" bigint NULL, + "ProcedureSrc_Id" bigint NULL, + "Item_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_MedicalActionSrcItem_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_MedicalActionSrcItem_MedicalActionSrc" FOREIGN KEY ("MedicalActionSrc_Id") REFERENCES "public"."MedicalActionSrc" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_MedicalActionSrcItem_ProcedureSrc" FOREIGN KEY ("ProcedureSrc_Id") REFERENCES "public"."ProcedureSrc" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "MedicineGroup" table +CREATE TABLE "public"."MedicineGroup" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(10) NULL, + "Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_MedicineGroup_Code" UNIQUE ("Code") +); +-- Create "MedicineMethod" table +CREATE TABLE "public"."MedicineMethod" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(10) NULL, + "Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_MedicineMethod_Code" UNIQUE ("Code") +); +-- Create "Medicine" table +CREATE TABLE "public"."Medicine" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(10) NULL, + "Name" character varying(50) NULL, + "MedicineGroup_Code" character varying(10) NULL, + "MedicineMethod_Code" character varying(10) NULL, + "Uom_Code" character varying(10) NULL, + "Dose" smallint NULL, + "Infra_Id" integer NULL, + "Stock" bigint NULL, + "Item_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Medicine_Code" UNIQUE ("Code"), + CONSTRAINT "fk_Medicine_Infra" FOREIGN KEY ("Infra_Id") REFERENCES "public"."Infra" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Medicine_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Medicine_MedicineGroup" FOREIGN KEY ("MedicineGroup_Code") REFERENCES "public"."MedicineGroup" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Medicine_MedicineMethod" FOREIGN KEY ("MedicineMethod_Code") REFERENCES "public"."MedicineMethod" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Medicine_Uom" FOREIGN KEY ("Uom_Code") REFERENCES "public"."Uom" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "MedicineMix" table +CREATE TABLE "public"."MedicineMix" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Name" character varying(50) NULL, + PRIMARY KEY ("Id") +); +-- Create "MedicineMixItem" table +CREATE TABLE "public"."MedicineMixItem" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "MedicineMix_Id" bigint NULL, + "Medicine_Id" bigint NULL, + "Dose" smallint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_MedicineMixItem_Medicine" FOREIGN KEY ("Medicine_Id") REFERENCES "public"."Medicine" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_MedicineMixItem_MedicineMix" FOREIGN KEY ("MedicineMix_Id") REFERENCES "public"."MedicineMix" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Nurse" table +CREATE TABLE "public"."Nurse" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Employee_Id" bigint NULL, + "IHS_Number" character varying(20) NULL, + "Unit_Id" integer NULL, + "Infra_Id" integer NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Nurse_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Nurse_Infra" FOREIGN KEY ("Infra_Id") REFERENCES "public"."Infra" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Nurse_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Nutritionist" table +CREATE TABLE "public"."Nutritionist" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Employee_Id" bigint NULL, + "IHS_Number" character varying(20) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Nutritionist_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "PersonAddress" table +CREATE TABLE "public"."PersonAddress" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Person_Id" bigint NULL, + "Address" character varying(150) NULL, + "Rt" character varying(2) NULL, + "Rw" character varying(2) NULL, + "Village_Code" character varying(10) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Person_Addresses" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "PersonContact" table +CREATE TABLE "public"."PersonContact" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Person_Id" bigint NULL, + "Type_Code" character varying(15) NULL, + "Value" character varying(100) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Person_Contacts" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Village" table +CREATE TABLE "public"."Village" ( + "Id" bigserial NOT NULL, + "District_Code" character varying(6) NULL, + "Code" character varying(10) NULL, + "Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Village_Code" UNIQUE ("Code"), + CONSTRAINT "fk_District_Villages" FOREIGN KEY ("District_Code") REFERENCES "public"."District" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "PersonRelative" table +CREATE TABLE "public"."PersonRelative" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Person_Id" bigint NULL, + "Relationship_Code" character varying(100) NOT NULL, + "Name" character varying(100) NULL, + "Address" character varying(100) NULL, + "Village_Code" character varying(10) NULL, + "Gender_Code" character varying(10) NULL, + "PhoneNumber" character varying(30) NULL, + "Education_Code" character varying(10) NULL, + "Occupation_Code" character varying(10) NULL, + "Occupation_Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_PersonRelative_Village" FOREIGN KEY ("Village_Code") REFERENCES "public"."Village" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Person_Relatives" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Pharmacist" table +CREATE TABLE "public"."Pharmacist" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Employee_Id" bigint NULL, + "IHS_Number" character varying(20) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Pharmacist_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "PracticeSchedule" table +CREATE TABLE "public"."PracticeSchedule" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Doctor_Id" bigint NULL, + "Unit_Code" character varying(10) NULL, + "Day_Code" smallint NULL, + "StartTime" character varying(5) NULL, + "EndTime" character varying(5) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_PracticeSchedule_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_PracticeSchedule_Unit" FOREIGN KEY ("Unit_Code") REFERENCES "public"."Unit" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Room" table +CREATE TABLE "public"."Room" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Infra_Id" integer NULL, + "Unit_Id" integer NULL, + "Specialist_Id" integer NULL, + "Subspecialist_Id" integer NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Room_Infra" FOREIGN KEY ("Infra_Id") REFERENCES "public"."Infra" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Room_Specialist" FOREIGN KEY ("Specialist_Id") REFERENCES "public"."Specialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Room_Subspecialist" FOREIGN KEY ("Subspecialist_Id") REFERENCES "public"."Subspecialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Room_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "SpecialistIntern" table +CREATE TABLE "public"."SpecialistIntern" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Person_Id" bigint NULL, + "Specialist_Id" integer NULL, + "Subspecialist_Id" integer NULL, + "User_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_SpecialistIntern_Person" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_SpecialistIntern_Specialist" FOREIGN KEY ("Specialist_Id") REFERENCES "public"."Specialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_SpecialistIntern_Subspecialist" FOREIGN KEY ("Subspecialist_Id") REFERENCES "public"."Subspecialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_SpecialistIntern_User" FOREIGN KEY ("User_Id") REFERENCES "public"."User" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20250904141448.sql b/cmd/main-migration/migrations/20250904141448.sql index 56a113ca..b2f69b7c 100644 --- a/cmd/main-migration/migrations/20250904141448.sql +++ b/cmd/main-migration/migrations/20250904141448.sql @@ -1,10 +1,10 @@ --- Modify "Doctor" table -ALTER TABLE "public"."Doctor" ADD CONSTRAINT "uni_Doctor_IHS_Number" UNIQUE ("IHS_Number"), ADD CONSTRAINT "uni_Doctor_SIP_Number" UNIQUE ("SIP_Number"); --- Modify "Laborant" table -ALTER TABLE "public"."Laborant" ADD CONSTRAINT "uni_Laborant_IHS_Number" UNIQUE ("IHS_Number"); --- Modify "Nurse" table -ALTER TABLE "public"."Nurse" ADD CONSTRAINT "uni_Nurse_IHS_Number" UNIQUE ("IHS_Number"); --- Modify "Nutritionist" table -ALTER TABLE "public"."Nutritionist" ADD CONSTRAINT "uni_Nutritionist_IHS_Number" UNIQUE ("IHS_Number"); --- Modify "Pharmacist" table -ALTER TABLE "public"."Pharmacist" ADD CONSTRAINT "uni_Pharmacist_IHS_Number" UNIQUE ("IHS_Number"); +-- Modify "Doctor" table +ALTER TABLE "public"."Doctor" ADD CONSTRAINT "uni_Doctor_IHS_Number" UNIQUE ("IHS_Number"), ADD CONSTRAINT "uni_Doctor_SIP_Number" UNIQUE ("SIP_Number"); +-- Modify "Laborant" table +ALTER TABLE "public"."Laborant" ADD CONSTRAINT "uni_Laborant_IHS_Number" UNIQUE ("IHS_Number"); +-- Modify "Nurse" table +ALTER TABLE "public"."Nurse" ADD CONSTRAINT "uni_Nurse_IHS_Number" UNIQUE ("IHS_Number"); +-- Modify "Nutritionist" table +ALTER TABLE "public"."Nutritionist" ADD CONSTRAINT "uni_Nutritionist_IHS_Number" UNIQUE ("IHS_Number"); +-- Modify "Pharmacist" table +ALTER TABLE "public"."Pharmacist" ADD CONSTRAINT "uni_Pharmacist_IHS_Number" UNIQUE ("IHS_Number"); diff --git a/cmd/main-migration/migrations/20250908062237.sql b/cmd/main-migration/migrations/20250908062237.sql index cc509de4..5a01ab09 100644 --- a/cmd/main-migration/migrations/20250908062237.sql +++ b/cmd/main-migration/migrations/20250908062237.sql @@ -1,96 +1,96 @@ --- Create "Appointment" table -CREATE TABLE "public"."Appointment" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "PracticeSchedule_Id" bigint NULL, - "Patient_Id" bigint NULL, - "Person_ResidentIdentityNumber" character varying(16) NULL, - "Person_Name" character varying(100) NULL, - "Person_PhoneNumber" character varying(30) NULL, - "PaymentMethod_Code" character varying(10) NULL, - "RefNumber" character varying(20) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Appointment_Patient" FOREIGN KEY ("Patient_Id") REFERENCES "public"."Patient" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Appointment_PracticeSchedule" FOREIGN KEY ("PracticeSchedule_Id") REFERENCES "public"."PracticeSchedule" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Modify "Encounter" table -ALTER TABLE "public"."Encounter" ADD COLUMN "Appointment_Doctor_Id" bigint NULL, ADD COLUMN "Appointment_Id" bigint NULL, ADD COLUMN "EarlyEducation" text NULL, ADD COLUMN "MedicalDischargeEducation" text NULL, ADD COLUMN "AdmDischargeEducation" text NULL, ADD COLUMN "DischargeReason" text NULL, ADD CONSTRAINT "fk_Encounter_Appointment" FOREIGN KEY ("Appointment_Id") REFERENCES "public"."Appointment" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_Encounter_Appointment_Doctor" FOREIGN KEY ("Appointment_Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; --- Create "Adime" table -CREATE TABLE "public"."Adime" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Employee_Id" bigint NULL, - "Time" timestamptz NULL, - "Value" text NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Adime_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Adime_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Ambulatory" table -CREATE TABLE "public"."Ambulatory" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Class_Code" character varying(10) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Ambulatory_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Emergency" table -CREATE TABLE "public"."Emergency" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Class_Code" character varying(10) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Emergency_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Inpatient" table -CREATE TABLE "public"."Inpatient" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Class_Code" character varying(10) NULL, - "Infra_Id" integer NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Inpatient_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Inpatient_Infra" FOREIGN KEY ("Infra_Id") REFERENCES "public"."Infra" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Sbar" table -CREATE TABLE "public"."Sbar" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Employee_Id" bigint NULL, - "Time" timestamptz NULL, - "Value" text NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Sbar_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Sbar_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Soapi" table -CREATE TABLE "public"."Soapi" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Employee_Id" bigint NULL, - "Time" timestamptz NULL, - "Value" text NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Soapi_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Soapi_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); +-- Create "Appointment" table +CREATE TABLE "public"."Appointment" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "PracticeSchedule_Id" bigint NULL, + "Patient_Id" bigint NULL, + "Person_ResidentIdentityNumber" character varying(16) NULL, + "Person_Name" character varying(100) NULL, + "Person_PhoneNumber" character varying(30) NULL, + "PaymentMethod_Code" character varying(10) NULL, + "RefNumber" character varying(20) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Appointment_Patient" FOREIGN KEY ("Patient_Id") REFERENCES "public"."Patient" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Appointment_PracticeSchedule" FOREIGN KEY ("PracticeSchedule_Id") REFERENCES "public"."PracticeSchedule" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Modify "Encounter" table +ALTER TABLE "public"."Encounter" ADD COLUMN "Appointment_Doctor_Id" bigint NULL, ADD COLUMN "Appointment_Id" bigint NULL, ADD COLUMN "EarlyEducation" text NULL, ADD COLUMN "MedicalDischargeEducation" text NULL, ADD COLUMN "AdmDischargeEducation" text NULL, ADD COLUMN "DischargeReason" text NULL, ADD CONSTRAINT "fk_Encounter_Appointment" FOREIGN KEY ("Appointment_Id") REFERENCES "public"."Appointment" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_Encounter_Appointment_Doctor" FOREIGN KEY ("Appointment_Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Create "Adime" table +CREATE TABLE "public"."Adime" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Employee_Id" bigint NULL, + "Time" timestamptz NULL, + "Value" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Adime_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Adime_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Ambulatory" table +CREATE TABLE "public"."Ambulatory" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Class_Code" character varying(10) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Ambulatory_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Emergency" table +CREATE TABLE "public"."Emergency" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Class_Code" character varying(10) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Emergency_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Inpatient" table +CREATE TABLE "public"."Inpatient" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Class_Code" character varying(10) NULL, + "Infra_Id" integer NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Inpatient_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Inpatient_Infra" FOREIGN KEY ("Infra_Id") REFERENCES "public"."Infra" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Sbar" table +CREATE TABLE "public"."Sbar" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Employee_Id" bigint NULL, + "Time" timestamptz NULL, + "Value" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Sbar_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Sbar_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Soapi" table +CREATE TABLE "public"."Soapi" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Employee_Id" bigint NULL, + "Time" timestamptz NULL, + "Value" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Soapi_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Soapi_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20250908062323.sql b/cmd/main-migration/migrations/20250908062323.sql index cc63543f..f6e757f5 100644 --- a/cmd/main-migration/migrations/20250908062323.sql +++ b/cmd/main-migration/migrations/20250908062323.sql @@ -1,2 +1,2 @@ --- Modify "Encounter" table -ALTER TABLE "public"."Encounter" DROP COLUMN "Assignment_Doctor_Id"; +-- Modify "Encounter" table +ALTER TABLE "public"."Encounter" DROP COLUMN "Assignment_Doctor_Id"; diff --git a/cmd/main-migration/migrations/20250908073811.sql b/cmd/main-migration/migrations/20250908073811.sql index ead1e965..330ce9a8 100644 --- a/cmd/main-migration/migrations/20250908073811.sql +++ b/cmd/main-migration/migrations/20250908073811.sql @@ -1,2 +1,2 @@ --- Modify "Encounter" table -ALTER TABLE "public"."Encounter" ADD COLUMN "DischargeMethod_Code" character varying(10) NULL; +-- Modify "Encounter" table +ALTER TABLE "public"."Encounter" ADD COLUMN "DischargeMethod_Code" character varying(10) NULL; diff --git a/cmd/main-migration/migrations/20250908073839.sql b/cmd/main-migration/migrations/20250908073839.sql index 43710589..75fb2190 100644 --- a/cmd/main-migration/migrations/20250908073839.sql +++ b/cmd/main-migration/migrations/20250908073839.sql @@ -1,2 +1,2 @@ --- Modify "Encounter" table -ALTER TABLE "public"."Encounter" DROP COLUMN "DischardeMethod_Code"; +-- Modify "Encounter" table +ALTER TABLE "public"."Encounter" DROP COLUMN "DischardeMethod_Code"; diff --git a/cmd/main-migration/migrations/20250910055902.sql b/cmd/main-migration/migrations/20250910055902.sql index 19583065..0ecfebf0 100644 --- a/cmd/main-migration/migrations/20250910055902.sql +++ b/cmd/main-migration/migrations/20250910055902.sql @@ -1,2 +1,2 @@ --- Modify "Encounter" table -ALTER TABLE "public"."Encounter" ADD COLUMN "Status_Code" character varying(10) NULL; +-- Modify "Encounter" table +ALTER TABLE "public"."Encounter" ADD COLUMN "Status_Code" character varying(10) NULL; diff --git a/cmd/main-migration/migrations/20250915123412.sql b/cmd/main-migration/migrations/20250915123412.sql index 5bb948f0..5fdf5b78 100644 --- a/cmd/main-migration/migrations/20250915123412.sql +++ b/cmd/main-migration/migrations/20250915123412.sql @@ -1,146 +1,146 @@ --- Create "DeviceOrder" table -CREATE TABLE "public"."DeviceOrder" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_DeviceOrder_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "DeviceOrderItem" table -CREATE TABLE "public"."DeviceOrderItem" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "DeviceOrder_Id" bigint NULL, - "Device_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_DeviceOrderItem_Device" FOREIGN KEY ("Device_Id") REFERENCES "public"."Device" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_DeviceOrderItem_DeviceOrder" FOREIGN KEY ("DeviceOrder_Id") REFERENCES "public"."DeviceOrder" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "MaterialOrder" table -CREATE TABLE "public"."MaterialOrder" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_MaterialOrder_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "MaterialOrderItem" table -CREATE TABLE "public"."MaterialOrderItem" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "MaterialOrder_Id" bigint NULL, - "Material_Id" bigint NULL, - "Count" integer NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_MaterialOrderItem_Material" FOREIGN KEY ("Material_Id") REFERENCES "public"."Material" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_MaterialOrderItem_MaterialOrder" FOREIGN KEY ("MaterialOrder_Id") REFERENCES "public"."MaterialOrder" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "McuOrder" table -CREATE TABLE "public"."McuOrder" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Status_Code" character varying(10) NOT NULL, - "Doctor_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_McuOrder_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_McuOrder_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "McuOrderItem" table -CREATE TABLE "public"."McuOrderItem" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "McuOrder_Id" bigint NULL, - "McuSrc_Id" bigint NULL, - "Result" text NULL, - "Status_Code" text NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_McuOrderItem_McuOrder" FOREIGN KEY ("McuOrder_Id") REFERENCES "public"."McuOrder" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_McuOrderItem_McuSrc" FOREIGN KEY ("McuSrc_Id") REFERENCES "public"."McuSrc" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Medication" table -CREATE TABLE "public"."Medication" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "IssuedAt" timestamptz NULL, - "Pharmacist_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Medication_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Medication_Pharmacist" FOREIGN KEY ("Pharmacist_Id") REFERENCES "public"."Pharmacist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "MedicationItem" table -CREATE TABLE "public"."MedicationItem" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Medication_Id" bigint NULL, - "IsMix" boolean NULL, - "Medicine_Id" bigint NULL, - "MedicineMix_Id" bigint NULL, - "Usage" smallint NULL, - "Interval" smallint NULL, - "IntervalUnit_Code" text NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_MedicationItem_Medication" FOREIGN KEY ("Medication_Id") REFERENCES "public"."Medication" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_MedicationItem_Medicine" FOREIGN KEY ("Medicine_Id") REFERENCES "public"."Medicine" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_MedicationItem_MedicineMix" FOREIGN KEY ("MedicineMix_Id") REFERENCES "public"."MedicineMix" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "MedicationItemDist" table -CREATE TABLE "public"."MedicationItemDist" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "MedicationItem_Id" bigint NULL, - "DateTime" timestamptz NULL, - "Remain" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_MedicationItemDist_MedicationItem" FOREIGN KEY ("MedicationItem_Id") REFERENCES "public"."MedicationItem" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Prescription" table -CREATE TABLE "public"."Prescription" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Doctor_Id" bigint NULL, - "IssuedAt" timestamptz NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Prescription_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Prescription_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "PrescriptionItem" table -CREATE TABLE "public"."PrescriptionItem" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Prescription_Id" bigint NULL, - "IsMix" boolean NULL, - "Medicine_Id" bigint NULL, - "MedicineMix_Id" bigint NULL, - "Usage" smallint NULL, - "Interval" smallint NULL, - "IntervalUnit_Code" text NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_PrescriptionItem_Medicine" FOREIGN KEY ("Medicine_Id") REFERENCES "public"."Medicine" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_PrescriptionItem_MedicineMix" FOREIGN KEY ("MedicineMix_Id") REFERENCES "public"."MedicineMix" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_PrescriptionItem_Prescription" FOREIGN KEY ("Prescription_Id") REFERENCES "public"."Prescription" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); +-- Create "DeviceOrder" table +CREATE TABLE "public"."DeviceOrder" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_DeviceOrder_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "DeviceOrderItem" table +CREATE TABLE "public"."DeviceOrderItem" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "DeviceOrder_Id" bigint NULL, + "Device_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_DeviceOrderItem_Device" FOREIGN KEY ("Device_Id") REFERENCES "public"."Device" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_DeviceOrderItem_DeviceOrder" FOREIGN KEY ("DeviceOrder_Id") REFERENCES "public"."DeviceOrder" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "MaterialOrder" table +CREATE TABLE "public"."MaterialOrder" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_MaterialOrder_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "MaterialOrderItem" table +CREATE TABLE "public"."MaterialOrderItem" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "MaterialOrder_Id" bigint NULL, + "Material_Id" bigint NULL, + "Count" integer NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_MaterialOrderItem_Material" FOREIGN KEY ("Material_Id") REFERENCES "public"."Material" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_MaterialOrderItem_MaterialOrder" FOREIGN KEY ("MaterialOrder_Id") REFERENCES "public"."MaterialOrder" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "McuOrder" table +CREATE TABLE "public"."McuOrder" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Status_Code" character varying(10) NOT NULL, + "Doctor_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_McuOrder_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_McuOrder_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "McuOrderItem" table +CREATE TABLE "public"."McuOrderItem" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "McuOrder_Id" bigint NULL, + "McuSrc_Id" bigint NULL, + "Result" text NULL, + "Status_Code" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_McuOrderItem_McuOrder" FOREIGN KEY ("McuOrder_Id") REFERENCES "public"."McuOrder" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_McuOrderItem_McuSrc" FOREIGN KEY ("McuSrc_Id") REFERENCES "public"."McuSrc" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Medication" table +CREATE TABLE "public"."Medication" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "IssuedAt" timestamptz NULL, + "Pharmacist_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Medication_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Medication_Pharmacist" FOREIGN KEY ("Pharmacist_Id") REFERENCES "public"."Pharmacist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "MedicationItem" table +CREATE TABLE "public"."MedicationItem" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Medication_Id" bigint NULL, + "IsMix" boolean NULL, + "Medicine_Id" bigint NULL, + "MedicineMix_Id" bigint NULL, + "Usage" smallint NULL, + "Interval" smallint NULL, + "IntervalUnit_Code" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_MedicationItem_Medication" FOREIGN KEY ("Medication_Id") REFERENCES "public"."Medication" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_MedicationItem_Medicine" FOREIGN KEY ("Medicine_Id") REFERENCES "public"."Medicine" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_MedicationItem_MedicineMix" FOREIGN KEY ("MedicineMix_Id") REFERENCES "public"."MedicineMix" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "MedicationItemDist" table +CREATE TABLE "public"."MedicationItemDist" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "MedicationItem_Id" bigint NULL, + "DateTime" timestamptz NULL, + "Remain" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_MedicationItemDist_MedicationItem" FOREIGN KEY ("MedicationItem_Id") REFERENCES "public"."MedicationItem" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Prescription" table +CREATE TABLE "public"."Prescription" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Doctor_Id" bigint NULL, + "IssuedAt" timestamptz NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Prescription_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Prescription_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "PrescriptionItem" table +CREATE TABLE "public"."PrescriptionItem" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Prescription_Id" bigint NULL, + "IsMix" boolean NULL, + "Medicine_Id" bigint NULL, + "MedicineMix_Id" bigint NULL, + "Usage" smallint NULL, + "Interval" smallint NULL, + "IntervalUnit_Code" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_PrescriptionItem_Medicine" FOREIGN KEY ("Medicine_Id") REFERENCES "public"."Medicine" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_PrescriptionItem_MedicineMix" FOREIGN KEY ("MedicineMix_Id") REFERENCES "public"."MedicineMix" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_PrescriptionItem_Prescription" FOREIGN KEY ("Prescription_Id") REFERENCES "public"."Prescription" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20250916043819.sql b/cmd/main-migration/migrations/20250916043819.sql index 1abe147b..63c18973 100644 --- a/cmd/main-migration/migrations/20250916043819.sql +++ b/cmd/main-migration/migrations/20250916043819.sql @@ -1,14 +1,14 @@ --- Modify "DeviceOrder" table -ALTER TABLE "public"."DeviceOrder" ADD COLUMN "Status_Code" text NULL; --- Modify "DeviceOrderItem" table -ALTER TABLE "public"."DeviceOrderItem" ADD COLUMN "Count" smallint NULL; --- Modify "MaterialOrder" table -ALTER TABLE "public"."MaterialOrder" ADD COLUMN "Status_Code" text NULL; --- Modify "Medication" table -ALTER TABLE "public"."Medication" ADD COLUMN "Status_Code" text NULL; --- Modify "MedicationItem" table -ALTER TABLE "public"."MedicationItem" ALTER COLUMN "Usage" TYPE numeric, ADD COLUMN "IsRedeemed" boolean NULL; --- Modify "PrescriptionItem" table -ALTER TABLE "public"."PrescriptionItem" ALTER COLUMN "Usage" TYPE numeric; --- Modify "MedicationItemDist" table -ALTER TABLE "public"."MedicationItemDist" ALTER COLUMN "Remain" TYPE numeric, ADD COLUMN "Nurse_Id" bigint NULL, ADD CONSTRAINT "fk_MedicationItemDist_Nurse" FOREIGN KEY ("Nurse_Id") REFERENCES "public"."Nurse" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "DeviceOrder" table +ALTER TABLE "public"."DeviceOrder" ADD COLUMN "Status_Code" text NULL; +-- Modify "DeviceOrderItem" table +ALTER TABLE "public"."DeviceOrderItem" ADD COLUMN "Count" smallint NULL; +-- Modify "MaterialOrder" table +ALTER TABLE "public"."MaterialOrder" ADD COLUMN "Status_Code" text NULL; +-- Modify "Medication" table +ALTER TABLE "public"."Medication" ADD COLUMN "Status_Code" text NULL; +-- Modify "MedicationItem" table +ALTER TABLE "public"."MedicationItem" ALTER COLUMN "Usage" TYPE numeric, ADD COLUMN "IsRedeemed" boolean NULL; +-- Modify "PrescriptionItem" table +ALTER TABLE "public"."PrescriptionItem" ALTER COLUMN "Usage" TYPE numeric; +-- Modify "MedicationItemDist" table +ALTER TABLE "public"."MedicationItemDist" ALTER COLUMN "Remain" TYPE numeric, ADD COLUMN "Nurse_Id" bigint NULL, ADD CONSTRAINT "fk_MedicationItemDist_Nurse" FOREIGN KEY ("Nurse_Id") REFERENCES "public"."Nurse" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20250917040616.sql b/cmd/main-migration/migrations/20250917040616.sql index 71fc13e7..3e3ea6d3 100644 --- a/cmd/main-migration/migrations/20250917040616.sql +++ b/cmd/main-migration/migrations/20250917040616.sql @@ -1,8 +1,8 @@ --- Modify "MedicationItem" table -ALTER TABLE "public"."MedicationItem" ADD COLUMN "Quantity" numeric NULL; --- Modify "MedicineMix" table -ALTER TABLE "public"."MedicineMix" ADD COLUMN "Note" text NULL; --- Modify "Prescription" table -ALTER TABLE "public"."Prescription" ADD COLUMN "Status_Code" text NULL; --- Modify "PrescriptionItem" table -ALTER TABLE "public"."PrescriptionItem" ADD COLUMN "Quantity" numeric NULL; +-- Modify "MedicationItem" table +ALTER TABLE "public"."MedicationItem" ADD COLUMN "Quantity" numeric NULL; +-- Modify "MedicineMix" table +ALTER TABLE "public"."MedicineMix" ADD COLUMN "Note" text NULL; +-- Modify "Prescription" table +ALTER TABLE "public"."Prescription" ADD COLUMN "Status_Code" text NULL; +-- Modify "PrescriptionItem" table +ALTER TABLE "public"."PrescriptionItem" ADD COLUMN "Quantity" numeric NULL; diff --git a/cmd/main-migration/migrations/20250917040751.sql b/cmd/main-migration/migrations/20250917040751.sql index 0b8f243b..b78a03a8 100644 --- a/cmd/main-migration/migrations/20250917040751.sql +++ b/cmd/main-migration/migrations/20250917040751.sql @@ -1,2 +1,2 @@ --- Modify "MedicationItem" table -ALTER TABLE "public"."MedicationItem" ADD COLUMN "Note" character varying(1024) NULL; +-- Modify "MedicationItem" table +ALTER TABLE "public"."MedicationItem" ADD COLUMN "Note" character varying(1024) NULL; diff --git a/cmd/main-migration/migrations/20250917045138.sql b/cmd/main-migration/migrations/20250917045138.sql index b40ade76..a572cf95 100644 --- a/cmd/main-migration/migrations/20250917045138.sql +++ b/cmd/main-migration/migrations/20250917045138.sql @@ -1,2 +1,2 @@ --- Modify "MedicineMixItem" table -ALTER TABLE "public"."MedicineMixItem" DROP CONSTRAINT "fk_MedicineMixItem_MedicineMix", ADD CONSTRAINT "fk_MedicineMix_MixItems" FOREIGN KEY ("MedicineMix_Id") REFERENCES "public"."MedicineMix" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "MedicineMixItem" table +ALTER TABLE "public"."MedicineMixItem" DROP CONSTRAINT "fk_MedicineMixItem_MedicineMix", ADD CONSTRAINT "fk_MedicineMix_MixItems" FOREIGN KEY ("MedicineMix_Id") REFERENCES "public"."MedicineMix" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20250917093645.sql b/cmd/main-migration/migrations/20250917093645.sql index b0922c6a..db4c5e13 100644 --- a/cmd/main-migration/migrations/20250917093645.sql +++ b/cmd/main-migration/migrations/20250917093645.sql @@ -1,4 +1,4 @@ --- Modify "MedicineMix" table -ALTER TABLE "public"."MedicineMix" DROP COLUMN "Note"; --- Modify "MedicineMixItem" table -ALTER TABLE "public"."MedicineMixItem" ADD COLUMN "Note" text NULL; +-- Modify "MedicineMix" table +ALTER TABLE "public"."MedicineMix" DROP COLUMN "Note"; +-- Modify "MedicineMixItem" table +ALTER TABLE "public"."MedicineMixItem" ADD COLUMN "Note" text NULL; diff --git a/cmd/main-migration/migrations/20250918073552.sql b/cmd/main-migration/migrations/20250918073552.sql index 1b45e5d4..cc438c30 100644 --- a/cmd/main-migration/migrations/20250918073552.sql +++ b/cmd/main-migration/migrations/20250918073552.sql @@ -1,10 +1,10 @@ --- Modify "McuOrder" table -ALTER TABLE "public"."McuOrder" ADD COLUMN "SpecimenPickTime" timestamptz NULL, ADD COLUMN "ExaminationDate" timestamptz NULL, ADD COLUMN "Number" smallint NULL, ADD COLUMN "Temperature" numeric NULL, ADD COLUMN "McuUrgencyLevel_Code" character varying(10) NOT NULL; --- Modify "McuOrderItem" table -ALTER TABLE "public"."McuOrderItem" ADD COLUMN "ExaminationDate" timestamptz NULL; --- Create index "idx_order_src" to table: "McuOrderItem" -CREATE UNIQUE INDEX "idx_order_src" ON "public"."McuOrderItem" ("McuOrder_Id", "McuSrc_Id"); --- Modify "PersonRelative" table -ALTER TABLE "public"."PersonRelative" ADD COLUMN "Responsible" boolean NULL; --- Modify "McuSrc" table -ALTER TABLE "public"."McuSrc" ALTER COLUMN "Id" TYPE bigint, ADD COLUMN "Item_Id" bigint NULL, ADD CONSTRAINT "fk_McuSrc_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "McuOrder" table +ALTER TABLE "public"."McuOrder" ADD COLUMN "SpecimenPickTime" timestamptz NULL, ADD COLUMN "ExaminationDate" timestamptz NULL, ADD COLUMN "Number" smallint NULL, ADD COLUMN "Temperature" numeric NULL, ADD COLUMN "McuUrgencyLevel_Code" character varying(10) NOT NULL; +-- Modify "McuOrderItem" table +ALTER TABLE "public"."McuOrderItem" ADD COLUMN "ExaminationDate" timestamptz NULL; +-- Create index "idx_order_src" to table: "McuOrderItem" +CREATE UNIQUE INDEX "idx_order_src" ON "public"."McuOrderItem" ("McuOrder_Id", "McuSrc_Id"); +-- Modify "PersonRelative" table +ALTER TABLE "public"."PersonRelative" ADD COLUMN "Responsible" boolean NULL; +-- Modify "McuSrc" table +ALTER TABLE "public"."McuSrc" ALTER COLUMN "Id" TYPE bigint, ADD COLUMN "Item_Id" bigint NULL, ADD CONSTRAINT "fk_McuSrc_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20250918073742.sql b/cmd/main-migration/migrations/20250918073742.sql index 28611d73..b6559d7e 100644 --- a/cmd/main-migration/migrations/20250918073742.sql +++ b/cmd/main-migration/migrations/20250918073742.sql @@ -1,31 +1,31 @@ --- Create "McuSubSrc" table -CREATE TABLE "public"."McuSubSrc" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(20) NULL, - "Name" character varying(50) NULL, - "McuSrc_Id" bigint NULL, - "Item_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_McuSubSrc_Code" UNIQUE ("Code"), - CONSTRAINT "fk_McuSubSrc_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_McuSubSrc_McuSrc" FOREIGN KEY ("McuSrc_Id") REFERENCES "public"."McuSrc" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "McuOrderSubItem" table -CREATE TABLE "public"."McuOrderSubItem" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "McuSubSrc_Id" bigint NULL, - "McuOrderItem_Id" bigint NULL, - "Result" text NULL, - "Status_Code" text NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_McuOrderSubItem_McuOrderItem" FOREIGN KEY ("McuOrderItem_Id") REFERENCES "public"."McuOrderItem" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_McuOrderSubItem_McuSubSrc" FOREIGN KEY ("McuSubSrc_Id") REFERENCES "public"."McuSubSrc" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create index "idx_order_sub_src" to table: "McuOrderSubItem" -CREATE UNIQUE INDEX "idx_order_sub_src" ON "public"."McuOrderSubItem" ("McuSubSrc_Id", "McuOrderItem_Id"); +-- Create "McuSubSrc" table +CREATE TABLE "public"."McuSubSrc" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(20) NULL, + "Name" character varying(50) NULL, + "McuSrc_Id" bigint NULL, + "Item_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_McuSubSrc_Code" UNIQUE ("Code"), + CONSTRAINT "fk_McuSubSrc_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_McuSubSrc_McuSrc" FOREIGN KEY ("McuSrc_Id") REFERENCES "public"."McuSrc" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "McuOrderSubItem" table +CREATE TABLE "public"."McuOrderSubItem" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "McuSubSrc_Id" bigint NULL, + "McuOrderItem_Id" bigint NULL, + "Result" text NULL, + "Status_Code" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_McuOrderSubItem_McuOrderItem" FOREIGN KEY ("McuOrderItem_Id") REFERENCES "public"."McuOrderItem" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_McuOrderSubItem_McuSubSrc" FOREIGN KEY ("McuSubSrc_Id") REFERENCES "public"."McuSubSrc" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create index "idx_order_sub_src" to table: "McuOrderSubItem" +CREATE UNIQUE INDEX "idx_order_sub_src" ON "public"."McuOrderSubItem" ("McuSubSrc_Id", "McuOrderItem_Id"); diff --git a/cmd/main-migration/migrations/20250918074745.sql b/cmd/main-migration/migrations/20250918074745.sql index 365227cb..edf84f66 100644 --- a/cmd/main-migration/migrations/20250918074745.sql +++ b/cmd/main-migration/migrations/20250918074745.sql @@ -1,2 +1,2 @@ --- Modify "McuOrder" table -ALTER TABLE "public"."McuOrder" ALTER COLUMN "McuUrgencyLevel_Code" TYPE character varying(15); +-- Modify "McuOrder" table +ALTER TABLE "public"."McuOrder" ALTER COLUMN "McuUrgencyLevel_Code" TYPE character varying(15); diff --git a/cmd/main-migration/migrations/20250923025134.sql b/cmd/main-migration/migrations/20250923025134.sql index 57a04744..e0665b1c 100644 --- a/cmd/main-migration/migrations/20250923025134.sql +++ b/cmd/main-migration/migrations/20250923025134.sql @@ -1,17 +1,17 @@ --- Create "Consultation" table -CREATE TABLE "public"."Consultation" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Case" character varying(2048) NULL, - "Solution" character varying(2048) NULL, - "Unit_Id" bigint NULL, - "Doctor_Id" bigint NULL, - "RepliedAt" timestamptz NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Consultation_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Consultation_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Consultation_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); +-- Create "Consultation" table +CREATE TABLE "public"."Consultation" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Case" character varying(2048) NULL, + "Solution" character varying(2048) NULL, + "Unit_Id" bigint NULL, + "Doctor_Id" bigint NULL, + "RepliedAt" timestamptz NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Consultation_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Consultation_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Consultation_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20250924051317.sql b/cmd/main-migration/migrations/20250924051317.sql index f0f58947..1ebb0438 100644 --- a/cmd/main-migration/migrations/20250924051317.sql +++ b/cmd/main-migration/migrations/20250924051317.sql @@ -1,2 +1,2 @@ --- Modify "Person" table -ALTER TABLE "public"."Person" ADD COLUMN "ResidentIdentityFileUrl" character varying(1024) NULL, ADD COLUMN "PassportFileUrl" character varying(1024) NULL, ADD COLUMN "DrivingLicenseFileUrl" character varying(1024) NULL, ADD COLUMN "FamilyIdentityFileUrl" character varying(1024) NULL; +-- Modify "Person" table +ALTER TABLE "public"."Person" ADD COLUMN "ResidentIdentityFileUrl" character varying(1024) NULL, ADD COLUMN "PassportFileUrl" character varying(1024) NULL, ADD COLUMN "DrivingLicenseFileUrl" character varying(1024) NULL, ADD COLUMN "FamilyIdentityFileUrl" character varying(1024) NULL; diff --git a/cmd/main-migration/migrations/20250929034321.sql b/cmd/main-migration/migrations/20250929034321.sql index bfdc5021..8c47f9c4 100644 --- a/cmd/main-migration/migrations/20250929034321.sql +++ b/cmd/main-migration/migrations/20250929034321.sql @@ -1,2 +1,2 @@ --- Modify "Soapi" table -ALTER TABLE "public"."Soapi" ADD COLUMN "TypeCode" text NULL; +-- Modify "Soapi" table +ALTER TABLE "public"."Soapi" ADD COLUMN "TypeCode" text NULL; diff --git a/cmd/main-migration/migrations/20250929034428.sql b/cmd/main-migration/migrations/20250929034428.sql index 84a214a5..9b7b69ea 100644 --- a/cmd/main-migration/migrations/20250929034428.sql +++ b/cmd/main-migration/migrations/20250929034428.sql @@ -1,2 +1,2 @@ --- Modify "Soapi" table -ALTER TABLE "public"."Soapi" ALTER COLUMN "TypeCode" TYPE character varying(11); +-- Modify "Soapi" table +ALTER TABLE "public"."Soapi" ALTER COLUMN "TypeCode" TYPE character varying(11); diff --git a/cmd/main-migration/migrations/20250930025550.sql b/cmd/main-migration/migrations/20250930025550.sql index cb24b7fc..f3902808 100644 --- a/cmd/main-migration/migrations/20250930025550.sql +++ b/cmd/main-migration/migrations/20250930025550.sql @@ -1,6 +1,6 @@ --- Modify "MedicationItem" table -ALTER TABLE "public"."MedicationItem" ALTER COLUMN "Usage" TYPE character varying(255), ADD COLUMN "Frequency" integer NULL, ADD COLUMN "Dose" numeric NULL; --- Modify "PrescriptionItem" table -ALTER TABLE "public"."PrescriptionItem" ALTER COLUMN "Usage" TYPE character varying(255), ADD COLUMN "Frequency" integer NULL, ADD COLUMN "Dose" numeric NULL; --- Modify "MedicineMix" table -ALTER TABLE "public"."MedicineMix" ADD COLUMN "Uom_Code" character varying(10) NULL, ADD CONSTRAINT "fk_MedicineMix_Uom" FOREIGN KEY ("Uom_Code") REFERENCES "public"."Uom" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "MedicationItem" table +ALTER TABLE "public"."MedicationItem" ALTER COLUMN "Usage" TYPE character varying(255), ADD COLUMN "Frequency" integer NULL, ADD COLUMN "Dose" numeric NULL; +-- Modify "PrescriptionItem" table +ALTER TABLE "public"."PrescriptionItem" ALTER COLUMN "Usage" TYPE character varying(255), ADD COLUMN "Frequency" integer NULL, ADD COLUMN "Dose" numeric NULL; +-- Modify "MedicineMix" table +ALTER TABLE "public"."MedicineMix" ADD COLUMN "Uom_Code" character varying(10) NULL, ADD CONSTRAINT "fk_MedicineMix_Uom" FOREIGN KEY ("Uom_Code") REFERENCES "public"."Uom" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20250930140351.sql b/cmd/main-migration/migrations/20250930140351.sql index c98fd12a..6c226a81 100644 --- a/cmd/main-migration/migrations/20250930140351.sql +++ b/cmd/main-migration/migrations/20250930140351.sql @@ -1,4 +1,4 @@ --- Rename a column from "CheckupCategory_Code" to "McuSrcCategory_Code" -ALTER TABLE "public"."McuSrc" RENAME COLUMN "CheckupCategory_Code" TO "McuSrcCategory_Code"; --- Modify "McuSrc" table -ALTER TABLE "public"."McuSrc" DROP CONSTRAINT "fk_McuSrc_CheckupCategory", ADD CONSTRAINT "fk_McuSrc_McuSrcCategory" FOREIGN KEY ("McuSrcCategory_Code") REFERENCES "public"."McuSrcCategory" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Rename a column from "CheckupCategory_Code" to "McuSrcCategory_Code" +ALTER TABLE "public"."McuSrc" RENAME COLUMN "CheckupCategory_Code" TO "McuSrcCategory_Code"; +-- Modify "McuSrc" table +ALTER TABLE "public"."McuSrc" DROP CONSTRAINT "fk_McuSrc_CheckupCategory", ADD CONSTRAINT "fk_McuSrc_McuSrcCategory" FOREIGN KEY ("McuSrcCategory_Code") REFERENCES "public"."McuSrcCategory" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251002085604.sql b/cmd/main-migration/migrations/20251002085604.sql index e215cd13..62302ec6 100644 --- a/cmd/main-migration/migrations/20251002085604.sql +++ b/cmd/main-migration/migrations/20251002085604.sql @@ -1,2 +1,2 @@ --- Modify "Division" table -ALTER TABLE "public"."Division" ALTER COLUMN "Parent_Id" TYPE integer, ADD CONSTRAINT "fk_Division_Childrens" FOREIGN KEY ("Parent_Id") REFERENCES "public"."Division" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "Division" table +ALTER TABLE "public"."Division" ALTER COLUMN "Parent_Id" TYPE integer, ADD CONSTRAINT "fk_Division_Childrens" FOREIGN KEY ("Parent_Id") REFERENCES "public"."Division" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251003032030.sql b/cmd/main-migration/migrations/20251003032030.sql index 2bdf73ba..210b76ac 100644 --- a/cmd/main-migration/migrations/20251003032030.sql +++ b/cmd/main-migration/migrations/20251003032030.sql @@ -1,6 +1,6 @@ --- Modify "Infra" table -ALTER TABLE "public"."Infra" ADD CONSTRAINT "fk_Infra_Childrens" FOREIGN KEY ("Parent_Id") REFERENCES "public"."Infra" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; --- Modify "DeviceOrder" table -ALTER TABLE "public"."DeviceOrder" ADD COLUMN "Doctor_Id" bigint NULL, ADD CONSTRAINT "fk_DeviceOrder_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; --- Modify "MaterialOrder" table -ALTER TABLE "public"."MaterialOrder" ADD COLUMN "Doctor_Id" bigint NULL, ADD CONSTRAINT "fk_MaterialOrder_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "Infra" table +ALTER TABLE "public"."Infra" ADD CONSTRAINT "fk_Infra_Childrens" FOREIGN KEY ("Parent_Id") REFERENCES "public"."Infra" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "DeviceOrder" table +ALTER TABLE "public"."DeviceOrder" ADD COLUMN "Doctor_Id" bigint NULL, ADD CONSTRAINT "fk_DeviceOrder_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "MaterialOrder" table +ALTER TABLE "public"."MaterialOrder" ADD COLUMN "Doctor_Id" bigint NULL, ADD CONSTRAINT "fk_MaterialOrder_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251005060450.sql b/cmd/main-migration/migrations/20251005060450.sql index 7ec05f92..652117a4 100644 --- a/cmd/main-migration/migrations/20251005060450.sql +++ b/cmd/main-migration/migrations/20251005060450.sql @@ -1,24 +1,24 @@ --- Modify "Person" table -ALTER TABLE "public"."Person" ADD COLUMN "Nationality" text NULL; --- Create "Chemo" table -CREATE TABLE "public"."Chemo" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Status_Code" text NULL, - "VerifiedAt" timestamptz NULL, - "VerifiedBy_User_Id" bigint NULL, - "SrcUnit_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Chemo_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Chemo_SrcUnit" FOREIGN KEY ("SrcUnit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Chemo_VerifiedBy" FOREIGN KEY ("VerifiedBy_User_Id") REFERENCES "public"."User" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Rename a column from "Unit_Id" to "DstUnit_Id" -ALTER TABLE "public"."Consultation" RENAME COLUMN "Unit_Id" TO "DstUnit_Id"; --- Rename a column from "Doctor_Id" to "DstDoctor_Id" -ALTER TABLE "public"."Consultation" RENAME COLUMN "Doctor_Id" TO "DstDoctor_Id"; --- Modify "Consultation" table -ALTER TABLE "public"."Consultation" DROP CONSTRAINT "fk_Consultation_Doctor", DROP CONSTRAINT "fk_Consultation_Unit", DROP COLUMN "Case", ALTER COLUMN "Solution" TYPE character varying(10240), ADD COLUMN "Date" timestamptz NULL, ADD COLUMN "Problem" character varying(10240) NULL, ADD CONSTRAINT "fk_Consultation_DstDoctor" FOREIGN KEY ("DstDoctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_Consultation_DstUnit" FOREIGN KEY ("DstUnit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "Person" table +ALTER TABLE "public"."Person" ADD COLUMN "Nationality" text NULL; +-- Create "Chemo" table +CREATE TABLE "public"."Chemo" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Status_Code" text NULL, + "VerifiedAt" timestamptz NULL, + "VerifiedBy_User_Id" bigint NULL, + "SrcUnit_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Chemo_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Chemo_SrcUnit" FOREIGN KEY ("SrcUnit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Chemo_VerifiedBy" FOREIGN KEY ("VerifiedBy_User_Id") REFERENCES "public"."User" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Rename a column from "Unit_Id" to "DstUnit_Id" +ALTER TABLE "public"."Consultation" RENAME COLUMN "Unit_Id" TO "DstUnit_Id"; +-- Rename a column from "Doctor_Id" to "DstDoctor_Id" +ALTER TABLE "public"."Consultation" RENAME COLUMN "Doctor_Id" TO "DstDoctor_Id"; +-- Modify "Consultation" table +ALTER TABLE "public"."Consultation" DROP CONSTRAINT "fk_Consultation_Doctor", DROP CONSTRAINT "fk_Consultation_Unit", DROP COLUMN "Case", ALTER COLUMN "Solution" TYPE character varying(10240), ADD COLUMN "Date" timestamptz NULL, ADD COLUMN "Problem" character varying(10240) NULL, ADD CONSTRAINT "fk_Consultation_DstDoctor" FOREIGN KEY ("DstDoctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_Consultation_DstUnit" FOREIGN KEY ("DstUnit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251006041122.sql b/cmd/main-migration/migrations/20251006041122.sql index 24ace4a9..e63133eb 100644 --- a/cmd/main-migration/migrations/20251006041122.sql +++ b/cmd/main-migration/migrations/20251006041122.sql @@ -1,2 +1,2 @@ --- Modify "DivisionPosition" table -ALTER TABLE "public"."DivisionPosition" ADD COLUMN "Employee_Id" bigint NULL, ADD CONSTRAINT "fk_DivisionPosition_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "DivisionPosition" table +ALTER TABLE "public"."DivisionPosition" ADD COLUMN "Employee_Id" bigint NULL, ADD CONSTRAINT "fk_DivisionPosition_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251006045658.sql b/cmd/main-migration/migrations/20251006045658.sql index a8c3a4d7..e14e6231 100644 --- a/cmd/main-migration/migrations/20251006045658.sql +++ b/cmd/main-migration/migrations/20251006045658.sql @@ -1,2 +1,2 @@ --- Modify "Person" table -ALTER TABLE "public"."Person" ADD COLUMN "CommunicationIssueStatus" boolean NULL, ADD COLUMN "Disabillity" character varying(100) NULL; +-- Modify "Person" table +ALTER TABLE "public"."Person" ADD COLUMN "CommunicationIssueStatus" boolean NULL, ADD COLUMN "Disabillity" character varying(100) NULL; diff --git a/cmd/main-migration/migrations/20251006045928.sql b/cmd/main-migration/migrations/20251006045928.sql index f495a26d..22fabb45 100644 --- a/cmd/main-migration/migrations/20251006045928.sql +++ b/cmd/main-migration/migrations/20251006045928.sql @@ -1,2 +1,2 @@ --- Rename a column from "Disabillity" to "Disability" -ALTER TABLE "public"."Person" RENAME COLUMN "Disabillity" TO "Disability"; +-- Rename a column from "Disabillity" to "Disability" +ALTER TABLE "public"."Person" RENAME COLUMN "Disabillity" TO "Disability"; diff --git a/cmd/main-migration/migrations/20251007022859.sql b/cmd/main-migration/migrations/20251007022859.sql index 03b0890b..4fd21d6c 100644 --- a/cmd/main-migration/migrations/20251007022859.sql +++ b/cmd/main-migration/migrations/20251007022859.sql @@ -1,2 +1,2 @@ --- Modify "Patient" table -ALTER TABLE "public"."Patient" ADD COLUMN "NewBornStatus" boolean NULL; +-- Modify "Patient" table +ALTER TABLE "public"."Patient" ADD COLUMN "NewBornStatus" boolean NULL; diff --git a/cmd/main-migration/migrations/20251008031337.sql b/cmd/main-migration/migrations/20251008031337.sql index fd2aff8a..a28ad527 100644 --- a/cmd/main-migration/migrations/20251008031337.sql +++ b/cmd/main-migration/migrations/20251008031337.sql @@ -1,2 +1,2 @@ --- Modify "PersonAddress" table -ALTER TABLE "public"."PersonAddress" ADD COLUMN "PostalCode" character varying(6) NULL; +-- Modify "PersonAddress" table +ALTER TABLE "public"."PersonAddress" ADD COLUMN "PostalCode" character varying(6) NULL; diff --git a/cmd/main-migration/migrations/20251008031554.sql b/cmd/main-migration/migrations/20251008031554.sql index 58cee318..6327ebfb 100644 --- a/cmd/main-migration/migrations/20251008031554.sql +++ b/cmd/main-migration/migrations/20251008031554.sql @@ -1,12 +1,12 @@ --- Create "Midwife" table -CREATE TABLE "public"."Midwife" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Employee_Id" bigint NULL, - "IHS_Number" character varying(20) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_Midwife_IHS_Number" UNIQUE ("IHS_Number"), - CONSTRAINT "fk_Midwife_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); +-- Create "Midwife" table +CREATE TABLE "public"."Midwife" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Employee_Id" bigint NULL, + "IHS_Number" character varying(20) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_Midwife_IHS_Number" UNIQUE ("IHS_Number"), + CONSTRAINT "fk_Midwife_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20251008052346.sql b/cmd/main-migration/migrations/20251008052346.sql index d664f92d..d726c20e 100644 --- a/cmd/main-migration/migrations/20251008052346.sql +++ b/cmd/main-migration/migrations/20251008052346.sql @@ -1,2 +1,2 @@ --- Modify "DivisionPosition" table -ALTER TABLE "public"."DivisionPosition" ADD COLUMN "HeadStatus" boolean NULL; +-- Modify "DivisionPosition" table +ALTER TABLE "public"."DivisionPosition" ADD COLUMN "HeadStatus" boolean NULL; diff --git a/cmd/main-migration/migrations/20251008073620.sql b/cmd/main-migration/migrations/20251008073620.sql index f3d9cf60..06f86561 100644 --- a/cmd/main-migration/migrations/20251008073620.sql +++ b/cmd/main-migration/migrations/20251008073620.sql @@ -1,2 +1,2 @@ --- Modify "Infra" table -ALTER TABLE "public"."Infra" ALTER COLUMN "InfraGroup_Code" TYPE character varying(15); +-- Modify "Infra" table +ALTER TABLE "public"."Infra" ALTER COLUMN "InfraGroup_Code" TYPE character varying(15); diff --git a/cmd/main-migration/migrations/20251009042854.sql b/cmd/main-migration/migrations/20251009042854.sql index c8b5ec23..e38c46d6 100644 --- a/cmd/main-migration/migrations/20251009042854.sql +++ b/cmd/main-migration/migrations/20251009042854.sql @@ -1,9 +1,9 @@ --- Create "PostalCode" table -CREATE TABLE "public"."PostalCode" ( - "Id" bigserial NOT NULL, - "Code" character varying(5) NULL, - "Village_Code" character varying(10) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_PostalCode_Code" UNIQUE ("Code"), - CONSTRAINT "fk_Village_PostalCodes" FOREIGN KEY ("Village_Code") REFERENCES "public"."Village" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION -); +-- Create "PostalCode" table +CREATE TABLE "public"."PostalCode" ( + "Id" bigserial NOT NULL, + "Code" character varying(5) NULL, + "Village_Code" character varying(10) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_PostalCode_Code" UNIQUE ("Code"), + CONSTRAINT "fk_Village_PostalCodes" FOREIGN KEY ("Village_Code") REFERENCES "public"."Village" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20251009052657.sql b/cmd/main-migration/migrations/20251009052657.sql index 5655a577..af68a0e4 100644 --- a/cmd/main-migration/migrations/20251009052657.sql +++ b/cmd/main-migration/migrations/20251009052657.sql @@ -1,8 +1,8 @@ --- Modify "Regency" table -ALTER TABLE "public"."Regency" DROP CONSTRAINT "fk_Province_Regencies", ALTER COLUMN "Id" TYPE bigint, ADD CONSTRAINT "fk_Regency_Province" FOREIGN KEY ("Province_Code") REFERENCES "public"."Province" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; --- Modify "District" table -ALTER TABLE "public"."District" DROP CONSTRAINT "fk_Regency_Districts", ADD CONSTRAINT "fk_District_Regency" FOREIGN KEY ("Regency_Code") REFERENCES "public"."Regency" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; --- Modify "Village" table -ALTER TABLE "public"."Village" DROP CONSTRAINT "fk_District_Villages", ADD CONSTRAINT "fk_Village_District" FOREIGN KEY ("District_Code") REFERENCES "public"."District" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; --- Modify "PostalCode" table -ALTER TABLE "public"."PostalCode" DROP CONSTRAINT "fk_Village_PostalCodes", ADD CONSTRAINT "fk_PostalCode_Village" FOREIGN KEY ("Village_Code") REFERENCES "public"."Village" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "Regency" table +ALTER TABLE "public"."Regency" DROP CONSTRAINT "fk_Province_Regencies", ALTER COLUMN "Id" TYPE bigint, ADD CONSTRAINT "fk_Regency_Province" FOREIGN KEY ("Province_Code") REFERENCES "public"."Province" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "District" table +ALTER TABLE "public"."District" DROP CONSTRAINT "fk_Regency_Districts", ADD CONSTRAINT "fk_District_Regency" FOREIGN KEY ("Regency_Code") REFERENCES "public"."Regency" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "Village" table +ALTER TABLE "public"."Village" DROP CONSTRAINT "fk_District_Villages", ADD CONSTRAINT "fk_Village_District" FOREIGN KEY ("District_Code") REFERENCES "public"."District" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "PostalCode" table +ALTER TABLE "public"."PostalCode" DROP CONSTRAINT "fk_Village_PostalCodes", ADD CONSTRAINT "fk_PostalCode_Village" FOREIGN KEY ("Village_Code") REFERENCES "public"."Village" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251010031743.sql b/cmd/main-migration/migrations/20251010031743.sql index 1dea016a..0fb84b12 100644 --- a/cmd/main-migration/migrations/20251010031743.sql +++ b/cmd/main-migration/migrations/20251010031743.sql @@ -1,6 +1,6 @@ --- Modify "Person" table -ALTER TABLE "public"."Person" ADD CONSTRAINT "fk_Person_BirthRegency" FOREIGN KEY ("BirthRegency_Code") REFERENCES "public"."Regency" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; --- Rename a column from "PostalCode" to "PostalCode_Code" -ALTER TABLE "public"."PersonAddress" RENAME COLUMN "PostalCode" TO "PostalCode_Code"; --- Modify "PersonAddress" table -ALTER TABLE "public"."PersonAddress" ADD CONSTRAINT "fk_PersonAddress_PostalCode" FOREIGN KEY ("PostalCode_Code") REFERENCES "public"."PostalCode" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "Person" table +ALTER TABLE "public"."Person" ADD CONSTRAINT "fk_Person_BirthRegency" FOREIGN KEY ("BirthRegency_Code") REFERENCES "public"."Regency" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Rename a column from "PostalCode" to "PostalCode_Code" +ALTER TABLE "public"."PersonAddress" RENAME COLUMN "PostalCode" TO "PostalCode_Code"; +-- Modify "PersonAddress" table +ALTER TABLE "public"."PersonAddress" ADD CONSTRAINT "fk_PersonAddress_PostalCode" FOREIGN KEY ("PostalCode_Code") REFERENCES "public"."PostalCode" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251010070721.sql b/cmd/main-migration/migrations/20251010070721.sql index ee030931..fe65c513 100644 --- a/cmd/main-migration/migrations/20251010070721.sql +++ b/cmd/main-migration/migrations/20251010070721.sql @@ -1,15 +1,15 @@ --- Create "PostalRegion" table -CREATE TABLE "public"."PostalRegion" ( - "Id" bigserial NOT NULL, - "Village_Code" character varying(10) NULL, - "Code" character varying(5) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_PostalRegion_Code" UNIQUE ("Code"), - CONSTRAINT "fk_PostalRegion_Village" FOREIGN KEY ("Village_Code") REFERENCES "public"."Village" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Rename a column from "PostalCode_Code" to "PostalRegion_Code" -ALTER TABLE "public"."PersonAddress" RENAME COLUMN "PostalCode_Code" TO "PostalRegion_Code"; --- Modify "PersonAddress" table -ALTER TABLE "public"."PersonAddress" DROP CONSTRAINT "fk_PersonAddress_PostalCode", ADD COLUMN "LocationType_Code" character varying(10) NULL, ADD CONSTRAINT "fk_PersonAddress_PostalRegion" FOREIGN KEY ("PostalRegion_Code") REFERENCES "public"."PostalRegion" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; --- Drop "PostalCode" table -DROP TABLE "public"."PostalCode"; +-- Create "PostalRegion" table +CREATE TABLE "public"."PostalRegion" ( + "Id" bigserial NOT NULL, + "Village_Code" character varying(10) NULL, + "Code" character varying(5) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_PostalRegion_Code" UNIQUE ("Code"), + CONSTRAINT "fk_PostalRegion_Village" FOREIGN KEY ("Village_Code") REFERENCES "public"."Village" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Rename a column from "PostalCode_Code" to "PostalRegion_Code" +ALTER TABLE "public"."PersonAddress" RENAME COLUMN "PostalCode_Code" TO "PostalRegion_Code"; +-- Modify "PersonAddress" table +ALTER TABLE "public"."PersonAddress" DROP CONSTRAINT "fk_PersonAddress_PostalCode", ADD COLUMN "LocationType_Code" character varying(10) NULL, ADD CONSTRAINT "fk_PersonAddress_PostalRegion" FOREIGN KEY ("PostalRegion_Code") REFERENCES "public"."PostalRegion" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Drop "PostalCode" table +DROP TABLE "public"."PostalCode"; diff --git a/cmd/main-migration/migrations/20251010072711.sql b/cmd/main-migration/migrations/20251010072711.sql index f4b24a4f..b57a06de 100644 --- a/cmd/main-migration/migrations/20251010072711.sql +++ b/cmd/main-migration/migrations/20251010072711.sql @@ -1,2 +1,2 @@ --- Modify "PersonAddress" table -ALTER TABLE "public"."PersonAddress" ADD CONSTRAINT "fk_PersonAddress_Village" FOREIGN KEY ("Village_Code") REFERENCES "public"."Village" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "PersonAddress" table +ALTER TABLE "public"."PersonAddress" ADD CONSTRAINT "fk_PersonAddress_Village" FOREIGN KEY ("Village_Code") REFERENCES "public"."Village" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251013044536.sql b/cmd/main-migration/migrations/20251013044536.sql index 84bdf0b0..175487d1 100644 --- a/cmd/main-migration/migrations/20251013044536.sql +++ b/cmd/main-migration/migrations/20251013044536.sql @@ -1,14 +1,14 @@ --- Create "CheckoutPolies" table -CREATE TABLE "public"."CheckoutPolies" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Unit_Id" integer NULL, - "Doctor_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_CheckoutPolies_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_CheckoutPolies_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_CheckoutPolies_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); +-- Create "CheckoutPolies" table +CREATE TABLE "public"."CheckoutPolies" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Unit_Id" integer NULL, + "Doctor_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_CheckoutPolies_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_CheckoutPolies_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_CheckoutPolies_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20251013051438.sql b/cmd/main-migration/migrations/20251013051438.sql index 791f3384..8a1ee2d4 100644 --- a/cmd/main-migration/migrations/20251013051438.sql +++ b/cmd/main-migration/migrations/20251013051438.sql @@ -1,2 +1,2 @@ --- Modify "Encounter" table -ALTER TABLE "public"."Encounter" ALTER COLUMN "DischargeMethod_Code" TYPE character varying(16); +-- Modify "Encounter" table +ALTER TABLE "public"."Encounter" ALTER COLUMN "DischargeMethod_Code" TYPE character varying(16); diff --git a/cmd/main-migration/migrations/20251013081808.sql b/cmd/main-migration/migrations/20251013081808.sql index 03bf02ce..871c8aba 100644 --- a/cmd/main-migration/migrations/20251013081808.sql +++ b/cmd/main-migration/migrations/20251013081808.sql @@ -1,16 +1,16 @@ --- Create "InternalReference" table -CREATE TABLE "public"."InternalReference" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Unit_Id" integer NULL, - "Doctor_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_InternalReference_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_InternalReference_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_InternalReference_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Drop "CheckoutPolies" table -DROP TABLE "public"."CheckoutPolies"; +-- Create "InternalReference" table +CREATE TABLE "public"."InternalReference" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Unit_Id" integer NULL, + "Doctor_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_InternalReference_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_InternalReference_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_InternalReference_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Drop "CheckoutPolies" table +DROP TABLE "public"."CheckoutPolies"; diff --git a/cmd/main-migration/migrations/20251014060047.sql b/cmd/main-migration/migrations/20251014060047.sql index 1d13853a..4503f7c8 100644 --- a/cmd/main-migration/migrations/20251014060047.sql +++ b/cmd/main-migration/migrations/20251014060047.sql @@ -1,36 +1,36 @@ --- Create "VClaimSepHist" table -CREATE TABLE "public"."VClaimSepHist" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "RequestPayload" text NULL, - "ResponseBody" text NULL, - "Message" text NULL, - PRIMARY KEY ("Id") -); --- Modify "Encounter" table -ALTER TABLE "public"."Encounter" ADD COLUMN "PaymentMethod_Code" character varying(10) NULL, ADD COLUMN "InsuranceCompany_Id" bigint NULL, ADD COLUMN "Member_Number" character varying(20) NULL, ADD COLUMN "Ref_Number" character varying(20) NULL, ADD COLUMN "Trx_Number" character varying(20) NULL, ADD COLUMN "Adm_Employee_Id" bigint NULL, ADD CONSTRAINT "uni_Encounter_Member_Number" UNIQUE ("Member_Number"), ADD CONSTRAINT "uni_Encounter_Ref_Number" UNIQUE ("Ref_Number"), ADD CONSTRAINT "uni_Encounter_Trx_Number" UNIQUE ("Trx_Number"), ADD CONSTRAINT "fk_Encounter_Adm_Employee" FOREIGN KEY ("Adm_Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_Encounter_InsuranceCompany" FOREIGN KEY ("InsuranceCompany_Id") REFERENCES "public"."InsuranceCompany" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; --- Create "VClaimSep" table -CREATE TABLE "public"."VClaimSep" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Number" character varying(19) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_VClaimSep_Number" UNIQUE ("Number"), - CONSTRAINT "fk_Encounter_VclaimSep" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "VClaimSepPrint" table -CREATE TABLE "public"."VClaimSepPrint" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "VclaimSep_Number" character varying(19) NULL, - "Counter" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_VClaimSepPrint_VclaimSep" FOREIGN KEY ("VclaimSep_Number") REFERENCES "public"."VClaimSep" ("Number") ON UPDATE NO ACTION ON DELETE NO ACTION -); +-- Create "VClaimSepHist" table +CREATE TABLE "public"."VClaimSepHist" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "RequestPayload" text NULL, + "ResponseBody" text NULL, + "Message" text NULL, + PRIMARY KEY ("Id") +); +-- Modify "Encounter" table +ALTER TABLE "public"."Encounter" ADD COLUMN "PaymentMethod_Code" character varying(10) NULL, ADD COLUMN "InsuranceCompany_Id" bigint NULL, ADD COLUMN "Member_Number" character varying(20) NULL, ADD COLUMN "Ref_Number" character varying(20) NULL, ADD COLUMN "Trx_Number" character varying(20) NULL, ADD COLUMN "Adm_Employee_Id" bigint NULL, ADD CONSTRAINT "uni_Encounter_Member_Number" UNIQUE ("Member_Number"), ADD CONSTRAINT "uni_Encounter_Ref_Number" UNIQUE ("Ref_Number"), ADD CONSTRAINT "uni_Encounter_Trx_Number" UNIQUE ("Trx_Number"), ADD CONSTRAINT "fk_Encounter_Adm_Employee" FOREIGN KEY ("Adm_Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_Encounter_InsuranceCompany" FOREIGN KEY ("InsuranceCompany_Id") REFERENCES "public"."InsuranceCompany" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Create "VClaimSep" table +CREATE TABLE "public"."VClaimSep" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Number" character varying(19) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_VClaimSep_Number" UNIQUE ("Number"), + CONSTRAINT "fk_Encounter_VclaimSep" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "VClaimSepPrint" table +CREATE TABLE "public"."VClaimSepPrint" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "VclaimSep_Number" character varying(19) NULL, + "Counter" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_VClaimSepPrint_VclaimSep" FOREIGN KEY ("VclaimSep_Number") REFERENCES "public"."VClaimSep" ("Number") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20251014063537.sql b/cmd/main-migration/migrations/20251014063537.sql index 7b77b3d9..4186478d 100644 --- a/cmd/main-migration/migrations/20251014063537.sql +++ b/cmd/main-migration/migrations/20251014063537.sql @@ -1,16 +1,16 @@ --- Create "VclaimSep" table -CREATE TABLE "public"."VclaimSep" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Number" character varying(19) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_VclaimSep_Number" UNIQUE ("Number"), - CONSTRAINT "fk_Encounter_VclaimSep" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Modify "VClaimSepPrint" table -ALTER TABLE "public"."VClaimSepPrint" DROP CONSTRAINT "fk_VClaimSepPrint_VclaimSep", ADD CONSTRAINT "fk_VClaimSepPrint_VclaimSep" FOREIGN KEY ("VclaimSep_Number") REFERENCES "public"."VclaimSep" ("Number") ON UPDATE NO ACTION ON DELETE NO ACTION; --- Drop "VClaimSep" table -DROP TABLE "public"."VClaimSep"; +-- Create "VclaimSep" table +CREATE TABLE "public"."VclaimSep" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Number" character varying(19) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_VclaimSep_Number" UNIQUE ("Number"), + CONSTRAINT "fk_Encounter_VclaimSep" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Modify "VClaimSepPrint" table +ALTER TABLE "public"."VClaimSepPrint" DROP CONSTRAINT "fk_VClaimSepPrint_VclaimSep", ADD CONSTRAINT "fk_VClaimSepPrint_VclaimSep" FOREIGN KEY ("VclaimSep_Number") REFERENCES "public"."VclaimSep" ("Number") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Drop "VClaimSep" table +DROP TABLE "public"."VClaimSep"; diff --git a/cmd/main-migration/migrations/20251014063720.sql b/cmd/main-migration/migrations/20251014063720.sql index 0763c12b..4512cb5e 100644 --- a/cmd/main-migration/migrations/20251014063720.sql +++ b/cmd/main-migration/migrations/20251014063720.sql @@ -1,26 +1,26 @@ --- Create "VclaimSepHist" table -CREATE TABLE "public"."VclaimSepHist" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "RequestPayload" text NULL, - "ResponseBody" text NULL, - "Message" text NULL, - PRIMARY KEY ("Id") -); --- Create "VclaimSepPrint" table -CREATE TABLE "public"."VclaimSepPrint" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "VclaimSep_Number" character varying(19) NULL, - "Counter" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_VclaimSepPrint_VclaimSep" FOREIGN KEY ("VclaimSep_Number") REFERENCES "public"."VclaimSep" ("Number") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Drop "VClaimSepHist" table -DROP TABLE "public"."VClaimSepHist"; --- Drop "VClaimSepPrint" table -DROP TABLE "public"."VClaimSepPrint"; +-- Create "VclaimSepHist" table +CREATE TABLE "public"."VclaimSepHist" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "RequestPayload" text NULL, + "ResponseBody" text NULL, + "Message" text NULL, + PRIMARY KEY ("Id") +); +-- Create "VclaimSepPrint" table +CREATE TABLE "public"."VclaimSepPrint" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "VclaimSep_Number" character varying(19) NULL, + "Counter" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_VclaimSepPrint_VclaimSep" FOREIGN KEY ("VclaimSep_Number") REFERENCES "public"."VclaimSep" ("Number") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Drop "VClaimSepHist" table +DROP TABLE "public"."VClaimSepHist"; +-- Drop "VClaimSepPrint" table +DROP TABLE "public"."VClaimSepPrint"; diff --git a/cmd/main-migration/migrations/20251015045455.sql b/cmd/main-migration/migrations/20251015045455.sql index f2b6be7a..ed3ccede 100644 --- a/cmd/main-migration/migrations/20251015045455.sql +++ b/cmd/main-migration/migrations/20251015045455.sql @@ -1,2 +1,2 @@ --- Modify "Chemo" table -ALTER TABLE "public"."Chemo" ADD COLUMN "ClassCode" text NULL; +-- Modify "Chemo" table +ALTER TABLE "public"."Chemo" ADD COLUMN "ClassCode" text NULL; diff --git a/cmd/main-migration/migrations/20251016010845.sql b/cmd/main-migration/migrations/20251016010845.sql index edbbb414..6463b8ef 100644 --- a/cmd/main-migration/migrations/20251016010845.sql +++ b/cmd/main-migration/migrations/20251016010845.sql @@ -1,2 +1,2 @@ --- Rename a column from "ClassCode" to "Class_Code" -ALTER TABLE "public"."Chemo" RENAME COLUMN "ClassCode" TO "Class_Code"; +-- Rename a column from "ClassCode" to "Class_Code" +ALTER TABLE "public"."Chemo" RENAME COLUMN "ClassCode" TO "Class_Code"; diff --git a/cmd/main-migration/migrations/20251016011023.sql b/cmd/main-migration/migrations/20251016011023.sql index 12e51e7d..945037f7 100644 --- a/cmd/main-migration/migrations/20251016011023.sql +++ b/cmd/main-migration/migrations/20251016011023.sql @@ -1,17 +1,17 @@ --- Create "PersonInsurance" table -CREATE TABLE "public"."PersonInsurance" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Person_Id" bigint NULL, - "InsuranceCompany_Id" bigint NULL, - "Ref_Number" character varying(20) NULL, - "DefaultStatus" boolean NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_PersonInsurance_Ref_Number" UNIQUE ("Ref_Number"), - CONSTRAINT "fk_PersonInsurance_InsuranceCompany" FOREIGN KEY ("InsuranceCompany_Id") REFERENCES "public"."InsuranceCompany" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Person_Insurances" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create index "idx_person_insurance" to table: "PersonInsurance" -CREATE UNIQUE INDEX "idx_person_insurance" ON "public"."PersonInsurance" ("Person_Id", "DefaultStatus"); +-- Create "PersonInsurance" table +CREATE TABLE "public"."PersonInsurance" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Person_Id" bigint NULL, + "InsuranceCompany_Id" bigint NULL, + "Ref_Number" character varying(20) NULL, + "DefaultStatus" boolean NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_PersonInsurance_Ref_Number" UNIQUE ("Ref_Number"), + CONSTRAINT "fk_PersonInsurance_InsuranceCompany" FOREIGN KEY ("InsuranceCompany_Id") REFERENCES "public"."InsuranceCompany" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Person_Insurances" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create index "idx_person_insurance" to table: "PersonInsurance" +CREATE UNIQUE INDEX "idx_person_insurance" ON "public"."PersonInsurance" ("Person_Id", "DefaultStatus"); diff --git a/cmd/main-migration/migrations/20251016062912.sql b/cmd/main-migration/migrations/20251016062912.sql index b9208471..f5fd01cb 100644 --- a/cmd/main-migration/migrations/20251016062912.sql +++ b/cmd/main-migration/migrations/20251016062912.sql @@ -1,54 +1,54 @@ --- Create "AmbulanceTransportReq" table -CREATE TABLE "public"."AmbulanceTransportReq" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Patient_Id" bigint NULL, - "Diagnoses" character varying(1024) NULL, - "RequestData" timestamptz NULL, - "UsageDate" timestamptz NULL, - "Address" character varying(100) NULL, - "RtRw" character varying(10) NULL, - "Province_Code" character varying(2) NULL, - "Regency_Code" character varying(4) NULL, - "District_Code" character varying(6) NULL, - "Village_Code" character varying(10) NULL, - "Facility_Code" character varying(10) NULL, - "Needs_Code" character varying(10) NULL, - "Contact_Name" character varying(100) NULL, - "Contact_Relationship_Code" character varying(10) NULL, - "Contact_PhoneNumber" character varying(20) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_AmbulanceTransportReq_District" FOREIGN KEY ("District_Code") REFERENCES "public"."District" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_AmbulanceTransportReq_Patient" FOREIGN KEY ("Patient_Id") REFERENCES "public"."Patient" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_AmbulanceTransportReq_Province" FOREIGN KEY ("Province_Code") REFERENCES "public"."Province" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_AmbulanceTransportReq_Regency" FOREIGN KEY ("Regency_Code") REFERENCES "public"."Regency" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_AmbulanceTransportReq_Village" FOREIGN KEY ("Village_Code") REFERENCES "public"."Village" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "Vehicle" table -CREATE TABLE "public"."Vehicle" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Type_Code" text NULL, - "PoliceNumber" text NULL, - "FrameNumber" text NULL, - "RegNumber" text NULL, - "AvailableStatus" boolean NULL, - PRIMARY KEY ("Id") -); --- Create "VehicleHist" table -CREATE TABLE "public"."VehicleHist" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Vehicle_Id" bigint NULL, - "Date" timestamptz NULL, - "Data" text NULL, - "Crud_Code" text NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_VehicleHist_Vehicle" FOREIGN KEY ("Vehicle_Id") REFERENCES "public"."Vehicle" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); +-- Create "AmbulanceTransportReq" table +CREATE TABLE "public"."AmbulanceTransportReq" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Patient_Id" bigint NULL, + "Diagnoses" character varying(1024) NULL, + "RequestData" timestamptz NULL, + "UsageDate" timestamptz NULL, + "Address" character varying(100) NULL, + "RtRw" character varying(10) NULL, + "Province_Code" character varying(2) NULL, + "Regency_Code" character varying(4) NULL, + "District_Code" character varying(6) NULL, + "Village_Code" character varying(10) NULL, + "Facility_Code" character varying(10) NULL, + "Needs_Code" character varying(10) NULL, + "Contact_Name" character varying(100) NULL, + "Contact_Relationship_Code" character varying(10) NULL, + "Contact_PhoneNumber" character varying(20) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_AmbulanceTransportReq_District" FOREIGN KEY ("District_Code") REFERENCES "public"."District" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_AmbulanceTransportReq_Patient" FOREIGN KEY ("Patient_Id") REFERENCES "public"."Patient" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_AmbulanceTransportReq_Province" FOREIGN KEY ("Province_Code") REFERENCES "public"."Province" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_AmbulanceTransportReq_Regency" FOREIGN KEY ("Regency_Code") REFERENCES "public"."Regency" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_AmbulanceTransportReq_Village" FOREIGN KEY ("Village_Code") REFERENCES "public"."Village" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "Vehicle" table +CREATE TABLE "public"."Vehicle" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Type_Code" text NULL, + "PoliceNumber" text NULL, + "FrameNumber" text NULL, + "RegNumber" text NULL, + "AvailableStatus" boolean NULL, + PRIMARY KEY ("Id") +); +-- Create "VehicleHist" table +CREATE TABLE "public"."VehicleHist" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Vehicle_Id" bigint NULL, + "Date" timestamptz NULL, + "Data" text NULL, + "Crud_Code" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_VehicleHist_Vehicle" FOREIGN KEY ("Vehicle_Id") REFERENCES "public"."Vehicle" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20251017060617.sql b/cmd/main-migration/migrations/20251017060617.sql index 8e3acbd2..ed6a5b78 100644 --- a/cmd/main-migration/migrations/20251017060617.sql +++ b/cmd/main-migration/migrations/20251017060617.sql @@ -1,2 +1,2 @@ --- Modify "MedicalActionSrc" table -ALTER TABLE "public"."MedicalActionSrc" ADD COLUMN "Type_Code" character varying(20) NULL; +-- Modify "MedicalActionSrc" table +ALTER TABLE "public"."MedicalActionSrc" ADD COLUMN "Type_Code" character varying(20) NULL; diff --git a/cmd/main-migration/migrations/20251017082207.sql b/cmd/main-migration/migrations/20251017082207.sql index 732c8d71..e7c1ebd3 100644 --- a/cmd/main-migration/migrations/20251017082207.sql +++ b/cmd/main-migration/migrations/20251017082207.sql @@ -1,2 +1,2 @@ --- Modify "Item" table -ALTER TABLE "public"."Item" ALTER COLUMN "ItemGroup_Code" TYPE character varying(15); +-- Modify "Item" table +ALTER TABLE "public"."Item" ALTER COLUMN "ItemGroup_Code" TYPE character varying(15); diff --git a/cmd/main-migration/migrations/20251018032635.sql b/cmd/main-migration/migrations/20251018032635.sql index d8c5a2c9..edd59e74 100644 --- a/cmd/main-migration/migrations/20251018032635.sql +++ b/cmd/main-migration/migrations/20251018032635.sql @@ -1,4 +1,4 @@ --- Modify "Employee" table -ALTER TABLE "public"."Employee" ADD COLUMN "Position_Code" character varying(20) NULL; --- Rename a column from "Position_Code" to "ContractPosition_Code" -ALTER TABLE "public"."User" RENAME COLUMN "Position_Code" TO "ContractPosition_Code"; +-- Modify "Employee" table +ALTER TABLE "public"."Employee" ADD COLUMN "Position_Code" character varying(20) NULL; +-- Rename a column from "Position_Code" to "ContractPosition_Code" +ALTER TABLE "public"."User" RENAME COLUMN "Position_Code" TO "ContractPosition_Code"; diff --git a/cmd/main-migration/migrations/20251018040322.sql b/cmd/main-migration/migrations/20251018040322.sql index d35e9199..9de5e2b8 100644 --- a/cmd/main-migration/migrations/20251018040322.sql +++ b/cmd/main-migration/migrations/20251018040322.sql @@ -1,13 +1,13 @@ --- Create "Intern" table -CREATE TABLE "public"."Intern" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Person_Id" bigint NULL, - "Position_Code" character varying(20) NULL, - "User_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Intern_Person" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Intern_User" FOREIGN KEY ("User_Id") REFERENCES "public"."User" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); +-- Create "Intern" table +CREATE TABLE "public"."Intern" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Person_Id" bigint NULL, + "Position_Code" character varying(20) NULL, + "User_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Intern_Person" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Intern_User" FOREIGN KEY ("User_Id") REFERENCES "public"."User" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20251019093915.sql b/cmd/main-migration/migrations/20251019093915.sql index add924ea..89c4087e 100644 --- a/cmd/main-migration/migrations/20251019093915.sql +++ b/cmd/main-migration/migrations/20251019093915.sql @@ -1,15 +1,15 @@ --- -- Rename a column from "Position_Code" to "ContractPosition_Code" --- ALTER TABLE "public"."User" RENAME COLUMN "Position_Code" TO "ContractPosition_Code"; --- -- Create "Intern" table --- CREATE TABLE "public"."Intern" ( --- "Id" bigserial NOT NULL, --- "CreatedAt" timestamptz NULL, --- "UpdatedAt" timestamptz NULL, --- "DeletedAt" timestamptz NULL, --- "Person_Id" bigint NULL, --- "Position_Code" character varying(20) NULL, --- "User_Id" bigint NULL, --- PRIMARY KEY ("Id"), --- CONSTRAINT "fk_Intern_Person" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, --- CONSTRAINT "fk_Intern_User" FOREIGN KEY ("User_Id") REFERENCES "public"."User" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION --- ); +-- -- Rename a column from "Position_Code" to "ContractPosition_Code" +-- ALTER TABLE "public"."User" RENAME COLUMN "Position_Code" TO "ContractPosition_Code"; +-- -- Create "Intern" table +-- CREATE TABLE "public"."Intern" ( +-- "Id" bigserial NOT NULL, +-- "CreatedAt" timestamptz NULL, +-- "UpdatedAt" timestamptz NULL, +-- "DeletedAt" timestamptz NULL, +-- "Person_Id" bigint NULL, +-- "Position_Code" character varying(20) NULL, +-- "User_Id" bigint NULL, +-- PRIMARY KEY ("Id"), +-- CONSTRAINT "fk_Intern_Person" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, +-- CONSTRAINT "fk_Intern_User" FOREIGN KEY ("User_Id") REFERENCES "public"."User" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +-- ); diff --git a/cmd/main-migration/migrations/20251020062553.sql b/cmd/main-migration/migrations/20251020062553.sql index a1e72bdd..0ed8501b 100644 --- a/cmd/main-migration/migrations/20251020062553.sql +++ b/cmd/main-migration/migrations/20251020062553.sql @@ -1,2 +1,2 @@ --- Rename a column from "RequestData" to "RequestDate" -ALTER TABLE "public"."AmbulanceTransportReq" RENAME COLUMN "RequestData" TO "RequestDate"; +-- Rename a column from "RequestData" to "RequestDate" +ALTER TABLE "public"."AmbulanceTransportReq" RENAME COLUMN "RequestData" TO "RequestDate"; diff --git a/cmd/main-migration/migrations/20251021041042.sql b/cmd/main-migration/migrations/20251021041042.sql index 43701307..2ff8aa1b 100644 --- a/cmd/main-migration/migrations/20251021041042.sql +++ b/cmd/main-migration/migrations/20251021041042.sql @@ -1,60 +1,60 @@ --- Create "DeathCause" table -CREATE TABLE "public"."DeathCause" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NOT NULL, - "Value" text NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_DeathCause_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "EduAssessment" table -CREATE TABLE "public"."EduAssessment" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NOT NULL, - "GeneralEdus" text NULL, - "SpecialEdus" text NULL, - "Assessments" text NULL, - "Plan" text NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_EduAssessment_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "GeneralConsent" table -CREATE TABLE "public"."GeneralConsent" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NOT NULL, - "Value" text NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_GeneralConsent_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "TherapyProtocol" table -CREATE TABLE "public"."TherapyProtocol" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NOT NULL, - "Doctor_Id" bigint NULL, - "Anamnesis" character varying(2048) NULL, - "MedicalDiagnoses" text NULL, - "FunctionDiagnoses" text NULL, - "Procedures" text NULL, - "SupportingExams" character varying(2048) NULL, - "Instruction" character varying(2048) NULL, - "Evaluation" character varying(2048) NULL, - "WorkCauseStatus" character varying(2048) NULL, - "Frequency" bigint NULL, - "IntervalUnit_Code" character varying(10) NULL, - "Duration" bigint NULL, - "DurationUnit_Code" character varying(10) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_TherapyProtocol_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_TherapyProtocol_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); +-- Create "DeathCause" table +CREATE TABLE "public"."DeathCause" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NOT NULL, + "Value" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_DeathCause_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "EduAssessment" table +CREATE TABLE "public"."EduAssessment" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NOT NULL, + "GeneralEdus" text NULL, + "SpecialEdus" text NULL, + "Assessments" text NULL, + "Plan" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_EduAssessment_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "GeneralConsent" table +CREATE TABLE "public"."GeneralConsent" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NOT NULL, + "Value" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_GeneralConsent_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "TherapyProtocol" table +CREATE TABLE "public"."TherapyProtocol" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NOT NULL, + "Doctor_Id" bigint NULL, + "Anamnesis" character varying(2048) NULL, + "MedicalDiagnoses" text NULL, + "FunctionDiagnoses" text NULL, + "Procedures" text NULL, + "SupportingExams" character varying(2048) NULL, + "Instruction" character varying(2048) NULL, + "Evaluation" character varying(2048) NULL, + "WorkCauseStatus" character varying(2048) NULL, + "Frequency" bigint NULL, + "IntervalUnit_Code" character varying(10) NULL, + "Duration" bigint NULL, + "DurationUnit_Code" character varying(10) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_TherapyProtocol_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_TherapyProtocol_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20251021075552.sql b/cmd/main-migration/migrations/20251021075552.sql index ead1e95b..c8f30e60 100644 --- a/cmd/main-migration/migrations/20251021075552.sql +++ b/cmd/main-migration/migrations/20251021075552.sql @@ -1,8 +1,8 @@ --- Rename a column from "DischargeMethod_Code" to "Discharge_Method_Code" -ALTER TABLE "public"."Encounter" RENAME COLUMN "DischargeMethod_Code" TO "Discharge_Method_Code"; --- Modify "Encounter" table -ALTER TABLE "public"."Encounter" ADD COLUMN "Discharge_Date" timestamptz NULL; --- Modify "DeathCause" table -ALTER TABLE "public"."DeathCause" DROP CONSTRAINT "fk_DeathCause_Encounter", ADD CONSTRAINT "fk_Encounter_DeathCause" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; --- Modify "InternalReference" table -ALTER TABLE "public"."InternalReference" DROP CONSTRAINT "fk_InternalReference_Encounter", ADD CONSTRAINT "fk_Encounter_InternalReferences" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Rename a column from "DischargeMethod_Code" to "Discharge_Method_Code" +ALTER TABLE "public"."Encounter" RENAME COLUMN "DischargeMethod_Code" TO "Discharge_Method_Code"; +-- Modify "Encounter" table +ALTER TABLE "public"."Encounter" ADD COLUMN "Discharge_Date" timestamptz NULL; +-- Modify "DeathCause" table +ALTER TABLE "public"."DeathCause" DROP CONSTRAINT "fk_DeathCause_Encounter", ADD CONSTRAINT "fk_Encounter_DeathCause" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "InternalReference" table +ALTER TABLE "public"."InternalReference" DROP CONSTRAINT "fk_InternalReference_Encounter", ADD CONSTRAINT "fk_Encounter_InternalReferences" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251023044432.sql b/cmd/main-migration/migrations/20251023044432.sql index 6a1d962b..e15529e4 100644 --- a/cmd/main-migration/migrations/20251023044432.sql +++ b/cmd/main-migration/migrations/20251023044432.sql @@ -1,90 +1,90 @@ --- Create "AdmEmployeeHist" table -CREATE TABLE "public"."AdmEmployeeHist" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Employee_Id" bigint NULL, - "StartedAt" timestamptz NULL, - "FinishedAt" timestamptz NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_AdmEmployeeHist_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "InstallationPosition" table -CREATE TABLE "public"."InstallationPosition" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Installation_Id" integer NOT NULL, - "Code" character varying(10) NOT NULL, - "Name" character varying(30) NOT NULL, - "HeadStatus" boolean NULL, - "Employee_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_InstallationPosition_Code" UNIQUE ("Code"), - CONSTRAINT "fk_InstallationPosition_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_InstallationPosition_Installation" FOREIGN KEY ("Installation_Id") REFERENCES "public"."Installation" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "ResponsibleDoctorHist" table -CREATE TABLE "public"."ResponsibleDoctorHist" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Doctor_Id" bigint NULL, - "StartedAt" timestamptz NULL, - "FinishedAt" timestamptz NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_ResponsibleDoctorHist_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "SpecialistPosition" table -CREATE TABLE "public"."SpecialistPosition" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Specialist_Id" integer NOT NULL, - "Code" character varying(10) NOT NULL, - "Name" character varying(30) NOT NULL, - "HeadStatus" boolean NULL, - "Employee_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_SpecialistPosition_Code" UNIQUE ("Code"), - CONSTRAINT "fk_SpecialistPosition_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_SpecialistPosition_Specialist" FOREIGN KEY ("Specialist_Id") REFERENCES "public"."Specialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "SubspecialistPosition" table -CREATE TABLE "public"."SubspecialistPosition" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Subspecialist_Id" integer NOT NULL, - "Code" character varying(10) NOT NULL, - "Name" character varying(30) NOT NULL, - "HeadStatus" boolean NULL, - "Employee_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_SubspecialistPosition_Code" UNIQUE ("Code"), - CONSTRAINT "fk_SubspecialistPosition_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_SubspecialistPosition_Subspecialist" FOREIGN KEY ("Subspecialist_Id") REFERENCES "public"."Subspecialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "UnitPosition" table -CREATE TABLE "public"."UnitPosition" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Unit_Id" integer NOT NULL, - "Code" character varying(10) NOT NULL, - "Name" character varying(30) NOT NULL, - "HeadStatus" boolean NULL, - "Employee_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_UnitPosition_Code" UNIQUE ("Code"), - CONSTRAINT "fk_UnitPosition_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_UnitPosition_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); +-- Create "AdmEmployeeHist" table +CREATE TABLE "public"."AdmEmployeeHist" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Employee_Id" bigint NULL, + "StartedAt" timestamptz NULL, + "FinishedAt" timestamptz NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_AdmEmployeeHist_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "InstallationPosition" table +CREATE TABLE "public"."InstallationPosition" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Installation_Id" integer NOT NULL, + "Code" character varying(10) NOT NULL, + "Name" character varying(30) NOT NULL, + "HeadStatus" boolean NULL, + "Employee_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_InstallationPosition_Code" UNIQUE ("Code"), + CONSTRAINT "fk_InstallationPosition_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_InstallationPosition_Installation" FOREIGN KEY ("Installation_Id") REFERENCES "public"."Installation" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "ResponsibleDoctorHist" table +CREATE TABLE "public"."ResponsibleDoctorHist" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Doctor_Id" bigint NULL, + "StartedAt" timestamptz NULL, + "FinishedAt" timestamptz NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_ResponsibleDoctorHist_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "SpecialistPosition" table +CREATE TABLE "public"."SpecialistPosition" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Specialist_Id" integer NOT NULL, + "Code" character varying(10) NOT NULL, + "Name" character varying(30) NOT NULL, + "HeadStatus" boolean NULL, + "Employee_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_SpecialistPosition_Code" UNIQUE ("Code"), + CONSTRAINT "fk_SpecialistPosition_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_SpecialistPosition_Specialist" FOREIGN KEY ("Specialist_Id") REFERENCES "public"."Specialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "SubspecialistPosition" table +CREATE TABLE "public"."SubspecialistPosition" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Subspecialist_Id" integer NOT NULL, + "Code" character varying(10) NOT NULL, + "Name" character varying(30) NOT NULL, + "HeadStatus" boolean NULL, + "Employee_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_SubspecialistPosition_Code" UNIQUE ("Code"), + CONSTRAINT "fk_SubspecialistPosition_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_SubspecialistPosition_Subspecialist" FOREIGN KEY ("Subspecialist_Id") REFERENCES "public"."Subspecialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "UnitPosition" table +CREATE TABLE "public"."UnitPosition" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Unit_Id" integer NOT NULL, + "Code" character varying(10) NOT NULL, + "Name" character varying(30) NOT NULL, + "HeadStatus" boolean NULL, + "Employee_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_UnitPosition_Code" UNIQUE ("Code"), + CONSTRAINT "fk_UnitPosition_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_UnitPosition_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20251024034832.sql b/cmd/main-migration/migrations/20251024034832.sql index 05794c82..11620cd2 100644 --- a/cmd/main-migration/migrations/20251024034832.sql +++ b/cmd/main-migration/migrations/20251024034832.sql @@ -1,12 +1,12 @@ --- Modify "Doctor" table -ALTER TABLE "public"."Doctor" ADD COLUMN "Code" character varying(20) NULL, ADD CONSTRAINT "uni_Doctor_Code" UNIQUE ("Code"); --- Modify "Laborant" table -ALTER TABLE "public"."Laborant" ADD COLUMN "Code" character varying(20) NULL, ADD CONSTRAINT "uni_Laborant_Code" UNIQUE ("Code"); --- Modify "Midwife" table -ALTER TABLE "public"."Midwife" ADD COLUMN "Code" character varying(20) NULL, ADD CONSTRAINT "uni_Midwife_Code" UNIQUE ("Code"); --- Modify "Nurse" table -ALTER TABLE "public"."Nurse" ADD COLUMN "Code" character varying(20) NULL, ADD CONSTRAINT "uni_Nurse_Code" UNIQUE ("Code"); --- Modify "Nutritionist" table -ALTER TABLE "public"."Nutritionist" ADD COLUMN "Code" character varying(20) NULL, ADD CONSTRAINT "uni_Nutritionist_Code" UNIQUE ("Code"); --- Modify "Pharmacist" table -ALTER TABLE "public"."Pharmacist" ADD COLUMN "Code" character varying(20) NULL, ADD CONSTRAINT "uni_Pharmacist_Code" UNIQUE ("Code"); +-- Modify "Doctor" table +ALTER TABLE "public"."Doctor" ADD COLUMN "Code" character varying(20) NULL, ADD CONSTRAINT "uni_Doctor_Code" UNIQUE ("Code"); +-- Modify "Laborant" table +ALTER TABLE "public"."Laborant" ADD COLUMN "Code" character varying(20) NULL, ADD CONSTRAINT "uni_Laborant_Code" UNIQUE ("Code"); +-- Modify "Midwife" table +ALTER TABLE "public"."Midwife" ADD COLUMN "Code" character varying(20) NULL, ADD CONSTRAINT "uni_Midwife_Code" UNIQUE ("Code"); +-- Modify "Nurse" table +ALTER TABLE "public"."Nurse" ADD COLUMN "Code" character varying(20) NULL, ADD CONSTRAINT "uni_Nurse_Code" UNIQUE ("Code"); +-- Modify "Nutritionist" table +ALTER TABLE "public"."Nutritionist" ADD COLUMN "Code" character varying(20) NULL, ADD CONSTRAINT "uni_Nutritionist_Code" UNIQUE ("Code"); +-- Modify "Pharmacist" table +ALTER TABLE "public"."Pharmacist" ADD COLUMN "Code" character varying(20) NULL, ADD CONSTRAINT "uni_Pharmacist_Code" UNIQUE ("Code"); diff --git a/cmd/main-migration/migrations/20251024074315.sql b/cmd/main-migration/migrations/20251024074315.sql index 99b3b76b..c2fd95d9 100644 --- a/cmd/main-migration/migrations/20251024074315.sql +++ b/cmd/main-migration/migrations/20251024074315.sql @@ -1,2 +1,2 @@ --- Modify "Employee" table -ALTER TABLE "public"."Employee" DROP COLUMN "Division_Code"; +-- Modify "Employee" table +ALTER TABLE "public"."Employee" DROP COLUMN "Division_Code"; diff --git a/cmd/main-migration/migrations/20251025013451.sql b/cmd/main-migration/migrations/20251025013451.sql index 0296b0f5..9a36b294 100644 --- a/cmd/main-migration/migrations/20251025013451.sql +++ b/cmd/main-migration/migrations/20251025013451.sql @@ -1,4 +1,4 @@ --- Modify "Patient" table -ALTER TABLE "public"."Patient" ADD COLUMN "RegisteredBy_User_Name" character varying(100) NULL; --- Modify "Person" table -ALTER TABLE "public"."Person" ADD COLUMN "Confidence" character varying(512) NULL, ADD COLUMN "MaritalStatus_Code" character varying(10) NULL; +-- Modify "Patient" table +ALTER TABLE "public"."Patient" ADD COLUMN "RegisteredBy_User_Name" character varying(100) NULL; +-- Modify "Person" table +ALTER TABLE "public"."Person" ADD COLUMN "Confidence" character varying(512) NULL, ADD COLUMN "MaritalStatus_Code" character varying(10) NULL; diff --git a/cmd/main-migration/migrations/20251025013609.sql b/cmd/main-migration/migrations/20251025013609.sql index 9793d86a..2084c529 100644 --- a/cmd/main-migration/migrations/20251025013609.sql +++ b/cmd/main-migration/migrations/20251025013609.sql @@ -1,12 +1,12 @@ --- Create "VclaimMember" table -CREATE TABLE "public"."VclaimMember" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "CardNumber" character varying(20) NULL, - "Person_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_VclaimMember_CardNumber" UNIQUE ("CardNumber"), - CONSTRAINT "fk_Person_VclaimMember" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); +-- Create "VclaimMember" table +CREATE TABLE "public"."VclaimMember" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "CardNumber" character varying(20) NULL, + "Person_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_VclaimMember_CardNumber" UNIQUE ("CardNumber"), + CONSTRAINT "fk_Person_VclaimMember" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20251027075128.sql b/cmd/main-migration/migrations/20251027075128.sql index 6d583866..7077e18a 100644 --- a/cmd/main-migration/migrations/20251027075128.sql +++ b/cmd/main-migration/migrations/20251027075128.sql @@ -1,2 +1,2 @@ --- Modify "Encounter" table -ALTER TABLE "public"."Encounter" ADD COLUMN "StartedAt" timestamptz NULL, ADD COLUMN "FinishedAt" timestamptz NULL, ADD COLUMN "RefType_Code" text NULL, ADD COLUMN "NewStatus" boolean NULL; +-- Modify "Encounter" table +ALTER TABLE "public"."Encounter" ADD COLUMN "StartedAt" timestamptz NULL, ADD COLUMN "FinishedAt" timestamptz NULL, ADD COLUMN "RefType_Code" text NULL, ADD COLUMN "NewStatus" boolean NULL; diff --git a/cmd/main-migration/migrations/20251027091406.sql b/cmd/main-migration/migrations/20251027091406.sql index 25df3058..1783d48a 100644 --- a/cmd/main-migration/migrations/20251027091406.sql +++ b/cmd/main-migration/migrations/20251027091406.sql @@ -1,2 +1,2 @@ --- Modify "Patient" table -ALTER TABLE "public"."Patient" ADD COLUMN "Parent_Number" character varying(15) NULL, ADD CONSTRAINT "fk_Patient_Parent" FOREIGN KEY ("Parent_Number") REFERENCES "public"."Patient" ("Number") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "Patient" table +ALTER TABLE "public"."Patient" ADD COLUMN "Parent_Number" character varying(15) NULL, ADD CONSTRAINT "fk_Patient_Parent" FOREIGN KEY ("Parent_Number") REFERENCES "public"."Patient" ("Number") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251102002037.sql b/cmd/main-migration/migrations/20251102002037.sql index 14a39ae1..7caa59b9 100644 --- a/cmd/main-migration/migrations/20251102002037.sql +++ b/cmd/main-migration/migrations/20251102002037.sql @@ -1,6 +1,6 @@ --- Modify "McuOrder" table -ALTER TABLE "public"."McuOrder" ADD COLUMN "Scope_Code" character varying(10) NULL; --- Create index "idx_McuOrder_Scope_Code" to table: "McuOrder" -CREATE INDEX "idx_McuOrder_Scope_Code" ON "public"."McuOrder" ("Scope_Code"); --- Create index "idx_McuSrcCategory_Scope_Code" to table: "McuSrcCategory" -CREATE INDEX "idx_McuSrcCategory_Scope_Code" ON "public"."McuSrcCategory" ("Scope_Code"); +-- Modify "McuOrder" table +ALTER TABLE "public"."McuOrder" ADD COLUMN "Scope_Code" character varying(10) NULL; +-- Create index "idx_McuOrder_Scope_Code" to table: "McuOrder" +CREATE INDEX "idx_McuOrder_Scope_Code" ON "public"."McuOrder" ("Scope_Code"); +-- Create index "idx_McuSrcCategory_Scope_Code" to table: "McuSrcCategory" +CREATE INDEX "idx_McuSrcCategory_Scope_Code" ON "public"."McuSrcCategory" ("Scope_Code"); diff --git a/cmd/main-migration/migrations/20251102091932.sql b/cmd/main-migration/migrations/20251102091932.sql index f10eadd3..a492130e 100644 --- a/cmd/main-migration/migrations/20251102091932.sql +++ b/cmd/main-migration/migrations/20251102091932.sql @@ -1,2 +1,2 @@ --- Rename a column from "McuUrgencyLevel_Code" to "UrgencyLevel_Code" -ALTER TABLE "public"."McuOrder" RENAME COLUMN "McuUrgencyLevel_Code" TO "UrgencyLevel_Code"; +-- Rename a column from "McuUrgencyLevel_Code" to "UrgencyLevel_Code" +ALTER TABLE "public"."McuOrder" RENAME COLUMN "McuUrgencyLevel_Code" TO "UrgencyLevel_Code"; diff --git a/cmd/main-migration/migrations/20251103081637.sql b/cmd/main-migration/migrations/20251103081637.sql index ca898d90..3232c88b 100644 --- a/cmd/main-migration/migrations/20251103081637.sql +++ b/cmd/main-migration/migrations/20251103081637.sql @@ -1,17 +1,17 @@ --- Create "ControlLetter" table -CREATE TABLE "public"."ControlLetter" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Unit_Id" bigint NULL, - "Specialist_Id" bigint NULL, - "Subspecialist_Id" bigint NULL, - "Date" timestamptz NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_ControlLetter_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_ControlLetter_Specialist" FOREIGN KEY ("Specialist_Id") REFERENCES "public"."Specialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_ControlLetter_Subspecialist" FOREIGN KEY ("Subspecialist_Id") REFERENCES "public"."Subspecialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_ControlLetter_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); +-- Create "ControlLetter" table +CREATE TABLE "public"."ControlLetter" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Unit_Id" bigint NULL, + "Specialist_Id" bigint NULL, + "Subspecialist_Id" bigint NULL, + "Date" timestamptz NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_ControlLetter_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_ControlLetter_Specialist" FOREIGN KEY ("Specialist_Id") REFERENCES "public"."Specialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_ControlLetter_Subspecialist" FOREIGN KEY ("Subspecialist_Id") REFERENCES "public"."Subspecialist" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_ControlLetter_Unit" FOREIGN KEY ("Unit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20251104042334.sql b/cmd/main-migration/migrations/20251104042334.sql index 7628d821..ac661e10 100644 --- a/cmd/main-migration/migrations/20251104042334.sql +++ b/cmd/main-migration/migrations/20251104042334.sql @@ -1,2 +1,2 @@ --- Modify "Chemo" table -ALTER TABLE "public"."Chemo" DROP COLUMN "Class_Code", ADD COLUMN "Bed" character varying(1024) NULL, ADD COLUMN "Needs" character varying(2048) NULL; +-- Modify "Chemo" table +ALTER TABLE "public"."Chemo" DROP COLUMN "Class_Code", ADD COLUMN "Bed" character varying(1024) NULL, ADD COLUMN "Needs" character varying(2048) NULL; diff --git a/cmd/main-migration/migrations/20251104043530.sql b/cmd/main-migration/migrations/20251104043530.sql index 0d34792a..7e76865c 100644 --- a/cmd/main-migration/migrations/20251104043530.sql +++ b/cmd/main-migration/migrations/20251104043530.sql @@ -1,19 +1,19 @@ --- Modify "Ambulatory" table -ALTER TABLE "public"."Ambulatory" DROP CONSTRAINT "fk_Ambulatory_Encounter", ADD COLUMN "VisitMode_Code" text NULL, ADD CONSTRAINT "fk_Encounter_Ambulatory" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; --- Modify "Emergency" table -ALTER TABLE "public"."Emergency" DROP CONSTRAINT "fk_Emergency_Encounter", ADD CONSTRAINT "fk_Encounter_Emergency" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; --- Modify "Inpatient" table -ALTER TABLE "public"."Inpatient" DROP CONSTRAINT "fk_Inpatient_Encounter", ADD CONSTRAINT "fk_Encounter_Inpatient" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; --- Create "Rehab" table -CREATE TABLE "public"."Rehab" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Doctor_Id" bigint NULL, - "AllocatedVisitCount" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Rehab_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_Rehab_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); +-- Modify "Ambulatory" table +ALTER TABLE "public"."Ambulatory" DROP CONSTRAINT "fk_Ambulatory_Encounter", ADD COLUMN "VisitMode_Code" text NULL, ADD CONSTRAINT "fk_Encounter_Ambulatory" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "Emergency" table +ALTER TABLE "public"."Emergency" DROP CONSTRAINT "fk_Emergency_Encounter", ADD CONSTRAINT "fk_Encounter_Emergency" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "Inpatient" table +ALTER TABLE "public"."Inpatient" DROP CONSTRAINT "fk_Inpatient_Encounter", ADD CONSTRAINT "fk_Encounter_Inpatient" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Create "Rehab" table +CREATE TABLE "public"."Rehab" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Doctor_Id" bigint NULL, + "AllocatedVisitCount" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Rehab_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Rehab_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20251104080952.sql b/cmd/main-migration/migrations/20251104080952.sql index 24fcc6a5..14e62172 100644 --- a/cmd/main-migration/migrations/20251104080952.sql +++ b/cmd/main-migration/migrations/20251104080952.sql @@ -1,2 +1,2 @@ --- Modify "ControlLetter" table -ALTER TABLE "public"."ControlLetter" ADD COLUMN "Doctor_Id" bigint NULL, ADD CONSTRAINT "fk_ControlLetter_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "ControlLetter" table +ALTER TABLE "public"."ControlLetter" ADD COLUMN "Doctor_Id" bigint NULL, ADD CONSTRAINT "fk_ControlLetter_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251104084135.sql b/cmd/main-migration/migrations/20251104084135.sql index 8c50d914..fa2c3276 100644 --- a/cmd/main-migration/migrations/20251104084135.sql +++ b/cmd/main-migration/migrations/20251104084135.sql @@ -1,17 +1,17 @@ --- Create "ChemoProtocol" table -CREATE TABLE "public"."ChemoProtocol" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Encounter_Id" bigint NULL, - "Patient_Weight" numeric NULL, - "Patient_Height" numeric NULL, - "Diagnoses" text NULL, - "Duration" bigint NULL, - "DurationUnit_Code" character varying(10) NULL, - "StartDate" timestamptz NULL, - "EndDate" timestamptz NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_ChemoProtocol_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); +-- Create "ChemoProtocol" table +CREATE TABLE "public"."ChemoProtocol" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Patient_Weight" numeric NULL, + "Patient_Height" numeric NULL, + "Diagnoses" text NULL, + "Duration" bigint NULL, + "DurationUnit_Code" character varying(10) NULL, + "StartDate" timestamptz NULL, + "EndDate" timestamptz NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_ChemoProtocol_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20251105044629.sql b/cmd/main-migration/migrations/20251105044629.sql index 24ba9d05..48780f06 100644 --- a/cmd/main-migration/migrations/20251105044629.sql +++ b/cmd/main-migration/migrations/20251105044629.sql @@ -1,38 +1,38 @@ --- Create "AntibioticSrcCategory" table -CREATE TABLE "public"."AntibioticSrcCategory" ( - "Id" serial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(20) NULL, - "Name" character varying(50) NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_AntibioticSrcCategory_Code" UNIQUE ("Code") -); --- Create "AntibioticSrc" table -CREATE TABLE "public"."AntibioticSrc" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "Code" character varying(20) NULL, - "Name" character varying(50) NULL, - "AntibioticSrcCategory_Code" character varying(20) NULL, - "Item_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "uni_AntibioticSrc_Code" UNIQUE ("Code"), - CONSTRAINT "fk_AntibioticSrc_AntibioticSrcCategory" FOREIGN KEY ("AntibioticSrcCategory_Code") REFERENCES "public"."AntibioticSrcCategory" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_AntibioticSrc_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); --- Create "AntibioticInUse" table -CREATE TABLE "public"."AntibioticInUse" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "McuOrder_Id" bigint NULL, - "AntibioticSrc_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_AntibioticInUse_AntibioticSrc" FOREIGN KEY ("AntibioticSrc_Id") REFERENCES "public"."AntibioticSrc" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_AntibioticInUse_McuOrder" FOREIGN KEY ("McuOrder_Id") REFERENCES "public"."McuOrder" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); +-- Create "AntibioticSrcCategory" table +CREATE TABLE "public"."AntibioticSrcCategory" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(20) NULL, + "Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_AntibioticSrcCategory_Code" UNIQUE ("Code") +); +-- Create "AntibioticSrc" table +CREATE TABLE "public"."AntibioticSrc" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(20) NULL, + "Name" character varying(50) NULL, + "AntibioticSrcCategory_Code" character varying(20) NULL, + "Item_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_AntibioticSrc_Code" UNIQUE ("Code"), + CONSTRAINT "fk_AntibioticSrc_AntibioticSrcCategory" FOREIGN KEY ("AntibioticSrcCategory_Code") REFERENCES "public"."AntibioticSrcCategory" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_AntibioticSrc_Item" FOREIGN KEY ("Item_Id") REFERENCES "public"."Item" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "AntibioticInUse" table +CREATE TABLE "public"."AntibioticInUse" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "McuOrder_Id" bigint NULL, + "AntibioticSrc_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_AntibioticInUse_AntibioticSrc" FOREIGN KEY ("AntibioticSrc_Id") REFERENCES "public"."AntibioticSrc" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_AntibioticInUse_McuOrder" FOREIGN KEY ("McuOrder_Id") REFERENCES "public"."McuOrder" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20251105121808.sql b/cmd/main-migration/migrations/20251105121808.sql index 41c1edf0..2010b216 100644 --- a/cmd/main-migration/migrations/20251105121808.sql +++ b/cmd/main-migration/migrations/20251105121808.sql @@ -1,2 +1,2 @@ --- Modify "AntibioticSrc" table -ALTER TABLE "public"."AntibioticSrc" DROP COLUMN "Item_Id"; +-- Modify "AntibioticSrc" table +ALTER TABLE "public"."AntibioticSrc" DROP COLUMN "Item_Id"; diff --git a/cmd/main-migration/migrations/20251106035305.sql b/cmd/main-migration/migrations/20251106035305.sql index d2ab1e94..a85728fc 100644 --- a/cmd/main-migration/migrations/20251106035305.sql +++ b/cmd/main-migration/migrations/20251106035305.sql @@ -1,4 +1,4 @@ --- Modify "Doctor" table -ALTER TABLE "public"."Doctor" ADD COLUMN "SIP_ExpiredDate" timestamptz NULL, ADD COLUMN "Unit_Code" character varying(10) NULL, ADD COLUMN "Specialist_Code" character varying(10) NULL, ADD COLUMN "Subspecialist_Code" character varying(10) NULL, ADD CONSTRAINT "uni_Doctor_Specialist_Code" UNIQUE ("Specialist_Code"), ADD CONSTRAINT "uni_Doctor_Subspecialist_Code" UNIQUE ("Subspecialist_Code"), ADD CONSTRAINT "uni_Doctor_Unit_Code" UNIQUE ("Unit_Code"); --- Modify "Employee" table -ALTER TABLE "public"."Employee" ADD COLUMN "Contract_ExpiredDate" timestamptz NULL; +-- Modify "Doctor" table +ALTER TABLE "public"."Doctor" ADD COLUMN "SIP_ExpiredDate" timestamptz NULL, ADD COLUMN "Unit_Code" character varying(10) NULL, ADD COLUMN "Specialist_Code" character varying(10) NULL, ADD COLUMN "Subspecialist_Code" character varying(10) NULL, ADD CONSTRAINT "uni_Doctor_Specialist_Code" UNIQUE ("Specialist_Code"), ADD CONSTRAINT "uni_Doctor_Subspecialist_Code" UNIQUE ("Subspecialist_Code"), ADD CONSTRAINT "uni_Doctor_Unit_Code" UNIQUE ("Unit_Code"); +-- Modify "Employee" table +ALTER TABLE "public"."Employee" ADD COLUMN "Contract_ExpiredDate" timestamptz NULL; diff --git a/cmd/main-migration/migrations/20251106040137.sql b/cmd/main-migration/migrations/20251106040137.sql index f9cb71cc..3b702be1 100644 --- a/cmd/main-migration/migrations/20251106040137.sql +++ b/cmd/main-migration/migrations/20251106040137.sql @@ -1,2 +1,2 @@ --- Modify "Doctor" table -ALTER TABLE "public"."Doctor" DROP CONSTRAINT "uni_Doctor_Specialist_Code", DROP CONSTRAINT "uni_Doctor_Subspecialist_Code", DROP CONSTRAINT "uni_Doctor_Unit_Code"; +-- Modify "Doctor" table +ALTER TABLE "public"."Doctor" DROP CONSTRAINT "uni_Doctor_Specialist_Code", DROP CONSTRAINT "uni_Doctor_Subspecialist_Code", DROP CONSTRAINT "uni_Doctor_Unit_Code"; diff --git a/cmd/main-migration/migrations/20251106041333.sql b/cmd/main-migration/migrations/20251106041333.sql index 0e4cc5c0..c33a9c92 100644 --- a/cmd/main-migration/migrations/20251106041333.sql +++ b/cmd/main-migration/migrations/20251106041333.sql @@ -1,2 +1,2 @@ --- Modify "Nurse" table -ALTER TABLE "public"."Nurse" ADD COLUMN "Unit_Code" character varying(10) NULL, ADD COLUMN "Infra_Code" character varying(10) NULL; +-- Modify "Nurse" table +ALTER TABLE "public"."Nurse" ADD COLUMN "Unit_Code" character varying(10) NULL, ADD COLUMN "Infra_Code" character varying(10) NULL; diff --git a/cmd/main-migration/migrations/20251106042006.sql b/cmd/main-migration/migrations/20251106042006.sql index a3f2f609..1e95edc7 100644 --- a/cmd/main-migration/migrations/20251106042006.sql +++ b/cmd/main-migration/migrations/20251106042006.sql @@ -1,2 +1,2 @@ --- Modify "SpecialistIntern" table -ALTER TABLE "public"."SpecialistIntern" ADD COLUMN "Specialist_Code" character varying(10) NULL, ADD COLUMN "Subspecialist_Code" character varying(10) NULL; +-- Modify "SpecialistIntern" table +ALTER TABLE "public"."SpecialistIntern" ADD COLUMN "Specialist_Code" character varying(10) NULL, ADD COLUMN "Subspecialist_Code" character varying(10) NULL; From 827c40dd069f818c6eb231cfa9d0b8a790734c12 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 6 Nov 2025 12:18:16 +0700 Subject: [PATCH 079/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 97 ++++--------------------- 1 file changed, 15 insertions(+), 82 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index e8641831..bb6413e8 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,6 +1,8 @@ -h1:lDfnkzBVHYhHwd5okbIRgBk5zo9kmeAK9Ideg1SsSw4= -20250904105930.sql h1:Vv4vCurl7m7/ZB6TjRpkubHpQ4RYwSUn0QHdzfoGpzY=20250904141448.sql h1:FYCHH9Os4KkrZMDu/jR8FMP+wLMRW+Mb0PkLU/9BRDg= -20250908062237.sql h1:oanBpKZd+akPu2I/xYhUSbd0G5tAFbXzKLER/Zs8ENI=20250908062323.sql h1:miNG9COddXkD1jGTgaROMAZ618eT6oiLGiJhXWnQwhE= +h1:PwMC7qEOPDdica7/V7qlIoAcAg48skkmfckAfhLgXHk= +20250904105930.sql h1:Vv4vCurl7m7/ZB6TjRpkubHpQ4RYwSUn0QHdzfoGpzY= +20250904141448.sql h1:FYCHH9Os4KkrZMDu/jR8FMP+wLMRW+Mb0PkLU/9BRDg= +20250908062237.sql h1:oanBpKZd+akPu2I/xYhUSbd0G5tAFbXzKLER/Zs8ENI= +20250908062323.sql h1:miNG9COddXkD1jGTgaROMAZ618eT6oiLGiJhXWnQwhE= 20250908073811.sql h1:gOi5cnGG1htlpfizybYmUIT0vYjZTBfXiI0nPSYK2u8= 20250908073839.sql h1:cWNDA4YikjoOteAJuNLFILjQUJPFB6o8Wxreiek4QyI= 20250910055902.sql h1:nxxOGnU0BbH/v3IPgeIOXOwH8d3tKomw7h6FTeMnnBs= @@ -64,82 +66,13 @@ h1:lDfnkzBVHYhHwd5okbIRgBk5zo9kmeAK9Ideg1SsSw4= 20251102091932.sql h1:A6y9j4wAqm4/HfMDxhpy/ChDn3UNRVN99KGgSCX+e18= 20251103081637.sql h1:RFqJNhJItSwJQaMP5IcQ14mL7eQ3EJjGZua9zLWzwMU= 20251104042334.sql h1:BbjLAwImggvI6489FQgD+S/AaafeiZut8k19TdH7XUE= -20251104043530.sq -h1:97IUzyfSecffgKmYYs+a+HW5thHnIY3OuWDTQYy3hGQ= -20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= -20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= -20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= -20250908062323.sql h1:oXl6Z143tOpIl4EfP4B8JNU8LrMvVmHEtCgAfiB4gs8= -20250908073811.sql h1:m2aNXfnGxnLq1+rVWrh4f60q7fhyhV3gEwNu/OIqQlE= -20250908073839.sql h1:cPk54xjLdMs26uY8ZHjNWLuyfAMzV7Zb0/9oJQrsw04= -20250910055902.sql h1:5xwjAV6QbtZT9empTJKfhyAjdknbHzb15B0Ku5dzqtQ= -20250915123412.sql h1:D83xaU2YlDEd21HLup/YQpQ2easMToYCyy/oK6AFgQs= -20250916043819.sql h1:ekoTJsBqQZ8G8n0qJ03d13+eoNoc7sAUEQGA5D/CCxk= -20250917040616.sql h1:zoCnmcXuM7AVv85SmN7RmFglCgJnoDmpRWExH0LAc9Q= -20250917040751.sql h1:J1xyRrh32y1+lezwAyNwPcUQ6ABBSgbvzNLva4SVdQU= -20250917045138.sql h1:jKe1Z0uOLG4SGBYM+S/3P+/zMPztmgoderD5swnMuCg= -20250917093645.sql h1:cNI3Pbz1R3LxvIXLuexafJFCXUXrmuFCgXXJ2sG+FW0= -20250918073552.sql h1:RJ1SvMzP6aeWnoPVD3eVAmIQOkcp6Php8z3QRri6v4g= -20250918073742.sql h1:+cEsnJTJFybe2fR69ZoOiX2R6c6iITl4m6WTZ1hjyzY= -20250918074745.sql h1:2hNVQCXF/dVYXAh+T/7oBFgERGWxzVb2FXJjwkFWGCI= -20250923025134.sql h1:Ykz/qpHiGDXPsCsWTjydQFVSibZP2D+h2fIeb2h2JGA= -20250924051317.sql h1:yQuW6SwJxIOM5fcxeAaie5lSm1oLysU/C2hH2xNCVoQ= -20250929034321.sql h1:101FJ8VH12mrZWlt/X1gvKUGOhoiF8tFbjiapAjnHzg= -20250929034428.sql h1:i+pROD9p+g5dOmmZma6WF/0Hw5g3Ha28NN85iTo1K34= -20250930025550.sql h1:+F+CsCUXD/ql0tHGEow70GhPBX1ZybVn+bh/T4YMh7Y= -20250930140351.sql h1:9AAEG1AnOAH+o0+oHL5G7I8vqlWOhwRlCGyyCpT/y1Q= -20251002085604.sql h1:3xZ68eYp4urXRnvotNH1XvG2mYOSDV/j3zHEZ/txg5E= -20251003032030.sql h1:HB+mQ2lXMNomHDpaRhB/9IwYI9/YiDO5eOJ+nAQH/jw= -20251005060450.sql h1:LbtCE2b+8osM3CvnmQJH1uCPtn+d7WchsslBOz8bL3Q= -20251006041122.sql h1:MlS7f21z06sutnf9dIekt5fuHJr4lgcQ4uCuCXAGsfc= -20251006045658.sql h1:3FmGCPCzjgMPdWDRodZTsx3KVaodd9zB9ilib69aewk= -20251006045928.sql h1:Z5g31PmnzNwk/OKdODcxZGm8fjJQdMFK32Xfnt3bRHg= -20251007022859.sql h1:FO03zEfaNEk/aXwY81d5Lp3MoBB9kPQuXlXJ4BPiSR8= -20251008031337.sql h1:l+sxUAGvcTfj3I6kAFHo+T6AYodC9k9GkR+jaKO2xXc= -20251008031554.sql h1:AqrVfIhSzY3PCy8ZlP5W91wn2iznfIuj5qQfubp6/94= -20251008052346.sql h1:nxnXmooIJ6r1mmzwnw+6efxLfc/k9h2aE6RMptPRons= -20251008073620.sql h1:6YsJp1W4SmQJ1lxpqF27BBlDC1zqhw7Yhc7pLzQTY6M= -20251009042854.sql h1:nkBV+R6j0fg7/JY6wH3eb5Vv0asJLnXmb6lINfT/GLQ= -20251009052657.sql h1:EPvdsib5rzCGPryd10HShGKvFPwM/R5S2lIVwtYxpms= -20251010031743.sql h1:T8IZmx8/btRFKLzTe78MzcBsPJNodnLvB0tby9QkirQ= -20251010070721.sql h1:5NQUk/yOV6sABLCB7swx++YIOyJe6MnU+yt1nRzde5w= -20251010072711.sql h1:ZJNqR2piyu8xJhBvVABSlnGEoKSKae3wuEs+wshPe4k= -20251013044536.sql h1:0Xjw8fNILiT8nnfrJDZgQnPf3dntmIoilbapnih8AE4= -20251013051438.sql h1:lfSuw5mgJnePBJamvhZ81osFIouXeiIEiSZ/evdwo48= -20251013081808.sql h1:ijgjNX08G6GBjA/ks8EKtb7P7Y7Cg7zbhqEOruGnv6M= -20251014060047.sql h1:0jqj49WTtneEIMQDBoo4c095ZGi8sCrA8NnHBrPU6D8= -20251014063537.sql h1:VZLXol0PTsTW21Epg6vBPsztWkDtcxup9F/z88EGgIg= -20251014063720.sql h1:2HVUyCV0ud3BJJDH2GEKZN/+IWLFPCsN1KqhP6csO14= -20251015045455.sql h1:MeLWmMhAOAz8b15Dd7IAQnt6JxjSml02XCXK22C0Lpg= -20251016010845.sql h1:4BncQdDOasRZJkzVJrSJJA7091A9VPNVx/faUCUPhBM= -20251016011023.sql h1:9JB9eFZKURK5RoCVDKR6glSvdJ8NTXrN7K/4q51zkz4= -20251016062912.sql h1:ACNn0fe+EMqUt3hoY+Dr3uqAV/QICBa1+mIW7fUc9Fk= -20251017060617.sql h1:4T3t9ifWrEQTPMSM0XJ98pF7Qdt+UfgtMui17bhrnWI= -20251017082207.sql h1:8vLG1l/saRRMHXkyA4nelJyjaSddhZd6r7R+Uo4JS/c= -20251018032635.sql h1:2xey5gnO3y2XSOrU8MLlIfoylPKbRGDRtHDD07B3MbQ= -20251018040322.sql h1:k/pdNiSoT8zFPqNQ/avOD0vYkNh3BTD64IlHrfVXr7I= -20251019093915.sql h1:hFcQE0y+p5dZiVwePGsRGto9m/q6kJNiUZbVDd5Rnjk= -20251020062553.sql h1:Iw7hulcm5iRQlfW+ygA4iTPxLqkxx6h9vXMXEwUAHKs= -20251021041042.sql h1:wMgSivBV2A0NDcsLmKGIp0kMcVh2IODSG9b4dgzCaOM= -20251021075552.sql h1:8gfSMAglflNO6L0sSzxFNEubYN8/O4thT7OQT+WH+3M= -20251023044432.sql h1:MkvajJs3bfk9+wHvQ43/ccAluJEBARm1gWr1u92ccLA= -20251024034832.sql h1:x3s3VEVYLOSKLAFxJGb2+c1FyTMMvPE+9k4Ew7rKQaI= -20251024074315.sql h1:EjAjelgi5qAfcRq/8vPTlGGYHvAKxNTllm8f0SzZDns= -20251025013451.sql h1:6hnuIiwYiG+6nLhOY/+Yyn+I6ZCFNRZxrJNqBV6HLqE= -20251025013609.sql h1:evPJaTD8WxYRMOJZHkSr7ONLx9PYxT+ankzQt9c/sJ0= -20251027075128.sql h1:/iFQBM1sytjqpyQSOx61q33gnorMgxTiFVSuL6bQqsM= -20251027091406.sql h1:eCZGtUkxAzEAqpC9UsGpP8Df9mS0DEOqSl885LgqpvM= -20251102002037.sql h1:lFJbuoZ2LMQnUNGdcwHVY3Xlfslgzu9t2WByT8yfOZI= -20251102091932.sql h1:rmdhb5m+P+fU8jROBZNyeYgZKuQvucsuljXv4ZVzvks= -20251103081637.sql h1:tf3BcwTeIw+oxMEisKDDfyKnBfalTLs8b0PJA8JWYxY= -20251104042334.sql h1:7PDMWOhmJywolAPKFZ14XaDBeMvcxShaXFN2IemNtzk= -20251104043530.sql h1:qvYVp3ysPf27f1BcoRNCFGovxuVE12lg9d6Xzda6zWU= -20251104080952.sql h1:avghpv1n3yaCDR/TA0X+hgxDGoLBQGu/GJUwj4VT/Ic= -20251104084135.sql h1:rg+eRE5/5sYWR7z+Xyn0zKw8rr8P/oWxF0xhcNVnNec= -20251105044629.sql h1:4NU27HeKUNFsV82LacnwmnCSAH0pSbZR9J9/ZESRs6M= -20251105121808.sql h1:fii6LjqWYjrm/pEIqttfvJI6QEUL49gque8wYHh1+yI= -20251106035305.sql h1:oQ7BwnxPuwY2q98adIVc+lNwL/Sz1OceLJeClDo9/TI= -20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= -20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= -20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -20251106050412.sql h1:MiEMJ1HCFYnalKuq3Z38xJeogfBAMqsTv2sG4EF8dDw= +20251104043530.sql h1:Y0sOQqgnHxd5vKPA4+4fAGGdWCv6duKAYgHnjRJZUIc= +20251104080952.sql h1:hDHzFs/k+NhPYJ64ifbVp+nTJLMCG5MIMJU1zBMP0V0= +20251104084135.sql h1:p97mW1MPtPrMWJKy/KZqvymMO/vlelnXp43N9bZVCTI= +20251105044629.sql h1:E4BkVD3YyWvd0D18jA57EwTmkeoAMUWrdTCEwdPHA1U= +20251105121808.sql h1:kyMNzaJLyVtS1QpkX7cnVvhQmrrIE8m3GxUWwrMeyUo= +20251106035305.sql h1:VInVWBP1xpEhVIm1+ymuPzu0joxV2oS4qkNIyQvmTSU= +20251106040137.sql h1:7glRO1VAgq89H6zhM6M50iLwMT0w2sb96DUGrvfXZo4= +20251106041333.sql h1:/2wLmx8awSYhVpusDPAI+VeYJOLeLCWsNaF79gl1lg8= +20251106042006.sql h1:05AZyIbRJi1W08ETScADyAhI3elW0bXaWizlCpDfFCI= +20251106050412.sql h1:0102Z6ifzlwDjvU9jveuzULJvlo+Lc/UwyCeHUrwx18= From 7037ceae558b674cbdf64364579823995ecacc9f Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Thu, 6 Nov 2025 12:28:53 +0700 Subject: [PATCH 080/329] feat/trx-orders: added AntibioticSrc flow --- .../main-handler/antibiotic-src/handler.go | 71 +++++ .../interface/main-handler/main-handler.go | 2 + .../main-use-case/antibiotic-src/case.go | 280 ++++++++++++++++++ .../main-use-case/antibiotic-src/helper.go | 30 ++ .../main-use-case/antibiotic-src/lib.go | 140 +++++++++ .../antibiotic-src/middleware-runner.go | 111 +++++++ .../main-use-case/antibiotic-src/tycovar.go | 44 +++ 7 files changed, 678 insertions(+) create mode 100644 internal/interface/main-handler/antibiotic-src/handler.go create mode 100644 internal/use-case/main-use-case/antibiotic-src/case.go create mode 100644 internal/use-case/main-use-case/antibiotic-src/helper.go create mode 100644 internal/use-case/main-use-case/antibiotic-src/lib.go create mode 100644 internal/use-case/main-use-case/antibiotic-src/middleware-runner.go create mode 100644 internal/use-case/main-use-case/antibiotic-src/tycovar.go diff --git a/internal/interface/main-handler/antibiotic-src/handler.go b/internal/interface/main-handler/antibiotic-src/handler.go new file mode 100644 index 00000000..506472f8 --- /dev/null +++ b/internal/interface/main-handler/antibiotic-src/handler.go @@ -0,0 +1,71 @@ +package antibioticsrc + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/antibiotic-src" + u "simrs-vx/internal/use-case/main-use-case/antibiotic-src" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint16(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint16(id) + 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 = uint16(id) + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} \ No newline at end of file diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index ffbdd9ab..1948447d 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -64,6 +64,7 @@ import ( zlc "simrs-vx/pkg/zerolog-ctx" /******************** sources ********************/ + antibioticsrc "simrs-vx/internal/interface/main-handler/antibiotic-src" antibioticsrccat "simrs-vx/internal/interface/main-handler/antibiotic-src-category" device "simrs-vx/internal/interface/main-handler/device" diagnosesrc "simrs-vx/internal/interface/main-handler/diagnose-src" @@ -135,6 +136,7 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/medicine-mix", medicicinemix.O) hc.RegCrud(r, "/v1/medicine-mix-item", medicicinemixitem.O) hc.RegCrud(r, "/v1/antibiotic-src-category", antibioticsrccat.O) + hc.RegCrud(r, "/v1/antibiotic-src", antibioticsrc.O) hc.RegCrud(r, "/v1/soapi", auth.GuardMW, soapi.O) hc.RegCrud(r, "/v1/adime", auth.GuardMW, adime.O) hc.RegCrud(r, "/v1/sbar", auth.GuardMW, sbar.O) diff --git a/internal/use-case/main-use-case/antibiotic-src/case.go b/internal/use-case/main-use-case/antibiotic-src/case.go new file mode 100644 index 00000000..e1ff1c44 --- /dev/null +++ b/internal/use-case/main-use-case/antibiotic-src/case.go @@ -0,0 +1,280 @@ +package antibioticsrc + +import ( + e "simrs-vx/internal/domain/main-entities/antibiotic-src" + "strconv" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "antibiotic-src" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.AntibioticSrc{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 err := createItem(&input, &event, tx); err != nil { + return err + } + + 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.AntibioticSrc + var dataList []e.AntibioticSrc + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.AntibioticSrc + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.AntibioticSrc + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.AntibioticSrc + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} \ No newline at end of file diff --git a/internal/use-case/main-use-case/antibiotic-src/helper.go b/internal/use-case/main-use-case/antibiotic-src/helper.go new file mode 100644 index 00000000..69dfb986 --- /dev/null +++ b/internal/use-case/main-use-case/antibiotic-src/helper.go @@ -0,0 +1,30 @@ +package antibioticsrc + +import ( + e "simrs-vx/internal/domain/main-entities/antibiotic-src" + + pl "simrs-vx/pkg/logger" + + "gorm.io/gorm" +) + +func setData(input any, data *e.AntibioticSrc) { + switch input.(type) { + case *e.CreateDto: + data.Code = input.(*e.CreateDto).Code + data.Name = input.(*e.CreateDto).Name + data.AntibioticSrcCategory_Code = input.(*e.CreateDto).AntibioticSrcCategory_Code + // data.Item_Id = input.(*e.CreateDto).Item_Id + case *e.UpdateDto: + data.Code = input.(*e.UpdateDto).Code + data.Name = input.(*e.UpdateDto).Name + data.AntibioticSrcCategory_Code = input.(*e.UpdateDto).AntibioticSrcCategory_Code + // data.Item_Id = input.(*e.UpdateDto).Item_Id + } +} + +func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { + // For antibiotic-src, we don't need to create items since Item_Id is commented out + // This function is kept for consistency with the pattern but does nothing + return nil +} diff --git a/internal/use-case/main-use-case/antibiotic-src/lib.go b/internal/use-case/main-use-case/antibiotic-src/lib.go new file mode 100644 index 00000000..24f91815 --- /dev/null +++ b/internal/use-case/main-use-case/antibiotic-src/lib.go @@ -0,0 +1,140 @@ +package antibioticsrc + +import ( + e "simrs-vx/internal/domain/main-entities/antibiotic-src" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.AntibioticSrc, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.AntibioticSrc{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.AntibioticSrc, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.AntibioticSrc{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.AntibioticSrc{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.AntibioticSrc, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.AntibioticSrc{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.First(&data, input.Id).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.AntibioticSrc, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.AntibioticSrc, 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 +} \ No newline at end of file diff --git a/internal/use-case/main-use-case/antibiotic-src/middleware-runner.go b/internal/use-case/main-use-case/antibiotic-src/middleware-runner.go new file mode 100644 index 00000000..2a939f32 --- /dev/null +++ b/internal/use-case/main-use-case/antibiotic-src/middleware-runner.go @@ -0,0 +1,111 @@ +package antibioticsrc + +import ( + e "simrs-vx/internal/domain/main-entities/antibiotic-src" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.AntibioticSrc) 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.AntibioticSrc) 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.AntibioticSrc) 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.AntibioticSrc) 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.AntibioticSrc) 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 +} + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// createMw{Name: "modif-input", Func: pm.ModifInput}, +// createMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/antibiotic-src/tycovar.go b/internal/use-case/main-use-case/antibiotic-src/tycovar.go new file mode 100644 index 00000000..94e36fd4 --- /dev/null +++ b/internal/use-case/main-use-case/antibiotic-src/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 antibioticsrc + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/antibiotic-src" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.AntibioticSrc, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.AntibioticSrc, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.AntibioticSrc, 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 From 13b0ea571eff3a91f526bf4806cf050d2b377961 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Thu, 6 Nov 2025 12:49:10 +0700 Subject: [PATCH 081/329] feat/trx-orders: added antibiotic-in-use flow --- .../main-entities/antibiotic-in-use/dto.go | 4 +- .../main-use-case/antibiotic-in-use/case.go | 389 ++++++++++++++++++ .../main-use-case/antibiotic-in-use/helper.go | 56 +++ .../main-use-case/antibiotic-in-use/lib.go | 140 +++++++ .../antibiotic-in-use/middleware-runner.go | 103 +++++ .../antibiotic-in-use/middleware.go | 9 + .../antibiotic-in-use/tycovar.go | 44 ++ 7 files changed, 744 insertions(+), 1 deletion(-) create mode 100644 internal/use-case/main-use-case/antibiotic-in-use/case.go create mode 100644 internal/use-case/main-use-case/antibiotic-in-use/helper.go create mode 100644 internal/use-case/main-use-case/antibiotic-in-use/lib.go create mode 100644 internal/use-case/main-use-case/antibiotic-in-use/middleware-runner.go create mode 100644 internal/use-case/main-use-case/antibiotic-in-use/middleware.go create mode 100644 internal/use-case/main-use-case/antibiotic-in-use/tycovar.go diff --git a/internal/domain/main-entities/antibiotic-in-use/dto.go b/internal/domain/main-entities/antibiotic-in-use/dto.go index 7fbce2dd..1c6ee63f 100644 --- a/internal/domain/main-entities/antibiotic-in-use/dto.go +++ b/internal/domain/main-entities/antibiotic-in-use/dto.go @@ -24,9 +24,11 @@ type FilterDto struct { AntibioticSrc_Id *uint `json:"mcu-src-id"` Result *string `json:"result"` Status_Code erc.DataStatusCode `json:"status-code"` + Includes string `json:"includes"` } type ReadDetailDto struct { - Id uint `json:"id"` + Id uint `json:"id"` + Includes string `json:"includes"` } type UpdateDto struct { diff --git a/internal/use-case/main-use-case/antibiotic-in-use/case.go b/internal/use-case/main-use-case/antibiotic-in-use/case.go new file mode 100644 index 00000000..20d95639 --- /dev/null +++ b/internal/use-case/main-use-case/antibiotic-in-use/case.go @@ -0,0 +1,389 @@ +package antibioticinuse + +import ( + "errors" + "strconv" + + e "simrs-vx/internal/domain/main-entities/antibiotic-in-use" + + ue "simrs-vx/internal/use-case/main-use-case/encounter" + umo "simrs-vx/internal/use-case/main-use-case/mcu-order" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "antibiotic-in-use" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.AntibioticInUse{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 + } + + // check if encounter is done + if ue.IsDone(*input.McuOrder_Id, &event, tx) { + return errors.New("encounter is already done") + } + + // check if mcu-order is completed + if umo.IsCompleted(*input.McuOrder_Id, &event, tx) { + return errors.New("mcu-order is already completed") + } + + // if !input.AuthInfo.IsDoctor() { + // 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) + // } + + // doctor_id, err := ud.GetIdByUserId(&input.AuthInfo.User_Id, &event, tx) + // if err != nil { + // return err + // } + + // verify the mcu-order belongs to the same doctor + // rdDto := e.ReadDetailDto{Id: *input.McuOrder_Id} + // if err := ValidateMcuOrderDoctor(rdDto, doctor_id, &event, tx); err != nil { + // return err + // } + + 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.AntibioticInUse + var dataList []e.AntibioticInUse + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.AntibioticInUse + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.AntibioticInUse + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err + } + + // if data.IsCompleted() { + // return errors.New("data already completed") + // } + + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err + } + + // if !input.AuthInfo.IsDoctor() { + // 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) + // } + + // doctor_id, err := ud.GetIdByUserId(&input.AuthInfo.User_Id, &event, tx) + // if err != nil { + // return err + // } + + // verify the mcu-order belongs to the same doctor + // if err := ValidateMcuOrderDoctor(e.ReadDetailDto{Id: *data.McuOrder_Id}, doctor_id, &event, tx); err != nil { + // return err + // } + + if err := UpdateData(input, data, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.AntibioticInUse + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} + +func SetSchedule(input e.SetScheduleDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.AntibioticInUse + var err error + + event := pl.Event{ + Feature: "SetSchedule", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "setSchedule") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + data, err = ReadDetailData(rdDto, &event, tx) + if err != nil { + return err + } + // if data.IsCompleted() { + // return errors.New("data already completed") + // } + + // data.ExaminationDate = input.ExaminationDate + // 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "setSchedule", + }, + Data: data.ToResponse(), + }, nil +} diff --git a/internal/use-case/main-use-case/antibiotic-in-use/helper.go b/internal/use-case/main-use-case/antibiotic-in-use/helper.go new file mode 100644 index 00000000..8f81510e --- /dev/null +++ b/internal/use-case/main-use-case/antibiotic-in-use/helper.go @@ -0,0 +1,56 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package antibioticinuse + +import ( + "errors" + + e "simrs-vx/internal/domain/main-entities/antibiotic-in-use" + emo "simrs-vx/internal/domain/main-entities/mcu-order" + + pl "simrs-vx/pkg/logger" + + "gorm.io/gorm" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.AntibioticInUse) { + 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.McuOrder_Id = inputSrc.McuOrder_Id + data.AntibioticSrc_Id = inputSrc.AntibioticSrc_Id + // data.ExaminationDate = inputSrc.ExaminationDate +} + +func ValidateMcuOrderDoctor(input e.ReadDetailDto, doctorId uint, event *pl.Event, tx *gorm.DB) error { + pl.SetLogInfo(event, input, "started", "ValidateMcuOrderDoctor") + + var mcuOrder emo.McuOrder + if err := tx.First(&mcuOrder, input.Id).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return errors.New("mcu-order not found") + } + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-get-fail", + Detail: "Failed to get mcu-order", + Raw: err, + } + return pl.SetLogError(event, input) + } + + if mcuOrder.Doctor_Id == nil || *mcuOrder.Doctor_Id != doctorId { + return errors.New("doctor is not authorized for this mcu-order") + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} diff --git a/internal/use-case/main-use-case/antibiotic-in-use/lib.go b/internal/use-case/main-use-case/antibiotic-in-use/lib.go new file mode 100644 index 00000000..e6b2d13d --- /dev/null +++ b/internal/use-case/main-use-case/antibiotic-in-use/lib.go @@ -0,0 +1,140 @@ +package antibioticinuse + +import ( + e "simrs-vx/internal/domain/main-entities/antibiotic-in-use" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.AntibioticInUse, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.AntibioticInUse{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.AntibioticInUse, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.AntibioticInUse{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.AntibioticInUse{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Order("\"CreatedAt\" DESC") + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.AntibioticInUse, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.AntibioticInUse{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.AntibioticInUse, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.AntibioticInUse, 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 +} \ No newline at end of file diff --git a/internal/use-case/main-use-case/antibiotic-in-use/middleware-runner.go b/internal/use-case/main-use-case/antibiotic-in-use/middleware-runner.go new file mode 100644 index 00000000..de906bf8 --- /dev/null +++ b/internal/use-case/main-use-case/antibiotic-in-use/middleware-runner.go @@ -0,0 +1,103 @@ +package antibioticinuse + +import ( + e "simrs-vx/internal/domain/main-entities/antibiotic-in-use" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.AntibioticInUse) 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.AntibioticInUse) 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.AntibioticInUse) 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.AntibioticInUse) 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.AntibioticInUse) 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 +} \ No newline at end of file diff --git a/internal/use-case/main-use-case/antibiotic-in-use/middleware.go b/internal/use-case/main-use-case/antibiotic-in-use/middleware.go new file mode 100644 index 00000000..f437fa0c --- /dev/null +++ b/internal/use-case/main-use-case/antibiotic-in-use/middleware.go @@ -0,0 +1,9 @@ +package antibioticinuse + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } \ No newline at end of file diff --git a/internal/use-case/main-use-case/antibiotic-in-use/tycovar.go b/internal/use-case/main-use-case/antibiotic-in-use/tycovar.go new file mode 100644 index 00000000..f35c0065 --- /dev/null +++ b/internal/use-case/main-use-case/antibiotic-in-use/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 antibioticinuse + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/antibiotic-in-use" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.AntibioticInUse, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.AntibioticInUse, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.AntibioticInUse, 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 \ No newline at end of file From 7423621a301154a681caefca77dfc8150f3cb258 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 13:34:49 +0700 Subject: [PATCH 082/329] prescription ids into codes --- .../migrations/20251106063418.sql | 2 + cmd/main-migration/migrations/atlas.sum | 157 +++++++++--------- .../domain/main-entities/prescription/dto.go | 8 +- .../main-entities/prescription/entity.go | 3 +- .../main-use-case/prescription/helper.go | 1 - 5 files changed, 86 insertions(+), 85 deletions(-) create mode 100644 cmd/main-migration/migrations/20251106063418.sql diff --git a/cmd/main-migration/migrations/20251106063418.sql b/cmd/main-migration/migrations/20251106063418.sql new file mode 100644 index 00000000..c04659a3 --- /dev/null +++ b/cmd/main-migration/migrations/20251106063418.sql @@ -0,0 +1,2 @@ +-- Modify "Prescription" table +ALTER TABLE "public"."Prescription" DROP CONSTRAINT "fk_Prescription_Doctor", DROP COLUMN "Doctor_Id", ADD CONSTRAINT "fk_Prescription_Doctor" FOREIGN KEY ("Doctor_Code") REFERENCES "public"."Doctor" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index bb6413e8..70ff0699 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,78 +1,79 @@ -h1:PwMC7qEOPDdica7/V7qlIoAcAg48skkmfckAfhLgXHk= -20250904105930.sql h1:Vv4vCurl7m7/ZB6TjRpkubHpQ4RYwSUn0QHdzfoGpzY= -20250904141448.sql h1:FYCHH9Os4KkrZMDu/jR8FMP+wLMRW+Mb0PkLU/9BRDg= -20250908062237.sql h1:oanBpKZd+akPu2I/xYhUSbd0G5tAFbXzKLER/Zs8ENI= -20250908062323.sql h1:miNG9COddXkD1jGTgaROMAZ618eT6oiLGiJhXWnQwhE= -20250908073811.sql h1:gOi5cnGG1htlpfizybYmUIT0vYjZTBfXiI0nPSYK2u8= -20250908073839.sql h1:cWNDA4YikjoOteAJuNLFILjQUJPFB6o8Wxreiek4QyI= -20250910055902.sql h1:nxxOGnU0BbH/v3IPgeIOXOwH8d3tKomw7h6FTeMnnBs= -20250915123412.sql h1:mz7SiWfrdf0qE1VTSAAnA/147d6gyp6ry5vZ2bR9SH0= -20250916043819.sql h1:RHXVtmMkB6wfv06HfPyHMBmUfIpFt1xveafNz0kwKnE= -20250917040616.sql h1:MYVDht+akBlzQGKNu2hTTTLPEcH1bxT/Q8MK6WEtuhs= -20250917040751.sql h1:J79YyS2JzWgh5oKXMTgh67uo3gLxKaAsxRiZmSIfjBs= -20250917045138.sql h1:/SM1N4O8X3yxpoJgMEARmS1uOkuLKsTOy4PLsRCOKaQ= -20250917093645.sql h1:PNBTGZ7s10e5b5+Tie8YfVQBN0zKtJ5T34oK1iOUEb4= -20250918073552.sql h1:jG7+g3i8ODYaJdcdZz12v3nbsZ5mB9wG6kWnGyTQIRI= -20250918073742.sql h1:j+rgw7puxE7s+phqPVZHmPk0af3rcaA56Itp86y1suY= -20250918074745.sql h1:rPmP4DXs6OnY4Vp+xO/z9jFpJt/RrJ52SJJjIIxeDvc= -20250923025134.sql h1:2r6pcwnBSU5Y9Czk1OHBoh4yZXiMtEca9X8843fTEX0= -20250924051317.sql h1:iUAk2gsGoEGIPQ0lEEUp8maMSId8emNbP+kP712ABIA= -20250929034321.sql h1:UlpALNVmdi95zOIT0yc6ZyTj9bBjQEIpZhvgrc52M+k= -20250929034428.sql h1:feF+H4nDyHh5bdx48Oiz0A1qecZfi6v3qTTdjzJ45Dg= -20250930025550.sql h1:6XT1kXI3Z3ZIxxmvT7poufZWWCW0QiejZPaFV5wBnjI= -20250930140351.sql h1:HxnmAbh9gCy8jwl/9ycGktiByaUripsjFFvohofY2CY= -20251002085604.sql h1:SjLPi+ZN6qDccK3DaEQCgNsZpPwr5kynWXwbwEsziCI= -20251003032030.sql h1:oHfxNSuqTxU8Zaf9H+h8TuUb1Da03wcyc6hZjDrUQ2s= -20251005060450.sql h1:GIuCcrd4MwjmXpvbzDzPYL18BV3QaZZ+Y2FmEzjvi0E= -20251006041122.sql h1:uNDQbSw0M08lYoMvUNlQtS3iDzpPM1ixT13ugSAoWjE= -20251006045658.sql h1:z+t7yCK54Q4SSiF9kUyUhkYB2F+kzSW9TB7ogxd9wzw= -20251006045928.sql h1:1lATLFLp4BWwGZqAjZdP0Dc6ypNXiYcwjoNkqGa8NFE= -20251007022859.sql h1:HXXwWrkyvzJzJGAt9mGskCRBBV/c1JfPmfjDocmJhQ4= -20251008031337.sql h1:Ln5pCF3Hxa5foHZLcds+z/us2eH6VAhhEj3w0TAGlVs= -20251008031554.sql h1:aB4MUS2lmqG0//4HKUWorcPSpWya0VC4QItvGyskEVI= -20251008052346.sql h1:MI3AZgU5XcwZT2OvvlWAxdRtL0eJ3jjRwt56IY1+pRU= -20251008073620.sql h1:sztWXuSNYwpEraaSapSsYwno75LO5H/N7ob7OJQ8X/A= -20251009042854.sql h1:TnPXj+dCJls3IU//cuqJZymyBzZMKs7ayazfgtAFRxM= -20251009052657.sql h1:leXbs0CP8r5dRilmYyLRk1MICqak3ea1/LWMtFrijqQ= -20251010031743.sql h1:SgHNY/lQ88G2F4nZyMfiOkDntb+gtOR+nEQLqXBTwv4= -20251010070721.sql h1:AnJnhXsMzDvK4AFgYw6B16Kpo/hljrZtcpc9m2VOSHQ= -20251010072711.sql h1:aXPTtNwLcTuw8C/yAxwxvqs0ayEjNzI1uuE0vE3ERa8= -20251013044536.sql h1:7Pq6JcvTpPBYDCW2dz3HdgUwY65HlhEVWy9TiG8iONE= -20251013051438.sql h1:X6t8bkqpUYYokBunSufMQUe5vCg0VyO6dxbm7ngosUc= -20251013081808.sql h1:495pLguXL2Ozh+ycn4UYZgZbn6WbjXNbyZUc3JU8qhI= -20251014060047.sql h1:nCgImMRGHhziiW57O1ofWaXCAPGaCOHN7PldQ3OSmM4= -20251014063537.sql h1:2cLmID79jP6cuQ1YJaWTtghFiM1GtHMC0ZQl30Hpy1M= -20251014063720.sql h1:bzLKKVAjSHgDFoiI/glj7t1ETlSAKx+AlsIAaP0ru2g= -20251015045455.sql h1:S547+UugQhlTRcn1Lm1IfqT5RNPttIWIiD+RTx69YaE= -20251016010845.sql h1:c9DUvxl17pUkf0azdYGM/YDzYxIJkLcfZOcMI4rL+R0= -20251016011023.sql h1:u3ivg83bXgYHBbojbWpemLxPE9Dmmj53B6LXo664jxw= -20251016062912.sql h1:W9n1hWchfYkqNX9LO9uxFxEXAb/iY+Pexjnhmp6PbgI= -20251017060617.sql h1:VU6yZ2+LfHpDZ3+TIH40t3F5YXPCpTppuF9+uSqa4b8= -20251017082207.sql h1:QshZslfedckz7iDpSGmPyY9sP6dy6ckHbs8L1TuXIA4= -20251018032635.sql h1:M1U/9W/F9wlW5YDmVAmHFfUJU7FWFaX0DblpfZcYWrE= -20251018040322.sql h1:Zk/vw0e6AzWFO2ElLOzB+OrSz6k+h1Ynxp0TImAzxwY= -20251019093915.sql h1:3Q0kPiZwJnHn5rAvdh0w1LBdiA7W2xBmZWncoPXb044= -20251020062553.sql h1:mJwC/J8GzPAIXckNMvy1f/Nguk2VVf8roD/Raclhbao= -20251021041042.sql h1:d1BAOGAQhqr+oOwcpAVozUsTh457VSDEk2qQFavGG58= -20251021075552.sql h1:TNChGQ1Zlr/1iQ6qvK4iDTAJpe6L/z/M6e/O0SkQVaM= -20251023044432.sql h1:GA2AdJk2ULyjr6igtu9C/CEi4YUIks8r9jXGGaCvPsk= -20251024034832.sql h1:RXmbEhMkOLK5g1QL6up8iRPcwYfo89oLP26ZHvrUK9o= -20251024074315.sql h1:3GnPQSbuAAfMa8oWDyBjhXqn1j1zunY/w0ydX0IGPrA= -20251025013451.sql h1:5eNrA9LDxA4i5CCP7wSyOgFZ6t6jBWVil+oGzJpkJ2E= -20251025013609.sql h1:+N6EHc1kv3hqf16CUhXe+UITPmoxOPfi4MECLmJXNrc= -20251027075128.sql h1:PQflgsjce/p2ClbybLtdehdPNDcMZ9Lb1vd98xd0K8E= -20251027091406.sql h1:bYXV57GvodCMjg0/ox+XKGIAGhrDlVuJ1wO4foNEKtQ= -20251102002037.sql h1:ZcwULsJU2lI9t5pX7ukmfAHSx4ZxdxLUX6jzLDc2SrU= -20251102091932.sql h1:A6y9j4wAqm4/HfMDxhpy/ChDn3UNRVN99KGgSCX+e18= -20251103081637.sql h1:RFqJNhJItSwJQaMP5IcQ14mL7eQ3EJjGZua9zLWzwMU= -20251104042334.sql h1:BbjLAwImggvI6489FQgD+S/AaafeiZut8k19TdH7XUE= -20251104043530.sql h1:Y0sOQqgnHxd5vKPA4+4fAGGdWCv6duKAYgHnjRJZUIc= -20251104080952.sql h1:hDHzFs/k+NhPYJ64ifbVp+nTJLMCG5MIMJU1zBMP0V0= -20251104084135.sql h1:p97mW1MPtPrMWJKy/KZqvymMO/vlelnXp43N9bZVCTI= -20251105044629.sql h1:E4BkVD3YyWvd0D18jA57EwTmkeoAMUWrdTCEwdPHA1U= -20251105121808.sql h1:kyMNzaJLyVtS1QpkX7cnVvhQmrrIE8m3GxUWwrMeyUo= -20251106035305.sql h1:VInVWBP1xpEhVIm1+ymuPzu0joxV2oS4qkNIyQvmTSU= -20251106040137.sql h1:7glRO1VAgq89H6zhM6M50iLwMT0w2sb96DUGrvfXZo4= -20251106041333.sql h1:/2wLmx8awSYhVpusDPAI+VeYJOLeLCWsNaF79gl1lg8= -20251106042006.sql h1:05AZyIbRJi1W08ETScADyAhI3elW0bXaWizlCpDfFCI= -20251106050412.sql h1:0102Z6ifzlwDjvU9jveuzULJvlo+Lc/UwyCeHUrwx18= +h1:5MZVEgV5zVF7bZ9mXYoi2ck0e9iRd7Ecib3j5OFA4/g= +20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= +20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= +20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= +20250908062323.sql h1:oXl6Z143tOpIl4EfP4B8JNU8LrMvVmHEtCgAfiB4gs8= +20250908073811.sql h1:m2aNXfnGxnLq1+rVWrh4f60q7fhyhV3gEwNu/OIqQlE= +20250908073839.sql h1:cPk54xjLdMs26uY8ZHjNWLuyfAMzV7Zb0/9oJQrsw04= +20250910055902.sql h1:5xwjAV6QbtZT9empTJKfhyAjdknbHzb15B0Ku5dzqtQ= +20250915123412.sql h1:D83xaU2YlDEd21HLup/YQpQ2easMToYCyy/oK6AFgQs= +20250916043819.sql h1:ekoTJsBqQZ8G8n0qJ03d13+eoNoc7sAUEQGA5D/CCxk= +20250917040616.sql h1:zoCnmcXuM7AVv85SmN7RmFglCgJnoDmpRWExH0LAc9Q= +20250917040751.sql h1:J1xyRrh32y1+lezwAyNwPcUQ6ABBSgbvzNLva4SVdQU= +20250917045138.sql h1:jKe1Z0uOLG4SGBYM+S/3P+/zMPztmgoderD5swnMuCg= +20250917093645.sql h1:cNI3Pbz1R3LxvIXLuexafJFCXUXrmuFCgXXJ2sG+FW0= +20250918073552.sql h1:RJ1SvMzP6aeWnoPVD3eVAmIQOkcp6Php8z3QRri6v4g= +20250918073742.sql h1:+cEsnJTJFybe2fR69ZoOiX2R6c6iITl4m6WTZ1hjyzY= +20250918074745.sql h1:2hNVQCXF/dVYXAh+T/7oBFgERGWxzVb2FXJjwkFWGCI= +20250923025134.sql h1:Ykz/qpHiGDXPsCsWTjydQFVSibZP2D+h2fIeb2h2JGA= +20250924051317.sql h1:yQuW6SwJxIOM5fcxeAaie5lSm1oLysU/C2hH2xNCVoQ= +20250929034321.sql h1:101FJ8VH12mrZWlt/X1gvKUGOhoiF8tFbjiapAjnHzg= +20250929034428.sql h1:i+pROD9p+g5dOmmZma6WF/0Hw5g3Ha28NN85iTo1K34= +20250930025550.sql h1:+F+CsCUXD/ql0tHGEow70GhPBX1ZybVn+bh/T4YMh7Y= +20250930140351.sql h1:9AAEG1AnOAH+o0+oHL5G7I8vqlWOhwRlCGyyCpT/y1Q= +20251002085604.sql h1:3xZ68eYp4urXRnvotNH1XvG2mYOSDV/j3zHEZ/txg5E= +20251003032030.sql h1:HB+mQ2lXMNomHDpaRhB/9IwYI9/YiDO5eOJ+nAQH/jw= +20251005060450.sql h1:LbtCE2b+8osM3CvnmQJH1uCPtn+d7WchsslBOz8bL3Q= +20251006041122.sql h1:MlS7f21z06sutnf9dIekt5fuHJr4lgcQ4uCuCXAGsfc= +20251006045658.sql h1:3FmGCPCzjgMPdWDRodZTsx3KVaodd9zB9ilib69aewk= +20251006045928.sql h1:Z5g31PmnzNwk/OKdODcxZGm8fjJQdMFK32Xfnt3bRHg= +20251007022859.sql h1:FO03zEfaNEk/aXwY81d5Lp3MoBB9kPQuXlXJ4BPiSR8= +20251008031337.sql h1:l+sxUAGvcTfj3I6kAFHo+T6AYodC9k9GkR+jaKO2xXc= +20251008031554.sql h1:AqrVfIhSzY3PCy8ZlP5W91wn2iznfIuj5qQfubp6/94= +20251008052346.sql h1:nxnXmooIJ6r1mmzwnw+6efxLfc/k9h2aE6RMptPRons= +20251008073620.sql h1:6YsJp1W4SmQJ1lxpqF27BBlDC1zqhw7Yhc7pLzQTY6M= +20251009042854.sql h1:nkBV+R6j0fg7/JY6wH3eb5Vv0asJLnXmb6lINfT/GLQ= +20251009052657.sql h1:EPvdsib5rzCGPryd10HShGKvFPwM/R5S2lIVwtYxpms= +20251010031743.sql h1:T8IZmx8/btRFKLzTe78MzcBsPJNodnLvB0tby9QkirQ= +20251010070721.sql h1:5NQUk/yOV6sABLCB7swx++YIOyJe6MnU+yt1nRzde5w= +20251010072711.sql h1:ZJNqR2piyu8xJhBvVABSlnGEoKSKae3wuEs+wshPe4k= +20251013044536.sql h1:0Xjw8fNILiT8nnfrJDZgQnPf3dntmIoilbapnih8AE4= +20251013051438.sql h1:lfSuw5mgJnePBJamvhZ81osFIouXeiIEiSZ/evdwo48= +20251013081808.sql h1:ijgjNX08G6GBjA/ks8EKtb7P7Y7Cg7zbhqEOruGnv6M= +20251014060047.sql h1:0jqj49WTtneEIMQDBoo4c095ZGi8sCrA8NnHBrPU6D8= +20251014063537.sql h1:VZLXol0PTsTW21Epg6vBPsztWkDtcxup9F/z88EGgIg= +20251014063720.sql h1:2HVUyCV0ud3BJJDH2GEKZN/+IWLFPCsN1KqhP6csO14= +20251015045455.sql h1:MeLWmMhAOAz8b15Dd7IAQnt6JxjSml02XCXK22C0Lpg= +20251016010845.sql h1:4BncQdDOasRZJkzVJrSJJA7091A9VPNVx/faUCUPhBM= +20251016011023.sql h1:9JB9eFZKURK5RoCVDKR6glSvdJ8NTXrN7K/4q51zkz4= +20251016062912.sql h1:ACNn0fe+EMqUt3hoY+Dr3uqAV/QICBa1+mIW7fUc9Fk= +20251017060617.sql h1:4T3t9ifWrEQTPMSM0XJ98pF7Qdt+UfgtMui17bhrnWI= +20251017082207.sql h1:8vLG1l/saRRMHXkyA4nelJyjaSddhZd6r7R+Uo4JS/c= +20251018032635.sql h1:2xey5gnO3y2XSOrU8MLlIfoylPKbRGDRtHDD07B3MbQ= +20251018040322.sql h1:k/pdNiSoT8zFPqNQ/avOD0vYkNh3BTD64IlHrfVXr7I= +20251019093915.sql h1:hFcQE0y+p5dZiVwePGsRGto9m/q6kJNiUZbVDd5Rnjk= +20251020062553.sql h1:Iw7hulcm5iRQlfW+ygA4iTPxLqkxx6h9vXMXEwUAHKs= +20251021041042.sql h1:wMgSivBV2A0NDcsLmKGIp0kMcVh2IODSG9b4dgzCaOM= +20251021075552.sql h1:8gfSMAglflNO6L0sSzxFNEubYN8/O4thT7OQT+WH+3M= +20251023044432.sql h1:MkvajJs3bfk9+wHvQ43/ccAluJEBARm1gWr1u92ccLA= +20251024034832.sql h1:x3s3VEVYLOSKLAFxJGb2+c1FyTMMvPE+9k4Ew7rKQaI= +20251024074315.sql h1:EjAjelgi5qAfcRq/8vPTlGGYHvAKxNTllm8f0SzZDns= +20251025013451.sql h1:6hnuIiwYiG+6nLhOY/+Yyn+I6ZCFNRZxrJNqBV6HLqE= +20251025013609.sql h1:evPJaTD8WxYRMOJZHkSr7ONLx9PYxT+ankzQt9c/sJ0= +20251027075128.sql h1:/iFQBM1sytjqpyQSOx61q33gnorMgxTiFVSuL6bQqsM= +20251027091406.sql h1:eCZGtUkxAzEAqpC9UsGpP8Df9mS0DEOqSl885LgqpvM= +20251102002037.sql h1:lFJbuoZ2LMQnUNGdcwHVY3Xlfslgzu9t2WByT8yfOZI= +20251102091932.sql h1:rmdhb5m+P+fU8jROBZNyeYgZKuQvucsuljXv4ZVzvks= +20251103081637.sql h1:tf3BcwTeIw+oxMEisKDDfyKnBfalTLs8b0PJA8JWYxY= +20251104042334.sql h1:7PDMWOhmJywolAPKFZ14XaDBeMvcxShaXFN2IemNtzk= +20251104043530.sql h1:qvYVp3ysPf27f1BcoRNCFGovxuVE12lg9d6Xzda6zWU= +20251104080952.sql h1:avghpv1n3yaCDR/TA0X+hgxDGoLBQGu/GJUwj4VT/Ic= +20251104084135.sql h1:rg+eRE5/5sYWR7z+Xyn0zKw8rr8P/oWxF0xhcNVnNec= +20251105044629.sql h1:4NU27HeKUNFsV82LacnwmnCSAH0pSbZR9J9/ZESRs6M= +20251105121808.sql h1:fii6LjqWYjrm/pEIqttfvJI6QEUL49gque8wYHh1+yI= +20251106035305.sql h1:oQ7BwnxPuwY2q98adIVc+lNwL/Sz1OceLJeClDo9/TI= +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= diff --git a/internal/domain/main-entities/prescription/dto.go b/internal/domain/main-entities/prescription/dto.go index f0c6901e..9c73c0ee 100644 --- a/internal/domain/main-entities/prescription/dto.go +++ b/internal/domain/main-entities/prescription/dto.go @@ -14,7 +14,7 @@ import ( type CreateDto struct { Encounter_Id *uint `json:"encounter_id"` - Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` IssuedAt *time.Time `json:"issuedAt"` Status_Code erc.DataStatusCode `json:"status_code"` @@ -29,7 +29,7 @@ type ReadListDto struct { type FilterDto struct { Encounter_Id *uint `json:"encounter-id"` - Doctor_Id *uint `json:"doctor-id"` + Doctor_Code *string `json:"doctor-code"` IssuedAt *time.Time `json:"issuedAt"` Status_Code *erc.DataStatusCode `json:"status-code"` } @@ -58,7 +58,7 @@ type ResponseDto struct { ecore.Main Encounter_Id *uint `json:"encounter_id"` Encounter *ee.Encounter `json:"encounter,omitempty"` - Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` Doctor *ed.Doctor `json:"doctor,omitempty"` IssuedAt *time.Time `json:"issuedAt"` Status_Code erc.DataStatusCode `json:"status_code"` @@ -68,7 +68,7 @@ func (d Prescription) ToResponse() ResponseDto { resp := ResponseDto{ Encounter_Id: d.Encounter_Id, Encounter: d.Encounter, - Doctor_Id: d.Doctor_Id, + Doctor_Code: d.Doctor_Code, Doctor: d.Doctor, IssuedAt: d.IssuedAt, Status_Code: d.Status_Code, diff --git a/internal/domain/main-entities/prescription/entity.go b/internal/domain/main-entities/prescription/entity.go index c32c9d9e..849e8083 100644 --- a/internal/domain/main-entities/prescription/entity.go +++ b/internal/domain/main-entities/prescription/entity.go @@ -14,9 +14,8 @@ type Prescription struct { ecore.Main // adjust this according to the needs Encounter_Id *uint `json:"encounter_id"` Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Doctor_Id *uint `json:"doctor_id"` Doctor_Code *string `json:"doctor_code" gorm:"size:20"` - Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"` IssuedAt *time.Time `json:"issuedAt"` Status_Code erc.DataStatusCode `json:"status_code"` } diff --git a/internal/use-case/main-use-case/prescription/helper.go b/internal/use-case/main-use-case/prescription/helper.go index 92fd4531..7260699e 100644 --- a/internal/use-case/main-use-case/prescription/helper.go +++ b/internal/use-case/main-use-case/prescription/helper.go @@ -37,7 +37,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Prescription) { } data.Encounter_Id = inputSrc.Encounter_Id - // data.Doctor_Id = inputSrc.Doctor_Id data.Doctor_Code = inputSrc.AuthInfo.Doctor_Code data.IssuedAt = inputSrc.IssuedAt } From 4aabf4ad5209a0e6304db6633e840fd5e174fd9a Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 14:23:51 +0700 Subject: [PATCH 083/329] specialist, subscpecialist, specialist-position, subspecialist-position ids into codes --- .../migrations/20251106071906.sql | 8 +++ cmd/main-migration/migrations/atlas.sum | 3 +- .../specialist-position/base/entity.go | 1 + .../main-entities/specialist-position/dto.go | 57 ++++++++++--------- .../domain/main-entities/specialist/dto.go | 25 ++++---- .../domain/main-entities/specialist/entity.go | 1 + .../subspecialist-position/base/entity.go | 15 ++--- .../subspecialist-position/dto.go | 57 ++++++++++--------- .../subspecialist/base/entity.go | 1 + .../domain/main-entities/subspecialist/dto.go | 27 ++++----- .../interface/main-handler/main-handler.go | 8 +-- .../specialist-position/handler.go | 18 +++--- .../main-handler/specialist/handler.go | 18 +++--- .../subspecialist-position/handler.go | 18 +++--- .../main-handler/subspecialist/handler.go | 18 +++--- .../main-use-case/specialist-position/case.go | 2 +- .../specialist-position/helper.go | 2 +- .../main-use-case/specialist-position/lib.go | 2 +- .../use-case/main-use-case/specialist/case.go | 4 +- .../main-use-case/specialist/helper.go | 2 +- .../subspecialist-position/case.go | 6 +- .../subspecialist-position/helper.go | 2 +- .../subspecialist-position/lib.go | 4 +- .../main-use-case/subspecialist/case.go | 4 +- .../main-use-case/subspecialist/lib.go | 7 +++ .../handler-crud-helper.go | 34 +++++++++++ 26 files changed, 201 insertions(+), 143 deletions(-) create mode 100644 cmd/main-migration/migrations/20251106071906.sql diff --git a/cmd/main-migration/migrations/20251106071906.sql b/cmd/main-migration/migrations/20251106071906.sql new file mode 100644 index 00000000..66793656 --- /dev/null +++ b/cmd/main-migration/migrations/20251106071906.sql @@ -0,0 +1,8 @@ +-- Modify "Specialist" table +ALTER TABLE "public"."Specialist" ADD COLUMN "Unit_Code" character varying(10) NULL; +-- Modify "SpecialistPosition" table +ALTER TABLE "public"."SpecialistPosition" ADD COLUMN "Specialist_Code" character varying(10) NULL; +-- Modify "Subspecialist" table +ALTER TABLE "public"."Subspecialist" ADD COLUMN "Specialist_Code" character varying(10) NULL; +-- Modify "SubspecialistPosition" table +ALTER TABLE "public"."SubspecialistPosition" ADD COLUMN "Subspecialist_Code" character varying(10) NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 70ff0699..fd8a8979 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:5MZVEgV5zVF7bZ9mXYoi2ck0e9iRd7Ecib3j5OFA4/g= +h1:CT5nygEUOdVE27HmnMPqwLegXYbJ41grmTvFn7AH8D8= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -77,3 +77,4 @@ h1:5MZVEgV5zVF7bZ9mXYoi2ck0e9iRd7Ecib3j5OFA4/g= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= 20251106050412.sql h1:MiEMJ1HCFYnalKuq3Z38xJeogfBAMqsTv2sG4EF8dDw= 20251106063418.sql h1:y3veDJPjKekOWLCZek/LgQwXPRhZtOppTfUXiqoL95s= +20251106071906.sql h1:/TUZA3XpMY23qEJXdkTwlzrNMvSSl6JJniPcgAttBaw= diff --git a/internal/domain/main-entities/specialist-position/base/entity.go b/internal/domain/main-entities/specialist-position/base/entity.go index 5910689e..5db268cd 100644 --- a/internal/domain/main-entities/specialist-position/base/entity.go +++ b/internal/domain/main-entities/specialist-position/base/entity.go @@ -8,6 +8,7 @@ import ( type Basic struct { ecore.SmallMain // adjust this according to the needs Specialist_Id *uint16 `json:"specialist_id" gorm:"not null"` + Specialist_Code *string `json:"specialist_code" gorm:"size:10"` Code string `json:"code" gorm:"unique;size:10;not null"` Name string `json:"name" gorm:"size:30;not null"` HeadStatus bool `json:"headStatus"` diff --git a/internal/domain/main-entities/specialist-position/dto.go b/internal/domain/main-entities/specialist-position/dto.go index 0641fb12..beebab28 100644 --- a/internal/domain/main-entities/specialist-position/dto.go +++ b/internal/domain/main-entities/specialist-position/dto.go @@ -7,11 +7,11 @@ import ( ) type CreateDto struct { - Specialist_Id *uint16 `json:"specialist_id" validate:"required"` - Code string `json:"code" validate:"maxLength=10;required"` - Name string `json:"name" validate:"maxLength=30;required"` - HeadStatus bool `json:"headStatus"` - Employee_Id *uint `json:"employee_id"` + Specialist_Code *string `json:"specialist_code" validate:"required"` + Code string `json:"code" validate:"maxLength=10;required"` + Name string `json:"name" validate:"maxLength=30;required"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` } type ReadListDto struct { @@ -22,26 +22,27 @@ type ReadListDto struct { } type FilterDto struct { - Specialist_Id *uint16 `json:"specialist-id"` - Code string `json:"code"` - Name string `json:"name"` - HeadStatus *bool `json:"head-status"` - Employee_Id *uint `json:"employee-id"` - Search string `json:"search" gormhelper:"searchColumns=Code,Name"` + Specialist_Code *string `json:"specialist-code"` + Code string `json:"code"` + Name string `json:"name"` + HeadStatus *bool `json:"head-status"` + Employee_Id *uint `json:"employee-id"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { @@ -52,24 +53,24 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain - Specialist_Id *uint16 `json:"specialist_id"` - Specialist *es.Specialist `json:"specialist,omitempty"` - Code string `json:"code"` - Name string `json:"name"` - HeadStatus bool `json:"headStatus"` - Employee_Id *uint `json:"employee_id"` - Employee *ee.Employee `json:"employee,omitempty"` + Specialist_Code *string `json:"specialist_code"` + Specialist *es.Specialist `json:"specialist,omitempty"` + Code string `json:"code"` + Name string `json:"name"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` + Employee *ee.Employee `json:"employee,omitempty"` } func (d SpecialistPosition) ToResponse() ResponseDto { resp := ResponseDto{ - Specialist_Id: d.Specialist_Id, - Specialist: d.Specialist, - Code: d.Code, - Name: d.Name, - HeadStatus: d.HeadStatus, - Employee_Id: d.Employee_Id, - Employee: d.Employee, + Specialist_Code: d.Specialist_Code, + Specialist: d.Specialist, + Code: d.Code, + Name: d.Name, + HeadStatus: d.HeadStatus, + Employee_Id: d.Employee_Id, + Employee: d.Employee, } resp.SmallMain = d.SmallMain return resp diff --git a/internal/domain/main-entities/specialist/dto.go b/internal/domain/main-entities/specialist/dto.go index 8724b9c5..a67a830f 100644 --- a/internal/domain/main-entities/specialist/dto.go +++ b/internal/domain/main-entities/specialist/dto.go @@ -8,9 +8,9 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=10"` - Name string `json:"name" validate:"maxLength=50"` - Unit_Id *uint16 `json:"unit_id"` + Code string `json:"code" validate:"maxLength=10"` + Name string `json:"name" validate:"maxLength=50"` + Unit_Code *string `json:"unit_code"` } type ReadListDto struct { @@ -21,25 +21,26 @@ type ReadListDto struct { } type FilterDto struct { - Code string `json:"code"` - Name string `json:"name"` - Unit_Id *uint16 `json:"unit-id"` - Search string `json:"search" gormhelper:"searchColumns=Code,Name"` + Code string `json:"code"` + Name string `json:"name"` + Unit_Code *string `json:"unit-code"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` Includes string `json:"includes"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { @@ -52,7 +53,7 @@ type ResponseDto struct { ecore.SmallMain Code string `json:"code"` Name string `json:"name"` - Unit_Id *uint16 `json:"unit_id"` + Unit_Code *string `json:"unit_code"` Unit *eu.Unit `json:"unit,omitempty"` SpecialistPositions []espb.Basic `json:"specialistPositions,omitempty"` Subspecialists []essb.Basic `json:"subspecialists,omitempty"` @@ -63,7 +64,7 @@ func (d Specialist) ToResponse() ResponseDto { Code: d.Code, Name: d.Name, Unit: d.Unit, - Unit_Id: d.Unit_Id, + Unit_Code: d.Unit_Code, SpecialistPositions: d.SpecialistPositions, Subspecialists: d.Subspecialists, } diff --git a/internal/domain/main-entities/specialist/entity.go b/internal/domain/main-entities/specialist/entity.go index 9efb83b0..912d433f 100644 --- a/internal/domain/main-entities/specialist/entity.go +++ b/internal/domain/main-entities/specialist/entity.go @@ -12,6 +12,7 @@ type Specialist struct { Code string `json:"code" gorm:"unique;size:10"` Name string `json:"name" gorm:"size:50"` Unit_Id *uint16 `json:"unit_id"` + Unit_Code *string `json:"unit_code" gorm:"size:10"` Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id"` SpecialistPositions []eub.Basic `json:"specialistPositions,omitempty" gorm:"foreignKey:Specialist_Id;references:Id"` Subspecialists []essb.Basic `json:"subspecialists,omitempty" gorm:"foreignKey:Specialist_Id;references:Id"` diff --git a/internal/domain/main-entities/subspecialist-position/base/entity.go b/internal/domain/main-entities/subspecialist-position/base/entity.go index 147fcecb..a0bd0834 100644 --- a/internal/domain/main-entities/subspecialist-position/base/entity.go +++ b/internal/domain/main-entities/subspecialist-position/base/entity.go @@ -6,13 +6,14 @@ import ( ) type Basic struct { - ecore.SmallMain // adjust this according to the needs - Subspecialist_Id *uint16 `json:"subspecialist_id" gorm:"not null"` - Code string `json:"code" gorm:"unique;size:10;not null"` - Name string `json:"name" gorm:"size:30;not null"` - HeadStatus bool `json:"headStatus"` - Employee_Id *uint `json:"employee_id"` - Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` + ecore.SmallMain // adjust this according to the needs + Subspecialist_Id *uint16 `json:"subspecialist_id" gorm:"not null"` + Subspecialist_Code *string `json:"subspecialist_code" gorm:"size:10"` + Code string `json:"code" gorm:"unique;size:10;not null"` + Name string `json:"name" gorm:"size:30;not null"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` + Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` } func (Basic) TableName() string { diff --git a/internal/domain/main-entities/subspecialist-position/dto.go b/internal/domain/main-entities/subspecialist-position/dto.go index 3c65841e..13532ab8 100644 --- a/internal/domain/main-entities/subspecialist-position/dto.go +++ b/internal/domain/main-entities/subspecialist-position/dto.go @@ -7,11 +7,11 @@ import ( ) type CreateDto struct { - Subspecialist_Id *uint16 `json:"subspecialist_id" validate:"required"` - Code string `json:"code" validate:"maxLength=10;required"` - Name string `json:"name" validate:"maxLength=30;required"` - HeadStatus bool `json:"headStatus"` - Employee_Id *uint `json:"employee_id"` + Subspecialist_Code *string `json:"subspecialist_code" validate:"required"` + Code string `json:"code" validate:"maxLength=10;required"` + Name string `json:"name" validate:"maxLength=30;required"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` } type ReadListDto struct { @@ -22,26 +22,27 @@ type ReadListDto struct { } type FilterDto struct { - Subspecialist_Id *uint16 `json:"subspecialist-id"` - Code string `json:"code"` - Name string `json:"name"` - HeadStatus *bool `json:"head-status"` - Employee_Id *uint `json:"employee-id"` - Search string `json:"search" gormhelper:"searchColumns=Code,Name"` + Subspecialist_Code *string `json:"subspecialist-code"` + Code string `json:"code"` + Name string `json:"name"` + HeadStatus *bool `json:"head-status"` + Employee_Id *uint `json:"employee-id"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { @@ -52,24 +53,24 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain - Subspecialist_Id *uint16 `json:"subspecialist_id"` - Subspecialist *es.Subspecialist `json:"subspecialist,omitempty"` - Code string `json:"code"` - Name string `json:"name"` - HeadStatus bool `json:"headStatus"` - Employee_Id *uint `json:"employee_id"` - Employee *ee.Employee `json:"employee,omitempty"` + Subspecialist_Code *string `json:"subspecialist_id"` + Subspecialist *es.Subspecialist `json:"subspecialist,omitempty"` + Code string `json:"code"` + Name string `json:"name"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` + Employee *ee.Employee `json:"employee,omitempty"` } func (d SubspecialistPosition) ToResponse() ResponseDto { resp := ResponseDto{ - Subspecialist_Id: d.Subspecialist_Id, - Subspecialist: d.Subspecialist, - Code: d.Code, - Name: d.Name, - HeadStatus: d.HeadStatus, - Employee_Id: d.Employee_Id, - Employee: d.Employee, + Subspecialist_Code: d.Subspecialist_Code, + Subspecialist: d.Subspecialist, + Code: d.Code, + Name: d.Name, + HeadStatus: d.HeadStatus, + Employee_Id: d.Employee_Id, + Employee: d.Employee, } resp.SmallMain = d.SmallMain return resp diff --git a/internal/domain/main-entities/subspecialist/base/entity.go b/internal/domain/main-entities/subspecialist/base/entity.go index bc516360..c89cb8f2 100644 --- a/internal/domain/main-entities/subspecialist/base/entity.go +++ b/internal/domain/main-entities/subspecialist/base/entity.go @@ -9,6 +9,7 @@ type Basic struct { Code string `json:"code" gorm:"unique;size:10"` Name string `json:"name" gorm:"size:50"` Specialist_Id *uint16 `json:"specialist_id"` + Specialist_Code *string `json:"specialist_code" gorm:"size:10"` } func (Basic) TableName() string { diff --git a/internal/domain/main-entities/subspecialist/dto.go b/internal/domain/main-entities/subspecialist/dto.go index 9a93394d..5ec895d6 100644 --- a/internal/domain/main-entities/subspecialist/dto.go +++ b/internal/domain/main-entities/subspecialist/dto.go @@ -27,18 +27,19 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` Includes string `json:"includes"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { @@ -49,20 +50,20 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain - Code string `json:"code"` - Name string `json:"name"` - Specialist_Id *uint16 `json:"specialist_id"` - Specialist *es.Specialist `json:"specialist,omitempty"` - Subspecialist []espb.Basic `json:"subspecialistPositions,omitempty"` + Code string `json:"code"` + Name string `json:"name"` + Specialist_Code *string `json:"specialist_ccode"` + Specialist *es.Specialist `json:"specialist,omitempty"` + Subspecialist []espb.Basic `json:"subspecialistPositions,omitempty"` } func (d Subspecialist) ToResponse() ResponseDto { resp := ResponseDto{ - Code: d.Code, - Name: d.Name, - Specialist_Id: d.Specialist_Id, - Specialist: d.Specialist, - Subspecialist: d.SubspecialistPositions, + Code: d.Code, + Name: d.Name, + Specialist_Code: d.Specialist_Code, + Specialist: d.Specialist, + Subspecialist: d.SubspecialistPositions, } resp.SmallMain = d.SmallMain return resp diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 0a6a917a..abed5f2d 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -314,16 +314,16 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/medical-action-src", medicalactionsrc.O) hc.RegCrud(r, "/v1/medical-action-src-item", medicalactionsrcitem.O) hc.RegCrud(r, "/v1/language", language.O) - hc.RegCrud(r, "/v1/specialist", specialist.O) - hc.RegCrud(r, "/v1/subspecialist", subspecialist.O) hc.RegCrud(r, "/v1/mcu-sub-src", mcusubsrc.O) hc.RegCrud(r, "/v1/vehicle", vehicle.O) hc.RegCrud(r, "/v1/vehicle-hist", vehiclehist.O) hc.RegCrud(r, "/v1/edu-assessment", eduassesment.O) hc.RegCrud(r, "/v1/installation-position", installationposition.O) hc.RegCrud(r, "/v1/unit-position", unitposition.O) - hc.RegCrud(r, "/v1/specialist-position", specialistposition.O) - hc.RegCrud(r, "/v1/subspecialist-position", subspecialistposition.O) + hc.RegCrudByCode(r, "/v1/specialist", specialist.O) + hc.RegCrudByCode(r, "/v1/subspecialist", subspecialist.O) + hc.RegCrudByCode(r, "/v1/specialist-position", specialistposition.O) + hc.RegCrudByCode(r, "/v1/subspecialist-position", subspecialistposition.O) hc.RegCrud(r, "/v1/village", village.O) hc.RegCrud(r, "/v1/district", district.O) diff --git a/internal/interface/main-handler/specialist-position/handler.go b/internal/interface/main-handler/specialist-position/handler.go index d16c2c7e..4d6376a1 100644 --- a/internal/interface/main-handler/specialist-position/handler.go +++ b/internal/interface/main-handler/specialist-position/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ 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.Code = code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/specialist/handler.go b/internal/interface/main-handler/specialist/handler.go index d3a074d8..246da8f4 100644 --- a/internal/interface/main-handler/specialist/handler.go +++ b/internal/interface/main-handler/specialist/handler.go @@ -33,21 +33,21 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} sf.UrlQueryParam(&dto, *r.URL) - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -55,19 +55,19 @@ 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.Code = code 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 { + code := rw.ValidateString(w, "", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/subspecialist-position/handler.go b/internal/interface/main-handler/subspecialist-position/handler.go index d8e27b14..e33c62b8 100644 --- a/internal/interface/main-handler/subspecialist-position/handler.go +++ b/internal/interface/main-handler/subspecialist-position/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ 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.Code = code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/subspecialist/handler.go b/internal/interface/main-handler/subspecialist/handler.go index c4b933b4..0e5a41d0 100644 --- a/internal/interface/main-handler/subspecialist/handler.go +++ b/internal/interface/main-handler/subspecialist/handler.go @@ -33,21 +33,21 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} sf.UrlQueryParam(&dto, *r.URL) - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -55,19 +55,19 @@ 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.Code = code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/use-case/main-use-case/specialist-position/case.go b/internal/use-case/main-use-case/specialist-position/case.go index c3c469e6..2addf80d 100644 --- a/internal/use-case/main-use-case/specialist-position/case.go +++ b/internal/use-case/main-use-case/specialist-position/case.go @@ -290,7 +290,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { func validateForeignKey(input e.CreateDto) error { // validate installation_id - if _, err := us.ReadDetail(es.ReadDetailDto{Id: *input.Specialist_Id}); err != nil { + if _, err := us.ReadDetail(es.ReadDetailDto{Code: input.Specialist_Code}); err != nil { return err } diff --git a/internal/use-case/main-use-case/specialist-position/helper.go b/internal/use-case/main-use-case/specialist-position/helper.go index 6c3d6434..43aaeb20 100644 --- a/internal/use-case/main-use-case/specialist-position/helper.go +++ b/internal/use-case/main-use-case/specialist-position/helper.go @@ -17,7 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.SpecialistPosition) inputSrc = &inputTemp.CreateDto } - data.Specialist_Id = inputSrc.Specialist_Id + data.Specialist_Code = inputSrc.Specialist_Code data.Code = inputSrc.Code data.Name = inputSrc.Name data.HeadStatus = inputSrc.HeadStatus diff --git a/internal/use-case/main-use-case/specialist-position/lib.go b/internal/use-case/main-use-case/specialist-position/lib.go index 3ae54f50..13c84f28 100644 --- a/internal/use-case/main-use-case/specialist-position/lib.go +++ b/internal/use-case/main-use-case/specialist-position/lib.go @@ -83,7 +83,7 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e } switch { - case input.Id != 0: + case input.Id != nil: getData = tx.First(&data, input.Id) case input.Code != nil && *input.Code != "": getData = tx.Where("code = ?", *input.Code).First(&data) diff --git a/internal/use-case/main-use-case/specialist/case.go b/internal/use-case/main-use-case/specialist/case.go index 229544be..c51a0002 100644 --- a/internal/use-case/main-use-case/specialist/case.go +++ b/internal/use-case/main-use-case/specialist/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: &input.Code} var data *e.Specialist var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Specialist var err error diff --git a/internal/use-case/main-use-case/specialist/helper.go b/internal/use-case/main-use-case/specialist/helper.go index 9c1e42fc..5c59b1cf 100644 --- a/internal/use-case/main-use-case/specialist/helper.go +++ b/internal/use-case/main-use-case/specialist/helper.go @@ -19,5 +19,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Specialist) { data.Code = inputSrc.Code data.Name = inputSrc.Name - data.Unit_Id = inputSrc.Unit_Id + data.Unit_Code = inputSrc.Unit_Code } diff --git a/internal/use-case/main-use-case/subspecialist-position/case.go b/internal/use-case/main-use-case/subspecialist-position/case.go index d954427a..0069a753 100644 --- a/internal/use-case/main-use-case/subspecialist-position/case.go +++ b/internal/use-case/main-use-case/subspecialist-position/case.go @@ -175,7 +175,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: &input.Code} var data *e.SubspecialistPosition var err error @@ -235,7 +235,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.SubspecialistPosition var err error @@ -290,7 +290,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { func validateForeignKey(input e.CreateDto) error { // validate installation_id - if _, err := us.ReadDetail(es.ReadDetailDto{Id: *input.Subspecialist_Id}); err != nil { + if _, err := us.ReadDetail(es.ReadDetailDto{Code: input.Subspecialist_Code}); err != nil { return err } diff --git a/internal/use-case/main-use-case/subspecialist-position/helper.go b/internal/use-case/main-use-case/subspecialist-position/helper.go index 1f4c9b2b..16ff54e0 100644 --- a/internal/use-case/main-use-case/subspecialist-position/helper.go +++ b/internal/use-case/main-use-case/subspecialist-position/helper.go @@ -17,7 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.SubspecialistPositi inputSrc = &inputTemp.CreateDto } - data.Subspecialist_Id = inputSrc.Subspecialist_Id + data.Subspecialist_Code = inputSrc.Subspecialist_Code data.Code = inputSrc.Code data.Name = inputSrc.Name data.HeadStatus = inputSrc.HeadStatus diff --git a/internal/use-case/main-use-case/subspecialist-position/lib.go b/internal/use-case/main-use-case/subspecialist-position/lib.go index 136e982e..edb422dd 100644 --- a/internal/use-case/main-use-case/subspecialist-position/lib.go +++ b/internal/use-case/main-use-case/subspecialist-position/lib.go @@ -83,10 +83,10 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e } switch { - case input.Id != 0: + case input.Id != nil: getData = tx.First(&data, input.Id) case input.Code != nil && *input.Code != "": - getData = tx.Where("code = ?", *input.Code).First(&data) + getData = tx.Where("\"Code\" = ?", *input.Code).First(&data) default: event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ diff --git a/internal/use-case/main-use-case/subspecialist/case.go b/internal/use-case/main-use-case/subspecialist/case.go index 50498b2a..42366adf 100644 --- a/internal/use-case/main-use-case/subspecialist/case.go +++ b/internal/use-case/main-use-case/subspecialist/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: &input.Code} var data *e.Subspecialist var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Subspecialist var err error diff --git a/internal/use-case/main-use-case/subspecialist/lib.go b/internal/use-case/main-use-case/subspecialist/lib.go index 46ec11f2..a6c4dbc5 100644 --- a/internal/use-case/main-use-case/subspecialist/lib.go +++ b/internal/use-case/main-use-case/subspecialist/lib.go @@ -81,6 +81,13 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e tx = dg.I } + if input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + if err := tx. Scopes(gh.Preload(input.Includes)). First(&data, input.Id).Error; err != nil { diff --git a/pkg/handler-crud-helper/handler-crud-helper.go b/pkg/handler-crud-helper/handler-crud-helper.go index d7da62f4..df475094 100644 --- a/pkg/handler-crud-helper/handler-crud-helper.go +++ b/pkg/handler-crud-helper/handler-crud-helper.go @@ -40,3 +40,37 @@ func RegCrud(r *http.ServeMux, path string, mwAndRouter ...any) { "DELETE /{id}": c.Delete, }) } + +func RegCrudByCode(r *http.ServeMux, path string, mwAndRouter ...any) { + sLength := len(mwAndRouter) + + mwCandidates := mwAndRouter[:sLength-1] + mwList := []hk.HandlerMw{} + for i := range mwCandidates { + // have to do it manually, since casting directly results unexpected result + myType := reflect.TypeOf(mwCandidates[i]) + if myType.String() != "func(http.Handler) http.Handler" { + panic("non middleware included as middleware") + } + mwList = append(mwList, mwCandidates[i].(func(http.Handler) http.Handler)) + + // if g, okHandler := mwCandidates[i].(func(http.Handler) http.Handler); !okHandler { + // panic("non middleware included") + // } else { + // mwList = append(mwList, g) + // } + } + + c, ok := mwAndRouter[sLength-1].(CrudBase) + if !ok { + panic("non CrudBase used in the last paramter") + } + + hk.GroupRoutes(path, r, mwList, hk.MapHandlerFunc{ + "POST /": c.Create, + "GET /": c.GetList, + "GET /{code}": c.GetDetail, + "PATCH /{code}": c.Update, + "DELETE /{code}": c.Delete, + }) +} From e821dc0347879c0f607b03b223e8429ede768778 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 14:32:54 +0700 Subject: [PATCH 084/329] remove ids fk --- cmd/main-migration/migrations/20251106073157.sql | 8 ++++++++ cmd/main-migration/migrations/atlas.sum | 3 ++- .../specialist-position/base/entity.go | 1 - .../main-entities/specialist-position/entity.go | 2 +- .../domain/main-entities/specialist/entity.go | 7 +++---- .../subspecialist-position/base/entity.go | 1 - .../subspecialist-position/entity.go | 2 +- .../main-entities/subspecialist/base/entity.go | 1 - .../domain/main-entities/subspecialist/dto.go | 16 ++++++++-------- .../domain/main-entities/subspecialist/entity.go | 4 ++-- .../main-use-case/subspecialist/helper.go | 2 +- 11 files changed, 26 insertions(+), 21 deletions(-) create mode 100644 cmd/main-migration/migrations/20251106073157.sql diff --git a/cmd/main-migration/migrations/20251106073157.sql b/cmd/main-migration/migrations/20251106073157.sql new file mode 100644 index 00000000..1cac4860 --- /dev/null +++ b/cmd/main-migration/migrations/20251106073157.sql @@ -0,0 +1,8 @@ +-- Modify "Specialist" table +ALTER TABLE "public"."Specialist" DROP CONSTRAINT "fk_Specialist_Unit", DROP COLUMN "Unit_Id", ADD CONSTRAINT "fk_Specialist_Unit" FOREIGN KEY ("Unit_Code") REFERENCES "public"."Unit" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "SpecialistPosition" table +ALTER TABLE "public"."SpecialistPosition" DROP CONSTRAINT "fk_SpecialistPosition_Specialist", DROP COLUMN "Specialist_Id", ADD CONSTRAINT "fk_SpecialistPosition_Specialist" FOREIGN KEY ("Specialist_Code") REFERENCES "public"."Specialist" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "Subspecialist" table +ALTER TABLE "public"."Subspecialist" DROP CONSTRAINT "fk_Subspecialist_Specialist", DROP COLUMN "Specialist_Id", ADD CONSTRAINT "fk_Subspecialist_Specialist" FOREIGN KEY ("Specialist_Code") REFERENCES "public"."Specialist" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "SubspecialistPosition" table +ALTER TABLE "public"."SubspecialistPosition" DROP CONSTRAINT "fk_SubspecialistPosition_Subspecialist", DROP COLUMN "Subspecialist_Id", ADD CONSTRAINT "fk_SubspecialistPosition_Subspecialist" FOREIGN KEY ("Subspecialist_Code") REFERENCES "public"."Subspecialist" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index fd8a8979..a0715aa2 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:CT5nygEUOdVE27HmnMPqwLegXYbJ41grmTvFn7AH8D8= +h1:cgdcTn/j8rHYtIwewbtRo4C+ybSGaJgHR2Fpstbj6/o= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -78,3 +78,4 @@ h1:CT5nygEUOdVE27HmnMPqwLegXYbJ41grmTvFn7AH8D8= 20251106050412.sql h1:MiEMJ1HCFYnalKuq3Z38xJeogfBAMqsTv2sG4EF8dDw= 20251106063418.sql h1:y3veDJPjKekOWLCZek/LgQwXPRhZtOppTfUXiqoL95s= 20251106071906.sql h1:/TUZA3XpMY23qEJXdkTwlzrNMvSSl6JJniPcgAttBaw= +20251106073157.sql h1:78txeibJ602DMD7huD618ZSMt6phSRzDNPTlo0PGyrc= diff --git a/internal/domain/main-entities/specialist-position/base/entity.go b/internal/domain/main-entities/specialist-position/base/entity.go index 5db268cd..b4a0abb2 100644 --- a/internal/domain/main-entities/specialist-position/base/entity.go +++ b/internal/domain/main-entities/specialist-position/base/entity.go @@ -7,7 +7,6 @@ import ( type Basic struct { ecore.SmallMain // adjust this according to the needs - Specialist_Id *uint16 `json:"specialist_id" gorm:"not null"` Specialist_Code *string `json:"specialist_code" gorm:"size:10"` Code string `json:"code" gorm:"unique;size:10;not null"` Name string `json:"name" gorm:"size:30;not null"` diff --git a/internal/domain/main-entities/specialist-position/entity.go b/internal/domain/main-entities/specialist-position/entity.go index 26c1d27f..429e5554 100644 --- a/internal/domain/main-entities/specialist-position/entity.go +++ b/internal/domain/main-entities/specialist-position/entity.go @@ -7,5 +7,5 @@ import ( type SpecialistPosition struct { esb.Basic - Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Id;references:Id"` + Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Code;references:Code"` } diff --git a/internal/domain/main-entities/specialist/entity.go b/internal/domain/main-entities/specialist/entity.go index 912d433f..4fef90a5 100644 --- a/internal/domain/main-entities/specialist/entity.go +++ b/internal/domain/main-entities/specialist/entity.go @@ -11,9 +11,8 @@ type Specialist struct { ecore.SmallMain // adjust this according to the needs Code string `json:"code" gorm:"unique;size:10"` Name string `json:"name" gorm:"size:50"` - Unit_Id *uint16 `json:"unit_id"` Unit_Code *string `json:"unit_code" gorm:"size:10"` - Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id"` - SpecialistPositions []eub.Basic `json:"specialistPositions,omitempty" gorm:"foreignKey:Specialist_Id;references:Id"` - Subspecialists []essb.Basic `json:"subspecialists,omitempty" gorm:"foreignKey:Specialist_Id;references:Id"` + Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` + SpecialistPositions []eub.Basic `json:"specialistPositions,omitempty" gorm:"foreignKey:Specialist_Code;references:Code"` + Subspecialists []essb.Basic `json:"subspecialists,omitempty" gorm:"foreignKey:Specialist_Code;references:Code"` } diff --git a/internal/domain/main-entities/subspecialist-position/base/entity.go b/internal/domain/main-entities/subspecialist-position/base/entity.go index a0bd0834..cb98dff6 100644 --- a/internal/domain/main-entities/subspecialist-position/base/entity.go +++ b/internal/domain/main-entities/subspecialist-position/base/entity.go @@ -7,7 +7,6 @@ import ( type Basic struct { ecore.SmallMain // adjust this according to the needs - Subspecialist_Id *uint16 `json:"subspecialist_id" gorm:"not null"` Subspecialist_Code *string `json:"subspecialist_code" gorm:"size:10"` Code string `json:"code" gorm:"unique;size:10;not null"` Name string `json:"name" gorm:"size:30;not null"` diff --git a/internal/domain/main-entities/subspecialist-position/entity.go b/internal/domain/main-entities/subspecialist-position/entity.go index 28a205ed..2deaf8b7 100644 --- a/internal/domain/main-entities/subspecialist-position/entity.go +++ b/internal/domain/main-entities/subspecialist-position/entity.go @@ -7,5 +7,5 @@ import ( type SubspecialistPosition struct { esb.Basic - Subspecialist *es.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Id;references:Id"` + Subspecialist *es.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Code;references:Code"` } diff --git a/internal/domain/main-entities/subspecialist/base/entity.go b/internal/domain/main-entities/subspecialist/base/entity.go index c89cb8f2..a94fb76d 100644 --- a/internal/domain/main-entities/subspecialist/base/entity.go +++ b/internal/domain/main-entities/subspecialist/base/entity.go @@ -8,7 +8,6 @@ type Basic struct { ecore.SmallMain // adjust this according to the needs Code string `json:"code" gorm:"unique;size:10"` Name string `json:"name" gorm:"size:50"` - Specialist_Id *uint16 `json:"specialist_id"` Specialist_Code *string `json:"specialist_code" gorm:"size:10"` } diff --git a/internal/domain/main-entities/subspecialist/dto.go b/internal/domain/main-entities/subspecialist/dto.go index 5ec895d6..6e10b573 100644 --- a/internal/domain/main-entities/subspecialist/dto.go +++ b/internal/domain/main-entities/subspecialist/dto.go @@ -7,9 +7,9 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=10"` - Name string `json:"name" validate:"maxLength=50"` - Specialist_Id *uint16 `json:"specialist_id"` + Code string `json:"code" validate:"maxLength=10"` + Name string `json:"name" validate:"maxLength=50"` + Specialist_Code *string `json:"specialist_code"` } type ReadListDto struct { @@ -20,10 +20,10 @@ type ReadListDto struct { } type FilterDto struct { - Code *string `json:"code"` - Name *string `json:"name"` - Specialist_Id *uint16 `json:"specialist-id"` - Search string `json:"search" gormhelper:"searchColumns=Code,Name"` + Code *string `json:"code"` + Name *string `json:"name"` + Specialist_Code *string `json:"specialist-code"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` } type ReadDetailDto struct { @@ -52,7 +52,7 @@ type ResponseDto struct { ecore.SmallMain Code string `json:"code"` Name string `json:"name"` - Specialist_Code *string `json:"specialist_ccode"` + Specialist_Code *string `json:"specialist_code"` Specialist *es.Specialist `json:"specialist,omitempty"` Subspecialist []espb.Basic `json:"subspecialistPositions,omitempty"` } diff --git a/internal/domain/main-entities/subspecialist/entity.go b/internal/domain/main-entities/subspecialist/entity.go index f2ff5d8e..44a40d4a 100644 --- a/internal/domain/main-entities/subspecialist/entity.go +++ b/internal/domain/main-entities/subspecialist/entity.go @@ -8,6 +8,6 @@ import ( type Subspecialist struct { esb.Basic - Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Id"` - SubspecialistPositions []espb.Basic `json:"subspecialistPositions,omitempty" gorm:"foreignKey:Subspecialist_Id;references:Id"` + Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Code;references:Code"` + SubspecialistPositions []espb.Basic `json:"subspecialistPositions,omitempty" gorm:"foreignKey:Subspecialist_Code;references:Code"` } diff --git a/internal/use-case/main-use-case/subspecialist/helper.go b/internal/use-case/main-use-case/subspecialist/helper.go index 5d04093f..08d64941 100644 --- a/internal/use-case/main-use-case/subspecialist/helper.go +++ b/internal/use-case/main-use-case/subspecialist/helper.go @@ -19,5 +19,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Subspecialist) { data.Code = inputSrc.Code data.Name = inputSrc.Name - data.Specialist_Id = inputSrc.Specialist_Id + data.Specialist_Code = inputSrc.Specialist_Code } From d5d4d663e146c73825da5472a5a4dff7390e1462 Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 6 Nov 2025 14:32:55 +0700 Subject: [PATCH 085/329] update entity and conslist --- .../migrations/20251106054706.sql | 6 ++ .../migrations/20251106054849.sql | 2 + cmd/main-migration/migrations/atlas.sum | 6 +- .../domain/main-entities/ambulatory/entity.go | 7 +- .../domain/main-entities/encounter/entity.go | 3 +- .../internal-reference/entity.go | 13 ++-- .../domain/main-entities/rehab/base/entity.go | 17 +++-- .../domain/references/clinical/clinical.go | 48 ++++++------- internal/domain/references/common/common.go | 5 ++ .../domain/references/encounter/encounter.go | 28 ++++---- .../encounter/request-validation.go | 70 +++++++++---------- .../use-case/main-use-case/encounter/case.go | 13 ++-- 12 files changed, 121 insertions(+), 97 deletions(-) create mode 100644 cmd/main-migration/migrations/20251106054706.sql create mode 100644 cmd/main-migration/migrations/20251106054849.sql diff --git a/cmd/main-migration/migrations/20251106054706.sql b/cmd/main-migration/migrations/20251106054706.sql new file mode 100644 index 00000000..dd292709 --- /dev/null +++ b/cmd/main-migration/migrations/20251106054706.sql @@ -0,0 +1,6 @@ +-- Modify "Ambulatory" table +ALTER TABLE "public"."Ambulatory" DROP COLUMN "VisitMode_Code"; +-- Modify "InternalReference" table +ALTER TABLE "public"."InternalReference" ADD COLUMN "Status_Code" text NULL; +-- Modify "Rehab" table +ALTER TABLE "public"."Rehab" ADD COLUMN "Parent_Encounter_Id" bigint NULL, ADD COLUMN "ExpiredAt" timestamptz NULL, ADD COLUMN "VisitMode_Code" text NULL, ADD COLUMN "Status_Code" text NULL; diff --git a/cmd/main-migration/migrations/20251106054849.sql b/cmd/main-migration/migrations/20251106054849.sql new file mode 100644 index 00000000..45e5f4e4 --- /dev/null +++ b/cmd/main-migration/migrations/20251106054849.sql @@ -0,0 +1,2 @@ +-- Modify "Rehab" table +ALTER TABLE "public"."Rehab" DROP COLUMN "Doctor_Id"; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 40b66b02..4dbe2544 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:drtrRtMhlNYK0c9wV3CUkJvXwWgrD8xGPPJy9wlcvNA= +h1:KxMvALnpFUI2RXpBZgkJ312FeLtrm9L0o+CqgJbm40U= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -68,4 +68,6 @@ h1:drtrRtMhlNYK0c9wV3CUkJvXwWgrD8xGPPJy9wlcvNA= 20251104042334.sql h1:7PDMWOhmJywolAPKFZ14XaDBeMvcxShaXFN2IemNtzk= 20251104043530.sql h1:qvYVp3ysPf27f1BcoRNCFGovxuVE12lg9d6Xzda6zWU= 20251104080952.sql h1:avghpv1n3yaCDR/TA0X+hgxDGoLBQGu/GJUwj4VT/Ic= -20251104084135.sql h1:Y4coFrHgDXd/DM8ihEy+qMkOSrO8M4SI4shRCJIiBBA= +20251104084135.sql h1:rg+eRE5/5sYWR7z+Xyn0zKw8rr8P/oWxF0xhcNVnNec= +20251106054706.sql h1:a17rQ3uAX09BpVFpAFoY8NM6gfsmYVvgNNZaQuWs6T0= +20251106054849.sql h1:TU0HU+jAfs5225rggWP5TjPgb272vQoeiLvEoGhKRbs= diff --git a/internal/domain/main-entities/ambulatory/entity.go b/internal/domain/main-entities/ambulatory/entity.go index ecf9915e..06754385 100644 --- a/internal/domain/main-entities/ambulatory/entity.go +++ b/internal/domain/main-entities/ambulatory/entity.go @@ -6,8 +6,7 @@ import ( ) type Ambulatory struct { - ecore.Main // adjust this according to the needs - Encounter_Id *uint `json:"encounter_id"` - Class_Code ere.AmbulatoryClassCode `json:"class_code" gorm:"size:10"` - VisitMode_Code ere.VisitModeCode `json:"visitMode_code"` + ecore.Main // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Class_Code ere.AmbulatoryClassCode `json:"class_code" gorm:"size:10"` } diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index 5e950def..c53912ab 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -68,7 +68,8 @@ type Encounter struct { Ambulatory *eam.Ambulatory `json:"ambulatory,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Emergency *eem.Emergency `json:"emergency,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Inpatient *eip.Inpatient `json:"inpatient,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Rehab *er.Basic `json:"rehab,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + Rehab_Adm *er.Basic `json:"rehab_adm,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + Rehab_Series *[]er.Basic `json:"rehab_series,omitempty" gorm:"foreignKey:Parent_Encounter_Id;references:Id"` } func (d Encounter) IsDone() bool { diff --git a/internal/domain/main-entities/internal-reference/entity.go b/internal/domain/main-entities/internal-reference/entity.go index 85334449..060b21aa 100644 --- a/internal/domain/main-entities/internal-reference/entity.go +++ b/internal/domain/main-entities/internal-reference/entity.go @@ -1,6 +1,8 @@ package internal_reference import ( + erc "simrs-vx/internal/domain/references/common" + ecore "simrs-vx/internal/domain/base-entities/core" ed "simrs-vx/internal/domain/main-entities/doctor" eu "simrs-vx/internal/domain/main-entities/unit" @@ -8,9 +10,10 @@ import ( type InternalReference struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Unit_Id *uint16 `json:"unit_id"` - Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` - Doctor_Id *uint `json:"doctor_id"` - Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` + Encounter_Id *uint `json:"encounter_id"` + Unit_Id *uint16 `json:"unit_id"` + Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` + Doctor_Id *uint `json:"doctor_id"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` + Status_Code *erc.DataApprovalCode `json:"status_code"` } diff --git a/internal/domain/main-entities/rehab/base/entity.go b/internal/domain/main-entities/rehab/base/entity.go index b1713811..d932a991 100644 --- a/internal/domain/main-entities/rehab/base/entity.go +++ b/internal/domain/main-entities/rehab/base/entity.go @@ -1,16 +1,21 @@ package base import ( + erc "simrs-vx/internal/domain/references/common" + ere "simrs-vx/internal/domain/references/encounter" + "time" + ecore "simrs-vx/internal/domain/base-entities/core" - ed "simrs-vx/internal/domain/main-entities/doctor" ) type Basic struct { - ecore.Main // adjust this according to the needs - Encounter_Id *uint `json:"encounter_id"` - Doctor_Id *uint `json:"doctor_id"` - Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` - AllocatedVisitCount *int `json:"allocatedVisitCount"` + ecore.Main // adjust this according to the needs + Parent_Encounter_Id *uint `json:"parent_encounter_id"` + Encounter_Id *uint `json:"encounter_id"` + AllocatedVisitCount *int `json:"allocatedVisitCount"` + ExpiredAt *time.Time `json:"expiredAt"` + VisitMode_Code *ere.VisitModeCode `json:"visitMode_code"` + Status_Code *erc.DataStatusCode `json:"status_code"` } func (Basic) TableName() string { diff --git a/internal/domain/references/clinical/clinical.go b/internal/domain/references/clinical/clinical.go index 8120adb3..26a1c651 100644 --- a/internal/domain/references/clinical/clinical.go +++ b/internal/domain/references/clinical/clinical.go @@ -2,25 +2,25 @@ package clinical type ( - SubjectCode string - ObjectCode string - AssessmentCode string - PlanCode string - InstructionCode string - HeadToToeCode string - McuUrgencyLevelCode string - SoapiTypeCode string - MedicalAction string - VehicleTypeCode string - GeneralEduCode string - SpecialEduCode string - EduAssessmentCode string - AbilityCode string - WillCode string - MedObstacleCode string - LearnMethodCode string - LangClassCode string - TranslatorSrcCode string + SubjectCode string + ObjectCode string + AssessmentCode string + PlanCode string + InstructionCode string + HeadToToeCode string + McuUrgencyLevelCode string + SoapiTypeCode string + MedicalActionTypeCode string + VehicleTypeCode string + GeneralEduCode string + SpecialEduCode string + EduAssessmentCode string + AbilityCode string + WillCode string + MedObstacleCode string + LearnMethodCode string + LangClassCode string + TranslatorSrcCode string ) const ( @@ -120,11 +120,11 @@ const ( STCProgress SoapiTypeCode = "progress" // CPPT STCDevRecord SoapiTypeCode = "dev-record" // Catatan Perkembangan - MAChemo MedicalAction = "chemo" - MAHemo MedicalAction = "hemo" - MAThalasemia MedicalAction = "thalasemia" - MAEchocardio MedicalAction = "echocardio" - MASpirometry MedicalAction = "spirometry" + MATCChemo MedicalActionTypeCode = "chemo" + MATCHemo MedicalActionTypeCode = "hemo" + MATCThalasemia MedicalActionTypeCode = "thalasemia" + MATCEchocardio MedicalActionTypeCode = "echocardio" + MATCSpirometry MedicalActionTypeCode = "spirometry" VTCAmbulance VehicleTypeCode = "ambulance" // Ambulans VTCTransport VehicleTypeCode = "transport" // Transport diff --git a/internal/domain/references/common/common.go b/internal/domain/references/common/common.go index 9e532b14..2941049c 100644 --- a/internal/domain/references/common/common.go +++ b/internal/domain/references/common/common.go @@ -15,6 +15,7 @@ type ( DataAvailabilityCode string DataVerifiedCode string CrudCode string + DataApprovalCode string ) const ( @@ -96,6 +97,10 @@ const ( CCRead CrudCode = "r" // Read CCUpdate CrudCode = "u" // Update CCDelete CrudCode = "d" // Delete + + DACNew DataApprovalCode = "new" + DACApproved DataApprovalCode = "approved" + DACRejected DataApprovalCode = "rejected" ) func GetDayCodes() map[DayCode]string { diff --git a/internal/domain/references/encounter/encounter.go b/internal/domain/references/encounter/encounter.go index 97eae05b..35681689 100644 --- a/internal/domain/references/encounter/encounter.go +++ b/internal/domain/references/encounter/encounter.go @@ -19,6 +19,7 @@ type ( AllPaymentMethodCode string SEPRefTypeCode string VisitModeCode string + PolySwitchCode string ) const ( @@ -32,18 +33,18 @@ const ( QSCCancel QueueStatusCode = "cancel" // Dibatalkan QSCSkip QueueStatusCode = "skip" // Dilewati - DMCHome DischargeMethodCode = "home" // Pulang - DMCHomeReq DischargeMethodCode = "home-request" // Pulang Atas Permintaan Sendiri - DMCConsulBack DischargeMethodCode = "consul-back" // Konsultasi Balik / Lanjutan - DMCConsulPoly DischargeMethodCode = "consul-poly" // Konsultasi Poliklinik Lain - DMCConsulExecutive DischargeMethodCode = "consul-executive" // Konsultasi Antar Dokter Eksekutif - DMCConsulChDay DischargeMethodCode = "consul-ch-day" // Konsultasi Hari Lain - DMCEmergency DischargeMethodCode = "emergency" // Rujuk IGD - DMCEmergencyCovid DischargeMethodCode = "emergency-covid" // Rujuk IGD Covid - DMCInpatient DischargeMethodCode = "inpatient" // Rujuk Rawat Inap - DMCExtRef DischargeMethodCode = "external" // Rujuk Faskes Lain - DMCDeath DischargeMethodCode = "death" // Meninggal - DMCDeathOnArrival DischargeMethodCode = "death-on-arrival" // Meninggal Saat Tiba + DMCHome DischargeMethodCode = "home" // Pulang + DMCHomeReq DischargeMethodCode = "home-request" // Pulang Atas Permintaan Sendiri + DMCConsulBack DischargeMethodCode = "consul-back" // Konsultasi Balik / Lanjutan + //DMCConsulPoly DischargeMethodCode = "consul-poly" // Konsultasi Poliklinik Lain + //DMCConsulExecutive DischargeMethodCode = "consul-executive" // Konsultasi Antar Dokter Eksekutif + DMCConsulChDay DischargeMethodCode = "consul-ch-day" // Konsultasi Hari Lain + DMCEmergency DischargeMethodCode = "emergency" // Rujuk IGD + DMCEmergencyCovid DischargeMethodCode = "emergency-covid" // Rujuk IGD Covid + DMCInpatient DischargeMethodCode = "inpatient" // Rujuk Rawat Inap + DMCExtRef DischargeMethodCode = "external" // Rujuk Faskes Lain + DMCDeath DischargeMethodCode = "death" // Meninggal + DMCDeathOnArrival DischargeMethodCode = "death-on-arrival" // Meninggal Saat Tiba TCAmbulance TransportationCode = "ambulance" // Ambulans TCCar TransportationCode = "car" // Mobil @@ -112,6 +113,9 @@ const ( VMCAdm VisitModeCode = "adm" VMCSeries VisitModeCode = "series" + + PSCConsulPoly PolySwitchCode = "consul-poly" // Konsultasi Poliklinik Lain + PSCConsulExecutive PolySwitchCode = "consul-executive" // Konsultasi Antar Dokter Eksekutif ) func (ec EncounterClassCode) Code() string { diff --git a/internal/interface/main-handler/encounter/request-validation.go b/internal/interface/main-handler/encounter/request-validation.go index 025298fc..0fb49e54 100644 --- a/internal/interface/main-handler/encounter/request-validation.go +++ b/internal/interface/main-handler/encounter/request-validation.go @@ -1,7 +1,6 @@ package encounter import ( - "fmt" "net/http" e "simrs-vx/internal/domain/main-entities/encounter" ere "simrs-vx/internal/domain/references/encounter" @@ -13,42 +12,41 @@ import ( const dataValidationFail = "data-validation-fail" func validateRequestCheckout(w http.ResponseWriter, i e.DischargeDto) (valid bool) { - switch *i.Discharge_Method_Code { - case ere.DMCDeath: - if i.DeathCause == nil { - rw.DataResponse(w, nil, d.FieldError{ - Code: dataValidationFail, - Message: "deathCause required if discharge_method_code is death", - }) - return - } - case ere.DMCConsulPoly, ere.DMCConsulExecutive: - if i.InternalReferences == nil { - rw.DataResponse(w, nil, d.FieldError{ - Code: dataValidationFail, - Message: fmt.Sprintf("internalReferences required if discharge_method_code is %s", *i.Discharge_Method_Code), - }) - return - } - - for _, v := range *i.InternalReferences { - if v.Unit_Id == nil { - rw.DataResponse(w, nil, d.FieldError{ - Code: dataValidationFail, - Message: "internalReferences.unit_id required", - }) - return - } - - if v.Doctor_Id == nil { - rw.DataResponse(w, nil, d.FieldError{ - Code: dataValidationFail, - Message: "internalReferences.doctor_id required", - }) - return - } - } + if *i.Discharge_Method_Code == ere.DMCDeath && i.DeathCause == nil { + rw.DataResponse(w, nil, d.FieldError{ + Code: dataValidationFail, + Message: "deathCause required if discharge_method_code is death", + }) + return } + + //case ere.DMCConsulPoly, ere.DMCConsulExecutive: + // if i.InternalReferences == nil { + // rw.DataResponse(w, nil, d.FieldError{ + // Code: dataValidationFail, + // Message: fmt.Sprintf("internalReferences required if discharge_method_code is %s", *i.Discharge_Method_Code), + // }) + // return + // } + // + // for _, v := range *i.InternalReferences { + // if v.Unit_Id == nil { + // rw.DataResponse(w, nil, d.FieldError{ + // Code: dataValidationFail, + // Message: "internalReferences.unit_id required", + // }) + // return + // } + // + // if v.Doctor_Id == nil { + // rw.DataResponse(w, nil, d.FieldError{ + // Code: dataValidationFail, + // Message: "internalReferences.doctor_id required", + // }) + // return + // } + // } + return true } diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 829cf86c..89395f83 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -458,19 +458,18 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) { return err } - switch *input.Discharge_Method_Code { - case ere.DMCDeath: + if *input.Discharge_Method_Code == ere.DMCDeath { // insert data death-cause if _, err = udc.CreateData(edc.CreateDto{Encounter_Id: &input.Id, Value: input.DeathCause}, &event, tx); err != nil { return err } - case ere.DMCConsulPoly, ere.DMCConsulExecutive: - // bulk insert internal-references - if err = createInternalReferences(input, &event, tx); err != nil { - return err - } } + //// bulk insert internal-references + //if err = createInternalReferences(input, &event, tx); err != nil { + // return err + //} + pl.SetLogInfo(&event, nil, "complete") return nil From d5082d01ede844399fe77c115293218caa7d65c8 Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 6 Nov 2025 14:34:44 +0700 Subject: [PATCH 086/329] fix import cycle encounter related --- .../domain/references/clinical/clinical.go | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/internal/domain/references/clinical/clinical.go b/internal/domain/references/clinical/clinical.go index 8120adb3..26a1c651 100644 --- a/internal/domain/references/clinical/clinical.go +++ b/internal/domain/references/clinical/clinical.go @@ -2,25 +2,25 @@ package clinical type ( - SubjectCode string - ObjectCode string - AssessmentCode string - PlanCode string - InstructionCode string - HeadToToeCode string - McuUrgencyLevelCode string - SoapiTypeCode string - MedicalAction string - VehicleTypeCode string - GeneralEduCode string - SpecialEduCode string - EduAssessmentCode string - AbilityCode string - WillCode string - MedObstacleCode string - LearnMethodCode string - LangClassCode string - TranslatorSrcCode string + SubjectCode string + ObjectCode string + AssessmentCode string + PlanCode string + InstructionCode string + HeadToToeCode string + McuUrgencyLevelCode string + SoapiTypeCode string + MedicalActionTypeCode string + VehicleTypeCode string + GeneralEduCode string + SpecialEduCode string + EduAssessmentCode string + AbilityCode string + WillCode string + MedObstacleCode string + LearnMethodCode string + LangClassCode string + TranslatorSrcCode string ) const ( @@ -120,11 +120,11 @@ const ( STCProgress SoapiTypeCode = "progress" // CPPT STCDevRecord SoapiTypeCode = "dev-record" // Catatan Perkembangan - MAChemo MedicalAction = "chemo" - MAHemo MedicalAction = "hemo" - MAThalasemia MedicalAction = "thalasemia" - MAEchocardio MedicalAction = "echocardio" - MASpirometry MedicalAction = "spirometry" + MATCChemo MedicalActionTypeCode = "chemo" + MATCHemo MedicalActionTypeCode = "hemo" + MATCThalasemia MedicalActionTypeCode = "thalasemia" + MATCEchocardio MedicalActionTypeCode = "echocardio" + MATCSpirometry MedicalActionTypeCode = "spirometry" VTCAmbulance VehicleTypeCode = "ambulance" // Ambulans VTCTransport VehicleTypeCode = "transport" // Transport From 5ba60938df98909020425756037b190a7ca72c0b Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 14:46:06 +0700 Subject: [PATCH 087/329] division, division-position ids into codes --- cmd/main-migration/migrations/20251106074218.sql | 4 ++++ cmd/main-migration/migrations/atlas.sum | 3 ++- .../domain/main-entities/division-position/base/entity.go | 1 + internal/domain/main-entities/division/entity.go | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 cmd/main-migration/migrations/20251106074218.sql diff --git a/cmd/main-migration/migrations/20251106074218.sql b/cmd/main-migration/migrations/20251106074218.sql new file mode 100644 index 00000000..f7536b57 --- /dev/null +++ b/cmd/main-migration/migrations/20251106074218.sql @@ -0,0 +1,4 @@ +-- Modify "Division" table +ALTER TABLE "public"."Division" ADD COLUMN "Parent_Code" character varying(10) NULL; +-- Modify "DivisionPosition" table +ALTER TABLE "public"."DivisionPosition" ADD COLUMN "Division_Code" character varying(10) NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index a0715aa2..5a963973 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:cgdcTn/j8rHYtIwewbtRo4C+ybSGaJgHR2Fpstbj6/o= +h1:aVDoCaB6Gy2SKHrUbR2KDqH9ByMHPVcYzTGW5846kt8= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -79,3 +79,4 @@ h1:cgdcTn/j8rHYtIwewbtRo4C+ybSGaJgHR2Fpstbj6/o= 20251106063418.sql h1:y3veDJPjKekOWLCZek/LgQwXPRhZtOppTfUXiqoL95s= 20251106071906.sql h1:/TUZA3XpMY23qEJXdkTwlzrNMvSSl6JJniPcgAttBaw= 20251106073157.sql h1:78txeibJ602DMD7huD618ZSMt6phSRzDNPTlo0PGyrc= +20251106074218.sql h1:8Xz7WywrtUnSxOHhlal53gG9rE7r86LFUt5zBFe/mIs= diff --git a/internal/domain/main-entities/division-position/base/entity.go b/internal/domain/main-entities/division-position/base/entity.go index ce8f3175..b2635553 100644 --- a/internal/domain/main-entities/division-position/base/entity.go +++ b/internal/domain/main-entities/division-position/base/entity.go @@ -8,6 +8,7 @@ import ( type Basic struct { ecore.SmallMain // adjust this according to the needs Division_Id *uint16 `json:"division_id"` + Division_Code *string `json:"division_code" gorm:"size:10"` Code string `json:"code" gorm:"unique;size:10"` Name string `json:"name" gorm:"size:50"` HeadStatus bool `json:"headStatus"` diff --git a/internal/domain/main-entities/division/entity.go b/internal/domain/main-entities/division/entity.go index 4051c138..bcef1c7f 100644 --- a/internal/domain/main-entities/division/entity.go +++ b/internal/domain/main-entities/division/entity.go @@ -10,6 +10,7 @@ type Division struct { Code string `json:"code" gorm:"unique;size:10"` Name string `json:"name" gorm:"size:50"` Parent_Id *uint16 `json:"parent_id"` + Parent_Code *string `json:"parent_code" gorm:"size:10"` Parent *Division `json:"parent" gorm:"foreignKey:Parent_Id;references:Id"` Childrens []Division `json:"childrens" gorm:"foreignKey:Parent_Id"` // may need references to self DivisionPositions []edpb.Basic `json:"divisionPositions,omitempty" gorm:"foreignKey:Division_Id;references:Id"` From 686f2fbd51fe174ce1550b42594ef5796879494b Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 6 Nov 2025 15:03:51 +0700 Subject: [PATCH 088/329] not yet finish --- .../domain/main-entities/ambulatory/dto.go | 10 ++-- .../main-entities/internal-reference/dto.go | 28 ++++++---- internal/domain/main-entities/rehab/dto.go | 35 ++++++++---- .../main-use-case/ambulatory/helper.go | 1 - .../use-case/main-use-case/encounter/case.go | 9 +-- .../main-use-case/encounter/helper.go | 56 +++++++++---------- .../use-case/main-use-case/encounter/lib.go | 2 +- .../use-case/main-use-case/rehab/helper.go | 5 +- 8 files changed, 80 insertions(+), 66 deletions(-) diff --git a/internal/domain/main-entities/ambulatory/dto.go b/internal/domain/main-entities/ambulatory/dto.go index f580467a..ec34f37f 100644 --- a/internal/domain/main-entities/ambulatory/dto.go +++ b/internal/domain/main-entities/ambulatory/dto.go @@ -6,9 +6,8 @@ import ( ) type CreateDto struct { - Encounter_Id *uint `json:"encounter_id"` - Class_Code ere.AmbulatoryClassCode `json:"class_code" validate:"maxLength=10"` - VisitMode_Code ere.VisitModeCode `json:"visitMode_code"` + Encounter_Id *uint `json:"encounter_id"` + Class_Code ere.AmbulatoryClassCode `json:"class_code" validate:"maxLength=10"` } type ReadListDto struct { @@ -50,9 +49,8 @@ type ResponseDto struct { func (d Ambulatory) ToResponse() ResponseDto { resp := ResponseDto{ - Encounter_Id: d.Encounter_Id, - Class_Code: d.Class_Code, - VisitMode_Code: d.VisitMode_Code, + Encounter_Id: d.Encounter_Id, + Class_Code: d.Class_Code, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/internal-reference/dto.go b/internal/domain/main-entities/internal-reference/dto.go index 360c3193..c957d60b 100644 --- a/internal/domain/main-entities/internal-reference/dto.go +++ b/internal/domain/main-entities/internal-reference/dto.go @@ -1,15 +1,18 @@ package internal_reference import ( + erc "simrs-vx/internal/domain/references/common" + ecore "simrs-vx/internal/domain/base-entities/core" ed "simrs-vx/internal/domain/main-entities/doctor" eu "simrs-vx/internal/domain/main-entities/unit" ) type CreateDto struct { - Encounter_Id *uint `json:"-"` - Unit_Id *uint16 `json:"unit_id"` - Doctor_Id *uint `json:"doctor_Id"` + Encounter_Id *uint `json:"-"` + Unit_Id *uint16 `json:"unit_id"` + Doctor_Id *uint `json:"doctor_Id"` + Status_Code erc.DataApprovalCode `json:"status_code"` } type ReadListDto struct { @@ -19,9 +22,10 @@ type ReadListDto struct { } type FilterDto struct { - Encounter_Id *uint `json:"encounter-id"` - Unit_Id *uint `json:"unit-id"` - Doctor_Id *uint `json:"doctor-id"` + Encounter_Id *uint `json:"encounter-id"` + Unit_Id *uint `json:"unit-id"` + Doctor_Id *uint `json:"doctor-id"` + Status_Code erc.DataApprovalCode `json:"status-code"` } type ReadDetailDto struct { @@ -46,11 +50,12 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Unit_Id *uint16 `json:"unit_id"` - Unit *eu.Unit `json:"unit,omitempty"` - Doctor_Id *uint `json:"doctor_id"` - Doctor *ed.Doctor `json:"doctor,omitempty"` + Encounter_Id *uint `json:"encounter_id"` + Unit_Id *uint16 `json:"unit_id"` + Unit *eu.Unit `json:"unit,omitempty"` + Doctor_Id *uint `json:"doctor_id"` + Doctor *ed.Doctor `json:"doctor,omitempty"` + Status_Code *erc.DataApprovalCode `json:"status_code"` } func (d InternalReference) ToResponse() ResponseDto { @@ -60,6 +65,7 @@ func (d InternalReference) ToResponse() ResponseDto { Unit: d.Unit, Doctor_Id: d.Doctor_Id, Doctor: d.Doctor, + Status_Code: d.Status_Code, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/rehab/dto.go b/internal/domain/main-entities/rehab/dto.go index 0cec61d8..9dd16c3e 100644 --- a/internal/domain/main-entities/rehab/dto.go +++ b/internal/domain/main-entities/rehab/dto.go @@ -1,14 +1,20 @@ package rehab import ( + erc "simrs-vx/internal/domain/references/common" + ere "simrs-vx/internal/domain/references/encounter" + ecore "simrs-vx/internal/domain/base-entities/core" - ed "simrs-vx/internal/domain/main-entities/doctor" + "time" ) type CreateDto struct { - Encounter_Id *uint `json:"encounter_id"` - Doctor_Id *uint `json:"doctor_id"` - AllocatedVisitCount *int `json:"allocatedVisitCount"` + Encounter_Id *uint `json:"encounter_id"` + Parent_Encounter_Id *uint `json:"parent_encounter_id"` + AllocatedVisitCount *int `json:"allocatedVisitCount"` + ExpiredAt *time.Time `json:"expiredAt"` + VisitMode_Code ere.VisitModeCode `json:"visitMode_code"` + Status_Code erc.DataStatusCode `json:"status_code"` } type ReadListDto struct { @@ -18,8 +24,9 @@ type ReadListDto struct { } type FilterDto struct { - Encounter_Id *uint `json:"encounter-id"` - Doctor_Id *uint `json:"doctor-id"` + Encounter_Id *uint `json:"encounter-id"` + Parent_Encounter_Id *uint `json:"parent-encounter-id"` + VisitMode_Code ere.VisitModeCode `json:"visitMode-code"` } type ReadDetailDto struct { @@ -44,18 +51,22 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Doctor_Id *uint `json:"doctor_id"` - Doctor *ed.Doctor `json:"doctor,omitempty"` - AllocatedVisitCount *int `json:"allocatedVisitCount"` + Encounter_Id *uint `json:"encounter_id"` + Parent_Encounter_Id *uint `json:"parent_encounter_id"` + AllocatedVisitCount *int `json:"allocatedVisitCount"` + ExpiredAt *time.Time `json:"expiredAt"` + VisitMode_Code *ere.VisitModeCode `json:"visitMode_code"` + Status_Code *erc.DataStatusCode `json:"status_code"` } func (d Rehab) ToResponse() ResponseDto { resp := ResponseDto{ Encounter_Id: d.Encounter_Id, - Doctor_Id: d.Doctor_Id, - Doctor: d.Doctor, + Parent_Encounter_Id: d.Parent_Encounter_Id, AllocatedVisitCount: d.AllocatedVisitCount, + ExpiredAt: d.ExpiredAt, + VisitMode_Code: d.VisitMode_Code, + Status_Code: d.Status_Code, } resp.Main = d.Main return resp diff --git a/internal/use-case/main-use-case/ambulatory/helper.go b/internal/use-case/main-use-case/ambulatory/helper.go index a8a00e0d..912211c0 100644 --- a/internal/use-case/main-use-case/ambulatory/helper.go +++ b/internal/use-case/main-use-case/ambulatory/helper.go @@ -22,7 +22,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Ambulatory) { data.Encounter_Id = inputSrc.Encounter_Id data.Class_Code = inputSrc.Class_Code - data.VisitMode_Code = inputSrc.VisitMode_Code } func CheckClassCode(input *string) (ere.AmbulatoryClassCode, error) { diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 102b8a1f..ec2ea231 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -128,9 +128,8 @@ func Create(input e.CreateDto) (*d.Data, error) { case ere.ECAmbulatory: subCodeAmbulatory := subCode.(ere.AmbulatoryClassCode) ambCreate := ea.CreateDto{ - Encounter_Id: &data.Id, - Class_Code: subCodeAmbulatory, - VisitMode_Code: *input.VisitMode_Code, + Encounter_Id: &data.Id, + Class_Code: subCodeAmbulatory, } _, err = ua.CreateData(ambCreate, &event, tx) if err != nil { @@ -153,7 +152,6 @@ func Create(input e.CreateDto) (*d.Data, error) { // create data rehab if _, err = ur.CreateData(er.CreateDto{ Encounter_Id: &data.Id, - Doctor_Id: input.Appointment_Doctor_Id, AllocatedVisitCount: input.AllocatedVisitCount}, &event, tx); err != nil { return err } @@ -441,7 +439,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { } func CheckOut(input e.DischargeDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Ambulatory"} + rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Ambulatory,Rehab"} var data *e.Encounter var err error @@ -682,7 +680,6 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { if data.Ambulatory.Class_Code == ere.ACCRehab { if err := updateRehabDoctor(er.UpdateDto{CreateDto: er.CreateDto{ Encounter_Id: &data.Id, - Doctor_Id: input.Responsible_Doctor_Id, }}, &event, tx); err != nil { return err } diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index 67cef58b..9c522ed6 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -781,31 +781,31 @@ func setDBError(event *pl.Event, err error, ctx any) error { return pl.SetLogError(event, ctx) } -func updateRehabDoctor(input er.UpdateDto, event *pl.Event, dbx ...*gorm.DB) error { - pl.SetLogInfo(event, "started", "DBUpdate") - - var tx *gorm.DB - if len(dbx) > 0 { - tx = dbx[0] - } else { - tx = dg.I - } - - result := tx. - Model(&er.Rehab{}). - Where("\"Encounter_Id\" = (?)", input.Encounter_Id). - Update("\"Doctor_Id\"", input.Doctor_Id) - - if result.Error != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-update-fail", - Detail: "Database update failed", - Raw: result.Error, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(event, nil, "complete") - return nil -} +//func updateRehabDoctor(input er.UpdateDto, event *pl.Event, dbx ...*gorm.DB) error { +// pl.SetLogInfo(event, "started", "DBUpdate") +// +// var tx *gorm.DB +// if len(dbx) > 0 { +// tx = dbx[0] +// } else { +// tx = dg.I +// } +// +// result := tx. +// Model(&er.Rehab{}). +// Where("\"Encounter_Id\" = (?)", input.Encounter_Id). +// Update("\"Doctor_Id\"", input.Doctor_Id) +// +// if result.Error != nil { +// event.Status = "failed" +// event.ErrInfo = pl.ErrorInfo{ +// Code: "data-update-fail", +// Detail: "Database update failed", +// Raw: result.Error, +// } +// return pl.SetLogError(event, input) +// } +// +// pl.SetLogInfo(event, nil, "complete") +// return nil +//} diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index 0c51a8d6..88c50113 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -292,5 +292,5 @@ func verifyAllocatedVisitCount(i e.CreateDto, event *pl.Event) (e.Encounter, boo return e.Encounter{}, false, pl.SetLogError(event, i) } - return recentEncounterAdm, countEncounterSeries < int64(*recentEncounterAdm.Rehab.AllocatedVisitCount), nil + return recentEncounterAdm, countEncounterSeries < int64(*recentEncounterAdm.Rehab_Adm.AllocatedVisitCount), nil } diff --git a/internal/use-case/main-use-case/rehab/helper.go b/internal/use-case/main-use-case/rehab/helper.go index 5c06ca0a..c5da08ad 100644 --- a/internal/use-case/main-use-case/rehab/helper.go +++ b/internal/use-case/main-use-case/rehab/helper.go @@ -18,6 +18,9 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Rehab) { } data.Encounter_Id = inputSrc.Encounter_Id - data.Doctor_Id = inputSrc.Doctor_Id + data.Parent_Encounter_Id = inputSrc.Parent_Encounter_Id data.AllocatedVisitCount = inputSrc.AllocatedVisitCount + data.ExpiredAt = inputSrc.ExpiredAt + data.VisitMode_Code = &inputSrc.VisitMode_Code + data.Status_Code = &inputSrc.Status_Code } From 3e3213da3884ed5f4b2fa287fd60ed3ef0d7acd7 Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 6 Nov 2025 15:10:16 +0700 Subject: [PATCH 089/329] rename encounter rehab --- cmd/main-migration/migrations/atlas.sum | 6 +++--- internal/domain/main-entities/encounter/entity.go | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 4dbe2544..6b18cefe 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:KxMvALnpFUI2RXpBZgkJ312FeLtrm9L0o+CqgJbm40U= +h1:cfOFDnxgOCgOIto2DMofzQkPlSF7P+eTsp8Msr3p8sw= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -69,5 +69,5 @@ h1:KxMvALnpFUI2RXpBZgkJ312FeLtrm9L0o+CqgJbm40U= 20251104043530.sql h1:qvYVp3ysPf27f1BcoRNCFGovxuVE12lg9d6Xzda6zWU= 20251104080952.sql h1:avghpv1n3yaCDR/TA0X+hgxDGoLBQGu/GJUwj4VT/Ic= 20251104084135.sql h1:rg+eRE5/5sYWR7z+Xyn0zKw8rr8P/oWxF0xhcNVnNec= -20251106054706.sql h1:a17rQ3uAX09BpVFpAFoY8NM6gfsmYVvgNNZaQuWs6T0= -20251106054849.sql h1:TU0HU+jAfs5225rggWP5TjPgb272vQoeiLvEoGhKRbs= +20251106054706.sql h1:WIUuH4oOWHkMJwo2OFlwQc+jT+B1xwXauw0+wbgVdnI= +20251106054849.sql h1:VJHNZBBzNiibsEwvDp90/h3BLOOLx76Pszpl6e/YqvU= diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index c53912ab..bfd70333 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -68,8 +68,8 @@ type Encounter struct { Ambulatory *eam.Ambulatory `json:"ambulatory,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Emergency *eem.Emergency `json:"emergency,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Inpatient *eip.Inpatient `json:"inpatient,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Rehab_Adm *er.Basic `json:"rehab_adm,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Rehab_Series *[]er.Basic `json:"rehab_series,omitempty" gorm:"foreignKey:Parent_Encounter_Id;references:Id"` + Rehab *er.Basic `json:"rehab,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + RehabChildren *[]er.Basic `json:"rehabChildren,omitempty" gorm:"foreignKey:Parent_Encounter_Id;references:Id"` } func (d Encounter) IsDone() bool { From b597b76092b58c3aa8f92efe4fca2941023895e1 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 15:24:42 +0700 Subject: [PATCH 090/329] division, division-position ids into codes --- .../migrations/20251106081846.sql | 6 ++ cmd/main-migration/migrations/atlas.sum | 3 +- .../division-position/base/entity.go | 1 - .../main-entities/division-position/dto.go | 55 ++++++++++--------- .../main-entities/division-position/entity.go | 2 +- internal/domain/main-entities/division/dto.go | 25 +++++---- .../domain/main-entities/division/entity.go | 9 ++- .../main-handler/division-position/handler.go | 18 +++--- .../main-handler/division/handler.go | 18 +++--- .../interface/main-handler/main-handler.go | 4 +- .../main-use-case/division-position/case.go | 4 +- .../main-use-case/division-position/helper.go | 2 +- .../main-use-case/division-position/lib.go | 9 ++- .../use-case/main-use-case/division/case.go | 4 +- .../use-case/main-use-case/division/helper.go | 2 +- .../use-case/main-use-case/division/lib.go | 9 ++- 16 files changed, 96 insertions(+), 75 deletions(-) create mode 100644 cmd/main-migration/migrations/20251106081846.sql diff --git a/cmd/main-migration/migrations/20251106081846.sql b/cmd/main-migration/migrations/20251106081846.sql new file mode 100644 index 00000000..352d6a39 --- /dev/null +++ b/cmd/main-migration/migrations/20251106081846.sql @@ -0,0 +1,6 @@ +-- Create index "idx_Division_Code" to table: "Division" +CREATE UNIQUE INDEX "idx_Division_Code" ON "public"."Division" ("Code"); +-- Modify "Division" table +ALTER TABLE "public"."Division" DROP CONSTRAINT "uni_Division_Code", DROP CONSTRAINT "fk_Division_Childrens", DROP COLUMN "Parent_Id", ADD CONSTRAINT "fk_Division_Childrens" FOREIGN KEY ("Parent_Code") REFERENCES "public"."Division" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "DivisionPosition" table +ALTER TABLE "public"."DivisionPosition" DROP CONSTRAINT "fk_DivisionPosition_Division", DROP COLUMN "Division_Id", ADD CONSTRAINT "fk_DivisionPosition_Division" FOREIGN KEY ("Division_Code") REFERENCES "public"."Division" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 5a963973..9f504821 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:aVDoCaB6Gy2SKHrUbR2KDqH9ByMHPVcYzTGW5846kt8= +h1:gZkp4dTWkJKTmsiLhz5DI6QMvJuBGfurq4lkNKPThjU= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -80,3 +80,4 @@ h1:aVDoCaB6Gy2SKHrUbR2KDqH9ByMHPVcYzTGW5846kt8= 20251106071906.sql h1:/TUZA3XpMY23qEJXdkTwlzrNMvSSl6JJniPcgAttBaw= 20251106073157.sql h1:78txeibJ602DMD7huD618ZSMt6phSRzDNPTlo0PGyrc= 20251106074218.sql h1:8Xz7WywrtUnSxOHhlal53gG9rE7r86LFUt5zBFe/mIs= +20251106081846.sql h1:jp91Bf5bxGXMiUB1VIuN6y768vb2iWwow44WfCE5J5k= diff --git a/internal/domain/main-entities/division-position/base/entity.go b/internal/domain/main-entities/division-position/base/entity.go index b2635553..6cf79b45 100644 --- a/internal/domain/main-entities/division-position/base/entity.go +++ b/internal/domain/main-entities/division-position/base/entity.go @@ -7,7 +7,6 @@ import ( type Basic struct { ecore.SmallMain // adjust this according to the needs - Division_Id *uint16 `json:"division_id"` Division_Code *string `json:"division_code" gorm:"size:10"` Code string `json:"code" gorm:"unique;size:10"` Name string `json:"name" gorm:"size:50"` diff --git a/internal/domain/main-entities/division-position/dto.go b/internal/domain/main-entities/division-position/dto.go index b93e0e98..55af6bf8 100644 --- a/internal/domain/main-entities/division-position/dto.go +++ b/internal/domain/main-entities/division-position/dto.go @@ -7,11 +7,11 @@ import ( ) type CreateDto struct { - Division_Id *uint16 `json:"division_id"` - Code string `json:"code" validate:"maxLength=10"` - Name string `json:"name" validate:"maxLength=50"` - HeadStatus bool `json:"headStatus"` - Employee_Id *uint `json:"employee_id"` + Division_Code *string `json:"division_code"` + Code string `json:"code" validate:"maxLength=10"` + Name string `json:"name" validate:"maxLength=50"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` } type ReadListDto struct { @@ -22,26 +22,27 @@ type ReadListDto struct { } type FilterDto struct { - Division_Id *uint16 `json:"division-id"` - Code string `json:"code"` - Name string `json:"name"` - HeadStatus *bool `json:"head-status"` - Employee_Id *uint `json:"employee-id"` - Search string `json:"search" gormhelper:"searchColumns=Code,Name"` + Division_Code *string `json:"division-code"` + Code string `json:"code"` + Name string `json:"name"` + HeadStatus *bool `json:"head-status"` + Employee_Id *uint `json:"employee-id"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { @@ -52,23 +53,23 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain - Division_Id *uint16 `json:"division_id"` - Division *ed.Division `json:"division,omitempty"` - Code string `json:"code"` - Name string `json:"name"` - HeadStatus bool `json:"headStatus"` - Employee_Id *uint `json:"employee_id"` - Employee *ee.Employee `json:"employee,omitempty"` + Division_Code *string `json:"division_code"` + Division *ed.Division `json:"division,omitempty"` + Code string `json:"code"` + Name string `json:"name"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` + Employee *ee.Employee `json:"employee,omitempty"` } func (d DivisionPosition) ToResponse() ResponseDto { resp := ResponseDto{ - Division_Id: d.Division_Id, - Code: d.Code, - Name: d.Name, - HeadStatus: d.HeadStatus, - Employee_Id: d.Employee_Id, - Employee: d.Employee, + Division_Code: d.Division_Code, + Code: d.Code, + Name: d.Name, + HeadStatus: d.HeadStatus, + Employee_Id: d.Employee_Id, + Employee: d.Employee, } resp.SmallMain = d.SmallMain if d.Division != nil { diff --git a/internal/domain/main-entities/division-position/entity.go b/internal/domain/main-entities/division-position/entity.go index d71ba01c..d654d21f 100644 --- a/internal/domain/main-entities/division-position/entity.go +++ b/internal/domain/main-entities/division-position/entity.go @@ -7,5 +7,5 @@ import ( type DivisionPosition struct { eb.Basic - Division *ed.Division `json:"division" gorm:"foreignKey:Division_Id;references:Id"` + Division *ed.Division `json:"division" gorm:"foreignKey:Division_Code;references:Code"` } diff --git a/internal/domain/main-entities/division/dto.go b/internal/domain/main-entities/division/dto.go index 38915b56..30f0b238 100644 --- a/internal/domain/main-entities/division/dto.go +++ b/internal/domain/main-entities/division/dto.go @@ -6,9 +6,9 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=10"` - Name string `json:"name" validate:"maxLength=50"` - Parent_Id *uint16 `json:"parent_id"` + Code string `json:"code" validate:"maxLength=10"` + Name string `json:"name" validate:"maxLength=50"` + Parent_Code *string `json:"parent_code"` } type ReadListDto struct { @@ -20,25 +20,26 @@ type ReadListDto struct { } type FilterDto struct { - Code string `json:"code"` - Name string `json:"name"` - Parent_Id *uint16 `json:"parent-id"` - Search string `json:"search" gormhelper:"searchColumns=Code,Name"` + Code string `json:"code"` + Name string `json:"name"` + Parent_Code *string `json:"parent-code"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` Includes string `json:"includes"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { @@ -51,7 +52,7 @@ type ResponseDto struct { ecore.SmallMain Code string `json:"code"` Name string `json:"name"` - Parent_Id *uint16 `json:"parent_id"` + Parent_Code *string `json:"parent_code"` Parent *Division `json:"parent,omitempty"` Childrens []Division `json:"childrens,omitempty"` DivisionPosition []edpb.Basic `json:"divisionPositions,omitempty"` @@ -61,7 +62,7 @@ func (d Division) ToResponse() ResponseDto { resp := ResponseDto{ Code: d.Code, Name: d.Name, - Parent_Id: d.Parent_Id, + Parent_Code: d.Parent_Code, Parent: d.Parent, Childrens: d.Childrens, DivisionPosition: d.DivisionPositions, diff --git a/internal/domain/main-entities/division/entity.go b/internal/domain/main-entities/division/entity.go index bcef1c7f..d79e9e86 100644 --- a/internal/domain/main-entities/division/entity.go +++ b/internal/domain/main-entities/division/entity.go @@ -7,11 +7,10 @@ import ( type Division struct { ecore.SmallMain // adjust this according to the needs - Code string `json:"code" gorm:"unique;size:10"` + Code string `json:"code" gorm:"uniqueIndex;size:10"` Name string `json:"name" gorm:"size:50"` - Parent_Id *uint16 `json:"parent_id"` Parent_Code *string `json:"parent_code" gorm:"size:10"` - Parent *Division `json:"parent" gorm:"foreignKey:Parent_Id;references:Id"` - Childrens []Division `json:"childrens" gorm:"foreignKey:Parent_Id"` // may need references to self - DivisionPositions []edpb.Basic `json:"divisionPositions,omitempty" gorm:"foreignKey:Division_Id;references:Id"` + Parent *Division `json:"parent" gorm:"foreignKey:Parent_Code;references:Code"` + Childrens []Division `json:"childrens" gorm:"foreignKey:Parent_Code;references:Code"` // may need references to self + DivisionPositions []edpb.Basic `json:"divisionPositions,omitempty" gorm:"foreignKey:Division_Code;references:Code"` } diff --git a/internal/interface/main-handler/division-position/handler.go b/internal/interface/main-handler/division-position/handler.go index 180b96ea..3b0f9627 100644 --- a/internal/interface/main-handler/division-position/handler.go +++ b/internal/interface/main-handler/division-position/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ 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.Code = code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/division/handler.go b/internal/interface/main-handler/division/handler.go index ee4cbea5..640c180e 100644 --- a/internal/interface/main-handler/division/handler.go +++ b/internal/interface/main-handler/division/handler.go @@ -33,21 +33,21 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} sf.UrlQueryParam(&dto, *r.URL) - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -55,19 +55,19 @@ 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.Code = code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index abed5f2d..071e7e24 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -290,8 +290,8 @@ func SetRoutes() http.Handler { }) /******************** sources ********************/ - hc.RegCrud(r, "/v1/division", division.O) - hc.RegCrud(r, "/v1/division-position", divisionposition.O) + hc.RegCrudByCode(r, "/v1/division", division.O) + hc.RegCrudByCode(r, "/v1/division-position", divisionposition.O) hc.RegCrud(r, "/v1/installation", installation.O) hc.RegCrud(r, "/v1/unit", unit.O) hc.RegCrud(r, "/v1/pharmacy-company", pharmacycompany.O) diff --git a/internal/use-case/main-use-case/division-position/case.go b/internal/use-case/main-use-case/division-position/case.go index 159e9edc..0490bcfe 100644 --- a/internal/use-case/main-use-case/division-position/case.go +++ b/internal/use-case/main-use-case/division-position/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: &input.Code} var data *e.DivisionPosition var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.DivisionPosition var err error diff --git a/internal/use-case/main-use-case/division-position/helper.go b/internal/use-case/main-use-case/division-position/helper.go index 482dbc4e..c3e0c71b 100644 --- a/internal/use-case/main-use-case/division-position/helper.go +++ b/internal/use-case/main-use-case/division-position/helper.go @@ -17,7 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.DivisionPosition) { inputSrc = &inputTemp.CreateDto } - data.Division_Id = inputSrc.Division_Id + data.Division_Code = inputSrc.Division_Code data.Code = inputSrc.Code data.Name = inputSrc.Name data.HeadStatus = inputSrc.HeadStatus diff --git a/internal/use-case/main-use-case/division-position/lib.go b/internal/use-case/main-use-case/division-position/lib.go index d1327d47..e5036812 100644 --- a/internal/use-case/main-use-case/division-position/lib.go +++ b/internal/use-case/main-use-case/division-position/lib.go @@ -81,7 +81,14 @@ 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 input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).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/division/case.go b/internal/use-case/main-use-case/division/case.go index daabd2f8..c955aed7 100644 --- a/internal/use-case/main-use-case/division/case.go +++ b/internal/use-case/main-use-case/division/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: &input.Code} var data *e.Division var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Division var err error diff --git a/internal/use-case/main-use-case/division/helper.go b/internal/use-case/main-use-case/division/helper.go index c0341ee0..2bb7a932 100644 --- a/internal/use-case/main-use-case/division/helper.go +++ b/internal/use-case/main-use-case/division/helper.go @@ -19,5 +19,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Division) { data.Code = inputSrc.Code data.Name = inputSrc.Name - data.Parent_Id = inputSrc.Parent_Id + data.Parent_Code = inputSrc.Parent_Code } diff --git a/internal/use-case/main-use-case/division/lib.go b/internal/use-case/main-use-case/division/lib.go index 56ce34f7..62a10d5b 100644 --- a/internal/use-case/main-use-case/division/lib.go +++ b/internal/use-case/main-use-case/division/lib.go @@ -91,9 +91,16 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e tx = dg.I } + if input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + if err := tx. Scopes(gh.Preload(input.Includes)). - First(&data, input.Id).Error; err != nil { + First(&data).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { return nil, processedErr } From 42b1b48e36d1be9c653dda5a7271be7969d7f837 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 15:32:05 +0700 Subject: [PATCH 091/329] unit,unit-position,installation-position ids into codes --- cmd/main-migration/migrations/20251106082844.sql | 6 ++++++ cmd/main-migration/migrations/atlas.sum | 3 ++- .../installation-position/base/entity.go | 15 ++++++++------- .../main-entities/unit-position/base/entity.go | 1 + internal/domain/main-entities/unit/entity.go | 15 ++++++++------- 5 files changed, 25 insertions(+), 15 deletions(-) create mode 100644 cmd/main-migration/migrations/20251106082844.sql diff --git a/cmd/main-migration/migrations/20251106082844.sql b/cmd/main-migration/migrations/20251106082844.sql new file mode 100644 index 00000000..c94fb359 --- /dev/null +++ b/cmd/main-migration/migrations/20251106082844.sql @@ -0,0 +1,6 @@ +-- Modify "InstallationPosition" table +ALTER TABLE "public"."InstallationPosition" ADD COLUMN "Installation_Code" character varying(10) NULL; +-- Modify "Unit" table +ALTER TABLE "public"."Unit" ADD COLUMN "Installation_Code" character varying(10) NULL; +-- Modify "UnitPosition" table +ALTER TABLE "public"."UnitPosition" ADD COLUMN "Unit_Code" character varying(10) NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 9f504821..8833af3a 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:gZkp4dTWkJKTmsiLhz5DI6QMvJuBGfurq4lkNKPThjU= +h1:w/qs7zN2FLnTjsmLVrFnMQWMxp3LYDJa0RLY74HVK0g= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -81,3 +81,4 @@ h1:gZkp4dTWkJKTmsiLhz5DI6QMvJuBGfurq4lkNKPThjU= 20251106073157.sql h1:78txeibJ602DMD7huD618ZSMt6phSRzDNPTlo0PGyrc= 20251106074218.sql h1:8Xz7WywrtUnSxOHhlal53gG9rE7r86LFUt5zBFe/mIs= 20251106081846.sql h1:jp91Bf5bxGXMiUB1VIuN6y768vb2iWwow44WfCE5J5k= +20251106082844.sql h1:RHYzRO4G1fSWwf+xc/3QezZ/Iil67cZPIgNpNz3TNhQ= diff --git a/internal/domain/main-entities/installation-position/base/entity.go b/internal/domain/main-entities/installation-position/base/entity.go index 02fbbe84..e5e8c589 100644 --- a/internal/domain/main-entities/installation-position/base/entity.go +++ b/internal/domain/main-entities/installation-position/base/entity.go @@ -6,13 +6,14 @@ import ( ) type Basic struct { - ecore.SmallMain // adjust this according to the needs - Installation_Id *uint16 `json:"installation_id" gorm:"not null"` - Code string `json:"code" gorm:"unique;size:10;not null"` - Name string `json:"name" gorm:"size:30;not null"` - HeadStatus bool `json:"headStatus"` - Employee_Id *uint `json:"employee_id"` - Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` + ecore.SmallMain // adjust this according to the needs + Installation_Id *uint16 `json:"installation_id" gorm:"not null"` + Installation_Code *string `json:"installation_code" gorm:"size:10"` + Code string `json:"code" gorm:"unique;size:10;not null"` + Name string `json:"name" gorm:"size:30;not null"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` + Employee *ee.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` } func (Basic) TableName() string { diff --git a/internal/domain/main-entities/unit-position/base/entity.go b/internal/domain/main-entities/unit-position/base/entity.go index b8e6a63a..e7376e51 100644 --- a/internal/domain/main-entities/unit-position/base/entity.go +++ b/internal/domain/main-entities/unit-position/base/entity.go @@ -8,6 +8,7 @@ import ( type Basic struct { ecore.SmallMain // adjust this according to the needs Unit_Id *uint16 `json:"unit_id" gorm:"not null"` + Unit_Code *string `json:"unit_code" gorm:"size:10"` Code string `json:"code" gorm:"unique;size:10;not null"` Name string `json:"name" gorm:"size:30;not null"` HeadStatus bool `json:"headStatus"` diff --git a/internal/domain/main-entities/unit/entity.go b/internal/domain/main-entities/unit/entity.go index 2142790f..254bc163 100644 --- a/internal/domain/main-entities/unit/entity.go +++ b/internal/domain/main-entities/unit/entity.go @@ -8,11 +8,12 @@ import ( ) type Unit struct { - ecore.SmallMain // adjust this according to the needs - Installation_Id *uint16 `json:"installation_id"` - Installation *ei.Installation `json:"installation" gorm:"foreignKey:Installation_Id"` - Code string `json:"code" gorm:"unique;size:10"` - Name string `json:"name" gorm:"size:50"` - Type_Code *ero.UnitTypeCode `json:"type_code"` - UnitPositions []eub.Basic `json:"unitPositions,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` + ecore.SmallMain // adjust this according to the needs + Installation_Id *uint16 `json:"installation_id"` + Installation_Code *string `json:"installation_code" gorm:"size:10"` + Installation *ei.Installation `json:"installation" gorm:"foreignKey:Installation_Id"` + Code string `json:"code" gorm:"unique;size:10"` + Name string `json:"name" gorm:"size:50"` + Type_Code *ero.UnitTypeCode `json:"type_code"` + UnitPositions []eub.Basic `json:"unitPositions,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` } From 6ed038eb543ebd8dffae80c314e4fa5311ae6382 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 15:48:32 +0700 Subject: [PATCH 092/329] unit, unit-position,installation-position removes ids --- .../installation-position/base/entity.go | 1 - .../installation-position/dto.go | 57 ++++++++++--------- .../installation-position/entity.go | 2 +- .../main-entities/installation/entity.go | 2 +- .../unit-position/base/entity.go | 1 - .../domain/main-entities/unit-position/dto.go | 15 ++--- internal/domain/main-entities/unit/dto.go | 45 ++++++++------- internal/domain/main-entities/unit/entity.go | 5 +- .../installation-position/handler.go | 18 +++--- .../interface/main-handler/main-handler.go | 16 +++--- .../main-handler/unit-position/handler.go | 18 +++--- .../interface/main-handler/unit/handler.go | 18 +++--- .../installation-position/case.go | 6 +- .../installation-position/helper.go | 2 +- .../installation-position/lib.go | 4 +- .../main-use-case/unit-position/case.go | 6 +- .../main-use-case/unit-position/helper.go | 2 +- .../main-use-case/unit-position/lib.go | 2 +- internal/use-case/main-use-case/unit/case.go | 4 +- .../use-case/main-use-case/unit/helper.go | 2 +- internal/use-case/main-use-case/unit/lib.go | 9 ++- 21 files changed, 121 insertions(+), 114 deletions(-) diff --git a/internal/domain/main-entities/installation-position/base/entity.go b/internal/domain/main-entities/installation-position/base/entity.go index e5e8c589..3ebc171b 100644 --- a/internal/domain/main-entities/installation-position/base/entity.go +++ b/internal/domain/main-entities/installation-position/base/entity.go @@ -7,7 +7,6 @@ import ( type Basic struct { ecore.SmallMain // adjust this according to the needs - Installation_Id *uint16 `json:"installation_id" gorm:"not null"` Installation_Code *string `json:"installation_code" gorm:"size:10"` Code string `json:"code" gorm:"unique;size:10;not null"` Name string `json:"name" gorm:"size:30;not null"` diff --git a/internal/domain/main-entities/installation-position/dto.go b/internal/domain/main-entities/installation-position/dto.go index aada7443..12e13afc 100644 --- a/internal/domain/main-entities/installation-position/dto.go +++ b/internal/domain/main-entities/installation-position/dto.go @@ -7,11 +7,11 @@ import ( ) type CreateDto struct { - Installation_Id *uint16 `json:"installation_id" validate:"required"` - Code string `json:"code" validate:"maxLength=10;required"` - Name string `json:"name" validate:"maxLength=30;required"` - HeadStatus bool `json:"headStatus"` - Employee_Id *uint `json:"employee_id"` + Installation_Code *string `json:"installation_code" validate:"required"` + Code string `json:"code" validate:"maxLength=10;required"` + Name string `json:"name" validate:"maxLength=30;required"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` } type ReadListDto struct { @@ -22,26 +22,27 @@ type ReadListDto struct { } type FilterDto struct { - Installation_Id *uint16 `json:"installation-id"` - Code string `json:"code"` - Name string `json:"name"` - HeadStatus *bool `json:"head-status"` - Employee_Id *uint `json:"employee-id"` - Search string `json:"search" gormhelper:"searchColumns=Code,Name"` + Installation_Code *string `json:"installation-code"` + Code string `json:"code"` + Name string `json:"name"` + HeadStatus *bool `json:"head-status"` + Employee_Id *uint `json:"employee-id"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { @@ -52,24 +53,24 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain - Installation_Id *uint16 `json:"installation_id"` - Installation *ei.Installation `json:"installation,omitempty"` - Code string `json:"code"` - Name string `json:"name"` - HeadStatus bool `json:"headStatus"` - Employee_Id *uint `json:"employee_id"` - Employee *ee.Employee `json:"employee,omitempty"` + Installation_Code *string `json:"installation_code"` + Installation *ei.Installation `json:"installation,omitempty"` + Code string `json:"code"` + Name string `json:"name"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` + Employee *ee.Employee `json:"employee,omitempty"` } func (d InstallationPosition) ToResponse() ResponseDto { resp := ResponseDto{ - Installation_Id: d.Installation_Id, - Installation: d.Installation, - Code: d.Code, - Name: d.Name, - HeadStatus: d.HeadStatus, - Employee_Id: d.Employee_Id, - Employee: d.Employee, + Installation_Code: d.Installation_Code, + Installation: d.Installation, + Code: d.Code, + Name: d.Name, + HeadStatus: d.HeadStatus, + Employee_Id: d.Employee_Id, + Employee: d.Employee, } resp.SmallMain = d.SmallMain return resp diff --git a/internal/domain/main-entities/installation-position/entity.go b/internal/domain/main-entities/installation-position/entity.go index 48e95ac5..ba8ddece 100644 --- a/internal/domain/main-entities/installation-position/entity.go +++ b/internal/domain/main-entities/installation-position/entity.go @@ -7,5 +7,5 @@ import ( type InstallationPosition struct { eib.Basic // adjust this according to the needs - Installation *ei.Installation `json:"installation,omitempty" gorm:"foreignKey:Installation_Id;references:Id"` + Installation *ei.Installation `json:"installation,omitempty" gorm:"foreignKey:Installation_Code;references:Code"` } diff --git a/internal/domain/main-entities/installation/entity.go b/internal/domain/main-entities/installation/entity.go index dea63a45..5cc82430 100644 --- a/internal/domain/main-entities/installation/entity.go +++ b/internal/domain/main-entities/installation/entity.go @@ -11,5 +11,5 @@ type Installation struct { Code string `json:"code" gorm:"unique;size:10"` Name string `json:"name" gorm:"size:50"` EncounterClass_Code ere.EncounterClassCode `json:"encounterClass_code" gorm:"size:10"` - InstallationPositions []eipb.Basic `json:"installationPositions,omitempty" gorm:"foreignKey:Installation_Id;references:Id"` + InstallationPositions []eipb.Basic `json:"installationPositions,omitempty" gorm:"foreignKey:Installation_Code;references:Code"` } diff --git a/internal/domain/main-entities/unit-position/base/entity.go b/internal/domain/main-entities/unit-position/base/entity.go index e7376e51..eb046dfc 100644 --- a/internal/domain/main-entities/unit-position/base/entity.go +++ b/internal/domain/main-entities/unit-position/base/entity.go @@ -7,7 +7,6 @@ import ( type Basic struct { ecore.SmallMain // adjust this according to the needs - Unit_Id *uint16 `json:"unit_id" gorm:"not null"` Unit_Code *string `json:"unit_code" gorm:"size:10"` Code string `json:"code" gorm:"unique;size:10;not null"` Name string `json:"name" gorm:"size:30;not null"` diff --git a/internal/domain/main-entities/unit-position/dto.go b/internal/domain/main-entities/unit-position/dto.go index cc52c493..856cec77 100644 --- a/internal/domain/main-entities/unit-position/dto.go +++ b/internal/domain/main-entities/unit-position/dto.go @@ -7,7 +7,7 @@ import ( ) type CreateDto struct { - Unit_Id *uint16 `json:"unit_id" validate:"required"` + Unit_Code *string `json:"unit_code" validate:"required"` Code string `json:"code" validate:"maxLength=10;required"` Name string `json:"name" validate:"maxLength=30;required"` HeadStatus bool `json:"headStatus"` @@ -22,7 +22,7 @@ type ReadListDto struct { } type FilterDto struct { - Unit_Id *uint16 `json:"unit-id"` + Unit_Code *string `json:"unit-code"` Code string `json:"code"` Name string `json:"name"` HeadStatus *bool `json:"head-status"` @@ -31,17 +31,18 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { @@ -52,7 +53,7 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain - Unit_Id *uint16 `json:"unit_id"` + Unit_Code *string `json:"unit_code"` Unit *eu.Unit `json:"unit,omitempty"` Code string `json:"code"` Name string `json:"name"` @@ -63,7 +64,7 @@ type ResponseDto struct { func (d UnitPosition) ToResponse() ResponseDto { resp := ResponseDto{ - Unit_Id: d.Unit_Id, + Unit_Code: d.Unit_Code, Unit: d.Unit, Code: d.Code, Name: d.Name, diff --git a/internal/domain/main-entities/unit/dto.go b/internal/domain/main-entities/unit/dto.go index e47afed9..f272ecec 100644 --- a/internal/domain/main-entities/unit/dto.go +++ b/internal/domain/main-entities/unit/dto.go @@ -7,9 +7,9 @@ import ( ) type CreateDto struct { - Installation_Id *uint16 `json:"installation_id"` - Code string `json:"code" validate:"maxLength=10"` - Name string `json:"name" validate:"maxLength=50"` + Installation_Code *string `json:"installation_code"` + Code string `json:"code" validate:"maxLength=10"` + Name string `json:"name" validate:"maxLength=50"` } type ReadListDto struct { @@ -20,26 +20,27 @@ type ReadListDto struct { } type FilterDto struct { - Installation_Id *uint16 `json:"installation-id"` - Code string `json:"code"` - Name string `json:"name"` - Search string `json:"search" gormhelper:"searchColumns=Code,Name"` + Installation_Code *string `json:"installation-code"` + Code string `json:"code"` + Name string `json:"name"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` } type ReadDetailDto struct { - Id uint16 `json:"id"` - Installation_Id *uint16 `json:"installation_id"` - Code *string `json:"code"` - Includes string `json:"includes"` + Id *uint16 `json:"id"` + Installation_Code *string `json:"installation_code"` + Code *string `json:"code"` + Includes string `json:"includes"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { @@ -50,19 +51,19 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain - Installation_Id *uint16 `json:"installation_id"` - Installation *ei.Installation `json:"installation,omitempty"` - Code string `json:"code"` - Name string `json:"name"` - UnitPositions []eipb.Basic `json:"unitPositions,omitempty"` + Installation_Code *string `json:"installation_code"` + Installation *ei.Installation `json:"installation,omitempty"` + Code string `json:"code"` + Name string `json:"name"` + UnitPositions []eipb.Basic `json:"unitPositions,omitempty"` } func (d Unit) ToResponse() ResponseDto { resp := ResponseDto{ - Installation_Id: d.Installation_Id, - Code: d.Code, - Name: d.Name, - UnitPositions: d.UnitPositions, + Installation_Code: d.Installation_Code, + Code: d.Code, + Name: d.Name, + UnitPositions: d.UnitPositions, } resp.SmallMain = d.SmallMain if d.Installation != nil { diff --git a/internal/domain/main-entities/unit/entity.go b/internal/domain/main-entities/unit/entity.go index 254bc163..97db9885 100644 --- a/internal/domain/main-entities/unit/entity.go +++ b/internal/domain/main-entities/unit/entity.go @@ -9,11 +9,10 @@ import ( type Unit struct { ecore.SmallMain // adjust this according to the needs - Installation_Id *uint16 `json:"installation_id"` Installation_Code *string `json:"installation_code" gorm:"size:10"` - Installation *ei.Installation `json:"installation" gorm:"foreignKey:Installation_Id"` + Installation *ei.Installation `json:"installation" gorm:"foreignKey:Installation_Code;references:Code"` Code string `json:"code" gorm:"unique;size:10"` Name string `json:"name" gorm:"size:50"` Type_Code *ero.UnitTypeCode `json:"type_code"` - UnitPositions []eub.Basic `json:"unitPositions,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` + UnitPositions []eub.Basic `json:"unitPositions,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` } diff --git a/internal/interface/main-handler/installation-position/handler.go b/internal/interface/main-handler/installation-position/handler.go index 59f35340..57a439be 100644 --- a/internal/interface/main-handler/installation-position/handler.go +++ b/internal/interface/main-handler/installation-position/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ 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.Code = code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 071e7e24..925f9dc6 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -292,8 +292,14 @@ func SetRoutes() http.Handler { /******************** sources ********************/ hc.RegCrudByCode(r, "/v1/division", division.O) hc.RegCrudByCode(r, "/v1/division-position", divisionposition.O) - hc.RegCrud(r, "/v1/installation", installation.O) - hc.RegCrud(r, "/v1/unit", unit.O) + hc.RegCrudByCode(r, "/v1/installation", installation.O) + hc.RegCrudByCode(r, "/v1/unit", unit.O) + hc.RegCrudByCode(r, "/v1/installation-position", installationposition.O) + hc.RegCrudByCode(r, "/v1/unit-position", unitposition.O) + hc.RegCrudByCode(r, "/v1/specialist", specialist.O) + hc.RegCrudByCode(r, "/v1/subspecialist", subspecialist.O) + hc.RegCrudByCode(r, "/v1/specialist-position", specialistposition.O) + hc.RegCrudByCode(r, "/v1/subspecialist-position", subspecialistposition.O) hc.RegCrud(r, "/v1/pharmacy-company", pharmacycompany.O) hc.RegCrud(r, "/v1/diagnose-src", diagnosesrc.O) hc.RegCrud(r, "/v1/procedure-src", proceduresrc.O) @@ -318,12 +324,6 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/vehicle", vehicle.O) hc.RegCrud(r, "/v1/vehicle-hist", vehiclehist.O) hc.RegCrud(r, "/v1/edu-assessment", eduassesment.O) - hc.RegCrud(r, "/v1/installation-position", installationposition.O) - hc.RegCrud(r, "/v1/unit-position", unitposition.O) - hc.RegCrudByCode(r, "/v1/specialist", specialist.O) - hc.RegCrudByCode(r, "/v1/subspecialist", subspecialist.O) - hc.RegCrudByCode(r, "/v1/specialist-position", specialistposition.O) - hc.RegCrudByCode(r, "/v1/subspecialist-position", subspecialistposition.O) hc.RegCrud(r, "/v1/village", village.O) hc.RegCrud(r, "/v1/district", district.O) diff --git a/internal/interface/main-handler/unit-position/handler.go b/internal/interface/main-handler/unit-position/handler.go index 82b89465..7780e80d 100644 --- a/internal/interface/main-handler/unit-position/handler.go +++ b/internal/interface/main-handler/unit-position/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ 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.Code = code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/unit/handler.go b/internal/interface/main-handler/unit/handler.go index a94ce74e..f31667a2 100644 --- a/internal/interface/main-handler/unit/handler.go +++ b/internal/interface/main-handler/unit/handler.go @@ -33,21 +33,21 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} sf.UrlQueryParam(&dto, *r.URL) - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -55,19 +55,19 @@ 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.Code = code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/use-case/main-use-case/installation-position/case.go b/internal/use-case/main-use-case/installation-position/case.go index f9458c0b..73e64630 100644 --- a/internal/use-case/main-use-case/installation-position/case.go +++ b/internal/use-case/main-use-case/installation-position/case.go @@ -175,7 +175,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: &input.Code} var data *e.InstallationPosition var err error @@ -235,7 +235,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.InstallationPosition var err error @@ -290,7 +290,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { func validateForeignKey(input e.CreateDto) error { // validate installation_id - if _, err := ui.ReadDetail(ei.ReadDetailDto{Id: *input.Installation_Id}); err != nil { + if _, err := ui.ReadDetail(ei.ReadDetailDto{Code: input.Installation_Code}); err != nil { return err } diff --git a/internal/use-case/main-use-case/installation-position/helper.go b/internal/use-case/main-use-case/installation-position/helper.go index 640993c8..2d36d402 100644 --- a/internal/use-case/main-use-case/installation-position/helper.go +++ b/internal/use-case/main-use-case/installation-position/helper.go @@ -17,7 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.InstallationPositio inputSrc = &inputTemp.CreateDto } - data.Installation_Id = inputSrc.Installation_Id + data.Installation_Code = inputSrc.Installation_Code data.Code = inputSrc.Code data.Name = inputSrc.Name data.HeadStatus = inputSrc.HeadStatus diff --git a/internal/use-case/main-use-case/installation-position/lib.go b/internal/use-case/main-use-case/installation-position/lib.go index bb33356f..d0cf72b3 100644 --- a/internal/use-case/main-use-case/installation-position/lib.go +++ b/internal/use-case/main-use-case/installation-position/lib.go @@ -83,10 +83,10 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e } switch { - case input.Id != 0: + case input.Id != nil: getData = tx.First(&data, input.Id) case input.Code != nil && *input.Code != "": - getData = tx.Where("code = ?", *input.Code).First(&data) + getData = tx.Where("\"Code\" = ?", *input.Code).First(&data) default: event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ diff --git a/internal/use-case/main-use-case/unit-position/case.go b/internal/use-case/main-use-case/unit-position/case.go index f3bd2840..47ea67cd 100644 --- a/internal/use-case/main-use-case/unit-position/case.go +++ b/internal/use-case/main-use-case/unit-position/case.go @@ -175,7 +175,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: &input.Code} var data *e.UnitPosition var err error @@ -235,7 +235,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.UnitPosition var err error @@ -290,7 +290,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { func validateForeignKey(input e.CreateDto) error { // validate installation_id - if _, err := uu.ReadDetail(eu.ReadDetailDto{Id: *input.Unit_Id}); err != nil { + if _, err := uu.ReadDetail(eu.ReadDetailDto{Code: &input.Code}); err != nil { return err } diff --git a/internal/use-case/main-use-case/unit-position/helper.go b/internal/use-case/main-use-case/unit-position/helper.go index c1db758d..827dfcc3 100644 --- a/internal/use-case/main-use-case/unit-position/helper.go +++ b/internal/use-case/main-use-case/unit-position/helper.go @@ -17,7 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.UnitPosition) { inputSrc = &inputTemp.CreateDto } - data.Unit_Id = inputSrc.Unit_Id + data.Unit_Code = inputSrc.Unit_Code data.Code = inputSrc.Code data.Name = inputSrc.Name data.HeadStatus = inputSrc.HeadStatus diff --git a/internal/use-case/main-use-case/unit-position/lib.go b/internal/use-case/main-use-case/unit-position/lib.go index c58edd4e..d6f42936 100644 --- a/internal/use-case/main-use-case/unit-position/lib.go +++ b/internal/use-case/main-use-case/unit-position/lib.go @@ -83,7 +83,7 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e } switch { - case input.Id != 0: + case input.Id != nil: getData = tx.First(&data, input.Id) case input.Code != nil && *input.Code != "": getData = tx.Where("code = ?", *input.Code).First(&data) diff --git a/internal/use-case/main-use-case/unit/case.go b/internal/use-case/main-use-case/unit/case.go index e11dbd21..650c4511 100644 --- a/internal/use-case/main-use-case/unit/case.go +++ b/internal/use-case/main-use-case/unit/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: &input.Code} var data *e.Unit var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Unit var err error diff --git a/internal/use-case/main-use-case/unit/helper.go b/internal/use-case/main-use-case/unit/helper.go index f7729ec9..8ee7f7e6 100644 --- a/internal/use-case/main-use-case/unit/helper.go +++ b/internal/use-case/main-use-case/unit/helper.go @@ -17,7 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Unit) { inputSrc = &inputTemp.CreateDto } - data.Installation_Id = inputSrc.Installation_Id + data.Installation_Code = inputSrc.Installation_Code data.Code = inputSrc.Code data.Name = inputSrc.Name } diff --git a/internal/use-case/main-use-case/unit/lib.go b/internal/use-case/main-use-case/unit/lib.go index 1a3e5652..3ec4a10c 100644 --- a/internal/use-case/main-use-case/unit/lib.go +++ b/internal/use-case/main-use-case/unit/lib.go @@ -81,9 +81,16 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e tx = dg.I } + if input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + if err := tx. Scopes(gh.Preload(input.Includes)). - First(&data, input.Id).Error; err != nil { + First(&data).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { return nil, processedErr } From b83e8971dccbe5cd440322a086a4bb762f014405 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 16:00:48 +0700 Subject: [PATCH 093/329] missing sql file for unit, installation --- cmd/main-migration/migrations/20251106090021.sql | 6 ++++++ cmd/main-migration/migrations/atlas.sum | 3 ++- internal/domain/main-entities/unit-position/entity.go | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 cmd/main-migration/migrations/20251106090021.sql diff --git a/cmd/main-migration/migrations/20251106090021.sql b/cmd/main-migration/migrations/20251106090021.sql new file mode 100644 index 00000000..c75c26e2 --- /dev/null +++ b/cmd/main-migration/migrations/20251106090021.sql @@ -0,0 +1,6 @@ +-- Modify "InstallationPosition" table +ALTER TABLE "public"."InstallationPosition" DROP CONSTRAINT "fk_InstallationPosition_Installation", DROP COLUMN "Installation_Id", ADD CONSTRAINT "fk_InstallationPosition_Installation" FOREIGN KEY ("Installation_Code") REFERENCES "public"."Installation" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "Unit" table +ALTER TABLE "public"."Unit" DROP CONSTRAINT "fk_Unit_Installation", DROP COLUMN "Installation_Id", ADD CONSTRAINT "fk_Unit_Installation" FOREIGN KEY ("Installation_Code") REFERENCES "public"."Installation" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "UnitPosition" table +ALTER TABLE "public"."UnitPosition" DROP CONSTRAINT "fk_UnitPosition_Unit", DROP COLUMN "Unit_Id", ADD CONSTRAINT "fk_UnitPosition_Unit" FOREIGN KEY ("Unit_Code") REFERENCES "public"."Unit" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 8833af3a..dc9df4a2 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:w/qs7zN2FLnTjsmLVrFnMQWMxp3LYDJa0RLY74HVK0g= +h1:Jut0rnI38bZU7g1hei5bIcYGzWrt4KxfWzasGJcbwi0= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -82,3 +82,4 @@ h1:w/qs7zN2FLnTjsmLVrFnMQWMxp3LYDJa0RLY74HVK0g= 20251106074218.sql h1:8Xz7WywrtUnSxOHhlal53gG9rE7r86LFUt5zBFe/mIs= 20251106081846.sql h1:jp91Bf5bxGXMiUB1VIuN6y768vb2iWwow44WfCE5J5k= 20251106082844.sql h1:RHYzRO4G1fSWwf+xc/3QezZ/Iil67cZPIgNpNz3TNhQ= +20251106090021.sql h1:dFDk6mq+zjbYWmfWIrHf9DiKvvoXHjrr0++zssMTWP8= diff --git a/internal/domain/main-entities/unit-position/entity.go b/internal/domain/main-entities/unit-position/entity.go index 9966cd4a..a7598049 100644 --- a/internal/domain/main-entities/unit-position/entity.go +++ b/internal/domain/main-entities/unit-position/entity.go @@ -7,5 +7,5 @@ import ( type UnitPosition struct { eub.Basic - Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` + Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` } From 883249ab8c021dd87a56f2e4fa9dcaa4babd0a35 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 16:09:20 +0700 Subject: [PATCH 094/329] fix (specialist): fix read detail data --- internal/use-case/main-use-case/specialist/lib.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/internal/use-case/main-use-case/specialist/lib.go b/internal/use-case/main-use-case/specialist/lib.go index 3e35d004..069f5fbb 100644 --- a/internal/use-case/main-use-case/specialist/lib.go +++ b/internal/use-case/main-use-case/specialist/lib.go @@ -81,9 +81,16 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e tx = dg.I } + if input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + if err := tx. Scopes(gh.Preload(input.Includes)). - First(&data, input.Id).Error; err != nil { + First(&data).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { return nil, processedErr } From 590e91726a74d8b35d21b3e3cf5f373b2a210b1f Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 16:23:52 +0700 Subject: [PATCH 095/329] add detail on soapi coonstlist --- .../domain/references/clinical/clinical.go | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/internal/domain/references/clinical/clinical.go b/internal/domain/references/clinical/clinical.go index 01d0461c..c5d949e2 100644 --- a/internal/domain/references/clinical/clinical.go +++ b/internal/domain/references/clinical/clinical.go @@ -25,6 +25,7 @@ type ( ) const ( + SCDetail SubjectCode = "detail" // Detail SCPrimaryComplain SubjectCode = "pri-complain" // Keluhan Utama SCSecComplain SubjectCode = "sec-complain" // Secondary Complaint SCCurrentDiseaseHistory SubjectCode = "cur-disea-hist" // Current Disease History @@ -35,6 +36,7 @@ const ( SCMedicationHistory SubjectCode = "med-hist" // Medication History SCBloodType SubjectCode = "blood-type" // Blood Type + Detail ObjectCode = "detail" // Detail OCConsciousnessLevel ObjectCode = "consc-level" // Tingkat Kesadaran OCConsciousnessLevelDet ObjectCode = "consc-level-det" // Detail Tingkat Kesadaran OCSystolicBloodPressure ObjectCode = "syst-bp" // Tekanan Darah Systolic @@ -64,6 +66,7 @@ const ( OCHeight ObjectCode = "height" // Tinggi Badan OCHeadToToe ObjectCode = "head-to-toe" // Kepala Sampai Kaki + ACDetail AssessmentCode = "detail" // Detail ACEarlyDiag AssessmentCode = "early-diag" // Diagnosis Awal ACLateDiag AssessmentCode = "late-diag" // Diagnosis Akhir ACSecDiag AssessmentCode = "sec-diag" // Diagnosis Sekunder @@ -194,7 +197,7 @@ type Soapi struct { // ---------------- SUBJECT ---------------- type SubjectSection struct { - Note string `json:"note,omitempty"` + Detail string `json:"detail,omitempty"` PrimComplain string `json:"prim-compl,omitempty"` SecComplainQ string `json:"sec-compl,omitempty"` PrimaryComplain string `json:"pri-complain,omitempty"` @@ -210,7 +213,7 @@ type SubjectSection struct { // ---------------- OBJECT ---------------- type ObjectSection struct { - Note string `json:"note,omitempty"` + Detail string `json:"detail,omitempty"` ConsciousnessLevel string `json:"consc-level,omitempty"` ConsciousnessLevelDet string `json:"consc-level-det,omitempty"` SystolicBloodPressure string `json:"syst-bp,omitempty"` @@ -243,9 +246,16 @@ type ObjectSection struct { // ---------------- ASSESSMENT ---------------- type AssessmentSection struct { - EarlyDiagnosis DiagnosisDetail `json:"early-diag,omitempty"` - LateDiagnosis DiagnosisDetail `json:"late-diag,omitempty"` - SecondaryDiag DiagnosisDetail `json:"sec-diag,omitempty"` + Detail string `json:"detail,omitempty"` + EarlyDiagnosis DiagnosisDetail `json:"early-diag,omitempty"` + LateDiagnosis DiagnosisDetail `json:"late-diag,omitempty"` + SecondaryDiag DiagnosisDetail `json:"sec-diag,omitempty"` + EarlyDiagnosisMed DiagnosisDetail `json:"early-med-diag,omitempty"` + LateDiagnosisMed DiagnosisDetail `json:"late-med-diag,omitempty"` + SecondaryDiagnosisMed DiagnosisDetail `json:"sec-med-diag,omitempty"` + EarlyDiagnosisFunc DiagnosisDetail `json:"early-func-diag,omitempty"` + LateDiagnosisFunc DiagnosisDetail `json:"late-func-diag,omitempty"` + SecondaryDiagnosisFunc DiagnosisDetail `json:"sec-func-diag,omitempty"` } // nested object {note, codes} From a73d7745e3ef90cc412fd361e4f7c0e1c2dcd6b3 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Thu, 6 Nov 2025 16:02:44 +0700 Subject: [PATCH 096/329] feat/sso-auth: added models --- .../domain/main-entities/auth-partner/dto.go | 67 +++++++++++++++++ .../main-entities/auth-partner/entity.go | 12 ++++ internal/domain/main-entities/ext-user/dto.go | 71 +++++++++++++++++++ .../domain/main-entities/ext-user/entity.go | 16 +++++ 4 files changed, 166 insertions(+) create mode 100644 internal/domain/main-entities/auth-partner/dto.go create mode 100644 internal/domain/main-entities/auth-partner/entity.go create mode 100644 internal/domain/main-entities/ext-user/dto.go create mode 100644 internal/domain/main-entities/ext-user/entity.go diff --git a/internal/domain/main-entities/auth-partner/dto.go b/internal/domain/main-entities/auth-partner/dto.go new file mode 100644 index 00000000..651ca4b7 --- /dev/null +++ b/internal/domain/main-entities/auth-partner/dto.go @@ -0,0 +1,67 @@ +package authpartner + +import ( + // internal - domain - main-entities + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type CreateDto struct { + Code string `json:"code"` + Name string `json:"name"` + SecretKey string `json:"secretKey"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Code *string `json:"code"` + Name *string `json:"name"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` +} + +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 + Code string `json:"code"` + Name string `json:"name"` + SecretKey string `json:"secretKey"` +} + +func (d AuthPartner) ToResponse() ResponseDto { + resp := ResponseDto{ + Code: d.Code, + Name: d.Name, + SecretKey: d.SecretKey, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []AuthPartner) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/auth-partner/entity.go b/internal/domain/main-entities/auth-partner/entity.go new file mode 100644 index 00000000..3a8cf4e6 --- /dev/null +++ b/internal/domain/main-entities/auth-partner/entity.go @@ -0,0 +1,12 @@ +package authpartner + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type AuthPartner struct { + ecore.Main // adjust this according to the needs + Code string `json:"code" gorm:"size:50"` + Name string `json:"name" gorm:"size:100"` + SecretKey string `json:"secretKey" gorm:"size:255"` +} diff --git a/internal/domain/main-entities/ext-user/dto.go b/internal/domain/main-entities/ext-user/dto.go new file mode 100644 index 00000000..4b434c55 --- /dev/null +++ b/internal/domain/main-entities/ext-user/dto.go @@ -0,0 +1,71 @@ +package extuser + +import ( + // internal - domain - main-entities + ecore "simrs-vx/internal/domain/base-entities/core" + eap "simrs-vx/internal/domain/main-entities/auth-partner" +) + +type CreateDto struct { + Name string `json:"name"` + AuthPartner_Code string `json:"authPartner_code"` + User_Name string `json:"user_name"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Name *string `json:"name"` + AuthPartner_Code *string `json:"authPartner_code"` + User_Name *string `json:"user_name"` +} + +type ReadDetailDto struct { + Id uint `json:"id"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + Name string `json:"name"` + AuthPartner_Code string `json:"authPartner_code"` + AuthPartner *eap.AuthPartner `json:"authPartner,omitempty"` + User_Name string `json:"user_name"` +} + +func (d ExtUser) ToResponse() ResponseDto { + resp := ResponseDto{ + Name: d.Name, + AuthPartner_Code: d.AuthPartner_Code, + AuthPartner: d.AuthPartner, + User_Name: d.User_Name, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []ExtUser) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} \ No newline at end of file diff --git a/internal/domain/main-entities/ext-user/entity.go b/internal/domain/main-entities/ext-user/entity.go new file mode 100644 index 00000000..ae293667 --- /dev/null +++ b/internal/domain/main-entities/ext-user/entity.go @@ -0,0 +1,16 @@ +package extuser + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + eap "simrs-vx/internal/domain/main-entities/auth-partner" + eau "simrs-vx/internal/domain/main-entities/user" +) + +type ExtUser struct { + ecore.Main // adjust this according to the needs + Name string `json:"name" gorm:"size:100"` + AuthPartner_Code string `json:"authPartner_code" gorm:"size:30"` + AuthPartner *eap.AuthPartner `json:"authPartner,omitempty" gorm:"foreignKey:AuthPartner_Code;references:Code"` + User_Name string `json:"user_name" gorm:"size:50"` + User *eau.User `json:"user,omitempty" gorm:"foreignKey:User_Name;references:Name"` +} From 6a2a8cc63c3f1551db619a65fad659c28a9c3a49 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Thu, 6 Nov 2025 18:13:26 +0700 Subject: [PATCH 097/329] dev: hotfix, cleaning + shortent code for auth --- .../main-use-case/authentication/case.go | 115 ++++++---------- .../main-use-case/authentication/helper.go | 129 +++++++++--------- 2 files changed, 103 insertions(+), 141 deletions(-) diff --git a/internal/use-case/main-use-case/authentication/case.go b/internal/use-case/main-use-case/authentication/case.go index 6a980d71..6cf94142 100644 --- a/internal/use-case/main-use-case/authentication/case.go +++ b/internal/use-case/main-use-case/authentication/case.go @@ -9,28 +9,28 @@ import ( "github.com/golang-jwt/jwt" "github.com/google/uuid" - - "simrs-vx/internal/domain/main-entities/intern" - eu "simrs-vx/internal/domain/main-entities/user" - - pa "simrs-vx/internal/lib/auth" - el "simrs-vx/pkg/logger" - p "simrs-vx/pkg/password" - - ed "simrs-vx/internal/domain/main-entities/doctor" - ee "simrs-vx/internal/domain/main-entities/employee" - em "simrs-vx/internal/domain/main-entities/midwife" - en "simrs-vx/internal/domain/main-entities/nurse" - erc "simrs-vx/internal/domain/references/common" - erg "simrs-vx/internal/domain/references/organization" - a "github.com/karincake/apem" dg "github.com/karincake/apem/db-gorm-pg" ms "github.com/karincake/apem/ms-redis" d "github.com/karincake/dodol" l "github.com/karincake/lepet" + + pa "simrs-vx/internal/lib/auth" + pl "simrs-vx/pkg/logger" + p "simrs-vx/pkg/password" + + ed "simrs-vx/internal/domain/main-entities/doctor" + ee "simrs-vx/internal/domain/main-entities/employee" + "simrs-vx/internal/domain/main-entities/intern" + em "simrs-vx/internal/domain/main-entities/midwife" + en "simrs-vx/internal/domain/main-entities/nurse" + eu "simrs-vx/internal/domain/main-entities/user" + erc "simrs-vx/internal/domain/references/common" + erg "simrs-vx/internal/domain/references/organization" ) +const source = "authentication" + var authCfg AuthCfg func init() { @@ -40,13 +40,18 @@ func init() { // Generates token and store in redis at one place // just return the error code func GenToken(input eu.LoginDto) (*d.Data, error) { + event := pl.Event{ + Feature: "Create", + Source: source, + } + // Get User user := &eu.User{Name: input.Name} // if input.Position_Code != "" { // user.Position_Code = input.Position_Code // } if errCode := getAndCheck(user, user); errCode != "" { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: errCode, Message: el.GenMessage(errCode)}} + return nil, d.FieldErrors{"authentication": d.FieldError{Code: errCode, Message: pl.GenMessage(errCode)}} } if user.LoginAttemptCount > 5 { @@ -54,7 +59,7 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { now := time.Now() lastAllowdLogin := user.LastAllowdLogin if lastAllowdLogin.After(now.Add(-time.Hour * 1)) { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-login-tooMany", Message: el.GenMessage("auth-login-tooMany")}} + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-login-tooMany", Message: pl.GenMessage("auth-login-tooMany")}} } else { tn := time.Now() user.LastAllowdLogin = &tn @@ -65,18 +70,18 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { tn := time.Now() user.LastAllowdLogin = &tn dg.I.Save(&user) - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-login-tooMany", Message: el.GenMessage("auth-login-tooMany")}} + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-login-tooMany", Message: pl.GenMessage("auth-login-tooMany")}} } } if !p.Check(input.Password, user.Password) { user.LoginAttemptCount++ dg.I.Save(&user) - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-login-incorrect", Message: el.GenMessage("auth-login-incorrect")}} + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-login-incorrect", Message: pl.GenMessage("auth-login-incorrect")}} } else if user.Status_Code == erc.USCBlocked { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-login-blocked", Message: el.GenMessage("auth-login-blocked")}} + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-login-blocked", Message: pl.GenMessage("auth-login-blocked")}} } else if user.Status_Code == erc.USCNew { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-login-unverified", Message: el.GenMessage("auth-login-unverified")}} + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-login-unverified", Message: pl.GenMessage("auth-login-unverified")}} } // Access token prep @@ -115,7 +120,7 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { employee := ee.Employee{} dg.I.Where("\"User_Id\" = ?", user.Id).First(&employee) if employee.Id == 0 { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noEmployee", Message: el.GenMessage("auth-noEmployee")}} + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noEmployee", Message: pl.GenMessage("auth-noEmployee")}} } atClaims["employee_id"] = employee.Id outputData["employee_id"] = employee.Id @@ -134,7 +139,7 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { doctor := ed.Doctor{} dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&doctor) if doctor.Id == 0 { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noDoctor", Message: el.GenMessage("auth-noDoctor")}} + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noDoctor", Message: pl.GenMessage("auth-noDoctor")}} } atClaims["doctor_code"] = doctor.Code outputData["doctor_code"] = doctor.Code @@ -152,7 +157,7 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { empData := en.Nurse{} dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) if empData.Id == 0 { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: el.GenMessage("auth-noNurse")}} + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: pl.GenMessage("auth-noNurse")}} } atClaims["nurse_code"] = empData.Code outputData["nurse_code"] = empData.Code @@ -160,40 +165,40 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { empData := em.Midwife{} dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) if empData.Id == 0 { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noMidwife", Message: el.GenMessage("auth-noMidwife")}} + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noMidwife", Message: pl.GenMessage("auth-noMidwife")}} } atClaims["midwife_code"] = empData.Code outputData["midwife_code"] = empData.Code } - errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: el.GenMessage("auth-getData-failed")}} + errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: pl.GenMessage("auth-getData-failed")}} // division position - divisionPositions, err := getDivisionPosition(employee.Id) + divisionPositions, err := getDivisionPosition(employee.Id, &event) if err != nil { return nil, errorGetPosition } // installation position - installationPositions, err := getInstallationPosition(employee.Id) + installationPositions, err := getInstallationPosition(employee.Id, &event) if err != nil { return nil, errorGetPosition } // unit position - unitPositions, err := getUnitPosition(employee.Id) + unitPositions, err := getUnitPosition(employee.Id, &event) if err != nil { return nil, errorGetPosition } // specialist position - specialistPositions, err := getSpecialistPosition(employee.Id) + specialistPositions, err := getSpecialistPosition(employee.Id, &event) if err != nil { return nil, errorGetPosition } // subspecialist position - subspecialistPositions, err := getSubspecialistPosition(employee.Id) + subspecialistPositions, err := getSubspecialistPosition(employee.Id, &event) if err != nil { return nil, errorGetPosition } @@ -220,7 +225,7 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims) ats, err := at.SignedString([]byte(atSecretKey)) if err != nil { - return nil, d.FieldErrors{"user": d.FieldError{Code: "token-sign-err", Message: el.GenMessage("token-sign-err")}} + return nil, d.FieldErrors{"user": d.FieldError{Code: "token-sign-err", Message: pl.GenMessage("token-sign-err")}} } outputData["accessToken"] = ats @@ -283,21 +288,21 @@ func VerifyToken(r *http.Request, tokenType TokenType) (data *jwt.Token, errCode func ExtractToken(r *http.Request, tokenType TokenType) (data *pa.AuthInfo, err error) { token, errCode, errDetail := VerifyToken(r, tokenType) if errCode != "" { - return nil, d.FieldError{Code: errCode, Message: el.GenMessage(errCode, errDetail)} + return nil, d.FieldError{Code: errCode, Message: pl.GenMessage(errCode, errDetail)} } claims, ok := token.Claims.(jwt.MapClaims) if ok && token.Valid { accessUuid, ok := claims["uuid"].(string) if !ok { - return nil, d.FieldError{Code: "token-invalid", Message: el.GenMessage("token-invalid", "uuid not available")} + return nil, d.FieldError{Code: "token-invalid", Message: pl.GenMessage("token-invalid", "uuid not available")} } user_id, myErr := strconv.ParseInt(fmt.Sprintf("%.f", claims["user_id"]), 10, 64) if myErr != nil { - return nil, d.FieldError{Code: "token-invalid", Message: el.GenMessage("token-invalid", "uuid is not available")} + return nil, d.FieldError{Code: "token-invalid", Message: pl.GenMessage("token-invalid", "uuid is not available")} } accessUuidRedis := ms.I.Get(accessUuid) if accessUuidRedis.String() == "" { - return nil, d.FieldError{Code: "token-unidentified", Message: el.GenMessage("token-unidentified")} + return nil, d.FieldError{Code: "token-unidentified", Message: pl.GenMessage("token-unidentified")} } data = &pa.AuthInfo{ @@ -324,41 +329,3 @@ func ExtractToken(r *http.Request, tokenType TokenType) (data *pa.AuthInfo, err func GetConfig() { a.ParseCfg(&authCfg) } - -func checkStrClaims(claim map[string]interface{}, key string) string { - if v, exist := claim[key]; exist && v != nil { - return v.(string) - } - return "" -} - -func checkStrPtrClaims(claim map[string]interface{}, key string) *string { - if v, exist := claim[key]; exist && v != nil { - val := v.(string) - return &val - } - return nil -} - -func checkIntClaims(claim map[string]interface{}, key string) int { - if v, exist := claim[key]; exist && v != nil { - return v.(int) - } - return 0 -} - -func checkIntPtrClaims(claim map[string]interface{}, key string) *int { - if v, exist := claim[key]; exist && v != nil { - val := int(v.(float64)) - return &val - } - return nil -} - -func checkUntPtrClaims(claim map[string]interface{}, key string) *uint { - if v, exist := claim[key]; exist && v != nil { - val := uint(v.(float64)) - return &val - } - return nil -} diff --git a/internal/use-case/main-use-case/authentication/helper.go b/internal/use-case/main-use-case/authentication/helper.go index bec64518..a919cfe9 100644 --- a/internal/use-case/main-use-case/authentication/helper.go +++ b/internal/use-case/main-use-case/authentication/helper.go @@ -1,6 +1,10 @@ package authentication import ( + dg "github.com/karincake/apem/db-gorm-pg" + + pl "simrs-vx/pkg/logger" + edp "simrs-vx/internal/domain/main-entities/division-position" eip "simrs-vx/internal/domain/main-entities/installation-position" esp "simrs-vx/internal/domain/main-entities/specialist-position" @@ -12,8 +16,6 @@ import ( usp "simrs-vx/internal/use-case/main-use-case/specialist-position" ussp "simrs-vx/internal/use-case/main-use-case/subspecialist-position" uup "simrs-vx/internal/use-case/main-use-case/unit-position" - - dg "github.com/karincake/apem/db-gorm-pg" ) // just return the error code @@ -28,43 +30,21 @@ func getAndCheck(input, condition any) (eCode string) { return "" } -func getDivisionPosition(employee_id uint) ([]string, error) { +func getDivisionPosition(employee_id uint, event *pl.Event) ([]string, error) { var result []string - // var employee ee.Employee - // if err := dg.I.Where("\"Employee_Id\" = ?", employee_id).First(&employee).Error; err != nil { - // if err == gorm.ErrRecordNotFound { - // return result, nil - // } - // return result, errors.New("no employee found") - // } - - //var divisionPositions []edp.DivisionPosition - //err := dg.I. - // Preload("Division"). - // Where("\"Employee_Id\" = ?", employee_id). - // Find(&divisionPositions).Error - //if err != nil { - // if err == gorm.ErrRecordNotFound { - // return result, nil - // } - // return result, err - //} - // get data division_position based on employee_id - dataDivisionPosition, err := udp.ReadList(edp.ReadListDto{ + data, _, err := udp.ReadListData(edp.ReadListDto{ FilterDto: edp.FilterDto{Employee_Id: &employee_id}, - Includes: "division"}) + Includes: "Division"}, event) if err != nil { return nil, err } - if list, ok := dataDivisionPosition.Data.([]edp.ResponseDto); ok { - if len(list) > 0 { - for _, dp := range list { - if dp.Division != nil { - result = append(result, "div-"+dp.Division.Code+"-"+dp.Code) - } + if len(data) > 0 { + for _, dp := range data { + if dp.Division != nil { + result = append(result, "div-"+dp.Division.Code+"-"+dp.Code) } } } @@ -72,23 +52,21 @@ func getDivisionPosition(employee_id uint) ([]string, error) { return result, nil } -func getInstallationPosition(employeeId uint) ([]string, error) { +func getInstallationPosition(employeeId uint, event *pl.Event) ([]string, error) { var result []string // get data unit_position based on employee_id - dataInstallationPosition, err := uip.ReadList(eip.ReadListDto{ + data, _, err := uip.ReadListData(eip.ReadListDto{ FilterDto: eip.FilterDto{Employee_Id: &employeeId}, - Includes: "installation"}) + Includes: "installation"}, event) if err != nil { return nil, err } - if list, ok := dataInstallationPosition.Data.([]eip.ResponseDto); ok { - if len(list) > 0 { - for _, dp := range list { - if dp.Installation != nil { - result = append(result, "inst-"+dp.Installation.Code+"-"+dp.Code) - } + if len(data) > 0 { + for _, dp := range data { + if dp.Installation != nil { + result = append(result, "inst-"+dp.Installation.Code+"-"+dp.Code) } } } @@ -96,23 +74,21 @@ func getInstallationPosition(employeeId uint) ([]string, error) { return result, nil } -func getUnitPosition(employeeId uint) ([]string, error) { +func getUnitPosition(employeeId uint, event *pl.Event) ([]string, error) { var result []string // get data unit_position based on employee_id - dataUnitPosition, err := uup.ReadList(eup.ReadListDto{ + data, _, err := uup.ReadListData(eup.ReadListDto{ FilterDto: eup.FilterDto{Employee_Id: &employeeId}, - Includes: "unit"}) + Includes: "unit"}, event) if err != nil { return nil, err } - if list, ok := dataUnitPosition.Data.([]eup.ResponseDto); ok { - if len(list) > 0 { - for _, dp := range list { - if dp.Unit != nil { - result = append(result, "unit-"+dp.Unit.Code+"-"+dp.Code) - } + if len(data) > 0 { + for _, dp := range data { + if dp.Unit != nil { + result = append(result, "unit-"+dp.Unit.Code+"-"+dp.Code) } } } @@ -120,23 +96,21 @@ func getUnitPosition(employeeId uint) ([]string, error) { return result, nil } -func getSpecialistPosition(employeeId uint) ([]string, error) { +func getSpecialistPosition(employeeId uint, event *pl.Event) ([]string, error) { var result []string // get data unit_position based on employee_id - dataSpecialistPosition, err := usp.ReadList(esp.ReadListDto{ + data, _, err := usp.ReadListData(esp.ReadListDto{ FilterDto: esp.FilterDto{Employee_Id: &employeeId}, - Includes: "specialist"}) + Includes: "specialist"}, event) if err != nil { return nil, err } - if list, ok := dataSpecialistPosition.Data.([]esp.ResponseDto); ok { - if len(list) > 0 { - for _, dp := range list { - if dp.Specialist != nil { - result = append(result, "spec-"+dp.Specialist.Code+"-"+dp.Code) - } + if len(data) > 0 { + for _, dp := range data { + if dp.Specialist != nil { + result = append(result, "spec-"+dp.Specialist.Code+"-"+dp.Code) } } } @@ -144,26 +118,47 @@ func getSpecialistPosition(employeeId uint) ([]string, error) { return result, nil } -func getSubspecialistPosition(employeeId uint) ([]string, error) { +func getSubspecialistPosition(employeeId uint, event *pl.Event) ([]string, error) { var result []string // get data unit_position based on employee_id - dataSubspecialistPosition, err := ussp.ReadList(essp.ReadListDto{ + data, _, err := ussp.ReadListData(essp.ReadListDto{ FilterDto: essp.FilterDto{Employee_Id: &employeeId}, - Includes: "subspecialist"}) + Includes: "subspecialist"}, event) if err != nil { return nil, err } - if list, ok := dataSubspecialistPosition.Data.([]essp.ResponseDto); ok { - if len(list) > 0 { - for _, dp := range list { - if dp.Subspecialist != nil { - result = append(result, "subspec-"+dp.Subspecialist.Code+"-"+dp.Code) - } + if len(data) > 0 { + for _, dp := range data { + if dp.Subspecialist != nil { + result = append(result, "subspec-"+dp.Subspecialist.Code+"-"+dp.Code) } } } return result, nil } + +func checkStrClaims(claim map[string]interface{}, key string) string { + if v, exist := claim[key]; exist && v != nil { + return v.(string) + } + return "" +} + +func checkStrPtrClaims(claim map[string]interface{}, key string) *string { + if v, exist := claim[key]; exist && v != nil { + val := v.(string) + return &val + } + return nil +} + +func checkUntPtrClaims(claim map[string]interface{}, key string) *uint { + if v, exist := claim[key]; exist && v != nil { + val := uint(v.(float64)) + return &val + } + return nil +} From 355c7053afa5f85098f1ce9edabde3191712fe54 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Thu, 6 Nov 2025 18:23:51 +0700 Subject: [PATCH 098/329] migration: updated sum for whatever the reason is --- cmd/main-migration/migrations/atlas.sum | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index dc9df4a2..d274aba5 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:Jut0rnI38bZU7g1hei5bIcYGzWrt4KxfWzasGJcbwi0= +h1:ZADUaOWJ3ITHhas6LbAgWte6gK6FX1BJEn9Wfoynmnk= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,11 +75,11 @@ h1:Jut0rnI38bZU7g1hei5bIcYGzWrt4KxfWzasGJcbwi0= 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= +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= From ad3501c1daace32cdc70c88694bc953dbb63dce9 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Thu, 6 Nov 2025 21:42:19 +0700 Subject: [PATCH 099/329] feat/sso-auth: improved the entities --- .../domain/main-entities/auth-partner/dto.go | 5 +++- internal/domain/main-entities/ext-user/dto.go | 23 +++++++++++-------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/internal/domain/main-entities/auth-partner/dto.go b/internal/domain/main-entities/auth-partner/dto.go index 651ca4b7..2b1589fb 100644 --- a/internal/domain/main-entities/auth-partner/dto.go +++ b/internal/domain/main-entities/auth-partner/dto.go @@ -15,6 +15,7 @@ type ReadListDto struct { FilterDto Includes string `json:"includes"` Pagination ecore.Pagination + Sort string `json:"sort"` } type FilterDto struct { @@ -23,7 +24,9 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` + Includes string `json:"includes"` } type UpdateDto struct { diff --git a/internal/domain/main-entities/ext-user/dto.go b/internal/domain/main-entities/ext-user/dto.go index 4b434c55..653dab92 100644 --- a/internal/domain/main-entities/ext-user/dto.go +++ b/internal/domain/main-entities/ext-user/dto.go @@ -16,16 +16,19 @@ type ReadListDto struct { FilterDto Includes string `json:"includes"` Pagination ecore.Pagination + Sort string `json:"sort"` } type FilterDto struct { Name *string `json:"name"` AuthPartner_Code *string `json:"authPartner_code"` User_Name *string `json:"user_name"` + Includes string `json:"includes"` } type ReadDetailDto struct { - Id uint `json:"id"` + Id uint `json:"id"` + Includes string `json:"includes"` } type UpdateDto struct { @@ -45,18 +48,18 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Name string `json:"name"` - AuthPartner_Code string `json:"authPartner_code"` - AuthPartner *eap.AuthPartner `json:"authPartner,omitempty"` - User_Name string `json:"user_name"` + Name string `json:"name"` + AuthPartner_Code string `json:"authPartner_code"` + AuthPartner *eap.AuthPartner `json:"authPartner,omitempty"` + User_Name string `json:"user_name"` } func (d ExtUser) ToResponse() ResponseDto { resp := ResponseDto{ - Name: d.Name, - AuthPartner_Code: d.AuthPartner_Code, - AuthPartner: d.AuthPartner, - User_Name: d.User_Name, + Name: d.Name, + AuthPartner_Code: d.AuthPartner_Code, + AuthPartner: d.AuthPartner, + User_Name: d.User_Name, } resp.Main = d.Main return resp @@ -68,4 +71,4 @@ func ToResponseList(data []ExtUser) []ResponseDto { resp[i] = u.ToResponse() } return resp -} \ No newline at end of file +} From d4e58e4f73407ee5b05f18a917382efdb16e2818 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Thu, 6 Nov 2025 21:48:42 +0700 Subject: [PATCH 100/329] feat/sso-auth: added the migration --- .../migrations/20251106144745.sql | 26 +++++++++++++++++++ cmd/main-migration/migrations/atlas.sum | 3 ++- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 cmd/main-migration/migrations/20251106144745.sql diff --git a/cmd/main-migration/migrations/20251106144745.sql b/cmd/main-migration/migrations/20251106144745.sql new file mode 100644 index 00000000..4e10ec66 --- /dev/null +++ b/cmd/main-migration/migrations/20251106144745.sql @@ -0,0 +1,26 @@ +-- Create "AuthPartner" table +CREATE TABLE "public"."AuthPartner" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(50) NULL, + "Name" character varying(100) NULL, + "SecretKey" character varying(255) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_AuthPartner_Code" UNIQUE ("Code"), + CONSTRAINT "uni_AuthPartner_Name" UNIQUE ("Name") +); +-- Create "ExtUser" table +CREATE TABLE "public"."ExtUser" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Name" character varying(100) NULL, + "AuthPartner_Code" character varying(30) NULL, + "User_Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_ExtUser_AuthPartner" FOREIGN KEY ("AuthPartner_Code") REFERENCES "public"."AuthPartner" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_ExtUser_User" FOREIGN KEY ("User_Name") REFERENCES "public"."User" ("Name") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index d274aba5..e1e6989d 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:ZADUaOWJ3ITHhas6LbAgWte6gK6FX1BJEn9Wfoynmnk= +h1:Zokt/6mjNJdmX2YBvxbhlp1P6FPkkfjVhx2W7FY10Bk= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -83,3 +83,4 @@ h1:ZADUaOWJ3ITHhas6LbAgWte6gK6FX1BJEn9Wfoynmnk= 20251106081846.sql h1:P+VsWwhGt60adDIZuE/Aa38JVp/yX1rnsdpXpxASodw= 20251106082844.sql h1:Dmi5A8i9frQZvdXYPwc7f8CisZtBH8liSXq1rI6z1iM= 20251106090021.sql h1:4JwdKgO8T46YhyWVJUxpRIwudBDlG8QN1brSOYmgQ20= +20251106144745.sql h1:yuma9OS/QMlH+mIjClgx7DBg//zbPnljeVFP9AladjI= From afde2f7cf4b73436947204e2aa4fac775b5bed5f Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Thu, 6 Nov 2025 21:48:42 +0700 Subject: [PATCH 101/329] feat/sso-auth: added the migration --- .../migrations/20251106144745.sql | 26 +++++++++++++++++++ cmd/main-migration/migrations/atlas.sum | 3 ++- internal/interface/migration/main-entities.go | 4 +++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 cmd/main-migration/migrations/20251106144745.sql diff --git a/cmd/main-migration/migrations/20251106144745.sql b/cmd/main-migration/migrations/20251106144745.sql new file mode 100644 index 00000000..4e10ec66 --- /dev/null +++ b/cmd/main-migration/migrations/20251106144745.sql @@ -0,0 +1,26 @@ +-- Create "AuthPartner" table +CREATE TABLE "public"."AuthPartner" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(50) NULL, + "Name" character varying(100) NULL, + "SecretKey" character varying(255) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_AuthPartner_Code" UNIQUE ("Code"), + CONSTRAINT "uni_AuthPartner_Name" UNIQUE ("Name") +); +-- Create "ExtUser" table +CREATE TABLE "public"."ExtUser" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Name" character varying(100) NULL, + "AuthPartner_Code" character varying(30) NULL, + "User_Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_ExtUser_AuthPartner" FOREIGN KEY ("AuthPartner_Code") REFERENCES "public"."AuthPartner" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_ExtUser_User" FOREIGN KEY ("User_Name") REFERENCES "public"."User" ("Name") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index d274aba5..e1e6989d 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:ZADUaOWJ3ITHhas6LbAgWte6gK6FX1BJEn9Wfoynmnk= +h1:Zokt/6mjNJdmX2YBvxbhlp1P6FPkkfjVhx2W7FY10Bk= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -83,3 +83,4 @@ h1:ZADUaOWJ3ITHhas6LbAgWte6gK6FX1BJEn9Wfoynmnk= 20251106081846.sql h1:P+VsWwhGt60adDIZuE/Aa38JVp/yX1rnsdpXpxASodw= 20251106082844.sql h1:Dmi5A8i9frQZvdXYPwc7f8CisZtBH8liSXq1rI6z1iM= 20251106090021.sql h1:4JwdKgO8T46YhyWVJUxpRIwudBDlG8QN1brSOYmgQ20= +20251106144745.sql h1:yuma9OS/QMlH+mIjClgx7DBg//zbPnljeVFP9AladjI= diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index af9fe034..9c5486d1 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -8,6 +8,7 @@ import ( antibioticinuse "simrs-vx/internal/domain/main-entities/antibiotic-in-use" antibioticsrccategory "simrs-vx/internal/domain/main-entities/antibiotic-src-category" 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" chemoprotocol "simrs-vx/internal/domain/main-entities/chemo-protocol" consultation "simrs-vx/internal/domain/main-entities/consultation" @@ -28,6 +29,7 @@ import ( employee "simrs-vx/internal/domain/main-entities/employee" encounter "simrs-vx/internal/domain/main-entities/encounter" ethnic "simrs-vx/internal/domain/main-entities/ethnic" + extuser "simrs-vx/internal/domain/main-entities/ext-user" generalconsent "simrs-vx/internal/domain/main-entities/general-consent" infra "simrs-vx/internal/domain/main-entities/infra" inpatient "simrs-vx/internal/domain/main-entities/inpatient" @@ -105,7 +107,9 @@ import ( func getMainEntities() []any { return []any{ + &authpartner.AuthPartner{}, &user.User{}, + &extuser.ExtUser{}, &division.Division{}, &divisionposition.DivisionPosition{}, &installation.Installation{}, From 72e0a1ce24b6cdcbbf2fa3685766579363b5f644 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Fri, 7 Nov 2025 08:19:21 +0700 Subject: [PATCH 102/329] feat/sso-auth: moved ext-user to user-fes --- .../domain/main-entities/{ext-user => user-fes}/dto.go | 7 ++++--- .../domain/main-entities/{ext-user => user-fes}/entity.go | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) rename internal/domain/main-entities/{ext-user => user-fes}/dto.go (91%) rename internal/domain/main-entities/{ext-user => user-fes}/entity.go (90%) diff --git a/internal/domain/main-entities/ext-user/dto.go b/internal/domain/main-entities/user-fes/dto.go similarity index 91% rename from internal/domain/main-entities/ext-user/dto.go rename to internal/domain/main-entities/user-fes/dto.go index 653dab92..6cb3636b 100644 --- a/internal/domain/main-entities/ext-user/dto.go +++ b/internal/domain/main-entities/user-fes/dto.go @@ -1,4 +1,5 @@ -package extuser +// FES = From External Source +package userfes import ( // internal - domain - main-entities @@ -54,7 +55,7 @@ type ResponseDto struct { User_Name string `json:"user_name"` } -func (d ExtUser) ToResponse() ResponseDto { +func (d UserFes) ToResponse() ResponseDto { resp := ResponseDto{ Name: d.Name, AuthPartner_Code: d.AuthPartner_Code, @@ -65,7 +66,7 @@ func (d ExtUser) ToResponse() ResponseDto { return resp } -func ToResponseList(data []ExtUser) []ResponseDto { +func ToResponseList(data []UserFes) []ResponseDto { resp := make([]ResponseDto, len(data)) for i, u := range data { resp[i] = u.ToResponse() diff --git a/internal/domain/main-entities/ext-user/entity.go b/internal/domain/main-entities/user-fes/entity.go similarity index 90% rename from internal/domain/main-entities/ext-user/entity.go rename to internal/domain/main-entities/user-fes/entity.go index ae293667..7356166c 100644 --- a/internal/domain/main-entities/ext-user/entity.go +++ b/internal/domain/main-entities/user-fes/entity.go @@ -1,4 +1,5 @@ -package extuser +// FES = From External Source +package userfes import ( ecore "simrs-vx/internal/domain/base-entities/core" @@ -6,7 +7,7 @@ import ( eau "simrs-vx/internal/domain/main-entities/user" ) -type ExtUser struct { +type UserFes struct { ecore.Main // adjust this according to the needs Name string `json:"name" gorm:"size:100"` AuthPartner_Code string `json:"authPartner_code" gorm:"size:30"` From bfbbb38220676b023923da7ecd1a5023120bf126 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Fri, 7 Nov 2025 13:52:30 +0700 Subject: [PATCH 103/329] room ids into codes --- .../migrations/20251107064812.sql | 2 ++ .../migrations/20251107064937.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 6 ++++-- .../domain/main-entities/room/base/entity.go | 20 +++++++++++-------- .../interface/main-handler/main-handler.go | 4 ++++ 5 files changed, 24 insertions(+), 10 deletions(-) create mode 100644 cmd/main-migration/migrations/20251107064812.sql create mode 100644 cmd/main-migration/migrations/20251107064937.sql diff --git a/cmd/main-migration/migrations/20251107064812.sql b/cmd/main-migration/migrations/20251107064812.sql new file mode 100644 index 00000000..2e5c78cf --- /dev/null +++ b/cmd/main-migration/migrations/20251107064812.sql @@ -0,0 +1,2 @@ +-- Modify "Room" table +ALTER TABLE "public"."Room" ADD COLUMN "Infra_Coode" character varying(10) NULL, ADD COLUMN "Unit_Code" character varying(10) NULL, ADD COLUMN "Specialist_Code" character varying(10) NULL, ADD COLUMN "Subspecialist_Code" character varying(10) NULL; diff --git a/cmd/main-migration/migrations/20251107064937.sql b/cmd/main-migration/migrations/20251107064937.sql new file mode 100644 index 00000000..d1111390 --- /dev/null +++ b/cmd/main-migration/migrations/20251107064937.sql @@ -0,0 +1,2 @@ +-- Rename a column from "Infra_Coode" to "Infra_Code" +ALTER TABLE "public"."Room" RENAME COLUMN "Infra_Coode" TO "Infra_Code"; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index fbab0579..83124cd0 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:3ftGXqIy9GWTwv7IK2HRZfSfwoKU5tLlKS8C1O91tDM= +h1:jXSMbKW9P12r6gmXKCW2NR6uOlJDF5wR2bjF61lxk94= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -84,4 +84,6 @@ h1:3ftGXqIy9GWTwv7IK2HRZfSfwoKU5tLlKS8C1O91tDM= 20251106082844.sql h1:Dmi5A8i9frQZvdXYPwc7f8CisZtBH8liSXq1rI6z1iM= 20251106090021.sql h1:4JwdKgO8T46YhyWVJUxpRIwudBDlG8QN1brSOYmgQ20= 20251106144745.sql h1:nqnQCzGrVJaq8ilOEOGXeRUL1dolj+OPWKuP8A92FRA= -20251107012049.sql h1:JoINgSA4u4SUeF+rfTqTUDEWyZBpKMDULDfVdbE5g9E= +20251107012049.sql h1:Pff4UqltGS3clSlGr0qq8CQM56L29wyxY0FC/N/YAhU= +20251107064812.sql h1:jjpcAi0B/geEOKWmmR6+1UhWMhjstWhWQcz9lUWrtTY= +20251107064937.sql h1:1nPu0THBf+YquFIJSE4pc1dA7r3EydH92cpp26ozysw= diff --git a/internal/domain/main-entities/room/base/entity.go b/internal/domain/main-entities/room/base/entity.go index e45a441d..2ac690b6 100644 --- a/internal/domain/main-entities/room/base/entity.go +++ b/internal/domain/main-entities/room/base/entity.go @@ -8,14 +8,18 @@ import ( ) type Basic struct { - ecore.SmallMain // adjust this according to the needs - Infra_Id *uint16 `json:"infra_id"` - Unit_Id *uint16 `json:"unit_id"` - Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id"` - Specialist_Id *uint16 `json:"specialist_id"` - Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Id"` - Subspecialist_Id *uint16 `json:"subspecialist_id"` - Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Id"` + ecore.SmallMain // adjust this according to the needs + Infra_Id *uint16 `json:"infra_id"` + Infra_Code *string `json:"infra_code" gorm:"size:10"` + Unit_Id *uint16 `json:"unit_id"` + Unit_Code *string `json:"unit_code" gorm:"size:10"` + Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id"` + Specialist_Id *uint16 `json:"specialist_id"` + Specialist_Code *string `json:"specialist_code" gorm:"size:10"` + Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Id"` + Subspecialist_Id *uint16 `json:"subspecialist_id"` + Subspecialist_Code *string `json:"subspecialist_code" gorm:"size:10"` + Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Id"` } func (Basic) TableName() string { diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 925f9dc6..e974564b 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -36,7 +36,9 @@ import ( /******************** actor ********************/ + doctor "simrs-vx/internal/interface/main-handler/doctor" employee "simrs-vx/internal/interface/main-handler/employee" + nurse "simrs-vx/internal/interface/main-handler/nurse" nutritionist "simrs-vx/internal/interface/main-handler/nutritionist" patient "simrs-vx/internal/interface/main-handler/patient" person "simrs-vx/internal/interface/main-handler/person" @@ -267,6 +269,8 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/person-contact", personcontact.O) hc.RegCrud(r, "/v1/person-insurance", personinsurance.O) hc.RegCrud(r, "/v1/employee", employee.O) + hc.RegCrudByCode(r, "/v1/doctor", doctor.O) + hc.RegCrudByCode(r, "/v1/nurse", nurse.O) hc.RegCrud(r, "/v1/nutritionist", nutritionist.O) hc.RegCrud(r, "/v1/pharmacist", pharmacist.O) hk.GroupRoutes("/v1/user", r, hk.MapHandlerFunc{ From feb54bd2f5b1cfbfe66e374168286dcc5167fdc8 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 7 Nov 2025 13:54:39 +0700 Subject: [PATCH 104/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 26 ++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 83124cd0..70dd468c 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:jXSMbKW9P12r6gmXKCW2NR6uOlJDF5wR2bjF61lxk94= +h1:mPG9xfcT+aorrateezmQ8OvETRVigtmHiY1O8i2dpwg= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,15 +75,15 @@ h1:jXSMbKW9P12r6gmXKCW2NR6uOlJDF5wR2bjF61lxk94= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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:jjpcAi0B/geEOKWmmR6+1UhWMhjstWhWQcz9lUWrtTY= -20251107064937.sql h1:1nPu0THBf+YquFIJSE4pc1dA7r3EydH92cpp26ozysw= +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= From a944105f72f273621167c99ea2003524fac47670 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Fri, 7 Nov 2025 15:28:32 +0700 Subject: [PATCH 105/329] infra, room, item, medicine, device, material ids into codes --- .../migrations/20251107071420.sql | 6 ++ .../migrations/20251107074318.sql | 4 ++ .../migrations/20251107075050.sql | 4 ++ .../migrations/20251107080604.sql | 2 + .../migrations/20251107081830.sql | 6 ++ cmd/main-migration/migrations/atlas.sum | 31 +++++---- internal/domain/main-entities/device/dto.go | 17 ++--- .../domain/main-entities/device/entity.go | 2 + internal/domain/main-entities/infra/dto.go | 41 +++++------ internal/domain/main-entities/infra/entity.go | 7 +- internal/domain/main-entities/item/dto.go | 15 ++-- internal/domain/main-entities/item/entity.go | 1 + internal/domain/main-entities/material/dto.go | 69 ++++++++++--------- .../domain/main-entities/material/entity.go | 2 + internal/domain/main-entities/medicine/dto.go | 27 ++++---- .../domain/main-entities/medicine/entity.go | 2 + .../domain/main-entities/room/base/entity.go | 10 +-- internal/domain/main-entities/room/dto.go | 48 ++++++------- internal/domain/main-entities/room/entity.go | 2 +- .../interface/main-handler/device/handler.go | 18 ++--- .../interface/main-handler/infra/handler.go | 18 ++--- .../interface/main-handler/item/handler.go | 18 ++--- .../interface/main-handler/main-handler.go | 10 +-- .../main-handler/material/handler.go | 18 ++--- .../main-handler/medicine/handler.go | 18 ++--- .../use-case/main-use-case/device/case.go | 4 +- .../use-case/main-use-case/device/helper.go | 8 +-- internal/use-case/main-use-case/device/lib.go | 7 ++ .../use-case/main-use-case/division/lib.go | 2 +- internal/use-case/main-use-case/infra/case.go | 8 +-- .../use-case/main-use-case/infra/helper.go | 12 ++-- internal/use-case/main-use-case/infra/lib.go | 11 ++- internal/use-case/main-use-case/item/case.go | 4 +- .../use-case/main-use-case/item/helper.go | 2 +- .../use-case/main-use-case/material/case.go | 4 +- .../use-case/main-use-case/material/helper.go | 8 +-- .../use-case/main-use-case/medicine/case.go | 4 +- .../use-case/main-use-case/medicine/helper.go | 8 +-- .../use-case/main-use-case/medicine/lib.go | 9 ++- .../use-case/main-use-case/room/helper.go | 8 +-- 40 files changed, 277 insertions(+), 218 deletions(-) create mode 100644 cmd/main-migration/migrations/20251107071420.sql create mode 100644 cmd/main-migration/migrations/20251107074318.sql create mode 100644 cmd/main-migration/migrations/20251107075050.sql create mode 100644 cmd/main-migration/migrations/20251107080604.sql create mode 100644 cmd/main-migration/migrations/20251107081830.sql diff --git a/cmd/main-migration/migrations/20251107071420.sql b/cmd/main-migration/migrations/20251107071420.sql new file mode 100644 index 00000000..a9727884 --- /dev/null +++ b/cmd/main-migration/migrations/20251107071420.sql @@ -0,0 +1,6 @@ +-- Modify "Infra" table +ALTER TABLE "public"."Infra" ADD COLUMN "Parent_Code" character varying(10) NULL, ADD COLUMN "Item_Code" character varying(50) NULL; +-- Create index "idx_Infra_Code" to table: "Infra" +CREATE UNIQUE INDEX "idx_Infra_Code" ON "public"."Infra" ("Code"); +-- Modify "Room" table +ALTER TABLE "public"."Room" DROP CONSTRAINT "fk_Room_Specialist", DROP CONSTRAINT "fk_Room_Subspecialist", DROP CONSTRAINT "fk_Room_Unit", DROP COLUMN "Infra_Id", DROP COLUMN "Unit_Id", DROP COLUMN "Specialist_Id", DROP COLUMN "Subspecialist_Id", ADD CONSTRAINT "fk_Room_Specialist" FOREIGN KEY ("Specialist_Code") REFERENCES "public"."Specialist" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_Room_Subspecialist" FOREIGN KEY ("Subspecialist_Code") REFERENCES "public"."Subspecialist" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_Room_Unit" FOREIGN KEY ("Unit_Code") REFERENCES "public"."Unit" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251107074318.sql b/cmd/main-migration/migrations/20251107074318.sql new file mode 100644 index 00000000..5156b74e --- /dev/null +++ b/cmd/main-migration/migrations/20251107074318.sql @@ -0,0 +1,4 @@ +-- Modify "Nurse" table +ALTER TABLE "public"."Nurse" DROP CONSTRAINT "fk_Nurse_Infra"; +-- Modify "Infra" table +ALTER TABLE "public"."Infra" DROP CONSTRAINT "uni_Infra_Code"; diff --git a/cmd/main-migration/migrations/20251107075050.sql b/cmd/main-migration/migrations/20251107075050.sql new file mode 100644 index 00000000..fee27fee --- /dev/null +++ b/cmd/main-migration/migrations/20251107075050.sql @@ -0,0 +1,4 @@ +-- Modify "Nurse" table +ALTER TABLE "public"."Nurse" ADD CONSTRAINT "fk_Nurse_Infra" FOREIGN KEY ("Infra_Code") REFERENCES "public"."Infra" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "Room" table +ALTER TABLE "public"."Room" ADD CONSTRAINT "fk_Room_Infra" FOREIGN KEY ("Infra_Code") REFERENCES "public"."Infra" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251107080604.sql b/cmd/main-migration/migrations/20251107080604.sql new file mode 100644 index 00000000..246be1fa --- /dev/null +++ b/cmd/main-migration/migrations/20251107080604.sql @@ -0,0 +1,2 @@ +-- Modify "Item" table +ALTER TABLE "public"."Item" ADD COLUMN "Infra_Code" character varying(10) NULL; diff --git a/cmd/main-migration/migrations/20251107081830.sql b/cmd/main-migration/migrations/20251107081830.sql new file mode 100644 index 00000000..a7490211 --- /dev/null +++ b/cmd/main-migration/migrations/20251107081830.sql @@ -0,0 +1,6 @@ +-- Modify "Device" table +ALTER TABLE "public"."Device" ADD COLUMN "Infra_Code" character varying(10) NULL, ADD COLUMN "Item_Code" character varying(50) NULL; +-- Modify "Material" table +ALTER TABLE "public"."Material" ADD COLUMN "Infra_Code" character varying(10) NULL, ADD COLUMN "Item_Code" character varying(50) NULL; +-- Modify "Medicine" table +ALTER TABLE "public"."Medicine" ADD COLUMN "Infra_Code" character varying(10) NULL, ADD COLUMN "Item_Code" character varying(50) NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 70dd468c..440bd74d 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:mPG9xfcT+aorrateezmQ8OvETRVigtmHiY1O8i2dpwg= +h1:A8U7W3JZbEUXu6uzF9wfKvSgX/j+G1nQoxchM989kiw= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,15 +75,20 @@ h1:mPG9xfcT+aorrateezmQ8OvETRVigtmHiY1O8i2dpwg= 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= +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:jjpcAi0B/geEOKWmmR6+1UhWMhjstWhWQcz9lUWrtTY= +20251107064937.sql h1:1nPu0THBf+YquFIJSE4pc1dA7r3EydH92cpp26ozysw= +20251107071420.sql h1:Q+e+OqjdiuK/sghDQ5NxjU+u2zYl+vh/eRBlUz9Idhg= +20251107074318.sql h1:VbOWMw2rClEWgMnDSejXPqXkFoQ4odVsHn3/UAEiCYA= +20251107075050.sql h1:ZZaKJEWXIJ94/0/2Gzzz+HXjmebEs5eP8iUIot26/c8= +20251107080604.sql h1:aq+tINa0ULCZlJcUK2jaeGh6rRH4jJz3e2NrK47m0Ec= +20251107081830.sql h1:Bl9kniyLWeMqd3nrvgCgiUpdcJWp8qX1F41JAM1WbiE= diff --git a/internal/domain/main-entities/device/dto.go b/internal/domain/main-entities/device/dto.go index 1c874576..36e90a0c 100644 --- a/internal/domain/main-entities/device/dto.go +++ b/internal/domain/main-entities/device/dto.go @@ -8,11 +8,11 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=10"` - Name string `json:"name" validate:"maxLength=50"` - Uom_Code string `json:"uom_code" validate:"maxLength=10"` - Infra_Id *uint16 `json:"infra_id"` - Item_Id *uint `json:"item_id"` + Code string `json:"code" validate:"maxLength=10"` + Name string `json:"name" validate:"maxLength=50"` + Uom_Code string `json:"uom_code" validate:"maxLength=10"` + Infra_Code *string `json:"infra_code"` + Item_Code *string `json:"item_code"` } type ReadListDto struct { @@ -32,17 +32,18 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` CreateDto } type DeleteDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/domain/main-entities/device/entity.go b/internal/domain/main-entities/device/entity.go index ca54c08d..c68b7c3e 100644 --- a/internal/domain/main-entities/device/entity.go +++ b/internal/domain/main-entities/device/entity.go @@ -14,7 +14,9 @@ type Device struct { Uom_Code string `json:"uom_code" gorm:"size:10"` Uom *eu.Uom `json:"uom,omitempty" gorm:"foreignKey:Uom_Code;references:Code"` Infra_Id *uint16 `json:"infra_id"` + Infra_Code *string `json:"infra_code" gorm:"size:10"` Infra *ein.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Id;references:Id"` Item_Id *uint `json:"item_id"` + Item_Code *string `json:"item_code" gorm:"size:50"` Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` } diff --git a/internal/domain/main-entities/infra/dto.go b/internal/domain/main-entities/infra/dto.go index de566fad..28ff8d93 100644 --- a/internal/domain/main-entities/infra/dto.go +++ b/internal/domain/main-entities/infra/dto.go @@ -9,15 +9,15 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=10"` - Name string `json:"name" validate:"maxLength=50"` - InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code" validate:"maxLength=15"` - Parent_Id *uint16 `json:"parent_id"` - Item_Id *uint `json:"item_id"` - Unit_Id *uint16 `json:"unit_id"` - Specialist_Id *uint16 `json:"specialist_id"` - Subspecialist_Id *uint16 `json:"subspecialist_id"` - Infra_Id *uint16 `json:"-"` // for room + Code string `json:"code" validate:"maxLength=10"` + Name string `json:"name" validate:"maxLength=50"` + InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code" validate:"maxLength=15"` + Parent_Code *string `json:"parent_code"` + Item_Id *uint `json:"-"` + Unit_Code *string `json:"unit_code"` + Specialist_Code *string `json:"specialist_code"` + Subspecialist_Code *string `json:"subspecialist_code"` + Infra_Code *string `json:"infra_code"` // for room } type ReadListDto struct { @@ -32,24 +32,25 @@ type FilterDto struct { Code string `json:"code"` Name string `json:"name"` InfraGroup_Code ero.InfraGroupCode `json:"infraGroup-code"` - Parent_Id *uint16 `json:"parent-id"` - Item_Id *uint `json:"item-id"` + Parent_Code *string `json:"parent-code"` + Item_Id *string `json:"item-code"` Search string `json:"search" gormhelper:"searchColumns=Code,Name"` } type ReadDetailDto struct { - Id uint16 `json:"id"` - Code *string `json:"code"` - Item_Id *uint `json:"item_id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` + Item_Code *string `json:"item_code"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { @@ -63,10 +64,10 @@ type ResponseDto struct { Code string `json:"code"` Name string `json:"name"` InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code"` - Parent_Id *uint16 `json:"parent_id"` + Parent_Code *string `json:"parent_code"` Parent *Infra `json:"parent,omitempty"` Childrens []Infra `json:"childrens,omitempty"` - Item_Id *uint `json:"item_id"` + Item_Code *string `json:"item_code"` Item *ei.Item `json:"item,omitempty"` Rooms []erb.Basic `json:"rooms,omitempty"` } @@ -76,10 +77,10 @@ func (d Infra) ToResponse() ResponseDto { Code: d.Code, Name: d.Name, InfraGroup_Code: d.InfraGroup_Code, - Parent_Id: d.Parent_Id, + Parent_Code: d.Parent_Code, Parent: d.Parent, Childrens: d.Childrens, - Item_Id: d.Item_Id, + Item_Code: d.Item_Code, Item: d.Item, Rooms: d.Rooms, } diff --git a/internal/domain/main-entities/infra/entity.go b/internal/domain/main-entities/infra/entity.go index 3d8c6f99..dfc19e3d 100644 --- a/internal/domain/main-entities/infra/entity.go +++ b/internal/domain/main-entities/infra/entity.go @@ -3,6 +3,7 @@ package infra import ( ecore "simrs-vx/internal/domain/base-entities/core" ei "simrs-vx/internal/domain/main-entities/item" + erb "simrs-vx/internal/domain/main-entities/room/base" ero "simrs-vx/internal/domain/references/organization" @@ -10,13 +11,15 @@ import ( type Infra struct { ecore.SmallMain // adjust this according to the needs - Code string `json:"code" gorm:"unique;size:10"` + Code string `json:"code" gorm:"uniqueIndex;size:10"` Name string `json:"name" gorm:"size:50"` InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code" gorm:"size:15"` Parent_Id *uint16 `json:"parent_id"` + Parent_Code *string `json:"parent_code" gorm:"size:10"` Parent *Infra `json:"parent" gorm:"foreignKey:Parent_Id;references:Id"` Childrens []Infra `json:"childrens" gorm:"foreignKey:Parent_Id"` // may need references to self Item_Id *uint `json:"item_id"` + Item_Code *string `json:"item_code" gorm:"size:50"` Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` - Rooms []erb.Basic `json:"rooms" gorm:"foreignKey:Infra_Id"` + Rooms []erb.Basic `json:"rooms" gorm:"foreignKey:Infra_Code;references:Code"` } diff --git a/internal/domain/main-entities/item/dto.go b/internal/domain/main-entities/item/dto.go index 22be4c1a..f20ce217 100644 --- a/internal/domain/main-entities/item/dto.go +++ b/internal/domain/main-entities/item/dto.go @@ -11,7 +11,7 @@ type CreateDto struct { Name string `json:"name" validate:"maxLength=100"` ItemGroup_Code ero.ItemGroupCode `json:"itemGroup_code" validate:"maxLength=10"` Uom_Code *string `json:"uom_code" validate:"maxLength=10"` - Infra_Id *uint16 `json:"infra_id"` + Infra_Code *string `json:"infra_code"` Stock *int `json:"stock"` } @@ -27,23 +27,24 @@ type FilterDto struct { Name string `json:"name"` ItemGroup_Code ero.ItemGroupCode `json:"itemGroup-code"` Uom_Code *string `json:"uom-code"` - Infra_Id *uint16 `json:"infra-id"` + Infra_Code *string `json:"infra-code"` Stock *int `json:"stock"` Search string `json:"search" gormhelper:"searchColumns=Code,Name"` } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` CreateDto } type DeleteDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` + Code *string `json:"code"` } type MetaDto struct { @@ -59,7 +60,7 @@ type ResponseDto struct { ItemGroup_Code ero.ItemGroupCode `json:"itemGroup_code"` Uom_Code *string `json:"uom_code"` Uom *eu.Uom `json:"uom,omitempty"` - Infra_Id *uint16 `json:"infra_id"` + Infra_Code *string `json:"infra_code"` Stock *int `json:"stock"` } @@ -70,7 +71,7 @@ func (d Item) ToResponse() ResponseDto { ItemGroup_Code: d.ItemGroup_Code, Uom_Code: d.Uom_Code, Uom: d.Uom, - Infra_Id: d.Infra_Id, + Infra_Code: d.Infra_Code, Stock: d.Stock, } resp.Main = d.Main diff --git a/internal/domain/main-entities/item/entity.go b/internal/domain/main-entities/item/entity.go index e0ff4e21..406c57e6 100644 --- a/internal/domain/main-entities/item/entity.go +++ b/internal/domain/main-entities/item/entity.go @@ -15,5 +15,6 @@ type Item struct { Uom_Code *string `json:"uom_code" gorm:"size:10"` Uom *eu.Uom `json:"uom,omitempty" gorm:"foreignKey:Uom_Code;references:Code"` Infra_Id *uint16 `json:"infra_id"` + Infra_Code *string `json:"infra_code" gorm:"size:10"` Stock *int `json:"stock"` } diff --git a/internal/domain/main-entities/material/dto.go b/internal/domain/main-entities/material/dto.go index 18a93723..fbedbf43 100644 --- a/internal/domain/main-entities/material/dto.go +++ b/internal/domain/main-entities/material/dto.go @@ -8,12 +8,12 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=10"` - Name string `json:"name" validate:"maxLength=50"` - Uom_Code string `json:"uom_code" validate:"maxLength=10"` - Infra_Id *uint16 `json:"infra_id"` - Stock *int `json:"stock"` - Item_Id *uint `json:"item_id"` + Code string `json:"code" validate:"maxLength=10"` + Name string `json:"name" validate:"maxLength=50"` + Uom_Code string `json:"uom_code" validate:"maxLength=10"` + Infra_Code *string `json:"infra_code"` + Stock *int `json:"stock"` + Item_Code *string `json:"item_code"` } type ReadListDto struct { @@ -24,28 +24,29 @@ type ReadListDto struct { } type FilterDto struct { - Code string `json:"code"` - Name string `json:"name"` - Uom_Code string `json:"uom-code"` - Infra_Id *uint16 `json:"infra-id"` - Stock *int `json:"stock"` - Item_Id *uint `json:"item-id"` - Search string `json:"search" gormhelper:"searchColumns=Code,Name"` + Code string `json:"code"` + Name string `json:"name"` + Uom_Code string `json:"uom-code"` + Infra_Code *string `json:"infra-code"` + Stock *int `json:"stock"` + Item_Code *string `json:"item-code"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` Item_Id *uint `json:"item_id"` } type UpdateDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` CreateDto } type DeleteDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` + Code *string `json:"code"` } type MetaDto struct { @@ -56,28 +57,28 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Code string `json:"code"` - Name string `json:"name"` - Uom_Code string `json:"uom_code"` - Uom *eu.Uom `json:"uom,omitempty"` - Infra_Id *uint16 `json:"infra_id"` - Infra *ein.Infra `json:"infra,omitempty"` - Stock *int `json:"stock"` - Item_Id *uint `json:"item_id"` - Item *ei.Item `json:"item,omitempty"` + Code string `json:"code"` + Name string `json:"name"` + Uom_Code string `json:"uom_code"` + Uom *eu.Uom `json:"uom,omitempty"` + Infra_Code *string `json:"infra_code"` + Infra *ein.Infra `json:"infra,omitempty"` + Stock *int `json:"stock"` + Item_Code *string `json:"item_code"` + Item *ei.Item `json:"item,omitempty"` } func (d Material) ToResponse() ResponseDto { resp := ResponseDto{ - Code: d.Code, - Name: d.Name, - Uom_Code: d.Uom_Code, - Uom: d.Uom, - Infra_Id: d.Infra_Id, - Infra: d.Infra, - Stock: d.Stock, - Item_Id: d.Item_Id, - Item: d.Item, + Code: d.Code, + Name: d.Name, + Uom_Code: d.Uom_Code, + Uom: d.Uom, + Infra_Code: d.Infra_Code, + Infra: d.Infra, + Stock: d.Stock, + Item_Code: d.Item_Code, + Item: d.Item, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/material/entity.go b/internal/domain/main-entities/material/entity.go index cdfd8bfd..50e6907e 100644 --- a/internal/domain/main-entities/material/entity.go +++ b/internal/domain/main-entities/material/entity.go @@ -14,8 +14,10 @@ type Material struct { Uom_Code string `json:"uom_code" gorm:"size:10"` Uom *eu.Uom `json:"uom,omitempty" gorm:"foreignKey:Uom_Code;references:Code"` Infra_Id *uint16 `json:"infra_id"` + Infra_Code *string `json:"infra_code" gorm:"size:10"` Infra *ein.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Id;references:Id"` Stock *int `json:"stock"` Item_Id *uint `json:"item_id"` + Item_Code *string `json:"item_code" gorm:"size:50"` Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` } diff --git a/internal/domain/main-entities/medicine/dto.go b/internal/domain/main-entities/medicine/dto.go index 82431fc1..945db1e5 100644 --- a/internal/domain/main-entities/medicine/dto.go +++ b/internal/domain/main-entities/medicine/dto.go @@ -16,9 +16,9 @@ type CreateDto struct { MedicineMethod_Code *string `json:"medicineMethod_code" validate:"maxLength=10"` Uom_Code *string `json:"uom_code" validate:"maxLength=10"` Dose uint8 `json:"dose"` - Infra_Id *uint16 `json:"infra_id"` + Infra_Code *string `json:"infra_code"` Stock *int `json:"stock"` - Item_Id *uint `json:"item_id"` + Item_Code *string `json:"item_code"` } type ReadListDto struct { @@ -35,25 +35,26 @@ type FilterDto struct { MedicineMethod_Code *string `json:"medicineMethod-code"` Uom_Code *string `json:"uom-code"` Dose uint8 `json:"dose"` - Infra_Id *uint16 `json:"infra-id"` + Infra_Code *string `json:"infra-code"` Stock *int `json:"stock"` - Item_Id *uint `json:"item-id"` + Item_Code *string `json:"item-code"` Search string `json:"search" gormhelper:"searchColumns=Code,Name"` } type ReadDetailDto struct { - Id uint16 `json:"id"` - Code *string `json:"code"` - Item_Id *uint `json:"item_id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` + Item_Code *uint `json:"item_code"` } type UpdateDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` CreateDto } type DeleteDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` + Code *string `json:"code"` } type MetaDto struct { @@ -73,10 +74,10 @@ type ResponseDto struct { Uom_Code *string `json:"uom_code"` Uom *eu.Uom `json:"uom"` Dose uint8 `json:"dose"` - Infra_Id *uint16 `json:"infra_id"` + Infra_Code *string `json:"infra_code"` Infra *ein.Infra `json:"infra,omitempty"` Stock *int `json:"stock"` - Item_Id *uint `json:"item_id"` + Item_Code *string `json:"item_code"` Item *eit.Item `json:"item,omitempty"` } @@ -91,10 +92,10 @@ func (d Medicine) ToResponse() ResponseDto { Uom_Code: d.Uom_Code, Uom: d.Uom, Dose: d.Dose, - Infra_Id: d.Infra_Id, + Infra_Code: d.Infra_Code, Infra: d.Infra, Stock: d.Stock, - Item_Id: d.Item_Id, + Item_Code: d.Item_Code, Item: d.Item, } resp.Main = d.Main diff --git a/internal/domain/main-entities/medicine/entity.go b/internal/domain/main-entities/medicine/entity.go index d538f496..bbcfec78 100644 --- a/internal/domain/main-entities/medicine/entity.go +++ b/internal/domain/main-entities/medicine/entity.go @@ -21,8 +21,10 @@ type Medicine struct { Uom *eu.Uom `json:"uom" gorm:"foreignKey:Uom_Code;references:Code"` Dose uint8 `json:"dose"` Infra_Id *uint16 `json:"infra_id"` + Infra_Code *string `json:"infra_code" gorm:"size:10"` Infra *ein.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Id;references:Id"` Stock *int `json:"stock"` Item_Id *uint `json:"item_id"` + Item_Code *string `json:"item_code" gorm:"size:50"` Item *eit.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` } diff --git a/internal/domain/main-entities/room/base/entity.go b/internal/domain/main-entities/room/base/entity.go index 2ac690b6..d5651ac9 100644 --- a/internal/domain/main-entities/room/base/entity.go +++ b/internal/domain/main-entities/room/base/entity.go @@ -9,17 +9,13 @@ import ( type Basic struct { ecore.SmallMain // adjust this according to the needs - Infra_Id *uint16 `json:"infra_id"` Infra_Code *string `json:"infra_code" gorm:"size:10"` - Unit_Id *uint16 `json:"unit_id"` Unit_Code *string `json:"unit_code" gorm:"size:10"` - Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id"` - Specialist_Id *uint16 `json:"specialist_id"` + Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` Specialist_Code *string `json:"specialist_code" gorm:"size:10"` - Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Id"` - Subspecialist_Id *uint16 `json:"subspecialist_id"` + Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Code;references:Code"` Subspecialist_Code *string `json:"subspecialist_code" gorm:"size:10"` - Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Id"` + Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Code;references:Code"` } func (Basic) TableName() string { diff --git a/internal/domain/main-entities/room/dto.go b/internal/domain/main-entities/room/dto.go index 0ca2e8d4..2ff41c3a 100644 --- a/internal/domain/main-entities/room/dto.go +++ b/internal/domain/main-entities/room/dto.go @@ -9,10 +9,10 @@ import ( ) type CreateDto struct { - Infra_Id *uint16 `json:"infra_id"` - Unit_Id *uint16 `json:"unit_id"` - Specialist_Id *uint16 `json:"specialist_id"` - Subspecialist_Id *uint16 `json:"subspecialist_id"` + Infra_Code *string `json:"infra_code"` + Unit_Code *string `json:"unit_code"` + Specialist_Code *string `json:"specialist_code"` + Subspecialist_Code *string `json:"subspecialist_code"` } type ReadListDto struct { @@ -22,10 +22,10 @@ type ReadListDto struct { } type FilterDto struct { - Infra_Id *uint16 `json:"infra-id"` - Unit_Id *uint16 `json:"unit-id"` - Specialist_Id *uint16 `json:"specialist-id"` - Subspecialist_Id *uint16 `json:"subspecialist-id"` + Infra_Code *string `json:"infra-code"` + Unit_Code *string `json:"unit-code"` + Specialist_Code *string `json:"specialist-code"` + Subspecialist_Code *string `json:"subspecialist-code"` } type ReadDetailDto struct { @@ -49,26 +49,26 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain - Infra_Id *uint16 `json:"infra_id"` - Infra *ei.Infra `json:"infra,omitempty"` - Unit_Id *uint16 `json:"unit_id"` - Unit *eu.Unit `json:"unit,omitempty"` - Specialist_Id *uint16 `json:"specialist_id"` - Specialist *es.Specialist `json:"specialist,omitempty"` - Subspecialist_Id *uint16 `json:"subspecialist_id"` - Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty"` + Infra_Code *string `json:"infra_code"` + Infra *ei.Infra `json:"infra,omitempty"` + Unit_Code *string `json:"unit_code"` + Unit *eu.Unit `json:"unit,omitempty"` + Specialist_Code *string `json:"specialist_code"` + Specialist *es.Specialist `json:"specialist,omitempty"` + Subspecialist_Code *string `json:"subspecialist_code"` + Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty"` } func (d Room) ToResponse() ResponseDto { resp := ResponseDto{ - Infra_Id: d.Infra_Id, - Infra: d.Infra, - Unit_Id: d.Unit_Id, - Unit: d.Unit, - Specialist_Id: d.Specialist_Id, - Specialist: d.Specialist, - Subspecialist_Id: d.Subspecialist_Id, - Subspecialist: d.Subspecialist, + Infra_Code: d.Infra_Code, + Infra: d.Infra, + Unit_Code: d.Unit_Code, + Unit: d.Unit, + Specialist_Code: d.Specialist_Code, + Specialist: d.Specialist, + Subspecialist_Code: d.Subspecialist_Code, + Subspecialist: d.Subspecialist, } resp.SmallMain = d.SmallMain return resp diff --git a/internal/domain/main-entities/room/entity.go b/internal/domain/main-entities/room/entity.go index 346c7741..49fb8cc6 100644 --- a/internal/domain/main-entities/room/entity.go +++ b/internal/domain/main-entities/room/entity.go @@ -7,5 +7,5 @@ import ( type Room struct { ebase.Basic - Infra *ei.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Id"` + Infra *ei.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Code;references:Code"` } diff --git a/internal/interface/main-handler/device/handler.go b/internal/interface/main-handler/device/handler.go index 1a3cb18d..c827f20f 100644 --- a/internal/interface/main-handler/device/handler.go +++ b/internal/interface/main-handler/device/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint(id) + dto.Code = code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/infra/handler.go b/internal/interface/main-handler/infra/handler.go index 71a8f1ec..fedccf48 100644 --- a/internal/interface/main-handler/infra/handler.go +++ b/internal/interface/main-handler/infra/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ 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.Code = code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/item/handler.go b/internal/interface/main-handler/item/handler.go index 124be7ef..a786e86b 100644 --- a/internal/interface/main-handler/item/handler.go +++ b/internal/interface/main-handler/item/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint(id) + dto.Code = code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index e974564b..6d0548e9 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -304,22 +304,22 @@ func SetRoutes() http.Handler { hc.RegCrudByCode(r, "/v1/subspecialist", subspecialist.O) hc.RegCrudByCode(r, "/v1/specialist-position", specialistposition.O) hc.RegCrudByCode(r, "/v1/subspecialist-position", subspecialistposition.O) + hc.RegCrudByCode(r, "/v1/infra", infra.O) hc.RegCrud(r, "/v1/pharmacy-company", pharmacycompany.O) hc.RegCrud(r, "/v1/diagnose-src", diagnosesrc.O) hc.RegCrud(r, "/v1/procedure-src", proceduresrc.O) hc.RegCrud(r, "/v1/uom", uom.O) - hc.RegCrud(r, "/v1/item", item.O) + hc.RegCrudByCode(r, "/v1/item", item.O) hc.RegCrud(r, "/v1/item-price", itemprice.O) - hc.RegCrud(r, "/v1/infra", infra.O) hc.RegCrud(r, "/v1/medicine-group", medicinegroup.O) hc.RegCrud(r, "/v1/medicine-method", medicinemethod.O) hc.RegCrud(r, "/v1/mcu-src-category", mcusrccategory.O) hc.RegCrud(r, "/v1/mcu-src", mcusrc.O) hc.RegCrud(r, "/v1/ethnic", ethnic.O) hc.RegCrud(r, "/v1/insurance-company", insurancecompany.O) - hc.RegCrud(r, "/v1/medicine", medicine.O) - hc.RegCrud(r, "/v1/device", device.O) - hc.RegCrud(r, "/v1/material", material.O) + hc.RegCrudByCode(r, "/v1/medicine", medicine.O) + hc.RegCrudByCode(r, "/v1/device", device.O) + hc.RegCrudByCode(r, "/v1/material", material.O) hc.RegCrud(r, "/v1/doctor-fee", doctorfee.O) hc.RegCrud(r, "/v1/medical-action-src", medicalactionsrc.O) hc.RegCrud(r, "/v1/medical-action-src-item", medicalactionsrcitem.O) diff --git a/internal/interface/main-handler/material/handler.go b/internal/interface/main-handler/material/handler.go index 2b152625..10de8a92 100644 --- a/internal/interface/main-handler/material/handler.go +++ b/internal/interface/main-handler/material/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint(id) + dto.Code = code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/medicine/handler.go b/internal/interface/main-handler/medicine/handler.go index 5a5b28e0..b6a3f185 100644 --- a/internal/interface/main-handler/medicine/handler.go +++ b/internal/interface/main-handler/medicine/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint(id) + dto.Code = code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/use-case/main-use-case/device/case.go b/internal/use-case/main-use-case/device/case.go index ff548a4b..126dff9f 100644 --- a/internal/use-case/main-use-case/device/case.go +++ b/internal/use-case/main-use-case/device/case.go @@ -169,7 +169,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: &input.Code} var data *e.Device var err error @@ -225,7 +225,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Device var err error diff --git a/internal/use-case/main-use-case/device/helper.go b/internal/use-case/main-use-case/device/helper.go index 08964464..21956cc5 100644 --- a/internal/use-case/main-use-case/device/helper.go +++ b/internal/use-case/main-use-case/device/helper.go @@ -30,8 +30,8 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Device) { data.Code = inputSrc.Code data.Name = inputSrc.Name data.Uom_Code = inputSrc.Uom_Code - data.Item_Id = inputSrc.Item_Id - data.Infra_Id = inputSrc.Infra_Id + data.Item_Code = inputSrc.Item_Code + data.Infra_Code = inputSrc.Infra_Code } func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { @@ -40,13 +40,13 @@ func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { Name: input.Name, ItemGroup_Code: ero.ITGCDevice, Uom_Code: &input.Uom_Code, - Infra_Id: input.Infra_Id, + Infra_Code: input.Infra_Code, } item, err := ui.CreateData(itemCreate, event, tx) if err != nil { return err } - input.Item_Id = &item.Id + input.Item_Code = &item.Code return nil } diff --git a/internal/use-case/main-use-case/device/lib.go b/internal/use-case/main-use-case/device/lib.go index 664db248..63c8cedb 100644 --- a/internal/use-case/main-use-case/device/lib.go +++ b/internal/use-case/main-use-case/device/lib.go @@ -81,6 +81,13 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e tx = dg.I } + if input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", *input.Id) + } + if err := tx.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/division/lib.go b/internal/use-case/main-use-case/division/lib.go index 62a10d5b..0b45ba11 100644 --- a/internal/use-case/main-use-case/division/lib.go +++ b/internal/use-case/main-use-case/division/lib.go @@ -52,7 +52,7 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Di EXISTS ( SELECT 1 FROM "Division" c - WHERE c."Parent_Id" = "Division"."Id" + WHERE c."Parent_Code" = "Division"."Code" ) `) } diff --git a/internal/use-case/main-use-case/infra/case.go b/internal/use-case/main-use-case/infra/case.go index 7c227e8b..4771f3cb 100644 --- a/internal/use-case/main-use-case/infra/case.go +++ b/internal/use-case/main-use-case/infra/case.go @@ -38,12 +38,12 @@ func Create(input e.CreateDto) (*d.Data, error) { } if input.InfraGroup_Code == ero.IFGCRoom { - if input.Parent_Id == nil { + if input.Parent_Code == nil { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "data-create-fail", - Detail: "parent_id is required", - Raw: errors.New("parent_id is required"), + Detail: "parent_code is required", + Raw: errors.New("parent_code is required"), } return pl.SetLogError(&event, input) @@ -59,7 +59,7 @@ func Create(input e.CreateDto) (*d.Data, error) { } if input.InfraGroup_Code == ero.IFGCRoom { - input.Infra_Id = &data.Id + input.Infra_Code = &data.Code if err := createRoom(&input, &event, tx); err != nil { return err } diff --git a/internal/use-case/main-use-case/infra/helper.go b/internal/use-case/main-use-case/infra/helper.go index 35388c85..2e6dc383 100644 --- a/internal/use-case/main-use-case/infra/helper.go +++ b/internal/use-case/main-use-case/infra/helper.go @@ -29,7 +29,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Infra) { data.Code = inputSrc.Code data.Name = inputSrc.Name data.InfraGroup_Code = inputSrc.InfraGroup_Code - data.Parent_Id = inputSrc.Parent_Id + data.Parent_Code = inputSrc.Parent_Code data.Item_Id = inputSrc.Item_Id } @@ -42,7 +42,7 @@ func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { tmp := "unit" return &tmp }(), - Infra_Id: input.Parent_Id, + Infra_Code: input.Parent_Code, } item, err := ui.CreateData(itemCreate, event, tx) if err != nil { @@ -55,10 +55,10 @@ func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { func createRoom(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { roomCreate := er.CreateDto{ - Infra_Id: input.Infra_Id, - Unit_Id: input.Unit_Id, - Specialist_Id: input.Specialist_Id, - Subspecialist_Id: input.Subspecialist_Id, + Infra_Code: input.Infra_Code, + Unit_Code: input.Unit_Code, + Specialist_Code: input.Specialist_Code, + Subspecialist_Code: input.Subspecialist_Code, } _, err := ur.CreateData(roomCreate, event, tx) if err != nil { diff --git a/internal/use-case/main-use-case/infra/lib.go b/internal/use-case/main-use-case/infra/lib.go index 234104bb..67062b31 100644 --- a/internal/use-case/main-use-case/infra/lib.go +++ b/internal/use-case/main-use-case/infra/lib.go @@ -52,7 +52,7 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.In EXISTS ( SELECT 1 FROM "Infra" c - WHERE c."Parent_Id" = "Infra"."Id" + WHERE c."Parent_Code" = "Infra"."Code" ) `) } @@ -91,6 +91,13 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e tx = dg.I } + if input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", *input.Id) + } + tx = tx.Preload("Parent"). Preload("Childrens"). Preload("Item"). @@ -99,7 +106,7 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e Preload("Rooms.Subspecialist"). Preload("Rooms.Unit") - if err := tx.First(&data, input.Id).Error; err != nil { + if err := tx.First(&data).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/item/case.go b/internal/use-case/main-use-case/item/case.go index 914d777f..58ce3213 100644 --- a/internal/use-case/main-use-case/item/case.go +++ b/internal/use-case/main-use-case/item/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: &input.Code} var data *e.Item var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Item var err error diff --git a/internal/use-case/main-use-case/item/helper.go b/internal/use-case/main-use-case/item/helper.go index 0ebfcd37..6f7e0c57 100644 --- a/internal/use-case/main-use-case/item/helper.go +++ b/internal/use-case/main-use-case/item/helper.go @@ -21,6 +21,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Item) { data.Name = inputSrc.Name data.ItemGroup_Code = inputSrc.ItemGroup_Code data.Uom_Code = inputSrc.Uom_Code - data.Infra_Id = inputSrc.Infra_Id + data.Infra_Code = inputSrc.Infra_Code data.Stock = inputSrc.Stock } diff --git a/internal/use-case/main-use-case/material/case.go b/internal/use-case/main-use-case/material/case.go index 42346dc6..5f5cec55 100644 --- a/internal/use-case/main-use-case/material/case.go +++ b/internal/use-case/main-use-case/material/case.go @@ -169,7 +169,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: &input.Code} var data *e.Material var err error @@ -225,7 +225,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Material var err error diff --git a/internal/use-case/main-use-case/material/helper.go b/internal/use-case/main-use-case/material/helper.go index 9cfefe27..ee415107 100644 --- a/internal/use-case/main-use-case/material/helper.go +++ b/internal/use-case/main-use-case/material/helper.go @@ -30,8 +30,8 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Material) { data.Name = inputSrc.Name data.Uom_Code = inputSrc.Uom_Code data.Stock = inputSrc.Stock - data.Item_Id = inputSrc.Item_Id - data.Infra_Id = inputSrc.Infra_Id + data.Item_Code = inputSrc.Item_Code + data.Infra_Code = inputSrc.Infra_Code } func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { @@ -40,7 +40,7 @@ func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { Name: input.Name, ItemGroup_Code: ero.ITGCMaterial, Uom_Code: &input.Uom_Code, - Infra_Id: input.Infra_Id, + Infra_Code: input.Infra_Code, Stock: input.Stock, } item, err := ui.CreateData(itemCreate, event, tx) @@ -48,6 +48,6 @@ func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { return err } - input.Item_Id = &item.Id + input.Item_Code = &item.Code return nil } diff --git a/internal/use-case/main-use-case/medicine/case.go b/internal/use-case/main-use-case/medicine/case.go index 5855d33c..3e5bee2d 100644 --- a/internal/use-case/main-use-case/medicine/case.go +++ b/internal/use-case/main-use-case/medicine/case.go @@ -169,7 +169,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: &input.Code} var data *e.Medicine var err error @@ -225,7 +225,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Medicine var err error diff --git a/internal/use-case/main-use-case/medicine/helper.go b/internal/use-case/main-use-case/medicine/helper.go index 388be819..1cf35762 100644 --- a/internal/use-case/main-use-case/medicine/helper.go +++ b/internal/use-case/main-use-case/medicine/helper.go @@ -33,9 +33,9 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Medicine) { data.MedicineMethod_Code = inputSrc.MedicineMethod_Code data.Uom_Code = inputSrc.Uom_Code data.Dose = inputSrc.Dose - data.Infra_Id = inputSrc.Infra_Id + data.Infra_Code = inputSrc.Infra_Code data.Stock = inputSrc.Stock - data.Item_Id = inputSrc.Item_Id + data.Item_Code = inputSrc.Item_Code } func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { @@ -44,7 +44,7 @@ func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { Name: input.Name, ItemGroup_Code: ero.ITGCMedicine, Uom_Code: input.Uom_Code, - Infra_Id: input.Infra_Id, + Infra_Code: input.Infra_Code, Stock: input.Stock, } item, err := ui.CreateData(itemCreate, event, tx) @@ -52,6 +52,6 @@ func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { return err } - input.Item_Id = &item.Id + input.Item_Code = &item.Code return nil } diff --git a/internal/use-case/main-use-case/medicine/lib.go b/internal/use-case/main-use-case/medicine/lib.go index 3b9d2fa1..f9fccb2e 100644 --- a/internal/use-case/main-use-case/medicine/lib.go +++ b/internal/use-case/main-use-case/medicine/lib.go @@ -81,8 +81,15 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e tx = dg.I } + if input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", *input.Id) + } + tx = tx.Preload("Item") - if err := tx.First(&data, input.Id).Error; err != nil { + if err := tx.First(&data).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/room/helper.go b/internal/use-case/main-use-case/room/helper.go index cc64e8c5..5e97a653 100644 --- a/internal/use-case/main-use-case/room/helper.go +++ b/internal/use-case/main-use-case/room/helper.go @@ -17,8 +17,8 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Room) { inputSrc = &inputTemp.CreateDto } - data.Infra_Id = inputSrc.Infra_Id - data.Unit_Id = inputSrc.Unit_Id - data.Specialist_Id = inputSrc.Specialist_Id - data.Subspecialist_Id = inputSrc.Subspecialist_Id + data.Infra_Code = inputSrc.Infra_Code + data.Unit_Code = inputSrc.Unit_Code + data.Specialist_Code = inputSrc.Specialist_Code + data.Subspecialist_Code = inputSrc.Subspecialist_Code } From c9d7400dad11fc473bd75642ba2bb748de0b0b40 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 7 Nov 2025 15:34:05 +0700 Subject: [PATCH 106/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 36 ++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 440bd74d..153eb372 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:A8U7W3JZbEUXu6uzF9wfKvSgX/j+G1nQoxchM989kiw= +h1:D7TdOht9cEt91EEPEvi05Frs3ZFC+Uz+y4K+bebB3BI= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,20 +75,20 @@ h1:A8U7W3JZbEUXu6uzF9wfKvSgX/j+G1nQoxchM989kiw= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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:jjpcAi0B/geEOKWmmR6+1UhWMhjstWhWQcz9lUWrtTY= -20251107064937.sql h1:1nPu0THBf+YquFIJSE4pc1dA7r3EydH92cpp26ozysw= -20251107071420.sql h1:Q+e+OqjdiuK/sghDQ5NxjU+u2zYl+vh/eRBlUz9Idhg= -20251107074318.sql h1:VbOWMw2rClEWgMnDSejXPqXkFoQ4odVsHn3/UAEiCYA= -20251107075050.sql h1:ZZaKJEWXIJ94/0/2Gzzz+HXjmebEs5eP8iUIot26/c8= -20251107080604.sql h1:aq+tINa0ULCZlJcUK2jaeGh6rRH4jJz3e2NrK47m0Ec= -20251107081830.sql h1:Bl9kniyLWeMqd3nrvgCgiUpdcJWp8qX1F41JAM1WbiE= +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= From e3b601f70385489265fbb5ed3c37562653ffa3cc Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Fri, 7 Nov 2025 16:17:16 +0700 Subject: [PATCH 107/329] infra, item remove parent_id, infra_id --- .../migrations/20251107091033.sql | 4 ++ .../migrations/20251107091209.sql | 2 + .../migrations/20251107091541.sql | 2 + cmd/main-migration/migrations/atlas.sum | 39 ++++++++++--------- internal/domain/main-entities/infra/dto.go | 12 +++--- internal/domain/main-entities/infra/entity.go | 10 ++--- internal/domain/main-entities/item/entity.go | 1 - .../use-case/main-use-case/infra/helper.go | 4 +- internal/use-case/main-use-case/infra/lib.go | 2 +- 9 files changed, 42 insertions(+), 34 deletions(-) create mode 100644 cmd/main-migration/migrations/20251107091033.sql create mode 100644 cmd/main-migration/migrations/20251107091209.sql create mode 100644 cmd/main-migration/migrations/20251107091541.sql diff --git a/cmd/main-migration/migrations/20251107091033.sql b/cmd/main-migration/migrations/20251107091033.sql new file mode 100644 index 00000000..dc0a8f60 --- /dev/null +++ b/cmd/main-migration/migrations/20251107091033.sql @@ -0,0 +1,4 @@ +-- Modify "Infra" table +ALTER TABLE "public"."Infra" ALTER COLUMN "Code" SET NOT NULL; +-- Modify "Item" table +ALTER TABLE "public"."Item" DROP COLUMN "Infra_Id"; diff --git a/cmd/main-migration/migrations/20251107091209.sql b/cmd/main-migration/migrations/20251107091209.sql new file mode 100644 index 00000000..d10ae684 --- /dev/null +++ b/cmd/main-migration/migrations/20251107091209.sql @@ -0,0 +1,2 @@ +-- Modify "Infra" table +ALTER TABLE "public"."Infra" DROP CONSTRAINT "fk_Infra_Childrens", DROP CONSTRAINT "fk_Infra_Item", DROP COLUMN "Parent_Id", ADD CONSTRAINT "fk_Infra_Childrens" FOREIGN KEY ("Parent_Code") REFERENCES "public"."Infra" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_Infra_Item" FOREIGN KEY ("Item_Code") REFERENCES "public"."Item" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251107091541.sql b/cmd/main-migration/migrations/20251107091541.sql new file mode 100644 index 00000000..a3445d0c --- /dev/null +++ b/cmd/main-migration/migrations/20251107091541.sql @@ -0,0 +1,2 @@ +-- Modify "Infra" table +ALTER TABLE "public"."Infra" DROP COLUMN "Item_Id"; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 153eb372..30f9fd3c 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:D7TdOht9cEt91EEPEvi05Frs3ZFC+Uz+y4K+bebB3BI= +h1:6umIsneejLUg0V9wUaB2HuCvEHD+2v/dwbxg+y23+wo= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,20 +75,23 @@ h1:D7TdOht9cEt91EEPEvi05Frs3ZFC+Uz+y4K+bebB3BI= 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= +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:jjpcAi0B/geEOKWmmR6+1UhWMhjstWhWQcz9lUWrtTY= +20251107064937.sql h1:1nPu0THBf+YquFIJSE4pc1dA7r3EydH92cpp26ozysw= +20251107071420.sql h1:Q+e+OqjdiuK/sghDQ5NxjU+u2zYl+vh/eRBlUz9Idhg= +20251107074318.sql h1:VbOWMw2rClEWgMnDSejXPqXkFoQ4odVsHn3/UAEiCYA= +20251107075050.sql h1:ZZaKJEWXIJ94/0/2Gzzz+HXjmebEs5eP8iUIot26/c8= +20251107080604.sql h1:aq+tINa0ULCZlJcUK2jaeGh6rRH4jJz3e2NrK47m0Ec= +20251107081830.sql h1:Bl9kniyLWeMqd3nrvgCgiUpdcJWp8qX1F41JAM1WbiE= +20251107091033.sql h1:ETTCaAHBT6wipXrEGXIepxLMdD2LNzprPAp99+jnW0w= +20251107091209.sql h1:BUI9JlTzZxCdVHsrRbOye7m47AJEvXNhCaCVv/HzILs= +20251107091541.sql h1:/tW2uXv/o0Q2E4lQzlYNgEftvDqjf3c2AQpZ83Vb6zc= diff --git a/internal/domain/main-entities/infra/dto.go b/internal/domain/main-entities/infra/dto.go index 28ff8d93..dfe271e5 100644 --- a/internal/domain/main-entities/infra/dto.go +++ b/internal/domain/main-entities/infra/dto.go @@ -13,7 +13,7 @@ type CreateDto struct { Name string `json:"name" validate:"maxLength=50"` InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code" validate:"maxLength=15"` Parent_Code *string `json:"parent_code"` - Item_Id *uint `json:"-"` + Item_Code *string `json:"-"` Unit_Code *string `json:"unit_code"` Specialist_Code *string `json:"specialist_code"` Subspecialist_Code *string `json:"subspecialist_code"` @@ -78,11 +78,11 @@ func (d Infra) ToResponse() ResponseDto { Name: d.Name, InfraGroup_Code: d.InfraGroup_Code, Parent_Code: d.Parent_Code, - Parent: d.Parent, - Childrens: d.Childrens, - Item_Code: d.Item_Code, - Item: d.Item, - Rooms: d.Rooms, + // Parent: d.Parent, + Childrens: d.Childrens, + Item_Code: d.Item_Code, + Item: d.Item, + Rooms: d.Rooms, } resp.SmallMain = d.SmallMain return resp diff --git a/internal/domain/main-entities/infra/entity.go b/internal/domain/main-entities/infra/entity.go index dfc19e3d..51cc8eaa 100644 --- a/internal/domain/main-entities/infra/entity.go +++ b/internal/domain/main-entities/infra/entity.go @@ -11,15 +11,13 @@ import ( type Infra struct { ecore.SmallMain // adjust this according to the needs - Code string `json:"code" gorm:"uniqueIndex;size:10"` + Code string `json:"code" gorm:"uniqueIndex;size:10;not null"` Name string `json:"name" gorm:"size:50"` InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code" gorm:"size:15"` - Parent_Id *uint16 `json:"parent_id"` Parent_Code *string `json:"parent_code" gorm:"size:10"` - Parent *Infra `json:"parent" gorm:"foreignKey:Parent_Id;references:Id"` - Childrens []Infra `json:"childrens" gorm:"foreignKey:Parent_Id"` // may need references to self - Item_Id *uint `json:"item_id"` + Parent *Infra `json:"parent" gorm:"foreignKey:Parent_Code;references:Code"` + Childrens []Infra `json:"childrens" gorm:"foreignKey:Parent_Code;references:Code"` Item_Code *string `json:"item_code" gorm:"size:50"` - Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` + Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Code;references:Code"` Rooms []erb.Basic `json:"rooms" gorm:"foreignKey:Infra_Code;references:Code"` } diff --git a/internal/domain/main-entities/item/entity.go b/internal/domain/main-entities/item/entity.go index 406c57e6..fc721713 100644 --- a/internal/domain/main-entities/item/entity.go +++ b/internal/domain/main-entities/item/entity.go @@ -14,7 +14,6 @@ type Item struct { ItemGroup_Code ero.ItemGroupCode `json:"itemGroup_code" gorm:"size:15"` Uom_Code *string `json:"uom_code" gorm:"size:10"` Uom *eu.Uom `json:"uom,omitempty" gorm:"foreignKey:Uom_Code;references:Code"` - Infra_Id *uint16 `json:"infra_id"` Infra_Code *string `json:"infra_code" gorm:"size:10"` Stock *int `json:"stock"` } diff --git a/internal/use-case/main-use-case/infra/helper.go b/internal/use-case/main-use-case/infra/helper.go index 2e6dc383..81de5389 100644 --- a/internal/use-case/main-use-case/infra/helper.go +++ b/internal/use-case/main-use-case/infra/helper.go @@ -30,7 +30,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Infra) { data.Name = inputSrc.Name data.InfraGroup_Code = inputSrc.InfraGroup_Code data.Parent_Code = inputSrc.Parent_Code - data.Item_Id = inputSrc.Item_Id + data.Item_Code = inputSrc.Item_Code } func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { @@ -49,7 +49,7 @@ func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { return err } - input.Item_Id = &item.Id + input.Item_Code = &item.Code return nil } diff --git a/internal/use-case/main-use-case/infra/lib.go b/internal/use-case/main-use-case/infra/lib.go index 67062b31..5e0592c3 100644 --- a/internal/use-case/main-use-case/infra/lib.go +++ b/internal/use-case/main-use-case/infra/lib.go @@ -126,7 +126,7 @@ func UpdateData(input e.UpdateDto, data *e.Infra, event *pl.Event, dbx ...*gorm. } else { tx = dg.I } - data.Parent = nil + // data.Parent = nil data.Childrens = nil data.Item = nil data.Rooms = nil From 8d9fe70d41002560da3157da26c06cb5de335aec Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 7 Nov 2025 16:21:03 +0700 Subject: [PATCH 108/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 42 ++++++++++++------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 30f9fd3c..0da32e52 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:6umIsneejLUg0V9wUaB2HuCvEHD+2v/dwbxg+y23+wo= +h1:69CxJYTc7MIeFR2nLQwjoba/TUnw7lIzVApYkI34yss= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,23 +75,23 @@ h1:6umIsneejLUg0V9wUaB2HuCvEHD+2v/dwbxg+y23+wo= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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:jjpcAi0B/geEOKWmmR6+1UhWMhjstWhWQcz9lUWrtTY= -20251107064937.sql h1:1nPu0THBf+YquFIJSE4pc1dA7r3EydH92cpp26ozysw= -20251107071420.sql h1:Q+e+OqjdiuK/sghDQ5NxjU+u2zYl+vh/eRBlUz9Idhg= -20251107074318.sql h1:VbOWMw2rClEWgMnDSejXPqXkFoQ4odVsHn3/UAEiCYA= -20251107075050.sql h1:ZZaKJEWXIJ94/0/2Gzzz+HXjmebEs5eP8iUIot26/c8= -20251107080604.sql h1:aq+tINa0ULCZlJcUK2jaeGh6rRH4jJz3e2NrK47m0Ec= -20251107081830.sql h1:Bl9kniyLWeMqd3nrvgCgiUpdcJWp8qX1F41JAM1WbiE= -20251107091033.sql h1:ETTCaAHBT6wipXrEGXIepxLMdD2LNzprPAp99+jnW0w= -20251107091209.sql h1:BUI9JlTzZxCdVHsrRbOye7m47AJEvXNhCaCVv/HzILs= -20251107091541.sql h1:/tW2uXv/o0Q2E4lQzlYNgEftvDqjf3c2AQpZ83Vb6zc= +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= From fc7e74b1c656c9b559d1d193ab20d501f9b59295 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Sat, 8 Nov 2025 06:07:14 +0700 Subject: [PATCH 109/329] feat/sso-auth: wip --- .../main-handler/authentication/handler.go | 28 +- .../main-use-case/authentication/case.go | 288 +++++++++++------- .../main-use-case/authentication/helper.go | 122 ++++++++ 3 files changed, 334 insertions(+), 104 deletions(-) diff --git a/internal/interface/main-handler/authentication/handler.go b/internal/interface/main-handler/authentication/handler.go index 709f33a3..fc36dc52 100644 --- a/internal/interface/main-handler/authentication/handler.go +++ b/internal/interface/main-handler/authentication/handler.go @@ -6,11 +6,13 @@ import ( d "github.com/karincake/dodol" rw "github.com/karincake/risoles" + sp "github.com/karincake/semprit" + sr "github.com/karincake/serabi" m "simrs-vx/internal/domain/main-entities/user" - s "simrs-vx/internal/use-case/main-use-case/authentication" - + mf "simrs-vx/internal/domain/main-entities/user-fes" pa "simrs-vx/internal/lib/auth" + s "simrs-vx/internal/use-case/main-use-case/authentication" ) func Login(w http.ResponseWriter, r *http.Request) { @@ -50,3 +52,25 @@ func GuardMW(next http.Handler) http.Handler { next.ServeHTTP(w, r.WithContext(ctx)) }) } + +func LoginFes(w http.ResponseWriter, r *http.Request) { + var input mf.LoginDto + err := sp.IOReaderJson(input, r.Body) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil) + } + + input.AuthPartner_Code = r.Header.Get("X-AuthPartner-Code") + input.AuthPartner_SecretKey = r.Header.Get("X-AuthPartner-SecretKey") + if err = (sr.Validate(input)); err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil) + } + + // input.Position = Position + res, err := s.GenTokenFes(input) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil) + } else { + rw.DataResponse(w, res, err) + } +} diff --git a/internal/use-case/main-use-case/authentication/case.go b/internal/use-case/main-use-case/authentication/case.go index 6cf94142..d523ae33 100644 --- a/internal/use-case/main-use-case/authentication/case.go +++ b/internal/use-case/main-use-case/authentication/case.go @@ -19,14 +19,9 @@ import ( pl "simrs-vx/pkg/logger" p "simrs-vx/pkg/password" - ed "simrs-vx/internal/domain/main-entities/doctor" - ee "simrs-vx/internal/domain/main-entities/employee" - "simrs-vx/internal/domain/main-entities/intern" - em "simrs-vx/internal/domain/main-entities/midwife" - en "simrs-vx/internal/domain/main-entities/nurse" eu "simrs-vx/internal/domain/main-entities/user" + euf "simrs-vx/internal/domain/main-entities/user-fes" erc "simrs-vx/internal/domain/references/common" - erg "simrs-vx/internal/domain/references/organization" ) const source = "authentication" @@ -113,113 +108,116 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { } // extra - role := []string{} - switch user.ContractPosition_Code { - case erg.CSCEmp: - // employee - employee := ee.Employee{} - dg.I.Where("\"User_Id\" = ?", user.Id).First(&employee) - if employee.Id == 0 { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noEmployee", Message: pl.GenMessage("auth-noEmployee")}} - } - atClaims["employee_id"] = employee.Id - outputData["employee_id"] = employee.Id - role = append(role, "emp-"+string(*employee.Position_Code)) + // role := []string{} + // switch user.ContractPosition_Code { + // case erg.CSCEmp: + // // employee + // employee := ee.Employee{} + // dg.I.Where("\"User_Id\" = ?", user.Id).First(&employee) + // if employee.Id == 0 { + // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noEmployee", Message: pl.GenMessage("auth-noEmployee")}} + // } + // atClaims["employee_id"] = employee.Id + // outputData["employee_id"] = employee.Id + // role = append(role, "emp-"+string(*employee.Position_Code)) - //if employee.Division_Code != nil { - // atClaims["employee_division_code"] = employee.Division_Code - // outputData["employee_division_code"] = employee.Division_Code - //} + // //if employee.Division_Code != nil { + // // atClaims["employee_division_code"] = employee.Division_Code + // // outputData["employee_division_code"] = employee.Division_Code + // //} - // employee position - if employee.Id > 0 && employee.Position_Code != nil { - atClaims["employee_position_code"] = *employee.Position_Code - switch *employee.Position_Code { - case erg.EPCDoc: - doctor := ed.Doctor{} - dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&doctor) - if doctor.Id == 0 { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noDoctor", Message: pl.GenMessage("auth-noDoctor")}} - } - atClaims["doctor_code"] = doctor.Code - outputData["doctor_code"] = doctor.Code + // // employee position + // if employee.Id > 0 && employee.Position_Code != nil { + // atClaims["employee_position_code"] = *employee.Position_Code + // switch *employee.Position_Code { + // case erg.EPCDoc: + // doctor := ed.Doctor{} + // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&doctor) + // if doctor.Id == 0 { + // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noDoctor", Message: pl.GenMessage("auth-noDoctor")}} + // } + // atClaims["doctor_code"] = doctor.Code + // outputData["doctor_code"] = doctor.Code - // specialist - if doctor.Specialist_Code != nil { - atClaims["specialist_code"] = doctor.Specialist_Code - outputData["specialist_code"] = doctor.Specialist_Code - } - if doctor.Subspecialist_Code != nil { - atClaims["subspecialist_code"] = doctor.Subspecialist_Code - outputData["subspecialist_code"] = doctor.Subspecialist_Code - } - case erg.EPCNur: - empData := en.Nurse{} - dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) - if empData.Id == 0 { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: pl.GenMessage("auth-noNurse")}} - } - atClaims["nurse_code"] = empData.Code - outputData["nurse_code"] = empData.Code - case erg.EPCMwi: - empData := em.Midwife{} - dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) - if empData.Id == 0 { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noMidwife", Message: pl.GenMessage("auth-noMidwife")}} - } - atClaims["midwife_code"] = empData.Code - outputData["midwife_code"] = empData.Code - } + // // specialist + // if doctor.Specialist_Code != nil { + // atClaims["specialist_code"] = doctor.Specialist_Code + // outputData["specialist_code"] = doctor.Specialist_Code + // } + // if doctor.Subspecialist_Code != nil { + // atClaims["subspecialist_code"] = doctor.Subspecialist_Code + // outputData["subspecialist_code"] = doctor.Subspecialist_Code + // } + // case erg.EPCNur: + // empData := en.Nurse{} + // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + // if empData.Id == 0 { + // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: pl.GenMessage("auth-noNurse")}} + // } + // atClaims["nurse_code"] = empData.Code + // outputData["nurse_code"] = empData.Code + // case erg.EPCMwi: + // empData := em.Midwife{} + // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + // if empData.Id == 0 { + // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noMidwife", Message: pl.GenMessage("auth-noMidwife")}} + // } + // atClaims["midwife_code"] = empData.Code + // outputData["midwife_code"] = empData.Code + // } - errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: pl.GenMessage("auth-getData-failed")}} + // errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: pl.GenMessage("auth-getData-failed")}} - // division position - divisionPositions, err := getDivisionPosition(employee.Id, &event) - if err != nil { - return nil, errorGetPosition - } + // // division position + // divisionPositions, err := getDivisionPosition(employee.Id, &event) + // if err != nil { + // return nil, errorGetPosition + // } - // installation position - installationPositions, err := getInstallationPosition(employee.Id, &event) - if err != nil { - return nil, errorGetPosition - } + // // installation position + // installationPositions, err := getInstallationPosition(employee.Id, &event) + // if err != nil { + // return nil, errorGetPosition + // } - // unit position - unitPositions, err := getUnitPosition(employee.Id, &event) - if err != nil { - return nil, errorGetPosition - } + // // unit position + // unitPositions, err := getUnitPosition(employee.Id, &event) + // if err != nil { + // return nil, errorGetPosition + // } - // specialist position - specialistPositions, err := getSpecialistPosition(employee.Id, &event) - if err != nil { - return nil, errorGetPosition - } + // // specialist position + // specialistPositions, err := getSpecialistPosition(employee.Id, &event) + // if err != nil { + // return nil, errorGetPosition + // } - // subspecialist position - subspecialistPositions, err := getSubspecialistPosition(employee.Id, &event) - if err != nil { - return nil, errorGetPosition - } + // // subspecialist position + // subspecialistPositions, err := getSubspecialistPosition(employee.Id, &event) + // if err != nil { + // return nil, errorGetPosition + // } - role = append(role, divisionPositions...) - role = append(role, installationPositions...) - role = append(role, unitPositions...) - role = append(role, specialistPositions...) - role = append(role, subspecialistPositions...) - // atClaims["division_positions"] = divsionPositions - // outputData["division_positions"] = divsionPositions - } - case erg.CSCInt: - intern := intern.Intern{} - dg.I.Where("\"User_Id\" = ?", user.Id).First(&intern) - role = append(role, "int-"+string(*intern.Position_Code)) - case erg.CSCSys: - role = append(role, "system") + // role = append(role, divisionPositions...) + // role = append(role, installationPositions...) + // role = append(role, unitPositions...) + // role = append(role, specialistPositions...) + // role = append(role, subspecialistPositions...) + // // atClaims["division_positions"] = divsionPositions + // // outputData["division_positions"] = divsionPositions + // } + // case erg.CSCInt: + // intern := intern.Intern{} + // dg.I.Where("\"User_Id\" = ?", user.Id).First(&intern) + // role = append(role, "int-"+string(*intern.Position_Code)) + // case erg.CSCSys: + // role = append(role, "system") + // } + // atClaims["roles"] = role + // outputData["roles"] = role + if err := populateRoles(user, atClaims, outputData, event); err != nil { + return nil, err } - atClaims["roles"] = role - outputData["roles"] = role // Generate jwt at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims) @@ -329,3 +327,89 @@ func ExtractToken(r *http.Request, tokenType TokenType) (data *pa.AuthInfo, err func GetConfig() { a.ParseCfg(&authCfg) } + +func GenTokenFes(input euf.LoginDto) (*d.Data, error) { + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Get User Fes + userFes := &euf.UserFes{Name: input.Name, AuthPartner_Code: input.AuthPartner_Code} + if errCode := getAndCheck(userFes, userFes); errCode != "" { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: errCode, Message: pl.GenMessage(errCode)}} + } + if userFes.AuthPartner.SecretKey != input.AuthPartner_SecretKey { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-secretKey-invalid", Message: pl.GenMessage("auth-secretKey-invalid")}} + } + + user := &eu.User{Name: userFes.User_Name} + if errCode := getAndCheck(user, user); errCode != "" { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: errCode, Message: pl.GenMessage(errCode)}} + } + + // Access token prep + id, err := uuid.NewRandom() + if err != nil { + panic(fmt.Sprintf(l.I.Msg("uuid-gen-fail"), err)) + } + if input.Duration == 0 { + input.Duration = 24 * 60 + } + duration := time.Minute * time.Duration(input.Duration) + aUuid := id.String() + atExpires := time.Now().Add(duration).Unix() + atSecretKey := authCfg.AtSecretKey + + // Create Claim + atClaims := jwt.MapClaims{} + atClaims["user_id"] = user.Id + atClaims["user_name"] = user.Name + atClaims["user_contractPosition_code"] = user.ContractPosition_Code + atClaims["uuid"] = aUuid + atClaims["exp"] = atExpires + + // Create output + outputData := d.II{ + "user_id": strconv.Itoa(int(user.Id)), + "user_name": user.Name, + "user_contractPosition_code": user.ContractPosition_Code, + } + + // extra + if err := populateRoles(user, atClaims, outputData, event); err != nil { + return nil, err + } + + // Generate jwt + at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims) + ats, err := at.SignedString([]byte(atSecretKey)) + if err != nil { + return nil, d.FieldErrors{"user": d.FieldError{Code: "token-sign-err", Message: pl.GenMessage("token-sign-err")}} + } + outputData["accessToken"] = ats + + // Save to redis + now := time.Now() + atx := time.Unix(atExpires, 0) //converting Unix to UTC(to Time object) + err = ms.I.Set(aUuid, strconv.Itoa(int(user.Id)), atx.Sub(now)).Err() + if err != nil { + panic(fmt.Sprintf(l.I.Msg("redis-store-fail"), err.Error())) + } + + tn := time.Now() + user.LoginAttemptCount = 0 + user.LastSuccessLogin = &tn + user.LastAllowdLogin = &tn + dg.I.Save(&user) + + // Current data + return &d.Data{ + Meta: d.IS{ + "source": "authentication", + "structure": "single-data", + "status": "verified", + }, + Data: outputData, + }, nil +} diff --git a/internal/use-case/main-use-case/authentication/helper.go b/internal/use-case/main-use-case/authentication/helper.go index a919cfe9..0da9f943 100644 --- a/internal/use-case/main-use-case/authentication/helper.go +++ b/internal/use-case/main-use-case/authentication/helper.go @@ -3,13 +3,23 @@ package authentication import ( dg "github.com/karincake/apem/db-gorm-pg" + "github.com/golang-jwt/jwt" + d "github.com/karincake/dodol" + pl "simrs-vx/pkg/logger" 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" eip "simrs-vx/internal/domain/main-entities/installation-position" + "simrs-vx/internal/domain/main-entities/intern" + em "simrs-vx/internal/domain/main-entities/midwife" + en "simrs-vx/internal/domain/main-entities/nurse" esp "simrs-vx/internal/domain/main-entities/specialist-position" 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" @@ -162,3 +172,115 @@ func checkUntPtrClaims(claim map[string]interface{}, key string) *uint { } return nil } + +func populateRoles(user *eu.User, atClaims jwt.MapClaims, outputData d.II, event pl.Event) error { + roles := []string{} + switch user.ContractPosition_Code { + case erg.CSCEmp: + // employee + employee := ee.Employee{} + dg.I.Where("\"User_Id\" = ?", user.Id).First(&employee) + if employee.Id == 0 { + return d.FieldErrors{"authentication": d.FieldError{Code: "auth-noEmployee", Message: pl.GenMessage("auth-noEmployee")}} + } + atClaims["employee_id"] = employee.Id + outputData["employee_id"] = employee.Id + roles = append(roles, "emp-"+string(*employee.Position_Code)) + + //if employee.Division_Code != nil { + // atClaims["employee_division_code"] = employee.Division_Code + // outputData["employee_division_code"] = employee.Division_Code + //} + + // employee position + if employee.Id > 0 && employee.Position_Code != nil { + atClaims["employee_position_code"] = *employee.Position_Code + switch *employee.Position_Code { + case erg.EPCDoc: + doctor := ed.Doctor{} + dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&doctor) + if doctor.Id == 0 { + return d.FieldErrors{"authentication": d.FieldError{Code: "auth-noDoctor", Message: pl.GenMessage("auth-noDoctor")}} + } + atClaims["doctor_code"] = doctor.Code + outputData["doctor_code"] = doctor.Code + + // specialist + if doctor.Specialist_Code != nil { + atClaims["specialist_code"] = doctor.Specialist_Code + outputData["specialist_code"] = doctor.Specialist_Code + } + if doctor.Subspecialist_Code != nil { + atClaims["subspecialist_code"] = doctor.Subspecialist_Code + outputData["subspecialist_code"] = doctor.Subspecialist_Code + } + case erg.EPCNur: + empData := en.Nurse{} + dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + if empData.Id == 0 { + return d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: pl.GenMessage("auth-noNurse")}} + } + atClaims["nurse_code"] = empData.Code + outputData["nurse_code"] = empData.Code + case erg.EPCMwi: + empData := em.Midwife{} + dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + if empData.Id == 0 { + return d.FieldErrors{"authentication": d.FieldError{Code: "auth-noMidwife", Message: pl.GenMessage("auth-noMidwife")}} + } + atClaims["midwife_code"] = empData.Code + outputData["midwife_code"] = empData.Code + } + + errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: pl.GenMessage("auth-getData-failed")}} + + // division position + divisionPositions, err := getDivisionPosition(employee.Id, &event) + if err != nil { + return errorGetPosition + } + + // installation position + installationPositions, err := getInstallationPosition(employee.Id, &event) + if err != nil { + return errorGetPosition + } + + // unit position + unitPositions, err := getUnitPosition(employee.Id, &event) + if err != nil { + return errorGetPosition + } + + // specialist position + specialistPositions, err := getSpecialistPosition(employee.Id, &event) + if err != nil { + return errorGetPosition + } + + // subspecialist position + subspecialistPositions, err := getSubspecialistPosition(employee.Id, &event) + if err != nil { + return errorGetPosition + } + + roles = append(roles, divisionPositions...) + roles = append(roles, installationPositions...) + roles = append(roles, unitPositions...) + roles = append(roles, specialistPositions...) + roles = append(roles, subspecialistPositions...) + // atClaims["division_positions"] = divsionPositions + // outputData["division_positions"] = divsionPositions + } + case erg.CSCInt: + intern := intern.Intern{} + dg.I.Where("\"User_Id\" = ?", user.Id).First(&intern) + roles = append(roles, "int-"+string(*intern.Position_Code)) + case erg.CSCSys: + roles = append(roles, "system") + } + + atClaims["roles"] = roles + outputData["roles"] = roles + return nil +} From fcbec59a1767772c331e6f4b186e2301dd0e1760 Mon Sep 17 00:00:00 2001 From: vanilia Date: Sun, 9 Nov 2025 22:25:55 +0700 Subject: [PATCH 110/329] add switch poly and spprove --- .../domain/main-entities/encounter/dto.go | 47 +- .../main-handler/encounter/handler.go | 54 +- .../encounter/request-validation.go | 88 +-- .../interface/main-handler/main-handler.go | 24 +- .../use-case/main-use-case/encounter/case.go | 398 +++++++------ .../main-use-case/encounter/helper.go | 529 ++++++++++++------ .../use-case/main-use-case/encounter/lib.go | 101 +++- .../internal-reference/helper.go | 4 + 8 files changed, 836 insertions(+), 409 deletions(-) diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index 6782b18c..966a53d3 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -1,6 +1,13 @@ package encounter import ( + eam "simrs-vx/internal/domain/main-entities/ambulatory" + edc "simrs-vx/internal/domain/main-entities/death-cause" + eem "simrs-vx/internal/domain/main-entities/emergency" + eip "simrs-vx/internal/domain/main-entities/inpatient" + eir "simrs-vx/internal/domain/main-entities/internal-reference" + er "simrs-vx/internal/domain/main-entities/rehab/base" + // std "time" @@ -19,7 +26,6 @@ import ( ea "simrs-vx/internal/domain/main-entities/appointment" ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/employee" - eir "simrs-vx/internal/domain/main-entities/internal-reference" ep "simrs-vx/internal/domain/main-entities/patient" es "simrs-vx/internal/domain/main-entities/specialist" ess "simrs-vx/internal/domain/main-entities/subspecialist" @@ -48,8 +54,10 @@ type CreateDto struct { Appointment_Id *uint `json:"appointment_id"` RefTypeCode ere.RefTypeCode `json:"refTypeCode"` NewStatus bool `json:"newStatus"` - VisitMode_Code *ere.VisitModeCode `json:"visitMode_code"` // if subClass_Code is rehab - AllocatedVisitCount *int `json:"allocatedVisitCount"` // if subClass_Code is rehab and VisitMode_Code is "adm" + + Id uint `json:"-"` + RecentEncounterAdm *Encounter `json:"-"` // if subClass_Code is rehab + VisitMode_Code ere.VisitModeCode `json:"-"` // if subClass_Code is rehab pa.AuthInfo } @@ -114,7 +122,6 @@ type DischargeDto struct { AdmDischargeEducation *string `json:"admDischargeEducation"` DischargeReason *string `json:"dischargeReason"` DeathCause *string `json:"deathCause"` - InternalReferences *[]eir.CreateDto `json:"internalReferences,omitempty"` } type CheckinDto struct { @@ -125,6 +132,17 @@ type CheckinDto struct { FinishedAt *time.Time `json:"finishedAt"` } +type SwitchUnitDto struct { + Id uint `json:"id"` + PolySwitchCode *ere.PolySwitchCode `json:"polySwitchCode"` + InternalReferences *[]eir.CreateDto `json:"internalReferences" validate:"required"` +} + +type ApproveUnitDto struct { + Id uint `json:"id"` + InternalReferences_Id uint16 `json:"internalReferences_id" validate:"required"` +} + type ResponseDto struct { ecore.Main Patient_Id *uint `json:"patient_id"` @@ -159,6 +177,17 @@ type ResponseDto struct { DischargeReason *string `json:"dischargeReason"` Status_Code erc.DataStatusCode `json:"status_code"` VclaimSep *evs.VclaimSep `json:"vclaimSep,omitempty"` + StartedAt *time.Time `json:"startedAt"` + FinishedAt *time.Time `json:"finishedAt"` + Discharge_Date *time.Time `json:"discharge_date"` + InternalReferences *[]eir.InternalReference `json:"internalReferences,omitempty"` + DeathCause *edc.DeathCause `json:"deathCause,omitempty"` + NewStatus bool `json:"newStatus"` + Ambulatory *eam.Ambulatory `json:"ambulatory,omitempty"` + Emergency *eem.Emergency `json:"emergency,omitempty"` + Inpatient *eip.Inpatient `json:"inpatient,omitempty"` + Rehab *er.Basic `json:"rehab,omitempty"` + RehabChildren *[]er.Basic `json:"rehabChildren,omitempty"` } func (d Encounter) ToResponse() ResponseDto { @@ -195,6 +224,16 @@ func (d Encounter) ToResponse() ResponseDto { DischargeReason: d.DischargeReason, Status_Code: d.Status_Code, VclaimSep: d.VclaimSep, + StartedAt: d.StartedAt, + FinishedAt: d.FinishedAt, + Discharge_Date: d.Discharge_Date, + InternalReferences: d.InternalReferences, + DeathCause: d.DeathCause, + NewStatus: d.NewStatus, + Emergency: d.Emergency, + Inpatient: d.Inpatient, + Rehab: d.Rehab, + RehabChildren: d.RehabChildren, } resp.Main = d.Main return resp diff --git a/internal/interface/main-handler/encounter/handler.go b/internal/interface/main-handler/encounter/handler.go index b66abe76..22d1d8cf 100644 --- a/internal/interface/main-handler/encounter/handler.go +++ b/internal/interface/main-handler/encounter/handler.go @@ -3,18 +3,17 @@ package encounter import ( "net/http" + pa "simrs-vx/internal/lib/auth" + + d "github.com/karincake/dodol" rw "github.com/karincake/risoles" sf "github.com/karincake/semprit" // ua "github.com/karincake/tumpeng/auth/svc" + erc "simrs-vx/internal/domain/references/common" e "simrs-vx/internal/domain/main-entities/encounter" u "simrs-vx/internal/use-case/main-use-case/encounter" - - erc "simrs-vx/internal/domain/references/common" - pa "simrs-vx/internal/lib/auth" - - d "github.com/karincake/dodol" ) type myBase struct{} @@ -31,7 +30,13 @@ func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - if valid := validateRequestCreate(w, dto); !valid { + + // validate SubClass + if err := verifyClassCode(dto); err != nil { + rw.DataResponse(w, nil, d.FieldError{ + Code: dataValidationFail, + Message: err.Error(), + }) return } @@ -192,3 +197,40 @@ func (obj myBase) Skip(w http.ResponseWriter, r *http.Request) { res, err := u.UpdateStatusCode(dto) rw.DataResponse(w, res, err) } + +func (obj myBase) RequestSwitchUnit(w http.ResponseWriter, r *http.Request) { + dto := e.SwitchUnitDto{} + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + + // validate request body + if valid := validateRequestSwitchUnit(w, dto); !valid { + return + } + + dto.Id = uint(id) + res, err := u.RequestSwitchUnit(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) ApproveSwitchUnit(w http.ResponseWriter, r *http.Request) { + dto := e.ApproveUnitDto{} + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + + dto.Id = uint(id) + res, err := u.ApproveSwitchUnit(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/encounter/request-validation.go b/internal/interface/main-handler/encounter/request-validation.go index d8e0619a..be370074 100644 --- a/internal/interface/main-handler/encounter/request-validation.go +++ b/internal/interface/main-handler/encounter/request-validation.go @@ -1,9 +1,14 @@ package encounter import ( + "errors" + "fmt" "net/http" e "simrs-vx/internal/domain/main-entities/encounter" ere "simrs-vx/internal/domain/references/encounter" + ua "simrs-vx/internal/use-case/main-use-case/ambulatory" + ue "simrs-vx/internal/use-case/main-use-case/emergency" + ui "simrs-vx/internal/use-case/main-use-case/inpatient" d "github.com/karincake/dodol" rw "github.com/karincake/risoles" @@ -11,6 +16,25 @@ import ( const dataValidationFail = "data-validation-fail" +func verifyClassCode(input e.CreateDto) (err error) { + switch input.Class_Code { + case ere.ECAmbulatory: + _, err = ua.CheckClassCode(input.SubClass_Code) + case ere.ECEmergency: + _, err = ue.CheckClassCode(input.SubClass_Code) + case ere.ECInpatient: + _, err = ui.CheckClassCode(input.SubClass_Code) + default: + return errors.New("invalid encounter class code") + } + + if err != nil { + return + } + + return nil +} + func validateRequestCheckout(w http.ResponseWriter, i e.DischargeDto) (valid bool) { if *i.Discharge_Method_Code == ere.DMCDeath && i.DeathCause == nil { rw.DataResponse(w, nil, d.FieldError{ @@ -19,34 +43,6 @@ func validateRequestCheckout(w http.ResponseWriter, i e.DischargeDto) (valid boo }) return } - - //case ere.DMCConsulPoly, ere.DMCConsulExecutive: - // if i.InternalReferences == nil { - // rw.DataResponse(w, nil, d.FieldError{ - // Code: dataValidationFail, - // Message: fmt.Sprintf("internalReferences required if discharge_method_code is %s", *i.Discharge_Method_Code), - // }) - // return - // } - // - // for _, v := range *i.InternalReferences { - // if v.Unit_Id == nil { - // rw.DataResponse(w, nil, d.FieldError{ - // Code: dataValidationFail, - // Message: "internalReferences.unit_id required", - // }) - // return - // } - // - // if v.Doctor_Id == nil { - // rw.DataResponse(w, nil, d.FieldError{ - // Code: dataValidationFail, - // Message: "internalReferences.doctor_id required", - // }) - // return - // } - // } - return true } @@ -62,18 +58,30 @@ func validateRequestCheckIn(w http.ResponseWriter, i e.CheckinDto) (valid bool) return true } -func validateRequestCreate(w http.ResponseWriter, i e.CreateDto) (valid bool) { - switch { - case i.Class_Code == ere.ECAmbulatory: - // field allocatedVisitCount required if ambulatory visitMode_Code is adm - if ere.AmbulatoryClassCode(*i.SubClass_Code) == ere.ACCRehab && *i.VisitMode_Code == ere.VMCAdm { - if *i.AllocatedVisitCount == 0 { - rw.DataResponse(w, nil, d.FieldError{ - Code: dataValidationFail, - Message: "allocatedVisitCount required", - }) - return - } +func validateRequestSwitchUnit(w http.ResponseWriter, i e.SwitchUnitDto) (valid bool) { + if i.InternalReferences == nil { + rw.DataResponse(w, nil, d.FieldError{ + Code: dataValidationFail, + Message: fmt.Sprintf("internalReferences required"), + }) + return + } + + for _, v := range *i.InternalReferences { + if v.Unit_Id == nil { + rw.DataResponse(w, nil, d.FieldError{ + Code: dataValidationFail, + Message: "internalReferences.unit_id required", + }) + return + } + + if v.Doctor_Id == nil { + rw.DataResponse(w, nil, d.FieldError{ + Code: dataValidationFail, + Message: "internalReferences.doctor_id required", + }) + return } } diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 1c703b64..ee33d4a5 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -144,17 +144,19 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/material-order-item", materialorderitem.O) hk.GroupRoutes("/v1/encounter", r, auth.GuardMW, hk.MapHandlerFunc{ - "GET /": encounter.O.GetList, - "GET /{id}": encounter.O.GetDetail, - "POST /": encounter.O.Create, - "PATCH /{id}": encounter.O.Update, - "DELETE /{id}": encounter.O.Delete, - "PATCH /{id}/check-out": encounter.O.CheckOut, - "PATCH /{id}/check-in": encounter.O.CheckIn, - "PATCH /{id}/proccess": encounter.O.Process, - "PATCH /{id}/cancel": encounter.O.Cancel, - "PATCH /{id}/reject": encounter.O.Reject, - "PATCH /{id}/skip": encounter.O.Skip, + "GET /": encounter.O.GetList, + "GET /{id}": encounter.O.GetDetail, + "POST /": encounter.O.Create, + "PATCH /{id}": encounter.O.Update, + "DELETE /{id}": encounter.O.Delete, + "PATCH /{id}/check-out": encounter.O.CheckOut, + "PATCH /{id}/check-in": encounter.O.CheckIn, + "PATCH /{id}/proccess": encounter.O.Process, + "PATCH /{id}/cancel": encounter.O.Cancel, + "PATCH /{id}/reject": encounter.O.Reject, + "PATCH /{id}/skip": encounter.O.Skip, + "PATCH /{id}/req-switch-unit": encounter.O.RequestSwitchUnit, + "PATCH /{id}/approve-switch-unit": encounter.O.ApproveSwitchUnit, }) hk.GroupRoutes("/v1/mcu-order", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": mcuorder.O.GetList, diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index ec2ea231..9798a28b 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -2,7 +2,7 @@ package encounter import ( "errors" - authhelper "simrs-vx/internal/lib/auth" + "fmt" "strconv" "time" @@ -17,28 +17,18 @@ import ( ere "simrs-vx/internal/domain/references/encounter" eaeh "simrs-vx/internal/domain/main-entities/adm-employee-hist" - ea "simrs-vx/internal/domain/main-entities/ambulatory" - ec "simrs-vx/internal/domain/main-entities/chemo" edc "simrs-vx/internal/domain/main-entities/death-cause" - ed "simrs-vx/internal/domain/main-entities/doctor" - ee "simrs-vx/internal/domain/main-entities/emergency" eem "simrs-vx/internal/domain/main-entities/employee" e "simrs-vx/internal/domain/main-entities/encounter" - ei "simrs-vx/internal/domain/main-entities/inpatient" - er "simrs-vx/internal/domain/main-entities/rehab" + eir "simrs-vx/internal/domain/main-entities/internal-reference" erdh "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" es "simrs-vx/internal/domain/main-entities/soapi" uaeh "simrs-vx/internal/use-case/main-use-case/adm-employee-hist" - ua "simrs-vx/internal/use-case/main-use-case/ambulatory" - uc "simrs-vx/internal/use-case/main-use-case/chemo" udc "simrs-vx/internal/use-case/main-use-case/death-cause" - ud "simrs-vx/internal/use-case/main-use-case/doctor" - ue "simrs-vx/internal/use-case/main-use-case/emergency" uem "simrs-vx/internal/use-case/main-use-case/employee" - ui "simrs-vx/internal/use-case/main-use-case/inpatient" - ur "simrs-vx/internal/use-case/main-use-case/rehab" - us "simrs-vx/internal/use-case/main-use-case/soapi" + uir "simrs-vx/internal/use-case/main-use-case/internal-reference" + urdh "simrs-vx/internal/use-case/main-use-case/responsible-doctor-hist" ) const source = "encounter" @@ -46,8 +36,11 @@ const source = "encounter" var now = time.Now() func Create(input e.CreateDto) (*d.Data, error) { - data := e.Encounter{} - createSoapi := []es.CreateDto{} + var ( + data e.Encounter + recentSoapiDataforCopy []es.CreateDto + err error + ) event := pl.Event{ Feature: "Create", @@ -57,51 +50,36 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - // validate SubClass - var subCode interface{} - subCode, err := verifyClassCode(input) - if err != nil { - return nil, err - } - - // verify whether the allocated visit count has not exceeded the limit - if input.Class_Code == ere.ECAmbulatory && subCode.(ere.AmbulatoryClassCode) == ere.ACCRehab && - *input.VisitMode_Code == ere.VMCSeries { - - dataEncounter, valid, err := verifyAllocatedVisitCount(input, &event) + // validate rehab bpjs + if input.RefTypeCode == ere.RTCBpjs && input.Class_Code == ere.ECAmbulatory && ere.AmbulatoryClassCode(*input.SubClass_Code) == ere.ACCRehab { + // identify visit mode from latest rehab data + recentRehabData, err := identifyVisitModeCode(input, &event) if err != nil { return nil, err } - if !valid { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "visit-limit-exceeded", - Detail: "Encounter has exceeded the allowed number of visits", - Raw: errors.New("visit count exceeds allowed limit"), + if recentRehabData != nil { + // determine VisitModeCode + input.VisitMode_Code, *input.RecentEncounterAdm, err = determineVisitMode(recentRehabData, input, &event) + if err != nil { + return nil, err } - return nil, pl.SetLogError(&event, input) + } else { + input.VisitMode_Code = ere.VMCAdm } - // get data soapi - createSoapi, err = getSoapiEncounterAdm(dataEncounter, &event) - if err != nil { - return nil, err + // if visitMode_Code is series, then get data soapi for copy + if input.VisitMode_Code == ere.VMCSeries { + // get data soapi + recentSoapiDataforCopy, err = getSoapiEncounterAdm(*input.RecentEncounterAdm, &event) + if err != nil { + return nil, err + } } } // check if patient is new in the hospital - dataPatient, err := ReadList(e.ReadListDto{ - FilterDto: e.FilterDto{Patient_Id: input.Patient_Id}, - AuthInfo: authhelper.AuthInfo{User_Id: input.User_Id}}) - if err != nil { - return nil, err - } - if list, ok := dataPatient.Data.([]e.ResponseDto); ok { - if len(list) < 1 { - input.NewStatus = true - } - } + input.NewStatus, err = identifyPatientStatus(input) err = dg.I.Transaction(func(tx *gorm.DB) error { mwRunner := newMiddlewareRunner(&event, tx) @@ -122,72 +100,18 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } else { data = *resData + input.Id = data.Id } - switch input.Class_Code { - case ere.ECAmbulatory: - subCodeAmbulatory := subCode.(ere.AmbulatoryClassCode) - ambCreate := ea.CreateDto{ - Encounter_Id: &data.Id, - Class_Code: subCodeAmbulatory, - } - _, err = ua.CreateData(ambCreate, &event, tx) - if err != nil { - return err - } - - if subCodeAmbulatory == ere.ACCChemo { - chemoCreate := ec.CreateDto{ - Encounter_Id: &data.Id, - Status_Code: erc.DVCNew, - SrcUnit_Id: input.Unit_Id, - } - _, err = uc.CreateData(chemoCreate, &event, tx) - if err != nil { - return err - } - } - - if subCodeAmbulatory == ere.ACCRehab && *input.VisitMode_Code == ere.VMCAdm { - // create data rehab - if _, err = ur.CreateData(er.CreateDto{ - Encounter_Id: &data.Id, - AllocatedVisitCount: input.AllocatedVisitCount}, &event, tx); err != nil { - return err - } - } else if subCodeAmbulatory == ere.ACCRehab && *input.VisitMode_Code == ere.VMCSeries { - // Insert Soapi - if err = us.CreateBulkData(createSoapi, data.Id, &event, tx); err != nil { - return err - } - } - - case ere.ECEmergency: - emerCreate := ee.CreateDto{ - Encounter_Id: &data.Id, - Class_Code: subCode.(ere.EmergencyClassCode), - } - _, err = ue.CreateData(emerCreate, &event, tx) - if err != nil { - return err - } - case ere.ECInpatient: - inpCreate := ei.CreateDto{ - Encounter_Id: &data.Id, - Class_Code: subCode.(ere.InpatientClassCode), - Infra_Id: input.Infra_Id, - } - _, err = ui.CreateData(inpCreate, &event, tx) - if err != nil { - return err - } - default: - return errors.New("invalid encounter class code") + // insert ambulatory/emergency/inpatient + err = insertdataClassCode(input, recentSoapiDataforCopy, &event, tx) + if err != nil { + return err } // insert adm_employee_hist if _, err := uaeh.CreateData(eaeh.CreateDto{ - Encounter_Id: &data.Main.Id, + Encounter_Id: &data.Id, Employee_Id: data.Adm_Employee_Id, StartedAt: &now}, &event, tx); err != nil { return err @@ -469,10 +393,15 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) { if data.Ambulatory != nil && (data.Ambulatory.Class_Code == ere.ACCReg || data.Ambulatory.Class_Code == ere.ACCRehab) { // validate if soapi exist - err = getSoapiByTypeCode(input.Id, *data.Ambulatory, &event, "check-out") - if err != nil { + if err = getSoapiByTypeCode(data, &event, "check-out"); err != nil { return err } + + // verify and update rehabData if visit count has reached the allowed limit + if err = verifyRehabLimit(data, &event, tx); err != nil { + return err + } + } else { // chemo TBC if err := checkSoapiByDocExists(data.Id, &event, tx); err != nil { @@ -495,27 +424,22 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) { } // update finishedAt in latest responsible_doctor_hist - if err = updateLatestResponsibleDoctorHist(e.CheckinDto{Id: input.Id, StartedAt: &now}, &event, tx); err != nil { + if err = updateLatestResponsibleDoctorHist(e.CheckinDto{Id: input.Id, FinishedAt: &now}, &event, tx); err != nil { return err } // update finishedAt in latest adm_employee_hist - if err = updateLatestAdmEmployeeHist(e.CheckinDto{Id: input.Id, StartedAt: &now}, &event, tx); err != nil { + if err = updateLatestAdmEmployeeHist(e.CheckinDto{Id: input.Id, FinishedAt: &now}, &event, tx); err != nil { return err } + // insert data death-cause if *input.Discharge_Method_Code == ere.DMCDeath { - // insert data death-cause if _, err = udc.CreateData(edc.CreateDto{Encounter_Id: &input.Id, Value: input.DeathCause}, &event, tx); err != nil { return err } } - //// bulk insert internal-references - //if err = createInternalReferences(input, &event, tx); err != nil { - // return err - //} - pl.SetLogInfo(&event, nil, "complete") return nil @@ -642,13 +566,13 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { // validate if soapi exist if data.Ambulatory != nil && (data.Ambulatory.Class_Code == ere.ACCReg || data.Ambulatory.Class_Code == ere.ACCRehab) { - err = getSoapiByTypeCode(input.Id, *data.Ambulatory, &event, "check-in") + err = getSoapiByTypeCode(data, &event, "check-in") if err != nil { return err } } - // Insert responsible_doctor_hist if responsible_doctor_id has changed && update latest history + // Upsert responsible_doctor_hist if responsible_doctor_id has changed if data.Responsible_Doctor_Id == nil || *input.Responsible_Doctor_Id != *data.Responsible_Doctor_Id { // upsert responsibleDoctorHist if err = upsertResponsibleDoctorHist(erdh.CreateDto{ @@ -660,7 +584,7 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { } } - // Insert adm_employee_hist if adm_employee_id has changed && update latest history + // Upsert adm_employee_hist if adm_employee_id has changed if input.Adm_Employee_Id != nil && *input.Adm_Employee_Id != *data.Adm_Employee_Id { // upsert admEmployeeHist if err = upsertAdmEmployeeHist(eaeh.CreateDto{ @@ -677,14 +601,6 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { return err } - if data.Ambulatory.Class_Code == ere.ACCRehab { - if err := updateRehabDoctor(er.UpdateDto{CreateDto: er.CreateDto{ - Encounter_Id: &data.Id, - }}, &event, tx); err != nil { - return err - } - } - pl.SetLogInfo(&event, nil, "complete") return nil @@ -704,43 +620,205 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { }, nil } -func validateForeignKey(input e.CheckinDto) error { - // validate employee_Id - if input.Adm_Employee_Id != nil { - if _, err := uem.ReadDetail(eem.ReadDetailDto{Id: uint16(*input.Adm_Employee_Id)}); err != nil { +func RequestSwitchUnit(input e.SwitchUnitDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Responsible_Doctor"} + var data *e.Encounter + var err error + + event := pl.Event{ + Feature: "RequestSwitchUnit", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "checkOut") + + unitIDs := make(map[uint16]struct{}) + doctorIDs := make(map[uint]struct{}) + for _, ref := range *input.InternalReferences { + if ref.Unit_Id != nil { + unitIDs[*ref.Unit_Id] = struct{}{} + } + if ref.Doctor_Id != nil { + doctorIDs[*ref.Doctor_Id] = struct{}{} + } + } + + // validate unit + if err = validateUnitIds(unitIDs, &event); err != nil { + return nil, err + } + + // validate doctor + if err = validateDoctorIds(doctorIDs, &event); err != nil { + return nil, err + } + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { return err } - } - // validate doctor_id - if input.Responsible_Doctor_Id != nil { - if _, err := ud.ReadDetail(ed.ReadDetailDto{Id: uint16(*input.Responsible_Doctor_Id)}); err != nil { + //if data.IsDone() { + // event.Status = "failed" + // event.ErrInfo = pl.ErrorInfo{ + // Code: "data-state-mismatch", + // Detail: "encounter is done", + // Raw: errors.New("encounter is done"), + // } + // return pl.SetLogError(&event, input) + //} + + // verify Soapi exist for current responsible doctor + dataSoapi, err := getSoapiByResponsibleDoctor(*data, &event) + if err != nil { return err } + if len(dataSoapi) < 1 { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "missing-soapi", + Detail: fmt.Sprintf("Missing soapi from latest responsible doctor"), + } + return pl.SetLogError(&event, input) + } + + // bulk internal references + if err := uir.CreateBulkData(*input.InternalReferences, input.Id, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + return nil + }) + + if err != nil { + return nil, err } - return nil + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "requestSwitchUnit", + }, + Data: data.ToResponse(), + }, nil } -func verifyClassCode(input e.CreateDto) (subCode interface{}, err error) { - switch input.Class_Code { - case ere.ECAmbulatory: - subCode, err = ua.CheckClassCode(input.SubClass_Code) - if err != nil { - return nil, err - } - case ere.ECEmergency: - subCode, err = ue.CheckClassCode(input.SubClass_Code) - if err != nil { - return nil, err - } - case ere.ECInpatient: - subCode, err = ui.CheckClassCode(input.SubClass_Code) - if err != nil { - return nil, err - } - default: - return nil, errors.New("invalid encounter class code") +func ApproveSwitchUnit(input e.ApproveUnitDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Responsible_Doctor"} + var data *e.Encounter + var err error + + event := pl.Event{ + Feature: "ApproveSwitchUnit", + Source: source, } - return + + // Start log + pl.SetLogInfo(&event, input, "started", "approveSwitchUnit") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err + } + + // get internal reference + irData, err := uir.ReadDetailData(eir.ReadDetailDto{ + Id: input.InternalReferences_Id, Includes: "Doctor"}, &event, tx) + if err != nil { + return err + } + + if *irData.Status_Code != erc.DACNew { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-state-mismatch", + Detail: "internal references is approve", + Raw: errors.New("internal references is approve"), + } + return pl.SetLogError(&event, input) + } + + //if data.IsDone() { + // event.Status = "failed" + // event.ErrInfo = pl.ErrorInfo{ + // Code: "data-state-mismatch", + // Detail: "encounter is done", + // Raw: errors.New("encounter is done"), + // } + // return pl.SetLogError(&event, input) + //} + + // verify Soapi exist for current responsible doctor + dataSoapi, err := getSoapiByResponsibleDoctor(*data, &event) + if err != nil { + return err + } + if len(dataSoapi) < 1 { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "missing-soapi", + Detail: fmt.Sprintf("Missing soapi from latest responsible doctor"), + } + return pl.SetLogError(&event, input) + } + + // update internal reference + if err = uir.UpdateData(eir.UpdateDto{ + Id: input.InternalReferences_Id, + CreateDto: eir.CreateDto{ + Encounter_Id: &input.Id, + Doctor_Id: irData.Doctor_Id, + Unit_Id: irData.Unit_Id, + Status_Code: erc.DACApproved, + }}, irData, &event, tx); err != nil { + return err + } + + // update encounter + if err = updateEncounterApproveSwitchUnit(*irData, &event, tx); err != nil { + return err + } + + // update latest responsible doctor hist + if err = updateLatestResponsibleDoctorHist(e.CheckinDto{Id: input.Id, FinishedAt: &now}, &event, tx); err != nil { + return err + } + + // create responsible doctor based on internal reference data + if _, err = urdh.CreateData(erdh.CreateDto{ + Encounter_Id: &input.Id, + Doctor_Id: irData.Doctor_Id, + StartedAt: &now, + }, &event, tx); err != nil { + return err + } + + // update data response + data.Responsible_Doctor_Id = irData.Doctor_Id + data.Unit = irData.Unit + data.Specialist_Id = irData.Doctor.Specialist_Id + data.Subspecialist_Id = irData.Doctor.Subspecialist_Id + + pl.SetLogInfo(&event, nil, "complete") + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + } diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index 9c522ed6..dc825348 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -10,6 +10,8 @@ import ( "strings" "time" + authhelper "simrs-vx/internal/lib/auth" + dg "github.com/karincake/apem/db-gorm-pg" "gorm.io/gorm" @@ -23,9 +25,13 @@ import ( eaeh "simrs-vx/internal/domain/main-entities/adm-employee-hist" ea "simrs-vx/internal/domain/main-entities/ambulatory" + ec "simrs-vx/internal/domain/main-entities/chemo" edo "simrs-vx/internal/domain/main-entities/device-order" ed "simrs-vx/internal/domain/main-entities/doctor" + ee "simrs-vx/internal/domain/main-entities/emergency" + eem "simrs-vx/internal/domain/main-entities/employee" e "simrs-vx/internal/domain/main-entities/encounter" + ei "simrs-vx/internal/domain/main-entities/inpatient" emo "simrs-vx/internal/domain/main-entities/material-order" emco "simrs-vx/internal/domain/main-entities/mcu-order" em "simrs-vx/internal/domain/main-entities/medication" @@ -36,19 +42,26 @@ import ( epi "simrs-vx/internal/domain/main-entities/prescription-item" er "simrs-vx/internal/domain/main-entities/rehab" erdh "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" + es "simrs-vx/internal/domain/main-entities/soapi" eu "simrs-vx/internal/domain/main-entities/unit" // udo "simrs-vx/internal/use-case/main-use-case/device-order" - es "simrs-vx/internal/domain/main-entities/soapi" uaeh "simrs-vx/internal/use-case/main-use-case/adm-employee-hist" - uir "simrs-vx/internal/use-case/main-use-case/internal-reference" + ua "simrs-vx/internal/use-case/main-use-case/ambulatory" + uc "simrs-vx/internal/use-case/main-use-case/chemo" + ud "simrs-vx/internal/use-case/main-use-case/doctor" + ue "simrs-vx/internal/use-case/main-use-case/emergency" + uem "simrs-vx/internal/use-case/main-use-case/employee" + ui "simrs-vx/internal/use-case/main-use-case/inpatient" um "simrs-vx/internal/use-case/main-use-case/medication" umei "simrs-vx/internal/use-case/main-use-case/medication-item" umi "simrs-vx/internal/use-case/main-use-case/medicine-mix" ummi "simrs-vx/internal/use-case/main-use-case/medicine-mix-item" up "simrs-vx/internal/use-case/main-use-case/prescription" upi "simrs-vx/internal/use-case/main-use-case/prescription-item" + ur "simrs-vx/internal/use-case/main-use-case/rehab" urdh "simrs-vx/internal/use-case/main-use-case/responsible-doctor-hist" + us "simrs-vx/internal/use-case/main-use-case/soapi" ) func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Encounter) { @@ -104,6 +117,19 @@ func setDataDischarge(src e.DischargeDto, dst *e.Encounter) { dst.FinishedAt = &now } +func setDataUpdateStatus(src e.UpdateStatusDto, dst *e.Encounter) { + dst.Status_Code = src.StatusCode +} + +func setDataCheckIn(src e.CheckinDto, dst *e.Encounter) { + if src.Adm_Employee_Id != nil { + dst.Adm_Employee_Id = src.Adm_Employee_Id + } + + dst.Responsible_Doctor_Id = src.Responsible_Doctor_Id + dst.StartedAt = src.StartedAt +} + func checkSoapiByDocExists(encounter_id uint, event *pl.Event, tx *gorm.DB) error { pl.SetLogInfo(event, nil, "started", "checkSoapiByDocExists") var soapies []es.Soapi @@ -335,113 +361,6 @@ func getMcuOrders(encounter_id uint, event *pl.Event, tx *gorm.DB) error { return nil } -func setDataUpdateStatus(src e.UpdateStatusDto, dst *e.Encounter) { - dst.Status_Code = src.StatusCode -} - -func setDataCheckIn(src e.CheckinDto, dst *e.Encounter) { - if src.Adm_Employee_Id != nil { - dst.Adm_Employee_Id = src.Adm_Employee_Id - } - - dst.Responsible_Doctor_Id = src.Responsible_Doctor_Id - dst.StartedAt = src.StartedAt -} - -func createInternalReferences(input e.DischargeDto, event *pl.Event, tx *gorm.DB) error { - unitIDs := make(map[uint16]struct{}) - doctorIDs := make(map[uint]struct{}) - - for _, ref := range *input.InternalReferences { - if ref.Unit_Id != nil { - unitIDs[*ref.Unit_Id] = struct{}{} - } - if ref.Doctor_Id != nil { - doctorIDs[*ref.Doctor_Id] = struct{}{} - } - } - - // validate unitIds - if len(unitIDs) > 0 { - var ids []uint16 - for id := range unitIDs { - ids = append(ids, id) - } - - units, err := getUnits(ids, event, tx) - if err != nil { - return fmt.Errorf("failed to fetch units: %w", err) - } - if len(units) != len(ids) { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-validation-fail", - Detail: "unit_id not found", - } - return pl.SetLogError(event, nil) - } - } - - // validate doctorIds - if len(doctorIDs) > 0 { - var ids []uint - for id := range doctorIDs { - ids = append(ids, id) - } - - doctors, err := getDoctors(ids, event, tx) - if err != nil { - return fmt.Errorf("failed to fetch doctors: %w", err) - } - if len(doctors) != len(ids) { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-validation-fail", - Detail: "doctor_id not found", - } - return pl.SetLogError(event, nil) - } - } - - if err := uir.CreateBulkData(*input.InternalReferences, input.Id, event, tx); err != nil { - return err - } - - return nil -} - -func getUnits(unitIds []uint16, event *pl.Event, tx *gorm.DB) ([]eu.Unit, error) { - pl.SetLogInfo(event, nil, "started", "getUnits") - var units []eu.Unit - err := tx.Where("\"Id\" IN ?", unitIds).Find(&units).Error - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-get-fail", - Detail: "get units", - Raw: err, - } - return nil, pl.SetLogError(event, nil) - } - return units, nil -} - -func getDoctors(doctorIds []uint, event *pl.Event, tx *gorm.DB) ([]ed.Doctor, error) { - pl.SetLogInfo(event, nil, "started", "getDoctors") - var doctors []ed.Doctor - err := tx.Where("\"Id\" IN ?", doctorIds).Find(&doctors).Error - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-get-fail", - Detail: "get doctors", - Raw: err, - } - return nil, pl.SetLogError(event, nil) - } - return doctors, nil -} - func upsertResponsibleDoctorHist(input erdh.CreateDto, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, nil, "started", "DBCreate") @@ -566,7 +485,7 @@ func updateLatestResponsibleDoctorHist(input e.CheckinDto, event *pl.Event, dbx result := tx. Model(&erdh.ResponsibleDoctorHist{}). Where("\"Id\" = (?)", subQuery). - Update("\"FinishedAt\"", input.StartedAt) + Update("\"FinishedAt\"", input.FinishedAt) if result.Error != nil { event.Status = "failed" @@ -607,7 +526,7 @@ func updateLatestAdmEmployeeHist(input e.CheckinDto, event *pl.Event, dbx ...*go result := tx. Model(&eaeh.AdmEmployeeHist{}). Where("\"Id\" = (?)", subQuery). - Update("\"FinishedAt\"", input.StartedAt) + Update("\"FinishedAt\"", input.FinishedAt) if result.Error != nil { event.Status = "failed" @@ -628,9 +547,7 @@ func updateLatestAdmEmployeeHist(input e.CheckinDto, event *pl.Event, dbx ...*go return nil } -func getSoapiEncounterAdm(enc e.Encounter, event *pl.Event) (dataSoapi []es.CreateDto, err error) { - var data []es.Soapi - +func getSoapiByResponsibleDoctor(enc e.Encounter, event *pl.Event) (data []es.Soapi, err error) { pl.SetLogInfo(event, enc, "started", "DBReadList") if enc.Responsible_Doctor == nil { @@ -653,21 +570,22 @@ func getSoapiEncounterAdm(enc e.Encounter, event *pl.Event) (dataSoapi []es.Crea if err != nil { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ - Raw: err, + Raw: err, + Code: "read-fail", + Detail: "Database read failed", } - - if errors.Is(err, gorm.ErrRecordNotFound) { - event.ErrInfo.Code = "data-not-found" - event.ErrInfo.Detail = "Data not found" - return nil, pl.SetLogError(event, enc) - } - - event.ErrInfo.Code = "read-fail" - event.ErrInfo.Detail = "Database read failed" return nil, pl.SetLogError(event, enc) } pl.SetLogInfo(event, nil, "complete") + return +} + +func getSoapiEncounterAdm(enc e.Encounter, event *pl.Event) (dataSoapi []es.CreateDto, err error) { + data, err := getSoapiByResponsibleDoctor(enc, event) + if err != nil { + return nil, err + } for _, s := range data { // set data soapi for copy @@ -690,39 +608,46 @@ func getSoapiEncounterAdm(enc e.Encounter, event *pl.Event) (dataSoapi []es.Crea return } -func getSoapiByTypeCode(encounterId uint, dataAmbulatory ea.Ambulatory, event *pl.Event, mode string) (err error) { - pl.SetLogInfo(event, encounterId, "started", "DBReadList") +func getSoapiByTypeCode(encounter *e.Encounter, event *pl.Event, mode string) (err error) { + pl.SetLogInfo(event, encounter, "started", "DBReadList") var ( dataSoapi []es.Soapi + amb = encounter.Ambulatory + rehab = encounter.Rehab ) // Set Query for get data Soapi tx := dg.I. Model(&es.Soapi{}). Joins("JOIN \"Employee\" ON \"Employee\".\"Id\" = \"Soapi\".\"Employee_Id\""). - Where("\"Encounter_Id\" = ?", encounterId). + Where("\"Encounter_Id\" = ?", encounter.Id). Where("\"Employee\".\"Position_Code\" = ?", erg.EPCDoc) // Set Case switch { - case dataAmbulatory.Class_Code == ere.ACCReg: + case amb.Class_Code == ere.ACCReg: tx = tx.Where("\"Soapi\".\"TypeCode\" = ?", ercl.STCEEarlyMedic) - case dataAmbulatory.Class_Code == ere.ACCRehab && dataAmbulatory.VisitMode_Code == ere.VMCAdm: + case amb.Class_Code == ere.ACCRehab && *rehab.VisitMode_Code == ere.VMCAdm: tx = tx.Where("\"Soapi\".\"TypeCode\" IN ?", []ercl.SoapiTypeCode{ercl.STCEEarlyMedic, ercl.STCFunc, ercl.STCEarlyRehab}) - case dataAmbulatory.Class_Code == ere.ACCRehab && dataAmbulatory.VisitMode_Code == ere.VMCSeries: + case amb.Class_Code == ere.ACCRehab && *rehab.VisitMode_Code == ere.VMCSeries: tx = tx.Where("\"Soapi\".\"TypeCode\" = ?", ercl.STCEarlyRehab) } if err = tx.Find(&dataSoapi).Error; err != nil { - return setDBError(event, err, encounterId) + return setDBError(event, err, encounter) } pl.SetLogInfo(event, nil, "complete") - return validateExistedSoapi(dataSoapi, &dataAmbulatory, event, mode) + return validateExistedSoapi(dataSoapi, encounter, event, mode) } -func validateExistedSoapi(dataSoapi []es.Soapi, dataAmbulatory *ea.Ambulatory, event *pl.Event, mode string) error { +func validateExistedSoapi(dataSoapi []es.Soapi, dataEncounter *e.Encounter, event *pl.Event, mode string) error { + var ( + amb = dataEncounter.Ambulatory + rehab = dataEncounter.Rehab + ) + typeExist := make(map[ercl.SoapiTypeCode]bool) for _, s := range dataSoapi { typeExist[s.TypeCode] = true @@ -731,11 +656,11 @@ func validateExistedSoapi(dataSoapi []es.Soapi, dataAmbulatory *ea.Ambulatory, e required := []ercl.SoapiTypeCode{} switch { - case dataAmbulatory.Class_Code == ere.ACCReg: + case amb.Class_Code == ere.ACCReg: required = []ercl.SoapiTypeCode{ercl.STCEEarlyMedic} - case dataAmbulatory.Class_Code == ere.ACCRehab && dataAmbulatory.VisitMode_Code == ere.VMCAdm: + case amb.Class_Code == ere.ACCRehab && *rehab.VisitMode_Code == ere.VMCAdm: required = []ercl.SoapiTypeCode{ercl.STCEEarlyMedic, ercl.STCFunc, ercl.STCEarlyRehab} - case dataAmbulatory.Class_Code == ere.ACCRehab && dataAmbulatory.VisitMode_Code == ere.VMCSeries: + case amb.Class_Code == ere.ACCRehab && *rehab.VisitMode_Code == ere.VMCSeries: required = []ercl.SoapiTypeCode{ercl.STCEarlyRehab} } @@ -762,6 +687,231 @@ func validateExistedSoapi(dataSoapi []es.Soapi, dataAmbulatory *ea.Ambulatory, e return nil } +func identifyPatientStatus(input e.CreateDto) (isNewPatient bool, err error) { + dataPatient, err := ReadList(e.ReadListDto{ + FilterDto: e.FilterDto{Patient_Id: input.Patient_Id}, + AuthInfo: authhelper.AuthInfo{User_Id: input.User_Id}}) + if err != nil { + return + } + + if list, ok := dataPatient.Data.([]e.ResponseDto); ok { + if len(list) < 1 { + isNewPatient = true + } + } + + return +} + +func determineVisitMode(recentRehabData *er.Rehab, input e.CreateDto, event *pl.Event) (ere.VisitModeCode, e.Encounter, error) { + var ( + visitModeCode ere.VisitModeCode + recentAdmEncounterData e.Encounter + isQuotaValid bool + err error + ) + + switch *recentRehabData.Status_Code { + case erc.DSCProcess: + visitModeCode = ere.VMCSeries + + // verify whether the allocated visit count has not exceeded the limit + recentAdmEncounterData, isQuotaValid, err = verifyAllocatedVisitCount(input, event) + if err != nil { + return "", e.Encounter{}, err + } + + if !isQuotaValid || recentRehabData.ExpiredAt.Before(*pu.GetTimeNow()) { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "visit-limit-exceeded", + Detail: "Encounter has exceeded the allowed number of visits or expired", + Raw: errors.New("visit count exceeds allowed limit"), + } + return "", e.Encounter{}, pl.SetLogError(event, input) + } + + case erc.DSCDone: + visitModeCode = ere.VMCAdm + + default: + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "invalid-status", + Detail: fmt.Sprintf("Unknown rehab status: %v", *recentRehabData.Status_Code), + Raw: errors.New("unsupported rehab status"), + } + return "", e.Encounter{}, pl.SetLogError(event, input) + } + + return visitModeCode, recentAdmEncounterData, nil +} + +func insertdataClassCode(input e.CreateDto, soapiData []es.CreateDto, event *pl.Event, tx *gorm.DB) (err error) { + switch input.Class_Code { + case ere.ECAmbulatory: + subCode := ere.AmbulatoryClassCode(*input.SubClass_Code) + ambCreate := ea.CreateDto{ + Encounter_Id: &input.Id, + Class_Code: subCode, + } + + // create data Ambulatory + _, err = ua.CreateData(ambCreate, event, tx) + if err != nil { + return err + } + + // insert chemo/rehab + err = insertDataSubClassAmbulatory(input, soapiData, event, tx) + if err != nil { + return err + } + + case ere.ECEmergency: + subCode := ere.EmergencyClassCode(*input.SubClass_Code) + emerCreate := ee.CreateDto{ + Encounter_Id: &input.Id, + Class_Code: subCode, + } + + // create data emergency + _, err = ue.CreateData(emerCreate, event, tx) + if err != nil { + return err + } + case ere.ECInpatient: + subCode := ere.InpatientClassCode(*input.SubClass_Code) + inpCreate := ei.CreateDto{ + Encounter_Id: &input.Id, + Class_Code: subCode, + Infra_Id: input.Infra_Id, + } + + // create data inpatient + _, err = ui.CreateData(inpCreate, event, tx) + if err != nil { + return err + } + default: + return errors.New("invalid encounter class code") + } + + return +} + +func insertDataSubClassAmbulatory(input e.CreateDto, soapiData []es.CreateDto, event *pl.Event, tx *gorm.DB) (err error) { + subCode := ere.AmbulatoryClassCode(*input.SubClass_Code) + + switch { + case subCode == ere.ACCChemo: + chemoCreate := ec.CreateDto{ + Encounter_Id: &input.Id, + Status_Code: erc.DVCNew, + SrcUnit_Id: input.Unit_Id, + } + + // create data chemo + _, err = uc.CreateData(chemoCreate, event, tx) + if err != nil { + return err + } + + case subCode == ere.ACCRehab: + rehabData := er.CreateDto{ + Encounter_Id: &input.Id, + VisitMode_Code: input.VisitMode_Code, + Status_Code: erc.DSCProcess, + } + + // if visitMode_code is series, then bulk insert soapi + if input.VisitMode_Code == ere.VMCSeries { + rehabData.Parent_Encounter_Id = &input.RecentEncounterAdm.Id + + // Insert Soapi + if err = us.CreateBulkData(soapiData, input.Id, event, tx); err != nil { + return err + } + } + + // create rehab + if _, err = ur.CreateData(rehabData, event, tx); err != nil { + return err + } + } + + return +} + +func verifyRehabLimit(data *e.Encounter, event *pl.Event, tx *gorm.DB) error { + // get data encounter adm + encounterAdmData, _, err := verifyAllocatedVisitCount(e.CreateDto{Patient_Id: data.Patient_Id}, event) + if err != nil { + return err + } + + // Check if the visit count has reached the allowed limit + // Mark rehab status as 'done' if exceeded. + if len(*encounterAdmData.RehabChildren) >= *encounterAdmData.Rehab.AllocatedVisitCount { + err = updateRehabStatus(er.UpdateDto{ + Id: uint16(encounterAdmData.Rehab.Id), + CreateDto: er.CreateDto{Status_Code: erc.DSCDone}}, event, tx) + if err != nil { + return err + } + } + + return nil +} + +func updateRehabStatus(input er.UpdateDto, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, "started", "DBUpdate") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + result := tx. + Model(&er.Rehab{}). + Where("\"Id\" = (?)", input.Id). + Update("\"Status_Code\"", input.Status_Code) + + if result.Error != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-update-fail", + Detail: "Database update failed", + Raw: result.Error, + } + return pl.SetLogError(event, input) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} + +func validateForeignKey(input e.CheckinDto) error { + // validate employee_Id + if input.Adm_Employee_Id != nil { + if _, err := uem.ReadDetail(eem.ReadDetailDto{Id: uint16(*input.Adm_Employee_Id)}); err != nil { + return err + } + } + + // validate doctor_id + if input.Responsible_Doctor_Id != nil { + if _, err := ud.ReadDetail(ed.ReadDetailDto{Id: uint16(*input.Responsible_Doctor_Id)}); err != nil { + return err + } + } + + return nil +} + func setSoapiError(event *pl.Event, detail string) error { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ @@ -781,31 +931,82 @@ func setDBError(event *pl.Event, err error, ctx any) error { return pl.SetLogError(event, ctx) } -//func updateRehabDoctor(input er.UpdateDto, event *pl.Event, dbx ...*gorm.DB) error { -// pl.SetLogInfo(event, "started", "DBUpdate") -// -// var tx *gorm.DB -// if len(dbx) > 0 { -// tx = dbx[0] -// } else { -// tx = dg.I -// } -// -// result := tx. -// Model(&er.Rehab{}). -// Where("\"Encounter_Id\" = (?)", input.Encounter_Id). -// Update("\"Doctor_Id\"", input.Doctor_Id) -// -// if result.Error != nil { -// event.Status = "failed" -// event.ErrInfo = pl.ErrorInfo{ -// Code: "data-update-fail", -// Detail: "Database update failed", -// Raw: result.Error, -// } -// return pl.SetLogError(event, input) -// } -// -// pl.SetLogInfo(event, nil, "complete") -// return nil -//} +func getUnits(unitIds []uint16, event *pl.Event) ([]eu.Unit, error) { + pl.SetLogInfo(event, nil, "started", "getUnits") + var units []eu.Unit + err := dg.I.Where("\"Id\" IN ?", unitIds).Find(&units).Error + if err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-get-fail", + Detail: "get units", + Raw: err, + } + return nil, pl.SetLogError(event, nil) + } + return units, nil +} + +func getDoctors(doctorIds []uint, event *pl.Event) ([]ed.Doctor, error) { + pl.SetLogInfo(event, nil, "started", "getDoctors") + var doctors []ed.Doctor + err := dg.I.Where("\"Id\" IN ?", doctorIds).Find(&doctors).Error + if err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-get-fail", + Detail: "get doctors", + Raw: err, + } + return nil, pl.SetLogError(event, nil) + } + return doctors, nil +} + +func validateUnitIds(unitIDs map[uint16]struct{}, event *pl.Event) error { + if len(unitIDs) > 0 { + var ids []uint16 + for id := range unitIDs { + ids = append(ids, id) + } + + units, err := getUnits(ids, event) + if err != nil { + return fmt.Errorf("failed to fetch units: %w", err) + } + if len(units) != len(ids) { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-validation-fail", + Detail: "unit_id not found", + } + return pl.SetLogError(event, nil) + } + } + + return nil +} + +func validateDoctorIds(doctorIDs map[uint]struct{}, event *pl.Event) error { + if len(doctorIDs) > 0 { + var ids []uint + for id := range doctorIDs { + ids = append(ids, id) + } + + doctors, err := getDoctors(ids, event) + if err != nil { + return fmt.Errorf("failed to fetch doctors: %w", err) + } + if len(doctors) != len(ids) { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-validation-fail", + Detail: "doctor_id not found", + } + return pl.SetLogError(event, nil) + } + } + + return nil +} diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index 88c50113..5f41bf8c 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -3,7 +3,7 @@ package encounter import ( // std "errors" - ere "simrs-vx/internal/domain/references/encounter" + eir "simrs-vx/internal/domain/main-entities/internal-reference" // external dg "github.com/karincake/apem/db-gorm-pg" gh "github.com/karincake/getuk" @@ -13,9 +13,14 @@ import ( pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" + ere "simrs-vx/internal/domain/references/encounter" + e "simrs-vx/internal/domain/main-entities/encounter" + er "simrs-vx/internal/domain/main-entities/rehab" ) +const ErrorReadFailed = "Database read failed" + func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Encounter, error) { pl.SetLogInfo(event, nil, "started", "DBCreate") @@ -249,20 +254,49 @@ func updateCheckInData(input e.CheckinDto, data *e.Encounter, event *pl.Event, d return nil } +func identifyVisitModeCode(i e.CreateDto, event *pl.Event) (recentRehabData *er.Rehab, err error) { + pl.SetLogInfo(event, nil, "started", "DBGetLatestRehab") + + var ( + tx = dg.I + ) + + err = tx. + Joins("JOIN \"Encounter\" ON \"Encounter\".\"Id\" = \"Rehab\".\"Encounter_Id\""). + Where("\"Encounter\".\"Patient_Id\" = ?", i.Patient_Id). + Order("\"CreatedAt\" DESC"). + First(&recentRehabData).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "read-recentRehab-fail", + Detail: ErrorReadFailed, + Raw: err, + } + return nil, pl.SetLogError(event, i) + } + + return +} + func verifyAllocatedVisitCount(i e.CreateDto, event *pl.Event) (e.Encounter, bool, error) { pl.SetLogInfo(event, nil, "started", "DBGetRecentEncounterAdm") var ( - tx = dg.I - recentEncounterAdm e.Encounter - countEncounterSeries int64 + tx = dg.I + recentEncounterAdm e.Encounter + valid = true ) err := tx. - Scopes(gh.Preload("Rehab,Responsible_Doctor")). - Joins("JOIN \"Ambulatory\" ON \"Ambulatory\".\"Encounter_Id\" = \"Encounter\".\"Id\""). - Where("\"Patient_Id\" = ?", i.Patient_Id). - Where("\"Ambulatory\".\"Class_Code\" = ? AND \"Ambulatory\".\"VisitMode_Code\" = ?", ere.ACCRehab, ere.VMCAdm). + Scopes(gh.Preload("RehabChildren,Rehab,Responsible_Doctor")). + Joins("JOIN \"Rehab\" ON \"Rehab\".\"Encounter_Id\" = \"Encounter\".\"Id\""). + Where("\"Encounter\".\"Patient_Id\" = ?", i.Patient_Id). + Where("\"Rehab\".\"VisitMode_Code\" = ?", ere.VMCAdm). Order("\"CreatedAt\" DESC"). First(&recentEncounterAdm).Error if err != nil { @@ -275,22 +309,41 @@ func verifyAllocatedVisitCount(i e.CreateDto, event *pl.Event) (e.Encounter, boo return e.Encounter{}, false, pl.SetLogError(event, i) } - err = tx. - Model(&e.Encounter{}). - Joins("JOIN \"Ambulatory\" ON \"Ambulatory\".\"Encounter_Id\" = \"Encounter\".\"Id\""). - Where("\"Patient_Id\" = ?", i.Patient_Id). - Where("\"Ambulatory\".\"Class_Code\" = ? AND \"Ambulatory\".\"VisitMode_Code\" = ?", ere.ACCRehab, ere.VMCSeries). - Where("\"Encounter\".\"CreatedAt\" > ?", recentEncounterAdm.CreatedAt). - Count(&countEncounterSeries).Error - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "read-countEncounter-fail", - Detail: "Database read failed", - Raw: err, - } - return e.Encounter{}, false, pl.SetLogError(event, i) + // validate count rehab children + if recentEncounterAdm.RehabChildren != nil { + valid = len(*recentEncounterAdm.RehabChildren) < *recentEncounterAdm.Rehab.AllocatedVisitCount } - return recentEncounterAdm, countEncounterSeries < int64(*recentEncounterAdm.Rehab_Adm.AllocatedVisitCount), nil + return recentEncounterAdm, valid, nil +} + +func updateEncounterApproveSwitchUnit(input eir.InternalReference, event *pl.Event, dbx ...*gorm.DB) (err error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.Model(&e.Encounter{}). + Where("\"Id\" = ?", input.Encounter_Id). + Updates(map[string]interface{}{ + "Responsible_Doctor_Id": input.Doctor_Id, + "Unit_Id": input.Unit_Id, + "Specialist_Id": input.Doctor.Specialist_Id, + "Subspecialist_Id": input.Doctor.Subspecialist_Id, + }).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "update-fail", + Detail: "Failed to update encounter approve switch unit", + Raw: err, + } + return pl.SetLogError(event, input) + } + + pl.SetLogInfo(event, input, "complete") + return nil } diff --git a/internal/use-case/main-use-case/internal-reference/helper.go b/internal/use-case/main-use-case/internal-reference/helper.go index dbd92f73..36c28540 100644 --- a/internal/use-case/main-use-case/internal-reference/helper.go +++ b/internal/use-case/main-use-case/internal-reference/helper.go @@ -6,6 +6,7 @@ package internal_reference import ( ir "simrs-vx/internal/domain/main-entities/internal-reference" + erc "simrs-vx/internal/domain/references/common" ) func setData[T *ir.CreateDto | *ir.UpdateDto](input T, data *ir.InternalReference) { @@ -20,16 +21,19 @@ func setData[T *ir.CreateDto | *ir.UpdateDto](input T, data *ir.InternalReferenc data.Encounter_Id = inputSrc.Encounter_Id data.Unit_Id = inputSrc.Unit_Id data.Doctor_Id = inputSrc.Doctor_Id + data.Status_Code = &inputSrc.Status_Code } func setBulkData(input []ir.CreateDto, encounterId uint) []ir.InternalReference { var data []ir.InternalReference for _, v := range input { + statusCode := erc.DACNew data = append(data, ir.InternalReference{ Encounter_Id: &encounterId, Unit_Id: v.Unit_Id, Doctor_Id: v.Doctor_Id, + Status_Code: &statusCode, }) } From 49922a6b7213c9365051bf74806084278c118ec8 Mon Sep 17 00:00:00 2001 From: vanilia Date: Sun, 9 Nov 2025 23:12:09 +0700 Subject: [PATCH 111/329] adjustment update rehab in checkout --- internal/use-case/main-use-case/encounter/case.go | 15 ++++++++------- .../use-case/main-use-case/encounter/helper.go | 15 ++++++++------- internal/use-case/main-use-case/encounter/lib.go | 2 +- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 9798a28b..533b2264 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -52,15 +52,15 @@ func Create(input e.CreateDto) (*d.Data, error) { // validate rehab bpjs if input.RefTypeCode == ere.RTCBpjs && input.Class_Code == ere.ECAmbulatory && ere.AmbulatoryClassCode(*input.SubClass_Code) == ere.ACCRehab { - // identify visit mode from latest rehab data - recentRehabData, err := identifyVisitModeCode(input, &event) + // get latest rehab data + recentRehabData, err := getLatestRehabData(input, &event) if err != nil { return nil, err } if recentRehabData != nil { // determine VisitModeCode - input.VisitMode_Code, *input.RecentEncounterAdm, err = determineVisitMode(recentRehabData, input, &event) + input.VisitMode_Code, input.RecentEncounterAdm, err = determineVisitMode(recentRehabData, input, &event) if err != nil { return nil, err } @@ -397,11 +397,12 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) { return err } - // verify and update rehabData if visit count has reached the allowed limit - if err = verifyRehabLimit(data, &event, tx); err != nil { - return err + if data.Ambulatory.Class_Code == ere.ACCRehab { + // verify and update rehabData if visit count has reached the allowed limit + if err = verifyRehabLimit(data, &event, tx); err != nil { + return err + } } - } else { // chemo TBC if err := checkSoapiByDocExists(data.Id, &event, tx); err != nil { diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index dc825348..1d313d5f 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -559,6 +559,7 @@ func getSoapiByResponsibleDoctor(enc e.Encounter, event *pl.Event) (data []es.So } err = dg.I. + Debug(). Model(&es.Soapi{}). Joins("JOIN \"Employee\" ON \"Employee\".\"Id\" = \"Soapi\".\"Employee_Id\""). Where("\"Encounter_Id\" = ?", enc.Id). @@ -704,7 +705,7 @@ func identifyPatientStatus(input e.CreateDto) (isNewPatient bool, err error) { return } -func determineVisitMode(recentRehabData *er.Rehab, input e.CreateDto, event *pl.Event) (ere.VisitModeCode, e.Encounter, error) { +func determineVisitMode(recentRehabData *er.Rehab, input e.CreateDto, event *pl.Event) (ere.VisitModeCode, *e.Encounter, error) { var ( visitModeCode ere.VisitModeCode recentAdmEncounterData e.Encounter @@ -719,7 +720,7 @@ func determineVisitMode(recentRehabData *er.Rehab, input e.CreateDto, event *pl. // verify whether the allocated visit count has not exceeded the limit recentAdmEncounterData, isQuotaValid, err = verifyAllocatedVisitCount(input, event) if err != nil { - return "", e.Encounter{}, err + return "", nil, err } if !isQuotaValid || recentRehabData.ExpiredAt.Before(*pu.GetTimeNow()) { @@ -729,7 +730,7 @@ func determineVisitMode(recentRehabData *er.Rehab, input e.CreateDto, event *pl. Detail: "Encounter has exceeded the allowed number of visits or expired", Raw: errors.New("visit count exceeds allowed limit"), } - return "", e.Encounter{}, pl.SetLogError(event, input) + return "", nil, pl.SetLogError(event, input) } case erc.DSCDone: @@ -742,10 +743,10 @@ func determineVisitMode(recentRehabData *er.Rehab, input e.CreateDto, event *pl. Detail: fmt.Sprintf("Unknown rehab status: %v", *recentRehabData.Status_Code), Raw: errors.New("unsupported rehab status"), } - return "", e.Encounter{}, pl.SetLogError(event, input) + return "", nil, pl.SetLogError(event, input) } - return visitModeCode, recentAdmEncounterData, nil + return visitModeCode, &recentAdmEncounterData, nil } func insertdataClassCode(input e.CreateDto, soapiData []es.CreateDto, event *pl.Event, tx *gorm.DB) (err error) { @@ -852,10 +853,10 @@ func verifyRehabLimit(data *e.Encounter, event *pl.Event, tx *gorm.DB) error { } // Check if the visit count has reached the allowed limit - // Mark rehab status as 'done' if exceeded. + // Mark latest rehab status as 'done' if exceeded. if len(*encounterAdmData.RehabChildren) >= *encounterAdmData.Rehab.AllocatedVisitCount { err = updateRehabStatus(er.UpdateDto{ - Id: uint16(encounterAdmData.Rehab.Id), + Id: uint16(data.Rehab.Id), CreateDto: er.CreateDto{Status_Code: erc.DSCDone}}, event, tx) if err != nil { return err diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index 5f41bf8c..373ce7f2 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -254,7 +254,7 @@ func updateCheckInData(input e.CheckinDto, data *e.Encounter, event *pl.Event, d return nil } -func identifyVisitModeCode(i e.CreateDto, event *pl.Event) (recentRehabData *er.Rehab, err error) { +func getLatestRehabData(i e.CreateDto, event *pl.Event) (recentRehabData *er.Rehab, err error) { pl.SetLogInfo(event, nil, "started", "DBGetLatestRehab") var ( From d7c62f62876257b33c4e595f414a6cb8d4f19d0f Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 10 Nov 2025 08:01:07 +0700 Subject: [PATCH 112/329] back to 0 --- cmd/main-migration/migrations/20251106054706.sql | 6 ------ cmd/main-migration/migrations/20251106054849.sql | 2 -- 2 files changed, 8 deletions(-) delete mode 100644 cmd/main-migration/migrations/20251106054706.sql delete mode 100644 cmd/main-migration/migrations/20251106054849.sql diff --git a/cmd/main-migration/migrations/20251106054706.sql b/cmd/main-migration/migrations/20251106054706.sql deleted file mode 100644 index dd292709..00000000 --- a/cmd/main-migration/migrations/20251106054706.sql +++ /dev/null @@ -1,6 +0,0 @@ --- Modify "Ambulatory" table -ALTER TABLE "public"."Ambulatory" DROP COLUMN "VisitMode_Code"; --- Modify "InternalReference" table -ALTER TABLE "public"."InternalReference" ADD COLUMN "Status_Code" text NULL; --- Modify "Rehab" table -ALTER TABLE "public"."Rehab" ADD COLUMN "Parent_Encounter_Id" bigint NULL, ADD COLUMN "ExpiredAt" timestamptz NULL, ADD COLUMN "VisitMode_Code" text NULL, ADD COLUMN "Status_Code" text NULL; diff --git a/cmd/main-migration/migrations/20251106054849.sql b/cmd/main-migration/migrations/20251106054849.sql deleted file mode 100644 index 45e5f4e4..00000000 --- a/cmd/main-migration/migrations/20251106054849.sql +++ /dev/null @@ -1,2 +0,0 @@ --- Modify "Rehab" table -ALTER TABLE "public"."Rehab" DROP COLUMN "Doctor_Id"; From 3e5889574cb9dc22334bb04e810fee57adbe1b0e Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 10 Nov 2025 08:43:19 +0700 Subject: [PATCH 113/329] delete comment --- .../encounter/request-validation.go | 27 ------------------- .../use-case/main-use-case/encounter/case.go | 5 ---- 2 files changed, 32 deletions(-) diff --git a/internal/interface/main-handler/encounter/request-validation.go b/internal/interface/main-handler/encounter/request-validation.go index 6f448661..ab00a711 100644 --- a/internal/interface/main-handler/encounter/request-validation.go +++ b/internal/interface/main-handler/encounter/request-validation.go @@ -19,33 +19,6 @@ func validateRequestCheckout(w http.ResponseWriter, i e.DischargeDto) (valid boo }) return } - - //case ere.DMCConsulPoly, ere.DMCConsulExecutive: - // if i.InternalReferences == nil { - // rw.DataResponse(w, nil, d.FieldError{ - // Code: dataValidationFail, - // Message: fmt.Sprintf("internalReferences required if discharge_method_code is %s", *i.Discharge_Method_Code), - // }) - // return - // } - // - // for _, v := range *i.InternalReferences { - // if v.Unit_Id == nil { - // rw.DataResponse(w, nil, d.FieldError{ - // Code: dataValidationFail, - // Message: "internalReferences.unit_id required", - // }) - // return - // } - // - // if v.Doctor_Id == nil { - // rw.DataResponse(w, nil, d.FieldError{ - // Code: dataValidationFail, - // Message: "internalReferences.doctor_id required", - // }) - // return - // } - // } return true } diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 63b2832f..96f59a89 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -513,11 +513,6 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) { } } - //// bulk insert internal-references - //if err = createInternalReferences(input, &event, tx); err != nil { - // return err - //} - pl.SetLogInfo(&event, nil, "complete") return nil From d564e2e330325e4dc04607e8a601a9bf7e458fc4 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 10 Nov 2025 08:45:42 +0700 Subject: [PATCH 114/329] update hash --- cmd/main-migration/migrations/atlas.sum | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index ca12c2ae..1a259164 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:VjwYayb6y4kUl9K9WTTwmXExlHijchOCRwnUYcRlhRI= +h1:nxld1x0gKb2nqU+0YPNq5FaAhodpZwnaSuBWyZrPO+0= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -95,5 +95,5 @@ h1:VjwYayb6y4kUl9K9WTTwmXExlHijchOCRwnUYcRlhRI= 20251107091033.sql h1:/cbkF1nO/IjNSIfDJJx456KJtQ9rWFXOBFAkR/M2xiE= 20251107091209.sql h1:jrLQOUeV8ji2fg0pnEcs1bw4ANUxzTSMXC/rrHLIY+M= 20251107091541.sql h1:6UqbhQQRmzA2+eKu5lIvkwOkk+lH70QLZC8Pjpjcq68= -20251110012217.sql h1:+4ZcAtlZobLY/iTU1hwVEuqCCYtbiDs2N75jTBz1eQM= -20251110012306.sql h1:w3ZvpG2IaS4sZ9WxKcaMAjmy1JhsOPg8zmwjDv4tv7Y= +20251110012217.sql h1:C9HpX0iyHzKjyNv/5DSAn2MCHj6MX4p5UQ/NrY7QD0w= +20251110012306.sql h1:J54yb27d30LBbYp9n1P66gFVRlxPguKu0kxmWIBBG8g= From 1c46354206b1b1c3633239a4e2d0fb7793e5bcdb Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 10 Nov 2025 08:50:46 +0700 Subject: [PATCH 115/329] fix (auth): extract code --- .../use-case/main-use-case/authentication/case.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/use-case/main-use-case/authentication/case.go b/internal/use-case/main-use-case/authentication/case.go index 6cf94142..c162c56c 100644 --- a/internal/use-case/main-use-case/authentication/case.go +++ b/internal/use-case/main-use-case/authentication/case.go @@ -313,12 +313,12 @@ func ExtractToken(r *http.Request, tokenType TokenType) (data *pa.AuthInfo, err data.User_ContractPosition_code = checkStrClaims(claims, "contractPosition_code") data.Employee_Position_Code = checkStrPtrClaims(claims, "employee_position_code") - data.Doctor_Code = checkStrPtrClaims(claims, "doctor_string") - data.Nurse_Code = checkStrPtrClaims(claims, "nurse_string") - data.Midwife_Code = checkStrPtrClaims(claims, "midwife_string") - data.Nutritionist_Code = checkStrPtrClaims(claims, "nutritionist_string") - data.Laborant_Code = checkStrPtrClaims(claims, "laborant_string") - data.Pharmachist_Code = checkStrPtrClaims(claims, "pharmachist_string") + data.Doctor_Code = checkStrPtrClaims(claims, "doctor_code") + data.Nurse_Code = checkStrPtrClaims(claims, "nurse_code") + data.Midwife_Code = checkStrPtrClaims(claims, "midwife_code") + data.Nutritionist_Code = checkStrPtrClaims(claims, "nutritionist_code") + data.Laborant_Code = checkStrPtrClaims(claims, "laborant_code") + data.Pharmachist_Code = checkStrPtrClaims(claims, "pharmachist_code") data.Intern_Position_Code = checkStrPtrClaims(claims, "intern_position_code") data.Employee_Id = checkUntPtrClaims(claims, "employee_id") return From 70caef2602f4976c3f4184cd80af369d815619bb Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 10 Nov 2025 08:55:01 +0700 Subject: [PATCH 116/329] adjustment new entity --- internal/use-case/main-use-case/ambulatory/helper.go | 1 - internal/use-case/main-use-case/rehab/helper.go | 1 - 2 files changed, 2 deletions(-) diff --git a/internal/use-case/main-use-case/ambulatory/helper.go b/internal/use-case/main-use-case/ambulatory/helper.go index a8a00e0d..912211c0 100644 --- a/internal/use-case/main-use-case/ambulatory/helper.go +++ b/internal/use-case/main-use-case/ambulatory/helper.go @@ -22,7 +22,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Ambulatory) { data.Encounter_Id = inputSrc.Encounter_Id data.Class_Code = inputSrc.Class_Code - data.VisitMode_Code = inputSrc.VisitMode_Code } func CheckClassCode(input *string) (ere.AmbulatoryClassCode, error) { diff --git a/internal/use-case/main-use-case/rehab/helper.go b/internal/use-case/main-use-case/rehab/helper.go index 5c06ca0a..c5774400 100644 --- a/internal/use-case/main-use-case/rehab/helper.go +++ b/internal/use-case/main-use-case/rehab/helper.go @@ -18,6 +18,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Rehab) { } data.Encounter_Id = inputSrc.Encounter_Id - data.Doctor_Id = inputSrc.Doctor_Id data.AllocatedVisitCount = inputSrc.AllocatedVisitCount } From 3c7b35ef04578eb3a119e47c77dfae5b7b8a5422 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 10 Nov 2025 12:29:58 +0700 Subject: [PATCH 117/329] several tables ids into codes --- .../migrations/20251110052049.sql | 14 ++++++++++ cmd/main-migration/migrations/atlas.sum | 3 +- .../main-entities/consultation/entity.go | 16 ++++++----- .../main-entities/control-letter/entity.go | 28 +++++++++++-------- .../domain/main-entities/encounter/entity.go | 4 +++ .../internal-reference/entity.go | 2 ++ .../main-entities/practice-schedule/entity.go | 17 +++++------ .../responsible-doctor-hist/entity.go | 1 + .../main-entities/therapy-protocol/entity.go | 5 ++-- .../use-case/main-use-case/encounter/case.go | 4 +-- .../use-case/main-use-case/encounter/lib.go | 5 ++-- 11 files changed, 65 insertions(+), 34 deletions(-) create mode 100644 cmd/main-migration/migrations/20251110052049.sql diff --git a/cmd/main-migration/migrations/20251110052049.sql b/cmd/main-migration/migrations/20251110052049.sql new file mode 100644 index 00000000..4a1d74d7 --- /dev/null +++ b/cmd/main-migration/migrations/20251110052049.sql @@ -0,0 +1,14 @@ +-- Modify "Consultation" table +ALTER TABLE "public"."Consultation" ADD COLUMN "DstUnit_Code" text NULL, ADD COLUMN "DstDoctor_Code" text NULL; +-- Modify "ControlLetter" table +ALTER TABLE "public"."ControlLetter" ADD COLUMN "Unit_Code" text NULL, ADD COLUMN "Specialist_Code" text NULL, ADD COLUMN "Subspecialist_Code" text NULL, ADD COLUMN "Doctor_Code" text NULL; +-- Modify "Encounter" table +ALTER TABLE "public"."Encounter" ADD COLUMN "Specialist_Code" text NULL, ADD COLUMN "Subspecialist_Code" text NULL, ADD COLUMN "Appointment_Doctor_Code" text NULL, ADD COLUMN "Responsible_Doctor_Code" text NULL; +-- Modify "InternalReference" table +ALTER TABLE "public"."InternalReference" ADD COLUMN "Unit_Code" text NULL, ADD COLUMN "Doctor_Code" text NULL; +-- Modify "PracticeSchedule" table +ALTER TABLE "public"."PracticeSchedule" ADD COLUMN "Doctor_Code" text NULL; +-- Modify "ResponsibleDoctorHist" table +ALTER TABLE "public"."ResponsibleDoctorHist" ADD COLUMN "Doctor_Code" text NULL; +-- Modify "TherapyProtocol" table +ALTER TABLE "public"."TherapyProtocol" ADD COLUMN "Doctor_Code" text NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 1a259164..176a43a0 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:nxld1x0gKb2nqU+0YPNq5FaAhodpZwnaSuBWyZrPO+0= +h1:O5HiMUpKZtVkRc3VxZfFYuLYjUJhPepU5bMnO87FdPI= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -97,3 +97,4 @@ h1:nxld1x0gKb2nqU+0YPNq5FaAhodpZwnaSuBWyZrPO+0= 20251107091541.sql h1:6UqbhQQRmzA2+eKu5lIvkwOkk+lH70QLZC8Pjpjcq68= 20251110012217.sql h1:C9HpX0iyHzKjyNv/5DSAn2MCHj6MX4p5UQ/NrY7QD0w= 20251110012306.sql h1:J54yb27d30LBbYp9n1P66gFVRlxPguKu0kxmWIBBG8g= +20251110052049.sql h1:1LkEGCWPe04T3D8F3VMnBP8eJgskrvCggsybNxJ7GuU= diff --git a/internal/domain/main-entities/consultation/entity.go b/internal/domain/main-entities/consultation/entity.go index 2fda8bd0..06a44d57 100644 --- a/internal/domain/main-entities/consultation/entity.go +++ b/internal/domain/main-entities/consultation/entity.go @@ -15,11 +15,13 @@ type Consultation struct { Encounter *ee.Encounter `json:"encounter" gorm:"foreignKey:Encounter_Id;references:Id"` Date *time.Time `json:"date"` - Problem *string `json:"case" gorm:"size:10240"` - Solution *string `json:"solution" gorm:"size:10240"` - DstUnit_Id *uint `json:"dstUnit_id"` - DstUnit *eu.Unit `json:"dstUnit" gorm:"foreignKey:DstUnit_Id;references:Id"` - DstDoctor_Id *uint `json:"dstDoctor_id"` - DstDoctor *ed.Doctor `json:"dstDoctor" gorm:"foreignKey:DstDoctor_Id;references:Id"` - RepliedAt *time.Time `json:"repliedAt"` + Problem *string `json:"case" gorm:"size:10240"` + Solution *string `json:"solution" gorm:"size:10240"` + DstUnit_Id *uint `json:"dstUnit_id"` + DstUnit_Code *string `json:"dstUnit_code"` + DstUnit *eu.Unit `json:"dstUnit" gorm:"foreignKey:DstUnit_Id;references:Id"` + DstDoctor_Id *uint `json:"dstDoctor_id"` + DstDoctor_Code *string `json:"dstDoctor_code"` + DstDoctor *ed.Doctor `json:"dstDoctor" gorm:"foreignKey:DstDoctor_Id;references:Id"` + RepliedAt *time.Time `json:"repliedAt"` } diff --git a/internal/domain/main-entities/control-letter/entity.go b/internal/domain/main-entities/control-letter/entity.go index abaf4a72..d0bc0a45 100644 --- a/internal/domain/main-entities/control-letter/entity.go +++ b/internal/domain/main-entities/control-letter/entity.go @@ -12,16 +12,20 @@ import ( ) type ControlLetter struct { - ecore.Main // adjust this according to the needs - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter" gorm:"foreignKey:Encounter_Id;references:Id"` - Unit_Id *uint `json:"unit_id"` - Unit *eu.Unit `json:"unit" gorm:"foreignKey:Unit_Id;references:Id"` - Specialist_Id *uint `json:"specialist_id"` - Specialist *es.Specialist `json:"specialist" gorm:"foreignKey:Specialist_Id;references:Id"` - Subspecialist_Id *uint `json:"subspecialist_id"` - Subspecialist *ess.Subspecialist `json:"subspecialist" gorm:"foreignKey:Subspecialist_Id;references:Id"` - Doctor_Id *uint `json:"doctor_id"` - Doctor *ed.Doctor `json:"doctor" gorm:"foreignKey:Doctor_Id;references:Id"` - Date *time.Time `json:"date"` + ecore.Main // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter" gorm:"foreignKey:Encounter_Id;references:Id"` + Unit_Id *uint `json:"unit_id"` + Unit_Code *string `json:"unit_code"` + Unit *eu.Unit `json:"unit" gorm:"foreignKey:Unit_Id;references:Id"` + Specialist_Id *uint `json:"specialist_id"` + Specialist_Code *string `json:"specialist_code"` + Specialist *es.Specialist `json:"specialist" gorm:"foreignKey:Specialist_Id;references:Id"` + Subspecialist_Id *uint `json:"subspecialist_id"` + Subspecialist_Code *string `json:"subspecialist_code"` + Subspecialist *ess.Subspecialist `json:"subspecialist" gorm:"foreignKey:Subspecialist_Id;references:Id"` + Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` + Doctor *ed.Doctor `json:"doctor" gorm:"foreignKey:Doctor_Id;references:Id"` + Date *time.Time `json:"date"` } diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index bfd70333..d3436c7a 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -32,9 +32,11 @@ type Encounter struct { Unit_Id *uint `json:"unit_id"` Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` Specialist_Id *uint16 `json:"specialist_id"` + Specialist_Code *string `json:"specialist_code"` Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Id;references:Id"` Subspecialist_Id *uint16 `json:"subspecialist_id"` Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Id;references:Id"` + Subspecialist_Code *string `json:"subspecialist_code"` VisitDate time.Time `json:"visitDate"` StartedAt *time.Time `json:"startedAt"` FinishedAt *time.Time `json:"finishedAt"` @@ -46,10 +48,12 @@ type Encounter struct { Ref_Number *string `json:"refNumber" gorm:"unique;size:20"` Trx_Number *string `json:"trxNumber" gorm:"unique;size:20"` Appointment_Doctor_Id *uint `json:"appointment_doctor_id"` + Appointment_Doctor_Code *string `json:"appointment_doctor_code"` Appointment_Doctor *ed.Doctor `json:"appointment_doctor,omitempty" gorm:"foreignKey:Appointment_Doctor_Id;references:Id"` Adm_Employee_Id *uint `json:"adm_employee_id"` Adm_Employee *ee.Employee `json:"adm_employee,omitempty" gorm:"foreignKey:Adm_Employee_Id;references:Id"` Responsible_Doctor_Id *uint `json:"responsible_doctor_id"` + Responsible_Doctor_Code *string `json:"responsible_doctor_code"` Responsible_Doctor *ed.Doctor `json:"responsible_doctor,omitempty" gorm:"foreignKey:Responsible_Doctor_Id;references:Id"` Discharge_Method_Code *ere.DischargeMethodCode `json:"discharge_method_code" gorm:"size:16"` RefSource_Name *string `json:"refSource_name" gorm:"size:100"` diff --git a/internal/domain/main-entities/internal-reference/entity.go b/internal/domain/main-entities/internal-reference/entity.go index 060b21aa..71045b09 100644 --- a/internal/domain/main-entities/internal-reference/entity.go +++ b/internal/domain/main-entities/internal-reference/entity.go @@ -12,8 +12,10 @@ type InternalReference struct { ecore.Main Encounter_Id *uint `json:"encounter_id"` Unit_Id *uint16 `json:"unit_id"` + Unit_Code *string `json:"unit_code"` Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` Status_Code *erc.DataApprovalCode `json:"status_code"` } diff --git a/internal/domain/main-entities/practice-schedule/entity.go b/internal/domain/main-entities/practice-schedule/entity.go index 524867c8..213d4495 100644 --- a/internal/domain/main-entities/practice-schedule/entity.go +++ b/internal/domain/main-entities/practice-schedule/entity.go @@ -8,12 +8,13 @@ import ( ) type PracticeSchedule struct { - ecore.Main // adjust this according to the needs - Doctor_Id *uint `json:"doctor_id"` - Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` - Unit_Code *string `json:"unit_code"` - Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` - Day_Code *erc.DayCode `json:"day_code"` - StartTime *string `json:"startTime" gorm:"size:5"` - EndTime *string `json:"endTime" gorm:"size:5"` + ecore.Main // adjust this according to the needs + Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` + Unit_Code *string `json:"unit_code"` + Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` + Day_Code *erc.DayCode `json:"day_code"` + StartTime *string `json:"startTime" gorm:"size:5"` + EndTime *string `json:"endTime" gorm:"size:5"` } diff --git a/internal/domain/main-entities/responsible-doctor-hist/entity.go b/internal/domain/main-entities/responsible-doctor-hist/entity.go index c9df2c13..75aa90f6 100644 --- a/internal/domain/main-entities/responsible-doctor-hist/entity.go +++ b/internal/domain/main-entities/responsible-doctor-hist/entity.go @@ -10,6 +10,7 @@ type ResponsibleDoctorHist struct { ecore.Main // adjust this according to the needs Encounter_Id *uint `json:"encounter_id"` Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` StartedAt *time.Time `json:"startedAt"` FinishedAt *time.Time `json:"finishedAt"` diff --git a/internal/domain/main-entities/therapy-protocol/entity.go b/internal/domain/main-entities/therapy-protocol/entity.go index f5ec318a..a91e18eb 100644 --- a/internal/domain/main-entities/therapy-protocol/entity.go +++ b/internal/domain/main-entities/therapy-protocol/entity.go @@ -13,8 +13,9 @@ type TherapyProtocol struct { Encounter_Id *uint `json:"encounter_id" gorm:"not null"` Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Doctor_Id *uint `json:"doctor_id"` - Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` + Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` Anamnesis *string `json:"anamnesis" gorm:"size:2048"` MedicalDiagnoses *string `json:"medicalDiagnoses"` diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 533b2264..e1643d83 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -802,8 +802,8 @@ func ApproveSwitchUnit(input e.ApproveUnitDto) (*d.Data, error) { // update data response data.Responsible_Doctor_Id = irData.Doctor_Id data.Unit = irData.Unit - data.Specialist_Id = irData.Doctor.Specialist_Id - data.Subspecialist_Id = irData.Doctor.Subspecialist_Id + data.Specialist_Code = irData.Doctor.Specialist_Code + data.Subspecialist_Code = irData.Doctor.Subspecialist_Code pl.SetLogInfo(&event, nil, "complete") return nil diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index 134f5594..8772a2f4 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -4,6 +4,7 @@ import ( // std "errors" eir "simrs-vx/internal/domain/main-entities/internal-reference" + // external dg "github.com/karincake/apem/db-gorm-pg" gh "github.com/karincake/getuk" @@ -333,8 +334,8 @@ func updateEncounterApproveSwitchUnit(input eir.InternalReference, event *pl.Eve Updates(map[string]interface{}{ "Responsible_Doctor_Id": input.Doctor_Id, "Unit_Id": input.Unit_Id, - "Specialist_Id": input.Doctor.Specialist_Id, - "Subspecialist_Id": input.Doctor.Subspecialist_Id, + "Specialist_Code": input.Doctor.Specialist_Code, + "Subspecialist_Code": input.Doctor.Subspecialist_Code, }).Error; err != nil { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ From 363467a8cb7facc2e260c4e39ac1d5f57a96e4b8 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 10 Nov 2025 12:39:13 +0700 Subject: [PATCH 118/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 48 ++++++++++++------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 176a43a0..3db34cf7 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:O5HiMUpKZtVkRc3VxZfFYuLYjUJhPepU5bMnO87FdPI= +h1:hb81CPD5BxIB57EVCP5A2oI+LHYxKAQkq+Q7yeGhbiw= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,26 +75,26 @@ h1:O5HiMUpKZtVkRc3VxZfFYuLYjUJhPepU5bMnO87FdPI= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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:1LkEGCWPe04T3D8F3VMnBP8eJgskrvCggsybNxJ7GuU= +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= From 6d49dca9253be238e0d9ccb21e7521573ab7b775 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 10 Nov 2025 13:25:00 +0700 Subject: [PATCH 119/329] remove several ids and fix constraint --- .../migrations/20251110062042.sql | 14 ++++ cmd/main-migration/migrations/atlas.sum | 49 ++++++------ .../domain/main-entities/consultation/dto.go | 46 +++++------ .../main-entities/consultation/entity.go | 6 +- .../main-entities/control-letter/dto.go | 76 +++++++++---------- .../main-entities/control-letter/entity.go | 12 +-- internal/domain/main-entities/doctor/dto.go | 7 +- .../domain/main-entities/encounter/dto.go | 76 +++++++++---------- .../domain/main-entities/encounter/entity.go | 14 ++-- .../main-entities/internal-reference/dto.go | 16 ++-- .../internal-reference/entity.go | 6 +- internal/domain/main-entities/nurse/dto.go | 7 +- .../main-entities/practice-schedule/dto.go | 40 +++++----- .../main-entities/practice-schedule/entity.go | 3 +- .../responsible-doctor-hist/dto.go | 8 +- .../responsible-doctor-hist/entity.go | 3 +- .../main-entities/therapy-protocol/dto.go | 10 +-- .../main-entities/therapy-protocol/entity.go | 3 +- .../interface/main-handler/doctor/handler.go | 18 ++--- .../encounter/request-validation.go | 12 +-- .../interface/main-handler/nurse/handler.go | 18 ++--- .../main-use-case/consultation/case.go | 11 +-- .../main-use-case/consultation/helper.go | 2 +- .../main-use-case/control-letter/helper.go | 8 +- .../use-case/main-use-case/doctor/case.go | 4 +- internal/use-case/main-use-case/doctor/lib.go | 2 +- .../use-case/main-use-case/encounter/case.go | 30 ++++---- .../main-use-case/encounter/helper.go | 64 ++++++++-------- .../use-case/main-use-case/encounter/lib.go | 8 +- .../internal-reference/helper.go | 8 +- internal/use-case/main-use-case/nurse/case.go | 4 +- internal/use-case/main-use-case/nurse/lib.go | 2 +- .../main-use-case/practice-schedule/helper.go | 2 +- .../responsible-doctor-hist/helper.go | 2 +- .../main-use-case/therapy-protocol/case.go | 6 +- .../main-use-case/therapy-protocol/helper.go | 2 +- 36 files changed, 294 insertions(+), 305 deletions(-) create mode 100644 cmd/main-migration/migrations/20251110062042.sql diff --git a/cmd/main-migration/migrations/20251110062042.sql b/cmd/main-migration/migrations/20251110062042.sql new file mode 100644 index 00000000..9ec62cf7 --- /dev/null +++ b/cmd/main-migration/migrations/20251110062042.sql @@ -0,0 +1,14 @@ +-- Modify "Consultation" table +ALTER TABLE "public"."Consultation" DROP CONSTRAINT "fk_Consultation_DstDoctor", DROP CONSTRAINT "fk_Consultation_DstUnit", DROP COLUMN "DstUnit_Id", DROP COLUMN "DstDoctor_Id", ALTER COLUMN "DstUnit_Code" TYPE character varying(10), ALTER COLUMN "DstDoctor_Code" TYPE character varying(20), ADD CONSTRAINT "fk_Consultation_DstDoctor" FOREIGN KEY ("DstDoctor_Code") REFERENCES "public"."Doctor" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_Consultation_DstUnit" FOREIGN KEY ("DstUnit_Code") REFERENCES "public"."Unit" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "ControlLetter" table +ALTER TABLE "public"."ControlLetter" DROP CONSTRAINT "fk_ControlLetter_Doctor", DROP CONSTRAINT "fk_ControlLetter_Specialist", DROP CONSTRAINT "fk_ControlLetter_Subspecialist", DROP CONSTRAINT "fk_ControlLetter_Unit", DROP COLUMN "Unit_Id", DROP COLUMN "Specialist_Id", DROP COLUMN "Subspecialist_Id", DROP COLUMN "Doctor_Id", ALTER COLUMN "Unit_Code" TYPE character varying(10), ALTER COLUMN "Specialist_Code" TYPE character varying(10), ALTER COLUMN "Subspecialist_Code" TYPE character varying(10), ALTER COLUMN "Doctor_Code" TYPE character varying(20), ADD CONSTRAINT "fk_ControlLetter_Doctor" FOREIGN KEY ("Doctor_Code") REFERENCES "public"."Doctor" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_ControlLetter_Specialist" FOREIGN KEY ("Specialist_Code") REFERENCES "public"."Specialist" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_ControlLetter_Subspecialist" FOREIGN KEY ("Subspecialist_Code") REFERENCES "public"."Subspecialist" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_ControlLetter_Unit" FOREIGN KEY ("Unit_Code") REFERENCES "public"."Unit" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "Encounter" table +ALTER TABLE "public"."Encounter" DROP CONSTRAINT "fk_Encounter_Appointment_Doctor", DROP CONSTRAINT "fk_Encounter_Responsible_Doctor", DROP CONSTRAINT "fk_Encounter_Specialist", DROP CONSTRAINT "fk_Encounter_Subspecialist", DROP COLUMN "Specialist_Id", DROP COLUMN "Subspecialist_Id", DROP COLUMN "Responsible_Doctor_Id", DROP COLUMN "Appointment_Doctor_Id", ALTER COLUMN "Specialist_Code" TYPE character varying(10), ALTER COLUMN "Subspecialist_Code" TYPE character varying(10), ALTER COLUMN "Appointment_Doctor_Code" TYPE character varying(20), ALTER COLUMN "Responsible_Doctor_Code" TYPE character varying(20), ADD COLUMN "Unit_Code" text NULL, ADD COLUMN "InsuranceCompany_Code" text NULL, ADD CONSTRAINT "fk_Encounter_Appointment_Doctor" FOREIGN KEY ("Appointment_Doctor_Code") REFERENCES "public"."Doctor" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_Encounter_Responsible_Doctor" FOREIGN KEY ("Responsible_Doctor_Code") REFERENCES "public"."Doctor" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_Encounter_Specialist" FOREIGN KEY ("Specialist_Code") REFERENCES "public"."Specialist" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_Encounter_Subspecialist" FOREIGN KEY ("Subspecialist_Code") REFERENCES "public"."Subspecialist" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "InternalReference" table +ALTER TABLE "public"."InternalReference" DROP CONSTRAINT "fk_InternalReference_Doctor", DROP CONSTRAINT "fk_InternalReference_Unit", DROP COLUMN "Unit_Id", DROP COLUMN "Doctor_Id", ALTER COLUMN "Unit_Code" TYPE character varying(10), ALTER COLUMN "Doctor_Code" TYPE character varying(20), ADD CONSTRAINT "fk_InternalReference_Doctor" FOREIGN KEY ("Doctor_Code") REFERENCES "public"."Doctor" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_InternalReference_Unit" FOREIGN KEY ("Unit_Code") REFERENCES "public"."Unit" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "PracticeSchedule" table +ALTER TABLE "public"."PracticeSchedule" DROP CONSTRAINT "fk_PracticeSchedule_Doctor", DROP COLUMN "Doctor_Id", ALTER COLUMN "Doctor_Code" TYPE character varying(20), ADD CONSTRAINT "fk_PracticeSchedule_Doctor" FOREIGN KEY ("Doctor_Code") REFERENCES "public"."Doctor" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "ResponsibleDoctorHist" table +ALTER TABLE "public"."ResponsibleDoctorHist" DROP CONSTRAINT "fk_ResponsibleDoctorHist_Doctor", DROP COLUMN "Doctor_Id", ALTER COLUMN "Doctor_Code" TYPE character varying(20), ADD CONSTRAINT "fk_ResponsibleDoctorHist_Doctor" FOREIGN KEY ("Doctor_Code") REFERENCES "public"."Doctor" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "TherapyProtocol" table +ALTER TABLE "public"."TherapyProtocol" DROP CONSTRAINT "fk_TherapyProtocol_Doctor", DROP COLUMN "Doctor_Id", ALTER COLUMN "Doctor_Code" TYPE character varying(20), ADD CONSTRAINT "fk_TherapyProtocol_Doctor" FOREIGN KEY ("Doctor_Code") REFERENCES "public"."Doctor" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 3db34cf7..c64990da 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:hb81CPD5BxIB57EVCP5A2oI+LHYxKAQkq+Q7yeGhbiw= +h1:BX21/eygPEF+JaTDfxN/z3+7YAe6EYWa1EK9N2PKhAE= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,26 +75,27 @@ h1:hb81CPD5BxIB57EVCP5A2oI+LHYxKAQkq+Q7yeGhbiw= 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= +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:1LkEGCWPe04T3D8F3VMnBP8eJgskrvCggsybNxJ7GuU= +20251110062042.sql h1:yUUNX3EekfedaGTt5Q89a0bgZoCu/kfdXLU4iljN5Xw= diff --git a/internal/domain/main-entities/consultation/dto.go b/internal/domain/main-entities/consultation/dto.go index 33868dd0..1b83df77 100644 --- a/internal/domain/main-entities/consultation/dto.go +++ b/internal/domain/main-entities/consultation/dto.go @@ -20,7 +20,7 @@ type CreateDto struct { Encounter_Id *uint `json:"encounter_id"` Date *time.Time `json:"date"` Problem *string `json:"problem" validate:"maxLength=10240"` - DstUnit_Id *uint `json:"dstUnit_id"` + DstUnit_Code *string `json:"dstUnit_code"` } type ReadListDto struct { @@ -30,9 +30,9 @@ type ReadListDto struct { } type FilterDto struct { - Encounter_Id *uint `json:"encounter-id"` - DstUnit_Id *uint `json:"dstUnit-id"` - DstDoctor_Id *uint `json:"dstDoctor-id"` + Encounter_Id *uint `json:"encounter-id"` + DstUnit_Code *string `json:"dstUnit-code"` + DstDoctor_Code *string `json:"dstDoctor-code"` } type ReadDetailDto struct { @@ -63,29 +63,29 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty"` - Date *time.Time `json:"date"` - Problem *string `json:"problem"` - Solution *string `json:"solution"` - DstUnit_Id *uint `json:"dstUnit_id"` - DstUnit *eu.Unit `json:"dstUnit,omitempty"` - DstDoctor_Id *uint `json:"dstDoctor_id"` - DstDoctor *ed.Doctor `json:"dstDoctor,omitempty"` - RepliedAt *time.Time `json:"repliedAt"` + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty"` + Date *time.Time `json:"date"` + Problem *string `json:"problem"` + Solution *string `json:"solution"` + DstUnit_Code *string `json:"dstUnit_code"` + DstUnit *eu.Unit `json:"dstUnit,omitempty"` + DstDoctor_Code *string `json:"dstDoctor_code"` + DstDoctor *ed.Doctor `json:"dstDoctor,omitempty"` + RepliedAt *time.Time `json:"repliedAt"` } func (d Consultation) ToResponse() ResponseDto { resp := ResponseDto{ - Encounter_Id: d.Encounter_Id, - Encounter: d.Encounter, - Date: d.Date, - Problem: d.Problem, - Solution: d.Solution, - DstUnit_Id: d.DstUnit_Id, - DstUnit: d.DstUnit, - DstDoctor_Id: d.DstDoctor_Id, - DstDoctor: d.DstDoctor, + Encounter_Id: d.Encounter_Id, + Encounter: d.Encounter, + Date: d.Date, + Problem: d.Problem, + Solution: d.Solution, + DstUnit_Code: d.DstUnit_Code, + DstUnit: d.DstUnit, + DstDoctor_Code: d.DstDoctor_Code, + DstDoctor: d.DstDoctor, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/consultation/entity.go b/internal/domain/main-entities/consultation/entity.go index 06a44d57..b8be3596 100644 --- a/internal/domain/main-entities/consultation/entity.go +++ b/internal/domain/main-entities/consultation/entity.go @@ -17,11 +17,9 @@ type Consultation struct { Problem *string `json:"case" gorm:"size:10240"` Solution *string `json:"solution" gorm:"size:10240"` - DstUnit_Id *uint `json:"dstUnit_id"` DstUnit_Code *string `json:"dstUnit_code"` - DstUnit *eu.Unit `json:"dstUnit" gorm:"foreignKey:DstUnit_Id;references:Id"` - DstDoctor_Id *uint `json:"dstDoctor_id"` + DstUnit *eu.Unit `json:"dstUnit" gorm:"foreignKey:DstUnit_Code;references:Code"` DstDoctor_Code *string `json:"dstDoctor_code"` - DstDoctor *ed.Doctor `json:"dstDoctor" gorm:"foreignKey:DstDoctor_Id;references:Id"` + DstDoctor *ed.Doctor `json:"dstDoctor" gorm:"foreignKey:DstDoctor_Code;references:Code"` RepliedAt *time.Time `json:"repliedAt"` } diff --git a/internal/domain/main-entities/control-letter/dto.go b/internal/domain/main-entities/control-letter/dto.go index c2bab776..87b82366 100644 --- a/internal/domain/main-entities/control-letter/dto.go +++ b/internal/domain/main-entities/control-letter/dto.go @@ -5,7 +5,6 @@ import ( "time" // internal - lib - pa "simrs-vx/internal/lib/auth" // internal - domain - base-entities ecore "simrs-vx/internal/domain/base-entities/core" @@ -20,12 +19,12 @@ import ( ) type CreateDto struct { - Encounter_Id *uint `json:"encounter_id"` - Unit_Id *uint `json:"unit_id"` - Specialist_Id *uint `json:"specialist_id"` - Subspecialist_Id *uint `json:"subspecialist_id"` - Doctor_Id *uint `json:"doctor_id"` - Date *time.Time `json:"date"` + Encounter_Id *uint `json:"encounter_id"` + Unit_Code *string `json:"unit_code"` + Specialist_Code *string `json:"specialist_code"` + Subspecialist_Code *string `json:"subspecialist_code"` + Doctor_Code *string `json:"doctor_code"` + Date *time.Time `json:"date"` } type ReadListDto struct { @@ -35,12 +34,12 @@ type ReadListDto struct { } type FilterDto struct { - Encounter_Id *uint `json:"encounter-id"` - Unit_Id *uint `json:"unit-id"` - Specialist_Id *uint `json:"specialist-id"` - Subspecialist_Id *uint `json:"subspecialist-id"` - Doctor_Id *uint `json:"doctor-id"` - Date *time.Time `json:"date"` + Encounter_Id *uint `json:"encounter-id"` + Unit_Code *string `json:"unit-code"` + Specialist_Code *string `json:"specialist-code"` + Subspecialist_Code *string `json:"subspecialist-code"` + Doctor_Code *string `json:"doctor-code"` + Date *time.Time `json:"date"` } type ReadDetailDto struct { @@ -57,13 +56,6 @@ type DeleteDto struct { Id uint `json:"id"` } -type ReplyDto struct { - Id uint `json:"id"` - Solution *string `json:"solution"` - - pa.AuthInfo -} - type MetaDto struct { PageNumber int `json:"page_number"` PageSize int `json:"page_size"` @@ -72,32 +64,32 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty"` - Unit_Id *uint `json:"unit_id"` - Unit *eu.Unit `json:"unit,omitempty"` - Specialist_Id *uint `json:"specialist_id"` - Specialist *es.Specialist `json:"specialist,omitempty"` - Subspecialist_Id *uint `json:"subspecialist_id"` - Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty"` - Doctor_Id *uint `json:"doctor_id"` - Doctor *ed.Doctor `json:"doctor,omitempty"` - Date *time.Time `json:"date"` + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty"` + Unit_Code *string `json:"unit_code"` + Unit *eu.Unit `json:"unit,omitempty"` + Specialist_Code *string `json:"specialist_code"` + Specialist *es.Specialist `json:"specialist,omitempty"` + Subspecialist_Code *string `json:"subspecialist_code"` + Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty"` + Doctor_Code *string `json:"doctor_code"` + Doctor *ed.Doctor `json:"doctor,omitempty"` + Date *time.Time `json:"date"` } func (d ControlLetter) ToResponse() ResponseDto { resp := ResponseDto{ - Encounter_Id: d.Encounter_Id, - Encounter: d.Encounter, - Unit_Id: d.Unit_Id, - Unit: d.Unit, - Specialist_Id: d.Specialist_Id, - Specialist: d.Specialist, - Subspecialist_Id: d.Subspecialist_Id, - Subspecialist: d.Subspecialist, - Doctor_Id: d.Doctor_Id, - Doctor: d.Doctor, - Date: d.Date, + Encounter_Id: d.Encounter_Id, + Encounter: d.Encounter, + Unit_Code: d.Unit_Code, + Unit: d.Unit, + Specialist_Code: d.Specialist_Code, + Specialist: d.Specialist, + Subspecialist_Code: d.Subspecialist_Code, + Subspecialist: d.Subspecialist, + Doctor_Code: d.Doctor_Code, + Doctor: d.Doctor, + Date: d.Date, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/control-letter/entity.go b/internal/domain/main-entities/control-letter/entity.go index d0bc0a45..2b8019b4 100644 --- a/internal/domain/main-entities/control-letter/entity.go +++ b/internal/domain/main-entities/control-letter/entity.go @@ -15,17 +15,13 @@ type ControlLetter struct { ecore.Main // adjust this according to the needs Encounter_Id *uint `json:"encounter_id"` Encounter *ee.Encounter `json:"encounter" gorm:"foreignKey:Encounter_Id;references:Id"` - Unit_Id *uint `json:"unit_id"` Unit_Code *string `json:"unit_code"` - Unit *eu.Unit `json:"unit" gorm:"foreignKey:Unit_Id;references:Id"` - Specialist_Id *uint `json:"specialist_id"` + Unit *eu.Unit `json:"unit" gorm:"foreignKey:Unit_Code;references:Code"` Specialist_Code *string `json:"specialist_code"` - Specialist *es.Specialist `json:"specialist" gorm:"foreignKey:Specialist_Id;references:Id"` - Subspecialist_Id *uint `json:"subspecialist_id"` + Specialist *es.Specialist `json:"specialist" gorm:"foreignKey:Specialist_Code;references:Code"` Subspecialist_Code *string `json:"subspecialist_code"` - Subspecialist *ess.Subspecialist `json:"subspecialist" gorm:"foreignKey:Subspecialist_Id;references:Id"` - Doctor_Id *uint `json:"doctor_id"` + Subspecialist *ess.Subspecialist `json:"subspecialist" gorm:"foreignKey:Subspecialist_Code;references:Code"` Doctor_Code *string `json:"doctor_code"` - Doctor *ed.Doctor `json:"doctor" gorm:"foreignKey:Doctor_Id;references:Id"` + Doctor *ed.Doctor `json:"doctor" gorm:"foreignKey:Doctor_Code;references:Code"` Date *time.Time `json:"date"` } diff --git a/internal/domain/main-entities/doctor/dto.go b/internal/domain/main-entities/doctor/dto.go index 67290551..e3d1f3ee 100644 --- a/internal/domain/main-entities/doctor/dto.go +++ b/internal/domain/main-entities/doctor/dto.go @@ -38,7 +38,7 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` Employee_Id *uint `json:"employee_id"` IHS_Number *string `json:"ihs_number"` @@ -46,12 +46,13 @@ type ReadDetailDto struct { } type UpdateDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` CreateDto } type DeleteDto struct { - Id uint `json:"id"` + Id uint `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index 966a53d3..7ac57b07 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -33,27 +33,27 @@ 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_Id *uint16 `json:"infra_id"` // for inpatient - Unit_Id *uint `json:"unit_id"` - Specialist_Id *uint16 `json:"specialist_id"` - Subspecialist_Id *uint16 `json:"subspecialist_id"` - VisitDate time.Time `json:"visitDate"` - PaymentMethod_Code erc.PaymentMethodCode `json:"paymentMethod_code" gorm:"size:10"` - InsuranceCompany_Id *uint `json:"insuranceCompany_id"` - 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_Id *uint `json:"appointment_doctor_id"` - Adm_Employee_Id *uint `json:"-"` - Responsible_Doctor_Id *uint `json:"responsible_doctor_id"` - RefSource_Name *string `json:"refSource_name" validate:"maxLength=100"` - Appointment_Id *uint `json:"appointment_id"` - RefTypeCode ere.RefTypeCode `json:"refTypeCode"` - NewStatus bool `json:"newStatus"` + 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_Id *uint16 `json:"infra_id"` // for inpatient + Unit_Id *uint `json:"unit_id"` + Specialist_Code *string `json:"specialist_code"` + Subspecialist_Code *string `json:"subspecialist_code"` + VisitDate time.Time `json:"visitDate"` + PaymentMethod_Code erc.PaymentMethodCode `json:"paymentMethod_code" gorm:"size:10"` + InsuranceCompany_Id *uint `json:"insuranceCompany_id"` + 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"` Id uint `json:"-"` RecentEncounterAdm *Encounter `json:"-"` // if subClass_Code is rehab @@ -76,11 +76,11 @@ type FilterDto struct { RegisteredAt *time.Time `json:"registeredAt"` Class_Code ere.EncounterClassCode `json:"class-code" validate:"maxLength=10"` Unit_Id *uint `json:"unit-id"` - Specialist_Id *uint16 `json:"specialist-id"` - Subspecialist_Id *uint16 `json:"subspecialist-id"` + Specialist_Code *string `json:"specialist-code"` + Subspecialist_Code *string `json:"subspecialist-code"` VisitDate time.Time `json:"visitDate"` - Appoinment_Doctor_Id *uint `json:"appointment-doctor-id"` - Responsible_Doctor_Id *uint `json:"responsible-doctor-id"` + Appoinment_Doctor_Code *string `json:"appointment-doctor-code"` + Responsible_Doctor_Code *string `json:"responsible-doctor-code"` DischargeMethod_Code ere.DischargeMethodCode `json:"dischargeMethod-code" validate:"maxLength=10"` RefSource_Name *string `json:"refSource-name" validate:"maxLength=100"` Appointment_Id *uint `json:"appointment-id"` @@ -125,11 +125,11 @@ type DischargeDto struct { } type CheckinDto struct { - Id uint `json:"id"` - Responsible_Doctor_Id *uint `json:"responsible_doctor_id"` - Adm_Employee_Id *uint `json:"adm_employee_id"` - StartedAt *time.Time `json:"startedAt"` - FinishedAt *time.Time `json:"finishedAt"` + Id uint `json:"id"` + Responsible_Doctor_Code *string `json:"responsible_doctor_code"` + Adm_Employee_Id *uint `json:"adm_employee_id"` + StartedAt *time.Time `json:"startedAt"` + FinishedAt *time.Time `json:"finishedAt"` } type SwitchUnitDto struct { @@ -150,9 +150,9 @@ type ResponseDto struct { RegisteredAt *time.Time `json:"registeredAt"` Class_Code ere.EncounterClassCode `json:"class_code"` Unit_Id *uint `json:"unit_id"` - Specialist_Id *uint16 `json:"specialist_id"` + Specialist_Code *string `json:"specialist_code"` Specialist *es.Specialist `json:"specialist,omitempty"` - Subspecialist_Id *uint16 `json:"subspecialist_id"` + Subspecialist_Code *string `json:"subspecialist_code"` Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty"` Unit *eu.Unit `json:"unit,omitempty"` VisitDate time.Time `json:"visitDate"` @@ -161,9 +161,9 @@ type ResponseDto struct { Member_Number *string `json:"member_number"` Ref_Number *string `json:"ref_number"` Trx_Number *string `json:"trx_number"` - Appointment_Doctor_Id *uint `json:"appointment_doctor_id"` + Appointment_Doctor_Code *string `json:"appointment_doctor_code"` Appointment_Doctor *ed.Doctor `json:"appointment_doctor,omitempty"` - Responsible_Doctor_Id *uint `json:"responsible_doctor_id"` + Responsible_Doctor_Code *string `json:"responsible_doctor_code"` Responsible_Doctor *ed.Doctor `json:"responsible_doctor,omitempty"` Adm_Employee_Id *uint `json:"adm_employee_id"` Adm_Employee *ee.Employee `json:"adm_employee,omitempty"` @@ -198,9 +198,9 @@ func (d Encounter) ToResponse() ResponseDto { Class_Code: d.Class_Code, Unit_Id: d.Unit_Id, Unit: d.Unit, - Specialist_Id: d.Specialist_Id, + Specialist_Code: d.Specialist_Code, Specialist: d.Specialist, - Subspecialist_Id: d.Subspecialist_Id, + Subspecialist_Code: d.Subspecialist_Code, Subspecialist: d.Subspecialist, VisitDate: d.VisitDate, PaymentMethod_Code: d.PaymentMethod_Code, @@ -208,11 +208,11 @@ func (d Encounter) ToResponse() ResponseDto { Member_Number: d.Member_Number, Ref_Number: d.Ref_Number, Trx_Number: d.Trx_Number, - Appointment_Doctor_Id: d.Appointment_Doctor_Id, + Appointment_Doctor_Code: d.Appointment_Doctor_Code, Appointment_Doctor: d.Appointment_Doctor, Adm_Employee_Id: d.Adm_Employee_Id, Adm_Employee: d.Adm_Employee, - Responsible_Doctor_Id: d.Responsible_Doctor_Id, + Responsible_Doctor_Code: d.Responsible_Doctor_Code, Responsible_Doctor: d.Responsible_Doctor, Discharge_Method_Code: d.Discharge_Method_Code, RefSource_Name: d.RefSource_Name, diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index d3436c7a..e07b2263 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -30,31 +30,29 @@ type Encounter struct { RegisteredAt *time.Time `json:"registeredAt"` Class_Code ere.EncounterClassCode `json:"class_code" gorm:"not null;size:10"` Unit_Id *uint `json:"unit_id"` + Unit_Code *string `json:"unit_code"` Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` - Specialist_Id *uint16 `json:"specialist_id"` Specialist_Code *string `json:"specialist_code"` - Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Id;references:Id"` - Subspecialist_Id *uint16 `json:"subspecialist_id"` - Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Id;references:Id"` + Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Code;references:Code"` Subspecialist_Code *string `json:"subspecialist_code"` + Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Code;references:Code"` VisitDate time.Time `json:"visitDate"` StartedAt *time.Time `json:"startedAt"` FinishedAt *time.Time `json:"finishedAt"` PaymentMethod_Code erc.PaymentMethodCode `json:"paymentMethod_code" gorm:"size:10"` InsuranceCompany_Id *uint `json:"insuranceCompany_id"` + InsuranceCompany_Code *string `json:"insuranceCompany_code"` InsuranceCompany *ei.InsuranceCompany `json:"insuranceCompany,omitempty" gorm:"foreignKey:InsuranceCompany_Id;references:Id"` Member_Number *string `json:"memberNumber" gorm:"unique;size:20"` RefType_Code *ere.RefTypeCode `json:"refType_code"` Ref_Number *string `json:"refNumber" gorm:"unique;size:20"` Trx_Number *string `json:"trxNumber" gorm:"unique;size:20"` - Appointment_Doctor_Id *uint `json:"appointment_doctor_id"` Appointment_Doctor_Code *string `json:"appointment_doctor_code"` - Appointment_Doctor *ed.Doctor `json:"appointment_doctor,omitempty" gorm:"foreignKey:Appointment_Doctor_Id;references:Id"` + Appointment_Doctor *ed.Doctor `json:"appointment_doctor,omitempty" gorm:"foreignKey:Appointment_Doctor_Code;references:Code"` Adm_Employee_Id *uint `json:"adm_employee_id"` Adm_Employee *ee.Employee `json:"adm_employee,omitempty" gorm:"foreignKey:Adm_Employee_Id;references:Id"` - Responsible_Doctor_Id *uint `json:"responsible_doctor_id"` Responsible_Doctor_Code *string `json:"responsible_doctor_code"` - Responsible_Doctor *ed.Doctor `json:"responsible_doctor,omitempty" gorm:"foreignKey:Responsible_Doctor_Id;references:Id"` + Responsible_Doctor *ed.Doctor `json:"responsible_doctor,omitempty" gorm:"foreignKey:Responsible_Doctor_Code;references:Code"` Discharge_Method_Code *ere.DischargeMethodCode `json:"discharge_method_code" gorm:"size:16"` RefSource_Name *string `json:"refSource_name" gorm:"size:100"` Appointment_Id *uint `json:"appointment_id"` diff --git a/internal/domain/main-entities/internal-reference/dto.go b/internal/domain/main-entities/internal-reference/dto.go index c957d60b..08eaaac2 100644 --- a/internal/domain/main-entities/internal-reference/dto.go +++ b/internal/domain/main-entities/internal-reference/dto.go @@ -10,8 +10,8 @@ import ( type CreateDto struct { Encounter_Id *uint `json:"-"` - Unit_Id *uint16 `json:"unit_id"` - Doctor_Id *uint `json:"doctor_Id"` + Unit_Code *string `json:"unit_code"` + Doctor_Code *string `json:"doctor_code"` Status_Code erc.DataApprovalCode `json:"status_code"` } @@ -23,8 +23,8 @@ type ReadListDto struct { type FilterDto struct { Encounter_Id *uint `json:"encounter-id"` - Unit_Id *uint `json:"unit-id"` - Doctor_Id *uint `json:"doctor-id"` + Unit_Code *uint `json:"unit-code"` + Doctor_Code *uint `json:"doctor-code"` Status_Code erc.DataApprovalCode `json:"status-code"` } @@ -51,9 +51,9 @@ type MetaDto struct { type ResponseDto struct { ecore.Main Encounter_Id *uint `json:"encounter_id"` - Unit_Id *uint16 `json:"unit_id"` + Unit_Code *string `json:"unit_id"` Unit *eu.Unit `json:"unit,omitempty"` - Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_id"` Doctor *ed.Doctor `json:"doctor,omitempty"` Status_Code *erc.DataApprovalCode `json:"status_code"` } @@ -61,9 +61,9 @@ type ResponseDto struct { func (d InternalReference) ToResponse() ResponseDto { resp := ResponseDto{ Encounter_Id: d.Encounter_Id, - Unit_Id: d.Unit_Id, + Unit_Code: d.Unit_Code, Unit: d.Unit, - Doctor_Id: d.Doctor_Id, + Doctor_Code: d.Doctor_Code, Doctor: d.Doctor, Status_Code: d.Status_Code, } diff --git a/internal/domain/main-entities/internal-reference/entity.go b/internal/domain/main-entities/internal-reference/entity.go index 71045b09..ae6307bb 100644 --- a/internal/domain/main-entities/internal-reference/entity.go +++ b/internal/domain/main-entities/internal-reference/entity.go @@ -11,11 +11,9 @@ import ( type InternalReference struct { ecore.Main Encounter_Id *uint `json:"encounter_id"` - Unit_Id *uint16 `json:"unit_id"` Unit_Code *string `json:"unit_code"` - Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` - Doctor_Id *uint `json:"doctor_id"` + Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` Doctor_Code *string `json:"doctor_code"` - Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"` Status_Code *erc.DataApprovalCode `json:"status_code"` } diff --git a/internal/domain/main-entities/nurse/dto.go b/internal/domain/main-entities/nurse/dto.go index f48014dd..b0cd6104 100644 --- a/internal/domain/main-entities/nurse/dto.go +++ b/internal/domain/main-entities/nurse/dto.go @@ -29,19 +29,20 @@ type FilterDto struct { Infra_Code *string `json:"infra-code"` } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` Employee_Id *uint `json:"employee_id"` IHS_Number *string `json:"ihs_number"` } type UpdateDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` CreateDto } type DeleteDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/domain/main-entities/practice-schedule/dto.go b/internal/domain/main-entities/practice-schedule/dto.go index 00eea2ad..832bc29d 100644 --- a/internal/domain/main-entities/practice-schedule/dto.go +++ b/internal/domain/main-entities/practice-schedule/dto.go @@ -6,11 +6,11 @@ import ( ) type CreateDto struct { - Doctor_Id *uint `json:"doctor_id"` - Unit_Code *string `json:"unit_code"` - Day_Code *erc.DayCode `json:"day_code"` - StartTime *string `json:"startTime" validate:"maxLength=5"` - EndTime *string `json:"endTime" validate:"maxLength=5"` + Doctor_Code *string `json:"doctor_code"` + Unit_Code *string `json:"unit_code"` + Day_Code *erc.DayCode `json:"day_code"` + StartTime *string `json:"startTime" validate:"maxLength=5"` + EndTime *string `json:"endTime" validate:"maxLength=5"` } type ReadListDto struct { @@ -20,11 +20,11 @@ type ReadListDto struct { } type FilterDto struct { - Doctor_Id *uint `json:"doctor-id"` - Unit_Code *string `json:"unit-code"` - Day_Code *erc.DayCode `json:"day-code"` - StartTime *string `json:"startTime"` - EndTime *string `json:"endTime"` + Doctor_Code *string `json:"doctor-code"` + Unit_Code *string `json:"unit-code"` + Day_Code *erc.DayCode `json:"day-code"` + StartTime *string `json:"startTime"` + EndTime *string `json:"endTime"` } type ReadDetailDto struct { @@ -48,20 +48,20 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Doctor_Id *uint `json:"doctor_id"` - Unit_Code *string `json:"unit_code"` - Day_Code *erc.DayCode `json:"day_code"` - StartTime *string `json:"startTime"` - EndTime *string `json:"endTime"` + Doctor_Code *string `json:"doctor_code"` + Unit_Code *string `json:"unit_code"` + Day_Code *erc.DayCode `json:"day_code"` + StartTime *string `json:"startTime"` + EndTime *string `json:"endTime"` } func (d PracticeSchedule) ToResponse() ResponseDto { resp := ResponseDto{ - Doctor_Id: d.Doctor_Id, - Unit_Code: d.Unit_Code, - Day_Code: d.Day_Code, - StartTime: d.StartTime, - EndTime: d.EndTime, + Doctor_Code: d.Doctor_Code, + Unit_Code: d.Unit_Code, + Day_Code: d.Day_Code, + StartTime: d.StartTime, + EndTime: d.EndTime, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/practice-schedule/entity.go b/internal/domain/main-entities/practice-schedule/entity.go index 213d4495..84ea3296 100644 --- a/internal/domain/main-entities/practice-schedule/entity.go +++ b/internal/domain/main-entities/practice-schedule/entity.go @@ -9,9 +9,8 @@ import ( type PracticeSchedule struct { ecore.Main // adjust this according to the needs - Doctor_Id *uint `json:"doctor_id"` Doctor_Code *string `json:"doctor_code"` - Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"` Unit_Code *string `json:"unit_code"` Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` Day_Code *erc.DayCode `json:"day_code"` diff --git a/internal/domain/main-entities/responsible-doctor-hist/dto.go b/internal/domain/main-entities/responsible-doctor-hist/dto.go index 68c8dd21..c96c588c 100644 --- a/internal/domain/main-entities/responsible-doctor-hist/dto.go +++ b/internal/domain/main-entities/responsible-doctor-hist/dto.go @@ -8,7 +8,7 @@ import ( type CreateDto struct { Encounter_Id *uint `json:"encounter_id"` - Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` StartedAt *time.Time `json:"startedAt"` FinishedAt *time.Time `json:"finishedAt"` } @@ -22,7 +22,7 @@ type ReadListDto struct { type FilterDto struct { Encounter_Id *uint `json:"encounter-id"` - Doctor_Id *uint `json:"doctor-id"` + Doctor_Code *string `json:"doctor-code"` StartedAt *time.Time `json:"startedAt"` FinishedAt *time.Time `json:"finishedAt"` } @@ -50,7 +50,7 @@ type MetaDto struct { type ResponseDto struct { ecore.Main // adjust this according to the needs Encounter_Id *uint `json:"encounter_id"` - Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` Doctor *ed.Doctor `json:"doctor,omitempty"` StartedAt *time.Time `json:"startedAt"` FinishedAt *time.Time `json:"finishedAt"` @@ -59,7 +59,7 @@ type ResponseDto struct { func (d ResponsibleDoctorHist) ToResponse() ResponseDto { resp := ResponseDto{ Encounter_Id: d.Encounter_Id, - Doctor_Id: d.Doctor_Id, + Doctor_Code: d.Doctor_Code, Doctor: d.Doctor, StartedAt: d.StartedAt, FinishedAt: d.FinishedAt, diff --git a/internal/domain/main-entities/responsible-doctor-hist/entity.go b/internal/domain/main-entities/responsible-doctor-hist/entity.go index 75aa90f6..d9b4946c 100644 --- a/internal/domain/main-entities/responsible-doctor-hist/entity.go +++ b/internal/domain/main-entities/responsible-doctor-hist/entity.go @@ -9,9 +9,8 @@ import ( type ResponsibleDoctorHist struct { ecore.Main // adjust this according to the needs Encounter_Id *uint `json:"encounter_id"` - Doctor_Id *uint `json:"doctor_id"` Doctor_Code *string `json:"doctor_code"` - Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"` StartedAt *time.Time `json:"startedAt"` FinishedAt *time.Time `json:"finishedAt"` } diff --git a/internal/domain/main-entities/therapy-protocol/dto.go b/internal/domain/main-entities/therapy-protocol/dto.go index f7a5f2e4..40633b89 100644 --- a/internal/domain/main-entities/therapy-protocol/dto.go +++ b/internal/domain/main-entities/therapy-protocol/dto.go @@ -9,7 +9,7 @@ import ( type CreateDto struct { Encounter_Id *uint `json:"encounter_id"` - Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` Anamnesis *string `json:"anamnesis" validate:"maxLength=2048"` MedicalDiagnoses *string `json:"medicalDiagnoses"` FunctionDiagnoses *string `json:"functionDiagnoses"` @@ -31,8 +31,8 @@ type ReadListDto struct { } type FilterDto struct { - Encounter_Id *uint `json:"encounter-id"` - Doctor_Id *uint `json:"doctor-id"` + Encounter_Id *uint `json:"encounter-id"` + Doctor_Code *string `json:"doctor-code"` } type ReadDetailDto struct { @@ -59,7 +59,7 @@ type ResponseDto struct { ecore.Main Encounter_Id *uint `json:"encounter_id"` Encounter *ee.Encounter `json:"encounter,omitempty"` - Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` Doctor *ed.Doctor `json:"doctor,omitempty"` Anamnesis *string `json:"anamnesis"` MedicalDiagnoses *string `json:"medicalDiagnoses"` @@ -79,7 +79,7 @@ func (d TherapyProtocol) ToResponse() ResponseDto { resp := ResponseDto{ Encounter_Id: d.Encounter_Id, Encounter: d.Encounter, - Doctor_Id: d.Doctor_Id, + Doctor_Code: d.Doctor_Code, Doctor: d.Doctor, Anamnesis: d.Anamnesis, MedicalDiagnoses: d.MedicalDiagnoses, diff --git a/internal/domain/main-entities/therapy-protocol/entity.go b/internal/domain/main-entities/therapy-protocol/entity.go index a91e18eb..7caaf0a6 100644 --- a/internal/domain/main-entities/therapy-protocol/entity.go +++ b/internal/domain/main-entities/therapy-protocol/entity.go @@ -13,9 +13,8 @@ type TherapyProtocol struct { Encounter_Id *uint `json:"encounter_id" gorm:"not null"` Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Doctor_Id *uint `json:"doctor_id"` Doctor_Code *string `json:"doctor_code"` - Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"` Anamnesis *string `json:"anamnesis" gorm:"size:2048"` MedicalDiagnoses *string `json:"medicalDiagnoses"` diff --git a/internal/interface/main-handler/doctor/handler.go b/internal/interface/main-handler/doctor/handler.go index ee1252ad..f62495d6 100644 --- a/internal/interface/main-handler/doctor/handler.go +++ b/internal/interface/main-handler/doctor/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "code", r.PathValue("code")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "code", r.PathValue("code")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint(id) + dto.Code = &code res, err := u.Update(dto) rw.DataResponse(w, res, err) } func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "code", r.PathValue("code")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/encounter/request-validation.go b/internal/interface/main-handler/encounter/request-validation.go index be370074..79cc832c 100644 --- a/internal/interface/main-handler/encounter/request-validation.go +++ b/internal/interface/main-handler/encounter/request-validation.go @@ -47,10 +47,10 @@ func validateRequestCheckout(w http.ResponseWriter, i e.DischargeDto) (valid boo } func validateRequestCheckIn(w http.ResponseWriter, i e.CheckinDto) (valid bool) { - if i.Responsible_Doctor_Id == nil { + if i.Responsible_Doctor_Code == nil { rw.DataResponse(w, nil, d.FieldError{ Code: dataValidationFail, - Message: "responsible_doctor_id required", + Message: "responsible_doctor_code required", }) return } @@ -68,18 +68,18 @@ func validateRequestSwitchUnit(w http.ResponseWriter, i e.SwitchUnitDto) (valid } for _, v := range *i.InternalReferences { - if v.Unit_Id == nil { + if v.Unit_Code == nil { rw.DataResponse(w, nil, d.FieldError{ Code: dataValidationFail, - Message: "internalReferences.unit_id required", + Message: "internalReferences.unit_code required", }) return } - if v.Doctor_Id == nil { + if v.Doctor_Code == nil { rw.DataResponse(w, nil, d.FieldError{ Code: dataValidationFail, - Message: "internalReferences.doctor_id required", + Message: "internalReferences.doctor_code required", }) return } diff --git a/internal/interface/main-handler/nurse/handler.go b/internal/interface/main-handler/nurse/handler.go index 8817ae14..b8252892 100644 --- a/internal/interface/main-handler/nurse/handler.go +++ b/internal/interface/main-handler/nurse/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "code", r.PathValue("code")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "code", r.PathValue("code")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint(id) + dto.Code = &code res, err := u.Update(dto) rw.DataResponse(w, res, err) } func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "code", r.PathValue("code")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/use-case/main-use-case/consultation/case.go b/internal/use-case/main-use-case/consultation/case.go index 3cda31d9..25306169 100644 --- a/internal/use-case/main-use-case/consultation/case.go +++ b/internal/use-case/main-use-case/consultation/case.go @@ -7,8 +7,6 @@ import ( e "simrs-vx/internal/domain/main-entities/consultation" ue "simrs-vx/internal/use-case/main-use-case/encounter" - ud "simrs-vx/internal/use-case/main-use-case/doctor" - dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -314,12 +312,7 @@ func Reply(input e.ReplyDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - doctor_id, err := ud.GetIdByUserId(&input.AuthInfo.User_Id, &event, tx) - if err != nil { - return err - } - - if data.DstDoctor_Id != nil && data.DstDoctor_Id != doctor_id { + if data.DstDoctor_Code != nil && data.DstDoctor_Code != input.AuthInfo.Doctor_Code { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "data-handled-mismatch", @@ -329,7 +322,7 @@ func Reply(input e.ReplyDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - data.DstDoctor_Id = doctor_id + data.DstDoctor_Code = input.AuthInfo.Doctor_Code data.Solution = input.Solution data.RepliedAt = pu.GetTimeNow() err = tx.Save(&data).Error diff --git a/internal/use-case/main-use-case/consultation/helper.go b/internal/use-case/main-use-case/consultation/helper.go index 519c3c91..3a518c77 100644 --- a/internal/use-case/main-use-case/consultation/helper.go +++ b/internal/use-case/main-use-case/consultation/helper.go @@ -20,5 +20,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Consultation) { data.Encounter_Id = inputSrc.Encounter_Id data.Date = inputSrc.Date data.Problem = inputSrc.Problem - data.DstUnit_Id = inputSrc.DstUnit_Id + data.DstUnit_Code = inputSrc.DstUnit_Code } diff --git a/internal/use-case/main-use-case/control-letter/helper.go b/internal/use-case/main-use-case/control-letter/helper.go index 5cc943c5..8ae71d3c 100644 --- a/internal/use-case/main-use-case/control-letter/helper.go +++ b/internal/use-case/main-use-case/control-letter/helper.go @@ -18,9 +18,9 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.ControlLetter) { } data.Encounter_Id = inputSrc.Encounter_Id - data.Unit_Id = inputSrc.Unit_Id - data.Specialist_Id = inputSrc.Specialist_Id - data.Subspecialist_Id = inputSrc.Subspecialist_Id - data.Doctor_Id = inputSrc.Doctor_Id + data.Unit_Code = inputSrc.Unit_Code + data.Specialist_Code = inputSrc.Specialist_Code + data.Subspecialist_Code = inputSrc.Subspecialist_Code + data.Doctor_Code = inputSrc.Doctor_Code data.Date = inputSrc.Date } diff --git a/internal/use-case/main-use-case/doctor/case.go b/internal/use-case/main-use-case/doctor/case.go index 74337056..cab7facc 100644 --- a/internal/use-case/main-use-case/doctor/case.go +++ b/internal/use-case/main-use-case/doctor/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Doctor var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Doctor var err error diff --git a/internal/use-case/main-use-case/doctor/lib.go b/internal/use-case/main-use-case/doctor/lib.go index 3355bb3c..12b62176 100644 --- a/internal/use-case/main-use-case/doctor/lib.go +++ b/internal/use-case/main-use-case/doctor/lib.go @@ -84,7 +84,7 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e if input.Employee_Id != nil { tx = tx.Where("\"Employee_Id\" = ?", *input.Employee_Id) } - if input.Id > 0 { + if input.Id != nil { tx = tx.Where("\"Id\" = ?", input.Id) } if err := tx.First(&data).Error; err != nil { diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index e1643d83..3a8c3b82 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -574,11 +574,11 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { } // Upsert responsible_doctor_hist if responsible_doctor_id has changed - if data.Responsible_Doctor_Id == nil || *input.Responsible_Doctor_Id != *data.Responsible_Doctor_Id { + if data.Responsible_Doctor_Code == nil || *input.Responsible_Doctor_Code != *data.Responsible_Doctor_Code { // upsert responsibleDoctorHist if err = upsertResponsibleDoctorHist(erdh.CreateDto{ Encounter_Id: &data.Id, - Doctor_Id: input.Responsible_Doctor_Id, + Doctor_Code: input.Responsible_Doctor_Code, StartedAt: input.StartedAt, }, &event, tx); err != nil { return err @@ -634,24 +634,24 @@ func RequestSwitchUnit(input e.SwitchUnitDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "checkOut") - unitIDs := make(map[uint16]struct{}) - doctorIDs := make(map[uint]struct{}) + unitCodes := make(map[string]struct{}) + doctorCodes := make(map[string]struct{}) for _, ref := range *input.InternalReferences { - if ref.Unit_Id != nil { - unitIDs[*ref.Unit_Id] = struct{}{} + if ref.Unit_Code != nil { + unitCodes[*ref.Unit_Code] = struct{}{} } - if ref.Doctor_Id != nil { - doctorIDs[*ref.Doctor_Id] = struct{}{} + if ref.Doctor_Code != nil { + doctorCodes[*ref.Doctor_Code] = struct{}{} } } // validate unit - if err = validateUnitIds(unitIDs, &event); err != nil { + if err = validateUnitCodes(unitCodes, &event); err != nil { return nil, err } // validate doctor - if err = validateDoctorIds(doctorIDs, &event); err != nil { + if err = validateDoctorCodes(doctorCodes, &event); err != nil { return nil, err } @@ -773,8 +773,8 @@ func ApproveSwitchUnit(input e.ApproveUnitDto) (*d.Data, error) { Id: input.InternalReferences_Id, CreateDto: eir.CreateDto{ Encounter_Id: &input.Id, - Doctor_Id: irData.Doctor_Id, - Unit_Id: irData.Unit_Id, + Doctor_Code: irData.Doctor_Code, + Unit_Code: irData.Unit_Code, Status_Code: erc.DACApproved, }}, irData, &event, tx); err != nil { return err @@ -793,15 +793,15 @@ func ApproveSwitchUnit(input e.ApproveUnitDto) (*d.Data, error) { // create responsible doctor based on internal reference data if _, err = urdh.CreateData(erdh.CreateDto{ Encounter_Id: &input.Id, - Doctor_Id: irData.Doctor_Id, + Doctor_Code: irData.Doctor_Code, StartedAt: &now, }, &event, tx); err != nil { return err } // update data response - data.Responsible_Doctor_Id = irData.Doctor_Id - data.Unit = irData.Unit + data.Responsible_Doctor_Code = irData.Doctor_Code + data.Unit = irData.Unit // TODO: check if this is correct data.Specialist_Code = irData.Doctor.Specialist_Code data.Subspecialist_Code = irData.Doctor.Subspecialist_Code diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index 1d313d5f..793b5305 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -77,17 +77,17 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Encounter) { data.RegisteredAt = inputSrc.RegisteredAt data.Class_Code = inputSrc.Class_Code data.Unit_Id = inputSrc.Unit_Id - data.Specialist_Id = inputSrc.Specialist_Id - data.Subspecialist_Id = inputSrc.Subspecialist_Id + data.Specialist_Code = inputSrc.Specialist_Code + data.Subspecialist_Code = inputSrc.Subspecialist_Code data.VisitDate = inputSrc.VisitDate data.PaymentMethod_Code = inputSrc.PaymentMethod_Code data.InsuranceCompany_Id = inputSrc.InsuranceCompany_Id data.Member_Number = inputSrc.Member_Number data.Ref_Number = inputSrc.Ref_Number data.Trx_Number = inputSrc.Trx_Number - data.Appointment_Doctor_Id = inputSrc.Appointment_Doctor_Id + data.Appointment_Doctor_Code = inputSrc.Appointment_Doctor_Code data.Adm_Employee_Id = inputSrc.Adm_Employee_Id - data.Responsible_Doctor_Id = inputSrc.Responsible_Doctor_Id + data.Responsible_Doctor_Code = inputSrc.Responsible_Doctor_Code data.RefSource_Name = inputSrc.RefSource_Name data.Appointment_Id = inputSrc.Appointment_Id data.Status_Code = erc.DSCProcess @@ -96,11 +96,11 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Encounter) { } func setDataUpdate(src e.UpdateDto, dst *e.Encounter) { - dst.Appointment_Doctor_Id = src.Appointment_Doctor_Id - dst.Responsible_Doctor_Id = src.Responsible_Doctor_Id + dst.Appointment_Doctor_Code = src.Appointment_Doctor_Code + dst.Responsible_Doctor_Code = src.Responsible_Doctor_Code dst.Unit_Id = src.Unit_Id - dst.Specialist_Id = src.Specialist_Id - dst.Subspecialist_Id = src.Subspecialist_Id + dst.Specialist_Code = src.Specialist_Code + dst.Subspecialist_Code = src.Subspecialist_Code dst.VisitDate = src.VisitDate } @@ -126,7 +126,7 @@ func setDataCheckIn(src e.CheckinDto, dst *e.Encounter) { dst.Adm_Employee_Id = src.Adm_Employee_Id } - dst.Responsible_Doctor_Id = src.Responsible_Doctor_Id + dst.Responsible_Doctor_Code = src.Responsible_Doctor_Code dst.StartedAt = src.StartedAt } @@ -395,9 +395,9 @@ func upsertResponsibleDoctorHist(input erdh.CreateDto, event *pl.Event, dbx ...* default: // Update if err := tx.Model(&latest).Updates(map[string]interface{}{ - "Doctor_Id": input.Doctor_Id, - "StartedAt": input.StartedAt, - "UpdatedAt": time.Now(), + "Doctor_Code": input.Doctor_Code, + "StartedAt": input.StartedAt, + "UpdatedAt": time.Now(), }).Error; err != nil { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ @@ -904,8 +904,8 @@ func validateForeignKey(input e.CheckinDto) error { } // validate doctor_id - if input.Responsible_Doctor_Id != nil { - if _, err := ud.ReadDetail(ed.ReadDetailDto{Id: uint16(*input.Responsible_Doctor_Id)}); err != nil { + if input.Responsible_Doctor_Code != nil { + if _, err := ud.ReadDetail(ed.ReadDetailDto{Code: input.Responsible_Doctor_Code}); err != nil { return err } } @@ -932,10 +932,10 @@ func setDBError(event *pl.Event, err error, ctx any) error { return pl.SetLogError(event, ctx) } -func getUnits(unitIds []uint16, event *pl.Event) ([]eu.Unit, error) { +func getUnits(unitIds []string, event *pl.Event) ([]eu.Unit, error) { pl.SetLogInfo(event, nil, "started", "getUnits") var units []eu.Unit - err := dg.I.Where("\"Id\" IN ?", unitIds).Find(&units).Error + err := dg.I.Where("\"Code\" IN ?", unitIds).Find(&units).Error if err != nil { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ @@ -948,10 +948,10 @@ func getUnits(unitIds []uint16, event *pl.Event) ([]eu.Unit, error) { return units, nil } -func getDoctors(doctorIds []uint, event *pl.Event) ([]ed.Doctor, error) { +func getDoctors(doctorIds []string, event *pl.Event) ([]ed.Doctor, error) { pl.SetLogInfo(event, nil, "started", "getDoctors") var doctors []ed.Doctor - err := dg.I.Where("\"Id\" IN ?", doctorIds).Find(&doctors).Error + err := dg.I.Where("\"Id\" Code ?", doctorIds).Find(&doctors).Error if err != nil { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ @@ -964,18 +964,18 @@ func getDoctors(doctorIds []uint, event *pl.Event) ([]ed.Doctor, error) { return doctors, nil } -func validateUnitIds(unitIDs map[uint16]struct{}, event *pl.Event) error { - if len(unitIDs) > 0 { - var ids []uint16 - for id := range unitIDs { - ids = append(ids, id) +func validateUnitCodes(unitCodes map[string]struct{}, event *pl.Event) error { + if len(unitCodes) > 0 { + var codes []string + for code := range unitCodes { + codes = append(codes, code) } - units, err := getUnits(ids, event) + units, err := getUnits(codes, event) if err != nil { return fmt.Errorf("failed to fetch units: %w", err) } - if len(units) != len(ids) { + if len(units) != len(codes) { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "data-validation-fail", @@ -988,18 +988,18 @@ func validateUnitIds(unitIDs map[uint16]struct{}, event *pl.Event) error { return nil } -func validateDoctorIds(doctorIDs map[uint]struct{}, event *pl.Event) error { - if len(doctorIDs) > 0 { - var ids []uint - for id := range doctorIDs { - ids = append(ids, id) +func validateDoctorCodes(doctorCodes map[string]struct{}, event *pl.Event) error { + if len(doctorCodes) > 0 { + var codes []string + for code := range doctorCodes { + codes = append(codes, code) } - doctors, err := getDoctors(ids, event) + doctors, err := getDoctors(codes, event) if err != nil { return fmt.Errorf("failed to fetch doctors: %w", err) } - if len(doctors) != len(ids) { + if len(doctors) != len(codes) { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "data-validation-fail", diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index 8772a2f4..840fefac 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -332,10 +332,10 @@ func updateEncounterApproveSwitchUnit(input eir.InternalReference, event *pl.Eve if err := tx.Model(&e.Encounter{}). Where("\"Id\" = ?", input.Encounter_Id). Updates(map[string]interface{}{ - "Responsible_Doctor_Id": input.Doctor_Id, - "Unit_Id": input.Unit_Id, - "Specialist_Code": input.Doctor.Specialist_Code, - "Subspecialist_Code": input.Doctor.Subspecialist_Code, + "Responsible_Doctor_Code": input.Doctor_Code, + "Unit_Code": input.Unit_Code, + "Specialist_Code": input.Doctor.Specialist_Code, + "Subspecialist_Code": input.Doctor.Subspecialist_Code, }).Error; err != nil { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ diff --git a/internal/use-case/main-use-case/internal-reference/helper.go b/internal/use-case/main-use-case/internal-reference/helper.go index 36c28540..234eb770 100644 --- a/internal/use-case/main-use-case/internal-reference/helper.go +++ b/internal/use-case/main-use-case/internal-reference/helper.go @@ -19,8 +19,8 @@ func setData[T *ir.CreateDto | *ir.UpdateDto](input T, data *ir.InternalReferenc } data.Encounter_Id = inputSrc.Encounter_Id - data.Unit_Id = inputSrc.Unit_Id - data.Doctor_Id = inputSrc.Doctor_Id + data.Unit_Code = inputSrc.Unit_Code + data.Doctor_Code = inputSrc.Doctor_Code data.Status_Code = &inputSrc.Status_Code } @@ -31,8 +31,8 @@ func setBulkData(input []ir.CreateDto, encounterId uint) []ir.InternalReference statusCode := erc.DACNew data = append(data, ir.InternalReference{ Encounter_Id: &encounterId, - Unit_Id: v.Unit_Id, - Doctor_Id: v.Doctor_Id, + Unit_Code: v.Unit_Code, + Doctor_Code: v.Doctor_Code, Status_Code: &statusCode, }) } diff --git a/internal/use-case/main-use-case/nurse/case.go b/internal/use-case/main-use-case/nurse/case.go index 6201e15b..e7d0ce0c 100644 --- a/internal/use-case/main-use-case/nurse/case.go +++ b/internal/use-case/main-use-case/nurse/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Nurse var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Nurse var err error diff --git a/internal/use-case/main-use-case/nurse/lib.go b/internal/use-case/main-use-case/nurse/lib.go index a59cc692..e0ce8ba6 100644 --- a/internal/use-case/main-use-case/nurse/lib.go +++ b/internal/use-case/main-use-case/nurse/lib.go @@ -84,7 +84,7 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e if input.Employee_Id != nil { tx = tx.Where("\"Employee_Id\" = ?", *input.Employee_Id) } - if input.Id > 0 { + if input.Id != nil { tx = tx.Where("\"Id\" = ?", input.Id) } if err := tx.First(&data).Error; err != nil { diff --git a/internal/use-case/main-use-case/practice-schedule/helper.go b/internal/use-case/main-use-case/practice-schedule/helper.go index 5c9f7815..ba61b691 100644 --- a/internal/use-case/main-use-case/practice-schedule/helper.go +++ b/internal/use-case/main-use-case/practice-schedule/helper.go @@ -17,7 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.PracticeSchedule) { inputSrc = &inputTemp.CreateDto } - data.Doctor_Id = inputSrc.Doctor_Id + data.Doctor_Code = inputSrc.Doctor_Code data.Unit_Code = inputSrc.Unit_Code data.Day_Code = inputSrc.Day_Code data.StartTime = inputSrc.StartTime diff --git a/internal/use-case/main-use-case/responsible-doctor-hist/helper.go b/internal/use-case/main-use-case/responsible-doctor-hist/helper.go index 6efd1097..33ee9da4 100644 --- a/internal/use-case/main-use-case/responsible-doctor-hist/helper.go +++ b/internal/use-case/main-use-case/responsible-doctor-hist/helper.go @@ -18,7 +18,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.ResponsibleDoctorHi } data.Encounter_Id = inputSrc.Encounter_Id - data.Doctor_Id = inputSrc.Doctor_Id + data.Doctor_Code = inputSrc.Doctor_Code data.StartedAt = inputSrc.StartedAt data.FinishedAt = inputSrc.FinishedAt } diff --git a/internal/use-case/main-use-case/therapy-protocol/case.go b/internal/use-case/main-use-case/therapy-protocol/case.go index 93cf05a4..bc65325f 100644 --- a/internal/use-case/main-use-case/therapy-protocol/case.go +++ b/internal/use-case/main-use-case/therapy-protocol/case.go @@ -299,9 +299,9 @@ func validateForeignKey(input e.CreateDto) error { } } - // validate doctor_id - if input.Doctor_Id != nil { - if _, err := ud.ReadDetail(ed.ReadDetailDto{Id: uint16(*input.Doctor_Id)}); err != nil { + // validate doctor_code + if input.Doctor_Code != nil { + if _, err := ud.ReadDetail(ed.ReadDetailDto{Code: input.Doctor_Code}); err != nil { return err } } diff --git a/internal/use-case/main-use-case/therapy-protocol/helper.go b/internal/use-case/main-use-case/therapy-protocol/helper.go index 12e48747..021c89ed 100644 --- a/internal/use-case/main-use-case/therapy-protocol/helper.go +++ b/internal/use-case/main-use-case/therapy-protocol/helper.go @@ -18,7 +18,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.TherapyProtocol) { } data.Encounter_Id = inputSrc.Encounter_Id - data.Doctor_Id = inputSrc.Doctor_Id + data.Doctor_Code = inputSrc.Doctor_Code data.Anamnesis = inputSrc.Anamnesis data.MedicalDiagnoses = inputSrc.MedicalDiagnoses data.FunctionDiagnoses = inputSrc.FunctionDiagnoses From f4268efc3fd756f24a44ced90ffe9fa2e8d87e9b Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 10 Nov 2025 13:26:13 +0700 Subject: [PATCH 120/329] add encounter document --- .../main-entities/encounter-document/entity.go | 17 +++++++++++++++++ .../domain/main-entities/encounter/entity.go | 2 ++ 2 files changed, 19 insertions(+) create mode 100644 internal/domain/main-entities/encounter-document/entity.go diff --git a/internal/domain/main-entities/encounter-document/entity.go b/internal/domain/main-entities/encounter-document/entity.go new file mode 100644 index 00000000..2aaec209 --- /dev/null +++ b/internal/domain/main-entities/encounter-document/entity.go @@ -0,0 +1,17 @@ +package encounter_document + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/employee" +) + +type EncounterDocument struct { + ecore.Main + Encounter_Id *uint `json:"encounter_id"` + Name string `json:"name"` + DocumentType string `json:"documentType"` + FilePath *string `json:"filePath"` + FileName *string `json:"fileName"` + Upload_Employee_Id *string `json:"upload_employee_id"` + Upload_Employee *ee.Employee `json:"upload_employee,omitempty" gorm:"foreignKey:Upload_Employee_Id;references:Id"` +} diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index bfd70333..b62cd383 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -9,6 +9,7 @@ import ( ed "simrs-vx/internal/domain/main-entities/doctor" eem "simrs-vx/internal/domain/main-entities/emergency" ee "simrs-vx/internal/domain/main-entities/employee" + eed "simrs-vx/internal/domain/main-entities/encounter-document" eip "simrs-vx/internal/domain/main-entities/inpatient" ei "simrs-vx/internal/domain/main-entities/insurance-company" eir "simrs-vx/internal/domain/main-entities/internal-reference" @@ -70,6 +71,7 @@ type Encounter struct { Inpatient *eip.Inpatient `json:"inpatient,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Rehab *er.Basic `json:"rehab,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` RehabChildren *[]er.Basic `json:"rehabChildren,omitempty" gorm:"foreignKey:Parent_Encounter_Id;references:Id"` + EncounterDocument *[]eed.EncounterDocument `json:"encounterDocument,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` } func (d Encounter) IsDone() bool { From 9a5516a1e9d726dafa8bfd24e51b85a956827500 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 10 Nov 2025 13:27:04 +0700 Subject: [PATCH 121/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 50 ++++++++++++------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index c64990da..73bcddde 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:BX21/eygPEF+JaTDfxN/z3+7YAe6EYWa1EK9N2PKhAE= +h1:CY3tmVMc8TOrAWeo+JbrRmrP/i5EAJ+c/ZA5/PEgxho= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,27 +75,27 @@ h1:BX21/eygPEF+JaTDfxN/z3+7YAe6EYWa1EK9N2PKhAE= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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:1LkEGCWPe04T3D8F3VMnBP8eJgskrvCggsybNxJ7GuU= -20251110062042.sql h1:yUUNX3EekfedaGTt5Q89a0bgZoCu/kfdXLU4iljN5Xw= +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= From be8acefeff331aa1bb741b055966ebe3a5a8cb2c Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 10 Nov 2025 13:34:04 +0700 Subject: [PATCH 122/329] change unit_id, insurance_company_id into code --- .../migrations/20251110063202.sql | 4 ++ cmd/main-migration/migrations/atlas.sum | 51 ++++++++++--------- internal/domain/main-entities/chemo/dto.go | 4 ++ internal/domain/main-entities/chemo/entity.go | 1 + .../domain/main-entities/encounter/dto.go | 14 ++--- .../domain/main-entities/encounter/entity.go | 6 +-- .../main-use-case/encounter/helper.go | 8 +-- 7 files changed, 48 insertions(+), 40 deletions(-) create mode 100644 cmd/main-migration/migrations/20251110063202.sql diff --git a/cmd/main-migration/migrations/20251110063202.sql b/cmd/main-migration/migrations/20251110063202.sql new file mode 100644 index 00000000..90c55b4d --- /dev/null +++ b/cmd/main-migration/migrations/20251110063202.sql @@ -0,0 +1,4 @@ +-- Modify "Chemo" table +ALTER TABLE "public"."Chemo" ADD COLUMN "SrcUnit_Code" text NULL; +-- Modify "Encounter" table +ALTER TABLE "public"."Encounter" DROP CONSTRAINT "fk_Encounter_InsuranceCompany", DROP CONSTRAINT "fk_Encounter_Unit", DROP COLUMN "Unit_Id", DROP COLUMN "InsuranceCompany_Id", ALTER COLUMN "Unit_Code" TYPE character varying(10), ALTER COLUMN "InsuranceCompany_Code" TYPE character varying(20), ADD CONSTRAINT "fk_Encounter_InsuranceCompany" FOREIGN KEY ("InsuranceCompany_Code") REFERENCES "public"."InsuranceCompany" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_Encounter_Unit" FOREIGN KEY ("Unit_Code") REFERENCES "public"."Unit" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 73bcddde..5b16d0e3 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:CY3tmVMc8TOrAWeo+JbrRmrP/i5EAJ+c/ZA5/PEgxho= +h1:o5Hy+7GMNij47fSD0WmODLv/+50U8aJ5oI2zZ657Bm4= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,27 +75,28 @@ h1:CY3tmVMc8TOrAWeo+JbrRmrP/i5EAJ+c/ZA5/PEgxho= 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= +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:1LkEGCWPe04T3D8F3VMnBP8eJgskrvCggsybNxJ7GuU= +20251110062042.sql h1:yUUNX3EekfedaGTt5Q89a0bgZoCu/kfdXLU4iljN5Xw= +20251110063202.sql h1:z/eZpUGtTKzG0D9erH5FEg0YqXU3d/Nou5IW0IjIA9E= diff --git a/internal/domain/main-entities/chemo/dto.go b/internal/domain/main-entities/chemo/dto.go index 653b5409..31660ef8 100644 --- a/internal/domain/main-entities/chemo/dto.go +++ b/internal/domain/main-entities/chemo/dto.go @@ -21,6 +21,7 @@ type CreateDto struct { Encounter_Id *uint `json:"encounter_id"` Status_Code erc.DataVerifiedCode `json:"status_code"` SrcUnit_Id *uint `json:"srcUnit_id"` + SrcUnit_Code *string `json:"srcUnit_code"` } type ReadListDto struct { @@ -34,6 +35,7 @@ type FilterDto struct { Status_Code *erc.DataVerifiedCode `json:"status-code"` VerifiedBy_User_Id *uint `json:"verifiedBy-user-id"` SrcUnit_Id *uint `json:"srcUnit-id"` + SrcUnit_Code *string `json:"srcUnit-code"` } type ReadDetailDto struct { @@ -73,6 +75,7 @@ type ResponseDto struct { VerifiedBy_User_Id *uint `json:"verifiedBy_user_id"` VerifiedBy *eus.User `json:"verifiedBy,omitempty"` SrcUnit_Id *uint `json:"srcUnit_id"` + SrcUnit_Code *string `json:"srcUnit_code"` SrcUnit *eun.Unit `json:"srcUnit,omitempty"` } @@ -85,6 +88,7 @@ func (d Chemo) ToResponse() ResponseDto { VerifiedBy_User_Id: d.VerifiedBy_User_Id, VerifiedBy: d.VerifiedBy, SrcUnit_Id: d.SrcUnit_Id, + SrcUnit_Code: d.SrcUnit_Code, SrcUnit: d.SrcUnit, } resp.Main = d.Main diff --git a/internal/domain/main-entities/chemo/entity.go b/internal/domain/main-entities/chemo/entity.go index a56dae76..60a0f9f1 100644 --- a/internal/domain/main-entities/chemo/entity.go +++ b/internal/domain/main-entities/chemo/entity.go @@ -20,6 +20,7 @@ type Chemo struct { VerifiedBy_User_Id *uint `json:"verifiedBy_user_id"` VerifiedBy *eus.User `json:"verifiedBy,omitempty" gorm:"foreignKey:VerifiedBy_User_Id;references:Id"` SrcUnit_Id *uint `json:"src_unit_id"` + SrcUnit_Code *string `json:"src_unit_code"` SrcUnit *eun.Unit `json:"src_unit,omitempty" gorm:"foreignKey:SrcUnit_Id;references:Id"` Bed *string `json:"bed" gorm:"size:1024"` Needs *string `json:"needs" gorm:"size:2048"` diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index 7ac57b07..af8c1336 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -38,12 +38,12 @@ type CreateDto struct { Class_Code ere.EncounterClassCode `json:"class_code" validate:"maxLength=10"` SubClass_Code *string `json:"subClass_code" validate:"maxLength=10"` // for sub Infra_Id *uint16 `json:"infra_id"` // for inpatient - Unit_Id *uint `json:"unit_id"` + 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 erc.PaymentMethodCode `json:"paymentMethod_code" gorm:"size:10"` - InsuranceCompany_Id *uint `json:"insuranceCompany_id"` + 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"` @@ -75,7 +75,7 @@ type FilterDto struct { Patient *ep.Patient `json:"patient,omitempty"` RegisteredAt *time.Time `json:"registeredAt"` Class_Code ere.EncounterClassCode `json:"class-code" validate:"maxLength=10"` - Unit_Id *uint `json:"unit-id"` + Unit_Code *string `json:"unit-code"` Specialist_Code *string `json:"specialist-code"` Subspecialist_Code *string `json:"subspecialist-code"` VisitDate time.Time `json:"visitDate"` @@ -149,7 +149,7 @@ type ResponseDto struct { Patient *ep.Patient `json:"patient,omitempty"` RegisteredAt *time.Time `json:"registeredAt"` Class_Code ere.EncounterClassCode `json:"class_code"` - Unit_Id *uint `json:"unit_id"` + Unit_Code *string `json:"unit_code"` Specialist_Code *string `json:"specialist_code"` Specialist *es.Specialist `json:"specialist,omitempty"` Subspecialist_Code *string `json:"subspecialist_code"` @@ -157,7 +157,7 @@ type ResponseDto struct { Unit *eu.Unit `json:"unit,omitempty"` VisitDate time.Time `json:"visitDate"` PaymentMethod_Code erc.PaymentMethodCode `json:"paymentMethod_code"` - InsuranceCompany_Id *uint `json:"insuranceCompany_id"` + InsuranceCompany_Code *string `json:"insuranceCompany_code"` Member_Number *string `json:"member_number"` Ref_Number *string `json:"ref_number"` Trx_Number *string `json:"trx_number"` @@ -196,7 +196,7 @@ func (d Encounter) ToResponse() ResponseDto { Patient: d.Patient, RegisteredAt: d.RegisteredAt, Class_Code: d.Class_Code, - Unit_Id: d.Unit_Id, + Unit_Code: d.Unit_Code, Unit: d.Unit, Specialist_Code: d.Specialist_Code, Specialist: d.Specialist, @@ -204,7 +204,7 @@ func (d Encounter) ToResponse() ResponseDto { Subspecialist: d.Subspecialist, VisitDate: d.VisitDate, PaymentMethod_Code: d.PaymentMethod_Code, - InsuranceCompany_Id: d.InsuranceCompany_Id, + InsuranceCompany_Code: d.InsuranceCompany_Code, Member_Number: d.Member_Number, Ref_Number: d.Ref_Number, Trx_Number: d.Trx_Number, diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index e07b2263..c9e9bb95 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -29,9 +29,8 @@ type Encounter struct { Patient *ep.Patient `json:"patient,omitempty" gorm:"foreignKey:Patient_Id;references:Id"` RegisteredAt *time.Time `json:"registeredAt"` Class_Code ere.EncounterClassCode `json:"class_code" gorm:"not null;size:10"` - Unit_Id *uint `json:"unit_id"` Unit_Code *string `json:"unit_code"` - Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` + Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` Specialist_Code *string `json:"specialist_code"` Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Code;references:Code"` Subspecialist_Code *string `json:"subspecialist_code"` @@ -40,9 +39,8 @@ type Encounter struct { StartedAt *time.Time `json:"startedAt"` FinishedAt *time.Time `json:"finishedAt"` PaymentMethod_Code erc.PaymentMethodCode `json:"paymentMethod_code" gorm:"size:10"` - InsuranceCompany_Id *uint `json:"insuranceCompany_id"` InsuranceCompany_Code *string `json:"insuranceCompany_code"` - InsuranceCompany *ei.InsuranceCompany `json:"insuranceCompany,omitempty" gorm:"foreignKey:InsuranceCompany_Id;references:Id"` + InsuranceCompany *ei.InsuranceCompany `json:"insuranceCompany,omitempty" gorm:"foreignKey:InsuranceCompany_Code;references:Code"` Member_Number *string `json:"memberNumber" gorm:"unique;size:20"` RefType_Code *ere.RefTypeCode `json:"refType_code"` Ref_Number *string `json:"refNumber" gorm:"unique;size:20"` diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index 793b5305..be187bea 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -76,12 +76,12 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Encounter) { data.Patient_Id = inputSrc.Patient_Id data.RegisteredAt = inputSrc.RegisteredAt data.Class_Code = inputSrc.Class_Code - data.Unit_Id = inputSrc.Unit_Id + 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_Id = inputSrc.InsuranceCompany_Id + data.InsuranceCompany_Code = inputSrc.InsuranceCompany_Code data.Member_Number = inputSrc.Member_Number data.Ref_Number = inputSrc.Ref_Number data.Trx_Number = inputSrc.Trx_Number @@ -98,7 +98,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Encounter) { 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_Id = src.Unit_Id + dst.Unit_Code = src.Unit_Code dst.Specialist_Code = src.Specialist_Code dst.Subspecialist_Code = src.Subspecialist_Code dst.VisitDate = src.VisitDate @@ -810,7 +810,7 @@ func insertDataSubClassAmbulatory(input e.CreateDto, soapiData []es.CreateDto, e chemoCreate := ec.CreateDto{ Encounter_Id: &input.Id, Status_Code: erc.DVCNew, - SrcUnit_Id: input.Unit_Id, + SrcUnit_Code: input.Unit_Code, } // create data chemo From 156cb0fd931a9c96b41c231e864ca0ba6440927f Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 10 Nov 2025 13:34:56 +0700 Subject: [PATCH 123/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 52 ++++++++++++------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 5b16d0e3..dad233fe 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:o5Hy+7GMNij47fSD0WmODLv/+50U8aJ5oI2zZ657Bm4= +h1:wRvp5REHLDtGi/6Rlwwc2eOHIhe0oJQVJSmeFCvfyb8= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,28 +75,28 @@ h1:o5Hy+7GMNij47fSD0WmODLv/+50U8aJ5oI2zZ657Bm4= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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:1LkEGCWPe04T3D8F3VMnBP8eJgskrvCggsybNxJ7GuU= -20251110062042.sql h1:yUUNX3EekfedaGTt5Q89a0bgZoCu/kfdXLU4iljN5Xw= -20251110063202.sql h1:z/eZpUGtTKzG0D9erH5FEg0YqXU3d/Nou5IW0IjIA9E= +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= From 9417ff07051d4b09d470ed6bca491ddde7556f07 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 10 Nov 2025 13:37:15 +0700 Subject: [PATCH 124/329] change srcUnit_id into code --- .../migrations/20251110063633.sql | 2 + cmd/main-migration/migrations/atlas.sum | 53 ++++++++++--------- internal/domain/main-entities/chemo/dto.go | 4 -- internal/domain/main-entities/chemo/entity.go | 3 +- .../use-case/main-use-case/chemo/helper.go | 2 +- 5 files changed, 31 insertions(+), 33 deletions(-) create mode 100644 cmd/main-migration/migrations/20251110063633.sql diff --git a/cmd/main-migration/migrations/20251110063633.sql b/cmd/main-migration/migrations/20251110063633.sql new file mode 100644 index 00000000..de41516f --- /dev/null +++ b/cmd/main-migration/migrations/20251110063633.sql @@ -0,0 +1,2 @@ +-- Modify "Chemo" table +ALTER TABLE "public"."Chemo" DROP CONSTRAINT "fk_Chemo_SrcUnit", DROP COLUMN "SrcUnit_Id", ALTER COLUMN "SrcUnit_Code" TYPE character varying(10), ADD CONSTRAINT "fk_Chemo_SrcUnit" FOREIGN KEY ("SrcUnit_Code") REFERENCES "public"."Unit" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index dad233fe..c27f97c1 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:wRvp5REHLDtGi/6Rlwwc2eOHIhe0oJQVJSmeFCvfyb8= +h1:bONKXih1Woh8TA4X9FVhqYCV+ZT5wGRr4g5xkpKLI2o= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,28 +75,29 @@ h1:wRvp5REHLDtGi/6Rlwwc2eOHIhe0oJQVJSmeFCvfyb8= 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= +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:1LkEGCWPe04T3D8F3VMnBP8eJgskrvCggsybNxJ7GuU= +20251110062042.sql h1:yUUNX3EekfedaGTt5Q89a0bgZoCu/kfdXLU4iljN5Xw= +20251110063202.sql h1:z/eZpUGtTKzG0D9erH5FEg0YqXU3d/Nou5IW0IjIA9E= +20251110063633.sql h1:81jDaSXtmWBCe64LiEASCNK0AuPeC+6js5srhLmRji8= diff --git a/internal/domain/main-entities/chemo/dto.go b/internal/domain/main-entities/chemo/dto.go index 31660ef8..5d8b9501 100644 --- a/internal/domain/main-entities/chemo/dto.go +++ b/internal/domain/main-entities/chemo/dto.go @@ -20,7 +20,6 @@ import ( type CreateDto struct { Encounter_Id *uint `json:"encounter_id"` Status_Code erc.DataVerifiedCode `json:"status_code"` - SrcUnit_Id *uint `json:"srcUnit_id"` SrcUnit_Code *string `json:"srcUnit_code"` } @@ -34,7 +33,6 @@ type FilterDto struct { Encounter_Id *uint `json:"encounter-id"` Status_Code *erc.DataVerifiedCode `json:"status-code"` VerifiedBy_User_Id *uint `json:"verifiedBy-user-id"` - SrcUnit_Id *uint `json:"srcUnit-id"` SrcUnit_Code *string `json:"srcUnit-code"` } @@ -74,7 +72,6 @@ type ResponseDto struct { VerifiedAt *time.Time `json:"verifiedAt"` VerifiedBy_User_Id *uint `json:"verifiedBy_user_id"` VerifiedBy *eus.User `json:"verifiedBy,omitempty"` - SrcUnit_Id *uint `json:"srcUnit_id"` SrcUnit_Code *string `json:"srcUnit_code"` SrcUnit *eun.Unit `json:"srcUnit,omitempty"` } @@ -87,7 +84,6 @@ func (d Chemo) ToResponse() ResponseDto { VerifiedAt: d.VerifiedAt, VerifiedBy_User_Id: d.VerifiedBy_User_Id, VerifiedBy: d.VerifiedBy, - SrcUnit_Id: d.SrcUnit_Id, SrcUnit_Code: d.SrcUnit_Code, SrcUnit: d.SrcUnit, } diff --git a/internal/domain/main-entities/chemo/entity.go b/internal/domain/main-entities/chemo/entity.go index 60a0f9f1..6f5180aa 100644 --- a/internal/domain/main-entities/chemo/entity.go +++ b/internal/domain/main-entities/chemo/entity.go @@ -19,9 +19,8 @@ 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_Id *uint `json:"src_unit_id"` SrcUnit_Code *string `json:"src_unit_code"` - SrcUnit *eun.Unit `json:"src_unit,omitempty" gorm:"foreignKey:SrcUnit_Id;references:Id"` + 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"` } diff --git a/internal/use-case/main-use-case/chemo/helper.go b/internal/use-case/main-use-case/chemo/helper.go index bb60a39b..51a09a3a 100644 --- a/internal/use-case/main-use-case/chemo/helper.go +++ b/internal/use-case/main-use-case/chemo/helper.go @@ -19,5 +19,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Chemo) { data.Encounter_Id = inputSrc.Encounter_Id data.Status_Code = inputSrc.Status_Code - data.SrcUnit_Id = inputSrc.SrcUnit_Id + data.SrcUnit_Code = inputSrc.SrcUnit_Code } From 9d8f09c0de2d55862ef056c7d89938efd18dcd24 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 10 Nov 2025 13:37:58 +0700 Subject: [PATCH 125/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 54 ++++++++++++------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index c27f97c1..ee8bafbe 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:bONKXih1Woh8TA4X9FVhqYCV+ZT5wGRr4g5xkpKLI2o= +h1:Cs+1IkfoV4LHZgT4hNYw7jF73tuz6WesEZdT1xmIvBA= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,29 +75,29 @@ h1:bONKXih1Woh8TA4X9FVhqYCV+ZT5wGRr4g5xkpKLI2o= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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:1LkEGCWPe04T3D8F3VMnBP8eJgskrvCggsybNxJ7GuU= -20251110062042.sql h1:yUUNX3EekfedaGTt5Q89a0bgZoCu/kfdXLU4iljN5Xw= -20251110063202.sql h1:z/eZpUGtTKzG0D9erH5FEg0YqXU3d/Nou5IW0IjIA9E= -20251110063633.sql h1:81jDaSXtmWBCe64LiEASCNK0AuPeC+6js5srhLmRji8= +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= From d5d9182ad65a14b040c68a96ba33adcd320fee21 Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 10 Nov 2025 14:17:56 +0700 Subject: [PATCH 126/329] revise refactor --- internal/domain/main-entities/internal-reference/dto.go | 2 +- .../domain/main-entities/subspecialist-position/dto.go | 2 +- internal/use-case/main-use-case/encounter/case.go | 4 ++-- internal/use-case/main-use-case/encounter/helper.go | 8 ++++---- internal/use-case/main-use-case/encounter/lib.go | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/internal/domain/main-entities/internal-reference/dto.go b/internal/domain/main-entities/internal-reference/dto.go index 08eaaac2..6ce50a77 100644 --- a/internal/domain/main-entities/internal-reference/dto.go +++ b/internal/domain/main-entities/internal-reference/dto.go @@ -51,7 +51,7 @@ type MetaDto struct { type ResponseDto struct { ecore.Main Encounter_Id *uint `json:"encounter_id"` - Unit_Code *string `json:"unit_id"` + Unit_Code *string `json:"unit_code"` Unit *eu.Unit `json:"unit,omitempty"` Doctor_Code *string `json:"doctor_id"` Doctor *ed.Doctor `json:"doctor,omitempty"` diff --git a/internal/domain/main-entities/subspecialist-position/dto.go b/internal/domain/main-entities/subspecialist-position/dto.go index 13532ab8..1c37a859 100644 --- a/internal/domain/main-entities/subspecialist-position/dto.go +++ b/internal/domain/main-entities/subspecialist-position/dto.go @@ -53,7 +53,7 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain - Subspecialist_Code *string `json:"subspecialist_id"` + Subspecialist_Code *string `json:"subspecialist_code"` Subspecialist *es.Subspecialist `json:"subspecialist,omitempty"` Code string `json:"code"` Name string `json:"name"` diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 3a8c3b82..d387fcc2 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -573,7 +573,7 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { } } - // Upsert responsible_doctor_hist if responsible_doctor_id has changed + // Upsert responsible_doctor_hist if responsible_doctor_code has changed if data.Responsible_Doctor_Code == nil || *input.Responsible_Doctor_Code != *data.Responsible_Doctor_Code { // upsert responsibleDoctorHist if err = upsertResponsibleDoctorHist(erdh.CreateDto{ @@ -801,7 +801,7 @@ func ApproveSwitchUnit(input e.ApproveUnitDto) (*d.Data, error) { // update data response data.Responsible_Doctor_Code = irData.Doctor_Code - data.Unit = irData.Unit // TODO: check if this is correct + data.Unit_Code = irData.Unit_Code // data.Specialist_Code = irData.Doctor.Specialist_Code data.Subspecialist_Code = irData.Doctor.Subspecialist_Code diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index be187bea..1f78d73e 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -903,7 +903,7 @@ func validateForeignKey(input e.CheckinDto) error { } } - // validate doctor_id + // validate doctor_Code if input.Responsible_Doctor_Code != nil { if _, err := ud.ReadDetail(ed.ReadDetailDto{Code: input.Responsible_Doctor_Code}); err != nil { return err @@ -951,7 +951,7 @@ func getUnits(unitIds []string, event *pl.Event) ([]eu.Unit, error) { func getDoctors(doctorIds []string, event *pl.Event) ([]ed.Doctor, error) { pl.SetLogInfo(event, nil, "started", "getDoctors") var doctors []ed.Doctor - err := dg.I.Where("\"Id\" Code ?", doctorIds).Find(&doctors).Error + err := dg.I.Where("\"Code\" IN ?", doctorIds).Find(&doctors).Error if err != nil { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ @@ -979,7 +979,7 @@ func validateUnitCodes(unitCodes map[string]struct{}, event *pl.Event) error { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "data-validation-fail", - Detail: "unit_id not found", + Detail: "unit_code not found", } return pl.SetLogError(event, nil) } @@ -1003,7 +1003,7 @@ func validateDoctorCodes(doctorCodes map[string]struct{}, event *pl.Event) error event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "data-validation-fail", - Detail: "doctor_id not found", + Detail: "doctor_code not found", } return pl.SetLogError(event, nil) } diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index 840fefac..22259c09 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -64,7 +64,7 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.En tx = tx.Model(&e.Encounter{}) if input.AuthInfo.Doctor_Code != nil { - tx.Where("\"Responsible_Doctor_Id\" = ?", *input.AuthInfo.Doctor_Code) // TODO: fix this + tx.Where("\"Responsible_Doctor_Code\" = ?", *input.AuthInfo.Doctor_Code) // } tx.Scopes(gh.Preload(input.Includes)). From 008bbfcc8c9bbd588df4754818d11edf3a938409 Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 10 Nov 2025 14:28:52 +0700 Subject: [PATCH 127/329] refactor encounter --- cmd/main-migration/migrations/atlas.sum | 54 ++++++++++++------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index ee8bafbe..ef1f8795 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:Cs+1IkfoV4LHZgT4hNYw7jF73tuz6WesEZdT1xmIvBA= +h1:4mUEGaMHpVG5OAo3DgtsqGkPtWwCZDAk0H5y2cG1QP4= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,29 +75,29 @@ h1:Cs+1IkfoV4LHZgT4hNYw7jF73tuz6WesEZdT1xmIvBA= 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= +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= From 850dce87cd899c19f5add0c756b604f745125d26 Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 10 Nov 2025 15:42:15 +0700 Subject: [PATCH 128/329] revise encounter --- .../use-case/main-use-case/encounter/helper.go | 15 ++++++++++++--- internal/use-case/main-use-case/encounter/lib.go | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index 1f78d73e..99b080ab 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -559,7 +559,6 @@ func getSoapiByResponsibleDoctor(enc e.Encounter, event *pl.Event) (data []es.So } err = dg.I. - Debug(). Model(&es.Soapi{}). Joins("JOIN \"Employee\" ON \"Employee\".\"Id\" = \"Soapi\".\"Employee_Id\""). Where("\"Encounter_Id\" = ?", enc.Id). @@ -723,16 +722,26 @@ func determineVisitMode(recentRehabData *er.Rehab, input e.CreateDto, event *pl. return "", nil, err } - if !isQuotaValid || recentRehabData.ExpiredAt.Before(*pu.GetTimeNow()) { + if !isQuotaValid { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "visit-limit-exceeded", - Detail: "Encounter has exceeded the allowed number of visits or expired", + Detail: "Encounter has exceeded the allowed number of visits", Raw: errors.New("visit count exceeds allowed limit"), } return "", nil, pl.SetLogError(event, input) } + if recentRehabData.ExpiredAt != nil && recentRehabData.ExpiredAt.Before(*pu.GetTimeNow()) { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "visit-limit-exceeded", + Detail: "Encounter period has expired", + Raw: errors.New("encounter expired"), + } + return "", nil, pl.SetLogError(event, input) + } + case erc.DSCDone: visitModeCode = ere.VMCAdm diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index 22259c09..d3cc544e 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -312,7 +312,7 @@ func verifyAllocatedVisitCount(i e.CreateDto, event *pl.Event) (e.Encounter, boo } // validate count rehab children - if recentEncounterAdm.RehabChildren != nil { + if recentEncounterAdm.RehabChildren != nil && len(*recentEncounterAdm.RehabChildren) > 0 { valid = len(*recentEncounterAdm.RehabChildren) < *recentEncounterAdm.Rehab.AllocatedVisitCount } From 46a67ea359fb123ad2cac0756b9bb77978d64d22 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 10 Nov 2025 15:58:45 +0700 Subject: [PATCH 129/329] add doctor_code into device-order,material-order,mcu-order --- .../migrations/20251110085551.sql | 8 +++ cmd/main-migration/migrations/atlas.sum | 55 ++++++++++--------- .../main-entities/device-order/entity.go | 1 + .../domain/main-entities/inpatient/entity.go | 1 + .../main-entities/material-order/entity.go | 1 + .../domain/main-entities/mcu-order/entity.go | 1 + 6 files changed, 40 insertions(+), 27 deletions(-) create mode 100644 cmd/main-migration/migrations/20251110085551.sql diff --git a/cmd/main-migration/migrations/20251110085551.sql b/cmd/main-migration/migrations/20251110085551.sql new file mode 100644 index 00000000..8cdcbc3b --- /dev/null +++ b/cmd/main-migration/migrations/20251110085551.sql @@ -0,0 +1,8 @@ +-- Modify "DeviceOrder" table +ALTER TABLE "public"."DeviceOrder" ADD COLUMN "Doctor_Code" text NULL; +-- Modify "Inpatient" table +ALTER TABLE "public"."Inpatient" ADD COLUMN "Infra_Code" character varying(10) NULL; +-- Modify "MaterialOrder" table +ALTER TABLE "public"."MaterialOrder" ADD COLUMN "Doctor_Code" text NULL; +-- Modify "McuOrder" table +ALTER TABLE "public"."McuOrder" ADD COLUMN "Doctor_Code" text NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index ee8bafbe..dea504e8 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:Cs+1IkfoV4LHZgT4hNYw7jF73tuz6WesEZdT1xmIvBA= +h1:0WHQByo4Ygfp9nGAp4I/lFIvSvl/PkL9DLUgA9rn1QQ= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,29 +75,30 @@ h1:Cs+1IkfoV4LHZgT4hNYw7jF73tuz6WesEZdT1xmIvBA= 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= +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:pAVoSz6QO8bwYqn9Y7f2Bgdvh8TVNMiv/JqJgwSI+ck= diff --git a/internal/domain/main-entities/device-order/entity.go b/internal/domain/main-entities/device-order/entity.go index 7f693518..5fd1b430 100644 --- a/internal/domain/main-entities/device-order/entity.go +++ b/internal/domain/main-entities/device-order/entity.go @@ -13,6 +13,7 @@ type DeviceOrder struct { Encounter_Id *uint `json:"encounter_id"` Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` Status_Code erc.DataStatusCode `json:"status_code"` } diff --git a/internal/domain/main-entities/inpatient/entity.go b/internal/domain/main-entities/inpatient/entity.go index f88eb2fb..7d4c54aa 100644 --- a/internal/domain/main-entities/inpatient/entity.go +++ b/internal/domain/main-entities/inpatient/entity.go @@ -11,5 +11,6 @@ type Inpatient struct { Encounter_Id *uint `json:"encounter_id"` Class_Code ere.InpatientClassCode `json:"class_code" gorm:"size:10"` Infra_Id *uint16 `json:"infra_id"` + Infra_Code string `json:"infra_code" gorm:"size:10"` Infra *ei.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Id;references:Id"` } diff --git a/internal/domain/main-entities/material-order/entity.go b/internal/domain/main-entities/material-order/entity.go index 27b5c011..ac572fb9 100644 --- a/internal/domain/main-entities/material-order/entity.go +++ b/internal/domain/main-entities/material-order/entity.go @@ -13,6 +13,7 @@ type MaterialOrder struct { Encounter_Id *uint `json:"encounter_id"` Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` Status_Code erc.DataStatusCode `json:"status_code"` } diff --git a/internal/domain/main-entities/mcu-order/entity.go b/internal/domain/main-entities/mcu-order/entity.go index bf4e2e77..e4acac0c 100644 --- a/internal/domain/main-entities/mcu-order/entity.go +++ b/internal/domain/main-entities/mcu-order/entity.go @@ -16,6 +16,7 @@ type McuOrder struct { Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Status_Code erc.DataStatusCode `json:"status_code" gorm:"not null;size:10"` Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` SpecimenPickTime *time.Time `json:"specimenPickTime"` ExaminationDate *time.Time `json:"examinationDate"` From 2f1a8574976b0fc37f880987240a018891ec054d Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 10 Nov 2025 16:00:57 +0700 Subject: [PATCH 130/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 56 ++++++++++++------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index dea504e8..ab44e5a2 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:0WHQByo4Ygfp9nGAp4I/lFIvSvl/PkL9DLUgA9rn1QQ= +h1:jtJgRhcOOs1tw/x4ItSCjrM4l4yLWZ/CDakq5hjqnyQ= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,30 +75,30 @@ h1:0WHQByo4Ygfp9nGAp4I/lFIvSvl/PkL9DLUgA9rn1QQ= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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:pAVoSz6QO8bwYqn9Y7f2Bgdvh8TVNMiv/JqJgwSI+ck= +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= From 42ac3deeb0625e8b64f2ff3abd5c91aa11a1aa43 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 10 Nov 2025 16:14:31 +0700 Subject: [PATCH 131/329] change ids into codes for device-order,material-order,mcu-order --- .../domain/main-entities/device-order/dto.go | 8 ++++---- .../domain/main-entities/device-order/entity.go | 7 +++---- internal/domain/main-entities/encounter/dto.go | 2 +- internal/domain/main-entities/inpatient/dto.go | 8 ++++---- .../domain/main-entities/inpatient/entity.go | 5 ++--- .../domain/main-entities/material-order/dto.go | 6 +++--- .../main-entities/material-order/entity.go | 7 +++---- internal/domain/main-entities/mcu-order/dto.go | 8 ++++---- .../domain/main-entities/mcu-order/entity.go | 7 +++---- .../use-case/main-use-case/device-order/case.go | 15 +++------------ .../main-use-case/device-order/helper.go | 2 +- .../use-case/main-use-case/encounter/helper.go | 2 +- .../use-case/main-use-case/inpatient/helper.go | 1 + .../main-use-case/material-order/case.go | 16 +++------------- .../main-use-case/material-order/helper.go | 2 +- .../use-case/main-use-case/mcu-order/case.go | 16 +++------------- .../use-case/main-use-case/mcu-order/helper.go | 3 +-- 17 files changed, 41 insertions(+), 74 deletions(-) diff --git a/internal/domain/main-entities/device-order/dto.go b/internal/domain/main-entities/device-order/dto.go index 3d944941..6371800c 100644 --- a/internal/domain/main-entities/device-order/dto.go +++ b/internal/domain/main-entities/device-order/dto.go @@ -18,7 +18,7 @@ import ( type CreateDto struct { Encounter_Id *uint `json:"encounter_id"` Status_Code erc.DataStatusCode `json:"status_code"` - Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` pa.AuthInfo } @@ -32,7 +32,7 @@ type ReadListDto struct { type FilterDto struct { Encounter_Id *uint `json:"encounter-id"` Status_Code erc.DataStatusCode `json:"status-code"` - Doctor_Id *uint `json:"doctor-id"` + Doctor_Code *string `json:"doctor-code"` } type ReadDetailDto struct { Id uint16 `json:"id"` @@ -57,7 +57,7 @@ type ResponseDto struct { ecore.Main Encounter_Id *uint `json:"encounter_id"` Encounter *ee.Encounter `json:"encounter,omitempty"` - Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` Doctor *ed.Doctor `json:"doctor,omitempty"` Status_Code erc.DataStatusCode `json:"status_code"` } @@ -66,7 +66,7 @@ func (d DeviceOrder) ToResponse() ResponseDto { resp := ResponseDto{ Encounter_Id: d.Encounter_Id, Encounter: d.Encounter, - Doctor_Id: d.Doctor_Id, + Doctor_Code: d.Doctor_Code, Doctor: d.Doctor, Status_Code: d.Status_Code, } diff --git a/internal/domain/main-entities/device-order/entity.go b/internal/domain/main-entities/device-order/entity.go index 5fd1b430..7ff4fa34 100644 --- a/internal/domain/main-entities/device-order/entity.go +++ b/internal/domain/main-entities/device-order/entity.go @@ -12,9 +12,8 @@ type DeviceOrder struct { ecore.Main // adjust this according to the needs Encounter_Id *uint `json:"encounter_id"` Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Doctor_Id *uint `json:"doctor_id"` Doctor_Code *string `json:"doctor_code"` - Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"` Status_Code erc.DataStatusCode `json:"status_code"` } @@ -22,6 +21,6 @@ func (d DeviceOrder) IsCompleted() bool { return d.Status_Code == erc.DSCDone } -func (d DeviceOrder) IsSameDoctor(doctor_id *uint) bool { - return d.Doctor_Id == doctor_id +func (d DeviceOrder) IsSameDoctor(doctor_code *string) bool { + return d.Doctor_Code == doctor_code } diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index af8c1336..290a7766 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -37,7 +37,7 @@ type CreateDto struct { 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_Id *uint16 `json:"infra_id"` // for inpatient + 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"` diff --git a/internal/domain/main-entities/inpatient/dto.go b/internal/domain/main-entities/inpatient/dto.go index 11a864eb..be817ad0 100644 --- a/internal/domain/main-entities/inpatient/dto.go +++ b/internal/domain/main-entities/inpatient/dto.go @@ -10,7 +10,7 @@ import ( type CreateDto struct { Encounter_Id *uint `json:"encounter_id"` Class_Code ere.InpatientClassCode `json:"class_code" validate:"maxLength=10"` - Infra_Id *uint16 `json:"infra_id"` + Infra_Code *string `json:"infra_code"` } type ReadListDto struct { @@ -22,7 +22,7 @@ type ReadListDto struct { type FilterDto struct { Encounter_Id *uint `json:"encounter-id"` Class_Code ere.InpatientClassCode `json:"class-code"` - Infra_Id *uint16 `json:"infra-id"` + Infra_Code *string `json:"infra-code"` } type ReadDetailDto struct { @@ -48,7 +48,7 @@ type ResponseDto struct { ecore.Main Encounter_Id *uint `json:"encounter_id"` Class_Code ere.InpatientClassCode `json:"class_code"` - Infra_Id *uint16 `json:"infra_id"` + Infra_Code *string `json:"infra_code"` Infra *ei.Infra `json:"infra,omitempty"` } @@ -56,7 +56,7 @@ func (d Inpatient) ToResponse() ResponseDto { resp := ResponseDto{ Encounter_Id: d.Encounter_Id, Class_Code: d.Class_Code, - Infra_Id: d.Infra_Id, + Infra_Code: d.Infra_Code, Infra: d.Infra, } resp.Main = d.Main diff --git a/internal/domain/main-entities/inpatient/entity.go b/internal/domain/main-entities/inpatient/entity.go index 7d4c54aa..39cc2dbe 100644 --- a/internal/domain/main-entities/inpatient/entity.go +++ b/internal/domain/main-entities/inpatient/entity.go @@ -10,7 +10,6 @@ type Inpatient struct { ecore.Main // adjust this according to the needs Encounter_Id *uint `json:"encounter_id"` Class_Code ere.InpatientClassCode `json:"class_code" gorm:"size:10"` - Infra_Id *uint16 `json:"infra_id"` - Infra_Code string `json:"infra_code" gorm:"size:10"` - Infra *ei.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Id;references:Id"` + Infra_Code *string `json:"infra_code" gorm:"size:10"` + Infra *ei.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Code;references:Code"` } diff --git a/internal/domain/main-entities/material-order/dto.go b/internal/domain/main-entities/material-order/dto.go index bd4f5c91..b830119d 100644 --- a/internal/domain/main-entities/material-order/dto.go +++ b/internal/domain/main-entities/material-order/dto.go @@ -18,7 +18,7 @@ import ( type CreateDto struct { Encounter_Id *uint `json:"encounter_id"` Status_Code erc.DataStatusCode `json:"status_code"` - Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` pa.AuthInfo } @@ -56,7 +56,7 @@ type ResponseDto struct { ecore.Main Encounter_Id *uint `json:"encounter_id"` Encounter *ee.Encounter `json:"encounter,omitempty"` - Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` Doctor *ed.Doctor `json:"doctor,omitempty"` Status_Code erc.DataStatusCode `json:"status_code"` } @@ -65,7 +65,7 @@ func (d MaterialOrder) ToResponse() ResponseDto { resp := ResponseDto{ Encounter_Id: d.Encounter_Id, Encounter: d.Encounter, - Doctor_Id: d.Doctor_Id, + Doctor_Code: d.Doctor_Code, Doctor: d.Doctor, Status_Code: d.Status_Code, } diff --git a/internal/domain/main-entities/material-order/entity.go b/internal/domain/main-entities/material-order/entity.go index ac572fb9..aec23316 100644 --- a/internal/domain/main-entities/material-order/entity.go +++ b/internal/domain/main-entities/material-order/entity.go @@ -12,9 +12,8 @@ type MaterialOrder struct { ecore.Main // adjust this according to the needs Encounter_Id *uint `json:"encounter_id"` Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Doctor_Id *uint `json:"doctor_id"` Doctor_Code *string `json:"doctor_code"` - Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"` Status_Code erc.DataStatusCode `json:"status_code"` } @@ -22,6 +21,6 @@ func (d MaterialOrder) IsCompleted() bool { return d.Status_Code == erc.DSCDone } -func (d MaterialOrder) IsSameDoctor(doctor_id *uint) bool { - return d.Doctor_Id == doctor_id +func (d MaterialOrder) IsSameDoctor(doctor_code *string) bool { + return d.Doctor_Code == doctor_code } diff --git a/internal/domain/main-entities/mcu-order/dto.go b/internal/domain/main-entities/mcu-order/dto.go index e63a3e08..594f72d7 100644 --- a/internal/domain/main-entities/mcu-order/dto.go +++ b/internal/domain/main-entities/mcu-order/dto.go @@ -22,7 +22,7 @@ import ( type CreateDto struct { Encounter_Id *uint `json:"encounter_id"` Status_Code erc.DataStatusCode `json:"status_code" gorm:"not null;size:10"` - Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` SpecimenPickTime *time.Time `json:"specimenPickTime"` ExaminationDate *time.Time `json:"examinationDate"` Number uint8 `json:"number"` @@ -42,7 +42,7 @@ type ReadListDto struct { type FilterDto struct { Encounter_Id *uint `json:"encounter-id"` Status_Code erc.DataStatusCode `json:"status-code" gorm:"not null;size:10"` - Doctor_Id *uint `json:"doctor-id"` + Doctor_Code *string `json:"doctor-code"` SpecimenPickTime *time.Time `json:"specimenPickTime"` ExaminationDate *time.Time `json:"examinationDate"` Number uint8 `json:"number"` @@ -79,7 +79,7 @@ type ResponseDto struct { Encounter_Id *uint `json:"encounter_id"` Encounter *ee.Encounter `json:"encounter,omitempty"` Status_Code erc.DataStatusCode `json:"status_code" gorm:"not null;size:10"` - Doctor_Id *uint `json:"doctor_id"` + Doctor_Code *string `json:"doctor_code"` Doctor *ed.Doctor `json:"doctor,omitempty"` SpecimenPickTime *time.Time `json:"specimenPickTime"` ExaminationDate *time.Time `json:"examinationDate"` @@ -93,7 +93,7 @@ func (d McuOrder) ToResponse() ResponseDto { Encounter_Id: d.Encounter_Id, Encounter: d.Encounter, Status_Code: d.Status_Code, - Doctor_Id: d.Doctor_Id, + Doctor_Code: d.Doctor_Code, Doctor: d.Doctor, SpecimenPickTime: d.SpecimenPickTime, ExaminationDate: d.ExaminationDate, diff --git a/internal/domain/main-entities/mcu-order/entity.go b/internal/domain/main-entities/mcu-order/entity.go index e4acac0c..b9e5d0d7 100644 --- a/internal/domain/main-entities/mcu-order/entity.go +++ b/internal/domain/main-entities/mcu-order/entity.go @@ -15,9 +15,8 @@ type McuOrder struct { Encounter_Id *uint `json:"encounter_id"` Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Status_Code erc.DataStatusCode `json:"status_code" gorm:"not null;size:10"` - Doctor_Id *uint `json:"doctor_id"` Doctor_Code *string `json:"doctor_code"` - Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"` SpecimenPickTime *time.Time `json:"specimenPickTime"` ExaminationDate *time.Time `json:"examinationDate"` Number uint8 `json:"number"` @@ -30,6 +29,6 @@ func (d McuOrder) IsCompleted() bool { return d.Status_Code == erc.DSCDone } -func (d McuOrder) IsSameDoctor(doctor_id *uint) bool { - return d.Doctor_Id == doctor_id +func (d McuOrder) IsSameDoctor(doctor_code *string) bool { + return d.Doctor_Code == doctor_code } diff --git a/internal/use-case/main-use-case/device-order/case.go b/internal/use-case/main-use-case/device-order/case.go index 89466ead..b48e7670 100644 --- a/internal/use-case/main-use-case/device-order/case.go +++ b/internal/use-case/main-use-case/device-order/case.go @@ -6,7 +6,6 @@ import ( e "simrs-vx/internal/domain/main-entities/device-order" - ud "simrs-vx/internal/use-case/main-use-case/doctor" ue "simrs-vx/internal/use-case/main-use-case/encounter" erc "simrs-vx/internal/domain/references/common" @@ -60,11 +59,7 @@ func Create(input e.CreateDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - doctor_id, err := ud.GetIdByUserId(&input.AuthInfo.User_Id, &event, tx) - if err != nil { - return err - } - input.Doctor_Id = doctor_id + input.Doctor_Code = input.AuthInfo.Doctor_Code if resData, err := CreateData(input, &event, tx); err != nil { return err @@ -236,11 +231,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - doctor_id, err := ud.GetIdByUserId(&input.AuthInfo.User_Id, &event, tx) - if err != nil { - return err - } - if !data.IsSameDoctor(doctor_id) { + if !data.IsSameDoctor(input.AuthInfo.Doctor_Code) { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "auth-forbidden", @@ -250,7 +241,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - input.Doctor_Id = doctor_id + input.Doctor_Code = input.AuthInfo.Doctor_Code if err := UpdateData(input, data, &event, tx); err != nil { return err diff --git a/internal/use-case/main-use-case/device-order/helper.go b/internal/use-case/main-use-case/device-order/helper.go index 3be32a7a..1fa0b4a8 100644 --- a/internal/use-case/main-use-case/device-order/helper.go +++ b/internal/use-case/main-use-case/device-order/helper.go @@ -21,5 +21,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.DeviceOrder) { } data.Encounter_Id = inputSrc.Encounter_Id - data.Doctor_Id = inputSrc.Doctor_Id + data.Doctor_Code = inputSrc.Doctor_Code } diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index be187bea..1e86121f 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -787,7 +787,7 @@ func insertdataClassCode(input e.CreateDto, soapiData []es.CreateDto, event *pl. inpCreate := ei.CreateDto{ Encounter_Id: &input.Id, Class_Code: subCode, - Infra_Id: input.Infra_Id, + Infra_Code: input.Infra_Code, } // create data inpatient diff --git a/internal/use-case/main-use-case/inpatient/helper.go b/internal/use-case/main-use-case/inpatient/helper.go index 45014af1..d59ea4d8 100644 --- a/internal/use-case/main-use-case/inpatient/helper.go +++ b/internal/use-case/main-use-case/inpatient/helper.go @@ -22,6 +22,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Inpatient) { data.Encounter_Id = inputSrc.Encounter_Id data.Class_Code = inputSrc.Class_Code + data.Infra_Code = inputSrc.Infra_Code } func CheckClassCode(input *string) (ere.InpatientClassCode, error) { diff --git a/internal/use-case/main-use-case/material-order/case.go b/internal/use-case/main-use-case/material-order/case.go index 713f64c0..a6d3943c 100644 --- a/internal/use-case/main-use-case/material-order/case.go +++ b/internal/use-case/main-use-case/material-order/case.go @@ -6,7 +6,6 @@ import ( e "simrs-vx/internal/domain/main-entities/material-order" - ud "simrs-vx/internal/use-case/main-use-case/doctor" ue "simrs-vx/internal/use-case/main-use-case/encounter" erc "simrs-vx/internal/domain/references/common" @@ -56,11 +55,7 @@ func Create(input e.CreateDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - doctor_id, err := ud.GetIdByUserId(&input.AuthInfo.User_Id, &event, tx) - if err != nil { - return err - } - input.Doctor_Id = doctor_id + input.Doctor_Code = input.AuthInfo.Doctor_Code if resData, err := CreateData(input, &event, tx); err != nil { return err @@ -233,12 +228,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - doctor_id, err := ud.GetIdByUserId(&input.AuthInfo.User_Id, &event, tx) - if err != nil { - return err - } - - if !data.IsSameDoctor(doctor_id) { + if !data.IsSameDoctor(input.AuthInfo.Doctor_Code) { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "auth-forbidden", @@ -248,7 +238,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - input.Doctor_Id = doctor_id + input.Doctor_Code = input.AuthInfo.Doctor_Code if err := UpdateData(input, data, &event, tx); err != nil { return err diff --git a/internal/use-case/main-use-case/material-order/helper.go b/internal/use-case/main-use-case/material-order/helper.go index fe0862e9..8f037f91 100644 --- a/internal/use-case/main-use-case/material-order/helper.go +++ b/internal/use-case/main-use-case/material-order/helper.go @@ -21,5 +21,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.MaterialOrder) { } data.Encounter_Id = inputSrc.Encounter_Id - data.Doctor_Id = inputSrc.Doctor_Id + data.Doctor_Code = inputSrc.Doctor_Code } diff --git a/internal/use-case/main-use-case/mcu-order/case.go b/internal/use-case/main-use-case/mcu-order/case.go index 19b34cbe..38f13088 100644 --- a/internal/use-case/main-use-case/mcu-order/case.go +++ b/internal/use-case/main-use-case/mcu-order/case.go @@ -6,7 +6,6 @@ import ( e "simrs-vx/internal/domain/main-entities/mcu-order" - ud "simrs-vx/internal/use-case/main-use-case/doctor" ue "simrs-vx/internal/use-case/main-use-case/encounter" erc "simrs-vx/internal/domain/references/common" @@ -56,11 +55,7 @@ func Create(input e.CreateDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - doctor_id, err := ud.GetIdByUserId(&input.AuthInfo.User_Id, &event, tx) - if err != nil { - return err - } - input.Doctor_Id = doctor_id + input.Doctor_Code = input.AuthInfo.Doctor_Code if resData, err := CreateData(input, &event, tx); err != nil { return err @@ -233,12 +228,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - doctor_id, err := ud.GetIdByUserId(&input.AuthInfo.User_Id, &event, tx) - if err != nil { - return err - } - - if !data.IsSameDoctor(doctor_id) { + if !data.IsSameDoctor(input.AuthInfo.Doctor_Code) { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "auth-forbidden", @@ -248,7 +238,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - input.Doctor_Id = doctor_id + input.Doctor_Code = input.AuthInfo.Doctor_Code if err := UpdateData(input, data, &event, tx); err != nil { return err diff --git a/internal/use-case/main-use-case/mcu-order/helper.go b/internal/use-case/main-use-case/mcu-order/helper.go index 7c21f1f6..1c803f68 100644 --- a/internal/use-case/main-use-case/mcu-order/helper.go +++ b/internal/use-case/main-use-case/mcu-order/helper.go @@ -21,12 +21,11 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.McuOrder) { } data.Encounter_Id = inputSrc.Encounter_Id - data.Doctor_Id = inputSrc.Doctor_Id + data.Doctor_Code = inputSrc.Doctor_Code data.SpecimenPickTime = inputSrc.SpecimenPickTime data.ExaminationDate = inputSrc.ExaminationDate data.Number = inputSrc.Number data.Temperature = inputSrc.Temperature data.UrgencyLevel_Code = inputSrc.UrgencyLevel_Code - data.Doctor_Id = inputSrc.Doctor_Id data.Scope_Code = inputSrc.Scope_Code } From 9a31e3458aec8b08f4a19b261356a2bbf62f787e Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 10 Nov 2025 16:15:43 +0700 Subject: [PATCH 132/329] missing sql for orders --- .../migrations/20251110091516.sql | 8 +++ cmd/main-migration/migrations/atlas.sum | 57 ++++++++++--------- 2 files changed, 37 insertions(+), 28 deletions(-) create mode 100644 cmd/main-migration/migrations/20251110091516.sql diff --git a/cmd/main-migration/migrations/20251110091516.sql b/cmd/main-migration/migrations/20251110091516.sql new file mode 100644 index 00000000..10010abb --- /dev/null +++ b/cmd/main-migration/migrations/20251110091516.sql @@ -0,0 +1,8 @@ +-- Modify "DeviceOrder" table +ALTER TABLE "public"."DeviceOrder" DROP CONSTRAINT "fk_DeviceOrder_Doctor", DROP COLUMN "Doctor_Id", ALTER COLUMN "Doctor_Code" TYPE character varying(20), ADD CONSTRAINT "fk_DeviceOrder_Doctor" FOREIGN KEY ("Doctor_Code") REFERENCES "public"."Doctor" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "Inpatient" table +ALTER TABLE "public"."Inpatient" DROP CONSTRAINT "fk_Inpatient_Infra", DROP COLUMN "Infra_Id", ADD CONSTRAINT "fk_Inpatient_Infra" FOREIGN KEY ("Infra_Code") REFERENCES "public"."Infra" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "MaterialOrder" table +ALTER TABLE "public"."MaterialOrder" DROP CONSTRAINT "fk_MaterialOrder_Doctor", DROP COLUMN "Doctor_Id", ALTER COLUMN "Doctor_Code" TYPE character varying(20), ADD CONSTRAINT "fk_MaterialOrder_Doctor" FOREIGN KEY ("Doctor_Code") REFERENCES "public"."Doctor" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "McuOrder" table +ALTER TABLE "public"."McuOrder" DROP CONSTRAINT "fk_McuOrder_Doctor", DROP COLUMN "Doctor_Id", ALTER COLUMN "Doctor_Code" TYPE character varying(20), ADD CONSTRAINT "fk_McuOrder_Doctor" FOREIGN KEY ("Doctor_Code") REFERENCES "public"."Doctor" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index ab44e5a2..ebd13cad 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:jtJgRhcOOs1tw/x4ItSCjrM4l4yLWZ/CDakq5hjqnyQ= +h1:BpoUN3cuDwl8qQq7oIvuL3/WTtOf2FQFeeJdrN48Rho= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,30 +75,31 @@ h1:jtJgRhcOOs1tw/x4ItSCjrM4l4yLWZ/CDakq5hjqnyQ= 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= +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:pAVoSz6QO8bwYqn9Y7f2Bgdvh8TVNMiv/JqJgwSI+ck= +20251110091516.sql h1:Ab7z5iz7MgeSKxkvXGQSTZfO2nRO6lu1c/5SwO3aeCs= From 84e8c02aa191b9d0b8aa7c4c6f0932bb3d213f34 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 10 Nov 2025 16:16:45 +0700 Subject: [PATCH 133/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 58 ++++++++++++------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index ebd13cad..f4a9539c 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:BpoUN3cuDwl8qQq7oIvuL3/WTtOf2FQFeeJdrN48Rho= +h1:j0mwMOjBr1U307mQWXlC/OO6O8rXMmMERX8HWYwlw+M= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,31 +75,31 @@ h1:BpoUN3cuDwl8qQq7oIvuL3/WTtOf2FQFeeJdrN48Rho= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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:pAVoSz6QO8bwYqn9Y7f2Bgdvh8TVNMiv/JqJgwSI+ck= -20251110091516.sql h1:Ab7z5iz7MgeSKxkvXGQSTZfO2nRO6lu1c/5SwO3aeCs= +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= From f2af40a40fb5549ffa6fd94a314ca3183e76e30a Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 10 Nov 2025 16:21:47 +0700 Subject: [PATCH 134/329] add deivice and material code for their orders --- .../migrations/20251110091948.sql | 4 ++ cmd/main-migration/migrations/atlas.sum | 59 ++++++++++--------- .../main-entities/device-order-item/entity.go | 1 + .../material-order-item/entity.go | 1 + 4 files changed, 36 insertions(+), 29 deletions(-) create mode 100644 cmd/main-migration/migrations/20251110091948.sql diff --git a/cmd/main-migration/migrations/20251110091948.sql b/cmd/main-migration/migrations/20251110091948.sql new file mode 100644 index 00000000..452f56ad --- /dev/null +++ b/cmd/main-migration/migrations/20251110091948.sql @@ -0,0 +1,4 @@ +-- Modify "DeviceOrderItem" table +ALTER TABLE "public"."DeviceOrderItem" ADD COLUMN "Device_Code" text NULL; +-- Modify "MaterialOrderItem" table +ALTER TABLE "public"."MaterialOrderItem" ADD COLUMN "Material_Code" text NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index f4a9539c..d5380a06 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:j0mwMOjBr1U307mQWXlC/OO6O8rXMmMERX8HWYwlw+M= +h1:nS/RlvaYUufpmk9gGH3DyaT5uz9TGBS6bHOoyUQiOVY= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,31 +75,32 @@ h1:j0mwMOjBr1U307mQWXlC/OO6O8rXMmMERX8HWYwlw+M= 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= +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:pAVoSz6QO8bwYqn9Y7f2Bgdvh8TVNMiv/JqJgwSI+ck= +20251110091516.sql h1:Ab7z5iz7MgeSKxkvXGQSTZfO2nRO6lu1c/5SwO3aeCs= +20251110091948.sql h1:cM8dIy7OHIxws4fcpJjHhY61+4Q1aNCXpyKh9BbSOB8= diff --git a/internal/domain/main-entities/device-order-item/entity.go b/internal/domain/main-entities/device-order-item/entity.go index 196415af..35ed1273 100644 --- a/internal/domain/main-entities/device-order-item/entity.go +++ b/internal/domain/main-entities/device-order-item/entity.go @@ -11,6 +11,7 @@ type DeviceOrderItem struct { DeviceOrder_Id *uint `json:"deviceOrder_id"` DeviceOrder *edo.DeviceOrder `json:"deviceOrder,omitempty" gorm:"foreignKey:DeviceOrder_Id;references:Id"` Device_Id *uint `json:"device_id"` + Device_Code *string `json:"device_code"` Device *ed.Device `json:"device,omitempty" gorm:"foreignKey:Device_Id;references:Id"` Count uint8 `json:"count"` } diff --git a/internal/domain/main-entities/material-order-item/entity.go b/internal/domain/main-entities/material-order-item/entity.go index 432a36b9..1ee8ff20 100644 --- a/internal/domain/main-entities/material-order-item/entity.go +++ b/internal/domain/main-entities/material-order-item/entity.go @@ -11,6 +11,7 @@ type MaterialOrderItem struct { MaterialOrder_Id *uint `json:"materialOrder_id"` MaterialOrder *emo.MaterialOrder `json:"materialOrder,omitempty" gorm:"foreignKey:MaterialOrder_Id;references:Id"` Material_Id *uint `json:"material_id"` + Material_Code *string `json:"material_code"` Material *em.Material `json:"material,omitempty" gorm:"foreignKey:Material_Id;references:Id"` Count *uint16 `json:"count"` } From 9479a674934591af732b3df0c33c4c11dd1b14e7 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 10 Nov 2025 16:22:16 +0700 Subject: [PATCH 135/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 60 ++++++++++++------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index d5380a06..3e5986fd 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:nS/RlvaYUufpmk9gGH3DyaT5uz9TGBS6bHOoyUQiOVY= +h1:t/RiG4+9F6uLvgSXMDmBBXDULzInvre2pxMfKdXmaAY= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,32 +75,32 @@ h1:nS/RlvaYUufpmk9gGH3DyaT5uz9TGBS6bHOoyUQiOVY= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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:pAVoSz6QO8bwYqn9Y7f2Bgdvh8TVNMiv/JqJgwSI+ck= -20251110091516.sql h1:Ab7z5iz7MgeSKxkvXGQSTZfO2nRO6lu1c/5SwO3aeCs= -20251110091948.sql h1:cM8dIy7OHIxws4fcpJjHhY61+4Q1aNCXpyKh9BbSOB8= +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= From 8d301af4e39b5c03bdc0e6e1ceecfc91ac3c56cd Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 10 Nov 2025 16:29:03 +0700 Subject: [PATCH 136/329] change id into code for device and material order item --- .../migrations/20251110092729.sql | 4 ++ cmd/main-migration/migrations/atlas.sum | 61 ++++++++++--------- .../main-entities/device-order-item/dto.go | 16 ++--- .../main-entities/device-order-item/entity.go | 3 +- .../main-entities/material-order-item/dto.go | 8 +-- .../material-order-item/entity.go | 3 +- .../main-use-case/device-order-item/helper.go | 2 +- .../material-order-item/helper.go | 2 +- 8 files changed, 51 insertions(+), 48 deletions(-) create mode 100644 cmd/main-migration/migrations/20251110092729.sql diff --git a/cmd/main-migration/migrations/20251110092729.sql b/cmd/main-migration/migrations/20251110092729.sql new file mode 100644 index 00000000..7f4702ab --- /dev/null +++ b/cmd/main-migration/migrations/20251110092729.sql @@ -0,0 +1,4 @@ +-- Modify "DeviceOrderItem" table +ALTER TABLE "public"."DeviceOrderItem" DROP CONSTRAINT "fk_DeviceOrderItem_Device", DROP COLUMN "Device_Id", ALTER COLUMN "Device_Code" TYPE character varying(10), ADD CONSTRAINT "fk_DeviceOrderItem_Device" FOREIGN KEY ("Device_Code") REFERENCES "public"."Device" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "MaterialOrderItem" table +ALTER TABLE "public"."MaterialOrderItem" DROP CONSTRAINT "fk_MaterialOrderItem_Material", DROP COLUMN "Material_Id", ALTER COLUMN "Material_Code" TYPE character varying(10), ADD CONSTRAINT "fk_MaterialOrderItem_Material" FOREIGN KEY ("Material_Code") REFERENCES "public"."Material" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 3e5986fd..48aaaef5 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:t/RiG4+9F6uLvgSXMDmBBXDULzInvre2pxMfKdXmaAY= +h1:ib+C98Dbbvu+hHl5iZy4QQGSDIllnGFtgsOJOC226jw= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,32 +75,33 @@ h1:t/RiG4+9F6uLvgSXMDmBBXDULzInvre2pxMfKdXmaAY= 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= +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:pAVoSz6QO8bwYqn9Y7f2Bgdvh8TVNMiv/JqJgwSI+ck= +20251110091516.sql h1:Ab7z5iz7MgeSKxkvXGQSTZfO2nRO6lu1c/5SwO3aeCs= +20251110091948.sql h1:cM8dIy7OHIxws4fcpJjHhY61+4Q1aNCXpyKh9BbSOB8= +20251110092729.sql h1:AAg9gXlwOWxOS5L6EryOUNrKkFna7i0oiKdiu3G1Hyg= diff --git a/internal/domain/main-entities/device-order-item/dto.go b/internal/domain/main-entities/device-order-item/dto.go index e89d5fad..afa08ed8 100644 --- a/internal/domain/main-entities/device-order-item/dto.go +++ b/internal/domain/main-entities/device-order-item/dto.go @@ -7,9 +7,9 @@ import ( ) type CreateDto struct { - DeviceOrder_Id *uint `json:"deviceOrder_id"` - Device_Id *uint `json:"device_id"` - Count uint8 `json:"count"` + DeviceOrder_Id *uint `json:"deviceOrder_id"` + Device_Code *string `json:"device_code"` + Count uint8 `json:"count"` } type ReadListDto struct { @@ -19,9 +19,9 @@ type ReadListDto struct { } type FilterDto struct { - DeviceOrder_Id *uint `json:"deviceOrder-id"` - Device_Id *uint `json:"device-id"` - Count uint8 `json:"count"` + DeviceOrder_Id *uint `json:"deviceOrder-id"` + Device_Code *string `json:"device-code"` + Count uint8 `json:"count"` } type ReadDetailDto struct { Id uint16 `json:"id"` @@ -46,7 +46,7 @@ type ResponseDto struct { ecore.Main DeviceOrder_Id *uint `json:"deviceOrder_id"` DeviceOrder *edo.DeviceOrder `json:"deviceOrder,omitempty"` - Device_Id *uint `json:"device_id"` + Device_Code *string `json:"device_code"` Device *ed.Device `json:"device,omitempty"` Count uint8 `json:"count"` } @@ -55,7 +55,7 @@ func (d DeviceOrderItem) ToResponse() ResponseDto { resp := ResponseDto{ DeviceOrder_Id: d.DeviceOrder_Id, DeviceOrder: d.DeviceOrder, - Device_Id: d.Device_Id, + Device_Code: d.Device_Code, Device: d.Device, Count: d.Count, } diff --git a/internal/domain/main-entities/device-order-item/entity.go b/internal/domain/main-entities/device-order-item/entity.go index 35ed1273..27197125 100644 --- a/internal/domain/main-entities/device-order-item/entity.go +++ b/internal/domain/main-entities/device-order-item/entity.go @@ -10,8 +10,7 @@ type DeviceOrderItem struct { ecore.Main // adjust this according to the needs DeviceOrder_Id *uint `json:"deviceOrder_id"` DeviceOrder *edo.DeviceOrder `json:"deviceOrder,omitempty" gorm:"foreignKey:DeviceOrder_Id;references:Id"` - Device_Id *uint `json:"device_id"` Device_Code *string `json:"device_code"` - Device *ed.Device `json:"device,omitempty" gorm:"foreignKey:Device_Id;references:Id"` + Device *ed.Device `json:"device,omitempty" gorm:"foreignKey:Device_Code;references:Code"` Count uint8 `json:"count"` } diff --git a/internal/domain/main-entities/material-order-item/dto.go b/internal/domain/main-entities/material-order-item/dto.go index b76792bf..c8fd363d 100644 --- a/internal/domain/main-entities/material-order-item/dto.go +++ b/internal/domain/main-entities/material-order-item/dto.go @@ -8,7 +8,7 @@ import ( type CreateDto struct { MaterialOrder_Id *uint `json:"materialOrder_id"` - Material_Id *uint `json:"material_id"` + Material_Code *string `json:"material_code"` Count *uint16 `json:"count"` } @@ -20,7 +20,7 @@ type ReadListDto struct { type FilterDto struct { MaterialOrder_Id *uint `json:"materialOrder-id"` - Material_Id *uint `json:"material-id"` + Material_Code *string `json:"material-code"` Count *uint16 `json:"count"` } type ReadDetailDto struct { @@ -46,7 +46,7 @@ type ResponseDto struct { ecore.Main MaterialOrder_Id *uint `json:"materialOrder_id"` MaterialOrder *emo.MaterialOrder `json:"materialOrder,omitempty"` - Material_Id *uint `json:"material_id"` + Material_Code *string `json:"material_code"` Material *em.Material `json:"material,omitempty"` Count *uint16 `json:"count"` } @@ -55,7 +55,7 @@ func (d MaterialOrderItem) ToResponse() ResponseDto { resp := ResponseDto{ MaterialOrder_Id: d.MaterialOrder_Id, MaterialOrder: d.MaterialOrder, - Material_Id: d.Material_Id, + Material_Code: d.Material_Code, Material: d.Material, Count: d.Count, } diff --git a/internal/domain/main-entities/material-order-item/entity.go b/internal/domain/main-entities/material-order-item/entity.go index 1ee8ff20..2a85122a 100644 --- a/internal/domain/main-entities/material-order-item/entity.go +++ b/internal/domain/main-entities/material-order-item/entity.go @@ -10,8 +10,7 @@ type MaterialOrderItem struct { ecore.Main // adjust this according to the needs MaterialOrder_Id *uint `json:"materialOrder_id"` MaterialOrder *emo.MaterialOrder `json:"materialOrder,omitempty" gorm:"foreignKey:MaterialOrder_Id;references:Id"` - Material_Id *uint `json:"material_id"` Material_Code *string `json:"material_code"` - Material *em.Material `json:"material,omitempty" gorm:"foreignKey:Material_Id;references:Id"` + Material *em.Material `json:"material,omitempty" gorm:"foreignKey:Material_Code;references:Code"` Count *uint16 `json:"count"` } diff --git a/internal/use-case/main-use-case/device-order-item/helper.go b/internal/use-case/main-use-case/device-order-item/helper.go index 5c6a0e68..8c0be91f 100644 --- a/internal/use-case/main-use-case/device-order-item/helper.go +++ b/internal/use-case/main-use-case/device-order-item/helper.go @@ -18,6 +18,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.DeviceOrderItem) { } data.DeviceOrder_Id = inputSrc.DeviceOrder_Id - data.Device_Id = inputSrc.Device_Id + data.Device_Code = inputSrc.Device_Code data.Count = inputSrc.Count } diff --git a/internal/use-case/main-use-case/material-order-item/helper.go b/internal/use-case/main-use-case/material-order-item/helper.go index 25e89a21..f66daa0b 100644 --- a/internal/use-case/main-use-case/material-order-item/helper.go +++ b/internal/use-case/main-use-case/material-order-item/helper.go @@ -18,6 +18,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.MaterialOrderItem) } data.MaterialOrder_Id = inputSrc.MaterialOrder_Id - data.Material_Id = inputSrc.Material_Id + data.Material_Code = inputSrc.Material_Code data.Count = inputSrc.Count } From 292494aef53d96a33cf6a101a5559c94bd1dfd78 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 10 Nov 2025 16:29:45 +0700 Subject: [PATCH 137/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 62 ++++++++++++------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 48aaaef5..2b03059b 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:ib+C98Dbbvu+hHl5iZy4QQGSDIllnGFtgsOJOC226jw= +h1:PwecfCdEjCSLS4UKY6o7TVTpykK+3hshlIMuxus+6i0= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,33 +75,33 @@ h1:ib+C98Dbbvu+hHl5iZy4QQGSDIllnGFtgsOJOC226jw= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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:pAVoSz6QO8bwYqn9Y7f2Bgdvh8TVNMiv/JqJgwSI+ck= -20251110091516.sql h1:Ab7z5iz7MgeSKxkvXGQSTZfO2nRO6lu1c/5SwO3aeCs= -20251110091948.sql h1:cM8dIy7OHIxws4fcpJjHhY61+4Q1aNCXpyKh9BbSOB8= -20251110092729.sql h1:AAg9gXlwOWxOS5L6EryOUNrKkFna7i0oiKdiu3G1Hyg= +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= From 698508603b0b8aafbf6aa36ce2f54dcfa9d589dc Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 10 Nov 2025 16:40:21 +0700 Subject: [PATCH 138/329] add code into several mcu src related --- .../migrations/20251110093522.sql | 8 +++ cmd/main-migration/migrations/atlas.sum | 63 ++++++++++--------- .../domain/main-entities/mcu-src/entity.go | 3 +- .../main-entities/mcu-sub-src/entity.go | 15 ++--- .../medical-action-src-item/entity.go | 17 ++--- .../medical-action-src/entity.go | 1 + 6 files changed, 61 insertions(+), 46 deletions(-) create mode 100644 cmd/main-migration/migrations/20251110093522.sql diff --git a/cmd/main-migration/migrations/20251110093522.sql b/cmd/main-migration/migrations/20251110093522.sql new file mode 100644 index 00000000..8ed5f757 --- /dev/null +++ b/cmd/main-migration/migrations/20251110093522.sql @@ -0,0 +1,8 @@ +-- Modify "McuSrc" table +ALTER TABLE "public"."McuSrc" ALTER COLUMN "Code" SET NOT NULL, ADD COLUMN "Item_Code" text NULL; +-- Modify "McuSubSrc" table +ALTER TABLE "public"."McuSubSrc" ADD COLUMN "McuSrc_Code" text NULL; +-- Modify "MedicalActionSrc" table +ALTER TABLE "public"."MedicalActionSrc" ADD COLUMN "Item_Code" text NULL; +-- Modify "MedicalActionSrcItem" table +ALTER TABLE "public"."MedicalActionSrcItem" ADD COLUMN "MedicalActionSrc_Code" text NULL, ADD COLUMN "ProcedureSrc_Code" text NULL, ADD COLUMN "Item_Code" text NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 2b03059b..31545436 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:PwecfCdEjCSLS4UKY6o7TVTpykK+3hshlIMuxus+6i0= +h1:7su4TCxtZLd3s2IfGnHk536Sn0iwiPX72MzTmVzghaQ= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,33 +75,34 @@ h1:PwecfCdEjCSLS4UKY6o7TVTpykK+3hshlIMuxus+6i0= 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= +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:pAVoSz6QO8bwYqn9Y7f2Bgdvh8TVNMiv/JqJgwSI+ck= +20251110091516.sql h1:Ab7z5iz7MgeSKxkvXGQSTZfO2nRO6lu1c/5SwO3aeCs= +20251110091948.sql h1:cM8dIy7OHIxws4fcpJjHhY61+4Q1aNCXpyKh9BbSOB8= +20251110092729.sql h1:AAg9gXlwOWxOS5L6EryOUNrKkFna7i0oiKdiu3G1Hyg= +20251110093522.sql h1:sCowKTPaaXKKaa5i5HKIlOaOeqre+5m4RxTUNHPrOX8= diff --git a/internal/domain/main-entities/mcu-src/entity.go b/internal/domain/main-entities/mcu-src/entity.go index d3f4fca1..6f97ac24 100644 --- a/internal/domain/main-entities/mcu-src/entity.go +++ b/internal/domain/main-entities/mcu-src/entity.go @@ -8,10 +8,11 @@ import ( type McuSrc struct { ecore.Main // adjust this according to the needs - Code string `json:"code" gorm:"unique;size:20"` + Code string `json:"code" gorm:"unique;size:20;not null"` Name string `json:"name" gorm:"size:50"` McuSrcCategory_Code *string `json:"mcuSrcCategory_code" gorm:"size:20"` McuSrcCategory *emsc.McuSrcCategory `json:"mcuSrcCategory,omitempty" gorm:"foreignKey:McuSrcCategory_Code;references:Code"` Item_Id *uint `json:"item_id"` + Item_Code *string `json:"item_code"` Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` } diff --git a/internal/domain/main-entities/mcu-sub-src/entity.go b/internal/domain/main-entities/mcu-sub-src/entity.go index 02559abb..d81e9d00 100644 --- a/internal/domain/main-entities/mcu-sub-src/entity.go +++ b/internal/domain/main-entities/mcu-sub-src/entity.go @@ -7,11 +7,12 @@ import ( ) type McuSubSrc struct { - ecore.Main // adjust this according to the needs - Code string `json:"code" gorm:"unique;size:20"` - Name string `json:"name" gorm:"size:50"` - McuSrc_Id *uint `json:"mcuSrc_id"` - McuSrc *ems.McuSrc `json:"mcuSrc,omitempty" gorm:"foreignKey:McuSrc_Id;references:Id"` - Item_Id *uint `json:"item_id"` - Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` + ecore.Main // adjust this according to the needs + Code string `json:"code" gorm:"unique;size:20"` + Name string `json:"name" gorm:"size:50"` + McuSrc_Id *uint `json:"mcuSrc_id"` + McuSrc_Code *string `json:"mcuSrc_code"` + McuSrc *ems.McuSrc `json:"mcuSrc,omitempty" gorm:"foreignKey:McuSrc_Id;references:Id"` + Item_Id *uint `json:"item_id"` + Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` } diff --git a/internal/domain/main-entities/medical-action-src-item/entity.go b/internal/domain/main-entities/medical-action-src-item/entity.go index 59ecb828..579d7d87 100644 --- a/internal/domain/main-entities/medical-action-src-item/entity.go +++ b/internal/domain/main-entities/medical-action-src-item/entity.go @@ -8,11 +8,14 @@ import ( ) type MedicalActionSrcItem struct { - ecore.Main // adjust this according to the needs - MedicalActionSrc_Id *uint `json:"medicalActionSrc_id"` - MedicalActionSrc *emas.MedicalActionSrc `json:"medicalActionSrc,omitempty" gorm:"foreignKey:MedicalActionSrc_Id;references:Id"` - ProcedureSrc_Id *uint `json:"procedureSrc_id"` - ProcedureSrc *eps.ProcedureSrc `json:"procedureSrc,omitempty" gorm:"foreignKey:ProcedureSrc_Id;references:Id"` - Item_Id *uint `json:"item_id"` - Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` + ecore.Main // adjust this according to the needs + MedicalActionSrc_Id *uint `json:"medicalActionSrc_id"` + MedicalActionSrc_Code *string `json:"medicalActionSrc_code"` + MedicalActionSrc *emas.MedicalActionSrc `json:"medicalActionSrc,omitempty" gorm:"foreignKey:MedicalActionSrc_Id;references:Id"` + ProcedureSrc_Id *uint `json:"procedureSrc_id"` + ProcedureSrc_Code *string `json:"procedureSrc_code"` + ProcedureSrc *eps.ProcedureSrc `json:"procedureSrc,omitempty" gorm:"foreignKey:ProcedureSrc_Id;references:Id"` + Item_Id *uint `json:"item_id"` + Item_Code *string `json:"item_code"` + Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` } diff --git a/internal/domain/main-entities/medical-action-src/entity.go b/internal/domain/main-entities/medical-action-src/entity.go index 60f15816..a4543d92 100644 --- a/internal/domain/main-entities/medical-action-src/entity.go +++ b/internal/domain/main-entities/medical-action-src/entity.go @@ -11,5 +11,6 @@ type MedicalActionSrc struct { Name string `json:"name" gorm:"size:50"` Type_Code string `json:"type_code" gorm:"size:20"` Item_Id *uint `json:"item_id"` + Item_Code *string `json:"item_code"` Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` } From b00e34a7001a73b0623d155ca38d640a66ae7099 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 10 Nov 2025 16:41:15 +0700 Subject: [PATCH 139/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 64 ++++++++++++------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 31545436..c5616081 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:7su4TCxtZLd3s2IfGnHk536Sn0iwiPX72MzTmVzghaQ= +h1:6IW+yN2RN0XymhaT/06JrQgiM+zJq5sv75us5k42LtI= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,34 +75,34 @@ h1:7su4TCxtZLd3s2IfGnHk536Sn0iwiPX72MzTmVzghaQ= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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:pAVoSz6QO8bwYqn9Y7f2Bgdvh8TVNMiv/JqJgwSI+ck= -20251110091516.sql h1:Ab7z5iz7MgeSKxkvXGQSTZfO2nRO6lu1c/5SwO3aeCs= -20251110091948.sql h1:cM8dIy7OHIxws4fcpJjHhY61+4Q1aNCXpyKh9BbSOB8= -20251110092729.sql h1:AAg9gXlwOWxOS5L6EryOUNrKkFna7i0oiKdiu3G1Hyg= -20251110093522.sql h1:sCowKTPaaXKKaa5i5HKIlOaOeqre+5m4RxTUNHPrOX8= +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= From 98d063b8c3c593edd1db52cab4c15d67679546fe Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 10 Nov 2025 17:06:10 +0700 Subject: [PATCH 140/329] remove ids from mcu related --- .../migrations/20251110100258.sql | 8 +++ .../migrations/20251110100545.sql | 2 + cmd/main-migration/migrations/atlas.sum | 66 ++++++++++--------- internal/domain/main-entities/mcu-src/dto.go | 15 +++-- .../domain/main-entities/mcu-src/entity.go | 3 +- .../domain/main-entities/mcu-sub-src/dto.go | 43 ++++++------ .../main-entities/mcu-sub-src/entity.go | 7 +- .../medical-action-src-item/dto.go | 36 +++++----- .../medical-action-src-item/entity.go | 9 +-- .../main-entities/medical-action-src/dto.go | 31 ++++----- .../medical-action-src/entity.go | 3 +- .../interface/main-handler/main-handler.go | 6 +- .../interface/main-handler/mcu-src/handler.go | 18 ++--- .../main-handler/mcu-sub-src/handler.go | 18 ++--- .../medical-action-src/handler.go | 18 ++--- .../use-case/main-use-case/mcu-src/case.go | 4 +- .../use-case/main-use-case/mcu-src/helper.go | 6 +- .../use-case/main-use-case/mcu-src/lib.go | 9 ++- .../main-use-case/mcu-sub-src/case.go | 4 +- .../main-use-case/mcu-sub-src/helper.go | 10 +-- .../use-case/main-use-case/mcu-sub-src/lib.go | 9 ++- .../medical-action-src-item/helper.go | 6 +- .../main-use-case/medical-action-src/case.go | 4 +- .../medical-action-src/helper.go | 8 +-- .../main-use-case/medical-action-src/lib.go | 9 ++- 25 files changed, 191 insertions(+), 161 deletions(-) create mode 100644 cmd/main-migration/migrations/20251110100258.sql create mode 100644 cmd/main-migration/migrations/20251110100545.sql diff --git a/cmd/main-migration/migrations/20251110100258.sql b/cmd/main-migration/migrations/20251110100258.sql new file mode 100644 index 00000000..9d902938 --- /dev/null +++ b/cmd/main-migration/migrations/20251110100258.sql @@ -0,0 +1,8 @@ +-- Modify "McuSrc" table +ALTER TABLE "public"."McuSrc" DROP CONSTRAINT "fk_McuSrc_Item", DROP COLUMN "Item_Id", ALTER COLUMN "Item_Code" TYPE character varying(50), ADD CONSTRAINT "fk_McuSrc_Item" FOREIGN KEY ("Item_Code") REFERENCES "public"."Item" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "McuSubSrc" table +ALTER TABLE "public"."McuSubSrc" DROP CONSTRAINT "fk_McuSubSrc_McuSrc", DROP COLUMN "McuSrc_Id", ALTER COLUMN "McuSrc_Code" TYPE character varying(20), ADD COLUMN "Item_Code" text NULL, ADD CONSTRAINT "fk_McuSubSrc_McuSrc" FOREIGN KEY ("McuSrc_Code") REFERENCES "public"."McuSrc" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "MedicalActionSrc" table +ALTER TABLE "public"."MedicalActionSrc" DROP CONSTRAINT "fk_MedicalActionSrc_Item", DROP COLUMN "Item_Id", ALTER COLUMN "Item_Code" TYPE character varying(50), ADD CONSTRAINT "fk_MedicalActionSrc_Item" FOREIGN KEY ("Item_Code") REFERENCES "public"."Item" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "MedicalActionSrcItem" table +ALTER TABLE "public"."MedicalActionSrcItem" DROP CONSTRAINT "fk_MedicalActionSrcItem_Item", DROP CONSTRAINT "fk_MedicalActionSrcItem_MedicalActionSrc", DROP CONSTRAINT "fk_MedicalActionSrcItem_ProcedureSrc", DROP COLUMN "MedicalActionSrc_Id", DROP COLUMN "ProcedureSrc_Id", DROP COLUMN "Item_Id", ALTER COLUMN "MedicalActionSrc_Code" TYPE character varying(20), ALTER COLUMN "ProcedureSrc_Code" TYPE character varying(10), ALTER COLUMN "Item_Code" TYPE character varying(50), ADD CONSTRAINT "fk_MedicalActionSrcItem_Item" FOREIGN KEY ("Item_Code") REFERENCES "public"."Item" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_MedicalActionSrcItem_MedicalActionSrc" FOREIGN KEY ("MedicalActionSrc_Code") REFERENCES "public"."MedicalActionSrc" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_MedicalActionSrcItem_ProcedureSrc" FOREIGN KEY ("ProcedureSrc_Code") REFERENCES "public"."ProcedureSrc" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251110100545.sql b/cmd/main-migration/migrations/20251110100545.sql new file mode 100644 index 00000000..3fdc6a82 --- /dev/null +++ b/cmd/main-migration/migrations/20251110100545.sql @@ -0,0 +1,2 @@ +-- Modify "McuSubSrc" table +ALTER TABLE "public"."McuSubSrc" DROP CONSTRAINT "fk_McuSubSrc_Item", DROP COLUMN "Item_Id", ALTER COLUMN "Item_Code" TYPE character varying(50), ADD CONSTRAINT "fk_McuSubSrc_Item" FOREIGN KEY ("Item_Code") REFERENCES "public"."Item" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index c5616081..7756676a 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:6IW+yN2RN0XymhaT/06JrQgiM+zJq5sv75us5k42LtI= +h1:A2lCKVFcUNfX413tNFZWZs6OkFj5+RmByLwekKRxWow= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,34 +75,36 @@ h1:6IW+yN2RN0XymhaT/06JrQgiM+zJq5sv75us5k42LtI= 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= +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:pAVoSz6QO8bwYqn9Y7f2Bgdvh8TVNMiv/JqJgwSI+ck= +20251110091516.sql h1:Ab7z5iz7MgeSKxkvXGQSTZfO2nRO6lu1c/5SwO3aeCs= +20251110091948.sql h1:cM8dIy7OHIxws4fcpJjHhY61+4Q1aNCXpyKh9BbSOB8= +20251110092729.sql h1:AAg9gXlwOWxOS5L6EryOUNrKkFna7i0oiKdiu3G1Hyg= +20251110093522.sql h1:sCowKTPaaXKKaa5i5HKIlOaOeqre+5m4RxTUNHPrOX8= +20251110100258.sql h1:3iVmC33XfxCquwfyWTC0QsUNPgiX9/mknggjTbJXfCk= +20251110100545.sql h1:b5pQN3cg59DahiA/rujc45RH53XQFaUmqVqouglFk1o= diff --git a/internal/domain/main-entities/mcu-src/dto.go b/internal/domain/main-entities/mcu-src/dto.go index 7ab13428..6db7af65 100644 --- a/internal/domain/main-entities/mcu-src/dto.go +++ b/internal/domain/main-entities/mcu-src/dto.go @@ -6,10 +6,10 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=20"` + Code *string `json:"code" validate:"maxLength=20"` Name string `json:"name" validate:"maxLength=50"` McuSrcCategory_Code *string `json:"mcuSrcCategory_code" validate:"maxLength=20"` - Item_Id *uint `json:"item_id"` + Item_Code *string `json:"item_code"` } type ReadListDto struct { @@ -27,17 +27,18 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { @@ -51,7 +52,7 @@ type ResponseDto struct { Code string `json:"code"` Name string `json:"name"` McuSrcCategory_Code *string `json:"mcuSrcCategory_code"` - Item_Id *uint `json:"item_id"` + Item_Code *string `json:"item_code"` Item *ei.Item `json:"item,omitempty"` } @@ -60,7 +61,7 @@ func (d McuSrc) ToResponse() ResponseDto { Code: d.Code, Name: d.Name, McuSrcCategory_Code: d.McuSrcCategory_Code, - Item_Id: d.Item_Id, + Item_Code: d.Item_Code, Item: d.Item, } resp.Main = d.Main diff --git a/internal/domain/main-entities/mcu-src/entity.go b/internal/domain/main-entities/mcu-src/entity.go index 6f97ac24..91ef8b99 100644 --- a/internal/domain/main-entities/mcu-src/entity.go +++ b/internal/domain/main-entities/mcu-src/entity.go @@ -12,7 +12,6 @@ type McuSrc struct { Name string `json:"name" gorm:"size:50"` McuSrcCategory_Code *string `json:"mcuSrcCategory_code" gorm:"size:20"` McuSrcCategory *emsc.McuSrcCategory `json:"mcuSrcCategory,omitempty" gorm:"foreignKey:McuSrcCategory_Code;references:Code"` - Item_Id *uint `json:"item_id"` Item_Code *string `json:"item_code"` - Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` + Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Code;references:Code"` } diff --git a/internal/domain/main-entities/mcu-sub-src/dto.go b/internal/domain/main-entities/mcu-sub-src/dto.go index f1b6d3bb..fde77fd2 100644 --- a/internal/domain/main-entities/mcu-sub-src/dto.go +++ b/internal/domain/main-entities/mcu-sub-src/dto.go @@ -7,10 +7,10 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=20"` - Name string `json:"name" validate:"maxLength=50"` - McuSrc_Id *uint `json:"mcuSrc_id"` - Item_Id *uint `json:"item_id"` + Code *string `json:"code" validate:"maxLength=20"` + Name string `json:"name" validate:"maxLength=50"` + McuSrc_Code *string `json:"mcuSrc_code"` + Item_Code *string `json:"item_code"` } type ReadListDto struct { @@ -21,24 +21,25 @@ type ReadListDto struct { } type FilterDto struct { - Code string `json:"code"` - Name string `json:"name"` + Code *string `json:"code"` + Name *string `json:"name"` CheckupCategory_Code *string `json:"checkupCategory-code"` Search string `json:"search" gormhelper:"searchColumns=Code,Name"` } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { @@ -49,22 +50,22 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Code string `json:"code"` - Name string `json:"name"` - McuSrc_Id *uint `json:"mcuSrc_id"` - McuSrc *ems.McuSrc `json:"mcuSrc,omitempty"` - Item_Id *uint `json:"item_id"` - Item *ei.Item `json:"item,omitempty"` + Code string `json:"code"` + Name string `json:"name"` + McuSrc_Code *string `json:"mcuSrc_code"` + McuSrc *ems.McuSrc `json:"mcuSrc,omitempty"` + Item_Code *string `json:"item_code"` + Item *ei.Item `json:"item,omitempty"` } func (d McuSubSrc) ToResponse() ResponseDto { resp := ResponseDto{ - Code: d.Code, - Name: d.Name, - McuSrc_Id: d.McuSrc_Id, - McuSrc: d.McuSrc, - Item_Id: d.Item_Id, - Item: d.Item, + Code: d.Code, + Name: d.Name, + McuSrc_Code: d.McuSrc_Code, + McuSrc: d.McuSrc, + Item_Code: d.Item_Code, + Item: d.Item, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/mcu-sub-src/entity.go b/internal/domain/main-entities/mcu-sub-src/entity.go index d81e9d00..888ebf90 100644 --- a/internal/domain/main-entities/mcu-sub-src/entity.go +++ b/internal/domain/main-entities/mcu-sub-src/entity.go @@ -10,9 +10,8 @@ type McuSubSrc struct { ecore.Main // adjust this according to the needs Code string `json:"code" gorm:"unique;size:20"` Name string `json:"name" gorm:"size:50"` - McuSrc_Id *uint `json:"mcuSrc_id"` McuSrc_Code *string `json:"mcuSrc_code"` - McuSrc *ems.McuSrc `json:"mcuSrc,omitempty" gorm:"foreignKey:McuSrc_Id;references:Id"` - Item_Id *uint `json:"item_id"` - Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` + McuSrc *ems.McuSrc `json:"mcuSrc,omitempty" gorm:"foreignKey:McuSrc_Code;references:Code"` + Item_Code *string `json:"item_code"` + Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Code;references:Code"` } diff --git a/internal/domain/main-entities/medical-action-src-item/dto.go b/internal/domain/main-entities/medical-action-src-item/dto.go index 540a6ca5..849e6b18 100644 --- a/internal/domain/main-entities/medical-action-src-item/dto.go +++ b/internal/domain/main-entities/medical-action-src-item/dto.go @@ -8,9 +8,9 @@ import ( ) type CreateDto struct { - MedicalActionSrc_Id *uint `json:"medicalActionSrc_id"` - ProcedureSrc_Id *uint `json:"procedureSrc_id"` - Item_Id *uint `json:"item_id"` + MedicalActionSrc_Code *string `json:"medicalActionSrc_code"` + ProcedureSrc_Code *string `json:"procedureSrc_code"` + Item_Code *string `json:"item_code"` } type ReadListDto struct { @@ -20,9 +20,9 @@ type ReadListDto struct { } type FilterDto struct { - MedicalActionSrc_Id *uint `json:"medicalActionSrc-id"` - ProcedureSrc_Id *uint `json:"procedureSrc-id"` - Item_Id *uint `json:"item-id"` + MedicalActionSrc_Code *string `json:"medicalActionSrc-code"` + ProcedureSrc_Code *string `json:"procedureSrc-code"` + Item_Code *string `json:"item-code"` } type ReadDetailDto struct { @@ -46,22 +46,22 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - MedicalActionSrc_Id *uint `json:"medicalActionSrc_id"` - MedicalActionSrc *emas.MedicalActionSrc `json:"medicalActionSrc,omitempty"` - ProcedureSrc_Id *uint `json:"procedureSrc_id"` - ProcedureSrc *eps.ProcedureSrc `json:"procedureSrc,omitempty"` - Item_Id *uint `json:"item_id"` - Item *ei.Item `json:"item,omitempty"` + MedicalActionSrc_Code *string `json:"medicalActionSrc_code"` + MedicalActionSrc *emas.MedicalActionSrc `json:"medicalActionSrc,omitempty"` + ProcedureSrc_Code *string `json:"procedureSrc_code"` + ProcedureSrc *eps.ProcedureSrc `json:"procedureSrc,omitempty"` + Item_Code *string `json:"item_code"` + Item *ei.Item `json:"item,omitempty"` } func (d MedicalActionSrcItem) ToResponse() ResponseDto { resp := ResponseDto{ - MedicalActionSrc_Id: d.MedicalActionSrc_Id, - MedicalActionSrc: d.MedicalActionSrc, - ProcedureSrc_Id: d.ProcedureSrc_Id, - ProcedureSrc: d.ProcedureSrc, - Item_Id: d.Item_Id, - Item: d.Item, + MedicalActionSrc_Code: d.MedicalActionSrc_Code, + MedicalActionSrc: d.MedicalActionSrc, + ProcedureSrc_Code: d.ProcedureSrc_Code, + ProcedureSrc: d.ProcedureSrc, + Item_Code: d.Item_Code, + Item: d.Item, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/medical-action-src-item/entity.go b/internal/domain/main-entities/medical-action-src-item/entity.go index 579d7d87..2474c08b 100644 --- a/internal/domain/main-entities/medical-action-src-item/entity.go +++ b/internal/domain/main-entities/medical-action-src-item/entity.go @@ -9,13 +9,10 @@ import ( type MedicalActionSrcItem struct { ecore.Main // adjust this according to the needs - MedicalActionSrc_Id *uint `json:"medicalActionSrc_id"` MedicalActionSrc_Code *string `json:"medicalActionSrc_code"` - MedicalActionSrc *emas.MedicalActionSrc `json:"medicalActionSrc,omitempty" gorm:"foreignKey:MedicalActionSrc_Id;references:Id"` - ProcedureSrc_Id *uint `json:"procedureSrc_id"` + MedicalActionSrc *emas.MedicalActionSrc `json:"medicalActionSrc,omitempty" gorm:"foreignKey:MedicalActionSrc_Code;references:Code"` ProcedureSrc_Code *string `json:"procedureSrc_code"` - ProcedureSrc *eps.ProcedureSrc `json:"procedureSrc,omitempty" gorm:"foreignKey:ProcedureSrc_Id;references:Id"` - Item_Id *uint `json:"item_id"` + ProcedureSrc *eps.ProcedureSrc `json:"procedureSrc,omitempty" gorm:"foreignKey:ProcedureSrc_Code;references:Code"` Item_Code *string `json:"item_code"` - Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` + Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Code;references:Code"` } diff --git a/internal/domain/main-entities/medical-action-src/dto.go b/internal/domain/main-entities/medical-action-src/dto.go index 32e248d8..9316677f 100644 --- a/internal/domain/main-entities/medical-action-src/dto.go +++ b/internal/domain/main-entities/medical-action-src/dto.go @@ -6,10 +6,10 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=20"` - Name string `json:"name" validate:"maxLength=50"` - Type_Code string `json:"type_code" validate:"maxLength=20"` - Item_Id *uint `json:"item_id"` + Code *string `json:"code" validate:"maxLength=20"` + Name string `json:"name" validate:"maxLength=50"` + Type_Code string `json:"type_code" validate:"maxLength=20"` + Item_Code *string `json:"item_code"` } type ReadListDto struct { @@ -20,25 +20,26 @@ type ReadListDto struct { } type FilterDto struct { - Code string `json:"code"` - Name string `json:"name"` - Type_Code string `json:"type_code"` - Item_Id *uint `json:"item-id"` - Search string `json:"search" gormhelper:"searchColumns=Code,Name"` + Code *string `json:"code"` + Name string `json:"name"` + Type_Code string `json:"type_code"` + Item_Code *string `json:"item-code"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` } type ReadDetailDto struct { - Id uint16 `json:"id"` - Code string `json:"code"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type UpdateDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` CreateDto } type DeleteDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` + Code *string `json:"code"` } type MetaDto struct { @@ -52,7 +53,7 @@ type ResponseDto struct { Code string `json:"code"` Name string `json:"name"` Type_Code string `json:"type_code"` - Item_Id *uint `json:"item_id"` + Item_Code *string `json:"item_code"` Item *ei.Item `json:"item,omitempty"` } @@ -61,7 +62,7 @@ func (d MedicalActionSrc) ToResponse() ResponseDto { Code: d.Code, Name: d.Name, Type_Code: d.Type_Code, - Item_Id: d.Item_Id, + Item_Code: d.Item_Code, Item: d.Item, } resp.Main = d.Main diff --git a/internal/domain/main-entities/medical-action-src/entity.go b/internal/domain/main-entities/medical-action-src/entity.go index a4543d92..db3672a6 100644 --- a/internal/domain/main-entities/medical-action-src/entity.go +++ b/internal/domain/main-entities/medical-action-src/entity.go @@ -10,7 +10,6 @@ type MedicalActionSrc struct { Code string `json:"code" gorm:"unique;size:20"` Name string `json:"name" gorm:"size:50"` Type_Code string `json:"type_code" gorm:"size:20"` - Item_Id *uint `json:"item_id"` Item_Code *string `json:"item_code"` - Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` + Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Code;references:Code"` } diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 15c236b8..74a5e40a 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -316,17 +316,17 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/medicine-group", medicinegroup.O) hc.RegCrud(r, "/v1/medicine-method", medicinemethod.O) hc.RegCrud(r, "/v1/mcu-src-category", mcusrccategory.O) - hc.RegCrud(r, "/v1/mcu-src", mcusrc.O) + hc.RegCrudByCode(r, "/v1/mcu-src", mcusrc.O) hc.RegCrud(r, "/v1/ethnic", ethnic.O) hc.RegCrud(r, "/v1/insurance-company", insurancecompany.O) hc.RegCrudByCode(r, "/v1/medicine", medicine.O) hc.RegCrudByCode(r, "/v1/device", device.O) hc.RegCrudByCode(r, "/v1/material", material.O) hc.RegCrud(r, "/v1/doctor-fee", doctorfee.O) - hc.RegCrud(r, "/v1/medical-action-src", medicalactionsrc.O) + hc.RegCrudByCode(r, "/v1/medical-action-src", medicalactionsrc.O) hc.RegCrud(r, "/v1/medical-action-src-item", medicalactionsrcitem.O) hc.RegCrud(r, "/v1/language", language.O) - hc.RegCrud(r, "/v1/mcu-sub-src", mcusubsrc.O) + hc.RegCrudByCode(r, "/v1/mcu-sub-src", mcusubsrc.O) hc.RegCrud(r, "/v1/vehicle", vehicle.O) hc.RegCrud(r, "/v1/vehicle-hist", vehiclehist.O) hc.RegCrud(r, "/v1/edu-assessment", eduassesment.O) diff --git a/internal/interface/main-handler/mcu-src/handler.go b/internal/interface/main-handler/mcu-src/handler.go index c607017d..7523ea7e 100644 --- a/internal/interface/main-handler/mcu-src/handler.go +++ b/internal/interface/main-handler/mcu-src/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ 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.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/mcu-sub-src/handler.go b/internal/interface/main-handler/mcu-sub-src/handler.go index 949be715..ad7868d9 100644 --- a/internal/interface/main-handler/mcu-sub-src/handler.go +++ b/internal/interface/main-handler/mcu-sub-src/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ 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.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/medical-action-src/handler.go b/internal/interface/main-handler/medical-action-src/handler.go index c8b24706..42d41c92 100644 --- a/internal/interface/main-handler/medical-action-src/handler.go +++ b/internal/interface/main-handler/medical-action-src/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint(id) + dto.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/use-case/main-use-case/mcu-src/case.go b/internal/use-case/main-use-case/mcu-src/case.go index 564a582b..31af8e84 100644 --- a/internal/use-case/main-use-case/mcu-src/case.go +++ b/internal/use-case/main-use-case/mcu-src/case.go @@ -170,7 +170,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.McuSrc var err error @@ -226,7 +226,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.McuSrc var err error diff --git a/internal/use-case/main-use-case/mcu-src/helper.go b/internal/use-case/main-use-case/mcu-src/helper.go index 9d808ca8..545def25 100644 --- a/internal/use-case/main-use-case/mcu-src/helper.go +++ b/internal/use-case/main-use-case/mcu-src/helper.go @@ -27,14 +27,14 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.McuSrc) { inputSrc = &inputTemp.CreateDto } - data.Code = inputSrc.Code + data.Code = *inputSrc.Code data.Name = inputSrc.Name data.McuSrcCategory_Code = inputSrc.McuSrcCategory_Code } func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { itemCreate := ei.CreateDto{ - Code: pu.AddPrefix("mcu-", input.Code), + Code: pu.AddPrefix("mcu-", *input.Code), Name: input.Name, ItemGroup_Code: ero.ITGCMCU, // Uom_Code: &input.Uom_Code, @@ -45,6 +45,6 @@ func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { return err } - input.Item_Id = &item.Id + input.Item_Code = &item.Code return nil } diff --git a/internal/use-case/main-use-case/mcu-src/lib.go b/internal/use-case/main-use-case/mcu-src/lib.go index e74d5ce8..d62c9282 100644 --- a/internal/use-case/main-use-case/mcu-src/lib.go +++ b/internal/use-case/main-use-case/mcu-src/lib.go @@ -81,7 +81,14 @@ 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 input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).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/mcu-sub-src/case.go b/internal/use-case/main-use-case/mcu-sub-src/case.go index ba533bc4..fbb9f468 100644 --- a/internal/use-case/main-use-case/mcu-sub-src/case.go +++ b/internal/use-case/main-use-case/mcu-sub-src/case.go @@ -170,7 +170,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.McuSubSrc var err error @@ -226,7 +226,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.McuSubSrc var err error diff --git a/internal/use-case/main-use-case/mcu-sub-src/helper.go b/internal/use-case/main-use-case/mcu-sub-src/helper.go index 95444d5a..962abe46 100644 --- a/internal/use-case/main-use-case/mcu-sub-src/helper.go +++ b/internal/use-case/main-use-case/mcu-sub-src/helper.go @@ -27,15 +27,15 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.McuSubSrc) { inputSrc = &inputTemp.CreateDto } - data.Code = inputSrc.Code + data.Code = *inputSrc.Code data.Name = inputSrc.Name - data.McuSrc_Id = inputSrc.McuSrc_Id - data.Item_Id = inputSrc.Item_Id + data.McuSrc_Code = inputSrc.McuSrc_Code + data.Item_Code = inputSrc.Item_Code } func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { itemCreate := ei.CreateDto{ - Code: pu.AddPrefix("mcuSub-", input.Code), + Code: pu.AddPrefix("mcuSub-", *input.Code), Name: input.Name, ItemGroup_Code: ero.ITGCMCUSub, // Uom_Code: &input.Uom_Code, @@ -46,6 +46,6 @@ func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { return err } - input.Item_Id = &item.Id + input.Item_Code = &item.Code return nil } diff --git a/internal/use-case/main-use-case/mcu-sub-src/lib.go b/internal/use-case/main-use-case/mcu-sub-src/lib.go index 96684fef..438eb7ac 100644 --- a/internal/use-case/main-use-case/mcu-sub-src/lib.go +++ b/internal/use-case/main-use-case/mcu-sub-src/lib.go @@ -81,7 +81,14 @@ 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 input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).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/medical-action-src-item/helper.go b/internal/use-case/main-use-case/medical-action-src-item/helper.go index 385b0f53..09d028a9 100644 --- a/internal/use-case/main-use-case/medical-action-src-item/helper.go +++ b/internal/use-case/main-use-case/medical-action-src-item/helper.go @@ -16,7 +16,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.MedicalActionSrcIte inputTemp := any(input).(*e.UpdateDto) inputSrc = &inputTemp.CreateDto } - data.MedicalActionSrc_Id = inputSrc.MedicalActionSrc_Id - data.ProcedureSrc_Id = inputSrc.ProcedureSrc_Id - data.Item_Id = inputSrc.Item_Id + data.MedicalActionSrc_Code = inputSrc.MedicalActionSrc_Code + data.ProcedureSrc_Code = inputSrc.ProcedureSrc_Code + data.Item_Code = inputSrc.Item_Code } diff --git a/internal/use-case/main-use-case/medical-action-src/case.go b/internal/use-case/main-use-case/medical-action-src/case.go index cd42766c..7ca58dde 100644 --- a/internal/use-case/main-use-case/medical-action-src/case.go +++ b/internal/use-case/main-use-case/medical-action-src/case.go @@ -169,7 +169,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.MedicalActionSrc var err error @@ -225,7 +225,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.MedicalActionSrc var err error diff --git a/internal/use-case/main-use-case/medical-action-src/helper.go b/internal/use-case/main-use-case/medical-action-src/helper.go index c955274d..910b6f8a 100644 --- a/internal/use-case/main-use-case/medical-action-src/helper.go +++ b/internal/use-case/main-use-case/medical-action-src/helper.go @@ -27,15 +27,15 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.MedicalActionSrc) { inputSrc = &inputTemp.CreateDto } - data.Code = inputSrc.Code + data.Code = *inputSrc.Code data.Name = inputSrc.Name data.Type_Code = inputSrc.Type_Code - data.Item_Id = inputSrc.Item_Id + data.Item_Code = inputSrc.Item_Code } func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { itemCreate := ei.CreateDto{ - Code: pu.AddPrefix("medAct-", input.Code), + Code: pu.AddPrefix("medAct-", *input.Code), Name: input.Name, ItemGroup_Code: ero.ITGCMedAct, } @@ -44,6 +44,6 @@ func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { return err } - input.Item_Id = &item.Id + input.Item_Code = &item.Code return nil } diff --git a/internal/use-case/main-use-case/medical-action-src/lib.go b/internal/use-case/main-use-case/medical-action-src/lib.go index 31492861..dd29a6b3 100644 --- a/internal/use-case/main-use-case/medical-action-src/lib.go +++ b/internal/use-case/main-use-case/medical-action-src/lib.go @@ -81,7 +81,14 @@ 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 input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { return nil, processedErr } From 6cb09a7ca7964f96f6b55d270e0f574878f657d7 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 10 Nov 2025 17:06:45 +0700 Subject: [PATCH 141/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 68 ++++++++++++------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 7756676a..293ca91a 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:A2lCKVFcUNfX413tNFZWZs6OkFj5+RmByLwekKRxWow= +h1:EhWXa9CRUdCX5FiHAOEgknGsAmS+hlumbeo45IiWbbs= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,36 +75,36 @@ h1:A2lCKVFcUNfX413tNFZWZs6OkFj5+RmByLwekKRxWow= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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:pAVoSz6QO8bwYqn9Y7f2Bgdvh8TVNMiv/JqJgwSI+ck= -20251110091516.sql h1:Ab7z5iz7MgeSKxkvXGQSTZfO2nRO6lu1c/5SwO3aeCs= -20251110091948.sql h1:cM8dIy7OHIxws4fcpJjHhY61+4Q1aNCXpyKh9BbSOB8= -20251110092729.sql h1:AAg9gXlwOWxOS5L6EryOUNrKkFna7i0oiKdiu3G1Hyg= -20251110093522.sql h1:sCowKTPaaXKKaa5i5HKIlOaOeqre+5m4RxTUNHPrOX8= -20251110100258.sql h1:3iVmC33XfxCquwfyWTC0QsUNPgiX9/mknggjTbJXfCk= -20251110100545.sql h1:b5pQN3cg59DahiA/rujc45RH53XQFaUmqVqouglFk1o= +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= From 683ddd3ef297923888464b6ece5f2490d78b0866 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Mon, 10 Nov 2025 22:53:32 +0700 Subject: [PATCH 142/329] feat/sso-auth: added the use cases --- .../main-use-case/auth-partner/case.go | 276 ++++++++++++++++ .../main-use-case/auth-partner/helper.go | 19 ++ .../main-use-case/auth-partner/lib.go | 150 +++++++++ .../auth-partner/middleware-runner.go | 103 ++++++ .../main-use-case/auth-partner/middleware.go | 9 + .../main-use-case/auth-partner/tycovar.go | 44 +++ .../main-use-case/authentication/case.go | 296 ++++-------------- .../main-use-case/authentication/helper.go | 105 +++++-- .../use-case/main-use-case/user-fes/case.go | 276 ++++++++++++++++ .../use-case/main-use-case/user-fes/helper.go | 18 ++ .../use-case/main-use-case/user-fes/lib.go | 143 +++++++++ .../user-fes/middleware-runner.go | 103 ++++++ .../main-use-case/user-fes/middleware.go | 5 + .../main-use-case/user-fes/tycovar.go | 44 +++ 14 files changed, 1314 insertions(+), 277 deletions(-) create mode 100644 internal/use-case/main-use-case/auth-partner/case.go create mode 100644 internal/use-case/main-use-case/auth-partner/helper.go create mode 100644 internal/use-case/main-use-case/auth-partner/lib.go create mode 100644 internal/use-case/main-use-case/auth-partner/middleware-runner.go create mode 100644 internal/use-case/main-use-case/auth-partner/middleware.go create mode 100644 internal/use-case/main-use-case/auth-partner/tycovar.go create mode 100644 internal/use-case/main-use-case/user-fes/case.go create mode 100644 internal/use-case/main-use-case/user-fes/helper.go create mode 100644 internal/use-case/main-use-case/user-fes/lib.go create mode 100644 internal/use-case/main-use-case/user-fes/middleware-runner.go create mode 100644 internal/use-case/main-use-case/user-fes/middleware.go create mode 100644 internal/use-case/main-use-case/user-fes/tycovar.go diff --git a/internal/use-case/main-use-case/auth-partner/case.go b/internal/use-case/main-use-case/auth-partner/case.go new file mode 100644 index 00000000..f5f7b423 --- /dev/null +++ b/internal/use-case/main-use-case/auth-partner/case.go @@ -0,0 +1,276 @@ +package authpartner + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/auth-partner" + "strconv" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" +) + +const source = "device" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.AuthPartner{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.AuthPartner + var dataList []e.AuthPartner + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.AuthPartner + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: &input.Id} + var data *e.AuthPartner + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: &input.Id} + var data *e.AuthPartner + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/auth-partner/helper.go b/internal/use-case/main-use-case/auth-partner/helper.go new file mode 100644 index 00000000..36e1ce7b --- /dev/null +++ b/internal/use-case/main-use-case/auth-partner/helper.go @@ -0,0 +1,19 @@ +package authpartner + +import ( + e "simrs-vx/internal/domain/main-entities/auth-partner" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.AuthPartner) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Code = inputSrc.Code + data.Name = inputSrc.Name + data.SecretKey = inputSrc.SecretKey +} diff --git a/internal/use-case/main-use-case/auth-partner/lib.go b/internal/use-case/main-use-case/auth-partner/lib.go new file mode 100644 index 00000000..41253e2c --- /dev/null +++ b/internal/use-case/main-use-case/auth-partner/lib.go @@ -0,0 +1,150 @@ +package authpartner + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/auth-partner" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.AuthPartner, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.AuthPartner{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.AuthPartner, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.AuthPartner{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.AuthPartner{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.AuthPartner, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.AuthPartner{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx. + Scopes(gh.Preload(input.Includes)). + First(&data).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.AuthPartner, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.AuthPartner, 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 +} diff --git a/internal/use-case/main-use-case/auth-partner/middleware-runner.go b/internal/use-case/main-use-case/auth-partner/middleware-runner.go new file mode 100644 index 00000000..d1cabe38 --- /dev/null +++ b/internal/use-case/main-use-case/auth-partner/middleware-runner.go @@ -0,0 +1,103 @@ +package authpartner + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/auth-partner" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" +) + +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.AuthPartner) 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.AuthPartner) 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.AuthPartner) 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.AuthPartner) 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.AuthPartner) 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/main-use-case/auth-partner/middleware.go b/internal/use-case/main-use-case/auth-partner/middleware.go new file mode 100644 index 00000000..4ec1231f --- /dev/null +++ b/internal/use-case/main-use-case/auth-partner/middleware.go @@ -0,0 +1,9 @@ +package authpartner + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/auth-partner/tycovar.go b/internal/use-case/main-use-case/auth-partner/tycovar.go new file mode 100644 index 00000000..43f69d98 --- /dev/null +++ b/internal/use-case/main-use-case/auth-partner/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 authpartner + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/auth-partner" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.AuthPartner, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.AuthPartner, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.AuthPartner, 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/main-use-case/authentication/case.go b/internal/use-case/main-use-case/authentication/case.go index d523ae33..94a28fef 100644 --- a/internal/use-case/main-use-case/authentication/case.go +++ b/internal/use-case/main-use-case/authentication/case.go @@ -8,7 +8,6 @@ import ( "time" "github.com/golang-jwt/jwt" - "github.com/google/uuid" a "github.com/karincake/apem" dg "github.com/karincake/apem/db-gorm-pg" ms "github.com/karincake/apem/ms-redis" @@ -19,6 +18,7 @@ import ( pl "simrs-vx/pkg/logger" p "simrs-vx/pkg/password" + eap "simrs-vx/internal/domain/main-entities/auth-partner" eu "simrs-vx/internal/domain/main-entities/user" euf "simrs-vx/internal/domain/main-entities/user-fes" erc "simrs-vx/internal/domain/references/common" @@ -42,13 +42,11 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { // Get User user := &eu.User{Name: input.Name} - // if input.Position_Code != "" { - // user.Position_Code = input.Position_Code - // } - if errCode := getAndCheck(user, user); errCode != "" { + if errCode := getAndCheck(user, user, nil); errCode != "" { return nil, d.FieldErrors{"authentication": d.FieldError{Code: errCode, Message: pl.GenMessage(errCode)}} } + // Check login attempt if user.LoginAttemptCount > 5 { if user.LastSuccessLogin != nil { now := time.Now() @@ -69,6 +67,7 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { } } + // Check password if !p.Check(input.Password, user.Password) { user.LoginAttemptCount++ dg.I.Save(&user) @@ -79,162 +78,14 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-login-unverified", Message: pl.GenMessage("auth-login-unverified")}} } - // Access token prep - id, err := uuid.NewRandom() - if err != nil { - panic(fmt.Sprintf(l.I.Msg("uuid-gen-fail"), err)) - } - if input.Duration == 0 { - input.Duration = 24 * 60 - } - duration := time.Minute * time.Duration(input.Duration) - aUuid := id.String() - atExpires := time.Now().Add(duration).Unix() - atSecretKey := authCfg.AtSecretKey - - // Create Claim + // Data and output population atClaims := jwt.MapClaims{} - atClaims["user_id"] = user.Id - atClaims["user_name"] = user.Name - atClaims["user_contractPosition_code"] = user.ContractPosition_Code - atClaims["uuid"] = aUuid - atClaims["exp"] = atExpires - - // Create output - outputData := d.II{ - "user_id": strconv.Itoa(int(user.Id)), - "user_name": user.Name, - "user_contractPosition_code": user.ContractPosition_Code, - } - - // extra - // role := []string{} - // switch user.ContractPosition_Code { - // case erg.CSCEmp: - // // employee - // employee := ee.Employee{} - // dg.I.Where("\"User_Id\" = ?", user.Id).First(&employee) - // if employee.Id == 0 { - // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noEmployee", Message: pl.GenMessage("auth-noEmployee")}} - // } - // atClaims["employee_id"] = employee.Id - // outputData["employee_id"] = employee.Id - // role = append(role, "emp-"+string(*employee.Position_Code)) - - // //if employee.Division_Code != nil { - // // atClaims["employee_division_code"] = employee.Division_Code - // // outputData["employee_division_code"] = employee.Division_Code - // //} - - // // employee position - // if employee.Id > 0 && employee.Position_Code != nil { - // atClaims["employee_position_code"] = *employee.Position_Code - // switch *employee.Position_Code { - // case erg.EPCDoc: - // doctor := ed.Doctor{} - // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&doctor) - // if doctor.Id == 0 { - // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noDoctor", Message: pl.GenMessage("auth-noDoctor")}} - // } - // atClaims["doctor_code"] = doctor.Code - // outputData["doctor_code"] = doctor.Code - - // // specialist - // if doctor.Specialist_Code != nil { - // atClaims["specialist_code"] = doctor.Specialist_Code - // outputData["specialist_code"] = doctor.Specialist_Code - // } - // if doctor.Subspecialist_Code != nil { - // atClaims["subspecialist_code"] = doctor.Subspecialist_Code - // outputData["subspecialist_code"] = doctor.Subspecialist_Code - // } - // case erg.EPCNur: - // empData := en.Nurse{} - // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) - // if empData.Id == 0 { - // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: pl.GenMessage("auth-noNurse")}} - // } - // atClaims["nurse_code"] = empData.Code - // outputData["nurse_code"] = empData.Code - // case erg.EPCMwi: - // empData := em.Midwife{} - // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) - // if empData.Id == 0 { - // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noMidwife", Message: pl.GenMessage("auth-noMidwife")}} - // } - // atClaims["midwife_code"] = empData.Code - // outputData["midwife_code"] = empData.Code - // } - - // errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: pl.GenMessage("auth-getData-failed")}} - - // // division position - // divisionPositions, err := getDivisionPosition(employee.Id, &event) - // if err != nil { - // return nil, errorGetPosition - // } - - // // installation position - // installationPositions, err := getInstallationPosition(employee.Id, &event) - // if err != nil { - // return nil, errorGetPosition - // } - - // // unit position - // unitPositions, err := getUnitPosition(employee.Id, &event) - // if err != nil { - // return nil, errorGetPosition - // } - - // // specialist position - // specialistPositions, err := getSpecialistPosition(employee.Id, &event) - // if err != nil { - // return nil, errorGetPosition - // } - - // // subspecialist position - // subspecialistPositions, err := getSubspecialistPosition(employee.Id, &event) - // if err != nil { - // return nil, errorGetPosition - // } - - // role = append(role, divisionPositions...) - // role = append(role, installationPositions...) - // role = append(role, unitPositions...) - // role = append(role, specialistPositions...) - // role = append(role, subspecialistPositions...) - // // atClaims["division_positions"] = divsionPositions - // // outputData["division_positions"] = divsionPositions - // } - // case erg.CSCInt: - // intern := intern.Intern{} - // dg.I.Where("\"User_Id\" = ?", user.Id).First(&intern) - // role = append(role, "int-"+string(*intern.Position_Code)) - // case erg.CSCSys: - // role = append(role, "system") - // } - // atClaims["roles"] = role - // outputData["roles"] = role - if err := populateRoles(user, atClaims, outputData, event); err != nil { + outputData := d.II{} + if err := populateRoles(user, input, atClaims, outputData, event); err != nil { return nil, err } - // Generate jwt - at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims) - ats, err := at.SignedString([]byte(atSecretKey)) - if err != nil { - return nil, d.FieldErrors{"user": d.FieldError{Code: "token-sign-err", Message: pl.GenMessage("token-sign-err")}} - } - outputData["accessToken"] = ats - - // Save to redis - now := time.Now() - atx := time.Unix(atExpires, 0) //converting Unix to UTC(to Time object) - err = ms.I.Set(aUuid, strconv.Itoa(int(user.Id)), atx.Sub(now)).Err() - if err != nil { - panic(fmt.Sprintf(l.I.Msg("redis-store-fail"), err.Error())) - } - + // Only manual login tn := time.Now() user.LoginAttemptCount = 0 user.LastSuccessLogin = &tn @@ -252,6 +103,51 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { }, nil } +func GenTokenFes(input euf.LoginDto) (*d.Data, error) { + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Get User Fes + userFes := &euf.UserFes{Name: input.Name, AuthPartner_Code: input.AuthPartner_Code} + if errCode := getAndCheck(userFes, userFes, "AuthPartner"); errCode != "" { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: errCode, Message: pl.GenMessage(errCode)}} + } + // Preload above fails and I am so done, do it manually + authPartner := eap.AuthPartner{} + if err := dg.I.Where("\"Code\" = ?", userFes.AuthPartner_Code).First(&authPartner).Error; err != nil { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-secretKey-invalid", Message: pl.GenMessage("auth-secretKey-invalid")}} + } + if authPartner.SecretKey != input.AuthPartner_SecretKey { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-secretKey-invalid", Message: pl.GenMessage("auth-secretKey-invalid")}} + } + + // Get User + user := &eu.User{Name: userFes.User_Name} + if errCode := getAndCheck(user, user, nil); errCode != "" { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: errCode, Message: pl.GenMessage(errCode)}} + } + + // Data and output population + atClaims := jwt.MapClaims{} + outputData := d.II{} + primInput := eu.LoginDto{Duration: input.Duration} + if err := populateRoles(user, primInput, atClaims, outputData, event); err != nil { + return nil, err + } + + // Current data + return &d.Data{ + Meta: d.IS{ + "source": "authentication", + "structure": "single-data", + "status": "verified", + }, + Data: outputData, + }, nil +} + func RevokeToken(uuid string) { ms.I.Del(uuid) } @@ -327,89 +223,3 @@ func ExtractToken(r *http.Request, tokenType TokenType) (data *pa.AuthInfo, err func GetConfig() { a.ParseCfg(&authCfg) } - -func GenTokenFes(input euf.LoginDto) (*d.Data, error) { - event := pl.Event{ - Feature: "Create", - Source: source, - } - - // Get User Fes - userFes := &euf.UserFes{Name: input.Name, AuthPartner_Code: input.AuthPartner_Code} - if errCode := getAndCheck(userFes, userFes); errCode != "" { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: errCode, Message: pl.GenMessage(errCode)}} - } - if userFes.AuthPartner.SecretKey != input.AuthPartner_SecretKey { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-secretKey-invalid", Message: pl.GenMessage("auth-secretKey-invalid")}} - } - - user := &eu.User{Name: userFes.User_Name} - if errCode := getAndCheck(user, user); errCode != "" { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: errCode, Message: pl.GenMessage(errCode)}} - } - - // Access token prep - id, err := uuid.NewRandom() - if err != nil { - panic(fmt.Sprintf(l.I.Msg("uuid-gen-fail"), err)) - } - if input.Duration == 0 { - input.Duration = 24 * 60 - } - duration := time.Minute * time.Duration(input.Duration) - aUuid := id.String() - atExpires := time.Now().Add(duration).Unix() - atSecretKey := authCfg.AtSecretKey - - // Create Claim - atClaims := jwt.MapClaims{} - atClaims["user_id"] = user.Id - atClaims["user_name"] = user.Name - atClaims["user_contractPosition_code"] = user.ContractPosition_Code - atClaims["uuid"] = aUuid - atClaims["exp"] = atExpires - - // Create output - outputData := d.II{ - "user_id": strconv.Itoa(int(user.Id)), - "user_name": user.Name, - "user_contractPosition_code": user.ContractPosition_Code, - } - - // extra - if err := populateRoles(user, atClaims, outputData, event); err != nil { - return nil, err - } - - // Generate jwt - at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims) - ats, err := at.SignedString([]byte(atSecretKey)) - if err != nil { - return nil, d.FieldErrors{"user": d.FieldError{Code: "token-sign-err", Message: pl.GenMessage("token-sign-err")}} - } - outputData["accessToken"] = ats - - // Save to redis - now := time.Now() - atx := time.Unix(atExpires, 0) //converting Unix to UTC(to Time object) - err = ms.I.Set(aUuid, strconv.Itoa(int(user.Id)), atx.Sub(now)).Err() - if err != nil { - panic(fmt.Sprintf(l.I.Msg("redis-store-fail"), err.Error())) - } - - tn := time.Now() - user.LoginAttemptCount = 0 - user.LastSuccessLogin = &tn - user.LastAllowdLogin = &tn - dg.I.Save(&user) - - // Current data - return &d.Data{ - Meta: d.IS{ - "source": "authentication", - "structure": "single-data", - "status": "verified", - }, - Data: outputData, - }, nil -} diff --git a/internal/use-case/main-use-case/authentication/helper.go b/internal/use-case/main-use-case/authentication/helper.go index 0da9f943..b7ccc660 100644 --- a/internal/use-case/main-use-case/authentication/helper.go +++ b/internal/use-case/main-use-case/authentication/helper.go @@ -1,10 +1,16 @@ package authentication import ( - dg "github.com/karincake/apem/db-gorm-pg" + "fmt" + "strconv" + "time" "github.com/golang-jwt/jwt" + "github.com/google/uuid" + dg "github.com/karincake/apem/db-gorm-pg" + ms "github.com/karincake/apem/ms-redis" d "github.com/karincake/dodol" + l "github.com/karincake/lepet" pl "simrs-vx/pkg/logger" @@ -29,8 +35,21 @@ import ( ) // just return the error code -func getAndCheck(input, condition any) (eCode string) { - result := dg.I.Where(condition).Find(&input) +func getAndCheck(input, condition any, includes any) (eCode string) { + qry := dg.I.Where(condition) + + // WARNING THIS PRELOAD FAILS + if includes != nil { + if val := includes.(string); val != "" { + qry = qry.Preload(val) + } else if vals := includes.([]string); len(vals) > 0 { + for _, val := range vals { + qry = qry.Preload(val) + } + } + } + + result := qry.First(&input) if result.Error != nil { return "fetch-fail" } else if result.RowsAffected == 0 { @@ -44,18 +63,14 @@ func getDivisionPosition(employee_id uint, event *pl.Event) ([]string, error) { var result []string // get data division_position based on employee_id - data, _, err := udp.ReadListData(edp.ReadListDto{ - FilterDto: edp.FilterDto{Employee_Id: &employee_id}, - Includes: "Division"}, event) + data, _, err := udp.ReadListData(edp.ReadListDto{FilterDto: edp.FilterDto{Employee_Id: &employee_id}}, event) if err != nil { return nil, err } if len(data) > 0 { for _, dp := range data { - if dp.Division != nil { - result = append(result, "div-"+dp.Division.Code+"-"+dp.Code) - } + result = append(result, "div-"+*dp.Division_Code) } } @@ -75,9 +90,7 @@ func getInstallationPosition(employeeId uint, event *pl.Event) ([]string, error) if len(data) > 0 { for _, dp := range data { - if dp.Installation != nil { - result = append(result, "inst-"+dp.Installation.Code+"-"+dp.Code) - } + result = append(result, "inst-"+*dp.Installation_Code+"-"+dp.Code) } } @@ -88,18 +101,14 @@ func getUnitPosition(employeeId uint, event *pl.Event) ([]string, error) { var result []string // get data unit_position based on employee_id - data, _, err := uup.ReadListData(eup.ReadListDto{ - FilterDto: eup.FilterDto{Employee_Id: &employeeId}, - Includes: "unit"}, event) + data, _, err := uup.ReadListData(eup.ReadListDto{FilterDto: eup.FilterDto{Employee_Id: &employeeId}}, event) if err != nil { return nil, err } if len(data) > 0 { for _, dp := range data { - if dp.Unit != nil { - result = append(result, "unit-"+dp.Unit.Code+"-"+dp.Code) - } + result = append(result, "unit-"+*dp.Unit_Code+"-"+dp.Code) } } @@ -110,18 +119,14 @@ func getSpecialistPosition(employeeId uint, event *pl.Event) ([]string, error) { var result []string // get data unit_position based on employee_id - data, _, err := usp.ReadListData(esp.ReadListDto{ - FilterDto: esp.FilterDto{Employee_Id: &employeeId}, - Includes: "specialist"}, event) + data, _, err := usp.ReadListData(esp.ReadListDto{FilterDto: esp.FilterDto{Employee_Id: &employeeId}}, event) if err != nil { return nil, err } if len(data) > 0 { for _, dp := range data { - if dp.Specialist != nil { - result = append(result, "spec-"+dp.Specialist.Code+"-"+dp.Code) - } + result = append(result, "spec-"+*dp.Specialist_Code+"-"+dp.Code) } } @@ -141,9 +146,7 @@ func getSubspecialistPosition(employeeId uint, event *pl.Event) ([]string, error if len(data) > 0 { for _, dp := range data { - if dp.Subspecialist != nil { - result = append(result, "subspec-"+dp.Subspecialist.Code+"-"+dp.Code) - } + result = append(result, "subspec-"+dp.Subspecialist.Code+"-"+dp.Code) } } @@ -173,7 +176,28 @@ func checkUntPtrClaims(claim map[string]interface{}, key string) *uint { return nil } -func populateRoles(user *eu.User, atClaims jwt.MapClaims, outputData d.II, event pl.Event) error { +func populateRoles(user *eu.User, input eu.LoginDto, atClaims jwt.MapClaims, outputData d.II, event pl.Event) error { + id, err := uuid.NewRandom() + if err != nil { + panic(fmt.Sprintf(l.I.Msg("uuid-gen-fail"), err)) + } + if input.Duration == 0 { + input.Duration = 24 * 60 + } + duration := time.Minute * time.Duration(input.Duration) + aUuid := id.String() + atExpires := time.Now().Add(duration).Unix() + + atClaims["uuid"] = aUuid + atClaims["exp"] = atExpires + atClaims["user_id"] = user.Id + atClaims["user_name"] = user.Name + atClaims["user_contractPosition_code"] = user.ContractPosition_Code + + outputData["user_id"] = user.Id + outputData["user_name"] = user.Name + outputData["user_contractPosition_code"] = user.ContractPosition_Code + roles := []string{} switch user.ContractPosition_Code { case erg.CSCEmp: @@ -187,11 +211,6 @@ func populateRoles(user *eu.User, atClaims jwt.MapClaims, outputData d.II, event outputData["employee_id"] = employee.Id roles = append(roles, "emp-"+string(*employee.Position_Code)) - //if employee.Division_Code != nil { - // atClaims["employee_division_code"] = employee.Division_Code - // outputData["employee_division_code"] = employee.Division_Code - //} - // employee position if employee.Id > 0 && employee.Position_Code != nil { atClaims["employee_position_code"] = *employee.Position_Code @@ -279,8 +298,26 @@ func populateRoles(user *eu.User, atClaims jwt.MapClaims, outputData d.II, event case erg.CSCSys: roles = append(roles, "system") } - atClaims["roles"] = roles outputData["roles"] = roles + + // Generate jwt + atSecretKey := authCfg.AtSecretKey + at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims) + ats, err := at.SignedString([]byte(atSecretKey)) + if err != nil { + return d.FieldErrors{"user": d.FieldError{Code: "token-sign-err", Message: pl.GenMessage("token-sign-err")}} + } + outputData["accessToken"] = ats + + // Save to redis + exp, _ := atClaims["exp"].(int64) + now := time.Now() + atx := time.Unix(exp, 0) //converting Unix to UTC(to Time object) + err = ms.I.Set(atClaims["uuid"].(string), strconv.Itoa(int(user.Id)), atx.Sub(now)).Err() + if err != nil { + panic(fmt.Sprintf(l.I.Msg("redis-store-fail"), err.Error())) + } + return nil } diff --git a/internal/use-case/main-use-case/user-fes/case.go b/internal/use-case/main-use-case/user-fes/case.go new file mode 100644 index 00000000..51225927 --- /dev/null +++ b/internal/use-case/main-use-case/user-fes/case.go @@ -0,0 +1,276 @@ +package userfes + +import ( + "strconv" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + "gorm.io/gorm" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + e "simrs-vx/internal/domain/main-entities/user-fes" +) + +const source = "ext-user" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.UserFes{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.UserFes + var dataList []e.UserFes + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.UserFes + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.UserFes + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.UserFes + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/user-fes/helper.go b/internal/use-case/main-use-case/user-fes/helper.go new file mode 100644 index 00000000..b83d303f --- /dev/null +++ b/internal/use-case/main-use-case/user-fes/helper.go @@ -0,0 +1,18 @@ +package userfes + +import ( + e "simrs-vx/internal/domain/main-entities/user-fes" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.UserFes) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + data.Name = inputSrc.Name + data.AuthPartner_Code = inputSrc.AuthPartner_Code + data.User_Name = inputSrc.User_Name +} diff --git a/internal/use-case/main-use-case/user-fes/lib.go b/internal/use-case/main-use-case/user-fes/lib.go new file mode 100644 index 00000000..ce7c8280 --- /dev/null +++ b/internal/use-case/main-use-case/user-fes/lib.go @@ -0,0 +1,143 @@ +package userfes + +import ( + "gorm.io/gorm" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + eu "simrs-vx/internal/domain/main-entities/user-fes" +) + +func CreateData(input eu.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*eu.UserFes, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := eu.UserFes{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input eu.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]eu.UserFes, *eu.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []eu.UserFes{} + pagination := gh.Pagination{} + count := int64(0) + meta := eu.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&eu.UserFes{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input eu.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*eu.UserFes, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := eu.UserFes{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input eu.UpdateDto, data *eu.UserFes, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *eu.UserFes, 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 +} diff --git a/internal/use-case/main-use-case/user-fes/middleware-runner.go b/internal/use-case/main-use-case/user-fes/middleware-runner.go new file mode 100644 index 00000000..f669d4cd --- /dev/null +++ b/internal/use-case/main-use-case/user-fes/middleware-runner.go @@ -0,0 +1,103 @@ +package userfes + +import ( + e "simrs-vx/internal/domain/main-entities/user-fes" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.UserFes) 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.UserFes) 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.UserFes) 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.UserFes) 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.UserFes) 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/main-use-case/user-fes/middleware.go b/internal/use-case/main-use-case/user-fes/middleware.go new file mode 100644 index 00000000..71dac997 --- /dev/null +++ b/internal/use-case/main-use-case/user-fes/middleware.go @@ -0,0 +1,5 @@ +package userfes + +func init() { + +} diff --git a/internal/use-case/main-use-case/user-fes/tycovar.go b/internal/use-case/main-use-case/user-fes/tycovar.go new file mode 100644 index 00000000..008f5cfa --- /dev/null +++ b/internal/use-case/main-use-case/user-fes/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 userfes + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/user-fes" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.UserFes, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.UserFes, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.UserFes, 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 From 02b0aa66ec1dae001936b18f627686c124abcfb5 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Mon, 10 Nov 2025 22:54:08 +0700 Subject: [PATCH 143/329] feat/sso-auth: added the handler --- .../main-handler/auth-partner/handler.go | 71 +++++++++++++++++++ .../main-handler/authentication/handler.go | 46 ++++++------ .../interface/main-handler/main-handler.go | 6 ++ .../main-handler/user-fes/handler.go | 71 +++++++++++++++++++ 4 files changed, 172 insertions(+), 22 deletions(-) create mode 100644 internal/interface/main-handler/auth-partner/handler.go create mode 100644 internal/interface/main-handler/user-fes/handler.go diff --git a/internal/interface/main-handler/auth-partner/handler.go b/internal/interface/main-handler/auth-partner/handler.go new file mode 100644 index 00000000..f31e538d --- /dev/null +++ b/internal/interface/main-handler/auth-partner/handler.go @@ -0,0 +1,71 @@ +package authpartner + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/auth-partner" + u "simrs-vx/internal/use-case/main-use-case/auth-partner" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := uint16(rw.ValidateInt(w, "id", r.PathValue("id"))) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = &id + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := uint16(rw.ValidateInt(w, "id", r.PathValue("id"))) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = id + res, err := u.Update(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { + id := uint16(rw.ValidateInt(w, "id", r.PathValue("id"))) + if id <= 0 { + return + } + + dto := e.DeleteDto{} + dto.Id = id + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/authentication/handler.go b/internal/interface/main-handler/authentication/handler.go index fc36dc52..243ba9cd 100644 --- a/internal/interface/main-handler/authentication/handler.go +++ b/internal/interface/main-handler/authentication/handler.go @@ -30,6 +30,30 @@ func Login(w http.ResponseWriter, r *http.Request) { } } +func LoginFes(w http.ResponseWriter, r *http.Request) { + var input mf.LoginDto + err := sp.IOReaderJson(&input, r.Body) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil) + return + } + + input.AuthPartner_Code = r.Header.Get("X-AuthPartner-Code") + input.AuthPartner_SecretKey = r.Header.Get("X-AuthPartner-SecretKey") + if err = sr.Validate(input); err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil) + return + } + + // input.Position = Position + res, err := s.GenTokenFes(input) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil) + } else { + rw.DataResponse(w, res, err) + } +} + func Logout(w http.ResponseWriter, r *http.Request) { ctxVal := r.Context().Value(pa.AuthKey{}) if ctxVal == nil { @@ -52,25 +76,3 @@ func GuardMW(next http.Handler) http.Handler { next.ServeHTTP(w, r.WithContext(ctx)) }) } - -func LoginFes(w http.ResponseWriter, r *http.Request) { - var input mf.LoginDto - err := sp.IOReaderJson(input, r.Body) - if err != nil { - rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil) - } - - input.AuthPartner_Code = r.Header.Get("X-AuthPartner-Code") - input.AuthPartner_SecretKey = r.Header.Get("X-AuthPartner-SecretKey") - if err = (sr.Validate(input)); err != nil { - rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil) - } - - // input.Position = Position - res, err := s.GenTokenFes(input) - if err != nil { - rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil) - } else { - rw.DataResponse(w, res, err) - } -} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 6d0548e9..117dfdb1 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -36,6 +36,7 @@ import ( /******************** actor ********************/ + authpartner "simrs-vx/internal/interface/main-handler/auth-partner" doctor "simrs-vx/internal/interface/main-handler/doctor" employee "simrs-vx/internal/interface/main-handler/employee" nurse "simrs-vx/internal/interface/main-handler/nurse" @@ -47,6 +48,7 @@ import ( personinsurance "simrs-vx/internal/interface/main-handler/person-insurance" pharmacist "simrs-vx/internal/interface/main-handler/pharmacist" user "simrs-vx/internal/interface/main-handler/user" + userfes "simrs-vx/internal/interface/main-handler/user-fes" /******************** external ********************/ a "github.com/karincake/apem" @@ -132,7 +134,9 @@ func SetRoutes() http.Handler { r.HandleFunc("/", home.Home) r.HandleFunc("POST /v1/authentication/login", auth.Login) + r.HandleFunc("POST /v1/authentication/login-fes", auth.LoginFes) hk.Route("POST /v1/authentication/logout", r, auth.GuardMW, auth.Logout) + hc.RegCrud(r, "/v1/auth-partner", authpartner.O) hc.RegCrud(r, "/v1/practice-schedule", practiceschedule.O) hc.RegCrud(r, "/v1/counter", counter.O) hc.RegCrud(r, "/v1/medicine-mix", medicicinemix.O) @@ -282,6 +286,8 @@ func SetRoutes() http.Handler { "PATCH /{id}/block": user.O.Block, "PATCH /{id}/active": user.O.Active, }) + hc.RegCrud(r, "/v1/user-fes", userfes.O) + hk.GroupRoutes("/v1/patient", r, hk.MapHandlerFunc{ "GET /": patient.O.GetList, "GET /{id}": patient.O.GetDetail, diff --git a/internal/interface/main-handler/user-fes/handler.go b/internal/interface/main-handler/user-fes/handler.go new file mode 100644 index 00000000..0c37ff08 --- /dev/null +++ b/internal/interface/main-handler/user-fes/handler.go @@ -0,0 +1,71 @@ +package userfes + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/user-fes" + u "simrs-vx/internal/use-case/main-use-case/user-fes" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := uint16(rw.ValidateInt(w, "id", r.PathValue("id"))) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint(id) + 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) +} From 27a23594a9a6cdc39b4ca989d30b0f56192e62d7 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Mon, 10 Nov 2025 23:00:31 +0700 Subject: [PATCH 144/329] feat/sso-auth: entities adjustment --- .../migrations/20251110155448.sql | 6 ++ cmd/main-migration/migrations/atlas.sum | 69 ++++++++++--------- .../domain/main-entities/auth-partner/dto.go | 4 +- .../main-entities/auth-partner/entity.go | 8 +-- internal/domain/main-entities/user-fes/dto.go | 11 ++- .../domain/main-entities/user-fes/entity.go | 11 +-- 6 files changed, 63 insertions(+), 46 deletions(-) create mode 100644 cmd/main-migration/migrations/20251110155448.sql diff --git a/cmd/main-migration/migrations/20251110155448.sql b/cmd/main-migration/migrations/20251110155448.sql new file mode 100644 index 00000000..203a27cb --- /dev/null +++ b/cmd/main-migration/migrations/20251110155448.sql @@ -0,0 +1,6 @@ +-- Modify "AuthPartner" table +ALTER TABLE "public"."AuthPartner" ALTER COLUMN "Id" TYPE integer; +-- Modify "UserFes" table +ALTER TABLE "public"."UserFes" ALTER COLUMN "AuthPartner_Code" TYPE character varying(50); +-- Create index "idx-userFes-name-authPartner_code" to table: "UserFes" +CREATE UNIQUE INDEX "idx-userFes-name-authPartner_code" ON "public"."UserFes" ("Name", "AuthPartner_Code"); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 293ca91a..2796b467 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:EhWXa9CRUdCX5FiHAOEgknGsAmS+hlumbeo45IiWbbs= +h1:TdKv/b2M3b7aDyV/8QudGz8wQGS3/qQOWTVom2eV120= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,36 +75,37 @@ h1:EhWXa9CRUdCX5FiHAOEgknGsAmS+hlumbeo45IiWbbs= 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= +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:nqz15bRA1LXvALj9cytCo2E4amyLAOq0qZl+jsqhVkk= diff --git a/internal/domain/main-entities/auth-partner/dto.go b/internal/domain/main-entities/auth-partner/dto.go index 2b1589fb..4a723251 100644 --- a/internal/domain/main-entities/auth-partner/dto.go +++ b/internal/domain/main-entities/auth-partner/dto.go @@ -45,7 +45,7 @@ type MetaDto struct { } type ResponseDto struct { - ecore.Main + ecore.SmallMain Code string `json:"code"` Name string `json:"name"` SecretKey string `json:"secretKey"` @@ -57,7 +57,7 @@ func (d AuthPartner) ToResponse() ResponseDto { Name: d.Name, SecretKey: d.SecretKey, } - resp.Main = d.Main + resp.SmallMain = d.SmallMain return resp } diff --git a/internal/domain/main-entities/auth-partner/entity.go b/internal/domain/main-entities/auth-partner/entity.go index b4ad8e49..3a810f51 100644 --- a/internal/domain/main-entities/auth-partner/entity.go +++ b/internal/domain/main-entities/auth-partner/entity.go @@ -5,8 +5,8 @@ import ( ) type AuthPartner struct { - ecore.Main // adjust this according to the needs - Code string `json:"code" gorm:"unique;size:50"` - Name string `json:"name" gorm:"unique;size:100"` - SecretKey string `json:"secretKey" gorm:"size:255"` + ecore.SmallMain // adjust this according to the needs + Code string `json:"code" gorm:"unique;size:50"` + Name string `json:"name" gorm:"unique;size:100"` + SecretKey string `json:"secretKey" gorm:"size:255"` } diff --git a/internal/domain/main-entities/user-fes/dto.go b/internal/domain/main-entities/user-fes/dto.go index 6cb3636b..3cf9d68e 100644 --- a/internal/domain/main-entities/user-fes/dto.go +++ b/internal/domain/main-entities/user-fes/dto.go @@ -41,6 +41,13 @@ type DeleteDto struct { Id uint `json:"id"` } +type LoginDto struct { + Name string `json:"name" validate:"required"` + Duration uint32 `json:"duration"` + AuthPartner_Code string `json:"X-AuthPartner-Code" validate:"required"` + AuthPartner_SecretKey string `json:"X-AuthPartner-SecretKey" validate:"required"` +} + type MetaDto struct { PageNumber int `json:"page_number"` PageSize int `json:"page_size"` @@ -59,8 +66,8 @@ func (d UserFes) ToResponse() ResponseDto { resp := ResponseDto{ Name: d.Name, AuthPartner_Code: d.AuthPartner_Code, - AuthPartner: d.AuthPartner, - User_Name: d.User_Name, + // AuthPartner: d.AuthPartner, + User_Name: d.User_Name, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/user-fes/entity.go b/internal/domain/main-entities/user-fes/entity.go index 7356166c..5261ed62 100644 --- a/internal/domain/main-entities/user-fes/entity.go +++ b/internal/domain/main-entities/user-fes/entity.go @@ -9,9 +9,12 @@ import ( type UserFes struct { ecore.Main // adjust this according to the needs - Name string `json:"name" gorm:"size:100"` - AuthPartner_Code string `json:"authPartner_code" gorm:"size:30"` + Name string `json:"name" gorm:"size:100;uniqueIndex:idx-userFes-name-authPartner_code"` + AuthPartner_Code string `json:"authPartner_code" gorm:"size:50;uniqueIndex:idx-userFes-name-authPartner_code"` AuthPartner *eap.AuthPartner `json:"authPartner,omitempty" gorm:"foreignKey:AuthPartner_Code;references:Code"` - User_Name string `json:"user_name" gorm:"size:50"` - User *eau.User `json:"user,omitempty" gorm:"foreignKey:User_Name;references:Name"` + // Even tried this one, still failed to preload + // AuthPartner_Id uint16 `json:"authPartner_id"` + // AuthPartner *eap.AuthPartner `json:"authPartner,omitempty" gorm:"foreignKey:AuthPartner_Id;references:Id"` + User_Name string `json:"user_name" gorm:"size:50"` + User *eau.User `json:"user,omitempty" gorm:"foreignKey:User_Name;references:Name"` } From ed0a22eb731466c05182881ef495ce01f2c84c22 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 11 Nov 2025 11:24:07 +0700 Subject: [PATCH 145/329] adjust org after refactor --- .../domain/main-entities/installation/dto.go | 13 +++++++------ .../main-handler/installation/handler.go | 18 +++++++++--------- .../main-use-case/installation/case.go | 4 ++-- .../main-use-case/installation/helper.go | 2 +- .../use-case/main-use-case/installation/lib.go | 9 ++++++++- .../main-use-case/specialist-position/case.go | 4 ++-- .../main-use-case/specialist-position/lib.go | 2 +- .../main-use-case/unit-position/lib.go | 2 +- 8 files changed, 31 insertions(+), 23 deletions(-) diff --git a/internal/domain/main-entities/installation/dto.go b/internal/domain/main-entities/installation/dto.go index 302025d8..758efb05 100644 --- a/internal/domain/main-entities/installation/dto.go +++ b/internal/domain/main-entities/installation/dto.go @@ -8,7 +8,7 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=10"` + Code *string `json:"code" validate:"maxLength=10"` Name string `json:"name" validate:"maxLength=50"` EncounterClass_Code ere.EncounterClassCode `json:"encounterClass_code" validate:"maxLength=10"` } @@ -21,25 +21,26 @@ type ReadListDto struct { } type FilterDto struct { - Code string `json:"code"` - Name string `json:"name"` + Code *string `json:"code"` + Name *string `json:"name"` EncounterClass_Code ere.EncounterClassCode `json:"encounterClass-code"` Search string `json:"search" gormhelper:"searchColumns=Code,Name"` } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` Includes string `json:"includes"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/interface/main-handler/installation/handler.go b/internal/interface/main-handler/installation/handler.go index 26885689..0b3f52ef 100644 --- a/internal/interface/main-handler/installation/handler.go +++ b/internal/interface/main-handler/installation/handler.go @@ -33,21 +33,21 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} sf.UrlQueryParam(&dto, *r.URL) - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -55,19 +55,19 @@ 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.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/use-case/main-use-case/installation/case.go b/internal/use-case/main-use-case/installation/case.go index 5e1339da..f66bedaf 100644 --- a/internal/use-case/main-use-case/installation/case.go +++ b/internal/use-case/main-use-case/installation/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Installation var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Installation var err error diff --git a/internal/use-case/main-use-case/installation/helper.go b/internal/use-case/main-use-case/installation/helper.go index 3ad22892..d3d96b5c 100644 --- a/internal/use-case/main-use-case/installation/helper.go +++ b/internal/use-case/main-use-case/installation/helper.go @@ -17,7 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Installation) { inputSrc = &inputTemp.CreateDto } - data.Code = inputSrc.Code + data.Code = *inputSrc.Code data.Name = inputSrc.Name data.EncounterClass_Code = inputSrc.EncounterClass_Code } diff --git a/internal/use-case/main-use-case/installation/lib.go b/internal/use-case/main-use-case/installation/lib.go index 82130c32..d75b2ecd 100644 --- a/internal/use-case/main-use-case/installation/lib.go +++ b/internal/use-case/main-use-case/installation/lib.go @@ -81,9 +81,16 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e tx = dg.I } + if input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", *input.Id) + } + if err := tx. Scopes(gh.Preload(input.Includes)). - First(&data, input.Id).Error; err != nil { + First(&data).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/specialist-position/case.go b/internal/use-case/main-use-case/specialist-position/case.go index 2addf80d..f4031b2f 100644 --- a/internal/use-case/main-use-case/specialist-position/case.go +++ b/internal/use-case/main-use-case/specialist-position/case.go @@ -175,7 +175,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: &input.Code} var data *e.SpecialistPosition var err error @@ -235,7 +235,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.SpecialistPosition var err error diff --git a/internal/use-case/main-use-case/specialist-position/lib.go b/internal/use-case/main-use-case/specialist-position/lib.go index 13c84f28..fea6bb9d 100644 --- a/internal/use-case/main-use-case/specialist-position/lib.go +++ b/internal/use-case/main-use-case/specialist-position/lib.go @@ -86,7 +86,7 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e case input.Id != nil: getData = tx.First(&data, input.Id) case input.Code != nil && *input.Code != "": - getData = tx.Where("code = ?", *input.Code).First(&data) + getData = tx.Where("\"Code\" = ?", *input.Code).First(&data) default: event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ diff --git a/internal/use-case/main-use-case/unit-position/lib.go b/internal/use-case/main-use-case/unit-position/lib.go index d6f42936..104357e5 100644 --- a/internal/use-case/main-use-case/unit-position/lib.go +++ b/internal/use-case/main-use-case/unit-position/lib.go @@ -86,7 +86,7 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e case input.Id != nil: getData = tx.First(&data, input.Id) case input.Code != nil && *input.Code != "": - getData = tx.Where("code = ?", *input.Code).First(&data) + getData = tx.Where("\"Code\" = ?", *input.Code).First(&data) default: event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ From 6db21ad11405aaa1094564bfbb04ca69e7621e3d Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 11 Nov 2025 11:39:44 +0700 Subject: [PATCH 146/329] fix (subspecialist): change source, wrong query --- internal/use-case/main-use-case/subspecialist/case.go | 2 +- internal/use-case/main-use-case/subspecialist/lib.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/use-case/main-use-case/subspecialist/case.go b/internal/use-case/main-use-case/subspecialist/case.go index 42366adf..51509c47 100644 --- a/internal/use-case/main-use-case/subspecialist/case.go +++ b/internal/use-case/main-use-case/subspecialist/case.go @@ -13,7 +13,7 @@ import ( "gorm.io/gorm" ) -const source = "specialist" +const source = "subspecialist" func Create(input e.CreateDto) (*d.Data, error) { data := e.Subspecialist{} diff --git a/internal/use-case/main-use-case/subspecialist/lib.go b/internal/use-case/main-use-case/subspecialist/lib.go index a6c4dbc5..c5a742df 100644 --- a/internal/use-case/main-use-case/subspecialist/lib.go +++ b/internal/use-case/main-use-case/subspecialist/lib.go @@ -90,7 +90,7 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e if err := tx. Scopes(gh.Preload(input.Includes)). - First(&data, input.Id).Error; err != nil { + First(&data).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { return nil, processedErr } From c6f5bbe8a2ac4cf944945117a3911bf6295750c2 Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 11 Nov 2025 14:21:17 +0700 Subject: [PATCH 147/329] update encounter cancel flow --- .../use-case/main-use-case/encounter/case.go | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index d387fcc2..9381e639 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -3,6 +3,7 @@ package encounter import ( "errors" "fmt" + us "simrs-vx/internal/use-case/main-use-case/soapi" "strconv" "time" @@ -489,6 +490,32 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) { return pl.SetLogError(&event, input) } + if input.StatusCode == erc.DSCCancel { + // TODO: Prevent cancellation if the billing has been verified + + // TODO: Only "supervisi pendaftaran" could cancel encounter + + // Prevent cancellation if soapi exist + encounterId := uint(input.Id) + dataSoapi, _, err := us.ReadListData(es.ReadListDto{ + FilterDto: es.FilterDto{ + Encounter_Id: &encounterId, + }}, &event, tx) + if err != nil { + return err + } + + if len(dataSoapi) > 0 { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "cancel-not-allowed", + Detail: "encounter can't be cancelled because SOAPI already exists", + Raw: errors.New("encounter has SOAPI records"), + } + return pl.SetLogError(&event, input) + } + } + mwRunner := newMiddlewareRunner(&event, tx) mwRunner.setMwType(pu.MWTPre) // Run pre-middleware From ac8b44366ba9a6435f3c870e471f7198382879c8 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 11 Nov 2025 14:30:14 +0700 Subject: [PATCH 148/329] add mcusrc_code in mcu and mcu sub item --- .../migrations/20251111072601.sql | 12 ++++ cmd/main-migration/migrations/atlas.sum | 69 ++++++++++--------- .../main-entities/mcu-order-item/entity.go | 1 + .../mcu-order-sub-item/entity.go | 1 + 4 files changed, 49 insertions(+), 34 deletions(-) create mode 100644 cmd/main-migration/migrations/20251111072601.sql diff --git a/cmd/main-migration/migrations/20251111072601.sql b/cmd/main-migration/migrations/20251111072601.sql new file mode 100644 index 00000000..06c6ef8b --- /dev/null +++ b/cmd/main-migration/migrations/20251111072601.sql @@ -0,0 +1,12 @@ +-- Drop index "idx_order_src" from table: "McuOrderItem" +DROP INDEX "public"."idx_order_src"; +-- Modify "McuOrderItem" table +ALTER TABLE "public"."McuOrderItem" ADD COLUMN "McuSrc_Code" text NULL; +-- Create index "idx_order_src" to table: "McuOrderItem" +CREATE UNIQUE INDEX "idx_order_src" ON "public"."McuOrderItem" ("McuOrder_Id", "McuSrc_Id", "McuSrc_Code"); +-- Drop index "idx_order_sub_src" from table: "McuOrderSubItem" +DROP INDEX "public"."idx_order_sub_src"; +-- Modify "McuOrderSubItem" table +ALTER TABLE "public"."McuOrderSubItem" ADD COLUMN "McuSubSrc_Code" text NULL; +-- Create index "idx_order_sub_src" to table: "McuOrderSubItem" +CREATE UNIQUE INDEX "idx_order_sub_src" ON "public"."McuOrderSubItem" ("McuSubSrc_Id", "McuSubSrc_Code", "McuOrderItem_Id"); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 293ca91a..ae7f3aae 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:EhWXa9CRUdCX5FiHAOEgknGsAmS+hlumbeo45IiWbbs= +h1:C7P95EefOgFoOpF4sqjEV1Ib2U1MXjtMOesKdEAqN6U= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,36 +75,37 @@ h1:EhWXa9CRUdCX5FiHAOEgknGsAmS+hlumbeo45IiWbbs= 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= +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= +20251111072601.sql h1:lZlTXC8kHh4S+R5TKx23VQDU/Nj2YF+QrDk9Ta2rNM0= diff --git a/internal/domain/main-entities/mcu-order-item/entity.go b/internal/domain/main-entities/mcu-order-item/entity.go index 6a4441d0..56687046 100644 --- a/internal/domain/main-entities/mcu-order-item/entity.go +++ b/internal/domain/main-entities/mcu-order-item/entity.go @@ -14,6 +14,7 @@ type McuOrderItem struct { McuOrder_Id *uint `json:"mcuOrder_id" gorm:"uniqueIndex:idx_order_src"` McuOrder *emo.McuOrder `json:"mcuOrder,omitempty" gorm:"foreignKey:McuOrder_Id;references:Id"` McuSrc_Id *uint `json:"mcuSrc_id" gorm:"uniqueIndex:idx_order_src"` + McuSrc_Code *string `json:"mcuSrc_code" gorm:"uniqueIndex:idx_order_src"` McuSrc *ems.McuSrc `json:"mcuSrc,omitempty" gorm:"foreignKey:McuSrc_Id;references:Id"` ExaminationDate *time.Time `json:"examinationDate"` Result *string `json:"result"` diff --git a/internal/domain/main-entities/mcu-order-sub-item/entity.go b/internal/domain/main-entities/mcu-order-sub-item/entity.go index 83ae4d53..5ae9463c 100644 --- a/internal/domain/main-entities/mcu-order-sub-item/entity.go +++ b/internal/domain/main-entities/mcu-order-sub-item/entity.go @@ -11,6 +11,7 @@ import ( type McuOrderSubItem struct { ecore.Main // adjust this according to the needs McuSubSrc_Id *uint `json:"mcuSubSrc_id" gorm:"uniqueIndex:idx_order_sub_src"` + McuSubSrc_Code *string `json:"mcuSubSrc_code" gorm:"uniqueIndex:idx_order_sub_src"` McuSubSrc *emss.McuSubSrc `json:"mcuSubSrc,omitempty" gorm:"foreignKey:McuSubSrc_Id;references:Id"` McuOrderItem_Id *uint `json:"mcuOrderItem_id" gorm:"uniqueIndex:idx_order_sub_src"` McuOrderItem *emoi.McuOrderItem `json:"mcuOrderItem,omitempty" gorm:"foreignKey:McuOrderItem_Id;references:Id"` From 7357e0de4d9ce43cf0cbae9b10c828b1fd7e843b Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 11 Nov 2025 14:32:08 +0700 Subject: [PATCH 149/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 70 ++++++++++++------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index ae7f3aae..e43196ac 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:C7P95EefOgFoOpF4sqjEV1Ib2U1MXjtMOesKdEAqN6U= +h1:vasJP/oxpmBaTqzDjsVao7o+/VZL6cw5bigh2fFk1+Q= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,37 +75,37 @@ h1:C7P95EefOgFoOpF4sqjEV1Ib2U1MXjtMOesKdEAqN6U= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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= -20251111072601.sql h1:lZlTXC8kHh4S+R5TKx23VQDU/Nj2YF+QrDk9Ta2rNM0= +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= +20251111072601.sql h1:6p2qynJ2vr3C18peYciAbOIWOoj/+PnNcobU3wNHboQ= From bdc441b8f9f60dc5b177a3cc701d36b3b186ba40 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 11 Nov 2025 14:39:09 +0700 Subject: [PATCH 150/329] changed mcu_id into code in mcu and mcu sub order item --- .../migrations/20251111073546.sql | 12 ++++ cmd/main-migration/migrations/atlas.sum | 71 ++++++++++--------- .../main-entities/mcu-order-item/dto.go | 8 +-- .../main-entities/mcu-order-item/entity.go | 3 +- .../main-entities/mcu-order-sub-item/dto.go | 8 +-- .../mcu-order-sub-item/entity.go | 3 +- .../main-use-case/mcu-order-item/helper.go | 2 +- .../main-use-case/mcu-order-item/lib.go | 2 +- .../mcu-order-sub-item/helper.go | 2 +- 9 files changed, 61 insertions(+), 50 deletions(-) create mode 100644 cmd/main-migration/migrations/20251111073546.sql diff --git a/cmd/main-migration/migrations/20251111073546.sql b/cmd/main-migration/migrations/20251111073546.sql new file mode 100644 index 00000000..dd99dc74 --- /dev/null +++ b/cmd/main-migration/migrations/20251111073546.sql @@ -0,0 +1,12 @@ +-- Drop index "idx_order_src" from table: "McuOrderItem" +DROP INDEX "public"."idx_order_src"; +-- Modify "McuOrderItem" table +ALTER TABLE "public"."McuOrderItem" DROP CONSTRAINT "fk_McuOrderItem_McuSrc", DROP COLUMN "McuSrc_Id", ALTER COLUMN "McuSrc_Code" TYPE character varying(20), ADD CONSTRAINT "fk_McuOrderItem_McuSrc" FOREIGN KEY ("McuSrc_Code") REFERENCES "public"."McuSrc" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Create index "idx_order_src" to table: "McuOrderItem" +CREATE UNIQUE INDEX "idx_order_src" ON "public"."McuOrderItem" ("McuOrder_Id", "McuSrc_Code"); +-- Drop index "idx_order_sub_src" from table: "McuOrderSubItem" +DROP INDEX "public"."idx_order_sub_src"; +-- Modify "McuOrderSubItem" table +ALTER TABLE "public"."McuOrderSubItem" DROP CONSTRAINT "fk_McuOrderSubItem_McuSubSrc", DROP COLUMN "McuSubSrc_Id", ALTER COLUMN "McuSubSrc_Code" TYPE character varying(20), ADD CONSTRAINT "fk_McuOrderSubItem_McuSubSrc" FOREIGN KEY ("McuSubSrc_Code") REFERENCES "public"."McuSubSrc" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Create index "idx_order_sub_src" to table: "McuOrderSubItem" +CREATE UNIQUE INDEX "idx_order_sub_src" ON "public"."McuOrderSubItem" ("McuSubSrc_Code", "McuOrderItem_Id"); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index e43196ac..1e4fb9ef 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:vasJP/oxpmBaTqzDjsVao7o+/VZL6cw5bigh2fFk1+Q= +h1:tc4xv8+poy7S/OAXRUIpl126iMf2PuZD9AcgnioQXYo= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,37 +75,38 @@ h1:vasJP/oxpmBaTqzDjsVao7o+/VZL6cw5bigh2fFk1+Q= 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= -20251111072601.sql h1:6p2qynJ2vr3C18peYciAbOIWOoj/+PnNcobU3wNHboQ= +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= +20251111072601.sql h1:lZlTXC8kHh4S+R5TKx23VQDU/Nj2YF+QrDk9Ta2rNM0= +20251111073546.sql h1:nTM5C+HLpBRPkFAsoSJU1RrnzZqoqnrHGvutInHSnCM= diff --git a/internal/domain/main-entities/mcu-order-item/dto.go b/internal/domain/main-entities/mcu-order-item/dto.go index 75e02184..6880c9b7 100644 --- a/internal/domain/main-entities/mcu-order-item/dto.go +++ b/internal/domain/main-entities/mcu-order-item/dto.go @@ -10,7 +10,7 @@ import ( type CreateDto struct { McuOrder_Id *uint `json:"mcuOrder_id"` - McuSrc_Id *uint `json:"mcuSrc_id"` + McuSrc_Code *string `json:"mcuSrc_code"` Result *string `json:"result"` Status_Code erc.DataStatusCode `json:"status_code"` ExaminationDate *time.Time `json:"examinationDate"` @@ -24,7 +24,7 @@ type ReadListDto struct { type FilterDto struct { McuOrder_Id *uint `json:"mcu-order-id"` - McuSrc_Id *uint `json:"mcu-src-id"` + McuSrc_Code *string `json:"mcu-src-code"` Result *string `json:"result"` Status_Code erc.DataStatusCode `json:"status-code"` } @@ -56,7 +56,7 @@ type ResponseDto struct { ecore.Main McuOrder_Id *uint `json:"mcuOrder_id"` McuOrder *emo.McuOrder `json:"mcuOrder,omitempty"` - McuSrc_Id *uint `json:"mcuSrc_id"` + McuSrc_Code *string `json:"mcuSrc_code"` McuSrc *ems.McuSrc `json:"mcuSrc,omitempty"` Result *string `json:"result"` Status_Code erc.DataStatusCode `json:"status_code"` @@ -67,7 +67,7 @@ func (d McuOrderItem) ToResponse() ResponseDto { resp := ResponseDto{ McuOrder_Id: d.McuOrder_Id, McuOrder: d.McuOrder, - McuSrc_Id: d.McuSrc_Id, + McuSrc_Code: d.McuSrc_Code, McuSrc: d.McuSrc, Result: d.Result, Status_Code: d.Status_Code, diff --git a/internal/domain/main-entities/mcu-order-item/entity.go b/internal/domain/main-entities/mcu-order-item/entity.go index 56687046..97384243 100644 --- a/internal/domain/main-entities/mcu-order-item/entity.go +++ b/internal/domain/main-entities/mcu-order-item/entity.go @@ -13,9 +13,8 @@ type McuOrderItem struct { ecore.Main // adjust this according to the needs McuOrder_Id *uint `json:"mcuOrder_id" gorm:"uniqueIndex:idx_order_src"` McuOrder *emo.McuOrder `json:"mcuOrder,omitempty" gorm:"foreignKey:McuOrder_Id;references:Id"` - McuSrc_Id *uint `json:"mcuSrc_id" gorm:"uniqueIndex:idx_order_src"` McuSrc_Code *string `json:"mcuSrc_code" gorm:"uniqueIndex:idx_order_src"` - McuSrc *ems.McuSrc `json:"mcuSrc,omitempty" gorm:"foreignKey:McuSrc_Id;references:Id"` + McuSrc *ems.McuSrc `json:"mcuSrc,omitempty" gorm:"foreignKey:McuSrc_Code;references:Code"` ExaminationDate *time.Time `json:"examinationDate"` Result *string `json:"result"` Status_Code erc.DataStatusCode `json:"status_code"` diff --git a/internal/domain/main-entities/mcu-order-sub-item/dto.go b/internal/domain/main-entities/mcu-order-sub-item/dto.go index 615b0ee9..a85d14e7 100644 --- a/internal/domain/main-entities/mcu-order-sub-item/dto.go +++ b/internal/domain/main-entities/mcu-order-sub-item/dto.go @@ -8,7 +8,7 @@ import ( ) type CreateDto struct { - McuSubSrc_Id *uint `json:"mcuSubSrc_id"` + McuSubSrc_Code *string `json:"mcuSubSrc_code"` McuOrderItem_Id *uint `json:"mcuOrderItem_id"` Result *string `json:"result"` Status_Code erc.DataStatusCode `json:"status_code"` @@ -22,7 +22,7 @@ type ReadListDto struct { type FilterDto struct { McuOrder_Id *uint `json:"mcuOrder-id"` - McuSrc_Id *uint `json:"mcuSrc-id"` + McuSrc_Code *string `json:"mcuSrc-code"` Result *string `json:"result"` Status_Code erc.DataStatusCode `json:"status-code"` } @@ -47,7 +47,7 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - McuSubSrc_Id *uint `json:"mcuSubSrc_id"` + McuSubSrc_Code *string `json:"mcuSubSrc_code"` McuSubSrc *emss.McuSubSrc `json:"mcuSubSrc,omitempty"` McuOrderItem_Id *uint `json:"mcuOrderItem_id"` McuOrderItem *emoi.McuOrderItem `json:"mcuOrderItem,omitempty"` @@ -57,7 +57,7 @@ type ResponseDto struct { func (d McuOrderSubItem) ToResponse() ResponseDto { resp := ResponseDto{ - McuSubSrc_Id: d.McuSubSrc_Id, + McuSubSrc_Code: d.McuSubSrc_Code, McuSubSrc: d.McuSubSrc, McuOrderItem_Id: d.McuOrderItem_Id, McuOrderItem: d.McuOrderItem, diff --git a/internal/domain/main-entities/mcu-order-sub-item/entity.go b/internal/domain/main-entities/mcu-order-sub-item/entity.go index 5ae9463c..a9bde496 100644 --- a/internal/domain/main-entities/mcu-order-sub-item/entity.go +++ b/internal/domain/main-entities/mcu-order-sub-item/entity.go @@ -10,9 +10,8 @@ import ( type McuOrderSubItem struct { ecore.Main // adjust this according to the needs - McuSubSrc_Id *uint `json:"mcuSubSrc_id" gorm:"uniqueIndex:idx_order_sub_src"` McuSubSrc_Code *string `json:"mcuSubSrc_code" gorm:"uniqueIndex:idx_order_sub_src"` - McuSubSrc *emss.McuSubSrc `json:"mcuSubSrc,omitempty" gorm:"foreignKey:McuSubSrc_Id;references:Id"` + McuSubSrc *emss.McuSubSrc `json:"mcuSubSrc,omitempty" gorm:"foreignKey:McuSubSrc_Code;references:Code"` McuOrderItem_Id *uint `json:"mcuOrderItem_id" gorm:"uniqueIndex:idx_order_sub_src"` McuOrderItem *emoi.McuOrderItem `json:"mcuOrderItem,omitempty" gorm:"foreignKey:McuOrderItem_Id;references:Id"` Result *string `json:"result"` diff --git a/internal/use-case/main-use-case/mcu-order-item/helper.go b/internal/use-case/main-use-case/mcu-order-item/helper.go index a2694ecd..8c6e861e 100644 --- a/internal/use-case/main-use-case/mcu-order-item/helper.go +++ b/internal/use-case/main-use-case/mcu-order-item/helper.go @@ -18,7 +18,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.McuOrderItem) { } data.McuOrder_Id = inputSrc.McuOrder_Id - data.McuSrc_Id = inputSrc.McuSrc_Id + data.McuSrc_Code = inputSrc.McuSrc_Code data.Result = inputSrc.Result data.Status_Code = inputSrc.Status_Code data.ExaminationDate = inputSrc.ExaminationDate diff --git a/internal/use-case/main-use-case/mcu-order-item/lib.go b/internal/use-case/main-use-case/mcu-order-item/lib.go index 4b5bb04f..015befea 100644 --- a/internal/use-case/main-use-case/mcu-order-item/lib.go +++ b/internal/use-case/main-use-case/mcu-order-item/lib.go @@ -24,7 +24,7 @@ func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.McuOrde deletedData := e.McuOrderItem{} tx.Unscoped(). - Where("\"McuOrder_Id\" = ? AND \"McuSrc_Id\" = ?", *input.McuOrder_Id, input.McuSrc_Id). + Where("\"McuOrder_Id\" = ? AND \"McuSrc_Code\" = ?", *input.McuOrder_Id, input.McuSrc_Code). First(&deletedData) if deletedData.Id != 0 { if err := tx.Unscoped().Model(e.McuOrderItem{}).Where("\"Id\" = ?", deletedData.Id).Update("\"DeletedAt\"", nil).Error; err != nil { diff --git a/internal/use-case/main-use-case/mcu-order-sub-item/helper.go b/internal/use-case/main-use-case/mcu-order-sub-item/helper.go index f8d9c30f..d7e6ed20 100644 --- a/internal/use-case/main-use-case/mcu-order-sub-item/helper.go +++ b/internal/use-case/main-use-case/mcu-order-sub-item/helper.go @@ -17,7 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.McuOrderSubItem) { inputSrc = &inputTemp.CreateDto } - data.McuSubSrc_Id = inputSrc.McuSubSrc_Id + data.McuSubSrc_Code = inputSrc.McuSubSrc_Code data.McuOrderItem_Id = inputSrc.McuOrderItem_Id data.Result = inputSrc.Result data.Status_Code = inputSrc.Status_Code From 75bce77a39f93f348a01aa4c66597a0ee7289ece Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 11 Nov 2025 15:02:41 +0700 Subject: [PATCH 151/329] add medicine code on medication related --- cmd/main-migration/migrations/20251111074148.sql | 2 ++ cmd/main-migration/migrations/20251111074652.sql | 10 ++++++++++ cmd/main-migration/migrations/atlas.sum | 4 +++- .../main-entities/medication-item-dist/entity.go | 1 + .../main-entities/medication-item/entity.go | 1 + .../domain/main-entities/medication/entity.go | 15 ++++++++------- .../main-entities/medicine-mix-item/entity.go | 1 + internal/domain/main-entities/medicine/entity.go | 6 ++---- .../main-entities/prescription-item/entity.go | 1 + 9 files changed, 29 insertions(+), 12 deletions(-) create mode 100644 cmd/main-migration/migrations/20251111074148.sql create mode 100644 cmd/main-migration/migrations/20251111074652.sql diff --git a/cmd/main-migration/migrations/20251111074148.sql b/cmd/main-migration/migrations/20251111074148.sql new file mode 100644 index 00000000..e93a1d57 --- /dev/null +++ b/cmd/main-migration/migrations/20251111074148.sql @@ -0,0 +1,2 @@ +-- Modify "Medicine" table +ALTER TABLE "public"."Medicine" DROP CONSTRAINT "fk_Medicine_Infra", DROP CONSTRAINT "fk_Medicine_Item", DROP COLUMN "Infra_Id", DROP COLUMN "Item_Id", ADD CONSTRAINT "fk_Medicine_Infra" FOREIGN KEY ("Infra_Code") REFERENCES "public"."Infra" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_Medicine_Item" FOREIGN KEY ("Item_Code") REFERENCES "public"."Item" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251111074652.sql b/cmd/main-migration/migrations/20251111074652.sql new file mode 100644 index 00000000..7ce19236 --- /dev/null +++ b/cmd/main-migration/migrations/20251111074652.sql @@ -0,0 +1,10 @@ +-- Modify "Medication" table +ALTER TABLE "public"."Medication" ADD COLUMN "Pharmacist_Code" text NULL; +-- Modify "MedicationItem" table +ALTER TABLE "public"."MedicationItem" ADD COLUMN "Medicine_Code" text NULL; +-- Modify "MedicationItemDist" table +ALTER TABLE "public"."MedicationItemDist" ADD COLUMN "Nurse_Code" text NULL; +-- Modify "MedicineMixItem" table +ALTER TABLE "public"."MedicineMixItem" ADD COLUMN "Medicine_Code" text NULL; +-- Modify "PrescriptionItem" table +ALTER TABLE "public"."PrescriptionItem" ADD COLUMN "Medicine_Code" text NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 1e4fb9ef..cd5da8db 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:tc4xv8+poy7S/OAXRUIpl126iMf2PuZD9AcgnioQXYo= +h1:9JvrXnwzDDikw08c4mmDuHhj5OIPvvtmKjQ37ETmF1I= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -110,3 +110,5 @@ h1:tc4xv8+poy7S/OAXRUIpl126iMf2PuZD9AcgnioQXYo= 20251110100545.sql h1:6/LV7751iyKxE2xI6vO1zly+aHUwxXD/IBwLcVpKxqM= 20251111072601.sql h1:lZlTXC8kHh4S+R5TKx23VQDU/Nj2YF+QrDk9Ta2rNM0= 20251111073546.sql h1:nTM5C+HLpBRPkFAsoSJU1RrnzZqoqnrHGvutInHSnCM= +20251111074148.sql h1:U2hX0ICVFut38Qh1s9664QdJFyNF+eutbqd1ryngSy0= +20251111074652.sql h1:KvTPlFQpwGTFLNls/UwA/JNG58ZNAIkiTq9WiO8ttOQ= diff --git a/internal/domain/main-entities/medication-item-dist/entity.go b/internal/domain/main-entities/medication-item-dist/entity.go index 99e16d48..64c732b7 100644 --- a/internal/domain/main-entities/medication-item-dist/entity.go +++ b/internal/domain/main-entities/medication-item-dist/entity.go @@ -15,5 +15,6 @@ type MedicationItemDist struct { DateTime *time.Time `json:"dateTime"` Remain float64 `json:"remain"` Nurse_Id *uint `json:"nurse_id"` + Nurse_Code *string `json:"nurse_code"` Nurse *en.Nurse `json:"nurse,omitempty" gorm:"foreignKey:Nurse_Id;references:Id"` } diff --git a/internal/domain/main-entities/medication-item/entity.go b/internal/domain/main-entities/medication-item/entity.go index ffef0761..88c53ff8 100644 --- a/internal/domain/main-entities/medication-item/entity.go +++ b/internal/domain/main-entities/medication-item/entity.go @@ -15,6 +15,7 @@ type MedicationItem struct { Medication *eme.Medication `json:"medication,omitempty" gorm:"foreignKey:Medication_Id;references:Id"` IsMix bool `json:"isMix"` Medicine_Id *uint `json:"medicine_id"` + Medicine_Code *string `json:"medicine_code"` Medicine *em.Medicine `json:"medicine,omitempty" gorm:"foreignKey:Medicine_Id;references:Id"` MedicineMix_Id *uint `json:"medicineMix_id"` MedicineMix *emm.MedicineMix `json:"medicineMix,omitempty" gorm:"foreignKey:MedicineMix_Id;references:Id"` diff --git a/internal/domain/main-entities/medication/entity.go b/internal/domain/main-entities/medication/entity.go index 0a59c27b..63ceb792 100644 --- a/internal/domain/main-entities/medication/entity.go +++ b/internal/domain/main-entities/medication/entity.go @@ -11,13 +11,14 @@ import ( ) type Medication struct { - ecore.Main // adjust this according to the needs - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - IssuedAt *time.Time `json:"issuedAt"` - Pharmacist_Id *uint `json:"pharmacist_id"` - Pharmacist *ep.Pharmacist `json:"pharmacist,omitempty" gorm:"foreignKey:Pharmacist_Id;references:Id"` - Status_Code erc.DataStatusCode `json:"status_code"` + ecore.Main // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + IssuedAt *time.Time `json:"issuedAt"` + Pharmacist_Id *uint `json:"pharmacist_id"` + Pharmacist_Code *string `json:"pharmacist_code"` + Pharmacist *ep.Pharmacist `json:"pharmacist,omitempty" gorm:"foreignKey:Pharmacist_Id;references:Id"` + Status_Code erc.DataStatusCode `json:"status_code"` } func (d Medication) IsCompleted() bool { diff --git a/internal/domain/main-entities/medicine-mix-item/entity.go b/internal/domain/main-entities/medicine-mix-item/entity.go index a642fce0..f0b760f6 100644 --- a/internal/domain/main-entities/medicine-mix-item/entity.go +++ b/internal/domain/main-entities/medicine-mix-item/entity.go @@ -9,6 +9,7 @@ type MedicineMixItem struct { ecore.Main // adjust this according to the needs MedicineMix_Id *uint `json:"medicineMix_id"` Medicine_Id *uint `json:"medicine_id"` + Medicine_Code *string `json:"medicine_code"` Medicine *em.Medicine `json:"medicine,omitempty" gorm:"foreignKey:Medicine_Id;references:Id"` Dose *uint8 `json:"dose"` Note *string `json:"note" gom:"size:1024"` diff --git a/internal/domain/main-entities/medicine/entity.go b/internal/domain/main-entities/medicine/entity.go index bbcfec78..dda220bc 100644 --- a/internal/domain/main-entities/medicine/entity.go +++ b/internal/domain/main-entities/medicine/entity.go @@ -20,11 +20,9 @@ type Medicine struct { Uom_Code *string `json:"uom_code" gorm:"size:10"` Uom *eu.Uom `json:"uom" gorm:"foreignKey:Uom_Code;references:Code"` Dose uint8 `json:"dose"` - Infra_Id *uint16 `json:"infra_id"` Infra_Code *string `json:"infra_code" gorm:"size:10"` - Infra *ein.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Id;references:Id"` + Infra *ein.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Code;references:Code"` Stock *int `json:"stock"` - Item_Id *uint `json:"item_id"` Item_Code *string `json:"item_code" gorm:"size:50"` - Item *eit.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` + Item *eit.Item `json:"item,omitempty" gorm:"foreignKey:Item_Code;references:Code"` } diff --git a/internal/domain/main-entities/prescription-item/entity.go b/internal/domain/main-entities/prescription-item/entity.go index 33696385..345ad07f 100644 --- a/internal/domain/main-entities/prescription-item/entity.go +++ b/internal/domain/main-entities/prescription-item/entity.go @@ -15,6 +15,7 @@ type PrescriptionItem struct { Prescription *ep.Prescription `json:"prescription,omitempty" gorm:"foreignKey:Prescription_Id;references:Id"` IsMix bool `json:"isMix"` Medicine_Id *uint `json:"medicine_id"` + Medicine_Code *string `json:"medicine_code"` Medicine *em.Medicine `json:"medicine,omitempty" gorm:"foreignKey:Medicine_Id;references:Id"` MedicineMix_Id *uint `json:"medicineMix_id"` MedicineMix *emm.MedicineMix `json:"medicineMix,omitempty" gorm:"foreignKey:MedicineMix_Id;references:Id"` From aa56c987a98fcc7e2d464e80ec4f4b06ecf9ec7b Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 11 Nov 2025 15:07:30 +0700 Subject: [PATCH 152/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 76 ++++++++++++------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index cd5da8db..7be03ff9 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:9JvrXnwzDDikw08c4mmDuHhj5OIPvvtmKjQ37ETmF1I= +h1:9chFiV9CWBjZHekeODQ1RI3YXRSeFuIJvDtAlbSgq9k= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,40 +75,40 @@ h1:9JvrXnwzDDikw08c4mmDuHhj5OIPvvtmKjQ37ETmF1I= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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= -20251111072601.sql h1:lZlTXC8kHh4S+R5TKx23VQDU/Nj2YF+QrDk9Ta2rNM0= -20251111073546.sql h1:nTM5C+HLpBRPkFAsoSJU1RrnzZqoqnrHGvutInHSnCM= -20251111074148.sql h1:U2hX0ICVFut38Qh1s9664QdJFyNF+eutbqd1ryngSy0= -20251111074652.sql h1:KvTPlFQpwGTFLNls/UwA/JNG58ZNAIkiTq9WiO8ttOQ= +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= +20251111072601.sql h1:6p2qynJ2vr3C18peYciAbOIWOoj/+PnNcobU3wNHboQ= +20251111073546.sql h1:BORlFReAZTDLUfpS/eIf5qGkJ+FNznMGK47HRiPkfL8= +20251111074148.sql h1:qzjLGQRWo1Gg8LkJFgTb5Ak7h53tdz+eQrpJqC9+Gc0= +20251111074652.sql h1:uuThrt4wjdq4qEbvS67fF0Nfw/dlj7vGnLqywWBznqk= From 4d5bc188fc3f590d415c9ea9e19bbe7b3d3bc0cb Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 11 Nov 2025 15:24:35 +0700 Subject: [PATCH 153/329] medicine_id into medicine_code in several medications related --- .../migrations/20251111082257.sql | 10 +++ cmd/main-migration/migrations/atlas.sum | 77 ++++++++++--------- .../main-entities/medication-item-dist/dto.go | 8 +- .../medication-item-dist/entity.go | 3 +- .../main-entities/medication-item/dto.go | 8 +- .../main-entities/medication-item/entity.go | 3 +- .../domain/main-entities/medication/dto.go | 40 +++++----- .../domain/main-entities/medication/entity.go | 3 +- .../main-entities/medicine-mix-item/dto.go | 8 +- .../main-entities/medicine-mix-item/entity.go | 3 +- .../main-entities/prescription-item/dto.go | 8 +- .../main-entities/prescription-item/entity.go | 3 +- .../main-use-case/authentication/case.go | 10 +++ .../main-use-case/encounter/helper.go | 4 +- .../medication-item-dist/case.go | 20 +++-- .../medication-item-dist/helper.go | 2 +- .../main-use-case/medication-item/helper.go | 2 +- .../use-case/main-use-case/medication/case.go | 15 ++-- .../main-use-case/medication/helper.go | 2 +- .../main-use-case/medicine-mix-item/helper.go | 2 +- .../main-use-case/prescription-item/helper.go | 2 +- .../main-use-case/prescription/helper.go | 4 +- 22 files changed, 130 insertions(+), 107 deletions(-) create mode 100644 cmd/main-migration/migrations/20251111082257.sql diff --git a/cmd/main-migration/migrations/20251111082257.sql b/cmd/main-migration/migrations/20251111082257.sql new file mode 100644 index 00000000..993534c2 --- /dev/null +++ b/cmd/main-migration/migrations/20251111082257.sql @@ -0,0 +1,10 @@ +-- Modify "Medication" table +ALTER TABLE "public"."Medication" DROP CONSTRAINT "fk_Medication_Pharmacist", DROP COLUMN "Pharmacist_Id", ALTER COLUMN "Pharmacist_Code" TYPE character varying(20), ADD CONSTRAINT "fk_Medication_Pharmacist" FOREIGN KEY ("Pharmacist_Code") REFERENCES "public"."Pharmacist" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "MedicationItem" table +ALTER TABLE "public"."MedicationItem" DROP CONSTRAINT "fk_MedicationItem_Medicine", DROP COLUMN "Medicine_Id", ALTER COLUMN "Medicine_Code" TYPE character varying(10), ADD CONSTRAINT "fk_MedicationItem_Medicine" FOREIGN KEY ("Medicine_Code") REFERENCES "public"."Medicine" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "MedicationItemDist" table +ALTER TABLE "public"."MedicationItemDist" DROP CONSTRAINT "fk_MedicationItemDist_Nurse", DROP COLUMN "Nurse_Id", ALTER COLUMN "Nurse_Code" TYPE character varying(20), ADD CONSTRAINT "fk_MedicationItemDist_Nurse" FOREIGN KEY ("Nurse_Code") REFERENCES "public"."Nurse" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "MedicineMixItem" table +ALTER TABLE "public"."MedicineMixItem" DROP CONSTRAINT "fk_MedicineMixItem_Medicine", DROP COLUMN "Medicine_Id", ALTER COLUMN "Medicine_Code" TYPE character varying(10), ADD CONSTRAINT "fk_MedicineMixItem_Medicine" FOREIGN KEY ("Medicine_Code") REFERENCES "public"."Medicine" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "PrescriptionItem" table +ALTER TABLE "public"."PrescriptionItem" DROP CONSTRAINT "fk_PrescriptionItem_Medicine", DROP COLUMN "Medicine_Id", ALTER COLUMN "Medicine_Code" TYPE character varying(10), ADD CONSTRAINT "fk_PrescriptionItem_Medicine" FOREIGN KEY ("Medicine_Code") REFERENCES "public"."Medicine" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 7be03ff9..055d8426 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:9chFiV9CWBjZHekeODQ1RI3YXRSeFuIJvDtAlbSgq9k= +h1:hjlt7JFxqRt51nzKyLmMo1uueJTYjcyE2zAVvFiHW1E= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,40 +75,41 @@ h1:9chFiV9CWBjZHekeODQ1RI3YXRSeFuIJvDtAlbSgq9k= 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= -20251111072601.sql h1:6p2qynJ2vr3C18peYciAbOIWOoj/+PnNcobU3wNHboQ= -20251111073546.sql h1:BORlFReAZTDLUfpS/eIf5qGkJ+FNznMGK47HRiPkfL8= -20251111074148.sql h1:qzjLGQRWo1Gg8LkJFgTb5Ak7h53tdz+eQrpJqC9+Gc0= -20251111074652.sql h1:uuThrt4wjdq4qEbvS67fF0Nfw/dlj7vGnLqywWBznqk= +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= +20251111072601.sql h1:lZlTXC8kHh4S+R5TKx23VQDU/Nj2YF+QrDk9Ta2rNM0= +20251111073546.sql h1:nTM5C+HLpBRPkFAsoSJU1RrnzZqoqnrHGvutInHSnCM= +20251111074148.sql h1:U2hX0ICVFut38Qh1s9664QdJFyNF+eutbqd1ryngSy0= +20251111074652.sql h1:KvTPlFQpwGTFLNls/UwA/JNG58ZNAIkiTq9WiO8ttOQ= +20251111082257.sql h1:tSzTg/99dYQKDM1MfIb4QTluZfNeCHytOiWAH1lOd0E= diff --git a/internal/domain/main-entities/medication-item-dist/dto.go b/internal/domain/main-entities/medication-item-dist/dto.go index 6936bdbc..613e87d9 100644 --- a/internal/domain/main-entities/medication-item-dist/dto.go +++ b/internal/domain/main-entities/medication-item-dist/dto.go @@ -18,7 +18,7 @@ type CreateDto struct { MedicationItem_Id *uint `json:"medicationItem_id"` DateTime *time.Time `json:"dateTime"` Remain float64 `json:"remain"` - Nurse_Id *uint `json:"nurse_id"` + Nurse_Code *string `json:"nurse_code"` } type ReadListDto struct { @@ -31,7 +31,7 @@ type FilterDto struct { MedicationItem_Id *uint `json:"medicationItem-id"` DateTime *time.Time `json:"dateTime"` Remain float64 `json:"remain"` - Nurse_Id *uint `json:"nurse-id"` + Nurse_Code *string `json:"nurse-code"` } type ReadDetailDto struct { Id uint16 `json:"id"` @@ -65,7 +65,7 @@ type ResponseDto struct { MedicationItem *emi.MedicationItem `json:"medicationItem,omitempty"` DateTime *time.Time `json:"dateTime"` Remain float64 `json:"remain"` - Nurse_Id *uint `json:"nurse_id"` + Nurse_Code *string `json:"nurse_code"` } func (d MedicationItemDist) ToResponse() ResponseDto { @@ -74,7 +74,7 @@ func (d MedicationItemDist) ToResponse() ResponseDto { MedicationItem: d.MedicationItem, DateTime: d.DateTime, Remain: d.Remain, - Nurse_Id: d.Nurse_Id, + Nurse_Code: d.Nurse_Code, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/medication-item-dist/entity.go b/internal/domain/main-entities/medication-item-dist/entity.go index 64c732b7..9a1b1f38 100644 --- a/internal/domain/main-entities/medication-item-dist/entity.go +++ b/internal/domain/main-entities/medication-item-dist/entity.go @@ -14,7 +14,6 @@ type MedicationItemDist struct { MedicationItem *emi.MedicationItem `json:"medicationItem,omitempty" gorm:"foreignKey:MedicationItem_Id;references:Id"` DateTime *time.Time `json:"dateTime"` Remain float64 `json:"remain"` - Nurse_Id *uint `json:"nurse_id"` Nurse_Code *string `json:"nurse_code"` - Nurse *en.Nurse `json:"nurse,omitempty" gorm:"foreignKey:Nurse_Id;references:Id"` + Nurse *en.Nurse `json:"nurse,omitempty" gorm:"foreignKey:Nurse_Code;references:Code"` } diff --git a/internal/domain/main-entities/medication-item/dto.go b/internal/domain/main-entities/medication-item/dto.go index 26a5b35e..636f5c42 100644 --- a/internal/domain/main-entities/medication-item/dto.go +++ b/internal/domain/main-entities/medication-item/dto.go @@ -12,7 +12,7 @@ import ( type CreateDto struct { Medication_Id *uint `json:"medication_id"` IsMix bool `json:"isMix"` - Medicine_Id *uint `json:"medicine_id"` + Medicine_Code *string `json:"medicine_code"` MedicineMix_Id *uint `json:"medicineMix_id"` Frequency *uint16 `json:"frequency"` Dose float64 `json:"dose"` @@ -35,7 +35,7 @@ type ReadListDto struct { type FilterDto struct { Medication_Id *uint `json:"medication-id"` IsMix bool `json:"isMix"` - Medicine_Id *uint `json:"medicine-id"` + Medicine_Code *string `json:"medicine-code"` MedicineMix_Id *uint `json:"medicineMix-id"` Usage float64 `json:"usage"` Interval uint8 `json:"interval"` @@ -68,7 +68,7 @@ type ResponseDto struct { Medication_Id *uint `json:"medication_id"` Medication *eme.Medication `json:"medication,omitempty"` IsMix bool `json:"isMix"` - Medicine_Id *uint `json:"medicine_id"` + Medicine_Code *string `json:"medicine_code"` Medicine *em.Medicine `json:"medicine,omitempty"` MedicineMix_Id *uint `json:"medicineMix_id"` MedicineMix *emm.MedicineMix `json:"medicineMix,omitempty"` @@ -85,7 +85,7 @@ func (d MedicationItem) ToResponse() ResponseDto { Medication_Id: d.Medication_Id, Medication: d.Medication, IsMix: d.IsMix, - Medicine_Id: d.Medicine_Id, + Medicine_Code: d.Medicine_Code, Medicine: d.Medicine, MedicineMix_Id: d.MedicineMix_Id, MedicineMix: d.MedicineMix, diff --git a/internal/domain/main-entities/medication-item/entity.go b/internal/domain/main-entities/medication-item/entity.go index 88c53ff8..8198afe1 100644 --- a/internal/domain/main-entities/medication-item/entity.go +++ b/internal/domain/main-entities/medication-item/entity.go @@ -14,9 +14,8 @@ type MedicationItem struct { Medication_Id *uint `json:"medication_id"` Medication *eme.Medication `json:"medication,omitempty" gorm:"foreignKey:Medication_Id;references:Id"` IsMix bool `json:"isMix"` - Medicine_Id *uint `json:"medicine_id"` Medicine_Code *string `json:"medicine_code"` - Medicine *em.Medicine `json:"medicine,omitempty" gorm:"foreignKey:Medicine_Id;references:Id"` + Medicine *em.Medicine `json:"medicine,omitempty" gorm:"foreignKey:Medicine_Code;references:Code"` MedicineMix_Id *uint `json:"medicineMix_id"` MedicineMix *emm.MedicineMix `json:"medicineMix,omitempty" gorm:"foreignKey:MedicineMix_Id;references:Id"` Frequency *uint16 `json:"frequency"` diff --git a/internal/domain/main-entities/medication/dto.go b/internal/domain/main-entities/medication/dto.go index 928b926c..67cc284f 100644 --- a/internal/domain/main-entities/medication/dto.go +++ b/internal/domain/main-entities/medication/dto.go @@ -19,10 +19,10 @@ import ( ) type CreateDto struct { - Encounter_Id *uint `json:"encounter_id"` - IssuedAt *time.Time `json:"issuedAt"` - Pharmacist_Id *uint `json:"pharmacist_id"` - Status_Code erc.DataStatusCode `json:"status_code"` + Encounter_Id *uint `json:"encounter_id"` + IssuedAt *time.Time `json:"issuedAt"` + Pharmacist_Code *string `json:"pharmacist_code"` + Status_Code erc.DataStatusCode `json:"status_code"` } type ReadListDto struct { @@ -32,10 +32,10 @@ type ReadListDto struct { } type FilterDto struct { - Encounter_Id *uint `json:"encounter-id"` - IssuedAt *time.Time `json:"issuedAt"` - Pharmacist_Id *uint `json:"pharmacist-id"` - Status_Code erc.DataStatusCode `json:"status-code"` + Encounter_Id *uint `json:"encounter-id"` + IssuedAt *time.Time `json:"issuedAt"` + Pharmacist_Code *string `json:"pharmacist-code"` + Status_Code erc.DataStatusCode `json:"status-code"` } type ReadDetailDto struct { Id uint `json:"id"` @@ -61,22 +61,22 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty"` - IssuedAt *time.Time `json:"issuedAt"` - Pharmacist_Id *uint `json:"pharmacist_id"` - Pharmacist *ep.Pharmacist `json:"pharmacist,omitempty"` - Status_Code erc.DataStatusCode `json:"status_code"` + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty"` + IssuedAt *time.Time `json:"issuedAt"` + Pharmacist_Code *string `json:"pharmacist_code"` + Pharmacist *ep.Pharmacist `json:"pharmacist,omitempty"` + Status_Code erc.DataStatusCode `json:"status_code"` } func (d Medication) ToResponse() ResponseDto { resp := ResponseDto{ - Encounter_Id: d.Encounter_Id, - Encounter: d.Encounter, - IssuedAt: d.IssuedAt, - Pharmacist_Id: d.Pharmacist_Id, - Pharmacist: d.Pharmacist, - Status_Code: d.Status_Code, + Encounter_Id: d.Encounter_Id, + Encounter: d.Encounter, + IssuedAt: d.IssuedAt, + Pharmacist_Code: d.Pharmacist_Code, + Pharmacist: d.Pharmacist, + Status_Code: d.Status_Code, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/medication/entity.go b/internal/domain/main-entities/medication/entity.go index 63ceb792..13781f85 100644 --- a/internal/domain/main-entities/medication/entity.go +++ b/internal/domain/main-entities/medication/entity.go @@ -15,9 +15,8 @@ type Medication struct { Encounter_Id *uint `json:"encounter_id"` Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` IssuedAt *time.Time `json:"issuedAt"` - Pharmacist_Id *uint `json:"pharmacist_id"` Pharmacist_Code *string `json:"pharmacist_code"` - Pharmacist *ep.Pharmacist `json:"pharmacist,omitempty" gorm:"foreignKey:Pharmacist_Id;references:Id"` + Pharmacist *ep.Pharmacist `json:"pharmacist,omitempty" gorm:"foreignKey:Pharmacist_Code;references:Code"` Status_Code erc.DataStatusCode `json:"status_code"` } diff --git a/internal/domain/main-entities/medicine-mix-item/dto.go b/internal/domain/main-entities/medicine-mix-item/dto.go index e834e7ec..12c78500 100644 --- a/internal/domain/main-entities/medicine-mix-item/dto.go +++ b/internal/domain/main-entities/medicine-mix-item/dto.go @@ -7,7 +7,7 @@ import ( type CreateDto struct { MedicineMix_Id *uint `json:"medicineMix_id"` - Medicine_Id *uint `json:"medicine_id"` + Medicine_Code *string `json:"medicine_code"` Dose *uint8 `json:"dose"` Note *string `json:"note" gom:"size:1024"` } @@ -20,7 +20,7 @@ type ReadListDto struct { type FilterDto struct { MedicineMix_Id *uint `json:"medicineMix-id"` - Medicine_Id *uint `json:"medicine-id"` + Medicine_Code *string `json:"medicine-code"` Dose *uint8 `json:"dose"` Note *string `json:"note" gom:"size:1024"` } @@ -47,7 +47,7 @@ type MetaDto struct { type ResponseDto struct { ecore.Main MedicineMix_Id *uint `json:"medicineMix_id"` - Medicine_Id *uint `json:"medicine_id"` + Medicine_Code *string `json:"medicine_code"` Medicine *em.Medicine `json:"medicine,omitempty"` Dose *uint8 `json:"dose"` Note *string `json:"note" gom:"size:1024"` @@ -56,7 +56,7 @@ type ResponseDto struct { func (d MedicineMixItem) ToResponse() ResponseDto { resp := ResponseDto{ MedicineMix_Id: d.MedicineMix_Id, - Medicine_Id: d.Medicine_Id, + Medicine_Code: d.Medicine_Code, Medicine: d.Medicine, Dose: d.Dose, Note: d.Note, diff --git a/internal/domain/main-entities/medicine-mix-item/entity.go b/internal/domain/main-entities/medicine-mix-item/entity.go index f0b760f6..3c9d9098 100644 --- a/internal/domain/main-entities/medicine-mix-item/entity.go +++ b/internal/domain/main-entities/medicine-mix-item/entity.go @@ -8,9 +8,8 @@ import ( type MedicineMixItem struct { ecore.Main // adjust this according to the needs MedicineMix_Id *uint `json:"medicineMix_id"` - Medicine_Id *uint `json:"medicine_id"` Medicine_Code *string `json:"medicine_code"` - Medicine *em.Medicine `json:"medicine,omitempty" gorm:"foreignKey:Medicine_Id;references:Id"` + Medicine *em.Medicine `json:"medicine,omitempty" gorm:"foreignKey:Medicine_Code;references:Code"` Dose *uint8 `json:"dose"` Note *string `json:"note" gom:"size:1024"` } diff --git a/internal/domain/main-entities/prescription-item/dto.go b/internal/domain/main-entities/prescription-item/dto.go index 64b5f78f..33e63ed2 100644 --- a/internal/domain/main-entities/prescription-item/dto.go +++ b/internal/domain/main-entities/prescription-item/dto.go @@ -12,7 +12,7 @@ import ( type CreateDto struct { Prescription_Id *uint `json:"prescription_id"` IsMix bool `json:"isMix"` - Medicine_Id *uint `json:"medicine_id"` + Medicine_Code *string `json:"medicine_code"` MedicineMix_Id *uint `json:"medicineMix_id"` Frequency *uint16 `json:"frequency" validate:"required"` Dose float64 `json:"dose" validate:"required"` @@ -32,7 +32,7 @@ type ReadListDto struct { type FilterDto struct { Prescription_Id *uint `json:"prescription-id"` IsMix bool `json:"isMix"` - Medicine_Id *uint `json:"medicine-id"` + Medicine_Code *string `json:"medicine-code"` MedicineMix_Id *uint `json:"medicineMix-id"` Usage float64 `json:"usage"` Interval uint8 `json:"interval"` @@ -63,7 +63,7 @@ type ResponseDto struct { Prescription_Id *uint `json:"prescription_id"` Prescription *ep.Prescription `json:"prescription,omitempty"` IsMix bool `json:"isMix"` - Medicine_Id *uint `json:"medicine_id"` + Medicine_Code *string `json:"medicine_code"` Medicine *em.Medicine `json:"medicine,omitempty"` MedicineMix_Id *uint `json:"medicineMix_id"` MedicineMix *emm.MedicineMix `json:"medicineMix,omitempty"` @@ -80,7 +80,7 @@ func (d PrescriptionItem) ToResponse() ResponseDto { Prescription_Id: d.Prescription_Id, Prescription: d.Prescription, IsMix: d.IsMix, - Medicine_Id: d.Medicine_Id, + Medicine_Code: d.Medicine_Code, Medicine: d.Medicine, MedicineMix_Id: d.MedicineMix_Id, MedicineMix: d.MedicineMix, diff --git a/internal/domain/main-entities/prescription-item/entity.go b/internal/domain/main-entities/prescription-item/entity.go index 345ad07f..93174079 100644 --- a/internal/domain/main-entities/prescription-item/entity.go +++ b/internal/domain/main-entities/prescription-item/entity.go @@ -14,9 +14,8 @@ type PrescriptionItem struct { Prescription_Id *uint `json:"prescription_id"` Prescription *ep.Prescription `json:"prescription,omitempty" gorm:"foreignKey:Prescription_Id;references:Id"` IsMix bool `json:"isMix"` - Medicine_Id *uint `json:"medicine_id"` Medicine_Code *string `json:"medicine_code"` - Medicine *em.Medicine `json:"medicine,omitempty" gorm:"foreignKey:Medicine_Id;references:Id"` + Medicine *em.Medicine `json:"medicine,omitempty" gorm:"foreignKey:Medicine_Code;references:Code"` MedicineMix_Id *uint `json:"medicineMix_id"` MedicineMix *emm.MedicineMix `json:"medicineMix,omitempty" gorm:"foreignKey:MedicineMix_Id;references:Id"` Frequency *uint16 `json:"frequency"` diff --git a/internal/use-case/main-use-case/authentication/case.go b/internal/use-case/main-use-case/authentication/case.go index c162c56c..bd9dcee6 100644 --- a/internal/use-case/main-use-case/authentication/case.go +++ b/internal/use-case/main-use-case/authentication/case.go @@ -24,7 +24,9 @@ import ( "simrs-vx/internal/domain/main-entities/intern" em "simrs-vx/internal/domain/main-entities/midwife" en "simrs-vx/internal/domain/main-entities/nurse" + ep "simrs-vx/internal/domain/main-entities/pharmacist" eu "simrs-vx/internal/domain/main-entities/user" + erc "simrs-vx/internal/domain/references/common" erg "simrs-vx/internal/domain/references/organization" ) @@ -169,6 +171,14 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { } atClaims["midwife_code"] = empData.Code outputData["midwife_code"] = empData.Code + case erg.EPCPha: + empData := ep.Pharmacist{} + dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + if empData.Id == 0 { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noPharmacist", Message: pl.GenMessage("auth-noPharmacist")}} + } + atClaims["pharmacist_code"] = empData.Code + outputData["pharmacist_code"] = empData.Code } errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: pl.GenMessage("auth-getData-failed")}} diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index 1e86121f..fc69549e 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -233,7 +233,7 @@ func createMedicineMixAndItem(input emi.MedicineMix, event *pl.Event, tx *gorm.D for _, medicineMixItem := range input.MixItems { medicineMixItemCreate := emmi.CreateDto{ MedicineMix_Id: &medicineMix.Id, - Medicine_Id: medicineMixItem.Medicine_Id, + Medicine_Code: medicineMixItem.Medicine_Code, Dose: medicineMixItem.Dose, } _, err := ummi.CreateData(medicineMixItemCreate, event, tx) @@ -251,7 +251,7 @@ func createMedicationItem(medication_id uint, input epi.PrescriptionItem, event medicationItemCreate := emei.CreateDto{ Medication_Id: &medication_id, IsMix: input.IsMix, - Medicine_Id: input.Medicine_Id, + Medicine_Code: input.Medicine_Code, MedicineMix_Id: input.MedicineMix_Id, Usage: input.Usage, Interval: input.Interval, diff --git a/internal/use-case/main-use-case/medication-item-dist/case.go b/internal/use-case/main-use-case/medication-item-dist/case.go index ff54c775..ef74fabd 100644 --- a/internal/use-case/main-use-case/medication-item-dist/case.go +++ b/internal/use-case/main-use-case/medication-item-dist/case.go @@ -6,8 +6,6 @@ import ( e "simrs-vx/internal/domain/main-entities/medication-item-dist" - un "simrs-vx/internal/use-case/main-use-case/nurse" - dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -303,11 +301,6 @@ func Consume(input e.ConsumeDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - nurse_id, err := un.GetIdByUserId(&input.AuthInfo.User_Id, &event, tx) - if err != nil { - return err - } - if data, err = ReadDetailData(rdDto, &event, tx); err != nil { return err } @@ -319,7 +312,18 @@ func Consume(input e.ConsumeDto) (*d.Data, error) { } data.Remain -= input.Usage - data.Nurse_Id = nurse_id + + if input.AuthInfo.Nurse_Code == nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "auth-noNurse", + Detail: "user position is not allowed, only nurse can do action consume medication", + Raw: errors.New("authentication failed"), + } + return pl.SetLogError(&event, input) + } + + data.Nurse_Code = input.AuthInfo.Nurse_Code if err := tx.Save(&data).Error; err != nil { event.Status = "failed" diff --git a/internal/use-case/main-use-case/medication-item-dist/helper.go b/internal/use-case/main-use-case/medication-item-dist/helper.go index 5b1b1d35..b789f22f 100644 --- a/internal/use-case/main-use-case/medication-item-dist/helper.go +++ b/internal/use-case/main-use-case/medication-item-dist/helper.go @@ -20,5 +20,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.MedicationItemDist) data.MedicationItem_Id = inputSrc.MedicationItem_Id data.DateTime = inputSrc.DateTime data.Remain = inputSrc.Remain - data.Nurse_Id = inputSrc.Nurse_Id + data.Nurse_Code = inputSrc.Nurse_Code } diff --git a/internal/use-case/main-use-case/medication-item/helper.go b/internal/use-case/main-use-case/medication-item/helper.go index dcee2cac..5f4cd27b 100644 --- a/internal/use-case/main-use-case/medication-item/helper.go +++ b/internal/use-case/main-use-case/medication-item/helper.go @@ -19,7 +19,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.MedicationItem) { data.Medication_Id = inputSrc.Medication_Id data.IsMix = inputSrc.IsMix - data.Medicine_Id = inputSrc.Medicine_Id + data.Medicine_Code = inputSrc.Medicine_Code data.MedicineMix_Id = inputSrc.MedicineMix_Id data.Frequency = inputSrc.Frequency data.Dose = inputSrc.Dose diff --git a/internal/use-case/main-use-case/medication/case.go b/internal/use-case/main-use-case/medication/case.go index 652f2010..bccbe347 100644 --- a/internal/use-case/main-use-case/medication/case.go +++ b/internal/use-case/main-use-case/medication/case.go @@ -8,8 +8,6 @@ import ( erc "simrs-vx/internal/domain/references/common" - up "simrs-vx/internal/use-case/main-use-case/pharmacist" - dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -313,13 +311,18 @@ func Complete(input e.ReadDetailDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - pharmacist_id, err := up.GetIdByUserId(&input.AuthInfo.User_Id, &event, tx) - if err != nil { - return err + if input.AuthInfo.Pharmachist_Code == nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "auth-noPharmacist", + Detail: "user position is not allowed, only pharmacist can do actioncomplete medication", + Raw: errors.New("authentication failed"), + } + return pl.SetLogError(&event, input) } data.Status_Code = erc.DSCDone - data.Pharmacist_Id = pharmacist_id + data.Pharmacist_Code = input.AuthInfo.Pharmachist_Code if err := tx.Save(&data).Error; err != nil { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ diff --git a/internal/use-case/main-use-case/medication/helper.go b/internal/use-case/main-use-case/medication/helper.go index 63290cb1..b9d0d508 100644 --- a/internal/use-case/main-use-case/medication/helper.go +++ b/internal/use-case/main-use-case/medication/helper.go @@ -30,7 +30,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Medication) { data.Encounter_Id = inputSrc.Encounter_Id data.IssuedAt = inputSrc.IssuedAt - data.Pharmacist_Id = inputSrc.Pharmacist_Id + data.Pharmacist_Code = inputSrc.Pharmacist_Code data.Status_Code = inputSrc.Status_Code } diff --git a/internal/use-case/main-use-case/medicine-mix-item/helper.go b/internal/use-case/main-use-case/medicine-mix-item/helper.go index 0a64f30c..597cee66 100644 --- a/internal/use-case/main-use-case/medicine-mix-item/helper.go +++ b/internal/use-case/main-use-case/medicine-mix-item/helper.go @@ -18,7 +18,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.MedicineMixItem) { } data.MedicineMix_Id = inputSrc.MedicineMix_Id - data.Medicine_Id = inputSrc.Medicine_Id + data.Medicine_Code = inputSrc.Medicine_Code data.Dose = inputSrc.Dose data.Note = inputSrc.Note } diff --git a/internal/use-case/main-use-case/prescription-item/helper.go b/internal/use-case/main-use-case/prescription-item/helper.go index 3f627ddf..174e9927 100644 --- a/internal/use-case/main-use-case/prescription-item/helper.go +++ b/internal/use-case/main-use-case/prescription-item/helper.go @@ -19,7 +19,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.PrescriptionItem) { data.Prescription_Id = inputSrc.Prescription_Id data.IsMix = inputSrc.IsMix - data.Medicine_Id = inputSrc.Medicine_Id + data.Medicine_Code = inputSrc.Medicine_Code data.MedicineMix_Id = inputSrc.MedicineMix_Id data.Frequency = inputSrc.Frequency data.Dose = inputSrc.Dose diff --git a/internal/use-case/main-use-case/prescription/helper.go b/internal/use-case/main-use-case/prescription/helper.go index 7260699e..0a10ae05 100644 --- a/internal/use-case/main-use-case/prescription/helper.go +++ b/internal/use-case/main-use-case/prescription/helper.go @@ -99,7 +99,7 @@ func createMedicineMixAndItem(input emi.MedicineMix, event *pl.Event, tx *gorm.D for _, medicineMixItem := range input.MixItems { medicineMixItemCreate := emmi.CreateDto{ MedicineMix_Id: &medicineMix.Id, - Medicine_Id: medicineMixItem.Medicine_Id, + Medicine_Code: medicineMixItem.Medicine_Code, Dose: medicineMixItem.Dose, } _, err := ummi.CreateData(medicineMixItemCreate, event, tx) @@ -117,7 +117,7 @@ func createMedicationItem(medication_id uint, input epi.PrescriptionItem, event medicationItemCreate := emei.CreateDto{ Medication_Id: &medication_id, IsMix: input.IsMix, - Medicine_Id: input.Medicine_Id, + Medicine_Code: input.Medicine_Code, MedicineMix_Id: input.MedicineMix_Id, Frequency: input.Frequency, Dose: input.Dose, From 9443e32963d66eae5470bb078104548ab372f885 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 11 Nov 2025 15:25:09 +0700 Subject: [PATCH 154/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 78 ++++++++++++------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 055d8426..fb7ec8eb 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:hjlt7JFxqRt51nzKyLmMo1uueJTYjcyE2zAVvFiHW1E= +h1:3V3a/T/te8iQqsolgRAJKr99GePHgSN9miJHUNngJ74= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,41 +75,41 @@ h1:hjlt7JFxqRt51nzKyLmMo1uueJTYjcyE2zAVvFiHW1E= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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= -20251111072601.sql h1:lZlTXC8kHh4S+R5TKx23VQDU/Nj2YF+QrDk9Ta2rNM0= -20251111073546.sql h1:nTM5C+HLpBRPkFAsoSJU1RrnzZqoqnrHGvutInHSnCM= -20251111074148.sql h1:U2hX0ICVFut38Qh1s9664QdJFyNF+eutbqd1ryngSy0= -20251111074652.sql h1:KvTPlFQpwGTFLNls/UwA/JNG58ZNAIkiTq9WiO8ttOQ= -20251111082257.sql h1:tSzTg/99dYQKDM1MfIb4QTluZfNeCHytOiWAH1lOd0E= +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= +20251111072601.sql h1:6p2qynJ2vr3C18peYciAbOIWOoj/+PnNcobU3wNHboQ= +20251111073546.sql h1:BORlFReAZTDLUfpS/eIf5qGkJ+FNznMGK47HRiPkfL8= +20251111074148.sql h1:qzjLGQRWo1Gg8LkJFgTb5Ak7h53tdz+eQrpJqC9+Gc0= +20251111074652.sql h1:uuThrt4wjdq4qEbvS67fF0Nfw/dlj7vGnLqywWBznqk= +20251111082257.sql h1:eUfu0tDtl9KqX7UK8is6Qc04NSQs4BXwKsykZwnVH1w= From 06fca51bcc4b8b178cbc1bf9d9ebf8c308a20e27 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 11 Nov 2025 15:34:33 +0700 Subject: [PATCH 155/329] fix conflict auth --- .../main-use-case/authentication/case.go | 155 +----------------- .../main-use-case/authentication/helper.go | 9 + 2 files changed, 14 insertions(+), 150 deletions(-) diff --git a/internal/use-case/main-use-case/authentication/case.go b/internal/use-case/main-use-case/authentication/case.go index ab071c66..15f18ef8 100644 --- a/internal/use-case/main-use-case/authentication/case.go +++ b/internal/use-case/main-use-case/authentication/case.go @@ -18,14 +18,9 @@ import ( pl "simrs-vx/pkg/logger" p "simrs-vx/pkg/password" - ed "simrs-vx/internal/domain/main-entities/doctor" - ee "simrs-vx/internal/domain/main-entities/employee" - "simrs-vx/internal/domain/main-entities/intern" - em "simrs-vx/internal/domain/main-entities/midwife" - en "simrs-vx/internal/domain/main-entities/nurse" + eap "simrs-vx/internal/domain/main-entities/auth-partner" eu "simrs-vx/internal/domain/main-entities/user" euf "simrs-vx/internal/domain/main-entities/user-fes" - erc "simrs-vx/internal/domain/references/common" ) @@ -85,152 +80,12 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { // Data and output population atClaims := jwt.MapClaims{} - atClaims["user_id"] = user.Id - atClaims["user_name"] = user.Name - atClaims["user_contractPosition_code"] = user.ContractPosition_Code - atClaims["uuid"] = aUuid - atClaims["exp"] = atExpires - - // Create output - outputData := d.II{ - "user_id": strconv.Itoa(int(user.Id)), - "user_name": user.Name, - "user_contractPosition_code": user.ContractPosition_Code, - } - - // extra - role := []string{} - switch user.ContractPosition_Code { - case erg.CSCEmp: - // employee - employee := ee.Employee{} - dg.I.Where("\"User_Id\" = ?", user.Id).First(&employee) - if employee.Id == 0 { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noEmployee", Message: pl.GenMessage("auth-noEmployee")}} - } - atClaims["employee_id"] = employee.Id - outputData["employee_id"] = employee.Id - role = append(role, "emp-"+string(*employee.Position_Code)) - - //if employee.Division_Code != nil { - // atClaims["employee_division_code"] = employee.Division_Code - // outputData["employee_division_code"] = employee.Division_Code - //} - - // employee position - if employee.Id > 0 && employee.Position_Code != nil { - atClaims["employee_position_code"] = *employee.Position_Code - switch *employee.Position_Code { - case erg.EPCDoc: - doctor := ed.Doctor{} - dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&doctor) - if doctor.Id == 0 { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noDoctor", Message: pl.GenMessage("auth-noDoctor")}} - } - atClaims["doctor_code"] = doctor.Code - outputData["doctor_code"] = doctor.Code - - // specialist - if doctor.Specialist_Code != nil { - atClaims["specialist_code"] = doctor.Specialist_Code - outputData["specialist_code"] = doctor.Specialist_Code - } - if doctor.Subspecialist_Code != nil { - atClaims["subspecialist_code"] = doctor.Subspecialist_Code - outputData["subspecialist_code"] = doctor.Subspecialist_Code - } - case erg.EPCNur: - empData := en.Nurse{} - dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) - if empData.Id == 0 { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: pl.GenMessage("auth-noNurse")}} - } - atClaims["nurse_code"] = empData.Code - outputData["nurse_code"] = empData.Code - case erg.EPCMwi: - empData := em.Midwife{} - dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) - if empData.Id == 0 { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noMidwife", Message: pl.GenMessage("auth-noMidwife")}} - } - atClaims["midwife_code"] = empData.Code - outputData["midwife_code"] = empData.Code - case erg.EPCPha: - empData := ep.Pharmacist{} - dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) - if empData.Id == 0 { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noPharmacist", Message: pl.GenMessage("auth-noPharmacist")}} - } - atClaims["pharmacist_code"] = empData.Code - outputData["pharmacist_code"] = empData.Code - } - - errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: pl.GenMessage("auth-getData-failed")}} - - // division position - divisionPositions, err := getDivisionPosition(employee.Id, &event) - if err != nil { - return nil, errorGetPosition - } - - // installation position - installationPositions, err := getInstallationPosition(employee.Id, &event) - if err != nil { - return nil, errorGetPosition - } - - // unit position - unitPositions, err := getUnitPosition(employee.Id, &event) - if err != nil { - return nil, errorGetPosition - } - - // specialist position - specialistPositions, err := getSpecialistPosition(employee.Id, &event) - if err != nil { - return nil, errorGetPosition - } - - // subspecialist position - subspecialistPositions, err := getSubspecialistPosition(employee.Id, &event) - if err != nil { - return nil, errorGetPosition - } - - role = append(role, divisionPositions...) - role = append(role, installationPositions...) - role = append(role, unitPositions...) - role = append(role, specialistPositions...) - role = append(role, subspecialistPositions...) - // atClaims["division_positions"] = divsionPositions - // outputData["division_positions"] = divsionPositions - } - case erg.CSCInt: - intern := intern.Intern{} - dg.I.Where("\"User_Id\" = ?", user.Id).First(&intern) - role = append(role, "int-"+string(*intern.Position_Code)) - case erg.CSCSys: - role = append(role, "system") - } - atClaims["roles"] = role - outputData["roles"] = role - - // Generate jwt - at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims) - ats, err := at.SignedString([]byte(atSecretKey)) - if err != nil { - return nil, d.FieldErrors{"user": d.FieldError{Code: "token-sign-err", Message: pl.GenMessage("token-sign-err")}} - } - outputData["accessToken"] = ats - - // Save to redis - now := time.Now() - atx := time.Unix(atExpires, 0) //converting Unix to UTC(to Time object) - err = ms.I.Set(aUuid, strconv.Itoa(int(user.Id)), atx.Sub(now)).Err() - if err != nil { - panic(fmt.Sprintf(l.I.Msg("redis-store-fail"), err.Error())) + outputData := d.II{} + if err := populateRoles(user, input, atClaims, outputData, event); err != nil { + return nil, err } + // Only manual login tn := time.Now() user.LoginAttemptCount = 0 user.LastSuccessLogin = &tn diff --git a/internal/use-case/main-use-case/authentication/helper.go b/internal/use-case/main-use-case/authentication/helper.go index b7ccc660..d0fe1af1 100644 --- a/internal/use-case/main-use-case/authentication/helper.go +++ b/internal/use-case/main-use-case/authentication/helper.go @@ -21,6 +21,7 @@ import ( "simrs-vx/internal/domain/main-entities/intern" em "simrs-vx/internal/domain/main-entities/midwife" en "simrs-vx/internal/domain/main-entities/nurse" + ep "simrs-vx/internal/domain/main-entities/pharmacist" esp "simrs-vx/internal/domain/main-entities/specialist-position" essp "simrs-vx/internal/domain/main-entities/subspecialist-position" eup "simrs-vx/internal/domain/main-entities/unit-position" @@ -249,6 +250,14 @@ func populateRoles(user *eu.User, input eu.LoginDto, atClaims jwt.MapClaims, out } atClaims["midwife_code"] = empData.Code outputData["midwife_code"] = empData.Code + case erg.EPCPha: + empData := ep.Pharmacist{} + dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + if empData.Id == 0 { + return d.FieldErrors{"authentication": d.FieldError{Code: "auth-noPharmacist", Message: pl.GenMessage("auth-noPharmacist")}} + } + atClaims["pharmacist_code"] = empData.Code + outputData["pharmacist_code"] = empData.Code } errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: pl.GenMessage("auth-getData-failed")}} From 733fb481b3f525fe84b047f371642ed8764142f4 Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 11 Nov 2025 15:35:19 +0700 Subject: [PATCH 156/329] tbc --- .../main-entities/file-attachment/dto.go | 8 +++---- internal/domain/references/upload/upload.go | 22 ++++++++++++++----- .../main-handler/file-attachment/handler.go | 8 +++---- .../file-attachment/validate-request.go | 11 +++++----- .../interface/main-handler/main-handler.go | 2 +- .../main-use-case/file-attachement/case.go | 22 +++++++++++++++---- 6 files changed, 49 insertions(+), 24 deletions(-) diff --git a/internal/domain/main-entities/file-attachment/dto.go b/internal/domain/main-entities/file-attachment/dto.go index db4bdee5..aeb01291 100644 --- a/internal/domain/main-entities/file-attachment/dto.go +++ b/internal/domain/main-entities/file-attachment/dto.go @@ -11,11 +11,11 @@ import ( ) type CreateDto struct { - EntityType_Code eru.EntityTypeCode `form:"entityType_code" validate:"required"` - Ref_Id *uint `form:"ref_id" validate:"required"` - Type_Code eru.UploadCode `form:"type_code" validate:"required"` + EntityType_Code eru.EntityTypeCode `form:"entityType_code"` + Ref_Id *uint `form:"ref_id"` + Type_Code eru.UploadCode `form:"type_code"` Name string `form:"name"` - Upload_Employee_Id *string `form:"upload_employee_id"` + Upload_Employee_Id *uint `form:"upload_employee_id"` FilePath string `json:"-"` File multipart.File `json:"-"` diff --git a/internal/domain/references/upload/upload.go b/internal/domain/references/upload/upload.go index 063f97b9..603be6c8 100644 --- a/internal/domain/references/upload/upload.go +++ b/internal/domain/references/upload/upload.go @@ -1,5 +1,7 @@ package upload +import "fmt" + type ( UploadCode string EntityTypeCode string @@ -16,22 +18,32 @@ const ( ETCPerson EntityTypeCode = "person" ETCEncounter EntityTypeCode = "encounter" + ETCMCU EntityTypeCode = "mcu" ) var validUploadCodesByEntity = map[EntityTypeCode][]UploadCode{ ETCPerson: { - UCPRN, UCPDL, UCPP, UCPFC, UCMIR, + UCPRN, UCPDL, UCPP, UCPFC, }, ETCEncounter: { UCSEP, UCSIPP, }, + ETCMCU: { + UCMIR, + }, } -func IsValidUploadCode(entity EntityTypeCode, code UploadCode) bool { - for _, c := range validUploadCodesByEntity[entity] { +func IsValidUploadCode(entity EntityTypeCode, code UploadCode) (bool, string) { + allowedCodes, ok := validUploadCodesByEntity[entity] + if !ok { + return false, fmt.Sprintf("unknown entityType_code: %s", entity) + } + + for _, c := range allowedCodes { if c == code { - return true + return true, "" } } - return false + + return false, fmt.Sprintf("invalid upload_code '%s' for entityType_code '%s'", code, entity) } diff --git a/internal/interface/main-handler/file-attachment/handler.go b/internal/interface/main-handler/file-attachment/handler.go index 2ce11505..e391566a 100644 --- a/internal/interface/main-handler/file-attachment/handler.go +++ b/internal/interface/main-handler/file-attachment/handler.go @@ -4,7 +4,6 @@ import ( "net/http" eru "simrs-vx/internal/domain/references/upload" "strconv" - "strings" d "github.com/karincake/dodol" rw "github.com/karincake/risoles" @@ -57,12 +56,13 @@ func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { MimeType: header.Header.Get("Content-Type"), } - errs := validateCreate(dto) - if len(errs) > 0 { + dataFail := validateCreate(dto) + if dataFail != "" { rw.DataResponse(w, nil, d.FieldError{ Code: "data-validation-fail", - Message: strings.Join(errs, "\n"), + Message: dataFail, }) + return } res, err := u.Create(dto) diff --git a/internal/interface/main-handler/file-attachment/validate-request.go b/internal/interface/main-handler/file-attachment/validate-request.go index bdc289c6..c5865597 100644 --- a/internal/interface/main-handler/file-attachment/validate-request.go +++ b/internal/interface/main-handler/file-attachment/validate-request.go @@ -4,17 +4,16 @@ import ( e "simrs-vx/internal/domain/main-entities/file-attachment" ) -func validateCreate(dto e.CreateDto) []string { - var errs []string +func validateCreate(dto e.CreateDto) string { switch { case dto.EntityType_Code == "": - errs = append(errs, "entityType_code is required") + return "entityType_code is required" case dto.Ref_Id == nil: - errs = append(errs, "ref_id is required") + return "ref_id is required" case dto.Type_Code == "": - errs = append(errs, "type_code is required") + return "type_code is required" } - return errs + return "" } diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 56d3088b..db87393e 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -269,7 +269,7 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/adm-employee-hist", admemployeehist.O) hc.RegCrud(r, "/v1/therapy-protocol", therapyprotocol.O) hc.RegCrud(r, "/v1/chemo-protocol", chemoprotocol.O) - hc.RegCrud(r, "POST /upload", fileattachment.O) + hc.RegCrud(r, "/v1/upload", fileattachment.O) /******************** actor ********************/ hc.RegCrud(r, "/v1/person", person.O) diff --git a/internal/use-case/main-use-case/file-attachement/case.go b/internal/use-case/main-use-case/file-attachement/case.go index 131be610..f0cd7a6a 100644 --- a/internal/use-case/main-use-case/file-attachement/case.go +++ b/internal/use-case/main-use-case/file-attachement/case.go @@ -42,8 +42,15 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } - if !eru.IsValidUploadCode(input.EntityType_Code, input.Type_Code) { - return errors.New("invalid upload code") + valid, msg := eru.IsValidUploadCode(input.EntityType_Code, input.Type_Code) + if !valid { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "invalid-code", + Detail: msg, + Raw: errors.New(msg), + } + return pl.SetLogError(&event, input) } input.FilePath, err = uploadAndGenerateFileUrl(input, &event) @@ -238,8 +245,15 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } - if !eru.IsValidUploadCode(input.EntityType_Code, input.Type_Code) { - return errors.New("invalid upload code") + valid, msg := eru.IsValidUploadCode(input.EntityType_Code, input.Type_Code) + if !valid { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "invalid-code", + Detail: msg, + Raw: errors.New(msg), + } + return pl.SetLogError(&event, input) } if data, err = ReadDetailData(rdDto, &event, tx); err != nil { From d6426babaae3b0e96c329edeadfdda98fe598962 Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 11 Nov 2025 15:37:52 +0700 Subject: [PATCH 157/329] update upload employee id --- cmd/main-migration/migrations/atlas.sum | 4 ++-- internal/domain/main-entities/file-attachment/entity.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index c29695a0..ceca9be1 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:l9TShSJKxWO7Ag2+PYB7DcVDd3pz/M2Sm0hpZYpUNBA= +h1:/ysf2SIdpKcuSzvAPNWONxzu08MCf8eE5krteU4Chas= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -108,4 +108,4 @@ h1:l9TShSJKxWO7Ag2+PYB7DcVDd3pz/M2Sm0hpZYpUNBA= 20251110093522.sql h1:nsz8jCxGjEdr/bz9g+4ozfZzIP803xONjVmucad1GMc= 20251110100258.sql h1:IBqt1VZj5WjQ+l9aAFGHOCCBtzb03KlLLihFLut7itg= 20251110100545.sql h1:6/LV7751iyKxE2xI6vO1zly+aHUwxXD/IBwLcVpKxqM= -20251111040358.sql h1:dbHqvkf0FWQVGpmTQAY0bdx6v2cXAxrPSH5byP0r/eU= +20251111040358.sql h1:c/RQSoA8yZl7cAcOv7n1RchmudPj7LdL3PEBdNvCUrA= diff --git a/internal/domain/main-entities/file-attachment/entity.go b/internal/domain/main-entities/file-attachment/entity.go index 8f224ce0..61b63e9e 100644 --- a/internal/domain/main-entities/file-attachment/entity.go +++ b/internal/domain/main-entities/file-attachment/entity.go @@ -14,6 +14,6 @@ type FileAttachment struct { Name string `json:"name"` FilePath *string `json:"filePath"` FileName *string `json:"fileName"` - Upload_Employee_Id *string `json:"upload_employee_id"` + Upload_Employee_Id *uint `json:"upload_employee_id"` Upload_Employee *ee.Employee `json:"upload_employee,omitempty" gorm:"foreignKey:Upload_Employee_Id;references:Id"` } From 9b7be9ca66fa9d492bba1449d908c59f48b5c159 Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 11 Nov 2025 15:58:40 +0700 Subject: [PATCH 158/329] delete fk from encounter --- cmd/main-migration/migrations/20251111085815.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 3 ++- internal/domain/main-entities/encounter/entity.go | 2 -- 3 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 cmd/main-migration/migrations/20251111085815.sql diff --git a/cmd/main-migration/migrations/20251111085815.sql b/cmd/main-migration/migrations/20251111085815.sql new file mode 100644 index 00000000..945c7329 --- /dev/null +++ b/cmd/main-migration/migrations/20251111085815.sql @@ -0,0 +1,2 @@ +-- Modify "FileAttachment" table +ALTER TABLE "public"."FileAttachment" DROP CONSTRAINT "fk_Encounter_FileAttachments"; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index ceca9be1..e1c7602d 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:/ysf2SIdpKcuSzvAPNWONxzu08MCf8eE5krteU4Chas= +h1:bPQtdFQustm+bzfbxrIgoD7sYhMS7+D4qaSmiyN6LUA= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -109,3 +109,4 @@ h1:/ysf2SIdpKcuSzvAPNWONxzu08MCf8eE5krteU4Chas= 20251110100258.sql h1:IBqt1VZj5WjQ+l9aAFGHOCCBtzb03KlLLihFLut7itg= 20251110100545.sql h1:6/LV7751iyKxE2xI6vO1zly+aHUwxXD/IBwLcVpKxqM= 20251111040358.sql h1:c/RQSoA8yZl7cAcOv7n1RchmudPj7LdL3PEBdNvCUrA= +20251111085815.sql h1:zY86Sl4p7yLEHvn9oJTjsK+yo5HfF4LsPa+uRHzsAeU= diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index dc7c2781..c9e9bb95 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -9,7 +9,6 @@ import ( ed "simrs-vx/internal/domain/main-entities/doctor" eem "simrs-vx/internal/domain/main-entities/emergency" ee "simrs-vx/internal/domain/main-entities/employee" - efa "simrs-vx/internal/domain/main-entities/file-attachment" eip "simrs-vx/internal/domain/main-entities/inpatient" ei "simrs-vx/internal/domain/main-entities/insurance-company" eir "simrs-vx/internal/domain/main-entities/internal-reference" @@ -71,7 +70,6 @@ type Encounter struct { Inpatient *eip.Inpatient `json:"inpatient,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Rehab *er.Basic `json:"rehab,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` RehabChildren *[]er.Basic `json:"rehabChildren,omitempty" gorm:"foreignKey:Parent_Encounter_Id;references:Id"` - FileAttachments *[]efa.FileAttachment `json:"fileAttachments,omitempty" gorm:"foreignKey:Ref_Id;references:Id"` } func (d Encounter) IsDone() bool { From 46bbf30c27a4f92bc2786e4870a8523897e51685 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 11 Nov 2025 16:26:11 +0700 Subject: [PATCH 159/329] language, and ethnic use code path --- internal/domain/main-entities/ethnic/dto.go | 11 ++++++----- internal/domain/main-entities/language/dto.go | 15 ++++++++------- .../interface/main-handler/ethnic/handler.go | 18 +++++++++--------- .../interface/main-handler/language/handler.go | 18 +++++++++--------- .../interface/main-handler/main-handler.go | 4 ++-- internal/use-case/main-use-case/ethnic/case.go | 4 ++-- .../use-case/main-use-case/ethnic/helper.go | 2 +- internal/use-case/main-use-case/ethnic/lib.go | 9 ++++++++- .../use-case/main-use-case/language/case.go | 4 ++-- .../use-case/main-use-case/language/helper.go | 2 +- .../use-case/main-use-case/language/lib.go | 12 +++++++++++- 11 files changed, 59 insertions(+), 40 deletions(-) diff --git a/internal/domain/main-entities/ethnic/dto.go b/internal/domain/main-entities/ethnic/dto.go index a8277e27..0d5aec53 100644 --- a/internal/domain/main-entities/ethnic/dto.go +++ b/internal/domain/main-entities/ethnic/dto.go @@ -5,8 +5,8 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=20"` - Name string `json:"name" validate:"maxLength=50"` + Code *string `json:"code" validate:"maxLength=20"` + Name string `json:"name" validate:"maxLength=50"` } type ReadListDto struct { @@ -23,17 +23,18 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` CreateDto } type DeleteDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/domain/main-entities/language/dto.go b/internal/domain/main-entities/language/dto.go index 069fbf50..ce64e6ab 100644 --- a/internal/domain/main-entities/language/dto.go +++ b/internal/domain/main-entities/language/dto.go @@ -5,8 +5,8 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=10"` - Name string `json:"name" validate:"maxLength=50"` + Code *string `json:"code" validate:"maxLength=10"` + Name string `json:"name" validate:"maxLength=50"` } type ReadListDto struct { @@ -23,18 +23,19 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` - Code string `json:"code"` - Name string `json:"name"` + Id *uint16 `json:"id"` + Code *string `json:"code"` + Name *string `json:"name"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/interface/main-handler/ethnic/handler.go b/internal/interface/main-handler/ethnic/handler.go index 8af8bde9..b3b02541 100644 --- a/internal/interface/main-handler/ethnic/handler.go +++ b/internal/interface/main-handler/ethnic/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint(id) + dto.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/language/handler.go b/internal/interface/main-handler/language/handler.go index 0c00bb1e..ca6c7338 100644 --- a/internal/interface/main-handler/language/handler.go +++ b/internal/interface/main-handler/language/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ 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.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 74a5e40a..b2589f86 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -317,7 +317,7 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/medicine-method", medicinemethod.O) hc.RegCrud(r, "/v1/mcu-src-category", mcusrccategory.O) hc.RegCrudByCode(r, "/v1/mcu-src", mcusrc.O) - hc.RegCrud(r, "/v1/ethnic", ethnic.O) + hc.RegCrudByCode(r, "/v1/ethnic", ethnic.O) hc.RegCrud(r, "/v1/insurance-company", insurancecompany.O) hc.RegCrudByCode(r, "/v1/medicine", medicine.O) hc.RegCrudByCode(r, "/v1/device", device.O) @@ -325,7 +325,7 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/doctor-fee", doctorfee.O) hc.RegCrudByCode(r, "/v1/medical-action-src", medicalactionsrc.O) hc.RegCrud(r, "/v1/medical-action-src-item", medicalactionsrcitem.O) - hc.RegCrud(r, "/v1/language", language.O) + hc.RegCrudByCode(r, "/v1/language", language.O) hc.RegCrudByCode(r, "/v1/mcu-sub-src", mcusubsrc.O) hc.RegCrud(r, "/v1/vehicle", vehicle.O) hc.RegCrud(r, "/v1/vehicle-hist", vehiclehist.O) diff --git a/internal/use-case/main-use-case/ethnic/case.go b/internal/use-case/main-use-case/ethnic/case.go index c8ca95a1..f219eb02 100644 --- a/internal/use-case/main-use-case/ethnic/case.go +++ b/internal/use-case/main-use-case/ethnic/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Ethnic var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Ethnic var err error diff --git a/internal/use-case/main-use-case/ethnic/helper.go b/internal/use-case/main-use-case/ethnic/helper.go index e53f707b..783f66ca 100644 --- a/internal/use-case/main-use-case/ethnic/helper.go +++ b/internal/use-case/main-use-case/ethnic/helper.go @@ -17,6 +17,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Ethnic) { inputSrc = &inputTemp.CreateDto } - data.Code = inputSrc.Code + data.Code = *inputSrc.Code data.Name = inputSrc.Name } diff --git a/internal/use-case/main-use-case/ethnic/lib.go b/internal/use-case/main-use-case/ethnic/lib.go index 0bc91e3f..d7cbe0b8 100644 --- a/internal/use-case/main-use-case/ethnic/lib.go +++ b/internal/use-case/main-use-case/ethnic/lib.go @@ -81,7 +81,14 @@ 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 input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).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/language/case.go b/internal/use-case/main-use-case/language/case.go index 885bcfeb..15fccb51 100644 --- a/internal/use-case/main-use-case/language/case.go +++ b/internal/use-case/main-use-case/language/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Language var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Language var err error diff --git a/internal/use-case/main-use-case/language/helper.go b/internal/use-case/main-use-case/language/helper.go index cd7215d4..caa47beb 100644 --- a/internal/use-case/main-use-case/language/helper.go +++ b/internal/use-case/main-use-case/language/helper.go @@ -17,6 +17,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Language) { inputSrc = &inputTemp.CreateDto } - data.Code = inputSrc.Code + data.Code = *inputSrc.Code data.Name = inputSrc.Name } diff --git a/internal/use-case/main-use-case/language/lib.go b/internal/use-case/main-use-case/language/lib.go index 11992794..ac0feccd 100644 --- a/internal/use-case/main-use-case/language/lib.go +++ b/internal/use-case/main-use-case/language/lib.go @@ -81,7 +81,17 @@ 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 input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + if input.Name != nil { + tx = tx.Where("\"Name\" = ?", *input.Name) + } + + if err := tx.First(&data).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { return nil, processedErr } From 896306b06d1686adb5f79b90e54f6c519a06f7d6 Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 11 Nov 2025 16:59:05 +0700 Subject: [PATCH 160/329] upload oke --- internal/use-case/main-use-case/encounter/lib.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index d3cc544e..5eac2db5 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -4,7 +4,6 @@ import ( // std "errors" eir "simrs-vx/internal/domain/main-entities/internal-reference" - // external dg "github.com/karincake/apem/db-gorm-pg" gh "github.com/karincake/getuk" From 62643ab6ce9df886c4016ba16123d930e622e8f6 Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 11 Nov 2025 17:04:52 +0700 Subject: [PATCH 161/329] delete --- .../migrations/20251111040358.sql | 17 ----------------- .../migrations/20251111085815.sql | 2 -- 2 files changed, 19 deletions(-) delete mode 100644 cmd/main-migration/migrations/20251111040358.sql delete mode 100644 cmd/main-migration/migrations/20251111085815.sql diff --git a/cmd/main-migration/migrations/20251111040358.sql b/cmd/main-migration/migrations/20251111040358.sql deleted file mode 100644 index 8de43539..00000000 --- a/cmd/main-migration/migrations/20251111040358.sql +++ /dev/null @@ -1,17 +0,0 @@ --- Create "FileAttachment" table -CREATE TABLE "public"."FileAttachment" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "EntityType_Code" text NULL, - "Ref_Id" bigint NULL, - "Type_Code" text NULL, - "Name" text NULL, - "FilePath" text NULL, - "FileName" text NULL, - "Upload_Employee_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_Encounter_FileAttachments" FOREIGN KEY ("Ref_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT "fk_FileAttachment_Upload_Employee" FOREIGN KEY ("Upload_Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); diff --git a/cmd/main-migration/migrations/20251111085815.sql b/cmd/main-migration/migrations/20251111085815.sql deleted file mode 100644 index 945c7329..00000000 --- a/cmd/main-migration/migrations/20251111085815.sql +++ /dev/null @@ -1,2 +0,0 @@ --- Modify "FileAttachment" table -ALTER TABLE "public"."FileAttachment" DROP CONSTRAINT "fk_Encounter_FileAttachments"; From 34267255b68568ef3a8b52af3940fc7bd7b24b3f Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 11 Nov 2025 17:19:39 +0700 Subject: [PATCH 162/329] update migration --- .../migrations/20251111100633.sql | 16 ++++ cmd/main-migration/migrations/atlas.sum | 79 ++++++++++--------- 2 files changed, 56 insertions(+), 39 deletions(-) create mode 100644 cmd/main-migration/migrations/20251111100633.sql diff --git a/cmd/main-migration/migrations/20251111100633.sql b/cmd/main-migration/migrations/20251111100633.sql new file mode 100644 index 00000000..73d12a54 --- /dev/null +++ b/cmd/main-migration/migrations/20251111100633.sql @@ -0,0 +1,16 @@ +-- Create "FileAttachment" table +CREATE TABLE "public"."FileAttachment" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "EntityType_Code" text NULL, + "Ref_Id" bigint NULL, + "Type_Code" text NULL, + "Name" text NULL, + "FilePath" text NULL, + "FileName" text NULL, + "Upload_Employee_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_FileAttachment_Upload_Employee" FOREIGN KEY ("Upload_Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index fb7ec8eb..3e0a3ad9 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:3V3a/T/te8iQqsolgRAJKr99GePHgSN9miJHUNngJ74= +h1:SAwbbwLaFxoG+YGdeC3/EzQ+sb+CbZ4HEYhp5XOI918= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,41 +75,42 @@ h1:3V3a/T/te8iQqsolgRAJKr99GePHgSN9miJHUNngJ74= 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= -20251111072601.sql h1:6p2qynJ2vr3C18peYciAbOIWOoj/+PnNcobU3wNHboQ= -20251111073546.sql h1:BORlFReAZTDLUfpS/eIf5qGkJ+FNznMGK47HRiPkfL8= -20251111074148.sql h1:qzjLGQRWo1Gg8LkJFgTb5Ak7h53tdz+eQrpJqC9+Gc0= -20251111074652.sql h1:uuThrt4wjdq4qEbvS67fF0Nfw/dlj7vGnLqywWBznqk= -20251111082257.sql h1:eUfu0tDtl9KqX7UK8is6Qc04NSQs4BXwKsykZwnVH1w= +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= +20251111072601.sql h1:dEhwrkT0hJ06/YcvQd5alvdskimcHcYT27QKAzVY5+8= +20251111073546.sql h1:JnJZ4SdOObSe6Jf8v/i/KiRxoCz5KMeXCYytQMZgkZM= +20251111074148.sql h1:95Ui1eo1P68itOz5kZDNFi2ha0ZhUF4gMYiYVcip6fo= +20251111074652.sql h1:vUZbN0qgktRQ2GAlCpdYrbld2grPiSbvcMePEQMfxPs= +20251111082257.sql h1:Zr3Xg5n+p4C8F6Evqm5PVC0pqUvPTBcq692PiUEJlT8= +20251111100633.sql h1:0z4WE0KP18j10gCd7nCltnP6u4NcLNJD5k9vTjq7J50= From 4f07f7f2a44a8cd208dc07a157b3a15599bf1934 Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 11 Nov 2025 18:10:50 +0700 Subject: [PATCH 163/329] adjustment fileattachemnt to encounterDocument --- .../migrations/20251111100633.sql | 16 ---------------- .../migrations/20251111111017.sql | 16 ++++++++++++++++ cmd/main-migration/migrations/atlas.sum | 4 ++-- .../encounter-document/entity.go | 18 ++++++++++++++++++ .../domain/main-entities/encounter/entity.go | 2 ++ .../main-entities/file-attachment/entity.go | 19 ------------------- internal/interface/migration/main-entities.go | 4 ++-- 7 files changed, 40 insertions(+), 39 deletions(-) delete mode 100644 cmd/main-migration/migrations/20251111100633.sql create mode 100644 cmd/main-migration/migrations/20251111111017.sql create mode 100644 internal/domain/main-entities/encounter-document/entity.go delete mode 100644 internal/domain/main-entities/file-attachment/entity.go diff --git a/cmd/main-migration/migrations/20251111100633.sql b/cmd/main-migration/migrations/20251111100633.sql deleted file mode 100644 index 73d12a54..00000000 --- a/cmd/main-migration/migrations/20251111100633.sql +++ /dev/null @@ -1,16 +0,0 @@ --- Create "FileAttachment" table -CREATE TABLE "public"."FileAttachment" ( - "Id" bigserial NOT NULL, - "CreatedAt" timestamptz NULL, - "UpdatedAt" timestamptz NULL, - "DeletedAt" timestamptz NULL, - "EntityType_Code" text NULL, - "Ref_Id" bigint NULL, - "Type_Code" text NULL, - "Name" text NULL, - "FilePath" text NULL, - "FileName" text NULL, - "Upload_Employee_Id" bigint NULL, - PRIMARY KEY ("Id"), - CONSTRAINT "fk_FileAttachment_Upload_Employee" FOREIGN KEY ("Upload_Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION -); diff --git a/cmd/main-migration/migrations/20251111111017.sql b/cmd/main-migration/migrations/20251111111017.sql new file mode 100644 index 00000000..4adcb5ac --- /dev/null +++ b/cmd/main-migration/migrations/20251111111017.sql @@ -0,0 +1,16 @@ +-- Create "EncounterDocument" table +CREATE TABLE "public"."EncounterDocument" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Type_Code" text NULL, + "Name" text NULL, + "FilePath" text NULL, + "FileName" text NULL, + "Upload_Employee_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_EncounterDocument_Upload_Employee" FOREIGN KEY ("Upload_Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Encounter_EncounterDocuments" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 3e0a3ad9..6bdc5512 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:SAwbbwLaFxoG+YGdeC3/EzQ+sb+CbZ4HEYhp5XOI918= +h1:G7XwMRXjqZGaTeOozryI7WRd+FUJqE+DYsSfura7viU= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -113,4 +113,4 @@ h1:SAwbbwLaFxoG+YGdeC3/EzQ+sb+CbZ4HEYhp5XOI918= 20251111074148.sql h1:95Ui1eo1P68itOz5kZDNFi2ha0ZhUF4gMYiYVcip6fo= 20251111074652.sql h1:vUZbN0qgktRQ2GAlCpdYrbld2grPiSbvcMePEQMfxPs= 20251111082257.sql h1:Zr3Xg5n+p4C8F6Evqm5PVC0pqUvPTBcq692PiUEJlT8= -20251111100633.sql h1:0z4WE0KP18j10gCd7nCltnP6u4NcLNJD5k9vTjq7J50= +20251111111017.sql h1:RNLwrUNguAy/m2h3oYwMd5VuL1juRJMS1Taqujvye08= diff --git a/internal/domain/main-entities/encounter-document/entity.go b/internal/domain/main-entities/encounter-document/entity.go new file mode 100644 index 00000000..6c98e1e2 --- /dev/null +++ b/internal/domain/main-entities/encounter-document/entity.go @@ -0,0 +1,18 @@ +package encounter_document + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/employee" + eru "simrs-vx/internal/domain/references/upload" +) + +type EncounterDocument struct { + ecore.Main + Encounter_Id *uint `json:"encounter_id"` + Type_Code eru.UploadCode `json:"type_code"` + Name string `json:"name"` + FilePath *string `json:"filePath"` + FileName *string `json:"fileName"` + Upload_Employee_Id *uint `json:"upload_employee_id"` + Upload_Employee *ee.Employee `json:"upload_employee,omitempty" gorm:"foreignKey:Upload_Employee_Id;references:Id"` +} diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index c9e9bb95..3939f546 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -9,6 +9,7 @@ import ( ed "simrs-vx/internal/domain/main-entities/doctor" eem "simrs-vx/internal/domain/main-entities/emergency" ee "simrs-vx/internal/domain/main-entities/employee" + eed "simrs-vx/internal/domain/main-entities/encounter-document" eip "simrs-vx/internal/domain/main-entities/inpatient" ei "simrs-vx/internal/domain/main-entities/insurance-company" eir "simrs-vx/internal/domain/main-entities/internal-reference" @@ -70,6 +71,7 @@ type Encounter struct { Inpatient *eip.Inpatient `json:"inpatient,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Rehab *er.Basic `json:"rehab,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` RehabChildren *[]er.Basic `json:"rehabChildren,omitempty" gorm:"foreignKey:Parent_Encounter_Id;references:Id"` + EncounterDocuments *[]eed.EncounterDocument `json:"encounterDocuments,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` } func (d Encounter) IsDone() bool { diff --git a/internal/domain/main-entities/file-attachment/entity.go b/internal/domain/main-entities/file-attachment/entity.go deleted file mode 100644 index 61b63e9e..00000000 --- a/internal/domain/main-entities/file-attachment/entity.go +++ /dev/null @@ -1,19 +0,0 @@ -package file_attachment - -import ( - ecore "simrs-vx/internal/domain/base-entities/core" - ee "simrs-vx/internal/domain/main-entities/employee" - eru "simrs-vx/internal/domain/references/upload" -) - -type FileAttachment struct { - ecore.Main - EntityType_Code eru.EntityTypeCode `json:"entityType_code"` - Ref_Id *uint `json:"ref_id"` - Type_Code eru.UploadCode `json:"type_code"` - Name string `json:"name"` - FilePath *string `json:"filePath"` - FileName *string `json:"fileName"` - Upload_Employee_Id *uint `json:"upload_employee_id"` - Upload_Employee *ee.Employee `json:"upload_employee,omitempty" gorm:"foreignKey:Upload_Employee_Id;references:Id"` -} diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index a88ef64f..272cd4ce 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -28,8 +28,8 @@ import ( emergency "simrs-vx/internal/domain/main-entities/emergency" employee "simrs-vx/internal/domain/main-entities/employee" encounter "simrs-vx/internal/domain/main-entities/encounter" + fileattachemnt "simrs-vx/internal/domain/main-entities/encounter-document" ethnic "simrs-vx/internal/domain/main-entities/ethnic" - fileattachemnt "simrs-vx/internal/domain/main-entities/file-attachment" generalconsent "simrs-vx/internal/domain/main-entities/general-consent" infra "simrs-vx/internal/domain/main-entities/infra" inpatient "simrs-vx/internal/domain/main-entities/inpatient" @@ -208,6 +208,6 @@ func getMainEntities() []any { &controlletter.ControlLetter{}, &rehab.Rehab{}, &chemoprotocol.ChemoProtocol{}, - &fileattachemnt.FileAttachment{}, + &fileattachemnt.EncounterDocument{}, } } From a365f2aff615a5b18f41a3ff6a178965757f78bc Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Wed, 12 Nov 2025 07:20:51 +0700 Subject: [PATCH 164/329] feat/sso-auth: adjust role const --- .../references/organization/organization.go | 28 +++++++++---------- .../main-use-case/authentication/helper.go | 12 ++++---- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/internal/domain/references/organization/organization.go b/internal/domain/references/organization/organization.go index 1dfe93ad..09b19dce 100644 --- a/internal/domain/references/organization/organization.go +++ b/internal/domain/references/organization/organization.go @@ -11,21 +11,21 @@ type ( ) const ( - CSCSys ContractPositionCode = "system" // System - CSCEmp ContractPositionCode = "employee" // Pegawai - CSCInt ContractPositionCode = "intern" // PPDS + CSCSys ContractPositionCode = "sys" // System + CSCEmp ContractPositionCode = "emp" // Pegawai + CSCInt ContractPositionCode = "int" // PPDS - EPCReg EmployeePositionCode = "registration" // Admisi/Pendaftaran - EPCNur EmployeePositionCode = "nurse" // Perawat - EPCDoc EmployeePositionCode = "doctor" // Dokter - EPCNut EmployeePositionCode = "nutritionist" // Ahli gizi - EPCMwi EmployeePositionCode = "mid-wife" // Bidan - EPCLab EmployeePositionCode = "laborant" // Laboran - EPCPha EmployeePositionCode = "pharmacy" // Farmasi - EPCPay EmployeePositionCode = "payment" // Pembayaran - EPCHur EmployeePositionCode = "human-resource" // Sumber Daya Manusia - EPCGea EmployeePositionCode = "general-affair" // Bagian Umum - EPCMan EmployeePositionCode = "management" // Manajemen + EPCReg EmployeePositionCode = "reg" // Admisi/Pendaftaran + EPCNur EmployeePositionCode = "nur" // Perawat + EPCDoc EmployeePositionCode = "doc" // Dokter + EPCNut EmployeePositionCode = "nut" // Ahli gizi + EPCMwi EmployeePositionCode = "miw" // Bidan + EPCLab EmployeePositionCode = "lab" // Laboran + EPCPha EmployeePositionCode = "pha" // Farmasi + EPCPay EmployeePositionCode = "pay" // Pembayaran + EPCHur EmployeePositionCode = "hue" // Sumber Daya Manusia + EPCGea EmployeePositionCode = "gea" // Bagian Umum + EPCMan EmployeePositionCode = "man" // Manajemen IPCSpecialist = "specialist-intern" IPCNurse = "nurse-intern" diff --git a/internal/use-case/main-use-case/authentication/helper.go b/internal/use-case/main-use-case/authentication/helper.go index b7ccc660..37afa11b 100644 --- a/internal/use-case/main-use-case/authentication/helper.go +++ b/internal/use-case/main-use-case/authentication/helper.go @@ -70,7 +70,7 @@ func getDivisionPosition(employee_id uint, event *pl.Event) ([]string, error) { if len(data) > 0 { for _, dp := range data { - result = append(result, "div-"+*dp.Division_Code) + result = append(result, "div|"+*dp.Division_Code+"|"+dp.Code) } } @@ -90,7 +90,7 @@ func getInstallationPosition(employeeId uint, event *pl.Event) ([]string, error) if len(data) > 0 { for _, dp := range data { - result = append(result, "inst-"+*dp.Installation_Code+"-"+dp.Code) + result = append(result, "inst|"+*dp.Installation_Code+"|"+dp.Code) } } @@ -108,7 +108,7 @@ func getUnitPosition(employeeId uint, event *pl.Event) ([]string, error) { if len(data) > 0 { for _, dp := range data { - result = append(result, "unit-"+*dp.Unit_Code+"-"+dp.Code) + result = append(result, "unit|"+*dp.Unit_Code+"|"+dp.Code) } } @@ -126,7 +126,7 @@ func getSpecialistPosition(employeeId uint, event *pl.Event) ([]string, error) { if len(data) > 0 { for _, dp := range data { - result = append(result, "spec-"+*dp.Specialist_Code+"-"+dp.Code) + result = append(result, "spec|"+*dp.Specialist_Code+"|"+dp.Code) } } @@ -146,7 +146,7 @@ func getSubspecialistPosition(employeeId uint, event *pl.Event) ([]string, error if len(data) > 0 { for _, dp := range data { - result = append(result, "subspec-"+dp.Subspecialist.Code+"-"+dp.Code) + result = append(result, "subspec|"+dp.Subspecialist.Code+"|"+dp.Code) } } @@ -209,7 +209,7 @@ func populateRoles(user *eu.User, input eu.LoginDto, atClaims jwt.MapClaims, out } atClaims["employee_id"] = employee.Id outputData["employee_id"] = employee.Id - roles = append(roles, "emp-"+string(*employee.Position_Code)) + roles = append(roles, "emp|"+string(*employee.Position_Code)) // employee position if employee.Id > 0 && employee.Position_Code != nil { From 1e61c13eb5a3eb73dcedbd506cfac227936f766b Mon Sep 17 00:00:00 2001 From: vanilia Date: Wed, 12 Nov 2025 09:03:56 +0700 Subject: [PATCH 165/329] revise upload --- .../main-entities/encounter-document/dto.go | 83 ++++++++ .../domain/main-entities/encounter/dto.go | 3 + .../{file-attachment => upload}/dto.go | 46 ++--- .../main-handler/file-attachment/handler.go | 162 --------------- .../interface/main-handler/main-handler.go | 4 +- .../interface/main-handler/upload/handler.go | 125 +++++++----- .../validate-request.go | 4 +- .../case.go | 106 +--------- .../encounter-document/helper.go | 44 +++++ .../lib.go | 22 +-- .../encounter-document/middleware-runner.go | 103 ++++++++++ .../encounter-document/middleware.go | 9 + .../tycovar.go | 23 +-- .../main-use-case/file-attachement/helper.go | 122 ------------ .../use-case/main-use-case/upload/case.go | 90 +++++++++ .../use-case/main-use-case/upload/helper.go | 184 ++++++++++++++++++ .../middleware-runner.go | 15 +- .../middleware.go | 2 +- .../use-case/main-use-case/upload/tycovar.go | 44 +++++ 19 files changed, 697 insertions(+), 494 deletions(-) create mode 100644 internal/domain/main-entities/encounter-document/dto.go rename internal/domain/main-entities/{file-attachment => upload}/dto.go (64%) delete mode 100644 internal/interface/main-handler/file-attachment/handler.go rename internal/interface/main-handler/{file-attachment => upload}/validate-request.go (76%) rename internal/use-case/main-use-case/{file-attachement => encounter-document}/case.go (68%) create mode 100644 internal/use-case/main-use-case/encounter-document/helper.go rename internal/use-case/main-use-case/{file-attachement => encounter-document}/lib.go (83%) create mode 100644 internal/use-case/main-use-case/encounter-document/middleware-runner.go create mode 100644 internal/use-case/main-use-case/encounter-document/middleware.go rename internal/use-case/main-use-case/{file-attachement => encounter-document}/tycovar.go (60%) delete mode 100644 internal/use-case/main-use-case/file-attachement/helper.go create mode 100644 internal/use-case/main-use-case/upload/case.go create mode 100644 internal/use-case/main-use-case/upload/helper.go rename internal/use-case/main-use-case/{file-attachement => upload}/middleware-runner.go (86%) rename internal/use-case/main-use-case/{file-attachement => upload}/middleware.go (89%) create mode 100644 internal/use-case/main-use-case/upload/tycovar.go diff --git a/internal/domain/main-entities/encounter-document/dto.go b/internal/domain/main-entities/encounter-document/dto.go new file mode 100644 index 00000000..c1e0894c --- /dev/null +++ b/internal/domain/main-entities/encounter-document/dto.go @@ -0,0 +1,83 @@ +package encounter_document + +import ( + eru "simrs-vx/internal/domain/references/upload" + // internal - domain - base-entities + ecore "simrs-vx/internal/domain/base-entities/core" + + ee "simrs-vx/internal/domain/main-entities/employee" +) + +type CreateDto struct { + Encounter_Id *uint `json:"encounter_id"` + Type_Code eru.UploadCode `json:"type_code"` + Name string `json:"name"` + FilePath string `json:"filePath"` + Filename string `json:"-"` + Upload_Employee_Id *uint `form:"upload_employee_id"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Encounter_Id *uint `json:"encounter-id"` + Type_Code eru.UploadCode `json:"type-code"` + Upload_Employee_Id *string `json:"encounter-document-employee-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 + Encounter_Id *uint `json:"encounter_id"` + Type_Code eru.UploadCode `json:"type_code"` + Name string `json:"name"` + FilePath *string `json:"filePath"` + FileName *string `json:"fileName"` + Upload_Employee_Id *uint `json:"upload_employee_id"` + Upload_Employee *ee.Employee `json:"upload_employee,omitempty"` +} + +func (d EncounterDocument) ToResponse() ResponseDto { + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Type_Code: d.Type_Code, + Name: d.Name, + FilePath: d.FilePath, + FileName: d.FileName, + Upload_Employee_Id: d.Upload_Employee_Id, + Upload_Employee: d.Upload_Employee, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []EncounterDocument) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index 290a7766..d3f2d04d 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -4,6 +4,7 @@ import ( eam "simrs-vx/internal/domain/main-entities/ambulatory" edc "simrs-vx/internal/domain/main-entities/death-cause" eem "simrs-vx/internal/domain/main-entities/emergency" + eed "simrs-vx/internal/domain/main-entities/encounter-document" eip "simrs-vx/internal/domain/main-entities/inpatient" eir "simrs-vx/internal/domain/main-entities/internal-reference" er "simrs-vx/internal/domain/main-entities/rehab/base" @@ -188,6 +189,7 @@ type ResponseDto struct { Inpatient *eip.Inpatient `json:"inpatient,omitempty"` Rehab *er.Basic `json:"rehab,omitempty"` RehabChildren *[]er.Basic `json:"rehabChildren,omitempty"` + EncounterDocuments *[]eed.EncounterDocument `json:"encounterDocuments,omitempty"` } func (d Encounter) ToResponse() ResponseDto { @@ -234,6 +236,7 @@ func (d Encounter) ToResponse() ResponseDto { Inpatient: d.Inpatient, Rehab: d.Rehab, RehabChildren: d.RehabChildren, + EncounterDocuments: d.EncounterDocuments, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/file-attachment/dto.go b/internal/domain/main-entities/upload/dto.go similarity index 64% rename from internal/domain/main-entities/file-attachment/dto.go rename to internal/domain/main-entities/upload/dto.go index 38941ec1..ca8e101b 100644 --- a/internal/domain/main-entities/file-attachment/dto.go +++ b/internal/domain/main-entities/upload/dto.go @@ -1,12 +1,10 @@ -package file_attachment +package upload import ( "mime/multipart" eru "simrs-vx/internal/domain/references/upload" // internal - domain - base-entities ecore "simrs-vx/internal/domain/base-entities/core" - - ee "simrs-vx/internal/domain/main-entities/employee" ) type CreateDto struct { @@ -19,7 +17,7 @@ type CreateDto struct { File multipart.File `json:"-"` FileHeader *multipart.FileHeader `json:"-"` - Filename string `json:"-"` + Filename string `json:"filename"` Size int64 `json:"-"` MimeType string `json:"-"` } @@ -37,7 +35,7 @@ type FilterDto struct { Name string `json:"name"` FilePath *string `json:"filePath"` FileName *string `json:"fileName"` - Upload_Employee_Id *string `json:"upload-employee-id"` + Upload_Employee_Id *string `json:"encounter-document-employee-id"` } type ReadDetailDto struct { @@ -61,36 +59,30 @@ type MetaDto struct { } type ResponseDto struct { - ecore.Main - EntityType_Code eru.EntityTypeCode `json:"entityType_code"` - Ref_Id *uint `json:"ref_id"` - Type_Code eru.UploadCode `json:"type_code"` - Name string `json:"name"` - FilePath *string `json:"filePath"` - FileName *string `json:"fileName"` - Upload_Employee_Id *uint `json:"upload_employee_id"` - Upload_Employee *ee.Employee `json:"upload_employee,omitempty"` + EntityType_Code eru.EntityTypeCode `json:"entityType_code"` + Ref_Id *uint `json:"ref_id"` + Type_Code eru.UploadCode `json:"type_code"` + Name string `json:"name"` + Upload_Employee_Id *uint `json:"upload_employee_id"` + FilePath string `json:"filePath"` + Filename string `json:"filename"` + FileHeader *multipart.FileHeader `json:"fileHeader"` + Size int64 `json:"size"` + MimeType string `json:"mimeType"` } -func (d FileAttachment) ToResponse() ResponseDto { +func (d CreateDto) ToResponse() ResponseDto { resp := ResponseDto{ EntityType_Code: d.EntityType_Code, Ref_Id: d.Ref_Id, Type_Code: d.Type_Code, Name: d.Name, - FilePath: d.FilePath, - FileName: d.FileName, Upload_Employee_Id: d.Upload_Employee_Id, - Upload_Employee: d.Upload_Employee, - } - resp.Main = d.Main - return resp -} - -func ToResponseList(data []FileAttachment) []ResponseDto { - resp := make([]ResponseDto, len(data)) - for i, u := range data { - resp[i] = u.ToResponse() + FilePath: d.FilePath, + Filename: d.Filename, + FileHeader: d.FileHeader, + Size: d.Size, + MimeType: d.MimeType, } return resp } diff --git a/internal/interface/main-handler/file-attachment/handler.go b/internal/interface/main-handler/file-attachment/handler.go deleted file mode 100644 index 4d64ec8d..00000000 --- a/internal/interface/main-handler/file-attachment/handler.go +++ /dev/null @@ -1,162 +0,0 @@ -package file_attachment - -import ( - "net/http" - eru "simrs-vx/internal/domain/references/upload" - "strconv" - - d "github.com/karincake/dodol" - rw "github.com/karincake/risoles" - sf "github.com/karincake/semprit" - - // ua "github.com/karincake/tumpeng/auth/svc" - - e "simrs-vx/internal/domain/main-entities/file-attachment" - u "simrs-vx/internal/use-case/main-use-case/file-attachement" -) - -type myBase struct{} - -var O myBase - -func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { - err := r.ParseMultipartForm(10 << 20) // 10 MB - if err != nil { - rw.DataResponse(w, nil, err) - return - } - - file, header, err := r.FormFile("content") - if err != nil { - rw.DataResponse(w, nil, err) - return - } - defer file.Close() - - refIDStr := r.FormValue("ref_id") - var refID *uint - if refIDStr != "" { - if id64, err := strconv.ParseUint(refIDStr, 10, 32); err == nil { - id := uint(id64) - refID = &id - } - } - - employeeIdStr := r.FormValue("upload_employee_id") - var employeeId *uint - if employeeIdStr != "" { - if id64, err := strconv.ParseUint(employeeIdStr, 10, 32); err == nil { - id := uint(id64) - employeeId = &id - } - } - - dto := e.CreateDto{ - EntityType_Code: eru.EntityTypeCode(r.FormValue("entityType_code")), - Ref_Id: refID, - Type_Code: eru.UploadCode(r.FormValue("type_code")), - Name: r.FormValue("name"), - Upload_Employee_Id: employeeId, - File: file, - FileHeader: header, - Filename: header.Filename, - Size: header.Size, - MimeType: header.Header.Get("Content-Type"), - } - - dataFail := validateCreate(dto) - if dataFail != "" { - rw.DataResponse(w, nil, d.FieldError{ - Code: "data-validation-fail", - Message: dataFail, - }) - return - } - - res, err := u.Create(dto) - rw.DataResponse(w, res, err) -} - -func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { - dto := e.ReadListDto{} - sf.UrlQueryParam(&dto, *r.URL) - res, err := u.ReadList(dto) - rw.DataResponse(w, res, err) -} - -func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { - return - } - dto := e.ReadDetailDto{} - dto.Id = uint16(id) - res, err := u.ReadDetail(dto) - rw.DataResponse(w, res, err) -} - -func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { - return - } - - err := r.ParseMultipartForm(10 << 20) // 10 MB - if err != nil { - rw.DataResponse(w, nil, err) - return - } - - file, header, err := r.FormFile("content") - if err != nil { - rw.DataResponse(w, nil, err) - return - } - defer file.Close() - - refIDStr := r.FormValue("ref_id") - var refID *uint - if refIDStr != "" { - if id64, err := strconv.ParseUint(refIDStr, 10, 32); err == nil { - id := uint(id64) - refID = &id - } - } - - employeeIdStr := r.FormValue("upload_employee_id") - var employeeId *uint - if employeeIdStr != "" { - if id64, err := strconv.ParseUint(employeeIdStr, 10, 32); err == nil { - id := uint(id64) - employeeId = &id - } - } - - dto := e.CreateDto{ - EntityType_Code: eru.EntityTypeCode(r.FormValue("entityType_code")), - Ref_Id: refID, - Type_Code: eru.UploadCode(r.FormValue("type_code")), - Name: r.FormValue("name"), - Upload_Employee_Id: employeeId, - File: file, - FileHeader: header, - Filename: header.Filename, - Size: header.Size, - MimeType: header.Header.Get("Content-Type"), - } - - res, err := u.Update(e.UpdateDto{Id: uint16(id), CreateDto: 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 = uint16(id) - res, err := u.Delete(dto) - rw.DataResponse(w, res, err) -} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 7706be6c..8e885dc3 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -16,7 +16,6 @@ import ( deviceorder "simrs-vx/internal/interface/main-handler/device-order" deviceorderitem "simrs-vx/internal/interface/main-handler/device-order-item" encounter "simrs-vx/internal/interface/main-handler/encounter" - fileattachment "simrs-vx/internal/interface/main-handler/file-attachment" internalreference "simrs-vx/internal/interface/main-handler/internal-reference" materialorder "simrs-vx/internal/interface/main-handler/material-order" materialorderitem "simrs-vx/internal/interface/main-handler/material-order-item" @@ -34,6 +33,7 @@ import ( responsibledoctorhist "simrs-vx/internal/interface/main-handler/responsible-doctor-hist" sbar "simrs-vx/internal/interface/main-handler/sbar" soapi "simrs-vx/internal/interface/main-handler/soapi" + upload "simrs-vx/internal/interface/main-handler/upload" /******************** actor ********************/ @@ -269,7 +269,7 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/adm-employee-hist", admemployeehist.O) hc.RegCrud(r, "/v1/therapy-protocol", therapyprotocol.O) hc.RegCrud(r, "/v1/chemo-protocol", chemoprotocol.O) - hc.RegCrud(r, "/v1/upload", fileattachment.O) + hc.RegCrud(r, "/v1/upload", upload.O) /******************** actor ********************/ hc.RegCrud(r, "/v1/person", person.O) diff --git a/internal/interface/main-handler/upload/handler.go b/internal/interface/main-handler/upload/handler.go index 0cff949e..9f1f45a0 100644 --- a/internal/interface/main-handler/upload/handler.go +++ b/internal/interface/main-handler/upload/handler.go @@ -1,56 +1,89 @@ package upload -// "net/http" +import ( + "net/http" + "strconv" -// uh "simrs-vx/pkg/upload-helper" + eru "simrs-vx/internal/domain/references/upload" -// uploadHandler handles single file upload requests -// func uploadHandler(w http.ResponseWriter, r *http.Request) { + d "github.com/karincake/dodol" + rw "github.com/karincake/risoles" -// if r.Method == "OPTIONS" { -// w.WriteHeader(http.StatusNoContent) -// return -// } + e "simrs-vx/internal/domain/main-entities/upload" -// if r.Method != "POST" { -// writeJSONResponse(w, http.StatusMethodNotAllowed, uh.UploadResponse{ -// Success: false, -// Message: "Method not allowed. Use POST.", -// }) -// return -// } + u "simrs-vx/internal/use-case/main-use-case/upload" +) -// // Parse multipart form (32MB max memory) -// err := r.ParseMultipartForm(32 << 20) -// if err != nil { -// writeJSONResponse(w, http.StatusBadRequest, uh.UploadResponse{ -// Success: false, -// Message: "Failed to parse multipart form", -// }) -// return -// } +type myBase struct{} -// // Get file from form -// file, header, err := r.FormFile("file") -// if err != nil { -// writeJSONResponse(w, http.StatusBadRequest, uh.UploadResponse{ -// Success: false, -// Message: "No file uploaded or invalid file field name. Use 'file' as field name.", -// }) -// return -// } -// defer file.Close() +var O myBase -// // Upload file -// response, err := service.UploadFile(file, header.Filename, header.Size) -// if err != nil { -// writeJSONResponse(w, http.StatusInternalServerError, *response) -// return -// } +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + err := r.ParseMultipartForm(10 << 20) // 10 MB + if err != nil { + rw.DataResponse(w, nil, err) + return + } -// if response.Success { -// writeJSONResponse(w, http.StatusOK, *response) -// } else { -// writeJSONResponse(w, http.StatusBadRequest, *response) -// } -// } + file, header, err := r.FormFile("content") + if err != nil { + rw.DataResponse(w, nil, err) + return + } + defer file.Close() + + refIDStr := r.FormValue("ref_id") + var refID *uint + if refIDStr != "" { + if id64, err := strconv.ParseUint(refIDStr, 10, 32); err == nil { + id := uint(id64) + refID = &id + } + } + + employeeIdStr := r.FormValue("upload_employee_id") + var employeeId *uint + if employeeIdStr != "" { + if id64, err := strconv.ParseUint(employeeIdStr, 10, 32); err == nil { + id := uint(id64) + employeeId = &id + } + } + + dto := e.CreateDto{ + EntityType_Code: eru.EntityTypeCode(r.FormValue("entityType_code")), + Ref_Id: refID, + Type_Code: eru.UploadCode(r.FormValue("type_code")), + Name: r.FormValue("name"), + Upload_Employee_Id: employeeId, + File: file, + FileHeader: header, + Filename: header.Filename, + Size: header.Size, + MimeType: header.Header.Get("Content-Type"), + } + + dataFail := validateCreate(dto) + if dataFail != "" { + rw.DataResponse(w, nil, d.FieldError{ + Code: "data-validation-fail", + Message: dataFail, + }) + return + } + + res, err := u.Upload(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { +} + +func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { +} diff --git a/internal/interface/main-handler/file-attachment/validate-request.go b/internal/interface/main-handler/upload/validate-request.go similarity index 76% rename from internal/interface/main-handler/file-attachment/validate-request.go rename to internal/interface/main-handler/upload/validate-request.go index c5865597..38ae492c 100644 --- a/internal/interface/main-handler/file-attachment/validate-request.go +++ b/internal/interface/main-handler/upload/validate-request.go @@ -1,7 +1,7 @@ -package file_attachment +package upload import ( - e "simrs-vx/internal/domain/main-entities/file-attachment" + e "simrs-vx/internal/domain/main-entities/upload" ) func validateCreate(dto e.CreateDto) string { diff --git a/internal/use-case/main-use-case/file-attachement/case.go b/internal/use-case/main-use-case/encounter-document/case.go similarity index 68% rename from internal/use-case/main-use-case/file-attachement/case.go rename to internal/use-case/main-use-case/encounter-document/case.go index f0cd7a6a..206b5e1d 100644 --- a/internal/use-case/main-use-case/file-attachement/case.go +++ b/internal/use-case/main-use-case/encounter-document/case.go @@ -1,9 +1,6 @@ -package file_attachment +package encounter_document import ( - "errors" - ep "simrs-vx/internal/domain/main-entities/person" - up "simrs-vx/internal/use-case/main-use-case/person" "strconv" pl "simrs-vx/pkg/logger" @@ -13,16 +10,15 @@ import ( d "github.com/karincake/dodol" "gorm.io/gorm" - ecore "simrs-vx/internal/domain/base-entities/core" eru "simrs-vx/internal/domain/references/upload" - e "simrs-vx/internal/domain/main-entities/file-attachment" + e "simrs-vx/internal/domain/main-entities/encounter-document" ) -const source = "file-attachment" +const source = "encounter-document" func Create(input e.CreateDto) (*d.Data, error) { - data := e.FileAttachment{} + data := e.EncounterDocument{} event := pl.Event{ Feature: "Create", @@ -42,58 +38,12 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } - valid, msg := eru.IsValidUploadCode(input.EntityType_Code, input.Type_Code) - if !valid { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "invalid-code", - Detail: msg, - Raw: errors.New(msg), - } - return pl.SetLogError(&event, input) - } - - input.FilePath, err = uploadAndGenerateFileUrl(input, &event) - if err != nil { - return err - } - - // get uploadData - dataUpload, _, err := ReadListData(e.ReadListDto{ - FilterDto: e.FilterDto{ - EntityType_Code: input.EntityType_Code, - Ref_Id: input.Ref_Id, - Type_Code: input.Type_Code, - }, - Pagination: ecore.Pagination{PageSize: 1}}, &event, tx) - if err != nil { - return err - } - - if len(dataUpload) > 0 { - if err := removeUploadedFile(string(input.EntityType_Code), *dataUpload[0].FilePath, &event); err != nil { - return err - } - } - if resData, err := CreateData(input, &event, tx); err != nil { return err } else { data = *resData } - if input.EntityType_Code == eru.ETCPerson { - // get person - dataPerson, err := up.ReadDetailData(ep.ReadDetailDto{Id: *data.Ref_Id}, &event, tx) - if err != nil { - return err - } - - if err := setPersonAttachment(dataPerson, data, &event, tx); err != nil { - return err - } - } - mwRunner.setMwType(pu.MWTPost) // Run post-middleware if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { @@ -120,8 +70,8 @@ func Create(input e.CreateDto) (*d.Data, error) { } func ReadList(input e.ReadListDto) (*d.Data, error) { - var data *e.FileAttachment - var dataList []e.FileAttachment + var data *e.EncounterDocument + var dataList []e.EncounterDocument var metaList *e.MetaDto var err error @@ -173,7 +123,7 @@ func ReadList(input e.ReadListDto) (*d.Data, error) { } func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { - var data *e.FileAttachment + var data *e.EncounterDocument var err error event := pl.Event{ @@ -221,7 +171,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { func Update(input e.UpdateDto) (*d.Data, error) { rdDto := e.ReadDetailDto{Id: uint16(input.Id)} - var data *e.FileAttachment + var data *e.EncounterDocument var err error event := pl.Event{ @@ -245,46 +195,10 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } - valid, msg := eru.IsValidUploadCode(input.EntityType_Code, input.Type_Code) - if !valid { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "invalid-code", - Detail: msg, - Raw: errors.New(msg), - } - return pl.SetLogError(&event, input) - } - - if data, err = ReadDetailData(rdDto, &event, tx); err != nil { - return err - } - - input.FilePath, err = uploadAndGenerateFileUrl(input.CreateDto, &event) - if err != nil { - return err - } - - if err := removeUploadedFile(string(input.EntityType_Code), *data.FilePath, &event); err != nil { - return err - } - if err = UpdateData(input, data, &event, tx); err != nil { return err } - if input.EntityType_Code == eru.ETCPerson { - // get person - dataPerson, err := up.ReadDetailData(ep.ReadDetailDto{Id: *data.Ref_Id}, &event, tx) - if err != nil { - return err - } - - if err := setPersonAttachment(dataPerson, *data, &event, tx); err != nil { - return err - } - } - pl.SetLogInfo(&event, nil, "complete") mwRunner.setMwType(pu.MWTPost) @@ -313,7 +227,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { func Delete(input e.DeleteDto) (*d.Data, error) { rdDto := e.ReadDetailDto{Id: uint16(input.Id)} - var data *e.FileAttachment + var data *e.EncounterDocument var err error event := pl.Event{ @@ -337,7 +251,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { return err } - if err := removeUploadedFile(string(data.EntityType_Code), *data.FilePath, &event); err != nil { + if err := removeUploadedFile(string(eru.ETCEncounter), *data.FilePath, &event); err != nil { return err } diff --git a/internal/use-case/main-use-case/encounter-document/helper.go b/internal/use-case/main-use-case/encounter-document/helper.go new file mode 100644 index 00000000..2f26f347 --- /dev/null +++ b/internal/use-case/main-use-case/encounter-document/helper.go @@ -0,0 +1,44 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package encounter_document + +import ( + pl "simrs-vx/pkg/logger" + pmh "simrs-vx/pkg/minio-helper" + + e "simrs-vx/internal/domain/main-entities/encounter-document" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.EncounterDocument) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Encounter_Id = inputSrc.Encounter_Id + data.Type_Code = inputSrc.Type_Code + data.Name = inputSrc.Name + data.FilePath = &inputSrc.FilePath + data.FileName = &inputSrc.Filename + data.Upload_Employee_Id = inputSrc.Upload_Employee_Id +} + +func removeUploadedFile(bucket, fileUrl string, event *pl.Event) error { + pl.SetLogInfo(event, nil, "started", "removeUploadedFile") + filename, err := pmh.GetFilename(fileUrl) + if err != nil { + return err + } + + err = pmh.I.RemoveObject(bucket, filename) + if err != nil { + return err + } + pl.SetLogInfo(event, nil, "complete") + return nil +} diff --git a/internal/use-case/main-use-case/file-attachement/lib.go b/internal/use-case/main-use-case/encounter-document/lib.go similarity index 83% rename from internal/use-case/main-use-case/file-attachement/lib.go rename to internal/use-case/main-use-case/encounter-document/lib.go index cd6a7e55..268c6a70 100644 --- a/internal/use-case/main-use-case/file-attachement/lib.go +++ b/internal/use-case/main-use-case/encounter-document/lib.go @@ -1,8 +1,8 @@ -package file_attachment +package encounter_document import ( "errors" - e "simrs-vx/internal/domain/main-entities/file-attachment" + e "simrs-vx/internal/domain/main-entities/encounter-document" plh "simrs-vx/pkg/lib-helper" pl "simrs-vx/pkg/logger" @@ -13,10 +13,10 @@ import ( "gorm.io/gorm" ) -func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.FileAttachment, error) { +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.EncounterDocument, error) { pl.SetLogInfo(event, nil, "started", "DBCreate") - data := e.FileAttachment{} + data := e.EncounterDocument{} setData(&input, &data) var tx *gorm.DB @@ -34,9 +34,9 @@ func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.FileAtt return &data, nil } -func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.FileAttachment, *e.MetaDto, error) { +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.EncounterDocument, *e.MetaDto, error) { pl.SetLogInfo(event, input, "started", "DBReadList") - data := []e.FileAttachment{} + data := []e.EncounterDocument{} pagination := gh.Pagination{} count := int64(0) meta := e.MetaDto{} @@ -49,7 +49,7 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Fi } tx = tx. - Model(&e.FileAttachment{}). + Model(&e.EncounterDocument{}). Scopes(gh.Preload(input.Includes)). Scopes(gh.Filter(input.FilterDto)). Count(&count). @@ -71,9 +71,9 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Fi return data, &meta, nil } -func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.FileAttachment, error) { +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.EncounterDocument, error) { pl.SetLogInfo(event, input, "started", "DBReadDetail") - data := e.FileAttachment{} + data := e.EncounterDocument{} var tx *gorm.DB if len(dbx) > 0 { @@ -92,7 +92,7 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e return &data, nil } -func UpdateData(input e.UpdateDto, data *e.FileAttachment, event *pl.Event, dbx ...*gorm.DB) error { +func UpdateData(input e.UpdateDto, data *e.EncounterDocument, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, data, "started", "DBUpdate") setData(&input, data) @@ -117,7 +117,7 @@ func UpdateData(input e.UpdateDto, data *e.FileAttachment, event *pl.Event, dbx return nil } -func DeleteData(data *e.FileAttachment, event *pl.Event, dbx ...*gorm.DB) error { +func DeleteData(data *e.EncounterDocument, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, data, "started", "DBDelete") var tx *gorm.DB if len(dbx) > 0 { diff --git a/internal/use-case/main-use-case/encounter-document/middleware-runner.go b/internal/use-case/main-use-case/encounter-document/middleware-runner.go new file mode 100644 index 00000000..06121b54 --- /dev/null +++ b/internal/use-case/main-use-case/encounter-document/middleware-runner.go @@ -0,0 +1,103 @@ +package encounter_document + +import ( + e "simrs-vx/internal/domain/main-entities/encounter-document" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.EncounterDocument) 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.EncounterDocument) 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.EncounterDocument) 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.EncounterDocument) 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.EncounterDocument) 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/main-use-case/encounter-document/middleware.go b/internal/use-case/main-use-case/encounter-document/middleware.go new file mode 100644 index 00000000..65fa9e30 --- /dev/null +++ b/internal/use-case/main-use-case/encounter-document/middleware.go @@ -0,0 +1,9 @@ +package encounter_document + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/file-attachement/tycovar.go b/internal/use-case/main-use-case/encounter-document/tycovar.go similarity index 60% rename from internal/use-case/main-use-case/file-attachement/tycovar.go rename to internal/use-case/main-use-case/encounter-document/tycovar.go index 84428b14..2f1e0d19 100644 --- a/internal/use-case/main-use-case/file-attachement/tycovar.go +++ b/internal/use-case/main-use-case/encounter-document/tycovar.go @@ -6,27 +6,27 @@ 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 file_attachment +package encounter_document import ( "gorm.io/gorm" - e "simrs-vx/internal/domain/main-entities/file-attachment" + e "simrs-vx/internal/domain/main-entities/encounter-document" ) type createMw struct { Name string - Func func(input *e.CreateDto, data *e.FileAttachment, tx *gorm.DB) error + Func func(input *e.CreateDto, data *e.EncounterDocument, tx *gorm.DB) error } type readListMw struct { Name string - Func func(input *e.ReadListDto, data *e.FileAttachment, tx *gorm.DB) error + Func func(input *e.ReadListDto, data *e.EncounterDocument, tx *gorm.DB) error } type readDetailMw struct { Name string - Func func(input *e.ReadDetailDto, data *e.FileAttachment, tx *gorm.DB) error + Func func(input *e.ReadDetailDto, data *e.EncounterDocument, tx *gorm.DB) error } type UpdateMw = readDetailMw @@ -42,16 +42,3 @@ var updatePreMw []readDetailMw var updatePostMw []readDetailMw var deletePreMw []readDetailMw var deletePostMw []readDetailMw - -type BPJSResponse struct { - MetaData struct { - Code string `json:"code"` - Message string `json:"message"` - } `json:"metaData"` - Response *struct { - Peserta struct { - NoKartu string `json:"noKartu"` - NIK string `json:"nik"` - } `json:"peserta"` - } `json:"response"` -} diff --git a/internal/use-case/main-use-case/file-attachement/helper.go b/internal/use-case/main-use-case/file-attachement/helper.go deleted file mode 100644 index 365660c9..00000000 --- a/internal/use-case/main-use-case/file-attachement/helper.go +++ /dev/null @@ -1,122 +0,0 @@ -/* -DESCRIPTION: -Any functions that are used internally by the use-case -*/ -package file_attachment - -import ( - "fmt" - "path/filepath" - "strings" - "time" - - pl "simrs-vx/pkg/logger" - pmh "simrs-vx/pkg/minio-helper" - puh "simrs-vx/pkg/upload-helper" - - dg "github.com/karincake/apem/db-gorm-pg" - "gorm.io/gorm" - - eru "simrs-vx/internal/domain/references/upload" - - e "simrs-vx/internal/domain/main-entities/file-attachment" - ep "simrs-vx/internal/domain/main-entities/person" -) - -func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.FileAttachment) { - var inputSrc *e.CreateDto - if inputT, ok := any(input).(*e.CreateDto); ok { - inputSrc = inputT - } else { - inputTemp := any(input).(*e.UpdateDto) - inputSrc = &inputTemp.CreateDto - } - - data.EntityType_Code = inputSrc.EntityType_Code - data.Ref_Id = inputSrc.Ref_Id - data.Type_Code = inputSrc.Type_Code - data.Name = inputSrc.Name - data.FilePath = &inputSrc.FilePath - data.FileName = &inputSrc.Filename - data.Upload_Employee_Id = inputSrc.Upload_Employee_Id -} - -func uploadAndGenerateFileUrl(input e.CreateDto, event *pl.Event) (string, error) { - pl.SetLogInfo(event, input, "started", "uploadAndGenerateFileUrl") - bucket := string(input.EntityType_Code) - ext := strings.ToLower(filepath.Ext(input.Filename)) - - if !puh.IsValidFileType(ext, bucket) { - return "", fmt.Errorf("invalid file type: %s", input.Filename) - } - objectName := fmt.Sprintf("%v/%s-%d%s", *input.Ref_Id, input.Type_Code, time.Now().UnixNano(), ext) - - uploadInput := pmh.UploadReaderInput{ - BucketName: bucket, - Name: objectName, - File: input.File, - Size: input.Size, - ContentType: input.MimeType, - } - - _, err := pmh.I.PutObject(uploadInput) - if err != nil { - return "", err - } - - // Build URL for access - publicUrl := pmh.I.GenerateUrl(bucket, objectName) - - pl.SetLogInfo(event, nil, "complete") - return publicUrl, nil -} - -func removeUploadedFile(bucket, fileUrl string, event *pl.Event) error { - pl.SetLogInfo(event, nil, "started", "removeUploadedFile") - filename, err := pmh.GetFilename(fileUrl) - if err != nil { - return err - } - - err = pmh.I.RemoveObject(bucket, filename) - if err != nil { - return err - } - pl.SetLogInfo(event, nil, "complete") - return nil -} - -func setPersonAttachment(dataPerson *ep.Person, data e.FileAttachment, event *pl.Event, dbx ...*gorm.DB) error { - pl.SetLogInfo(event, dataPerson, "started", "DBUpdate") - - switch data.Type_Code { - case eru.UCPRN: - dataPerson.ResidentIdentityFileUrl = data.FilePath - case eru.UCPDL: - dataPerson.DrivingLicenseFileUrl = data.FilePath - case eru.UCPP: - dataPerson.PassportFileUrl = data.FilePath - case eru.UCPFC: - dataPerson.FamilyIdentityFileUrl = data.FilePath - } - - var tx *gorm.DB - if len(dbx) > 0 { - tx = dbx[0] - } else { - tx = dg.I - } - - if err := tx.Save(&dataPerson).Error; err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-update-fail", - Detail: "Database update failed", - Raw: err, - } - return pl.SetLogError(event, dataPerson) - } - - pl.SetLogInfo(event, nil, "complete") - return nil -} diff --git a/internal/use-case/main-use-case/upload/case.go b/internal/use-case/main-use-case/upload/case.go new file mode 100644 index 00000000..40ff74f6 --- /dev/null +++ b/internal/use-case/main-use-case/upload/case.go @@ -0,0 +1,90 @@ +package upload + +import ( + "errors" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + "gorm.io/gorm" + + eru "simrs-vx/internal/domain/references/upload" + + e "simrs-vx/internal/domain/main-entities/upload" +) + +const source = "upload" + +func Upload(input e.CreateDto) (*d.Data, error) { + event := pl.Event{ + Feature: "Upload", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + var data interface{} + err := dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + + // Run pre-middleware + err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data) + if err != nil { + return err + } + + // validate entityType_Code and Type_Code + valid, msg := eru.IsValidUploadCode(input.EntityType_Code, input.Type_Code) + if !valid { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "invalid-code", + Detail: msg, + Raw: errors.New(msg), + } + return pl.SetLogError(&event, input) + } + + // upload file + input.FilePath, err = uploadAndGenerateFileUrl(input, &event) + if err != nil { + return err + } + + if input.EntityType_Code == eru.ETCEncounter { + data, err = setEncounterDocument(input, &event, tx) + if err != nil { + return err + } + + } else if input.EntityType_Code == eru.ETCPerson { + data, err = setPersonAttachment(input, &event, tx) + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: input.ToResponse(), + }, nil +} diff --git a/internal/use-case/main-use-case/upload/helper.go b/internal/use-case/main-use-case/upload/helper.go new file mode 100644 index 00000000..65edb9eb --- /dev/null +++ b/internal/use-case/main-use-case/upload/helper.go @@ -0,0 +1,184 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package upload + +import ( + "fmt" + "path/filepath" + ecore "simrs-vx/internal/domain/base-entities/core" + eru "simrs-vx/internal/domain/references/upload" + "strings" + "time" + + pl "simrs-vx/pkg/logger" + pmh "simrs-vx/pkg/minio-helper" + puh "simrs-vx/pkg/upload-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + "gorm.io/gorm" + + ee "simrs-vx/internal/domain/main-entities/encounter-document" + ep "simrs-vx/internal/domain/main-entities/person" + e "simrs-vx/internal/domain/main-entities/upload" + + ue "simrs-vx/internal/use-case/main-use-case/encounter-document" + up "simrs-vx/internal/use-case/main-use-case/person" +) + +func uploadAndGenerateFileUrl(input e.CreateDto, event *pl.Event) (string, error) { + pl.SetLogInfo(event, input, "started", "uploadAndGenerateFileUrl") + bucket := string(input.EntityType_Code) + ext := strings.ToLower(filepath.Ext(input.Filename)) + + if !puh.IsValidFileType(ext, bucket) { + return "", fmt.Errorf("invalid file type: %s", input.Filename) + } + objectName := fmt.Sprintf("%v/%s-%d%s", *input.Ref_Id, input.Type_Code, time.Now().UnixNano(), ext) + + uploadInput := pmh.UploadReaderInput{ + BucketName: bucket, + Name: objectName, + File: input.File, + Size: input.Size, + ContentType: input.MimeType, + } + + _, err := pmh.I.PutObject(uploadInput) + if err != nil { + return "", err + } + + // Build URL for access + publicUrl := pmh.I.GenerateUrl(bucket, objectName) + + pl.SetLogInfo(event, nil, "complete") + return publicUrl, nil +} + +func removeUploadedFile(bucket, fileUrl string, refId uint, event *pl.Event) error { + pl.SetLogInfo(event, nil, "started", "removeUploadedFile") + filename, err := pmh.GetFilename(fileUrl) + if err != nil { + return err + } + + filePath := fmt.Sprintf("%v/%s", refId, filename) + err = pmh.I.RemoveObject(bucket, filePath) + if err != nil { + return err + } + pl.SetLogInfo(event, nil, "complete") + return nil +} + +func updatePersonAttachment(dataPerson *ep.Person, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, dataPerson, "started", "DBUpdate") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.Save(&dataPerson).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-update-fail", + Detail: "Database update failed", + Raw: err, + } + return pl.SetLogError(event, dataPerson) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} + +func setPersonAttachment(input e.CreateDto, event *pl.Event, tx *gorm.DB) (*ep.Person, error) { + // get person + dataPerson, err := up.ReadDetailData(ep.ReadDetailDto{Id: *input.Ref_Id}, event, tx) + if err != nil { + return nil, err + } + + var removeUrl string + switch input.Type_Code { + case eru.UCPRN: + removeUrl = *dataPerson.ResidentIdentityFileUrl + dataPerson.ResidentIdentityFileUrl = &input.FilePath + case eru.UCPDL: + removeUrl = *dataPerson.DrivingLicenseFileUrl + dataPerson.DrivingLicenseFileUrl = &input.FilePath + case eru.UCPP: + removeUrl = *dataPerson.PassportFileUrl + dataPerson.PassportFileUrl = &input.FilePath + case eru.UCPFC: + removeUrl = *dataPerson.FamilyIdentityFileUrl + dataPerson.FamilyIdentityFileUrl = &input.FilePath + } + + if removeUrl != "" { + if err := removeUploadedFile(string(input.EntityType_Code), removeUrl, *input.Ref_Id, event); err != nil { + return nil, err + } + } + + if err = updatePersonAttachment(dataPerson, event, tx); err != nil { + return nil, err + } + + return dataPerson, nil +} + +func setEncounterDocument(input e.CreateDto, event *pl.Event, tx *gorm.DB) (*ee.EncounterDocument, error) { + data := ee.EncounterDocument{} + + // get EncounterDocument + dataUpload, _, err := ue.ReadListData(ee.ReadListDto{ + FilterDto: ee.FilterDto{ + Encounter_Id: input.Ref_Id, + Type_Code: input.Type_Code}, + Pagination: ecore.Pagination{PageSize: 1}}, event, tx) + if err != nil { + return nil, err + } + + // set data + createDto := ee.CreateDto{ + Encounter_Id: input.Ref_Id, + Type_Code: input.Type_Code, + Name: input.Name, + FilePath: input.FilePath, + Filename: input.Filename, + Upload_Employee_Id: input.Upload_Employee_Id, + } + + if len(dataUpload) > 0 { + if err := removeUploadedFile(string(input.EntityType_Code), *dataUpload[0].FilePath, *dataUpload[0].Encounter_Id, event); err != nil { + return nil, err + } + + // update data + err = ue.UpdateData(ee.UpdateDto{ + Id: uint16(dataUpload[0].Id), + CreateDto: createDto}, &dataUpload[0], event, tx) + if err != nil { + return nil, err + } + + data = dataUpload[0] + data.FilePath = &input.FilePath + } else { + // insert data + resData, err := ue.CreateData(createDto, event, tx) + if err != nil { + return nil, err + } + data = *resData + } + + return &data, nil +} diff --git a/internal/use-case/main-use-case/file-attachement/middleware-runner.go b/internal/use-case/main-use-case/upload/middleware-runner.go similarity index 86% rename from internal/use-case/main-use-case/file-attachement/middleware-runner.go rename to internal/use-case/main-use-case/upload/middleware-runner.go index a8926620..88e3e637 100644 --- a/internal/use-case/main-use-case/file-attachement/middleware-runner.go +++ b/internal/use-case/main-use-case/upload/middleware-runner.go @@ -1,11 +1,12 @@ -package file_attachment +package upload import ( - e "simrs-vx/internal/domain/main-entities/file-attachment" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/upload" ) type middlewareRunner struct { @@ -23,7 +24,7 @@ func newMiddlewareRunner(event *pl.Event, tx *gorm.DB) *middlewareRunner { } // ExecuteCreateMiddleware executes create middleware -func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.FileAttachment) error { +func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto, data interface{}) error { for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -38,7 +39,7 @@ func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e return nil } -func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.FileAttachment) error { +func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data interface{}) error { for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -53,7 +54,7 @@ func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, inpu return nil } -func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.FileAttachment) error { +func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data interface{}) error { for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -68,7 +69,7 @@ func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, return nil } -func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.FileAttachment) error { +func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data interface{}) error { for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -83,7 +84,7 @@ func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, inpu return nil } -func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.FileAttachment) error { +func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data interface{}) error { for _, middleware := range middlewares { logData := pu.GetLogData(input, data) diff --git a/internal/use-case/main-use-case/file-attachement/middleware.go b/internal/use-case/main-use-case/upload/middleware.go similarity index 89% rename from internal/use-case/main-use-case/file-attachement/middleware.go rename to internal/use-case/main-use-case/upload/middleware.go index 4f9e1fe5..63beb606 100644 --- a/internal/use-case/main-use-case/file-attachement/middleware.go +++ b/internal/use-case/main-use-case/upload/middleware.go @@ -1,4 +1,4 @@ -package file_attachment +package upload // example of middleware // func init() { diff --git a/internal/use-case/main-use-case/upload/tycovar.go b/internal/use-case/main-use-case/upload/tycovar.go new file mode 100644 index 00000000..4849e215 --- /dev/null +++ b/internal/use-case/main-use-case/upload/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 upload + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/upload" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data interface{}, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data interface{}, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data interface{}, 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 From e968c13b1daaef6389f3eb62db642dcbeb3d1272 Mon Sep 17 00:00:00 2001 From: vanilia Date: Wed, 12 Nov 2025 10:12:44 +0700 Subject: [PATCH 166/329] oke --- cmd/main-migration/migrations/atlas.sum | 78 +++++++++++++------------ 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index fb7ec8eb..f59b4131 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,5 @@ h1:3V3a/T/te8iQqsolgRAJKr99GePHgSN9miJHUNngJ74= +h1:IAvX8SEd9TnVqJ7EYac7IGQ2CGS+5RhltXZ10G5+w7s= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,41 +76,42 @@ h1:3V3a/T/te8iQqsolgRAJKr99GePHgSN9miJHUNngJ74= 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= -20251111072601.sql h1:6p2qynJ2vr3C18peYciAbOIWOoj/+PnNcobU3wNHboQ= -20251111073546.sql h1:BORlFReAZTDLUfpS/eIf5qGkJ+FNznMGK47HRiPkfL8= -20251111074148.sql h1:qzjLGQRWo1Gg8LkJFgTb5Ak7h53tdz+eQrpJqC9+Gc0= -20251111074652.sql h1:uuThrt4wjdq4qEbvS67fF0Nfw/dlj7vGnLqywWBznqk= -20251111082257.sql h1:eUfu0tDtl9KqX7UK8is6Qc04NSQs4BXwKsykZwnVH1w= +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= +20251111072601.sql h1:dEhwrkT0hJ06/YcvQd5alvdskimcHcYT27QKAzVY5+8= +20251111073546.sql h1:JnJZ4SdOObSe6Jf8v/i/KiRxoCz5KMeXCYytQMZgkZM= +20251111074148.sql h1:95Ui1eo1P68itOz5kZDNFi2ha0ZhUF4gMYiYVcip6fo= +20251111074652.sql h1:vUZbN0qgktRQ2GAlCpdYrbld2grPiSbvcMePEQMfxPs= +20251111082257.sql h1:Zr3Xg5n+p4C8F6Evqm5PVC0pqUvPTBcq692PiUEJlT8= +20251111111017.sql h1:8Kr6FFtkSeaenB/n/aKlOaz/K33SqazxMuH26oI0JI4= From 78f1502930180b2bdd25c40f9bf46a1af0e96654 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Wed, 12 Nov 2025 12:07:22 +0700 Subject: [PATCH 167/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 80 ++++++++++++------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 6bdc5512..36eff156 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:G7XwMRXjqZGaTeOozryI7WRd+FUJqE+DYsSfura7viU= +h1:gxzRzsKXNeg9LaO7Hak8tLYmALxv5wumfuA+BSfFD3E= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,42 +75,42 @@ h1:G7XwMRXjqZGaTeOozryI7WRd+FUJqE+DYsSfura7viU= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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= -20251111072601.sql h1:dEhwrkT0hJ06/YcvQd5alvdskimcHcYT27QKAzVY5+8= -20251111073546.sql h1:JnJZ4SdOObSe6Jf8v/i/KiRxoCz5KMeXCYytQMZgkZM= -20251111074148.sql h1:95Ui1eo1P68itOz5kZDNFi2ha0ZhUF4gMYiYVcip6fo= -20251111074652.sql h1:vUZbN0qgktRQ2GAlCpdYrbld2grPiSbvcMePEQMfxPs= -20251111082257.sql h1:Zr3Xg5n+p4C8F6Evqm5PVC0pqUvPTBcq692PiUEJlT8= -20251111111017.sql h1:RNLwrUNguAy/m2h3oYwMd5VuL1juRJMS1Taqujvye08= +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= +20251111072601.sql h1:6p2qynJ2vr3C18peYciAbOIWOoj/+PnNcobU3wNHboQ= +20251111073546.sql h1:BORlFReAZTDLUfpS/eIf5qGkJ+FNznMGK47HRiPkfL8= +20251111074148.sql h1:qzjLGQRWo1Gg8LkJFgTb5Ak7h53tdz+eQrpJqC9+Gc0= +20251111074652.sql h1:uuThrt4wjdq4qEbvS67fF0Nfw/dlj7vGnLqywWBznqk= +20251111082257.sql h1:eUfu0tDtl9KqX7UK8is6Qc04NSQs4BXwKsykZwnVH1w= +20251111111017.sql h1:UGUI29WXoDdEp4jWtbzrFGhfO8XO50IafBE7cMfo70k= From ccc341be3471a8bb5b8704fd6b264383f3f95a65 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Wed, 12 Nov 2025 16:57:52 +0700 Subject: [PATCH 168/329] refactor several data source tables from id into code --- .../domain/main-entities/diagnose-src/dto.go | 13 ++++---- internal/domain/main-entities/district/dto.go | 13 ++++---- .../main-entities/insurance-company/dto.go | 9 +++--- .../main-entities/mcu-src-category/dto.go | 9 +++--- .../main-entities/medicine-group/dto.go | 11 +++---- .../main-entities/medicine-method/dto.go | 11 +++---- .../domain/main-entities/nutritionist/dto.go | 7 +++-- .../domain/main-entities/pharmacist/dto.go | 7 +++-- .../main-entities/pharmacy-company/dto.go | 13 ++++---- .../domain/main-entities/postal-region/dto.go | 11 +++---- .../domain/main-entities/procedure-src/dto.go | 13 ++++---- internal/domain/main-entities/province/dto.go | 11 +++---- internal/domain/main-entities/regency/dto.go | 13 ++++---- internal/domain/main-entities/uom/dto.go | 11 +++---- internal/domain/main-entities/village/dto.go | 13 ++++---- .../main-handler/diagnose-src/handler.go | 18 +++++------ .../main-handler/district/handler.go | 18 +++++------ .../main-handler/insurance-company/handler.go | 18 +++++------ .../interface/main-handler/main-handler.go | 30 +++++++++---------- .../main-handler/mcu-src-category/handler.go | 18 +++++------ .../main-handler/medicine-group/handler.go | 18 +++++------ .../main-handler/medicine-method/handler.go | 18 +++++------ .../main-handler/nutritionist/handler.go | 18 +++++------ .../main-handler/pharmacist/handler.go | 18 +++++------ .../main-handler/pharmacy-company/handler.go | 18 +++++------ .../main-handler/postal-region/handler.go | 18 +++++------ .../main-handler/procedure-src/handler.go | 18 +++++------ .../main-handler/province/handler.go | 18 +++++------ .../interface/main-handler/regency/handler.go | 18 +++++------ .../interface/main-handler/uom/handler.go | 18 +++++------ .../interface/main-handler/village/handler.go | 18 +++++------ .../main-use-case/diagnose-src/case.go | 4 +-- .../main-use-case/diagnose-src/helper.go | 2 +- .../main-use-case/diagnose-src/lib.go | 9 +++++- .../use-case/main-use-case/district/case.go | 4 +-- .../use-case/main-use-case/district/helper.go | 2 +- .../use-case/main-use-case/district/lib.go | 9 +++++- .../main-use-case/insurance-company/case.go | 4 +-- .../main-use-case/insurance-company/helper.go | 2 +- .../main-use-case/insurance-company/lib.go | 9 +++++- .../main-use-case/mcu-src-category/case.go | 4 +-- .../main-use-case/mcu-src-category/helper.go | 2 +- .../main-use-case/mcu-src-category/lib.go | 9 +++++- .../main-use-case/medicine-group/case.go | 4 +-- .../main-use-case/medicine-group/helper.go | 2 +- .../main-use-case/medicine-group/lib.go | 9 +++++- .../main-use-case/medicine-method/case.go | 4 +-- .../main-use-case/medicine-method/helper.go | 2 +- .../main-use-case/medicine-method/lib.go | 9 +++++- .../main-use-case/nutritionist/case.go | 4 +-- .../main-use-case/nutritionist/lib.go | 2 +- .../use-case/main-use-case/pharmacist/case.go | 4 +-- .../use-case/main-use-case/pharmacist/lib.go | 2 +- .../main-use-case/pharmacy-company/case.go | 4 +-- .../main-use-case/pharmacy-company/helper.go | 2 +- .../main-use-case/pharmacy-company/lib.go | 9 +++++- .../main-use-case/postal-region/case.go | 4 +-- .../main-use-case/postal-region/helper.go | 2 +- .../main-use-case/postal-region/lib.go | 9 +++++- .../main-use-case/procedure-src/case.go | 4 +-- .../main-use-case/procedure-src/helper.go | 2 +- .../main-use-case/procedure-src/lib.go | 9 +++++- .../use-case/main-use-case/province/case.go | 4 +-- .../use-case/main-use-case/province/helper.go | 2 +- .../use-case/main-use-case/province/lib.go | 9 +++++- .../use-case/main-use-case/regency/helper.go | 2 +- .../use-case/main-use-case/regency/lib.go | 9 +++++- internal/use-case/main-use-case/uom/case.go | 4 +-- internal/use-case/main-use-case/uom/helper.go | 2 +- internal/use-case/main-use-case/uom/lib.go | 10 ++++++- .../use-case/main-use-case/village/case.go | 4 +-- .../use-case/main-use-case/village/helper.go | 2 +- .../use-case/main-use-case/village/lib.go | 9 +++++- 73 files changed, 388 insertions(+), 281 deletions(-) diff --git a/internal/domain/main-entities/diagnose-src/dto.go b/internal/domain/main-entities/diagnose-src/dto.go index 6266484a..695fd9f5 100644 --- a/internal/domain/main-entities/diagnose-src/dto.go +++ b/internal/domain/main-entities/diagnose-src/dto.go @@ -5,9 +5,9 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=10"` - Name string `json:"name" validate:"maxLength=2048"` - IndName string `json:"indName" validate:"maxLength=2048"` + Code *string `json:"code" validate:"maxLength=10"` + Name string `json:"name" validate:"maxLength=2048"` + IndName string `json:"indName" validate:"maxLength=2048"` } type ReadListDto struct { @@ -25,17 +25,18 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/domain/main-entities/district/dto.go b/internal/domain/main-entities/district/dto.go index ae818d45..acba34de 100644 --- a/internal/domain/main-entities/district/dto.go +++ b/internal/domain/main-entities/district/dto.go @@ -8,9 +8,9 @@ import ( ) type CreateDto struct { - Regency_Code string `json:"regency_code" validate:"numeric;maxLength=4"` - Code string `json:"code" validate:"numeric;maxLength=6"` - Name string `json:"name" validate:"alphaSpace;maxLength=50"` + Regency_Code string `json:"regency_code" validate:"numeric;maxLength=4"` + Code *string `json:"code" validate:"numeric;maxLength=6"` + Name string `json:"name" validate:"alphaSpace;maxLength=50"` } type ReadListDto struct { @@ -28,17 +28,18 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint32 `json:"id"` + Id *uint32 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint32 `json:"id"` + Id *uint32 `json:"id"` CreateDto } type DeleteDto struct { - Id uint32 `json:"id"` + Id *uint32 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/domain/main-entities/insurance-company/dto.go b/internal/domain/main-entities/insurance-company/dto.go index e4104bf7..b3451ea8 100644 --- a/internal/domain/main-entities/insurance-company/dto.go +++ b/internal/domain/main-entities/insurance-company/dto.go @@ -6,7 +6,7 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=20"` + Code *string `json:"code" validate:"maxLength=20"` Name string `json:"name" validate:"maxLength=50"` Regency_Code *string `json:"regency_code" validate:"maxLength=4"` Address string `json:"address" validate:"maxLength=100"` @@ -30,18 +30,19 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` PhoneNumber *string `json:"phoneNumber"` } type UpdateDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` CreateDto } type DeleteDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/domain/main-entities/mcu-src-category/dto.go b/internal/domain/main-entities/mcu-src-category/dto.go index c1988790..f9bb7d00 100644 --- a/internal/domain/main-entities/mcu-src-category/dto.go +++ b/internal/domain/main-entities/mcu-src-category/dto.go @@ -7,7 +7,7 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=20"` + Code *string `json:"code" validate:"maxLength=20"` Name string `json:"name" validate:"maxLength=50"` Scope_Code erc.McuScopeCode `json:"scope_code" validate:"maxLength=10"` } @@ -27,17 +27,18 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/domain/main-entities/medicine-group/dto.go b/internal/domain/main-entities/medicine-group/dto.go index 1f71debe..d131379e 100644 --- a/internal/domain/main-entities/medicine-group/dto.go +++ b/internal/domain/main-entities/medicine-group/dto.go @@ -5,8 +5,8 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=10"` - Name string `json:"name" validate:"maxLength=50"` + Code *string `json:"code" validate:"maxLength=10"` + Name string `json:"name" validate:"maxLength=50"` } type ReadListDto struct { @@ -23,17 +23,18 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` CreateDto } type DeleteDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/domain/main-entities/medicine-method/dto.go b/internal/domain/main-entities/medicine-method/dto.go index 4840fd27..44b04b8c 100644 --- a/internal/domain/main-entities/medicine-method/dto.go +++ b/internal/domain/main-entities/medicine-method/dto.go @@ -5,8 +5,8 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=10"` - Name string `json:"name" validate:"maxLength=50"` + Code *string `json:"code" validate:"maxLength=10"` + Name string `json:"name" validate:"maxLength=50"` } type ReadListDto struct { @@ -23,17 +23,18 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/domain/main-entities/nutritionist/dto.go b/internal/domain/main-entities/nutritionist/dto.go index 832d6873..26a9ccad 100644 --- a/internal/domain/main-entities/nutritionist/dto.go +++ b/internal/domain/main-entities/nutritionist/dto.go @@ -24,19 +24,20 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` Employee_Id *uint `json:"employee_id"` IHS_Number *string `json:"ihs_number"` } type UpdateDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` CreateDto } type DeleteDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/domain/main-entities/pharmacist/dto.go b/internal/domain/main-entities/pharmacist/dto.go index ded53ac8..7962ccb5 100644 --- a/internal/domain/main-entities/pharmacist/dto.go +++ b/internal/domain/main-entities/pharmacist/dto.go @@ -24,19 +24,20 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` Employee_Id *uint `json:"employee_id"` IHS_Number *string `json:"ihs_number"` } type UpdateDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` CreateDto } type DeleteDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/domain/main-entities/pharmacy-company/dto.go b/internal/domain/main-entities/pharmacy-company/dto.go index 2bb7e1ac..437c0ef6 100644 --- a/internal/domain/main-entities/pharmacy-company/dto.go +++ b/internal/domain/main-entities/pharmacy-company/dto.go @@ -5,9 +5,9 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=20"` - Name string `json:"name" validate:"maxLength=100"` - Regency_Code string `json:"regency_code" validate:"maxLength=4"` + Code *string `json:"code" validate:"maxLength=20"` + Name string `json:"name" validate:"maxLength=100"` + Regency_Code string `json:"regency_code" validate:"maxLength=4"` } type ReadListDto struct { @@ -25,17 +25,18 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/domain/main-entities/postal-region/dto.go b/internal/domain/main-entities/postal-region/dto.go index bc3a0fdc..d33d211a 100644 --- a/internal/domain/main-entities/postal-region/dto.go +++ b/internal/domain/main-entities/postal-region/dto.go @@ -6,8 +6,8 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"numeric;maxLength=5"` - Village_Code string `json:"village_code" validate:"numeric;maxLength=10"` + Code *string `json:"code" validate:"numeric;maxLength=5"` + Village_Code string `json:"village_code" validate:"numeric;maxLength=10"` } type ReadListDto struct { @@ -24,17 +24,18 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint32 `json:"id"` + Id *uint32 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint32 `json:"id"` + Id *uint32 `json:"id"` CreateDto } type DeleteDto struct { - Id uint32 `json:"id"` + Id *uint32 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/domain/main-entities/procedure-src/dto.go b/internal/domain/main-entities/procedure-src/dto.go index 477a9885..9881a4e1 100644 --- a/internal/domain/main-entities/procedure-src/dto.go +++ b/internal/domain/main-entities/procedure-src/dto.go @@ -5,9 +5,9 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=10"` - Name string `json:"name" validate:"maxLength=2048"` - IndName string `json:"indName" validate:"maxLength=2048"` + Code *string `json:"code" validate:"maxLength=10"` + Name string `json:"name" validate:"maxLength=2048"` + IndName string `json:"indName" validate:"maxLength=2048"` } type ReadListDto struct { @@ -25,17 +25,18 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/domain/main-entities/province/dto.go b/internal/domain/main-entities/province/dto.go index a7cc5a70..0b7dbc65 100644 --- a/internal/domain/main-entities/province/dto.go +++ b/internal/domain/main-entities/province/dto.go @@ -6,8 +6,8 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"required;minLength=2;maxLength=2"` - Name string `json:"name" validate:"required;maxLength=10"` + Code *string `json:"code" validate:"required;minLength=2;maxLength=2"` + Name string `json:"name" validate:"required;maxLength=10"` } type ReadListDto struct { @@ -24,17 +24,18 @@ type FilterDto struct { } type ReadDetailDto struct { - Id int16 `json:"id"` + Id *int16 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id int16 `json:"id"` + Id *int16 `json:"id"` CreateDto } type DeleteDto struct { - Id int16 `json:"id"` + Id *int16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/domain/main-entities/regency/dto.go b/internal/domain/main-entities/regency/dto.go index 40682f43..3663518c 100644 --- a/internal/domain/main-entities/regency/dto.go +++ b/internal/domain/main-entities/regency/dto.go @@ -8,9 +8,9 @@ import ( ) type CreateDto struct { - Province_Code string `json:"province_code" validate:"numeric;maxLength=2"` - Code string `json:"code" validate:"numeric;maxLength=4"` - Name string `json:"name" validate:"alphaSpace;maxLength=50"` + Province_Code string `json:"province_code" validate:"numeric;maxLength=2"` + Code *string `json:"code" validate:"numeric;maxLength=4"` + Name string `json:"name" validate:"alphaSpace;maxLength=50"` } type ReadListDto struct { @@ -28,17 +28,18 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/domain/main-entities/uom/dto.go b/internal/domain/main-entities/uom/dto.go index 4feb5746..b6997d67 100644 --- a/internal/domain/main-entities/uom/dto.go +++ b/internal/domain/main-entities/uom/dto.go @@ -5,8 +5,8 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=10"` - Name string `json:"name" validate:"maxLength=50"` + Code *string `json:"code" validate:"maxLength=10"` + Name string `json:"name" validate:"maxLength=50"` } type ReadListDto struct { @@ -23,17 +23,18 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id *uint16 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/domain/main-entities/village/dto.go b/internal/domain/main-entities/village/dto.go index bfa8cfc3..f3f400f0 100644 --- a/internal/domain/main-entities/village/dto.go +++ b/internal/domain/main-entities/village/dto.go @@ -8,9 +8,9 @@ import ( ) type CreateDto struct { - District_Code string `json:"district_code" validate:"numeric;maxLength=6"` - Code string `json:"code" validate:"numeric;maxLength=10"` - Name string `json:"name" validate:"alphaSpace;maxLength=50"` + District_Code string `json:"district_code" validate:"numeric;maxLength=6"` + Code *string `json:"code" validate:"numeric;maxLength=10"` + Name string `json:"name" validate:"alphaSpace;maxLength=50"` } type ReadListDto struct { @@ -28,17 +28,18 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint32 `json:"id"` + Id *uint32 `json:"id"` Code *string `json:"code"` } type UpdateDto struct { - Id uint32 `json:"id"` + Id *uint32 `json:"id"` CreateDto } type DeleteDto struct { - Id uint32 `json:"id"` + Id *uint32 `json:"id"` + Code *string `json:"code"` } type MetaDto struct { diff --git a/internal/interface/main-handler/diagnose-src/handler.go b/internal/interface/main-handler/diagnose-src/handler.go index 6c2e9faf..7e62109d 100644 --- a/internal/interface/main-handler/diagnose-src/handler.go +++ b/internal/interface/main-handler/diagnose-src/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ 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.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/district/handler.go b/internal/interface/main-handler/district/handler.go index bdba5d96..a3d59606 100644 --- a/internal/interface/main-handler/district/handler.go +++ b/internal/interface/main-handler/district/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint32(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint32(id) + dto.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint32(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/insurance-company/handler.go b/internal/interface/main-handler/insurance-company/handler.go index 009c93ab..7aed0eb0 100644 --- a/internal/interface/main-handler/insurance-company/handler.go +++ b/internal/interface/main-handler/insurance-company/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint(id) + dto.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 8e885dc3..04bef359 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -279,8 +279,8 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/employee", employee.O) hc.RegCrudByCode(r, "/v1/doctor", doctor.O) hc.RegCrudByCode(r, "/v1/nurse", nurse.O) - hc.RegCrud(r, "/v1/nutritionist", nutritionist.O) - hc.RegCrud(r, "/v1/pharmacist", pharmacist.O) + hc.RegCrudByCode(r, "/v1/nutritionist", nutritionist.O) + hc.RegCrudByCode(r, "/v1/pharmacist", pharmacist.O) hk.GroupRoutes("/v1/user", r, hk.MapHandlerFunc{ "GET /": user.O.GetList, "GET /{id}": user.O.GetDetail, @@ -314,18 +314,18 @@ func SetRoutes() http.Handler { hc.RegCrudByCode(r, "/v1/specialist-position", specialistposition.O) hc.RegCrudByCode(r, "/v1/subspecialist-position", subspecialistposition.O) hc.RegCrudByCode(r, "/v1/infra", infra.O) - hc.RegCrud(r, "/v1/pharmacy-company", pharmacycompany.O) - hc.RegCrud(r, "/v1/diagnose-src", diagnosesrc.O) - hc.RegCrud(r, "/v1/procedure-src", proceduresrc.O) - hc.RegCrud(r, "/v1/uom", uom.O) + hc.RegCrudByCode(r, "/v1/pharmacy-company", pharmacycompany.O) + hc.RegCrudByCode(r, "/v1/diagnose-src", diagnosesrc.O) + hc.RegCrudByCode(r, "/v1/procedure-src", proceduresrc.O) + hc.RegCrudByCode(r, "/v1/uom", uom.O) hc.RegCrudByCode(r, "/v1/item", item.O) hc.RegCrud(r, "/v1/item-price", itemprice.O) - hc.RegCrud(r, "/v1/medicine-group", medicinegroup.O) - hc.RegCrud(r, "/v1/medicine-method", medicinemethod.O) - hc.RegCrud(r, "/v1/mcu-src-category", mcusrccategory.O) + hc.RegCrudByCode(r, "/v1/medicine-group", medicinegroup.O) + hc.RegCrudByCode(r, "/v1/medicine-method", medicinemethod.O) + hc.RegCrudByCode(r, "/v1/mcu-src-category", mcusrccategory.O) hc.RegCrudByCode(r, "/v1/mcu-src", mcusrc.O) hc.RegCrudByCode(r, "/v1/ethnic", ethnic.O) - hc.RegCrud(r, "/v1/insurance-company", insurancecompany.O) + hc.RegCrudByCode(r, "/v1/insurance-company", insurancecompany.O) hc.RegCrudByCode(r, "/v1/medicine", medicine.O) hc.RegCrudByCode(r, "/v1/device", device.O) hc.RegCrudByCode(r, "/v1/material", material.O) @@ -338,11 +338,11 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/vehicle-hist", vehiclehist.O) hc.RegCrud(r, "/v1/edu-assessment", eduassesment.O) - hc.RegCrud(r, "/v1/village", village.O) - hc.RegCrud(r, "/v1/district", district.O) - hc.RegCrud(r, "/v1/regency", regency.O) - hc.RegCrud(r, "/v1/province", province.O) - hc.RegCrud(r, "/v1/postal-region", postalregion.O) + hc.RegCrudByCode(r, "/v1/village", village.O) + hc.RegCrudByCode(r, "/v1/district", district.O) + hc.RegCrudByCode(r, "/v1/regency", regency.O) + hc.RegCrudByCode(r, "/v1/province", province.O) + hc.RegCrudByCode(r, "/v1/postal-region", postalregion.O) ///// return cmw.SetCors(handlerlogger.SetLog(r)) diff --git a/internal/interface/main-handler/mcu-src-category/handler.go b/internal/interface/main-handler/mcu-src-category/handler.go index 7dde9c66..1f11cef4 100644 --- a/internal/interface/main-handler/mcu-src-category/handler.go +++ b/internal/interface/main-handler/mcu-src-category/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ 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.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/medicine-group/handler.go b/internal/interface/main-handler/medicine-group/handler.go index 26818135..623e6d7c 100644 --- a/internal/interface/main-handler/medicine-group/handler.go +++ b/internal/interface/main-handler/medicine-group/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint(id) + dto.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/medicine-method/handler.go b/internal/interface/main-handler/medicine-method/handler.go index cab79d7c..af731e1e 100644 --- a/internal/interface/main-handler/medicine-method/handler.go +++ b/internal/interface/main-handler/medicine-method/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ 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.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/nutritionist/handler.go b/internal/interface/main-handler/nutritionist/handler.go index 708a8b52..1bfa138a 100644 --- a/internal/interface/main-handler/nutritionist/handler.go +++ b/internal/interface/main-handler/nutritionist/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint(id) + dto.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/pharmacist/handler.go b/internal/interface/main-handler/pharmacist/handler.go index fd0746e7..94069b20 100644 --- a/internal/interface/main-handler/pharmacist/handler.go +++ b/internal/interface/main-handler/pharmacist/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint(id) + dto.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/pharmacy-company/handler.go b/internal/interface/main-handler/pharmacy-company/handler.go index 2f0584ba..9ed222be 100644 --- a/internal/interface/main-handler/pharmacy-company/handler.go +++ b/internal/interface/main-handler/pharmacy-company/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ 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.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/postal-region/handler.go b/internal/interface/main-handler/postal-region/handler.go index baf3b2d6..92d11d37 100644 --- a/internal/interface/main-handler/postal-region/handler.go +++ b/internal/interface/main-handler/postal-region/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint32(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint32(id) + dto.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint32(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/procedure-src/handler.go b/internal/interface/main-handler/procedure-src/handler.go index ade14b42..d0e3ee49 100644 --- a/internal/interface/main-handler/procedure-src/handler.go +++ b/internal/interface/main-handler/procedure-src/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ 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.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/province/handler.go b/internal/interface/main-handler/province/handler.go index f95aec2e..626c9ecd 100644 --- a/internal/interface/main-handler/province/handler.go +++ b/internal/interface/main-handler/province/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = int16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = int16(id) + dto.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = int16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/regency/handler.go b/internal/interface/main-handler/regency/handler.go index e6170867..d6e2f654 100644 --- a/internal/interface/main-handler/regency/handler.go +++ b/internal/interface/main-handler/regency/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ 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.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/uom/handler.go b/internal/interface/main-handler/uom/handler.go index b75a4ae0..507681d3 100644 --- a/internal/interface/main-handler/uom/handler.go +++ b/internal/interface/main-handler/uom/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ 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.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/village/handler.go b/internal/interface/main-handler/village/handler.go index 76138e72..fa8a04af 100644 --- a/internal/interface/main-handler/village/handler.go +++ b/internal/interface/main-handler/village/handler.go @@ -33,19 +33,19 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.ReadDetailDto{} - dto.Id = uint32(id) + dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } @@ -53,19 +53,19 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint32(id) + dto.Code = &code 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 { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { return } dto := e.DeleteDto{} - dto.Id = uint32(id) + dto.Code = &code res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/use-case/main-use-case/diagnose-src/case.go b/internal/use-case/main-use-case/diagnose-src/case.go index 184e68a8..f999da19 100644 --- a/internal/use-case/main-use-case/diagnose-src/case.go +++ b/internal/use-case/main-use-case/diagnose-src/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.DiagnoseSrc var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.DiagnoseSrc var err error diff --git a/internal/use-case/main-use-case/diagnose-src/helper.go b/internal/use-case/main-use-case/diagnose-src/helper.go index 29622782..9ebfce05 100644 --- a/internal/use-case/main-use-case/diagnose-src/helper.go +++ b/internal/use-case/main-use-case/diagnose-src/helper.go @@ -17,7 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.DiagnoseSrc) { inputSrc = &inputTemp.CreateDto } - data.Code = inputSrc.Code + data.Code = *inputSrc.Code data.Name = inputSrc.Name data.IndName = inputSrc.IndName } diff --git a/internal/use-case/main-use-case/diagnose-src/lib.go b/internal/use-case/main-use-case/diagnose-src/lib.go index d45f6bb3..b2473532 100644 --- a/internal/use-case/main-use-case/diagnose-src/lib.go +++ b/internal/use-case/main-use-case/diagnose-src/lib.go @@ -81,7 +81,14 @@ 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 input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).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/district/case.go b/internal/use-case/main-use-case/district/case.go index b7a4b1a0..ccae0a25 100644 --- a/internal/use-case/main-use-case/district/case.go +++ b/internal/use-case/main-use-case/district/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.District var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.District var err error diff --git a/internal/use-case/main-use-case/district/helper.go b/internal/use-case/main-use-case/district/helper.go index 3959233c..2b6cb1c0 100644 --- a/internal/use-case/main-use-case/district/helper.go +++ b/internal/use-case/main-use-case/district/helper.go @@ -18,6 +18,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.District) { } data.Regency_Code = inputSrc.Regency_Code - data.Code = inputSrc.Code + data.Code = *inputSrc.Code data.Name = inputSrc.Name } diff --git a/internal/use-case/main-use-case/district/lib.go b/internal/use-case/main-use-case/district/lib.go index 4c8ac32f..173f0b69 100644 --- a/internal/use-case/main-use-case/district/lib.go +++ b/internal/use-case/main-use-case/district/lib.go @@ -81,7 +81,14 @@ 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 input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).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/insurance-company/case.go b/internal/use-case/main-use-case/insurance-company/case.go index 29aed939..e7c66e27 100644 --- a/internal/use-case/main-use-case/insurance-company/case.go +++ b/internal/use-case/main-use-case/insurance-company/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.InsuranceCompany var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.InsuranceCompany var err error diff --git a/internal/use-case/main-use-case/insurance-company/helper.go b/internal/use-case/main-use-case/insurance-company/helper.go index d9969523..d10f2d0f 100644 --- a/internal/use-case/main-use-case/insurance-company/helper.go +++ b/internal/use-case/main-use-case/insurance-company/helper.go @@ -17,7 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.InsuranceCompany) { inputSrc = &inputTemp.CreateDto } - data.Code = inputSrc.Code + data.Code = *inputSrc.Code data.Name = inputSrc.Name data.Regency_Code = inputSrc.Regency_Code data.Address = inputSrc.Address diff --git a/internal/use-case/main-use-case/insurance-company/lib.go b/internal/use-case/main-use-case/insurance-company/lib.go index 262a99d9..666c053f 100644 --- a/internal/use-case/main-use-case/insurance-company/lib.go +++ b/internal/use-case/main-use-case/insurance-company/lib.go @@ -81,7 +81,14 @@ 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 input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).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/mcu-src-category/case.go b/internal/use-case/main-use-case/mcu-src-category/case.go index c105603c..805fdcfe 100644 --- a/internal/use-case/main-use-case/mcu-src-category/case.go +++ b/internal/use-case/main-use-case/mcu-src-category/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.McuSrcCategory var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.McuSrcCategory var err error diff --git a/internal/use-case/main-use-case/mcu-src-category/helper.go b/internal/use-case/main-use-case/mcu-src-category/helper.go index f733012a..8d5784e3 100644 --- a/internal/use-case/main-use-case/mcu-src-category/helper.go +++ b/internal/use-case/main-use-case/mcu-src-category/helper.go @@ -17,7 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.McuSrcCategory) { inputSrc = &inputTemp.CreateDto } - data.Code = inputSrc.Code + data.Code = *inputSrc.Code data.Name = inputSrc.Name data.Scope_Code = inputSrc.Scope_Code } diff --git a/internal/use-case/main-use-case/mcu-src-category/lib.go b/internal/use-case/main-use-case/mcu-src-category/lib.go index 0cd44cfd..7f0fb8d3 100644 --- a/internal/use-case/main-use-case/mcu-src-category/lib.go +++ b/internal/use-case/main-use-case/mcu-src-category/lib.go @@ -81,7 +81,14 @@ 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 input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).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/medicine-group/case.go b/internal/use-case/main-use-case/medicine-group/case.go index 180c6e00..83601465 100644 --- a/internal/use-case/main-use-case/medicine-group/case.go +++ b/internal/use-case/main-use-case/medicine-group/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.MedicineGroup var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.MedicineGroup var err error diff --git a/internal/use-case/main-use-case/medicine-group/helper.go b/internal/use-case/main-use-case/medicine-group/helper.go index 7b98cf36..30df50fe 100644 --- a/internal/use-case/main-use-case/medicine-group/helper.go +++ b/internal/use-case/main-use-case/medicine-group/helper.go @@ -17,6 +17,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.MedicineGroup) { inputSrc = &inputTemp.CreateDto } - data.Code = inputSrc.Code + data.Code = *inputSrc.Code data.Name = inputSrc.Name } diff --git a/internal/use-case/main-use-case/medicine-group/lib.go b/internal/use-case/main-use-case/medicine-group/lib.go index 9c3214a9..0755ccd2 100644 --- a/internal/use-case/main-use-case/medicine-group/lib.go +++ b/internal/use-case/main-use-case/medicine-group/lib.go @@ -81,7 +81,14 @@ 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 input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).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/medicine-method/case.go b/internal/use-case/main-use-case/medicine-method/case.go index 012b77b0..5dc99bb2 100644 --- a/internal/use-case/main-use-case/medicine-method/case.go +++ b/internal/use-case/main-use-case/medicine-method/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.MedicineMethod var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.MedicineMethod var err error diff --git a/internal/use-case/main-use-case/medicine-method/helper.go b/internal/use-case/main-use-case/medicine-method/helper.go index d9142ae1..6839c7a6 100644 --- a/internal/use-case/main-use-case/medicine-method/helper.go +++ b/internal/use-case/main-use-case/medicine-method/helper.go @@ -17,6 +17,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.MedicineMethod) { inputSrc = &inputTemp.CreateDto } - data.Code = inputSrc.Code + data.Code = *inputSrc.Code data.Name = inputSrc.Name } diff --git a/internal/use-case/main-use-case/medicine-method/lib.go b/internal/use-case/main-use-case/medicine-method/lib.go index a9206cbe..893f8588 100644 --- a/internal/use-case/main-use-case/medicine-method/lib.go +++ b/internal/use-case/main-use-case/medicine-method/lib.go @@ -81,7 +81,14 @@ 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 input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).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/nutritionist/case.go b/internal/use-case/main-use-case/nutritionist/case.go index 8be3a320..5f98235c 100644 --- a/internal/use-case/main-use-case/nutritionist/case.go +++ b/internal/use-case/main-use-case/nutritionist/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Nutritionist var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Nutritionist var err error diff --git a/internal/use-case/main-use-case/nutritionist/lib.go b/internal/use-case/main-use-case/nutritionist/lib.go index 1f7c72b3..485e5351 100644 --- a/internal/use-case/main-use-case/nutritionist/lib.go +++ b/internal/use-case/main-use-case/nutritionist/lib.go @@ -84,7 +84,7 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e if input.Employee_Id != nil { tx = tx.Where("\"Employee_Id\" = ?", *input.Employee_Id) } - if input.Id > 0 { + if input.Id != nil { tx = tx.Where("\"Id\" = ?", input.Id) } if err := tx.First(&data).Error; err != nil { diff --git a/internal/use-case/main-use-case/pharmacist/case.go b/internal/use-case/main-use-case/pharmacist/case.go index 132987be..1ee63b66 100644 --- a/internal/use-case/main-use-case/pharmacist/case.go +++ b/internal/use-case/main-use-case/pharmacist/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Pharmacist var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Pharmacist var err error diff --git a/internal/use-case/main-use-case/pharmacist/lib.go b/internal/use-case/main-use-case/pharmacist/lib.go index 365ba118..d8077dca 100644 --- a/internal/use-case/main-use-case/pharmacist/lib.go +++ b/internal/use-case/main-use-case/pharmacist/lib.go @@ -84,7 +84,7 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e if input.Employee_Id != nil { tx = tx.Where("\"Employee_Id\" = ?", *input.Employee_Id) } - if input.Id > 0 { + if input.Id != nil { tx = tx.Where("\"Id\" = ?", input.Id) } if err := tx.First(&data).Error; err != nil { diff --git a/internal/use-case/main-use-case/pharmacy-company/case.go b/internal/use-case/main-use-case/pharmacy-company/case.go index cce54750..8e29df2d 100644 --- a/internal/use-case/main-use-case/pharmacy-company/case.go +++ b/internal/use-case/main-use-case/pharmacy-company/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.PharmacyCompany var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.PharmacyCompany var err error diff --git a/internal/use-case/main-use-case/pharmacy-company/helper.go b/internal/use-case/main-use-case/pharmacy-company/helper.go index d712a9ff..7249db89 100644 --- a/internal/use-case/main-use-case/pharmacy-company/helper.go +++ b/internal/use-case/main-use-case/pharmacy-company/helper.go @@ -17,7 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.PharmacyCompany) { inputSrc = &inputTemp.CreateDto } - data.Code = inputSrc.Code + data.Code = *inputSrc.Code data.Name = inputSrc.Name data.Regency_Code = inputSrc.Regency_Code } diff --git a/internal/use-case/main-use-case/pharmacy-company/lib.go b/internal/use-case/main-use-case/pharmacy-company/lib.go index 08b0ff64..afcdf2ca 100644 --- a/internal/use-case/main-use-case/pharmacy-company/lib.go +++ b/internal/use-case/main-use-case/pharmacy-company/lib.go @@ -81,7 +81,14 @@ 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 input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).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/postal-region/case.go b/internal/use-case/main-use-case/postal-region/case.go index 513b0d49..514841d7 100644 --- a/internal/use-case/main-use-case/postal-region/case.go +++ b/internal/use-case/main-use-case/postal-region/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.PostalRegion var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.PostalRegion var err error diff --git a/internal/use-case/main-use-case/postal-region/helper.go b/internal/use-case/main-use-case/postal-region/helper.go index 65114fbe..dbce19e2 100644 --- a/internal/use-case/main-use-case/postal-region/helper.go +++ b/internal/use-case/main-use-case/postal-region/helper.go @@ -17,5 +17,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.PostalRegion) { inputSrc = &inputTemp.CreateDto } data.Village_Code = inputSrc.Village_Code - data.Code = inputSrc.Code + data.Code = *inputSrc.Code } diff --git a/internal/use-case/main-use-case/postal-region/lib.go b/internal/use-case/main-use-case/postal-region/lib.go index 53070293..c44c18e1 100644 --- a/internal/use-case/main-use-case/postal-region/lib.go +++ b/internal/use-case/main-use-case/postal-region/lib.go @@ -81,12 +81,19 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e tx = dg.I } + if input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + tx = tx.Preload("Village"). Preload("Village.District"). Preload("Village.District.Regency"). Preload("Village.District.Regency.Province") - if err := tx.First(&data, input.Id).Error; err != nil { + if err := tx.First(&data).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/procedure-src/case.go b/internal/use-case/main-use-case/procedure-src/case.go index 1b91f6bb..fa7d2a67 100644 --- a/internal/use-case/main-use-case/procedure-src/case.go +++ b/internal/use-case/main-use-case/procedure-src/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.ProcedureSrc var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.ProcedureSrc var err error diff --git a/internal/use-case/main-use-case/procedure-src/helper.go b/internal/use-case/main-use-case/procedure-src/helper.go index 2832fd49..1963d52a 100644 --- a/internal/use-case/main-use-case/procedure-src/helper.go +++ b/internal/use-case/main-use-case/procedure-src/helper.go @@ -17,7 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.ProcedureSrc) { inputSrc = &inputTemp.CreateDto } - data.Code = inputSrc.Code + data.Code = *inputSrc.Code data.Name = inputSrc.Name data.IndName = inputSrc.IndName } diff --git a/internal/use-case/main-use-case/procedure-src/lib.go b/internal/use-case/main-use-case/procedure-src/lib.go index 5e0e9685..582df536 100644 --- a/internal/use-case/main-use-case/procedure-src/lib.go +++ b/internal/use-case/main-use-case/procedure-src/lib.go @@ -81,7 +81,14 @@ 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 input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).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/province/case.go b/internal/use-case/main-use-case/province/case.go index 50d5e7ab..6a2d1f3c 100644 --- a/internal/use-case/main-use-case/province/case.go +++ b/internal/use-case/main-use-case/province/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Province var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Province var err error diff --git a/internal/use-case/main-use-case/province/helper.go b/internal/use-case/main-use-case/province/helper.go index 62774538..e560a2a4 100644 --- a/internal/use-case/main-use-case/province/helper.go +++ b/internal/use-case/main-use-case/province/helper.go @@ -17,6 +17,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Province) { inputSrc = &inputTemp.CreateDto } - data.Code = inputSrc.Code + data.Code = *inputSrc.Code data.Name = inputSrc.Name } diff --git a/internal/use-case/main-use-case/province/lib.go b/internal/use-case/main-use-case/province/lib.go index 84b06235..289d02f4 100644 --- a/internal/use-case/main-use-case/province/lib.go +++ b/internal/use-case/main-use-case/province/lib.go @@ -81,7 +81,14 @@ 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 input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).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/regency/helper.go b/internal/use-case/main-use-case/regency/helper.go index aa867cf0..c67cd607 100644 --- a/internal/use-case/main-use-case/regency/helper.go +++ b/internal/use-case/main-use-case/regency/helper.go @@ -17,7 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Regency) { inputSrc = &inputTemp.CreateDto } data.Province_Code = inputSrc.Province_Code - data.Code = inputSrc.Code + data.Code = *inputSrc.Code data.Name = inputSrc.Name } diff --git a/internal/use-case/main-use-case/regency/lib.go b/internal/use-case/main-use-case/regency/lib.go index e59dae52..9d1a55ea 100644 --- a/internal/use-case/main-use-case/regency/lib.go +++ b/internal/use-case/main-use-case/regency/lib.go @@ -81,7 +81,14 @@ 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 input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).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/uom/case.go b/internal/use-case/main-use-case/uom/case.go index 29c4516b..2fdf6364 100644 --- a/internal/use-case/main-use-case/uom/case.go +++ b/internal/use-case/main-use-case/uom/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Uom var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Uom var err error diff --git a/internal/use-case/main-use-case/uom/helper.go b/internal/use-case/main-use-case/uom/helper.go index ea0b875c..f0474069 100644 --- a/internal/use-case/main-use-case/uom/helper.go +++ b/internal/use-case/main-use-case/uom/helper.go @@ -17,6 +17,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Uom) { inputSrc = &inputTemp.CreateDto } - data.Code = inputSrc.Code + data.Code = *inputSrc.Code data.Name = inputSrc.Name } diff --git a/internal/use-case/main-use-case/uom/lib.go b/internal/use-case/main-use-case/uom/lib.go index 05c22be1..64c1818d 100644 --- a/internal/use-case/main-use-case/uom/lib.go +++ b/internal/use-case/main-use-case/uom/lib.go @@ -81,7 +81,15 @@ 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 input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).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/village/case.go b/internal/use-case/main-use-case/village/case.go index 787fdb12..e59bd3b3 100644 --- a/internal/use-case/main-use-case/village/case.go +++ b/internal/use-case/main-use-case/village/case.go @@ -166,7 +166,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Village var err error @@ -222,7 +222,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: input.Id} + rdDto := e.ReadDetailDto{Code: input.Code} var data *e.Village var err error diff --git a/internal/use-case/main-use-case/village/helper.go b/internal/use-case/main-use-case/village/helper.go index bc50fd04..acc58456 100644 --- a/internal/use-case/main-use-case/village/helper.go +++ b/internal/use-case/main-use-case/village/helper.go @@ -17,6 +17,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Village) { inputSrc = &inputTemp.CreateDto } data.District_Code = inputSrc.District_Code - data.Code = inputSrc.Code + data.Code = *inputSrc.Code data.Name = inputSrc.Name } diff --git a/internal/use-case/main-use-case/village/lib.go b/internal/use-case/main-use-case/village/lib.go index 21ca8e6c..f60bfd7b 100644 --- a/internal/use-case/main-use-case/village/lib.go +++ b/internal/use-case/main-use-case/village/lib.go @@ -81,7 +81,14 @@ 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 input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { return nil, processedErr } From ebc2ca5659e2665f8509c8419dab49d516601435 Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 13 Nov 2025 09:57:10 +0700 Subject: [PATCH 169/329] set infra --- cmd/main-sync-api/config.yml-example | 41 --- cmd/main-sync-api/main.go | 15 - cmd/simgos-sync-api/config.yml-example | 6 +- cmd/simgos-sync-migration/Makefile | 18 ++ cmd/simgos-sync-migration/README-ATLAS.MD | 59 ++++ cmd/simgos-sync-migration/atlas.hcl.example | 22 ++ cmd/simgos-sync-migration/migration.go | 9 + internal/infra/sync-cfg/sync-cfg.go | 8 +- internal/infra/sync-cfg/tycovar.go | 5 +- .../interface/main-handler/main-handler.go | 2 + .../main-sync-handler/main-sync-handler.go | 36 --- internal/interface/migration/migration.go | 2 + .../migration/simgos-sync-entities.go | 5 + internal/interface/migration/tycovar.go | 5 +- .../installation/handler.go | 51 ++++ .../simgos-sync-handler.go | 9 +- internal/use-case/main-sync-use-case/.keep | 0 .../simgos-sync-use-case/installation/case.go | 263 ++++++++++++++++++ .../installation/helper.go | 23 ++ .../simgos-sync-use-case/installation/lib.go | 149 ++++++++++ .../installation/middleware-runner.go | 103 +++++++ .../installation/middleware.go | 9 + .../installation/tycovar.go | 44 +++ .../handler-crud-helper.go | 64 +++++ 24 files changed, 843 insertions(+), 105 deletions(-) delete mode 100644 cmd/main-sync-api/config.yml-example delete mode 100644 cmd/main-sync-api/main.go create mode 100644 cmd/simgos-sync-migration/Makefile create mode 100644 cmd/simgos-sync-migration/README-ATLAS.MD create mode 100644 cmd/simgos-sync-migration/atlas.hcl.example create mode 100644 cmd/simgos-sync-migration/migration.go delete mode 100644 internal/interface/main-sync-handler/main-sync-handler.go create mode 100644 internal/interface/migration/simgos-sync-entities.go create mode 100644 internal/interface/simgos-sync-handler/installation/handler.go delete mode 100644 internal/use-case/main-sync-use-case/.keep create mode 100644 internal/use-case/simgos-sync-use-case/installation/case.go create mode 100644 internal/use-case/simgos-sync-use-case/installation/helper.go create mode 100644 internal/use-case/simgos-sync-use-case/installation/lib.go create mode 100644 internal/use-case/simgos-sync-use-case/installation/middleware-runner.go create mode 100644 internal/use-case/simgos-sync-use-case/installation/middleware.go create mode 100644 internal/use-case/simgos-sync-use-case/installation/tycovar.go diff --git a/cmd/main-sync-api/config.yml-example b/cmd/main-sync-api/config.yml-example deleted file mode 100644 index edb5c84b..00000000 --- a/cmd/main-sync-api/config.yml-example +++ /dev/null @@ -1,41 +0,0 @@ -appCfg: - fullName: SIMRS Sync - codeName: simrs-sync - version: 0.1.0 - env: development - lang: en - -dbCfg: - dsn: - maxOpenConns: 5 - maxIdleConns: 5 - maxIdleTime: 100 - -multiDbCfg: - dbs : - - name: simrs_sync - dsn: - maxOpenConns: 5 - maxIdleConns: 5 - maxIdleTime: 100 - -httpCfg: - host: 127.0.0.1 - port: 8003 - -loggerCfg: - hideTime: true - hideLevel: true - -langCfg: - active: en - path: ../../assets/language/en - fileName: data.json - -corsCfg: - allowedOrigin: - allowedMethod: GET, POST, PUT, PATCH, DELETE, OPTIONS - -syncUrlCfg: - target: - host: \ No newline at end of file diff --git a/cmd/main-sync-api/main.go b/cmd/main-sync-api/main.go deleted file mode 100644 index 5bfdd36b..00000000 --- a/cmd/main-sync-api/main.go +++ /dev/null @@ -1,15 +0,0 @@ -package main - -import ( - a "github.com/karincake/apem" - - h "simrs-vx/internal/interface/main-sync-handler" - - d "github.com/karincake/apem/db-gorm-pg" - - l "github.com/karincake/apem/logger-zerolog" -) - -func main() { - a.Run(h.SetRoutes(), &l.O, &d.O) -} diff --git a/cmd/simgos-sync-api/config.yml-example b/cmd/simgos-sync-api/config.yml-example index 153be50e..98544958 100644 --- a/cmd/simgos-sync-api/config.yml-example +++ b/cmd/simgos-sync-api/config.yml-example @@ -34,8 +34,4 @@ langCfg: corsCfg: allowedOrigin: - allowedMethod: GET, POST, PUT, PATCH, DELETE, OPTIONS - -syncUrlCfg: - target: - host: \ No newline at end of file + allowedMethod: GET, POST, PUT, PATCH, DELETE, OPTIONS \ No newline at end of file diff --git a/cmd/simgos-sync-migration/Makefile b/cmd/simgos-sync-migration/Makefile new file mode 100644 index 00000000..e83356e5 --- /dev/null +++ b/cmd/simgos-sync-migration/Makefile @@ -0,0 +1,18 @@ +# Makefile for Atlas migrations + +# Default environment +ENV ?= gorm + +.PHONY: diff apply hash + +## Generate a new migration diff +diff: + atlas migrate diff --env $(ENV) + +## Apply migrations to the database +apply: + atlas migrate apply --env $(ENV) + +## Calculate the schema hash +hash: + atlas migrate hash diff --git a/cmd/simgos-sync-migration/README-ATLAS.MD b/cmd/simgos-sync-migration/README-ATLAS.MD new file mode 100644 index 00000000..da249823 --- /dev/null +++ b/cmd/simgos-sync-migration/README-ATLAS.MD @@ -0,0 +1,59 @@ +# Database Migration with Atlas + +This project uses [Atlas](https://atlasgo.io/) for database schema management and migrations. + +## 📋 Prerequisites + +1. **Download and Install Atlas CLI** + Run the following command in PowerShell or Git Bash: + + ```sh + curl -sSf https://atlasgo.sh | sh + ``` + Verify installation: + + ```sh + atlas version + ``` + +2. Install GORM Provider + Run inside your Go project: + + ```sh + go get -u ariga.io/atlas-provider-gorm + ``` + +3. Create atlas.hcl configuration file + Just create an atlas.hcl file in your project root as example given at atlas.hcl.example +4. Create migrations folder + ```sh + mkdir migrations + ``` +5. Usage +You can use the provided Makefile for common commands: + + Generate a migration diff + ```sh + make diff + ``` + + Apply migrations + ```sh + make apply + ``` + + Compute schema hash + ```sh + make hash + ``` + + If you don’t have make installed, you can run the Atlas commands directly: + ```sh + atlas migrate diff --env gorm + ``` + ```sh + atlas migrate apply --env gorm + ``` + ```sh + atlas migrate hash + ``` \ No newline at end of file diff --git a/cmd/simgos-sync-migration/atlas.hcl.example b/cmd/simgos-sync-migration/atlas.hcl.example new file mode 100644 index 00000000..857d1352 --- /dev/null +++ b/cmd/simgos-sync-migration/atlas.hcl.example @@ -0,0 +1,22 @@ +data "external_schema" "gorm" { + program = [ + "go", + "run", + "-mod=mod", + ".", + ] +} + +env "gorm" { + src = data.external_schema.gorm.url + dev = "" // dsn db to check the diff + migration { + dir = "file://migrations" + } + url = "" // dsn db to apply + format { + migrate { + diff = "{{ sql . \" \" }}" + } + } +} \ No newline at end of file diff --git a/cmd/simgos-sync-migration/migration.go b/cmd/simgos-sync-migration/migration.go new file mode 100644 index 00000000..fdd2c995 --- /dev/null +++ b/cmd/simgos-sync-migration/migration.go @@ -0,0 +1,9 @@ +package main + +import ( + m "simrs-vx/internal/interface/migration" +) + +func main() { + m.Migrate(m.SimgosSync) +} diff --git a/internal/infra/sync-cfg/sync-cfg.go b/internal/infra/sync-cfg/sync-cfg.go index 0368a7c4..a5579219 100644 --- a/internal/infra/sync-cfg/sync-cfg.go +++ b/internal/infra/sync-cfg/sync-cfg.go @@ -7,8 +7,12 @@ import ( func SetConfig() { a.ParseSingleCfg(&O) - if O.Host == "" || O.Target == "" { - panic("sync url config host or target empty") + //if O.Host == "" || O.Target == "" { + // panic("sync url config host or target empty") + //} + + if O.BaseUrl == "" { + panic("config bpjs base url empty") } lo.I.Println("sync url config loaded, status: DONE!!") } diff --git a/internal/infra/sync-cfg/tycovar.go b/internal/infra/sync-cfg/tycovar.go index 9bb59f3d..081ef762 100644 --- a/internal/infra/sync-cfg/tycovar.go +++ b/internal/infra/sync-cfg/tycovar.go @@ -3,6 +3,7 @@ package synccfg var O SyncUrlCfg = SyncUrlCfg{} type SyncUrlCfg struct { - Target string `yaml:"target"` - Host string `yaml:"host"` + Target string `yaml:"target"` + Host string `yaml:"host"` + BaseUrl string `yaml:"baseUrl"` } diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 8e885dc3..55f45479 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -60,6 +60,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" /******************** pkg ********************/ cmw "simrs-vx/pkg/cors-manager-mw" @@ -128,6 +129,7 @@ func SetRoutes() http.Handler { a.RegisterExtCall(mh.I.SetClient) a.RegisterExtCall(ibpjs.SetConfig) a.RegisterExtCall(validation.RegisterValidation) + a.RegisterExtCall(simgossync.SetConfig) r := http.NewServeMux() diff --git a/internal/interface/main-sync-handler/main-sync-handler.go b/internal/interface/main-sync-handler/main-sync-handler.go deleted file mode 100644 index c8ba5144..00000000 --- a/internal/interface/main-sync-handler/main-sync-handler.go +++ /dev/null @@ -1,36 +0,0 @@ -package mainsynchandler - -import ( - "net/http" - - /******************** infra ********************/ - gs "simrs-vx/internal/infra/gorm-setting" - synccfg "simrs-vx/internal/infra/sync-cfg" - - /******************** pkg ********************/ - cmw "simrs-vx/pkg/cors-manager-mw" - lh "simrs-vx/pkg/lang-helper" - handlerlogger "simrs-vx/pkg/middleware/handler-logger" - zlc "simrs-vx/pkg/zerolog-ctx" - - /******************** external ********************/ - a "github.com/karincake/apem" - - /******************** internal ********************/ - "simrs-vx/internal/interface/main-handler/home" -) - -func SetRoutes() http.Handler { - /// - a.RegisterExtCall(gs.Adjust) - a.RegisterExtCall(zlc.Adjust) - a.RegisterExtCall(lh.Populate) - a.RegisterExtCall(synccfg.SetConfig) - - r := http.NewServeMux() - - /******************** Main ********************/ - r.HandleFunc("/", home.Home) - - return cmw.SetCors(handlerlogger.SetLog(r)) -} diff --git a/internal/interface/migration/migration.go b/internal/interface/migration/migration.go index 6cec68dc..a446ac1a 100644 --- a/internal/interface/migration/migration.go +++ b/internal/interface/migration/migration.go @@ -31,6 +31,8 @@ func getEntities(input string) []any { return getMainEntities() case "satusehat": return getSatuSehatEntities() + case "simgos-sync": + return getSimgosSync() } return nil } diff --git a/internal/interface/migration/simgos-sync-entities.go b/internal/interface/migration/simgos-sync-entities.go new file mode 100644 index 00000000..c6b51988 --- /dev/null +++ b/internal/interface/migration/simgos-sync-entities.go @@ -0,0 +1,5 @@ +package migration + +func getSimgosSync() []any { + return []any{} +} diff --git a/internal/interface/migration/tycovar.go b/internal/interface/migration/tycovar.go index f86f855d..977c4689 100644 --- a/internal/interface/migration/tycovar.go +++ b/internal/interface/migration/tycovar.go @@ -2,6 +2,7 @@ package migration const ( - Main = "main" - SatuSehat = "satusehat" + Main = "main" + SatuSehat = "satusehat" + SimgosSync = "simgos-sync" ) diff --git a/internal/interface/simgos-sync-handler/installation/handler.go b/internal/interface/simgos-sync-handler/installation/handler.go new file mode 100644 index 00000000..8e8b15bf --- /dev/null +++ b/internal/interface/simgos-sync-handler/installation/handler.go @@ -0,0 +1,51 @@ +package installation + +import ( + "net/http" + + rw "github.com/karincake/risoles" + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/installation" + u "simrs-vx/internal/use-case/main-use-case/installation" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Code = &code + res, err := u.Update(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { + return + } + + dto := e.DeleteDto{} + dto.Code = &code + res, err := u.Delete(dto) + 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 f51106a9..ed3246f7 100644 --- a/internal/interface/simgos-sync-handler/simgos-sync-handler.go +++ b/internal/interface/simgos-sync-handler/simgos-sync-handler.go @@ -2,10 +2,10 @@ package simgossynchandler import ( "net/http" + hc "simrs-vx/pkg/handler-crud-helper" /******************** infra ********************/ gs "simrs-vx/internal/infra/gorm-setting" - synccfg "simrs-vx/internal/infra/sync-cfg" /******************** pkg ********************/ cmw "simrs-vx/pkg/cors-manager-mw" @@ -18,6 +18,9 @@ import ( /******************** internal ********************/ "simrs-vx/internal/interface/main-handler/home" + + /********************* source *********************/ + installation "simrs-vx/internal/interface/simgos-sync-handler/installation" ) func SetRoutes() http.Handler { @@ -25,12 +28,14 @@ func SetRoutes() http.Handler { a.RegisterExtCall(gs.Adjust) a.RegisterExtCall(zlc.Adjust) a.RegisterExtCall(lh.Populate) - a.RegisterExtCall(synccfg.SetConfig) r := http.NewServeMux() /******************** Main ********************/ r.HandleFunc("/", home.Home) + /******************** Source ******************/ + hc.RegCrudByCode(r, "/v1/installation", installation.O) + return cmw.SetCors(handlerlogger.SetLog(r)) } diff --git a/internal/use-case/main-sync-use-case/.keep b/internal/use-case/main-sync-use-case/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/internal/use-case/simgos-sync-use-case/installation/case.go b/internal/use-case/simgos-sync-use-case/installation/case.go new file mode 100644 index 00000000..7d8187cc --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/installation/case.go @@ -0,0 +1,263 @@ +package installation + +import ( + e "simrs-vx/internal/domain/main-entities/installation" + "strconv" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "installation" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.Installation{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + err := dg.I.Transaction(func(tx *gorm.DB) error { + if resData, err := CreateData(input, &event, tx); err != nil { + return err + } else { + data = *resData + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.Installation + var dataList []e.Installation + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.Installation + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Code: input.Code} + var data *e.Installation + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Code: input.Code} + var data *e.Installation + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/simgos-sync-use-case/installation/helper.go b/internal/use-case/simgos-sync-use-case/installation/helper.go new file mode 100644 index 00000000..d3d96b5c --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/installation/helper.go @@ -0,0 +1,23 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package installation + +import ( + e "simrs-vx/internal/domain/main-entities/installation" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Installation) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Code = *inputSrc.Code + data.Name = inputSrc.Name + data.EncounterClass_Code = inputSrc.EncounterClass_Code +} diff --git a/internal/use-case/simgos-sync-use-case/installation/lib.go b/internal/use-case/simgos-sync-use-case/installation/lib.go new file mode 100644 index 00000000..d75b2ecd --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/installation/lib.go @@ -0,0 +1,149 @@ +package installation + +import ( + e "simrs-vx/internal/domain/main-entities/installation" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Installation, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.Installation{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Installation, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.Installation{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.Installation{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.Installation, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.Installation{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", *input.Id) + } + + if err := tx. + Scopes(gh.Preload(input.Includes)). + First(&data).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.Installation, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.Installation, 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 +} diff --git a/internal/use-case/simgos-sync-use-case/installation/middleware-runner.go b/internal/use-case/simgos-sync-use-case/installation/middleware-runner.go new file mode 100644 index 00000000..fce572bb --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/installation/middleware-runner.go @@ -0,0 +1,103 @@ +package installation + +import ( + e "simrs-vx/internal/domain/main-entities/installation" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.Installation) 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.Installation) 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.Installation) 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.Installation) 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.Installation) 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/installation/middleware.go b/internal/use-case/simgos-sync-use-case/installation/middleware.go new file mode 100644 index 00000000..3d414c9b --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/installation/middleware.go @@ -0,0 +1,9 @@ +package installation + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/simgos-sync-use-case/installation/tycovar.go b/internal/use-case/simgos-sync-use-case/installation/tycovar.go new file mode 100644 index 00000000..de8e9c9e --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/installation/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 installation + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/installation" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.Installation, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Installation, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Installation, 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/pkg/handler-crud-helper/handler-crud-helper.go b/pkg/handler-crud-helper/handler-crud-helper.go index df475094..a5700dad 100644 --- a/pkg/handler-crud-helper/handler-crud-helper.go +++ b/pkg/handler-crud-helper/handler-crud-helper.go @@ -74,3 +74,67 @@ func RegCrudByCode(r *http.ServeMux, path string, mwAndRouter ...any) { "DELETE /{code}": c.Delete, }) } + +func RegCrudSimgosSync(r *http.ServeMux, path string, mwAndRouter ...any) { + sLength := len(mwAndRouter) + + mwCandidates := mwAndRouter[:sLength-1] + mwList := []hk.HandlerMw{} + for i := range mwCandidates { + // have to do it manually, since casting directly results unexpected result + myType := reflect.TypeOf(mwCandidates[i]) + if myType.String() != "func(http.Handler) http.Handler" { + panic("non middleware included as middleware") + } + mwList = append(mwList, mwCandidates[i].(func(http.Handler) http.Handler)) + + // if g, okHandler := mwCandidates[i].(func(http.Handler) http.Handler); !okHandler { + // panic("non middleware included") + // } else { + // mwList = append(mwList, g) + // } + } + + c, ok := mwAndRouter[sLength-1].(CrudBase) + if !ok { + panic("non CrudBase used in the last paramter") + } + + hk.GroupRoutes(path, r, mwList, hk.MapHandlerFunc{ + "POST /": c.Create, + "PATCH /{id}": c.Update, + "DELETE /{id}": c.Delete, + }) +} + +func RegCrudByCodeSimgosSync(r *http.ServeMux, path string, mwAndRouter ...any) { + sLength := len(mwAndRouter) + + mwCandidates := mwAndRouter[:sLength-1] + mwList := []hk.HandlerMw{} + for i := range mwCandidates { + // have to do it manually, since casting directly results unexpected result + myType := reflect.TypeOf(mwCandidates[i]) + if myType.String() != "func(http.Handler) http.Handler" { + panic("non middleware included as middleware") + } + mwList = append(mwList, mwCandidates[i].(func(http.Handler) http.Handler)) + + // if g, okHandler := mwCandidates[i].(func(http.Handler) http.Handler); !okHandler { + // panic("non middleware included") + // } else { + // mwList = append(mwList, g) + // } + } + + c, ok := mwAndRouter[sLength-1].(CrudBase) + if !ok { + panic("non CrudBase used in the last paramter") + } + + hk.GroupRoutes(path, r, mwList, hk.MapHandlerFunc{ + "POST /": c.Create, + "PATCH /{code}": c.Update, + "DELETE /{code}": c.Delete, + }) +} From 4b78e489ef806ebba23700f1914b1e018ff35f36 Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 13 Nov 2025 10:33:37 +0700 Subject: [PATCH 170/329] add instalation entity --- cmd/simgos-sync-migration/Makefile | 18 ++++++ cmd/simgos-sync-migration/README-ATLAS.MD | 59 +++++++++++++++++++ cmd/simgos-sync-migration/atlas.hcl.example | 22 +++++++ cmd/simgos-sync-migration/migration.go | 9 +++ internal/domain/references/common/common.go | 4 ++ .../simgos-entities/installation/entity.go | 12 ++++ internal/domain/simgos-sync-entities/.keep | 0 .../sync-entities/installation/entity.go | 29 +++++++++ internal/interface/migration/migration.go | 2 + .../migration/simgossync-entities.go | 9 +++ internal/interface/migration/tycovar.go | 5 +- 11 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 cmd/simgos-sync-migration/Makefile create mode 100644 cmd/simgos-sync-migration/README-ATLAS.MD create mode 100644 cmd/simgos-sync-migration/atlas.hcl.example create mode 100644 cmd/simgos-sync-migration/migration.go create mode 100644 internal/domain/simgos-entities/installation/entity.go delete mode 100644 internal/domain/simgos-sync-entities/.keep create mode 100644 internal/domain/sync-entities/installation/entity.go create mode 100644 internal/interface/migration/simgossync-entities.go diff --git a/cmd/simgos-sync-migration/Makefile b/cmd/simgos-sync-migration/Makefile new file mode 100644 index 00000000..e83356e5 --- /dev/null +++ b/cmd/simgos-sync-migration/Makefile @@ -0,0 +1,18 @@ +# Makefile for Atlas migrations + +# Default environment +ENV ?= gorm + +.PHONY: diff apply hash + +## Generate a new migration diff +diff: + atlas migrate diff --env $(ENV) + +## Apply migrations to the database +apply: + atlas migrate apply --env $(ENV) + +## Calculate the schema hash +hash: + atlas migrate hash diff --git a/cmd/simgos-sync-migration/README-ATLAS.MD b/cmd/simgos-sync-migration/README-ATLAS.MD new file mode 100644 index 00000000..da249823 --- /dev/null +++ b/cmd/simgos-sync-migration/README-ATLAS.MD @@ -0,0 +1,59 @@ +# Database Migration with Atlas + +This project uses [Atlas](https://atlasgo.io/) for database schema management and migrations. + +## 📋 Prerequisites + +1. **Download and Install Atlas CLI** + Run the following command in PowerShell or Git Bash: + + ```sh + curl -sSf https://atlasgo.sh | sh + ``` + Verify installation: + + ```sh + atlas version + ``` + +2. Install GORM Provider + Run inside your Go project: + + ```sh + go get -u ariga.io/atlas-provider-gorm + ``` + +3. Create atlas.hcl configuration file + Just create an atlas.hcl file in your project root as example given at atlas.hcl.example +4. Create migrations folder + ```sh + mkdir migrations + ``` +5. Usage +You can use the provided Makefile for common commands: + + Generate a migration diff + ```sh + make diff + ``` + + Apply migrations + ```sh + make apply + ``` + + Compute schema hash + ```sh + make hash + ``` + + If you don’t have make installed, you can run the Atlas commands directly: + ```sh + atlas migrate diff --env gorm + ``` + ```sh + atlas migrate apply --env gorm + ``` + ```sh + atlas migrate hash + ``` \ No newline at end of file diff --git a/cmd/simgos-sync-migration/atlas.hcl.example b/cmd/simgos-sync-migration/atlas.hcl.example new file mode 100644 index 00000000..857d1352 --- /dev/null +++ b/cmd/simgos-sync-migration/atlas.hcl.example @@ -0,0 +1,22 @@ +data "external_schema" "gorm" { + program = [ + "go", + "run", + "-mod=mod", + ".", + ] +} + +env "gorm" { + src = data.external_schema.gorm.url + dev = "" // dsn db to check the diff + migration { + dir = "file://migrations" + } + url = "" // dsn db to apply + format { + migrate { + diff = "{{ sql . \" \" }}" + } + } +} \ No newline at end of file diff --git a/cmd/simgos-sync-migration/migration.go b/cmd/simgos-sync-migration/migration.go new file mode 100644 index 00000000..fdd2c995 --- /dev/null +++ b/cmd/simgos-sync-migration/migration.go @@ -0,0 +1,9 @@ +package main + +import ( + m "simrs-vx/internal/interface/migration" +) + +func main() { + m.Migrate(m.SimgosSync) +} diff --git a/internal/domain/references/common/common.go b/internal/domain/references/common/common.go index 2941049c..71396f2a 100644 --- a/internal/domain/references/common/common.go +++ b/internal/domain/references/common/common.go @@ -16,6 +16,7 @@ type ( DataVerifiedCode string CrudCode string DataApprovalCode string + ProcessStatusCode string ) const ( @@ -101,6 +102,9 @@ const ( DACNew DataApprovalCode = "new" DACApproved DataApprovalCode = "approved" DACRejected DataApprovalCode = "rejected" + + PSCSuccess ProcessStatusCode = "success" + PSCFailed ProcessStatusCode = "failed" ) func GetDayCodes() map[DayCode]string { diff --git a/internal/domain/simgos-entities/installation/entity.go b/internal/domain/simgos-entities/installation/entity.go new file mode 100644 index 00000000..88028fc4 --- /dev/null +++ b/internal/domain/simgos-entities/installation/entity.go @@ -0,0 +1,12 @@ +package installation + +type MInstalasi struct { + NoInstalasi uint `json:"no_instalasi"` + NamaInstalasi string `json:"nama_instalasi"` + StatusRawatInap *uint `json:"status_rawat_inap"` + StAktif *uint64 `json:"st_aktif"` +} + +func (MInstalasi) TableName() string { + return "m_instalasi" +} diff --git a/internal/domain/simgos-sync-entities/.keep b/internal/domain/simgos-sync-entities/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/internal/domain/sync-entities/installation/entity.go b/internal/domain/sync-entities/installation/entity.go new file mode 100644 index 00000000..46ffe71b --- /dev/null +++ b/internal/domain/sync-entities/installation/entity.go @@ -0,0 +1,29 @@ +package installation + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + erc "simrs-vx/internal/domain/references/common" + "time" +) + +type InstallationLink struct { + ecore.Main + Simx_Id string `json:"simx_id" gorm:"unique"` + Simgos_Id uint64 `json:"simgos_id" gorm:"unique"` +} + +type InstallationSimxLog struct { + ecore.Main + Value *string `json:"value"` + Date *time.Time `json:"date"` + Status erc.ProcessStatusCode `json:"status"` + ErrMessage *string `json:"errMessage"` +} + +type InstallationSimgosLog struct { + ecore.Main + Value *string `json:"value"` + Date *time.Time `json:"date"` + Status erc.ProcessStatusCode `json:"status"` + ErrMessage *string `json:"errMessage"` +} diff --git a/internal/interface/migration/migration.go b/internal/interface/migration/migration.go index 6cec68dc..31ec1840 100644 --- a/internal/interface/migration/migration.go +++ b/internal/interface/migration/migration.go @@ -31,6 +31,8 @@ func getEntities(input string) []any { return getMainEntities() case "satusehat": return getSatuSehatEntities() + case "simgossync": + return getSimgosSyncEntities() } return nil } diff --git a/internal/interface/migration/simgossync-entities.go b/internal/interface/migration/simgossync-entities.go new file mode 100644 index 00000000..175a0ba9 --- /dev/null +++ b/internal/interface/migration/simgossync-entities.go @@ -0,0 +1,9 @@ +package migration + +func getSimgosSyncEntities() []any { + return []any{ + //&installation.InstallationLink{}, + //&installation.InstallationSimxLog{}, + //&installation.InstallationSimgosLog{}, + } +} diff --git a/internal/interface/migration/tycovar.go b/internal/interface/migration/tycovar.go index f86f855d..f6c57b4b 100644 --- a/internal/interface/migration/tycovar.go +++ b/internal/interface/migration/tycovar.go @@ -2,6 +2,7 @@ package migration const ( - Main = "main" - SatuSehat = "satusehat" + Main = "main" + SatuSehat = "satusehat" + SimgosSync = "simgossync" ) From 8cfd561a6cc328983a741f3d435a0d4c32d0deb1 Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 13 Nov 2025 10:57:53 +0700 Subject: [PATCH 171/329] add migration sync --- .../migrations/20251113035508.sql | 36 +++++++++++++++++++ .../migrations/atlas.sum | 2 ++ .../sync-entities/installation/entity.go | 4 +-- .../migration/simgossync-entities.go | 11 ++++-- 4 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 cmd/simgos-sync-migration/migrations/20251113035508.sql create mode 100644 cmd/simgos-sync-migration/migrations/atlas.sum diff --git a/cmd/simgos-sync-migration/migrations/20251113035508.sql b/cmd/simgos-sync-migration/migrations/20251113035508.sql new file mode 100644 index 00000000..5dddf417 --- /dev/null +++ b/cmd/simgos-sync-migration/migrations/20251113035508.sql @@ -0,0 +1,36 @@ +-- Create "InstallationLink" table +CREATE TABLE "public"."InstallationLink" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Simx_Id" bigint NULL, + "Simgos_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_InstallationLink_Simgos_Id" UNIQUE ("Simgos_Id"), + CONSTRAINT "uni_InstallationLink_Simx_Id" UNIQUE ("Simx_Id") +); +-- Create "InstallationSimgosLog" table +CREATE TABLE "public"."InstallationSimgosLog" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Value" text NULL, + "Date" timestamptz NULL, + "Status" text NULL, + "ErrMessage" text NULL, + PRIMARY KEY ("Id") +); +-- Create "InstallationSimxLog" table +CREATE TABLE "public"."InstallationSimxLog" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Value" text NULL, + "Date" timestamptz NULL, + "Status" text NULL, + "ErrMessage" text NULL, + PRIMARY KEY ("Id") +); diff --git a/cmd/simgos-sync-migration/migrations/atlas.sum b/cmd/simgos-sync-migration/migrations/atlas.sum new file mode 100644 index 00000000..50f3c7d3 --- /dev/null +++ b/cmd/simgos-sync-migration/migrations/atlas.sum @@ -0,0 +1,2 @@ +h1:OaRZyFJMii/8wQ0XLWEpF9MIL8IXblx3IYvB7LN2XQ4= +20251113035508.sql h1:p/FKefphuiBjEND87ChQLS/lcZcnvn0aT5tRV43Dn5o= diff --git a/internal/domain/sync-entities/installation/entity.go b/internal/domain/sync-entities/installation/entity.go index 46ffe71b..a7818f3f 100644 --- a/internal/domain/sync-entities/installation/entity.go +++ b/internal/domain/sync-entities/installation/entity.go @@ -8,8 +8,8 @@ import ( type InstallationLink struct { ecore.Main - Simx_Id string `json:"simx_id" gorm:"unique"` - Simgos_Id uint64 `json:"simgos_id" gorm:"unique"` + Simx_Id uint `json:"simx_id" gorm:"unique"` + Simgos_Id uint `json:"simgos_id" gorm:"unique"` } type InstallationSimxLog struct { diff --git a/internal/interface/migration/simgossync-entities.go b/internal/interface/migration/simgossync-entities.go index 175a0ba9..3b67265f 100644 --- a/internal/interface/migration/simgossync-entities.go +++ b/internal/interface/migration/simgossync-entities.go @@ -1,9 +1,14 @@ package migration +import ( + /************** Source ***************/ + installation "simrs-vx/internal/domain/sync-entities/installation" +) + func getSimgosSyncEntities() []any { return []any{ - //&installation.InstallationLink{}, - //&installation.InstallationSimxLog{}, - //&installation.InstallationSimgosLog{}, + &installation.InstallationLink{}, + &installation.InstallationSimxLog{}, + &installation.InstallationSimgosLog{}, } } From 91afde0624c73680444965abc6b707d8bd2f0ebd Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 13 Nov 2025 11:39:12 +0700 Subject: [PATCH 172/329] on going installation --- .../installation/handler.go | 2 +- .../simgos-sync-handler.go | 11 ++-- .../main-use-case/installation/case.go | 3 +- .../simgos-sync-use-case/installation/case.go | 4 ++ .../installation/helper.go | 5 +- .../simgos-sync-use-case/installation/lib.go | 9 +-- .../handler-crud-helper.go | 64 ------------------- 7 files changed, 22 insertions(+), 76 deletions(-) diff --git a/internal/interface/simgos-sync-handler/installation/handler.go b/internal/interface/simgos-sync-handler/installation/handler.go index 8e8b15bf..01a6beab 100644 --- a/internal/interface/simgos-sync-handler/installation/handler.go +++ b/internal/interface/simgos-sync-handler/installation/handler.go @@ -7,7 +7,7 @@ import ( // ua "github.com/karincake/tumpeng/auth/svc" e "simrs-vx/internal/domain/main-entities/installation" - u "simrs-vx/internal/use-case/main-use-case/installation" + u "simrs-vx/internal/use-case/simgos-sync-use-case/installation" ) type myBase struct{} diff --git a/internal/interface/simgos-sync-handler/simgos-sync-handler.go b/internal/interface/simgos-sync-handler/simgos-sync-handler.go index ed3246f7..963ec93c 100644 --- a/internal/interface/simgos-sync-handler/simgos-sync-handler.go +++ b/internal/interface/simgos-sync-handler/simgos-sync-handler.go @@ -2,8 +2,6 @@ package simgossynchandler import ( "net/http" - hc "simrs-vx/pkg/handler-crud-helper" - /******************** infra ********************/ gs "simrs-vx/internal/infra/gorm-setting" @@ -15,11 +13,10 @@ import ( /******************** external ********************/ a "github.com/karincake/apem" + hk "github.com/karincake/hongkue" /******************** internal ********************/ "simrs-vx/internal/interface/main-handler/home" - - /********************* source *********************/ installation "simrs-vx/internal/interface/simgos-sync-handler/installation" ) @@ -35,7 +32,11 @@ func SetRoutes() http.Handler { r.HandleFunc("/", home.Home) /******************** Source ******************/ - hc.RegCrudByCode(r, "/v1/installation", installation.O) + hk.GroupRoutes("/v1/installation", r, hk.MapHandlerFunc{ + "POST /": installation.O.Create, + "PATCH /{id}": installation.O.Update, + "DELETE /{id}": installation.O.Delete, + }) return cmw.SetCors(handlerlogger.SetLog(r)) } diff --git a/internal/use-case/main-use-case/installation/case.go b/internal/use-case/main-use-case/installation/case.go index f66bedaf..f3ce5d59 100644 --- a/internal/use-case/main-use-case/installation/case.go +++ b/internal/use-case/main-use-case/installation/case.go @@ -1,7 +1,6 @@ package installation import ( - e "simrs-vx/internal/domain/main-entities/installation" "strconv" dg "github.com/karincake/apem/db-gorm-pg" @@ -11,6 +10,8 @@ import ( pu "simrs-vx/pkg/use-case-helper" "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/installation" ) const source = "installation" diff --git a/internal/use-case/simgos-sync-use-case/installation/case.go b/internal/use-case/simgos-sync-use-case/installation/case.go index 7d8187cc..398289cd 100644 --- a/internal/use-case/simgos-sync-use-case/installation/case.go +++ b/internal/use-case/simgos-sync-use-case/installation/case.go @@ -27,6 +27,10 @@ func Create(input e.CreateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "create") err := dg.I.Transaction(func(tx *gorm.DB) error { + // TODO: Insert + + // TODO: InsertSimxLog + if resData, err := CreateData(input, &event, tx); err != nil { return err } else { diff --git a/internal/use-case/simgos-sync-use-case/installation/helper.go b/internal/use-case/simgos-sync-use-case/installation/helper.go index d3d96b5c..af56b5c6 100644 --- a/internal/use-case/simgos-sync-use-case/installation/helper.go +++ b/internal/use-case/simgos-sync-use-case/installation/helper.go @@ -6,9 +6,10 @@ package installation import ( e "simrs-vx/internal/domain/main-entities/installation" + esimgos "simrs-vx/internal/domain/simgos-entities/installation" ) -func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Installation) { +func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T, data *esimgos.MInstalasi) { var inputSrc *e.CreateDto if inputT, ok := any(input).(*e.CreateDto); ok { inputSrc = inputT @@ -17,6 +18,8 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Installation) { inputSrc = &inputTemp.CreateDto } + data.NamaInstalasi = inputSrc.Name + data.StatusRawatInap = 1 data.Code = *inputSrc.Code data.Name = inputSrc.Name data.EncounterClass_Code = inputSrc.EncounterClass_Code diff --git a/internal/use-case/simgos-sync-use-case/installation/lib.go b/internal/use-case/simgos-sync-use-case/installation/lib.go index d75b2ecd..07afe61a 100644 --- a/internal/use-case/simgos-sync-use-case/installation/lib.go +++ b/internal/use-case/simgos-sync-use-case/installation/lib.go @@ -1,8 +1,6 @@ package installation import ( - e "simrs-vx/internal/domain/main-entities/installation" - plh "simrs-vx/pkg/lib-helper" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -10,12 +8,15 @@ import ( dg "github.com/karincake/apem/db-gorm-pg" gh "github.com/karincake/getuk" "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/installation" + esimgos "simrs-vx/internal/domain/simgos-entities/installation" ) -func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Installation, error) { +func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esimgos.MInstalasi, error) { pl.SetLogInfo(event, nil, "started", "DBCreate") - data := e.Installation{} + data := esimgos.MInstalasi{} setData(&input, &data) var tx *gorm.DB diff --git a/pkg/handler-crud-helper/handler-crud-helper.go b/pkg/handler-crud-helper/handler-crud-helper.go index a5700dad..df475094 100644 --- a/pkg/handler-crud-helper/handler-crud-helper.go +++ b/pkg/handler-crud-helper/handler-crud-helper.go @@ -74,67 +74,3 @@ func RegCrudByCode(r *http.ServeMux, path string, mwAndRouter ...any) { "DELETE /{code}": c.Delete, }) } - -func RegCrudSimgosSync(r *http.ServeMux, path string, mwAndRouter ...any) { - sLength := len(mwAndRouter) - - mwCandidates := mwAndRouter[:sLength-1] - mwList := []hk.HandlerMw{} - for i := range mwCandidates { - // have to do it manually, since casting directly results unexpected result - myType := reflect.TypeOf(mwCandidates[i]) - if myType.String() != "func(http.Handler) http.Handler" { - panic("non middleware included as middleware") - } - mwList = append(mwList, mwCandidates[i].(func(http.Handler) http.Handler)) - - // if g, okHandler := mwCandidates[i].(func(http.Handler) http.Handler); !okHandler { - // panic("non middleware included") - // } else { - // mwList = append(mwList, g) - // } - } - - c, ok := mwAndRouter[sLength-1].(CrudBase) - if !ok { - panic("non CrudBase used in the last paramter") - } - - hk.GroupRoutes(path, r, mwList, hk.MapHandlerFunc{ - "POST /": c.Create, - "PATCH /{id}": c.Update, - "DELETE /{id}": c.Delete, - }) -} - -func RegCrudByCodeSimgosSync(r *http.ServeMux, path string, mwAndRouter ...any) { - sLength := len(mwAndRouter) - - mwCandidates := mwAndRouter[:sLength-1] - mwList := []hk.HandlerMw{} - for i := range mwCandidates { - // have to do it manually, since casting directly results unexpected result - myType := reflect.TypeOf(mwCandidates[i]) - if myType.String() != "func(http.Handler) http.Handler" { - panic("non middleware included as middleware") - } - mwList = append(mwList, mwCandidates[i].(func(http.Handler) http.Handler)) - - // if g, okHandler := mwCandidates[i].(func(http.Handler) http.Handler); !okHandler { - // panic("non middleware included") - // } else { - // mwList = append(mwList, g) - // } - } - - c, ok := mwAndRouter[sLength-1].(CrudBase) - if !ok { - panic("non CrudBase used in the last paramter") - } - - hk.GroupRoutes(path, r, mwList, hk.MapHandlerFunc{ - "POST /": c.Create, - "PATCH /{code}": c.Update, - "DELETE /{code}": c.Delete, - }) -} From 4f9663d98ae9ed0c696b695c9b76c072475b690f Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 13 Nov 2025 11:41:29 +0700 Subject: [PATCH 173/329] update m_installation --- internal/domain/simgos-entities/installation/entity.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/domain/simgos-entities/installation/entity.go b/internal/domain/simgos-entities/installation/entity.go index 88028fc4..d620af5e 100644 --- a/internal/domain/simgos-entities/installation/entity.go +++ b/internal/domain/simgos-entities/installation/entity.go @@ -1,10 +1,10 @@ package installation type MInstalasi struct { - NoInstalasi uint `json:"no_instalasi"` - NamaInstalasi string `json:"nama_instalasi"` - StatusRawatInap *uint `json:"status_rawat_inap"` - StAktif *uint64 `json:"st_aktif"` + NoInstalasi uint `json:"no_instalasi"` + NamaInstalasi string `json:"nama_instalasi"` + StatusRawatInap uint `json:"status_rawat_inap"` + StAktif uint `json:"st_aktif"` } func (MInstalasi) TableName() string { From 1e54d3bc3f68110b717e0d45d961c157b0fc31f5 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 13 Nov 2025 14:51:45 +0700 Subject: [PATCH 174/329] fix (encounter): add guard for create, delete and cancel --- .../domain/main-entities/encounter/dto.go | 4 ++ .../main-handler/encounter/handler.go | 11 +++++ internal/lib/auth/tycovar.go | 2 +- .../main-use-case/authentication/case.go | 2 +- .../use-case/main-use-case/encounter/case.go | 48 +++++++++++++++---- pkg/use-case-helper/use-case-helper.go | 16 +++++++ 6 files changed, 73 insertions(+), 10 deletions(-) diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index d3f2d04d..f43a1de9 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -104,10 +104,14 @@ type UpdateDto struct { type UpdateStatusDto struct { Id uint16 `json:"id"` StatusCode erc.DataStatusCode `json:"status_code"` + + pa.AuthInfo } type DeleteDto struct { Id uint16 `json:"id"` + + pa.AuthInfo } type MetaDto struct { diff --git a/internal/interface/main-handler/encounter/handler.go b/internal/interface/main-handler/encounter/handler.go index 22d1d8cf..c8fcfa1a 100644 --- a/internal/interface/main-handler/encounter/handler.go +++ b/internal/interface/main-handler/encounter/handler.go @@ -89,9 +89,14 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { if id <= 0 { return } + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } dto := e.DeleteDto{} dto.Id = uint16(id) + dto.AuthInfo = *authInfo res, err := u.Delete(dto) rw.DataResponse(w, res, err) } @@ -159,11 +164,17 @@ func (obj myBase) Cancel(w http.ResponseWriter, r *http.Request) { return } + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + dto := e.UpdateStatusDto{ Id: uint16(id), StatusCode: erc.DSCCancel, } + dto.AuthInfo = *authInfo res, err := u.UpdateStatusCode(dto) rw.DataResponse(w, res, err) } diff --git a/internal/lib/auth/tycovar.go b/internal/lib/auth/tycovar.go index 467bd1b6..3567cd61 100644 --- a/internal/lib/auth/tycovar.go +++ b/internal/lib/auth/tycovar.go @@ -11,7 +11,7 @@ type AuthInfo struct { Uuid string User_Id uint User_Name string - User_ContractPosition_code string + User_ContractPosition_Code string Employee_Position_Code *string Employee_Id *uint Doctor_Code *string diff --git a/internal/use-case/main-use-case/authentication/case.go b/internal/use-case/main-use-case/authentication/case.go index 15f18ef8..db83d315 100644 --- a/internal/use-case/main-use-case/authentication/case.go +++ b/internal/use-case/main-use-case/authentication/case.go @@ -205,7 +205,7 @@ func ExtractToken(r *http.Request, tokenType TokenType) (data *pa.AuthInfo, err User_Name: fmt.Sprintf("%v", claims["user_name"]), } - data.User_ContractPosition_code = checkStrClaims(claims, "contractPosition_code") + data.User_ContractPosition_Code = checkStrClaims(claims, "contractPosition_code") data.Employee_Position_Code = checkStrPtrClaims(claims, "employee_position_code") data.Doctor_Code = checkStrPtrClaims(claims, "doctor_code") data.Nurse_Code = checkStrPtrClaims(claims, "nurse_code") diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 9381e639..8a006a35 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -16,10 +16,10 @@ import ( erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" + erg "simrs-vx/internal/domain/references/organization" eaeh "simrs-vx/internal/domain/main-entities/adm-employee-hist" edc "simrs-vx/internal/domain/main-entities/death-cause" - eem "simrs-vx/internal/domain/main-entities/employee" e "simrs-vx/internal/domain/main-entities/encounter" eir "simrs-vx/internal/domain/main-entities/internal-reference" erdh "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" @@ -27,7 +27,6 @@ import ( uaeh "simrs-vx/internal/use-case/main-use-case/adm-employee-hist" udc "simrs-vx/internal/use-case/main-use-case/death-cause" - uem "simrs-vx/internal/use-case/main-use-case/employee" uir "simrs-vx/internal/use-case/main-use-case/internal-reference" urdh "simrs-vx/internal/use-case/main-use-case/responsible-doctor-hist" ) @@ -79,6 +78,19 @@ func Create(input e.CreateDto) (*d.Data, error) { } } + // check only user with registration position is allowed to create encounter + if input.AuthInfo.User_ContractPosition_Code != string(erg.EPCReg) { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "auth-forbidden", + Detail: "user position is not allowed, only user with registration position is allowed to create encounter", + Raw: errors.New("authentication failed"), + } + return nil, pl.SetLogError(&event, input) + } else { + input.Adm_Employee_Id = input.AuthInfo.Employee_Id + } + // check if patient is new in the hospital input.NewStatus, err = identifyPatientStatus(input) @@ -90,12 +102,6 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } - if emp, err := uem.ReadDetailData(eem.ReadDetailDto{User_Id: &input.AuthInfo.User_Id}, &event, tx); err != nil { - return err - } else { - input.Adm_Employee_Id = &emp.Id - } - // create encounter if resData, err := CreateData(input, &event, tx); err != nil { return err @@ -322,6 +328,17 @@ func Delete(input e.DeleteDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "delete") + // check only user with registration position is allowed to create encounter + if input.AuthInfo.User_ContractPosition_Code != string(erg.EPCReg) { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "auth-forbidden", + Detail: "user position is not allowed, only user with registration position is allowed to create encounter", + Raw: errors.New("authentication failed"), + } + return nil, pl.SetLogError(&event, input) + } + err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") if data, err = ReadDetailData(rdDto, &event, tx); err != nil { @@ -494,6 +511,21 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) { // TODO: Prevent cancellation if the billing has been verified // TODO: Only "supervisi pendaftaran" could cancel encounter + roleAllowedToCancel := []string{ + string(erg.EPCReg), + string(erg.EPCNur), + string(erg.EPCDoc), + } + + if !pu.Contains(roleAllowedToCancel, input.AuthInfo.User_ContractPosition_Code) { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "auth-forbidden", + Detail: "user position is not allowed, only user with registration, nurse, or doctor position is allowed to cancel encounter", + Raw: errors.New("authentication failed"), + } + return pl.SetLogError(&event, input) + } // Prevent cancellation if soapi exist encounterId := uint(input.Id) diff --git a/pkg/use-case-helper/use-case-helper.go b/pkg/use-case-helper/use-case-helper.go index a80595bb..07df05ba 100644 --- a/pkg/use-case-helper/use-case-helper.go +++ b/pkg/use-case-helper/use-case-helper.go @@ -150,3 +150,19 @@ func IsDateBeforeNow(t *time.Time) bool { } return t.Before(time.Now()) } + +// Contains reports whether v is present in s. +func Contains[S ~[]E, E comparable](s S, v E) bool { + return index(s, v) >= 0 +} + +// Index returns the index of the first occurrence of v in s, +// or -1 if not present. +func index[S ~[]E, E comparable](s S, v E) int { + for i := range s { + if v == s[i] { + return i + } + } + return -1 +} From 3720ca2e718206292e08eb753b5ddf9c78cd6de9 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Sat, 8 Nov 2025 06:07:14 +0700 Subject: [PATCH 175/329] feat/sso-auth: wip --- .../main-handler/authentication/handler.go | 28 +- .../main-use-case/authentication/case.go | 332 ++++++++++++------ .../main-use-case/authentication/helper.go | 122 +++++++ 3 files changed, 368 insertions(+), 114 deletions(-) diff --git a/internal/interface/main-handler/authentication/handler.go b/internal/interface/main-handler/authentication/handler.go index 709f33a3..fc36dc52 100644 --- a/internal/interface/main-handler/authentication/handler.go +++ b/internal/interface/main-handler/authentication/handler.go @@ -6,11 +6,13 @@ import ( d "github.com/karincake/dodol" rw "github.com/karincake/risoles" + sp "github.com/karincake/semprit" + sr "github.com/karincake/serabi" m "simrs-vx/internal/domain/main-entities/user" - s "simrs-vx/internal/use-case/main-use-case/authentication" - + mf "simrs-vx/internal/domain/main-entities/user-fes" pa "simrs-vx/internal/lib/auth" + s "simrs-vx/internal/use-case/main-use-case/authentication" ) func Login(w http.ResponseWriter, r *http.Request) { @@ -50,3 +52,25 @@ func GuardMW(next http.Handler) http.Handler { next.ServeHTTP(w, r.WithContext(ctx)) }) } + +func LoginFes(w http.ResponseWriter, r *http.Request) { + var input mf.LoginDto + err := sp.IOReaderJson(input, r.Body) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil) + } + + input.AuthPartner_Code = r.Header.Get("X-AuthPartner-Code") + input.AuthPartner_SecretKey = r.Header.Get("X-AuthPartner-SecretKey") + if err = (sr.Validate(input)); err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil) + } + + // input.Position = Position + res, err := s.GenTokenFes(input) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil) + } else { + rw.DataResponse(w, res, err) + } +} diff --git a/internal/use-case/main-use-case/authentication/case.go b/internal/use-case/main-use-case/authentication/case.go index bd9dcee6..061677d4 100644 --- a/internal/use-case/main-use-case/authentication/case.go +++ b/internal/use-case/main-use-case/authentication/case.go @@ -19,16 +19,9 @@ import ( pl "simrs-vx/pkg/logger" p "simrs-vx/pkg/password" - ed "simrs-vx/internal/domain/main-entities/doctor" - ee "simrs-vx/internal/domain/main-entities/employee" - "simrs-vx/internal/domain/main-entities/intern" - em "simrs-vx/internal/domain/main-entities/midwife" - en "simrs-vx/internal/domain/main-entities/nurse" - ep "simrs-vx/internal/domain/main-entities/pharmacist" eu "simrs-vx/internal/domain/main-entities/user" - + euf "simrs-vx/internal/domain/main-entities/user-fes" erc "simrs-vx/internal/domain/references/common" - erg "simrs-vx/internal/domain/references/organization" ) const source = "authentication" @@ -115,121 +108,150 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { } // extra - role := []string{} - switch user.ContractPosition_Code { - case erg.CSCEmp: - // employee - employee := ee.Employee{} - dg.I.Where("\"User_Id\" = ?", user.Id).First(&employee) - if employee.Id == 0 { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noEmployee", Message: pl.GenMessage("auth-noEmployee")}} - } - atClaims["employee_id"] = employee.Id - outputData["employee_id"] = employee.Id - role = append(role, "emp-"+string(*employee.Position_Code)) + // role := []string{} + // switch user.ContractPosition_Code { + // case erg.CSCEmp: + // // employee + // employee := ee.Employee{} + // dg.I.Where("\"User_Id\" = ?", user.Id).First(&employee) + // if employee.Id == 0 { + // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noEmployee", Message: pl.GenMessage("auth-noEmployee")}} + // } + // atClaims["employee_id"] = employee.Id + // outputData["employee_id"] = employee.Id + // role = append(role, "emp-"+string(*employee.Position_Code)) - //if employee.Division_Code != nil { - // atClaims["employee_division_code"] = employee.Division_Code - // outputData["employee_division_code"] = employee.Division_Code - //} + // //if employee.Division_Code != nil { + // // atClaims["employee_division_code"] = employee.Division_Code + // // outputData["employee_division_code"] = employee.Division_Code + // //} - // employee position - if employee.Id > 0 && employee.Position_Code != nil { - atClaims["employee_position_code"] = *employee.Position_Code - switch *employee.Position_Code { - case erg.EPCDoc: - doctor := ed.Doctor{} - dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&doctor) - if doctor.Id == 0 { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noDoctor", Message: pl.GenMessage("auth-noDoctor")}} - } - atClaims["doctor_code"] = doctor.Code - outputData["doctor_code"] = doctor.Code + // // employee position + // if employee.Id > 0 && employee.Position_Code != nil { + // atClaims["employee_position_code"] = *employee.Position_Code + // switch *employee.Position_Code { + // case erg.EPCDoc: + // doctor := ed.Doctor{} + // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&doctor) + // if doctor.Id == 0 { + // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noDoctor", Message: pl.GenMessage("auth-noDoctor")}} + // } + // atClaims["doctor_code"] = doctor.Code + // outputData["doctor_code"] = doctor.Code - // specialist - if doctor.Specialist_Code != nil { - atClaims["specialist_code"] = doctor.Specialist_Code - outputData["specialist_code"] = doctor.Specialist_Code - } - if doctor.Subspecialist_Code != nil { - atClaims["subspecialist_code"] = doctor.Subspecialist_Code - outputData["subspecialist_code"] = doctor.Subspecialist_Code - } - case erg.EPCNur: - empData := en.Nurse{} - dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) - if empData.Id == 0 { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: pl.GenMessage("auth-noNurse")}} - } - atClaims["nurse_code"] = empData.Code - outputData["nurse_code"] = empData.Code - case erg.EPCMwi: - empData := em.Midwife{} - dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) - if empData.Id == 0 { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noMidwife", Message: pl.GenMessage("auth-noMidwife")}} - } - atClaims["midwife_code"] = empData.Code - outputData["midwife_code"] = empData.Code - case erg.EPCPha: - empData := ep.Pharmacist{} - dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) - if empData.Id == 0 { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noPharmacist", Message: pl.GenMessage("auth-noPharmacist")}} - } - atClaims["pharmacist_code"] = empData.Code - outputData["pharmacist_code"] = empData.Code - } + // // specialist + // if doctor.Specialist_Code != nil { + // atClaims["specialist_code"] = doctor.Specialist_Code + // outputData["specialist_code"] = doctor.Specialist_Code + // } + // if doctor.Subspecialist_Code != nil { + // atClaims["subspecialist_code"] = doctor.Subspecialist_Code + // outputData["subspecialist_code"] = doctor.Subspecialist_Code + // } + // case erg.EPCNur: + // empData := en.Nurse{} + // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + // if empData.Id == 0 { + // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: pl.GenMessage("auth-noNurse")}} + // } + // atClaims["nurse_code"] = empData.Code + // outputData["nurse_code"] = empData.Code + // case erg.EPCMwi: + // empData := em.Midwife{} + // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + // if empData.Id == 0 { + // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noMidwife", Message: pl.GenMessage("auth-noMidwife")}} + // } + // atClaims["midwife_code"] = empData.Code + // outputData["midwife_code"] = empData.Code + // case erg.EPCPha: + // empData := ep.Pharmacist{} + // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + // if empData.Id == 0 { + // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noPharmacist", Message: pl.GenMessage("auth-noPharmacist")}} + // } + // atClaims["pharmacist_code"] = empData.Code + // outputData["pharmacist_code"] = empData.Code + // } + // // specialist + // if doctor.Specialist_Code != nil { + // atClaims["specialist_code"] = doctor.Specialist_Code + // outputData["specialist_code"] = doctor.Specialist_Code + // } + // if doctor.Subspecialist_Code != nil { + // atClaims["subspecialist_code"] = doctor.Subspecialist_Code + // outputData["subspecialist_code"] = doctor.Subspecialist_Code + // } + // case erg.EPCNur: + // empData := en.Nurse{} + // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + // if empData.Id == 0 { + // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: pl.GenMessage("auth-noNurse")}} + // } + // atClaims["nurse_code"] = empData.Code + // outputData["nurse_code"] = empData.Code + // case erg.EPCMwi: + // empData := em.Midwife{} + // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + // if empData.Id == 0 { + // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noMidwife", Message: pl.GenMessage("auth-noMidwife")}} + // } + // atClaims["midwife_code"] = empData.Code + // outputData["midwife_code"] = empData.Code + // } - errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: pl.GenMessage("auth-getData-failed")}} + // errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: pl.GenMessage("auth-getData-failed")}} - // division position - divisionPositions, err := getDivisionPosition(employee.Id, &event) - if err != nil { - return nil, errorGetPosition - } + // // division position + // divisionPositions, err := getDivisionPosition(employee.Id, &event) + // if err != nil { + // return nil, errorGetPosition + // } - // installation position - installationPositions, err := getInstallationPosition(employee.Id, &event) - if err != nil { - return nil, errorGetPosition - } + // // installation position + // installationPositions, err := getInstallationPosition(employee.Id, &event) + // if err != nil { + // return nil, errorGetPosition + // } - // unit position - unitPositions, err := getUnitPosition(employee.Id, &event) - if err != nil { - return nil, errorGetPosition - } + // // unit position + // unitPositions, err := getUnitPosition(employee.Id, &event) + // if err != nil { + // return nil, errorGetPosition + // } - // specialist position - specialistPositions, err := getSpecialistPosition(employee.Id, &event) - if err != nil { - return nil, errorGetPosition - } + // // specialist position + // specialistPositions, err := getSpecialistPosition(employee.Id, &event) + // if err != nil { + // return nil, errorGetPosition + // } - // subspecialist position - subspecialistPositions, err := getSubspecialistPosition(employee.Id, &event) - if err != nil { - return nil, errorGetPosition - } + // // subspecialist position + // subspecialistPositions, err := getSubspecialistPosition(employee.Id, &event) + // if err != nil { + // return nil, errorGetPosition + // } - role = append(role, divisionPositions...) - role = append(role, installationPositions...) - role = append(role, unitPositions...) - role = append(role, specialistPositions...) - role = append(role, subspecialistPositions...) - // atClaims["division_positions"] = divsionPositions - // outputData["division_positions"] = divsionPositions - } - case erg.CSCInt: - intern := intern.Intern{} - dg.I.Where("\"User_Id\" = ?", user.Id).First(&intern) - role = append(role, "int-"+string(*intern.Position_Code)) - case erg.CSCSys: - role = append(role, "system") + // role = append(role, divisionPositions...) + // role = append(role, installationPositions...) + // role = append(role, unitPositions...) + // role = append(role, specialistPositions...) + // role = append(role, subspecialistPositions...) + // // atClaims["division_positions"] = divsionPositions + // // outputData["division_positions"] = divsionPositions + // } + // case erg.CSCInt: + // intern := intern.Intern{} + // dg.I.Where("\"User_Id\" = ?", user.Id).First(&intern) + // role = append(role, "int-"+string(*intern.Position_Code)) + // case erg.CSCSys: + // role = append(role, "system") + // } + // atClaims["roles"] = role + // outputData["roles"] = role + if err := populateRoles(user, atClaims, outputData, event); err != nil { + return nil, err } - atClaims["roles"] = role - outputData["roles"] = role // Generate jwt at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims) @@ -339,3 +361,89 @@ func ExtractToken(r *http.Request, tokenType TokenType) (data *pa.AuthInfo, err func GetConfig() { a.ParseCfg(&authCfg) } + +func GenTokenFes(input euf.LoginDto) (*d.Data, error) { + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Get User Fes + userFes := &euf.UserFes{Name: input.Name, AuthPartner_Code: input.AuthPartner_Code} + if errCode := getAndCheck(userFes, userFes); errCode != "" { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: errCode, Message: pl.GenMessage(errCode)}} + } + if userFes.AuthPartner.SecretKey != input.AuthPartner_SecretKey { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-secretKey-invalid", Message: pl.GenMessage("auth-secretKey-invalid")}} + } + + user := &eu.User{Name: userFes.User_Name} + if errCode := getAndCheck(user, user); errCode != "" { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: errCode, Message: pl.GenMessage(errCode)}} + } + + // Access token prep + id, err := uuid.NewRandom() + if err != nil { + panic(fmt.Sprintf(l.I.Msg("uuid-gen-fail"), err)) + } + if input.Duration == 0 { + input.Duration = 24 * 60 + } + duration := time.Minute * time.Duration(input.Duration) + aUuid := id.String() + atExpires := time.Now().Add(duration).Unix() + atSecretKey := authCfg.AtSecretKey + + // Create Claim + atClaims := jwt.MapClaims{} + atClaims["user_id"] = user.Id + atClaims["user_name"] = user.Name + atClaims["user_contractPosition_code"] = user.ContractPosition_Code + atClaims["uuid"] = aUuid + atClaims["exp"] = atExpires + + // Create output + outputData := d.II{ + "user_id": strconv.Itoa(int(user.Id)), + "user_name": user.Name, + "user_contractPosition_code": user.ContractPosition_Code, + } + + // extra + if err := populateRoles(user, atClaims, outputData, event); err != nil { + return nil, err + } + + // Generate jwt + at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims) + ats, err := at.SignedString([]byte(atSecretKey)) + if err != nil { + return nil, d.FieldErrors{"user": d.FieldError{Code: "token-sign-err", Message: pl.GenMessage("token-sign-err")}} + } + outputData["accessToken"] = ats + + // Save to redis + now := time.Now() + atx := time.Unix(atExpires, 0) //converting Unix to UTC(to Time object) + err = ms.I.Set(aUuid, strconv.Itoa(int(user.Id)), atx.Sub(now)).Err() + if err != nil { + panic(fmt.Sprintf(l.I.Msg("redis-store-fail"), err.Error())) + } + + tn := time.Now() + user.LoginAttemptCount = 0 + user.LastSuccessLogin = &tn + user.LastAllowdLogin = &tn + dg.I.Save(&user) + + // Current data + return &d.Data{ + Meta: d.IS{ + "source": "authentication", + "structure": "single-data", + "status": "verified", + }, + Data: outputData, + }, nil +} diff --git a/internal/use-case/main-use-case/authentication/helper.go b/internal/use-case/main-use-case/authentication/helper.go index a919cfe9..0da9f943 100644 --- a/internal/use-case/main-use-case/authentication/helper.go +++ b/internal/use-case/main-use-case/authentication/helper.go @@ -3,13 +3,23 @@ package authentication import ( dg "github.com/karincake/apem/db-gorm-pg" + "github.com/golang-jwt/jwt" + d "github.com/karincake/dodol" + pl "simrs-vx/pkg/logger" 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" eip "simrs-vx/internal/domain/main-entities/installation-position" + "simrs-vx/internal/domain/main-entities/intern" + em "simrs-vx/internal/domain/main-entities/midwife" + en "simrs-vx/internal/domain/main-entities/nurse" esp "simrs-vx/internal/domain/main-entities/specialist-position" 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" @@ -162,3 +172,115 @@ func checkUntPtrClaims(claim map[string]interface{}, key string) *uint { } return nil } + +func populateRoles(user *eu.User, atClaims jwt.MapClaims, outputData d.II, event pl.Event) error { + roles := []string{} + switch user.ContractPosition_Code { + case erg.CSCEmp: + // employee + employee := ee.Employee{} + dg.I.Where("\"User_Id\" = ?", user.Id).First(&employee) + if employee.Id == 0 { + return d.FieldErrors{"authentication": d.FieldError{Code: "auth-noEmployee", Message: pl.GenMessage("auth-noEmployee")}} + } + atClaims["employee_id"] = employee.Id + outputData["employee_id"] = employee.Id + roles = append(roles, "emp-"+string(*employee.Position_Code)) + + //if employee.Division_Code != nil { + // atClaims["employee_division_code"] = employee.Division_Code + // outputData["employee_division_code"] = employee.Division_Code + //} + + // employee position + if employee.Id > 0 && employee.Position_Code != nil { + atClaims["employee_position_code"] = *employee.Position_Code + switch *employee.Position_Code { + case erg.EPCDoc: + doctor := ed.Doctor{} + dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&doctor) + if doctor.Id == 0 { + return d.FieldErrors{"authentication": d.FieldError{Code: "auth-noDoctor", Message: pl.GenMessage("auth-noDoctor")}} + } + atClaims["doctor_code"] = doctor.Code + outputData["doctor_code"] = doctor.Code + + // specialist + if doctor.Specialist_Code != nil { + atClaims["specialist_code"] = doctor.Specialist_Code + outputData["specialist_code"] = doctor.Specialist_Code + } + if doctor.Subspecialist_Code != nil { + atClaims["subspecialist_code"] = doctor.Subspecialist_Code + outputData["subspecialist_code"] = doctor.Subspecialist_Code + } + case erg.EPCNur: + empData := en.Nurse{} + dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + if empData.Id == 0 { + return d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: pl.GenMessage("auth-noNurse")}} + } + atClaims["nurse_code"] = empData.Code + outputData["nurse_code"] = empData.Code + case erg.EPCMwi: + empData := em.Midwife{} + dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + if empData.Id == 0 { + return d.FieldErrors{"authentication": d.FieldError{Code: "auth-noMidwife", Message: pl.GenMessage("auth-noMidwife")}} + } + atClaims["midwife_code"] = empData.Code + outputData["midwife_code"] = empData.Code + } + + errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: pl.GenMessage("auth-getData-failed")}} + + // division position + divisionPositions, err := getDivisionPosition(employee.Id, &event) + if err != nil { + return errorGetPosition + } + + // installation position + installationPositions, err := getInstallationPosition(employee.Id, &event) + if err != nil { + return errorGetPosition + } + + // unit position + unitPositions, err := getUnitPosition(employee.Id, &event) + if err != nil { + return errorGetPosition + } + + // specialist position + specialistPositions, err := getSpecialistPosition(employee.Id, &event) + if err != nil { + return errorGetPosition + } + + // subspecialist position + subspecialistPositions, err := getSubspecialistPosition(employee.Id, &event) + if err != nil { + return errorGetPosition + } + + roles = append(roles, divisionPositions...) + roles = append(roles, installationPositions...) + roles = append(roles, unitPositions...) + roles = append(roles, specialistPositions...) + roles = append(roles, subspecialistPositions...) + // atClaims["division_positions"] = divsionPositions + // outputData["division_positions"] = divsionPositions + } + case erg.CSCInt: + intern := intern.Intern{} + dg.I.Where("\"User_Id\" = ?", user.Id).First(&intern) + roles = append(roles, "int-"+string(*intern.Position_Code)) + case erg.CSCSys: + roles = append(roles, "system") + } + + atClaims["roles"] = roles + outputData["roles"] = roles + return nil +} From 5aa45088f401ad4164797586ca40a81f3ab2ac82 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Mon, 10 Nov 2025 22:53:32 +0700 Subject: [PATCH 176/329] feat/sso-auth: added the use cases --- internal/domain/main-entities/user-fes/dto.go | 11 +- internal/lib/auth/tycovar.go | 2 +- .../main-use-case/auth-partner/case.go | 276 +++++++++++ .../main-use-case/auth-partner/helper.go | 19 + .../main-use-case/auth-partner/lib.go | 150 ++++++ .../auth-partner/middleware-runner.go | 103 ++++ .../main-use-case/auth-partner/middleware.go | 9 + .../main-use-case/auth-partner/tycovar.go | 44 ++ .../main-use-case/authentication/case.go | 332 ++----------- .../main-use-case/authentication/case.go.bu | 463 ++++++++++++++++++ .../main-use-case/authentication/helper.go | 116 +++-- .../main-use-case/authentication/helper.go.bu | 323 ++++++++++++ .../use-case/main-use-case/user-fes/case.go | 276 +++++++++++ .../use-case/main-use-case/user-fes/helper.go | 18 + .../use-case/main-use-case/user-fes/lib.go | 143 ++++++ .../user-fes/middleware-runner.go | 103 ++++ .../main-use-case/user-fes/middleware.go | 5 + .../main-use-case/user-fes/tycovar.go | 44 ++ 18 files changed, 2121 insertions(+), 316 deletions(-) create mode 100644 internal/use-case/main-use-case/auth-partner/case.go create mode 100644 internal/use-case/main-use-case/auth-partner/helper.go create mode 100644 internal/use-case/main-use-case/auth-partner/lib.go create mode 100644 internal/use-case/main-use-case/auth-partner/middleware-runner.go create mode 100644 internal/use-case/main-use-case/auth-partner/middleware.go create mode 100644 internal/use-case/main-use-case/auth-partner/tycovar.go create mode 100644 internal/use-case/main-use-case/authentication/case.go.bu create mode 100644 internal/use-case/main-use-case/authentication/helper.go.bu create mode 100644 internal/use-case/main-use-case/user-fes/case.go create mode 100644 internal/use-case/main-use-case/user-fes/helper.go create mode 100644 internal/use-case/main-use-case/user-fes/lib.go create mode 100644 internal/use-case/main-use-case/user-fes/middleware-runner.go create mode 100644 internal/use-case/main-use-case/user-fes/middleware.go create mode 100644 internal/use-case/main-use-case/user-fes/tycovar.go diff --git a/internal/domain/main-entities/user-fes/dto.go b/internal/domain/main-entities/user-fes/dto.go index 6cb3636b..3cf9d68e 100644 --- a/internal/domain/main-entities/user-fes/dto.go +++ b/internal/domain/main-entities/user-fes/dto.go @@ -41,6 +41,13 @@ type DeleteDto struct { Id uint `json:"id"` } +type LoginDto struct { + Name string `json:"name" validate:"required"` + Duration uint32 `json:"duration"` + AuthPartner_Code string `json:"X-AuthPartner-Code" validate:"required"` + AuthPartner_SecretKey string `json:"X-AuthPartner-SecretKey" validate:"required"` +} + type MetaDto struct { PageNumber int `json:"page_number"` PageSize int `json:"page_size"` @@ -59,8 +66,8 @@ func (d UserFes) ToResponse() ResponseDto { resp := ResponseDto{ Name: d.Name, AuthPartner_Code: d.AuthPartner_Code, - AuthPartner: d.AuthPartner, - User_Name: d.User_Name, + // AuthPartner: d.AuthPartner, + User_Name: d.User_Name, } resp.Main = d.Main return resp diff --git a/internal/lib/auth/tycovar.go b/internal/lib/auth/tycovar.go index 467bd1b6..3567cd61 100644 --- a/internal/lib/auth/tycovar.go +++ b/internal/lib/auth/tycovar.go @@ -11,7 +11,7 @@ type AuthInfo struct { Uuid string User_Id uint User_Name string - User_ContractPosition_code string + User_ContractPosition_Code string Employee_Position_Code *string Employee_Id *uint Doctor_Code *string diff --git a/internal/use-case/main-use-case/auth-partner/case.go b/internal/use-case/main-use-case/auth-partner/case.go new file mode 100644 index 00000000..f5f7b423 --- /dev/null +++ b/internal/use-case/main-use-case/auth-partner/case.go @@ -0,0 +1,276 @@ +package authpartner + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/auth-partner" + "strconv" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" +) + +const source = "device" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.AuthPartner{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.AuthPartner + var dataList []e.AuthPartner + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.AuthPartner + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: &input.Id} + var data *e.AuthPartner + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: &input.Id} + var data *e.AuthPartner + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/auth-partner/helper.go b/internal/use-case/main-use-case/auth-partner/helper.go new file mode 100644 index 00000000..36e1ce7b --- /dev/null +++ b/internal/use-case/main-use-case/auth-partner/helper.go @@ -0,0 +1,19 @@ +package authpartner + +import ( + e "simrs-vx/internal/domain/main-entities/auth-partner" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.AuthPartner) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Code = inputSrc.Code + data.Name = inputSrc.Name + data.SecretKey = inputSrc.SecretKey +} diff --git a/internal/use-case/main-use-case/auth-partner/lib.go b/internal/use-case/main-use-case/auth-partner/lib.go new file mode 100644 index 00000000..41253e2c --- /dev/null +++ b/internal/use-case/main-use-case/auth-partner/lib.go @@ -0,0 +1,150 @@ +package authpartner + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/auth-partner" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.AuthPartner, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.AuthPartner{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.AuthPartner, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.AuthPartner{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.AuthPartner{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.AuthPartner, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.AuthPartner{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx. + Scopes(gh.Preload(input.Includes)). + First(&data).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.AuthPartner, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.AuthPartner, 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 +} diff --git a/internal/use-case/main-use-case/auth-partner/middleware-runner.go b/internal/use-case/main-use-case/auth-partner/middleware-runner.go new file mode 100644 index 00000000..d1cabe38 --- /dev/null +++ b/internal/use-case/main-use-case/auth-partner/middleware-runner.go @@ -0,0 +1,103 @@ +package authpartner + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/auth-partner" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" +) + +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.AuthPartner) 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.AuthPartner) 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.AuthPartner) 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.AuthPartner) 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.AuthPartner) 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/main-use-case/auth-partner/middleware.go b/internal/use-case/main-use-case/auth-partner/middleware.go new file mode 100644 index 00000000..4ec1231f --- /dev/null +++ b/internal/use-case/main-use-case/auth-partner/middleware.go @@ -0,0 +1,9 @@ +package authpartner + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/auth-partner/tycovar.go b/internal/use-case/main-use-case/auth-partner/tycovar.go new file mode 100644 index 00000000..43f69d98 --- /dev/null +++ b/internal/use-case/main-use-case/auth-partner/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 authpartner + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/auth-partner" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.AuthPartner, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.AuthPartner, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.AuthPartner, 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/main-use-case/authentication/case.go b/internal/use-case/main-use-case/authentication/case.go index 061677d4..db83d315 100644 --- a/internal/use-case/main-use-case/authentication/case.go +++ b/internal/use-case/main-use-case/authentication/case.go @@ -8,7 +8,6 @@ import ( "time" "github.com/golang-jwt/jwt" - "github.com/google/uuid" a "github.com/karincake/apem" dg "github.com/karincake/apem/db-gorm-pg" ms "github.com/karincake/apem/ms-redis" @@ -19,6 +18,7 @@ import ( pl "simrs-vx/pkg/logger" p "simrs-vx/pkg/password" + eap "simrs-vx/internal/domain/main-entities/auth-partner" eu "simrs-vx/internal/domain/main-entities/user" euf "simrs-vx/internal/domain/main-entities/user-fes" erc "simrs-vx/internal/domain/references/common" @@ -42,13 +42,11 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { // Get User user := &eu.User{Name: input.Name} - // if input.Position_Code != "" { - // user.Position_Code = input.Position_Code - // } - if errCode := getAndCheck(user, user); errCode != "" { + if errCode := getAndCheck(user, user, nil); errCode != "" { return nil, d.FieldErrors{"authentication": d.FieldError{Code: errCode, Message: pl.GenMessage(errCode)}} } + // Check login attempt if user.LoginAttemptCount > 5 { if user.LastSuccessLogin != nil { now := time.Now() @@ -69,6 +67,7 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { } } + // Check password if !p.Check(input.Password, user.Password) { user.LoginAttemptCount++ dg.I.Save(&user) @@ -79,196 +78,14 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-login-unverified", Message: pl.GenMessage("auth-login-unverified")}} } - // Access token prep - id, err := uuid.NewRandom() - if err != nil { - panic(fmt.Sprintf(l.I.Msg("uuid-gen-fail"), err)) - } - if input.Duration == 0 { - input.Duration = 24 * 60 - } - duration := time.Minute * time.Duration(input.Duration) - aUuid := id.String() - atExpires := time.Now().Add(duration).Unix() - atSecretKey := authCfg.AtSecretKey - - // Create Claim + // Data and output population atClaims := jwt.MapClaims{} - atClaims["user_id"] = user.Id - atClaims["user_name"] = user.Name - atClaims["user_contractPosition_code"] = user.ContractPosition_Code - atClaims["uuid"] = aUuid - atClaims["exp"] = atExpires - - // Create output - outputData := d.II{ - "user_id": strconv.Itoa(int(user.Id)), - "user_name": user.Name, - "user_contractPosition_code": user.ContractPosition_Code, - } - - // extra - // role := []string{} - // switch user.ContractPosition_Code { - // case erg.CSCEmp: - // // employee - // employee := ee.Employee{} - // dg.I.Where("\"User_Id\" = ?", user.Id).First(&employee) - // if employee.Id == 0 { - // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noEmployee", Message: pl.GenMessage("auth-noEmployee")}} - // } - // atClaims["employee_id"] = employee.Id - // outputData["employee_id"] = employee.Id - // role = append(role, "emp-"+string(*employee.Position_Code)) - - // //if employee.Division_Code != nil { - // // atClaims["employee_division_code"] = employee.Division_Code - // // outputData["employee_division_code"] = employee.Division_Code - // //} - - // // employee position - // if employee.Id > 0 && employee.Position_Code != nil { - // atClaims["employee_position_code"] = *employee.Position_Code - // switch *employee.Position_Code { - // case erg.EPCDoc: - // doctor := ed.Doctor{} - // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&doctor) - // if doctor.Id == 0 { - // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noDoctor", Message: pl.GenMessage("auth-noDoctor")}} - // } - // atClaims["doctor_code"] = doctor.Code - // outputData["doctor_code"] = doctor.Code - - // // specialist - // if doctor.Specialist_Code != nil { - // atClaims["specialist_code"] = doctor.Specialist_Code - // outputData["specialist_code"] = doctor.Specialist_Code - // } - // if doctor.Subspecialist_Code != nil { - // atClaims["subspecialist_code"] = doctor.Subspecialist_Code - // outputData["subspecialist_code"] = doctor.Subspecialist_Code - // } - // case erg.EPCNur: - // empData := en.Nurse{} - // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) - // if empData.Id == 0 { - // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: pl.GenMessage("auth-noNurse")}} - // } - // atClaims["nurse_code"] = empData.Code - // outputData["nurse_code"] = empData.Code - // case erg.EPCMwi: - // empData := em.Midwife{} - // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) - // if empData.Id == 0 { - // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noMidwife", Message: pl.GenMessage("auth-noMidwife")}} - // } - // atClaims["midwife_code"] = empData.Code - // outputData["midwife_code"] = empData.Code - // case erg.EPCPha: - // empData := ep.Pharmacist{} - // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) - // if empData.Id == 0 { - // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noPharmacist", Message: pl.GenMessage("auth-noPharmacist")}} - // } - // atClaims["pharmacist_code"] = empData.Code - // outputData["pharmacist_code"] = empData.Code - // } - // // specialist - // if doctor.Specialist_Code != nil { - // atClaims["specialist_code"] = doctor.Specialist_Code - // outputData["specialist_code"] = doctor.Specialist_Code - // } - // if doctor.Subspecialist_Code != nil { - // atClaims["subspecialist_code"] = doctor.Subspecialist_Code - // outputData["subspecialist_code"] = doctor.Subspecialist_Code - // } - // case erg.EPCNur: - // empData := en.Nurse{} - // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) - // if empData.Id == 0 { - // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: pl.GenMessage("auth-noNurse")}} - // } - // atClaims["nurse_code"] = empData.Code - // outputData["nurse_code"] = empData.Code - // case erg.EPCMwi: - // empData := em.Midwife{} - // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) - // if empData.Id == 0 { - // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noMidwife", Message: pl.GenMessage("auth-noMidwife")}} - // } - // atClaims["midwife_code"] = empData.Code - // outputData["midwife_code"] = empData.Code - // } - - // errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: pl.GenMessage("auth-getData-failed")}} - - // // division position - // divisionPositions, err := getDivisionPosition(employee.Id, &event) - // if err != nil { - // return nil, errorGetPosition - // } - - // // installation position - // installationPositions, err := getInstallationPosition(employee.Id, &event) - // if err != nil { - // return nil, errorGetPosition - // } - - // // unit position - // unitPositions, err := getUnitPosition(employee.Id, &event) - // if err != nil { - // return nil, errorGetPosition - // } - - // // specialist position - // specialistPositions, err := getSpecialistPosition(employee.Id, &event) - // if err != nil { - // return nil, errorGetPosition - // } - - // // subspecialist position - // subspecialistPositions, err := getSubspecialistPosition(employee.Id, &event) - // if err != nil { - // return nil, errorGetPosition - // } - - // role = append(role, divisionPositions...) - // role = append(role, installationPositions...) - // role = append(role, unitPositions...) - // role = append(role, specialistPositions...) - // role = append(role, subspecialistPositions...) - // // atClaims["division_positions"] = divsionPositions - // // outputData["division_positions"] = divsionPositions - // } - // case erg.CSCInt: - // intern := intern.Intern{} - // dg.I.Where("\"User_Id\" = ?", user.Id).First(&intern) - // role = append(role, "int-"+string(*intern.Position_Code)) - // case erg.CSCSys: - // role = append(role, "system") - // } - // atClaims["roles"] = role - // outputData["roles"] = role - if err := populateRoles(user, atClaims, outputData, event); err != nil { + outputData := d.II{} + if err := populateRoles(user, input, atClaims, outputData, event); err != nil { return nil, err } - // Generate jwt - at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims) - ats, err := at.SignedString([]byte(atSecretKey)) - if err != nil { - return nil, d.FieldErrors{"user": d.FieldError{Code: "token-sign-err", Message: pl.GenMessage("token-sign-err")}} - } - outputData["accessToken"] = ats - - // Save to redis - now := time.Now() - atx := time.Unix(atExpires, 0) //converting Unix to UTC(to Time object) - err = ms.I.Set(aUuid, strconv.Itoa(int(user.Id)), atx.Sub(now)).Err() - if err != nil { - panic(fmt.Sprintf(l.I.Msg("redis-store-fail"), err.Error())) - } - + // Only manual login tn := time.Now() user.LoginAttemptCount = 0 user.LastSuccessLogin = &tn @@ -286,6 +103,51 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { }, nil } +func GenTokenFes(input euf.LoginDto) (*d.Data, error) { + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Get User Fes + userFes := &euf.UserFes{Name: input.Name, AuthPartner_Code: input.AuthPartner_Code} + if errCode := getAndCheck(userFes, userFes, "AuthPartner"); errCode != "" { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: errCode, Message: pl.GenMessage(errCode)}} + } + // Preload above fails and I am so done, do it manually + authPartner := eap.AuthPartner{} + if err := dg.I.Where("\"Code\" = ?", userFes.AuthPartner_Code).First(&authPartner).Error; err != nil { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-secretKey-invalid", Message: pl.GenMessage("auth-secretKey-invalid")}} + } + if authPartner.SecretKey != input.AuthPartner_SecretKey { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-secretKey-invalid", Message: pl.GenMessage("auth-secretKey-invalid")}} + } + + // Get User + user := &eu.User{Name: userFes.User_Name} + if errCode := getAndCheck(user, user, nil); errCode != "" { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: errCode, Message: pl.GenMessage(errCode)}} + } + + // Data and output population + atClaims := jwt.MapClaims{} + outputData := d.II{} + primInput := eu.LoginDto{Duration: input.Duration} + if err := populateRoles(user, primInput, atClaims, outputData, event); err != nil { + return nil, err + } + + // Current data + return &d.Data{ + Meta: d.IS{ + "source": "authentication", + "structure": "single-data", + "status": "verified", + }, + Data: outputData, + }, nil +} + func RevokeToken(uuid string) { ms.I.Del(uuid) } @@ -343,7 +205,7 @@ func ExtractToken(r *http.Request, tokenType TokenType) (data *pa.AuthInfo, err User_Name: fmt.Sprintf("%v", claims["user_name"]), } - data.User_ContractPosition_code = checkStrClaims(claims, "contractPosition_code") + data.User_ContractPosition_Code = checkStrClaims(claims, "contractPosition_code") data.Employee_Position_Code = checkStrPtrClaims(claims, "employee_position_code") data.Doctor_Code = checkStrPtrClaims(claims, "doctor_code") data.Nurse_Code = checkStrPtrClaims(claims, "nurse_code") @@ -361,89 +223,3 @@ func ExtractToken(r *http.Request, tokenType TokenType) (data *pa.AuthInfo, err func GetConfig() { a.ParseCfg(&authCfg) } - -func GenTokenFes(input euf.LoginDto) (*d.Data, error) { - event := pl.Event{ - Feature: "Create", - Source: source, - } - - // Get User Fes - userFes := &euf.UserFes{Name: input.Name, AuthPartner_Code: input.AuthPartner_Code} - if errCode := getAndCheck(userFes, userFes); errCode != "" { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: errCode, Message: pl.GenMessage(errCode)}} - } - if userFes.AuthPartner.SecretKey != input.AuthPartner_SecretKey { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-secretKey-invalid", Message: pl.GenMessage("auth-secretKey-invalid")}} - } - - user := &eu.User{Name: userFes.User_Name} - if errCode := getAndCheck(user, user); errCode != "" { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: errCode, Message: pl.GenMessage(errCode)}} - } - - // Access token prep - id, err := uuid.NewRandom() - if err != nil { - panic(fmt.Sprintf(l.I.Msg("uuid-gen-fail"), err)) - } - if input.Duration == 0 { - input.Duration = 24 * 60 - } - duration := time.Minute * time.Duration(input.Duration) - aUuid := id.String() - atExpires := time.Now().Add(duration).Unix() - atSecretKey := authCfg.AtSecretKey - - // Create Claim - atClaims := jwt.MapClaims{} - atClaims["user_id"] = user.Id - atClaims["user_name"] = user.Name - atClaims["user_contractPosition_code"] = user.ContractPosition_Code - atClaims["uuid"] = aUuid - atClaims["exp"] = atExpires - - // Create output - outputData := d.II{ - "user_id": strconv.Itoa(int(user.Id)), - "user_name": user.Name, - "user_contractPosition_code": user.ContractPosition_Code, - } - - // extra - if err := populateRoles(user, atClaims, outputData, event); err != nil { - return nil, err - } - - // Generate jwt - at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims) - ats, err := at.SignedString([]byte(atSecretKey)) - if err != nil { - return nil, d.FieldErrors{"user": d.FieldError{Code: "token-sign-err", Message: pl.GenMessage("token-sign-err")}} - } - outputData["accessToken"] = ats - - // Save to redis - now := time.Now() - atx := time.Unix(atExpires, 0) //converting Unix to UTC(to Time object) - err = ms.I.Set(aUuid, strconv.Itoa(int(user.Id)), atx.Sub(now)).Err() - if err != nil { - panic(fmt.Sprintf(l.I.Msg("redis-store-fail"), err.Error())) - } - - tn := time.Now() - user.LoginAttemptCount = 0 - user.LastSuccessLogin = &tn - user.LastAllowdLogin = &tn - dg.I.Save(&user) - - // Current data - return &d.Data{ - Meta: d.IS{ - "source": "authentication", - "structure": "single-data", - "status": "verified", - }, - Data: outputData, - }, nil -} diff --git a/internal/use-case/main-use-case/authentication/case.go.bu b/internal/use-case/main-use-case/authentication/case.go.bu new file mode 100644 index 00000000..1743407a --- /dev/null +++ b/internal/use-case/main-use-case/authentication/case.go.bu @@ -0,0 +1,463 @@ +package authentication + +import ( + "fmt" + "net/http" + "strconv" + "strings" + "time" + + "github.com/golang-jwt/jwt" + "github.com/google/uuid" + a "github.com/karincake/apem" + dg "github.com/karincake/apem/db-gorm-pg" + ms "github.com/karincake/apem/ms-redis" + d "github.com/karincake/dodol" + l "github.com/karincake/lepet" + + pa "simrs-vx/internal/lib/auth" + pl "simrs-vx/pkg/logger" + p "simrs-vx/pkg/password" + +<<<<<<< HEAD + ed "simrs-vx/internal/domain/main-entities/doctor" + ee "simrs-vx/internal/domain/main-entities/employee" + "simrs-vx/internal/domain/main-entities/intern" + em "simrs-vx/internal/domain/main-entities/midwife" + en "simrs-vx/internal/domain/main-entities/nurse" + ep "simrs-vx/internal/domain/main-entities/pharmacist" + eu "simrs-vx/internal/domain/main-entities/user" + +======= + eu "simrs-vx/internal/domain/main-entities/user" + euf "simrs-vx/internal/domain/main-entities/user-fes" +>>>>>>> fc7e74b (feat/sso-auth: wip) + erc "simrs-vx/internal/domain/references/common" +) + +const source = "authentication" + +var authCfg AuthCfg + +func init() { + a.RegisterExtCall(GetConfig) +} + +// Generates token and store in redis at one place +// just return the error code +func GenToken(input eu.LoginDto) (*d.Data, error) { + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Get User + user := &eu.User{Name: input.Name} + // if input.Position_Code != "" { + // user.Position_Code = input.Position_Code + // } + if errCode := getAndCheck(user, user); errCode != "" { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: errCode, Message: pl.GenMessage(errCode)}} + } + + if user.LoginAttemptCount > 5 { + if user.LastSuccessLogin != nil { + now := time.Now() + lastAllowdLogin := user.LastAllowdLogin + if lastAllowdLogin.After(now.Add(-time.Hour * 1)) { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-login-tooMany", Message: pl.GenMessage("auth-login-tooMany")}} + } else { + tn := time.Now() + user.LastAllowdLogin = &tn + user.LoginAttemptCount = 0 + dg.I.Save(&user) + } + } else { + tn := time.Now() + user.LastAllowdLogin = &tn + dg.I.Save(&user) + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-login-tooMany", Message: pl.GenMessage("auth-login-tooMany")}} + } + } + + if !p.Check(input.Password, user.Password) { + user.LoginAttemptCount++ + dg.I.Save(&user) + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-login-incorrect", Message: pl.GenMessage("auth-login-incorrect")}} + } else if user.Status_Code == erc.USCBlocked { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-login-blocked", Message: pl.GenMessage("auth-login-blocked")}} + } else if user.Status_Code == erc.USCNew { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-login-unverified", Message: pl.GenMessage("auth-login-unverified")}} + } + + // Access token prep + id, err := uuid.NewRandom() + if err != nil { + panic(fmt.Sprintf(l.I.Msg("uuid-gen-fail"), err)) + } + if input.Duration == 0 { + input.Duration = 24 * 60 + } + duration := time.Minute * time.Duration(input.Duration) + aUuid := id.String() + atExpires := time.Now().Add(duration).Unix() + atSecretKey := authCfg.AtSecretKey + + // Create Claim + atClaims := jwt.MapClaims{} + atClaims["user_id"] = user.Id + atClaims["user_name"] = user.Name + atClaims["user_contractPosition_code"] = user.ContractPosition_Code + atClaims["uuid"] = aUuid + atClaims["exp"] = atExpires + + // Create output + outputData := d.II{ + "user_id": strconv.Itoa(int(user.Id)), + "user_name": user.Name, + "user_contractPosition_code": user.ContractPosition_Code, + } + + // extra + // role := []string{} + // switch user.ContractPosition_Code { + // case erg.CSCEmp: + // // employee + // employee := ee.Employee{} + // dg.I.Where("\"User_Id\" = ?", user.Id).First(&employee) + // if employee.Id == 0 { + // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noEmployee", Message: pl.GenMessage("auth-noEmployee")}} + // } + // atClaims["employee_id"] = employee.Id + // outputData["employee_id"] = employee.Id + // role = append(role, "emp-"+string(*employee.Position_Code)) + + // //if employee.Division_Code != nil { + // // atClaims["employee_division_code"] = employee.Division_Code + // // outputData["employee_division_code"] = employee.Division_Code + // //} + + // // employee position + // if employee.Id > 0 && employee.Position_Code != nil { + // atClaims["employee_position_code"] = *employee.Position_Code + // switch *employee.Position_Code { + // case erg.EPCDoc: + // doctor := ed.Doctor{} + // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&doctor) + // if doctor.Id == 0 { + // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noDoctor", Message: pl.GenMessage("auth-noDoctor")}} + // } + // atClaims["doctor_code"] = doctor.Code + // outputData["doctor_code"] = doctor.Code + +<<<<<<< HEAD + // specialist + if doctor.Specialist_Code != nil { + atClaims["specialist_code"] = doctor.Specialist_Code + outputData["specialist_code"] = doctor.Specialist_Code + } + if doctor.Subspecialist_Code != nil { + atClaims["subspecialist_code"] = doctor.Subspecialist_Code + outputData["subspecialist_code"] = doctor.Subspecialist_Code + } + case erg.EPCNur: + empData := en.Nurse{} + dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + if empData.Id == 0 { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: pl.GenMessage("auth-noNurse")}} + } + atClaims["nurse_code"] = empData.Code + outputData["nurse_code"] = empData.Code + case erg.EPCMwi: + empData := em.Midwife{} + dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + if empData.Id == 0 { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noMidwife", Message: pl.GenMessage("auth-noMidwife")}} + } + atClaims["midwife_code"] = empData.Code + outputData["midwife_code"] = empData.Code + case erg.EPCPha: + empData := ep.Pharmacist{} + dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + if empData.Id == 0 { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noPharmacist", Message: pl.GenMessage("auth-noPharmacist")}} + } + atClaims["pharmacist_code"] = empData.Code + outputData["pharmacist_code"] = empData.Code + } +======= + // // specialist + // if doctor.Specialist_Code != nil { + // atClaims["specialist_code"] = doctor.Specialist_Code + // outputData["specialist_code"] = doctor.Specialist_Code + // } + // if doctor.Subspecialist_Code != nil { + // atClaims["subspecialist_code"] = doctor.Subspecialist_Code + // outputData["subspecialist_code"] = doctor.Subspecialist_Code + // } + // case erg.EPCNur: + // empData := en.Nurse{} + // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + // if empData.Id == 0 { + // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: pl.GenMessage("auth-noNurse")}} + // } + // atClaims["nurse_code"] = empData.Code + // outputData["nurse_code"] = empData.Code + // case erg.EPCMwi: + // empData := em.Midwife{} + // dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + // if empData.Id == 0 { + // return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noMidwife", Message: pl.GenMessage("auth-noMidwife")}} + // } + // atClaims["midwife_code"] = empData.Code + // outputData["midwife_code"] = empData.Code + // } +>>>>>>> fc7e74b (feat/sso-auth: wip) + + // errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: pl.GenMessage("auth-getData-failed")}} + + // // division position + // divisionPositions, err := getDivisionPosition(employee.Id, &event) + // if err != nil { + // return nil, errorGetPosition + // } + + // // installation position + // installationPositions, err := getInstallationPosition(employee.Id, &event) + // if err != nil { + // return nil, errorGetPosition + // } + + // // unit position + // unitPositions, err := getUnitPosition(employee.Id, &event) + // if err != nil { + // return nil, errorGetPosition + // } + + // // specialist position + // specialistPositions, err := getSpecialistPosition(employee.Id, &event) + // if err != nil { + // return nil, errorGetPosition + // } + + // // subspecialist position + // subspecialistPositions, err := getSubspecialistPosition(employee.Id, &event) + // if err != nil { + // return nil, errorGetPosition + // } + + // role = append(role, divisionPositions...) + // role = append(role, installationPositions...) + // role = append(role, unitPositions...) + // role = append(role, specialistPositions...) + // role = append(role, subspecialistPositions...) + // // atClaims["division_positions"] = divsionPositions + // // outputData["division_positions"] = divsionPositions + // } + // case erg.CSCInt: + // intern := intern.Intern{} + // dg.I.Where("\"User_Id\" = ?", user.Id).First(&intern) + // role = append(role, "int-"+string(*intern.Position_Code)) + // case erg.CSCSys: + // role = append(role, "system") + // } + // atClaims["roles"] = role + // outputData["roles"] = role + if err := populateRoles(user, atClaims, outputData, event); err != nil { + return nil, err + } + + // Generate jwt + at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims) + ats, err := at.SignedString([]byte(atSecretKey)) + if err != nil { + return nil, d.FieldErrors{"user": d.FieldError{Code: "token-sign-err", Message: pl.GenMessage("token-sign-err")}} + } + outputData["accessToken"] = ats + + // Save to redis + now := time.Now() + atx := time.Unix(atExpires, 0) //converting Unix to UTC(to Time object) + err = ms.I.Set(aUuid, strconv.Itoa(int(user.Id)), atx.Sub(now)).Err() + if err != nil { + panic(fmt.Sprintf(l.I.Msg("redis-store-fail"), err.Error())) + } + + tn := time.Now() + user.LoginAttemptCount = 0 + user.LastSuccessLogin = &tn + user.LastAllowdLogin = &tn + dg.I.Save(&user) + + // Current data + return &d.Data{ + Meta: d.IS{ + "source": "authentication", + "structure": "single-data", + "status": "verified", + }, + Data: outputData, + }, nil +} + +func RevokeToken(uuid string) { + ms.I.Del(uuid) +} + +func VerifyToken(r *http.Request, tokenType TokenType) (data *jwt.Token, errCode, errDetail string) { + auth := r.Header.Get("Authorization") + if auth == "" { + return nil, "auth-missingHeader", "" + } + authArr := strings.Split(auth, " ") + if len(authArr) == 2 { + auth = authArr[1] + } + + token, err := jwt.Parse(auth, func(token *jwt.Token) (any, error) { + //Make sure that the token method conform to "SigningMethodHMAC" + if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { + return nil, fmt.Errorf(l.I.Msg("token-sign-unexcpeted"), token.Header["alg"]) + } + if tokenType == AccessToken { + return []byte(authCfg.AtSecretKey), nil + } else { + return []byte(authCfg.RtSecretKey), nil + } + }) + if err != nil { + return nil, "token-parse-fail", err.Error() + } + return token, "", "" +} + +func ExtractToken(r *http.Request, tokenType TokenType) (data *pa.AuthInfo, err error) { + token, errCode, errDetail := VerifyToken(r, tokenType) + if errCode != "" { + return nil, d.FieldError{Code: errCode, Message: pl.GenMessage(errCode, errDetail)} + } + claims, ok := token.Claims.(jwt.MapClaims) + if ok && token.Valid { + accessUuid, ok := claims["uuid"].(string) + if !ok { + return nil, d.FieldError{Code: "token-invalid", Message: pl.GenMessage("token-invalid", "uuid not available")} + } + user_id, myErr := strconv.ParseInt(fmt.Sprintf("%.f", claims["user_id"]), 10, 64) + if myErr != nil { + return nil, d.FieldError{Code: "token-invalid", Message: pl.GenMessage("token-invalid", "uuid is not available")} + } + accessUuidRedis := ms.I.Get(accessUuid) + if accessUuidRedis.String() == "" { + return nil, d.FieldError{Code: "token-unidentified", Message: pl.GenMessage("token-unidentified")} + } + + data = &pa.AuthInfo{ + Uuid: accessUuid, + User_Id: uint(user_id), + User_Name: fmt.Sprintf("%v", claims["user_name"]), + } + + data.User_ContractPosition_code = checkStrClaims(claims, "contractPosition_code") + data.Employee_Position_Code = checkStrPtrClaims(claims, "employee_position_code") + data.Doctor_Code = checkStrPtrClaims(claims, "doctor_code") + data.Nurse_Code = checkStrPtrClaims(claims, "nurse_code") + data.Midwife_Code = checkStrPtrClaims(claims, "midwife_code") + data.Nutritionist_Code = checkStrPtrClaims(claims, "nutritionist_code") + data.Laborant_Code = checkStrPtrClaims(claims, "laborant_code") + data.Pharmachist_Code = checkStrPtrClaims(claims, "pharmachist_code") + data.Intern_Position_Code = checkStrPtrClaims(claims, "intern_position_code") + data.Employee_Id = checkUntPtrClaims(claims, "employee_id") + return + } + return nil, d.FieldError{Code: "token", Message: "token-invalid"} +} + +func GetConfig() { + a.ParseCfg(&authCfg) +} + +func GenTokenFes(input euf.LoginDto) (*d.Data, error) { + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Get User Fes + userFes := &euf.UserFes{Name: input.Name, AuthPartner_Code: input.AuthPartner_Code} + if errCode := getAndCheck(userFes, userFes); errCode != "" { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: errCode, Message: pl.GenMessage(errCode)}} + } + if userFes.AuthPartner.SecretKey != input.AuthPartner_SecretKey { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-secretKey-invalid", Message: pl.GenMessage("auth-secretKey-invalid")}} + } + + user := &eu.User{Name: userFes.User_Name} + if errCode := getAndCheck(user, user); errCode != "" { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: errCode, Message: pl.GenMessage(errCode)}} + } + + // Access token prep + id, err := uuid.NewRandom() + if err != nil { + panic(fmt.Sprintf(l.I.Msg("uuid-gen-fail"), err)) + } + if input.Duration == 0 { + input.Duration = 24 * 60 + } + duration := time.Minute * time.Duration(input.Duration) + aUuid := id.String() + atExpires := time.Now().Add(duration).Unix() + atSecretKey := authCfg.AtSecretKey + + // Create Claim + atClaims := jwt.MapClaims{} + atClaims["user_id"] = user.Id + atClaims["user_name"] = user.Name + atClaims["user_contractPosition_code"] = user.ContractPosition_Code + atClaims["uuid"] = aUuid + atClaims["exp"] = atExpires + + // Create output + outputData := d.II{ + "user_id": strconv.Itoa(int(user.Id)), + "user_name": user.Name, + "user_contractPosition_code": user.ContractPosition_Code, + } + + // extra + if err := populateRoles(user, atClaims, outputData, event); err != nil { + return nil, err + } + + // Generate jwt + at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims) + ats, err := at.SignedString([]byte(atSecretKey)) + if err != nil { + return nil, d.FieldErrors{"user": d.FieldError{Code: "token-sign-err", Message: pl.GenMessage("token-sign-err")}} + } + outputData["accessToken"] = ats + + // Save to redis + now := time.Now() + atx := time.Unix(atExpires, 0) //converting Unix to UTC(to Time object) + err = ms.I.Set(aUuid, strconv.Itoa(int(user.Id)), atx.Sub(now)).Err() + if err != nil { + panic(fmt.Sprintf(l.I.Msg("redis-store-fail"), err.Error())) + } + + tn := time.Now() + user.LoginAttemptCount = 0 + user.LastSuccessLogin = &tn + user.LastAllowdLogin = &tn + dg.I.Save(&user) + + // Current data + return &d.Data{ + Meta: d.IS{ + "source": "authentication", + "structure": "single-data", + "status": "verified", + }, + Data: outputData, + }, nil +} diff --git a/internal/use-case/main-use-case/authentication/helper.go b/internal/use-case/main-use-case/authentication/helper.go index 0da9f943..c0a3bd0f 100644 --- a/internal/use-case/main-use-case/authentication/helper.go +++ b/internal/use-case/main-use-case/authentication/helper.go @@ -1,10 +1,16 @@ package authentication import ( - dg "github.com/karincake/apem/db-gorm-pg" + "fmt" + "strconv" + "time" "github.com/golang-jwt/jwt" + "github.com/google/uuid" + dg "github.com/karincake/apem/db-gorm-pg" + ms "github.com/karincake/apem/ms-redis" d "github.com/karincake/dodol" + l "github.com/karincake/lepet" pl "simrs-vx/pkg/logger" @@ -15,6 +21,7 @@ import ( "simrs-vx/internal/domain/main-entities/intern" em "simrs-vx/internal/domain/main-entities/midwife" en "simrs-vx/internal/domain/main-entities/nurse" + ep "simrs-vx/internal/domain/main-entities/pharmacist" esp "simrs-vx/internal/domain/main-entities/specialist-position" essp "simrs-vx/internal/domain/main-entities/subspecialist-position" eup "simrs-vx/internal/domain/main-entities/unit-position" @@ -29,8 +36,21 @@ import ( ) // just return the error code -func getAndCheck(input, condition any) (eCode string) { - result := dg.I.Where(condition).Find(&input) +func getAndCheck(input, condition any, includes any) (eCode string) { + qry := dg.I.Where(condition) + + // WARNING THIS PRELOAD FAILS + if includes != nil { + if val := includes.(string); val != "" { + qry = qry.Preload(val) + } else if vals := includes.([]string); len(vals) > 0 { + for _, val := range vals { + qry = qry.Preload(val) + } + } + } + + result := qry.First(&input) if result.Error != nil { return "fetch-fail" } else if result.RowsAffected == 0 { @@ -44,18 +64,14 @@ func getDivisionPosition(employee_id uint, event *pl.Event) ([]string, error) { var result []string // get data division_position based on employee_id - data, _, err := udp.ReadListData(edp.ReadListDto{ - FilterDto: edp.FilterDto{Employee_Id: &employee_id}, - Includes: "Division"}, event) + data, _, err := udp.ReadListData(edp.ReadListDto{FilterDto: edp.FilterDto{Employee_Id: &employee_id}}, event) if err != nil { return nil, err } if len(data) > 0 { for _, dp := range data { - if dp.Division != nil { - result = append(result, "div-"+dp.Division.Code+"-"+dp.Code) - } + result = append(result, "div|"+*dp.Division_Code+"|"+dp.Code) } } @@ -75,9 +91,7 @@ func getInstallationPosition(employeeId uint, event *pl.Event) ([]string, error) if len(data) > 0 { for _, dp := range data { - if dp.Installation != nil { - result = append(result, "inst-"+dp.Installation.Code+"-"+dp.Code) - } + result = append(result, "inst|"+*dp.Installation_Code+"|"+dp.Code) } } @@ -88,18 +102,14 @@ func getUnitPosition(employeeId uint, event *pl.Event) ([]string, error) { var result []string // get data unit_position based on employee_id - data, _, err := uup.ReadListData(eup.ReadListDto{ - FilterDto: eup.FilterDto{Employee_Id: &employeeId}, - Includes: "unit"}, event) + data, _, err := uup.ReadListData(eup.ReadListDto{FilterDto: eup.FilterDto{Employee_Id: &employeeId}}, event) if err != nil { return nil, err } if len(data) > 0 { for _, dp := range data { - if dp.Unit != nil { - result = append(result, "unit-"+dp.Unit.Code+"-"+dp.Code) - } + result = append(result, "unit|"+*dp.Unit_Code+"|"+dp.Code) } } @@ -110,18 +120,14 @@ func getSpecialistPosition(employeeId uint, event *pl.Event) ([]string, error) { var result []string // get data unit_position based on employee_id - data, _, err := usp.ReadListData(esp.ReadListDto{ - FilterDto: esp.FilterDto{Employee_Id: &employeeId}, - Includes: "specialist"}, event) + data, _, err := usp.ReadListData(esp.ReadListDto{FilterDto: esp.FilterDto{Employee_Id: &employeeId}}, event) if err != nil { return nil, err } if len(data) > 0 { for _, dp := range data { - if dp.Specialist != nil { - result = append(result, "spec-"+dp.Specialist.Code+"-"+dp.Code) - } + result = append(result, "spec|"+*dp.Specialist_Code+"|"+dp.Code) } } @@ -141,9 +147,7 @@ func getSubspecialistPosition(employeeId uint, event *pl.Event) ([]string, error if len(data) > 0 { for _, dp := range data { - if dp.Subspecialist != nil { - result = append(result, "subspec-"+dp.Subspecialist.Code+"-"+dp.Code) - } + result = append(result, "subspec|"+dp.Subspecialist.Code+"|"+dp.Code) } } @@ -173,7 +177,28 @@ func checkUntPtrClaims(claim map[string]interface{}, key string) *uint { return nil } -func populateRoles(user *eu.User, atClaims jwt.MapClaims, outputData d.II, event pl.Event) error { +func populateRoles(user *eu.User, input eu.LoginDto, atClaims jwt.MapClaims, outputData d.II, event pl.Event) error { + id, err := uuid.NewRandom() + if err != nil { + panic(fmt.Sprintf(l.I.Msg("uuid-gen-fail"), err)) + } + if input.Duration == 0 { + input.Duration = 24 * 60 + } + duration := time.Minute * time.Duration(input.Duration) + aUuid := id.String() + atExpires := time.Now().Add(duration).Unix() + + atClaims["uuid"] = aUuid + atClaims["exp"] = atExpires + atClaims["user_id"] = user.Id + atClaims["user_name"] = user.Name + atClaims["user_contractPosition_code"] = user.ContractPosition_Code + + outputData["user_id"] = user.Id + outputData["user_name"] = user.Name + outputData["user_contractPosition_code"] = user.ContractPosition_Code + roles := []string{} switch user.ContractPosition_Code { case erg.CSCEmp: @@ -185,12 +210,7 @@ func populateRoles(user *eu.User, atClaims jwt.MapClaims, outputData d.II, event } atClaims["employee_id"] = employee.Id outputData["employee_id"] = employee.Id - roles = append(roles, "emp-"+string(*employee.Position_Code)) - - //if employee.Division_Code != nil { - // atClaims["employee_division_code"] = employee.Division_Code - // outputData["employee_division_code"] = employee.Division_Code - //} + roles = append(roles, "emp|"+string(*employee.Position_Code)) // employee position if employee.Id > 0 && employee.Position_Code != nil { @@ -230,6 +250,14 @@ func populateRoles(user *eu.User, atClaims jwt.MapClaims, outputData d.II, event } atClaims["midwife_code"] = empData.Code outputData["midwife_code"] = empData.Code + case erg.EPCPha: + empData := ep.Pharmacist{} + dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + if empData.Id == 0 { + return d.FieldErrors{"authentication": d.FieldError{Code: "auth-noPharmacist", Message: pl.GenMessage("auth-noPharmacist")}} + } + atClaims["pharmacist_code"] = empData.Code + outputData["pharmacist_code"] = empData.Code } errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: pl.GenMessage("auth-getData-failed")}} @@ -279,8 +307,26 @@ func populateRoles(user *eu.User, atClaims jwt.MapClaims, outputData d.II, event case erg.CSCSys: roles = append(roles, "system") } - atClaims["roles"] = roles outputData["roles"] = roles + + // Generate jwt + atSecretKey := authCfg.AtSecretKey + at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims) + ats, err := at.SignedString([]byte(atSecretKey)) + if err != nil { + return d.FieldErrors{"user": d.FieldError{Code: "token-sign-err", Message: pl.GenMessage("token-sign-err")}} + } + outputData["accessToken"] = ats + + // Save to redis + exp, _ := atClaims["exp"].(int64) + now := time.Now() + atx := time.Unix(exp, 0) //converting Unix to UTC(to Time object) + err = ms.I.Set(atClaims["uuid"].(string), strconv.Itoa(int(user.Id)), atx.Sub(now)).Err() + if err != nil { + panic(fmt.Sprintf(l.I.Msg("redis-store-fail"), err.Error())) + } + return nil } diff --git a/internal/use-case/main-use-case/authentication/helper.go.bu b/internal/use-case/main-use-case/authentication/helper.go.bu new file mode 100644 index 00000000..b7ccc660 --- /dev/null +++ b/internal/use-case/main-use-case/authentication/helper.go.bu @@ -0,0 +1,323 @@ +package authentication + +import ( + "fmt" + "strconv" + "time" + + "github.com/golang-jwt/jwt" + "github.com/google/uuid" + dg "github.com/karincake/apem/db-gorm-pg" + ms "github.com/karincake/apem/ms-redis" + d "github.com/karincake/dodol" + l "github.com/karincake/lepet" + + pl "simrs-vx/pkg/logger" + + 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" + eip "simrs-vx/internal/domain/main-entities/installation-position" + "simrs-vx/internal/domain/main-entities/intern" + em "simrs-vx/internal/domain/main-entities/midwife" + en "simrs-vx/internal/domain/main-entities/nurse" + esp "simrs-vx/internal/domain/main-entities/specialist-position" + 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" + usp "simrs-vx/internal/use-case/main-use-case/specialist-position" + ussp "simrs-vx/internal/use-case/main-use-case/subspecialist-position" + uup "simrs-vx/internal/use-case/main-use-case/unit-position" +) + +// just return the error code +func getAndCheck(input, condition any, includes any) (eCode string) { + qry := dg.I.Where(condition) + + // WARNING THIS PRELOAD FAILS + if includes != nil { + if val := includes.(string); val != "" { + qry = qry.Preload(val) + } else if vals := includes.([]string); len(vals) > 0 { + for _, val := range vals { + qry = qry.Preload(val) + } + } + } + + result := qry.First(&input) + if result.Error != nil { + return "fetch-fail" + } else if result.RowsAffected == 0 { + return "auth-login-incorrect" + } + + return "" +} + +func getDivisionPosition(employee_id uint, event *pl.Event) ([]string, error) { + var result []string + + // get data division_position based on employee_id + data, _, err := udp.ReadListData(edp.ReadListDto{FilterDto: edp.FilterDto{Employee_Id: &employee_id}}, event) + if err != nil { + return nil, err + } + + if len(data) > 0 { + for _, dp := range data { + result = append(result, "div-"+*dp.Division_Code) + } + } + + return result, nil +} + +func getInstallationPosition(employeeId uint, event *pl.Event) ([]string, error) { + var result []string + + // get data unit_position based on employee_id + data, _, err := uip.ReadListData(eip.ReadListDto{ + FilterDto: eip.FilterDto{Employee_Id: &employeeId}, + Includes: "installation"}, event) + if err != nil { + return nil, err + } + + if len(data) > 0 { + for _, dp := range data { + result = append(result, "inst-"+*dp.Installation_Code+"-"+dp.Code) + } + } + + return result, nil +} + +func getUnitPosition(employeeId uint, event *pl.Event) ([]string, error) { + var result []string + + // get data unit_position based on employee_id + data, _, err := uup.ReadListData(eup.ReadListDto{FilterDto: eup.FilterDto{Employee_Id: &employeeId}}, event) + if err != nil { + return nil, err + } + + if len(data) > 0 { + for _, dp := range data { + result = append(result, "unit-"+*dp.Unit_Code+"-"+dp.Code) + } + } + + return result, nil +} + +func getSpecialistPosition(employeeId uint, event *pl.Event) ([]string, error) { + var result []string + + // get data unit_position based on employee_id + data, _, err := usp.ReadListData(esp.ReadListDto{FilterDto: esp.FilterDto{Employee_Id: &employeeId}}, event) + if err != nil { + return nil, err + } + + if len(data) > 0 { + for _, dp := range data { + result = append(result, "spec-"+*dp.Specialist_Code+"-"+dp.Code) + } + } + + return result, nil +} + +func getSubspecialistPosition(employeeId uint, event *pl.Event) ([]string, error) { + var result []string + + // get data unit_position based on employee_id + data, _, err := ussp.ReadListData(essp.ReadListDto{ + FilterDto: essp.FilterDto{Employee_Id: &employeeId}, + Includes: "subspecialist"}, event) + if err != nil { + return nil, err + } + + if len(data) > 0 { + for _, dp := range data { + result = append(result, "subspec-"+dp.Subspecialist.Code+"-"+dp.Code) + } + } + + return result, nil +} + +func checkStrClaims(claim map[string]interface{}, key string) string { + if v, exist := claim[key]; exist && v != nil { + return v.(string) + } + return "" +} + +func checkStrPtrClaims(claim map[string]interface{}, key string) *string { + if v, exist := claim[key]; exist && v != nil { + val := v.(string) + return &val + } + return nil +} + +func checkUntPtrClaims(claim map[string]interface{}, key string) *uint { + if v, exist := claim[key]; exist && v != nil { + val := uint(v.(float64)) + return &val + } + return nil +} + +func populateRoles(user *eu.User, input eu.LoginDto, atClaims jwt.MapClaims, outputData d.II, event pl.Event) error { + id, err := uuid.NewRandom() + if err != nil { + panic(fmt.Sprintf(l.I.Msg("uuid-gen-fail"), err)) + } + if input.Duration == 0 { + input.Duration = 24 * 60 + } + duration := time.Minute * time.Duration(input.Duration) + aUuid := id.String() + atExpires := time.Now().Add(duration).Unix() + + atClaims["uuid"] = aUuid + atClaims["exp"] = atExpires + atClaims["user_id"] = user.Id + atClaims["user_name"] = user.Name + atClaims["user_contractPosition_code"] = user.ContractPosition_Code + + outputData["user_id"] = user.Id + outputData["user_name"] = user.Name + outputData["user_contractPosition_code"] = user.ContractPosition_Code + + roles := []string{} + switch user.ContractPosition_Code { + case erg.CSCEmp: + // employee + employee := ee.Employee{} + dg.I.Where("\"User_Id\" = ?", user.Id).First(&employee) + if employee.Id == 0 { + return d.FieldErrors{"authentication": d.FieldError{Code: "auth-noEmployee", Message: pl.GenMessage("auth-noEmployee")}} + } + atClaims["employee_id"] = employee.Id + outputData["employee_id"] = employee.Id + roles = append(roles, "emp-"+string(*employee.Position_Code)) + + // employee position + if employee.Id > 0 && employee.Position_Code != nil { + atClaims["employee_position_code"] = *employee.Position_Code + switch *employee.Position_Code { + case erg.EPCDoc: + doctor := ed.Doctor{} + dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&doctor) + if doctor.Id == 0 { + return d.FieldErrors{"authentication": d.FieldError{Code: "auth-noDoctor", Message: pl.GenMessage("auth-noDoctor")}} + } + atClaims["doctor_code"] = doctor.Code + outputData["doctor_code"] = doctor.Code + + // specialist + if doctor.Specialist_Code != nil { + atClaims["specialist_code"] = doctor.Specialist_Code + outputData["specialist_code"] = doctor.Specialist_Code + } + if doctor.Subspecialist_Code != nil { + atClaims["subspecialist_code"] = doctor.Subspecialist_Code + outputData["subspecialist_code"] = doctor.Subspecialist_Code + } + case erg.EPCNur: + empData := en.Nurse{} + dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + if empData.Id == 0 { + return d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: pl.GenMessage("auth-noNurse")}} + } + atClaims["nurse_code"] = empData.Code + outputData["nurse_code"] = empData.Code + case erg.EPCMwi: + empData := em.Midwife{} + dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&empData) + if empData.Id == 0 { + return d.FieldErrors{"authentication": d.FieldError{Code: "auth-noMidwife", Message: pl.GenMessage("auth-noMidwife")}} + } + atClaims["midwife_code"] = empData.Code + outputData["midwife_code"] = empData.Code + } + + errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: pl.GenMessage("auth-getData-failed")}} + + // division position + divisionPositions, err := getDivisionPosition(employee.Id, &event) + if err != nil { + return errorGetPosition + } + + // installation position + installationPositions, err := getInstallationPosition(employee.Id, &event) + if err != nil { + return errorGetPosition + } + + // unit position + unitPositions, err := getUnitPosition(employee.Id, &event) + if err != nil { + return errorGetPosition + } + + // specialist position + specialistPositions, err := getSpecialistPosition(employee.Id, &event) + if err != nil { + return errorGetPosition + } + + // subspecialist position + subspecialistPositions, err := getSubspecialistPosition(employee.Id, &event) + if err != nil { + return errorGetPosition + } + + roles = append(roles, divisionPositions...) + roles = append(roles, installationPositions...) + roles = append(roles, unitPositions...) + roles = append(roles, specialistPositions...) + roles = append(roles, subspecialistPositions...) + // atClaims["division_positions"] = divsionPositions + // outputData["division_positions"] = divsionPositions + } + case erg.CSCInt: + intern := intern.Intern{} + dg.I.Where("\"User_Id\" = ?", user.Id).First(&intern) + roles = append(roles, "int-"+string(*intern.Position_Code)) + case erg.CSCSys: + roles = append(roles, "system") + } + atClaims["roles"] = roles + outputData["roles"] = roles + + // Generate jwt + atSecretKey := authCfg.AtSecretKey + at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims) + ats, err := at.SignedString([]byte(atSecretKey)) + if err != nil { + return d.FieldErrors{"user": d.FieldError{Code: "token-sign-err", Message: pl.GenMessage("token-sign-err")}} + } + outputData["accessToken"] = ats + + // Save to redis + exp, _ := atClaims["exp"].(int64) + now := time.Now() + atx := time.Unix(exp, 0) //converting Unix to UTC(to Time object) + err = ms.I.Set(atClaims["uuid"].(string), strconv.Itoa(int(user.Id)), atx.Sub(now)).Err() + if err != nil { + panic(fmt.Sprintf(l.I.Msg("redis-store-fail"), err.Error())) + } + + return nil +} diff --git a/internal/use-case/main-use-case/user-fes/case.go b/internal/use-case/main-use-case/user-fes/case.go new file mode 100644 index 00000000..51225927 --- /dev/null +++ b/internal/use-case/main-use-case/user-fes/case.go @@ -0,0 +1,276 @@ +package userfes + +import ( + "strconv" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + "gorm.io/gorm" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + e "simrs-vx/internal/domain/main-entities/user-fes" +) + +const source = "ext-user" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.UserFes{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.UserFes + var dataList []e.UserFes + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.UserFes + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.UserFes + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.UserFes + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/user-fes/helper.go b/internal/use-case/main-use-case/user-fes/helper.go new file mode 100644 index 00000000..b83d303f --- /dev/null +++ b/internal/use-case/main-use-case/user-fes/helper.go @@ -0,0 +1,18 @@ +package userfes + +import ( + e "simrs-vx/internal/domain/main-entities/user-fes" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.UserFes) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + data.Name = inputSrc.Name + data.AuthPartner_Code = inputSrc.AuthPartner_Code + data.User_Name = inputSrc.User_Name +} diff --git a/internal/use-case/main-use-case/user-fes/lib.go b/internal/use-case/main-use-case/user-fes/lib.go new file mode 100644 index 00000000..ce7c8280 --- /dev/null +++ b/internal/use-case/main-use-case/user-fes/lib.go @@ -0,0 +1,143 @@ +package userfes + +import ( + "gorm.io/gorm" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + eu "simrs-vx/internal/domain/main-entities/user-fes" +) + +func CreateData(input eu.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*eu.UserFes, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := eu.UserFes{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input eu.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]eu.UserFes, *eu.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []eu.UserFes{} + pagination := gh.Pagination{} + count := int64(0) + meta := eu.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&eu.UserFes{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input eu.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*eu.UserFes, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := eu.UserFes{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input eu.UpdateDto, data *eu.UserFes, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *eu.UserFes, 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 +} diff --git a/internal/use-case/main-use-case/user-fes/middleware-runner.go b/internal/use-case/main-use-case/user-fes/middleware-runner.go new file mode 100644 index 00000000..f669d4cd --- /dev/null +++ b/internal/use-case/main-use-case/user-fes/middleware-runner.go @@ -0,0 +1,103 @@ +package userfes + +import ( + e "simrs-vx/internal/domain/main-entities/user-fes" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.UserFes) 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.UserFes) 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.UserFes) 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.UserFes) 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.UserFes) 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/main-use-case/user-fes/middleware.go b/internal/use-case/main-use-case/user-fes/middleware.go new file mode 100644 index 00000000..71dac997 --- /dev/null +++ b/internal/use-case/main-use-case/user-fes/middleware.go @@ -0,0 +1,5 @@ +package userfes + +func init() { + +} diff --git a/internal/use-case/main-use-case/user-fes/tycovar.go b/internal/use-case/main-use-case/user-fes/tycovar.go new file mode 100644 index 00000000..008f5cfa --- /dev/null +++ b/internal/use-case/main-use-case/user-fes/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 userfes + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/user-fes" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.UserFes, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.UserFes, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.UserFes, 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 From fe804dabb3334d708cf9fb80390559a4c742f0ef Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Mon, 10 Nov 2025 22:54:08 +0700 Subject: [PATCH 177/329] feat/sso-auth: added the handler --- .../main-handler/auth-partner/handler.go | 71 +++++++++++++++++++ .../main-handler/authentication/handler.go | 46 ++++++------ .../interface/main-handler/main-handler.go | 6 ++ .../main-handler/user-fes/handler.go | 71 +++++++++++++++++++ 4 files changed, 172 insertions(+), 22 deletions(-) create mode 100644 internal/interface/main-handler/auth-partner/handler.go create mode 100644 internal/interface/main-handler/user-fes/handler.go diff --git a/internal/interface/main-handler/auth-partner/handler.go b/internal/interface/main-handler/auth-partner/handler.go new file mode 100644 index 00000000..f31e538d --- /dev/null +++ b/internal/interface/main-handler/auth-partner/handler.go @@ -0,0 +1,71 @@ +package authpartner + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/auth-partner" + u "simrs-vx/internal/use-case/main-use-case/auth-partner" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := uint16(rw.ValidateInt(w, "id", r.PathValue("id"))) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = &id + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := uint16(rw.ValidateInt(w, "id", r.PathValue("id"))) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = id + res, err := u.Update(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { + id := uint16(rw.ValidateInt(w, "id", r.PathValue("id"))) + if id <= 0 { + return + } + + dto := e.DeleteDto{} + dto.Id = id + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/authentication/handler.go b/internal/interface/main-handler/authentication/handler.go index fc36dc52..243ba9cd 100644 --- a/internal/interface/main-handler/authentication/handler.go +++ b/internal/interface/main-handler/authentication/handler.go @@ -30,6 +30,30 @@ func Login(w http.ResponseWriter, r *http.Request) { } } +func LoginFes(w http.ResponseWriter, r *http.Request) { + var input mf.LoginDto + err := sp.IOReaderJson(&input, r.Body) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil) + return + } + + input.AuthPartner_Code = r.Header.Get("X-AuthPartner-Code") + input.AuthPartner_SecretKey = r.Header.Get("X-AuthPartner-SecretKey") + if err = sr.Validate(input); err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil) + return + } + + // input.Position = Position + res, err := s.GenTokenFes(input) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil) + } else { + rw.DataResponse(w, res, err) + } +} + func Logout(w http.ResponseWriter, r *http.Request) { ctxVal := r.Context().Value(pa.AuthKey{}) if ctxVal == nil { @@ -52,25 +76,3 @@ func GuardMW(next http.Handler) http.Handler { next.ServeHTTP(w, r.WithContext(ctx)) }) } - -func LoginFes(w http.ResponseWriter, r *http.Request) { - var input mf.LoginDto - err := sp.IOReaderJson(input, r.Body) - if err != nil { - rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil) - } - - input.AuthPartner_Code = r.Header.Get("X-AuthPartner-Code") - input.AuthPartner_SecretKey = r.Header.Get("X-AuthPartner-SecretKey") - if err = (sr.Validate(input)); err != nil { - rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil) - } - - // input.Position = Position - res, err := s.GenTokenFes(input) - if err != nil { - rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil) - } else { - rw.DataResponse(w, res, err) - } -} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index b2589f86..013bc98c 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -36,6 +36,7 @@ import ( /******************** actor ********************/ + authpartner "simrs-vx/internal/interface/main-handler/auth-partner" doctor "simrs-vx/internal/interface/main-handler/doctor" employee "simrs-vx/internal/interface/main-handler/employee" nurse "simrs-vx/internal/interface/main-handler/nurse" @@ -47,6 +48,7 @@ import ( personinsurance "simrs-vx/internal/interface/main-handler/person-insurance" pharmacist "simrs-vx/internal/interface/main-handler/pharmacist" user "simrs-vx/internal/interface/main-handler/user" + userfes "simrs-vx/internal/interface/main-handler/user-fes" /******************** external ********************/ a "github.com/karincake/apem" @@ -132,7 +134,9 @@ func SetRoutes() http.Handler { r.HandleFunc("/", home.Home) r.HandleFunc("POST /v1/authentication/login", auth.Login) + r.HandleFunc("POST /v1/authentication/login-fes", auth.LoginFes) hk.Route("POST /v1/authentication/logout", r, auth.GuardMW, auth.Logout) + hc.RegCrud(r, "/v1/auth-partner", authpartner.O) hc.RegCrud(r, "/v1/practice-schedule", practiceschedule.O) hc.RegCrud(r, "/v1/counter", counter.O) hc.RegCrud(r, "/v1/medicine-mix", medicicinemix.O) @@ -284,6 +288,8 @@ func SetRoutes() http.Handler { "PATCH /{id}/block": user.O.Block, "PATCH /{id}/active": user.O.Active, }) + hc.RegCrud(r, "/v1/user-fes", userfes.O) + hk.GroupRoutes("/v1/patient", r, hk.MapHandlerFunc{ "GET /": patient.O.GetList, "GET /{id}": patient.O.GetDetail, diff --git a/internal/interface/main-handler/user-fes/handler.go b/internal/interface/main-handler/user-fes/handler.go new file mode 100644 index 00000000..0c37ff08 --- /dev/null +++ b/internal/interface/main-handler/user-fes/handler.go @@ -0,0 +1,71 @@ +package userfes + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/user-fes" + u "simrs-vx/internal/use-case/main-use-case/user-fes" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := uint16(rw.ValidateInt(w, "id", r.PathValue("id"))) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint(id) + 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) +} From eb57a01a943aed5cd4b86063e5a55a6dd39b703e Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Mon, 10 Nov 2025 23:00:31 +0700 Subject: [PATCH 178/329] feat/sso-auth: entities adjustment --- .../migrations/20251110155448.sql | 6 ++ cmd/main-migration/migrations/atlas.sum | 81 ++++++++++--------- .../domain/main-entities/auth-partner/dto.go | 4 +- .../main-entities/auth-partner/entity.go | 8 +- .../domain/main-entities/user-fes/entity.go | 11 ++- 5 files changed, 60 insertions(+), 50 deletions(-) create mode 100644 cmd/main-migration/migrations/20251110155448.sql diff --git a/cmd/main-migration/migrations/20251110155448.sql b/cmd/main-migration/migrations/20251110155448.sql new file mode 100644 index 00000000..203a27cb --- /dev/null +++ b/cmd/main-migration/migrations/20251110155448.sql @@ -0,0 +1,6 @@ +-- Modify "AuthPartner" table +ALTER TABLE "public"."AuthPartner" ALTER COLUMN "Id" TYPE integer; +-- Modify "UserFes" table +ALTER TABLE "public"."UserFes" ALTER COLUMN "AuthPartner_Code" TYPE character varying(50); +-- Create index "idx-userFes-name-authPartner_code" to table: "UserFes" +CREATE UNIQUE INDEX "idx-userFes-name-authPartner_code" ON "public"."UserFes" ("Name", "AuthPartner_Code"); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 36eff156..8c3dedc2 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:gxzRzsKXNeg9LaO7Hak8tLYmALxv5wumfuA+BSfFD3E= +h1:eTC10wvsOLnENRLwgViQvRs0NYu3w94Ah1fOaGCqFEg= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,42 +75,43 @@ h1:gxzRzsKXNeg9LaO7Hak8tLYmALxv5wumfuA+BSfFD3E= 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= -20251111072601.sql h1:6p2qynJ2vr3C18peYciAbOIWOoj/+PnNcobU3wNHboQ= -20251111073546.sql h1:BORlFReAZTDLUfpS/eIf5qGkJ+FNznMGK47HRiPkfL8= -20251111074148.sql h1:qzjLGQRWo1Gg8LkJFgTb5Ak7h53tdz+eQrpJqC9+Gc0= -20251111074652.sql h1:uuThrt4wjdq4qEbvS67fF0Nfw/dlj7vGnLqywWBznqk= -20251111082257.sql h1:eUfu0tDtl9KqX7UK8is6Qc04NSQs4BXwKsykZwnVH1w= -20251111111017.sql h1:UGUI29WXoDdEp4jWtbzrFGhfO8XO50IafBE7cMfo70k= +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= diff --git a/internal/domain/main-entities/auth-partner/dto.go b/internal/domain/main-entities/auth-partner/dto.go index 2b1589fb..4a723251 100644 --- a/internal/domain/main-entities/auth-partner/dto.go +++ b/internal/domain/main-entities/auth-partner/dto.go @@ -45,7 +45,7 @@ type MetaDto struct { } type ResponseDto struct { - ecore.Main + ecore.SmallMain Code string `json:"code"` Name string `json:"name"` SecretKey string `json:"secretKey"` @@ -57,7 +57,7 @@ func (d AuthPartner) ToResponse() ResponseDto { Name: d.Name, SecretKey: d.SecretKey, } - resp.Main = d.Main + resp.SmallMain = d.SmallMain return resp } diff --git a/internal/domain/main-entities/auth-partner/entity.go b/internal/domain/main-entities/auth-partner/entity.go index b4ad8e49..3a810f51 100644 --- a/internal/domain/main-entities/auth-partner/entity.go +++ b/internal/domain/main-entities/auth-partner/entity.go @@ -5,8 +5,8 @@ import ( ) type AuthPartner struct { - ecore.Main // adjust this according to the needs - Code string `json:"code" gorm:"unique;size:50"` - Name string `json:"name" gorm:"unique;size:100"` - SecretKey string `json:"secretKey" gorm:"size:255"` + ecore.SmallMain // adjust this according to the needs + Code string `json:"code" gorm:"unique;size:50"` + Name string `json:"name" gorm:"unique;size:100"` + SecretKey string `json:"secretKey" gorm:"size:255"` } diff --git a/internal/domain/main-entities/user-fes/entity.go b/internal/domain/main-entities/user-fes/entity.go index 7356166c..5261ed62 100644 --- a/internal/domain/main-entities/user-fes/entity.go +++ b/internal/domain/main-entities/user-fes/entity.go @@ -9,9 +9,12 @@ import ( type UserFes struct { ecore.Main // adjust this according to the needs - Name string `json:"name" gorm:"size:100"` - AuthPartner_Code string `json:"authPartner_code" gorm:"size:30"` + Name string `json:"name" gorm:"size:100;uniqueIndex:idx-userFes-name-authPartner_code"` + AuthPartner_Code string `json:"authPartner_code" gorm:"size:50;uniqueIndex:idx-userFes-name-authPartner_code"` AuthPartner *eap.AuthPartner `json:"authPartner,omitempty" gorm:"foreignKey:AuthPartner_Code;references:Code"` - User_Name string `json:"user_name" gorm:"size:50"` - User *eau.User `json:"user,omitempty" gorm:"foreignKey:User_Name;references:Name"` + // Even tried this one, still failed to preload + // AuthPartner_Id uint16 `json:"authPartner_id"` + // AuthPartner *eap.AuthPartner `json:"authPartner,omitempty" gorm:"foreignKey:AuthPartner_Id;references:Id"` + User_Name string `json:"user_name" gorm:"size:50"` + User *eau.User `json:"user,omitempty" gorm:"foreignKey:User_Name;references:Name"` } From a552e51fa7506fae96aa254d24fc14c5f4dca9ae Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Thu, 13 Nov 2025 17:27:59 +0700 Subject: [PATCH 179/329] feat/prescription: updated entities --- .../migrations/20251113101344.sql | 11 +++ cmd/main-migration/migrations/atlas.sum | 3 +- .../domain/main-entities/medicine-form/dto.go | 67 +++++++++++++++++++ .../main-entities/medicine-form/entity.go | 11 +++ internal/interface/migration/main-entities.go | 2 + 5 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 cmd/main-migration/migrations/20251113101344.sql create mode 100644 internal/domain/main-entities/medicine-form/dto.go create mode 100644 internal/domain/main-entities/medicine-form/entity.go diff --git a/cmd/main-migration/migrations/20251113101344.sql b/cmd/main-migration/migrations/20251113101344.sql new file mode 100644 index 00000000..cda3abed --- /dev/null +++ b/cmd/main-migration/migrations/20251113101344.sql @@ -0,0 +1,11 @@ +-- Create "MedicineForm" table +CREATE TABLE "public"."MedicineForm" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(20) NULL, + "Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_MedicineForm_Code" UNIQUE ("Code") +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 8c3dedc2..12fe7e83 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:eTC10wvsOLnENRLwgViQvRs0NYu3w94Ah1fOaGCqFEg= +h1:6WOy+P2ZTzKcl82qh91tJo8GQlP7SQq7ijFoGqOnC14= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -115,3 +115,4 @@ h1:eTC10wvsOLnENRLwgViQvRs0NYu3w94Ah1fOaGCqFEg= 20251111074652.sql h1:ddfQ/sRKMezPM75xBFTGytUQX5AwZ3znrJVpg73gKPA= 20251111082257.sql h1:ZsdLY1ROouos0l3oS0lkeSiuKLEUGbVvBhpcM2AVhkw= 20251111111017.sql h1:qrJ93dNtQwcuAvpsP/lAK/H63C4cinXrsVaPmWsTqkU= +20251113101344.sql h1:oG4MVNBSZ5CiFS3CfhoLr5oqBFIGwhLo+QiVcZ6W25A= diff --git a/internal/domain/main-entities/medicine-form/dto.go b/internal/domain/main-entities/medicine-form/dto.go new file mode 100644 index 00000000..a7145a2f --- /dev/null +++ b/internal/domain/main-entities/medicine-form/dto.go @@ -0,0 +1,67 @@ +package medicineform + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type CreateDto struct { + Code *string `json:"code" validate:"maxLength=20"` + Name string `json:"name" validate:"maxLength=50"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Sort string `json:"sort"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Code string `json:"code"` + Name string `json:"name"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` +} + +type ReadDetailDto struct { + Id *uint16 `json:"id"` + Code *string `json:"code"` +} + +type UpdateDto struct { + Id *uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id *uint `json:"id"` + Code *string `json:"code"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.SmallMain + Code string `json:"code"` + Name string `json:"name"` +} + +func (d MedicineForm) ToResponse() ResponseDto { + resp := ResponseDto{ + Code: d.Code, + Name: d.Name, + } + resp.SmallMain = d.SmallMain + return resp +} + +func ToResponseList(data []MedicineForm) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/medicine-form/entity.go b/internal/domain/main-entities/medicine-form/entity.go new file mode 100644 index 00000000..75b1b104 --- /dev/null +++ b/internal/domain/main-entities/medicine-form/entity.go @@ -0,0 +1,11 @@ +package medicineform + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type MedicineForm struct { + ecore.SmallMain // adjust this according to the needs + Code string `json:"code" gorm:"unique;size:20"` + Name string `json:"name" gorm:"size:50"` +} diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index 272cd4ce..94b5d545 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -57,6 +57,7 @@ import ( medicationitem "simrs-vx/internal/domain/main-entities/medication-item" medicationitemdist "simrs-vx/internal/domain/main-entities/medication-item-dist" medicine "simrs-vx/internal/domain/main-entities/medicine" + medicineform "simrs-vx/internal/domain/main-entities/medicine-form" medicinegroup "simrs-vx/internal/domain/main-entities/medicine-group" medicinemethod "simrs-vx/internal/domain/main-entities/medicine-method" medicinemix "simrs-vx/internal/domain/main-entities/medicine-mix" @@ -145,6 +146,7 @@ func getMainEntities() []any { ðnic.Ethnic{}, &insurancecompany.InsuranceCompany{}, &medicine.Medicine{}, + &medicineform.MedicineForm{}, &medicinemix.MedicineMix{}, &medicinemixitem.MedicineMixItem{}, &medicalactionsrc.MedicalActionSrc{}, From e75025f87d202e515d88ecd5d866e4852878b3db Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 13 Nov 2025 17:28:20 +0700 Subject: [PATCH 180/329] add create installation --- .../domain/main-entities/installation/dto.go | 1 + .../main-use-case/installation/case.go | 9 +- .../installation/middleware-runner.go | 3 +- .../main-use-case/installation/middleware.go | 15 +- .../main-use-case/installation/tycovar.go | 4 +- .../simgos-sync-plugin/installation/plugin.go | 46 +++++ .../simgos-sync-use-case/installation/case.go | 157 ++++++++++-------- .../installation/helper.go | 39 ++++- .../simgos-sync-use-case/installation/lib.go | 90 +++++++--- 9 files changed, 254 insertions(+), 110 deletions(-) create mode 100644 internal/use-case/simgos-sync-plugin/installation/plugin.go diff --git a/internal/domain/main-entities/installation/dto.go b/internal/domain/main-entities/installation/dto.go index 758efb05..5cc0ed5c 100644 --- a/internal/domain/main-entities/installation/dto.go +++ b/internal/domain/main-entities/installation/dto.go @@ -8,6 +8,7 @@ import ( ) type CreateDto struct { + Id *uint `json:"id"` Code *string `json:"code" validate:"maxLength=10"` Name string `json:"name" validate:"maxLength=50"` EncounterClass_Code ere.EncounterClassCode `json:"encounterClass_code" validate:"maxLength=10"` diff --git a/internal/use-case/main-use-case/installation/case.go b/internal/use-case/main-use-case/installation/case.go index f3ce5d59..8e577a30 100644 --- a/internal/use-case/main-use-case/installation/case.go +++ b/internal/use-case/main-use-case/installation/case.go @@ -1,6 +1,7 @@ package installation import ( + egos "simrs-vx/internal/domain/simgos-entities/installation" "strconv" dg "github.com/karincake/apem/db-gorm-pg" @@ -18,6 +19,7 @@ const source = "installation" func Create(input e.CreateDto) (*d.Data, error) { data := e.Installation{} + sgData := egos.MInstalasi{} event := pl.Event{ Feature: "Create", @@ -29,11 +31,6 @@ func Create(input e.CreateDto) (*d.Data, error) { 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 resData, err := CreateData(input, &event, tx); err != nil { return err @@ -43,7 +40,7 @@ func Create(input e.CreateDto) (*d.Data, error) { mwRunner.setMwType(pu.MWTPost) // Run post-middleware - if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &sgData); err != nil { return err } 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 fce572bb..0abd6b29 100644 --- a/internal/use-case/main-use-case/installation/middleware-runner.go +++ b/internal/use-case/main-use-case/installation/middleware-runner.go @@ -2,6 +2,7 @@ package installation import ( e "simrs-vx/internal/domain/main-entities/installation" + egos "simrs-vx/internal/domain/simgos-entities/installation" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -23,7 +24,7 @@ func newMiddlewareRunner(event *pl.Event, tx *gorm.DB) *middlewareRunner { } // ExecuteCreateMiddleware executes create middleware -func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.Installation) error { +func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *egos.MInstalasi) error { for _, middleware := range middlewares { logData := pu.GetLogData(input, data) diff --git a/internal/use-case/main-use-case/installation/middleware.go b/internal/use-case/main-use-case/installation/middleware.go index 3d414c9b..46c4be1d 100644 --- a/internal/use-case/main-use-case/installation/middleware.go +++ b/internal/use-case/main-use-case/installation/middleware.go @@ -1,9 +1,12 @@ package installation +import ( + plugin "simrs-vx/internal/use-case/simgos-sync-plugin/installation" +) + // example of middleware -// func init() { -// createPreMw = append(createPreMw, -// CreateMw{Name: "modif-input", Func: pm.ModifInput}, -// CreateMw{Name: "check-data", Func: pm.CheckData}, -// ) -// } +func init() { + createPostMw = append(createPostMw, + createMw{Name: "create-installation", Func: plugin.Create}, + ) +} diff --git a/internal/use-case/main-use-case/installation/tycovar.go b/internal/use-case/main-use-case/installation/tycovar.go index de8e9c9e..975ebd34 100644 --- a/internal/use-case/main-use-case/installation/tycovar.go +++ b/internal/use-case/main-use-case/installation/tycovar.go @@ -9,6 +9,8 @@ functionality. The purpose of this is to make the code more maintainable. package installation import ( + egos "simrs-vx/internal/domain/simgos-entities/installation" + "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/installation" @@ -16,7 +18,7 @@ import ( type createMw struct { Name string - Func func(input *e.CreateDto, data *e.Installation, tx *gorm.DB) error + Func func(input *e.CreateDto, data *egos.MInstalasi, tx *gorm.DB) error } type readListMw struct { diff --git a/internal/use-case/simgos-sync-plugin/installation/plugin.go b/internal/use-case/simgos-sync-plugin/installation/plugin.go new file mode 100644 index 00000000..92ef479b --- /dev/null +++ b/internal/use-case/simgos-sync-plugin/installation/plugin.go @@ -0,0 +1,46 @@ +package installation + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + sync "simrs-vx/internal/infra/sync-cfg" + + e "simrs-vx/internal/domain/main-entities/installation" + egos "simrs-vx/internal/domain/simgos-entities/installation" + + "gorm.io/gorm" +) + +var endpoint = fmt.Sprintf("%s/v1/installation", sync.O.BaseUrl) + +func Create(input *e.CreateDto, data *egos.MInstalasi, tx *gorm.DB) error { + 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() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + if err := json.Unmarshal(body, &data); err != nil { + return fmt.Errorf("failed to parse response JSON: %w", err) + } + + return nil +} diff --git a/internal/use-case/simgos-sync-use-case/installation/case.go b/internal/use-case/simgos-sync-use-case/installation/case.go index 398289cd..2990d5ae 100644 --- a/internal/use-case/simgos-sync-use-case/installation/case.go +++ b/internal/use-case/simgos-sync-use-case/installation/case.go @@ -1,8 +1,9 @@ package installation import ( - e "simrs-vx/internal/domain/main-entities/installation" + erc "simrs-vx/internal/domain/references/common" "strconv" + "time" dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -11,13 +12,18 @@ import ( pu "simrs-vx/pkg/use-case-helper" "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/installation" + egos "simrs-vx/internal/domain/simgos-entities/installation" + esync "simrs-vx/internal/domain/sync-entities/installation" ) const source = "installation" -func Create(input e.CreateDto) (*d.Data, error) { - data := e.Installation{} +var now = time.Now() +func Create(input e.CreateDto) (*d.Data, error) { + sgData := egos.MInstalasi{} event := pl.Event{ Feature: "Create", Source: source, @@ -27,14 +33,35 @@ func Create(input e.CreateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "create") err := dg.I.Transaction(func(tx *gorm.DB) error { - // TODO: Insert + // Insert Simgos + sgData, err := CreateSimgosData(input, &event, tx) + if err != nil { + errMsg := err.Error() + inputLog := esync.InstallationSimxLog{ + Date: &now, + Status: erc.PSCFailed, + ErrMessage: &errMsg, + } - // TODO: InsertSimxLog - - if resData, err := CreateData(input, &event, tx); err != nil { - return err + // InsertSimxLog + if err = CreateSimxLogData(input, inputLog, &event, tx); err != nil { + return err + } } else { - data = *resData + inputLog := esync.InstallationSimxLog{ + Date: &now, + Status: erc.PSCSuccess, + } + + // InsertSimxLog + if err = CreateSimxLogData(input, inputLog, &event, tx); err != nil { + return err + } + } + + // InsertSimxLink + if err = CreateInstallationLinkData(*input.Id, sgData.NoInstalasi, &event, tx); err != nil { + return err } pl.SetLogInfo(&event, nil, "complete") @@ -52,7 +79,7 @@ func Create(input e.CreateDto) (*d.Data, error) { "structure": "single-data", "status": "created", }, - Data: data.ToResponse(), + Data: sgData, }, nil } @@ -156,61 +183,61 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { }, nil } -func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Code: input.Code} - var data *e.Installation - var err error - - event := pl.Event{ - Feature: "Update", - Source: source, - } - - // Start log - pl.SetLogInfo(&event, input, "started", "update") - - err = dg.I.Transaction(func(tx *gorm.DB) error { - pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - if data, err = ReadDetailData(rdDto, &event, tx); err != nil { - 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") - - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { - return err - } - - return nil - }) - - if err != nil { - return nil, err - } - - return &d.Data{ - Meta: d.IS{ - "source": source, - "structure": "single-data", - "status": "updated", - }, - Data: data.ToResponse(), - }, nil - -} +//func Update(input e.UpdateDto) (*d.Data, error) { +// rdDto := e.ReadDetailDto{Code: input.Code} +// var data *e.Installation +// var err error +// +// event := pl.Event{ +// Feature: "Update", +// Source: source, +// } +// +// // Start log +// pl.SetLogInfo(&event, input, "started", "update") +// +// err = dg.I.Transaction(func(tx *gorm.DB) error { +// pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") +// if data, err = ReadDetailData(rdDto, &event, tx); err != nil { +// 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") +// +// mwRunner.setMwType(pu.MWTPost) +// // Run post-middleware +// if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { +// return err +// } +// +// return nil +// }) +// +// if err != nil { +// return nil, err +// } +// +// return &d.Data{ +// Meta: d.IS{ +// "source": source, +// "structure": "single-data", +// "status": "updated", +// }, +// Data: data.ToResponse(), +// }, nil +// +//} func Delete(input e.DeleteDto) (*d.Data, error) { rdDto := e.ReadDetailDto{Code: input.Code} diff --git a/internal/use-case/simgos-sync-use-case/installation/helper.go b/internal/use-case/simgos-sync-use-case/installation/helper.go index af56b5c6..eae50f99 100644 --- a/internal/use-case/simgos-sync-use-case/installation/helper.go +++ b/internal/use-case/simgos-sync-use-case/installation/helper.go @@ -5,11 +5,13 @@ Any functions that are used internally by the use-case package installation import ( + "encoding/json" e "simrs-vx/internal/domain/main-entities/installation" esimgos "simrs-vx/internal/domain/simgos-entities/installation" + esync "simrs-vx/internal/domain/sync-entities/installation" ) -func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T, data *esimgos.MInstalasi) { +func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MInstalasi) { var inputSrc *e.CreateDto if inputT, ok := any(input).(*e.CreateDto); ok { inputSrc = inputT @@ -19,8 +21,35 @@ func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T, data *esimgos.MInstal } data.NamaInstalasi = inputSrc.Name - data.StatusRawatInap = 1 - data.Code = *inputSrc.Code - data.Name = inputSrc.Name - data.EncounterClass_Code = inputSrc.EncounterClass_Code + data.StatusRawatInap = 0 + data.StAktif = 1 + + return +} + +func setDataSimxLog[T *e.CreateDto | *e.UpdateDto](input T, inputLog esync.InstallationSimxLog) (data esync.InstallationSimxLog) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + // encode to JSON + jsonData, _ := json.Marshal(inputSrc) + jsonString := string(jsonData) + + data.Value = &jsonString + data.Date = &now + data.Status = inputLog.Status + data.ErrMessage = inputLog.ErrMessage + + return +} + +func setDataSimxLink(simxId, simgosId uint) (data esync.InstallationLink) { + data.Simx_Id = simxId + data.Simgos_Id = simgosId + return } diff --git a/internal/use-case/simgos-sync-use-case/installation/lib.go b/internal/use-case/simgos-sync-use-case/installation/lib.go index 07afe61a..e76eb127 100644 --- a/internal/use-case/simgos-sync-use-case/installation/lib.go +++ b/internal/use-case/simgos-sync-use-case/installation/lib.go @@ -11,13 +11,13 @@ import ( e "simrs-vx/internal/domain/main-entities/installation" esimgos "simrs-vx/internal/domain/simgos-entities/installation" + esync "simrs-vx/internal/domain/sync-entities/installation" ) func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esimgos.MInstalasi, error) { pl.SetLogInfo(event, nil, "started", "DBCreate") - data := esimgos.MInstalasi{} - setData(&input, &data) + data := setDataSimgos(&input) var tx *gorm.DB if len(dbx) > 0 { @@ -34,6 +34,44 @@ func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esi return &data, nil } +func CreateSimxLogData(input e.CreateDto, inputLog esync.InstallationSimxLog, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, nil, "started", "DBCreate") + data := setDataSimxLog(&input, inputLog) + + 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 +} + +func CreateInstallationLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) 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 plh.HandleCreateError(data, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} + func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Installation, *e.MetaDto, error) { pl.SetLogInfo(event, input, "started", "DBReadList") data := []e.Installation{} @@ -101,30 +139,30 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e return &data, nil } -func UpdateData(input e.UpdateDto, data *e.Installation, event *pl.Event, dbx ...*gorm.DB) error { - pl.SetLogInfo(event, data, "started", "DBUpdate") - setData(&input, data) - - var tx *gorm.DB - if len(dbx) > 0 { - tx = dbx[0] - } else { - tx = dg.I - } - - 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 UpdateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) error { +// pl.SetLogInfo(event, input, "started", "DBUpdate") +// setData(&input, data) +// +// var tx *gorm.DB +// if len(dbx) > 0 { +// tx = dbx[0] +// } else { +// tx = dg.I +// } +// +// 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 DeleteData(data *e.Installation, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, data, "started", "DBDelete") From 403c085d56fa209ddb34ac0f5993ca1c028d5d62 Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 13 Nov 2025 17:31:49 +0700 Subject: [PATCH 181/329] revise m_instalasi --- internal/domain/simgos-entities/installation/entity.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/domain/simgos-entities/installation/entity.go b/internal/domain/simgos-entities/installation/entity.go index d620af5e..faf2786e 100644 --- a/internal/domain/simgos-entities/installation/entity.go +++ b/internal/domain/simgos-entities/installation/entity.go @@ -1,10 +1,10 @@ package installation type MInstalasi struct { - NoInstalasi uint `json:"no_instalasi"` - NamaInstalasi string `json:"nama_instalasi"` - StatusRawatInap uint `json:"status_rawat_inap"` - StAktif uint `json:"st_aktif"` + No_Instalasi uint `json:"no_instalasi" gorm:"primaryKey;autoIncrement"` + Nama_Instalasi string `json:"nama_instalasi"` + Status_Rawat_Inap uint `json:"status_rawat_inap"` + St_Aktif uint `json:"st_aktif"` } func (MInstalasi) TableName() string { From 50b2c7b781adbf89eb11f42ebe52e9b56877ea4c Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Thu, 13 Nov 2025 19:07:04 +0700 Subject: [PATCH 182/329] feat/prescription: relating MedicineForm --- cmd/main-migration/migrations/20251113120533.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 5 +++-- internal/domain/main-entities/medicine/entity.go | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 cmd/main-migration/migrations/20251113120533.sql diff --git a/cmd/main-migration/migrations/20251113120533.sql b/cmd/main-migration/migrations/20251113120533.sql new file mode 100644 index 00000000..b8d56fe8 --- /dev/null +++ b/cmd/main-migration/migrations/20251113120533.sql @@ -0,0 +1,2 @@ +-- Modify "Medicine" table +ALTER TABLE "public"."Medicine" ADD COLUMN "MedicineForm_Code" character varying(20) NULL, ADD CONSTRAINT "fk_Medicine_MedicineForm" FOREIGN KEY ("MedicineForm_Code") REFERENCES "public"."MedicineForm" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 12fe7e83..1c172e0c 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:6WOy+P2ZTzKcl82qh91tJo8GQlP7SQq7ijFoGqOnC14= +h1:RvRW5FTVb8Zdn/J5rSwIrXB7cbCmWJBNaVsxqArNl4E= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -115,4 +115,5 @@ h1:6WOy+P2ZTzKcl82qh91tJo8GQlP7SQq7ijFoGqOnC14= 20251111074652.sql h1:ddfQ/sRKMezPM75xBFTGytUQX5AwZ3znrJVpg73gKPA= 20251111082257.sql h1:ZsdLY1ROouos0l3oS0lkeSiuKLEUGbVvBhpcM2AVhkw= 20251111111017.sql h1:qrJ93dNtQwcuAvpsP/lAK/H63C4cinXrsVaPmWsTqkU= -20251113101344.sql h1:oG4MVNBSZ5CiFS3CfhoLr5oqBFIGwhLo+QiVcZ6W25A= +20251113101344.sql h1:xaOZvAUP1fFfnO+syEFOzJUIg5lTfBe5AWHPbBWuCLA= +20251113120533.sql h1:MOk7YBwVLRCoqgPrC/mQAarp5WRl4aTk6NAzIoQPMNc= diff --git a/internal/domain/main-entities/medicine/entity.go b/internal/domain/main-entities/medicine/entity.go index dda220bc..0a79e7e5 100644 --- a/internal/domain/main-entities/medicine/entity.go +++ b/internal/domain/main-entities/medicine/entity.go @@ -4,6 +4,7 @@ import ( ecore "simrs-vx/internal/domain/base-entities/core" ein "simrs-vx/internal/domain/main-entities/infra" eit "simrs-vx/internal/domain/main-entities/item" + emf "simrs-vx/internal/domain/main-entities/medicine-form" emg "simrs-vx/internal/domain/main-entities/medicine-group" emm "simrs-vx/internal/domain/main-entities/medicine-method" eu "simrs-vx/internal/domain/main-entities/uom" @@ -17,6 +18,8 @@ type Medicine struct { MedicineGroup *emg.MedicineGroup `json:"medicineGroup,omitempty" gorm:"foreignKey:MedicineGroup_Code;references:Code"` MedicineMethod_Code *string `json:"medicineMethod_code" gorm:"size:10"` MedicineMethod *emm.MedicineMethod `json:"medicineMethod,omitempty" gorm:"foreignKey:MedicineMethod_Code;references:Code"` + MedicineForm_Code *string `json:"medicineForm_code" gorm:"size:20"` + MedicineForm *emf.MedicineForm `json:"medicineForm,omitempty" gorm:"foreignKey:MedicineForm_Code;references:Code"` Uom_Code *string `json:"uom_code" gorm:"size:10"` Uom *eu.Uom `json:"uom" gorm:"foreignKey:Uom_Code;references:Code"` Dose uint8 `json:"dose"` From 29469d4c50864b442455d88489132a45258c63e8 Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 13 Nov 2025 20:54:35 +0700 Subject: [PATCH 183/329] add installation --- internal/domain/sync-entities/log/dto.go | 12 ++ internal/infra/simgos-db/simgos-db.go | 9 + internal/infra/simgos-db/tycovar.go | 5 + internal/infra/sync-cfg/sync-cfg.go | 7 +- internal/infra/sync-cfg/tycovar.go | 5 +- .../installation/handler.go | 46 ++-- .../simgos-sync-handler.go | 8 +- .../main-use-case/installation/case.go | 43 +++- .../installation/middleware-runner.go | 25 ++- .../main-use-case/installation/middleware.go | 6 +- .../main-use-case/installation/tycovar.go | 11 +- .../simgos-sync-plugin/installation/plugin.go | 49 ++++- .../simgos-sync-use-case/installation/case.go | 197 ++++++++++-------- .../installation/helper.go | 33 +-- .../simgos-sync-use-case/installation/lib.go | 20 +- 15 files changed, 313 insertions(+), 163 deletions(-) create mode 100644 internal/domain/sync-entities/log/dto.go create mode 100644 internal/infra/simgos-db/simgos-db.go create mode 100644 internal/infra/simgos-db/tycovar.go diff --git a/internal/domain/sync-entities/log/dto.go b/internal/domain/sync-entities/log/dto.go new file mode 100644 index 00000000..32f5be6f --- /dev/null +++ b/internal/domain/sync-entities/log/dto.go @@ -0,0 +1,12 @@ +package log + +import ( + erc "simrs-vx/internal/domain/references/common" +) + +type SimxLogDto struct { + Payload any `json:"payload"` + IsSuccess bool `json:"isSuccess"` + ErrMessage *string `json:"errMessage"` + Method erc.CrudCode `json:"method"` +} diff --git a/internal/infra/simgos-db/simgos-db.go b/internal/infra/simgos-db/simgos-db.go new file mode 100644 index 00000000..4387ad7f --- /dev/null +++ b/internal/infra/simgos-db/simgos-db.go @@ -0,0 +1,9 @@ +package simgos_db + +import ( + dg "github.com/karincake/apem/db-gorm-pg" +) + +func SetInstance() { + I = dg.IS["simrs"] +} diff --git a/internal/infra/simgos-db/tycovar.go b/internal/infra/simgos-db/tycovar.go new file mode 100644 index 00000000..b9c9f2b3 --- /dev/null +++ b/internal/infra/simgos-db/tycovar.go @@ -0,0 +1,5 @@ +package simgos_db + +import "gorm.io/gorm" + +var I *gorm.DB diff --git a/internal/infra/sync-cfg/sync-cfg.go b/internal/infra/sync-cfg/sync-cfg.go index a5579219..a6a5d703 100644 --- a/internal/infra/sync-cfg/sync-cfg.go +++ b/internal/infra/sync-cfg/sync-cfg.go @@ -7,12 +7,9 @@ import ( func SetConfig() { a.ParseSingleCfg(&O) - //if O.Host == "" || O.Target == "" { - // panic("sync url config host or target empty") - //} - if O.BaseUrl == "" { - panic("config bpjs base url empty") + if O.Host == "" || O.Prefix == "" { + panic("config sync host and prefix empty") } lo.I.Println("sync url config loaded, status: DONE!!") } diff --git a/internal/infra/sync-cfg/tycovar.go b/internal/infra/sync-cfg/tycovar.go index 081ef762..fdcda00b 100644 --- a/internal/infra/sync-cfg/tycovar.go +++ b/internal/infra/sync-cfg/tycovar.go @@ -3,7 +3,6 @@ package synccfg var O SyncUrlCfg = SyncUrlCfg{} type SyncUrlCfg struct { - Target string `yaml:"target"` - Host string `yaml:"host"` - BaseUrl string `yaml:"baseUrl"` + Prefix string `yaml:"prefix"` + Host string `yaml:"host"` } diff --git a/internal/interface/simgos-sync-handler/installation/handler.go b/internal/interface/simgos-sync-handler/installation/handler.go index 01a6beab..6f9a708d 100644 --- a/internal/interface/simgos-sync-handler/installation/handler.go +++ b/internal/interface/simgos-sync-handler/installation/handler.go @@ -7,6 +7,7 @@ import ( // ua "github.com/karincake/tumpeng/auth/svc" e "simrs-vx/internal/domain/main-entities/installation" + esync "simrs-vx/internal/domain/sync-entities/log" u "simrs-vx/internal/use-case/simgos-sync-use-case/installation" ) @@ -23,29 +24,38 @@ func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { rw.DataResponse(w, res, err) } -func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - code := rw.ValidateString(w, "code", r.PathValue("code")) - if code == "" { - return - } - - dto := e.UpdateDto{} +func (obj myBase) CreateLog(w http.ResponseWriter, r *http.Request) { + dto := esync.SimxLogDto{} if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Code = &code - res, err := u.Update(dto) + res, err := u.CreateSimxLog(dto) rw.DataResponse(w, res, err) } +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + //code := rw.ValidateString(w, "code", r.PathValue("code")) + //if code == "" { + // return + //} + // + //dto := e.UpdateDto{} + //if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + // return + //} + //dto.Code = &code + //res, err := u.Update(dto) + //rw.DataResponse(w, res, err) +} + func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { - code := rw.ValidateString(w, "code", r.PathValue("code")) - if code == "" { - return - } - - dto := e.DeleteDto{} - dto.Code = &code - res, err := u.Delete(dto) - rw.DataResponse(w, res, err) + //code := rw.ValidateString(w, "code", r.PathValue("code")) + //if code == "" { + // return + //} + // + //dto := e.DeleteDto{} + //dto.Code = &code + //res, err := u.Delete(dto) + //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 963ec93c..71002949 100644 --- a/internal/interface/simgos-sync-handler/simgos-sync-handler.go +++ b/internal/interface/simgos-sync-handler/simgos-sync-handler.go @@ -2,8 +2,11 @@ package simgossynchandler import ( "net/http" + /******************** infra ********************/ gs "simrs-vx/internal/infra/gorm-setting" + simgosdb "simrs-vx/internal/infra/simgos-db" + simgossync "simrs-vx/internal/infra/sync-cfg" /******************** pkg ********************/ cmw "simrs-vx/pkg/cors-manager-mw" @@ -25,6 +28,8 @@ func SetRoutes() http.Handler { a.RegisterExtCall(gs.Adjust) a.RegisterExtCall(zlc.Adjust) a.RegisterExtCall(lh.Populate) + a.RegisterExtCall(simgossync.SetConfig) + a.RegisterExtCall(simgosdb.SetInstance) r := http.NewServeMux() @@ -32,8 +37,9 @@ func SetRoutes() http.Handler { r.HandleFunc("/", home.Home) /******************** Source ******************/ - hk.GroupRoutes("/v1/installation", r, hk.MapHandlerFunc{ + hk.GroupRoutes("/new-to-old/v1/installation", r, hk.MapHandlerFunc{ "POST /": installation.O.Create, + "POST /log": installation.O.CreateLog, "PATCH /{id}": installation.O.Update, "DELETE /{id}": installation.O.Delete, }) diff --git a/internal/use-case/main-use-case/installation/case.go b/internal/use-case/main-use-case/installation/case.go index 8e577a30..d0a409c0 100644 --- a/internal/use-case/main-use-case/installation/case.go +++ b/internal/use-case/main-use-case/installation/case.go @@ -1,7 +1,7 @@ package installation import ( - egos "simrs-vx/internal/domain/simgos-entities/installation" + erc "simrs-vx/internal/domain/references/common" "strconv" dg "github.com/karincake/apem/db-gorm-pg" @@ -13,6 +13,8 @@ import ( "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/installation" + egos "simrs-vx/internal/domain/simgos-entities/installation" + esync "simrs-vx/internal/domain/sync-entities/log" ) const source = "installation" @@ -28,19 +30,18 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") + mwRunner := newMiddlewareRunner(&event) err := dg.I.Transaction(func(tx *gorm.DB) error { - mwRunner := newMiddlewareRunner(&event, tx) - 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, &sgData); err != nil { + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &sgData); err != nil { return err } @@ -49,7 +50,29 @@ func Create(input e.CreateDto) (*d.Data, error) { return nil }) + var errMsg string + inputLog := esync.SimxLogDto{ + Payload: input, + Method: erc.CCCreate, + } + if err != nil { + // Run log-middleware + errMsg = err.Error() + inputLog.ErrMessage = &errMsg + inputLog.IsSuccess = false + + // create log failed + if err = mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog); err != nil { + return nil, err + } + + return nil, err + } + + // create log success + inputLog.IsSuccess = true + if err = mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog); err != nil { return nil, err } @@ -78,7 +101,7 @@ 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 := newMiddlewareRunner(&event) mwRunner.setMwType(pu.MWTPre) // Run pre-middleware if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { @@ -129,7 +152,7 @@ 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 := newMiddlewareRunner(&event) mwRunner.setMwType(pu.MWTPre) // Run pre-middleware if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { @@ -182,7 +205,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } - mwRunner := newMiddlewareRunner(&event, tx) + mwRunner := newMiddlewareRunner(&event) mwRunner.setMwType(pu.MWTPre) // Run pre-middleware if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { @@ -238,7 +261,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { return err } - mwRunner := newMiddlewareRunner(&event, tx) + mwRunner := newMiddlewareRunner(&event) mwRunner.setMwType(pu.MWTPre) // Run pre-middleware if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { 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 0abd6b29..acfaaa47 100644 --- a/internal/use-case/main-use-case/installation/middleware-runner.go +++ b/internal/use-case/main-use-case/installation/middleware-runner.go @@ -1,12 +1,14 @@ package installation import ( - e "simrs-vx/internal/domain/main-entities/installation" - egos "simrs-vx/internal/domain/simgos-entities/installation" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/installation" + egos "simrs-vx/internal/domain/simgos-entities/installation" + esync "simrs-vx/internal/domain/sync-entities/log" ) type middlewareRunner struct { @@ -16,10 +18,9 @@ type middlewareRunner struct { } // NewMiddlewareExecutor creates a new middleware executor -func newMiddlewareRunner(event *pl.Event, tx *gorm.DB) *middlewareRunner { +func newMiddlewareRunner(event *pl.Event) *middlewareRunner { return &middlewareRunner{ Event: event, - Tx: tx, } } @@ -39,6 +40,22 @@ func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e return nil } +// ExecuteCreateMiddleware executes create middleware +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) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.Installation) error { for _, middleware := range middlewares { logData := pu.GetLogData(input, data) diff --git a/internal/use-case/main-use-case/installation/middleware.go b/internal/use-case/main-use-case/installation/middleware.go index 46c4be1d..222ec563 100644 --- a/internal/use-case/main-use-case/installation/middleware.go +++ b/internal/use-case/main-use-case/installation/middleware.go @@ -6,7 +6,11 @@ import ( // example of middleware func init() { - createPostMw = append(createPostMw, + createPreMw = append(createPreMw, createMw{Name: "create-installation", Func: plugin.Create}, ) + + createSimxLogMw = append(createSimxLogMw, + createLogMw{Name: "create-log", Func: plugin.CreateLog}, + ) } diff --git a/internal/use-case/main-use-case/installation/tycovar.go b/internal/use-case/main-use-case/installation/tycovar.go index 975ebd34..e704b3a1 100644 --- a/internal/use-case/main-use-case/installation/tycovar.go +++ b/internal/use-case/main-use-case/installation/tycovar.go @@ -14,6 +14,7 @@ import ( "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/installation" + elog "simrs-vx/internal/domain/sync-entities/log" ) type createMw struct { @@ -21,6 +22,11 @@ type createMw struct { Func func(input *e.CreateDto, data *egos.MInstalasi, tx *gorm.DB) error } +type createLogMw struct { + Name string + Func func(input *elog.SimxLogDto) error +} + type readListMw struct { Name string Func func(input *e.ReadListDto, data *e.Installation, tx *gorm.DB) error @@ -34,8 +40,9 @@ type readDetailMw struct { type UpdateMw = readDetailMw type DeleteMw = readDetailMw -var createPreMw []createMw // preprocess middleware -var createPostMw []createMw // postprocess middleware +var createPreMw []createMw // preprocess middleware +var createPostMw []createMw // postprocess middleware +var createSimxLogMw []createLogMw var readListPreMw []readListMw // .. var readListPostMw []readListMw // .. var readDetailPreMw []readDetailMw diff --git a/internal/use-case/simgos-sync-plugin/installation/plugin.go b/internal/use-case/simgos-sync-plugin/installation/plugin.go index 92ef479b..b566302b 100644 --- a/internal/use-case/simgos-sync-plugin/installation/plugin.go +++ b/internal/use-case/simgos-sync-plugin/installation/plugin.go @@ -6,25 +6,29 @@ import ( "fmt" "io" "net/http" + + "gorm.io/gorm" + sync "simrs-vx/internal/infra/sync-cfg" e "simrs-vx/internal/domain/main-entities/installation" egos "simrs-vx/internal/domain/simgos-entities/installation" - - "gorm.io/gorm" + elog "simrs-vx/internal/domain/sync-entities/log" ) -var endpoint = fmt.Sprintf("%s/v1/installation", sync.O.BaseUrl) - func Create(input *e.CreateDto, data *egos.MInstalasi, tx *gorm.DB) error { + var endpoint = fmt.Sprintf("%s%s/v1/installation", sync.O.Host, sync.O.Prefix) + 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) @@ -33,6 +37,10 @@ func Create(input *e.CreateDto, data *egos.MInstalasi, tx *gorm.DB) error { } defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return fmt.Errorf(resp.Status) + } + body, err := io.ReadAll(resp.Body) if err != nil { return err @@ -44,3 +52,36 @@ func Create(input *e.CreateDto, data *egos.MInstalasi, tx *gorm.DB) error { return nil } + +func CreateLog(input *elog.SimxLogDto) error { + var endpoint = fmt.Sprintf("%s%s/v1/installation/log", sync.O.Host, sync.O.Prefix) + + 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() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf(resp.Status) + } + + _, err = io.ReadAll(resp.Body) + if err != nil { + return err + } + + return nil +} diff --git a/internal/use-case/simgos-sync-use-case/installation/case.go b/internal/use-case/simgos-sync-use-case/installation/case.go index 2990d5ae..f38cca14 100644 --- a/internal/use-case/simgos-sync-use-case/installation/case.go +++ b/internal/use-case/simgos-sync-use-case/installation/case.go @@ -1,9 +1,8 @@ package installation import ( - erc "simrs-vx/internal/domain/references/common" + esync "simrs-vx/internal/domain/sync-entities/log" "strconv" - "time" dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -14,16 +13,63 @@ import ( "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/installation" - egos "simrs-vx/internal/domain/simgos-entities/installation" - esync "simrs-vx/internal/domain/sync-entities/installation" ) const source = "installation" -var now = time.Now() - func Create(input e.CreateDto) (*d.Data, error) { - sgData := egos.MInstalasi{} + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + // Define trx + txSync := dg.I.Begin() + txSimgos := dg.IS["simrs"].Begin() + + // STEP 1: Insert to simgos + sgData, err := CreateSimgosData(input, &event, txSimgos) + if err != nil { + return nil, err + } + + // STEP 2: Insert to Link + if err = CreateInstallationLinkData(*input.Id, sgData.No_Instalasi, &event, txSync); err != nil { + txSimgos.Rollback() + return nil, err + } + + // STEP 3: Commit two trx + if err = txSimgos.Commit().Error; err != nil { + txSimgos.Rollback() + txSync.Rollback() + return nil, err + } + + if err = txSync.Commit().Error; err != nil { + // STEP 4: Rollback Partial + go func() { + _ = DeleteSimgosData(sgData, &event) + }() + return nil, err + } + + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: sgData, + }, nil +} + +func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { event := pl.Event{ Feature: "Create", Source: source, @@ -33,34 +79,8 @@ func Create(input e.CreateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "create") err := dg.I.Transaction(func(tx *gorm.DB) error { - // Insert Simgos - sgData, err := CreateSimgosData(input, &event, tx) - if err != nil { - errMsg := err.Error() - inputLog := esync.InstallationSimxLog{ - Date: &now, - Status: erc.PSCFailed, - ErrMessage: &errMsg, - } - - // InsertSimxLog - if err = CreateSimxLogData(input, inputLog, &event, tx); err != nil { - return err - } - } else { - inputLog := esync.InstallationSimxLog{ - Date: &now, - Status: erc.PSCSuccess, - } - - // InsertSimxLog - if err = CreateSimxLogData(input, inputLog, &event, tx); err != nil { - return err - } - } - - // InsertSimxLink - if err = CreateInstallationLinkData(*input.Id, sgData.NoInstalasi, &event, tx); err != nil { + // InsertSimxLog + if err := CreateSimxLogData(input, &event, tx); err != nil { return err } @@ -79,7 +99,6 @@ func Create(input e.CreateDto) (*d.Data, error) { "structure": "single-data", "status": "created", }, - Data: sgData, }, nil } @@ -239,56 +258,56 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { // //} -func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Code: input.Code} - var data *e.Installation - var err error - - event := pl.Event{ - Feature: "Delete", - Source: source, - } - - // Start log - pl.SetLogInfo(&event, input, "started", "delete") - - err = dg.I.Transaction(func(tx *gorm.DB) error { - pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - if data, err = ReadDetailData(rdDto, &event, tx); err != nil { - 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 { - return err - } - - return nil - }) - - if err != nil { - return nil, err - } - - return &d.Data{ - Meta: d.IS{ - "source": source, - "structure": "single-data", - "status": "deleted", - }, - Data: data.ToResponse(), - }, nil - -} +//func Delete(input e.DeleteDto) (*d.Data, error) { +// rdDto := e.ReadDetailDto{Code: input.Code} +// var data *e.Installation +// var err error +// +// event := pl.Event{ +// Feature: "Delete", +// Source: source, +// } +// +// // Start log +// pl.SetLogInfo(&event, input, "started", "delete") +// +// err = dg.I.Transaction(func(tx *gorm.DB) error { +// pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") +// if data, err = ReadDetailData(rdDto, &event, tx); err != nil { +// 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 { +// return err +// } +// +// return nil +// }) +// +// if err != nil { +// return nil, err +// } +// +// return &d.Data{ +// Meta: d.IS{ +// "source": source, +// "structure": "single-data", +// "status": "deleted", +// }, +// Data: data.ToResponse(), +// }, nil +// +//} diff --git a/internal/use-case/simgos-sync-use-case/installation/helper.go b/internal/use-case/simgos-sync-use-case/installation/helper.go index eae50f99..51316d79 100644 --- a/internal/use-case/simgos-sync-use-case/installation/helper.go +++ b/internal/use-case/simgos-sync-use-case/installation/helper.go @@ -7,8 +7,10 @@ package installation import ( "encoding/json" e "simrs-vx/internal/domain/main-entities/installation" + erc "simrs-vx/internal/domain/references/common" esimgos "simrs-vx/internal/domain/simgos-entities/installation" esync "simrs-vx/internal/domain/sync-entities/installation" + "simrs-vx/internal/domain/sync-entities/log" ) func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MInstalasi) { @@ -20,30 +22,31 @@ func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MInstal inputSrc = &inputTemp.CreateDto } - data.NamaInstalasi = inputSrc.Name - data.StatusRawatInap = 0 - data.StAktif = 1 + data.Nama_Instalasi = inputSrc.Name + data.Status_Rawat_Inap = 0 + data.St_Aktif = 1 return } -func setDataSimxLog[T *e.CreateDto | *e.UpdateDto](input T, inputLog esync.InstallationSimxLog) (data esync.InstallationSimxLog) { - var inputSrc *e.CreateDto - if inputT, ok := any(input).(*e.CreateDto); ok { - inputSrc = inputT - } else { - inputTemp := any(input).(*e.UpdateDto) - inputSrc = &inputTemp.CreateDto - } - +func setDataSimxLog(input *log.SimxLogDto) (data esync.InstallationSimxLog) { // encode to JSON - jsonData, _ := json.Marshal(inputSrc) + 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 = inputLog.Status - data.ErrMessage = inputLog.ErrMessage + data.Status = status return } diff --git a/internal/use-case/simgos-sync-use-case/installation/lib.go b/internal/use-case/simgos-sync-use-case/installation/lib.go index e76eb127..b260776e 100644 --- a/internal/use-case/simgos-sync-use-case/installation/lib.go +++ b/internal/use-case/simgos-sync-use-case/installation/lib.go @@ -1,9 +1,11 @@ package installation import ( + esync "simrs-vx/internal/domain/sync-entities/log" 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" gh "github.com/karincake/getuk" @@ -11,9 +13,10 @@ import ( e "simrs-vx/internal/domain/main-entities/installation" esimgos "simrs-vx/internal/domain/simgos-entities/installation" - esync "simrs-vx/internal/domain/sync-entities/installation" ) +var now = time.Now() + func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esimgos.MInstalasi, error) { pl.SetLogInfo(event, nil, "started", "DBCreate") @@ -23,7 +26,7 @@ func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esi if len(dbx) > 0 { tx = dbx[0] } else { - tx = dg.I + tx = dg.IS["simrs"] } if err := tx.Create(&data).Error; err != nil { @@ -34,9 +37,9 @@ func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esi return &data, nil } -func CreateSimxLogData(input e.CreateDto, inputLog esync.InstallationSimxLog, event *pl.Event, dbx ...*gorm.DB) error { +func CreateSimxLogData(input esync.SimxLogDto, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, nil, "started", "DBCreate") - data := setDataSimxLog(&input, inputLog) + data := setDataSimxLog(&input) var tx *gorm.DB if len(dbx) > 0 { @@ -164,14 +167,9 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e // return nil //} -func DeleteData(data *e.Installation, event *pl.Event, dbx ...*gorm.DB) error { +func DeleteSimgosData(data *esimgos.MInstalasi, event *pl.Event) error { pl.SetLogInfo(event, data, "started", "DBDelete") - var tx *gorm.DB - if len(dbx) > 0 { - tx = dbx[0] - } else { - tx = dg.I - } + var tx = dg.IS["simrs"] if err := tx.Delete(&data).Error; err != nil { event.Status = "failed" From 435d3512fe93319d8b22c12743c4567efdef4d30 Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 13 Nov 2025 21:01:03 +0700 Subject: [PATCH 184/329] revise instalasi entity --- cmd/simgos-sync-migration/migrations/atlas.sum | 4 ++-- internal/domain/simgos-entities/installation/entity.go | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/simgos-sync-migration/migrations/atlas.sum b/cmd/simgos-sync-migration/migrations/atlas.sum index 50f3c7d3..f1405dd2 100644 --- a/cmd/simgos-sync-migration/migrations/atlas.sum +++ b/cmd/simgos-sync-migration/migrations/atlas.sum @@ -1,2 +1,2 @@ -h1:OaRZyFJMii/8wQ0XLWEpF9MIL8IXblx3IYvB7LN2XQ4= -20251113035508.sql h1:p/FKefphuiBjEND87ChQLS/lcZcnvn0aT5tRV43Dn5o= +h1:8jMmMBxSEls9jaOUrpQQV0wUPlORRwJWd5g9742Z2fQ= +20251113035508.sql h1:rjDlu6yDdy5xv6nrCOr7NialrLSLT23pzduYNq29Hf0= diff --git a/internal/domain/simgos-entities/installation/entity.go b/internal/domain/simgos-entities/installation/entity.go index faf2786e..f2b291f5 100644 --- a/internal/domain/simgos-entities/installation/entity.go +++ b/internal/domain/simgos-entities/installation/entity.go @@ -1,10 +1,10 @@ package installation type MInstalasi struct { - No_Instalasi uint `json:"no_instalasi" gorm:"primaryKey;autoIncrement"` - Nama_Instalasi string `json:"nama_instalasi"` - Status_Rawat_Inap uint `json:"status_rawat_inap"` - St_Aktif uint `json:"st_aktif"` + No_Instalasi uint `json:"no_instalasi" gorm:"primaryKey;autoIncrement;column:no_instalasi"` + Nama_Instalasi string `json:"nama_instalasi" gorm:"column:nama_instalasi"` + Status_Rawat_Inap uint `json:"status_rawat_inap" gorm:"column:status_rawat_inap"` + St_Aktif uint `json:"st_aktif" gorm:"column:st_aktif"` } func (MInstalasi) TableName() string { From d3ddebb2264b15a73e2350e7ceeff1105a759b10 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Fri, 14 Nov 2025 08:39:01 +0700 Subject: [PATCH 185/329] feat/prescription: added MedicineForm flow --- .../interface/main-handler/main-handler.go | 3 + .../main-handler/medicine-form/handler.go | 71 +++++ .../main-use-case/medicine-form/case.go | 276 ++++++++++++++++++ .../main-use-case/medicine-form/helper.go | 22 ++ .../main-use-case/medicine-form/lib.go | 147 ++++++++++ .../medicine-form/middleware-runner.go | 103 +++++++ .../main-use-case/medicine-form/middleware.go | 9 + .../main-use-case/medicine-form/tycovar.go | 44 +++ 8 files changed, 675 insertions(+) create mode 100644 internal/interface/main-handler/medicine-form/handler.go create mode 100644 internal/use-case/main-use-case/medicine-form/case.go create mode 100644 internal/use-case/main-use-case/medicine-form/helper.go create mode 100644 internal/use-case/main-use-case/medicine-form/lib.go create mode 100644 internal/use-case/main-use-case/medicine-form/middleware-runner.go create mode 100644 internal/use-case/main-use-case/medicine-form/middleware.go create mode 100644 internal/use-case/main-use-case/medicine-form/tycovar.go diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 04bef359..346436d0 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -91,6 +91,7 @@ import ( medicalactionsrc "simrs-vx/internal/interface/main-handler/medical-action-src" medicalactionsrcitem "simrs-vx/internal/interface/main-handler/medical-action-src-item" medicine "simrs-vx/internal/interface/main-handler/medicine" + medicineform "simrs-vx/internal/interface/main-handler/medicine-form" medicinegroup "simrs-vx/internal/interface/main-handler/medicine-group" medicinemethod "simrs-vx/internal/interface/main-handler/medicine-method" pharmacycompany "simrs-vx/internal/interface/main-handler/pharmacy-company" @@ -140,6 +141,7 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/auth-partner", authpartner.O) hc.RegCrud(r, "/v1/practice-schedule", practiceschedule.O) hc.RegCrud(r, "/v1/counter", counter.O) + hc.RegCrudByCode(r, "/v1/medicine-form", medicineform.O) hc.RegCrud(r, "/v1/medicine-mix", medicicinemix.O) hc.RegCrud(r, "/v1/medicine-mix-item", medicicinemixitem.O) hc.RegCrud(r, "/v1/soapi", auth.GuardMW, soapi.O) @@ -188,6 +190,7 @@ func SetRoutes() http.Handler { "POST /": prescription.O.Create, "PATCH /{id}": prescription.O.Update, "DELETE /{id}": prescription.O.Delete, + "PATCH /{id}/submit": prescription.O.Submit, "PATCH /{id}/approve": prescription.O.Approve, }) hk.GroupRoutes("/v1/mcu-order-sub-item", r, auth.GuardMW, hk.MapHandlerFunc{ diff --git a/internal/interface/main-handler/medicine-form/handler.go b/internal/interface/main-handler/medicine-form/handler.go new file mode 100644 index 00000000..a363fb30 --- /dev/null +++ b/internal/interface/main-handler/medicine-form/handler.go @@ -0,0 +1,71 @@ +package medicineform + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/medicine-form" + u "simrs-vx/internal/use-case/main-use-case/medicine-form" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { + return + } + dto := e.ReadDetailDto{} + dto.Code = &code + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Code = &code + res, err := u.Update(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { + return + } + + dto := e.DeleteDto{} + dto.Code = &code + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/use-case/main-use-case/medicine-form/case.go b/internal/use-case/main-use-case/medicine-form/case.go new file mode 100644 index 00000000..6eb0fb75 --- /dev/null +++ b/internal/use-case/main-use-case/medicine-form/case.go @@ -0,0 +1,276 @@ +package medicineform + +import ( + e "simrs-vx/internal/domain/main-entities/medicine-form" + "strconv" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "medicine-form" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.MedicineForm{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.MedicineForm + var dataList []e.MedicineForm + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.MedicineForm + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Code: input.Code} + var data *e.MedicineForm + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Code: input.Code} + var data *e.MedicineForm + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/medicine-form/helper.go b/internal/use-case/main-use-case/medicine-form/helper.go new file mode 100644 index 00000000..8e80369c --- /dev/null +++ b/internal/use-case/main-use-case/medicine-form/helper.go @@ -0,0 +1,22 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package medicineform + +import ( + e "simrs-vx/internal/domain/main-entities/medicine-form" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.MedicineForm) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Code = *inputSrc.Code + data.Name = inputSrc.Name +} diff --git a/internal/use-case/main-use-case/medicine-form/lib.go b/internal/use-case/main-use-case/medicine-form/lib.go new file mode 100644 index 00000000..01d570a2 --- /dev/null +++ b/internal/use-case/main-use-case/medicine-form/lib.go @@ -0,0 +1,147 @@ +package medicineform + +import ( + e "simrs-vx/internal/domain/main-entities/medicine-form" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.MedicineForm, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.MedicineForm{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.MedicineForm, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.MedicineForm{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.MedicineForm{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.MedicineForm, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.MedicineForm{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.MedicineForm, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.MedicineForm, 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 +} diff --git a/internal/use-case/main-use-case/medicine-form/middleware-runner.go b/internal/use-case/main-use-case/medicine-form/middleware-runner.go new file mode 100644 index 00000000..9b22189b --- /dev/null +++ b/internal/use-case/main-use-case/medicine-form/middleware-runner.go @@ -0,0 +1,103 @@ +package medicineform + +import ( + e "simrs-vx/internal/domain/main-entities/medicine-form" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.MedicineForm) 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.MedicineForm) 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.MedicineForm) 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.MedicineForm) 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.MedicineForm) 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/main-use-case/medicine-form/middleware.go b/internal/use-case/main-use-case/medicine-form/middleware.go new file mode 100644 index 00000000..b4388010 --- /dev/null +++ b/internal/use-case/main-use-case/medicine-form/middleware.go @@ -0,0 +1,9 @@ +package medicineform + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/medicine-form/tycovar.go b/internal/use-case/main-use-case/medicine-form/tycovar.go new file mode 100644 index 00000000..8dbd3509 --- /dev/null +++ b/internal/use-case/main-use-case/medicine-form/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 medicineform + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/medicine-form" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.MedicineForm, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.MedicineForm, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.MedicineForm, 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 From 9d26054e1b6bd3058670778515d4c9450e7378e8 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Fri, 14 Nov 2025 08:39:50 +0700 Subject: [PATCH 186/329] feat/prescription: more flow on medicine --- internal/domain/main-entities/medicine/dto.go | 5 +++++ internal/use-case/main-use-case/medicine/lib.go | 2 ++ 2 files changed, 7 insertions(+) diff --git a/internal/domain/main-entities/medicine/dto.go b/internal/domain/main-entities/medicine/dto.go index 945db1e5..71d41d42 100644 --- a/internal/domain/main-entities/medicine/dto.go +++ b/internal/domain/main-entities/medicine/dto.go @@ -4,6 +4,7 @@ import ( ecore "simrs-vx/internal/domain/base-entities/core" ein "simrs-vx/internal/domain/main-entities/infra" eit "simrs-vx/internal/domain/main-entities/item" + emf "simrs-vx/internal/domain/main-entities/medicine-form" emg "simrs-vx/internal/domain/main-entities/medicine-group" emm "simrs-vx/internal/domain/main-entities/medicine-method" eu "simrs-vx/internal/domain/main-entities/uom" @@ -71,6 +72,8 @@ type ResponseDto struct { MedicineGroup *emg.MedicineGroup `json:"medicineGroup"` MedicineMethod_Code *string `json:"medicineMethod_code"` MedicineMethod *emm.MedicineMethod `json:"medicineMethod"` + MedicineForm_Code *string `json:"medicineForm_code"` + MedicineForm *emf.MedicineForm `json:"medicineForm"` Uom_Code *string `json:"uom_code"` Uom *eu.Uom `json:"uom"` Dose uint8 `json:"dose"` @@ -89,6 +92,8 @@ func (d Medicine) ToResponse() ResponseDto { MedicineGroup: d.MedicineGroup, MedicineMethod_Code: d.MedicineMethod_Code, MedicineMethod: d.MedicineMethod, + MedicineForm_Code: d.MedicineForm_Code, + MedicineForm: d.MedicineForm, Uom_Code: d.Uom_Code, Uom: d.Uom, Dose: d.Dose, diff --git a/internal/use-case/main-use-case/medicine/lib.go b/internal/use-case/main-use-case/medicine/lib.go index f9fccb2e..8dfc4457 100644 --- a/internal/use-case/main-use-case/medicine/lib.go +++ b/internal/use-case/main-use-case/medicine/lib.go @@ -1,6 +1,7 @@ package medicine import ( + "fmt" e "simrs-vx/internal/domain/main-entities/medicine" plh "simrs-vx/pkg/lib-helper" @@ -47,6 +48,7 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Me tx = dg.I } + fmt.Println(input.Includes) tx = tx. Model(&e.Medicine{}). Scopes(gh.Preload(input.Includes)). From ae2ca4b1159f831bffa81c6a143cae838b68e31f Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Fri, 14 Nov 2025 08:40:17 +0700 Subject: [PATCH 187/329] feat/prescription: finalize Prescription --- .../main-entities/prescription-item/dto.go | 2 +- .../main-entities/prescription/entity.go | 4 ++ internal/domain/references/common/common.go | 1 + .../main-handler/prescription/handler.go | 12 ++++ .../main-use-case/prescription/case.go | 63 +++++++++++++++++++ 5 files changed, 81 insertions(+), 1 deletion(-) diff --git a/internal/domain/main-entities/prescription-item/dto.go b/internal/domain/main-entities/prescription-item/dto.go index 33e63ed2..6e871428 100644 --- a/internal/domain/main-entities/prescription-item/dto.go +++ b/internal/domain/main-entities/prescription-item/dto.go @@ -19,7 +19,7 @@ type CreateDto struct { Usage string `json:"usage"` Interval uint8 `json:"interval"` IntervalUnit_Code erc.TimeUnitCode `json:"intervalUnit_code"` - IntervalMultiplier *uint16 `json:"intervalMultiplier" validate:"required"` + IntervalMultiplier *uint16 `json:"intervalMultiplier"` Quantity float64 `json:"quantity"` } diff --git a/internal/domain/main-entities/prescription/entity.go b/internal/domain/main-entities/prescription/entity.go index 849e8083..8c879b29 100644 --- a/internal/domain/main-entities/prescription/entity.go +++ b/internal/domain/main-entities/prescription/entity.go @@ -20,6 +20,10 @@ type Prescription struct { Status_Code erc.DataStatusCode `json:"status_code"` } +func (d Prescription) IsNotNew() bool { + return d.Status_Code != erc.DSCNew +} + func (d Prescription) IsApproved() bool { return d.Status_Code == erc.DSCDone } diff --git a/internal/domain/references/common/common.go b/internal/domain/references/common/common.go index 2941049c..44a5c79b 100644 --- a/internal/domain/references/common/common.go +++ b/internal/domain/references/common/common.go @@ -58,6 +58,7 @@ const ( SCInactive ActiveStatusCode = "inactive" // Tidak aktif DSCNew DataStatusCode = "new" // Baru + DSCSubmited DataStatusCode = "submited" // Submited DSCReview DataStatusCode = "review" // Review DSCProcess DataStatusCode = "process" // Proses DSCDone DataStatusCode = "done" // Selesai diff --git a/internal/interface/main-handler/prescription/handler.go b/internal/interface/main-handler/prescription/handler.go index 24d73372..30d5998e 100644 --- a/internal/interface/main-handler/prescription/handler.go +++ b/internal/interface/main-handler/prescription/handler.go @@ -78,6 +78,18 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { rw.DataResponse(w, res, err) } +func (obj myBase) Submit(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.ReadDetailDto{} + dto.Id = uint(id) + res, err := u.Submit(dto) + rw.DataResponse(w, res, err) +} + func (obj myBase) Approve(w http.ResponseWriter, r *http.Request) { id := rw.ValidateInt(w, "id", r.PathValue("id")) if id <= 0 { diff --git a/internal/use-case/main-use-case/prescription/case.go b/internal/use-case/main-use-case/prescription/case.go index fa68ec44..e67ec03d 100644 --- a/internal/use-case/main-use-case/prescription/case.go +++ b/internal/use-case/main-use-case/prescription/case.go @@ -279,6 +279,69 @@ func Delete(input e.DeleteDto) (*d.Data, error) { } +func Submit(input e.ReadDetailDto) (*d.Data, error) { + var data *e.Prescription + var err error + + event := pl.Event{ + Feature: "Process", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "process") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + data, err = ReadDetailData(input, &event, tx) + if err != nil { + return err + } + + if data.IsNotNew() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-state-mismatch", + Detail: "prescription is not in new state", + Raw: errors.New("prescription is not in new state"), + } + return pl.SetLogError(&event, input) + } + + data.Status_Code = erc.DSCSubmited + 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 := createMedication(input.Id, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "submited", + }, + Data: data.ToResponse(), + }, nil + +} + func Approve(input e.ReadDetailDto) (*d.Data, error) { var data *e.Prescription var err error From 73d869f4c94c003429ba20ad7e478556549ff8a9 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Fri, 14 Nov 2025 09:52:07 +0700 Subject: [PATCH 188/329] feat (user): add position reg --- internal/use-case/main-use-case/user/case.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/use-case/main-use-case/user/case.go b/internal/use-case/main-use-case/user/case.go index 7c66b153..50b676af 100644 --- a/internal/use-case/main-use-case/user/case.go +++ b/internal/use-case/main-use-case/user/case.go @@ -166,6 +166,8 @@ func Create(input e.CreateDto) (*d.Data, error) { if _, err := umw.CreateData(createMidWife, &event, tx); err != nil { return err } + case ero.EPCReg: + // do nothing default: return errors.New("invalid employee position") } From 9e4357780b25257f32558400f6fed15cb07f4ea9 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 14 Nov 2025 09:52:50 +0700 Subject: [PATCH 189/329] add sync installation --- .../installation/handler.go | 50 +-- .../main-use-case/installation/case.go | 126 +++---- .../installation/middleware-runner.go | 19 +- .../main-use-case/installation/middleware.go | 6 + .../main-use-case/installation/tycovar.go | 22 +- .../simgos-sync-plugin/installation/plugin.go | 150 +++++--- .../simgos-sync-use-case/installation/case.go | 324 +++++++----------- .../simgos-sync-use-case/installation/lib.go | 186 +++++----- 8 files changed, 442 insertions(+), 441 deletions(-) diff --git a/internal/interface/simgos-sync-handler/installation/handler.go b/internal/interface/simgos-sync-handler/installation/handler.go index 6f9a708d..36424e71 100644 --- a/internal/interface/simgos-sync-handler/installation/handler.go +++ b/internal/interface/simgos-sync-handler/installation/handler.go @@ -2,6 +2,7 @@ package installation import ( "net/http" + "strconv" rw "github.com/karincake/risoles" // ua "github.com/karincake/tumpeng/auth/svc" @@ -34,28 +35,35 @@ func (obj myBase) CreateLog(w http.ResponseWriter, r *http.Request) { } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - //code := rw.ValidateString(w, "code", r.PathValue("code")) - //if code == "" { - // return - //} - // - //dto := e.UpdateDto{} - //if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { - // return - //} - //dto.Code = &code - //res, err := u.Update(dto) - //rw.DataResponse(w, res, err) + id := rw.ValidateString(w, "id", r.PathValue("id")) + if id == "" { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + + val, _ := strconv.ParseUint(id, 10, 16) + valUint := uint16(val) + dto.Id = &valUint + + res, err := u.Update(dto) + rw.DataResponse(w, res, err) } func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { - //code := rw.ValidateString(w, "code", r.PathValue("code")) - //if code == "" { - // return - //} - // - //dto := e.DeleteDto{} - //dto.Code = &code - //res, err := u.Delete(dto) - //rw.DataResponse(w, res, err) + id := rw.ValidateString(w, "id", r.PathValue("id")) + if id == "" { + return + } + + dto := e.DeleteDto{} + val, _ := strconv.ParseUint(id, 10, 16) + valUint := uint16(val) + dto.Id = &valUint + + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) } diff --git a/internal/use-case/main-use-case/installation/case.go b/internal/use-case/main-use-case/installation/case.go index d0a409c0..b80b6ca5 100644 --- a/internal/use-case/main-use-case/installation/case.go +++ b/internal/use-case/main-use-case/installation/case.go @@ -13,7 +13,6 @@ import ( "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/installation" - egos "simrs-vx/internal/domain/simgos-entities/installation" esync "simrs-vx/internal/domain/sync-entities/log" ) @@ -21,7 +20,6 @@ const source = "installation" func Create(input e.CreateDto) (*d.Data, error) { data := e.Installation{} - sgData := egos.MInstalasi{} event := pl.Event{ Feature: "Create", @@ -37,44 +35,24 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } else { data = *resData + id := uint(data.Id) + input.Id = &id } mwRunner.setMwType(pu.MWTPre) // Run pre-middleware - if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &sgData); err != nil { + if err := mwRunner.RunCreateMiddleware(createPreMw, &input); err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") - return nil }) - var errMsg string - inputLog := esync.SimxLogDto{ - Payload: input, - Method: erc.CCCreate, - } - - if err != nil { - // Run log-middleware - errMsg = err.Error() - inputLog.ErrMessage = &errMsg - inputLog.IsSuccess = false - - // create log failed - if err = mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog); err != nil { - return nil, err - } - + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } - // create log success - inputLog.IsSuccess = true - if err = mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog); err != nil { - return nil, err - } + pl.SetLogInfo(&event, nil, "complete") return &d.Data{ Meta: d.II{ @@ -87,7 +65,6 @@ func Create(input e.CreateDto) (*d.Data, error) { } func ReadList(input e.ReadListDto) (*d.Data, error) { - var data *e.Installation var dataList []e.Installation var metaList *e.MetaDto var err error @@ -101,23 +78,11 @@ 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 }) @@ -152,23 +117,11 @@ 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 }) @@ -198,6 +151,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "update") + mwRunner := newMiddlewareRunner(&event) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -205,32 +159,26 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } - mwRunner := newMiddlewareRunner(&event) - mwRunner.setMwType(pu.MWTPre) - // Run pre-middleware - if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { - return err - } - + input.Id = &data.Id if err := UpdateData(input, data, &event, tx); err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") - - 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.RunUpdateMiddleware(updatePreMw, &input); err != nil { return err } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -254,6 +202,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "delete") + mwRunner := newMiddlewareRunner(&event) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -261,30 +210,26 @@ func Delete(input e.DeleteDto) (*d.Data, error) { return err } - mwRunner := newMiddlewareRunner(&event) - mwRunner.setMwType(pu.MWTPre) - // Run pre-middleware - if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { - return err - } - + input.Id = &data.Id 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.RunDeleteMiddleware(deletePreMw, &input); err != nil { return err } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -295,3 +240,32 @@ func Delete(input e.DeleteDto) (*d.Data, error) { }, nil } + +func runLogMiddleware(err error, input any, mwRunner *middlewareRunner) error { + var errMsg string + inputLog := esync.SimxLogDto{ + Payload: input, + Method: erc.CCCreate, + } + + if err != nil { + // Run log-middleware + errMsg = err.Error() + inputLog.ErrMessage = &errMsg + inputLog.IsSuccess = false + + // create log failed + if errMiddleware := mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog); errMiddleware != nil { + return errMiddleware + } + return err + } + + // create log success + inputLog.IsSuccess = true + if err = mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog); err != nil { + return err + } + + return nil +} 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 acfaaa47..5a8e2ad0 100644 --- a/internal/use-case/main-use-case/installation/middleware-runner.go +++ b/internal/use-case/main-use-case/installation/middleware-runner.go @@ -7,7 +7,6 @@ import ( "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/installation" - egos "simrs-vx/internal/domain/simgos-entities/installation" esync "simrs-vx/internal/domain/sync-entities/log" ) @@ -25,13 +24,13 @@ func newMiddlewareRunner(event *pl.Event) *middlewareRunner { } // ExecuteCreateMiddleware executes create middleware -func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *egos.MInstalasi) error { +func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto) 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) } @@ -86,13 +85,13 @@ func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, return nil } -func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Installation) error { +func (me *middlewareRunner) RunUpdateMiddleware(middlewares []UpdateMw, input *e.UpdateDto) 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,13 +100,13 @@ func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, inpu return nil } -func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Installation) 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) } diff --git a/internal/use-case/main-use-case/installation/middleware.go b/internal/use-case/main-use-case/installation/middleware.go index 222ec563..dd4b0b42 100644 --- a/internal/use-case/main-use-case/installation/middleware.go +++ b/internal/use-case/main-use-case/installation/middleware.go @@ -13,4 +13,10 @@ func init() { createSimxLogMw = append(createSimxLogMw, createLogMw{Name: "create-log", Func: plugin.CreateLog}, ) + + updatePreMw = append(updatePreMw, + updateMw{Name: "update-installation", Func: plugin.Update}) + + deletePreMw = append(deletePreMw, + deleteMw{Name: "delete-installation", Func: plugin.Delete}) } diff --git a/internal/use-case/main-use-case/installation/tycovar.go b/internal/use-case/main-use-case/installation/tycovar.go index e704b3a1..262bba8c 100644 --- a/internal/use-case/main-use-case/installation/tycovar.go +++ b/internal/use-case/main-use-case/installation/tycovar.go @@ -9,8 +9,6 @@ functionality. The purpose of this is to make the code more maintainable. package installation import ( - egos "simrs-vx/internal/domain/simgos-entities/installation" - "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/installation" @@ -19,7 +17,7 @@ import ( type createMw struct { Name string - Func func(input *e.CreateDto, data *egos.MInstalasi, tx *gorm.DB) error + Func func(input *e.CreateDto) error } type createLogMw struct { @@ -27,6 +25,16 @@ type createLogMw struct { Func func(input *elog.SimxLogDto) error } +type updateMw struct { + Name string + Func func(input *e.UpdateDto) error +} + +type deleteMw struct { + Name string + Func func(input *e.DeleteDto) error +} + type readListMw struct { Name string Func func(input *e.ReadListDto, data *e.Installation, tx *gorm.DB) error @@ -37,8 +45,8 @@ type readDetailMw struct { Func func(input *e.ReadDetailDto, data *e.Installation, 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 @@ -47,7 +55,7 @@ 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 diff --git a/internal/use-case/simgos-sync-plugin/installation/plugin.go b/internal/use-case/simgos-sync-plugin/installation/plugin.go index b566302b..06c9bebe 100644 --- a/internal/use-case/simgos-sync-plugin/installation/plugin.go +++ b/internal/use-case/simgos-sync-plugin/installation/plugin.go @@ -7,54 +7,14 @@ import ( "io" "net/http" - "gorm.io/gorm" - sync "simrs-vx/internal/infra/sync-cfg" e "simrs-vx/internal/domain/main-entities/installation" - egos "simrs-vx/internal/domain/simgos-entities/installation" elog "simrs-vx/internal/domain/sync-entities/log" ) -func Create(input *e.CreateDto, data *egos.MInstalasi, tx *gorm.DB) error { - var endpoint = fmt.Sprintf("%s%s/v1/installation", sync.O.Host, sync.O.Prefix) - - 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() - - if resp.StatusCode != http.StatusOK { - return fmt.Errorf(resp.Status) - } - - body, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - if err := json.Unmarshal(body, &data); err != nil { - return fmt.Errorf("failed to parse response JSON: %w", err) - } - - return nil -} - -func CreateLog(input *elog.SimxLogDto) error { - var endpoint = fmt.Sprintf("%s%s/v1/installation/log", sync.O.Host, sync.O.Prefix) +func Create(input *e.CreateDto) error { + endpoint := getPrefixEndpoint() jsonData, err := json.Marshal(input) if err != nil { @@ -85,3 +45,109 @@ func CreateLog(input *elog.SimxLogDto) error { return nil } + +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() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf(resp.Status) + } + + _, err = io.ReadAll(resp.Body) + if err != nil { + return err + } + + return nil +} + +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() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf(resp.Status) + } + + _, err = io.ReadAll(resp.Body) + if err != nil { + return err + } + + return nil +} + +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() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf(resp.Status) + } + + _, err = io.ReadAll(resp.Body) + if err != nil { + return err + } + + return nil +} + +func getPrefixEndpoint() string { + return fmt.Sprintf("%s%s/v1/installation", sync.O.Host, sync.O.Prefix) +} diff --git a/internal/use-case/simgos-sync-use-case/installation/case.go b/internal/use-case/simgos-sync-use-case/installation/case.go index f38cca14..6c3a79bd 100644 --- a/internal/use-case/simgos-sync-use-case/installation/case.go +++ b/internal/use-case/simgos-sync-use-case/installation/case.go @@ -1,14 +1,14 @@ package installation import ( + "errors" + esimgos "simrs-vx/internal/domain/simgos-entities/installation" esync "simrs-vx/internal/domain/sync-entities/log" - "strconv" dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" pl "simrs-vx/pkg/logger" - pu "simrs-vx/pkg/use-case-helper" "gorm.io/gorm" @@ -18,6 +18,11 @@ import ( const source = "installation" func Create(input e.CreateDto) (*d.Data, error) { + var ( + txSync = dg.I.Begin() + txSimgos = dg.IS["simrs"].Begin() + ) + event := pl.Event{ Feature: "Create", Source: source, @@ -26,10 +31,6 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - // Define trx - txSync := dg.I.Begin() - txSimgos := dg.IS["simrs"].Begin() - // STEP 1: Insert to simgos sgData, err := CreateSimgosData(input, &event, txSimgos) if err != nil { @@ -37,7 +38,7 @@ func Create(input e.CreateDto) (*d.Data, error) { } // STEP 2: Insert to Link - if err = CreateInstallationLinkData(*input.Id, sgData.No_Instalasi, &event, txSync); err != nil { + if err = CreateLinkData(*input.Id, sgData.No_Instalasi, &event, txSync); err != nil { txSimgos.Rollback() return nil, err } @@ -65,7 +66,6 @@ func Create(input e.CreateDto) (*d.Data, error) { "structure": "single-data", "status": "created", }, - Data: sgData, }, nil } @@ -80,7 +80,7 @@ func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { err := dg.I.Transaction(func(tx *gorm.DB) error { // InsertSimxLog - if err := CreateSimxLogData(input, &event, tx); err != nil { + if err := CreateLogData(input, &event, tx); err != nil { return err } @@ -93,6 +93,8 @@ func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.II{ "source": source, @@ -102,212 +104,152 @@ func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { }, nil } -func ReadList(input e.ReadListDto) (*d.Data, error) { - var data *e.Installation - var dataList []e.Installation - var metaList *e.MetaDto - var err error +func Update(input e.UpdateDto) (*d.Data, error) { + var ( + txSync = dg.I.Begin() + txSimgos = dg.IS["simrs"].Begin() + sgData *esimgos.MInstalasi + err error + ) event := pl.Event{ - Feature: "ReadList", + Feature: "Update", Source: source, } // Start log - pl.SetLogInfo(&event, input, "started", "readList") + pl.SetLogInfo(&event, input, "started", "update") - 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 + // STEP 1: Get Installation Link + syncLink, errGetLink := ReadDetailLinkData(*input.Id, &event) + if errGetLink != nil { + if !errors.Is(err, gorm.ErrRecordNotFound) { + return nil, err + } + } + + if errGetLink != nil && errors.Is(errGetLink, gorm.ErrRecordNotFound) { + // STEP 2.1: Insert to simgos + sgData, err = CreateSimgosData(input.CreateDto, &event, txSimgos) + if err != nil { + return nil, err } - if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { - return err + // STEP 2.2: Insert to Link + simxId := uint(*input.Id) + if err = CreateLinkData(simxId, sgData.No_Instalasi, &event, txSync); err != nil { + txSimgos.Rollback() + return nil, err } - - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { - return err + } else { + // Step 3.1: Update Simgos + err = UpdateSimgosData(input, syncLink, &event, txSimgos) + if err != nil { + return nil, err } + } - return nil - }) - - if err != nil { + // STEP 4: Commit two trx + if err = txSimgos.Commit().Error; err != nil { + txSimgos.Rollback() + txSync.Rollback() return nil, err } - return &d.Data{ - Meta: d.IS{ - "source": source, - "structure": "list-data", - "status": "fetched", - "page_number": strconv.Itoa(metaList.PageNumber), - "page_size": strconv.Itoa(metaList.PageSize), - "record_totalCount": strconv.Itoa(metaList.Count), - "record_currentCount": strconv.Itoa(len(dataList)), - }, - Data: e.ToResponseList(dataList), - }, nil -} - -func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { - var data *e.Installation - var err error - - event := pl.Event{ - Feature: "ReadDetail", - Source: source, + if errGetLink != nil { + if err = txSync.Commit().Error; err != nil { + // STEP 5.1: Rollback Partial + go func() { + _ = DeleteSimgosData(sgData, &event) + }() + return nil, err + } } - // Start log - 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 - }) - - if err != nil { - return nil, err - } + pl.SetLogInfo(&event, nil, "complete") return &d.Data{ Meta: d.IS{ "source": source, "structure": "single-data", - "status": "fetched", + "status": "updated", }, - Data: data.ToResponse(), }, nil } -//func Update(input e.UpdateDto) (*d.Data, error) { -// rdDto := e.ReadDetailDto{Code: input.Code} -// var data *e.Installation -// var err error -// -// event := pl.Event{ -// Feature: "Update", -// Source: source, -// } -// -// // Start log -// pl.SetLogInfo(&event, input, "started", "update") -// -// err = dg.I.Transaction(func(tx *gorm.DB) error { -// pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") -// if data, err = ReadDetailData(rdDto, &event, tx); err != nil { -// 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") -// -// mwRunner.setMwType(pu.MWTPost) -// // Run post-middleware -// if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { -// return err -// } -// -// return nil -// }) -// -// if err != nil { -// return nil, err -// } -// -// return &d.Data{ -// Meta: d.IS{ -// "source": source, -// "structure": "single-data", -// "status": "updated", -// }, -// Data: data.ToResponse(), -// }, nil -// -//} +func Delete(input e.DeleteDto) (*d.Data, error) { + var ( + txSync = dg.I.Begin() + txSimgos = dg.IS["simrs"].Begin() + sgData *esimgos.MInstalasi + err error + ) -//func Delete(input e.DeleteDto) (*d.Data, error) { -// rdDto := e.ReadDetailDto{Code: input.Code} -// var data *e.Installation -// var err error -// -// event := pl.Event{ -// Feature: "Delete", -// Source: source, -// } -// -// // Start log -// pl.SetLogInfo(&event, input, "started", "delete") -// -// err = dg.I.Transaction(func(tx *gorm.DB) error { -// pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") -// if data, err = ReadDetailData(rdDto, &event, tx); err != nil { -// 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 { -// return err -// } -// -// return nil -// }) -// -// if err != nil { -// return nil, err -// } -// -// return &d.Data{ -// Meta: d.IS{ -// "source": source, -// "structure": "single-data", -// "status": "deleted", -// }, -// Data: data.ToResponse(), -// }, nil -// -//} + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + // STEP 1: Get Installation Link + syncLink, errGetLink := ReadDetailLinkData(*input.Id, &event) + if errGetLink != nil { + if !errors.Is(err, gorm.ErrRecordNotFound) { + return nil, err + } + } + + if errGetLink == nil { + // STEP 2: Get Simgos + sgData, err = ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) + if err != nil { + return nil, err + } + + // STEP 3: Delete M_Instalation Simgos + err = DeleteSimgosData(sgData, &event, txSimgos) + if err != nil { + return nil, err + } + + // STEP 4: Delete Installation Link + err = DeleteLinkData(syncLink, &event, txSync) + if err != nil { + txSimgos.Rollback() + return nil, err + } + + // STEP 4: Commit two trx + if err = txSimgos.Commit().Error; err != nil { + txSimgos.Rollback() + txSync.Rollback() + return nil, err + } + + if err = txSync.Commit().Error; err != nil { + // STEP 5: Rollback Partial + go func() { + inputRollback := e.UpdateDto{ + CreateDto: e.CreateDto{ + Name: sgData.Nama_Instalasi, + }, + } + _ = UpdateSimgosData(inputRollback, syncLink, &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/installation/lib.go b/internal/use-case/simgos-sync-use-case/installation/lib.go index b260776e..3e7ca854 100644 --- a/internal/use-case/simgos-sync-use-case/installation/lib.go +++ b/internal/use-case/simgos-sync-use-case/installation/lib.go @@ -1,18 +1,17 @@ package installation import ( - esync "simrs-vx/internal/domain/sync-entities/log" + esynclog "simrs-vx/internal/domain/sync-entities/log" 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" - gh "github.com/karincake/getuk" "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/installation" esimgos "simrs-vx/internal/domain/simgos-entities/installation" + esync "simrs-vx/internal/domain/sync-entities/installation" ) var now = time.Now() @@ -37,26 +36,76 @@ func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esi return &data, nil } -func CreateSimxLogData(input esync.SimxLogDto, event *pl.Event, dbx ...*gorm.DB) error { - pl.SetLogInfo(event, nil, "started", "DBCreate") - data := setDataSimxLog(&input) +func ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.MInstalasi, error) { + pl.SetLogInfo(event, simgosId, "started", "DBReadDetail") + data := esimgos.MInstalasi{} + + var tx = dg.IS["simrs"] + + if err := tx. + Where("\"no_instalasi\" = ?", simgosId). + First(&data).Error; err != nil { + return nil, err + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateSimgosData(input e.UpdateDto, dataSimgos *esync.InstallationLink, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, input, "started", "DBUpdate") + + data := setDataSimgos(&input) + data.No_Instalasi = dataSimgos.Simgos_Id var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] } else { - tx = dg.I + tx = dg.IS["simrs"] } - if err := tx.Create(&data).Error; err != nil { - return plh.HandleCreateError(input, event, err) + 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 CreateInstallationLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) error { +func DeleteSimgosData(data *esimgos.MInstalasi, 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"] + } + + data.St_Aktif = 0 + + if err := tx.Save(&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 CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, nil, "started", "DBCreate") data := setDataSimxLink(simxId, simgosId) @@ -75,101 +124,31 @@ func CreateInstallationLinkData(simxId, simgosId uint, event *pl.Event, dbx ...* return nil } -func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Installation, *e.MetaDto, error) { - pl.SetLogInfo(event, input, "started", "DBReadList") - data := []e.Installation{} - pagination := gh.Pagination{} - count := int64(0) - meta := e.MetaDto{} +func ReadDetailLinkData(simxId uint16, event *pl.Event) (*esync.InstallationLink, error) { + pl.SetLogInfo(event, simxId, "started", "DBReadDetail") + data := esync.InstallationLink{} - var tx *gorm.DB - if len(dbx) > 0 { - tx = dbx[0] - } else { - tx = dg.I - } - - tx = tx. - Model(&e.Installation{}). - Scopes(gh.Preload(input.Includes)). - Scopes(gh.Filter(input.FilterDto)). - Count(&count). - Scopes(gh.Paginate(input, &pagination)). - Scopes(gh.Sort(input.Sort)) - - if err := tx.Find(&data).Error; err != nil { - if err == gorm.ErrRecordNotFound { - return nil, &meta, nil - } - return nil, nil, plh.HandleListError(input, event, err) - } - - meta.Count = int(count) - meta.PageNumber = pagination.PageNumber - meta.PageSize = pagination.PageSize - - pl.SetLogInfo(event, nil, "complete") - return data, &meta, nil -} - -func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.Installation, error) { - pl.SetLogInfo(event, input, "started", "DBReadDetail") - data := e.Installation{} - - var tx *gorm.DB - if len(dbx) > 0 { - tx = dbx[0] - } else { - tx = dg.I - } - - if input.Code != nil { - tx = tx.Where("\"Code\" = ?", *input.Code) - } - if input.Id != nil { - tx = tx.Where("\"Id\" = ?", *input.Id) - } + var tx = dg.I if err := tx. - Scopes(gh.Preload(input.Includes)). + Where("\"Simx_Id\" = ?", simxId). First(&data).Error; err != nil { - if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { - return nil, processedErr - } + return nil, err } pl.SetLogInfo(event, nil, "complete") return &data, nil } -//func UpdateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) error { -// pl.SetLogInfo(event, input, "started", "DBUpdate") -// setData(&input, data) -// -// var tx *gorm.DB -// if len(dbx) > 0 { -// tx = dbx[0] -// } else { -// tx = dg.I -// } -// -// 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 DeleteSimgosData(data *esimgos.MInstalasi, event *pl.Event) error { +func DeleteLinkData(data *esync.InstallationLink, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, data, "started", "DBDelete") - var tx = dg.IS["simrs"] + + 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" @@ -184,3 +163,22 @@ func DeleteSimgosData(data *esimgos.MInstalasi, event *pl.Event) error { 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 +} From a053a351147b64f2b6125066236239fee537a455 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 14 Nov 2025 10:08:49 +0700 Subject: [PATCH 190/329] update sync --- cmd/main-api/config.yml-example | 6 +++++- internal/interface/migration/simgos-sync-entities.go | 5 ----- .../interface/simgos-sync-handler/simgos-sync-handler.go | 3 --- 3 files changed, 5 insertions(+), 9 deletions(-) delete mode 100644 internal/interface/migration/simgos-sync-entities.go diff --git a/cmd/main-api/config.yml-example b/cmd/main-api/config.yml-example index 60b1644c..448cff66 100644 --- a/cmd/main-api/config.yml-example +++ b/cmd/main-api/config.yml-example @@ -66,4 +66,8 @@ corsCfg: allowedMethod: bpjsCfg: - baseUrl: \ No newline at end of file + baseUrl: + +syncUrlCfg: + host: + prefix: new-to-old \ No newline at end of file diff --git a/internal/interface/migration/simgos-sync-entities.go b/internal/interface/migration/simgos-sync-entities.go deleted file mode 100644 index c6b51988..00000000 --- a/internal/interface/migration/simgos-sync-entities.go +++ /dev/null @@ -1,5 +0,0 @@ -package migration - -func getSimgosSync() []any { - return []any{} -} diff --git a/internal/interface/simgos-sync-handler/simgos-sync-handler.go b/internal/interface/simgos-sync-handler/simgos-sync-handler.go index 71002949..ce2b4ab9 100644 --- a/internal/interface/simgos-sync-handler/simgos-sync-handler.go +++ b/internal/interface/simgos-sync-handler/simgos-sync-handler.go @@ -6,8 +6,6 @@ import ( /******************** infra ********************/ gs "simrs-vx/internal/infra/gorm-setting" simgosdb "simrs-vx/internal/infra/simgos-db" - simgossync "simrs-vx/internal/infra/sync-cfg" - /******************** pkg ********************/ cmw "simrs-vx/pkg/cors-manager-mw" lh "simrs-vx/pkg/lang-helper" @@ -28,7 +26,6 @@ func SetRoutes() http.Handler { a.RegisterExtCall(gs.Adjust) a.RegisterExtCall(zlc.Adjust) a.RegisterExtCall(lh.Populate) - a.RegisterExtCall(simgossync.SetConfig) a.RegisterExtCall(simgosdb.SetInstance) r := http.NewServeMux() From d4c3b0e31ccc5f62241321615c9425fad974ed7a Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Fri, 14 Nov 2025 10:11:10 +0700 Subject: [PATCH 191/329] feat (user): status_code static as active --- internal/use-case/main-use-case/user/helper.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/use-case/main-use-case/user/helper.go b/internal/use-case/main-use-case/user/helper.go index acb32331..ed500bac 100644 --- a/internal/use-case/main-use-case/user/helper.go +++ b/internal/use-case/main-use-case/user/helper.go @@ -18,6 +18,7 @@ import ( ee "simrs-vx/internal/domain/main-entities/employee" esi "simrs-vx/internal/domain/main-entities/specialist-intern" e "simrs-vx/internal/domain/main-entities/user" + erc "simrs-vx/internal/domain/references/common" erg "simrs-vx/internal/domain/references/organization" ) @@ -29,7 +30,7 @@ func setCreate(src e.CreateDto, dst *e.User) error { dst.Name = src.Name dst.Password = pass - dst.Status_Code = src.Status_Code + dst.Status_Code = erc.USCActive dst.ContractPosition_Code = src.ContractPosition_Code return nil From 07e3c3b707056d47b372db6f178c2f62f8d8fda6 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Fri, 14 Nov 2025 10:37:21 +0700 Subject: [PATCH 192/329] fix (encounter): missmatch position checking --- internal/lib/auth/tycovar.go | 4 ++ .../use-case/main-use-case/encounter/case.go | 39 +++++++++++++++++-- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/internal/lib/auth/tycovar.go b/internal/lib/auth/tycovar.go index 3567cd61..70a6fec2 100644 --- a/internal/lib/auth/tycovar.go +++ b/internal/lib/auth/tycovar.go @@ -92,3 +92,7 @@ func (a AuthInfo) IsNurseIntern() bool { } return *a.Intern_Position_Code == string(ero.IPCNurse) } + +func (a AuthInfo) HasEmployeePosition() bool { + return a.Employee_Position_Code != nil +} diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 8a006a35..e3d564ff 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -78,8 +78,19 @@ func Create(input e.CreateDto) (*d.Data, error) { } } + // check if user has employee position + if !input.AuthInfo.HasEmployeePosition() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "auth-forbidden", + Detail: "user has no employee position", + Raw: errors.New("authentication failed"), + } + return nil, pl.SetLogError(&event, input) + } + // check only user with registration position is allowed to create encounter - if input.AuthInfo.User_ContractPosition_Code != string(erg.EPCReg) { + if input.AuthInfo.Employee_Position_Code != nil && *input.AuthInfo.Employee_Position_Code != string(erg.EPCReg) { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "auth-forbidden", @@ -328,8 +339,19 @@ func Delete(input e.DeleteDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "delete") + // check if user has employee position + if !input.AuthInfo.HasEmployeePosition() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "auth-forbidden", + Detail: "user has no employee position", + Raw: errors.New("authentication failed"), + } + return nil, pl.SetLogError(&event, input) + } + // check only user with registration position is allowed to create encounter - if input.AuthInfo.User_ContractPosition_Code != string(erg.EPCReg) { + if input.AuthInfo.Employee_Position_Code != nil && *input.AuthInfo.Employee_Position_Code != string(erg.EPCReg) { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "auth-forbidden", @@ -517,7 +539,18 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) { string(erg.EPCDoc), } - if !pu.Contains(roleAllowedToCancel, input.AuthInfo.User_ContractPosition_Code) { + // check if user has employee position + if !input.AuthInfo.HasEmployeePosition() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "auth-forbidden", + Detail: "user has no employee position", + Raw: errors.New("authentication failed"), + } + return pl.SetLogError(&event, input) + } + + if input.AuthInfo.Employee_Position_Code != nil && !pu.Contains(roleAllowedToCancel, *input.AuthInfo.Employee_Position_Code) { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "auth-forbidden", From 05682754b5240107455c981dab50ee6c338dfc67 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 14 Nov 2025 10:38:00 +0700 Subject: [PATCH 193/329] add constant upload --- internal/domain/references/upload/upload.go | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/internal/domain/references/upload/upload.go b/internal/domain/references/upload/upload.go index 603be6c8..b22960f4 100644 --- a/internal/domain/references/upload/upload.go +++ b/internal/domain/references/upload/upload.go @@ -8,13 +8,16 @@ type ( ) const ( - UCPRN UploadCode = "person-resident-number" // Person Resident Number - UCPDL UploadCode = "person-driver-license" // Person Driver License - UCPP UploadCode = "person-passport" // Person Passport - UCPFC UploadCode = "person-family-card" // Person Family Card - UCMIR UploadCode = "mcu-item-result" // Mcu Item Result - UCSEP UploadCode = "vclaim-sep" // SEP - UCSIPP UploadCode = "vclaim-sipp" // SIPP + UCPRN UploadCode = "person-resident-number" // Person Resident Number + UCPDL UploadCode = "person-driver-license" // Person Driver License + UCPP UploadCode = "person-passport" // Person Passport + UCPFC UploadCode = "person-family-card" // Person Family Card + UCMIR UploadCode = "mcu-item-result" // Mcu Item Result + UCEnPatient UploadCode = "encounter-patient" + UCEnSupport UploadCode = "encounter-support" + UcEnOther UploadCode = "encounter-other" + UCSEP UploadCode = "vclaim-sep" // SEP + UCSIPP UploadCode = "vclaim-sipp" // SIPP ETCPerson EntityTypeCode = "person" ETCEncounter EntityTypeCode = "encounter" @@ -26,7 +29,7 @@ var validUploadCodesByEntity = map[EntityTypeCode][]UploadCode{ UCPRN, UCPDL, UCPP, UCPFC, }, ETCEncounter: { - UCSEP, UCSIPP, + UCSEP, UCSIPP, UCEnPatient, UCEnSupport, UcEnOther, }, ETCMCU: { UCMIR, From b604216649a42d20fee2063796b35ebd3551f5e1 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 14 Nov 2025 11:27:43 +0700 Subject: [PATCH 194/329] adjust upload --- .../encounter-document/handler.go | 71 +++++++++++++++++++ .../interface/main-handler/main-handler.go | 11 +-- .../interface/main-handler/upload/handler.go | 5 +- .../main-use-case/encounter-document/case.go | 13 ---- .../use-case/main-use-case/upload/case.go | 1 + .../use-case/main-use-case/upload/helper.go | 43 +++++++---- 6 files changed, 110 insertions(+), 34 deletions(-) create mode 100644 internal/interface/main-handler/encounter-document/handler.go diff --git a/internal/interface/main-handler/encounter-document/handler.go b/internal/interface/main-handler/encounter-document/handler.go new file mode 100644 index 00000000..60fa6d6a --- /dev/null +++ b/internal/interface/main-handler/encounter-document/handler.go @@ -0,0 +1,71 @@ +package encounter_document + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + e "simrs-vx/internal/domain/main-entities/encounter-document" + u "simrs-vx/internal/use-case/main-use-case/encounter-document" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + + sf.UrlQueryParam(&dto, *r.URL) + dto.Id = uint16(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint16(id) + 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 = uint16(id) + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 346436d0..c834d963 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -2,6 +2,7 @@ package handler import ( "net/http" + encounterdocument "simrs-vx/internal/interface/main-handler/encounter-document" /******************** main / transaction ********************/ adime "simrs-vx/internal/interface/main-handler/adime" @@ -72,6 +73,7 @@ import ( /******************** sources ********************/ device "simrs-vx/internal/interface/main-handler/device" diagnosesrc "simrs-vx/internal/interface/main-handler/diagnose-src" + district "simrs-vx/internal/interface/main-handler/district" division "simrs-vx/internal/interface/main-handler/division" divisionposition "simrs-vx/internal/interface/main-handler/division-position" doctorfee "simrs-vx/internal/interface/main-handler/doctor-fee" @@ -95,7 +97,10 @@ import ( medicinegroup "simrs-vx/internal/interface/main-handler/medicine-group" medicinemethod "simrs-vx/internal/interface/main-handler/medicine-method" pharmacycompany "simrs-vx/internal/interface/main-handler/pharmacy-company" + postalregion "simrs-vx/internal/interface/main-handler/postal-region" proceduresrc "simrs-vx/internal/interface/main-handler/procedure-src" + province "simrs-vx/internal/interface/main-handler/province" + regency "simrs-vx/internal/interface/main-handler/regency" specialist "simrs-vx/internal/interface/main-handler/specialist" specialistposition "simrs-vx/internal/interface/main-handler/specialist-position" subspecialist "simrs-vx/internal/interface/main-handler/subspecialist" @@ -106,11 +111,6 @@ import ( uom "simrs-vx/internal/interface/main-handler/uom" vehicle "simrs-vx/internal/interface/main-handler/vehicle" vehiclehist "simrs-vx/internal/interface/main-handler/vehicle-hist" - - district "simrs-vx/internal/interface/main-handler/district" - postalregion "simrs-vx/internal/interface/main-handler/postal-region" - province "simrs-vx/internal/interface/main-handler/province" - regency "simrs-vx/internal/interface/main-handler/regency" village "simrs-vx/internal/interface/main-handler/village" ///// Internal @@ -273,6 +273,7 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/therapy-protocol", therapyprotocol.O) hc.RegCrud(r, "/v1/chemo-protocol", chemoprotocol.O) hc.RegCrud(r, "/v1/upload", upload.O) + hc.RegCrud(r, "/v1/encounter-document", encounterdocument.O) /******************** actor ********************/ hc.RegCrud(r, "/v1/person", person.O) diff --git a/internal/interface/main-handler/upload/handler.go b/internal/interface/main-handler/upload/handler.go index 9f1f45a0..abf8919d 100644 --- a/internal/interface/main-handler/upload/handler.go +++ b/internal/interface/main-handler/upload/handler.go @@ -6,11 +6,11 @@ import ( eru "simrs-vx/internal/domain/references/upload" + e "simrs-vx/internal/domain/main-entities/upload" + d "github.com/karincake/dodol" rw "github.com/karincake/risoles" - e "simrs-vx/internal/domain/main-entities/upload" - u "simrs-vx/internal/use-case/main-use-case/upload" ) @@ -86,4 +86,5 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { } func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { + } diff --git a/internal/use-case/main-use-case/encounter-document/case.go b/internal/use-case/main-use-case/encounter-document/case.go index 206b5e1d..88592db7 100644 --- a/internal/use-case/main-use-case/encounter-document/case.go +++ b/internal/use-case/main-use-case/encounter-document/case.go @@ -244,13 +244,6 @@ 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 := removeUploadedFile(string(eru.ETCEncounter), *data.FilePath, &event); err != nil { return err } @@ -259,12 +252,6 @@ func Delete(input e.DeleteDto) (*d.Data, error) { return err } - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { - return err - } - return nil }) diff --git a/internal/use-case/main-use-case/upload/case.go b/internal/use-case/main-use-case/upload/case.go index 40ff74f6..0d11a308 100644 --- a/internal/use-case/main-use-case/upload/case.go +++ b/internal/use-case/main-use-case/upload/case.go @@ -4,6 +4,7 @@ import ( "errors" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" + "strconv" dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" diff --git a/internal/use-case/main-use-case/upload/helper.go b/internal/use-case/main-use-case/upload/helper.go index 652d80fa..0ddfd220 100644 --- a/internal/use-case/main-use-case/upload/helper.go +++ b/internal/use-case/main-use-case/upload/helper.go @@ -164,29 +164,44 @@ func setEncounterDocument(input e.CreateDto, event *pl.Event, tx *gorm.DB) (*ee. Upload_Employee_Id: input.Upload_Employee_Id, } - if len(dataUpload) > 0 { - if err := removeUploadedFile(string(input.EntityType_Code), *dataUpload[0].FilePath, *dataUpload[0].Encounter_Id, event); err != nil { - return nil, err + if input.Type_Code == eru.UCSEP || input.Type_Code == eru.UCSIPP { + if len(dataUpload) > 0 { + data = dataUpload[0] + + // remove file + if err := removeUploadedFile(string(input.EntityType_Code), *data.FilePath, *data.Encounter_Id, event); err != nil { + return nil, err + } + + // update data + err = ue.UpdateData(ee.UpdateDto{ + Id: uint16(data.Id), + CreateDto: createDto}, &data, event, tx) + if err != nil { + return nil, err + } + + data.FilePath = &input.FilePath + + return &data, nil } - // update data - err = ue.UpdateData(ee.UpdateDto{ - Id: uint16(dataUpload[0].Id), - CreateDto: createDto}, &dataUpload[0], event, tx) - if err != nil { - return nil, err - } - - data = dataUpload[0] - data.FilePath = &input.FilePath - } else { // insert data resData, err := ue.CreateData(createDto, event, tx) if err != nil { return nil, err } data = *resData + + return &data, nil } + // insert data + resData, err := ue.CreateData(createDto, event, tx) + if err != nil { + return nil, err + } + data = *resData + return &data, nil } From 85761d9be4c8ab2785149c3a572ca65d4216c189 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 14 Nov 2025 12:03:18 +0700 Subject: [PATCH 195/329] adjust upload --- internal/interface/main-handler/main-handler.go | 2 +- internal/interface/main-handler/upload/handler.go | 7 +++---- internal/use-case/main-use-case/upload/helper.go | 9 --------- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 707f6fd6..b6edbbee 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -2,7 +2,6 @@ package handler import ( "net/http" - encounterdocument "simrs-vx/internal/interface/main-handler/encounter-document" "simrs-vx/internal/interface/main-handler/upload" /******************** main / transaction ********************/ @@ -18,6 +17,7 @@ import ( deviceorder "simrs-vx/internal/interface/main-handler/device-order" deviceorderitem "simrs-vx/internal/interface/main-handler/device-order-item" encounter "simrs-vx/internal/interface/main-handler/encounter" + encounterdocument "simrs-vx/internal/interface/main-handler/encounter-document" internalreference "simrs-vx/internal/interface/main-handler/internal-reference" materialorder "simrs-vx/internal/interface/main-handler/material-order" materialorderitem "simrs-vx/internal/interface/main-handler/material-order-item" diff --git a/internal/interface/main-handler/upload/handler.go b/internal/interface/main-handler/upload/handler.go index abf8919d..72a71fbf 100644 --- a/internal/interface/main-handler/upload/handler.go +++ b/internal/interface/main-handler/upload/handler.go @@ -4,13 +4,12 @@ import ( "net/http" "strconv" - eru "simrs-vx/internal/domain/references/upload" - - e "simrs-vx/internal/domain/main-entities/upload" - d "github.com/karincake/dodol" rw "github.com/karincake/risoles" + eru "simrs-vx/internal/domain/references/upload" + + e "simrs-vx/internal/domain/main-entities/upload" u "simrs-vx/internal/use-case/main-use-case/upload" ) diff --git a/internal/use-case/main-use-case/upload/helper.go b/internal/use-case/main-use-case/upload/helper.go index 0ddfd220..e9e0ff29 100644 --- a/internal/use-case/main-use-case/upload/helper.go +++ b/internal/use-case/main-use-case/upload/helper.go @@ -185,15 +185,6 @@ func setEncounterDocument(input e.CreateDto, event *pl.Event, tx *gorm.DB) (*ee. return &data, nil } - - // insert data - resData, err := ue.CreateData(createDto, event, tx) - if err != nil { - return nil, err - } - data = *resData - - return &data, nil } // insert data From 12108e11764cc299388650a10dea8493dbd93357 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Fri, 14 Nov 2025 13:43:27 +0700 Subject: [PATCH 196/329] add status code therapy protocol --- .../migrations/20251114062746.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 5 ++-- .../main-entities/therapy-protocol/entity.go | 25 ++++++++++--------- 3 files changed, 18 insertions(+), 14 deletions(-) create mode 100644 cmd/main-migration/migrations/20251114062746.sql diff --git a/cmd/main-migration/migrations/20251114062746.sql b/cmd/main-migration/migrations/20251114062746.sql new file mode 100644 index 00000000..cdcfb350 --- /dev/null +++ b/cmd/main-migration/migrations/20251114062746.sql @@ -0,0 +1,2 @@ +-- Modify "TherapyProtocol" table +ALTER TABLE "public"."TherapyProtocol" ADD COLUMN "Status_Code" character varying(10) NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 1c172e0c..d2484ac6 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:RvRW5FTVb8Zdn/J5rSwIrXB7cbCmWJBNaVsxqArNl4E= +h1:ZxTxK8LgNDXKTGBTF9olozXM0T7DDjK1+OJiwUwomeY= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -116,4 +116,5 @@ h1:RvRW5FTVb8Zdn/J5rSwIrXB7cbCmWJBNaVsxqArNl4E= 20251111082257.sql h1:ZsdLY1ROouos0l3oS0lkeSiuKLEUGbVvBhpcM2AVhkw= 20251111111017.sql h1:qrJ93dNtQwcuAvpsP/lAK/H63C4cinXrsVaPmWsTqkU= 20251113101344.sql h1:xaOZvAUP1fFfnO+syEFOzJUIg5lTfBe5AWHPbBWuCLA= -20251113120533.sql h1:MOk7YBwVLRCoqgPrC/mQAarp5WRl4aTk6NAzIoQPMNc= +20251113120533.sql h1:f3/U1Ve2yF2zSMhkt+xtwF8wUYfUKYwgbNeGfE37EW4= +20251114062746.sql h1:4ypWL0cP2AUJLVHhPKo3GAQ7uqolL6F8o4nUW32KnCI= diff --git a/internal/domain/main-entities/therapy-protocol/entity.go b/internal/domain/main-entities/therapy-protocol/entity.go index 7caaf0a6..1378eb25 100644 --- a/internal/domain/main-entities/therapy-protocol/entity.go +++ b/internal/domain/main-entities/therapy-protocol/entity.go @@ -16,16 +16,17 @@ type TherapyProtocol struct { Doctor_Code *string `json:"doctor_code"` Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"` - Anamnesis *string `json:"anamnesis" gorm:"size:2048"` - MedicalDiagnoses *string `json:"medicalDiagnoses"` - FunctionDiagnoses *string `json:"functionDiagnoses"` - Procedures *string `json:"procedures"` - SupportingExams *string `json:"supportingExams" gorm:"size:2048"` - Instruction *string `json:"instruction" gorm:"size:2048"` - Evaluation *string `json:"evaluation" gorm:"size:2048"` - WorkCauseStatus *string `json:"workCauseStatus" gorm:"size:2048"` - Frequency *uint `json:"frequency"` - IntervalUnit_Code *common.TimeUnitCode `json:"intervalUnit_code" gorm:"size:10"` - Duration *uint `json:"duration"` - DurationUnit_Code *common.TimeUnitCode `json:"durationUnit_code" gorm:"size:10"` + Anamnesis *string `json:"anamnesis" gorm:"size:2048"` + MedicalDiagnoses *string `json:"medicalDiagnoses"` + FunctionDiagnoses *string `json:"functionDiagnoses"` + Procedures *string `json:"procedures"` + SupportingExams *string `json:"supportingExams" gorm:"size:2048"` + Instruction *string `json:"instruction" gorm:"size:2048"` + Evaluation *string `json:"evaluation" gorm:"size:2048"` + WorkCauseStatus *string `json:"workCauseStatus" gorm:"size:2048"` + Frequency *uint `json:"frequency"` + IntervalUnit_Code *common.TimeUnitCode `json:"intervalUnit_code" gorm:"size:10"` + Duration *uint `json:"duration"` + DurationUnit_Code *common.TimeUnitCode `json:"durationUnit_code" gorm:"size:10"` + Status_Code *common.DataVerifiedCode `json:"status_code" gorm:"size:10"` } From b51606b408db18ed9e39ebac99ac69bae01f069e Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Fri, 14 Nov 2025 13:45:20 +0700 Subject: [PATCH 197/329] add makefile command --- cmd/main-migration/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd/main-migration/Makefile b/cmd/main-migration/Makefile index f445a815..a93bb244 100644 --- a/cmd/main-migration/Makefile +++ b/cmd/main-migration/Makefile @@ -16,3 +16,7 @@ apply: ## Calculate the schema hash hash: atlas migrate hash + +## Apply non-linear +apply-non-linear: + atlas migrate apply --env $(ENV) --exec-order non-linear \ No newline at end of file From fbd8d30ec6be9afdbd43384d1e4e319bc6addb93 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 14 Nov 2025 14:11:55 +0700 Subject: [PATCH 198/329] add sync unit --- cmd/main-migration/migrations/atlas.sum | 4 +-- .../migrations/20251114071129.sql | 36 +++++++++++++++++++ .../migrations/atlas.sum | 3 +- .../domain/simgos-entities/unit/entity.go | 11 ++++++ internal/domain/sync-entities/unit/entity.go | 29 +++++++++++++++ .../migration/simgossync-entities.go | 4 +++ 6 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 cmd/simgos-sync-migration/migrations/20251114071129.sql create mode 100644 internal/domain/simgos-entities/unit/entity.go create mode 100644 internal/domain/sync-entities/unit/entity.go diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 1c172e0c..5e8b0d0f 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:RvRW5FTVb8Zdn/J5rSwIrXB7cbCmWJBNaVsxqArNl4E= +h1:hrZ5BrQCFCoyZbD1KKYCyR53xT2LTdRCIONnoNRierc= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -116,4 +116,4 @@ h1:RvRW5FTVb8Zdn/J5rSwIrXB7cbCmWJBNaVsxqArNl4E= 20251111082257.sql h1:ZsdLY1ROouos0l3oS0lkeSiuKLEUGbVvBhpcM2AVhkw= 20251111111017.sql h1:qrJ93dNtQwcuAvpsP/lAK/H63C4cinXrsVaPmWsTqkU= 20251113101344.sql h1:xaOZvAUP1fFfnO+syEFOzJUIg5lTfBe5AWHPbBWuCLA= -20251113120533.sql h1:MOk7YBwVLRCoqgPrC/mQAarp5WRl4aTk6NAzIoQPMNc= +20251113120533.sql h1:f3/U1Ve2yF2zSMhkt+xtwF8wUYfUKYwgbNeGfE37EW4= diff --git a/cmd/simgos-sync-migration/migrations/20251114071129.sql b/cmd/simgos-sync-migration/migrations/20251114071129.sql new file mode 100644 index 00000000..4499a544 --- /dev/null +++ b/cmd/simgos-sync-migration/migrations/20251114071129.sql @@ -0,0 +1,36 @@ +-- Create "UnitLink" table +CREATE TABLE "public"."UnitLink" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Simx_Id" bigint NULL, + "Simgos_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_UnitLink_Simgos_Id" UNIQUE ("Simgos_Id"), + CONSTRAINT "uni_UnitLink_Simx_Id" UNIQUE ("Simx_Id") +); +-- Create "UnitSimgosLog" table +CREATE TABLE "public"."UnitSimgosLog" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Value" text NULL, + "Date" timestamptz NULL, + "Status" text NULL, + "ErrMessage" text NULL, + PRIMARY KEY ("Id") +); +-- Create "UnitSimxLog" table +CREATE TABLE "public"."UnitSimxLog" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Value" text NULL, + "Date" timestamptz NULL, + "Status" text NULL, + "ErrMessage" text NULL, + PRIMARY KEY ("Id") +); diff --git a/cmd/simgos-sync-migration/migrations/atlas.sum b/cmd/simgos-sync-migration/migrations/atlas.sum index f1405dd2..e8418ec2 100644 --- a/cmd/simgos-sync-migration/migrations/atlas.sum +++ b/cmd/simgos-sync-migration/migrations/atlas.sum @@ -1,2 +1,3 @@ -h1:8jMmMBxSEls9jaOUrpQQV0wUPlORRwJWd5g9742Z2fQ= +h1:xxkaO6rL13nwrZd1vrsoGJrrwCtXPgGRmwGEjWJ1V/c= 20251113035508.sql h1:rjDlu6yDdy5xv6nrCOr7NialrLSLT23pzduYNq29Hf0= +20251114071129.sql h1:O4nfv4l9vcXpE2Kyu7vjnubD8kDZ7JltRaF2auOdMpc= diff --git a/internal/domain/simgos-entities/unit/entity.go b/internal/domain/simgos-entities/unit/entity.go new file mode 100644 index 00000000..20fa0000 --- /dev/null +++ b/internal/domain/simgos-entities/unit/entity.go @@ -0,0 +1,11 @@ +package unit + +type MPloy struct { + Kode uint `json:"kode" gorm:"primaryKey;autoIncrement;column:kode"` + Nama string `json:"nama" gorm:"column:nama"` + Jenispoly uint `json:"jenispoly" gorm:"column:jenispoly"` +} + +func (MPloy) TableName() string { + return "m_poly" +} diff --git a/internal/domain/sync-entities/unit/entity.go b/internal/domain/sync-entities/unit/entity.go new file mode 100644 index 00000000..d7491ea8 --- /dev/null +++ b/internal/domain/sync-entities/unit/entity.go @@ -0,0 +1,29 @@ +package unit + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + erc "simrs-vx/internal/domain/references/common" + "time" +) + +type UnitLink struct { + ecore.Main + Simx_Id uint `json:"simx_id" gorm:"unique"` + Simgos_Id uint `json:"simgos_id" gorm:"unique"` +} + +type UnitSimxLog struct { + ecore.Main + Value *string `json:"value"` + Date *time.Time `json:"date"` + Status erc.ProcessStatusCode `json:"status"` + ErrMessage *string `json:"errMessage"` +} + +type UnitSimgosLog struct { + ecore.Main + Value *string `json:"value"` + Date *time.Time `json:"date"` + Status erc.ProcessStatusCode `json:"status"` + ErrMessage *string `json:"errMessage"` +} diff --git a/internal/interface/migration/simgossync-entities.go b/internal/interface/migration/simgossync-entities.go index 3b67265f..d48cf699 100644 --- a/internal/interface/migration/simgossync-entities.go +++ b/internal/interface/migration/simgossync-entities.go @@ -3,6 +3,7 @@ package migration import ( /************** Source ***************/ installation "simrs-vx/internal/domain/sync-entities/installation" + unit "simrs-vx/internal/domain/sync-entities/unit" ) func getSimgosSyncEntities() []any { @@ -10,5 +11,8 @@ func getSimgosSyncEntities() []any { &installation.InstallationLink{}, &installation.InstallationSimxLog{}, &installation.InstallationSimgosLog{}, + &unit.UnitLink{}, + &unit.UnitSimxLog{}, + &unit.UnitSimgosLog{}, } } From d03c1c7a93093e4eebe56a356343fb96d82d9946 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Fri, 14 Nov 2025 14:16:07 +0700 Subject: [PATCH 199/329] feat (therapy-protocol): add verification --- .../main-entities/therapy-protocol/dto.go | 74 +++++++++++-------- .../main-entities/therapy-protocol/entity.go | 4 + .../interface/main-handler/main-handler.go | 19 +++-- .../main-handler/therapy-protocol/handler.go | 46 ++++++++++++ .../main-use-case/therapy-protocol/case.go | 65 ++++++++++++++++ 5 files changed, 167 insertions(+), 41 deletions(-) diff --git a/internal/domain/main-entities/therapy-protocol/dto.go b/internal/domain/main-entities/therapy-protocol/dto.go index 40633b89..a1d311dc 100644 --- a/internal/domain/main-entities/therapy-protocol/dto.go +++ b/internal/domain/main-entities/therapy-protocol/dto.go @@ -4,24 +4,27 @@ import ( ecore "simrs-vx/internal/domain/base-entities/core" ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/encounter" - "simrs-vx/internal/domain/references/common" + erc "simrs-vx/internal/domain/references/common" + + pa "simrs-vx/internal/lib/auth" ) type CreateDto struct { - Encounter_Id *uint `json:"encounter_id"` - Doctor_Code *string `json:"doctor_code"` - Anamnesis *string `json:"anamnesis" validate:"maxLength=2048"` - MedicalDiagnoses *string `json:"medicalDiagnoses"` - FunctionDiagnoses *string `json:"functionDiagnoses"` - Procedures *string `json:"procedures"` - SupportingExams *string `json:"supportingExams" validate:"maxLength=2048"` - Instruction *string `json:"instruction" validate:"maxLength=2048"` - Evaluation *string `json:"evaluation" validate:"maxLength=2048"` - WorkCauseStatus *string `json:"workCauseStatus"` - Frequency *uint `json:"frequency"` - IntervalUnit_Code *common.TimeUnitCode `json:"intervalUnit_code" validate:"maxLength=10"` - Duration *uint `json:"duration"` - DurationUnit_Code *common.TimeUnitCode `json:"durationUnit_code" validate:"maxLength=10"` + Encounter_Id *uint `json:"encounter_id"` + Doctor_Code *string `json:"doctor_code"` + Anamnesis *string `json:"anamnesis" validate:"maxLength=2048"` + MedicalDiagnoses *string `json:"medicalDiagnoses"` + FunctionDiagnoses *string `json:"functionDiagnoses"` + Procedures *string `json:"procedures"` + SupportingExams *string `json:"supportingExams" validate:"maxLength=2048"` + Instruction *string `json:"instruction" validate:"maxLength=2048"` + Evaluation *string `json:"evaluation" validate:"maxLength=2048"` + WorkCauseStatus *string `json:"workCauseStatus"` + Frequency *uint `json:"frequency"` + IntervalUnit_Code *erc.TimeUnitCode `json:"intervalUnit_code" validate:"maxLength=10"` + Duration *uint `json:"duration"` + DurationUnit_Code *erc.TimeUnitCode `json:"durationUnit_code" validate:"maxLength=10"` + Status_Code *erc.DataVerifiedCode `json:"status_code"` } type ReadListDto struct { @@ -49,6 +52,13 @@ type DeleteDto struct { Id uint `json:"id"` } +type VerifyDto struct { + Id uint `json:"id"` + Status_Code erc.DataVerifiedCode `json:"status_code"` + + pa.AuthInfo +} + type MetaDto struct { PageNumber int `json:"page_number"` PageSize int `json:"page_size"` @@ -57,22 +67,23 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty"` - Doctor_Code *string `json:"doctor_code"` - Doctor *ed.Doctor `json:"doctor,omitempty"` - Anamnesis *string `json:"anamnesis"` - MedicalDiagnoses *string `json:"medicalDiagnoses"` - FunctionDiagnoses *string `json:"functionDiagnoses"` - Procedures *string `json:"procedures"` - SupportingExams *string `json:"supportingExams"` - Instruction *string `json:"instruction"` - Evaluation *string `json:"evaluation"` - WorkCauseStatus *string `json:"workCauseStatus"` - Frequency *uint `json:"frequency"` - IntervalUnit_Code *common.TimeUnitCode `json:"intervalUnit_code"` - Duration *uint `json:"duration"` - DurationUnit_Code *common.TimeUnitCode `json:"durationUnit_code"` + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty"` + Doctor_Code *string `json:"doctor_code"` + Doctor *ed.Doctor `json:"doctor,omitempty"` + Anamnesis *string `json:"anamnesis"` + MedicalDiagnoses *string `json:"medicalDiagnoses"` + FunctionDiagnoses *string `json:"functionDiagnoses"` + Procedures *string `json:"procedures"` + SupportingExams *string `json:"supportingExams"` + Instruction *string `json:"instruction"` + Evaluation *string `json:"evaluation"` + WorkCauseStatus *string `json:"workCauseStatus"` + Frequency *uint `json:"frequency"` + IntervalUnit_Code *erc.TimeUnitCode `json:"intervalUnit_code"` + Duration *uint `json:"duration"` + DurationUnit_Code *erc.TimeUnitCode `json:"durationUnit_code"` + Status_Code *erc.DataVerifiedCode `json:"status_code"` } func (d TherapyProtocol) ToResponse() ResponseDto { @@ -93,6 +104,7 @@ func (d TherapyProtocol) ToResponse() ResponseDto { IntervalUnit_Code: d.IntervalUnit_Code, Duration: d.Duration, DurationUnit_Code: d.DurationUnit_Code, + Status_Code: d.Status_Code, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/therapy-protocol/entity.go b/internal/domain/main-entities/therapy-protocol/entity.go index 1378eb25..e7607eea 100644 --- a/internal/domain/main-entities/therapy-protocol/entity.go +++ b/internal/domain/main-entities/therapy-protocol/entity.go @@ -30,3 +30,7 @@ type TherapyProtocol struct { DurationUnit_Code *common.TimeUnitCode `json:"durationUnit_code" gorm:"size:10"` Status_Code *common.DataVerifiedCode `json:"status_code" gorm:"size:10"` } + +func (d TherapyProtocol) IsNew() bool { + return d.Status_Code != nil && *d.Status_Code == common.DVCNew +} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index a06c5c18..aa6f76fb 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -152,7 +152,6 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/prescription-item", prescriptionitem.O) hc.RegCrud(r, "/v1/device-order-item", deviceorderitem.O) hc.RegCrud(r, "/v1/material-order-item", materialorderitem.O) - hk.GroupRoutes("/v1/encounter", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": encounter.O.GetList, "GET /{id}": encounter.O.GetDetail, @@ -211,7 +210,6 @@ func SetRoutes() http.Handler { "DELETE /{id}": medication.O.Delete, "PATCH /{id}/complete": medication.O.Complete, }) - hk.GroupRoutes("/v1/medication-item", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": medicationitem.O.GetList, "GET /{id}": medicationitem.O.GetDetail, @@ -220,7 +218,6 @@ func SetRoutes() http.Handler { "DELETE /{id}": medicationitem.O.Delete, "PATCH /{id}/redeem": medicationitem.O.Redeem, }) - hk.GroupRoutes("/v1/medication-item-dist", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": medicationitemdist.O.GetList, "GET /{id}": medicationitemdist.O.GetDetail, @@ -229,7 +226,6 @@ func SetRoutes() http.Handler { "DELETE /{id}": medicationitemdist.O.Delete, "PATCH /{id}/consume": medicationitemdist.O.Consume, }) - hk.GroupRoutes("/v1/device-order", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": deviceorder.O.GetList, "GET /{id}": deviceorder.O.GetDetail, @@ -238,7 +234,6 @@ func SetRoutes() http.Handler { "DELETE /{id}": deviceorder.O.Delete, "PATCH /{id}/complete": deviceorder.O.Complete, }) - hk.GroupRoutes("/v1/material-order", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": materialorder.O.GetList, "GET /{id}": materialorder.O.GetDetail, @@ -247,7 +242,6 @@ func SetRoutes() http.Handler { "DELETE /{id}": materialorder.O.Delete, "PATCH /{id}/complete": materialorder.O.Complete, }) - hk.GroupRoutes("/v1/consultation", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": consultation.O.GetList, "GET /{id}": consultation.O.GetDetail, @@ -256,7 +250,6 @@ func SetRoutes() http.Handler { "DELETE /{id}": consultation.O.Delete, "PATCH /{id}/reply": consultation.O.Reply, }) - hk.GroupRoutes("/v1/chemo", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": chemo.O.GetList, "GET /{id}": chemo.O.GetDetail, @@ -266,13 +259,20 @@ func SetRoutes() http.Handler { "PATCH /{id}/verify": chemo.O.Verify, "PATCH /{id}/reject": chemo.O.Reject, }) - hc.RegCrud(r, "/v1/control-letter", controlletter.O) hc.RegCrud(r, "/v1/internal-reference", internalreference.O) hc.RegCrud(r, "/v1/ambulance-transport-req", ambulancetransportrequest.O) hc.RegCrud(r, "/v1/responsible-doctor-hist", responsibledoctorhist.O) hc.RegCrud(r, "/v1/adm-employee-hist", admemployeehist.O) - hc.RegCrud(r, "/v1/therapy-protocol", therapyprotocol.O) + hk.GroupRoutes("/v1/therapy-protocol", r, auth.GuardMW, hk.MapHandlerFunc{ + "GET /": therapyprotocol.O.GetList, + "GET /{id}": therapyprotocol.O.GetDetail, + "POST /": therapyprotocol.O.Create, + "PATCH /{id}": therapyprotocol.O.Update, + "DELETE /{id}": therapyprotocol.O.Delete, + "PATCH /{id}/verify": therapyprotocol.O.Verify, + "PATCH /{id}/reject": therapyprotocol.O.Reject, + }) hc.RegCrud(r, "/v1/chemo-protocol", chemoprotocol.O) hc.RegCrud(r, "/v1/upload", upload.O) hc.RegCrud(r, "/v1/encounter-document", encounterdocument.O) @@ -297,7 +297,6 @@ func SetRoutes() http.Handler { "PATCH /{id}/active": user.O.Active, }) hc.RegCrud(r, "/v1/user-fes", userfes.O) - hk.GroupRoutes("/v1/patient", r, hk.MapHandlerFunc{ "GET /": patient.O.GetList, "GET /{id}": patient.O.GetDetail, diff --git a/internal/interface/main-handler/therapy-protocol/handler.go b/internal/interface/main-handler/therapy-protocol/handler.go index 2d9efc3b..769e5677 100644 --- a/internal/interface/main-handler/therapy-protocol/handler.go +++ b/internal/interface/main-handler/therapy-protocol/handler.go @@ -9,7 +9,12 @@ import ( // ua "github.com/karincake/tumpeng/auth/svc" e "simrs-vx/internal/domain/main-entities/therapy-protocol" + erc "simrs-vx/internal/domain/references/common" u "simrs-vx/internal/use-case/main-use-case/therapy-protocol" + + d "github.com/karincake/dodol" + + pa "simrs-vx/internal/lib/auth" ) type myBase struct{} @@ -71,3 +76,44 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { res, err := u.Delete(dto) rw.DataResponse(w, res, err) } + +func (obj myBase) Verify(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.VerifyDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + + dto.Id = uint(id) + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + + dto.AuthInfo = *authInfo + dto.Status_Code = erc.DVCVerified + res, err := u.Verify(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Reject(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.VerifyDto{} + dto.Id = uint(id) + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + dto.AuthInfo = *authInfo + dto.Status_Code = erc.DVCRejected + res, err := u.Verify(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/use-case/main-use-case/therapy-protocol/case.go b/internal/use-case/main-use-case/therapy-protocol/case.go index bc65325f..ed4f3a21 100644 --- a/internal/use-case/main-use-case/therapy-protocol/case.go +++ b/internal/use-case/main-use-case/therapy-protocol/case.go @@ -1,6 +1,7 @@ package therapy_protocol import ( + "errors" "strconv" "gorm.io/gorm" @@ -15,6 +16,8 @@ import ( ee "simrs-vx/internal/domain/main-entities/encounter" e "simrs-vx/internal/domain/main-entities/therapy-protocol" + erc "simrs-vx/internal/domain/references/common" + ud "simrs-vx/internal/use-case/main-use-case/doctor" ue "simrs-vx/internal/use-case/main-use-case/encounter" ) @@ -45,6 +48,8 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } + statusNew := erc.DVCNew + input.Status_Code = &statusNew if resData, err := CreateData(input, &event, tx); err != nil { return err } else { @@ -291,6 +296,66 @@ func Delete(input e.DeleteDto) (*d.Data, error) { } +func Verify(input e.VerifyDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.TherapyProtocol + var err error + + event := pl.Event{ + Feature: "Verify", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "verify") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err + } + + if !data.IsNew() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-state-mismatch", + Detail: "data is not new", + Raw: errors.New("data is not new"), + } + return pl.SetLogError(&event, input) + } + + data.Status_Code = &input.Status_Code + err = tx.Save(&data).Error + if 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "verify", + }, + Data: data.ToResponse(), + }, nil +} + func validateForeignKey(input e.CreateDto) error { // validate encounter if input.Encounter_Id != nil { From 46407cdf572a9ff40160bf580d1fe23b3773d481 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 14 Nov 2025 14:18:10 +0700 Subject: [PATCH 200/329] sync unit on going --- .../simgos-sync-use-case/unit/case.go | 255 ++++++++++++++++++ .../simgos-sync-use-case/unit/helper.go | 60 +++++ .../use-case/simgos-sync-use-case/unit/lib.go | 184 +++++++++++++ .../unit/middleware-runner.go | 104 +++++++ .../simgos-sync-use-case/unit/middleware.go | 9 + .../simgos-sync-use-case/unit/tycovar.go | 44 +++ 6 files changed, 656 insertions(+) create mode 100644 internal/use-case/simgos-sync-use-case/unit/case.go create mode 100644 internal/use-case/simgos-sync-use-case/unit/helper.go create mode 100644 internal/use-case/simgos-sync-use-case/unit/lib.go create mode 100644 internal/use-case/simgos-sync-use-case/unit/middleware-runner.go create mode 100644 internal/use-case/simgos-sync-use-case/unit/middleware.go create mode 100644 internal/use-case/simgos-sync-use-case/unit/tycovar.go diff --git a/internal/use-case/simgos-sync-use-case/unit/case.go b/internal/use-case/simgos-sync-use-case/unit/case.go new file mode 100644 index 00000000..bc14a72d --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/unit/case.go @@ -0,0 +1,255 @@ +package unit + +import ( + "errors" + esimgos "simrs-vx/internal/domain/simgos-entities/installation" + esync "simrs-vx/internal/domain/sync-entities/log" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/installation" +) + +const source = "installation" + +func Create(input e.CreateDto) (*d.Data, error) { + var ( + txSync = dg.I.Begin() + txSimgos = dg.IS["simrs"].Begin() + ) + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + // STEP 1: Insert to simgos + sgData, err := CreateSimgosData(input, &event, txSimgos) + if err != nil { + return nil, err + } + + // STEP 2: Insert to Link + if err = CreateLinkData(*input.Id, sgData.No_Instalasi, &event, txSync); err != nil { + txSimgos.Rollback() + return nil, err + } + + // STEP 3: Commit two trx + if err = txSimgos.Commit().Error; err != nil { + txSimgos.Rollback() + txSync.Rollback() + return nil, err + } + + if err = txSync.Commit().Error; err != nil { + // STEP 4: Rollback Partial + go func() { + _ = DeleteSimgosData(sgData, &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 esync.SimxLogDto) (*d.Data, error) { + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + err := dg.I.Transaction(func(tx *gorm.DB) error { + // InsertSimxLog + if err := CreateLogData(input, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + 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.UpdateDto) (*d.Data, error) { + var ( + txSync = dg.I.Begin() + txSimgos = dg.IS["simrs"].Begin() + sgData *esimgos.MInstalasi + err error + ) + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + // STEP 1: Get Installation Link + syncLink, errGetLink := ReadDetailLinkData(*input.Id, &event) + if errGetLink != nil { + if !errors.Is(err, gorm.ErrRecordNotFound) { + return nil, err + } + } + + if errGetLink != nil && errors.Is(errGetLink, gorm.ErrRecordNotFound) { + // STEP 2.1: Insert to simgos + sgData, err = CreateSimgosData(input.CreateDto, &event, txSimgos) + if err != nil { + return nil, err + } + + // STEP 2.2: Insert to Link + simxId := uint(*input.Id) + if err = CreateLinkData(simxId, sgData.No_Instalasi, &event, txSync); err != nil { + txSimgos.Rollback() + return nil, err + } + } else { + // Step 3.1: Update Simgos + err = UpdateSimgosData(input, syncLink, &event, txSimgos) + if err != nil { + return nil, err + } + } + + // STEP 4: Commit two trx + if err = txSimgos.Commit().Error; err != nil { + txSimgos.Rollback() + txSync.Rollback() + return nil, err + } + + if errGetLink != nil { + if err = txSync.Commit().Error; err != nil { + // STEP 5.1: Rollback Partial + go func() { + _ = DeleteSimgosData(sgData, &event) + }() + return nil, err + } + } + + 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 ( + txSync = dg.I.Begin() + txSimgos = dg.IS["simrs"].Begin() + sgData *esimgos.MInstalasi + err error + ) + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + // STEP 1: Get Installation Link + syncLink, errGetLink := ReadDetailLinkData(*input.Id, &event) + if errGetLink != nil { + if !errors.Is(err, gorm.ErrRecordNotFound) { + return nil, err + } + } + + if errGetLink == nil { + // STEP 2: Get Simgos + sgData, err = ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) + if err != nil { + return nil, err + } + + // STEP 3: Delete M_Instalation Simgos + err = DeleteSimgosData(sgData, &event, txSimgos) + if err != nil { + return nil, err + } + + // STEP 4: Delete Installation Link + err = DeleteLinkData(syncLink, &event, txSync) + if err != nil { + txSimgos.Rollback() + return nil, err + } + + // STEP 4: Commit two trx + if err = txSimgos.Commit().Error; err != nil { + txSimgos.Rollback() + txSync.Rollback() + return nil, err + } + + if err = txSync.Commit().Error; err != nil { + // STEP 5: Rollback Partial + go func() { + inputRollback := e.UpdateDto{ + CreateDto: e.CreateDto{ + Name: sgData.Nama_Instalasi, + }, + } + _ = UpdateSimgosData(inputRollback, syncLink, &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/unit/helper.go b/internal/use-case/simgos-sync-use-case/unit/helper.go new file mode 100644 index 00000000..53c518e2 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/unit/helper.go @@ -0,0 +1,60 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package unit + +import ( + "encoding/json" + erc "simrs-vx/internal/domain/references/common" + + e "simrs-vx/internal/domain/main-entities/installation" + + esimgos "simrs-vx/internal/domain/simgos-entities/unit" + esync "simrs-vx/internal/domain/sync-entities/installation" + esyncLog "simrs-vx/internal/domain/sync-entities/log" +) + +func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Nama_Instalasi = inputSrc.Name + data.Status_Rawat_Inap = 0 + data.St_Aktif = 1 + + return +} + +func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.InstallationSimxLog) { + // 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.InstallationLink) { + data.Simx_Id = simxId + data.Simgos_Id = simgosId + return +} diff --git a/internal/use-case/simgos-sync-use-case/unit/lib.go b/internal/use-case/simgos-sync-use-case/unit/lib.go new file mode 100644 index 00000000..091082f1 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/unit/lib.go @@ -0,0 +1,184 @@ +package unit + +import ( + esynclog "simrs-vx/internal/domain/sync-entities/log" + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + "time" + + dg "github.com/karincake/apem/db-gorm-pg" + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/installation" + esimgos "simrs-vx/internal/domain/simgos-entities/installation" + esync "simrs-vx/internal/domain/sync-entities/installation" +) + +var now = time.Now() + +func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esimgos.MInstalasi, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := setDataSimgos(&input) + + 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 ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.MInstalasi, error) { + pl.SetLogInfo(event, simgosId, "started", "DBReadDetail") + data := esimgos.MInstalasi{} + + var tx = dg.IS["simrs"] + + if err := tx. + Where("\"no_instalasi\" = ?", simgosId). + First(&data).Error; err != nil { + return nil, err + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateSimgosData(input e.UpdateDto, dataSimgos *esync.InstallationLink, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, input, "started", "DBUpdate") + + data := setDataSimgos(&input) + data.No_Instalasi = dataSimgos.Simgos_Id + + 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 DeleteSimgosData(data *esimgos.MInstalasi, 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"] + } + + data.St_Aktif = 0 + + if err := tx.Save(&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 CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) 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 plh.HandleCreateError(data, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} + +func ReadDetailLinkData(simxId uint16, event *pl.Event) (*esync.InstallationLink, error) { + pl.SetLogInfo(event, simxId, "started", "DBReadDetail") + data := esync.InstallationLink{} + + var tx = dg.I + + if err := tx. + Where("\"Simx_Id\" = ?", simxId). + First(&data).Error; err != nil { + return nil, err + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func DeleteLinkData(data *esync.InstallationLink, 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/unit/middleware-runner.go b/internal/use-case/simgos-sync-use-case/unit/middleware-runner.go new file mode 100644 index 00000000..64426eb9 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/unit/middleware-runner.go @@ -0,0 +1,104 @@ +package unit + +import ( + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/unit" +) + +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.Unit) 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.Unit) 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.Unit) 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.Unit) 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.Unit) 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/unit/middleware.go b/internal/use-case/simgos-sync-use-case/unit/middleware.go new file mode 100644 index 00000000..bac48f4d --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/unit/middleware.go @@ -0,0 +1,9 @@ +package unit + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/simgos-sync-use-case/unit/tycovar.go b/internal/use-case/simgos-sync-use-case/unit/tycovar.go new file mode 100644 index 00000000..e1a7c69f --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/unit/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 unit + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/unit" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.Unit, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Unit, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Unit, 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 From 12abbfa41a35e0de1babc47ed9a6c8e74d834bfe Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 14 Nov 2025 14:19:14 +0700 Subject: [PATCH 201/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 88 ++++++++++++------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index d2484ac6..cac4826e 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:ZxTxK8LgNDXKTGBTF9olozXM0T7DDjK1+OJiwUwomeY= +h1:t3DFzssEf9liKwykDE17fo19llwCgpTgEuSUd9VGusk= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,46 +75,46 @@ h1:ZxTxK8LgNDXKTGBTF9olozXM0T7DDjK1+OJiwUwomeY= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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:4ypWL0cP2AUJLVHhPKo3GAQ7uqolL6F8o4nUW32KnCI= +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= From c19965f4c31a11e3ff3c5826cd8857dfd1b363b2 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Sat, 15 Nov 2025 01:16:21 +0700 Subject: [PATCH 202/329] feat/things-munaja: device order items preload --- .../device-order-item/base/entity.go | 14 ++++++++++++++ .../main-entities/device-order-item/entity.go | 11 +++-------- .../domain/main-entities/device-order/entity.go | 15 ++++++++------- 3 files changed, 25 insertions(+), 15 deletions(-) create mode 100644 internal/domain/main-entities/device-order-item/base/entity.go diff --git a/internal/domain/main-entities/device-order-item/base/entity.go b/internal/domain/main-entities/device-order-item/base/entity.go new file mode 100644 index 00000000..54cbe611 --- /dev/null +++ b/internal/domain/main-entities/device-order-item/base/entity.go @@ -0,0 +1,14 @@ +package base + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ed "simrs-vx/internal/domain/main-entities/device" +) + +type DeviceOrderItem struct { + ecore.Main // adjust this according to the needs + DeviceOrder_Id *uint `json:"deviceOrder_id"` + Device_Code *string `json:"device_code"` + Device *ed.Device `json:"device,omitempty" gorm:"foreignKey:Device_Code;references:Code"` + Count uint8 `json:"count"` +} diff --git a/internal/domain/main-entities/device-order-item/entity.go b/internal/domain/main-entities/device-order-item/entity.go index 27197125..a0743643 100644 --- a/internal/domain/main-entities/device-order-item/entity.go +++ b/internal/domain/main-entities/device-order-item/entity.go @@ -1,16 +1,11 @@ package deviceorderitem import ( - ecore "simrs-vx/internal/domain/base-entities/core" - ed "simrs-vx/internal/domain/main-entities/device" edo "simrs-vx/internal/domain/main-entities/device-order" + eb "simrs-vx/internal/domain/main-entities/device-order-item/base" ) type DeviceOrderItem struct { - ecore.Main // adjust this according to the needs - DeviceOrder_Id *uint `json:"deviceOrder_id"` - DeviceOrder *edo.DeviceOrder `json:"deviceOrder,omitempty" gorm:"foreignKey:DeviceOrder_Id;references:Id"` - Device_Code *string `json:"device_code"` - Device *ed.Device `json:"device,omitempty" gorm:"foreignKey:Device_Code;references:Code"` - Count uint8 `json:"count"` + eb.DeviceOrderItem + DeviceOrder *edo.DeviceOrder `json:"deviceOrder,omitempty" gorm:"foreignKey:DeviceOrder_Id;references:Id"` } diff --git a/internal/domain/main-entities/device-order/entity.go b/internal/domain/main-entities/device-order/entity.go index 7ff4fa34..d9ba5a59 100644 --- a/internal/domain/main-entities/device-order/entity.go +++ b/internal/domain/main-entities/device-order/entity.go @@ -2,19 +2,20 @@ package deviceorder import ( ecore "simrs-vx/internal/domain/base-entities/core" + edoi "simrs-vx/internal/domain/main-entities/device-order-item/base" ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/encounter" - erc "simrs-vx/internal/domain/references/common" ) type DeviceOrder struct { - ecore.Main // adjust this according to the needs - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Doctor_Code *string `json:"doctor_code"` - Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"` - Status_Code erc.DataStatusCode `json:"status_code"` + ecore.Main // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + Doctor_Code *string `json:"doctor_code"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"` + Status_Code erc.DataStatusCode `json:"status_code"` + Items []*edoi.DeviceOrderItem `json:"items" gorm:"foreignKey:DeviceOrder_Id;references:Id"` } func (d DeviceOrder) IsCompleted() bool { From 03210549bb470c260f0d6d0257bac5bb9f147fe3 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Mon, 17 Nov 2025 07:57:22 +0700 Subject: [PATCH 203/329] feat/things-munaja: adjust prescription --- .../prescription-item/base/entity.go | 25 +++++++++++++++++++ .../main-entities/prescription-item/dto.go | 1 + .../main-entities/prescription-item/entity.go | 22 +++------------- .../domain/main-entities/prescription/dto.go | 15 ++++++----- .../main-entities/prescription/entity.go | 16 ++++++------ .../main-handler/prescription/handler.go | 1 + .../main-use-case/prescription-item/lib.go | 4 +-- 7 files changed, 51 insertions(+), 33 deletions(-) create mode 100644 internal/domain/main-entities/prescription-item/base/entity.go diff --git a/internal/domain/main-entities/prescription-item/base/entity.go b/internal/domain/main-entities/prescription-item/base/entity.go new file mode 100644 index 00000000..a5cb5c44 --- /dev/null +++ b/internal/domain/main-entities/prescription-item/base/entity.go @@ -0,0 +1,25 @@ +package prescriptionitem + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + em "simrs-vx/internal/domain/main-entities/medicine" + emm "simrs-vx/internal/domain/main-entities/medicine-mix" + + erc "simrs-vx/internal/domain/references/common" +) + +type PrescriptionItem struct { + ecore.Main // adjust this according to the needs + Prescription_Id *uint `json:"prescription_id"` + IsMix bool `json:"isMix"` + Medicine_Code *string `json:"medicine_code"` + Medicine *em.Medicine `json:"medicine,omitempty" gorm:"foreignKey:Medicine_Code;references:Code"` + MedicineMix_Id *uint `json:"medicineMix_id"` + MedicineMix *emm.MedicineMix `json:"medicineMix,omitempty" gorm:"foreignKey:MedicineMix_Id;references:Id"` + Frequency *uint16 `json:"frequency"` + Dose float64 `json:"dose"` + Usage string `json:"usage" gorm:"size:255"` + Interval uint8 `json:"interval"` + IntervalUnit_Code erc.TimeUnitCode `json:"intervalUnit_code"` + Quantity float64 `json:"quantity"` +} diff --git a/internal/domain/main-entities/prescription-item/dto.go b/internal/domain/main-entities/prescription-item/dto.go index 6e871428..44619ec8 100644 --- a/internal/domain/main-entities/prescription-item/dto.go +++ b/internal/domain/main-entities/prescription-item/dto.go @@ -27,6 +27,7 @@ type ReadListDto struct { FilterDto Includes string `json:"includes"` Pagination ecore.Pagination + Sort string `json:"sort"` } type FilterDto struct { diff --git a/internal/domain/main-entities/prescription-item/entity.go b/internal/domain/main-entities/prescription-item/entity.go index 93174079..465059d7 100644 --- a/internal/domain/main-entities/prescription-item/entity.go +++ b/internal/domain/main-entities/prescription-item/entity.go @@ -2,26 +2,12 @@ package prescriptionitem import ( ecore "simrs-vx/internal/domain/base-entities/core" - em "simrs-vx/internal/domain/main-entities/medicine" - emm "simrs-vx/internal/domain/main-entities/medicine-mix" ep "simrs-vx/internal/domain/main-entities/prescription" - - erc "simrs-vx/internal/domain/references/common" + epib "simrs-vx/internal/domain/main-entities/prescription-item/base" ) type PrescriptionItem struct { - ecore.Main // adjust this according to the needs - Prescription_Id *uint `json:"prescription_id"` - Prescription *ep.Prescription `json:"prescription,omitempty" gorm:"foreignKey:Prescription_Id;references:Id"` - IsMix bool `json:"isMix"` - Medicine_Code *string `json:"medicine_code"` - Medicine *em.Medicine `json:"medicine,omitempty" gorm:"foreignKey:Medicine_Code;references:Code"` - MedicineMix_Id *uint `json:"medicineMix_id"` - MedicineMix *emm.MedicineMix `json:"medicineMix,omitempty" gorm:"foreignKey:MedicineMix_Id;references:Id"` - Frequency *uint16 `json:"frequency"` - Dose float64 `json:"dose"` - Usage string `json:"usage" gorm:"size:255"` - Interval uint8 `json:"interval"` - IntervalUnit_Code erc.TimeUnitCode `json:"intervalUnit_code"` - Quantity float64 `json:"quantity"` + ecore.Main // adjust this according to the needs + epib.PrescriptionItem + Prescription *ep.Prescription `json:"prescription,omitempty" gorm:"foreignKey:Prescription_Id;references:Id"` } diff --git a/internal/domain/main-entities/prescription/dto.go b/internal/domain/main-entities/prescription/dto.go index 9c73c0ee..7c4040fa 100644 --- a/internal/domain/main-entities/prescription/dto.go +++ b/internal/domain/main-entities/prescription/dto.go @@ -6,6 +6,7 @@ import ( ecore "simrs-vx/internal/domain/base-entities/core" ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/encounter" + epi "simrs-vx/internal/domain/main-entities/prescription-item/base" pa "simrs-vx/internal/lib/auth" @@ -56,12 +57,13 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty"` - Doctor_Code *string `json:"doctor_code"` - Doctor *ed.Doctor `json:"doctor,omitempty"` - IssuedAt *time.Time `json:"issuedAt"` - Status_Code erc.DataStatusCode `json:"status_code"` + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty"` + Doctor_Code *string `json:"doctor_code"` + Doctor *ed.Doctor `json:"doctor,omitempty"` + IssuedAt *time.Time `json:"issuedAt"` + Status_Code erc.DataStatusCode `json:"status_code"` + Items []epi.PrescriptionItem `json:"items" gorm:"foreignKey:Prescription_Id;references:Id"` } func (d Prescription) ToResponse() ResponseDto { @@ -72,6 +74,7 @@ func (d Prescription) ToResponse() ResponseDto { Doctor: d.Doctor, IssuedAt: d.IssuedAt, Status_Code: d.Status_Code, + Items: d.Items, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/prescription/entity.go b/internal/domain/main-entities/prescription/entity.go index 8c879b29..f7cc3597 100644 --- a/internal/domain/main-entities/prescription/entity.go +++ b/internal/domain/main-entities/prescription/entity.go @@ -4,6 +4,7 @@ import ( ecore "simrs-vx/internal/domain/base-entities/core" ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/encounter" + epi "simrs-vx/internal/domain/main-entities/prescription-item/base" "time" @@ -11,13 +12,14 @@ import ( ) type Prescription struct { - ecore.Main // adjust this according to the needs - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Doctor_Code *string `json:"doctor_code" gorm:"size:20"` - Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"` - IssuedAt *time.Time `json:"issuedAt"` - Status_Code erc.DataStatusCode `json:"status_code"` + ecore.Main // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + Doctor_Code *string `json:"doctor_code" gorm:"size:20"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"` + IssuedAt *time.Time `json:"issuedAt"` + Status_Code erc.DataStatusCode `json:"status_code"` + Items []epi.PrescriptionItem `json:"items" gorm:"foreignKey:Prescription_Id;references:Id"` } func (d Prescription) IsNotNew() bool { diff --git a/internal/interface/main-handler/prescription/handler.go b/internal/interface/main-handler/prescription/handler.go index 30d5998e..c7649d34 100644 --- a/internal/interface/main-handler/prescription/handler.go +++ b/internal/interface/main-handler/prescription/handler.go @@ -46,6 +46,7 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { return } dto := e.ReadDetailDto{} + sf.UrlQueryParam(&dto, *r.URL) dto.Id = uint(id) res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) diff --git a/internal/use-case/main-use-case/prescription-item/lib.go b/internal/use-case/main-use-case/prescription-item/lib.go index aa6f97bf..aa5c9e2b 100644 --- a/internal/use-case/main-use-case/prescription-item/lib.go +++ b/internal/use-case/main-use-case/prescription-item/lib.go @@ -47,13 +47,13 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Pr tx = dg.I } - tx = tx. + tx = tx.Debug(). Model(&e.PrescriptionItem{}). Scopes(gh.Preload(input.Includes)). Scopes(gh.Filter(input.FilterDto)). Count(&count). Scopes(gh.Paginate(input, &pagination)). - Order("\"CreatedAt\" DESC") + Scopes(gh.Sort(input.Sort)) if err := tx.Find(&data).Error; err != nil { if err == gorm.ErrRecordNotFound { From 65f5c6dc20229fc85d649489a7b055ce10495476 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Mon, 17 Nov 2025 07:58:22 +0700 Subject: [PATCH 204/329] feat/things-munaja: adjust DeviceOrder --- .../device-order-item/base/entity.go | 4 ++-- .../main-entities/device-order-item/dto.go | 10 +++++----- .../main-entities/device-order-item/entity.go | 2 ++ .../domain/main-entities/device-order/dto.go | 13 ++++++++----- .../domain/main-entities/device-order/entity.go | 17 +++++++++-------- .../main-use-case/device-order-item/helper.go | 2 +- 6 files changed, 27 insertions(+), 21 deletions(-) diff --git a/internal/domain/main-entities/device-order-item/base/entity.go b/internal/domain/main-entities/device-order-item/base/entity.go index 54cbe611..95eaa895 100644 --- a/internal/domain/main-entities/device-order-item/base/entity.go +++ b/internal/domain/main-entities/device-order-item/base/entity.go @@ -1,4 +1,4 @@ -package base +package deviceorderitem import ( ecore "simrs-vx/internal/domain/base-entities/core" @@ -10,5 +10,5 @@ type DeviceOrderItem struct { DeviceOrder_Id *uint `json:"deviceOrder_id"` Device_Code *string `json:"device_code"` Device *ed.Device `json:"device,omitempty" gorm:"foreignKey:Device_Code;references:Code"` - Count uint8 `json:"count"` + Quantity uint8 `json:"quantity"` } diff --git a/internal/domain/main-entities/device-order-item/dto.go b/internal/domain/main-entities/device-order-item/dto.go index afa08ed8..4464c91d 100644 --- a/internal/domain/main-entities/device-order-item/dto.go +++ b/internal/domain/main-entities/device-order-item/dto.go @@ -9,7 +9,7 @@ import ( type CreateDto struct { DeviceOrder_Id *uint `json:"deviceOrder_id"` Device_Code *string `json:"device_code"` - Count uint8 `json:"count"` + Quantity uint8 `json:"quantity"` } type ReadListDto struct { @@ -19,9 +19,9 @@ type ReadListDto struct { } type FilterDto struct { - DeviceOrder_Id *uint `json:"deviceOrder-id"` + DeviceOrder_Id *uint `json:"device-order-id"` Device_Code *string `json:"device-code"` - Count uint8 `json:"count"` + Quantity uint8 `json:"quantity"` } type ReadDetailDto struct { Id uint16 `json:"id"` @@ -48,7 +48,7 @@ type ResponseDto struct { DeviceOrder *edo.DeviceOrder `json:"deviceOrder,omitempty"` Device_Code *string `json:"device_code"` Device *ed.Device `json:"device,omitempty"` - Count uint8 `json:"count"` + Quantity uint8 `json:"quantity"` } func (d DeviceOrderItem) ToResponse() ResponseDto { @@ -57,7 +57,7 @@ func (d DeviceOrderItem) ToResponse() ResponseDto { DeviceOrder: d.DeviceOrder, Device_Code: d.Device_Code, Device: d.Device, - Count: d.Count, + Quantity: d.Quantity, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/device-order-item/entity.go b/internal/domain/main-entities/device-order-item/entity.go index a0743643..f214ec6a 100644 --- a/internal/domain/main-entities/device-order-item/entity.go +++ b/internal/domain/main-entities/device-order-item/entity.go @@ -1,11 +1,13 @@ package deviceorderitem import ( + ecore "simrs-vx/internal/domain/base-entities/core" edo "simrs-vx/internal/domain/main-entities/device-order" eb "simrs-vx/internal/domain/main-entities/device-order-item/base" ) type DeviceOrderItem struct { + ecore.Main // adjust this according to the needs eb.DeviceOrderItem DeviceOrder *edo.DeviceOrder `json:"deviceOrder,omitempty" gorm:"foreignKey:DeviceOrder_Id;references:Id"` } diff --git a/internal/domain/main-entities/device-order/dto.go b/internal/domain/main-entities/device-order/dto.go index 6371800c..cdff2a18 100644 --- a/internal/domain/main-entities/device-order/dto.go +++ b/internal/domain/main-entities/device-order/dto.go @@ -11,6 +11,7 @@ import ( erc "simrs-vx/internal/domain/references/common" // internal - domain - main-entities + edoi "simrs-vx/internal/domain/main-entities/device-order-item/base" ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/encounter" ) @@ -55,11 +56,12 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty"` - Doctor_Code *string `json:"doctor_code"` - Doctor *ed.Doctor `json:"doctor,omitempty"` - Status_Code erc.DataStatusCode `json:"status_code"` + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty"` + Doctor_Code *string `json:"doctor_code"` + Doctor *ed.Doctor `json:"doctor,omitempty"` + Status_Code erc.DataStatusCode `json:"status_code"` + Items []edoi.DeviceOrderItem `json:"items"` } func (d DeviceOrder) ToResponse() ResponseDto { @@ -69,6 +71,7 @@ func (d DeviceOrder) ToResponse() ResponseDto { Doctor_Code: d.Doctor_Code, Doctor: d.Doctor, Status_Code: d.Status_Code, + Items: d.Items, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/device-order/entity.go b/internal/domain/main-entities/device-order/entity.go index d9ba5a59..7ed304e5 100644 --- a/internal/domain/main-entities/device-order/entity.go +++ b/internal/domain/main-entities/device-order/entity.go @@ -1,21 +1,22 @@ package deviceorder import ( + erc "simrs-vx/internal/domain/references/common" + ecore "simrs-vx/internal/domain/base-entities/core" edoi "simrs-vx/internal/domain/main-entities/device-order-item/base" ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/encounter" - erc "simrs-vx/internal/domain/references/common" ) type DeviceOrder struct { - ecore.Main // adjust this according to the needs - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Doctor_Code *string `json:"doctor_code"` - Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"` - Status_Code erc.DataStatusCode `json:"status_code"` - Items []*edoi.DeviceOrderItem `json:"items" gorm:"foreignKey:DeviceOrder_Id;references:Id"` + ecore.Main // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + Doctor_Code *string `json:"doctor_code"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"` + Status_Code erc.DataStatusCode `json:"status_code"` + Items []edoi.DeviceOrderItem `json:"items" gorm:"foreignKey:DeviceOrder_Id;references:Id"` } func (d DeviceOrder) IsCompleted() bool { diff --git a/internal/use-case/main-use-case/device-order-item/helper.go b/internal/use-case/main-use-case/device-order-item/helper.go index 8c0be91f..6f3f7ce8 100644 --- a/internal/use-case/main-use-case/device-order-item/helper.go +++ b/internal/use-case/main-use-case/device-order-item/helper.go @@ -19,5 +19,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.DeviceOrderItem) { data.DeviceOrder_Id = inputSrc.DeviceOrder_Id data.Device_Code = inputSrc.Device_Code - data.Count = inputSrc.Count + data.Quantity = inputSrc.Quantity } From 712de2fdb02190669728fd8fab516d162320ce81 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Mon, 17 Nov 2025 08:00:04 +0700 Subject: [PATCH 205/329] feat/things-munaja: migration --- .../migrations/20251117005942.sql | 2 + cmd/main-migration/migrations/atlas.sum | 89 ++++++++++--------- 2 files changed, 47 insertions(+), 44 deletions(-) create mode 100644 cmd/main-migration/migrations/20251117005942.sql diff --git a/cmd/main-migration/migrations/20251117005942.sql b/cmd/main-migration/migrations/20251117005942.sql new file mode 100644 index 00000000..84a34010 --- /dev/null +++ b/cmd/main-migration/migrations/20251117005942.sql @@ -0,0 +1,2 @@ +-- Rename a column from "Count" to "Quantity" +ALTER TABLE "public"."DeviceOrderItem" RENAME COLUMN "Count" TO "Quantity"; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index cac4826e..a6e1b68c 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:t3DFzssEf9liKwykDE17fo19llwCgpTgEuSUd9VGusk= +h1:fNeqUpbdIqGDiH68u1bwwMgHTEOmmEWeI+IIYEq6pto= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,46 +75,47 @@ h1:t3DFzssEf9liKwykDE17fo19llwCgpTgEuSUd9VGusk= 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= +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:mW/TC8GgFgPLZ7PBVQnn9mChEekAcwfQMCbzXnoaw9w= From ebb3500d34e359ea45e28efc4586eb2c0bca6a0e Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 17 Nov 2025 11:05:21 +0700 Subject: [PATCH 206/329] unit finish --- internal/domain/main-entities/unit/dto.go | 1 + .../simgos-sync-handler.go | 8 + .../simgos-sync-handler/unit/handler.go | 66 ++++++++ .../main-use-case/installation/middleware.go | 6 +- internal/use-case/main-use-case/unit/case.go | 120 +++++++------- .../main-use-case/unit/middleware-runner.go | 38 +++-- .../use-case/main-use-case/unit/middleware.go | 23 ++- .../use-case/main-use-case/unit/tycovar.go | 31 +++- .../simgos-sync-plugin/unit/plugin.go | 153 ++++++++++++++++++ .../simgos-sync-use-case/installation/case.go | 127 +++++---------- .../simgos-sync-use-case/installation/lib.go | 42 ++++- .../simgos-sync-use-case/unit/case.go | 141 ++++++---------- .../simgos-sync-use-case/unit/helper.go | 15 +- .../use-case/simgos-sync-use-case/unit/lib.go | 72 +++++---- 14 files changed, 528 insertions(+), 315 deletions(-) create mode 100644 internal/interface/simgos-sync-handler/unit/handler.go create mode 100644 internal/use-case/simgos-sync-plugin/unit/plugin.go diff --git a/internal/domain/main-entities/unit/dto.go b/internal/domain/main-entities/unit/dto.go index f272ecec..7b071a84 100644 --- a/internal/domain/main-entities/unit/dto.go +++ b/internal/domain/main-entities/unit/dto.go @@ -7,6 +7,7 @@ import ( ) type CreateDto struct { + Id *uint `json:"id"` Installation_Code *string `json:"installation_code"` Code string `json:"code" validate:"maxLength=10"` Name string `json:"name" validate:"maxLength=50"` diff --git a/internal/interface/simgos-sync-handler/simgos-sync-handler.go b/internal/interface/simgos-sync-handler/simgos-sync-handler.go index aebcc9bb..3b1908a9 100644 --- a/internal/interface/simgos-sync-handler/simgos-sync-handler.go +++ b/internal/interface/simgos-sync-handler/simgos-sync-handler.go @@ -19,6 +19,7 @@ import ( /******************** internal ********************/ "simrs-vx/internal/interface/main-handler/home" installation "simrs-vx/internal/interface/simgos-sync-handler/installation" + unit "simrs-vx/internal/interface/simgos-sync-handler/unit" ) func SetRoutes() http.Handler { @@ -42,5 +43,12 @@ func SetRoutes() http.Handler { "DELETE /{id}": installation.O.Delete, }) + hk.GroupRoutes(prefix+"/v1/unit", r, hk.MapHandlerFunc{ + "POST /": unit.O.Create, + "POST /log": unit.O.CreateLog, + "PATCH /{id}": unit.O.Update, + "DELETE /{id}": unit.O.Delete, + }) + return cmw.SetCors(handlerlogger.SetLog(r)) } diff --git a/internal/interface/simgos-sync-handler/unit/handler.go b/internal/interface/simgos-sync-handler/unit/handler.go new file mode 100644 index 00000000..b1cac1c5 --- /dev/null +++ b/internal/interface/simgos-sync-handler/unit/handler.go @@ -0,0 +1,66 @@ +package unit + +import ( + "net/http" + + rw "github.com/karincake/risoles" + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/unit" + esync "simrs-vx/internal/domain/sync-entities/log" + u "simrs-vx/internal/use-case/simgos-sync-use-case/unit" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + 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) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + + val := uint16(id) + dto.Id = &val + + 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{} + val := uint16(id) + dto.Id = &val + + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/use-case/main-use-case/installation/middleware.go b/internal/use-case/main-use-case/installation/middleware.go index dd4b0b42..b8dfa4c8 100644 --- a/internal/use-case/main-use-case/installation/middleware.go +++ b/internal/use-case/main-use-case/installation/middleware.go @@ -7,12 +7,10 @@ import ( // example of middleware func init() { createPreMw = append(createPreMw, - createMw{Name: "create-installation", Func: plugin.Create}, - ) + createMw{Name: "create-installation", Func: plugin.Create}) createSimxLogMw = append(createSimxLogMw, - createLogMw{Name: "create-log", Func: plugin.CreateLog}, - ) + createLogMw{Name: "create-log", Func: plugin.CreateLog}) updatePreMw = append(updatePreMw, updateMw{Name: "update-installation", Func: plugin.Update}) diff --git a/internal/use-case/main-use-case/unit/case.go b/internal/use-case/main-use-case/unit/case.go index 650c4511..75b1c4ab 100644 --- a/internal/use-case/main-use-case/unit/case.go +++ b/internal/use-case/main-use-case/unit/case.go @@ -2,6 +2,8 @@ package unit import ( e "simrs-vx/internal/domain/main-entities/unit" + erc "simrs-vx/internal/domain/references/common" + esync "simrs-vx/internal/domain/sync-entities/log" "strconv" dg "github.com/karincake/apem/db-gorm-pg" @@ -25,36 +27,32 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") + mwRunner := newMiddlewareRunner(&event) 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 resData, err := CreateData(input, &event, tx); err != nil { return err } else { data = *resData + id := uint(data.Id) + input.Id = &id } - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input); err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") - return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.II{ "source": source, @@ -66,7 +64,6 @@ func Create(input e.CreateDto) (*d.Data, error) { } func ReadList(input e.ReadListDto) (*d.Data, error) { - var data *e.Unit var dataList []e.Unit var metaList *e.MetaDto var err error @@ -80,23 +77,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 }) @@ -131,23 +114,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 }) @@ -177,6 +146,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "update") + mwRunner := newMiddlewareRunner(&event) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -184,32 +154,26 @@ 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 - } - + input.Id = &data.Id if err := UpdateData(input, data, &event, tx); err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") - - 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.RunUpdateMiddleware(updatePreMw, &input); err != nil { return err } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -233,6 +197,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "delete") + mwRunner := newMiddlewareRunner(&event) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -240,30 +205,26 @@ 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 - } - + input.Id = &data.Id 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 { + // Run pre-middleware + if err := mwRunner.RunDeleteMiddleware(deletePreMw, &input); err != nil { return err } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -274,3 +235,32 @@ func Delete(input e.DeleteDto) (*d.Data, error) { }, nil } + +func runLogMiddleware(err error, input any, mwRunner *middlewareRunner) error { + var errMsg string + inputLog := esync.SimxLogDto{ + Payload: input, + Method: erc.CCCreate, + } + + if err != nil { + // Run log-middleware + errMsg = err.Error() + inputLog.ErrMessage = &errMsg + inputLog.IsSuccess = false + + // create log failed + if errMiddleware := mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog); errMiddleware != nil { + return errMiddleware + } + return err + } + + // create log success + inputLog.IsSuccess = true + if err = mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog); err != nil { + return err + } + + return nil +} 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 fdce9d02..3c7fa241 100644 --- a/internal/use-case/main-use-case/unit/middleware-runner.go +++ b/internal/use-case/main-use-case/unit/middleware-runner.go @@ -2,6 +2,7 @@ package unit import ( e "simrs-vx/internal/domain/main-entities/unit" + esync "simrs-vx/internal/domain/sync-entities/log" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -15,21 +16,36 @@ type middlewareRunner struct { } // NewMiddlewareExecutor creates a new middleware executor -func newMiddlewareRunner(event *pl.Event, tx *gorm.DB) *middlewareRunner { +func newMiddlewareRunner(event *pl.Event) *middlewareRunner { return &middlewareRunner{ Event: event, - Tx: tx, } } // ExecuteCreateMiddleware executes create middleware -func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.Unit) error { +func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto) 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 +} + +// ExecuteCreateMiddleware executes create middleware +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 +84,13 @@ func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, return nil } -func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Unit) error { +func (me *middlewareRunner) RunUpdateMiddleware(middlewares []UpdateMw, input *e.UpdateDto) 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 +99,13 @@ func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, inpu return nil } -func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Unit) 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) } diff --git a/internal/use-case/main-use-case/unit/middleware.go b/internal/use-case/main-use-case/unit/middleware.go index bac48f4d..e3144448 100644 --- a/internal/use-case/main-use-case/unit/middleware.go +++ b/internal/use-case/main-use-case/unit/middleware.go @@ -1,9 +1,20 @@ package unit +import ( + plugin "simrs-vx/internal/use-case/simgos-sync-plugin/unit" +) + // example of middleware -// func init() { -// createPreMw = append(createPreMw, -// CreateMw{Name: "modif-input", Func: pm.ModifInput}, -// CreateMw{Name: "check-data", Func: pm.CheckData}, -// ) -// } +func init() { + createPreMw = append(createPreMw, + createMw{Name: "create-unit", Func: plugin.Create}) + + createSimxLogMw = append(createSimxLogMw, + createLogMw{Name: "create-log", Func: plugin.CreateLog}) + + updatePreMw = append(updatePreMw, + updateMw{Name: "update-unit", Func: plugin.Update}) + + deletePreMw = append(deletePreMw, + deleteMw{Name: "delete-unit", Func: plugin.Delete}) +} diff --git a/internal/use-case/main-use-case/unit/tycovar.go b/internal/use-case/main-use-case/unit/tycovar.go index e1a7c69f..bf717333 100644 --- a/internal/use-case/main-use-case/unit/tycovar.go +++ b/internal/use-case/main-use-case/unit/tycovar.go @@ -12,11 +12,27 @@ import ( "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/unit" + elog "simrs-vx/internal/domain/sync-entities/log" ) type createMw struct { Name string - Func func(input *e.CreateDto, data *e.Unit, tx *gorm.DB) error + Func func(input *e.CreateDto) error +} + +type createLogMw struct { + Name string + Func func(input *elog.SimxLogDto) error +} + +type updateMw struct { + Name string + Func func(input *e.UpdateDto) error +} + +type deleteMw struct { + Name string + Func func(input *e.DeleteDto) error } type readListMw struct { @@ -29,16 +45,17 @@ type readDetailMw struct { Func func(input *e.ReadDetailDto, data *e.Unit, 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 +var createPreMw []createMw // preprocess middleware +var createPostMw []createMw // postprocess middleware +var createSimxLogMw []createLogMw 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 diff --git a/internal/use-case/simgos-sync-plugin/unit/plugin.go b/internal/use-case/simgos-sync-plugin/unit/plugin.go new file mode 100644 index 00000000..8462f18d --- /dev/null +++ b/internal/use-case/simgos-sync-plugin/unit/plugin.go @@ -0,0 +1,153 @@ +package unit + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + + sync "simrs-vx/internal/infra/sync-cfg" + + e "simrs-vx/internal/domain/main-entities/unit" + elog "simrs-vx/internal/domain/sync-entities/log" +) + +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() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf(resp.Status) + } + + _, err = io.ReadAll(resp.Body) + if err != nil { + return err + } + + return nil +} + +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() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf(resp.Status) + } + + _, err = io.ReadAll(resp.Body) + if err != nil { + return err + } + + return nil +} + +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() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf(resp.Status) + } + + _, err = io.ReadAll(resp.Body) + if err != nil { + return err + } + + return nil +} + +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() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf(resp.Status) + } + + _, err = io.ReadAll(resp.Body) + if err != nil { + return err + } + + return nil +} + +func getPrefixEndpoint() string { + return fmt.Sprintf("%s%s/v1/unit", sync.O.Host, sync.O.Prefix) +} diff --git a/internal/use-case/simgos-sync-use-case/installation/case.go b/internal/use-case/simgos-sync-use-case/installation/case.go index 6c3a79bd..755c65d3 100644 --- a/internal/use-case/simgos-sync-use-case/installation/case.go +++ b/internal/use-case/simgos-sync-use-case/installation/case.go @@ -1,7 +1,6 @@ package installation import ( - "errors" esimgos "simrs-vx/internal/domain/simgos-entities/installation" esync "simrs-vx/internal/domain/sync-entities/log" @@ -38,22 +37,23 @@ func Create(input e.CreateDto) (*d.Data, error) { } // STEP 2: Insert to Link - if err = CreateLinkData(*input.Id, sgData.No_Instalasi, &event, txSync); err != nil { + syncLink, err := CreateLinkData(*input.Id, sgData.No_Instalasi, &event, txSync) + if err != nil { txSimgos.Rollback() return nil, err } // STEP 3: Commit two trx - if err = txSimgos.Commit().Error; err != nil { - txSimgos.Rollback() + if err = txSync.Commit().Error; err != nil { txSync.Rollback() + txSimgos.Rollback() return nil, err } - if err = txSync.Commit().Error; err != nil { + if err = txSimgos.Commit().Error; err != nil { // STEP 4: Rollback Partial go func() { - _ = DeleteSimgosData(sgData, &event) + _ = DeleteLinkData(syncLink, &event) }() return nil, err } @@ -106,9 +106,7 @@ func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { func Update(input e.UpdateDto) (*d.Data, error) { var ( - txSync = dg.I.Begin() txSimgos = dg.IS["simrs"].Begin() - sgData *esimgos.MInstalasi err error ) @@ -121,51 +119,23 @@ func Update(input e.UpdateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "update") // STEP 1: Get Installation Link - syncLink, errGetLink := ReadDetailLinkData(*input.Id, &event) - if errGetLink != nil { - if !errors.Is(err, gorm.ErrRecordNotFound) { - return nil, err - } + syncLink, err := ReadDetailLinkData(*input.Id, &event) + if err != nil { + return nil, err } - if errGetLink != nil && errors.Is(errGetLink, gorm.ErrRecordNotFound) { - // STEP 2.1: Insert to simgos - sgData, err = CreateSimgosData(input.CreateDto, &event, txSimgos) - if err != nil { - return nil, err - } - - // STEP 2.2: Insert to Link - simxId := uint(*input.Id) - if err = CreateLinkData(simxId, sgData.No_Instalasi, &event, txSync); err != nil { - txSimgos.Rollback() - return nil, err - } - } else { - // Step 3.1: Update Simgos - err = UpdateSimgosData(input, syncLink, &event, txSimgos) - if err != nil { - return nil, err - } + // Step 2: Update Simgos + err = UpdateSimgosData(input, syncLink, &event, txSimgos) + if err != nil { + return nil, err } // STEP 4: Commit two trx if err = txSimgos.Commit().Error; err != nil { txSimgos.Rollback() - txSync.Rollback() return nil, err } - if errGetLink != nil { - if err = txSync.Commit().Error; err != nil { - // STEP 5.1: Rollback Partial - go func() { - _ = DeleteSimgosData(sgData, &event) - }() - return nil, err - } - } - pl.SetLogInfo(&event, nil, "complete") return &d.Data{ @@ -194,52 +164,43 @@ func Delete(input e.DeleteDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "delete") // STEP 1: Get Installation Link - syncLink, errGetLink := ReadDetailLinkData(*input.Id, &event) - if errGetLink != nil { - if !errors.Is(err, gorm.ErrRecordNotFound) { - return nil, err - } + syncLink, err := ReadDetailLinkData(*input.Id, &event) + if err != nil { + return nil, err } - if errGetLink == nil { - // STEP 2: Get Simgos - sgData, err = ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) - if err != nil { - return nil, err - } + // STEP 2: Get Simgos + sgData, err = ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) + if err != nil { + return nil, err + } - // STEP 3: Delete M_Instalation Simgos - err = DeleteSimgosData(sgData, &event, txSimgos) - if err != nil { - return nil, err - } + // STEP 3: Delete M_Instalation Simgos + err = SoftDeleteSimgosData(sgData, &event, txSimgos) + if err != nil { + return nil, err + } - // STEP 4: Delete Installation Link - err = DeleteLinkData(syncLink, &event, txSync) - if err != nil { - txSimgos.Rollback() - return nil, err - } + // STEP 4: Delete Installation Link + err = DeleteLinkData(syncLink, &event, txSync) + if err != nil { + txSimgos.Rollback() + return nil, err + } - // STEP 4: Commit two trx - if err = txSimgos.Commit().Error; err != nil { - txSimgos.Rollback() - txSync.Rollback() - return nil, err - } + // STEP 4: Commit two trx + if err = txSync.Commit().Error; err != nil { + txSync.Rollback() + txSimgos.Rollback() + return nil, err + } - if err = txSync.Commit().Error; err != nil { - // STEP 5: Rollback Partial - go func() { - inputRollback := e.UpdateDto{ - CreateDto: e.CreateDto{ - Name: sgData.Nama_Instalasi, - }, - } - _ = UpdateSimgosData(inputRollback, syncLink, &event) - }() - return nil, err - } + if err = txSimgos.Commit().Error; err != nil { + // STEP 5: Rollback Partial + go func() { + _, _ = CreateLinkData(uint(*input.Id), sgData.No_Instalasi, &event) + }() + return nil, err } pl.SetLogInfo(&event, nil, "complete") diff --git a/internal/use-case/simgos-sync-use-case/installation/lib.go b/internal/use-case/simgos-sync-use-case/installation/lib.go index 3e7ca854..77140553 100644 --- a/internal/use-case/simgos-sync-use-case/installation/lib.go +++ b/internal/use-case/simgos-sync-use-case/installation/lib.go @@ -4,6 +4,7 @@ import ( esynclog "simrs-vx/internal/domain/sync-entities/log" 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" @@ -45,7 +46,9 @@ func ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.MInstalasi if err := tx. Where("\"no_instalasi\" = ?", simgosId). First(&data).Error; err != nil { - return nil, err + if processedErr := pu.HandleReadError(err, event, source, simgosId, data); processedErr != nil { + return nil, processedErr + } } pl.SetLogInfo(event, nil, "complete") @@ -79,7 +82,32 @@ func UpdateSimgosData(input e.UpdateDto, dataSimgos *esync.InstallationLink, eve return nil } -func DeleteSimgosData(data *esimgos.MInstalasi, event *pl.Event, dbx ...*gorm.DB) error { +func HardDeleteSimgosData(data *esimgos.MInstalasi, 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 SoftDeleteSimgosData(data *esimgos.MInstalasi, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, data, "started", "DBDelete") var tx *gorm.DB @@ -105,7 +133,7 @@ func DeleteSimgosData(data *esimgos.MInstalasi, event *pl.Event, dbx ...*gorm.DB return nil } -func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) error { +func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.InstallationLink, error) { pl.SetLogInfo(event, nil, "started", "DBCreate") data := setDataSimxLink(simxId, simgosId) @@ -117,11 +145,11 @@ func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) err } if err := tx.Create(&data).Error; err != nil { - return plh.HandleCreateError(data, event, err) + return nil, plh.HandleCreateError(data, event, err) } pl.SetLogInfo(event, nil, "complete") - return nil + return &data, nil } func ReadDetailLinkData(simxId uint16, event *pl.Event) (*esync.InstallationLink, error) { @@ -133,7 +161,9 @@ func ReadDetailLinkData(simxId uint16, event *pl.Event) (*esync.InstallationLink if err := tx. Where("\"Simx_Id\" = ?", simxId). First(&data).Error; err != nil { - return nil, err + if processedErr := pu.HandleReadError(err, event, source, simxId, data); processedErr != nil { + return nil, processedErr + } } pl.SetLogInfo(event, nil, "complete") diff --git a/internal/use-case/simgos-sync-use-case/unit/case.go b/internal/use-case/simgos-sync-use-case/unit/case.go index bc14a72d..bb87f1c6 100644 --- a/internal/use-case/simgos-sync-use-case/unit/case.go +++ b/internal/use-case/simgos-sync-use-case/unit/case.go @@ -1,21 +1,18 @@ package unit import ( - "errors" - esimgos "simrs-vx/internal/domain/simgos-entities/installation" - esync "simrs-vx/internal/domain/sync-entities/log" + pl "simrs-vx/pkg/logger" dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" - - pl "simrs-vx/pkg/logger" - "gorm.io/gorm" - e "simrs-vx/internal/domain/main-entities/installation" + e "simrs-vx/internal/domain/main-entities/unit" + esimgos "simrs-vx/internal/domain/simgos-entities/unit" + esync "simrs-vx/internal/domain/sync-entities/log" ) -const source = "installation" +const source = "unit" func Create(input e.CreateDto) (*d.Data, error) { var ( @@ -38,22 +35,23 @@ func Create(input e.CreateDto) (*d.Data, error) { } // STEP 2: Insert to Link - if err = CreateLinkData(*input.Id, sgData.No_Instalasi, &event, txSync); err != nil { + syncLink, err := CreateLinkData(*input.Id, sgData.Kode, &event, txSync) + if err != nil { txSimgos.Rollback() return nil, err } // STEP 3: Commit two trx - if err = txSimgos.Commit().Error; err != nil { - txSimgos.Rollback() + if err = txSync.Commit().Error; err != nil { txSync.Rollback() + txSimgos.Rollback() return nil, err } - if err = txSync.Commit().Error; err != nil { + if err = txSimgos.Commit().Error; err != nil { // STEP 4: Rollback Partial go func() { - _ = DeleteSimgosData(sgData, &event) + _ = DeleteLinkData(syncLink, &event) }() return nil, err } @@ -106,9 +104,7 @@ func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { func Update(input e.UpdateDto) (*d.Data, error) { var ( - txSync = dg.I.Begin() txSimgos = dg.IS["simrs"].Begin() - sgData *esimgos.MInstalasi err error ) @@ -121,51 +117,23 @@ func Update(input e.UpdateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "update") // STEP 1: Get Installation Link - syncLink, errGetLink := ReadDetailLinkData(*input.Id, &event) - if errGetLink != nil { - if !errors.Is(err, gorm.ErrRecordNotFound) { - return nil, err - } + syncLink, err := ReadDetailLinkData(*input.Id, &event) + if err != nil { + return nil, err } - if errGetLink != nil && errors.Is(errGetLink, gorm.ErrRecordNotFound) { - // STEP 2.1: Insert to simgos - sgData, err = CreateSimgosData(input.CreateDto, &event, txSimgos) - if err != nil { - return nil, err - } - - // STEP 2.2: Insert to Link - simxId := uint(*input.Id) - if err = CreateLinkData(simxId, sgData.No_Instalasi, &event, txSync); err != nil { - txSimgos.Rollback() - return nil, err - } - } else { - // Step 3.1: Update Simgos - err = UpdateSimgosData(input, syncLink, &event, txSimgos) - if err != nil { - return nil, err - } + // Step 2: Update Simgos + err = UpdateSimgosData(input, syncLink, &event, txSimgos) + if err != nil { + return nil, err } // STEP 4: Commit two trx if err = txSimgos.Commit().Error; err != nil { txSimgos.Rollback() - txSync.Rollback() return nil, err } - if errGetLink != nil { - if err = txSync.Commit().Error; err != nil { - // STEP 5.1: Rollback Partial - go func() { - _ = DeleteSimgosData(sgData, &event) - }() - return nil, err - } - } - pl.SetLogInfo(&event, nil, "complete") return &d.Data{ @@ -181,7 +149,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { var ( txSync = dg.I.Begin() txSimgos = dg.IS["simrs"].Begin() - sgData *esimgos.MInstalasi + sgData *esimgos.MPloy err error ) @@ -194,52 +162,43 @@ func Delete(input e.DeleteDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "delete") // STEP 1: Get Installation Link - syncLink, errGetLink := ReadDetailLinkData(*input.Id, &event) - if errGetLink != nil { - if !errors.Is(err, gorm.ErrRecordNotFound) { - return nil, err - } + syncLink, err := ReadDetailLinkData(*input.Id, &event) + if err != nil { + return nil, err } - if errGetLink == nil { - // STEP 2: Get Simgos - sgData, err = ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) - if err != nil { - return nil, err - } + // STEP 2: Get Simgos + sgData, err = ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) + if err != nil { + return nil, err + } - // STEP 3: Delete M_Instalation Simgos - err = DeleteSimgosData(sgData, &event, txSimgos) - if err != nil { - return nil, err - } + // STEP 3: Delete M_Poly Simgos + err = HardDeleteSimgosData(sgData, &event, txSimgos) + if err != nil { + return nil, err + } - // STEP 4: Delete Installation Link - err = DeleteLinkData(syncLink, &event, txSync) - if err != nil { - txSimgos.Rollback() - return nil, err - } + // STEP 4: Delete Installation Link + err = DeleteLinkData(syncLink, &event, txSync) + if err != nil { + txSimgos.Rollback() + return nil, err + } - // STEP 4: Commit two trx - if err = txSimgos.Commit().Error; err != nil { - txSimgos.Rollback() - txSync.Rollback() - return nil, err - } + // STEP 4: Commit two trx + if err = txSync.Commit().Error; err != nil { + txSync.Rollback() + txSimgos.Rollback() + return nil, err + } - if err = txSync.Commit().Error; err != nil { - // STEP 5: Rollback Partial - go func() { - inputRollback := e.UpdateDto{ - CreateDto: e.CreateDto{ - Name: sgData.Nama_Instalasi, - }, - } - _ = UpdateSimgosData(inputRollback, syncLink, &event) - }() - return nil, err - } + if err = txSimgos.Commit().Error; err != nil { + // STEP 5: Rollback Partial + go func() { + _, _ = CreateLinkData(uint(*input.Id), sgData.Kode, &event) + }() + return nil, err } pl.SetLogInfo(&event, nil, "complete") diff --git a/internal/use-case/simgos-sync-use-case/unit/helper.go b/internal/use-case/simgos-sync-use-case/unit/helper.go index 53c518e2..a499958c 100644 --- a/internal/use-case/simgos-sync-use-case/unit/helper.go +++ b/internal/use-case/simgos-sync-use-case/unit/helper.go @@ -8,14 +8,14 @@ import ( "encoding/json" erc "simrs-vx/internal/domain/references/common" - e "simrs-vx/internal/domain/main-entities/installation" + e "simrs-vx/internal/domain/main-entities/unit" esimgos "simrs-vx/internal/domain/simgos-entities/unit" - esync "simrs-vx/internal/domain/sync-entities/installation" esyncLog "simrs-vx/internal/domain/sync-entities/log" + esync "simrs-vx/internal/domain/sync-entities/unit" ) -func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.) { +func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MPloy) { var inputSrc *e.CreateDto if inputT, ok := any(input).(*e.CreateDto); ok { inputSrc = inputT @@ -24,14 +24,13 @@ func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.) { inputSrc = &inputTemp.CreateDto } - data.Nama_Instalasi = inputSrc.Name - data.Status_Rawat_Inap = 0 - data.St_Aktif = 1 + data.Nama = inputSrc.Name + data.Jenispoly = 0 return } -func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.InstallationSimxLog) { +func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.UnitSimxLog) { // encode to JSON jsonData, _ := json.MarshalIndent(input.Payload, "", " ") jsonString := string(jsonData) @@ -53,7 +52,7 @@ func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.InstallationSimxLog) return } -func setDataSimxLink(simxId, simgosId uint) (data esync.InstallationLink) { +func setDataSimxLink(simxId, simgosId uint) (data esync.UnitLink) { data.Simx_Id = simxId data.Simgos_Id = simgosId return diff --git a/internal/use-case/simgos-sync-use-case/unit/lib.go b/internal/use-case/simgos-sync-use-case/unit/lib.go index 091082f1..720bd413 100644 --- a/internal/use-case/simgos-sync-use-case/unit/lib.go +++ b/internal/use-case/simgos-sync-use-case/unit/lib.go @@ -1,22 +1,23 @@ package unit import ( - esynclog "simrs-vx/internal/domain/sync-entities/log" 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/installation" - esimgos "simrs-vx/internal/domain/simgos-entities/installation" - esync "simrs-vx/internal/domain/sync-entities/installation" + e "simrs-vx/internal/domain/main-entities/unit" + esimgos "simrs-vx/internal/domain/simgos-entities/unit" + esynclog "simrs-vx/internal/domain/sync-entities/log" + esync "simrs-vx/internal/domain/sync-entities/unit" ) var now = time.Now() -func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esimgos.MInstalasi, error) { +func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esimgos.MPloy, error) { pl.SetLogInfo(event, nil, "started", "DBCreate") data := setDataSimgos(&input) @@ -36,27 +37,29 @@ func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esi return &data, nil } -func ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.MInstalasi, error) { +func ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.MPloy, error) { pl.SetLogInfo(event, simgosId, "started", "DBReadDetail") - data := esimgos.MInstalasi{} + data := esimgos.MPloy{} var tx = dg.IS["simrs"] if err := tx. - Where("\"no_instalasi\" = ?", simgosId). + Where("\"kode\" = ?", simgosId). First(&data).Error; err != nil { - return nil, err + if processedErr := pu.HandleReadError(err, event, source, simgosId, data); processedErr != nil { + return nil, processedErr + } } pl.SetLogInfo(event, nil, "complete") return &data, nil } -func UpdateSimgosData(input e.UpdateDto, dataSimgos *esync.InstallationLink, event *pl.Event, dbx ...*gorm.DB) error { +func UpdateSimgosData(input e.UpdateDto, dataSimgos *esync.UnitLink, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, input, "started", "DBUpdate") data := setDataSimgos(&input) - data.No_Instalasi = dataSimgos.Simgos_Id + data.Kode = dataSimgos.Simgos_Id var tx *gorm.DB if len(dbx) > 0 { @@ -79,7 +82,7 @@ func UpdateSimgosData(input e.UpdateDto, dataSimgos *esync.InstallationLink, eve return nil } -func DeleteSimgosData(data *esimgos.MInstalasi, event *pl.Event, dbx ...*gorm.DB) error { +func HardDeleteSimgosData(data *esimgos.MPloy, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, data, "started", "DBDelete") var tx *gorm.DB @@ -89,9 +92,8 @@ func DeleteSimgosData(data *esimgos.MInstalasi, event *pl.Event, dbx ...*gorm.DB tx = dg.IS["simrs"] } - data.St_Aktif = 0 - - if err := tx.Save(&data).Error; err != nil { + if err := tx. + Delete(&data).Error; err != nil { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "data-delete-fail", @@ -105,7 +107,7 @@ func DeleteSimgosData(data *esimgos.MInstalasi, event *pl.Event, dbx ...*gorm.DB return nil } -func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) error { +func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.UnitLink, error) { pl.SetLogInfo(event, nil, "started", "DBCreate") data := setDataSimxLink(simxId, simgosId) @@ -117,30 +119,32 @@ func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) err } if err := tx.Create(&data).Error; err != nil { - return plh.HandleCreateError(data, event, err) - } - - pl.SetLogInfo(event, nil, "complete") - return nil -} - -func ReadDetailLinkData(simxId uint16, event *pl.Event) (*esync.InstallationLink, error) { - pl.SetLogInfo(event, simxId, "started", "DBReadDetail") - data := esync.InstallationLink{} - - var tx = dg.I - - if err := tx. - Where("\"Simx_Id\" = ?", simxId). - First(&data).Error; err != nil { - return nil, err + return nil, plh.HandleCreateError(data, event, err) } pl.SetLogInfo(event, nil, "complete") return &data, nil } -func DeleteLinkData(data *esync.InstallationLink, event *pl.Event, dbx ...*gorm.DB) error { +func ReadDetailLinkData(simxId uint16, event *pl.Event) (*esync.UnitLink, error) { + pl.SetLogInfo(event, simxId, "started", "DBReadDetail") + data := esync.UnitLink{} + + 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.UnitLink, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, data, "started", "DBDelete") var tx *gorm.DB From 49c82c957e9183c0761a2f64bcbb18b81b4125ec Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 17 Nov 2025 11:17:43 +0700 Subject: [PATCH 207/329] add entity sync for division, specialist and subspecialist --- .../migrations/20251117041601.sql | 108 ++++++++++++++++++ .../migrations/atlas.sum | 5 +- .../domain/sync-entities/division/entity.go | 29 +++++ .../domain/sync-entities/specialist/entity.go | 29 +++++ .../sync-entities/subspecialist/entity.go | 29 +++++ internal/interface/migration/migration.go | 2 +- .../migration/simgossync-entities.go | 14 ++- 7 files changed, 212 insertions(+), 4 deletions(-) create mode 100644 cmd/simgos-sync-migration/migrations/20251117041601.sql create mode 100644 internal/domain/sync-entities/division/entity.go create mode 100644 internal/domain/sync-entities/specialist/entity.go create mode 100644 internal/domain/sync-entities/subspecialist/entity.go diff --git a/cmd/simgos-sync-migration/migrations/20251117041601.sql b/cmd/simgos-sync-migration/migrations/20251117041601.sql new file mode 100644 index 00000000..7c33b155 --- /dev/null +++ b/cmd/simgos-sync-migration/migrations/20251117041601.sql @@ -0,0 +1,108 @@ +-- Create "DivisionLink" table +CREATE TABLE "public"."DivisionLink" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Simx_Id" bigint NULL, + "Simgos_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_DivisionLink_Simgos_Id" UNIQUE ("Simgos_Id"), + CONSTRAINT "uni_DivisionLink_Simx_Id" UNIQUE ("Simx_Id") +); +-- Create "DivisionSimgosLog" table +CREATE TABLE "public"."DivisionSimgosLog" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Value" text NULL, + "Date" timestamptz NULL, + "Status" text NULL, + "ErrMessage" text NULL, + PRIMARY KEY ("Id") +); +-- Create "DivisionSimxLog" table +CREATE TABLE "public"."DivisionSimxLog" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Value" text NULL, + "Date" timestamptz NULL, + "Status" text NULL, + "ErrMessage" text NULL, + PRIMARY KEY ("Id") +); +-- Create "SpecialistLink" table +CREATE TABLE "public"."SpecialistLink" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Simx_Id" bigint NULL, + "Simgos_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_SpecialistLink_Simgos_Id" UNIQUE ("Simgos_Id"), + CONSTRAINT "uni_SpecialistLink_Simx_Id" UNIQUE ("Simx_Id") +); +-- Create "SpecialistSimgosLog" table +CREATE TABLE "public"."SpecialistSimgosLog" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Value" text NULL, + "Date" timestamptz NULL, + "Status" text NULL, + "ErrMessage" text NULL, + PRIMARY KEY ("Id") +); +-- Create "SpecialistSimxLog" table +CREATE TABLE "public"."SpecialistSimxLog" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Value" text NULL, + "Date" timestamptz NULL, + "Status" text NULL, + "ErrMessage" text NULL, + PRIMARY KEY ("Id") +); +-- Create "SubspecialistLink" table +CREATE TABLE "public"."SubspecialistLink" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Simx_Id" bigint NULL, + "Simgos_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_SubspecialistLink_Simgos_Id" UNIQUE ("Simgos_Id"), + CONSTRAINT "uni_SubspecialistLink_Simx_Id" UNIQUE ("Simx_Id") +); +-- Create "SubspecialistSimgosLog" table +CREATE TABLE "public"."SubspecialistSimgosLog" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Value" text NULL, + "Date" timestamptz NULL, + "Status" text NULL, + "ErrMessage" text NULL, + PRIMARY KEY ("Id") +); +-- Create "SubspecialistSimxLog" table +CREATE TABLE "public"."SubspecialistSimxLog" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Value" text NULL, + "Date" timestamptz NULL, + "Status" text NULL, + "ErrMessage" text NULL, + PRIMARY KEY ("Id") +); diff --git a/cmd/simgos-sync-migration/migrations/atlas.sum b/cmd/simgos-sync-migration/migrations/atlas.sum index e8418ec2..30f8c5dc 100644 --- a/cmd/simgos-sync-migration/migrations/atlas.sum +++ b/cmd/simgos-sync-migration/migrations/atlas.sum @@ -1,3 +1,4 @@ -h1:xxkaO6rL13nwrZd1vrsoGJrrwCtXPgGRmwGEjWJ1V/c= +h1:SN+f41iFH0m63kHeZHYricAjil5GJ9EC0LBOSdFDnmY= 20251113035508.sql h1:rjDlu6yDdy5xv6nrCOr7NialrLSLT23pzduYNq29Hf0= -20251114071129.sql h1:O4nfv4l9vcXpE2Kyu7vjnubD8kDZ7JltRaF2auOdMpc= +20251114071129.sql h1:Z0GQ5bJo3C+tplaWzxT8n3J9HLkEaVsRVp5nn7bmYow= +20251117041601.sql h1:mIxZ2luKQREXUBY36PwLNDFI/Wf1T6Z2DDoGOueXFwI= diff --git a/internal/domain/sync-entities/division/entity.go b/internal/domain/sync-entities/division/entity.go new file mode 100644 index 00000000..9841c208 --- /dev/null +++ b/internal/domain/sync-entities/division/entity.go @@ -0,0 +1,29 @@ +package division + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + erc "simrs-vx/internal/domain/references/common" + "time" +) + +type DivisionLink struct { + ecore.Main + Simx_Id uint `json:"simx_id" gorm:"unique"` + Simgos_Id uint `json:"simgos_id" gorm:"unique"` +} + +type DivisionSimxLog struct { + ecore.Main + Value *string `json:"value"` + Date *time.Time `json:"date"` + Status erc.ProcessStatusCode `json:"status"` + ErrMessage *string `json:"errMessage"` +} + +type DivisionSimgosLog struct { + ecore.Main + Value *string `json:"value"` + Date *time.Time `json:"date"` + Status erc.ProcessStatusCode `json:"status"` + ErrMessage *string `json:"errMessage"` +} diff --git a/internal/domain/sync-entities/specialist/entity.go b/internal/domain/sync-entities/specialist/entity.go new file mode 100644 index 00000000..0eb8683c --- /dev/null +++ b/internal/domain/sync-entities/specialist/entity.go @@ -0,0 +1,29 @@ +package specialist + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + erc "simrs-vx/internal/domain/references/common" + "time" +) + +type SpecialistLink struct { + ecore.Main + Simx_Id uint `json:"simx_id" gorm:"unique"` + Simgos_Id uint `json:"simgos_id" gorm:"unique"` +} + +type SpecialistSimxLog struct { + ecore.Main + Value *string `json:"value"` + Date *time.Time `json:"date"` + Status erc.ProcessStatusCode `json:"status"` + ErrMessage *string `json:"errMessage"` +} + +type SpecialistSimgosLog struct { + ecore.Main + Value *string `json:"value"` + Date *time.Time `json:"date"` + Status erc.ProcessStatusCode `json:"status"` + ErrMessage *string `json:"errMessage"` +} diff --git a/internal/domain/sync-entities/subspecialist/entity.go b/internal/domain/sync-entities/subspecialist/entity.go new file mode 100644 index 00000000..76e16614 --- /dev/null +++ b/internal/domain/sync-entities/subspecialist/entity.go @@ -0,0 +1,29 @@ +package subspecialist + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + erc "simrs-vx/internal/domain/references/common" + "time" +) + +type SubspecialistLink struct { + ecore.Main + Simx_Id uint `json:"simx_id" gorm:"unique"` + Simgos_Id uint `json:"simgos_id" gorm:"unique"` +} + +type SubspecialistSimxLog struct { + ecore.Main + Value *string `json:"value"` + Date *time.Time `json:"date"` + Status erc.ProcessStatusCode `json:"status"` + ErrMessage *string `json:"errMessage"` +} + +type SubspecialistSimgosLog struct { + ecore.Main + Value *string `json:"value"` + Date *time.Time `json:"date"` + Status erc.ProcessStatusCode `json:"status"` + ErrMessage *string `json:"errMessage"` +} diff --git a/internal/interface/migration/migration.go b/internal/interface/migration/migration.go index 31ec1840..15341164 100644 --- a/internal/interface/migration/migration.go +++ b/internal/interface/migration/migration.go @@ -32,7 +32,7 @@ func getEntities(input string) []any { case "satusehat": return getSatuSehatEntities() case "simgossync": - return getSimgosSyncEntities() + return getSyncEntities() } return nil } diff --git a/internal/interface/migration/simgossync-entities.go b/internal/interface/migration/simgossync-entities.go index d48cf699..efc4cce9 100644 --- a/internal/interface/migration/simgossync-entities.go +++ b/internal/interface/migration/simgossync-entities.go @@ -2,11 +2,14 @@ package migration import ( /************** Source ***************/ + division "simrs-vx/internal/domain/sync-entities/division" installation "simrs-vx/internal/domain/sync-entities/installation" + specialist "simrs-vx/internal/domain/sync-entities/specialist" + subspecialist "simrs-vx/internal/domain/sync-entities/subspecialist" unit "simrs-vx/internal/domain/sync-entities/unit" ) -func getSimgosSyncEntities() []any { +func getSyncEntities() []any { return []any{ &installation.InstallationLink{}, &installation.InstallationSimxLog{}, @@ -14,5 +17,14 @@ func getSimgosSyncEntities() []any { &unit.UnitLink{}, &unit.UnitSimxLog{}, &unit.UnitSimgosLog{}, + &division.DivisionLink{}, + &division.DivisionSimxLog{}, + &division.DivisionSimgosLog{}, + &specialist.SpecialistLink{}, + &specialist.SpecialistSimxLog{}, + &specialist.SpecialistSimgosLog{}, + &subspecialist.SubspecialistLink{}, + &subspecialist.SubspecialistSimxLog{}, + &subspecialist.SubspecialistSimgosLog{}, } } From 34b79e6472a12dc31d8b8cce61849bdfea6043ab Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 17 Nov 2025 12:06:09 +0700 Subject: [PATCH 208/329] on going division --- .../simgos-sync-handler/division/handler.go | 66 ++++++ .../simgos-sync-handler.go | 20 +- .../simgos-sync-plugin/division/plugin.go | 153 +++++++++++++ .../simgos-sync-use-case/division/case.go | 214 ++++++++++++++++++ .../simgos-sync-use-case/division/helper.go | 58 +++++ .../simgos-sync-use-case/division/lib.go | 188 +++++++++++++++ .../division/middleware-runner.go | 104 +++++++++ .../division/middleware.go | 9 + .../simgos-sync-use-case/division/tycovar.go | 44 ++++ .../simgos-sync-use-case/installation/case.go | 5 +- .../installation/helper.go | 4 +- .../simgos-sync-use-case/installation/lib.go | 2 +- .../handler-crud-helper.go | 33 +++ pkg/handler-crud-helper/types.go | 7 + 14 files changed, 886 insertions(+), 21 deletions(-) create mode 100644 internal/interface/simgos-sync-handler/division/handler.go create mode 100644 internal/use-case/simgos-sync-plugin/division/plugin.go create mode 100644 internal/use-case/simgos-sync-use-case/division/case.go create mode 100644 internal/use-case/simgos-sync-use-case/division/helper.go create mode 100644 internal/use-case/simgos-sync-use-case/division/lib.go create mode 100644 internal/use-case/simgos-sync-use-case/division/middleware-runner.go create mode 100644 internal/use-case/simgos-sync-use-case/division/middleware.go create mode 100644 internal/use-case/simgos-sync-use-case/division/tycovar.go diff --git a/internal/interface/simgos-sync-handler/division/handler.go b/internal/interface/simgos-sync-handler/division/handler.go new file mode 100644 index 00000000..0f87ca8a --- /dev/null +++ b/internal/interface/simgos-sync-handler/division/handler.go @@ -0,0 +1,66 @@ +package division + +import ( + "net/http" + + rw "github.com/karincake/risoles" + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/division" + esync "simrs-vx/internal/domain/sync-entities/log" + u "simrs-vx/internal/use-case/simgos-sync-use-case/division" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + 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) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + + val := uint16(id) + dto.Id = &val + + 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{} + val := uint16(id) + dto.Id = &val + + res, err := u.Delete(dto) + 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 3b1908a9..590d7b9d 100644 --- a/internal/interface/simgos-sync-handler/simgos-sync-handler.go +++ b/internal/interface/simgos-sync-handler/simgos-sync-handler.go @@ -2,6 +2,7 @@ package simgossynchandler import ( "net/http" + hc "simrs-vx/pkg/handler-crud-helper" /******************** infra ********************/ gs "simrs-vx/internal/infra/gorm-setting" @@ -14,10 +15,9 @@ import ( /******************** external ********************/ a "github.com/karincake/apem" - hk "github.com/karincake/hongkue" - /******************** internal ********************/ "simrs-vx/internal/interface/main-handler/home" + division "simrs-vx/internal/interface/simgos-sync-handler/division" installation "simrs-vx/internal/interface/simgos-sync-handler/installation" unit "simrs-vx/internal/interface/simgos-sync-handler/unit" ) @@ -36,19 +36,9 @@ func SetRoutes() http.Handler { /******************** Source ******************/ prefix := "/new-to-old" - hk.GroupRoutes(prefix+"/v1/installation", r, hk.MapHandlerFunc{ - "POST /": installation.O.Create, - "POST /log": installation.O.CreateLog, - "PATCH /{id}": installation.O.Update, - "DELETE /{id}": installation.O.Delete, - }) - - hk.GroupRoutes(prefix+"/v1/unit", r, hk.MapHandlerFunc{ - "POST /": unit.O.Create, - "POST /log": unit.O.CreateLog, - "PATCH /{id}": unit.O.Update, - "DELETE /{id}": unit.O.Delete, - }) + hc.SyncCrud(r, prefix+"/v1/installation", installation.O) + hc.SyncCrud(r, prefix+"/v1/unit", unit.O) + hc.SyncCrud(r, prefix+"/v1/division", division.O) return cmw.SetCors(handlerlogger.SetLog(r)) } diff --git a/internal/use-case/simgos-sync-plugin/division/plugin.go b/internal/use-case/simgos-sync-plugin/division/plugin.go new file mode 100644 index 00000000..06e54e31 --- /dev/null +++ b/internal/use-case/simgos-sync-plugin/division/plugin.go @@ -0,0 +1,153 @@ +package division + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + + sync "simrs-vx/internal/infra/sync-cfg" + + e "simrs-vx/internal/domain/main-entities/unit" + elog "simrs-vx/internal/domain/sync-entities/log" +) + +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() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf(resp.Status) + } + + _, err = io.ReadAll(resp.Body) + if err != nil { + return err + } + + return nil +} + +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() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf(resp.Status) + } + + _, err = io.ReadAll(resp.Body) + if err != nil { + return err + } + + return nil +} + +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() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf(resp.Status) + } + + _, err = io.ReadAll(resp.Body) + if err != nil { + return err + } + + return nil +} + +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() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf(resp.Status) + } + + _, err = io.ReadAll(resp.Body) + if err != nil { + return err + } + + return nil +} + +func getPrefixEndpoint() string { + return fmt.Sprintf("%s%s/v1/division", sync.O.Host, sync.O.Prefix) +} diff --git a/internal/use-case/simgos-sync-use-case/division/case.go b/internal/use-case/simgos-sync-use-case/division/case.go new file mode 100644 index 00000000..074bf2a7 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/division/case.go @@ -0,0 +1,214 @@ +package division + +import ( + pl "simrs-vx/pkg/logger" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/division" + esync "simrs-vx/internal/domain/sync-entities/log" + //esimgos "simrs-vx/internal/domain/simgos-entities/installation" +) + +const source = "division" + +func Create(input e.CreateDto) (*d.Data, error) { + //var ( + // txSync = dg.I.Begin() + // txSimgos = dg.IS["simrs"].Begin() + //) + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + // STEP 1: Insert to simgos + //sgData, err := CreateSimgosData(input, &event, txSimgos) + //if err != nil { + // return nil, err + //} + // + //// STEP 2: Insert to Link + //syncLink, err := CreateLinkData(*input.Id, sgData.Kode, &event, txSync) + //if err != nil { + // txSimgos.Rollback() + // return nil, err + //} + // + //// STEP 3: Commit two trx + //if err = txSync.Commit().Error; err != nil { + // txSync.Rollback() + // txSimgos.Rollback() + // return nil, err + //} + // + //if err = txSimgos.Commit().Error; err != nil { + // // STEP 4: Rollback Partial + // 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 esync.SimxLogDto) (*d.Data, error) { + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + err := dg.I.Transaction(func(tx *gorm.DB) error { + // InsertSimxLog + if err := CreateLogData(input, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + 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.UpdateDto) (*d.Data, error) { + //var ( + // txSimgos = dg.IS["simrs"].Begin() + // err error + //) + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + //// STEP 1: Get Installation Link + //syncLink, err := ReadDetailLinkData(*input.Id, &event) + //if err != nil { + // return nil, err + //} + // + //// Step 2: Update Simgos + //err = UpdateSimgosData(input, syncLink, &event, txSimgos) + //if err != nil { + // return nil, err + //} + // + //// STEP 4: Commit two trx + //if err = txSimgos.Commit().Error; err != nil { + // txSimgos.Rollback() + // return nil, err + //} + + 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 ( + // txSync = dg.I.Begin() + // txSimgos = dg.IS["simrs"].Begin() + // sgData *esimgos.MPloy + // err error + //) + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + //// STEP 1: Get Installation Link + //syncLink, err := ReadDetailLinkData(*input.Id, &event) + //if err != nil { + // return nil, err + //} + // + //// STEP 2: Get Simgos + //sgData, err = ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) + //if err != nil { + // return nil, err + //} + // + //// STEP 3: Delete M_Poly Simgos + //err = HardDeleteSimgosData(sgData, &event, txSimgos) + //if err != nil { + // return nil, err + //} + // + //// STEP 4: Delete Installation Link + //err = DeleteLinkData(syncLink, &event, txSync) + //if err != nil { + // txSimgos.Rollback() + // return nil, err + //} + // + //// STEP 4: Commit two trx + //if err = txSync.Commit().Error; err != nil { + // txSync.Rollback() + // txSimgos.Rollback() + // return nil, err + //} + // + //if err = txSimgos.Commit().Error; err != nil { + // // STEP 5: Rollback Partial + // go func() { + // _, _ = CreateLinkData(uint(*input.Id), sgData.Kode, &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/division/helper.go b/internal/use-case/simgos-sync-use-case/division/helper.go new file mode 100644 index 00000000..210d6e7c --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/division/helper.go @@ -0,0 +1,58 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package division + +import ( + "encoding/json" + erc "simrs-vx/internal/domain/references/common" + + //e "simrs-vx/internal/domain/main-entities/division" + // esimgos "simrs-vx/internal/domain/simgos-entities/divison" TBC + esync "simrs-vx/internal/domain/sync-entities/division" + esyncLog "simrs-vx/internal/domain/sync-entities/log" +) + +//func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MPloy) { +// var inputSrc *e.CreateDto +// if inputT, ok := any(input).(*e.CreateDto); ok { +// inputSrc = inputT +// } else { +// inputTemp := any(input).(*e.UpdateDto) +// inputSrc = &inputTemp.CreateDto +// } +// +// data.Nama = inputSrc.Name +// data.Jenispoly = 0 +// +// return +//} + +func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.DivisionSimxLog) { + // 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.DivisionLink) { + data.Simx_Id = simxId + data.Simgos_Id = simgosId + return +} diff --git a/internal/use-case/simgos-sync-use-case/division/lib.go b/internal/use-case/simgos-sync-use-case/division/lib.go new file mode 100644 index 00000000..ce13068d --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/division/lib.go @@ -0,0 +1,188 @@ +package division + +import ( + 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/division" + esync "simrs-vx/internal/domain/sync-entities/division" + //esimgos "simrs-vx/internal/domain/simgos-entities/unit" + esynclog "simrs-vx/internal/domain/sync-entities/log" +) + +var now = time.Now() + +//func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esimgos.MPloy, error) { +// pl.SetLogInfo(event, nil, "started", "DBCreate") +// +// data := setDataSimgos(&input) +// +// 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 ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.MPloy, error) { +// pl.SetLogInfo(event, simgosId, "started", "DBReadDetail") +// data := esimgos.MPloy{} +// +// var tx = dg.IS["simrs"] +// +// if err := tx. +// Where("\"kode\" = ?", 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 UpdateSimgosData(input e.UpdateDto, dataSimgos *esync.DivisionLink, event *pl.Event, dbx ...*gorm.DB) error { +// pl.SetLogInfo(event, input, "started", "DBUpdate") +// +// data := setDataSimgos(&input) +// data.Kode = dataSimgos.Simgos_Id +// +// 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 HardDeleteSimgosData(data *esimgos.MPloy, 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 CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.DivisionLink, 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 uint16, event *pl.Event) (*esync.DivisionLink, error) { + pl.SetLogInfo(event, simxId, "started", "DBReadDetail") + data := esync.DivisionLink{} + + 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.DivisionLink, 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/division/middleware-runner.go b/internal/use-case/simgos-sync-use-case/division/middleware-runner.go new file mode 100644 index 00000000..dad68114 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/division/middleware-runner.go @@ -0,0 +1,104 @@ +package division + +import ( + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/division" +) + +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.Division) 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.Division) 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.Division) 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.Division) 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.Division) 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/division/middleware.go b/internal/use-case/simgos-sync-use-case/division/middleware.go new file mode 100644 index 00000000..f066ffb8 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/division/middleware.go @@ -0,0 +1,9 @@ +package division + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/simgos-sync-use-case/division/tycovar.go b/internal/use-case/simgos-sync-use-case/division/tycovar.go new file mode 100644 index 00000000..c7733117 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/division/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 division + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/division" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.Division, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Division, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Division, 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/installation/case.go b/internal/use-case/simgos-sync-use-case/installation/case.go index 755c65d3..c920fca1 100644 --- a/internal/use-case/simgos-sync-use-case/installation/case.go +++ b/internal/use-case/simgos-sync-use-case/installation/case.go @@ -1,9 +1,6 @@ package installation import ( - esimgos "simrs-vx/internal/domain/simgos-entities/installation" - esync "simrs-vx/internal/domain/sync-entities/log" - dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -12,6 +9,8 @@ import ( "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/installation" + esimgos "simrs-vx/internal/domain/simgos-entities/installation" + esync "simrs-vx/internal/domain/sync-entities/log" ) const source = "installation" diff --git a/internal/use-case/simgos-sync-use-case/installation/helper.go b/internal/use-case/simgos-sync-use-case/installation/helper.go index 51316d79..aa33ef4b 100644 --- a/internal/use-case/simgos-sync-use-case/installation/helper.go +++ b/internal/use-case/simgos-sync-use-case/installation/helper.go @@ -10,7 +10,7 @@ import ( erc "simrs-vx/internal/domain/references/common" esimgos "simrs-vx/internal/domain/simgos-entities/installation" esync "simrs-vx/internal/domain/sync-entities/installation" - "simrs-vx/internal/domain/sync-entities/log" + esyncLog "simrs-vx/internal/domain/sync-entities/log" ) func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MInstalasi) { @@ -29,7 +29,7 @@ func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MInstal return } -func setDataSimxLog(input *log.SimxLogDto) (data esync.InstallationSimxLog) { +func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.InstallationSimxLog) { // encode to JSON jsonData, _ := json.MarshalIndent(input.Payload, "", " ") jsonString := string(jsonData) diff --git a/internal/use-case/simgos-sync-use-case/installation/lib.go b/internal/use-case/simgos-sync-use-case/installation/lib.go index 77140553..9b057ece 100644 --- a/internal/use-case/simgos-sync-use-case/installation/lib.go +++ b/internal/use-case/simgos-sync-use-case/installation/lib.go @@ -1,7 +1,6 @@ package installation import ( - esynclog "simrs-vx/internal/domain/sync-entities/log" plh "simrs-vx/pkg/lib-helper" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -13,6 +12,7 @@ import ( e "simrs-vx/internal/domain/main-entities/installation" esimgos "simrs-vx/internal/domain/simgos-entities/installation" esync "simrs-vx/internal/domain/sync-entities/installation" + esynclog "simrs-vx/internal/domain/sync-entities/log" ) var now = time.Now() diff --git a/pkg/handler-crud-helper/handler-crud-helper.go b/pkg/handler-crud-helper/handler-crud-helper.go index df475094..3003e812 100644 --- a/pkg/handler-crud-helper/handler-crud-helper.go +++ b/pkg/handler-crud-helper/handler-crud-helper.go @@ -74,3 +74,36 @@ func RegCrudByCode(r *http.ServeMux, path string, mwAndRouter ...any) { "DELETE /{code}": c.Delete, }) } + +func SyncCrud(r *http.ServeMux, path string, mwAndRouter ...any) { + sLength := len(mwAndRouter) + + mwCandidates := mwAndRouter[:sLength-1] + mwList := []hk.HandlerMw{} + for i := range mwCandidates { + // have to do it manually, since casting directly results unexpected result + myType := reflect.TypeOf(mwCandidates[i]) + if myType.String() != "func(http.Handler) http.Handler" { + panic("non middleware included as middleware") + } + mwList = append(mwList, mwCandidates[i].(func(http.Handler) http.Handler)) + + // if g, okHandler := mwCandidates[i].(func(http.Handler) http.Handler); !okHandler { + // panic("non middleware included") + // } else { + // mwList = append(mwList, g) + // } + } + + c, ok := mwAndRouter[sLength-1].(SyncCrudBase) + if !ok { + panic("non CrudBase used in the last paramter") + } + + hk.GroupRoutes(path, r, mwList, hk.MapHandlerFunc{ + "POST /": c.Create, + "POST /log": c.CreateLog, + "PATCH /{id}": c.Update, + "DELETE /{id}": c.Delete, + }) +} diff --git a/pkg/handler-crud-helper/types.go b/pkg/handler-crud-helper/types.go index e85f22fc..891af38e 100644 --- a/pkg/handler-crud-helper/types.go +++ b/pkg/handler-crud-helper/types.go @@ -9,3 +9,10 @@ type CrudBase interface { Update(w http.ResponseWriter, r *http.Request) Delete(w http.ResponseWriter, r *http.Request) } + +type SyncCrudBase interface { + Create(w http.ResponseWriter, r *http.Request) + CreateLog(w http.ResponseWriter, r *http.Request) + Update(w http.ResponseWriter, r *http.Request) + Delete(w http.ResponseWriter, r *http.Request) +} From 9cf28432491b7089b91a96584b20ccd71eae132e Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 17 Nov 2025 14:33:49 +0700 Subject: [PATCH 209/329] add general consent template --- assets/docs/general-consent.html | 273 +++++++++++++++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 assets/docs/general-consent.html diff --git a/assets/docs/general-consent.html b/assets/docs/general-consent.html new file mode 100644 index 00000000..e311cb54 --- /dev/null +++ b/assets/docs/general-consent.html @@ -0,0 +1,273 @@ + + + + General Consent + + + + + + + + +
+ logo + +
+ PEMERINTAH PROVINSI JAWA TIMUR +
+
+ RUMAH SAKIT UMUM DAERAH Dr. SAIFUL ANWAR +
+
+ TERAKREDITASI KARS VERSI 2012 TINGKAT PARIPURNA +
+
+ Jl. Jaksa Agung Suprapto No. 2 MALANG 65111 +
+
Telp. (0341) 362101, Fax. (0341) 362110
+
Email: rsu-drsaifulanwar@jatimprov.go.id
+
Website: www.rsudsaifulanwar.jatimprov.go.id
+
+ logo +
+ +
+ +
+ FORMULIR PEMBERIAN INFORMASI DAN PERSETUJUAN UMUM +
+
+ (GENERAL CONSENT) +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1. + Hak dan Kewajiban sebagai pasien : + Dengan menandatangani dokumen ini saya mengakui bahwa pada proses + pendaftaran untuk mendapatkan perawatan di RSUD Dr. Saiful Anwar telah + mendapatkan informasi tentang hak dan kewajiban saya sebagai pasien + (melalui leaflet/banner dan atau petugas). Saya berhak mendapatkan + pelayanan kesehatan sesuai standar, mendapatkan informasi yang cukup + tentang keadaan kesehatan, rencana tindakan, manfaat, risiko, + alternatif tindakan, serta biaya yang akan timbul. Saya berkewajiban + memberikan informasi kesehatan yang jujur dan lengkap kepada tenaga + kesehatan, mematuhi aturan rumah sakit, serta memenuhi kewajiban + pembayaran sesuai ketentuan yang berlaku. +
2. + Persetujuan Pelayanan : + Saya menyetujui dan memberikan persetujuan untuk dirawat di RSUD Dr. + Saiful Anwar dan dengan ini saya meminta dan memberikan kuasa kepada + RSUD Dr. Saiful Anwar, dokter dan perawat serta tenaga kesehatan + lainnya untuk memberikan asuhan keperawatan, pemeriksaan fisik yang + dilakukan oleh dokter dan perawat dan melakukan prosedur diagnostik + radiologi dan/atau terapi dan tata laksana sesuai pertimbangan dokter + yang diperlukan atau disarankan pada perawatan saya. Hal ini mencakup + seluruh pemeriksaan dan prosedur diagnostik rutin termasuk X-ray, + pemberian dan/atau tindakan medis serta penyuntikan (intramuskular, + intravena dan prosedur invasif lainnya), produk farmasi dan + obat-obatan, pemasangan alat kesehatan (kecuali yang membutuhkan + persetujuan khusus/tertulis) dan pengambilan darah untuk pemeriksaan + laboratorium atau pemeriksaan patologi. +
3. + Akses Informasi Kesehatan : + Saya memberi kuasa kepada setiap dan seluruh orang yang merawat saya + untuk memeriksa dan/atau memberitahukan informasi kesehatan saya + kepada pemberi kesehatan lain yang turut merawat saya selama di rumah + sakit ini, sesuai kebutuhan pelayanan. +
4. + Rahasia Kedokteran : + Saya setuju RSUD Dr. Saiful Anwar Malang wajib menjamin kerahasiaan + informasi medis saya baik untuk kepentingan perawatan dan pengobatan, + pendidikan maupun penelitian, sesuai ketentuan yang berlaku. +
5. + Membuka Rahasia Kedokteran : + Saya setuju untuk membuka rahasia kedokteran terkait dengan kondisi + kesehatan, asuhan dan pengobatan yang saya terima kepada: +
a) Dokter dan tenaga kesehatan lain yang turut merawat/memberikan + asuhan kepada saya; +
b) Perusahaan asuransi kesehatan atau perusahaan lainnya atau pihak + lain yang menjamin pembiayaan saya; +
c) Anggota keluarga saya : + .......................................... +
Saya memahami bahwa pembukaan rahasia ini hanya sejauh yang + diperlukan untuk tujuan perawatan, pembiayaan atau administrasi yang + terkait. +
6. + Privasi : + Saya memberi kuasa kepada RSUD Dr. Saiful Anwar Malang untuk menjaga + privasi dan kerahasiaan penyakit saya selama dalam perawatan, serta + membatasi akses terhadap informasi yang tidak berkepentingan. +
7. + Barang Pribadi : + Saya setuju untuk tidak membawa barang-barang berharga yang tidak + diperlukan (seperti perhiasan, elektronik, dll) selama dalam perawatan + di RSUD Dr. Saiful Anwar. Jika saya tetap membawa dan terjadi + kehilangan, kerusakan atau pencurian, maka RSUD Dr. Saiful Anwar tidak + bertanggung jawab atas hal tersebut, kecuali bila ada perjanjian + tertulis yang menyatakan lain. +
8. + Pengajuan Keluhan : + Saya menyatakan bahwa saya telah menerima informasi tentang adanya + tata cara mengajukan dan mengatasi keluhan terkait pelayanan medik + yang diberikan terhadap diri saya. Saya setuju untuk mengikuti tata + cara pengajuan keluhan sesuai prosedur yang ada di rumah sakit. +
9. + Kewajiban Pembayaran : + Saya menyatakan setuju, baik sebagai wali ataupun sebagai pasien, + bahwa sesuai pertimbangan pelayanan yang diberikan kepada pasien, maka + saya wajib untuk membayar total biaya pelayanan sesuai acuan biaya dan + ketentuan RSUD Dr. Saiful Anwar Malang dengan jaminan atau pribadi. + Apabila asuransi kesehatan swasta atau program pemerintah menanggung + pembiayaan saya, saya memberi wewenang kepada rumah sakit untuk + memberi tagihan dari semua pelayanan dan tindakan medis yang + diberikan. Tanggungan Asuransi saya mungkin menyatakan bahwa sebagian + pembayaran tetap menjadi tanggung jawab pribadi saya atau tidak + ditanggung oleh asuransi, maka rumah sakit berwenang memberi tagihan + untuk biaya yang tidak ditanggung oleh asuransi dan saya bertanggung + jawab untuk membayarnya. Apabila saya tidak memberikan persetujuan, + atau dikemudian hari mencabut persetujuan saya untuk melepaskan + rahasia kedokteran saya kepada perusahaan asuransi yang saya tentukan, + maka saya pribadi bertanggung jawab untuk membayar semua pelayanan dan + tindakan medis dari RSUD Dr. Saiful Anwar Malang. +
10. + Rumah Sakit Pendidikan : + Saya mengetahui bahwa RSUD Dr. Saiful Anwar merupakan rumah sakit + pendidikan yang menjadi tempat praktik klinik bagi mahasiswa + kedokteran dan profesi-profesi kesehatan lainnya, karena itu mereka + mungkin berpartisipasi dan atau terlibat dalam perawatan saya dan saya + menyetujui bahwa mereka berpartisipasi dalam perawatan saya sepanjang + di bawah supervisi dokter penanggung jawab pasien (DPJP). +
11. + Selama Dalam Perawatan : + Selama dalam perawatan saya dan keluarga saya akan mematuhi ketentuan + untuk tidak mengambil, menyimpan, mengedarkan gambar/video dokumen dan + aktivitas pelayanan selama di RS tanpa seizin rumah sakit. +
12. + Penegasan Kepercayaan : + Melalui dokumen ini, saya menegaskan kembali bahwa saya mempercayakan + kepada semua tenaga kesehatan rumah sakit untuk memberikan perawatan, + diagnostik dan terapi kepada saya sebagai pasien rawat inap atau rawat + jalan atau Instalasi Gawat Darurat (IGD), termasuk semua pemeriksaan + penunjang yang dibutuhkan untuk pengobatan dan tindakan yang + diperlukan. +
+ +

+ +
+ Saya menyetujui setiap pernyataan dalam formulir ini dan menandatangani + tanpa paksaan. +
+ + + + + +
+ Malang, ............................................................ +
+ + + + + + + + +
+ Pasien/Keluarga


.......................................
Nama + terang +
+ Pemberi Informasi


.......................................
Nama + terang +
+ Saksi I


.......................................
Nama + terang +
+ Saksi II


.......................................
Nama + terang +
+ + From ea681071357b7f9b76544231cb3cd4d49bc0c668 Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 17 Nov 2025 14:38:08 +0700 Subject: [PATCH 210/329] add division --- .../domain/simgos-entities/division/entity.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 internal/domain/simgos-entities/division/entity.go diff --git a/internal/domain/simgos-entities/division/entity.go b/internal/domain/simgos-entities/division/entity.go new file mode 100644 index 00000000..c10f5429 --- /dev/null +++ b/internal/domain/simgos-entities/division/entity.go @@ -0,0 +1,18 @@ +package division + +type MUnit struct { + KodeUnit uint `json:"kode_unit" gorm:"primaryKey;autoIncrement;column:kode_unit"` + NamaUnit string `json:"nama_unit" gorm:"column:nama_unit"` + GrupUnit uint `json:"grup_unit" gorm:"column:grup_unit"` + NamaGrupunit string `json:"nama_grupunit" gorm:"column:nama_grupunit"` + PendapatanUnit string `json:"pendapatan_unit" gorm:"column:pendapatan_unit"` + Smf string `json:"smf" gorm:"column:smf"` + HaveSubspecialis uint `json:"have_subspecialis" gorm:"column:have_subspecialis"` + KelSmfTarif string `json:"kel_smf_tarif" gorm:"column:kel_smf_tarif"` + IsPilihSatker uint `json:"is_pilih_satker" gorm:"column:is_pilih_satker"` + NamaTempatlayanan string `json:"nama_tempatlayanan" gorm:"column:nama_tempatlayanan"` +} + +func (MUnit) TableName() string { + return "m_unit" +} From 13ddfaab5f49f40944ead52b1f99d7cfd8885293 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 17 Nov 2025 14:49:34 +0700 Subject: [PATCH 211/329] rename and adjust upload code into doctypecode --- .../main-entities/encounter-document/dto.go | 32 ++++++++--------- .../encounter-document/entity.go | 14 ++++---- internal/domain/main-entities/patient/dto.go | 2 +- internal/domain/main-entities/upload/dto.go | 7 ++-- internal/domain/references/upload/upload.go | 35 ++++++++++--------- .../interface/main-handler/upload/handler.go | 2 +- .../use-case/main-use-case/upload/helper.go | 10 +++--- pkg/upload-helper/upload-helper.go | 14 ++++---- 8 files changed, 59 insertions(+), 57 deletions(-) diff --git a/internal/domain/main-entities/encounter-document/dto.go b/internal/domain/main-entities/encounter-document/dto.go index c1e0894c..4bc76994 100644 --- a/internal/domain/main-entities/encounter-document/dto.go +++ b/internal/domain/main-entities/encounter-document/dto.go @@ -9,12 +9,12 @@ import ( ) type CreateDto struct { - Encounter_Id *uint `json:"encounter_id"` - Type_Code eru.UploadCode `json:"type_code"` - Name string `json:"name"` - FilePath string `json:"filePath"` - Filename string `json:"-"` - Upload_Employee_Id *uint `form:"upload_employee_id"` + Encounter_Id *uint `json:"encounter_id"` + Type_Code eru.DocTypeCode `json:"type_code"` + Name string `json:"name"` + FilePath string `json:"filePath"` + Filename string `json:"-"` + Upload_Employee_Id *uint `form:"upload_employee_id"` } type ReadListDto struct { @@ -24,9 +24,9 @@ type ReadListDto struct { } type FilterDto struct { - Encounter_Id *uint `json:"encounter-id"` - Type_Code eru.UploadCode `json:"type-code"` - Upload_Employee_Id *string `json:"encounter-document-employee-id"` + Encounter_Id *uint `json:"encounter-id"` + Type_Code eru.DocTypeCode `json:"type-code"` + Upload_Employee_Id *string `json:"encounter-document-employee-id"` } type ReadDetailDto struct { @@ -51,13 +51,13 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Type_Code eru.UploadCode `json:"type_code"` - Name string `json:"name"` - FilePath *string `json:"filePath"` - FileName *string `json:"fileName"` - Upload_Employee_Id *uint `json:"upload_employee_id"` - Upload_Employee *ee.Employee `json:"upload_employee,omitempty"` + Encounter_Id *uint `json:"encounter_id"` + Type_Code eru.DocTypeCode `json:"type_code"` + Name string `json:"name"` + FilePath *string `json:"filePath"` + FileName *string `json:"fileName"` + Upload_Employee_Id *uint `json:"upload_employee_id"` + Upload_Employee *ee.Employee `json:"upload_employee,omitempty"` } func (d EncounterDocument) ToResponse() ResponseDto { diff --git a/internal/domain/main-entities/encounter-document/entity.go b/internal/domain/main-entities/encounter-document/entity.go index 6c98e1e2..b0b040fc 100644 --- a/internal/domain/main-entities/encounter-document/entity.go +++ b/internal/domain/main-entities/encounter-document/entity.go @@ -8,11 +8,11 @@ import ( type EncounterDocument struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Type_Code eru.UploadCode `json:"type_code"` - Name string `json:"name"` - FilePath *string `json:"filePath"` - FileName *string `json:"fileName"` - Upload_Employee_Id *uint `json:"upload_employee_id"` - Upload_Employee *ee.Employee `json:"upload_employee,omitempty" gorm:"foreignKey:Upload_Employee_Id;references:Id"` + Encounter_Id *uint `json:"encounter_id"` + Type_Code eru.DocTypeCode `json:"type_code"` + Name string `json:"name"` + FilePath *string `json:"filePath"` + FileName *string `json:"fileName"` + Upload_Employee_Id *uint `json:"upload_employee_id"` + Upload_Employee *ee.Employee `json:"upload_employee,omitempty" gorm:"foreignKey:Upload_Employee_Id;references:Id"` } diff --git a/internal/domain/main-entities/patient/dto.go b/internal/domain/main-entities/patient/dto.go index dd6c1f00..ec270abf 100644 --- a/internal/domain/main-entities/patient/dto.go +++ b/internal/domain/main-entities/patient/dto.go @@ -68,7 +68,7 @@ type SearchDto struct { type UploadDto struct { Id uint `json:"-"` - Code eru.UploadCode `json:"-"` + Code eru.DocTypeCode `json:"-"` File multipart.File `json:"-"` FileHeader *multipart.FileHeader `json:"-"` Filename string `json:"-"` diff --git a/internal/domain/main-entities/upload/dto.go b/internal/domain/main-entities/upload/dto.go index ca8e101b..445b1402 100644 --- a/internal/domain/main-entities/upload/dto.go +++ b/internal/domain/main-entities/upload/dto.go @@ -3,6 +3,7 @@ package upload import ( "mime/multipart" eru "simrs-vx/internal/domain/references/upload" + // internal - domain - base-entities ecore "simrs-vx/internal/domain/base-entities/core" ) @@ -10,7 +11,7 @@ import ( type CreateDto struct { EntityType_Code eru.EntityTypeCode `form:"entityType_code"` Ref_Id *uint `form:"ref_id"` - Type_Code eru.UploadCode `form:"type_code"` + Type_Code eru.DocTypeCode `form:"type_code"` Name string `form:"name"` Upload_Employee_Id *uint `form:"upload_employee_id"` FilePath string `json:"-"` @@ -31,7 +32,7 @@ type ReadListDto struct { type FilterDto struct { EntityType_Code eru.EntityTypeCode `json:"entityType-code"` Ref_Id *uint `json:"ref-id"` - Type_Code eru.UploadCode `json:"type-code"` + Type_Code eru.DocTypeCode `json:"type-code"` Name string `json:"name"` FilePath *string `json:"filePath"` FileName *string `json:"fileName"` @@ -61,7 +62,7 @@ type MetaDto struct { type ResponseDto struct { EntityType_Code eru.EntityTypeCode `json:"entityType_code"` Ref_Id *uint `json:"ref_id"` - Type_Code eru.UploadCode `json:"type_code"` + Type_Code eru.DocTypeCode `json:"type_code"` Name string `json:"name"` Upload_Employee_Id *uint `json:"upload_employee_id"` FilePath string `json:"filePath"` diff --git a/internal/domain/references/upload/upload.go b/internal/domain/references/upload/upload.go index b22960f4..0817e23c 100644 --- a/internal/domain/references/upload/upload.go +++ b/internal/domain/references/upload/upload.go @@ -3,40 +3,41 @@ package upload import "fmt" type ( - UploadCode string + DocTypeCode string EntityTypeCode string ) const ( - UCPRN UploadCode = "person-resident-number" // Person Resident Number - UCPDL UploadCode = "person-driver-license" // Person Driver License - UCPP UploadCode = "person-passport" // Person Passport - UCPFC UploadCode = "person-family-card" // Person Family Card - UCMIR UploadCode = "mcu-item-result" // Mcu Item Result - UCEnPatient UploadCode = "encounter-patient" - UCEnSupport UploadCode = "encounter-support" - UcEnOther UploadCode = "encounter-other" - UCSEP UploadCode = "vclaim-sep" // SEP - UCSIPP UploadCode = "vclaim-sipp" // SIPP + DTCPRN DocTypeCode = "person-resident-number" // Person Resident Number + DTCPDL DocTypeCode = "person-driver-license" // Person Driver License + DTCPP DocTypeCode = "person-passport" // Person Passport + DTCPFC DocTypeCode = "person-family-card" // Person Family Card + DTCMIR DocTypeCode = "mcu-item-result" // Mcu Item Result + DTCEnPatient DocTypeCode = "encounter-patient" + DTCEnSupport DocTypeCode = "encounter-support" + DTCEnOther DocTypeCode = "encounter-other" + DTCSEP DocTypeCode = "vclaim-sep" // SEP + DTCSIPP DocTypeCode = "vclaim-sipp" // SIPP + DTCGC DocTypeCode = "general-consent" ETCPerson EntityTypeCode = "person" ETCEncounter EntityTypeCode = "encounter" ETCMCU EntityTypeCode = "mcu" ) -var validUploadCodesByEntity = map[EntityTypeCode][]UploadCode{ +var validUploadCodesByEntity = map[EntityTypeCode][]DocTypeCode{ ETCPerson: { - UCPRN, UCPDL, UCPP, UCPFC, + DTCPRN, DTCPDL, DTCPP, DTCPFC, }, ETCEncounter: { - UCSEP, UCSIPP, UCEnPatient, UCEnSupport, UcEnOther, + DTCSEP, DTCSIPP, DTCEnPatient, DTCEnSupport, DTCEnOther, }, ETCMCU: { - UCMIR, + DTCMIR, }, } -func IsValidUploadCode(entity EntityTypeCode, code UploadCode) (bool, string) { +func IsValidUploadCode(entity EntityTypeCode, code DocTypeCode) (bool, string) { allowedCodes, ok := validUploadCodesByEntity[entity] if !ok { return false, fmt.Sprintf("unknown entityType_code: %s", entity) @@ -48,5 +49,5 @@ func IsValidUploadCode(entity EntityTypeCode, code UploadCode) (bool, string) { } } - return false, fmt.Sprintf("invalid upload_code '%s' for entityType_code '%s'", code, entity) + return false, fmt.Sprintf("invalid doctype_code '%s' for entityType_code '%s'", code, entity) } diff --git a/internal/interface/main-handler/upload/handler.go b/internal/interface/main-handler/upload/handler.go index 72a71fbf..8a09c9ae 100644 --- a/internal/interface/main-handler/upload/handler.go +++ b/internal/interface/main-handler/upload/handler.go @@ -52,7 +52,7 @@ func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { dto := e.CreateDto{ EntityType_Code: eru.EntityTypeCode(r.FormValue("entityType_code")), Ref_Id: refID, - Type_Code: eru.UploadCode(r.FormValue("type_code")), + Type_Code: eru.DocTypeCode(r.FormValue("type_code")), Name: r.FormValue("name"), Upload_Employee_Id: employeeId, File: file, diff --git a/internal/use-case/main-use-case/upload/helper.go b/internal/use-case/main-use-case/upload/helper.go index e9e0ff29..1880676f 100644 --- a/internal/use-case/main-use-case/upload/helper.go +++ b/internal/use-case/main-use-case/upload/helper.go @@ -106,22 +106,22 @@ func setPersonAttachment(input e.CreateDto, event *pl.Event, tx *gorm.DB) (*ep.P var removeUrl string switch input.Type_Code { - case eru.UCPRN: + case eru.DTCPRN: if dataPerson.ResidentIdentityFileUrl != nil { removeUrl = *dataPerson.ResidentIdentityFileUrl } dataPerson.ResidentIdentityFileUrl = &input.FilePath - case eru.UCPDL: + case eru.DTCPDL: if dataPerson.DrivingLicenseFileUrl != nil { removeUrl = *dataPerson.DrivingLicenseFileUrl } dataPerson.DrivingLicenseFileUrl = &input.FilePath - case eru.UCPP: + case eru.DTCPP: if dataPerson.PassportFileUrl != nil { removeUrl = *dataPerson.PassportFileUrl } dataPerson.PassportFileUrl = &input.FilePath - case eru.UCPFC: + case eru.DTCPFC: if dataPerson.FamilyIdentityFileUrl != nil { removeUrl = *dataPerson.FamilyIdentityFileUrl } @@ -164,7 +164,7 @@ func setEncounterDocument(input e.CreateDto, event *pl.Event, tx *gorm.DB) (*ee. Upload_Employee_Id: input.Upload_Employee_Id, } - if input.Type_Code == eru.UCSEP || input.Type_Code == eru.UCSIPP { + if input.Type_Code == eru.DTCSEP || input.Type_Code == eru.DTCSIPP { if len(dataUpload) > 0 { data = dataUpload[0] diff --git a/pkg/upload-helper/upload-helper.go b/pkg/upload-helper/upload-helper.go index d6f1cd29..85f5448f 100644 --- a/pkg/upload-helper/upload-helper.go +++ b/pkg/upload-helper/upload-helper.go @@ -11,15 +11,15 @@ import ( func getBucketForType(docType string) (string, error) { switch strings.ToLower(docType) { case "resident", "resident-number", "ktp": - return string(ere.UCPRN), nil + return string(ere.DTCPRN), nil case "driver-license", "sim", "license": - return string(ere.UCPDL), nil + return string(ere.DTCPDL), nil case "passport", "paspor": - return string(ere.UCPP), nil + return string(ere.DTCPP), nil case "family-card", "kk", "family": - return string(ere.UCPFC), nil + return string(ere.DTCPFC), nil case "mcu", "medical", "mcu-result": - return string(ere.UCMIR), nil + return string(ere.DTCMIR), nil default: return "", fmt.Errorf("unknown document type: %s", docType) } @@ -28,9 +28,9 @@ func getBucketForType(docType string) (string, error) { // getValidFileTypesForBucket returns allowed file types for each bucket func getValidFileTypesForBucket(bucketName string) []string { switch bucketName { - case string(ere.UCPRN), string(ere.UCPDL), string(ere.UCPP), string(ere.UCPFC): + case string(ere.DTCPRN), string(ere.DTCPDL), string(ere.DTCPP), string(ere.DTCPFC): return []string{".jpg", ".jpeg", ".png", ".pdf", ".gif"} - case string(ere.UCMIR): + case string(ere.DTCMIR): return []string{".jpg", ".jpeg", ".png", ".pdf", ".gif", ".doc", ".docx", ".xls", ".xlsx"} default: return []string{".jpg", ".jpeg", ".png", ".pdf"} From 0bec4c3095c62f0f191e7e364f8799ae7ae6bf2d Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 17 Nov 2025 14:55:10 +0700 Subject: [PATCH 212/329] add fileUrl into general-consent --- cmd/main-migration/migrations/20251117075427.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 5 +++-- internal/domain/main-entities/general-consent/entity.go | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 cmd/main-migration/migrations/20251117075427.sql diff --git a/cmd/main-migration/migrations/20251117075427.sql b/cmd/main-migration/migrations/20251117075427.sql new file mode 100644 index 00000000..a6e0599b --- /dev/null +++ b/cmd/main-migration/migrations/20251117075427.sql @@ -0,0 +1,2 @@ +-- Modify "GeneralConsent" table +ALTER TABLE "public"."GeneralConsent" ADD COLUMN "FileUrl" character varying(1024) NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index a6e1b68c..94a7b195 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:fNeqUpbdIqGDiH68u1bwwMgHTEOmmEWeI+IIYEq6pto= +h1:2JitBq/ClDO+w/9iPRmvv946fDfbSDFoHbpHL20aqNI= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -118,4 +118,5 @@ h1:fNeqUpbdIqGDiH68u1bwwMgHTEOmmEWeI+IIYEq6pto= 20251113101344.sql h1:xaOZvAUP1fFfnO+syEFOzJUIg5lTfBe5AWHPbBWuCLA= 20251113120533.sql h1:f3/U1Ve2yF2zSMhkt+xtwF8wUYfUKYwgbNeGfE37EW4= 20251114062746.sql h1:FInLaEFQByESEwFJKuKnuUSTKmcDpi3ZXaxkKwz2+D8= -20251117005942.sql h1:mW/TC8GgFgPLZ7PBVQnn9mChEekAcwfQMCbzXnoaw9w= +20251117005942.sql h1:wD3BWrUSmo1HlW16V3lkaBkJvbAZ0fNk77te7J9NhOc= +20251117075427.sql h1:/PZovLaMdWILT6y1uNuBo9EyMHyxp3vQ7BwndRpQriY= diff --git a/internal/domain/main-entities/general-consent/entity.go b/internal/domain/main-entities/general-consent/entity.go index 96758406..f5ce6394 100644 --- a/internal/domain/main-entities/general-consent/entity.go +++ b/internal/domain/main-entities/general-consent/entity.go @@ -10,4 +10,5 @@ type GeneralConsent struct { Encounter_Id *uint `json:"encounter_id" gorm:"not null"` Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Value *string `json:"value"` + FileUrl *string `json:"fileUrl" gorm:"size:1024"` } From 05f54e4e341b285fcf3c1416ea73f4fdeb1c7c84 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 17 Nov 2025 15:20:24 +0700 Subject: [PATCH 213/329] refactor (upload-file) --- .../main-entities/encounter-document/dto.go | 8 +- .../encounter-document/entity.go | 4 +- internal/domain/main-entities/patient/dto.go | 4 +- .../domain/references/encounter/encounter.go | 47 ++++++++ internal/domain/references/upload/upload.go | 53 --------- .../interface/main-handler/main-handler.go | 4 +- .../{upload => upload-file}/handler.go | 13 +-- .../validate-request.go | 6 +- .../main-use-case/encounter-document/case.go | 4 +- .../main-use-case/upload-file/case.go | 76 +++++++++++++ .../{upload => upload-file}/helper.go | 21 ++-- .../main-use-case/upload-file/tycovar.go} | 59 +++------- .../use-case/main-use-case/upload/case.go | 90 --------------- .../main-use-case/upload/middleware-runner.go | 104 ------------------ .../main-use-case/upload/middleware.go | 9 -- .../use-case/main-use-case/upload/tycovar.go | 44 -------- pkg/upload-helper/upload-helper.go | 2 +- 17 files changed, 169 insertions(+), 379 deletions(-) delete mode 100644 internal/domain/references/upload/upload.go rename internal/interface/main-handler/{upload => upload-file}/handler.go (84%) rename internal/interface/main-handler/{upload => upload-file}/validate-request.go (64%) create mode 100644 internal/use-case/main-use-case/upload-file/case.go rename internal/use-case/main-use-case/{upload => upload-file}/helper.go (89%) rename internal/{domain/main-entities/upload/dto.go => use-case/main-use-case/upload-file/tycovar.go} (53%) delete mode 100644 internal/use-case/main-use-case/upload/case.go delete mode 100644 internal/use-case/main-use-case/upload/middleware-runner.go delete mode 100644 internal/use-case/main-use-case/upload/middleware.go delete mode 100644 internal/use-case/main-use-case/upload/tycovar.go diff --git a/internal/domain/main-entities/encounter-document/dto.go b/internal/domain/main-entities/encounter-document/dto.go index 4bc76994..6381413b 100644 --- a/internal/domain/main-entities/encounter-document/dto.go +++ b/internal/domain/main-entities/encounter-document/dto.go @@ -1,7 +1,7 @@ package encounter_document import ( - eru "simrs-vx/internal/domain/references/upload" + ere "simrs-vx/internal/domain/references/encounter" // internal - domain - base-entities ecore "simrs-vx/internal/domain/base-entities/core" @@ -10,7 +10,7 @@ import ( type CreateDto struct { Encounter_Id *uint `json:"encounter_id"` - Type_Code eru.DocTypeCode `json:"type_code"` + Type_Code ere.DocTypeCode `json:"type_code"` Name string `json:"name"` FilePath string `json:"filePath"` Filename string `json:"-"` @@ -25,7 +25,7 @@ type ReadListDto struct { type FilterDto struct { Encounter_Id *uint `json:"encounter-id"` - Type_Code eru.DocTypeCode `json:"type-code"` + Type_Code ere.DocTypeCode `json:"type-code"` Upload_Employee_Id *string `json:"encounter-document-employee-id"` } @@ -52,7 +52,7 @@ type MetaDto struct { type ResponseDto struct { ecore.Main Encounter_Id *uint `json:"encounter_id"` - Type_Code eru.DocTypeCode `json:"type_code"` + Type_Code ere.DocTypeCode `json:"type_code"` Name string `json:"name"` FilePath *string `json:"filePath"` FileName *string `json:"fileName"` diff --git a/internal/domain/main-entities/encounter-document/entity.go b/internal/domain/main-entities/encounter-document/entity.go index b0b040fc..61152eb4 100644 --- a/internal/domain/main-entities/encounter-document/entity.go +++ b/internal/domain/main-entities/encounter-document/entity.go @@ -3,13 +3,13 @@ package encounter_document import ( ecore "simrs-vx/internal/domain/base-entities/core" ee "simrs-vx/internal/domain/main-entities/employee" - eru "simrs-vx/internal/domain/references/upload" + ere "simrs-vx/internal/domain/references/encounter" ) type EncounterDocument struct { ecore.Main Encounter_Id *uint `json:"encounter_id"` - Type_Code eru.DocTypeCode `json:"type_code"` + Type_Code ere.DocTypeCode `json:"type_code"` Name string `json:"name"` FilePath *string `json:"filePath"` FileName *string `json:"fileName"` diff --git a/internal/domain/main-entities/patient/dto.go b/internal/domain/main-entities/patient/dto.go index ec270abf..ae387895 100644 --- a/internal/domain/main-entities/patient/dto.go +++ b/internal/domain/main-entities/patient/dto.go @@ -12,7 +12,7 @@ import ( epr "simrs-vx/internal/domain/main-entities/person-relative" erc "simrs-vx/internal/domain/references/common" - eru "simrs-vx/internal/domain/references/upload" + ere "simrs-vx/internal/domain/references/encounter" pa "simrs-vx/internal/lib/auth" ) @@ -68,7 +68,7 @@ type SearchDto struct { type UploadDto struct { Id uint `json:"-"` - Code eru.DocTypeCode `json:"-"` + Code ere.DocTypeCode `json:"-"` File multipart.File `json:"-"` FileHeader *multipart.FileHeader `json:"-"` Filename string `json:"-"` diff --git a/internal/domain/references/encounter/encounter.go b/internal/domain/references/encounter/encounter.go index dc3dd09e..532e1625 100644 --- a/internal/domain/references/encounter/encounter.go +++ b/internal/domain/references/encounter/encounter.go @@ -1,5 +1,7 @@ package encounter +import "fmt" + type ( EncounterClassCode string QueueStatusCode string @@ -18,6 +20,8 @@ type ( SEPRefTypeCode string VisitModeCode string PolySwitchCode string + DocTypeCode string + EntityTypeCode string ) const ( @@ -104,6 +108,22 @@ const ( PSCConsulPoly PolySwitchCode = "consul-poly" // Konsultasi Poliklinik Lain PSCConsulExecutive PolySwitchCode = "consul-executive" // Konsultasi Antar Dokter Eksekutif + + DTCPRN DocTypeCode = "person-resident-number" // Person Resident Number + DTCPDL DocTypeCode = "person-driver-license" // Person Driver License + DTCPP DocTypeCode = "person-passport" // Person Passport + DTCPFC DocTypeCode = "person-family-card" // Person Family Card + DTCMIR DocTypeCode = "mcu-item-result" // Mcu Item Result + DTCEnPatient DocTypeCode = "encounter-patient" + DTCEnSupport DocTypeCode = "encounter-support" + DTCEnOther DocTypeCode = "encounter-other" + DTCSEP DocTypeCode = "vclaim-sep" // SEP + DTCSIPP DocTypeCode = "vclaim-sipp" // SIPP + DTCGC DocTypeCode = "general-consent" + + ETCPerson EntityTypeCode = "person" + ETCEncounter EntityTypeCode = "encounter" + ETCMCU EntityTypeCode = "mcu" ) func (ec EncounterClassCode) Code() string { @@ -118,3 +138,30 @@ func (ec EncounterClassCode) Code() string { return "UNKNOWN" } } + +var validUploadCodesByEntity = map[EntityTypeCode][]DocTypeCode{ + ETCPerson: { + DTCPRN, DTCPDL, DTCPP, DTCPFC, + }, + ETCEncounter: { + DTCSEP, DTCSIPP, DTCEnPatient, DTCEnSupport, DTCGC, DTCEnOther, + }, + ETCMCU: { + DTCMIR, + }, +} + +func IsValidUploadCode(entity EntityTypeCode, code DocTypeCode) (bool, string) { + allowedCodes, ok := validUploadCodesByEntity[entity] + if !ok { + return false, fmt.Sprintf("unknown entityType_code: %s", entity) + } + + for _, c := range allowedCodes { + if c == code { + return true, "" + } + } + + return false, fmt.Sprintf("invalid doctype_code '%s' for entityType_code '%s'", code, entity) +} diff --git a/internal/domain/references/upload/upload.go b/internal/domain/references/upload/upload.go deleted file mode 100644 index 0817e23c..00000000 --- a/internal/domain/references/upload/upload.go +++ /dev/null @@ -1,53 +0,0 @@ -package upload - -import "fmt" - -type ( - DocTypeCode string - EntityTypeCode string -) - -const ( - DTCPRN DocTypeCode = "person-resident-number" // Person Resident Number - DTCPDL DocTypeCode = "person-driver-license" // Person Driver License - DTCPP DocTypeCode = "person-passport" // Person Passport - DTCPFC DocTypeCode = "person-family-card" // Person Family Card - DTCMIR DocTypeCode = "mcu-item-result" // Mcu Item Result - DTCEnPatient DocTypeCode = "encounter-patient" - DTCEnSupport DocTypeCode = "encounter-support" - DTCEnOther DocTypeCode = "encounter-other" - DTCSEP DocTypeCode = "vclaim-sep" // SEP - DTCSIPP DocTypeCode = "vclaim-sipp" // SIPP - DTCGC DocTypeCode = "general-consent" - - ETCPerson EntityTypeCode = "person" - ETCEncounter EntityTypeCode = "encounter" - ETCMCU EntityTypeCode = "mcu" -) - -var validUploadCodesByEntity = map[EntityTypeCode][]DocTypeCode{ - ETCPerson: { - DTCPRN, DTCPDL, DTCPP, DTCPFC, - }, - ETCEncounter: { - DTCSEP, DTCSIPP, DTCEnPatient, DTCEnSupport, DTCEnOther, - }, - ETCMCU: { - DTCMIR, - }, -} - -func IsValidUploadCode(entity EntityTypeCode, code DocTypeCode) (bool, string) { - allowedCodes, ok := validUploadCodesByEntity[entity] - if !ok { - return false, fmt.Sprintf("unknown entityType_code: %s", entity) - } - - for _, c := range allowedCodes { - if c == code { - return true, "" - } - } - - return false, fmt.Sprintf("invalid doctype_code '%s' for entityType_code '%s'", code, entity) -} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index aa6f76fb..0027fbc7 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -34,7 +34,7 @@ import ( responsibledoctorhist "simrs-vx/internal/interface/main-handler/responsible-doctor-hist" sbar "simrs-vx/internal/interface/main-handler/sbar" soapi "simrs-vx/internal/interface/main-handler/soapi" - upload "simrs-vx/internal/interface/main-handler/upload" + uploadfile "simrs-vx/internal/interface/main-handler/upload-file" /******************** actor ********************/ authpartner "simrs-vx/internal/interface/main-handler/auth-partner" @@ -274,7 +274,7 @@ func SetRoutes() http.Handler { "PATCH /{id}/reject": therapyprotocol.O.Reject, }) hc.RegCrud(r, "/v1/chemo-protocol", chemoprotocol.O) - hc.RegCrud(r, "/v1/upload", upload.O) + hc.RegCrud(r, "/v1/upload-file", uploadfile.O) hc.RegCrud(r, "/v1/encounter-document", encounterdocument.O) /******************** actor ********************/ diff --git a/internal/interface/main-handler/upload/handler.go b/internal/interface/main-handler/upload-file/handler.go similarity index 84% rename from internal/interface/main-handler/upload/handler.go rename to internal/interface/main-handler/upload-file/handler.go index 8a09c9ae..ac09fb65 100644 --- a/internal/interface/main-handler/upload/handler.go +++ b/internal/interface/main-handler/upload-file/handler.go @@ -1,4 +1,4 @@ -package upload +package uploadfile import ( "net/http" @@ -7,10 +7,9 @@ import ( d "github.com/karincake/dodol" rw "github.com/karincake/risoles" - eru "simrs-vx/internal/domain/references/upload" + ere "simrs-vx/internal/domain/references/encounter" - e "simrs-vx/internal/domain/main-entities/upload" - u "simrs-vx/internal/use-case/main-use-case/upload" + u "simrs-vx/internal/use-case/main-use-case/upload-file" ) type myBase struct{} @@ -49,10 +48,10 @@ func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { } } - dto := e.CreateDto{ - EntityType_Code: eru.EntityTypeCode(r.FormValue("entityType_code")), + dto := u.CreateDto{ + EntityType_Code: ere.EntityTypeCode(r.FormValue("entityType_code")), Ref_Id: refID, - Type_Code: eru.DocTypeCode(r.FormValue("type_code")), + Type_Code: ere.DocTypeCode(r.FormValue("type_code")), Name: r.FormValue("name"), Upload_Employee_Id: employeeId, File: file, diff --git a/internal/interface/main-handler/upload/validate-request.go b/internal/interface/main-handler/upload-file/validate-request.go similarity index 64% rename from internal/interface/main-handler/upload/validate-request.go rename to internal/interface/main-handler/upload-file/validate-request.go index 38ae492c..72161e81 100644 --- a/internal/interface/main-handler/upload/validate-request.go +++ b/internal/interface/main-handler/upload-file/validate-request.go @@ -1,10 +1,10 @@ -package upload +package uploadfile import ( - e "simrs-vx/internal/domain/main-entities/upload" + u "simrs-vx/internal/use-case/main-use-case/upload-file" ) -func validateCreate(dto e.CreateDto) string { +func validateCreate(dto u.CreateDto) string { switch { case dto.EntityType_Code == "": diff --git a/internal/use-case/main-use-case/encounter-document/case.go b/internal/use-case/main-use-case/encounter-document/case.go index 88592db7..979c6611 100644 --- a/internal/use-case/main-use-case/encounter-document/case.go +++ b/internal/use-case/main-use-case/encounter-document/case.go @@ -10,7 +10,7 @@ import ( d "github.com/karincake/dodol" "gorm.io/gorm" - eru "simrs-vx/internal/domain/references/upload" + ere "simrs-vx/internal/domain/references/encounter" e "simrs-vx/internal/domain/main-entities/encounter-document" ) @@ -244,7 +244,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { return err } - if err := removeUploadedFile(string(eru.ETCEncounter), *data.FilePath, &event); err != nil { + if err := removeUploadedFile(string(ere.ETCEncounter), *data.FilePath, &event); err != nil { return err } diff --git a/internal/use-case/main-use-case/upload-file/case.go b/internal/use-case/main-use-case/upload-file/case.go new file mode 100644 index 00000000..20d000dc --- /dev/null +++ b/internal/use-case/main-use-case/upload-file/case.go @@ -0,0 +1,76 @@ +package uploadfile + +import ( + "errors" + pl "simrs-vx/pkg/logger" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + "gorm.io/gorm" + + ere "simrs-vx/internal/domain/references/encounter" +) + +const source = "upload-file" + +func Upload(input CreateDto) (*d.Data, error) { + event := pl.Event{ + Feature: "Upload", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + var ( + err error + ) + err = dg.I.Transaction(func(tx *gorm.DB) error { + // validate entityType_Code and Type_Code + valid, msg := ere.IsValidUploadCode(input.EntityType_Code, input.Type_Code) + if !valid { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "invalid-code", + Detail: msg, + Raw: errors.New(msg), + } + return pl.SetLogError(&event, input) + } + + // upload file + input.FilePath, err = uploadAndGenerateFileUrl(input, &event) + if err != nil { + return err + } + + if input.EntityType_Code == ere.ETCEncounter { + _, err = setEncounterDocument(input, &event, tx) + if err != nil { + return err + } + + } else if input.EntityType_Code == ere.ETCPerson { + _, err = setPersonAttachment(input, &event, tx) + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: d.IS{ + "fileUrl": input.FilePath, + }, + }, nil +} diff --git a/internal/use-case/main-use-case/upload/helper.go b/internal/use-case/main-use-case/upload-file/helper.go similarity index 89% rename from internal/use-case/main-use-case/upload/helper.go rename to internal/use-case/main-use-case/upload-file/helper.go index 1880676f..176de93f 100644 --- a/internal/use-case/main-use-case/upload/helper.go +++ b/internal/use-case/main-use-case/upload-file/helper.go @@ -2,13 +2,13 @@ DESCRIPTION: Any functions that are used internally by the use-case */ -package upload +package uploadfile import ( "fmt" "path/filepath" ecore "simrs-vx/internal/domain/base-entities/core" - eru "simrs-vx/internal/domain/references/upload" + ere "simrs-vx/internal/domain/references/encounter" "strings" "time" @@ -21,13 +21,12 @@ import ( ee "simrs-vx/internal/domain/main-entities/encounter-document" ep "simrs-vx/internal/domain/main-entities/person" - e "simrs-vx/internal/domain/main-entities/upload" ue "simrs-vx/internal/use-case/main-use-case/encounter-document" up "simrs-vx/internal/use-case/main-use-case/person" ) -func uploadAndGenerateFileUrl(input e.CreateDto, event *pl.Event) (string, error) { +func uploadAndGenerateFileUrl(input CreateDto, event *pl.Event) (string, error) { pl.SetLogInfo(event, input, "started", "uploadAndGenerateFileUrl") bucket := string(input.EntityType_Code) ext := strings.ToLower(filepath.Ext(input.Filename)) @@ -97,7 +96,7 @@ func updatePersonAttachment(dataPerson *ep.Person, event *pl.Event, dbx ...*gorm return nil } -func setPersonAttachment(input e.CreateDto, event *pl.Event, tx *gorm.DB) (*ep.Person, error) { +func setPersonAttachment(input CreateDto, event *pl.Event, tx *gorm.DB) (*ep.Person, error) { // get person dataPerson, err := up.ReadDetailData(ep.ReadDetailDto{Id: *input.Ref_Id}, event, tx) if err != nil { @@ -106,22 +105,22 @@ func setPersonAttachment(input e.CreateDto, event *pl.Event, tx *gorm.DB) (*ep.P var removeUrl string switch input.Type_Code { - case eru.DTCPRN: + case ere.DTCPRN: if dataPerson.ResidentIdentityFileUrl != nil { removeUrl = *dataPerson.ResidentIdentityFileUrl } dataPerson.ResidentIdentityFileUrl = &input.FilePath - case eru.DTCPDL: + case ere.DTCPDL: if dataPerson.DrivingLicenseFileUrl != nil { removeUrl = *dataPerson.DrivingLicenseFileUrl } dataPerson.DrivingLicenseFileUrl = &input.FilePath - case eru.DTCPP: + case ere.DTCPP: if dataPerson.PassportFileUrl != nil { removeUrl = *dataPerson.PassportFileUrl } dataPerson.PassportFileUrl = &input.FilePath - case eru.DTCPFC: + case ere.DTCPFC: if dataPerson.FamilyIdentityFileUrl != nil { removeUrl = *dataPerson.FamilyIdentityFileUrl } @@ -141,7 +140,7 @@ func setPersonAttachment(input e.CreateDto, event *pl.Event, tx *gorm.DB) (*ep.P return dataPerson, nil } -func setEncounterDocument(input e.CreateDto, event *pl.Event, tx *gorm.DB) (*ee.EncounterDocument, error) { +func setEncounterDocument(input CreateDto, event *pl.Event, tx *gorm.DB) (*ee.EncounterDocument, error) { data := ee.EncounterDocument{} // get EncounterDocument @@ -164,7 +163,7 @@ func setEncounterDocument(input e.CreateDto, event *pl.Event, tx *gorm.DB) (*ee. Upload_Employee_Id: input.Upload_Employee_Id, } - if input.Type_Code == eru.DTCSEP || input.Type_Code == eru.DTCSIPP { + if input.Type_Code == ere.DTCSEP || input.Type_Code == ere.DTCSIPP { if len(dataUpload) > 0 { data = dataUpload[0] diff --git a/internal/domain/main-entities/upload/dto.go b/internal/use-case/main-use-case/upload-file/tycovar.go similarity index 53% rename from internal/domain/main-entities/upload/dto.go rename to internal/use-case/main-use-case/upload-file/tycovar.go index 445b1402..a5d63454 100644 --- a/internal/domain/main-entities/upload/dto.go +++ b/internal/use-case/main-use-case/upload-file/tycovar.go @@ -1,17 +1,22 @@ -package upload +/* +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 uploadfile import ( "mime/multipart" - eru "simrs-vx/internal/domain/references/upload" - - // internal - domain - base-entities - ecore "simrs-vx/internal/domain/base-entities/core" + ere "simrs-vx/internal/domain/references/encounter" ) type CreateDto struct { - EntityType_Code eru.EntityTypeCode `form:"entityType_code"` + EntityType_Code ere.EntityTypeCode `form:"entityType_code"` Ref_Id *uint `form:"ref_id"` - Type_Code eru.DocTypeCode `form:"type_code"` + Type_Code ere.DocTypeCode `form:"type_code"` Name string `form:"name"` Upload_Employee_Id *uint `form:"upload_employee_id"` FilePath string `json:"-"` @@ -23,46 +28,10 @@ type CreateDto struct { MimeType string `json:"-"` } -type ReadListDto struct { - FilterDto - Includes string `json:"includes"` - Pagination ecore.Pagination -} - -type FilterDto struct { - EntityType_Code eru.EntityTypeCode `json:"entityType-code"` - Ref_Id *uint `json:"ref-id"` - Type_Code eru.DocTypeCode `json:"type-code"` - Name string `json:"name"` - FilePath *string `json:"filePath"` - FileName *string `json:"fileName"` - Upload_Employee_Id *string `json:"encounter-document-employee-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 { - EntityType_Code eru.EntityTypeCode `json:"entityType_code"` + EntityType_Code ere.EntityTypeCode `json:"entityType_code"` Ref_Id *uint `json:"ref_id"` - Type_Code eru.DocTypeCode `json:"type_code"` + Type_Code ere.DocTypeCode `json:"type_code"` Name string `json:"name"` Upload_Employee_Id *uint `json:"upload_employee_id"` FilePath string `json:"filePath"` diff --git a/internal/use-case/main-use-case/upload/case.go b/internal/use-case/main-use-case/upload/case.go deleted file mode 100644 index 40ff74f6..00000000 --- a/internal/use-case/main-use-case/upload/case.go +++ /dev/null @@ -1,90 +0,0 @@ -package upload - -import ( - "errors" - pl "simrs-vx/pkg/logger" - pu "simrs-vx/pkg/use-case-helper" - - dg "github.com/karincake/apem/db-gorm-pg" - d "github.com/karincake/dodol" - "gorm.io/gorm" - - eru "simrs-vx/internal/domain/references/upload" - - e "simrs-vx/internal/domain/main-entities/upload" -) - -const source = "upload" - -func Upload(input e.CreateDto) (*d.Data, error) { - event := pl.Event{ - Feature: "Upload", - Source: source, - } - - // Start log - pl.SetLogInfo(&event, input, "started", "create") - - var data interface{} - err := dg.I.Transaction(func(tx *gorm.DB) error { - mwRunner := newMiddlewareRunner(&event, tx) - mwRunner.setMwType(pu.MWTPre) - - // Run pre-middleware - err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data) - if err != nil { - return err - } - - // validate entityType_Code and Type_Code - valid, msg := eru.IsValidUploadCode(input.EntityType_Code, input.Type_Code) - if !valid { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "invalid-code", - Detail: msg, - Raw: errors.New(msg), - } - return pl.SetLogError(&event, input) - } - - // upload file - input.FilePath, err = uploadAndGenerateFileUrl(input, &event) - if err != nil { - return err - } - - if input.EntityType_Code == eru.ETCEncounter { - data, err = setEncounterDocument(input, &event, tx) - if err != nil { - return err - } - - } else if input.EntityType_Code == eru.ETCPerson { - data, err = setPersonAttachment(input, &event, tx) - } - - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { - return err - } - - pl.SetLogInfo(&event, nil, "complete") - - return nil - }) - - if err != nil { - return nil, err - } - - return &d.Data{ - Meta: d.II{ - "source": source, - "structure": "single-data", - "status": "created", - }, - Data: input.ToResponse(), - }, nil -} diff --git a/internal/use-case/main-use-case/upload/middleware-runner.go b/internal/use-case/main-use-case/upload/middleware-runner.go deleted file mode 100644 index 88e3e637..00000000 --- a/internal/use-case/main-use-case/upload/middleware-runner.go +++ /dev/null @@ -1,104 +0,0 @@ -package upload - -import ( - pl "simrs-vx/pkg/logger" - pu "simrs-vx/pkg/use-case-helper" - - "gorm.io/gorm" - - e "simrs-vx/internal/domain/main-entities/upload" -) - -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 interface{}) 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 interface{}) 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 interface{}) 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 interface{}) 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 interface{}) 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/main-use-case/upload/middleware.go b/internal/use-case/main-use-case/upload/middleware.go deleted file mode 100644 index 63beb606..00000000 --- a/internal/use-case/main-use-case/upload/middleware.go +++ /dev/null @@ -1,9 +0,0 @@ -package upload - -// example of middleware -// func init() { -// createPreMw = append(createPreMw, -// CreateMw{Name: "modif-input", Func: pm.ModifInput}, -// CreateMw{Name: "check-data", Func: pm.CheckData}, -// ) -// } diff --git a/internal/use-case/main-use-case/upload/tycovar.go b/internal/use-case/main-use-case/upload/tycovar.go deleted file mode 100644 index 4849e215..00000000 --- a/internal/use-case/main-use-case/upload/tycovar.go +++ /dev/null @@ -1,44 +0,0 @@ -/* -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 upload - -import ( - "gorm.io/gorm" - - e "simrs-vx/internal/domain/main-entities/upload" -) - -type createMw struct { - Name string - Func func(input *e.CreateDto, data interface{}, tx *gorm.DB) error -} - -type readListMw struct { - Name string - Func func(input *e.ReadListDto, data interface{}, tx *gorm.DB) error -} - -type readDetailMw struct { - Name string - Func func(input *e.ReadDetailDto, data interface{}, 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/pkg/upload-helper/upload-helper.go b/pkg/upload-helper/upload-helper.go index 85f5448f..0dce8fd7 100644 --- a/pkg/upload-helper/upload-helper.go +++ b/pkg/upload-helper/upload-helper.go @@ -5,7 +5,7 @@ import ( "path/filepath" "strings" - ere "simrs-vx/internal/domain/references/upload" + ere "simrs-vx/internal/domain/references/encounter" ) func getBucketForType(docType string) (string, error) { From e78ad5aa836787c807790ca743f69a80c25af35c Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 17 Nov 2025 15:29:46 +0700 Subject: [PATCH 214/329] add docs config parser --- internal/infra/docs-cfg/docs-cfg.go | 17 +++++++++++++++++ internal/interface/main-handler/main-handler.go | 2 ++ 2 files changed, 19 insertions(+) create mode 100644 internal/infra/docs-cfg/docs-cfg.go diff --git a/internal/infra/docs-cfg/docs-cfg.go b/internal/infra/docs-cfg/docs-cfg.go new file mode 100644 index 00000000..e6d32c92 --- /dev/null +++ b/internal/infra/docs-cfg/docs-cfg.go @@ -0,0 +1,17 @@ +package docscfg + +import a "github.com/karincake/apem" + +type DocsCfg struct { + Path string +} + +var O DocsCfg = DocsCfg{} + +func ParseCfg() { + a.ParseSingleCfg(&O) +} + +func (c DocsCfg) GetPath() string { + return c.Path +} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 0027fbc7..649c59cc 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -57,6 +57,7 @@ import ( /******************** infra ********************/ ibpjs "simrs-vx/internal/infra/bpjs" + docscfg "simrs-vx/internal/infra/docs-cfg" gs "simrs-vx/internal/infra/gorm-setting" minio "simrs-vx/internal/infra/minio" ssdb "simrs-vx/internal/infra/ss-db" @@ -131,6 +132,7 @@ func SetRoutes() http.Handler { a.RegisterExtCall(ibpjs.SetConfig) a.RegisterExtCall(validation.RegisterValidation) a.RegisterExtCall(simgossync.SetConfig) + a.RegisterExtCall(docscfg.ParseCfg) r := http.NewServeMux() From 8911bb678c411b16245a5a0d3ef763c60c67700b Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 17 Nov 2025 16:17:26 +0700 Subject: [PATCH 215/329] add divisi --- internal/domain/main-entities/division/dto.go | 1 + .../use-case/main-use-case/division/case.go | 97 +++++---- .../division/middleware-runner.go | 38 +++- .../main-use-case/division/middleware.go | 23 ++- .../main-use-case/division/tycovar.go | 31 ++- .../main-use-case/unit/middleware-runner.go | 4 +- .../simgos-sync-plugin/division/plugin.go | 56 +++-- .../simgos-sync-plugin/installation/plugin.go | 54 +++-- .../simgos-sync-plugin/unit/plugin.go | 54 +++-- .../simgos-sync-use-case/division/case.go | 194 +++++++++--------- .../simgos-sync-use-case/division/helper.go | 30 ++- .../simgos-sync-use-case/division/lib.go | 176 ++++++++-------- 12 files changed, 431 insertions(+), 327 deletions(-) diff --git a/internal/domain/main-entities/division/dto.go b/internal/domain/main-entities/division/dto.go index 30f0b238..d74b54f7 100644 --- a/internal/domain/main-entities/division/dto.go +++ b/internal/domain/main-entities/division/dto.go @@ -6,6 +6,7 @@ import ( ) type CreateDto struct { + Id *uint `json:"id"` Code string `json:"code" validate:"maxLength=10"` Name string `json:"name" validate:"maxLength=50"` Parent_Code *string `json:"parent_code"` diff --git a/internal/use-case/main-use-case/division/case.go b/internal/use-case/main-use-case/division/case.go index c955aed7..4be7ce82 100644 --- a/internal/use-case/main-use-case/division/case.go +++ b/internal/use-case/main-use-case/division/case.go @@ -2,6 +2,8 @@ package division import ( e "simrs-vx/internal/domain/main-entities/division" + erc "simrs-vx/internal/domain/references/common" + esync "simrs-vx/internal/domain/sync-entities/log" "strconv" dg "github.com/karincake/apem/db-gorm-pg" @@ -25,36 +27,32 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") + mwRunner := newMiddlewareRunner(&event) 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 resData, err := CreateData(input, &event, tx); err != nil { return err } else { data = *resData + id := uint(data.Id) + input.Id = &id } - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input); err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") - return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.II{ "source": source, @@ -80,7 +78,7 @@ 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 := newMiddlewareRunner(&event) mwRunner.setMwType(pu.MWTPre) // Run pre-middleware if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { @@ -131,7 +129,7 @@ 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 := newMiddlewareRunner(&event) mwRunner.setMwType(pu.MWTPre) // Run pre-middleware if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { @@ -177,6 +175,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "update") + mwRunner := newMiddlewareRunner(&event) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -184,32 +183,26 @@ 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 - } - + input.Id = &data.Id if err := UpdateData(input, data, &event, tx); err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") - - 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.RunUpdateMiddleware(updatePreMw, &input); err != nil { return err } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -233,6 +226,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "delete") + mwRunner := newMiddlewareRunner(&event) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -240,30 +234,26 @@ 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 - } - + input.Id = &data.Id 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.RunDeleteMiddleware(deletePreMw, &input); err != nil { return err } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -274,3 +264,32 @@ func Delete(input e.DeleteDto) (*d.Data, error) { }, nil } + +func runLogMiddleware(err error, input any, mwRunner *middlewareRunner) error { + var errMsg string + inputLog := esync.SimxLogDto{ + Payload: input, + Method: erc.CCCreate, + } + + if err != nil { + // Run log-middleware + errMsg = err.Error() + inputLog.ErrMessage = &errMsg + inputLog.IsSuccess = false + + // create log failed + if errMiddleware := mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog); errMiddleware != nil { + return errMiddleware + } + return err + } + + // create log success + inputLog.IsSuccess = true + if err = mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog); err != nil { + return err + } + + return nil +} 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 915cce28..b39e3176 100644 --- a/internal/use-case/main-use-case/division/middleware-runner.go +++ b/internal/use-case/main-use-case/division/middleware-runner.go @@ -2,6 +2,7 @@ package division import ( e "simrs-vx/internal/domain/main-entities/division" + esync "simrs-vx/internal/domain/sync-entities/log" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -15,21 +16,36 @@ type middlewareRunner struct { } // NewMiddlewareExecutor creates a new middleware executor -func newMiddlewareRunner(event *pl.Event, tx *gorm.DB) *middlewareRunner { +func newMiddlewareRunner(event *pl.Event) *middlewareRunner { return &middlewareRunner{ Event: event, - Tx: tx, } } // ExecuteCreateMiddleware executes create middleware -func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.Division) error { +func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto) 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 +} + +// ExecuteCreateMiddleware executes createlog middleware +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 +84,13 @@ func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, return nil } -func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Division) error { +func (me *middlewareRunner) RunUpdateMiddleware(middlewares []updateMw, input *e.UpdateDto) 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 +99,13 @@ func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, inpu return nil } -func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Division) 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) } diff --git a/internal/use-case/main-use-case/division/middleware.go b/internal/use-case/main-use-case/division/middleware.go index f066ffb8..317b137a 100644 --- a/internal/use-case/main-use-case/division/middleware.go +++ b/internal/use-case/main-use-case/division/middleware.go @@ -1,9 +1,20 @@ package division +import ( + plugin "simrs-vx/internal/use-case/simgos-sync-plugin/division" +) + // example of middleware -// func init() { -// createPreMw = append(createPreMw, -// CreateMw{Name: "modif-input", Func: pm.ModifInput}, -// CreateMw{Name: "check-data", Func: pm.CheckData}, -// ) -// } +func init() { + createPreMw = append(createPreMw, + createMw{Name: "create-unit", Func: plugin.Create}) + + createSimxLogMw = append(createSimxLogMw, + createLogMw{Name: "create-log", Func: plugin.CreateLog}) + + updatePreMw = append(updatePreMw, + updateMw{Name: "update-unit", Func: plugin.Update}) + + deletePreMw = append(deletePreMw, + deleteMw{Name: "delete-unit", Func: plugin.Delete}) +} diff --git a/internal/use-case/main-use-case/division/tycovar.go b/internal/use-case/main-use-case/division/tycovar.go index c7733117..cef873ee 100644 --- a/internal/use-case/main-use-case/division/tycovar.go +++ b/internal/use-case/main-use-case/division/tycovar.go @@ -12,11 +12,27 @@ import ( "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/division" + elog "simrs-vx/internal/domain/sync-entities/log" ) type createMw struct { Name string - Func func(input *e.CreateDto, data *e.Division, tx *gorm.DB) error + Func func(input *e.CreateDto) error +} + +type createLogMw struct { + Name string + Func func(input *elog.SimxLogDto) error +} + +type updateMw struct { + Name string + Func func(input *e.UpdateDto) error +} + +type deleteMw struct { + Name string + Func func(input *e.DeleteDto) error } type readListMw struct { @@ -29,16 +45,17 @@ type readDetailMw struct { Func func(input *e.ReadDetailDto, data *e.Division, 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 +var createPreMw []createMw // preprocess middleware +var createPostMw []createMw // postprocess middleware +var createSimxLogMw []createLogMw 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 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 3c7fa241..f45fe208 100644 --- a/internal/use-case/main-use-case/unit/middleware-runner.go +++ b/internal/use-case/main-use-case/unit/middleware-runner.go @@ -84,7 +84,7 @@ func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, return nil } -func (me *middlewareRunner) RunUpdateMiddleware(middlewares []UpdateMw, input *e.UpdateDto) error { +func (me *middlewareRunner) RunUpdateMiddleware(middlewares []updateMw, input *e.UpdateDto) error { for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) @@ -99,7 +99,7 @@ func (me *middlewareRunner) RunUpdateMiddleware(middlewares []UpdateMw, input *e return nil } -func (me *middlewareRunner) RunDeleteMiddleware(middlewares []DeleteMw, input *e.DeleteDto) error { +func (me *middlewareRunner) RunDeleteMiddleware(middlewares []deleteMw, input *e.DeleteDto) error { for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) diff --git a/internal/use-case/simgos-sync-plugin/division/plugin.go b/internal/use-case/simgos-sync-plugin/division/plugin.go index 06e54e31..54c1403c 100644 --- a/internal/use-case/simgos-sync-plugin/division/plugin.go +++ b/internal/use-case/simgos-sync-plugin/division/plugin.go @@ -9,8 +9,10 @@ import ( sync "simrs-vx/internal/infra/sync-cfg" - e "simrs-vx/internal/domain/main-entities/unit" + 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 { @@ -34,15 +36,18 @@ func Create(input *e.CreateDto) error { } defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return fmt.Errorf(resp.Status) - } - - _, err = io.ReadAll(resp.Body) + 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 } @@ -68,15 +73,18 @@ func CreateLog(input *elog.SimxLogDto) error { } defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return fmt.Errorf(resp.Status) - } - - _, err = io.ReadAll(resp.Body) + 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 } @@ -102,15 +110,18 @@ func Update(input *e.UpdateDto) error { } defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return fmt.Errorf(resp.Status) - } - - _, err = io.ReadAll(resp.Body) + 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 } @@ -136,15 +147,18 @@ func Delete(input *e.DeleteDto) error { } defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return fmt.Errorf(resp.Status) - } - - _, err = io.ReadAll(resp.Body) + 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 } diff --git a/internal/use-case/simgos-sync-plugin/installation/plugin.go b/internal/use-case/simgos-sync-plugin/installation/plugin.go index 06c9bebe..f2495139 100644 --- a/internal/use-case/simgos-sync-plugin/installation/plugin.go +++ b/internal/use-case/simgos-sync-plugin/installation/plugin.go @@ -11,6 +11,8 @@ import ( 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 { @@ -34,15 +36,18 @@ func Create(input *e.CreateDto) error { } defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return fmt.Errorf(resp.Status) - } - - _, err = io.ReadAll(resp.Body) + 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 } @@ -68,15 +73,18 @@ func CreateLog(input *elog.SimxLogDto) error { } defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return fmt.Errorf(resp.Status) - } - - _, err = io.ReadAll(resp.Body) + 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 } @@ -102,15 +110,18 @@ func Update(input *e.UpdateDto) error { } defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return fmt.Errorf(resp.Status) - } - - _, err = io.ReadAll(resp.Body) + 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 } @@ -136,15 +147,18 @@ func Delete(input *e.DeleteDto) error { } defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return fmt.Errorf(resp.Status) - } - - _, err = io.ReadAll(resp.Body) + 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 } diff --git a/internal/use-case/simgos-sync-plugin/unit/plugin.go b/internal/use-case/simgos-sync-plugin/unit/plugin.go index 8462f18d..e854d898 100644 --- a/internal/use-case/simgos-sync-plugin/unit/plugin.go +++ b/internal/use-case/simgos-sync-plugin/unit/plugin.go @@ -11,6 +11,8 @@ import ( 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 { @@ -34,15 +36,18 @@ func Create(input *e.CreateDto) error { } defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return fmt.Errorf(resp.Status) - } - - _, err = io.ReadAll(resp.Body) + 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 } @@ -68,15 +73,18 @@ func CreateLog(input *elog.SimxLogDto) error { } defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return fmt.Errorf(resp.Status) - } - - _, err = io.ReadAll(resp.Body) + 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 } @@ -102,15 +110,18 @@ func Update(input *e.UpdateDto) error { } defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return fmt.Errorf(resp.Status) - } - - _, err = io.ReadAll(resp.Body) + 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 } @@ -136,15 +147,18 @@ func Delete(input *e.DeleteDto) error { } defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return fmt.Errorf(resp.Status) - } - - _, err = io.ReadAll(resp.Body) + 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 } diff --git a/internal/use-case/simgos-sync-use-case/division/case.go b/internal/use-case/simgos-sync-use-case/division/case.go index 074bf2a7..14dd0886 100644 --- a/internal/use-case/simgos-sync-use-case/division/case.go +++ b/internal/use-case/simgos-sync-use-case/division/case.go @@ -8,17 +8,17 @@ import ( "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/division" + esimgos "simrs-vx/internal/domain/simgos-entities/division" esync "simrs-vx/internal/domain/sync-entities/log" - //esimgos "simrs-vx/internal/domain/simgos-entities/installation" ) const source = "division" func Create(input e.CreateDto) (*d.Data, error) { - //var ( - // txSync = dg.I.Begin() - // txSimgos = dg.IS["simrs"].Begin() - //) + var ( + txSync = dg.I.Begin() + txSimgos = dg.IS["simrs"].Begin() + ) event := pl.Event{ Feature: "Create", @@ -29,32 +29,32 @@ func Create(input e.CreateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "create") // STEP 1: Insert to simgos - //sgData, err := CreateSimgosData(input, &event, txSimgos) - //if err != nil { - // return nil, err - //} - // - //// STEP 2: Insert to Link - //syncLink, err := CreateLinkData(*input.Id, sgData.Kode, &event, txSync) - //if err != nil { - // txSimgos.Rollback() - // return nil, err - //} - // - //// STEP 3: Commit two trx - //if err = txSync.Commit().Error; err != nil { - // txSync.Rollback() - // txSimgos.Rollback() - // return nil, err - //} - // - //if err = txSimgos.Commit().Error; err != nil { - // // STEP 4: Rollback Partial - // go func() { - // _ = DeleteLinkData(syncLink, &event) - // }() - // return nil, err - //} + sgData, err := CreateSimgosData(input, &event, txSimgos) + if err != nil { + return nil, err + } + + // STEP 2: Insert to Link + syncLink, err := CreateLinkData(*input.Id, sgData.KodeUnit, &event, txSync) + if err != nil { + txSimgos.Rollback() + return nil, err + } + + // STEP 3: Commit two trx + if err = txSync.Commit().Error; err != nil { + txSync.Rollback() + txSimgos.Rollback() + return nil, err + } + + if err = txSimgos.Commit().Error; err != nil { + // STEP 4: Rollback Partial + go func() { + _ = DeleteLinkData(syncLink, &event) + }() + return nil, err + } pl.SetLogInfo(&event, nil, "complete") @@ -103,10 +103,10 @@ func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - //var ( - // txSimgos = dg.IS["simrs"].Begin() - // err error - //) + var ( + txSimgos = dg.IS["simrs"].Begin() + err error + ) event := pl.Event{ Feature: "Update", @@ -116,23 +116,23 @@ func Update(input e.UpdateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "update") - //// STEP 1: Get Installation Link - //syncLink, err := ReadDetailLinkData(*input.Id, &event) - //if err != nil { - // return nil, err - //} - // - //// Step 2: Update Simgos - //err = UpdateSimgosData(input, syncLink, &event, txSimgos) - //if err != nil { - // return nil, err - //} - // - //// STEP 4: Commit two trx - //if err = txSimgos.Commit().Error; err != nil { - // txSimgos.Rollback() - // return nil, err - //} + // STEP 1: Get Installation Link + syncLink, err := ReadDetailLinkData(*input.Id, &event) + if err != nil { + return nil, err + } + + // Step 2: Update Simgos + err = UpdateSimgosData(input, syncLink, &event, txSimgos) + if err != nil { + return nil, err + } + + // STEP 4: Commit two trx + if err = txSimgos.Commit().Error; err != nil { + txSimgos.Rollback() + return nil, err + } pl.SetLogInfo(&event, nil, "complete") @@ -146,12 +146,12 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - //var ( - // txSync = dg.I.Begin() - // txSimgos = dg.IS["simrs"].Begin() - // sgData *esimgos.MPloy - // err error - //) + var ( + txSync = dg.I.Begin() + txSimgos = dg.IS["simrs"].Begin() + sgData *esimgos.MUnit + err error + ) event := pl.Event{ Feature: "Delete", @@ -161,45 +161,45 @@ func Delete(input e.DeleteDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "delete") - //// STEP 1: Get Installation Link - //syncLink, err := ReadDetailLinkData(*input.Id, &event) - //if err != nil { - // return nil, err - //} - // - //// STEP 2: Get Simgos - //sgData, err = ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) - //if err != nil { - // return nil, err - //} - // - //// STEP 3: Delete M_Poly Simgos - //err = HardDeleteSimgosData(sgData, &event, txSimgos) - //if err != nil { - // return nil, err - //} - // - //// STEP 4: Delete Installation Link - //err = DeleteLinkData(syncLink, &event, txSync) - //if err != nil { - // txSimgos.Rollback() - // return nil, err - //} - // - //// STEP 4: Commit two trx - //if err = txSync.Commit().Error; err != nil { - // txSync.Rollback() - // txSimgos.Rollback() - // return nil, err - //} - // - //if err = txSimgos.Commit().Error; err != nil { - // // STEP 5: Rollback Partial - // go func() { - // _, _ = CreateLinkData(uint(*input.Id), sgData.Kode, &event) - // }() - // return nil, err - //} + // STEP 1: Get Installation Link + syncLink, err := ReadDetailLinkData(*input.Id, &event) + if err != nil { + return nil, err + } + + // STEP 2: Get Simgos + sgData, err = ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) + if err != nil { + return nil, err + } + + // STEP 3: Delete M_Unit Simgos + err = HardDeleteSimgosData(sgData, &event, txSimgos) + if err != nil { + return nil, err + } + + // STEP 4: Delete Installation Link + err = DeleteLinkData(syncLink, &event, txSync) + if err != nil { + txSimgos.Rollback() + return nil, err + } + + // STEP 4: Commit two trx + if err = txSync.Commit().Error; err != nil { + txSync.Rollback() + txSimgos.Rollback() + return nil, err + } + + if err = txSimgos.Commit().Error; err != nil { + // STEP 5: Rollback Partial + go func() { + _, _ = CreateLinkData(uint(*input.Id), sgData.KodeUnit, &event) + }() + return nil, err + } pl.SetLogInfo(&event, nil, "complete") diff --git a/internal/use-case/simgos-sync-use-case/division/helper.go b/internal/use-case/simgos-sync-use-case/division/helper.go index 210d6e7c..e180d771 100644 --- a/internal/use-case/simgos-sync-use-case/division/helper.go +++ b/internal/use-case/simgos-sync-use-case/division/helper.go @@ -8,26 +8,24 @@ import ( "encoding/json" erc "simrs-vx/internal/domain/references/common" - //e "simrs-vx/internal/domain/main-entities/division" - // esimgos "simrs-vx/internal/domain/simgos-entities/divison" TBC + e "simrs-vx/internal/domain/main-entities/division" + esimgos "simrs-vx/internal/domain/simgos-entities/division" esync "simrs-vx/internal/domain/sync-entities/division" esyncLog "simrs-vx/internal/domain/sync-entities/log" ) -//func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MPloy) { -// var inputSrc *e.CreateDto -// if inputT, ok := any(input).(*e.CreateDto); ok { -// inputSrc = inputT -// } else { -// inputTemp := any(input).(*e.UpdateDto) -// inputSrc = &inputTemp.CreateDto -// } -// -// data.Nama = inputSrc.Name -// data.Jenispoly = 0 -// -// return -//} +func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MUnit) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.NamaUnit = inputSrc.Name + return +} func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.DivisionSimxLog) { // encode to JSON diff --git a/internal/use-case/simgos-sync-use-case/division/lib.go b/internal/use-case/simgos-sync-use-case/division/lib.go index ce13068d..681be276 100644 --- a/internal/use-case/simgos-sync-use-case/division/lib.go +++ b/internal/use-case/simgos-sync-use-case/division/lib.go @@ -9,103 +9,103 @@ import ( dg "github.com/karincake/apem/db-gorm-pg" "gorm.io/gorm" - //e "simrs-vx/internal/domain/main-entities/division" + e "simrs-vx/internal/domain/main-entities/division" + esimgos "simrs-vx/internal/domain/simgos-entities/division" esync "simrs-vx/internal/domain/sync-entities/division" - //esimgos "simrs-vx/internal/domain/simgos-entities/unit" esynclog "simrs-vx/internal/domain/sync-entities/log" ) var now = time.Now() -//func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esimgos.MPloy, error) { -// pl.SetLogInfo(event, nil, "started", "DBCreate") -// -// data := setDataSimgos(&input) -// -// 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 CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esimgos.MUnit, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") -//func ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.MPloy, error) { -// pl.SetLogInfo(event, simgosId, "started", "DBReadDetail") -// data := esimgos.MPloy{} -// -// var tx = dg.IS["simrs"] -// -// if err := tx. -// Where("\"kode\" = ?", 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 -//} + data := setDataSimgos(&input) -//func UpdateSimgosData(input e.UpdateDto, dataSimgos *esync.DivisionLink, event *pl.Event, dbx ...*gorm.DB) error { -// pl.SetLogInfo(event, input, "started", "DBUpdate") -// -// data := setDataSimgos(&input) -// data.Kode = dataSimgos.Simgos_Id -// -// 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 -//} + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.IS["simrs"] + } -//func HardDeleteSimgosData(data *esimgos.MPloy, 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 -//} + if err := tx.Create(&data).Error; err != nil { + return nil, plh.HandleCreateError(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.MUnit, error) { + pl.SetLogInfo(event, simgosId, "started", "DBReadDetail") + data := esimgos.MUnit{} + + var tx = dg.IS["simrs"] + + if err := tx. + Where("\"kode_unit\" = ?", 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 UpdateSimgosData(input e.UpdateDto, dataSimgos *esync.DivisionLink, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, input, "started", "DBUpdate") + + data := setDataSimgos(&input) + data.KodeUnit = dataSimgos.Simgos_Id + + 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 HardDeleteSimgosData(data *esimgos.MUnit, 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 CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.DivisionLink, error) { pl.SetLogInfo(event, nil, "started", "DBCreate") From 8073236d06ec563669b84fda0a1f210529fca79a Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 17 Nov 2025 16:20:14 +0700 Subject: [PATCH 216/329] feat (general-consent): add crud --- cmd/main-api/config.yml-example | 5 +- .../main-entities/general-consent/dto.go | 64 ++++ .../main-entities/general-consent/entity.go | 2 +- internal/domain/references/common/common.go | 6 + .../main-handler/general-consent/handler.go | 72 +++++ .../interface/main-handler/main-handler.go | 2 + .../main-use-case/general-consent/case.go | 282 ++++++++++++++++++ .../main-use-case/general-consent/helper.go | 22 ++ .../main-use-case/general-consent/lib.go | 140 +++++++++ .../general-consent/middleware-runner.go | 103 +++++++ .../general-consent/middleware.go | 9 + .../main-use-case/general-consent/tycovar.go | 44 +++ .../main-use-case/generate-file/case.go | 45 +++ .../main-use-case/generate-file/tycovar.go | 25 ++ 14 files changed, 819 insertions(+), 2 deletions(-) create mode 100644 internal/domain/main-entities/general-consent/dto.go create mode 100644 internal/interface/main-handler/general-consent/handler.go create mode 100644 internal/use-case/main-use-case/general-consent/case.go create mode 100644 internal/use-case/main-use-case/general-consent/helper.go create mode 100644 internal/use-case/main-use-case/general-consent/lib.go create mode 100644 internal/use-case/main-use-case/general-consent/middleware-runner.go create mode 100644 internal/use-case/main-use-case/general-consent/middleware.go create mode 100644 internal/use-case/main-use-case/general-consent/tycovar.go create mode 100644 internal/use-case/main-use-case/generate-file/case.go create mode 100644 internal/use-case/main-use-case/generate-file/tycovar.go diff --git a/cmd/main-api/config.yml-example b/cmd/main-api/config.yml-example index 448cff66..22fdf651 100644 --- a/cmd/main-api/config.yml-example +++ b/cmd/main-api/config.yml-example @@ -70,4 +70,7 @@ bpjsCfg: syncUrlCfg: host: - prefix: new-to-old \ No newline at end of file + prefix: new-to-old + +docsCfg: + path: ../../assets/docs/ \ No newline at end of file diff --git a/internal/domain/main-entities/general-consent/dto.go b/internal/domain/main-entities/general-consent/dto.go new file mode 100644 index 00000000..3c659f2f --- /dev/null +++ b/internal/domain/main-entities/general-consent/dto.go @@ -0,0 +1,64 @@ +package generalconsent + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type CreateDto struct { + Encounter_Id *uint `json:"-"` + Value *string `json:"value"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Encounter_Id *uint `json:"encounter-id"` +} + +type ReadDetailDto struct { + Id uint `json:"id"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + Encounter_Id *uint `json:"encounter_id"` + Value *string `json:"value"` + FileUrl *string `json:"fileUrl"` +} + +func (d GeneralConsent) ToResponse() ResponseDto { + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Value: d.Value, + FileUrl: d.FileUrl, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []GeneralConsent) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/general-consent/entity.go b/internal/domain/main-entities/general-consent/entity.go index f5ce6394..bf9381ec 100644 --- a/internal/domain/main-entities/general-consent/entity.go +++ b/internal/domain/main-entities/general-consent/entity.go @@ -1,4 +1,4 @@ -package general_consent +package generalconsent import ( "simrs-vx/internal/domain/base-entities/core" diff --git a/internal/domain/references/common/common.go b/internal/domain/references/common/common.go index 5b3f675b..cc466d7b 100644 --- a/internal/domain/references/common/common.go +++ b/internal/domain/references/common/common.go @@ -17,6 +17,7 @@ type ( CrudCode string DataApprovalCode string ProcessStatusCode string + DocFormatTypeCode string ) const ( @@ -106,6 +107,11 @@ const ( PSCSuccess ProcessStatusCode = "success" PSCFailed ProcessStatusCode = "failed" + + DFTCPDF DocFormatTypeCode = "pdf" + DFTCTXLSX DocFormatTypeCode = "xlsx" + DFTCTCSV DocFormatTypeCode = "csv" + DFTCTXLS DocFormatTypeCode = "xls" ) func GetDayCodes() map[DayCode]string { diff --git a/internal/interface/main-handler/general-consent/handler.go b/internal/interface/main-handler/general-consent/handler.go new file mode 100644 index 00000000..0a2e2f6a --- /dev/null +++ b/internal/interface/main-handler/general-consent/handler.go @@ -0,0 +1,72 @@ +package generalconsent + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/general-consent" + u "simrs-vx/internal/use-case/main-use-case/general-consent" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + sf.UrlQueryParam(&dto, *r.URL) + dto.Id = uint(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint(id) + 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/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 649c59cc..8ce9fadf 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -17,6 +17,7 @@ import ( deviceorderitem "simrs-vx/internal/interface/main-handler/device-order-item" encounter "simrs-vx/internal/interface/main-handler/encounter" encounterdocument "simrs-vx/internal/interface/main-handler/encounter-document" + generalconsent "simrs-vx/internal/interface/main-handler/general-consent" internalreference "simrs-vx/internal/interface/main-handler/internal-reference" materialorder "simrs-vx/internal/interface/main-handler/material-order" materialorderitem "simrs-vx/internal/interface/main-handler/material-order-item" @@ -278,6 +279,7 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/chemo-protocol", chemoprotocol.O) hc.RegCrud(r, "/v1/upload-file", uploadfile.O) hc.RegCrud(r, "/v1/encounter-document", encounterdocument.O) + hc.RegCrud(r, "/v1/general-consent", generalconsent.O) /******************** actor ********************/ hc.RegCrud(r, "/v1/person", person.O) diff --git a/internal/use-case/main-use-case/general-consent/case.go b/internal/use-case/main-use-case/general-consent/case.go new file mode 100644 index 00000000..a8c181ef --- /dev/null +++ b/internal/use-case/main-use-case/general-consent/case.go @@ -0,0 +1,282 @@ +package generalconsent + +import ( + "strconv" + + // main entities + e "simrs-vx/internal/domain/main-entities/general-consent" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + "gorm.io/gorm" +) + +const source = "general-consent" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.GeneralConsent{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.GeneralConsent + var dataList []e.GeneralConsent + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.GeneralConsent + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.GeneralConsent + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 + } + + // Get Updated Data + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: uint(input.Id)} + var data *e.GeneralConsent + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/general-consent/helper.go b/internal/use-case/main-use-case/general-consent/helper.go new file mode 100644 index 00000000..015d4716 --- /dev/null +++ b/internal/use-case/main-use-case/general-consent/helper.go @@ -0,0 +1,22 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package generalconsent + +import ( + e "simrs-vx/internal/domain/main-entities/general-consent" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.GeneralConsent) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Encounter_Id = inputSrc.Encounter_Id + data.Value = inputSrc.Value +} diff --git a/internal/use-case/main-use-case/general-consent/lib.go b/internal/use-case/main-use-case/general-consent/lib.go new file mode 100644 index 00000000..e365523d --- /dev/null +++ b/internal/use-case/main-use-case/general-consent/lib.go @@ -0,0 +1,140 @@ +package generalconsent + +import ( + "errors" + e "simrs-vx/internal/domain/main-entities/general-consent" + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.GeneralConsent, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.GeneralConsent{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.GeneralConsent, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.GeneralConsent{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.GeneralConsent{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Order("\"CreatedAt\" DESC") + + if err := tx.Find(&data).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.GeneralConsent, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.GeneralConsent{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.First(&data, input.Id).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.GeneralConsent, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.GeneralConsent, 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 +} diff --git a/internal/use-case/main-use-case/general-consent/middleware-runner.go b/internal/use-case/main-use-case/general-consent/middleware-runner.go new file mode 100644 index 00000000..4dfc739a --- /dev/null +++ b/internal/use-case/main-use-case/general-consent/middleware-runner.go @@ -0,0 +1,103 @@ +package generalconsent + +import ( + e "simrs-vx/internal/domain/main-entities/general-consent" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.GeneralConsent) 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.GeneralConsent) 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.GeneralConsent) 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.GeneralConsent) 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.GeneralConsent) 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/main-use-case/general-consent/middleware.go b/internal/use-case/main-use-case/general-consent/middleware.go new file mode 100644 index 00000000..69311dfc --- /dev/null +++ b/internal/use-case/main-use-case/general-consent/middleware.go @@ -0,0 +1,9 @@ +package generalconsent + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/general-consent/tycovar.go b/internal/use-case/main-use-case/general-consent/tycovar.go new file mode 100644 index 00000000..b91396b9 --- /dev/null +++ b/internal/use-case/main-use-case/general-consent/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 generalconsent + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/general-consent" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.GeneralConsent, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.GeneralConsent, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.GeneralConsent, 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/main-use-case/generate-file/case.go b/internal/use-case/main-use-case/generate-file/case.go new file mode 100644 index 00000000..72182513 --- /dev/null +++ b/internal/use-case/main-use-case/generate-file/case.go @@ -0,0 +1,45 @@ +package generatefile + +import ( + // "encoding/json" + + // egc "simrs-vx/internal/domain/main-entities/general-consent" + // ugc "simrs-vx/internal/use-case/main-use-case/general-consent" + + pl "simrs-vx/pkg/logger" + + d "github.com/karincake/dodol" + + ere "simrs-vx/internal/domain/references/encounter" +) + +const source = "generate-file" + +func Generate(input GenerateDto) (*d.Data, error) { + event := pl.Event{ + Feature: "Generate", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + switch input.Type_Code { + // general-consent + case ere.DTCGC: + // get value from general consent by ref_id + // gc, err := ugc.ReadDetailData(ugc.ReadDetailDto{Ref_Id: input.Ref_Id}, &event, nil) + // if err != nil { + // return nil, err + // } + + // map template data + // gc + // templateData := GeneralConsentPDF{} + // gcUnmarshalled := json.Unmarshal(g) + + return nil, nil + } + + return nil, nil +} diff --git a/internal/use-case/main-use-case/generate-file/tycovar.go b/internal/use-case/main-use-case/generate-file/tycovar.go new file mode 100644 index 00000000..716e277d --- /dev/null +++ b/internal/use-case/main-use-case/generate-file/tycovar.go @@ -0,0 +1,25 @@ +package generatefile + +import ( + erc "simrs-vx/internal/domain/references/common" + ere "simrs-vx/internal/domain/references/encounter" +) + +type GeneralConsentPDF struct { + PatientRelatives_Name []string `json:"patientRelatives_name"` + Responsible_Name string `json:"responsible_name"` + InformationGivenBy_Name string `json:"informationGivenBy_name"` + Witness1_Name string `json:"witness1_name"` + Witness2_Name string `json:"witness2_name"` +} + +type GenerateDto struct { + EntityType_Code ere.EntityTypeCode `form:"entityType_code"` + Ref_Id *uint `form:"ref_id"` + Type_Code ere.DocTypeCode `form:"type_code"` + FormatType erc.DocFormatTypeCode `form:"formatType"` +} + +type ResponseDto struct { + FileUrl string `json:"fileUrl"` +} From f9bb097a500c32a841a1716d7574a2b2a68dadf2 Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 17 Nov 2025 16:27:06 +0700 Subject: [PATCH 217/329] add mpolihfis --- .../domain/simgos-entities/specialist/entity.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 internal/domain/simgos-entities/specialist/entity.go diff --git a/internal/domain/simgos-entities/specialist/entity.go b/internal/domain/simgos-entities/specialist/entity.go new file mode 100644 index 00000000..b9eb7b56 --- /dev/null +++ b/internal/domain/simgos-entities/specialist/entity.go @@ -0,0 +1,15 @@ +package division + +type MPolihfis struct { + Id uint `json:"id" gorm:"primaryKey;autoIncrement;column:id"` + Code string `json:"code" gorm:"column:code"` + Poliklinik string `json:"poliklinik" gorm:"column:poliklinik"` + CodePolirs string `json:"code_polirs" gorm:"column:code_polirs"` + Poliklinikrs string `json:"poliklinikrs" gorm:"column:poliklinikrs"` + Active uint `json:"active" gorm:"column:active"` + Status uint `json:"status" gorm:"column:status"` +} + +func (MPolihfis) TableName() string { + return "m_polihfis" +} From 69a13dd37d517d1b5a6ba5073907842a7d2cadc2 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 17 Nov 2025 17:18:22 +0700 Subject: [PATCH 218/329] feat (generate-file): not tested yet --- go.mod | 1 + go.sum | 2 + .../main-handler/generate-file/handler.go | 18 +++ .../interface/main-handler/main-handler.go | 2 + .../main-use-case/generate-file/case.go | 64 +++++++-- .../main-use-case/generate-file/helper.go | 83 +++++++++++ .../main-use-case/generate-file/tycovar.go | 22 ++- pkg/file-helper/file-helper.go | 33 +++++ pkg/pdf-helper/pdf-helper.go | 131 ++++++++++++++++++ 9 files changed, 340 insertions(+), 16 deletions(-) create mode 100644 internal/interface/main-handler/generate-file/handler.go create mode 100644 internal/use-case/main-use-case/generate-file/helper.go create mode 100644 pkg/file-helper/file-helper.go create mode 100644 pkg/pdf-helper/pdf-helper.go diff --git a/go.mod b/go.mod index 9d557637..b44bb011 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( require ( ariga.io/atlas v0.36.2-0.20250806044935-5bb51a0a956e // indirect + github.com/SebastiaanKlippert/go-wkhtmltopdf v1.9.3 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/go-ini/ini v1.67.0 // indirect github.com/go-redis/redis v6.15.9+incompatible // indirect diff --git a/go.sum b/go.sum index 9681a749..da70ac51 100644 --- a/go.sum +++ b/go.sum @@ -19,6 +19,8 @@ github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0/go.mod h github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/SebastiaanKlippert/go-wkhtmltopdf v1.9.3 h1:vrA6+R1BMLKMTbos8jAeuBrImHPGtY4gTlcue3OIej8= +github.com/SebastiaanKlippert/go-wkhtmltopdf v1.9.3/go.mod h1:SQq4xfIdvf6WYKSDxAJc+xOJdolt+/bc1jnQKMtPMvQ= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= diff --git a/internal/interface/main-handler/generate-file/handler.go b/internal/interface/main-handler/generate-file/handler.go new file mode 100644 index 00000000..c6d6c67d --- /dev/null +++ b/internal/interface/main-handler/generate-file/handler.go @@ -0,0 +1,18 @@ +package generatefile + +import ( + "net/http" + + rw "github.com/karincake/risoles" + + u "simrs-vx/internal/use-case/main-use-case/generate-file" +) + +func Generate(w http.ResponseWriter, r *http.Request) { + dto := u.GenerateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Generate(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 8ce9fadf..4a49c022 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -18,6 +18,7 @@ import ( encounter "simrs-vx/internal/interface/main-handler/encounter" encounterdocument "simrs-vx/internal/interface/main-handler/encounter-document" generalconsent "simrs-vx/internal/interface/main-handler/general-consent" + generatefile "simrs-vx/internal/interface/main-handler/generate-file" internalreference "simrs-vx/internal/interface/main-handler/internal-reference" materialorder "simrs-vx/internal/interface/main-handler/material-order" materialorderitem "simrs-vx/internal/interface/main-handler/material-order-item" @@ -280,6 +281,7 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/upload-file", uploadfile.O) hc.RegCrud(r, "/v1/encounter-document", encounterdocument.O) hc.RegCrud(r, "/v1/general-consent", generalconsent.O) + r.HandleFunc("POST /v1/generate-file", generatefile.Generate) /******************** actor ********************/ hc.RegCrud(r, "/v1/person", person.O) diff --git a/internal/use-case/main-use-case/generate-file/case.go b/internal/use-case/main-use-case/generate-file/case.go index 72182513..c39a7edc 100644 --- a/internal/use-case/main-use-case/generate-file/case.go +++ b/internal/use-case/main-use-case/generate-file/case.go @@ -1,15 +1,18 @@ package generatefile import ( - // "encoding/json" + "encoding/json" + "errors" - // egc "simrs-vx/internal/domain/main-entities/general-consent" - // ugc "simrs-vx/internal/use-case/main-use-case/general-consent" + egc "simrs-vx/internal/domain/main-entities/general-consent" + ugc "simrs-vx/internal/use-case/main-use-case/general-consent" pl "simrs-vx/pkg/logger" + dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" + erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" ) @@ -28,18 +31,55 @@ func Generate(input GenerateDto) (*d.Data, error) { // general-consent case ere.DTCGC: // get value from general consent by ref_id - // gc, err := ugc.ReadDetailData(ugc.ReadDetailDto{Ref_Id: input.Ref_Id}, &event, nil) - // if err != nil { - // return nil, err - // } + gc, err := ugc.ReadDetailData(egc.ReadDetailDto{Id: *input.Ref_Id}, &event, nil) + if err != nil { + return nil, err + } // map template data - // gc - // templateData := GeneralConsentPDF{} - // gcUnmarshalled := json.Unmarshal(g) + templateData := GeneralConsentPDF{} + if gc.Value != nil { + err := json.Unmarshal([]byte(*gc.Value), &templateData) + if err != nil { + event.ErrInfo = pl.ErrorInfo{ + Code: "data-unmarshal-fail", + Detail: err.Error(), + Raw: err, + } + return nil, err + } + } else { + return nil, errors.New("no value in this general consent") + } - return nil, nil + input.FormatType = erc.DFTCPDF + input.TemplateName = TDNGC + + // generate file + urlPub, err := generateFile(input, templateData) + if err != nil { + return nil, err + } + + gc.FileUrl = &urlPub + if err := dg.I.Save(&gc).Error; err != nil { + return nil, err + } + + response := ResponseDto{ + FileUrl: urlPub, + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: response, + }, nil + default: + return nil, errors.New("invalid type code") } - return nil, nil } diff --git a/internal/use-case/main-use-case/generate-file/helper.go b/internal/use-case/main-use-case/generate-file/helper.go new file mode 100644 index 00000000..ec377dc2 --- /dev/null +++ b/internal/use-case/main-use-case/generate-file/helper.go @@ -0,0 +1,83 @@ +package generatefile + +import ( + "errors" + "fmt" + "mime" + "path/filepath" + "time" + + erc "simrs-vx/internal/domain/references/common" + docscfg "simrs-vx/internal/infra/docs-cfg" + pf "simrs-vx/pkg/file-helper" + pm "simrs-vx/pkg/minio-helper" + pp "simrs-vx/pkg/pdf-helper" +) + +// generate temporary file, upload to minio, generate public url, delete temporary file +func generateFile(input GenerateDto, templateData any) (string, error) { + newPath, err := pf.PathToSaveFile(fmt.Sprintf("./public/%s/%d/%s", input.EntityType_Code, *input.Ref_Id, input.Type_Code)) + if err != nil { + return "", err + } + + fPath := fmt.Sprintf("%s/%s_%s.%s", newPath, input.Type_Code, time.Now().Format("20060102150405"), input.FormatType) + + templatePath := docscfg.O.GetPath() + string(input.TemplateName) + + switch input.FormatType { + case erc.DFTCPDF: + if err := generatePDF(GeneratePDFdto{ + TemplatePath: templatePath, + TemplateData: templateData, + PdfPath: fPath, + }); err != nil { + return "", err + } + case erc.DFTCTXLSX: + // TODO: generate xlsx + case erc.DFTCTCSV: + // TODO: generate csv + default: + return "", errors.New("invalid format type") + } + + bucketName := input.EntityType_Code + + objectName := fmt.Sprintf("%v/%s-%d", *input.Ref_Id, input.Type_Code, time.Now().UnixNano()) + pdfUpload := pm.UploadPathInput{ + BucketName: string(bucketName), + Name: objectName, + Path: fPath, + ContentType: mime.TypeByExtension(filepath.Ext(fPath)), + } + + // create bucket if not exist, create object in bucket + info, err := pm.I.FPutObject(pdfUpload) + if err != nil { + return "", err + } + + // generate public url + urlPub := pm.I.GenerateUrl(info.Bucket, info.Key) + if err := pf.DeleteFolder(fPath); err != nil { + return "", err + } + + return urlPub, nil +} + +func generatePDF(input GeneratePDFdto) error { + // parse template data into html template + r := pp.NewRequestPdf("") + if err := r.ParseTemplate(input.TemplatePath, input.TemplateData); err == nil { + _, err := r.GenerateByCommand(input.PdfPath, input.TemplatePath) + if err != nil { + return errors.New("generate pdf by command error : " + err.Error()) + } + } else { + return errors.New("parse template error : " + err.Error()) + } + + return nil +} diff --git a/internal/use-case/main-use-case/generate-file/tycovar.go b/internal/use-case/main-use-case/generate-file/tycovar.go index 716e277d..17c5abc1 100644 --- a/internal/use-case/main-use-case/generate-file/tycovar.go +++ b/internal/use-case/main-use-case/generate-file/tycovar.go @@ -14,12 +14,26 @@ type GeneralConsentPDF struct { } type GenerateDto struct { - EntityType_Code ere.EntityTypeCode `form:"entityType_code"` - Ref_Id *uint `form:"ref_id"` - Type_Code ere.DocTypeCode `form:"type_code"` - FormatType erc.DocFormatTypeCode `form:"formatType"` + EntityType_Code ere.EntityTypeCode `json:"entityType_code"` + Ref_Id *uint `json:"ref_id"` + Type_Code ere.DocTypeCode `json:"type_code"` + FormatType erc.DocFormatTypeCode `json:"formatType"` + TemplateName TemplateDocsName `json:"-"` +} + +type GeneratePDFdto struct { + TemplatePath string + TemplateData any + PdfPath string } type ResponseDto struct { FileUrl string `json:"fileUrl"` } + +type TemplateDocsName string + +// TemplateDocsName is the name of the template file in the assets/docs folder +const ( + TDNGC TemplateDocsName = "general-consent.html" +) diff --git a/pkg/file-helper/file-helper.go b/pkg/file-helper/file-helper.go new file mode 100644 index 00000000..bd0849c7 --- /dev/null +++ b/pkg/file-helper/file-helper.go @@ -0,0 +1,33 @@ +package filehelper + +import ( + "fmt" + "os" + "path/filepath" +) + +// const DEFAULT_EXPIRY_FILES = time.Hour * 24 * 7 + +func PathAgreement(medicalNumber string) (string, error) { + outputPath := fmt.Sprintf("./public/patient/%s", medicalNumber) + err := os.MkdirAll(outputPath, os.ModePerm) + return outputPath, err +} + +func PathToSaveFile(outputPath string) (string, error) { + err := os.MkdirAll(outputPath, os.ModePerm) + return outputPath, err +} + +func RenameFile(srcPath, dstPath string) error { + return os.Rename(srcPath, dstPath) +} + +func DeleteFolder(path string) error { + return os.RemoveAll(path) +} + +func PathToUrl(fileName string) *string { + fileUrl := filepath.ToSlash(fmt.Sprintf("%c%s", os.PathSeparator, fileName)) + return &fileUrl +} diff --git a/pkg/pdf-helper/pdf-helper.go b/pkg/pdf-helper/pdf-helper.go new file mode 100644 index 00000000..597052eb --- /dev/null +++ b/pkg/pdf-helper/pdf-helper.go @@ -0,0 +1,131 @@ +package pdfhelper + +import ( + "bytes" + "html/template" + "log" + "os" + "os/exec" + "strconv" + "strings" + "time" + + "github.com/SebastiaanKlippert/go-wkhtmltopdf" +) + +// pdf requestpdf struct +type RequestPdf struct { + body string +} + +// new request to pdf function +func NewRequestPdf(body string) *RequestPdf { + return &RequestPdf{ + body: body, + } +} + +// parsing template function +func (r *RequestPdf) ParseTemplate(templatePath string, data interface{}) error { + f := strings.Split(templatePath, "/") + fileName := f[len(f)-1] + funcs := template.FuncMap{ + "nl2br": func(text string) template.HTML { + return template.HTML(strings.Replace(template.HTMLEscapeString(text), "\n", "
", -1)) + }, + } + t, err := template.New(fileName).Funcs(funcs).ParseFiles(templatePath) + if err != nil { + return err + } + buf := new(bytes.Buffer) + if err = t.Execute(buf, data); err != nil { + return err + } + r.body = buf.String() + + return nil +} + +func (r *RequestPdf) GenerateByCommand(pdfPath string, templatePath string) (bool, error) { + // wkhtmltopdf -L 0 -R 0 -B 0 -s Legal --enable-local-file-access resultAntigen2.html out.pdf + t := time.Now().Unix() + + if _, err := os.Stat("cloneTemplate/"); os.IsNotExist(err) { + errDir := os.Mkdir("cloneTemplate/", 0777) + if errDir != nil { + log.Fatal(errDir) + } + } + htmlName := strconv.FormatInt(int64(t), 10) + ".html" + err := os.WriteFile("cloneTemplate/"+htmlName, []byte(r.body), 0644) + if err != nil { + panic(err) + } + + cmd := exec.Command("wkhtmltopdf", "--enable-local-file-access", "-L", "0", "-R", "0", "-B", "0", "-s", "A4", "cloneTemplate/"+htmlName, pdfPath) + + if err := cmd.Run(); err != nil { + return false, err + } + dir, err := os.Getwd() + if err != nil { + panic(err) + } + defer os.RemoveAll(dir + "/cloneTemplate") + return true, nil +} + +// generate pdf function +func (r *RequestPdf) GeneratePDF(pdfPath string) (bool, error) { + t := time.Now().Unix() + + if _, err := os.Stat("cloneTemplate/"); os.IsNotExist(err) { + errDir := os.Mkdir("cloneTemplate/", 0777) + if errDir != nil { + log.Fatal(errDir) + } + } + err1 := os.WriteFile("cloneTemplate/"+strconv.FormatInt(int64(t), 10)+".html", []byte(r.body), 0644) + if err1 != nil { + panic(err1) + } + + f, err := os.Open("cloneTemplate/" + strconv.FormatInt(int64(t), 10) + ".html") + if f != nil { + defer f.Close() + } + if err != nil { + log.Fatal(err) + } + + pdfg, err := wkhtmltopdf.NewPDFGenerator() + if err != nil { + log.Fatal(err) + } + + pdfg.AddPage(wkhtmltopdf.NewPageReader(f)) + + pdfg.PageSize.Set(wkhtmltopdf.PageSizeA4) + + pdfg.Dpi.Set(300) + + err = pdfg.Create() + if err != nil { + log.Fatal(err) + } + + err = pdfg.WriteFile(pdfPath) + if err != nil { + log.Fatal(err) + } + + dir, err := os.Getwd() + if err != nil { + panic(err) + } + + defer os.RemoveAll(dir + "/cloneTemplate") + + return true, nil +} From c8e17619d8f2860d44b137bf7b76281623251bed Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 17 Nov 2025 17:34:17 +0700 Subject: [PATCH 219/329] feat (generate-file): add validation --- internal/use-case/main-use-case/generate-file/tycovar.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/use-case/main-use-case/generate-file/tycovar.go b/internal/use-case/main-use-case/generate-file/tycovar.go index 17c5abc1..b5d09ceb 100644 --- a/internal/use-case/main-use-case/generate-file/tycovar.go +++ b/internal/use-case/main-use-case/generate-file/tycovar.go @@ -14,9 +14,9 @@ type GeneralConsentPDF struct { } type GenerateDto struct { - EntityType_Code ere.EntityTypeCode `json:"entityType_code"` - Ref_Id *uint `json:"ref_id"` - Type_Code ere.DocTypeCode `json:"type_code"` + EntityType_Code ere.EntityTypeCode `json:"entityType_code" validate:"required"` + Ref_Id *uint `json:"ref_id" validate:"required"` + Type_Code ere.DocTypeCode `json:"type_code" validate:"required"` FormatType erc.DocFormatTypeCode `json:"formatType"` TemplateName TemplateDocsName `json:"-"` } From e8fbd042b67f0ff5a37667eac633e9dc333a472d Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 17 Nov 2025 18:59:45 +0700 Subject: [PATCH 220/329] add specialist and subspecialist --- .../domain/main-entities/specialist/dto.go | 1 + .../domain/main-entities/subspecialist/dto.go | 1 + .../simgos-sync-handler.go | 4 + .../simgos-sync-handler/specialist/handler.go | 66 ++++++ .../subspecialist/handler.go | 66 ++++++ .../use-case/main-use-case/division/case.go | 9 +- .../use-case/main-use-case/specialist/case.go | 101 +++++---- .../specialist/middleware-runner.go | 38 +++- .../main-use-case/specialist/middleware.go | 23 +- .../main-use-case/specialist/tycovar.go | 31 ++- .../main-use-case/subspecialist/case.go | 91 +++++--- .../subspecialist/middleware-runner.go | 37 ++- .../main-use-case/subspecialist/tycovar.go | 32 ++- .../simgos-sync-plugin/specialist/plugin.go | 167 ++++++++++++++ .../subspecialist/plugin.go | 167 ++++++++++++++ .../simgos-sync-use-case/specialist/case.go | 214 ++++++++++++++++++ .../simgos-sync-use-case/specialist/helper.go | 60 +++++ .../simgos-sync-use-case/specialist/lib.go | 188 +++++++++++++++ .../specialist/middleware-runner.go | 104 +++++++++ .../specialist/middleware.go | 9 + .../specialist/tycovar.go | 44 ++++ .../subspecialist/case.go | 214 ++++++++++++++++++ .../subspecialist/helper.go | 59 +++++ .../simgos-sync-use-case/subspecialist/lib.go | 187 +++++++++++++++ .../subspecialist/middleware-runner.go | 104 +++++++++ .../subspecialist/middleware.go | 9 + .../subspecialist/tycovar.go | 44 ++++ 27 files changed, 1948 insertions(+), 122 deletions(-) create mode 100644 internal/interface/simgos-sync-handler/specialist/handler.go create mode 100644 internal/interface/simgos-sync-handler/subspecialist/handler.go create mode 100644 internal/use-case/simgos-sync-plugin/specialist/plugin.go create mode 100644 internal/use-case/simgos-sync-plugin/subspecialist/plugin.go create mode 100644 internal/use-case/simgos-sync-use-case/specialist/case.go create mode 100644 internal/use-case/simgos-sync-use-case/specialist/helper.go create mode 100644 internal/use-case/simgos-sync-use-case/specialist/lib.go create mode 100644 internal/use-case/simgos-sync-use-case/specialist/middleware-runner.go create mode 100644 internal/use-case/simgos-sync-use-case/specialist/middleware.go create mode 100644 internal/use-case/simgos-sync-use-case/specialist/tycovar.go create mode 100644 internal/use-case/simgos-sync-use-case/subspecialist/case.go create mode 100644 internal/use-case/simgos-sync-use-case/subspecialist/helper.go create mode 100644 internal/use-case/simgos-sync-use-case/subspecialist/lib.go create mode 100644 internal/use-case/simgos-sync-use-case/subspecialist/middleware-runner.go create mode 100644 internal/use-case/simgos-sync-use-case/subspecialist/middleware.go create mode 100644 internal/use-case/simgos-sync-use-case/subspecialist/tycovar.go diff --git a/internal/domain/main-entities/specialist/dto.go b/internal/domain/main-entities/specialist/dto.go index a67a830f..2d656556 100644 --- a/internal/domain/main-entities/specialist/dto.go +++ b/internal/domain/main-entities/specialist/dto.go @@ -8,6 +8,7 @@ import ( ) type CreateDto struct { + Id *uint `json:"id"` Code string `json:"code" validate:"maxLength=10"` Name string `json:"name" validate:"maxLength=50"` Unit_Code *string `json:"unit_code"` diff --git a/internal/domain/main-entities/subspecialist/dto.go b/internal/domain/main-entities/subspecialist/dto.go index 6e10b573..72959023 100644 --- a/internal/domain/main-entities/subspecialist/dto.go +++ b/internal/domain/main-entities/subspecialist/dto.go @@ -7,6 +7,7 @@ import ( ) type CreateDto struct { + Id *uint `json:"id"` Code string `json:"code" validate:"maxLength=10"` Name string `json:"name" validate:"maxLength=50"` Specialist_Code *string `json:"specialist_code"` diff --git a/internal/interface/simgos-sync-handler/simgos-sync-handler.go b/internal/interface/simgos-sync-handler/simgos-sync-handler.go index 590d7b9d..6b63e1d6 100644 --- a/internal/interface/simgos-sync-handler/simgos-sync-handler.go +++ b/internal/interface/simgos-sync-handler/simgos-sync-handler.go @@ -19,6 +19,8 @@ import ( "simrs-vx/internal/interface/main-handler/home" division "simrs-vx/internal/interface/simgos-sync-handler/division" installation "simrs-vx/internal/interface/simgos-sync-handler/installation" + specialist "simrs-vx/internal/interface/simgos-sync-handler/specialist" + subspecialist "simrs-vx/internal/interface/simgos-sync-handler/subspecialist" unit "simrs-vx/internal/interface/simgos-sync-handler/unit" ) @@ -39,6 +41,8 @@ func SetRoutes() http.Handler { hc.SyncCrud(r, prefix+"/v1/installation", installation.O) hc.SyncCrud(r, prefix+"/v1/unit", unit.O) hc.SyncCrud(r, prefix+"/v1/division", division.O) + hc.SyncCrud(r, prefix+"/v1/specialist", specialist.O) + hc.SyncCrud(r, prefix+"/v1/subspecialist", subspecialist.O) return cmw.SetCors(handlerlogger.SetLog(r)) } diff --git a/internal/interface/simgos-sync-handler/specialist/handler.go b/internal/interface/simgos-sync-handler/specialist/handler.go new file mode 100644 index 00000000..79289472 --- /dev/null +++ b/internal/interface/simgos-sync-handler/specialist/handler.go @@ -0,0 +1,66 @@ +package specialist + +import ( + "net/http" + + rw "github.com/karincake/risoles" + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/specialist" + esync "simrs-vx/internal/domain/sync-entities/log" + u "simrs-vx/internal/use-case/simgos-sync-use-case/specialist" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + 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) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + + val := uint16(id) + dto.Id = &val + + 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{} + val := uint16(id) + dto.Id = &val + + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/simgos-sync-handler/subspecialist/handler.go b/internal/interface/simgos-sync-handler/subspecialist/handler.go new file mode 100644 index 00000000..fcd03c6b --- /dev/null +++ b/internal/interface/simgos-sync-handler/subspecialist/handler.go @@ -0,0 +1,66 @@ +package subspecialist + +import ( + "net/http" + + rw "github.com/karincake/risoles" + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/subspecialist" + esync "simrs-vx/internal/domain/sync-entities/log" + u "simrs-vx/internal/use-case/simgos-sync-use-case/subspecialist" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + 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) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + + val := uint16(id) + dto.Id = &val + + 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{} + val := uint16(id) + dto.Id = &val + + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/use-case/main-use-case/division/case.go b/internal/use-case/main-use-case/division/case.go index 4be7ce82..8f2e8488 100644 --- a/internal/use-case/main-use-case/division/case.go +++ b/internal/use-case/main-use-case/division/case.go @@ -1,18 +1,19 @@ package division import ( - e "simrs-vx/internal/domain/main-entities/division" - erc "simrs-vx/internal/domain/references/common" - esync "simrs-vx/internal/domain/sync-entities/log" "strconv" dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" + "gorm.io/gorm" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" - "gorm.io/gorm" + erc "simrs-vx/internal/domain/references/common" + + e "simrs-vx/internal/domain/main-entities/division" + esync "simrs-vx/internal/domain/sync-entities/log" ) const source = "division" diff --git a/internal/use-case/main-use-case/specialist/case.go b/internal/use-case/main-use-case/specialist/case.go index c51a0002..f9f5442b 100644 --- a/internal/use-case/main-use-case/specialist/case.go +++ b/internal/use-case/main-use-case/specialist/case.go @@ -1,7 +1,6 @@ package specialist import ( - e "simrs-vx/internal/domain/main-entities/specialist" "strconv" dg "github.com/karincake/apem/db-gorm-pg" @@ -11,6 +10,11 @@ import ( pu "simrs-vx/pkg/use-case-helper" "gorm.io/gorm" + + erc "simrs-vx/internal/domain/references/common" + + e "simrs-vx/internal/domain/main-entities/specialist" + esync "simrs-vx/internal/domain/sync-entities/log" ) const source = "specialist" @@ -25,36 +29,32 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") + mwRunner := newMiddlewareRunner(&event) 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 resData, err := CreateData(input, &event, tx); err != nil { return err } else { data = *resData + id := uint(data.Id) + input.Id = &id } - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input); err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") - return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.II{ "source": source, @@ -80,7 +80,7 @@ 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 := newMiddlewareRunner(&event) mwRunner.setMwType(pu.MWTPre) // Run pre-middleware if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { @@ -131,7 +131,7 @@ 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 := newMiddlewareRunner(&event) mwRunner.setMwType(pu.MWTPre) // Run pre-middleware if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { @@ -177,6 +177,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "update") + mwRunner := newMiddlewareRunner(&event) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -184,32 +185,26 @@ 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 - } - + input.Id = &data.Id if err := UpdateData(input, data, &event, tx); err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") - - 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.RunUpdateMiddleware(updatePreMw, &input); err != nil { return err } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -233,6 +228,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "delete") + mwRunner := newMiddlewareRunner(&event) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -240,30 +236,26 @@ 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 - } - + input.Id = &data.Id 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.RunDeleteMiddleware(deletePreMw, &input); err != nil { return err } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -274,3 +266,32 @@ func Delete(input e.DeleteDto) (*d.Data, error) { }, nil } + +func runLogMiddleware(err error, input any, mwRunner *middlewareRunner) error { + var errMsg string + inputLog := esync.SimxLogDto{ + Payload: input, + Method: erc.CCCreate, + } + + if err != nil { + // Run log-middleware + errMsg = err.Error() + inputLog.ErrMessage = &errMsg + inputLog.IsSuccess = false + + // create log failed + if errMiddleware := mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog); errMiddleware != nil { + return errMiddleware + } + return err + } + + // create log success + inputLog.IsSuccess = true + if err = mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog); err != nil { + return err + } + + return nil +} 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 4aa6cdd4..c937d2bc 100644 --- a/internal/use-case/main-use-case/specialist/middleware-runner.go +++ b/internal/use-case/main-use-case/specialist/middleware-runner.go @@ -2,6 +2,7 @@ package specialist import ( e "simrs-vx/internal/domain/main-entities/specialist" + esync "simrs-vx/internal/domain/sync-entities/log" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -15,21 +16,36 @@ type middlewareRunner struct { } // NewMiddlewareExecutor creates a new middleware executor -func newMiddlewareRunner(event *pl.Event, tx *gorm.DB) *middlewareRunner { +func newMiddlewareRunner(event *pl.Event) *middlewareRunner { return &middlewareRunner{ Event: event, - Tx: tx, } } // ExecuteCreateMiddleware executes create middleware -func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.Specialist) error { +func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto) 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 +} + +// ExecuteCreateMiddleware executes createlog middleware +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 +84,13 @@ func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, return nil } -func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Specialist) error { +func (me *middlewareRunner) RunUpdateMiddleware(middlewares []updateMw, input *e.UpdateDto) 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 +99,13 @@ func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, inpu return nil } -func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Specialist) 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) } diff --git a/internal/use-case/main-use-case/specialist/middleware.go b/internal/use-case/main-use-case/specialist/middleware.go index 298e51a8..5d119b01 100644 --- a/internal/use-case/main-use-case/specialist/middleware.go +++ b/internal/use-case/main-use-case/specialist/middleware.go @@ -1,9 +1,20 @@ package specialist +import ( + plugin "simrs-vx/internal/use-case/simgos-sync-plugin/specialist" +) + // example of middleware -// func init() { -// createPreMw = append(createPreMw, -// CreateMw{Name: "modif-input", Func: pm.ModifInput}, -// CreateMw{Name: "check-data", Func: pm.CheckData}, -// ) -// } +func init() { + createPreMw = append(createPreMw, + createMw{Name: "create-unit", Func: plugin.Create}) + + createSimxLogMw = append(createSimxLogMw, + createLogMw{Name: "create-log", Func: plugin.CreateLog}) + + updatePreMw = append(updatePreMw, + updateMw{Name: "update-unit", Func: plugin.Update}) + + deletePreMw = append(deletePreMw, + deleteMw{Name: "delete-unit", Func: plugin.Delete}) +} diff --git a/internal/use-case/main-use-case/specialist/tycovar.go b/internal/use-case/main-use-case/specialist/tycovar.go index 16fa50b0..d0755799 100644 --- a/internal/use-case/main-use-case/specialist/tycovar.go +++ b/internal/use-case/main-use-case/specialist/tycovar.go @@ -12,11 +12,27 @@ import ( "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/specialist" + elog "simrs-vx/internal/domain/sync-entities/log" ) type createMw struct { Name string - Func func(input *e.CreateDto, data *e.Specialist, tx *gorm.DB) error + Func func(input *e.CreateDto) error +} + +type createLogMw struct { + Name string + Func func(input *elog.SimxLogDto) error +} + +type updateMw struct { + Name string + Func func(input *e.UpdateDto) error +} + +type deleteMw struct { + Name string + Func func(input *e.DeleteDto) error } type readListMw struct { @@ -29,16 +45,17 @@ type readDetailMw struct { Func func(input *e.ReadDetailDto, data *e.Specialist, 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 +var createPreMw []createMw // preprocess middleware +var createPostMw []createMw // postprocess middleware +var createSimxLogMw []createLogMw 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 diff --git a/internal/use-case/main-use-case/subspecialist/case.go b/internal/use-case/main-use-case/subspecialist/case.go index 51509c47..ca99750d 100644 --- a/internal/use-case/main-use-case/subspecialist/case.go +++ b/internal/use-case/main-use-case/subspecialist/case.go @@ -2,6 +2,8 @@ package subspecialist import ( e "simrs-vx/internal/domain/main-entities/subspecialist" + erc "simrs-vx/internal/domain/references/common" + esync "simrs-vx/internal/domain/sync-entities/log" "strconv" dg "github.com/karincake/apem/db-gorm-pg" @@ -25,36 +27,32 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") + mwRunner := newMiddlewareRunner(&event) 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 resData, err := CreateData(input, &event, tx); err != nil { return err } else { data = *resData + id := uint(data.Id) + input.Id = &id } - mwRunner.setMwType(pu.MWTPost) + mwRunner.setMwType(pu.MWTPre) // Run post-middleware - if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + if err := mwRunner.RunCreateMiddleware(createPreMw, &input); err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") - return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.II{ "source": source, @@ -80,7 +78,7 @@ 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 := newMiddlewareRunner(&event) mwRunner.setMwType(pu.MWTPre) // Run pre-middleware if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { @@ -131,7 +129,7 @@ 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 := newMiddlewareRunner(&event) mwRunner.setMwType(pu.MWTPre) // Run pre-middleware if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { @@ -177,6 +175,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "update") + mwRunner := newMiddlewareRunner(&event) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -184,32 +183,26 @@ 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 - } - + input.Id = &data.Id if err := UpdateData(input, data, &event, tx); err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") - - mwRunner.setMwType(pu.MWTPost) + mwRunner.setMwType(pu.MWTPre) // Run post-middleware - if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + if err := mwRunner.RunUpdateMiddleware(updatePreMw, &input); err != nil { return err } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -233,6 +226,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "delete") + mwRunner := newMiddlewareRunner(&event) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -240,30 +234,26 @@ 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 - } - + input.Id = &data.Id if err := DeleteData(data, &event, tx); err != nil { return err } - mwRunner.setMwType(pu.MWTPost) + mwRunner.setMwType(pu.MWTPre) // Run post-middleware - if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + if err := mwRunner.RunDeleteMiddleware(deletePreMw, &input); err != nil { return err } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -274,3 +264,32 @@ func Delete(input e.DeleteDto) (*d.Data, error) { }, nil } + +func runLogMiddleware(err error, input any, mwRunner *middlewareRunner) error { + var errMsg string + inputLog := esync.SimxLogDto{ + Payload: input, + Method: erc.CCCreate, + } + + if err != nil { + // Run log-middleware + errMsg = err.Error() + inputLog.ErrMessage = &errMsg + inputLog.IsSuccess = false + + // create log failed + if errMiddleware := mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog); errMiddleware != nil { + return errMiddleware + } + return err + } + + // create log success + inputLog.IsSuccess = true + if err = mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog); err != nil { + return err + } + + return nil +} 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 c7e5f285..065e5ecc 100644 --- a/internal/use-case/main-use-case/subspecialist/middleware-runner.go +++ b/internal/use-case/main-use-case/subspecialist/middleware-runner.go @@ -2,6 +2,7 @@ package subspecialist import ( e "simrs-vx/internal/domain/main-entities/subspecialist" + esync "simrs-vx/internal/domain/sync-entities/log" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -15,21 +16,35 @@ type middlewareRunner struct { } // NewMiddlewareExecutor creates a new middleware executor -func newMiddlewareRunner(event *pl.Event, tx *gorm.DB) *middlewareRunner { +func newMiddlewareRunner(event *pl.Event) *middlewareRunner { return &middlewareRunner{ Event: event, - Tx: tx, } } // ExecuteCreateMiddleware executes create middleware -func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.Subspecialist) error { +func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto) 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 +83,13 @@ func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, return nil } -func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Subspecialist) error { +func (me *middlewareRunner) RunUpdateMiddleware(middlewares []updateMw, input *e.UpdateDto) 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 +98,13 @@ func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, inpu return nil } -func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Subspecialist) 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) } diff --git a/internal/use-case/main-use-case/subspecialist/tycovar.go b/internal/use-case/main-use-case/subspecialist/tycovar.go index ed4540b8..cd26e517 100644 --- a/internal/use-case/main-use-case/subspecialist/tycovar.go +++ b/internal/use-case/main-use-case/subspecialist/tycovar.go @@ -9,6 +9,8 @@ functionality. The purpose of this is to make the code more maintainable. package subspecialist import ( + elog "simrs-vx/internal/domain/sync-entities/log" + "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/subspecialist" @@ -16,7 +18,22 @@ import ( type createMw struct { Name string - Func func(input *e.CreateDto, data *e.Subspecialist, tx *gorm.DB) error + Func func(input *e.CreateDto) error +} + +type createLogMw struct { + Name string + Func func(input *elog.SimxLogDto) error +} + +type updateMw struct { + Name string + Func func(input *e.UpdateDto) error +} + +type deleteMw struct { + Name string + Func func(input *e.DeleteDto) error } type readListMw struct { @@ -29,16 +46,17 @@ type readDetailMw struct { Func func(input *e.ReadDetailDto, data *e.Subspecialist, 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 +var createPreMw []createMw // preprocess middleware +var createPostMw []createMw // postprocess middleware +var createSimxLogMw []createLogMw 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 diff --git a/internal/use-case/simgos-sync-plugin/specialist/plugin.go b/internal/use-case/simgos-sync-plugin/specialist/plugin.go new file mode 100644 index 00000000..892d7a17 --- /dev/null +++ b/internal/use-case/simgos-sync-plugin/specialist/plugin.go @@ -0,0 +1,167 @@ +package specialist + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + + sync "simrs-vx/internal/infra/sync-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 +} + +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 +} + +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 +} + +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 +} + +func getPrefixEndpoint() string { + return fmt.Sprintf("%s%s/v1/specialist", sync.O.Host, sync.O.Prefix) +} diff --git a/internal/use-case/simgos-sync-plugin/subspecialist/plugin.go b/internal/use-case/simgos-sync-plugin/subspecialist/plugin.go new file mode 100644 index 00000000..15d6f650 --- /dev/null +++ b/internal/use-case/simgos-sync-plugin/subspecialist/plugin.go @@ -0,0 +1,167 @@ +package subspecialist + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + + sync "simrs-vx/internal/infra/sync-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 +} + +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 +} + +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 +} + +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 +} + +func getPrefixEndpoint() string { + return fmt.Sprintf("%s%s/v1/subspecialist", sync.O.Host, sync.O.Prefix) +} diff --git a/internal/use-case/simgos-sync-use-case/specialist/case.go b/internal/use-case/simgos-sync-use-case/specialist/case.go new file mode 100644 index 00000000..4e6de31d --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/specialist/case.go @@ -0,0 +1,214 @@ +package specialist + +import ( + pl "simrs-vx/pkg/logger" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/specialist" + esimgos "simrs-vx/internal/domain/simgos-entities/specialist" + esync "simrs-vx/internal/domain/sync-entities/log" +) + +const source = "specialist" + +func Create(input e.CreateDto) (*d.Data, error) { + var ( + txSync = dg.I.Begin() + txSimgos = dg.IS["simrs"].Begin() + ) + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + // STEP 1: Insert to simgos + sgData, err := CreateSimgosData(input, &event, txSimgos) + if err != nil { + return nil, err + } + + // STEP 2: Insert to Link + syncLink, err := CreateLinkData(*input.Id, sgData.Id, &event, txSync) + if err != nil { + txSimgos.Rollback() + return nil, err + } + + // STEP 3: Commit two trx + if err = txSync.Commit().Error; err != nil { + txSync.Rollback() + txSimgos.Rollback() + return nil, err + } + + if err = txSimgos.Commit().Error; err != nil { + // STEP 4: Rollback Partial + 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 esync.SimxLogDto) (*d.Data, error) { + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + err := dg.I.Transaction(func(tx *gorm.DB) error { + // InsertSimxLog + if err := CreateLogData(input, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + 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.UpdateDto) (*d.Data, error) { + var ( + txSimgos = dg.IS["simrs"].Begin() + err error + ) + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + // STEP 1: Get Installation Link + syncLink, err := ReadDetailLinkData(*input.Id, &event) + if err != nil { + return nil, err + } + + // Step 2: Update Simgos + err = UpdateSimgosData(input, syncLink, &event, txSimgos) + if err != nil { + return nil, err + } + + // STEP 4: Commit two trx + if err = txSimgos.Commit().Error; err != nil { + txSimgos.Rollback() + return nil, err + } + + 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 ( + txSync = dg.I.Begin() + txSimgos = dg.IS["simrs"].Begin() + sgData *esimgos.MPolihfis + err error + ) + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + // STEP 1: Get Installation Link + syncLink, err := ReadDetailLinkData(*input.Id, &event) + if err != nil { + return nil, err + } + + // STEP 2: Get Simgos + sgData, err = ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) + if err != nil { + return nil, err + } + + // STEP 3: Delete M_Unit Simgos + err = HardDeleteSimgosData(sgData, &event, txSimgos) + if err != nil { + return nil, err + } + + // STEP 4: Delete Installation Link + err = DeleteLinkData(syncLink, &event, txSync) + if err != nil { + txSimgos.Rollback() + return nil, err + } + + // STEP 4: Commit two trx + if err = txSync.Commit().Error; err != nil { + txSync.Rollback() + txSimgos.Rollback() + return nil, err + } + + if err = txSimgos.Commit().Error; err != nil { + // STEP 5: Rollback Partial + go func() { + _, _ = CreateLinkData(uint(*input.Id), sgData.Id, &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/specialist/helper.go b/internal/use-case/simgos-sync-use-case/specialist/helper.go new file mode 100644 index 00000000..95839354 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/specialist/helper.go @@ -0,0 +1,60 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package specialist + +import ( + "encoding/json" + erc "simrs-vx/internal/domain/references/common" + + e "simrs-vx/internal/domain/main-entities/specialist" + esimgos "simrs-vx/internal/domain/simgos-entities/specialist" + esyncLog "simrs-vx/internal/domain/sync-entities/log" + esync "simrs-vx/internal/domain/sync-entities/specialist" +) + +func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MPolihfis) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Code = inputSrc.Code + data.Poliklinik = inputSrc.Name + data.Active = 1 + data.Status = 1 + + return +} + +func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.SpecialistSimxLog) { + // 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.SpecialistLink) { + data.Simx_Id = simxId + data.Simgos_Id = simgosId + return +} diff --git a/internal/use-case/simgos-sync-use-case/specialist/lib.go b/internal/use-case/simgos-sync-use-case/specialist/lib.go new file mode 100644 index 00000000..c7123f0b --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/specialist/lib.go @@ -0,0 +1,188 @@ +package specialist + +import ( + 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/specialist" + esimgos "simrs-vx/internal/domain/simgos-entities/specialist" + esynclog "simrs-vx/internal/domain/sync-entities/log" + esync "simrs-vx/internal/domain/sync-entities/specialist" +) + +var now = time.Now() + +func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esimgos.MPolihfis, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := setDataSimgos(&input) + + 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 ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.MPolihfis, error) { + pl.SetLogInfo(event, simgosId, "started", "DBReadDetail") + data := esimgos.MPolihfis{} + + var tx = dg.IS["simrs"] + + if err := tx. + Where("\"id\" = ?", 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 UpdateSimgosData(input e.UpdateDto, dataSimgos *esync.SpecialistLink, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, input, "started", "DBUpdate") + + data := setDataSimgos(&input) + data.Id = dataSimgos.Simgos_Id + + 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 HardDeleteSimgosData(data *esimgos.MPolihfis, 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 CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.SpecialistLink, 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 uint16, event *pl.Event) (*esync.SpecialistLink, error) { + pl.SetLogInfo(event, simxId, "started", "DBReadDetail") + data := esync.SpecialistLink{} + + 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.SpecialistLink, 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/specialist/middleware-runner.go b/internal/use-case/simgos-sync-use-case/specialist/middleware-runner.go new file mode 100644 index 00000000..938c1f92 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/specialist/middleware-runner.go @@ -0,0 +1,104 @@ +package specialist + +import ( + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/specialist" +) + +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.Specialist) 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.Specialist) 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.Specialist) 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.Specialist) 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.Specialist) 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/specialist/middleware.go b/internal/use-case/simgos-sync-use-case/specialist/middleware.go new file mode 100644 index 00000000..298e51a8 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/specialist/middleware.go @@ -0,0 +1,9 @@ +package specialist + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/simgos-sync-use-case/specialist/tycovar.go b/internal/use-case/simgos-sync-use-case/specialist/tycovar.go new file mode 100644 index 00000000..16fa50b0 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/specialist/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 specialist + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/specialist" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.Specialist, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Specialist, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Specialist, 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/subspecialist/case.go b/internal/use-case/simgos-sync-use-case/subspecialist/case.go new file mode 100644 index 00000000..e16d50bd --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/subspecialist/case.go @@ -0,0 +1,214 @@ +package subspecialist + +import ( + pl "simrs-vx/pkg/logger" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/subspecialist" + //esimgos "simrs-vx/internal/domain/simgos-entities/specialist" + esync "simrs-vx/internal/domain/sync-entities/log" +) + +const source = "subspecialist" + +func Create(input e.CreateDto) (*d.Data, error) { + //var ( + // txSync = dg.I.Begin() + // txSimgos = dg.IS["simrs"].Begin() + //) + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + //// STEP 1: Insert to simgos + //sgData, err := CreateSimgosData(input, &event, txSimgos) + //if err != nil { + // return nil, err + //} + // + //// STEP 2: Insert to Link + //syncLink, err := CreateLinkData(*input.Id, sgData.Id, &event, txSync) + //if err != nil { + // txSimgos.Rollback() + // return nil, err + //} + // + //// STEP 3: Commit two trx + //if err = txSync.Commit().Error; err != nil { + // txSync.Rollback() + // txSimgos.Rollback() + // return nil, err + //} + // + //if err = txSimgos.Commit().Error; err != nil { + // // STEP 4: Rollback Partial + // 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 esync.SimxLogDto) (*d.Data, error) { + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + err := dg.I.Transaction(func(tx *gorm.DB) error { + // InsertSimxLog + if err := CreateLogData(input, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + 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.UpdateDto) (*d.Data, error) { + //var ( + // txSimgos = dg.IS["simrs"].Begin() + // err error + //) + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + //// STEP 1: Get Installation Link + //syncLink, err := ReadDetailLinkData(*input.Id, &event) + //if err != nil { + // return nil, err + //} + // + //// Step 2: Update Simgos + //err = UpdateSimgosData(input, syncLink, &event, txSimgos) + //if err != nil { + // return nil, err + //} + // + //// STEP 4: Commit two trx + //if err = txSimgos.Commit().Error; err != nil { + // txSimgos.Rollback() + // return nil, err + //} + + 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 ( + // txSync = dg.I.Begin() + // txSimgos = dg.IS["simrs"].Begin() + // sgData *esimgos.MPolihfis + // err error + //) + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + //// STEP 1: Get Installation Link + //syncLink, err := ReadDetailLinkData(*input.Id, &event) + //if err != nil { + // return nil, err + //} + // + //// STEP 2: Get Simgos + //sgData, err = ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) + //if err != nil { + // return nil, err + //} + // + //// STEP 3: Delete M_Unit Simgos + //err = HardDeleteSimgosData(sgData, &event, txSimgos) + //if err != nil { + // return nil, err + //} + // + //// STEP 4: Delete Installation Link + //err = DeleteLinkData(syncLink, &event, txSync) + //if err != nil { + // txSimgos.Rollback() + // return nil, err + //} + // + //// STEP 4: Commit two trx + //if err = txSync.Commit().Error; err != nil { + // txSync.Rollback() + // txSimgos.Rollback() + // return nil, err + //} + // + //if err = txSimgos.Commit().Error; err != nil { + // // STEP 5: Rollback Partial + // go func() { + // _, _ = CreateLinkData(uint(*input.Id), sgData.Id, &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/subspecialist/helper.go b/internal/use-case/simgos-sync-use-case/subspecialist/helper.go new file mode 100644 index 00000000..898f161c --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/subspecialist/helper.go @@ -0,0 +1,59 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package subspecialist + +import ( + "encoding/json" + erc "simrs-vx/internal/domain/references/common" + //esimgos "simrs-vx/internal/domain/simgos-entities/specialist" + esyncLog "simrs-vx/internal/domain/sync-entities/log" + esync "simrs-vx/internal/domain/sync-entities/specialist" +) + +//func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MPolihfis) { +// var inputSrc *e.CreateDto +// if inputT, ok := any(input).(*e.CreateDto); ok { +// inputSrc = inputT +// } else { +// inputTemp := any(input).(*e.UpdateDto) +// inputSrc = &inputTemp.CreateDto +// } +// +// data.Code = inputSrc.Code +// data.Poliklinik = inputSrc.Name +// data.CodePolirs = *inputSrc.Unit_Code +// data.Active = 1 +// data.Status = 1 +// +// return +//} + +func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.SpecialistSimxLog) { + // 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.SpecialistLink) { + data.Simx_Id = simxId + data.Simgos_Id = simgosId + return +} diff --git a/internal/use-case/simgos-sync-use-case/subspecialist/lib.go b/internal/use-case/simgos-sync-use-case/subspecialist/lib.go new file mode 100644 index 00000000..781e899d --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/subspecialist/lib.go @@ -0,0 +1,187 @@ +package subspecialist + +import ( + 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" + + //esimgos "simrs-vx/internal/domain/simgos-entities/specialist" + esynclog "simrs-vx/internal/domain/sync-entities/log" + esync "simrs-vx/internal/domain/sync-entities/specialist" +) + +var now = time.Now() + +//func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esimgos.MPolihfis, error) { +// pl.SetLogInfo(event, nil, "started", "DBCreate") +// +// data := setDataSimgos(&input) +// +// 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 ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.MPolihfis, error) { +// pl.SetLogInfo(event, simgosId, "started", "DBReadDetail") +// data := esimgos.MPolihfis{} +// +// var tx = dg.IS["simrs"] +// +// if err := tx. +// Where("\"kode_unit\" = ?", 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 UpdateSimgosData(input e.UpdateDto, dataSimgos *esync.SpecialistLink, event *pl.Event, dbx ...*gorm.DB) error { +// pl.SetLogInfo(event, input, "started", "DBUpdate") +// +// data := setDataSimgos(&input) +// data.Id = dataSimgos.Simgos_Id +// +// 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 HardDeleteSimgosData(data *esimgos.MPolihfis, 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 CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.SpecialistLink, 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 uint16, event *pl.Event) (*esync.SpecialistLink, error) { + pl.SetLogInfo(event, simxId, "started", "DBReadDetail") + data := esync.SpecialistLink{} + + 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.SpecialistLink, 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/subspecialist/middleware-runner.go b/internal/use-case/simgos-sync-use-case/subspecialist/middleware-runner.go new file mode 100644 index 00000000..134041f1 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/subspecialist/middleware-runner.go @@ -0,0 +1,104 @@ +package subspecialist + +import ( + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/subspecialist" +) + +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.Subspecialist) 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.Subspecialist) 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.Subspecialist) 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.Subspecialist) 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.Subspecialist) 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/subspecialist/middleware.go b/internal/use-case/simgos-sync-use-case/subspecialist/middleware.go new file mode 100644 index 00000000..ad2ba452 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/subspecialist/middleware.go @@ -0,0 +1,9 @@ +package subspecialist + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/simgos-sync-use-case/subspecialist/tycovar.go b/internal/use-case/simgos-sync-use-case/subspecialist/tycovar.go new file mode 100644 index 00000000..ed4540b8 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/subspecialist/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 subspecialist + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/subspecialist" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.Subspecialist, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Subspecialist, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Subspecialist, 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 From 938ec89c20e3c7b24e9a72d4c2d238bb2d377ef2 Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 18 Nov 2025 09:58:41 +0700 Subject: [PATCH 221/329] add enabled sync --- cmd/main-api/config.yml-example | 1 + internal/infra/sync-cfg/tycovar.go | 1 + .../division/middleware-runner.go | 35 +++++++++++++++++-- .../installation/middleware-runner.go | 30 +++++++++++++++- .../specialist/middleware-runner.go | 35 +++++++++++++++++-- .../subspecialist/middleware-runner.go | 35 +++++++++++++++++-- .../main-use-case/unit/middleware-runner.go | 35 +++++++++++++++++-- 7 files changed, 159 insertions(+), 13 deletions(-) diff --git a/cmd/main-api/config.yml-example b/cmd/main-api/config.yml-example index 448cff66..b2426b1f 100644 --- a/cmd/main-api/config.yml-example +++ b/cmd/main-api/config.yml-example @@ -69,5 +69,6 @@ bpjsCfg: baseUrl: syncUrlCfg: + enable: false host: prefix: new-to-old \ No newline at end of file diff --git a/internal/infra/sync-cfg/tycovar.go b/internal/infra/sync-cfg/tycovar.go index fdcda00b..6ae230fb 100644 --- a/internal/infra/sync-cfg/tycovar.go +++ b/internal/infra/sync-cfg/tycovar.go @@ -5,4 +5,5 @@ var O SyncUrlCfg = SyncUrlCfg{} type SyncUrlCfg struct { Prefix string `yaml:"prefix"` Host string `yaml:"host"` + Enable bool `yaml:"enable"` } 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 b39e3176..51c90d77 100644 --- a/internal/use-case/main-use-case/division/middleware-runner.go +++ b/internal/use-case/main-use-case/division/middleware-runner.go @@ -1,29 +1,38 @@ package division import ( - e "simrs-vx/internal/domain/main-entities/division" - esync "simrs-vx/internal/domain/sync-entities/log" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" "gorm.io/gorm" + + sync "simrs-vx/internal/infra/sync-cfg" + + e "simrs-vx/internal/domain/main-entities/division" + esync "simrs-vx/internal/domain/sync-entities/log" ) 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) *middlewareRunner { return &middlewareRunner{ - Event: event, + Event: event, + SyncOn: sync.O.Enable, } } // ExecuteCreateMiddleware executes create middleware func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) @@ -40,6 +49,10 @@ func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e // ExecuteCreateMiddleware executes createlog middleware func (me *middlewareRunner) RunCreateLogMiddleware(middlewares []createLogMw, input *esync.SimxLogDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) @@ -55,6 +68,10 @@ func (me *middlewareRunner) RunCreateLogMiddleware(middlewares []createLogMw, in } func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.Division) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -70,6 +87,10 @@ func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, inpu } func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Division) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -85,6 +106,10 @@ func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, } func (me *middlewareRunner) RunUpdateMiddleware(middlewares []updateMw, input *e.UpdateDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) @@ -100,6 +125,10 @@ func (me *middlewareRunner) RunUpdateMiddleware(middlewares []updateMw, input *e } func (me *middlewareRunner) RunDeleteMiddleware(middlewares []deleteMw, input *e.DeleteDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) 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 5a8e2ad0..b85e3236 100644 --- a/internal/use-case/main-use-case/installation/middleware-runner.go +++ b/internal/use-case/main-use-case/installation/middleware-runner.go @@ -6,6 +6,8 @@ import ( "gorm.io/gorm" + sync "simrs-vx/internal/infra/sync-cfg" + e "simrs-vx/internal/domain/main-entities/installation" esync "simrs-vx/internal/domain/sync-entities/log" ) @@ -14,17 +16,23 @@ 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) *middlewareRunner { return &middlewareRunner{ - Event: event, + Event: event, + SyncOn: sync.O.Enable, } } // ExecuteCreateMiddleware executes create middleware func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) @@ -41,6 +49,10 @@ func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e // ExecuteCreateMiddleware executes create middleware func (me *middlewareRunner) RunCreateLogMiddleware(middlewares []createLogMw, input *esync.SimxLogDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) @@ -56,6 +68,10 @@ func (me *middlewareRunner) RunCreateLogMiddleware(middlewares []createLogMw, in } func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.Installation) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -71,6 +87,10 @@ func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, inpu } func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Installation) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -86,6 +106,10 @@ func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, } func (me *middlewareRunner) RunUpdateMiddleware(middlewares []UpdateMw, input *e.UpdateDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) @@ -101,6 +125,10 @@ func (me *middlewareRunner) RunUpdateMiddleware(middlewares []UpdateMw, input *e } func (me *middlewareRunner) RunDeleteMiddleware(middlewares []DeleteMw, input *e.DeleteDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) 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 c937d2bc..9a10d624 100644 --- a/internal/use-case/main-use-case/specialist/middleware-runner.go +++ b/internal/use-case/main-use-case/specialist/middleware-runner.go @@ -1,29 +1,38 @@ package specialist import ( - e "simrs-vx/internal/domain/main-entities/specialist" - esync "simrs-vx/internal/domain/sync-entities/log" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" "gorm.io/gorm" + + sync "simrs-vx/internal/infra/sync-cfg" + + e "simrs-vx/internal/domain/main-entities/specialist" + esync "simrs-vx/internal/domain/sync-entities/log" ) 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) *middlewareRunner { return &middlewareRunner{ - Event: event, + Event: event, + SyncOn: sync.O.Enable, } } // ExecuteCreateMiddleware executes create middleware func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) @@ -40,6 +49,10 @@ func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e // ExecuteCreateMiddleware executes createlog middleware func (me *middlewareRunner) RunCreateLogMiddleware(middlewares []createLogMw, input *esync.SimxLogDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) @@ -55,6 +68,10 @@ func (me *middlewareRunner) RunCreateLogMiddleware(middlewares []createLogMw, in } func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.Specialist) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -70,6 +87,10 @@ func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, inpu } func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Specialist) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -85,6 +106,10 @@ func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, } func (me *middlewareRunner) RunUpdateMiddleware(middlewares []updateMw, input *e.UpdateDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) @@ -100,6 +125,10 @@ func (me *middlewareRunner) RunUpdateMiddleware(middlewares []updateMw, input *e } func (me *middlewareRunner) RunDeleteMiddleware(middlewares []deleteMw, input *e.DeleteDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) 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 065e5ecc..ad1eba08 100644 --- a/internal/use-case/main-use-case/subspecialist/middleware-runner.go +++ b/internal/use-case/main-use-case/subspecialist/middleware-runner.go @@ -1,29 +1,38 @@ package subspecialist import ( - e "simrs-vx/internal/domain/main-entities/subspecialist" - esync "simrs-vx/internal/domain/sync-entities/log" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" "gorm.io/gorm" + + sync "simrs-vx/internal/infra/sync-cfg" + + e "simrs-vx/internal/domain/main-entities/subspecialist" + esync "simrs-vx/internal/domain/sync-entities/log" ) 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) *middlewareRunner { return &middlewareRunner{ - Event: event, + Event: event, + SyncOn: sync.O.Enable, } } // ExecuteCreateMiddleware executes create middleware func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) @@ -39,6 +48,10 @@ func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e } func (me *middlewareRunner) RunCreateLogMiddleware(middlewares []createLogMw, input *esync.SimxLogDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) @@ -54,6 +67,10 @@ func (me *middlewareRunner) RunCreateLogMiddleware(middlewares []createLogMw, in } func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.Subspecialist) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -69,6 +86,10 @@ func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, inpu } func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Subspecialist) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -84,6 +105,10 @@ func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, } func (me *middlewareRunner) RunUpdateMiddleware(middlewares []updateMw, input *e.UpdateDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) @@ -99,6 +124,10 @@ func (me *middlewareRunner) RunUpdateMiddleware(middlewares []updateMw, input *e } func (me *middlewareRunner) RunDeleteMiddleware(middlewares []deleteMw, input *e.DeleteDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) 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 f45fe208..979548bc 100644 --- a/internal/use-case/main-use-case/unit/middleware-runner.go +++ b/internal/use-case/main-use-case/unit/middleware-runner.go @@ -1,29 +1,38 @@ package unit import ( - e "simrs-vx/internal/domain/main-entities/unit" - esync "simrs-vx/internal/domain/sync-entities/log" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" "gorm.io/gorm" + + sync "simrs-vx/internal/infra/sync-cfg" + + e "simrs-vx/internal/domain/main-entities/unit" + esync "simrs-vx/internal/domain/sync-entities/log" ) 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) *middlewareRunner { return &middlewareRunner{ - Event: event, + Event: event, + SyncOn: sync.O.Enable, } } // ExecuteCreateMiddleware executes create middleware func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) @@ -40,6 +49,10 @@ func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e // ExecuteCreateMiddleware executes create middleware func (me *middlewareRunner) RunCreateLogMiddleware(middlewares []createLogMw, input *esync.SimxLogDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) @@ -55,6 +68,10 @@ func (me *middlewareRunner) RunCreateLogMiddleware(middlewares []createLogMw, in } func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.Unit) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -70,6 +87,10 @@ func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, inpu } func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Unit) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -85,6 +106,10 @@ func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, } func (me *middlewareRunner) RunUpdateMiddleware(middlewares []updateMw, input *e.UpdateDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) @@ -100,6 +125,10 @@ func (me *middlewareRunner) RunUpdateMiddleware(middlewares []updateMw, input *e } func (me *middlewareRunner) RunDeleteMiddleware(middlewares []deleteMw, input *e.DeleteDto) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, nil) From 12dda8a6782532120782b838bd6d444f345574f6 Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 18 Nov 2025 12:02:10 +0700 Subject: [PATCH 222/329] update dual trx --- .../simgos-sync-use-case/division/case.go | 145 ++++++++---------- .../simgos-sync-use-case/installation/case.go | 144 ++++++++--------- .../simgos-sync-use-case/specialist/case.go | 145 ++++++++---------- .../subspecialist/case.go | 142 ++++++++--------- .../simgos-sync-use-case/unit/case.go | 142 ++++++++--------- pkg/dualtrx-helper/dualtrx-helper.go | 66 ++++++++ 6 files changed, 384 insertions(+), 400 deletions(-) create mode 100644 pkg/dualtrx-helper/dualtrx-helper.go diff --git a/internal/use-case/simgos-sync-use-case/division/case.go b/internal/use-case/simgos-sync-use-case/division/case.go index 14dd0886..699848e9 100644 --- a/internal/use-case/simgos-sync-use-case/division/case.go +++ b/internal/use-case/simgos-sync-use-case/division/case.go @@ -3,21 +3,24 @@ package division import ( pl "simrs-vx/pkg/logger" - dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" "gorm.io/gorm" + dualtx "simrs-vx/pkg/dualtrx-helper" + e "simrs-vx/internal/domain/main-entities/division" esimgos "simrs-vx/internal/domain/simgos-entities/division" - esync "simrs-vx/internal/domain/sync-entities/log" + esync "simrs-vx/internal/domain/sync-entities/division" + elog "simrs-vx/internal/domain/sync-entities/log" ) const source = "division" func Create(input e.CreateDto) (*d.Data, error) { var ( - txSync = dg.I.Begin() - txSimgos = dg.IS["simrs"].Begin() + sgData *esimgos.MUnit + syncLink *esync.DivisionLink + err error ) event := pl.Event{ @@ -28,31 +31,26 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - // STEP 1: Insert to simgos - sgData, err := CreateSimgosData(input, &event, txSimgos) + err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + // STEP 1: Insert to simgos + sgData, err = CreateSimgosData(input, &event, tx.Simgos) + if err != nil { + return err + } + + // STEP 2: Insert to Link + syncLink, err = CreateLinkData(*input.Id, sgData.KodeUnit, &event, tx.Sync) + if err != nil { + return err + } + + return nil + }) + if err != nil { - return nil, err - } - - // STEP 2: Insert to Link - syncLink, err := CreateLinkData(*input.Id, sgData.KodeUnit, &event, txSync) - if err != nil { - txSimgos.Rollback() - return nil, err - } - - // STEP 3: Commit two trx - if err = txSync.Commit().Error; err != nil { - txSync.Rollback() - txSimgos.Rollback() - return nil, err - } - - if err = txSimgos.Commit().Error; err != nil { - // STEP 4: Rollback Partial - go func() { - _ = DeleteLinkData(syncLink, &event) - }() + if syncLink != nil { + go func() { _ = DeleteLinkData(syncLink, &event) }() + } return nil, err } @@ -67,7 +65,7 @@ func Create(input e.CreateDto) (*d.Data, error) { }, nil } -func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { +func CreateSimxLog(input elog.SimxLogDto) (*d.Data, error) { event := pl.Event{ Feature: "Create", Source: source, @@ -76,14 +74,13 @@ func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - err := dg.I.Transaction(func(tx *gorm.DB) error { - // InsertSimxLog + tx := dualtx.NewTx() + err := tx.Sync.Transaction(func(tx *gorm.DB) error { + // Insert to Log if err := CreateLogData(input, &event, tx); err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") - return nil }) @@ -103,11 +100,6 @@ func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - var ( - txSimgos = dg.IS["simrs"].Begin() - err error - ) - event := pl.Event{ Feature: "Update", Source: source, @@ -116,23 +108,21 @@ func Update(input e.UpdateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "update") - // STEP 1: Get Installation Link + // STEP 1: Get Link syncLink, err := ReadDetailLinkData(*input.Id, &event) if err != nil { return nil, err } - // Step 2: Update Simgos - err = UpdateSimgosData(input, syncLink, &event, txSimgos) - if err != nil { - return nil, err - } + tx := dualtx.NewTx() + err = tx.Simgos.Transaction(func(tx *gorm.DB) error { + // Step 2: Update Simgos + if err = UpdateSimgosData(input, syncLink, &event, tx); err != nil { + return err + } - // STEP 4: Commit two trx - if err = txSimgos.Commit().Error; err != nil { - txSimgos.Rollback() - return nil, err - } + return nil + }) pl.SetLogInfo(&event, nil, "complete") @@ -146,12 +136,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - var ( - txSync = dg.I.Begin() - txSimgos = dg.IS["simrs"].Begin() - sgData *esimgos.MUnit - err error - ) + var isLinkDeleted bool event := pl.Event{ Feature: "Delete", @@ -161,43 +146,41 @@ func Delete(input e.DeleteDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "delete") - // STEP 1: Get Installation Link + // STEP 1: Get Link syncLink, err := ReadDetailLinkData(*input.Id, &event) if err != nil { return nil, err } // STEP 2: Get Simgos - sgData, err = ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) + sgData, err := ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) if err != nil { return nil, err } - // STEP 3: Delete M_Unit Simgos - err = HardDeleteSimgosData(sgData, &event, txSimgos) + err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + // STEP 3: Delete Simgos + err = HardDeleteSimgosData(sgData, &event, tx.Simgos) + if 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 { - return nil, err - } - - // STEP 4: Delete Installation Link - err = DeleteLinkData(syncLink, &event, txSync) - if err != nil { - txSimgos.Rollback() - return nil, err - } - - // STEP 4: Commit two trx - if err = txSync.Commit().Error; err != nil { - txSync.Rollback() - txSimgos.Rollback() - return nil, err - } - - if err = txSimgos.Commit().Error; err != nil { - // STEP 5: Rollback Partial - go func() { - _, _ = CreateLinkData(uint(*input.Id), sgData.KodeUnit, &event) - }() + if isLinkDeleted { + go func() { + _, _ = CreateLinkData(uint(*input.Id), sgData.KodeUnit, &event) + }() + } return nil, err } diff --git a/internal/use-case/simgos-sync-use-case/installation/case.go b/internal/use-case/simgos-sync-use-case/installation/case.go index c920fca1..f4b8d2b1 100644 --- a/internal/use-case/simgos-sync-use-case/installation/case.go +++ b/internal/use-case/simgos-sync-use-case/installation/case.go @@ -1,24 +1,27 @@ package installation import ( - dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" pl "simrs-vx/pkg/logger" "gorm.io/gorm" + dualtx "simrs-vx/pkg/dualtrx-helper" + e "simrs-vx/internal/domain/main-entities/installation" esimgos "simrs-vx/internal/domain/simgos-entities/installation" - esync "simrs-vx/internal/domain/sync-entities/log" + esync "simrs-vx/internal/domain/sync-entities/installation" + elog "simrs-vx/internal/domain/sync-entities/log" ) const source = "installation" func Create(input e.CreateDto) (*d.Data, error) { var ( - txSync = dg.I.Begin() - txSimgos = dg.IS["simrs"].Begin() + sgData *esimgos.MInstalasi + syncLink *esync.InstallationLink + err error ) event := pl.Event{ @@ -29,31 +32,26 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - // STEP 1: Insert to simgos - sgData, err := CreateSimgosData(input, &event, txSimgos) + err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + // STEP 1: Insert to simgos + sgData, err = CreateSimgosData(input, &event, tx.Simgos) + if err != nil { + return err + } + + // STEP 2: Insert to Link + syncLink, err = CreateLinkData(*input.Id, sgData.No_Instalasi, &event, tx.Sync) + if err != nil { + return err + } + + return nil + }) + if err != nil { - return nil, err - } - - // STEP 2: Insert to Link - syncLink, err := CreateLinkData(*input.Id, sgData.No_Instalasi, &event, txSync) - if err != nil { - txSimgos.Rollback() - return nil, err - } - - // STEP 3: Commit two trx - if err = txSync.Commit().Error; err != nil { - txSync.Rollback() - txSimgos.Rollback() - return nil, err - } - - if err = txSimgos.Commit().Error; err != nil { - // STEP 4: Rollback Partial - go func() { - _ = DeleteLinkData(syncLink, &event) - }() + if syncLink != nil { + go func() { _ = DeleteLinkData(syncLink, &event) }() + } return nil, err } @@ -68,7 +66,7 @@ func Create(input e.CreateDto) (*d.Data, error) { }, nil } -func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { +func CreateSimxLog(input elog.SimxLogDto) (*d.Data, error) { event := pl.Event{ Feature: "Create", Source: source, @@ -77,14 +75,13 @@ func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - err := dg.I.Transaction(func(tx *gorm.DB) error { - // InsertSimxLog + tx := dualtx.NewTx() + err := tx.Sync.Transaction(func(tx *gorm.DB) error { + // Insert to Log if err := CreateLogData(input, &event, tx); err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") - return nil }) @@ -104,11 +101,6 @@ func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - var ( - txSimgos = dg.IS["simrs"].Begin() - err error - ) - event := pl.Event{ Feature: "Update", Source: source, @@ -117,23 +109,21 @@ func Update(input e.UpdateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "update") - // STEP 1: Get Installation Link + // STEP 1: Get Link syncLink, err := ReadDetailLinkData(*input.Id, &event) if err != nil { return nil, err } - // Step 2: Update Simgos - err = UpdateSimgosData(input, syncLink, &event, txSimgos) - if err != nil { - return nil, err - } + tx := dualtx.NewTx() + err = tx.Simgos.Transaction(func(tx *gorm.DB) error { + // Step 2: Update Simgos + if err = UpdateSimgosData(input, syncLink, &event, tx); err != nil { + return err + } - // STEP 4: Commit two trx - if err = txSimgos.Commit().Error; err != nil { - txSimgos.Rollback() - return nil, err - } + return nil + }) pl.SetLogInfo(&event, nil, "complete") @@ -147,12 +137,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - var ( - txSync = dg.I.Begin() - txSimgos = dg.IS["simrs"].Begin() - sgData *esimgos.MInstalasi - err error - ) + var isLinkDeleted bool event := pl.Event{ Feature: "Delete", @@ -162,43 +147,42 @@ func Delete(input e.DeleteDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "delete") - // STEP 1: Get Installation Link + // STEP 1: Get Link syncLink, err := ReadDetailLinkData(*input.Id, &event) if err != nil { return nil, err } // STEP 2: Get Simgos - sgData, err = ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) + sgData, err := ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) if err != nil { return nil, err } - // STEP 3: Delete M_Instalation Simgos - err = SoftDeleteSimgosData(sgData, &event, txSimgos) + err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + // STEP 3: Delete Simgos + err = SoftDeleteSimgosData(sgData, &event, tx.Simgos) + if 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 { - return nil, err - } + if isLinkDeleted { + go func() { + _, _ = CreateLinkData(uint(*input.Id), sgData.No_Instalasi, &event) + }() + } - // STEP 4: Delete Installation Link - err = DeleteLinkData(syncLink, &event, txSync) - if err != nil { - txSimgos.Rollback() - return nil, err - } - - // STEP 4: Commit two trx - if err = txSync.Commit().Error; err != nil { - txSync.Rollback() - txSimgos.Rollback() - return nil, err - } - - if err = txSimgos.Commit().Error; err != nil { - // STEP 5: Rollback Partial - go func() { - _, _ = CreateLinkData(uint(*input.Id), sgData.No_Instalasi, &event) - }() return nil, err } diff --git a/internal/use-case/simgos-sync-use-case/specialist/case.go b/internal/use-case/simgos-sync-use-case/specialist/case.go index 4e6de31d..58da2a2f 100644 --- a/internal/use-case/simgos-sync-use-case/specialist/case.go +++ b/internal/use-case/simgos-sync-use-case/specialist/case.go @@ -3,21 +3,24 @@ package specialist import ( pl "simrs-vx/pkg/logger" - dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" "gorm.io/gorm" + dualtx "simrs-vx/pkg/dualtrx-helper" + e "simrs-vx/internal/domain/main-entities/specialist" esimgos "simrs-vx/internal/domain/simgos-entities/specialist" - esync "simrs-vx/internal/domain/sync-entities/log" + elog "simrs-vx/internal/domain/sync-entities/log" + esync "simrs-vx/internal/domain/sync-entities/specialist" ) const source = "specialist" func Create(input e.CreateDto) (*d.Data, error) { var ( - txSync = dg.I.Begin() - txSimgos = dg.IS["simrs"].Begin() + sgData *esimgos.MPolihfis + syncLink *esync.SpecialistLink + err error ) event := pl.Event{ @@ -28,34 +31,28 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - // STEP 1: Insert to simgos - sgData, err := CreateSimgosData(input, &event, txSimgos) + err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + // STEP 1: Insert to simgos + sgData, err = CreateSimgosData(input, &event, tx.Simgos) + if err != nil { + return err + } + + // STEP 2: Insert to Link + syncLink, err = CreateLinkData(*input.Id, sgData.Id, &event, tx.Sync) + if err != nil { + return err + } + + return nil + }) + if err != nil { + if syncLink != nil { + go func() { _ = DeleteLinkData(syncLink, &event) }() + } return nil, err } - - // STEP 2: Insert to Link - syncLink, err := CreateLinkData(*input.Id, sgData.Id, &event, txSync) - if err != nil { - txSimgos.Rollback() - return nil, err - } - - // STEP 3: Commit two trx - if err = txSync.Commit().Error; err != nil { - txSync.Rollback() - txSimgos.Rollback() - return nil, err - } - - if err = txSimgos.Commit().Error; err != nil { - // STEP 4: Rollback Partial - go func() { - _ = DeleteLinkData(syncLink, &event) - }() - return nil, err - } - pl.SetLogInfo(&event, nil, "complete") return &d.Data{ @@ -67,7 +64,7 @@ func Create(input e.CreateDto) (*d.Data, error) { }, nil } -func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { +func CreateSimxLog(input elog.SimxLogDto) (*d.Data, error) { event := pl.Event{ Feature: "Create", Source: source, @@ -76,14 +73,13 @@ func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - err := dg.I.Transaction(func(tx *gorm.DB) error { - // InsertSimxLog + tx := dualtx.NewTx() + err := tx.Sync.Transaction(func(tx *gorm.DB) error { + // Insert to Log if err := CreateLogData(input, &event, tx); err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") - return nil }) @@ -103,11 +99,6 @@ func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - var ( - txSimgos = dg.IS["simrs"].Begin() - err error - ) - event := pl.Event{ Feature: "Update", Source: source, @@ -122,17 +113,16 @@ func Update(input e.UpdateDto) (*d.Data, error) { return nil, err } - // Step 2: Update Simgos - err = UpdateSimgosData(input, syncLink, &event, txSimgos) - if err != nil { - return nil, err - } + tx := dualtx.NewTx() + err = tx.Simgos.Transaction(func(tx *gorm.DB) error { + // Step 2: Update Simgos + err = UpdateSimgosData(input, syncLink, &event, tx) + if err != nil { + return err + } - // STEP 4: Commit two trx - if err = txSimgos.Commit().Error; err != nil { - txSimgos.Rollback() - return nil, err - } + return nil + }) pl.SetLogInfo(&event, nil, "complete") @@ -146,12 +136,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - var ( - txSync = dg.I.Begin() - txSimgos = dg.IS["simrs"].Begin() - sgData *esimgos.MPolihfis - err error - ) + var isLinkDeleted bool event := pl.Event{ Feature: "Delete", @@ -161,43 +146,41 @@ func Delete(input e.DeleteDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "delete") - // STEP 1: Get Installation Link + // STEP 1: Get Link syncLink, err := ReadDetailLinkData(*input.Id, &event) if err != nil { return nil, err } // STEP 2: Get Simgos - sgData, err = ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) + sgData, err := ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) if err != nil { return nil, err } - // STEP 3: Delete M_Unit Simgos - err = HardDeleteSimgosData(sgData, &event, txSimgos) + err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + // STEP 3: Delete Simgos + err = HardDeleteSimgosData(sgData, &event, tx.Simgos) + if 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 { - return nil, err - } - - // STEP 4: Delete Installation Link - err = DeleteLinkData(syncLink, &event, txSync) - if err != nil { - txSimgos.Rollback() - return nil, err - } - - // STEP 4: Commit two trx - if err = txSync.Commit().Error; err != nil { - txSync.Rollback() - txSimgos.Rollback() - return nil, err - } - - if err = txSimgos.Commit().Error; err != nil { - // STEP 5: Rollback Partial - go func() { - _, _ = CreateLinkData(uint(*input.Id), sgData.Id, &event) - }() + if isLinkDeleted { + go func() { + _, _ = CreateLinkData(uint(*input.Id), sgData.Id, &event) + }() + } return nil, err } diff --git a/internal/use-case/simgos-sync-use-case/subspecialist/case.go b/internal/use-case/simgos-sync-use-case/subspecialist/case.go index e16d50bd..50b6c09b 100644 --- a/internal/use-case/simgos-sync-use-case/subspecialist/case.go +++ b/internal/use-case/simgos-sync-use-case/subspecialist/case.go @@ -1,23 +1,25 @@ package subspecialist import ( + dualtx "simrs-vx/pkg/dualtrx-helper" pl "simrs-vx/pkg/logger" - dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/subspecialist" //esimgos "simrs-vx/internal/domain/simgos-entities/specialist" - esync "simrs-vx/internal/domain/sync-entities/log" + elog "simrs-vx/internal/domain/sync-entities/log" + //esync "simrs-vx/internal/domain/sync-entities/subspecialist" ) const source = "subspecialist" func Create(input e.CreateDto) (*d.Data, error) { //var ( - // txSync = dg.I.Begin() - // txSimgos = dg.IS["simrs"].Begin() + // sgData *esimgos.MUnit + // syncLink *esync.SubspecialistLink + // err error //) event := pl.Event{ @@ -28,31 +30,26 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - //// STEP 1: Insert to simgos - //sgData, err := CreateSimgosData(input, &event, txSimgos) + //err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + // // STEP 1: Insert to simgos + // sgData, err = CreateSimgosData(input, &event, tx.Simgos) + // if err != nil { + // return err + // } + // + // // STEP 2: Insert to Link + // syncLink, err = CreateLinkData(*input.Id, sgData.KodeUnit, &event, tx.Sync) + // if err != nil { + // return err + // } + // + // return nil + //}) + // //if err != nil { - // return nil, err - //} - // - //// STEP 2: Insert to Link - //syncLink, err := CreateLinkData(*input.Id, sgData.Id, &event, txSync) - //if err != nil { - // txSimgos.Rollback() - // return nil, err - //} - // - //// STEP 3: Commit two trx - //if err = txSync.Commit().Error; err != nil { - // txSync.Rollback() - // txSimgos.Rollback() - // return nil, err - //} - // - //if err = txSimgos.Commit().Error; err != nil { - // // STEP 4: Rollback Partial - // go func() { - // _ = DeleteLinkData(syncLink, &event) - // }() + // if syncLink != nil { + // go func() { _ = DeleteLinkData(syncLink, &event) }() + // } // return nil, err //} @@ -67,7 +64,7 @@ func Create(input e.CreateDto) (*d.Data, error) { }, nil } -func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { +func CreateSimxLog(input elog.SimxLogDto) (*d.Data, error) { event := pl.Event{ Feature: "Create", Source: source, @@ -76,8 +73,9 @@ func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - err := dg.I.Transaction(func(tx *gorm.DB) error { - // InsertSimxLog + tx := dualtx.NewTx() + err := tx.Sync.Transaction(func(tx *gorm.DB) error { + // Insert to Log if err := CreateLogData(input, &event, tx); err != nil { return err } @@ -103,11 +101,6 @@ func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - //var ( - // txSimgos = dg.IS["simrs"].Begin() - // err error - //) - event := pl.Event{ Feature: "Update", Source: source, @@ -116,23 +109,21 @@ func Update(input e.UpdateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "update") - //// STEP 1: Get Installation Link + //// STEP 1: Get Link //syncLink, err := ReadDetailLinkData(*input.Id, &event) //if err != nil { // return nil, err //} // - //// Step 2: Update Simgos - //err = UpdateSimgosData(input, syncLink, &event, txSimgos) - //if err != nil { - // return nil, err - //} + //tx := dualtx.NewTx() + //err = tx.Simgos.Transaction(func(tx *gorm.DB) error { + // // Step 2: Update Simgos + // if err = UpdateSimgosData(input, syncLink, &event, tx); err != nil { + // return err + // } // - //// STEP 4: Commit two trx - //if err = txSimgos.Commit().Error; err != nil { - // txSimgos.Rollback() - // return nil, err - //} + // return nil + //}) pl.SetLogInfo(&event, nil, "complete") @@ -146,12 +137,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - //var ( - // txSync = dg.I.Begin() - // txSimgos = dg.IS["simrs"].Begin() - // sgData *esimgos.MPolihfis - // err error - //) + //var isLinkDeleted bool event := pl.Event{ Feature: "Delete", @@ -161,43 +147,41 @@ func Delete(input e.DeleteDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "delete") - //// STEP 1: Get Installation Link + //// STEP 1: Get Link //syncLink, err := ReadDetailLinkData(*input.Id, &event) //if err != nil { // return nil, err //} // //// STEP 2: Get Simgos - //sgData, err = ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) + //sgData, err := ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) //if err != nil { // return nil, err //} // - //// STEP 3: Delete M_Unit Simgos - //err = HardDeleteSimgosData(sgData, &event, txSimgos) + //err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + // // STEP 3: Delete Simgos + // err = HardDeleteSimgosData(sgData, &event, tx.Simgos) + // if 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 { - // return nil, err - //} - // - //// STEP 4: Delete Installation Link - //err = DeleteLinkData(syncLink, &event, txSync) - //if err != nil { - // txSimgos.Rollback() - // return nil, err - //} - // - //// STEP 4: Commit two trx - //if err = txSync.Commit().Error; err != nil { - // txSync.Rollback() - // txSimgos.Rollback() - // return nil, err - //} - // - //if err = txSimgos.Commit().Error; err != nil { - // // STEP 5: Rollback Partial - // go func() { - // _, _ = CreateLinkData(uint(*input.Id), sgData.Id, &event) - // }() + // if isLinkDeleted { + // go func() { + // _, _ = CreateLinkData(uint(*input.Id), sgData.KodeUnit, &event) + // }() + // } // return nil, err //} diff --git a/internal/use-case/simgos-sync-use-case/unit/case.go b/internal/use-case/simgos-sync-use-case/unit/case.go index bb87f1c6..42094d22 100644 --- a/internal/use-case/simgos-sync-use-case/unit/case.go +++ b/internal/use-case/simgos-sync-use-case/unit/case.go @@ -3,21 +3,24 @@ package unit import ( pl "simrs-vx/pkg/logger" - dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" "gorm.io/gorm" + dualtx "simrs-vx/pkg/dualtrx-helper" + e "simrs-vx/internal/domain/main-entities/unit" esimgos "simrs-vx/internal/domain/simgos-entities/unit" - esync "simrs-vx/internal/domain/sync-entities/log" + elog "simrs-vx/internal/domain/sync-entities/log" + esync "simrs-vx/internal/domain/sync-entities/unit" ) const source = "unit" func Create(input e.CreateDto) (*d.Data, error) { var ( - txSync = dg.I.Begin() - txSimgos = dg.IS["simrs"].Begin() + sgData *esimgos.MPloy + syncLink *esync.UnitLink + err error ) event := pl.Event{ @@ -28,31 +31,26 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - // STEP 1: Insert to simgos - sgData, err := CreateSimgosData(input, &event, txSimgos) + err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + // STEP 1: Insert to simgos + sgData, err = CreateSimgosData(input, &event, tx.Simgos) + if err != nil { + return err + } + + // STEP 2: Insert to Link + syncLink, err = CreateLinkData(*input.Id, sgData.Kode, &event, tx.Sync) + if err != nil { + return err + } + + return nil + }) + if err != nil { - return nil, err - } - - // STEP 2: Insert to Link - syncLink, err := CreateLinkData(*input.Id, sgData.Kode, &event, txSync) - if err != nil { - txSimgos.Rollback() - return nil, err - } - - // STEP 3: Commit two trx - if err = txSync.Commit().Error; err != nil { - txSync.Rollback() - txSimgos.Rollback() - return nil, err - } - - if err = txSimgos.Commit().Error; err != nil { - // STEP 4: Rollback Partial - go func() { - _ = DeleteLinkData(syncLink, &event) - }() + if syncLink != nil { + go func() { _ = DeleteLinkData(syncLink, &event) }() + } return nil, err } @@ -67,7 +65,7 @@ func Create(input e.CreateDto) (*d.Data, error) { }, nil } -func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { +func CreateSimxLog(input elog.SimxLogDto) (*d.Data, error) { event := pl.Event{ Feature: "Create", Source: source, @@ -76,14 +74,13 @@ func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - err := dg.I.Transaction(func(tx *gorm.DB) error { - // InsertSimxLog + tx := dualtx.NewTx() + err := tx.Sync.Transaction(func(tx *gorm.DB) error { + // Insert to Log if err := CreateLogData(input, &event, tx); err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") - return nil }) @@ -103,11 +100,6 @@ func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - var ( - txSimgos = dg.IS["simrs"].Begin() - err error - ) - event := pl.Event{ Feature: "Update", Source: source, @@ -122,17 +114,16 @@ func Update(input e.UpdateDto) (*d.Data, error) { return nil, err } - // Step 2: Update Simgos - err = UpdateSimgosData(input, syncLink, &event, txSimgos) - if err != nil { - return nil, err - } + tx := dualtx.NewTx() + err = tx.Simgos.Transaction(func(tx *gorm.DB) error { + // Step 2: Update Simgos + err = UpdateSimgosData(input, syncLink, &event, tx) + if err != nil { + return err + } - // STEP 4: Commit two trx - if err = txSimgos.Commit().Error; err != nil { - txSimgos.Rollback() - return nil, err - } + return nil + }) pl.SetLogInfo(&event, nil, "complete") @@ -146,12 +137,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - var ( - txSync = dg.I.Begin() - txSimgos = dg.IS["simrs"].Begin() - sgData *esimgos.MPloy - err error - ) + var isLinkDeleted bool event := pl.Event{ Feature: "Delete", @@ -168,36 +154,34 @@ func Delete(input e.DeleteDto) (*d.Data, error) { } // STEP 2: Get Simgos - sgData, err = ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) + sgData, err := ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) if err != nil { return nil, err } - // STEP 3: Delete M_Poly Simgos - err = HardDeleteSimgosData(sgData, &event, txSimgos) + err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + // STEP 3: Delete M_Poly Simgos + err = HardDeleteSimgosData(sgData, &event, tx.Simgos) + if err != nil { + return err + } + + // STEP 4: Delete Installation Link + err = DeleteLinkData(syncLink, &event, tx.Sync) + if err != nil { + return err + } + + isLinkDeleted = true + return nil + }) + if err != nil { - return nil, err - } - - // STEP 4: Delete Installation Link - err = DeleteLinkData(syncLink, &event, txSync) - if err != nil { - txSimgos.Rollback() - return nil, err - } - - // STEP 4: Commit two trx - if err = txSync.Commit().Error; err != nil { - txSync.Rollback() - txSimgos.Rollback() - return nil, err - } - - if err = txSimgos.Commit().Error; err != nil { - // STEP 5: Rollback Partial - go func() { - _, _ = CreateLinkData(uint(*input.Id), sgData.Kode, &event) - }() + if isLinkDeleted { + go func() { + _, _ = CreateLinkData(uint(*input.Id), sgData.Kode, &event) + }() + } return nil, err } diff --git a/pkg/dualtrx-helper/dualtrx-helper.go b/pkg/dualtrx-helper/dualtrx-helper.go new file mode 100644 index 00000000..2f16203c --- /dev/null +++ b/pkg/dualtrx-helper/dualtrx-helper.go @@ -0,0 +1,66 @@ +package dualtrx_helper + +import ( + dg "github.com/karincake/apem/db-gorm-pg" + "gorm.io/gorm" +) + +type Dualtx struct { + Sync *gorm.DB + Simgos *gorm.DB +} + +func NewDualtx() *Dualtx { + return &Dualtx{ + Sync: dg.I.Begin(), + Simgos: dg.IS["simrs"].Begin(), + } +} + +func NewTx() *Dualtx { + return &Dualtx{ + Sync: dg.I, + Simgos: dg.IS["simrs"], + } +} + +func (t *Dualtx) Commit() error { + if err := t.Sync.Commit().Error; err != nil { + return err + } + + if err := t.Simgos.Commit().Error; err != nil { + return err + } + return nil +} + +func (t *Dualtx) Rollback() { + t.Sync.Rollback() + t.Simgos.Rollback() +} + +type DualTxFunc func(tx *Dualtx) error + +func WithDualTx(fn DualTxFunc) error { + var ( + tx = NewDualtx() + err error + ) + + defer func() { + if err != nil { + tx.Rollback() + } + }() + + if err = fn(tx); err != nil { + return err + } + + if err = tx.Commit(); err != nil { + return err + } + + return nil +} From 6ab240b8d5e33012fa89f72fa7cd6dcc5348c8e6 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 18 Nov 2025 12:15:04 +0700 Subject: [PATCH 223/329] adjust html template --- assets/docs/general-consent.html | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/assets/docs/general-consent.html b/assets/docs/general-consent.html index e311cb54..4cedc378 100644 --- a/assets/docs/general-consent.html +++ b/assets/docs/general-consent.html @@ -125,7 +125,17 @@ >
c) Anggota keluarga saya : - .......................................... + {{ range $i, $name := .FamilyMembers }} + {{ if lt $i 2 }} +
  • {{ $name }}
  • + {{ end }} + {{ end }} + +{{ end }}
    Saya memahami bahwa pembukaan rahasia ini hanya sejauh yang diperlukan untuk tujuan perawatan, pembiayaan atau administrasi yang @@ -252,20 +262,16 @@ > - Pasien/Keluarga


    .......................................
    Nama - terang + Pasien/keluarga/
    penanggung jawab


    .......................................
    {{ .Responsible_Name }} - Pemberi Informasi


    .......................................
    Nama - terang + Pemberi Informasi


    .......................................
    {{ .InformationGivenBy_Name }} - Saksi I


    .......................................
    Nama - terang + Saksi I


    .......................................
    {{ .Witness1_Name }} - Saksi II


    .......................................
    Nama - terang + Saksi II


    .......................................
    {{ .Witness2_Name }} From 601bed360087023c0b77a7b4544292ced13bb49a Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 18 Nov 2025 12:16:51 +0700 Subject: [PATCH 224/329] update sum --- cmd/main-migration/migrations/atlas.sum | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 94a7b195..4898eefa 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:2JitBq/ClDO+w/9iPRmvv946fDfbSDFoHbpHL20aqNI= +h1:vOoMJhDkNM1zFHHQLD+cHi5Xz/K4Bnv0bSNVF8IjdLs= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -119,4 +119,4 @@ h1:2JitBq/ClDO+w/9iPRmvv946fDfbSDFoHbpHL20aqNI= 20251113120533.sql h1:f3/U1Ve2yF2zSMhkt+xtwF8wUYfUKYwgbNeGfE37EW4= 20251114062746.sql h1:FInLaEFQByESEwFJKuKnuUSTKmcDpi3ZXaxkKwz2+D8= 20251117005942.sql h1:wD3BWrUSmo1HlW16V3lkaBkJvbAZ0fNk77te7J9NhOc= -20251117075427.sql h1:/PZovLaMdWILT6y1uNuBo9EyMHyxp3vQ7BwndRpQriY= +20251117075427.sql h1:TqU9VKZa3I8YNXUGQWY3WVBYN+1FvyyaKy0hB1jgAho= From 94314e641d40a21f8ee81da8fb1d1516387ca85d Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 18 Nov 2025 13:51:27 +0700 Subject: [PATCH 225/329] rename package --- .../use-case/simgos-sync-use-case/division/case.go | 10 +++++----- .../simgos-sync-use-case/installation/case.go | 10 +++++----- .../use-case/simgos-sync-use-case/specialist/case.go | 10 +++++----- .../simgos-sync-use-case/subspecialist/case.go | 11 ++++++----- internal/use-case/simgos-sync-use-case/unit/case.go | 10 +++++----- 5 files changed, 26 insertions(+), 25 deletions(-) diff --git a/internal/use-case/simgos-sync-use-case/division/case.go b/internal/use-case/simgos-sync-use-case/division/case.go index 699848e9..62c04143 100644 --- a/internal/use-case/simgos-sync-use-case/division/case.go +++ b/internal/use-case/simgos-sync-use-case/division/case.go @@ -6,7 +6,7 @@ import ( d "github.com/karincake/dodol" "gorm.io/gorm" - dualtx "simrs-vx/pkg/dualtrx-helper" + db "simrs-vx/pkg/dualtrx-helper" e "simrs-vx/internal/domain/main-entities/division" esimgos "simrs-vx/internal/domain/simgos-entities/division" @@ -31,7 +31,7 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + err = db.WithDualTx(func(tx *db.Dualtx) error { // STEP 1: Insert to simgos sgData, err = CreateSimgosData(input, &event, tx.Simgos) if err != nil { @@ -74,7 +74,7 @@ func CreateSimxLog(input elog.SimxLogDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - tx := dualtx.NewTx() + tx := db.NewTx() err := tx.Sync.Transaction(func(tx *gorm.DB) error { // Insert to Log if err := CreateLogData(input, &event, tx); err != nil { @@ -114,7 +114,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { return nil, err } - tx := dualtx.NewTx() + tx := db.NewTx() err = tx.Simgos.Transaction(func(tx *gorm.DB) error { // Step 2: Update Simgos if err = UpdateSimgosData(input, syncLink, &event, tx); err != nil { @@ -158,7 +158,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { return nil, err } - err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + err = db.WithDualTx(func(tx *db.Dualtx) error { // STEP 3: Delete Simgos err = HardDeleteSimgosData(sgData, &event, tx.Simgos) if err != nil { diff --git a/internal/use-case/simgos-sync-use-case/installation/case.go b/internal/use-case/simgos-sync-use-case/installation/case.go index f4b8d2b1..edbf709d 100644 --- a/internal/use-case/simgos-sync-use-case/installation/case.go +++ b/internal/use-case/simgos-sync-use-case/installation/case.go @@ -7,7 +7,7 @@ import ( "gorm.io/gorm" - dualtx "simrs-vx/pkg/dualtrx-helper" + db "simrs-vx/pkg/dualtrx-helper" e "simrs-vx/internal/domain/main-entities/installation" esimgos "simrs-vx/internal/domain/simgos-entities/installation" @@ -32,7 +32,7 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + err = db.WithDualTx(func(tx *db.Dualtx) error { // STEP 1: Insert to simgos sgData, err = CreateSimgosData(input, &event, tx.Simgos) if err != nil { @@ -75,7 +75,7 @@ func CreateSimxLog(input elog.SimxLogDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - tx := dualtx.NewTx() + tx := db.NewTx() err := tx.Sync.Transaction(func(tx *gorm.DB) error { // Insert to Log if err := CreateLogData(input, &event, tx); err != nil { @@ -115,7 +115,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { return nil, err } - tx := dualtx.NewTx() + tx := db.NewTx() err = tx.Simgos.Transaction(func(tx *gorm.DB) error { // Step 2: Update Simgos if err = UpdateSimgosData(input, syncLink, &event, tx); err != nil { @@ -159,7 +159,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { return nil, err } - err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + err = db.WithDualTx(func(tx *db.Dualtx) error { // STEP 3: Delete Simgos err = SoftDeleteSimgosData(sgData, &event, tx.Simgos) if err != nil { diff --git a/internal/use-case/simgos-sync-use-case/specialist/case.go b/internal/use-case/simgos-sync-use-case/specialist/case.go index 58da2a2f..cf76771c 100644 --- a/internal/use-case/simgos-sync-use-case/specialist/case.go +++ b/internal/use-case/simgos-sync-use-case/specialist/case.go @@ -6,7 +6,7 @@ import ( d "github.com/karincake/dodol" "gorm.io/gorm" - dualtx "simrs-vx/pkg/dualtrx-helper" + db "simrs-vx/pkg/dualtrx-helper" e "simrs-vx/internal/domain/main-entities/specialist" esimgos "simrs-vx/internal/domain/simgos-entities/specialist" @@ -31,7 +31,7 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + err = db.WithDualTx(func(tx *db.Dualtx) error { // STEP 1: Insert to simgos sgData, err = CreateSimgosData(input, &event, tx.Simgos) if err != nil { @@ -73,7 +73,7 @@ func CreateSimxLog(input elog.SimxLogDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - tx := dualtx.NewTx() + tx := db.NewTx() err := tx.Sync.Transaction(func(tx *gorm.DB) error { // Insert to Log if err := CreateLogData(input, &event, tx); err != nil { @@ -113,7 +113,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { return nil, err } - tx := dualtx.NewTx() + tx := db.NewTx() err = tx.Simgos.Transaction(func(tx *gorm.DB) error { // Step 2: Update Simgos err = UpdateSimgosData(input, syncLink, &event, tx) @@ -158,7 +158,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { return nil, err } - err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + err = db.WithDualTx(func(tx *db.Dualtx) error { // STEP 3: Delete Simgos err = HardDeleteSimgosData(sgData, &event, tx.Simgos) if err != nil { diff --git a/internal/use-case/simgos-sync-use-case/subspecialist/case.go b/internal/use-case/simgos-sync-use-case/subspecialist/case.go index 50b6c09b..2c633101 100644 --- a/internal/use-case/simgos-sync-use-case/subspecialist/case.go +++ b/internal/use-case/simgos-sync-use-case/subspecialist/case.go @@ -1,12 +1,13 @@ package subspecialist import ( - dualtx "simrs-vx/pkg/dualtrx-helper" 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/subspecialist" //esimgos "simrs-vx/internal/domain/simgos-entities/specialist" elog "simrs-vx/internal/domain/sync-entities/log" @@ -30,7 +31,7 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - //err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + //err = db.WithDualTx(func(tx *db.Dualtx) error { // // STEP 1: Insert to simgos // sgData, err = CreateSimgosData(input, &event, tx.Simgos) // if err != nil { @@ -73,7 +74,7 @@ func CreateSimxLog(input elog.SimxLogDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - tx := dualtx.NewTx() + tx := db.NewTx() err := tx.Sync.Transaction(func(tx *gorm.DB) error { // Insert to Log if err := CreateLogData(input, &event, tx); err != nil { @@ -115,7 +116,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { // return nil, err //} // - //tx := dualtx.NewTx() + //tx := db.NewTx() //err = tx.Simgos.Transaction(func(tx *gorm.DB) error { // // Step 2: Update Simgos // if err = UpdateSimgosData(input, syncLink, &event, tx); err != nil { @@ -159,7 +160,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { // return nil, err //} // - //err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + //err = db.WithDualTx(func(tx *db.Dualtx) error { // // STEP 3: Delete Simgos // err = HardDeleteSimgosData(sgData, &event, tx.Simgos) // if err != nil { diff --git a/internal/use-case/simgos-sync-use-case/unit/case.go b/internal/use-case/simgos-sync-use-case/unit/case.go index 42094d22..e17a8b22 100644 --- a/internal/use-case/simgos-sync-use-case/unit/case.go +++ b/internal/use-case/simgos-sync-use-case/unit/case.go @@ -6,7 +6,7 @@ import ( d "github.com/karincake/dodol" "gorm.io/gorm" - dualtx "simrs-vx/pkg/dualtrx-helper" + db "simrs-vx/pkg/dualtrx-helper" e "simrs-vx/internal/domain/main-entities/unit" esimgos "simrs-vx/internal/domain/simgos-entities/unit" @@ -31,7 +31,7 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + err = db.WithDualTx(func(tx *db.Dualtx) error { // STEP 1: Insert to simgos sgData, err = CreateSimgosData(input, &event, tx.Simgos) if err != nil { @@ -74,7 +74,7 @@ func CreateSimxLog(input elog.SimxLogDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - tx := dualtx.NewTx() + tx := db.NewTx() err := tx.Sync.Transaction(func(tx *gorm.DB) error { // Insert to Log if err := CreateLogData(input, &event, tx); err != nil { @@ -114,7 +114,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { return nil, err } - tx := dualtx.NewTx() + tx := db.NewTx() err = tx.Simgos.Transaction(func(tx *gorm.DB) error { // Step 2: Update Simgos err = UpdateSimgosData(input, syncLink, &event, tx) @@ -159,7 +159,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { return nil, err } - err = dualtx.WithDualTx(func(tx *dualtx.Dualtx) error { + err = db.WithDualTx(func(tx *db.Dualtx) error { // STEP 3: Delete M_Poly Simgos err = HardDeleteSimgosData(sgData, &event, tx.Simgos) if err != nil { From 0d340553b32f6f55fa059c95786bd9bad7636197 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 18 Nov 2025 14:44:19 +0700 Subject: [PATCH 226/329] feat (generate-file): general-consent pdf done --- assets/docs/general-consent.html | 82 +++++++--- .../main-entities/general-consent/dto.go | 2 +- .../main-use-case/general-consent/case.go | 13 ++ .../main-use-case/generate-file/case.go | 11 +- .../main-use-case/generate-file/helper.go | 17 +- .../main-use-case/generate-file/tycovar.go | 2 + pkg/conv-helper/conv-helper.go | 153 ++++++++++++++++++ pkg/use-case-helper/use-case-helper.go | 42 +++++ 8 files changed, 299 insertions(+), 23 deletions(-) create mode 100644 pkg/conv-helper/conv-helper.go diff --git a/assets/docs/general-consent.html b/assets/docs/general-consent.html index 4cedc378..a3f69826 100644 --- a/assets/docs/general-consent.html +++ b/assets/docs/general-consent.html @@ -125,11 +125,11 @@ >
    c) Anggota keluarga saya : - {{ if eq (len .FamilyMembers) 0 }} + {{ if eq (len .PatientRelatives_Name) 0 }} .......................................... {{ else }} -
      - {{ range $i, $name := .FamilyMembers }} +
        + {{ range $i, $name := .PatientRelatives_Name }} {{ if lt $i 2 }}
      • {{ $name }}
      • {{ end }} @@ -247,7 +247,7 @@
        - Malang, ............................................................ + Malang, {{ .Date }}
        @@ -260,20 +260,66 @@ border-collapse: collapse; " > - - - Pasien/keluarga/
        penanggung jawab


        .......................................
        {{ .Responsible_Name }} - - - Pemberi Informasi


        .......................................
        {{ .InformationGivenBy_Name }} - - - Saksi I


        .......................................
        {{ .Witness1_Name }} - - - Saksi II


        .......................................
        {{ .Witness2_Name }} - - + + +
        + Pasien/keluarga/
        penanggung jawab +
        + +
        + ....................................... +
        + +
        + {{ .Responsible_Name }} +
        + + + +
        + Pemberi Informasi +
        + +
        + ....................................... +
        + +
        + {{ .InformationGivenBy_Name }} +
        + + + +
        + Saksi I +
        + +
        + ....................................... +
        + +
        + {{ .Witness1_Name }} +
        + + + +
        + Saksi II +
        + +
        + ....................................... +
        + +
        + {{ .Witness2_Name }} +
        + + + + + diff --git a/internal/domain/main-entities/general-consent/dto.go b/internal/domain/main-entities/general-consent/dto.go index 3c659f2f..03dd7dc9 100644 --- a/internal/domain/main-entities/general-consent/dto.go +++ b/internal/domain/main-entities/general-consent/dto.go @@ -5,7 +5,7 @@ import ( ) type CreateDto struct { - Encounter_Id *uint `json:"-"` + Encounter_Id *uint `json:"encounter_id"` Value *string `json:"value"` } diff --git a/internal/use-case/main-use-case/general-consent/case.go b/internal/use-case/main-use-case/general-consent/case.go index a8c181ef..e6dd2a61 100644 --- a/internal/use-case/main-use-case/general-consent/case.go +++ b/internal/use-case/main-use-case/general-consent/case.go @@ -1,11 +1,14 @@ package generalconsent import ( + "errors" "strconv" // main entities e "simrs-vx/internal/domain/main-entities/general-consent" + ue "simrs-vx/internal/use-case/main-use-case/encounter" + pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -35,6 +38,11 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } + // check if encounter is done + if ue.IsDone(*input.Encounter_Id, &event, tx) { + return errors.New("encounter is already done") + } + if resData, err := CreateData(input, &event, tx); err != nil { return err } else { @@ -192,6 +200,11 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } + // check if encounter is done + if ue.IsDone(*input.Encounter_Id, &event, tx) { + return errors.New("encounter is already done") + } + if err := UpdateData(input, data, &event, tx); err != nil { return err } diff --git a/internal/use-case/main-use-case/generate-file/case.go b/internal/use-case/main-use-case/generate-file/case.go index c39a7edc..1c3ca51b 100644 --- a/internal/use-case/main-use-case/generate-file/case.go +++ b/internal/use-case/main-use-case/generate-file/case.go @@ -8,6 +8,7 @@ import ( ugc "simrs-vx/internal/use-case/main-use-case/general-consent" pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -31,11 +32,17 @@ func Generate(input GenerateDto) (*d.Data, error) { // general-consent case ere.DTCGC: // get value from general consent by ref_id - gc, err := ugc.ReadDetailData(egc.ReadDetailDto{Id: *input.Ref_Id}, &event, nil) + gc, err := ugc.ReadDetailData(egc.ReadDetailDto{Id: *input.Ref_Id}, &event) if err != nil { return nil, err } + if gc.FileUrl != nil { + if err := removeFile(string(input.EntityType_Code), *gc.FileUrl); err != nil { + return nil, err + } + } + // map template data templateData := GeneralConsentPDF{} if gc.Value != nil { @@ -54,6 +61,8 @@ func Generate(input GenerateDto) (*d.Data, error) { input.FormatType = erc.DFTCPDF input.TemplateName = TDNGC + input.Encounter_Id = gc.Encounter_Id + templateData.Date = pu.FormatIndonesianDate(gc.CreatedAt) // generate file urlPub, err := generateFile(input, templateData) diff --git a/internal/use-case/main-use-case/generate-file/helper.go b/internal/use-case/main-use-case/generate-file/helper.go index ec377dc2..9bee2212 100644 --- a/internal/use-case/main-use-case/generate-file/helper.go +++ b/internal/use-case/main-use-case/generate-file/helper.go @@ -9,19 +9,21 @@ import ( erc "simrs-vx/internal/domain/references/common" docscfg "simrs-vx/internal/infra/docs-cfg" + pc "simrs-vx/pkg/conv-helper" pf "simrs-vx/pkg/file-helper" pm "simrs-vx/pkg/minio-helper" pp "simrs-vx/pkg/pdf-helper" + pu "simrs-vx/pkg/use-case-helper" ) // generate temporary file, upload to minio, generate public url, delete temporary file func generateFile(input GenerateDto, templateData any) (string, error) { - newPath, err := pf.PathToSaveFile(fmt.Sprintf("./public/%s/%d/%s", input.EntityType_Code, *input.Ref_Id, input.Type_Code)) + newPath, err := pf.PathToSaveFile(fmt.Sprintf("./temporary/%s", input.EntityType_Code)) if err != nil { return "", err } - fPath := fmt.Sprintf("%s/%s_%s.%s", newPath, input.Type_Code, time.Now().Format("20060102150405"), input.FormatType) + fPath := fmt.Sprintf("%s/%s-%s.%s", newPath, input.Type_Code, time.Now().Format("20060102150405"), input.FormatType) templatePath := docscfg.O.GetPath() + string(input.TemplateName) @@ -44,7 +46,7 @@ func generateFile(input GenerateDto, templateData any) (string, error) { bucketName := input.EntityType_Code - objectName := fmt.Sprintf("%v/%s-%d", *input.Ref_Id, input.Type_Code, time.Now().UnixNano()) + objectName := fmt.Sprintf("%s/%s-%d.%s", *pc.UintToString(input.Encounter_Id), input.Type_Code, time.Now().UnixNano(), input.FormatType) pdfUpload := pm.UploadPathInput{ BucketName: string(bucketName), Name: objectName, @@ -81,3 +83,12 @@ func generatePDF(input GeneratePDFdto) error { return nil } + +func removeFile(bucket, fileUrl string) error { + fPath := pu.GetLastTwoPathSegments(fileUrl) + err := pm.I.RemoveObject(bucket, fPath) + if err != nil { + return err + } + return nil +} diff --git a/internal/use-case/main-use-case/generate-file/tycovar.go b/internal/use-case/main-use-case/generate-file/tycovar.go index b5d09ceb..1e16cdb8 100644 --- a/internal/use-case/main-use-case/generate-file/tycovar.go +++ b/internal/use-case/main-use-case/generate-file/tycovar.go @@ -11,6 +11,7 @@ type GeneralConsentPDF struct { InformationGivenBy_Name string `json:"informationGivenBy_name"` Witness1_Name string `json:"witness1_name"` Witness2_Name string `json:"witness2_name"` + Date string `json:"date"` } type GenerateDto struct { @@ -19,6 +20,7 @@ type GenerateDto struct { Type_Code ere.DocTypeCode `json:"type_code" validate:"required"` FormatType erc.DocFormatTypeCode `json:"formatType"` TemplateName TemplateDocsName `json:"-"` + Encounter_Id *uint `json:"-"` } type GeneratePDFdto struct { diff --git a/pkg/conv-helper/conv-helper.go b/pkg/conv-helper/conv-helper.go new file mode 100644 index 00000000..03063c74 --- /dev/null +++ b/pkg/conv-helper/conv-helper.go @@ -0,0 +1,153 @@ +package convhelper + +import ( + "fmt" + "strconv" + "time" + + "gorm.io/gorm" +) + +// check string pointer, if nil return default value +func StrConvDefault(f *string, def string) string { + if f == nil { + return def + } + return *f +} + +// check string pointer, if nil return empty string +func StrConvEmpty(f *string) string { + return StrConvDefault(f, "-") +} + +func ByteConvStr(f *byte) string { + if f != nil { + return strconv.Itoa(int(*f)) + } + return "" +} + +func Float32Conv(f *float32) float32 { + if f == nil { + return 0 + } + return *f +} + +func StrRelConv(b bool, d string) string { + if b { + return d + } else { + return "" + } +} + +func UintToString(f interface{}) *string { + if f == nil { + return nil + } + + var t string + switch v := f.(type) { + case uint: + t = strconv.FormatUint(uint64(v), 10) + case uint8: + t = strconv.FormatUint(uint64(v), 10) + case uint16: + t = strconv.FormatUint(uint64(v), 10) + case uint32: + t = strconv.FormatUint(uint64(v), 10) + case uint64: + t = strconv.FormatUint(v, 10) + // Handle pointer types + case *uint: + if v != nil { + t = strconv.FormatUint(uint64(*v), 10) + } + case *uint8: + if v != nil { + t = strconv.FormatUint(uint64(*v), 10) + } + case *uint16: + if v != nil { + t = strconv.FormatUint(uint64(*v), 10) + } + case *uint32: + if v != nil { + t = strconv.FormatUint(uint64(*v), 10) + } + case *uint64: + if v != nil { + t = strconv.FormatUint(*v, 10) + } + default: + return nil // Unsupported type + } + + return &t +} + +func BoolToString(f *bool) *string { + if f == nil { + return nil + } + t := strconv.FormatBool(*f) + return &t +} + +func TimeToString(f *time.Time) *string { + if f == nil { + return nil + } + t := f.Format("2006-01-02 15:04:05") + return &t +} + +// Handling gorm.DeletedAt +func DeletedAtToString(deletedAt *gorm.DeletedAt) *string { + if deletedAt == nil || !deletedAt.Valid { + return nil + } + return TimeToString(&deletedAt.Time) +} + +func BoolToFloat64(b bool) float64 { + if b { + return 1.0 + } + return 0.0 +} + +func Float64ToBool(f float64) bool { + return f == 1.0 +} + +func StringToBool(s string) bool { + return s == "1" +} + +func StringToFloat32(s string) float32 { + f, _ := strconv.ParseFloat(s, 32) + return float32(f) +} + +func StringToFloat64(s string) float64 { + f, _ := strconv.ParseFloat(s, 64) + return f +} + +func Float64ToString(f float64) string { + return fmt.Sprintf("%.2f", f) +} + +func StringToUint64(s string) *uint64 { + if s == "" { + return nil + } + u, err := strconv.ParseUint(s, 10, 64) + if err != nil { + return nil + } + return &u +} diff --git a/pkg/use-case-helper/use-case-helper.go b/pkg/use-case-helper/use-case-helper.go index 07df05ba..019f9773 100644 --- a/pkg/use-case-helper/use-case-helper.go +++ b/pkg/use-case-helper/use-case-helper.go @@ -3,6 +3,7 @@ package usecasehelper import ( "errors" "fmt" + "net/url" "strings" "time" @@ -166,3 +167,44 @@ func index[S ~[]E, E comparable](s S, v E) int { } return -1 } + +func FormatIndonesianDate(t time.Time) string { + monthNames := [...]string{ + "", // dummy index 0 + "Januari", + "Februari", + "Maret", + "April", + "Mei", + "Juni", + "Juli", + "Agustus", + "September", + "Oktober", + "November", + "Desember", + } + + return fmt.Sprintf("%d %s %d", t.Day(), monthNames[int(t.Month())], t.Year()) +} + +func GetLastTwoPathSegments(s string) string { + u, err := url.Parse(s) + var path string + + if err == nil && u.Path != "" { + path = u.Path + } else { + path = s + } + + parts := strings.Split(strings.Trim(path, "/"), "/") + n := len(parts) + + if n >= 2 { + return parts[n-2] + "/" + parts[n-1] + } + + // fallback: return entire string if less than 2 segments + return strings.Trim(path, "/") +} From 572eb57e0989ad7ee27469c3ae7f35e976a657c9 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 18 Nov 2025 14:50:14 +0700 Subject: [PATCH 227/329] adjust encounter and general-consent relation --- cmd/main-migration/migrations/20251118074929.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 3 ++- internal/domain/main-entities/encounter/entity.go | 2 ++ internal/domain/main-entities/general-consent/entity.go | 8 +++----- 4 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 cmd/main-migration/migrations/20251118074929.sql diff --git a/cmd/main-migration/migrations/20251118074929.sql b/cmd/main-migration/migrations/20251118074929.sql new file mode 100644 index 00000000..758110f2 --- /dev/null +++ b/cmd/main-migration/migrations/20251118074929.sql @@ -0,0 +1,2 @@ +-- Modify "GeneralConsent" table +ALTER TABLE "public"."GeneralConsent" DROP CONSTRAINT "fk_GeneralConsent_Encounter", ADD CONSTRAINT "fk_Encounter_GeneralConsents" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 4898eefa..1b7a22ba 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:vOoMJhDkNM1zFHHQLD+cHi5Xz/K4Bnv0bSNVF8IjdLs= +h1:afszGTkDIE06d7AaxnxHvAka95f66k0PzwbeS26VK6I= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -120,3 +120,4 @@ h1:vOoMJhDkNM1zFHHQLD+cHi5Xz/K4Bnv0bSNVF8IjdLs= 20251114062746.sql h1:FInLaEFQByESEwFJKuKnuUSTKmcDpi3ZXaxkKwz2+D8= 20251117005942.sql h1:wD3BWrUSmo1HlW16V3lkaBkJvbAZ0fNk77te7J9NhOc= 20251117075427.sql h1:TqU9VKZa3I8YNXUGQWY3WVBYN+1FvyyaKy0hB1jgAho= +20251118074929.sql h1:KQfYOHalnSiUPpKzSUDqdlEWMbRWyNu3PmCqsjuCUGU= diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index 3939f546..c188bb1a 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -10,6 +10,7 @@ import ( eem "simrs-vx/internal/domain/main-entities/emergency" ee "simrs-vx/internal/domain/main-entities/employee" eed "simrs-vx/internal/domain/main-entities/encounter-document" + egc "simrs-vx/internal/domain/main-entities/general-consent" eip "simrs-vx/internal/domain/main-entities/inpatient" ei "simrs-vx/internal/domain/main-entities/insurance-company" eir "simrs-vx/internal/domain/main-entities/internal-reference" @@ -72,6 +73,7 @@ type Encounter struct { Rehab *er.Basic `json:"rehab,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` RehabChildren *[]er.Basic `json:"rehabChildren,omitempty" gorm:"foreignKey:Parent_Encounter_Id;references:Id"` EncounterDocuments *[]eed.EncounterDocument `json:"encounterDocuments,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + GeneralConsents *[]egc.GeneralConsent `json:"generalConsents,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` } func (d Encounter) IsDone() bool { diff --git a/internal/domain/main-entities/general-consent/entity.go b/internal/domain/main-entities/general-consent/entity.go index f5ce6394..622c82bc 100644 --- a/internal/domain/main-entities/general-consent/entity.go +++ b/internal/domain/main-entities/general-consent/entity.go @@ -2,13 +2,11 @@ package general_consent import ( "simrs-vx/internal/domain/base-entities/core" - ee "simrs-vx/internal/domain/main-entities/encounter" ) type GeneralConsent struct { core.Main - Encounter_Id *uint `json:"encounter_id" gorm:"not null"` - Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Value *string `json:"value"` - FileUrl *string `json:"fileUrl" gorm:"size:1024"` + Encounter_Id *uint `json:"encounter_id" gorm:"not null"` + Value *string `json:"value"` + FileUrl *string `json:"fileUrl" gorm:"size:1024"` } From 1ef408b5146b7ebbbdbfd3bbb47c061489021242 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 18 Nov 2025 15:13:25 +0700 Subject: [PATCH 228/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 94 ++++++++++++------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 1b7a22ba..62ea73a1 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:afszGTkDIE06d7AaxnxHvAka95f66k0PzwbeS26VK6I= +h1:6x+AHHox9nrbIP7wp+zosvvnBVMqyCJh3f/Z2Kl7T7w= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,49 +75,49 @@ h1:afszGTkDIE06d7AaxnxHvAka95f66k0PzwbeS26VK6I= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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:KQfYOHalnSiUPpKzSUDqdlEWMbRWyNu3PmCqsjuCUGU= +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= From 03b75196360c94bb2c24d3933d5db1c6b36b866c Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 18 Nov 2025 15:29:46 +0700 Subject: [PATCH 229/329] add patient and encounter --- .../migrations/20251118082246.sql | 36 ++++++++ .../migrations/20251118082915.sql | 36 ++++++++ .../migrations/atlas.sum | 6 +- .../simgos-entities/Encounter/entity.go | 90 +++++++++++++++++++ .../domain/simgos-entities/division/entity.go | 20 ++--- .../domain/simgos-entities/patient/entity.go | 80 +++++++++++++++++ .../domain/sync-entities/encounter/entity.go | 31 +++++++ .../domain/sync-entities/patient/entity.go | 31 +++++++ .../migration/simgossync-entities.go | 8 ++ 9 files changed, 326 insertions(+), 12 deletions(-) create mode 100644 cmd/simgos-sync-migration/migrations/20251118082246.sql create mode 100644 cmd/simgos-sync-migration/migrations/20251118082915.sql create mode 100644 internal/domain/simgos-entities/Encounter/entity.go create mode 100644 internal/domain/simgos-entities/patient/entity.go create mode 100644 internal/domain/sync-entities/encounter/entity.go create mode 100644 internal/domain/sync-entities/patient/entity.go diff --git a/cmd/simgos-sync-migration/migrations/20251118082246.sql b/cmd/simgos-sync-migration/migrations/20251118082246.sql new file mode 100644 index 00000000..f5d9dbf5 --- /dev/null +++ b/cmd/simgos-sync-migration/migrations/20251118082246.sql @@ -0,0 +1,36 @@ +-- Create "PatientLink" table +CREATE TABLE "public"."PatientLink" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Simx_Id" bigint NULL, + "Simgos_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_PatientLink_Simgos_Id" UNIQUE ("Simgos_Id"), + CONSTRAINT "uni_PatientLink_Simx_Id" UNIQUE ("Simx_Id") +); +-- Create "PatientSimgosLog" table +CREATE TABLE "public"."PatientSimgosLog" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Value" text NULL, + "Date" timestamptz NULL, + "Status" text NULL, + "ErrMessage" text NULL, + PRIMARY KEY ("Id") +); +-- Create "PatientSimxLog" table +CREATE TABLE "public"."PatientSimxLog" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Value" text NULL, + "Date" timestamptz NULL, + "Status" text NULL, + "ErrMessage" text NULL, + PRIMARY KEY ("Id") +); diff --git a/cmd/simgos-sync-migration/migrations/20251118082915.sql b/cmd/simgos-sync-migration/migrations/20251118082915.sql new file mode 100644 index 00000000..90b41344 --- /dev/null +++ b/cmd/simgos-sync-migration/migrations/20251118082915.sql @@ -0,0 +1,36 @@ +-- Create "EncounterLink" table +CREATE TABLE "public"."EncounterLink" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Simx_Id" bigint NULL, + "Simgos_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_EncounterLink_Simgos_Id" UNIQUE ("Simgos_Id"), + CONSTRAINT "uni_EncounterLink_Simx_Id" UNIQUE ("Simx_Id") +); +-- Create "EncounterSimgosLog" table +CREATE TABLE "public"."EncounterSimgosLog" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Value" text NULL, + "Date" timestamptz NULL, + "Status" text NULL, + "ErrMessage" text NULL, + PRIMARY KEY ("Id") +); +-- Create "EncounterSimxLog" table +CREATE TABLE "public"."EncounterSimxLog" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Value" text NULL, + "Date" timestamptz NULL, + "Status" text NULL, + "ErrMessage" text NULL, + PRIMARY KEY ("Id") +); diff --git a/cmd/simgos-sync-migration/migrations/atlas.sum b/cmd/simgos-sync-migration/migrations/atlas.sum index 30f8c5dc..07e5fbaf 100644 --- a/cmd/simgos-sync-migration/migrations/atlas.sum +++ b/cmd/simgos-sync-migration/migrations/atlas.sum @@ -1,4 +1,6 @@ -h1:SN+f41iFH0m63kHeZHYricAjil5GJ9EC0LBOSdFDnmY= +h1:keVmwgYtvwxSqkq+7nB0BA25JFYRAVBpBBu5eA4Q9Hw= 20251113035508.sql h1:rjDlu6yDdy5xv6nrCOr7NialrLSLT23pzduYNq29Hf0= 20251114071129.sql h1:Z0GQ5bJo3C+tplaWzxT8n3J9HLkEaVsRVp5nn7bmYow= -20251117041601.sql h1:mIxZ2luKQREXUBY36PwLNDFI/Wf1T6Z2DDoGOueXFwI= +20251117041601.sql h1:l/RPG5mObqCSBjO4mzG+wTq2ieSycvlfOSz4czpUdWY= +20251118082246.sql h1:VFnYls2DBC8tJm2aw0iBcbWGLsKezYdOHJJV9iS7MjI= +20251118082915.sql h1:tAm67fXrH+8IJCjKbJroIqc1uQyqCnuGJnQtLmw7D20= diff --git a/internal/domain/simgos-entities/Encounter/entity.go b/internal/domain/simgos-entities/Encounter/entity.go new file mode 100644 index 00000000..16ba873e --- /dev/null +++ b/internal/domain/simgos-entities/Encounter/entity.go @@ -0,0 +1,90 @@ +package encounter + +import "time" + +type TPendaftaran struct { + Nomr string `json:"nomr" gorm:"column:nomr"` + Tglreg *time.Time `json:"tglreg" gorm:"column:tglreg"` + Kddokter uint `json:"kddokter" gorm:"column:kddokter"` + Kdpoly uint `json:"kdpoly" gorm:"column:kdpoly"` + Subspesialis *uint `json:"subspesialis" gorm:"column:subspesialis"` + Kdrujuk uint `json:"kdrujuk" gorm:"column:kdrujuk"` + Kdcarabayar uint `json:"kdcarabayar" gorm:"column:kdcarabayar"` + Nojaminan string `json:"nojaminan" gorm:"column:nojaminan"` + Shift uint `json:"shift" gorm:"column:shift"` + Status uint `json:"status" gorm:"column:status"` + KeteranganStatus *uint `json:"keterangan_status" gorm:"column:keterangan_status"` + Pasienbaru uint `json:"pasienbaru" gorm:"column:pasienbaru"` + Nip string `json:"nip" gorm:"column:nip"` + Idxdaftar uint `json:"idxdaftar" gorm:"column:idxdaftar"` + Masukpoly *time.Time `json:"masukpoly" gorm:"column:masukpoly"` + Keluarpoly *time.Time `json:"keluarpoly" gorm:"column:keluarpoly"` + Ketrujuk string `json:"ketrujuk" gorm:"column:ketrujuk"` + Ketbayar string `json:"ketbayar" gorm:"column:ketbayar"` + 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"` + Jamreg *time.Time `json:"jamreg" gorm:"column:jamreg"` + MintaRujukan string `json:"minta_rujukan" gorm:"column:minta_rujukan"` + Batal *string `json:"batal" gorm:"column:batal"` + NoSjp *string `json:"no_sjp" gorm:"column:no_sjp"` + NoPeserta *string `json:"no_peserta" gorm:"column:no_peserta"` + Nokartu string `json:"nokartu" gorm:"column:nokartu"` + Norujukan string `json:"norujukan" gorm:"column:norujukan"` + Tglrujukan *time.Time `json:"tglrujukan" gorm:"column:tglrujukan"` + DiagnosaAwal string `json:"diagnosa_awal" gorm:"column:diagnosa_awal"` + Nosep string `json:"nosep" gorm:"column:nosep"` + DiagnosaUtama string `json:"diagnosa_utama" gorm:"column:diagnosa_utama"` + KelasDaftar uint `json:"kelas_daftar" gorm:"column:kelas_daftar"` + KelasRawat *uint `json:"kelas_rawat" gorm:"column:kelas_rawat"` + TglKelasDaftar *time.Time `json:"tgl_kelas_daftar" gorm:"column:tgl_kelas_daftar"` + TglKelasRawat *time.Time `json:"tgl_kelas_rawat" gorm:"column:tgl_kelas_rawat"` + UserKelasDaftar *string `json:"user_kelas_daftar" gorm:"column:user_kelas_daftar"` + UserKelasRawat *string `json:"user_kelas_rawat" gorm:"column:user_kelas_rawat"` + StAsalMasuk string `json:"st_asal_masuk" gorm:"column:st_asal_masuk"` + StatusKecelakaan string `json:"status_kecelakaan" gorm:"column:status_kecelakaan"` + Catatan string `json:"catatan" gorm:"column:catatan"` + NoAntrian *string `json:"no_antrian" gorm:"column:no_antrian"` + StPelayanan *uint `json:"st_pelayanan" gorm:"column:st_pelayanan"` + PetugasKlinik string `json:"petugas_klinik" gorm:"column:petugas_klinik"` + Strujukan uint `json:"strujukan" gorm:"column:strujukan"` + IdPatientEklaim *uint `json:"id_patient_eklaim" gorm:"column:id_patient_eklaim"` + HakKelas *uint `json:"hak_kelas" gorm:"column:hak_kelas"` + SttsKtp string `json:"stts_ktp" gorm:"column:stts_ktp"` + StMeninggal *uint `json:"st_meninggal" gorm:"column:st_meninggal"` + DtMeninggal *time.Time `json:"dt_meninggal" gorm:"column:dt_meninggal"` + SebabMati1 *string `json:"sebab_mati_1" gorm:"column:sebab_mati_1"` + SebabMati2 *string `json:"sebab_mati_2" gorm:"column:sebab_mati_2"` + SebabMati3 *string `json:"sebab_mati_3" gorm:"column:sebab_mati_3"` + IcdMati1 *string `json:"icd_mati_1" gorm:"column:icd_mati_1"` + IcdMati2 *string `json:"icd_mati_2" gorm:"column:icd_mati_2"` + IcdMati3 *string `json:"icd_mati_3" gorm:"column:icd_mati_3"` + KeteranganLain *string `json:"keterangan_lain" gorm:"column:keterangan_lain"` + DokumenPendukung *string `json:"dokumen_pendukung" gorm:"column:dokumen_pendukung"` + NoKunjung uint `json:"no_kunjung" gorm:"column:no_kunjung"` + KdJamin *uint `json:"kd_jamin" gorm:"column:kd_jamin"` + NamaJamin *string `json:"nama_jamin" gorm:"column:nama_jamin"` + SepFile string `json:"sep_file" gorm:"column:sep_file"` + JenisFaskes *string `json:"jenis_faskes" gorm:"column:jenis_faskes"` + Nosipp *string `json:"nosipp" gorm:"column:nosipp"` + SippFile *string `json:"sipp_file" gorm:"column:sipp_file"` + Nosurkon *string `json:"nosurkon" gorm:"column:nosurkon"` + NomorBarcode *string `json:"nomor_barcode" gorm:"column:nomor_barcode"` + BarcodeCode *string `json:"barcode_code" gorm:"column:barcode_code"` + PartialType *string `json:"partial_type" gorm:"column:partial_type"` + IsPartial *uint `json:"is_partial" gorm:"column:is_partial"` + IsPenunjang *uint `json:"is_penunjang" gorm:"column:is_penunjang"` + TindakanCode *string `json:"tindakan_code" gorm:"column:tindakan_code"` + StatusSep *uint `json:"status_sep" gorm:"column:status_sep"` + PoliNameHfis *string `json:"poli_name_hfis" gorm:"column:poli_name_hfis"` + SpesialisIdHfis *string `json:"spesialis_id_hfis" gorm:"column:spesialis_id_hfis"` + DokterNameHfis *string `json:"dokter_name_hfis" gorm:"column:dokter_name_hfis"` + DokterIdHfis *string `json:"dokter_id_hfis" gorm:"column:dokter_id_hfis"` + StatusBridging *string `json:"status_bridging" gorm:"column:status_bridging"` + NoSpri *string `json:"no_spri" gorm:"column:no_spri"` +} + +func (TPendaftaran) TableName() string { + return "t_pendaftaran" +} diff --git a/internal/domain/simgos-entities/division/entity.go b/internal/domain/simgos-entities/division/entity.go index c10f5429..0cc38494 100644 --- a/internal/domain/simgos-entities/division/entity.go +++ b/internal/domain/simgos-entities/division/entity.go @@ -1,16 +1,16 @@ package division type MUnit struct { - KodeUnit uint `json:"kode_unit" gorm:"primaryKey;autoIncrement;column:kode_unit"` - NamaUnit string `json:"nama_unit" gorm:"column:nama_unit"` - GrupUnit uint `json:"grup_unit" gorm:"column:grup_unit"` - NamaGrupunit string `json:"nama_grupunit" gorm:"column:nama_grupunit"` - PendapatanUnit string `json:"pendapatan_unit" gorm:"column:pendapatan_unit"` - Smf string `json:"smf" gorm:"column:smf"` - HaveSubspecialis uint `json:"have_subspecialis" gorm:"column:have_subspecialis"` - KelSmfTarif string `json:"kel_smf_tarif" gorm:"column:kel_smf_tarif"` - IsPilihSatker uint `json:"is_pilih_satker" gorm:"column:is_pilih_satker"` - NamaTempatlayanan string `json:"nama_tempatlayanan" gorm:"column:nama_tempatlayanan"` + KodeUnit uint `json:"kode_unit" gorm:"primaryKey;autoIncrement;column:kode_unit"` + NamaUnit string `json:"nama_unit" gorm:"column:nama_unit"` + GrupUnit uint `json:"grup_unit" gorm:"column:grup_unit"` + NamaGrupunit string `json:"nama_grupunit" gorm:"column:nama_grupunit"` + PendapatanUnit string `json:"pendapatan_unit" gorm:"column:pendapatan_unit"` + Smf *string `json:"smf" gorm:"column:smf"` + HaveSubspecialis *uint `json:"have_subspecialis" gorm:"column:have_subspecialis"` + KelSmfTarif *string `json:"kel_smf_tarif" gorm:"column:kel_smf_tarif"` + IsPilihSatker *uint `json:"is_pilih_satker" gorm:"column:is_pilih_satker"` + NamaTempatlayanan string `json:"nama_tempatlayanan" gorm:"column:nama_tempatlayanan"` } func (MUnit) TableName() string { diff --git a/internal/domain/simgos-entities/patient/entity.go b/internal/domain/simgos-entities/patient/entity.go new file mode 100644 index 00000000..3013e121 --- /dev/null +++ b/internal/domain/simgos-entities/patient/entity.go @@ -0,0 +1,80 @@ +package patient + +import "time" + +type MPasien struct { + Id uint `json:"id" gorm:"primaryKey;autoIncrement;column:id"` + Nomr string `json:"nomr" gorm:"column:nomr"` + Title string `json:"title" gorm:"column:title"` + Nama string `json:"nama" gorm:"column:nama"` + Tempat string `json:"tempat" gorm:"column:tempat"` + Tgllahir *time.Time `json:"tgllahir" gorm:"column:tgllahir"` + Jeniskelamin string `json:"jeniskelamin" gorm:"column:jeniskelamin"` + Alamat string `json:"alamat" gorm:"column:alamat"` + Kelurahan uint `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 *time.Time `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" json:"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 string `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 (MPasien) TableName() string { + return "m_pasien" +} diff --git a/internal/domain/sync-entities/encounter/entity.go b/internal/domain/sync-entities/encounter/entity.go new file mode 100644 index 00000000..f92d3e42 --- /dev/null +++ b/internal/domain/sync-entities/encounter/entity.go @@ -0,0 +1,31 @@ +package encounter + +import ( + "time" + + erc "simrs-vx/internal/domain/references/common" + + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type EncounterLink struct { + ecore.Main + Simx_Id uint `json:"simx_id" gorm:"unique"` + Simgos_Id uint `json:"simgos_id" gorm:"unique"` +} + +type EncounterSimxLog struct { + ecore.Main + Value *string `json:"value"` + Date *time.Time `json:"date"` + Status erc.ProcessStatusCode `json:"status"` + ErrMessage *string `json:"errMessage"` +} + +type EncounterSimgosLog struct { + ecore.Main + Value *string `json:"value"` + Date *time.Time `json:"date"` + Status erc.ProcessStatusCode `json:"status"` + ErrMessage *string `json:"errMessage"` +} diff --git a/internal/domain/sync-entities/patient/entity.go b/internal/domain/sync-entities/patient/entity.go new file mode 100644 index 00000000..e8c5b325 --- /dev/null +++ b/internal/domain/sync-entities/patient/entity.go @@ -0,0 +1,31 @@ +package patient + +import ( + "time" + + erc "simrs-vx/internal/domain/references/common" + + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type PatientLink struct { + ecore.Main + Simx_Id uint `json:"simx_id" gorm:"unique"` + Simgos_Id uint `json:"simgos_id" gorm:"unique"` +} + +type PatientSimxLog struct { + ecore.Main + Value *string `json:"value"` + Date *time.Time `json:"date"` + Status erc.ProcessStatusCode `json:"status"` + ErrMessage *string `json:"errMessage"` +} + +type PatientSimgosLog struct { + ecore.Main + Value *string `json:"value"` + Date *time.Time `json:"date"` + Status erc.ProcessStatusCode `json:"status"` + ErrMessage *string `json:"errMessage"` +} diff --git a/internal/interface/migration/simgossync-entities.go b/internal/interface/migration/simgossync-entities.go index efc4cce9..b10c8607 100644 --- a/internal/interface/migration/simgossync-entities.go +++ b/internal/interface/migration/simgossync-entities.go @@ -3,7 +3,9 @@ package migration import ( /************** Source ***************/ division "simrs-vx/internal/domain/sync-entities/division" + encounter "simrs-vx/internal/domain/sync-entities/encounter" installation "simrs-vx/internal/domain/sync-entities/installation" + patient "simrs-vx/internal/domain/sync-entities/patient" specialist "simrs-vx/internal/domain/sync-entities/specialist" subspecialist "simrs-vx/internal/domain/sync-entities/subspecialist" unit "simrs-vx/internal/domain/sync-entities/unit" @@ -26,5 +28,11 @@ func getSyncEntities() []any { &subspecialist.SubspecialistLink{}, &subspecialist.SubspecialistSimxLog{}, &subspecialist.SubspecialistSimgosLog{}, + &patient.PatientLink{}, + &patient.PatientSimxLog{}, + &patient.PatientSimgosLog{}, + &encounter.EncounterLink{}, + &encounter.EncounterSimxLog{}, + &encounter.EncounterSimgosLog{}, } } From 8a95d681a06656013ebec8c5a6c758e865bfe8d3 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 18 Nov 2025 15:34:58 +0700 Subject: [PATCH 230/329] adjustment --- assets/docs/general-consent.html | 12 ++++++------ .../use-case/main-use-case/generate-file/tycovar.go | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/assets/docs/general-consent.html b/assets/docs/general-consent.html index a3f69826..de84a742 100644 --- a/assets/docs/general-consent.html +++ b/assets/docs/general-consent.html @@ -125,11 +125,11 @@ >
        c) Anggota keluarga saya : - {{ if eq (len .PatientRelatives_Name) 0 }} + {{ if eq (len .Relatives) 0 }} .......................................... {{ else }}
          - {{ range $i, $name := .PatientRelatives_Name }} + {{ range $i, $name := .Relatives }} {{ if lt $i 2 }}
        • {{ $name }}
        • {{ end }} @@ -271,7 +271,7 @@
          - {{ .Responsible_Name }} + {{ .Responsible }}
          @@ -285,7 +285,7 @@
          - {{ .InformationGivenBy_Name }} + {{ .Informant }}
          @@ -299,7 +299,7 @@
          - {{ .Witness1_Name }} + {{ .Witness1 }}
          @@ -313,7 +313,7 @@
          - {{ .Witness2_Name }} + {{ .Witness2 }}
          diff --git a/internal/use-case/main-use-case/generate-file/tycovar.go b/internal/use-case/main-use-case/generate-file/tycovar.go index 1e16cdb8..f9fdf689 100644 --- a/internal/use-case/main-use-case/generate-file/tycovar.go +++ b/internal/use-case/main-use-case/generate-file/tycovar.go @@ -6,12 +6,12 @@ import ( ) type GeneralConsentPDF struct { - PatientRelatives_Name []string `json:"patientRelatives_name"` - Responsible_Name string `json:"responsible_name"` - InformationGivenBy_Name string `json:"informationGivenBy_name"` - Witness1_Name string `json:"witness1_name"` - Witness2_Name string `json:"witness2_name"` - Date string `json:"date"` + Relatives []string `json:"relatives"` + Responsible string `json:"responsible"` + Informant string `json:"informant"` + Witness1 string `json:"witness1"` + Witness2 string `json:"witness2"` + Date string `json:"date"` } type GenerateDto struct { From 8644bcaedc8d4179e4c84f8d97c3474fc22b1fbd Mon Sep 17 00:00:00 2001 From: vanilia Date: Wed, 19 Nov 2025 13:21:04 +0700 Subject: [PATCH 231/329] add patient --- .../domain/main-entities/person/entity.go | 2 +- .../{Encounter => encounter}/entity.go | 0 .../domain/simgos-entities/patient/entity.go | 6 +- .../simgos-sync-handler/patient/handler.go | 63 ++++ .../simgos-sync-handler.go | 2 + .../main-use-case/division/middleware.go | 8 +- .../main-use-case/installation/middleware.go | 8 +- .../use-case/main-use-case/patient/case.go | 151 ++++++--- .../use-case/main-use-case/patient/lib.go | 3 +- .../patient/middleware-runner.go | 81 ++++- .../main-use-case/patient/middleware.go | 19 +- .../use-case/main-use-case/patient/tycovar.go | 35 +- .../main-use-case/person-address/lib.go | 25 ++ .../main-use-case/person-contact/lib.go | 25 ++ .../main-use-case/person-insurance/lib.go | 25 ++ .../main-use-case/person-relative/lib.go | 25 ++ .../main-use-case/specialist/middleware.go | 8 +- internal/use-case/main-use-case/unit/case.go | 2 +- .../use-case/main-use-case/unit/middleware.go | 8 +- .../simgos-sync-plugin/patient/plugin.go | 167 +++++++++ .../simgos-sync-use-case/patient/case.go | 203 +++++++++++ .../simgos-sync-use-case/patient/helper.go | 316 ++++++++++++++++++ .../simgos-sync-use-case/patient/lib.go | 194 +++++++++++ .../patient/middleware-runner.go | 104 ++++++ .../patient/middleware.go | 9 + .../simgos-sync-use-case/patient/tycovar.go | 44 +++ 26 files changed, 1454 insertions(+), 79 deletions(-) rename internal/domain/simgos-entities/{Encounter => encounter}/entity.go (100%) create mode 100644 internal/interface/simgos-sync-handler/patient/handler.go create mode 100644 internal/use-case/simgos-sync-plugin/patient/plugin.go create mode 100644 internal/use-case/simgos-sync-use-case/patient/case.go create mode 100644 internal/use-case/simgos-sync-use-case/patient/helper.go create mode 100644 internal/use-case/simgos-sync-use-case/patient/lib.go create mode 100644 internal/use-case/simgos-sync-use-case/patient/middleware-runner.go create mode 100644 internal/use-case/simgos-sync-use-case/patient/middleware.go create mode 100644 internal/use-case/simgos-sync-use-case/patient/tycovar.go diff --git a/internal/domain/main-entities/person/entity.go b/internal/domain/main-entities/person/entity.go index d6e6744a..f36ec83a 100644 --- a/internal/domain/main-entities/person/entity.go +++ b/internal/domain/main-entities/person/entity.go @@ -34,7 +34,7 @@ type Person struct { Ocupation_Code *erp.OcupationCode `json:"occupation_code" gorm:"size:15"` Ocupation_Name *string `json:"occupation_name" gorm:"size:50"` MaritalStatus_Code *erp.MaritalStatusCode `json:"maritalStatus_code" gorm:"size:10"` - Nationality *string `json:"nationality": gorm:"size:50"` + Nationality *string `json:"nationality" gorm:"size:50"` Ethnic_Code *string `json:"ethnic_code" gorm:"size:20"` Ethnic *ee.Ethnic `json:"ethnic,omitempty" gorm:"foreignKey:Ethnic_Code;references:Code"` Language_Code *string `json:"language_code" gorm:"size:10"` diff --git a/internal/domain/simgos-entities/Encounter/entity.go b/internal/domain/simgos-entities/encounter/entity.go similarity index 100% rename from internal/domain/simgos-entities/Encounter/entity.go rename to internal/domain/simgos-entities/encounter/entity.go diff --git a/internal/domain/simgos-entities/patient/entity.go b/internal/domain/simgos-entities/patient/entity.go index 3013e121..20b7fee6 100644 --- a/internal/domain/simgos-entities/patient/entity.go +++ b/internal/domain/simgos-entities/patient/entity.go @@ -4,14 +4,14 @@ import "time" type MPasien struct { Id uint `json:"id" gorm:"primaryKey;autoIncrement;column:id"` - Nomr string `json:"nomr" gorm:"column:nomr"` + 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 *time.Time `json:"tgllahir" gorm:"column:tgllahir"` Jeniskelamin string `json:"jeniskelamin" gorm:"column:jeniskelamin"` Alamat string `json:"alamat" gorm:"column:alamat"` - Kelurahan uint `json:"kelurahan" gorm:"column:kelurahan"` + 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"` @@ -41,7 +41,7 @@ type MPasien struct { 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" json:"bahasa"` + 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"` diff --git a/internal/interface/simgos-sync-handler/patient/handler.go b/internal/interface/simgos-sync-handler/patient/handler.go new file mode 100644 index 00000000..ae2e1db8 --- /dev/null +++ b/internal/interface/simgos-sync-handler/patient/handler.go @@ -0,0 +1,63 @@ +package patient + +import ( + "net/http" + + rw "github.com/karincake/risoles" + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/patient" + esync "simrs-vx/internal/domain/sync-entities/log" + u "simrs-vx/internal/use-case/simgos-sync-use-case/patient" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.Patient{} + 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) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.Patient{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint(id) + + 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/simgos-sync-handler.go b/internal/interface/simgos-sync-handler/simgos-sync-handler.go index 6b63e1d6..dee6fb3f 100644 --- a/internal/interface/simgos-sync-handler/simgos-sync-handler.go +++ b/internal/interface/simgos-sync-handler/simgos-sync-handler.go @@ -19,6 +19,7 @@ import ( "simrs-vx/internal/interface/main-handler/home" division "simrs-vx/internal/interface/simgos-sync-handler/division" installation "simrs-vx/internal/interface/simgos-sync-handler/installation" + patient "simrs-vx/internal/interface/simgos-sync-handler/patient" specialist "simrs-vx/internal/interface/simgos-sync-handler/specialist" subspecialist "simrs-vx/internal/interface/simgos-sync-handler/subspecialist" unit "simrs-vx/internal/interface/simgos-sync-handler/unit" @@ -43,6 +44,7 @@ func SetRoutes() http.Handler { hc.SyncCrud(r, prefix+"/v1/division", division.O) hc.SyncCrud(r, prefix+"/v1/specialist", specialist.O) hc.SyncCrud(r, prefix+"/v1/subspecialist", subspecialist.O) + hc.SyncCrud(r, prefix+"/v1/patient", patient.O) return cmw.SetCors(handlerlogger.SetLog(r)) } diff --git a/internal/use-case/main-use-case/division/middleware.go b/internal/use-case/main-use-case/division/middleware.go index 317b137a..83452940 100644 --- a/internal/use-case/main-use-case/division/middleware.go +++ b/internal/use-case/main-use-case/division/middleware.go @@ -7,14 +7,14 @@ import ( // example of middleware func init() { createPreMw = append(createPreMw, - createMw{Name: "create-unit", Func: plugin.Create}) + createMw{Name: "sync-create-division", Func: plugin.Create}) createSimxLogMw = append(createSimxLogMw, - createLogMw{Name: "create-log", Func: plugin.CreateLog}) + createLogMw{Name: "create-sync-log", Func: plugin.CreateLog}) updatePreMw = append(updatePreMw, - updateMw{Name: "update-unit", Func: plugin.Update}) + updateMw{Name: "sync-update-division", Func: plugin.Update}) deletePreMw = append(deletePreMw, - deleteMw{Name: "delete-unit", Func: plugin.Delete}) + deleteMw{Name: "sync-delete-division", Func: plugin.Delete}) } diff --git a/internal/use-case/main-use-case/installation/middleware.go b/internal/use-case/main-use-case/installation/middleware.go index b8dfa4c8..f32b7381 100644 --- a/internal/use-case/main-use-case/installation/middleware.go +++ b/internal/use-case/main-use-case/installation/middleware.go @@ -7,14 +7,14 @@ import ( // example of middleware func init() { createPreMw = append(createPreMw, - createMw{Name: "create-installation", Func: plugin.Create}) + createMw{Name: "sync-create-installation", Func: plugin.Create}) createSimxLogMw = append(createSimxLogMw, - createLogMw{Name: "create-log", Func: plugin.CreateLog}) + createLogMw{Name: "create-sync-log", Func: plugin.CreateLog}) updatePreMw = append(updatePreMw, - updateMw{Name: "update-installation", Func: plugin.Update}) + updateMw{Name: "sync-update-installation", Func: plugin.Update}) deletePreMw = append(deletePreMw, - deleteMw{Name: "delete-installation", Func: plugin.Delete}) + deleteMw{Name: "sync-delete-installation", Func: plugin.Delete}) } diff --git a/internal/use-case/main-use-case/patient/case.go b/internal/use-case/main-use-case/patient/case.go index a0766d12..96a5f06d 100644 --- a/internal/use-case/main-use-case/patient/case.go +++ b/internal/use-case/main-use-case/patient/case.go @@ -3,22 +3,25 @@ package patient import ( "strconv" - evm "simrs-vx/internal/domain/bpjs-entities/vclaim-member" - e "simrs-vx/internal/domain/main-entities/patient" - - uvm "simrs-vx/internal/use-case/bpjs-use-case/vclaim-member" - upe "simrs-vx/internal/use-case/main-use-case/person" - upa "simrs-vx/internal/use-case/main-use-case/person-address" - upc "simrs-vx/internal/use-case/main-use-case/person-contact" - upi "simrs-vx/internal/use-case/main-use-case/person-insurance" - upr "simrs-vx/internal/use-case/main-use-case/person-relative" - pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" "gorm.io/gorm" + + erc "simrs-vx/internal/domain/references/common" + + evm "simrs-vx/internal/domain/bpjs-entities/vclaim-member" + e "simrs-vx/internal/domain/main-entities/patient" + esync "simrs-vx/internal/domain/sync-entities/log" + + uvm "simrs-vx/internal/use-case/bpjs-use-case/vclaim-member" + upe "simrs-vx/internal/use-case/main-use-case/person" + upa "simrs-vx/internal/use-case/main-use-case/person-address" + upc "simrs-vx/internal/use-case/main-use-case/person-contact" + upi "simrs-vx/internal/use-case/main-use-case/person-insurance" + upr "simrs-vx/internal/use-case/main-use-case/person-relative" ) const source = "patient" @@ -33,9 +36,9 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") + mwRunner := newMiddlewareRunner(&event) 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 { @@ -88,21 +91,26 @@ func Create(input e.CreateDto) (*d.Data, error) { data = *resData } - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + dataPatient, err := ReadDetailData(e.ReadDetailDto{Id: uint16(data.Id)}, &event, tx) + if err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunCreateSyncMiddleware(createSimxSyncMw, dataPatient); err != nil { + return err + } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.II{ "source": source, @@ -128,7 +136,7 @@ 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 := newMiddlewareRunner(&event) mwRunner.setMwType(pu.MWTPre) // Run pre-middleware if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { @@ -179,7 +187,7 @@ 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 := newMiddlewareRunner(&event) mwRunner.setMwType(pu.MWTPre) // Run pre-middleware if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { @@ -225,6 +233,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "update") + mwRunner := newMiddlewareRunner(&event) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -232,13 +241,6 @@ 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 person_id, err := upe.CreateOrUpdatePerson(input.Person, &event, tx); err != nil { return err } else { @@ -277,21 +279,26 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } - pl.SetLogInfo(&event, nil, "complete") + dataPatient, err := ReadDetailData(e.ReadDetailDto{Id: uint16(data.Id)}, &event) + if err != nil { + return err + } - mwRunner.setMwType(pu.MWTPost) + mwRunner.setMwType(pu.MWTPre) // Run post-middleware - if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + if err := mwRunner.RunUpdateMiddleware(updatePreMw, dataPatient); err != nil { return err } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -315,6 +322,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "delete") + mwRunner := newMiddlewareRunner(&event) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -322,30 +330,68 @@ 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 - } + input.Id = data.Id + // Delete Patient if err := DeleteData(data, &event, tx); err != nil { return err } - mwRunner.setMwType(pu.MWTPost) + // Delete PersonInsurance + if insurance := data.Person.Insurances; insurance != nil && len(*insurance) > 0 { + if err = upi.DeleteMultipleData(data.Person_Id, &event, tx); err != nil { + return err + } + } + + // Delete PersonRelative + if relative := data.Person.Relatives; relative != nil && len(*relative) > 0 { + if err = upr.DeleteMultipleData(data.Person_Id, &event, tx); err != nil { + return err + } + } + + // Delete PersonContacts + if contact := data.Person.Contacts; contact != nil && len(*contact) > 0 { + if err = upc.DeleteMultipleData(data.Person_Id, &event, tx); err != nil { + return err + } + } + + // Delete PersonAddress + if address := data.Person.Addresses; address != nil && len(*address) > 0 { + if err = upa.DeleteMultipleData(data.Person_Id, &event, tx); err != nil { + return err + } + } + + // Delete VclaimMember + if vclaim := data.Person.VclaimMember; vclaim != nil { + if err = uvm.DeleteData(vclaim, &event, tx); err != nil { + return err + } + } + + // Delete Person + if err = upe.DeleteData(data.Person, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPre) // Run post-middleware - if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + if err := mwRunner.RunDeleteMiddleware(deletePreMw, &input); err != nil { return err } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -421,3 +467,32 @@ func Search(input e.SearchDto) (*d.Data, error) { Data: e.ToResponseList(dataList), }, nil } + +func runLogMiddleware(err error, input any, mwRunner *middlewareRunner) error { + var errMsg string + inputLog := esync.SimxLogDto{ + Payload: input, + Method: erc.CCCreate, + } + + if err != nil { + // Run log-middleware + errMsg = err.Error() + inputLog.ErrMessage = &errMsg + inputLog.IsSuccess = false + + // create log failed + if errMiddleware := mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog); errMiddleware != nil { + return errMiddleware + } + return err + } + + // create log success + inputLog.IsSuccess = true + if err = mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog); err != nil { + return err + } + + return nil +} diff --git a/internal/use-case/main-use-case/patient/lib.go b/internal/use-case/main-use-case/patient/lib.go index 36c9d416..e615c854 100644 --- a/internal/use-case/main-use-case/patient/lib.go +++ b/internal/use-case/main-use-case/patient/lib.go @@ -92,7 +92,8 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e Preload("Person.Relatives.Village.District.Regency.Province"). Preload("Person.Addresses.Village.District.Regency.Province"). Preload("Person.Addresses.PostalRegion.Village.District.Regency.Province"). - Preload("Person.Insurances.InsuranceCompany") + Preload("Person.Insurances.InsuranceCompany"). + Preload("Person.VclaimMember") if err := tx.First(&data, input.Id).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { 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 2e9ea66a..f9e05bb7 100644 --- a/internal/use-case/main-use-case/patient/middleware-runner.go +++ b/internal/use-case/main-use-case/patient/middleware-runner.go @@ -1,24 +1,29 @@ package patient import ( - e "simrs-vx/internal/domain/main-entities/patient" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" "gorm.io/gorm" + + sync "simrs-vx/internal/infra/sync-cfg" + + e "simrs-vx/internal/domain/main-entities/patient" + esync "simrs-vx/internal/domain/sync-entities/log" ) 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) *middlewareRunner { return &middlewareRunner{ - Event: event, - Tx: tx, + Event: event, + SyncOn: sync.O.Enable, } } @@ -38,7 +43,51 @@ func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e return nil } +// ExecuteCreateMiddleware executes create middleware +func (me *middlewareRunner) RunCreateSyncMiddleware(middlewares []createSyncMw, input *e.Patient) error { + if !me.SyncOn { + return nil + } + + 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) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +// ExecuteCreateMiddleware executes create middleware +func (me *middlewareRunner) RunCreateLogMiddleware(middlewares []createLogMw, input *esync.SimxLogDto) error { + if !me.SyncOn { + return nil + } + + 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) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.Patient) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -54,6 +103,10 @@ func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, inpu } func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Patient) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -68,13 +121,17 @@ func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, return nil } -func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Patient) error { +func (me *middlewareRunner) RunUpdateMiddleware(middlewares []updateMw, input *e.Patient) error { + if !me.SyncOn { + return nil + } + 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 +140,17 @@ func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, inpu return nil } -func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Patient) error { +func (me *middlewareRunner) RunDeleteMiddleware(middlewares []deleteMw, input *e.DeleteDto) error { + if !me.SyncOn { + return nil + } + 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) } diff --git a/internal/use-case/main-use-case/patient/middleware.go b/internal/use-case/main-use-case/patient/middleware.go index 6b0175dc..cc97473f 100644 --- a/internal/use-case/main-use-case/patient/middleware.go +++ b/internal/use-case/main-use-case/patient/middleware.go @@ -6,16 +6,29 @@ import ( "io" "net/http" + "gorm.io/gorm" + e "simrs-vx/internal/domain/main-entities/patient" - "gorm.io/gorm" + plugin "simrs-vx/internal/use-case/simgos-sync-plugin/patient" ) // example of middleware func init() { createPreMw = append(createPreMw, - createMw{Name: "check-vclaim-member", Func: checkVclaimMember}, - ) + createMw{Name: "check-vclaim-member", Func: checkVclaimMember}) + + createSimxSyncMw = append(createSimxSyncMw, + createSyncMw{Name: "sync-create-patient", Func: plugin.Create}) + + createSimxLogMw = append(createSimxLogMw, + createLogMw{Name: "create-sync-log", Func: plugin.CreateLog}) + + updatePreMw = append(updatePreMw, + updateMw{Name: "sync-update-patient", Func: plugin.Update}) + + deletePreMw = append(deletePreMw, + deleteMw{Name: "sync-delete-patient", Func: plugin.Delete}) } func checkVclaimMember(input *e.CreateDto, data *e.Patient, tx *gorm.DB) error { diff --git a/internal/use-case/main-use-case/patient/tycovar.go b/internal/use-case/main-use-case/patient/tycovar.go index 29e5c368..cedb1514 100644 --- a/internal/use-case/main-use-case/patient/tycovar.go +++ b/internal/use-case/main-use-case/patient/tycovar.go @@ -12,6 +12,7 @@ import ( "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/patient" + elog "simrs-vx/internal/domain/sync-entities/log" ) type createMw struct { @@ -19,6 +20,26 @@ type createMw struct { Func func(input *e.CreateDto, data *e.Patient, tx *gorm.DB) error } +type createSyncMw struct { + Name string + Func func(input *e.Patient) error +} + +type createLogMw struct { + Name string + Func func(input *elog.SimxLogDto) error +} + +type updateMw struct { + Name string + Func func(input *e.Patient) error +} + +type deleteMw struct { + Name string + Func func(input *e.DeleteDto) error +} + type readListMw struct { Name string Func func(input *e.ReadListDto, data *e.Patient, tx *gorm.DB) error @@ -29,18 +50,20 @@ type readDetailMw struct { Func func(input *e.ReadDetailDto, data *e.Patient, 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 +var createPreMw []createMw // preprocess middleware +var createPostMw []createMw // postprocess middleware +var createSimxSyncMw []createSyncMw // postprocess middleware +var createSimxLogMw []createLogMw 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 type BPJSResponse struct { diff --git a/internal/use-case/main-use-case/person-address/lib.go b/internal/use-case/main-use-case/person-address/lib.go index d0a581bd..94cbfa69 100644 --- a/internal/use-case/main-use-case/person-address/lib.go +++ b/internal/use-case/main-use-case/person-address/lib.go @@ -191,3 +191,28 @@ func CreateOrUpdateBatch(input []e.UpdateDto, event *pl.Event, tx ...*gorm.DB) e return nil } + +func DeleteMultipleData(personId *uint, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, personId, "started", "DBDelete") + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx. + Where("\"Person_Id\" = ?", *personId). + Delete(&e.PersonAddress{}).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-delete-fail", + Detail: "Database delete failed", + Raw: err, + } + return pl.SetLogError(event, personId) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} diff --git a/internal/use-case/main-use-case/person-contact/lib.go b/internal/use-case/main-use-case/person-contact/lib.go index 034800a4..2c0028bf 100644 --- a/internal/use-case/main-use-case/person-contact/lib.go +++ b/internal/use-case/main-use-case/person-contact/lib.go @@ -191,3 +191,28 @@ func CreateOrUpdateBatch(input []e.UpdateDto, event *pl.Event, tx ...*gorm.DB) e return nil } + +func DeleteMultipleData(personId *uint, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, personId, "started", "DBDelete") + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx. + Where("\"Person_Id\" = ?", *personId). + Delete(&e.PersonContact{}).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-delete-fail", + Detail: "Database delete failed", + Raw: err, + } + return pl.SetLogError(event, personId) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} diff --git a/internal/use-case/main-use-case/person-insurance/lib.go b/internal/use-case/main-use-case/person-insurance/lib.go index 86c6dc83..835694ff 100644 --- a/internal/use-case/main-use-case/person-insurance/lib.go +++ b/internal/use-case/main-use-case/person-insurance/lib.go @@ -191,3 +191,28 @@ func CreateOrUpdateBatch(input []e.UpdateDto, event *pl.Event, tx ...*gorm.DB) e return nil } + +func DeleteMultipleData(personId *uint, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, personId, "started", "DBDelete") + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx. + Where("\"Person_Id\" = ?", *personId). + Delete(&e.PersonInsurance{}).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-delete-fail", + Detail: "Database delete failed", + Raw: err, + } + return pl.SetLogError(event, personId) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} diff --git a/internal/use-case/main-use-case/person-relative/lib.go b/internal/use-case/main-use-case/person-relative/lib.go index 28e12e2b..4531f736 100644 --- a/internal/use-case/main-use-case/person-relative/lib.go +++ b/internal/use-case/main-use-case/person-relative/lib.go @@ -191,3 +191,28 @@ func CreateOrUpdateBatch(input []e.UpdateDto, event *pl.Event, tx ...*gorm.DB) e return nil } + +func DeleteMultipleData(personId *uint, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, personId, "started", "DBDelete") + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx. + Where("\"Person_Id\" = ?", *personId). + Delete(&e.PersonRelative{}).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-delete-fail", + Detail: "Database delete failed", + Raw: err, + } + return pl.SetLogError(event, personId) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} diff --git a/internal/use-case/main-use-case/specialist/middleware.go b/internal/use-case/main-use-case/specialist/middleware.go index 5d119b01..969436e5 100644 --- a/internal/use-case/main-use-case/specialist/middleware.go +++ b/internal/use-case/main-use-case/specialist/middleware.go @@ -7,14 +7,14 @@ import ( // example of middleware func init() { createPreMw = append(createPreMw, - createMw{Name: "create-unit", Func: plugin.Create}) + createMw{Name: "sync-create-specialist", Func: plugin.Create}) createSimxLogMw = append(createSimxLogMw, - createLogMw{Name: "create-log", Func: plugin.CreateLog}) + createLogMw{Name: "create-sync-log", Func: plugin.CreateLog}) updatePreMw = append(updatePreMw, - updateMw{Name: "update-unit", Func: plugin.Update}) + updateMw{Name: "sync-update-specialiast", Func: plugin.Update}) deletePreMw = append(deletePreMw, - deleteMw{Name: "delete-unit", Func: plugin.Delete}) + deleteMw{Name: "sync-delete-specialist", Func: plugin.Delete}) } diff --git a/internal/use-case/main-use-case/unit/case.go b/internal/use-case/main-use-case/unit/case.go index 75b1c4ab..1db6fb79 100644 --- a/internal/use-case/main-use-case/unit/case.go +++ b/internal/use-case/main-use-case/unit/case.go @@ -210,7 +210,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { return err } - mwRunner.setMwType(pu.MWTPost) + mwRunner.setMwType(pu.MWTPre) // Run pre-middleware if err := mwRunner.RunDeleteMiddleware(deletePreMw, &input); err != nil { return err diff --git a/internal/use-case/main-use-case/unit/middleware.go b/internal/use-case/main-use-case/unit/middleware.go index e3144448..0e62f502 100644 --- a/internal/use-case/main-use-case/unit/middleware.go +++ b/internal/use-case/main-use-case/unit/middleware.go @@ -7,14 +7,14 @@ import ( // example of middleware func init() { createPreMw = append(createPreMw, - createMw{Name: "create-unit", Func: plugin.Create}) + createMw{Name: "sync-create-unit", Func: plugin.Create}) createSimxLogMw = append(createSimxLogMw, - createLogMw{Name: "create-log", Func: plugin.CreateLog}) + createLogMw{Name: "create-sync-log", Func: plugin.CreateLog}) updatePreMw = append(updatePreMw, - updateMw{Name: "update-unit", Func: plugin.Update}) + updateMw{Name: "sync-update-unit", Func: plugin.Update}) deletePreMw = append(deletePreMw, - deleteMw{Name: "delete-unit", Func: plugin.Delete}) + deleteMw{Name: "sync-delete-unit", Func: plugin.Delete}) } diff --git a/internal/use-case/simgos-sync-plugin/patient/plugin.go b/internal/use-case/simgos-sync-plugin/patient/plugin.go new file mode 100644 index 00000000..b10fdce5 --- /dev/null +++ b/internal/use-case/simgos-sync-plugin/patient/plugin.go @@ -0,0 +1,167 @@ +package patient + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + + d "github.com/karincake/dodol" + + sync "simrs-vx/internal/infra/sync-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 +} + +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 +} + +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 +} + +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 +} + +func getPrefixEndpoint() string { + return fmt.Sprintf("%s%s/v1/patient", sync.O.Host, sync.O.Prefix) +} diff --git a/internal/use-case/simgos-sync-use-case/patient/case.go b/internal/use-case/simgos-sync-use-case/patient/case.go new file mode 100644 index 00000000..e6d13c89 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/patient/case.go @@ -0,0 +1,203 @@ +package patient + +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/patient" + esimgos "simrs-vx/internal/domain/simgos-entities/patient" + elog "simrs-vx/internal/domain/sync-entities/log" + esync "simrs-vx/internal/domain/sync-entities/patient" +) + +const source = "patient" + +func Create(input e.Patient) (*d.Data, error) { + var ( + sgData *esimgos.MPasien + syncLink *esync.PatientLink + err error + ) + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + err = db.WithDualTx(func(tx *db.Dualtx) error { + // STEP 1: Insert to simgos + sgData, err = CreateSimgosData(input, &event, tx.Simgos) + if err != nil { + return err + } + + // STEP 2: Insert to Link + syncLink, err = CreateLinkData(input.Id, sgData.Id, &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.Patient) (*d.Data, error) { + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + // STEP 1: Get Link + syncLink, err := ReadDetailLinkData(uint16(input.Id), &event) + if err != nil { + return nil, err + } + + // STEP 2: Get Simgos + patientData, err := ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) + if err != nil { + return nil, err + } + + tx := db.NewTx() + err = tx.Simgos.Transaction(func(tx *gorm.DB) error { + // Step 3: Update Simgos + if err = UpdateSimgosData(input, syncLink.Simgos_Id, patientData.Nomr, &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") + + // STEP 1: Get Link + syncLink, err := ReadDetailLinkData(uint16(input.Id), &event) + if err != nil { + return nil, err + } + + // STEP 2: Get Simgos + sgData, err := ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) + if err != nil { + return nil, err + } + + err = db.WithDualTx(func(tx *db.Dualtx) error { + // STEP 3: Delete Simgos + err = HardDeleteSimgosData(sgData, &event, tx.Simgos) + if 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, sgData.Id, &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/patient/helper.go b/internal/use-case/simgos-sync-use-case/patient/helper.go new file mode 100644 index 00000000..4b7ddfe6 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/patient/helper.go @@ -0,0 +1,316 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package patient + +import ( + "encoding/json" + "fmt" + erc "simrs-vx/internal/domain/references/common" + erp "simrs-vx/internal/domain/references/person" + "strconv" + + e "simrs-vx/internal/domain/main-entities/patient" + ep "simrs-vx/internal/domain/main-entities/person" + 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" + esimgos "simrs-vx/internal/domain/simgos-entities/patient" + esyncLog "simrs-vx/internal/domain/sync-entities/log" + esync "simrs-vx/internal/domain/sync-entities/patient" + + dg "github.com/karincake/apem/db-gorm-pg" + "gorm.io/gorm/clause" +) + +func setDataSimgos(input *e.Patient) (data esimgos.MPasien) { + if p := input.Person; p != nil { + mapPerson(p, &data) + } + + if input.Person != nil && input.Person.Addresses != nil { + mapAddress(input.Person.Addresses, &data) + } + + if input.Person != nil && input.Person.Contacts != nil { + mapContact(input.Person.Contacts, &data) + } + + if input.Person != nil && input.Person.Relatives != nil { + mapRelative(input.Person.Relatives, &data) + } + + data.Nip = input.RegisteredBy_User_Name + data.Tgldaftar = input.RegisteredAt + + return +} + +func generateNomrPatient() (string, error) { + const prefix = "12" // fixed starting prefix (same as $awal_rm) in simgos + const maxSuffix = 999999 + + type Row struct { + Nomr string `gorm:"column:nomr"` + } + + var r Row + + // Lock rows for this prefix → prevents race condition + if err := dg.IS["simrs"]. + Table("m_pasien"). + Select("nomr"). + Where("nomr LIKE ?", prefix+"%"). + Order("nomr DESC"). + Clauses(clause.Locking{Strength: "UPDATE"}). + Limit(1). + Scan(&r).Error; err != nil { + return "", err + } + + // No existing NOMR → start fresh + if r.Nomr == "" { + return prefix + "000001", nil + } + + suffix := r.Nomr[len(prefix):] // extract numeric part + num, _ := strconv.Atoi(suffix) + + // 3. If suffix reaches 999999 → increment the prefix + if num == maxSuffix { + p, _ := strconv.Atoi(prefix) + p++ + return fmt.Sprintf("%d000001", p), nil + } + + // 4. Normal increment + return prefix + fmt.Sprintf("%06d", num+1), nil +} + +func mapPerson(p *ep.Person, data *esimgos.MPasien) { + if p.FrontTitle != nil { + data.Title = *p.FrontTitle + } + + if p.BirthRegency != nil { + data.Tempat = p.BirthRegency.Name + } + + if p.BirthDate != nil { + data.Tgllahir = p.BirthDate + } + + if p.Gender_Code != nil { + if *p.Gender_Code == erp.GCMale { + data.Jeniskelamin = "L" + } else if *p.Gender_Code == erp.GCFemale { + data.Jeniskelamin = "P" + } + } + + data.Nama = p.Name + data.Noktp = *p.ResidentIdentityNumber + data.NoktpBaru = *p.ResidentIdentityNumber + data.Pekerjaan = *p.Ocupation_Name + + data.Status, data.TxtStatus = setMaritalStatus(p.MaritalStatus_Code) + data.Agama, data.TxtAgama = setReligion(p.Religion_Code) + data.Pendidikan, data.TxtPendidikan = setEducation(p.Education_Code) + + if c := p.VclaimMember; c != nil && c.CardNumber != nil { + data.NoKartu = *c.CardNumber + } + + if l := p.Language; l != nil { + data.Bahasa = l.Name + } + + if p.CommunicationIssueStatus { + data.HambatanKomunikasi = "Y" + } else { + data.HambatanKomunikasi = "T" + } + + if p.Nationality != nil { + data.Kebangsaan = *p.Nationality + } + + if p.Ethnic != nil { + data.Suku = p.Ethnic.Name + } +} + +func setMaritalStatus(code *erp.MaritalStatusCode) (uint, string) { + if code != nil { + switch *code { + case erp.MaritalStatusSingle: + return 1, "Belum Menikah" + case erp.MaritalStatusMarried: + return 2, "Menikah" + case erp.MaritalStatusDivorced: + return 4, "Cerai" + case erp.MaritalStatusWidowed: + return 3, "Janda/Duda" + default: + return 0, "Tidak Diketahui" + } + } else { + return 0, "Tidak Diketahui" + } +} + +func setReligion(code *erp.ReligionCode) (uint, string) { + if code != nil { + switch *code { + case erp.RCIslam: + return 1, "Islam" + case erp.RCProtestan: + return 2, "Kristen Protestan" + case erp.RCKatolik: + return 3, "Katholik" + case erp.RCHindu: + return 4, "Hindu" + case erp.RCBudha: + return 5, "Budha" + case erp.RCKonghucu: + return 6, "Konghucu" + default: + return 9, "Lainnya" + } + } else { + return 0, "Tidak Diketahui" + } +} + +func setEducation(code *erp.EducationCode) (uint, string) { + if code != nil { + switch *code { + case erp.ECTS: + return 0, "Tidak Sekolah" + case erp.ECSD: + return 1, string(erp.ECSD) + case erp.ECSLTP: + return 2, string(erp.ECSLTP) + case erp.ECSLTA: + return 3, string(erp.ECSLTA) + case erp.ECD1, erp.ECD2, erp.ECD3, erp.ECD4: + return 4, "D3/Akademik" + case erp.ECS1, erp.ECS2, erp.ECS3: + return 5, "Universitas" + case erp.ECOther: + return 6, "Lainnya" + default: + return 7, "Tidak Diketahui" + } + } else { + return 7, "Tidak Diketahui" + } +} + +func mapAddress(addresses *[]epa.PersonAddress, data *esimgos.MPasien) { + if addresses == nil || len(*addresses) == 0 { + return + } + + a := (*addresses)[0] + data.Alamat = a.Address + data.AlamatKtp = a.Address + + if v := a.Village; v != nil { + villageCode, _ := strconv.Atoi(v.Code) + data.Kelurahan = uint64(villageCode) + data.TxtKelurahan = v.Name + + if d := v.District; d != nil { + districtCode, _ := strconv.Atoi(d.Code) + data.Kdkecamatan = uint(districtCode) + data.TxtKecamatan = d.Name + + if r := d.Regency; r != nil { + regencyCode, _ := strconv.Atoi(r.Code) + data.Kota = uint(regencyCode) + data.TxtKota = r.Name + + if p := r.Province; p != nil { + provinceCode, _ := strconv.Atoi(p.Code) + data.Kdprovinsi = uint(provinceCode) + data.TxtProvinsi = p.Name + } + } + } + } +} + +func mapContact(contact *[]epc.PersonContact, data *esimgos.MPasien) { + if contact == nil || len(*contact) == 0 { + return + } + + for _, c := range *contact { + if c.Type_Code == erp.CTPhone || c.Type_Code == erp.CTMPhone { + data.Notelp = c.Value + break + } + } + +} + +func mapRelative(relative *[]epr.PersonRelative, data *esimgos.MPasien) { + if relative == nil || len(*relative) == 0 { + return + } + + r := (*relative)[0] + data.PenanggungjawabNama = *r.Name + + switch r.Relationship_Code { + case erp.RCMother, erp.RCFather: + data.PenanggungjawabHubungan = "ORANG TUA" + switch { + case r.Relationship_Code == erp.RCMother: + data.NamaIbu = *r.Name + eduCode, _ := setEducation(r.Education_Code) + data.PendidikanIbu = strconv.Itoa(int(eduCode)) + case r.Relationship_Code == erp.RCFather: + data.NamaAyah = *r.Name + eduCode, _ := setEducation(r.Education_Code) + data.PendidikanAyah = strconv.Itoa(int(eduCode)) + } + case erp.RCChild: + data.PenanggungjawabHubungan = "ANAK" + default: + data.PenanggungjawabHubungan = "LAINNYA" + } + + data.PenanggungjawabAlamat = *r.Address + data.PenanggungjawabPhone = *r.PhoneNumber +} + +func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.PatientSimxLog) { + // 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.PatientLink) { + data.Simx_Id = simxId + data.Simgos_Id = simgosId + return +} diff --git a/internal/use-case/simgos-sync-use-case/patient/lib.go b/internal/use-case/simgos-sync-use-case/patient/lib.go new file mode 100644 index 00000000..44d4c209 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/patient/lib.go @@ -0,0 +1,194 @@ +package patient + +import ( + 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/patient" + esimgos "simrs-vx/internal/domain/simgos-entities/patient" + esynclog "simrs-vx/internal/domain/sync-entities/log" + esync "simrs-vx/internal/domain/sync-entities/patient" +) + +var now = time.Now() + +func CreateSimgosData(input e.Patient, event *pl.Event, dbx ...*gorm.DB) (*esimgos.MPasien, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := setDataSimgos(&input) + nomr, err := generateNomrPatient() + if err != nil { + return nil, plh.HandleCreateError(input, event, err) + } + data.Nomr = nomr + + 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 ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.MPasien, error) { + pl.SetLogInfo(event, simgosId, "started", "DBReadDetail") + data := esimgos.MPasien{} + + var tx = dg.IS["simrs"] + + if err := tx. + Where("\"id\" = ?", 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 UpdateSimgosData(input e.Patient, patientId uint, patientNomr string, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, input, "started", "DBUpdate") + + data := setDataSimgos(&input) + data.Id = patientId + data.Nomr = patientNomr + + 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 HardDeleteSimgosData(data *esimgos.MPasien, 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 CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.PatientLink, 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 uint16, event *pl.Event) (*esync.PatientLink, error) { + pl.SetLogInfo(event, simxId, "started", "DBReadDetail") + data := esync.PatientLink{} + + 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.PatientLink, 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/patient/middleware-runner.go b/internal/use-case/simgos-sync-use-case/patient/middleware-runner.go new file mode 100644 index 00000000..648be8d7 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/patient/middleware-runner.go @@ -0,0 +1,104 @@ +package patient + +import ( + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/patient" +) + +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.Patient) 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.Patient) 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.Patient) 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.Patient) 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.Patient) 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/patient/middleware.go b/internal/use-case/simgos-sync-use-case/patient/middleware.go new file mode 100644 index 00000000..5fe75e0a --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/patient/middleware.go @@ -0,0 +1,9 @@ +package patient + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/simgos-sync-use-case/patient/tycovar.go b/internal/use-case/simgos-sync-use-case/patient/tycovar.go new file mode 100644 index 00000000..d7e9abfe --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/patient/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 patient + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/patient" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.Patient, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Patient, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Patient, 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 From 5740ea3b7642dad86c79667a683ea38d97d147c4 Mon Sep 17 00:00:00 2001 From: vanilia Date: Wed, 19 Nov 2025 13:35:19 +0700 Subject: [PATCH 232/329] change index person --- cmd/main-migration/migrations/20251119063438.sql | 4 ++++ cmd/main-migration/migrations/atlas.sum | 3 ++- internal/domain/main-entities/person/entity.go | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 cmd/main-migration/migrations/20251119063438.sql diff --git a/cmd/main-migration/migrations/20251119063438.sql b/cmd/main-migration/migrations/20251119063438.sql new file mode 100644 index 00000000..1d67246e --- /dev/null +++ b/cmd/main-migration/migrations/20251119063438.sql @@ -0,0 +1,4 @@ +-- Modify "Person" table +ALTER TABLE "public"."Person" DROP CONSTRAINT "uni_Person_ResidentIdentityNumber", ALTER COLUMN "ResidentIdentityNumber" TYPE text; +-- Create index "idx_resident_identity" to table: "Person" +CREATE UNIQUE INDEX "idx_resident_identity" ON "public"."Person" ("ResidentIdentityNumber") WHERE ("DeletedAt" IS NULL); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 4898eefa..7d7f66ee 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:vOoMJhDkNM1zFHHQLD+cHi5Xz/K4Bnv0bSNVF8IjdLs= +h1:UhULOHIbuhMYkKVWh97sQJdSpsgfHegvn8gwivFk6YQ= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -120,3 +120,4 @@ h1:vOoMJhDkNM1zFHHQLD+cHi5Xz/K4Bnv0bSNVF8IjdLs= 20251114062746.sql h1:FInLaEFQByESEwFJKuKnuUSTKmcDpi3ZXaxkKwz2+D8= 20251117005942.sql h1:wD3BWrUSmo1HlW16V3lkaBkJvbAZ0fNk77te7J9NhOc= 20251117075427.sql h1:TqU9VKZa3I8YNXUGQWY3WVBYN+1FvyyaKy0hB1jgAho= +20251119063438.sql h1:7BCr8Pr2doQT2BmsKYpyGa7gap4pWH711vClDw/VQ6s= diff --git a/internal/domain/main-entities/person/entity.go b/internal/domain/main-entities/person/entity.go index d6e6744a..aa00e6f9 100644 --- a/internal/domain/main-entities/person/entity.go +++ b/internal/domain/main-entities/person/entity.go @@ -25,7 +25,7 @@ type Person struct { BirthRegency_Code *string `json:"birthRegency_code" gorm:"size:4"` BirthRegency *er.Regency `json:"birthRegency,omitempty" gorm:"foreignKey:BirthRegency_Code;references:Code"` Gender_Code *erp.GenderCode `json:"gender_code" gorm:"size:10"` - ResidentIdentityNumber *string `json:"residentIdentityNumber" gorm:"unique;size:16"` + ResidentIdentityNumber *string `json:"residentIdentityNumber" gorm:"uniqueIndex:idx_resident_identity,where:\"DeletedAt\" IS NULL"` PassportNumber *string `json:"passportNumber" gorm:"unique;size:20"` DrivingLicenseNumber *string `json:"drivingLicenseNumber" gorm:"unique;size:20"` Religion_Code *erp.ReligionCode `json:"religion_code" gorm:"size:10"` From 015ab2d3fb82da0867b76d5de3c1ce9c96f3223d Mon Sep 17 00:00:00 2001 From: vanilia Date: Wed, 19 Nov 2025 13:59:19 +0700 Subject: [PATCH 233/329] update person entity --- cmd/main-migration/migrations/20251119065730.sql | 6 ++++++ cmd/main-migration/migrations/atlas.sum | 5 +++-- internal/domain/main-entities/person/entity.go | 8 ++++---- internal/domain/simgos-entities/patient/entity.go | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 cmd/main-migration/migrations/20251119065730.sql diff --git a/cmd/main-migration/migrations/20251119065730.sql b/cmd/main-migration/migrations/20251119065730.sql new file mode 100644 index 00000000..23015cdb --- /dev/null +++ b/cmd/main-migration/migrations/20251119065730.sql @@ -0,0 +1,6 @@ +-- Modify "Person" table +ALTER TABLE "public"."Person" DROP CONSTRAINT "uni_Person_DrivingLicenseNumber", DROP CONSTRAINT "uni_Person_PassportNumber", ALTER COLUMN "ResidentIdentityNumber" TYPE character varying(16), ALTER COLUMN "Nationality" TYPE character varying(50); +-- Create index "idx_driver_license" to table: "Person" +CREATE UNIQUE INDEX "idx_driver_license" ON "public"."Person" ("DrivingLicenseNumber") WHERE ("DeletedAt" IS NULL); +-- Create index "idx_passport" to table: "Person" +CREATE UNIQUE INDEX "idx_passport" ON "public"."Person" ("PassportNumber") WHERE ("DeletedAt" IS NULL); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 7d7f66ee..6ebacb54 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:UhULOHIbuhMYkKVWh97sQJdSpsgfHegvn8gwivFk6YQ= +h1:f+74L4+GTfxWUjGdRBK4+cl+dMKS9xAWE2a+KlI27MY= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -120,4 +120,5 @@ h1:UhULOHIbuhMYkKVWh97sQJdSpsgfHegvn8gwivFk6YQ= 20251114062746.sql h1:FInLaEFQByESEwFJKuKnuUSTKmcDpi3ZXaxkKwz2+D8= 20251117005942.sql h1:wD3BWrUSmo1HlW16V3lkaBkJvbAZ0fNk77te7J9NhOc= 20251117075427.sql h1:TqU9VKZa3I8YNXUGQWY3WVBYN+1FvyyaKy0hB1jgAho= -20251119063438.sql h1:7BCr8Pr2doQT2BmsKYpyGa7gap4pWH711vClDw/VQ6s= +20251119063438.sql h1:esk+Su7PqfQmRmRv7aDlGvzollkNAA3UK27W430xFHI= +20251119065730.sql h1:pYEs4zblH2NuhGSsM+9iPKCkAV7w81KQWdnUIifD1rk= diff --git a/internal/domain/main-entities/person/entity.go b/internal/domain/main-entities/person/entity.go index aa00e6f9..8d7f79a8 100644 --- a/internal/domain/main-entities/person/entity.go +++ b/internal/domain/main-entities/person/entity.go @@ -25,16 +25,16 @@ type Person struct { BirthRegency_Code *string `json:"birthRegency_code" gorm:"size:4"` BirthRegency *er.Regency `json:"birthRegency,omitempty" gorm:"foreignKey:BirthRegency_Code;references:Code"` Gender_Code *erp.GenderCode `json:"gender_code" gorm:"size:10"` - ResidentIdentityNumber *string `json:"residentIdentityNumber" gorm:"uniqueIndex:idx_resident_identity,where:\"DeletedAt\" IS NULL"` - PassportNumber *string `json:"passportNumber" gorm:"unique;size:20"` - DrivingLicenseNumber *string `json:"drivingLicenseNumber" gorm:"unique;size:20"` + ResidentIdentityNumber *string `json:"residentIdentityNumber" gorm:"uniqueIndex:idx_resident_identity,where:\"DeletedAt\" IS NULL;size:16"` + PassportNumber *string `json:"passportNumber" gorm:"uniqueIndex:idx_passport,where:\"DeletedAt\" IS NULL;size:20"` + DrivingLicenseNumber *string `json:"drivingLicenseNumber" gorm:"uniqueIndex:idx_driver_license,where:\"DeletedAt\" IS NULL;size:20"` Religion_Code *erp.ReligionCode `json:"religion_code" gorm:"size:10"` Confidence *string `json:"confidence" gorm:"size:512"` Education_Code *erp.EducationCode `json:"education_code" gorm:"size:10"` Ocupation_Code *erp.OcupationCode `json:"occupation_code" gorm:"size:15"` Ocupation_Name *string `json:"occupation_name" gorm:"size:50"` MaritalStatus_Code *erp.MaritalStatusCode `json:"maritalStatus_code" gorm:"size:10"` - Nationality *string `json:"nationality": gorm:"size:50"` + Nationality *string `json:"nationality" gorm:"size:50"` Ethnic_Code *string `json:"ethnic_code" gorm:"size:20"` Ethnic *ee.Ethnic `json:"ethnic,omitempty" gorm:"foreignKey:Ethnic_Code;references:Code"` Language_Code *string `json:"language_code" gorm:"size:10"` diff --git a/internal/domain/simgos-entities/patient/entity.go b/internal/domain/simgos-entities/patient/entity.go index 3013e121..605c5722 100644 --- a/internal/domain/simgos-entities/patient/entity.go +++ b/internal/domain/simgos-entities/patient/entity.go @@ -41,7 +41,7 @@ type MPasien struct { 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" json:"bahasa"` + 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"` From 211ec21d1263df4323e2a7c54d99fc19351cda3d Mon Sep 17 00:00:00 2001 From: vanilia Date: Wed, 19 Nov 2025 14:03:08 +0700 Subject: [PATCH 234/329] update migration --- cmd/main-migration/migrations/atlas.sum | 96 +++++++++++++------------ 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 62ea73a1..ab838f3d 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:6x+AHHox9nrbIP7wp+zosvvnBVMqyCJh3f/Z2Kl7T7w= +h1:FJ97x7mv6aBxLgnUAvO7/mGPnvoi+qZNnd1APvyv4yA= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,49 +75,51 @@ h1:6x+AHHox9nrbIP7wp+zosvvnBVMqyCJh3f/Z2Kl7T7w= 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= +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:dPEFgPyVuuJpWp84xqyZlXeSTK8BMYWNQfklQavOpA0= From f207b2716f762f3ed260ed4ef2b4064bb45567c0 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Wed, 19 Nov 2025 14:10:28 +0700 Subject: [PATCH 235/329] adjust control letter template html --- assets/docs/control-letter.html | 132 ++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 assets/docs/control-letter.html diff --git a/assets/docs/control-letter.html b/assets/docs/control-letter.html new file mode 100644 index 00000000..10425b28 --- /dev/null +++ b/assets/docs/control-letter.html @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + +
          + logo + +
          + SURAT RENCANA KONTROL +
          +
          + RSUD dr. Saiful Anwar +
          +
          +
          + No. :replace +
          +
          +
          + Kepada Yth +
          +
          +
          + DANI SETIAWAN +
          +
          + Sp./Sub. Rehabilitasi Medik +
          +
          + +
          + Mohon Pemeriksaan dan Penanganan Lebih Lanjut: +
          + + + + + + + + + + + + + + + + + + + + + + + +
          + No.Kartu + + :Replace +
          + Nama Peserta + + :Replace +
          + Tgl.Lahir + + :Replace +
          + Diagnosa + + :Replace +
          + Rencana Kontrol + + :Replace +
          + +
          + Demikian atas bantuannya, diucapkan banyak terima kasih. +
          + + + + + + +
          + Mengetahui, DPJP :Replace +
          + +
          + Tgl. Entry: 2025-06-07 | Tgl. Cetak: 07-06-2025 16:52 PM +
          + +
          + + + \ No newline at end of file From f00a39d1b09b0c7bf8a8b90b175521e8ebb1163e Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Wed, 19 Nov 2025 14:27:56 +0700 Subject: [PATCH 236/329] add vclaim sep control letter --- .../migrations/20251119072302.sql | 2 + .../migrations/20251119072450.sql | 15 +++++ cmd/main-migration/migrations/atlas.sum | 6 +- .../vclaim-sep-control-letter/dto.go | 61 ++++++++++++++++++ .../vclaim-sep-control-letter/entity.go | 13 ++++ .../bpjs-entities/vclaim-sep-print/entity.go | 6 +- .../bpjs-entities/vclaim-sep/entitiy.go | 8 ++- internal/interface/migration/main-entities.go | 2 + .../main-use-case/generate-file/tycovar.go | 63 +++++++++++++++++++ 9 files changed, 168 insertions(+), 8 deletions(-) create mode 100644 cmd/main-migration/migrations/20251119072302.sql create mode 100644 cmd/main-migration/migrations/20251119072450.sql create mode 100644 internal/domain/bpjs-entities/vclaim-sep-control-letter/dto.go create mode 100644 internal/domain/bpjs-entities/vclaim-sep-control-letter/entity.go create mode 100644 internal/use-case/main-use-case/generate-file/tycovar.go diff --git a/cmd/main-migration/migrations/20251119072302.sql b/cmd/main-migration/migrations/20251119072302.sql new file mode 100644 index 00000000..28208ae7 --- /dev/null +++ b/cmd/main-migration/migrations/20251119072302.sql @@ -0,0 +1,2 @@ +-- Modify "VclaimSepPrint" table +ALTER TABLE "public"."VclaimSepPrint" DROP CONSTRAINT "fk_VclaimSepPrint_VclaimSep", ADD CONSTRAINT "fk_VclaimSep_Prints" FOREIGN KEY ("VclaimSep_Number") REFERENCES "public"."VclaimSep" ("Number") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251119072450.sql b/cmd/main-migration/migrations/20251119072450.sql new file mode 100644 index 00000000..1332c843 --- /dev/null +++ b/cmd/main-migration/migrations/20251119072450.sql @@ -0,0 +1,15 @@ +-- Create "VclaimSepControlLetter" table +CREATE TABLE "public"."VclaimSepControlLetter" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "VclaimSep_Number" character varying(19) NULL, + "Number" character varying(20) NULL, + "Value" text NULL, + "FileUrl" character varying(1024) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_VclaimSepControlLetter_FileUrl" UNIQUE ("FileUrl"), + CONSTRAINT "uni_VclaimSepControlLetter_Number" UNIQUE ("Number"), + CONSTRAINT "fk_VclaimSep_ControlLetters" FOREIGN KEY ("VclaimSep_Number") REFERENCES "public"."VclaimSep" ("Number") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index ab838f3d..e4ce72b0 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:FJ97x7mv6aBxLgnUAvO7/mGPnvoi+qZNnd1APvyv4yA= +h1:8gw1BB9DWz+cNATJjG1oMXA+QAF1HrIw47xjbI33aC4= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -122,4 +122,6 @@ h1:FJ97x7mv6aBxLgnUAvO7/mGPnvoi+qZNnd1APvyv4yA= 20251117075427.sql h1:TqU9VKZa3I8YNXUGQWY3WVBYN+1FvyyaKy0hB1jgAho= 20251118074929.sql h1:p1KsWqCuR1JXA/jVO5BmOhCcaQ8clT7t0YRszAhPFbg= 20251119063438.sql h1:NVGM0X/LHD37EaPl8SNzkNiZDJ7AB1QR+LLwLh6WRdg= -20251119065730.sql h1:dPEFgPyVuuJpWp84xqyZlXeSTK8BMYWNQfklQavOpA0= +20251119065730.sql h1:U5lzk1WvMB0bw3kwckou7jkEt4bwdYItwHr2Vxqe7w4= +20251119072302.sql h1:8L+NsXPFXGZDQZIOhShvuBM9aLwU3h95tXnz6jxHhlA= +20251119072450.sql h1:ksTc8ljaHFrBo1/HiHtcnT+iJ7kPS93KgetFTf3p4Qc= diff --git a/internal/domain/bpjs-entities/vclaim-sep-control-letter/dto.go b/internal/domain/bpjs-entities/vclaim-sep-control-letter/dto.go new file mode 100644 index 00000000..f12b57da --- /dev/null +++ b/internal/domain/bpjs-entities/vclaim-sep-control-letter/dto.go @@ -0,0 +1,61 @@ +package vclaimsepcontrolletter + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type CreateDto struct { + VclaimSep_Number *string `json:"vclaimSep_number"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Sort string `json:"sort"` + Pagination ecore.Pagination +} + +type FilterDto struct { + VclaimSep_Number *string `json:"vclaimSep_number"` +} + +type ReadDetailDto struct { + Id uint `json:"id"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + VclaimSep_Number *string `json:"vclaimSep_number"` + Counter *uint `json:"counter"` +} + +func (d VclaimSepControlLetter) ToResponse() ResponseDto { + resp := ResponseDto{ + VclaimSep_Number: d.VclaimSep_Number, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []VclaimSepControlLetter) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/bpjs-entities/vclaim-sep-control-letter/entity.go b/internal/domain/bpjs-entities/vclaim-sep-control-letter/entity.go new file mode 100644 index 00000000..57f758fb --- /dev/null +++ b/internal/domain/bpjs-entities/vclaim-sep-control-letter/entity.go @@ -0,0 +1,13 @@ +package vclaimsepcontrolletter + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type VclaimSepControlLetter struct { + ecore.Main + VclaimSep_Number *string `json:"vclaimSep_number"` + Number *string `json:"number" gorm:"unique;size:20"` + Value *string `json:"value"` + FileUrl *string `json:"fileUrl" gorm:"unique;size:1024"` +} diff --git a/internal/domain/bpjs-entities/vclaim-sep-print/entity.go b/internal/domain/bpjs-entities/vclaim-sep-print/entity.go index 1bd5e9fc..52809352 100644 --- a/internal/domain/bpjs-entities/vclaim-sep-print/entity.go +++ b/internal/domain/bpjs-entities/vclaim-sep-print/entity.go @@ -2,12 +2,10 @@ package vclaimsepprint import ( ecore "simrs-vx/internal/domain/base-entities/core" - evs "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" ) type VclaimSepPrint struct { ecore.Main - VclaimSep_Number *string `json:"vclaimSep_number"` - VclaimSep *evs.VclaimSep `json:"vclaimSep,omitempty" gorm:"foreignKey:VclaimSep_Number;references:Number"` - Counter *uint `json:"counter"` + VclaimSep_Number *string `json:"vclaimSep_number"` + Counter *uint `json:"counter"` } diff --git a/internal/domain/bpjs-entities/vclaim-sep/entitiy.go b/internal/domain/bpjs-entities/vclaim-sep/entitiy.go index e23106d8..f175e4cb 100644 --- a/internal/domain/bpjs-entities/vclaim-sep/entitiy.go +++ b/internal/domain/bpjs-entities/vclaim-sep/entitiy.go @@ -2,10 +2,14 @@ package vclaimsep import ( ecore "simrs-vx/internal/domain/base-entities/core" + evscl "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-control-letter" + evsp "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-print" ) type VclaimSep struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Number *string `json:"number" gorm:"unique;size:19"` + Encounter_Id *uint `json:"encounter_id"` + Number *string `json:"number" gorm:"unique;size:19"` + Prints []*evsp.VclaimSepPrint `json:"prints,omitempty" gorm:"foreignKey:VclaimSep_Number;references:Number"` + ControlLetters []*evscl.VclaimSepControlLetter `json:"controlLetters,omitempty" gorm:"foreignKey:VclaimSep_Number;references:Number"` } diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index 94b5d545..23e7422c 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -103,6 +103,7 @@ import ( ///BPJS vclaimmember "simrs-vx/internal/domain/bpjs-entities/vclaim-member" vclaimsep "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" + vclaimsepcontrolletter "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-control-letter" vclaimsephist "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-hist" vclaimsepprint "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-print" ) @@ -211,5 +212,6 @@ func getMainEntities() []any { &rehab.Rehab{}, &chemoprotocol.ChemoProtocol{}, &fileattachemnt.EncounterDocument{}, + &vclaimsepcontrolletter.VclaimSepControlLetter{}, } } diff --git a/internal/use-case/main-use-case/generate-file/tycovar.go b/internal/use-case/main-use-case/generate-file/tycovar.go new file mode 100644 index 00000000..fed3e28c --- /dev/null +++ b/internal/use-case/main-use-case/generate-file/tycovar.go @@ -0,0 +1,63 @@ +package generatefile + +import ( + erc "simrs-vx/internal/domain/references/common" + ere "simrs-vx/internal/domain/references/encounter" +) + +type GeneralConsentPDF struct { + Relatives []string `json:"relatives"` + Responsible string `json:"responsible"` + Informant string `json:"informant"` + Witness1 string `json:"witness1"` + Witness2 string `json:"witness2"` + Date string `json:"date"` +} + +type GenerateDto struct { + EntityType_Code ere.EntityTypeCode `json:"entityType_code" validate:"required"` + Ref_Id *uint `json:"ref_id" validate:"required"` + Type_Code ere.DocTypeCode `json:"type_code" validate:"required"` + FormatType erc.DocFormatTypeCode `json:"formatType"` + TemplateName TemplateDocsName `json:"-"` + Encounter_Id *uint `json:"-"` +} + +type VclaimControlLetter struct { + Number string `json:"noSuratKontrol"` + Date string `json:"tglRencanaKontrol"` + Doctor_Name string `json:"namaDokter"` + DstUnit_Name string `json:"namaPoliTujuan"` + ResponsibleDoctor_Name string `json:"namaDokterPembuat"` + VclaimSep VclaimSep `json:"sep"` +} + +type VclaimSep struct { + VclaimMember VclaimMember `json:"peserta"` + Diagnose string `json:"diagnosa"` + Number string `json:"noSep"` +} + +type VclaimMember struct { + CardNumber string `json:"noKartu"` + Name string `json:"nama"` + BirthDate string `json:"tglLahir"` + Gender string `json:"kelamin"` +} + +type GeneratePDFdto struct { + TemplatePath string + TemplateData any + PdfPath string +} + +type ResponseDto struct { + FileUrl string `json:"fileUrl"` +} + +type TemplateDocsName string + +// TemplateDocsName is the name of the template file in the assets/docs folder +const ( + TDNGC TemplateDocsName = "general-consent.html" +) From f8674b4eca6cd88761eee4ce6fb46d92cec8ba7c Mon Sep 17 00:00:00 2001 From: vanilia Date: Wed, 19 Nov 2025 16:10:21 +0700 Subject: [PATCH 237/329] adjust patient --- internal/domain/main-entities/patient/dto.go | 1 + .../use-case/main-use-case/patient/case.go | 7 ++ .../use-case/main-use-case/patient/helper.go | 77 ++++++++++++------- .../patient/middleware-runner.go | 19 +++++ .../use-case/main-use-case/patient/tycovar.go | 6 ++ .../simgos-sync-use-case/patient/case.go | 28 +++++++ 6 files changed, 109 insertions(+), 29 deletions(-) diff --git a/internal/domain/main-entities/patient/dto.go b/internal/domain/main-entities/patient/dto.go index ec270abf..56a52e0f 100644 --- a/internal/domain/main-entities/patient/dto.go +++ b/internal/domain/main-entities/patient/dto.go @@ -28,6 +28,7 @@ type CreateDto struct { RegisteredAt *time.Time `json:"registeredAt"` RegisteredBy_User_Name *string `json:"registeredBy_user_name" validate:"maxLength=100"` Status_Code erc.ActiveStatusCode `json:"status_code" validate:"maxLength=10"` + Number *string `json:"number"` pa.AuthInfo } diff --git a/internal/use-case/main-use-case/patient/case.go b/internal/use-case/main-use-case/patient/case.go index 6c048322..1a8437e5 100644 --- a/internal/use-case/main-use-case/patient/case.go +++ b/internal/use-case/main-use-case/patient/case.go @@ -45,6 +45,13 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } + // Run pre-middleware -> Generate number + nomr, err := mwRunner.RunGenerateNumberMiddleware(generatePatientNumber) + if err != nil { + return err + } + input.Number = nomr + if person_id, err := upe.CreateOrUpdatePerson(input.Person, &event, tx); err != nil { return err } else { diff --git a/internal/use-case/main-use-case/patient/helper.go b/internal/use-case/main-use-case/patient/helper.go index c53ebca3..2c62ca21 100644 --- a/internal/use-case/main-use-case/patient/helper.go +++ b/internal/use-case/main-use-case/patient/helper.go @@ -24,7 +24,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Patient) error { inputSrc = &inputTemp.CreateDto } - if data.Id == 0 { + if data.Number == nil { medRecNum, err := GenerateNextMedicalRecordNumber() if err != nil { return err @@ -52,38 +52,57 @@ func GenerateNextMedicalRecordNumber() (string, error) { return "", err } - var nextInt int64 - var format string + //var nextInt int64 + //var format string + //if last == "" { + // // No existing records, start with 10 digits + // nextInt = 1 + // format = "%08d" + //} else { + // n, err := strconv.ParseInt(last, 10, 64) + // if err != nil { + // return "", err + // } + // nextInt = n + 1 + // + // // Dynamically determine format based on existing number + // digitCount := len(last) + // + // // If the incremented number needs more digits, expand format + // nextStr := strconv.FormatInt(nextInt, 10) + // if len(nextStr) > digitCount { + // digitCount = len(nextStr) + // } + // + // // Ensure minimum 10 digits as per requirement + // if digitCount < 10 { + // digitCount = 10 + // } + // + // format = fmt.Sprintf("%%0%dd", digitCount) + //} + + const prefix = "12" // fixed starting prefix (same as $awal_rm) in simgos + const maxSuffix = 999999 + + // No existing NOMR → start fresh if last == "" { - // No existing records, start with 10 digits - nextInt = 1 - format = "%010d" - } else { - n, err := strconv.ParseInt(last, 10, 64) - if err != nil { - return "", err - } - nextInt = n + 1 - - // Dynamically determine format based on existing number - digitCount := len(last) - - // If the incremented number needs more digits, expand format - nextStr := strconv.FormatInt(nextInt, 10) - if len(nextStr) > digitCount { - digitCount = len(nextStr) - } - - // Ensure minimum 10 digits as per requirement - if digitCount < 10 { - digitCount = 10 - } - - format = fmt.Sprintf("%%0%dd", digitCount) + return prefix + "000001", nil } - return fmt.Sprintf(format, nextInt), nil + suffix := last[len(prefix):] // extract numeric part + num, _ := strconv.Atoi(suffix) + + // 3. If suffix reaches 999999 → increment the prefix + if num == maxSuffix { + p, _ := strconv.Atoi(prefix) + p++ + return fmt.Sprintf("%d000001", p), nil + } + + // 4. Normal increment + return prefix + fmt.Sprintf("%06d", num+1), nil } func endpointMapper(noBpjs string) string { 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 f9e05bb7..1ea1623d 100644 --- a/internal/use-case/main-use-case/patient/middleware-runner.go +++ b/internal/use-case/main-use-case/patient/middleware-runner.go @@ -159,6 +159,25 @@ func (me *middlewareRunner) RunDeleteMiddleware(middlewares []deleteMw, input *e return nil } +func (me *middlewareRunner) RunGenerateNumberMiddleware(middlewares generateNumberMw) (generateNorm *string, err error) { + if !me.SyncOn { + return nil, nil + } + + logData := pu.GetLogData(nil, nil) + + pl.SetLogInfo(me.Event, logData, "started", middlewares.Name) + + generateNorm, err = middlewares.Func() + if err != nil { + return nil, pu.HandleMiddlewareError(me.Event, string(me.MwType), middlewares.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + + return +} + func (me *middlewareRunner) setMwType(mwType pu.MWType) { me.MwType = mwType } diff --git a/internal/use-case/main-use-case/patient/tycovar.go b/internal/use-case/main-use-case/patient/tycovar.go index cedb1514..d2370122 100644 --- a/internal/use-case/main-use-case/patient/tycovar.go +++ b/internal/use-case/main-use-case/patient/tycovar.go @@ -50,6 +50,11 @@ type readDetailMw struct { Func func(input *e.ReadDetailDto, data *e.Patient, tx *gorm.DB) error } +type generateNumberMw struct { + Name string + Func func() (*string, error) +} + type UpdateMw = updateMw type DeleteMw = deleteMw @@ -65,6 +70,7 @@ var updatePreMw []updateMw var updatePostMw []readDetailMw var deletePreMw []deleteMw var deletePostMw []readDetailMw +var generatePatientNumber generateNumberMw type BPJSResponse struct { MetaData struct { diff --git a/internal/use-case/simgos-sync-use-case/patient/case.go b/internal/use-case/simgos-sync-use-case/patient/case.go index dd95bed4..b87cd952 100644 --- a/internal/use-case/simgos-sync-use-case/patient/case.go +++ b/internal/use-case/simgos-sync-use-case/patient/case.go @@ -201,3 +201,31 @@ func Delete(input e.DeleteDto) (*d.Data, error) { }, nil } + +func Generate() (*d.Data, error) { + event := pl.Event{ + Feature: "Generate Nomr", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, nil, "started", "create") + + norm, err := generateNomrPatient() + if err != nil { + return nil, err + } + + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data:d.II{ + + } + }, nil +} From a5ea881e1f6ff35be2d71acdaa63fd7bca7f9302 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Wed, 19 Nov 2025 16:17:23 +0700 Subject: [PATCH 238/329] wip, need to test --- assets/docs/control-letter.html | 20 +- .../vclaim-sep-control-letter/dto.go | 16 +- .../domain/references/encounter/encounter.go | 1 + .../vclaim-sep-control-letter/case.go | 277 ++++++++++++++++++ .../vclaim-sep-control-letter/helper.go | 24 ++ .../vclaim-sep-control-letter/lib.go | 148 ++++++++++ .../middleware-runner.go | 103 +++++++ .../vclaim-sep-control-letter/middleware.go | 9 + .../vclaim-sep-control-letter/tycovar.go | 44 +++ .../main-use-case/generate-file/case.go | 97 +++++- .../main-use-case/generate-file/tycovar.go | 61 +++- 11 files changed, 775 insertions(+), 25 deletions(-) create mode 100644 internal/use-case/bpjs-use-case/vclaim-sep-control-letter/case.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-sep-control-letter/helper.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-sep-control-letter/lib.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-sep-control-letter/middleware-runner.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-sep-control-letter/middleware.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-sep-control-letter/tycovar.go diff --git a/assets/docs/control-letter.html b/assets/docs/control-letter.html index 10425b28..c55c7b9d 100644 --- a/assets/docs/control-letter.html +++ b/assets/docs/control-letter.html @@ -37,7 +37,7 @@
          - No. :replace + No. : {{ .Number }}
          @@ -52,10 +52,10 @@
          - DANI SETIAWAN + {{ .Doctor_Name }}
          - Sp./Sub. Rehabilitasi Medik + Sp./Sub. {{ .DstUnit_Name }}
          @@ -72,7 +72,7 @@ No.Kartu - :Replace + : {{ .CardNumber }} @@ -80,7 +80,7 @@ Nama Peserta - :Replace + : {{ .Name }} @@ -88,7 +88,7 @@ Tgl.Lahir - :Replace + : {{ .BirthDate }} @@ -96,7 +96,7 @@ Diagnosa - :Replace + : {{ .Diagnose }} @@ -104,7 +104,7 @@ Rencana Kontrol - :Replace + : {{ .PlanDate }} @@ -117,13 +117,13 @@ - Mengetahui, DPJP :Replace + Mengetahui, DPJP : {{ .ResponsibleDoctor_Name }}
          - Tgl. Entry: 2025-06-07 | Tgl. Cetak: 07-06-2025 16:52 PM + Tgl. Cetak : {{ .PrintDate }}
          diff --git a/internal/domain/bpjs-entities/vclaim-sep-control-letter/dto.go b/internal/domain/bpjs-entities/vclaim-sep-control-letter/dto.go index f12b57da..19530c2c 100644 --- a/internal/domain/bpjs-entities/vclaim-sep-control-letter/dto.go +++ b/internal/domain/bpjs-entities/vclaim-sep-control-letter/dto.go @@ -6,6 +6,9 @@ import ( type CreateDto struct { VclaimSep_Number *string `json:"vclaimSep_number"` + Number *string `json:"number" gorm:"unique;size:20"` + Value *string `json:"value"` + FileUrl *string `json:"fileUrl" gorm:"unique;size:1024"` } type ReadListDto struct { @@ -20,7 +23,8 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` + Number *string `json:"number"` } type UpdateDto struct { @@ -29,7 +33,8 @@ type UpdateDto struct { } type DeleteDto struct { - Id uint `json:"id"` + Id uint `json:"id"` + Number *string `json:"number"` } type MetaDto struct { @@ -41,12 +46,17 @@ type MetaDto struct { type ResponseDto struct { ecore.Main VclaimSep_Number *string `json:"vclaimSep_number"` - Counter *uint `json:"counter"` + Number *string `json:"number"` + Value *string `json:"value"` + FileUrl *string `json:"fileUrl"` } func (d VclaimSepControlLetter) ToResponse() ResponseDto { resp := ResponseDto{ VclaimSep_Number: d.VclaimSep_Number, + Number: d.Number, + Value: d.Value, + FileUrl: d.FileUrl, } resp.Main = d.Main return resp diff --git a/internal/domain/references/encounter/encounter.go b/internal/domain/references/encounter/encounter.go index 532e1625..1acee75b 100644 --- a/internal/domain/references/encounter/encounter.go +++ b/internal/domain/references/encounter/encounter.go @@ -120,6 +120,7 @@ const ( DTCSEP DocTypeCode = "vclaim-sep" // SEP DTCSIPP DocTypeCode = "vclaim-sipp" // SIPP DTCGC DocTypeCode = "general-consent" + DTCVSCL DocTypeCode = "vclaim-control-letter" // vclaim control letter ETCPerson EntityTypeCode = "person" ETCEncounter EntityTypeCode = "encounter" diff --git a/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/case.go b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/case.go new file mode 100644 index 00000000..7c19819f --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/case.go @@ -0,0 +1,277 @@ +package vclaimsepcontrolletter + +import ( + "strconv" + + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-control-letter" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "vclaim-sep-control-letter" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.VclaimSepControlLetter{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.VclaimSepControlLetter + var dataList []e.VclaimSepControlLetter + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.VclaimSepControlLetter + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Number: input.Number} + var data *e.VclaimSepControlLetter + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Number: input.Number} + var data *e.VclaimSepControlLetter + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/helper.go b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/helper.go new file mode 100644 index 00000000..891e7c4d --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/helper.go @@ -0,0 +1,24 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package vclaimsepcontrolletter + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-control-letter" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.VclaimSepControlLetter) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.VclaimSep_Number = inputSrc.VclaimSep_Number + data.Number = inputSrc.Number + data.Value = inputSrc.Value + data.FileUrl = inputSrc.FileUrl +} diff --git a/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/lib.go b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/lib.go new file mode 100644 index 00000000..9f66baff --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/lib.go @@ -0,0 +1,148 @@ +package vclaimsepcontrolletter + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-control-letter" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.VclaimSepControlLetter, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.VclaimSepControlLetter{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + setData(&input, &data) + + if err := tx.Create(&data).Error; err != nil { + return nil, plh.HandleCreateError(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.VclaimSepControlLetter, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.VclaimSepControlLetter{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.VclaimSepControlLetter{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.VclaimSepControlLetter, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.VclaimSepControlLetter{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if input.Number != nil { + tx = tx.Where("\"Number\" = ?", *input.Number) + } + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", *input.Id) + } + + if err := tx.First(&data).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.VclaimSepControlLetter, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.VclaimSepControlLetter, 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 +} diff --git a/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/middleware-runner.go b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/middleware-runner.go new file mode 100644 index 00000000..c0a0ecae --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/middleware-runner.go @@ -0,0 +1,103 @@ +package vclaimsepcontrolletter + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-control-letter" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.VclaimSepControlLetter) 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.VclaimSepControlLetter) 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.VclaimSepControlLetter) 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.VclaimSepControlLetter) 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.VclaimSepControlLetter) 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/bpjs-use-case/vclaim-sep-control-letter/middleware.go b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/middleware.go new file mode 100644 index 00000000..57262cc2 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/middleware.go @@ -0,0 +1,9 @@ +package vclaimsepcontrolletter + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/tycovar.go b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/tycovar.go new file mode 100644 index 00000000..2e921ae9 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/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 vclaimsepcontrolletter + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-control-letter" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.VclaimSepControlLetter, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.VclaimSepControlLetter, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.VclaimSepControlLetter, 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/main-use-case/generate-file/case.go b/internal/use-case/main-use-case/generate-file/case.go index 1c3ca51b..f0e71203 100644 --- a/internal/use-case/main-use-case/generate-file/case.go +++ b/internal/use-case/main-use-case/generate-file/case.go @@ -4,9 +4,15 @@ import ( "encoding/json" "errors" + evs "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" + evscl "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-control-letter" egc "simrs-vx/internal/domain/main-entities/general-consent" + + uvs "simrs-vx/internal/use-case/bpjs-use-case/vclaim-sep" + uvscl "simrs-vx/internal/use-case/bpjs-use-case/vclaim-sep-control-letter" ugc "simrs-vx/internal/use-case/main-use-case/general-consent" + pc "simrs-vx/pkg/conv-helper" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -25,6 +31,8 @@ func Generate(input GenerateDto) (*d.Data, error) { Source: source, } + var response ResponseDto + // Start log pl.SetLogInfo(&event, input, "started", "create") @@ -32,7 +40,7 @@ func Generate(input GenerateDto) (*d.Data, error) { // general-consent case ere.DTCGC: // get value from general consent by ref_id - gc, err := ugc.ReadDetailData(egc.ReadDetailDto{Id: *input.Ref_Id}, &event) + gc, err := ugc.ReadDetailData(egc.ReadDetailDto{Id: uint(*pc.StringToUint64(*input.Ref_Id))}, &event) if err != nil { return nil, err } @@ -75,20 +83,89 @@ func Generate(input GenerateDto) (*d.Data, error) { return nil, err } - response := ResponseDto{ + response = ResponseDto{ + FileUrl: urlPub, + } + + // control-letter + case ere.DTCVSCL: + // get value from control letter by ref_id + cl, err := uvscl.ReadDetailData(evscl.ReadDetailDto{Number: input.Ref_Id}, &event) + if err != nil { + if !pu.IsDataNotFoundError(err) { + return nil, err + } + } + + if cl != nil && cl.FileUrl != nil { + if err := removeFile(string(input.EntityType_Code), *cl.FileUrl); err != nil { + return nil, err + } + } + + // map template data + clData := VclaimControlLetter{} + if input.Data != nil { + err := json.Unmarshal([]byte(*input.Data), &clData) + if err != nil { + event.ErrInfo = pl.ErrorInfo{ + Code: "data-unmarshal-fail", + Detail: err.Error(), + Raw: err, + } + return nil, err + } + } else { + return nil, errors.New("there is no data to be used") + } + + if cl == nil { + createCL := evscl.CreateDto{ + VclaimSep_Number: &clData.VclaimSep.Number, + Number: &clData.Number, + Value: input.Data, + } + if cl, err = uvscl.CreateData(createCL, &event); err != nil { + return nil, err + } + + } + // get encounter id by vclaim sep number + vs, err := uvs.ReadDetailData(evs.ReadDetailDto{Number: &clData.VclaimSep.Number}, &event) + if err != nil { + return nil, err + } + + input.FormatType = erc.DFTCPDF + input.TemplateName = TDNCL + input.Encounter_Id = vs.Encounter_Id + + templateData := clData.generateTemplateData() + // generate file + urlPub, err := generateFile(input, templateData) + if err != nil { + return nil, err + } + + cl.FileUrl = &urlPub + if err := dg.I.Save(&cl).Error; err != nil { + return nil, err + } + + response = ResponseDto{ FileUrl: urlPub, } - return &d.Data{ - Meta: d.II{ - "source": source, - "structure": "single-data", - "status": "created", - }, - Data: response, - }, nil default: return nil, errors.New("invalid type code") } + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: response, + }, nil } diff --git a/internal/use-case/main-use-case/generate-file/tycovar.go b/internal/use-case/main-use-case/generate-file/tycovar.go index fed3e28c..ecfbc6a1 100644 --- a/internal/use-case/main-use-case/generate-file/tycovar.go +++ b/internal/use-case/main-use-case/generate-file/tycovar.go @@ -1,8 +1,13 @@ package generatefile import ( + "fmt" + "time" + erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" + + pu "simrs-vx/pkg/use-case-helper" ) type GeneralConsentPDF struct { @@ -14,18 +19,34 @@ type GeneralConsentPDF struct { Date string `json:"date"` } +type ControlLetterPDF struct { + Number string + Doctor_Name string + DstUnit_Name string + CardNumber string + Name string + BirthDate string + Diagnose string + PlanDate string + ResponsibleDoctor_Name string + PrintDate string +} + type GenerateDto struct { EntityType_Code ere.EntityTypeCode `json:"entityType_code" validate:"required"` - Ref_Id *uint `json:"ref_id" validate:"required"` + Ref_Id *string `json:"ref_id" validate:"required"` Type_Code ere.DocTypeCode `json:"type_code" validate:"required"` FormatType erc.DocFormatTypeCode `json:"formatType"` TemplateName TemplateDocsName `json:"-"` Encounter_Id *uint `json:"-"` + + Data *string `json:"data"` } type VclaimControlLetter struct { Number string `json:"noSuratKontrol"` - Date string `json:"tglRencanaKontrol"` + PlannedControlDate string `json:"tglRencanaKontrol"` + IssuedDate string `json:"tglTerbit"` Doctor_Name string `json:"namaDokter"` DstUnit_Name string `json:"namaPoliTujuan"` ResponsibleDoctor_Name string `json:"namaDokterPembuat"` @@ -60,4 +81,40 @@ type TemplateDocsName string // TemplateDocsName is the name of the template file in the assets/docs folder const ( TDNGC TemplateDocsName = "general-consent.html" + TDNCL TemplateDocsName = "control-letter.html" ) + +func (v VclaimControlLetter) generateTemplateData() ControlLetterPDF { + + return ControlLetterPDF{ + Number: v.Number, + Doctor_Name: v.Doctor_Name, + DstUnit_Name: v.DstUnit_Name, + CardNumber: v.VclaimSep.VclaimMember.CardNumber, + Name: v.generateNameWithGender(), + BirthDate: v.generateBirthDate(), + Diagnose: v.VclaimSep.Diagnose, + PlanDate: v.PlannedControlDate, + ResponsibleDoctor_Name: v.ResponsibleDoctor_Name, + PrintDate: generatePrintDate(), + } +} + +func (v VclaimControlLetter) generateNameWithGender() string { + gender := "Perempuan" + if v.VclaimSep.VclaimMember.Gender == "L" { + gender = "Laki-Laki" + } + + return fmt.Sprintf("%s (%s)", v.VclaimSep.VclaimMember.Name, gender) +} + +func (v VclaimControlLetter) generateBirthDate() string { + t, _ := time.Parse("2006-01-02", v.VclaimSep.VclaimMember.BirthDate) + return pu.FormatIndonesianDate(t) +} + +func generatePrintDate() string { + now := time.Now() + return now.Format("2006/01/02") +} From 279636682d01ad6ace029c55e5256f7012a7a547 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Thu, 20 Nov 2025 07:56:31 +0700 Subject: [PATCH 239/329] feat/things-munaja: updated mcu-order-item --- .../migrations/20251120005512.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 5 +++-- .../mcu-order-item/base/entity.go | 20 +++++++++++++++++++ .../main-entities/mcu-order-item/entity.go | 14 +++---------- 4 files changed, 28 insertions(+), 13 deletions(-) create mode 100644 cmd/main-migration/migrations/20251120005512.sql create mode 100644 internal/domain/main-entities/mcu-order-item/base/entity.go diff --git a/cmd/main-migration/migrations/20251120005512.sql b/cmd/main-migration/migrations/20251120005512.sql new file mode 100644 index 00000000..8fd4b6af --- /dev/null +++ b/cmd/main-migration/migrations/20251120005512.sql @@ -0,0 +1,2 @@ +-- Modify "McuOrderItem" table +ALTER TABLE "public"."McuOrderItem" ADD COLUMN "Note" character varying(1024) NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index a6e1b68c..9f7c1d2e 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:fNeqUpbdIqGDiH68u1bwwMgHTEOmmEWeI+IIYEq6pto= +h1:NZkNXHrJksgpcktPStE4yM6IBy+NgX8X6cY2ffSLCDU= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -118,4 +118,5 @@ h1:fNeqUpbdIqGDiH68u1bwwMgHTEOmmEWeI+IIYEq6pto= 20251113101344.sql h1:xaOZvAUP1fFfnO+syEFOzJUIg5lTfBe5AWHPbBWuCLA= 20251113120533.sql h1:f3/U1Ve2yF2zSMhkt+xtwF8wUYfUKYwgbNeGfE37EW4= 20251114062746.sql h1:FInLaEFQByESEwFJKuKnuUSTKmcDpi3ZXaxkKwz2+D8= -20251117005942.sql h1:mW/TC8GgFgPLZ7PBVQnn9mChEekAcwfQMCbzXnoaw9w= +20251117005942.sql h1:wD3BWrUSmo1HlW16V3lkaBkJvbAZ0fNk77te7J9NhOc= +20251120005512.sql h1:gd0rKVlIHXbOQ6J3Bl6NTiZ6fF3GQdobgAUVXW455wI= diff --git a/internal/domain/main-entities/mcu-order-item/base/entity.go b/internal/domain/main-entities/mcu-order-item/base/entity.go new file mode 100644 index 00000000..dcfb0625 --- /dev/null +++ b/internal/domain/main-entities/mcu-order-item/base/entity.go @@ -0,0 +1,20 @@ +package mcuorderitem + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ems "simrs-vx/internal/domain/main-entities/mcu-src" + "time" + + erc "simrs-vx/internal/domain/references/common" +) + +type McuOrderItem struct { + ecore.Main // adjust this according to the needs + McuOrder_Id *uint `json:"mcuOrder_id" gorm:"uniqueIndex:idx_order_src"` + McuSrc_Code *string `json:"mcuSrc_code" gorm:"uniqueIndex:idx_order_src"` + McuSrc *ems.McuSrc `json:"mcuSrc,omitempty" gorm:"foreignKey:McuSrc_Code;references:Code"` + ExaminationDate *time.Time `json:"examinationDate"` + Note *string `json:"note" gorm:"size:1024"` + Result *string `json:"result"` + Status_Code erc.DataStatusCode `json:"status_code"` +} diff --git a/internal/domain/main-entities/mcu-order-item/entity.go b/internal/domain/main-entities/mcu-order-item/entity.go index 97384243..48a57bac 100644 --- a/internal/domain/main-entities/mcu-order-item/entity.go +++ b/internal/domain/main-entities/mcu-order-item/entity.go @@ -1,23 +1,15 @@ package mcuorderitem import ( - ecore "simrs-vx/internal/domain/base-entities/core" emo "simrs-vx/internal/domain/main-entities/mcu-order" - ems "simrs-vx/internal/domain/main-entities/mcu-src" - "time" + emoib "simrs-vx/internal/domain/main-entities/mcu-order-item/base" erc "simrs-vx/internal/domain/references/common" ) type McuOrderItem struct { - ecore.Main // adjust this according to the needs - McuOrder_Id *uint `json:"mcuOrder_id" gorm:"uniqueIndex:idx_order_src"` - McuOrder *emo.McuOrder `json:"mcuOrder,omitempty" gorm:"foreignKey:McuOrder_Id;references:Id"` - McuSrc_Code *string `json:"mcuSrc_code" gorm:"uniqueIndex:idx_order_src"` - McuSrc *ems.McuSrc `json:"mcuSrc,omitempty" gorm:"foreignKey:McuSrc_Code;references:Code"` - ExaminationDate *time.Time `json:"examinationDate"` - Result *string `json:"result"` - Status_Code erc.DataStatusCode `json:"status_code"` + emoib.McuOrderItem + McuOrder *emo.McuOrder `json:"mcuOrder,omitempty" gorm:"foreignKey:McuOrder_Id;references:Id"` } func (d McuOrderItem) IsCompleted() bool { From 9a056701c6bdd4257eaba6764f8ab8666e4a35d2 Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 20 Nov 2025 09:10:58 +0700 Subject: [PATCH 240/329] update nomr patient --- .../simgos-sync-handler/patient/handler.go | 5 +++ .../simgos-sync-handler.go | 2 + .../use-case/main-use-case/patient/helper.go | 5 ++- .../main-use-case/patient/middleware.go | 2 + .../simgos-sync-plugin/patient/plugin.go | 40 +++++++++++++++++++ .../simgos-sync-use-case/patient/case.go | 8 ++-- .../simgos-sync-use-case/patient/helper.go | 1 + .../simgos-sync-use-case/patient/lib.go | 6 --- 8 files changed, 58 insertions(+), 11 deletions(-) diff --git a/internal/interface/simgos-sync-handler/patient/handler.go b/internal/interface/simgos-sync-handler/patient/handler.go index ae2e1db8..cfc0c8da 100644 --- a/internal/interface/simgos-sync-handler/patient/handler.go +++ b/internal/interface/simgos-sync-handler/patient/handler.go @@ -61,3 +61,8 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { res, err := u.Delete(dto) rw.DataResponse(w, res, err) } + +func (obj myBase) GenerateNomr(w http.ResponseWriter, r *http.Request) { + res, err := u.GenerateNomr() + 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 dee6fb3f..2a67b7e9 100644 --- a/internal/interface/simgos-sync-handler/simgos-sync-handler.go +++ b/internal/interface/simgos-sync-handler/simgos-sync-handler.go @@ -1,6 +1,7 @@ package simgossynchandler import ( + "fmt" "net/http" hc "simrs-vx/pkg/handler-crud-helper" @@ -45,6 +46,7 @@ func SetRoutes() http.Handler { hc.SyncCrud(r, prefix+"/v1/specialist", specialist.O) hc.SyncCrud(r, prefix+"/v1/subspecialist", subspecialist.O) hc.SyncCrud(r, prefix+"/v1/patient", patient.O) + r.HandleFunc(fmt.Sprintf("GET %s/v1/patient-nomr-generator", prefix), patient.O.GenerateNomr) return cmw.SetCors(handlerlogger.SetLog(r)) } diff --git a/internal/use-case/main-use-case/patient/helper.go b/internal/use-case/main-use-case/patient/helper.go index 2c62ca21..82142632 100644 --- a/internal/use-case/main-use-case/patient/helper.go +++ b/internal/use-case/main-use-case/patient/helper.go @@ -24,12 +24,15 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Patient) error { inputSrc = &inputTemp.CreateDto } - if data.Number == nil { + switch { + case inputSrc.Number == nil && data.Number == nil: medRecNum, err := GenerateNextMedicalRecordNumber() if err != nil { return err } data.Number = &medRecNum + case inputSrc.Number != nil: + data.Number = inputSrc.Number } data.Person_Id = inputSrc.Person_Id diff --git a/internal/use-case/main-use-case/patient/middleware.go b/internal/use-case/main-use-case/patient/middleware.go index cc97473f..4270c14c 100644 --- a/internal/use-case/main-use-case/patient/middleware.go +++ b/internal/use-case/main-use-case/patient/middleware.go @@ -29,6 +29,8 @@ func init() { deletePreMw = append(deletePreMw, deleteMw{Name: "sync-delete-patient", Func: plugin.Delete}) + + generatePatientNumber = generateNumberMw{Name: "generate-nomr-patient", Func: plugin.GenerateNomrPatient} } func checkVclaimMember(input *e.CreateDto, data *e.Patient, tx *gorm.DB) error { diff --git a/internal/use-case/simgos-sync-plugin/patient/plugin.go b/internal/use-case/simgos-sync-plugin/patient/plugin.go index b10fdce5..ebfb8dc4 100644 --- a/internal/use-case/simgos-sync-plugin/patient/plugin.go +++ b/internal/use-case/simgos-sync-plugin/patient/plugin.go @@ -162,6 +162,46 @@ func Delete(input *e.DeleteDto) error { return nil } +func GenerateNomrPatient() (*string, error) { + prefixEndpoint := getPrefixEndpoint() + endpoint := fmt.Sprintf("%s-nomr-generator", prefixEndpoint) + + req, err := http.NewRequest("GET", endpoint, nil) + if err != nil { + return nil, err + } + + req.Header.Set("Content-Type", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + bodyBytes, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + if resp.StatusCode != http.StatusOK { + errors := d.FieldError{} + _ = json.Unmarshal(bodyBytes, &errors) + + return nil, fmt.Errorf(errors.Message) + } + + var result map[string]any + if err = json.Unmarshal(bodyBytes, &result); err != nil { + return nil, err + } + + dataMap := result["data"].(map[string]any) + nomr := dataMap["nomr"].(string) + + return &nomr, nil +} + func getPrefixEndpoint() string { return fmt.Sprintf("%s%s/v1/patient", sync.O.Host, sync.O.Prefix) } diff --git a/internal/use-case/simgos-sync-use-case/patient/case.go b/internal/use-case/simgos-sync-use-case/patient/case.go index b87cd952..d403a8ac 100644 --- a/internal/use-case/simgos-sync-use-case/patient/case.go +++ b/internal/use-case/simgos-sync-use-case/patient/case.go @@ -202,7 +202,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { } -func Generate() (*d.Data, error) { +func GenerateNomr() (*d.Data, error) { event := pl.Event{ Feature: "Generate Nomr", Source: source, @@ -224,8 +224,8 @@ func Generate() (*d.Data, error) { "structure": "single-data", "status": "created", }, - Data:d.II{ - - } + Data: d.IS{ + "nomr": norm, + }, }, nil } diff --git a/internal/use-case/simgos-sync-use-case/patient/helper.go b/internal/use-case/simgos-sync-use-case/patient/helper.go index 4b7ddfe6..0bffcc9b 100644 --- a/internal/use-case/simgos-sync-use-case/patient/helper.go +++ b/internal/use-case/simgos-sync-use-case/patient/helper.go @@ -43,6 +43,7 @@ func setDataSimgos(input *e.Patient) (data esimgos.MPasien) { data.Nip = input.RegisteredBy_User_Name data.Tgldaftar = input.RegisteredAt + data.Nomr = *input.Number return } diff --git a/internal/use-case/simgos-sync-use-case/patient/lib.go b/internal/use-case/simgos-sync-use-case/patient/lib.go index 20f6cdcf..6d50f877 100644 --- a/internal/use-case/simgos-sync-use-case/patient/lib.go +++ b/internal/use-case/simgos-sync-use-case/patient/lib.go @@ -21,11 +21,6 @@ func CreateSimgosData(input e.Patient, event *pl.Event, dbx ...*gorm.DB) (*esimg pl.SetLogInfo(event, nil, "started", "DBCreate") data := setDataSimgos(&input) - nomr, err := generateNomrPatient() - if err != nil { - return nil, plh.HandleCreateError(input, event, err) - } - data.Nomr = nomr var tx *gorm.DB if len(dbx) > 0 { @@ -65,7 +60,6 @@ func UpdateSimgosData(input e.Patient, patientData *esimgos.MPasien, event *pl.E data := setDataSimgos(&input) data.Id = patientData.Id - data.Nomr = patientData.Nomr data.CreatedAt = patientData.CreatedAt var tx *gorm.DB From ffb8c4e413b410c84d4337e482b5dd0c7b30180a Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 20 Nov 2025 13:18:33 +0700 Subject: [PATCH 241/329] feat (generate-file): control letter done --- assets/docs/control-letter.html | 67 ++++-- .../main-use-case/generate-file/case.go | 226 +++++++++--------- .../main-use-case/generate-file/helper.go | 9 +- .../main-use-case/generate-file/tycovar.go | 9 +- pkg/pdf-helper/pdf-helper.go | 19 +- 5 files changed, 185 insertions(+), 145 deletions(-) diff --git a/assets/docs/control-letter.html b/assets/docs/control-letter.html index c55c7b9d..780a052f 100644 --- a/assets/docs/control-letter.html +++ b/assets/docs/control-letter.html @@ -3,6 +3,9 @@ @@ -25,7 +34,7 @@ - - - - @@ -94,7 +94,7 @@ @@ -112,7 +112,7 @@ - + @@ -324,7 +324,7 @@
          - logo + logo
          @@ -35,15 +44,10 @@ RSUD dr. Saiful Anwar
          -
          - No. : {{ .Number }} -
          +
          + No. : {{ .Number }}
          @@ -65,46 +69,50 @@ Mohon Pemeriksaan dan Penanganan Lebih Lanjut:
          - + + + + +
          No.Kartu : - : {{ .CardNumber }} + {{ .CardNumber }}
          Nama Peserta : - : {{ .Name }} + {{ .Name }}
          Tgl.Lahir : - : {{ .BirthDate }} + {{ .BirthDate }}
          Diagnosa : - : {{ .Diagnose }} + {{ .Diagnose }}
          Rencana Kontrol : - : {{ .PlanDate }} + {{ .PlanDate }}
          @@ -112,19 +120,26 @@
          Demikian atas bantuannya, diucapkan banyak terima kasih.
          - - - - - - -
          - Mengetahui, DPJP : {{ .ResponsibleDoctor_Name }} -
          -
          - Tgl. Cetak : {{ .PrintDate }} -
          + + + + + + + + + + + + + + + + + + +
          Mengetahui:
          Tgl. Cetak: {{ .PrintDate }}{{ .ResponsibleDoctor_Name }}
          diff --git a/internal/use-case/main-use-case/generate-file/case.go b/internal/use-case/main-use-case/generate-file/case.go index f0e71203..39cb2f02 100644 --- a/internal/use-case/main-use-case/generate-file/case.go +++ b/internal/use-case/main-use-case/generate-file/case.go @@ -18,6 +18,7 @@ import ( dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" + "gorm.io/gorm" erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" @@ -36,128 +37,137 @@ func Generate(input GenerateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - switch input.Type_Code { - // general-consent - case ere.DTCGC: - // get value from general consent by ref_id - gc, err := ugc.ReadDetailData(egc.ReadDetailDto{Id: uint(*pc.StringToUint64(*input.Ref_Id))}, &event) - if err != nil { - return nil, err - } - - if gc.FileUrl != nil { - if err := removeFile(string(input.EntityType_Code), *gc.FileUrl); err != nil { - return nil, err - } - } - - // map template data - templateData := GeneralConsentPDF{} - if gc.Value != nil { - err := json.Unmarshal([]byte(*gc.Value), &templateData) + err := dg.I.Transaction(func(tx *gorm.DB) error { + switch input.Type_Code { + // general-consent + case ere.DTCGC: + // get value from general consent by ref_id + gc, err := ugc.ReadDetailData(egc.ReadDetailDto{Id: uint(*pc.StringToUint64(*input.Ref_Id))}, &event) if err != nil { - event.ErrInfo = pl.ErrorInfo{ - Code: "data-unmarshal-fail", - Detail: err.Error(), - Raw: err, + return err + } + + if gc.FileUrl != nil { + if err := removeFile(string(input.EntityType_Code), *gc.FileUrl); err != nil { + return err } - return nil, err } - } else { - return nil, errors.New("no value in this general consent") - } - input.FormatType = erc.DFTCPDF - input.TemplateName = TDNGC - input.Encounter_Id = gc.Encounter_Id - templateData.Date = pu.FormatIndonesianDate(gc.CreatedAt) - - // generate file - urlPub, err := generateFile(input, templateData) - if err != nil { - return nil, err - } - - gc.FileUrl = &urlPub - if err := dg.I.Save(&gc).Error; err != nil { - return nil, err - } - - response = ResponseDto{ - FileUrl: urlPub, - } - - // control-letter - case ere.DTCVSCL: - // get value from control letter by ref_id - cl, err := uvscl.ReadDetailData(evscl.ReadDetailDto{Number: input.Ref_Id}, &event) - if err != nil { - if !pu.IsDataNotFoundError(err) { - return nil, err + // map template data + templateData := GeneralConsentPDF{} + if gc.Value != nil { + err := json.Unmarshal([]byte(*gc.Value), &templateData) + if err != nil { + event.ErrInfo = pl.ErrorInfo{ + Code: "data-unmarshal-fail", + Detail: err.Error(), + Raw: err, + } + return err + } + } else { + return errors.New("no value in this general consent") } - } - if cl != nil && cl.FileUrl != nil { - if err := removeFile(string(input.EntityType_Code), *cl.FileUrl); err != nil { - return nil, err - } - } + input.FormatType = erc.DFTCPDF + input.TemplateName = TDNGC + input.Encounter_Id = gc.Encounter_Id + templateData.Date = pu.FormatIndonesianDate(gc.CreatedAt) - // map template data - clData := VclaimControlLetter{} - if input.Data != nil { - err := json.Unmarshal([]byte(*input.Data), &clData) + // generate file + urlPub, err := generateFile(input, templateData) if err != nil { - event.ErrInfo = pl.ErrorInfo{ - Code: "data-unmarshal-fail", - Detail: err.Error(), - Raw: err, + return err + } + + gc.FileUrl = &urlPub + if err := dg.I.Save(&gc).Error; err != nil { + return err + } + + response = ResponseDto{ + FileUrl: urlPub, + } + + // control-letter + case ere.DTCVSCL: + // get value from control letter by ref_id + cl, err := uvscl.ReadDetailData(evscl.ReadDetailDto{Number: input.Ref_Id}, &event) + if err != nil { + if !pu.IsDataNotFoundError(err) { + return err } - return nil, err - } - } else { - return nil, errors.New("there is no data to be used") - } - - if cl == nil { - createCL := evscl.CreateDto{ - VclaimSep_Number: &clData.VclaimSep.Number, - Number: &clData.Number, - Value: input.Data, - } - if cl, err = uvscl.CreateData(createCL, &event); err != nil { - return nil, err } - } - // get encounter id by vclaim sep number - vs, err := uvs.ReadDetailData(evs.ReadDetailDto{Number: &clData.VclaimSep.Number}, &event) - if err != nil { - return nil, err + if cl != nil && cl.FileUrl != nil { + if err := removeFile(string(input.EntityType_Code), *cl.FileUrl); err != nil { + return err + } + } + + // map template data + clData := VclaimControlLetter{} + if input.Data != nil { + err := json.Unmarshal([]byte(*input.Data), &clData) + if err != nil { + event.ErrInfo = pl.ErrorInfo{ + Code: "data-unmarshal-fail", + Detail: err.Error(), + Raw: err, + } + return err + } + } else { + return errors.New("there is no data to be used") + } + + if cl == nil { + createCL := evscl.CreateDto{ + VclaimSep_Number: &clData.VclaimSep.Number, + Number: &clData.Number, + Value: input.Data, + } + if cl, err = uvscl.CreateData(createCL, &event, tx); err != nil { + return err + } + + } + // get encounter id by vclaim sep number + vs, err := uvs.ReadDetailData(evs.ReadDetailDto{Number: &clData.VclaimSep.Number}, &event) + if err != nil { + return err + } + + input.FormatType = erc.DFTCPDF + input.TemplateName = TDNCL + input.Encounter_Id = vs.Encounter_Id + input.UseA5Lanscape = true + + templateData := clData.generateTemplateData() + // generate file + urlPub, err := generateFile(input, templateData) + if err != nil { + return err + } + + cl.FileUrl = &urlPub + if err := tx.Save(&cl).Error; err != nil { + return err + } + + response = ResponseDto{ + FileUrl: urlPub, + } + + default: + return errors.New("invalid type code") } - input.FormatType = erc.DFTCPDF - input.TemplateName = TDNCL - input.Encounter_Id = vs.Encounter_Id + return nil + }) - templateData := clData.generateTemplateData() - // generate file - urlPub, err := generateFile(input, templateData) - if err != nil { - return nil, err - } - - cl.FileUrl = &urlPub - if err := dg.I.Save(&cl).Error; err != nil { - return nil, err - } - - response = ResponseDto{ - FileUrl: urlPub, - } - - default: - return nil, errors.New("invalid type code") + if err != nil { + return nil, err } return &d.Data{ diff --git a/internal/use-case/main-use-case/generate-file/helper.go b/internal/use-case/main-use-case/generate-file/helper.go index 9bee2212..8cd3543f 100644 --- a/internal/use-case/main-use-case/generate-file/helper.go +++ b/internal/use-case/main-use-case/generate-file/helper.go @@ -30,9 +30,10 @@ func generateFile(input GenerateDto, templateData any) (string, error) { switch input.FormatType { case erc.DFTCPDF: if err := generatePDF(GeneratePDFdto{ - TemplatePath: templatePath, - TemplateData: templateData, - PdfPath: fPath, + TemplatePath: templatePath, + TemplateData: templateData, + PdfPath: fPath, + UseA5Lanscape: input.UseA5Lanscape, }); err != nil { return "", err } @@ -73,7 +74,7 @@ func generatePDF(input GeneratePDFdto) error { // parse template data into html template r := pp.NewRequestPdf("") if err := r.ParseTemplate(input.TemplatePath, input.TemplateData); err == nil { - _, err := r.GenerateByCommand(input.PdfPath, input.TemplatePath) + _, err := r.GenerateByCommand(input.PdfPath, input.TemplatePath, input.UseA5Lanscape) if err != nil { return errors.New("generate pdf by command error : " + err.Error()) } diff --git a/internal/use-case/main-use-case/generate-file/tycovar.go b/internal/use-case/main-use-case/generate-file/tycovar.go index ecfbc6a1..2f6a0ced 100644 --- a/internal/use-case/main-use-case/generate-file/tycovar.go +++ b/internal/use-case/main-use-case/generate-file/tycovar.go @@ -39,6 +39,7 @@ type GenerateDto struct { FormatType erc.DocFormatTypeCode `json:"formatType"` TemplateName TemplateDocsName `json:"-"` Encounter_Id *uint `json:"-"` + UseA5Lanscape bool `json:"-"` Data *string `json:"data"` } @@ -46,7 +47,6 @@ type GenerateDto struct { type VclaimControlLetter struct { Number string `json:"noSuratKontrol"` PlannedControlDate string `json:"tglRencanaKontrol"` - IssuedDate string `json:"tglTerbit"` Doctor_Name string `json:"namaDokter"` DstUnit_Name string `json:"namaPoliTujuan"` ResponsibleDoctor_Name string `json:"namaDokterPembuat"` @@ -67,9 +67,10 @@ type VclaimMember struct { } type GeneratePDFdto struct { - TemplatePath string - TemplateData any - PdfPath string + TemplatePath string + TemplateData any + PdfPath string + UseA5Lanscape bool } type ResponseDto struct { diff --git a/pkg/pdf-helper/pdf-helper.go b/pkg/pdf-helper/pdf-helper.go index 597052eb..9878ecbd 100644 --- a/pkg/pdf-helper/pdf-helper.go +++ b/pkg/pdf-helper/pdf-helper.go @@ -47,9 +47,9 @@ func (r *RequestPdf) ParseTemplate(templatePath string, data interface{}) error return nil } -func (r *RequestPdf) GenerateByCommand(pdfPath string, templatePath string) (bool, error) { - // wkhtmltopdf -L 0 -R 0 -B 0 -s Legal --enable-local-file-access resultAntigen2.html out.pdf +func (r *RequestPdf) GenerateByCommand(pdfPath string, templatePath string, useA5Lanscape bool) (bool, error) { t := time.Now().Unix() + var cmd *exec.Cmd if _, err := os.Stat("cloneTemplate/"); os.IsNotExist(err) { errDir := os.Mkdir("cloneTemplate/", 0777) @@ -63,7 +63,20 @@ func (r *RequestPdf) GenerateByCommand(pdfPath string, templatePath string) (boo panic(err) } - cmd := exec.Command("wkhtmltopdf", "--enable-local-file-access", "-L", "0", "-R", "0", "-B", "0", "-s", "A4", "cloneTemplate/"+htmlName, pdfPath) + if !useA5Lanscape { + cmd = exec.Command("wkhtmltopdf", "--enable-local-file-access", "-L", "0", "-R", "0", "-B", "0", "-s", "A4", "cloneTemplate/"+htmlName, pdfPath) + } else { + cmd = exec.Command("wkhtmltopdf", + "--enable-local-file-access", + "-L", "0", // left margin + "-R", "0", // right margin + "-B", "0", // bottom margin + "-T", "0", // top margin + "-s", "A5", // page size A5 + "-O", "Landscape", // landscape mode + "cloneTemplate/"+htmlName, + pdfPath) + } if err := cmd.Run(); err != nil { return false, err From b5b15ed852cabcde316df810175b1676cc32b011 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 20 Nov 2025 13:24:51 +0700 Subject: [PATCH 242/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 98 +++++++++++++------------ 1 file changed, 52 insertions(+), 46 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 9f7c1d2e..5645ddc2 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:NZkNXHrJksgpcktPStE4yM6IBy+NgX8X6cY2ffSLCDU= +h1:DgafJ/z7PUlDk6JQZ+ZwOf1lD4zj6ErO+ojgeSuBuk0= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,48 +75,54 @@ h1:NZkNXHrJksgpcktPStE4yM6IBy+NgX8X6cY2ffSLCDU= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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= -20251120005512.sql h1:gd0rKVlIHXbOQ6J3Bl6NTiZ6fF3GQdobgAUVXW455wI= +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= From 7c600dce5f917d48c85686fcd315fc2f11c724fe Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Thu, 20 Nov 2025 13:39:51 +0700 Subject: [PATCH 243/329] feat/things-munaja: device and mcu order --- .../main-entities/device-order-item/dto.go | 1 + .../domain/main-entities/mcu-order/dto.go | 5 +- .../domain/main-entities/mcu-order/entity.go | 6 ++ .../interface/main-handler/main-handler.go | 1 + .../main-handler/mcu-order/handler.go | 12 ++++ .../main-use-case/device-order-item/lib.go | 4 +- .../use-case/main-use-case/mcu-order/case.go | 59 +++++++++++++++++++ 7 files changed, 85 insertions(+), 3 deletions(-) diff --git a/internal/domain/main-entities/device-order-item/dto.go b/internal/domain/main-entities/device-order-item/dto.go index 4464c91d..3d31c66d 100644 --- a/internal/domain/main-entities/device-order-item/dto.go +++ b/internal/domain/main-entities/device-order-item/dto.go @@ -15,6 +15,7 @@ type CreateDto struct { type ReadListDto struct { FilterDto Includes string `json:"includes"` + Sort string `json:"sort"` Pagination ecore.Pagination } diff --git a/internal/domain/main-entities/mcu-order/dto.go b/internal/domain/main-entities/mcu-order/dto.go index 594f72d7..2835ce2c 100644 --- a/internal/domain/main-entities/mcu-order/dto.go +++ b/internal/domain/main-entities/mcu-order/dto.go @@ -17,6 +17,7 @@ import ( // internal - domain - main-entities ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/encounter" + emoib "simrs-vx/internal/domain/main-entities/mcu-order-item/base" ) type CreateDto struct { @@ -85,7 +86,8 @@ type ResponseDto struct { ExaminationDate *time.Time `json:"examinationDate"` Number uint8 `json:"number"` Temperature float64 `json:"temperature"` - UrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"urgencyLevel_code""` + UrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"urgencyLevel_code"` + Items []*emoib.McuOrderItem `json:"items"` } func (d McuOrder) ToResponse() ResponseDto { @@ -100,6 +102,7 @@ func (d McuOrder) ToResponse() ResponseDto { Number: d.Number, Temperature: d.Temperature, UrgencyLevel_Code: d.UrgencyLevel_Code, + Items: d.Items, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/mcu-order/entity.go b/internal/domain/main-entities/mcu-order/entity.go index b9e5d0d7..81fb7495 100644 --- a/internal/domain/main-entities/mcu-order/entity.go +++ b/internal/domain/main-entities/mcu-order/entity.go @@ -4,6 +4,7 @@ import ( ecore "simrs-vx/internal/domain/base-entities/core" ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/encounter" + emoib "simrs-vx/internal/domain/main-entities/mcu-order-item/base" "time" ercl "simrs-vx/internal/domain/references/clinical" @@ -23,6 +24,11 @@ type McuOrder struct { Temperature float64 `json:"temperature"` UrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"urgencyLevel_code" gorm:"not null;size:15"` Scope_Code ercl.McuScopeCode `json:"scope_code" gorm:"index;size:10"` + Items []*emoib.McuOrderItem `json:"items" gorm:"foreignKey:McuOrder_Id;references:Id"` +} + +func (d McuOrder) IsNotNew() bool { + return d.Status_Code != erc.DSCNew } func (d McuOrder) IsCompleted() bool { diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index aa6f76fb..6fcecac3 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -173,6 +173,7 @@ func SetRoutes() http.Handler { "POST /": mcuorder.O.Create, "PATCH /{id}": mcuorder.O.Update, "DELETE /{id}": mcuorder.O.Delete, + "PATCH /{id}/submit": mcuorder.O.Submit, "PATCH /{id}/complete": mcuorder.O.Complete, "PATCH /{id}/set-schedule": mcuorder.O.SetSchedule, }) diff --git a/internal/interface/main-handler/mcu-order/handler.go b/internal/interface/main-handler/mcu-order/handler.go index ac4aca9f..bbbd1c56 100644 --- a/internal/interface/main-handler/mcu-order/handler.go +++ b/internal/interface/main-handler/mcu-order/handler.go @@ -85,6 +85,18 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { rw.DataResponse(w, res, err) } +func (obj myBase) Submit(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.ReadDetailDto{} + dto.Id = uint(id) + res, err := u.Submit(dto) + rw.DataResponse(w, res, err) +} + func (obj myBase) Complete(w http.ResponseWriter, r *http.Request) { id := rw.ValidateInt(w, "id", r.PathValue("id")) if id <= 0 { diff --git a/internal/use-case/main-use-case/device-order-item/lib.go b/internal/use-case/main-use-case/device-order-item/lib.go index 70ccc5d7..84838096 100644 --- a/internal/use-case/main-use-case/device-order-item/lib.go +++ b/internal/use-case/main-use-case/device-order-item/lib.go @@ -52,8 +52,8 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.De Scopes(gh.Preload(input.Includes)). Scopes(gh.Filter(input.FilterDto)). Count(&count). - Scopes(gh.Paginate(input, &pagination)). - Order("\"CreatedAt\" DESC") + Scopes(gh.Sort(input.Sort)). + Scopes(gh.Paginate(input, &pagination)) if err := tx.Find(&data).Error; err != nil { if err == gorm.ErrRecordNotFound { diff --git a/internal/use-case/main-use-case/mcu-order/case.go b/internal/use-case/main-use-case/mcu-order/case.go index 38f13088..6d7c4fed 100644 --- a/internal/use-case/main-use-case/mcu-order/case.go +++ b/internal/use-case/main-use-case/mcu-order/case.go @@ -324,6 +324,65 @@ func Delete(input e.DeleteDto) (*d.Data, error) { } +func Submit(input e.ReadDetailDto) (*d.Data, error) { + var data *e.McuOrder + var err error + + event := pl.Event{ + Feature: "Process", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "process") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + data, err = ReadDetailData(input, &event, tx) + if err != nil { + return err + } + + if data.IsNotNew() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-state-mismatch", + Detail: "prescription is not in new state", + Raw: errors.New("prescription is not in new state"), + } + return pl.SetLogError(&event, input) + } + + data.Status_Code = erc.DSCSubmited + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "submited", + }, + Data: data.ToResponse(), + }, nil + +} + func Complete(input e.ReadDetailDto) (*d.Data, error) { var data *e.McuOrder var err error From 46d0c17669b467cee217ea327ac75b48229062c2 Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 20 Nov 2025 14:16:08 +0700 Subject: [PATCH 244/329] encounter mapping --- internal/domain/references/person/person.go | 3 + .../domain/simgos-entities/patient/entity.go | 2 +- .../interface/main-handler/patient/handler.go | 8 + .../use-case/main-use-case/patient/case.go | 14 ++ .../simgos-sync-use-case/encounter/case.go | 197 ++++++++++++++++++ .../simgos-sync-use-case/encounter/helper.go | 74 +++++++ .../simgos-sync-use-case/encounter/lib.go | 188 +++++++++++++++++ .../encounter/middleware-runner.go | 104 +++++++++ .../encounter/middleware.go | 9 + .../simgos-sync-use-case/encounter/tycovar.go | 44 ++++ .../simgos-sync-use-case/patient/case.go | 2 +- .../simgos-sync-use-case/patient/helper.go | 109 ++++++---- 12 files changed, 714 insertions(+), 40 deletions(-) create mode 100644 internal/use-case/simgos-sync-use-case/encounter/case.go create mode 100644 internal/use-case/simgos-sync-use-case/encounter/helper.go create mode 100644 internal/use-case/simgos-sync-use-case/encounter/lib.go create mode 100644 internal/use-case/simgos-sync-use-case/encounter/middleware-runner.go create mode 100644 internal/use-case/simgos-sync-use-case/encounter/middleware.go create mode 100644 internal/use-case/simgos-sync-use-case/encounter/tycovar.go diff --git a/internal/domain/references/person/person.go b/internal/domain/references/person/person.go index 1648b578..dfd35179 100644 --- a/internal/domain/references/person/person.go +++ b/internal/domain/references/person/person.go @@ -112,6 +112,9 @@ const ( RCNephew RelationshipCode = "nephew" // Keponakan RCGdChild RelationshipCode = "gd-child" // Cucu RCOther RelationshipCode = "other" // Lainnya + RCFriend RelationshipCode = "friend" // Teman + RCSpouse RelationshipCode = "spouse" // Pasangan (Suami / Istri) + RCSelf RelationshipCode = "self" // Diri Sendiri ALTCIdn AddressLocationTypeCode = "identity" // Sesuai Identitas ALTCDom AddressLocationTypeCode = "domicile" // Sesuai Domisili diff --git a/internal/domain/simgos-entities/patient/entity.go b/internal/domain/simgos-entities/patient/entity.go index 20b7fee6..67958d56 100644 --- a/internal/domain/simgos-entities/patient/entity.go +++ b/internal/domain/simgos-entities/patient/entity.go @@ -65,7 +65,7 @@ type MPasien struct { 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 string `json:"st_identitas_ortu" gorm:"column:st_identitas_ortu"` + StIdentitasOrtu uint `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"` diff --git a/internal/interface/main-handler/patient/handler.go b/internal/interface/main-handler/patient/handler.go index 9fd5fdce..41fca562 100644 --- a/internal/interface/main-handler/patient/handler.go +++ b/internal/interface/main-handler/patient/handler.go @@ -2,6 +2,7 @@ package patient import ( "net/http" + pa "simrs-vx/internal/lib/auth" rw "github.com/karincake/risoles" sf "github.com/karincake/semprit" @@ -19,10 +20,17 @@ type myBase struct{} var O myBase func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + dto := e.CreateDto{} if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } + + dto.AuthInfo = *authInfo res, err := u.Create(dto) rw.DataResponse(w, res, err) } diff --git a/internal/use-case/main-use-case/patient/case.go b/internal/use-case/main-use-case/patient/case.go index 1a8437e5..0ed93bbe 100644 --- a/internal/use-case/main-use-case/patient/case.go +++ b/internal/use-case/main-use-case/patient/case.go @@ -1,6 +1,7 @@ package patient import ( + "errors" "strconv" pl "simrs-vx/pkg/logger" @@ -38,6 +39,19 @@ func Create(input e.CreateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "create") mwRunner := newMiddlewareRunner(&event) + // check if user has employee position + if !input.AuthInfo.HasEmployeePosition() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "auth-forbidden", + Detail: "user has no employee position", + Raw: errors.New("authentication failed"), + } + return nil, pl.SetLogError(&event, input) + } + + input.RegisteredBy_User_Name = &input.AuthInfo.User_Name + err := dg.I.Transaction(func(tx *gorm.DB) error { mwRunner.setMwType(pu.MWTPre) // Run pre-middleware diff --git a/internal/use-case/simgos-sync-use-case/encounter/case.go b/internal/use-case/simgos-sync-use-case/encounter/case.go new file mode 100644 index 00000000..57650594 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/encounter/case.go @@ -0,0 +1,197 @@ +package encounter + +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/division" + esimgos "simrs-vx/internal/domain/simgos-entities/division" + esync "simrs-vx/internal/domain/sync-entities/division" + elog "simrs-vx/internal/domain/sync-entities/log" +) + +const source = "division" + +func Create(input e.CreateDto) (*d.Data, error) { + var ( + sgData *esimgos.MUnit + syncLink *esync.DivisionLink + err error + ) + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + err = db.WithDualTx(func(tx *db.Dualtx) error { + // STEP 1: Insert to simgos + sgData, err = CreateSimgosData(input, &event, tx.Simgos) + if err != nil { + return err + } + + // STEP 2: Insert to Link + syncLink, err = CreateLinkData(*input.Id, sgData.KodeUnit, &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.UpdateDto) (*d.Data, error) { + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + // STEP 1: Get Link + syncLink, err := ReadDetailLinkData(*input.Id, &event) + if err != nil { + return nil, err + } + + tx := db.NewTx() + err = tx.Simgos.Transaction(func(tx *gorm.DB) error { + // Step 2: Update Simgos + if err = UpdateSimgosData(input, syncLink, &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") + + // STEP 1: Get Link + syncLink, err := ReadDetailLinkData(*input.Id, &event) + if err != nil { + return nil, err + } + + // STEP 2: Get Simgos + sgData, err := ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) + if err != nil { + return nil, err + } + + err = db.WithDualTx(func(tx *db.Dualtx) error { + // STEP 3: Delete Simgos + err = HardDeleteSimgosData(sgData, &event, tx.Simgos) + if 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(uint(*input.Id), sgData.KodeUnit, &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/encounter/helper.go b/internal/use-case/simgos-sync-use-case/encounter/helper.go new file mode 100644 index 00000000..6fb47ac9 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/encounter/helper.go @@ -0,0 +1,74 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package encounter + +import ( + "encoding/json" + "strconv" + + erc "simrs-vx/internal/domain/references/common" + ere "simrs-vx/internal/domain/references/encounter" + + e "simrs-vx/internal/domain/main-entities/encounter" + esimgos "simrs-vx/internal/domain/simgos-entities/encounter" + esync "simrs-vx/internal/domain/sync-entities/encounter" + esyncLog "simrs-vx/internal/domain/sync-entities/encounter" +) + +func setDataSimgos(input *e.Encounter) (data esimgos.TPendaftaran) { + data.Nomr = *input.Patient.Number + data.Tglreg = input.RegisteredAt + + kddokter, _ := strconv.Atoi(*input.Appointment_Doctor_Code) + data.Kddokter = uint(kddokter) + + kdpoly, _ := strconv.Atoi(*input.Unit_Code) + data.Kdpoly = uint(kdpoly) + + setKdrujuk(input.RefType_Code, data) + + return +} + +func setKdrujuk(input *ere.RefTypeCode, data esimgos.TPendaftaran) { + switch *input { + case ere.RTCGov: + data.Kdrujuk = 1 + case ere.RTCPrivate: + data.Kdrujuk = 2 + case ere.RTCBpjs: + data.Kdrujuk = 3 + default: + data.Kdrujuk = 0 + } +} + +func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.DivisionSimxLog) { + // 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.DivisionLink) { + data.Simx_Id = simxId + data.Simgos_Id = simgosId + return +} diff --git a/internal/use-case/simgos-sync-use-case/encounter/lib.go b/internal/use-case/simgos-sync-use-case/encounter/lib.go new file mode 100644 index 00000000..f713ca6c --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/encounter/lib.go @@ -0,0 +1,188 @@ +package encounter + +import ( + 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/division" + esimgos "simrs-vx/internal/domain/simgos-entities/division" + esync "simrs-vx/internal/domain/sync-entities/division" + esynclog "simrs-vx/internal/domain/sync-entities/log" +) + +var now = time.Now() + +func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esimgos.MUnit, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := setDataSimgos(&input) + + 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 ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.MUnit, error) { + pl.SetLogInfo(event, simgosId, "started", "DBReadDetail") + data := esimgos.MUnit{} + + var tx = dg.IS["simrs"] + + if err := tx. + Where("\"kode_unit\" = ?", 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 UpdateSimgosData(input e.UpdateDto, dataSimgos *esync.DivisionLink, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, input, "started", "DBUpdate") + + data := setDataSimgos(&input) + data.KodeUnit = dataSimgos.Simgos_Id + + 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 HardDeleteSimgosData(data *esimgos.MUnit, 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 CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.DivisionLink, 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 uint16, event *pl.Event) (*esync.DivisionLink, error) { + pl.SetLogInfo(event, simxId, "started", "DBReadDetail") + data := esync.DivisionLink{} + + 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.DivisionLink, 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/encounter/middleware-runner.go b/internal/use-case/simgos-sync-use-case/encounter/middleware-runner.go new file mode 100644 index 00000000..83e0252c --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/encounter/middleware-runner.go @@ -0,0 +1,104 @@ +package encounter + +import ( + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/encounter" +) + +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.Encounter) 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.Encounter) 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.Encounter) 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.Encounter) 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.Encounter) 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/encounter/middleware.go b/internal/use-case/simgos-sync-use-case/encounter/middleware.go new file mode 100644 index 00000000..8a047d33 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/encounter/middleware.go @@ -0,0 +1,9 @@ +package encounter + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/simgos-sync-use-case/encounter/tycovar.go b/internal/use-case/simgos-sync-use-case/encounter/tycovar.go new file mode 100644 index 00000000..17890a1b --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/encounter/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 encounter + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/encounter" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.Encounter, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Encounter, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Encounter, 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/patient/case.go b/internal/use-case/simgos-sync-use-case/patient/case.go index d403a8ac..104e79e9 100644 --- a/internal/use-case/simgos-sync-use-case/patient/case.go +++ b/internal/use-case/simgos-sync-use-case/patient/case.go @@ -211,7 +211,7 @@ func GenerateNomr() (*d.Data, error) { // Start log pl.SetLogInfo(&event, nil, "started", "create") - norm, err := generateNomrPatient() + norm, err := generateNomrPatient("12") if err != nil { return nil, err } diff --git a/internal/use-case/simgos-sync-use-case/patient/helper.go b/internal/use-case/simgos-sync-use-case/patient/helper.go index 0bffcc9b..8ab4c326 100644 --- a/internal/use-case/simgos-sync-use-case/patient/helper.go +++ b/internal/use-case/simgos-sync-use-case/patient/helper.go @@ -39,21 +39,33 @@ func setDataSimgos(input *e.Patient) (data esimgos.MPasien) { if input.Person != nil && input.Person.Relatives != nil { mapRelative(input.Person.Relatives, &data) + } else { + data.PenanggungjawabHubungan = "DIRI SENDIRI" + data.PenanggungjawabNama = input.Person.Name + data.PenanggungjawabPhone = data.Notelp + data.PenanggungjawabAlamat = data.Alamat } data.Nip = input.RegisteredBy_User_Name data.Tgldaftar = input.RegisteredAt data.Nomr = *input.Number + nomrBaru, _ := generateNomrPatient("00") + data.NomrBaru = &nomrBaru + return } -func generateNomrPatient() (string, error) { - const prefix = "12" // fixed starting prefix (same as $awal_rm) in simgos +func generateNomrPatient(prefix string) (string, error) { const maxSuffix = 999999 + column := "nomr" + if prefix == "00" { + column = "nomr_baru" + } + type Row struct { - Nomr string `gorm:"column:nomr"` + Value string `gorm:"column:value"` } var r Row @@ -61,31 +73,35 @@ func generateNomrPatient() (string, error) { // Lock rows for this prefix → prevents race condition if err := dg.IS["simrs"]. Table("m_pasien"). - Select("nomr"). - Where("nomr LIKE ?", prefix+"%"). - Order("nomr DESC"). + Select(fmt.Sprintf("%s AS value", column)). + Where(fmt.Sprintf("%s LIKE ?", column), prefix+"%"). + Order(fmt.Sprintf("%s DESC", column)). Clauses(clause.Locking{Strength: "UPDATE"}). Limit(1). Scan(&r).Error; err != nil { return "", err } - // No existing NOMR → start fresh - if r.Nomr == "" { + // No existing number → start at 000001 + if r.Value == "" || len(r.Value) < len(prefix) { return prefix + "000001", nil } - suffix := r.Nomr[len(prefix):] // extract numeric part - num, _ := strconv.Atoi(suffix) - - // 3. If suffix reaches 999999 → increment the prefix - if num == maxSuffix { - p, _ := strconv.Atoi(prefix) - p++ - return fmt.Sprintf("%d000001", p), nil + suffix := r.Value[len(prefix):] + num, err := strconv.Atoi(suffix) + if err != nil { + // data corrupt, reset nomor + return prefix + "000001", nil } - // 4. Normal increment + // If reached 999999 → increment prefix + if num >= maxSuffix { + p, _ := strconv.Atoi(prefix) + p++ + return fmt.Sprintf("%02d000001", p), nil + } + + // Normal increment return prefix + fmt.Sprintf("%06d", num+1), nil } @@ -262,30 +278,47 @@ func mapRelative(relative *[]epr.PersonRelative, data *esimgos.MPasien) { return } - r := (*relative)[0] - data.PenanggungjawabNama = *r.Name + for _, r := range *relative { + if r.Responsible { + data.PenanggungjawabNama = *r.Name - switch r.Relationship_Code { - case erp.RCMother, erp.RCFather: - data.PenanggungjawabHubungan = "ORANG TUA" - switch { - case r.Relationship_Code == erp.RCMother: - data.NamaIbu = *r.Name - eduCode, _ := setEducation(r.Education_Code) - data.PendidikanIbu = strconv.Itoa(int(eduCode)) - case r.Relationship_Code == erp.RCFather: - data.NamaAyah = *r.Name - eduCode, _ := setEducation(r.Education_Code) - data.PendidikanAyah = strconv.Itoa(int(eduCode)) + switch r.Relationship_Code { + case erp.RCMother, erp.RCFather: + data.PenanggungjawabHubungan = "ORANG TUA" + switch { + case r.Relationship_Code == erp.RCMother: + data.NamaIbu = *r.Name + eduCode, _ := setEducation(r.Education_Code) + data.PendidikanIbu = strconv.Itoa(int(eduCode)) + case r.Relationship_Code == erp.RCFather: + data.NamaAyah = *r.Name + eduCode, _ := setEducation(r.Education_Code) + data.PendidikanAyah = strconv.Itoa(int(eduCode)) + } + case erp.RCChild: + data.PenanggungjawabHubungan = "ANAK" + case erp.RCSibling: + data.PenanggungjawabHubungan = "SAUDARA" + case erp.RCUncle, erp.RCAunt, + erp.RCGdMother, erp.RCGdFather, + erp.RCNephew, erp.RCGdChild: + data.PenanggungjawabHubungan = "KELUARGA LAIN" + case erp.RCFriend: + data.PenanggungjawabHubungan = "TEMAN" + case erp.RCSpouse: + data.PenanggungjawabHubungan = "SUAMI/ISTRI" + case erp.RCSelf: + data.PenanggungjawabHubungan = "DIRI SENDIRI" + default: + data.PenanggungjawabHubungan = "LAINNYA ..." + } + + data.PenanggungjawabAlamat = *r.Address + data.PenanggungjawabPhone = *r.PhoneNumber + + break } - case erp.RCChild: - data.PenanggungjawabHubungan = "ANAK" - default: - data.PenanggungjawabHubungan = "LAINNYA" } - - data.PenanggungjawabAlamat = *r.Address - data.PenanggungjawabPhone = *r.PhoneNumber } func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.PatientSimxLog) { From 990f50e50c7d6f5b92f13572a131d265a924d3e1 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 20 Nov 2025 14:45:18 +0700 Subject: [PATCH 245/329] add resume entity --- .../migrations/20251120074415.sql | 11 ++ cmd/main-migration/migrations/atlas.sum | 105 +++++++++--------- internal/domain/main-entities/resume/dto.go | 64 +++++++++++ .../domain/main-entities/resume/entity.go | 12 ++ internal/interface/migration/main-entities.go | 2 + 5 files changed, 142 insertions(+), 52 deletions(-) create mode 100644 cmd/main-migration/migrations/20251120074415.sql create mode 100644 internal/domain/main-entities/resume/dto.go create mode 100644 internal/domain/main-entities/resume/entity.go diff --git a/cmd/main-migration/migrations/20251120074415.sql b/cmd/main-migration/migrations/20251120074415.sql new file mode 100644 index 00000000..ae6cd675 --- /dev/null +++ b/cmd/main-migration/migrations/20251120074415.sql @@ -0,0 +1,11 @@ +-- Create "Resume" table +CREATE TABLE "public"."Resume" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NOT NULL, + "Value" text NULL, + "FileUrl" character varying(1024) NULL, + PRIMARY KEY ("Id") +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 5645ddc2..0d9edc98 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:DgafJ/z7PUlDk6JQZ+ZwOf1lD4zj6ErO+ojgeSuBuk0= +h1:4U2KWXwY59v9g8NqCRfUlRU8S0gFHP+2zZo3VIYCy80= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,54 +75,55 @@ h1:DgafJ/z7PUlDk6JQZ+ZwOf1lD4zj6ErO+ojgeSuBuk0= 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= +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:4gmYBcmga1SBxRwrVaovGVvpRZFMV7vYzce0/IalryY= diff --git a/internal/domain/main-entities/resume/dto.go b/internal/domain/main-entities/resume/dto.go new file mode 100644 index 00000000..ea9485d7 --- /dev/null +++ b/internal/domain/main-entities/resume/dto.go @@ -0,0 +1,64 @@ +package resume + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type CreateDto struct { + Encounter_Id *uint `json:"encounter_id"` + Value *string `json:"value"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Encounter_Id *uint `json:"encounter-id"` +} + +type ReadDetailDto struct { + Id uint `json:"id"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + Encounter_Id *uint `json:"encounter_id"` + Value *string `json:"value"` + FileUrl *string `json:"fileUrl"` +} + +func (d Resume) ToResponse() ResponseDto { + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Value: d.Value, + FileUrl: d.FileUrl, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []Resume) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/resume/entity.go b/internal/domain/main-entities/resume/entity.go new file mode 100644 index 00000000..cf756870 --- /dev/null +++ b/internal/domain/main-entities/resume/entity.go @@ -0,0 +1,12 @@ +package resume + +import ( + "simrs-vx/internal/domain/base-entities/core" +) + +type Resume struct { + core.Main + Encounter_Id *uint `json:"encounter_id" gorm:"not null"` + Value *string `json:"value"` + FileUrl *string `json:"fileUrl" gorm:"size:1024"` +} diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index 23e7422c..d55a5e27 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -82,6 +82,7 @@ import ( regency "simrs-vx/internal/domain/main-entities/regency" rehab "simrs-vx/internal/domain/main-entities/rehab" responsibledoctorhist "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" + resume "simrs-vx/internal/domain/main-entities/resume" room "simrs-vx/internal/domain/main-entities/room" sbar "simrs-vx/internal/domain/main-entities/sbar" soapi "simrs-vx/internal/domain/main-entities/soapi" @@ -213,5 +214,6 @@ func getMainEntities() []any { &chemoprotocol.ChemoProtocol{}, &fileattachemnt.EncounterDocument{}, &vclaimsepcontrolletter.VclaimSepControlLetter{}, + &resume.Resume{}, } } From dd5f6f78e34eb493747e26da8c746e0b09741358 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 21 Nov 2025 10:21:21 +0700 Subject: [PATCH 246/329] add cud sync encounter --- .../domain/main-entities/encounter/entity.go | 2 +- .../domain/references/encounter/encounter.go | 1 + .../simgos-entities/encounter/entity.go | 2 +- .../use-case/main-use-case/encounter/case.go | 198 +++++++++++------- .../encounter/middleware-runner.go | 71 +++++-- .../main-use-case/encounter/tycovar.go | 30 ++- .../use-case/main-use-case/patient/case.go | 2 - .../simgos-sync-use-case/encounter/case.go | 24 +-- .../simgos-sync-use-case/encounter/helper.go | 141 ++++++++++++- .../simgos-sync-use-case/encounter/lib.go | 28 +-- 10 files changed, 364 insertions(+), 135 deletions(-) diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index c188bb1a..4d814ed0 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -40,7 +40,7 @@ type Encounter struct { VisitDate time.Time `json:"visitDate"` StartedAt *time.Time `json:"startedAt"` FinishedAt *time.Time `json:"finishedAt"` - PaymentMethod_Code erc.PaymentMethodCode `json:"paymentMethod_code" gorm:"size:10"` + PaymentMethod_Code ere.AllPaymentMethodCode `json:"paymentMethod_code" gorm:"size:10"` InsuranceCompany_Code *string `json:"insuranceCompany_code"` InsuranceCompany *ei.InsuranceCompany `json:"insuranceCompany,omitempty" gorm:"foreignKey:InsuranceCompany_Code;references:Code"` Member_Number *string `json:"memberNumber" gorm:"unique;size:20"` diff --git a/internal/domain/references/encounter/encounter.go b/internal/domain/references/encounter/encounter.go index 532e1625..66025373 100644 --- a/internal/domain/references/encounter/encounter.go +++ b/internal/domain/references/encounter/encounter.go @@ -99,6 +99,7 @@ const ( APMCJkmm AllPaymentMethodCode = "jkmm" // JKMM APMCSpm AllPaymentMethodCode = "spm" // SPM APMCPks AllPaymentMethodCode = "pks" // PKS + APMCUmum AllPaymentMethodCode = "umum" SRTCInternal SEPRefTypeCode = "internal" // Rujukan Internal SRTCExternal SEPRefTypeCode = "external" // Faskes Lain diff --git a/internal/domain/simgos-entities/encounter/entity.go b/internal/domain/simgos-entities/encounter/entity.go index 16ba873e..cd8f538d 100644 --- a/internal/domain/simgos-entities/encounter/entity.go +++ b/internal/domain/simgos-entities/encounter/entity.go @@ -16,7 +16,7 @@ type TPendaftaran struct { KeteranganStatus *uint `json:"keterangan_status" gorm:"column:keterangan_status"` Pasienbaru uint `json:"pasienbaru" gorm:"column:pasienbaru"` Nip string `json:"nip" gorm:"column:nip"` - Idxdaftar uint `json:"idxdaftar" gorm:"column:idxdaftar"` + Idxdaftar uint `json:"idxdaftar" gorm:"primaryKey;autoIncrement;column:idxdaftar"` Masukpoly *time.Time `json:"masukpoly" gorm:"column:masukpoly"` Keluarpoly *time.Time `json:"keluarpoly" gorm:"column:keluarpoly"` Ketrujuk string `json:"ketrujuk" gorm:"column:ketrujuk"` diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index e3d564ff..37e08bc5 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -3,7 +3,6 @@ package encounter import ( "errors" "fmt" - us "simrs-vx/internal/use-case/main-use-case/soapi" "strconv" "time" @@ -24,11 +23,13 @@ import ( eir "simrs-vx/internal/domain/main-entities/internal-reference" erdh "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" es "simrs-vx/internal/domain/main-entities/soapi" + esync "simrs-vx/internal/domain/sync-entities/log" uaeh "simrs-vx/internal/use-case/main-use-case/adm-employee-hist" udc "simrs-vx/internal/use-case/main-use-case/death-cause" uir "simrs-vx/internal/use-case/main-use-case/internal-reference" urdh "simrs-vx/internal/use-case/main-use-case/responsible-doctor-hist" + us "simrs-vx/internal/use-case/main-use-case/soapi" ) const source = "encounter" @@ -50,34 +51,6 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - // validate rehab bpjs - if input.RefTypeCode == ere.RTCBpjs && input.Class_Code == ere.ECAmbulatory && ere.AmbulatoryClassCode(*input.SubClass_Code) == ere.ACCRehab { - // get latest rehab data - recentRehabData, err := getLatestRehabData(input, &event) - if err != nil { - return nil, err - } - - if recentRehabData != nil { - // determine VisitModeCode - input.VisitMode_Code, input.RecentEncounterAdm, err = determineVisitMode(recentRehabData, input, &event) - if err != nil { - return nil, err - } - } else { - input.VisitMode_Code = ere.VMCAdm - } - - // if visitMode_Code is series, then get data soapi for copy - if input.VisitMode_Code == ere.VMCSeries { - // get data soapi - recentSoapiDataforCopy, err = getSoapiEncounterAdm(*input.RecentEncounterAdm, &event) - if err != nil { - return nil, err - } - } - } - // check if user has employee position if !input.AuthInfo.HasEmployeePosition() { event.Status = "failed" @@ -102,17 +75,44 @@ func Create(input e.CreateDto) (*d.Data, error) { input.Adm_Employee_Id = input.AuthInfo.Employee_Id } - // check if patient is new in the hospital - input.NewStatus, err = identifyPatientStatus(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 + // validate rehab by bpjs + if input.RefTypeCode == ere.RTCBpjs && + input.Class_Code == ere.ECAmbulatory && + ere.AmbulatoryClassCode(*input.SubClass_Code) == ere.ACCRehab { + // get latest rehab data + recentRehabData, err := getLatestRehabData(input, &event) + if err != nil { + return nil, err } + // If recentRehabData is nil, then visitMode_Code = "adm" + if recentRehabData != nil { + // If recentRehabData is not nil, determine the visitMode_Code: + // If the mode is "series", verify whether the visit count still remains + // and whether the series has not expired. + input.VisitMode_Code, input.RecentEncounterAdm, err = determineVisitMode(recentRehabData, input, &event) + if err != nil { + return nil, err + } + } else { + input.VisitMode_Code = ere.VMCAdm + } + + // When visitMode_Code is "series", load the associated SOAPI record to copy its values. + if input.VisitMode_Code == ere.VMCSeries { + // get data soapi + recentSoapiDataforCopy, err = getSoapiEncounterAdm(*input.RecentEncounterAdm, &event) + if err != nil { + return nil, err + } + } + } + + // check if patient is new in the hospital + input.NewStatus, err = identifyPatientStatus(input) + mwRunner := newMiddlewareRunner(&event) + + err = dg.I.Transaction(func(tx *gorm.DB) error { // create encounter if resData, err := CreateData(input, &event, tx); err != nil { return err @@ -128,28 +128,36 @@ func Create(input e.CreateDto) (*d.Data, error) { } // insert adm_employee_hist - if _, err := uaeh.CreateData(eaeh.CreateDto{ + if _, err = uaeh.CreateData(eaeh.CreateDto{ Encounter_Id: &data.Id, Employee_Id: data.Adm_Employee_Id, StartedAt: &now}, &event, tx); err != nil { return err } - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + dataEncounter, err := ReadDetailData(e.ReadDetailDto{ + Id: uint16(data.Id), + Includes: "Adm_Employee.User,Patient.Person.Relatives,Patient.Person.VclaimMember"}, + &event, tx) + if err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, dataEncounter); err != nil { + return err + } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.II{ "source": source, @@ -175,7 +183,7 @@ 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 := newMiddlewareRunner(&event) mwRunner.setMwType(pu.MWTPre) // Run pre-middleware if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { @@ -226,7 +234,7 @@ 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 := newMiddlewareRunner(&event) mwRunner.setMwType(pu.MWTPre) // Run pre-middleware if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { @@ -261,7 +269,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { } func Update(input e.UpdateDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Id: input.Id} var data *e.Encounter var err error @@ -272,6 +280,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "update") + mwRunner := newMiddlewareRunner(&event) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -289,32 +298,33 @@ func Update(input e.UpdateDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - 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") + dataEncounter, err := ReadDetailData(e.ReadDetailDto{ + Id: uint16(data.Id), + Includes: "Adm_Employee.User,Patient.Person.Relatives,Patient.Person.VclaimMember"}, + &event, tx) + if err != nil { + return err + } - mwRunner.setMwType(pu.MWTPost) + mwRunner.setMwType(pu.MWTPre) // Run post-middleware - if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + if err := mwRunner.RunUpdateMiddleware(updatePreMw, dataEncounter); err != nil { return err } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -327,7 +337,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id)} + rdDto := e.ReadDetailDto{Id: input.Id} var data *e.Encounter var err error @@ -361,36 +371,33 @@ func Delete(input e.DeleteDto) (*d.Data, error) { return nil, pl.SetLogError(&event, input) } + mwRunner := newMiddlewareRunner(&event) + err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") if data, err = ReadDetailData(rdDto, &event, tx); err != nil { 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.RunDeleteMiddleware(deletePreMw, &input); err != nil { return err } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -581,12 +588,12 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) { } } - mwRunner := newMiddlewareRunner(&event, tx) - mwRunner.setMwType(pu.MWTPre) - // Run pre-middleware - if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { - return err - } + //mwRunner := newMiddlewareRunner(&event) + //mwRunner.setMwType(pu.MWTPre) + //// Run pre-middleware + //if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { + // return err + //} if err := UpdateStatusData(input, data, &event, tx); err != nil { return err @@ -594,11 +601,11 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) { pl.SetLogInfo(&event, nil, "complete") - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { - return err - } + //mwRunner.setMwType(pu.MWTPost) + //// Run post-middleware + //if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + // return err + //} return nil }) @@ -915,3 +922,32 @@ func ApproveSwitchUnit(input e.ApproveUnitDto) (*d.Data, error) { }, nil } + +func runLogMiddleware(err error, input any, mwRunner *middlewareRunner) error { + var errMsg string + inputLog := esync.SimxLogDto{ + Payload: input, + Method: erc.CCCreate, + } + + if err != nil { + // Run log-middleware + errMsg = err.Error() + inputLog.ErrMessage = &errMsg + inputLog.IsSuccess = false + + // create log failed + if errMiddleware := mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog); errMiddleware != nil { + return errMiddleware + } + return err + } + + // create log success + inputLog.IsSuccess = true + if err = mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog); err != nil { + return err + } + + return nil +} 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 1448a7af..b030d286 100644 --- a/internal/use-case/main-use-case/encounter/middleware-runner.go +++ b/internal/use-case/main-use-case/encounter/middleware-runner.go @@ -1,35 +1,64 @@ package encounter import ( - e "simrs-vx/internal/domain/main-entities/encounter" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" "gorm.io/gorm" + + sync "simrs-vx/internal/infra/sync-cfg" + + e "simrs-vx/internal/domain/main-entities/encounter" + esync "simrs-vx/internal/domain/sync-entities/log" ) 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) *middlewareRunner { return &middlewareRunner{ - Event: event, - Tx: tx, + Event: event, + SyncOn: sync.O.Enable, } } // ExecuteCreateMiddleware executes create middleware -func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.Encounter) error { +func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.Encounter) error { + if !me.SyncOn { + return nil + } + 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 +} + +// ExecuteCreateMiddleware executes create middleware +func (me *middlewareRunner) RunCreateLogMiddleware(middlewares []createLogMw, input *esync.SimxLogDto) error { + if !me.SyncOn { + return nil + } + + 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) } @@ -39,6 +68,10 @@ func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e } func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.Encounter) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -54,6 +87,10 @@ func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, inpu } func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Encounter) error { + if !me.SyncOn { + return nil + } + for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -68,13 +105,17 @@ func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, return nil } -func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Encounter) error { +func (me *middlewareRunner) RunUpdateMiddleware(middlewares []updateMw, input *e.Encounter) error { + if !me.SyncOn { + return nil + } + 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 +124,17 @@ func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, inpu return nil } -func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Encounter) error { +func (me *middlewareRunner) RunDeleteMiddleware(middlewares []deleteMw, input *e.DeleteDto) error { + if !me.SyncOn { + return nil + } + 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) } diff --git a/internal/use-case/main-use-case/encounter/tycovar.go b/internal/use-case/main-use-case/encounter/tycovar.go index 17890a1b..f618bd19 100644 --- a/internal/use-case/main-use-case/encounter/tycovar.go +++ b/internal/use-case/main-use-case/encounter/tycovar.go @@ -12,13 +12,28 @@ import ( "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/encounter" + elog "simrs-vx/internal/domain/sync-entities/log" ) type createMw struct { Name string - Func func(input *e.CreateDto, data *e.Encounter, tx *gorm.DB) error + Func func(input *e.Encounter) error } +type createLogMw struct { + Name string + Func func(input *elog.SimxLogDto) error +} + +type updateMw struct { + Name string + Func func(input *e.Encounter) error +} + +type deleteMw struct { + Name string + Func func(input *e.DeleteDto) error +} type readListMw struct { Name string Func func(input *e.ReadListDto, data *e.Encounter, tx *gorm.DB) error @@ -29,16 +44,17 @@ type readDetailMw struct { Func func(input *e.ReadDetailDto, data *e.Encounter, 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 +var createPreMw []createMw // preprocess middleware +var createPostMw []createMw // postprocess middleware +var createSimxLogMw []createLogMw 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 diff --git a/internal/use-case/main-use-case/patient/case.go b/internal/use-case/main-use-case/patient/case.go index 0ed93bbe..24aa4394 100644 --- a/internal/use-case/main-use-case/patient/case.go +++ b/internal/use-case/main-use-case/patient/case.go @@ -351,8 +351,6 @@ func Delete(input e.DeleteDto) (*d.Data, error) { return err } - input.Id = data.Id - // Delete Patient if err := DeleteData(data, &event, tx); err != nil { return err diff --git a/internal/use-case/simgos-sync-use-case/encounter/case.go b/internal/use-case/simgos-sync-use-case/encounter/case.go index 57650594..591dae36 100644 --- a/internal/use-case/simgos-sync-use-case/encounter/case.go +++ b/internal/use-case/simgos-sync-use-case/encounter/case.go @@ -8,18 +8,18 @@ import ( db "simrs-vx/pkg/dualtrx-helper" - e "simrs-vx/internal/domain/main-entities/division" - esimgos "simrs-vx/internal/domain/simgos-entities/division" - esync "simrs-vx/internal/domain/sync-entities/division" + e "simrs-vx/internal/domain/main-entities/encounter" + esimgos "simrs-vx/internal/domain/simgos-entities/encounter" + esync "simrs-vx/internal/domain/sync-entities/encounter" elog "simrs-vx/internal/domain/sync-entities/log" ) -const source = "division" +const source = "encounter" -func Create(input e.CreateDto) (*d.Data, error) { +func Create(input e.Encounter) (*d.Data, error) { var ( - sgData *esimgos.MUnit - syncLink *esync.DivisionLink + sgData *esimgos.TPendaftaran + syncLink *esync.EncounterLink err error ) @@ -39,7 +39,7 @@ func Create(input e.CreateDto) (*d.Data, error) { } // STEP 2: Insert to Link - syncLink, err = CreateLinkData(*input.Id, sgData.KodeUnit, &event, tx.Sync) + syncLink, err = CreateLinkData(input.Id, sgData.Idxdaftar, &event, tx.Sync) if err != nil { return err } @@ -99,7 +99,7 @@ func CreateSimxLog(input elog.SimxLogDto) (*d.Data, error) { }, nil } -func Update(input e.UpdateDto) (*d.Data, error) { +func Update(input e.Encounter) (*d.Data, error) { event := pl.Event{ Feature: "Update", Source: source, @@ -109,7 +109,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "update") // STEP 1: Get Link - syncLink, err := ReadDetailLinkData(*input.Id, &event) + syncLink, err := ReadDetailLinkData(uint16(input.Id), &event) if err != nil { return nil, err } @@ -147,7 +147,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "delete") // STEP 1: Get Link - syncLink, err := ReadDetailLinkData(*input.Id, &event) + syncLink, err := ReadDetailLinkData(input.Id, &event) if err != nil { return nil, err } @@ -178,7 +178,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { if err != nil { if isLinkDeleted { go func() { - _, _ = CreateLinkData(uint(*input.Id), sgData.KodeUnit, &event) + _, _ = CreateLinkData(uint(input.Id), sgData.Idxdaftar, &event) }() } return nil, err diff --git a/internal/use-case/simgos-sync-use-case/encounter/helper.go b/internal/use-case/simgos-sync-use-case/encounter/helper.go index 6fb47ac9..b9daa7de 100644 --- a/internal/use-case/simgos-sync-use-case/encounter/helper.go +++ b/internal/use-case/simgos-sync-use-case/encounter/helper.go @@ -6,6 +6,8 @@ package encounter import ( "encoding/json" + epr "simrs-vx/internal/domain/main-entities/person-relative" + erp "simrs-vx/internal/domain/references/person" "strconv" erc "simrs-vx/internal/domain/references/common" @@ -14,21 +16,68 @@ import ( e "simrs-vx/internal/domain/main-entities/encounter" esimgos "simrs-vx/internal/domain/simgos-entities/encounter" esync "simrs-vx/internal/domain/sync-entities/encounter" - esyncLog "simrs-vx/internal/domain/sync-entities/encounter" + esyncLog "simrs-vx/internal/domain/sync-entities/log" ) func setDataSimgos(input *e.Encounter) (data esimgos.TPendaftaran) { data.Nomr = *input.Patient.Number data.Tglreg = input.RegisteredAt + // set kddokter kddokter, _ := strconv.Atoi(*input.Appointment_Doctor_Code) data.Kddokter = uint(kddokter) + // set kdpoly kdpoly, _ := strconv.Atoi(*input.Unit_Code) data.Kdpoly = uint(kdpoly) + // set kdrujuk setKdrujuk(input.RefType_Code, data) - + + // set kdcarabayar + setKdcarabayar(input.PaymentMethod_Code, data) + + // TODO: shift + + // set status + setStatus(input.Discharge_Method_Code, data) + if input.Status_Code == erc.DSCCancel { + data.Status = 11 + } + + // set pasienbaru + if input.NewStatus { + data.Pasienbaru = 1 + } + + if emp := input.Adm_Employee; emp != nil { + if user := emp.User; user != nil { + data.Nip = user.Name + } + } + + data.Masukpoly = input.StartedAt + data.Keluarpoly = input.FinishedAt + + if input.RefSource_Name != nil { + data.Ketrujuk = *input.RefSource_Name + } else { + data.Ketrujuk = "TR" + } + + // TODO: preload person.relative, person.vclaimMember + if p := input.Patient.Person; p != nil { + mapRelative(p.Relatives, data) + + if bpjs := p.VclaimMember; bpjs != nil { + data.Nokartu = *bpjs.CardNumber + } + } + + data.Jamreg = input.RegisteredAt + + // TODO: norujukan, tglrujukan, dokumen_pendukung sep_file + return } @@ -45,7 +94,91 @@ func setKdrujuk(input *ere.RefTypeCode, data esimgos.TPendaftaran) { } } -func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.DivisionSimxLog) { +func setKdcarabayar(input ere.AllPaymentMethodCode, data esimgos.TPendaftaran) { + switch input { + case ere.APMCPks: + data.Kdcarabayar = 12 + case ere.APMCJkn: + data.Kdcarabayar = 5 + case ere.APMCJkmm: + data.Kdcarabayar = 9 + case ere.APMCSpm: + data.Kdcarabayar = 10 + default: + data.Kdcarabayar = 1 + } +} + +func setStatus(code *ere.DischargeMethodCode, data esimgos.TPendaftaran) { + switch *code { + case ere.DMCHome: + data.Status = 1 + case ere.DMCInpatient: + data.Status = 2 + case ere.DMCDeathOnArrival: + data.Status = 3 + case ere.DMCDeath: + data.Status = 8 + case ere.DMCHomeReq: + data.Status = 7 + case ere.DMCConsulPoly: + data.Status = 5 + case ere.DMCExtRef: + data.Status = 6 + case ere.DMCConsulChDay: + data.Status = 12 + case ere.DMCEmergency: + data.Status = 10 + case ere.DMCEmergencyCovid: + data.Status = 13 + case ere.DMCConsulExecutive: + data.Status = 15 + case ere.DMCConsulBack: + data.Status = 100 + default: + data.Status = 0 + } +} + +func mapRelative(relative *[]epr.PersonRelative, data esimgos.TPendaftaran) { + if relative == nil || len(*relative) == 0 { + return + } + + for _, r := range *relative { + if r.Responsible { + data.PenanggungjawabNama = *r.Name + + switch r.Relationship_Code { + case erp.RCMother, erp.RCFather: + data.PenanggungjawabHubungan = "ORANG TUA" + case erp.RCChild: + data.PenanggungjawabHubungan = "ANAK" + case erp.RCSibling: + data.PenanggungjawabHubungan = "SAUDARA" + case erp.RCUncle, erp.RCAunt, + erp.RCGdMother, erp.RCGdFather, + erp.RCNephew, erp.RCGdChild: + data.PenanggungjawabHubungan = "KELUARGA LAIN" + case erp.RCFriend: + data.PenanggungjawabHubungan = "TEMAN" + case erp.RCSpouse: + data.PenanggungjawabHubungan = "SUAMI/ISTRI" + case erp.RCSelf: + data.PenanggungjawabHubungan = "DIRI SENDIRI" + default: + data.PenanggungjawabHubungan = "LAINNYA ..." + } + + data.PenanggungjawabAlamat = *r.Address + data.PenanggungjawabPhone = *r.PhoneNumber + + break + } + } +} + +func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.EncounterSimxLog) { // encode to JSON jsonData, _ := json.MarshalIndent(input.Payload, "", " ") jsonString := string(jsonData) @@ -67,7 +200,7 @@ func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.DivisionSimxLog) { return } -func setDataSimxLink(simxId, simgosId uint) (data esync.DivisionLink) { +func setDataSimxLink(simxId, simgosId uint) (data esync.EncounterLink) { data.Simx_Id = simxId data.Simgos_Id = simgosId return diff --git a/internal/use-case/simgos-sync-use-case/encounter/lib.go b/internal/use-case/simgos-sync-use-case/encounter/lib.go index f713ca6c..9ccf433c 100644 --- a/internal/use-case/simgos-sync-use-case/encounter/lib.go +++ b/internal/use-case/simgos-sync-use-case/encounter/lib.go @@ -9,15 +9,15 @@ import ( dg "github.com/karincake/apem/db-gorm-pg" "gorm.io/gorm" - e "simrs-vx/internal/domain/main-entities/division" - esimgos "simrs-vx/internal/domain/simgos-entities/division" - esync "simrs-vx/internal/domain/sync-entities/division" + e "simrs-vx/internal/domain/main-entities/encounter" + esimgos "simrs-vx/internal/domain/simgos-entities/encounter" + esync "simrs-vx/internal/domain/sync-entities/encounter" esynclog "simrs-vx/internal/domain/sync-entities/log" ) var now = time.Now() -func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esimgos.MUnit, error) { +func CreateSimgosData(input e.Encounter, event *pl.Event, dbx ...*gorm.DB) (*esimgos.TPendaftaran, error) { pl.SetLogInfo(event, nil, "started", "DBCreate") data := setDataSimgos(&input) @@ -37,14 +37,14 @@ func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esi return &data, nil } -func ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.MUnit, error) { +func ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.TPendaftaran, error) { pl.SetLogInfo(event, simgosId, "started", "DBReadDetail") - data := esimgos.MUnit{} + data := esimgos.TPendaftaran{} var tx = dg.IS["simrs"] if err := tx. - Where("\"kode_unit\" = ?", simgosId). + Where("\"idxdaftar\" = ?", simgosId). First(&data).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, simgosId, data); processedErr != nil { return nil, processedErr @@ -55,11 +55,11 @@ func ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.MUnit, err return &data, nil } -func UpdateSimgosData(input e.UpdateDto, dataSimgos *esync.DivisionLink, event *pl.Event, dbx ...*gorm.DB) error { +func UpdateSimgosData(input e.Encounter, dataSimgos *esync.EncounterLink, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, input, "started", "DBUpdate") data := setDataSimgos(&input) - data.KodeUnit = dataSimgos.Simgos_Id + data.Idxdaftar = dataSimgos.Simgos_Id var tx *gorm.DB if len(dbx) > 0 { @@ -82,7 +82,7 @@ func UpdateSimgosData(input e.UpdateDto, dataSimgos *esync.DivisionLink, event * return nil } -func HardDeleteSimgosData(data *esimgos.MUnit, event *pl.Event, dbx ...*gorm.DB) error { +func HardDeleteSimgosData(data *esimgos.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, data, "started", "DBDelete") var tx *gorm.DB @@ -107,7 +107,7 @@ func HardDeleteSimgosData(data *esimgos.MUnit, event *pl.Event, dbx ...*gorm.DB) return nil } -func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.DivisionLink, error) { +func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.EncounterLink, error) { pl.SetLogInfo(event, nil, "started", "DBCreate") data := setDataSimxLink(simxId, simgosId) @@ -126,9 +126,9 @@ func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*e return &data, nil } -func ReadDetailLinkData(simxId uint16, event *pl.Event) (*esync.DivisionLink, error) { +func ReadDetailLinkData(simxId uint16, event *pl.Event) (*esync.EncounterLink, error) { pl.SetLogInfo(event, simxId, "started", "DBReadDetail") - data := esync.DivisionLink{} + data := esync.EncounterLink{} var tx = dg.I @@ -144,7 +144,7 @@ func ReadDetailLinkData(simxId uint16, event *pl.Event) (*esync.DivisionLink, er return &data, nil } -func DeleteLinkData(data *esync.DivisionLink, event *pl.Event, dbx ...*gorm.DB) error { +func DeleteLinkData(data *esync.EncounterLink, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, data, "started", "DBDelete") var tx *gorm.DB From 0b0676214c097806009cab99bda8028fe584fcd5 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 21 Nov 2025 10:39:37 +0700 Subject: [PATCH 247/329] add vclaimreference --- .../migrations/20251121033803.sql | 14 +++++++ cmd/main-migration/migrations/atlas.sum | 5 ++- .../{vclaim-sep => vclaim-reference}/dto.go | 40 +++++++++---------- .../bpjs-entities/vclaim-reference/entity.go | 15 +++++++ .../domain/main-entities/encounter/entity.go | 11 +++-- internal/interface/migration/main-entities.go | 2 + 6 files changed, 61 insertions(+), 26 deletions(-) create mode 100644 cmd/main-migration/migrations/20251121033803.sql rename internal/domain/bpjs-entities/{vclaim-sep => vclaim-reference}/dto.go (51%) create mode 100644 internal/domain/bpjs-entities/vclaim-reference/entity.go diff --git a/cmd/main-migration/migrations/20251121033803.sql b/cmd/main-migration/migrations/20251121033803.sql new file mode 100644 index 00000000..48cb7f47 --- /dev/null +++ b/cmd/main-migration/migrations/20251121033803.sql @@ -0,0 +1,14 @@ +-- Create "VclaimReference" table +CREATE TABLE "public"."VclaimReference" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Date" timestamptz NULL, + "SrcCode" text NULL, + "SrcName" text NULL, + "Number" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Encounter_VclaimReference" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 0d9edc98..87b0571b 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:4U2KWXwY59v9g8NqCRfUlRU8S0gFHP+2zZo3VIYCy80= +h1:9o177sOy5hbZmLRLBxkW8WN1dveIe0pyAXoU84eeq0Y= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -126,4 +126,5 @@ h1:4U2KWXwY59v9g8NqCRfUlRU8S0gFHP+2zZo3VIYCy80= 20251119072302.sql h1:qCuI2WMEMF/XNbjV+RXPjBnuCKLu1Fia+mR9HiLWBIs= 20251119072450.sql h1:Xg+bTwqGyKPNFEQhJylvpz1wifdfmDJvcAq6vmNf0Ng= 20251120005512.sql h1:Ek6qpacAI/qVuTYxKno+uJyzn7s5z9pf3t7VA8gTzm4= -20251120074415.sql h1:4gmYBcmga1SBxRwrVaovGVvpRZFMV7vYzce0/IalryY= +20251120074415.sql h1:NNUeJVA03EeBHJhHqPXEZoDv/PnC6yK1/cRhmukyaJo= +20251121033803.sql h1:1s3DvgbqF+lh/or9X6WGN2lwnYCZkP8JH6uJFHql15g= diff --git a/internal/domain/bpjs-entities/vclaim-sep/dto.go b/internal/domain/bpjs-entities/vclaim-reference/dto.go similarity index 51% rename from internal/domain/bpjs-entities/vclaim-sep/dto.go rename to internal/domain/bpjs-entities/vclaim-reference/dto.go index 8a174688..027359a3 100644 --- a/internal/domain/bpjs-entities/vclaim-sep/dto.go +++ b/internal/domain/bpjs-entities/vclaim-reference/dto.go @@ -1,16 +1,16 @@ -package vclaimsep +package vclaimreference import ( ecore "simrs-vx/internal/domain/base-entities/core" - evsh "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-hist" + "time" ) type CreateDto struct { - Encounter_Id *uint `json:"encounter_id"` - Number *string `json:"number" validate:"maxLength=19"` - RequestPayload []byte `json:"requestPayload" validate:"maxLength=1024"` - - VclaimSepHist evsh.CreateDto + Encounter_Id *uint `json:"encounter_id"` + Date *time.Time `json:"date"` + SrcCode *string `json:"src_code"` + SrcName *string `json:"src_name"` + Number *string `json:"number"` } type ReadListDto struct { @@ -21,12 +21,11 @@ type ReadListDto struct { } type FilterDto struct { - Number *string `json:"number"` + Encounter_Id *uint `json:"encounter-id"` } type ReadDetailDto struct { - Id uint `json:"id"` - Number *string `json:"number"` + Id uint `json:"id"` } type UpdateDto struct { @@ -35,8 +34,7 @@ type UpdateDto struct { } type DeleteDto struct { - Id uint `json:"id"` - Number *string `json:"number"` + Id uint `json:"id"` } type MetaDto struct { @@ -47,27 +45,29 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Number *string `json:"number"` + Encounter_Id *uint `json:"encounter_id"` + Date *time.Time `json:"date"` + SrcCode *string `json:"src_code"` + SrcName *string `json:"src_name"` + Number *string `json:"number"` } -func (d VclaimSep) ToResponse() ResponseDto { +func (d VclaimReference) ToResponse() ResponseDto { resp := ResponseDto{ Encounter_Id: d.Encounter_Id, + Date: d.Date, + SrcCode: d.SrcCode, + SrcName: d.SrcName, Number: d.Number, } resp.Main = d.Main return resp } -func ToResponseList(data []VclaimSep) []ResponseDto { +func ToResponseList(data []VclaimReference) []ResponseDto { resp := make([]ResponseDto, len(data)) for i, u := range data { resp[i] = u.ToResponse() } return resp } - -func (c CreateDto) IsMessageSuccess() bool { - return c.VclaimSepHist.Message == "Sukses" -} diff --git a/internal/domain/bpjs-entities/vclaim-reference/entity.go b/internal/domain/bpjs-entities/vclaim-reference/entity.go new file mode 100644 index 00000000..a9a974d7 --- /dev/null +++ b/internal/domain/bpjs-entities/vclaim-reference/entity.go @@ -0,0 +1,15 @@ +package vclaimreference + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + "time" +) + +type VclaimReference struct { + ecore.Main + Encounter_Id *uint `json:"encounter_id"` + Date *time.Time `json:"date"` + SrcCode *string `json:"src_code"` + SrcName *string `json:"src_name"` + Number *string `json:"number"` +} diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index c188bb1a..61496f9e 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -1,7 +1,13 @@ package encounter import ( + "time" + + erc "simrs-vx/internal/domain/references/common" + ere "simrs-vx/internal/domain/references/encounter" + ecore "simrs-vx/internal/domain/base-entities/core" + evr "simrs-vx/internal/domain/bpjs-entities/vclaim-reference" evs "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" eam "simrs-vx/internal/domain/main-entities/ambulatory" ea "simrs-vx/internal/domain/main-entities/appointment" @@ -19,10 +25,6 @@ import ( es "simrs-vx/internal/domain/main-entities/specialist" ess "simrs-vx/internal/domain/main-entities/subspecialist" eu "simrs-vx/internal/domain/main-entities/unit" - - erc "simrs-vx/internal/domain/references/common" - ere "simrs-vx/internal/domain/references/encounter" - "time" ) type Encounter struct { @@ -74,6 +76,7 @@ type Encounter struct { RehabChildren *[]er.Basic `json:"rehabChildren,omitempty" gorm:"foreignKey:Parent_Encounter_Id;references:Id"` EncounterDocuments *[]eed.EncounterDocument `json:"encounterDocuments,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` GeneralConsents *[]egc.GeneralConsent `json:"generalConsents,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + VclaimReference *evr.VclaimReference `json:"vclaimReference,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` } func (d Encounter) IsDone() bool { diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index d55a5e27..0b4a62fd 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -103,6 +103,7 @@ import ( ///BPJS vclaimmember "simrs-vx/internal/domain/bpjs-entities/vclaim-member" + vclaimreference "simrs-vx/internal/domain/bpjs-entities/vclaim-reference" vclaimsep "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" vclaimsepcontrolletter "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-control-letter" vclaimsephist "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-hist" @@ -215,5 +216,6 @@ func getMainEntities() []any { &fileattachemnt.EncounterDocument{}, &vclaimsepcontrolletter.VclaimSepControlLetter{}, &resume.Resume{}, + &vclaimreference.VclaimReference{}, } } From c997c2472eb9107bb320917daea466320f272970 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 21 Nov 2025 20:21:28 +0700 Subject: [PATCH 248/329] add vclaim reference --- .../domain/main-entities/encounter/dto.go | 57 ++-- .../bpjs-use-case/vclaim-reference/case.go | 277 ++++++++++++++++++ .../bpjs-use-case/vclaim-reference/helper.go | 25 ++ .../bpjs-use-case/vclaim-reference/lib.go | 140 +++++++++ .../vclaim-reference/middleware-runner.go | 103 +++++++ .../vclaim-reference/middleware.go | 9 + .../bpjs-use-case/vclaim-reference/tycovar.go | 44 +++ .../simgos-sync-use-case/encounter/helper.go | 90 +++++- 8 files changed, 709 insertions(+), 36 deletions(-) create mode 100644 internal/use-case/bpjs-use-case/vclaim-reference/case.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-reference/helper.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-reference/lib.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-reference/middleware-runner.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-reference/middleware.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-reference/tycovar.go diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index f43a1de9..e2fe33ac 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -34,27 +34,28 @@ 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 erc.PaymentMethodCode `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"` + 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"` Id uint `json:"-"` RecentEncounterAdm *Encounter `json:"-"` // if subClass_Code is rehab @@ -63,6 +64,18 @@ type CreateDto struct { pa.AuthInfo } +type TRujukan struct { + NoSep string `json:"noSep"` + TglRujukan string `json:"tglRujukan"` + PpkDirujuk string `json:"ppkDirujuk"` + JnsPelayanan string `json:"jnsPelayanan"` + Catatan string `json:"catatan"` + DiagRujukan string `json:"diagRujukan"` + TipeRujukan string `json:"tipeRujukan"` + PoliRujukan string `json:"poliRujukan"` + User string `json:"user"` +} + type ReadListDto struct { FilterDto Includes string `json:"includes"` @@ -161,7 +174,7 @@ type ResponseDto struct { Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty"` Unit *eu.Unit `json:"unit,omitempty"` VisitDate time.Time `json:"visitDate"` - PaymentMethod_Code erc.PaymentMethodCode `json:"paymentMethod_code"` + PaymentMethod_Code ere.AllPaymentMethodCode `json:"paymentMethod_code"` InsuranceCompany_Code *string `json:"insuranceCompany_code"` Member_Number *string `json:"member_number"` Ref_Number *string `json:"ref_number"` diff --git a/internal/use-case/bpjs-use-case/vclaim-reference/case.go b/internal/use-case/bpjs-use-case/vclaim-reference/case.go new file mode 100644 index 00000000..bfbfea34 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-reference/case.go @@ -0,0 +1,277 @@ +package vclaimreference + +import ( + "strconv" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" + + e "simrs-vx/internal/domain/bpjs-entities/vclaim-reference" +) + +const source = "vclaim-reference" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.VclaimReference{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.VclaimReference + var dataList []e.VclaimReference + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.VclaimReference + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.VclaimReference + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.VclaimReference + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/bpjs-use-case/vclaim-reference/helper.go b/internal/use-case/bpjs-use-case/vclaim-reference/helper.go new file mode 100644 index 00000000..9127921f --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-reference/helper.go @@ -0,0 +1,25 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package vclaimreference + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-reference" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.VclaimReference) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Encounter_Id = inputSrc.Encounter_Id + data.Date = inputSrc.Date + data.SrcCode = inputSrc.SrcCode + data.SrcName = inputSrc.SrcName + data.Number = inputSrc.Number +} diff --git a/internal/use-case/bpjs-use-case/vclaim-reference/lib.go b/internal/use-case/bpjs-use-case/vclaim-reference/lib.go new file mode 100644 index 00000000..3f784edf --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-reference/lib.go @@ -0,0 +1,140 @@ +package vclaimreference + +import ( + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "github.com/AzureAD/microsoft-authentication-library-for-go/apps/errors" + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" + + e "simrs-vx/internal/domain/bpjs-entities/vclaim-reference" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.VclaimReference, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.VclaimReference{} + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.VclaimReference, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.VclaimReference{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.VclaimReference{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.VclaimReference, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.VclaimReference{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.First(&data, input.Id).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.VclaimReference, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.VclaimReference, 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 +} diff --git a/internal/use-case/bpjs-use-case/vclaim-reference/middleware-runner.go b/internal/use-case/bpjs-use-case/vclaim-reference/middleware-runner.go new file mode 100644 index 00000000..c8ad1e8f --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-reference/middleware-runner.go @@ -0,0 +1,103 @@ +package vclaimreference + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-reference" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.VclaimReference) 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.VclaimReference) 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.VclaimReference) 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.VclaimReference) 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.VclaimReference) 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/bpjs-use-case/vclaim-reference/middleware.go b/internal/use-case/bpjs-use-case/vclaim-reference/middleware.go new file mode 100644 index 00000000..defdfa84 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-reference/middleware.go @@ -0,0 +1,9 @@ +package vclaimreference + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/bpjs-use-case/vclaim-reference/tycovar.go b/internal/use-case/bpjs-use-case/vclaim-reference/tycovar.go new file mode 100644 index 00000000..29add547 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-reference/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 vclaimreference + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/bpjs-entities/vclaim-reference" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.VclaimReference, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.VclaimReference, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.VclaimReference, 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/encounter/helper.go b/internal/use-case/simgos-sync-use-case/encounter/helper.go index b9daa7de..586dbd81 100644 --- a/internal/use-case/simgos-sync-use-case/encounter/helper.go +++ b/internal/use-case/simgos-sync-use-case/encounter/helper.go @@ -17,9 +17,12 @@ import ( esimgos "simrs-vx/internal/domain/simgos-entities/encounter" 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/clause" ) -func setDataSimgos(input *e.Encounter) (data esimgos.TPendaftaran) { +func setDataCreate(input *e.Encounter) (data esimgos.TPendaftaran, err error) { data.Nomr = *input.Patient.Number data.Tglreg = input.RegisteredAt @@ -39,33 +42,28 @@ func setDataSimgos(input *e.Encounter) (data esimgos.TPendaftaran) { // TODO: shift - // set status - setStatus(input.Discharge_Method_Code, data) - if input.Status_Code == erc.DSCCancel { - data.Status = 11 - } - // set pasienbaru if input.NewStatus { data.Pasienbaru = 1 } + // set nip if emp := input.Adm_Employee; emp != nil { if user := emp.User; user != nil { data.Nip = user.Name } } - data.Masukpoly = input.StartedAt - data.Keluarpoly = input.FinishedAt - - if input.RefSource_Name != nil { - data.Ketrujuk = *input.RefSource_Name + if ref := input.VclaimReference; ref != nil { + data.Ketrujuk = *ref.SrcCode + data.Norujukan = *ref.Number + data.Tglrujukan = ref.Date + data.Strujukan = 1 } else { data.Ketrujuk = "TR" + data.Strujukan = 0 } - // TODO: preload person.relative, person.vclaimMember if p := input.Patient.Person; p != nil { mapRelative(p.Relatives, data) @@ -76,7 +74,54 @@ func setDataSimgos(input *e.Encounter) (data esimgos.TPendaftaran) { data.Jamreg = input.RegisteredAt - // TODO: norujukan, tglrujukan, dokumen_pendukung sep_file + // default kelas daftar + data.KelasDaftar = 3 + + // TODO: st_asal_masuk + + // set noAntrian + defaultFromSimx := "rehab" + data.NoAntrian = &defaultFromSimx + + // set no_kunjung + noKunjung, err := generateNoKunjung() + if err != nil { + return esimgos.TPendaftaran{}, err + } + + data.NoKunjung = uint(noKunjung) + + return +} + +func setDataUpdate(input *e.Encounter, data esimgos.TPendaftaran) { + // set kddokter + kddokter, _ := strconv.Atoi(*input.Responsible_Doctor_Code) + data.Kddokter = uint(kddokter) + + // set kdpoly + kdpoly, _ := strconv.Atoi(*input.Unit_Code) + data.Kdpoly = uint(kdpoly) + + // set status + setStatus(input.Discharge_Method_Code, data) + if input.Status_Code == erc.DSCCancel { + data.Status = 11 + } + + data.Masukpoly = input.StartedAt + data.Keluarpoly = input.FinishedAt + + if p := input.Patient.Person; p != nil { + mapRelative(p.Relatives, data) + } + + // set petugas_klinik + if emp := input.Adm_Employee; emp != nil { + if user := emp.User; user != nil { + data.PetugasKlinik = user.Name + } + } return } @@ -205,3 +250,20 @@ func setDataSimxLink(simxId, simgosId uint) (data esync.EncounterLink) { data.Simgos_Id = simgosId return } + +func generateNoKunjung() (int, error) { + var lastNumber int + + // Lock rows for this prefix → prevents race condition + if err := dg.IS["simrs"]. + Table("t_pendaftaran"). + Select("COALESCE(MAX(no_kunjung),0)"). + Where("tglreg = CURRENT_DATE"). + Order("no_kunjung DESC"). + Clauses(clause.Locking{Strength: "UPDATE"}). + Scan(&lastNumber).Error; err != nil { + return 0, err + } + + return lastNumber + 1, nil +} From a4032b5fbad908bbd15416e75c3f576f13957f37 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 21 Nov 2025 20:26:26 +0700 Subject: [PATCH 249/329] apply deleted sep dto --- .../domain/bpjs-entities/vclaim-sep/dto.go | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 internal/domain/bpjs-entities/vclaim-sep/dto.go diff --git a/internal/domain/bpjs-entities/vclaim-sep/dto.go b/internal/domain/bpjs-entities/vclaim-sep/dto.go new file mode 100644 index 00000000..8a174688 --- /dev/null +++ b/internal/domain/bpjs-entities/vclaim-sep/dto.go @@ -0,0 +1,73 @@ +package vclaimsep + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + evsh "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-hist" +) + +type CreateDto struct { + Encounter_Id *uint `json:"encounter_id"` + Number *string `json:"number" validate:"maxLength=19"` + RequestPayload []byte `json:"requestPayload" validate:"maxLength=1024"` + + VclaimSepHist evsh.CreateDto +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Sort string `json:"sort"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Number *string `json:"number"` +} + +type ReadDetailDto struct { + Id uint `json:"id"` + Number *string `json:"number"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` + Number *string `json:"number"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + Encounter_Id *uint `json:"encounter_id"` + Number *string `json:"number"` +} + +func (d VclaimSep) ToResponse() ResponseDto { + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Number: d.Number, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []VclaimSep) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} + +func (c CreateDto) IsMessageSuccess() bool { + return c.VclaimSepHist.Message == "Sukses" +} From 8051552d701ebd2e1558f465b532dff865b8df05 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Sun, 23 Nov 2025 18:37:28 +0700 Subject: [PATCH 250/329] feat/things-munaja: adjust employee - person --- internal/domain/main-entities/employee/dto.go | 29 +++++++++++-------- .../person-address/base/entity.go | 22 ++++++++++++++ .../main-entities/person-address/entity.go | 17 ++--------- .../person-contact/base/entity.go | 13 +++++++++ .../main-entities/person-contact/entity.go | 8 ++--- .../domain/main-entities/person/entity.go | 2 +- internal/domain/main-entities/soapi/dto.go | 2 +- .../references/organization/organization.go | 12 ++++---- internal/lib/auth/tycovar.go | 24 +++++++-------- 9 files changed, 77 insertions(+), 52 deletions(-) create mode 100644 internal/domain/main-entities/person-address/base/entity.go create mode 100644 internal/domain/main-entities/person-contact/base/entity.go diff --git a/internal/domain/main-entities/employee/dto.go b/internal/domain/main-entities/employee/dto.go index 85b7008a..5b2c674d 100644 --- a/internal/domain/main-entities/employee/dto.go +++ b/internal/domain/main-entities/employee/dto.go @@ -4,6 +4,7 @@ import ( ecore "simrs-vx/internal/domain/base-entities/core" ep "simrs-vx/internal/domain/main-entities/person" eu "simrs-vx/internal/domain/main-entities/user" + "time" erc "simrs-vx/internal/domain/references/common" erg "simrs-vx/internal/domain/references/organization" @@ -55,22 +56,26 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - User_Id *uint `json:"user_id"` - User *eu.User `json:"user,omitempty"` - Person_Id *uint `json:"person_id"` - Person *ep.Person `json:"person,omitempty"` - Number *string `json:"number"` - Status_Code erc.ActiveStatusCode `json:"status_code"` + User_Id *uint `json:"user_id"` + User *eu.User `json:"user,omitempty"` + Person_Id *uint `json:"person_id"` + Person *ep.Person `json:"person,omitempty"` + Number *string `json:"number"` + Position_Code *erg.EmployeePositionCode `json:"position_code"` + Contract_ExpiredDate *time.Time `json:"contract_expiredDate"` + Status_Code erc.ActiveStatusCode `json:"status_code"` } func (d Employee) ToResponse() ResponseDto { resp := ResponseDto{ - User_Id: d.User_Id, - User: d.User, - Person_Id: d.Person_Id, - Person: d.Person, - Number: d.Number, - Status_Code: d.Status_Code, + User_Id: d.User_Id, + User: d.User, + Person_Id: d.Person_Id, + Person: d.Person, + Number: d.Number, + Position_Code: d.Position_Code, + Contract_ExpiredDate: d.Contract_ExpiredDate, + Status_Code: d.Status_Code, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/person-address/base/entity.go b/internal/domain/main-entities/person-address/base/entity.go new file mode 100644 index 00000000..65d71912 --- /dev/null +++ b/internal/domain/main-entities/person-address/base/entity.go @@ -0,0 +1,22 @@ +package personaddress + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + epr "simrs-vx/internal/domain/main-entities/postal-region" + ev "simrs-vx/internal/domain/main-entities/village" + + erp "simrs-vx/internal/domain/references/person" +) + +type PersonAddress struct { + ecore.Main // adjust this according to the needs + Person_Id uint `json:"person_id"` + Address string `json:"address" gorm:"size:150"` + LocationType_Code erp.AddressLocationTypeCode `json:"locationType_code" gorm:"size:10"` + Rt string `json:"rt" gorm:"size:2"` + Rw string `json:"rw" gorm:"size:2"` + PostalRegion_Code *string `json:"postalRegion_code" gorm:"size:6"` + PostalRegion *epr.PostalRegion `json:"postalRegion,omitempty" gorm:"foreignKey:PostalRegion_Code;references:Code"` + Village_Code *string `json:"village_code" gorm:"size:10"` + Village *ev.Village `json:"village,omitempty" gorm:"foreignKey:Village_Code;references:Code"` +} diff --git a/internal/domain/main-entities/person-address/entity.go b/internal/domain/main-entities/person-address/entity.go index 65d71912..f53e2859 100644 --- a/internal/domain/main-entities/person-address/entity.go +++ b/internal/domain/main-entities/person-address/entity.go @@ -1,22 +1,9 @@ package personaddress import ( - ecore "simrs-vx/internal/domain/base-entities/core" - epr "simrs-vx/internal/domain/main-entities/postal-region" - ev "simrs-vx/internal/domain/main-entities/village" - - erp "simrs-vx/internal/domain/references/person" + eb "simrs-vx/internal/domain/main-entities/person-address/base" ) type PersonAddress struct { - ecore.Main // adjust this according to the needs - Person_Id uint `json:"person_id"` - Address string `json:"address" gorm:"size:150"` - LocationType_Code erp.AddressLocationTypeCode `json:"locationType_code" gorm:"size:10"` - Rt string `json:"rt" gorm:"size:2"` - Rw string `json:"rw" gorm:"size:2"` - PostalRegion_Code *string `json:"postalRegion_code" gorm:"size:6"` - PostalRegion *epr.PostalRegion `json:"postalRegion,omitempty" gorm:"foreignKey:PostalRegion_Code;references:Code"` - Village_Code *string `json:"village_code" gorm:"size:10"` - Village *ev.Village `json:"village,omitempty" gorm:"foreignKey:Village_Code;references:Code"` + eb.PersonAddress } diff --git a/internal/domain/main-entities/person-contact/base/entity.go b/internal/domain/main-entities/person-contact/base/entity.go new file mode 100644 index 00000000..b39aa53e --- /dev/null +++ b/internal/domain/main-entities/person-contact/base/entity.go @@ -0,0 +1,13 @@ +package personcontact + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + erp "simrs-vx/internal/domain/references/person" +) + +type PersonContact struct { + ecore.Main // adjust this according to the needs + Person_Id uint `json:"person_id"` + Type_Code erp.ContactTypeCode `json:"type_code" gorm:"size:15"` + Value string `json:"value" gorm:"size:100"` +} diff --git a/internal/domain/main-entities/person-contact/entity.go b/internal/domain/main-entities/person-contact/entity.go index b39aa53e..3ba257c4 100644 --- a/internal/domain/main-entities/person-contact/entity.go +++ b/internal/domain/main-entities/person-contact/entity.go @@ -1,13 +1,9 @@ package personcontact import ( - ecore "simrs-vx/internal/domain/base-entities/core" - erp "simrs-vx/internal/domain/references/person" + eb "simrs-vx/internal/domain/main-entities/person-contact/base" ) type PersonContact struct { - ecore.Main // adjust this according to the needs - Person_Id uint `json:"person_id"` - Type_Code erp.ContactTypeCode `json:"type_code" gorm:"size:15"` - Value string `json:"value" gorm:"size:100"` + eb.PersonContact } diff --git a/internal/domain/main-entities/person/entity.go b/internal/domain/main-entities/person/entity.go index d6e6744a..f36ec83a 100644 --- a/internal/domain/main-entities/person/entity.go +++ b/internal/domain/main-entities/person/entity.go @@ -34,7 +34,7 @@ type Person struct { Ocupation_Code *erp.OcupationCode `json:"occupation_code" gorm:"size:15"` Ocupation_Name *string `json:"occupation_name" gorm:"size:50"` MaritalStatus_Code *erp.MaritalStatusCode `json:"maritalStatus_code" gorm:"size:10"` - Nationality *string `json:"nationality": gorm:"size:50"` + Nationality *string `json:"nationality" gorm:"size:50"` Ethnic_Code *string `json:"ethnic_code" gorm:"size:20"` Ethnic *ee.Ethnic `json:"ethnic,omitempty" gorm:"foreignKey:Ethnic_Code;references:Code"` Language_Code *string `json:"language_code" gorm:"size:10"` diff --git a/internal/domain/main-entities/soapi/dto.go b/internal/domain/main-entities/soapi/dto.go index b8f1b827..3edc18e3 100644 --- a/internal/domain/main-entities/soapi/dto.go +++ b/internal/domain/main-entities/soapi/dto.go @@ -32,7 +32,7 @@ type FilterDto struct { Encounter_Id *uint `json:"encounter-id"` Employee_Id *uint `json:"employee-id"` Time *time.Time `json:"time"` - TypeCode erc.SoapiTypeCode `json:"typeCode"` + TypeCode erc.SoapiTypeCode `json:"type-code"` Value *string `json:"value"` } diff --git a/internal/domain/references/organization/organization.go b/internal/domain/references/organization/organization.go index 09b19dce..e12531cd 100644 --- a/internal/domain/references/organization/organization.go +++ b/internal/domain/references/organization/organization.go @@ -18,14 +18,16 @@ const ( EPCReg EmployeePositionCode = "reg" // Admisi/Pendaftaran EPCNur EmployeePositionCode = "nur" // Perawat EPCDoc EmployeePositionCode = "doc" // Dokter - EPCNut EmployeePositionCode = "nut" // Ahli gizi EPCMwi EmployeePositionCode = "miw" // Bidan + EPCThr EmployeePositionCode = "thr" // Terapis + EPCNut EmployeePositionCode = "nut" // Ahli gizi EPCLab EmployeePositionCode = "lab" // Laboran EPCPha EmployeePositionCode = "pha" // Farmasi - EPCPay EmployeePositionCode = "pay" // Pembayaran - EPCHur EmployeePositionCode = "hue" // Sumber Daya Manusia - EPCGea EmployeePositionCode = "gea" // Bagian Umum - EPCMan EmployeePositionCode = "man" // Manajemen + EPCNom EmployeePositionCode = "nom" // Non Medic + // EPCPay EmployeePositionCode = "pay" // Pembayaran + // EPCHur EmployeePositionCode = "hue" // Sumber Daya Manusia + // EPCGea EmployeePositionCode = "gea" // Bagian Umum + // EPCMan EmployeePositionCode = "man" // Manajemen IPCSpecialist = "specialist-intern" IPCNurse = "nurse-intern" diff --git a/internal/lib/auth/tycovar.go b/internal/lib/auth/tycovar.go index 70a6fec2..117d0c73 100644 --- a/internal/lib/auth/tycovar.go +++ b/internal/lib/auth/tycovar.go @@ -65,19 +65,19 @@ func (a AuthInfo) IsPharmacist() bool { return *a.Employee_Position_Code == string(ero.EPCPha) } -func (a AuthInfo) IsPayment() bool { - if a.Employee_Position_Code == nil { - return false - } - return *a.Employee_Position_Code == string(ero.EPCPay) -} +// func (a AuthInfo) IsPayment() bool { +// if a.Employee_Position_Code == nil { +// return false +// } +// return *a.Employee_Position_Code == string(ero.EPCPay) +// } -func (a AuthInfo) IsManagement() bool { - if a.Employee_Position_Code == nil { - return false - } - return *a.Employee_Position_Code == string(ero.EPCMan) -} +// func (a AuthInfo) IsManagement() bool { +// if a.Employee_Position_Code == nil { +// return false +// } +// return *a.Employee_Position_Code == string(ero.EPCMan) +// } func (a AuthInfo) IsSpecialistIntern() bool { if a.Intern_Position_Code == nil { From 8c53dfb0dec039a5c336a6b0ae1830170e8a805c Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Mon, 24 Nov 2025 05:08:26 +0700 Subject: [PATCH 251/329] feat/things-munaja: added unit on login --- internal/use-case/main-use-case/authentication/helper.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/use-case/main-use-case/authentication/helper.go b/internal/use-case/main-use-case/authentication/helper.go index c0a3bd0f..7af3afa5 100644 --- a/internal/use-case/main-use-case/authentication/helper.go +++ b/internal/use-case/main-use-case/authentication/helper.go @@ -226,6 +226,10 @@ func populateRoles(user *eu.User, input eu.LoginDto, atClaims jwt.MapClaims, out outputData["doctor_code"] = doctor.Code // specialist + if doctor.Unit_Code != nil { + atClaims["unit_code"] = doctor.Unit_Code + outputData["unit_code"] = doctor.Unit_Code + } if doctor.Specialist_Code != nil { atClaims["specialist_code"] = doctor.Specialist_Code outputData["specialist_code"] = doctor.Specialist_Code From 157ea603a471cce0ed83811674d23cb20ef9c1ff Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 24 Nov 2025 10:17:37 +0700 Subject: [PATCH 252/329] set checkin checkout --- .../domain/main-entities/encounter/dto.go | 4 + .../main-handler/encounter/handler.go | 33 ++- .../simgos-sync-handler/encounter/handler.go | 63 ++++++ .../simgos-sync-handler.go | 2 + .../use-case/main-use-case/encounter/case.go | 200 ++++++++++++------ .../main-use-case/encounter/helper.go | 2 +- .../encounter/middleware-runner.go | 36 ++++ .../main-use-case/encounter/middleware.go | 22 +- .../main-use-case/encounter/tycovar.go | 12 ++ .../simgos-sync-plugin/encounter/plugin.go | 167 +++++++++++++++ .../simgos-sync-use-case/encounter/case.go | 102 ++++++++- .../simgos-sync-use-case/encounter/helper.go | 118 +++++++---- .../simgos-sync-use-case/encounter/lib.go | 69 +++++- 13 files changed, 694 insertions(+), 136 deletions(-) create mode 100644 internal/interface/simgos-sync-handler/encounter/handler.go create mode 100644 internal/use-case/simgos-sync-plugin/encounter/plugin.go diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index e2fe33ac..849a5834 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -140,6 +140,8 @@ type DischargeDto struct { AdmDischargeEducation *string `json:"admDischargeEducation"` DischargeReason *string `json:"dischargeReason"` DeathCause *string `json:"deathCause"` + + pa.AuthInfo } type CheckinDto struct { @@ -148,6 +150,8 @@ type CheckinDto struct { Adm_Employee_Id *uint `json:"adm_employee_id"` StartedAt *time.Time `json:"startedAt"` FinishedAt *time.Time `json:"finishedAt"` + + pa.AuthInfo } type SwitchUnitDto struct { diff --git a/internal/interface/main-handler/encounter/handler.go b/internal/interface/main-handler/encounter/handler.go index c8fcfa1a..0c87b7b2 100644 --- a/internal/interface/main-handler/encounter/handler.go +++ b/internal/interface/main-handler/encounter/handler.go @@ -70,6 +70,11 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + id := rw.ValidateInt(w, "id", r.PathValue("id")) if id <= 0 { return @@ -80,29 +85,39 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { return } dto.Id = uint16(id) + dto.AuthInfo = *authInfo + 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 - } authInfo, err := pa.GetAuthInfo(r) if err != nil { rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) } + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.DeleteDto{} dto.Id = uint16(id) dto.AuthInfo = *authInfo + res, err := u.Delete(dto) rw.DataResponse(w, res, err) } func (obj myBase) CheckOut(w http.ResponseWriter, r *http.Request) { dto := e.DischargeDto{} + + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + id := rw.ValidateInt(w, "id", r.PathValue("id")) if id <= 0 { return @@ -118,12 +133,20 @@ func (obj myBase) CheckOut(w http.ResponseWriter, r *http.Request) { } dto.Id = uint(id) + dto.AuthInfo = *authInfo + res, err := u.CheckOut(dto) rw.DataResponse(w, res, err) } func (obj myBase) CheckIn(w http.ResponseWriter, r *http.Request) { dto := e.CheckinDto{} + + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + id := rw.ValidateInt(w, "id", r.PathValue("id")) if id <= 0 { return @@ -139,6 +162,8 @@ func (obj myBase) CheckIn(w http.ResponseWriter, r *http.Request) { } dto.Id = uint(id) + dto.AuthInfo = *authInfo + res, err := u.CheckIn(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/simgos-sync-handler/encounter/handler.go b/internal/interface/simgos-sync-handler/encounter/handler.go new file mode 100644 index 00000000..41ce9415 --- /dev/null +++ b/internal/interface/simgos-sync-handler/encounter/handler.go @@ -0,0 +1,63 @@ +package encounter + +import ( + "net/http" + + rw "github.com/karincake/risoles" + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/encounter" + esync "simrs-vx/internal/domain/sync-entities/log" + u "simrs-vx/internal/use-case/simgos-sync-use-case/encounter" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.Encounter{} + 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) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.Encounter{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint(id) + + 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 = uint16(id) + + res, err := u.Delete(dto) + 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 2a67b7e9..b5b65507 100644 --- a/internal/interface/simgos-sync-handler/simgos-sync-handler.go +++ b/internal/interface/simgos-sync-handler/simgos-sync-handler.go @@ -19,6 +19,7 @@ import ( /******************** internal ********************/ "simrs-vx/internal/interface/main-handler/home" division "simrs-vx/internal/interface/simgos-sync-handler/division" + encounter "simrs-vx/internal/interface/simgos-sync-handler/encounter" installation "simrs-vx/internal/interface/simgos-sync-handler/installation" patient "simrs-vx/internal/interface/simgos-sync-handler/patient" specialist "simrs-vx/internal/interface/simgos-sync-handler/specialist" @@ -47,6 +48,7 @@ func SetRoutes() http.Handler { hc.SyncCrud(r, prefix+"/v1/subspecialist", subspecialist.O) hc.SyncCrud(r, prefix+"/v1/patient", patient.O) r.HandleFunc(fmt.Sprintf("GET %s/v1/patient-nomr-generator", prefix), patient.O.GenerateNomr) + hc.SyncCrud(r, prefix+"/v1/encounter", encounter.O) return cmw.SetCors(handlerlogger.SetLog(r)) } diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 37e08bc5..45a85a00 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -3,6 +3,7 @@ package encounter import ( "errors" "fmt" + "simrs-vx/internal/lib/auth" "strconv" "time" @@ -17,6 +18,7 @@ import ( ere "simrs-vx/internal/domain/references/encounter" erg "simrs-vx/internal/domain/references/organization" + ev "simrs-vx/internal/domain/bpjs-entities/vclaim-reference" eaeh "simrs-vx/internal/domain/main-entities/adm-employee-hist" edc "simrs-vx/internal/domain/main-entities/death-cause" e "simrs-vx/internal/domain/main-entities/encounter" @@ -25,6 +27,7 @@ import ( es "simrs-vx/internal/domain/main-entities/soapi" esync "simrs-vx/internal/domain/sync-entities/log" + uv "simrs-vx/internal/use-case/bpjs-use-case/vclaim-reference" uaeh "simrs-vx/internal/use-case/main-use-case/adm-employee-hist" udc "simrs-vx/internal/use-case/main-use-case/death-cause" uir "simrs-vx/internal/use-case/main-use-case/internal-reference" @@ -51,28 +54,10 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - // check if user has employee position - if !input.AuthInfo.HasEmployeePosition() { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "auth-forbidden", - Detail: "user has no employee position", - Raw: errors.New("authentication failed"), - } - return nil, pl.SetLogError(&event, input) - } - - // check only user with registration position is allowed to create encounter - if input.AuthInfo.Employee_Position_Code != nil && *input.AuthInfo.Employee_Position_Code != string(erg.EPCReg) { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "auth-forbidden", - Detail: "user position is not allowed, only user with registration position is allowed to create encounter", - Raw: errors.New("authentication failed"), - } - return nil, pl.SetLogError(&event, input) - } else { - input.Adm_Employee_Id = input.AuthInfo.Employee_Id + roleAllowed := []string{string(erg.EPCReg)} + err = validateAuth(input.AuthInfo, roleAllowed, "create-encounter", &event) + if err != nil { + return nil, err } // validate rehab by bpjs @@ -90,6 +75,7 @@ func Create(input e.CreateDto) (*d.Data, error) { // If recentRehabData is not nil, determine the visitMode_Code: // If the mode is "series", verify whether the visit count still remains // and whether the series has not expired. + // If visitMode is "series", then get encounterAdm input.VisitMode_Code, input.RecentEncounterAdm, err = determineVisitMode(recentRehabData, input, &event) if err != nil { return nil, err @@ -110,6 +96,8 @@ func Create(input e.CreateDto) (*d.Data, error) { // check if patient is new in the hospital input.NewStatus, err = identifyPatientStatus(input) + input.Adm_Employee_Id = input.AuthInfo.Employee_Id + mwRunner := newMiddlewareRunner(&event) err = dg.I.Transaction(func(tx *gorm.DB) error { @@ -127,7 +115,19 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } - // insert adm_employee_hist + // insert vclaimReference + if vr := input.VclaimReference; vr != nil { + t, _ := time.Parse("2006-01-02", vr.TglRujukan) + + _, err = uv.CreateData(ev.CreateDto{ + Encounter_Id: &data.Id, + Date: &t, + SrcCode: input.Ref_Number, + SrcName: input.RefSource_Name, + Number: &vr.NoSep}, &event, tx) + } + + // insert adm_employee_hist (employee with role reg for create) if _, err = uaeh.CreateData(eaeh.CreateDto{ Encounter_Id: &data.Id, Employee_Id: data.Adm_Employee_Id, @@ -137,7 +137,7 @@ func Create(input e.CreateDto) (*d.Data, error) { dataEncounter, err := ReadDetailData(e.ReadDetailDto{ Id: uint16(data.Id), - Includes: "Adm_Employee.User,Patient.Person.Relatives,Patient.Person.VclaimMember"}, + Includes: "Adm_Employee.User,Patient.Person.Relatives,Patient.Person.VclaimMember,VclaimReference"}, &event, tx) if err != nil { return err @@ -280,6 +280,14 @@ func Update(input e.UpdateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "update") + + roleAllowed := []string{string(erg.EPCReg)} + err = validateAuth(input.AuthInfo, roleAllowed, "update-encounter", &event) + if err != nil { + return nil, err + } + input.Adm_Employee_Id = input.AuthInfo.Employee_Id + mwRunner := newMiddlewareRunner(&event) err = dg.I.Transaction(func(tx *gorm.DB) error { @@ -349,26 +357,10 @@ func Delete(input e.DeleteDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "delete") - // check if user has employee position - if !input.AuthInfo.HasEmployeePosition() { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "auth-forbidden", - Detail: "user has no employee position", - Raw: errors.New("authentication failed"), - } - return nil, pl.SetLogError(&event, input) - } - - // check only user with registration position is allowed to create encounter - if input.AuthInfo.Employee_Position_Code != nil && *input.AuthInfo.Employee_Position_Code != string(erg.EPCReg) { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "auth-forbidden", - Detail: "user position is not allowed, only user with registration position is allowed to create encounter", - Raw: errors.New("authentication failed"), - } - return nil, pl.SetLogError(&event, input) + roleAllowed := []string{string(erg.EPCReg)} + err = validateAuth(input.AuthInfo, roleAllowed, "delete-encounter", &event) + if err != nil { + return nil, err } mwRunner := newMiddlewareRunner(&event) @@ -379,6 +371,33 @@ func Delete(input e.DeleteDto) (*d.Data, error) { return err } + if data.IsDone() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-state-mismatch", + Detail: "encounter is done", + Raw: errors.New("encounter is done"), + } + return pl.SetLogError(&event, input) + } + + // Prevent delete if soapi exist + dataSoapi, _, err := us.ReadListData(es.ReadListDto{ + FilterDto: es.FilterDto{Encounter_Id: &data.Id}}, &event, tx) + if err != nil { + return err + } + + if len(dataSoapi) > 0 { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "cancel-not-allowed", + Detail: "encounter can't be deleted because SOAPI already exists", + Raw: errors.New("encounter has SOAPI records"), + } + return pl.SetLogError(&event, input) + } + if err := DeleteData(data, &event, tx); err != nil { return err } @@ -422,6 +441,14 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "checkOut") + roleAllowed := []string{string(erg.EPCNur), string(erg.EPCDoc)} + err = validateAuth(input.AuthInfo, roleAllowed, "checkOut-encounter", &event) + if err != nil { + return nil, err + } + + mwRunner := newMiddlewareRunner(&event) + err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") if data, err = ReadDetailData(rdDto, &event, tx); err != nil { @@ -445,7 +472,7 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) { } if data.Ambulatory.Class_Code == ere.ACCRehab { - // verify and update rehabData if visit count has reached the allowed limit + // verify and update rehabData to DONE if visit count has reached the allowed limit if err = verifyRehabLimit(data, &event, tx); err != nil { return err } @@ -488,15 +515,21 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) { } } - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCheckoutMiddleware(checkoutEncounter, &input); err != nil { + return err + } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -568,11 +601,8 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) { } // Prevent cancellation if soapi exist - encounterId := uint(input.Id) dataSoapi, _, err := us.ReadListData(es.ReadListDto{ - FilterDto: es.FilterDto{ - Encounter_Id: &encounterId, - }}, &event, tx) + FilterDto: es.FilterDto{Encounter_Id: &data.Id}}, &event, tx) if err != nil { return err } @@ -588,25 +618,12 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) { } } - //mwRunner := newMiddlewareRunner(&event) - //mwRunner.setMwType(pu.MWTPre) - //// Run pre-middleware - //if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { - // return err - //} - if err := UpdateStatusData(input, data, &event, tx); err != nil { return err } pl.SetLogInfo(&event, nil, "complete") - //mwRunner.setMwType(pu.MWTPost) - //// Run post-middleware - //if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { - // return err - //} - return nil }) @@ -638,6 +655,13 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "checkIn") + roleAllowed := []string{string(erg.EPCNur), string(erg.EPCDoc)} + err = validateAuth(input.AuthInfo, roleAllowed, "checkIn-encounter", &event) + if err != nil { + return nil, err + } + input.Adm_Employee_Id = input.AuthInfo.Employee_Id + // validate foreign key if err := validateForeignKey(input); err != nil { return nil, err @@ -648,6 +672,8 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { input.StartedAt = &now } + mwRunner := newMiddlewareRunner(&event) + err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") if data, err = ReadDetailData(rdDto, &event, tx); err != nil { @@ -685,7 +711,7 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { } // Upsert adm_employee_hist if adm_employee_id has changed - if input.Adm_Employee_Id != nil && *input.Adm_Employee_Id != *data.Adm_Employee_Id { + if *input.Adm_Employee_Id != *data.Adm_Employee_Id { // upsert admEmployeeHist if err = upsertAdmEmployeeHist(eaeh.CreateDto{ Encounter_Id: &data.Id, @@ -701,15 +727,29 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { return err } - pl.SetLogInfo(&event, nil, "complete") + dataEncounter, err := ReadDetailData(e.ReadDetailDto{ + Id: uint16(data.Id), + Includes: "Adm_Employee.User"}, + &event, tx) + if err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCheckinMiddleware(checkinEncounterMw, dataEncounter); err != nil { + return err + } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -951,3 +991,29 @@ func runLogMiddleware(err error, input any, mwRunner *middlewareRunner) error { return nil } + +func validateAuth(a auth.AuthInfo, roleAllowed []string, action string, event *pl.Event) error { + // check if user has employee position + if !a.HasEmployeePosition() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "auth-forbidden", + Detail: "missing employee position", + Raw: errors.New("authentication failed"), + } + return pl.SetLogError(event, a) + } + + // check only roleAllowed position is allowed to create encounter + if a.Employee_Position_Code != nil && !pu.Contains(roleAllowed, *a.Employee_Position_Code) { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "auth-forbidden", + Detail: fmt.Sprintf("position '%s' is not allowed to %s", *a.Employee_Position_Code, action), + Raw: errors.New("authentication failed"), + } + return pl.SetLogError(event, a) + } + + return nil +} diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index 1de331b8..3b215c36 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -617,7 +617,7 @@ func getSoapiByTypeCode(encounter *e.Encounter, event *pl.Event, mode string) (e rehab = encounter.Rehab ) - // Set Query for get data Soapi + // Set Query for get data Soapi by doc tx := dg.I. Model(&es.Soapi{}). Joins("JOIN \"Employee\" ON \"Employee\".\"Id\" = \"Soapi\".\"Employee_Id\""). 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 b030d286..78558cd0 100644 --- a/internal/use-case/main-use-case/encounter/middleware-runner.go +++ b/internal/use-case/main-use-case/encounter/middleware-runner.go @@ -143,6 +143,42 @@ func (me *middlewareRunner) RunDeleteMiddleware(middlewares []deleteMw, input *e return nil } +func (me *middlewareRunner) RunCheckinMiddleware(middleware checkinMw, input *e.Encounter) error { + if !me.SyncOn { + return nil + } + + 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) + } + + pl.SetLogInfo(me.Event, nil, "complete") + + return nil +} + +func (me *middlewareRunner) RunCheckoutMiddleware(middleware checkoutMw, input *e.DischargeDto) error { + if !me.SyncOn { + return nil + } + + 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) + } + + pl.SetLogInfo(me.Event, nil, "complete") + + return nil +} + func (me *middlewareRunner) setMwType(mwType pu.MWType) { me.MwType = mwType } diff --git a/internal/use-case/main-use-case/encounter/middleware.go b/internal/use-case/main-use-case/encounter/middleware.go index 8a047d33..bb5fab3f 100644 --- a/internal/use-case/main-use-case/encounter/middleware.go +++ b/internal/use-case/main-use-case/encounter/middleware.go @@ -1,9 +1,17 @@ package encounter -// 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/encounter" + +func init() { + createPreMw = append(createPreMw, + createMw{Name: "sync-update-encounter", Func: plugin.Create}) + + createSimxLogMw = append(createSimxLogMw, + createLogMw{Name: "create-sync-log", Func: plugin.CreateLog}) + + updatePreMw = append(updatePreMw, + updateMw{Name: "sync-update-patient", Func: plugin.Update}) + + deletePreMw = append(deletePreMw, + deleteMw{Name: "sync-delete-patient", Func: plugin.Delete}) +} diff --git a/internal/use-case/main-use-case/encounter/tycovar.go b/internal/use-case/main-use-case/encounter/tycovar.go index f618bd19..f2309211 100644 --- a/internal/use-case/main-use-case/encounter/tycovar.go +++ b/internal/use-case/main-use-case/encounter/tycovar.go @@ -44,6 +44,16 @@ type readDetailMw struct { Func func(input *e.ReadDetailDto, data *e.Encounter, tx *gorm.DB) error } +type checkinMw struct { + Name string + Func func(input *e.Encounter) error +} + +type checkoutMw struct { + Name string + Func func(input *e.DischargeDto) error +} + type UpdateMw = updateMw type DeleteMw = deleteMw @@ -58,3 +68,5 @@ var updatePreMw []updateMw var updatePostMw []readDetailMw var deletePreMw []deleteMw var deletePostMw []readDetailMw +var checkinEncounterMw checkinMw +var checkoutEncounter checkoutMw diff --git a/internal/use-case/simgos-sync-plugin/encounter/plugin.go b/internal/use-case/simgos-sync-plugin/encounter/plugin.go new file mode 100644 index 00000000..70d3e8be --- /dev/null +++ b/internal/use-case/simgos-sync-plugin/encounter/plugin.go @@ -0,0 +1,167 @@ +package encounter + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + + d "github.com/karincake/dodol" + + sync "simrs-vx/internal/infra/sync-cfg" + + e "simrs-vx/internal/domain/main-entities/encounter" + elog "simrs-vx/internal/domain/sync-entities/log" +) + +func Create(input *e.Encounter) 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 +} + +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 +} + +func Update(input *e.Encounter) 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 +} + +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 +} + +func getPrefixEndpoint() string { + return fmt.Sprintf("%s%s/v1/encounter", sync.O.Host, sync.O.Prefix) +} diff --git a/internal/use-case/simgos-sync-use-case/encounter/case.go b/internal/use-case/simgos-sync-use-case/encounter/case.go index 591dae36..50a822ed 100644 --- a/internal/use-case/simgos-sync-use-case/encounter/case.go +++ b/internal/use-case/simgos-sync-use-case/encounter/case.go @@ -33,7 +33,7 @@ func Create(input e.Encounter) (*d.Data, error) { err = db.WithDualTx(func(tx *db.Dualtx) error { // STEP 1: Insert to simgos - sgData, err = CreateSimgosData(input, &event, tx.Simgos) + sgData, err = CreateTPendaftaranData(input, &event, tx.Simgos) if err != nil { return err } @@ -114,10 +114,16 @@ func Update(input e.Encounter) (*d.Data, error) { return nil, err } + // STEP 2: Get Simgos + simgos, err := ReadEncounterDetailData(uint16(syncLink.Simgos_Id), &event) + if err != nil { + return nil, err + } + tx := db.NewTx() err = tx.Simgos.Transaction(func(tx *gorm.DB) error { // Step 2: Update Simgos - if err = UpdateSimgosData(input, syncLink, &event, tx); err != nil { + if err = UpdateTPendaftaranData(input, *simgos, &event, tx); err != nil { return err } @@ -153,14 +159,14 @@ func Delete(input e.DeleteDto) (*d.Data, error) { } // STEP 2: Get Simgos - sgData, err := ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) + sgData, err := ReadEncounterDetailData(uint16(syncLink.Simgos_Id), &event) if err != nil { return nil, err } err = db.WithDualTx(func(tx *db.Dualtx) error { // STEP 3: Delete Simgos - err = HardDeleteSimgosData(sgData, &event, tx.Simgos) + err = HardDeleteTPendaftaranData(sgData, &event, tx.Simgos) if err != nil { return err } @@ -195,3 +201,91 @@ func Delete(input e.DeleteDto) (*d.Data, error) { }, nil } + +func CheckIn(input e.Encounter) (*d.Data, error) { + event := pl.Event{ + Feature: "CheckIn", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "check-in") + + // STEP 1: Get Link + syncLink, err := ReadDetailLinkData(uint16(input.Id), &event) + if err != nil { + return nil, err + } + + // STEP 2: Get Simgos + simgos, err := ReadEncounterDetailData(uint16(syncLink.Simgos_Id), &event) + if err != nil { + return nil, err + } + + tx := db.NewTx() + err = tx.Simgos.Transaction(func(tx *gorm.DB) error { + // Step 2: Update Simgos + if err = UpdateCheckinData(input, *simgos, &event, tx); err != nil { + return err + } + + // TODO: insert t_pemeriksaan_hist + + return nil + }) + + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + }, nil +} + +func CheckOut(input e.DischargeDto) (*d.Data, error) { + event := pl.Event{ + Feature: "CheckIn", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "check-in") + + // STEP 1: Get Link + syncLink, err := ReadDetailLinkData(uint16(input.Id), &event) + if err != nil { + return nil, err + } + + // STEP 2: Get Simgos + simgos, err := ReadEncounterDetailData(uint16(syncLink.Simgos_Id), &event) + if err != nil { + return nil, err + } + + tx := db.NewTx() + err = tx.Simgos.Transaction(func(tx *gorm.DB) error { + // Step 2: Update Simgos + if err = UpdateCheckoutData(input, *simgos, &event, tx); err != nil { + return err + } + + // TODO: insert t_pemeriksaan_hist + + return nil + }) + + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + }, nil +} diff --git a/internal/use-case/simgos-sync-use-case/encounter/helper.go b/internal/use-case/simgos-sync-use-case/encounter/helper.go index 586dbd81..4672daa5 100644 --- a/internal/use-case/simgos-sync-use-case/encounter/helper.go +++ b/internal/use-case/simgos-sync-use-case/encounter/helper.go @@ -7,11 +7,10 @@ package encounter import ( "encoding/json" epr "simrs-vx/internal/domain/main-entities/person-relative" - erp "simrs-vx/internal/domain/references/person" - "strconv" - erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" + erp "simrs-vx/internal/domain/references/person" + "strconv" e "simrs-vx/internal/domain/main-entities/encounter" esimgos "simrs-vx/internal/domain/simgos-entities/encounter" @@ -22,17 +21,47 @@ import ( "gorm.io/gorm/clause" ) -func setDataCreate(input *e.Encounter) (data esimgos.TPendaftaran, err error) { +func setDataCreateTPendaftaran(input *e.Encounter) (data esimgos.TPendaftaran, err error) { data.Nomr = *input.Patient.Number + + // set pasienbaru + if input.NewStatus { + data.Pasienbaru = 1 + } + + // default kelas daftar + data.KelasDaftar = 3 + + // set noAntrian + defaultFromSimx := "rehab" + data.NoAntrian = &defaultFromSimx + + // set no_kunjung + noKunjung, err := generateNoKunjung() + if err != nil { + return esimgos.TPendaftaran{}, err + } + data.NoKunjung = uint(noKunjung) + + setDataTPendaftaran(input, data) + + return +} + +func setDataTPendaftaran(input *e.Encounter, data esimgos.TPendaftaran) { data.Tglreg = input.RegisteredAt // set kddokter - kddokter, _ := strconv.Atoi(*input.Appointment_Doctor_Code) - data.Kddokter = uint(kddokter) + if d := input.Appointment_Doctor_Code; d != nil { + kddokter, _ := strconv.Atoi(*input.Appointment_Doctor_Code) + data.Kddokter = uint(kddokter) + } // set kdpoly - kdpoly, _ := strconv.Atoi(*input.Unit_Code) - data.Kdpoly = uint(kdpoly) + if p := input.Unit_Code; p != nil { + kdpoly, _ := strconv.Atoi(*input.Unit_Code) + data.Kdpoly = uint(kdpoly) + } // set kdrujuk setKdrujuk(input.RefType_Code, data) @@ -42,11 +71,6 @@ func setDataCreate(input *e.Encounter) (data esimgos.TPendaftaran, err error) { // TODO: shift - // set pasienbaru - if input.NewStatus { - data.Pasienbaru = 1 - } - // set nip if emp := input.Adm_Employee; emp != nil { if user := emp.User; user != nil { @@ -74,54 +98,40 @@ func setDataCreate(input *e.Encounter) (data esimgos.TPendaftaran, err error) { data.Jamreg = input.RegisteredAt - // default kelas daftar - data.KelasDaftar = 3 - // TODO: st_asal_masuk - // set noAntrian - defaultFromSimx := "rehab" - data.NoAntrian = &defaultFromSimx - - // set no_kunjung - noKunjung, err := generateNoKunjung() - if err != nil { - return esimgos.TPendaftaran{}, err - } - - data.NoKunjung = uint(noKunjung) - return } -func setDataUpdate(input *e.Encounter, data esimgos.TPendaftaran) { +func setDataCheckIn(input e.Encounter, data esimgos.TPendaftaran) { // set kddokter kddokter, _ := strconv.Atoi(*input.Responsible_Doctor_Code) data.Kddokter = uint(kddokter) - // set kdpoly - kdpoly, _ := strconv.Atoi(*input.Unit_Code) - data.Kdpoly = uint(kdpoly) - - // set status - setStatus(input.Discharge_Method_Code, data) - if input.Status_Code == erc.DSCCancel { - data.Status = 11 + // set petugas_klinik + if data.PetugasKlinik != "" { + if a := input.Adm_Employee; a != nil { + if u := a.User; u != nil { + data.PetugasKlinik = u.Name + } + } } data.Masukpoly = input.StartedAt - data.Keluarpoly = input.FinishedAt + return +} - if p := input.Patient.Person; p != nil { - mapRelative(p.Relatives, data) - } +func setDataCheckOut(input e.DischargeDto, data esimgos.TPendaftaran) { + data.Keluarpoly = &now - // set petugas_klinik - if emp := input.Adm_Employee; emp != nil { - if user := emp.User; user != nil { - data.PetugasKlinik = user.Name - } + // set status + setStatus(input.Discharge_Method_Code, data) + if data.Status == 8 || data.Status == 3 { + data.SebabMati1 = input.DeathCause } + //if input.Status_Code == erc.DSCCancel { + // data.Status = 11 + //} return } @@ -162,18 +172,34 @@ func setStatus(code *ere.DischargeMethodCode, data esimgos.TPendaftaran) { data.Status = 2 case ere.DMCDeathOnArrival: data.Status = 3 + data.StMeninggal = func(u uint) *uint { return &u }(1) + data.DtMeninggal = &now case ere.DMCDeath: data.Status = 8 + data.StMeninggal = func(u uint) *uint { return &u }(1) + data.DtMeninggal = &now case ere.DMCHomeReq: data.Status = 7 case ere.DMCConsulPoly: data.Status = 5 + data.PoliNameHfis = nil + data.SpesialisIdHfis = nil + data.DokterNameHfis = nil + data.DokterIdHfis = nil case ere.DMCExtRef: data.Status = 6 case ere.DMCConsulChDay: data.Status = 12 + data.PoliNameHfis = nil + data.SpesialisIdHfis = nil + data.DokterNameHfis = nil + data.DokterIdHfis = nil case ere.DMCEmergency: data.Status = 10 + data.PoliNameHfis = nil + data.SpesialisIdHfis = nil + data.DokterNameHfis = nil + data.DokterIdHfis = nil case ere.DMCEmergencyCovid: data.Status = 13 case ere.DMCConsulExecutive: diff --git a/internal/use-case/simgos-sync-use-case/encounter/lib.go b/internal/use-case/simgos-sync-use-case/encounter/lib.go index 9ccf433c..f4c0023f 100644 --- a/internal/use-case/simgos-sync-use-case/encounter/lib.go +++ b/internal/use-case/simgos-sync-use-case/encounter/lib.go @@ -17,10 +17,13 @@ import ( var now = time.Now() -func CreateSimgosData(input e.Encounter, event *pl.Event, dbx ...*gorm.DB) (*esimgos.TPendaftaran, error) { +func CreateTPendaftaranData(input e.Encounter, event *pl.Event, dbx ...*gorm.DB) (*esimgos.TPendaftaran, error) { pl.SetLogInfo(event, nil, "started", "DBCreate") - data := setDataSimgos(&input) + data, err := setDataCreateTPendaftaran(&input) + if err != nil { + return nil, plh.HandleCreateError(input, event, err) + } var tx *gorm.DB if len(dbx) > 0 { @@ -37,7 +40,7 @@ func CreateSimgosData(input e.Encounter, event *pl.Event, dbx ...*gorm.DB) (*esi return &data, nil } -func ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.TPendaftaran, error) { +func ReadEncounterDetailData(simgosId uint16, event *pl.Event) (*esimgos.TPendaftaran, error) { pl.SetLogInfo(event, simgosId, "started", "DBReadDetail") data := esimgos.TPendaftaran{} @@ -55,11 +58,10 @@ func ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.TPendaftar return &data, nil } -func UpdateSimgosData(input e.Encounter, dataSimgos *esync.EncounterLink, event *pl.Event, dbx ...*gorm.DB) error { +func UpdateTPendaftaranData(input e.Encounter, data esimgos.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, input, "started", "DBUpdate") - data := setDataSimgos(&input) - data.Idxdaftar = dataSimgos.Simgos_Id + setDataTPendaftaran(&input, data) var tx *gorm.DB if len(dbx) > 0 { @@ -82,7 +84,7 @@ func UpdateSimgosData(input e.Encounter, dataSimgos *esync.EncounterLink, event return nil } -func HardDeleteSimgosData(data *esimgos.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) error { +func HardDeleteTPendaftaranData(data *esimgos.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, data, "started", "DBDelete") var tx *gorm.DB @@ -107,6 +109,59 @@ func HardDeleteSimgosData(data *esimgos.TPendaftaran, event *pl.Event, dbx ...*g return nil } +func UpdateCheckinData(input e.Encounter, data esimgos.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, input, "started", "DBUpdate") + + setDataCheckIn(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 UpdateCheckoutData(input e.DischargeDto, data esimgos.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, input, "started", "DBUpdate") + + setDataCheckOut(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 CreateTPemeriksaanHist func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.EncounterLink, error) { pl.SetLogInfo(event, nil, "started", "DBCreate") data := setDataSimxLink(simxId, simgosId) From f4768490fb5c377df60464b8e1678a7ebec9a1b5 Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 24 Nov 2025 10:36:57 +0700 Subject: [PATCH 253/329] add t_pemeriksaan_entity --- .../{installation => m_instalasi}/entity.go | 2 +- .../{patient => m_pasien}/entity.go | 2 +- .../{specialist => m_polihfis}/entity.go | 0 .../{unit => m_poly}/entity.go | 6 ++--- .../{division => m_unit}/entity.go | 2 +- .../t_pemeriksaan_hist/entity.go | 27 +++++++++++++++++++ .../{encounter => t_pendaftaran}/entity.go | 2 +- 7 files changed, 34 insertions(+), 7 deletions(-) rename internal/domain/simgos-entities/{installation => m_instalasi}/entity.go (95%) rename internal/domain/simgos-entities/{patient => m_pasien}/entity.go (99%) rename internal/domain/simgos-entities/{specialist => m_polihfis}/entity.go (100%) rename internal/domain/simgos-entities/{unit => m_poly}/entity.go (75%) rename internal/domain/simgos-entities/{division => m_unit}/entity.go (98%) create mode 100644 internal/domain/simgos-entities/t_pemeriksaan_hist/entity.go rename internal/domain/simgos-entities/{encounter => t_pendaftaran}/entity.go (99%) diff --git a/internal/domain/simgos-entities/installation/entity.go b/internal/domain/simgos-entities/m_instalasi/entity.go similarity index 95% rename from internal/domain/simgos-entities/installation/entity.go rename to internal/domain/simgos-entities/m_instalasi/entity.go index f2b291f5..bbeb3ed7 100644 --- a/internal/domain/simgos-entities/installation/entity.go +++ b/internal/domain/simgos-entities/m_instalasi/entity.go @@ -1,4 +1,4 @@ -package installation +package m_instalasi type MInstalasi struct { No_Instalasi uint `json:"no_instalasi" gorm:"primaryKey;autoIncrement;column:no_instalasi"` diff --git a/internal/domain/simgos-entities/patient/entity.go b/internal/domain/simgos-entities/m_pasien/entity.go similarity index 99% rename from internal/domain/simgos-entities/patient/entity.go rename to internal/domain/simgos-entities/m_pasien/entity.go index 20b7fee6..dce1abbf 100644 --- a/internal/domain/simgos-entities/patient/entity.go +++ b/internal/domain/simgos-entities/m_pasien/entity.go @@ -1,4 +1,4 @@ -package patient +package m_pasien import "time" diff --git a/internal/domain/simgos-entities/specialist/entity.go b/internal/domain/simgos-entities/m_polihfis/entity.go similarity index 100% rename from internal/domain/simgos-entities/specialist/entity.go rename to internal/domain/simgos-entities/m_polihfis/entity.go diff --git a/internal/domain/simgos-entities/unit/entity.go b/internal/domain/simgos-entities/m_poly/entity.go similarity index 75% rename from internal/domain/simgos-entities/unit/entity.go rename to internal/domain/simgos-entities/m_poly/entity.go index 20fa0000..52fe20eb 100644 --- a/internal/domain/simgos-entities/unit/entity.go +++ b/internal/domain/simgos-entities/m_poly/entity.go @@ -1,11 +1,11 @@ -package unit +package m_poly -type MPloy struct { +type MPoly struct { Kode uint `json:"kode" gorm:"primaryKey;autoIncrement;column:kode"` Nama string `json:"nama" gorm:"column:nama"` Jenispoly uint `json:"jenispoly" gorm:"column:jenispoly"` } -func (MPloy) TableName() string { +func (MPoly) TableName() string { return "m_poly" } diff --git a/internal/domain/simgos-entities/division/entity.go b/internal/domain/simgos-entities/m_unit/entity.go similarity index 98% rename from internal/domain/simgos-entities/division/entity.go rename to internal/domain/simgos-entities/m_unit/entity.go index 0cc38494..3d67d8fd 100644 --- a/internal/domain/simgos-entities/division/entity.go +++ b/internal/domain/simgos-entities/m_unit/entity.go @@ -1,4 +1,4 @@ -package division +package m_unit type MUnit struct { KodeUnit uint `json:"kode_unit" gorm:"primaryKey;autoIncrement;column:kode_unit"` diff --git a/internal/domain/simgos-entities/t_pemeriksaan_hist/entity.go b/internal/domain/simgos-entities/t_pemeriksaan_hist/entity.go new file mode 100644 index 00000000..cfb0dda6 --- /dev/null +++ b/internal/domain/simgos-entities/t_pemeriksaan_hist/entity.go @@ -0,0 +1,27 @@ +package t_pemeriksaan_hist + +import "time" + +type TPemeriksaanHist struct { + IdPemeriksaanHist uint `json:"id_pemeriksaanhist" gorm:"primaryKey;column:id_pemeriksaanhist"` + Idxdaftar *uint `json:"idxdaftar" gorm:"column:idxdaftar"` + Kdpoly *uint `json:"kdpoly" gorm:"column:kdpoly"` + DokterPengonsul *uint `json:"dokter_pengonsul" gorm:"column:dokter_pengonsul"` + DokterPenerima *uint `json:"dokter_penerima" gorm:"column:dokter_penerima"` + StartKonsul *time.Time `json:"start_konsul" gorm:"column:start_konsul"` + EndKonsul *time.Time `json:"end_konsul" gorm:"column:end_konsul"` + UserKonsul *string `json:"user_konsul" gorm:"column:user_konsul;size:100"` + TglEntriKonsul *time.Time `json:"tgl_entri_konsul" gorm:"column:tgl_entri_konsul"` + IP *string `json:"ip" gorm:"column:ip;size:50"` + UserPenerima *string `json:"user_penerima" gorm:"column:user_penerima;size:100"` + MasukPoly *time.Time `json:"masuk_poly" gorm:"column:masuk_poly"` + PerawatPenerima *uint `json:"perawat_penerima" gorm:"column:perawat_penerima"` + StAktif *uint16 `json:"st_aktif" gorm:"column:st_aktif"` + UserBatal *string `json:"user_batal" gorm:"column:user_batal;size:100"` + TglBatal *time.Time `json:"tgl_batal" gorm:"column:tgl_batal"` + IdxBillRajal *uint `json:"idxbillrajal" gorm:"column:idxbillrajal"` +} + +func (TPemeriksaanHist) TableName() string { + return "t_pemeriksaan_hist" +} diff --git a/internal/domain/simgos-entities/encounter/entity.go b/internal/domain/simgos-entities/t_pendaftaran/entity.go similarity index 99% rename from internal/domain/simgos-entities/encounter/entity.go rename to internal/domain/simgos-entities/t_pendaftaran/entity.go index 16ba873e..0a510311 100644 --- a/internal/domain/simgos-entities/encounter/entity.go +++ b/internal/domain/simgos-entities/t_pendaftaran/entity.go @@ -1,4 +1,4 @@ -package encounter +package t_pendaftaran import "time" From 6d51f9587574b1411c81d169ae89025ec2cf5863 Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 24 Nov 2025 10:50:00 +0700 Subject: [PATCH 254/329] rename entity simgos --- .../domain/simgos-entities/{m_instalasi => m-instalasi}/entity.go | 0 internal/domain/simgos-entities/{m_pasien => m-pasien}/entity.go | 0 .../domain/simgos-entities/{m_polihfis => m-polihfis}/entity.go | 0 internal/domain/simgos-entities/{m_poly => m-poly}/entity.go | 0 internal/domain/simgos-entities/{m_unit => m-unit}/entity.go | 0 .../{t_pemeriksaan_hist => t-pemeriksaan-hist}/entity.go | 0 .../simgos-entities/{t_pendaftaran => t-pendaftaran}/entity.go | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename internal/domain/simgos-entities/{m_instalasi => m-instalasi}/entity.go (100%) rename internal/domain/simgos-entities/{m_pasien => m-pasien}/entity.go (100%) rename internal/domain/simgos-entities/{m_polihfis => m-polihfis}/entity.go (100%) rename internal/domain/simgos-entities/{m_poly => m-poly}/entity.go (100%) rename internal/domain/simgos-entities/{m_unit => m-unit}/entity.go (100%) rename internal/domain/simgos-entities/{t_pemeriksaan_hist => t-pemeriksaan-hist}/entity.go (100%) rename internal/domain/simgos-entities/{t_pendaftaran => t-pendaftaran}/entity.go (100%) diff --git a/internal/domain/simgos-entities/m_instalasi/entity.go b/internal/domain/simgos-entities/m-instalasi/entity.go similarity index 100% rename from internal/domain/simgos-entities/m_instalasi/entity.go rename to internal/domain/simgos-entities/m-instalasi/entity.go diff --git a/internal/domain/simgos-entities/m_pasien/entity.go b/internal/domain/simgos-entities/m-pasien/entity.go similarity index 100% rename from internal/domain/simgos-entities/m_pasien/entity.go rename to internal/domain/simgos-entities/m-pasien/entity.go diff --git a/internal/domain/simgos-entities/m_polihfis/entity.go b/internal/domain/simgos-entities/m-polihfis/entity.go similarity index 100% rename from internal/domain/simgos-entities/m_polihfis/entity.go rename to internal/domain/simgos-entities/m-polihfis/entity.go diff --git a/internal/domain/simgos-entities/m_poly/entity.go b/internal/domain/simgos-entities/m-poly/entity.go similarity index 100% rename from internal/domain/simgos-entities/m_poly/entity.go rename to internal/domain/simgos-entities/m-poly/entity.go diff --git a/internal/domain/simgos-entities/m_unit/entity.go b/internal/domain/simgos-entities/m-unit/entity.go similarity index 100% rename from internal/domain/simgos-entities/m_unit/entity.go rename to internal/domain/simgos-entities/m-unit/entity.go diff --git a/internal/domain/simgos-entities/t_pemeriksaan_hist/entity.go b/internal/domain/simgos-entities/t-pemeriksaan-hist/entity.go similarity index 100% rename from internal/domain/simgos-entities/t_pemeriksaan_hist/entity.go rename to internal/domain/simgos-entities/t-pemeriksaan-hist/entity.go diff --git a/internal/domain/simgos-entities/t_pendaftaran/entity.go b/internal/domain/simgos-entities/t-pendaftaran/entity.go similarity index 100% rename from internal/domain/simgos-entities/t_pendaftaran/entity.go rename to internal/domain/simgos-entities/t-pendaftaran/entity.go From f54a2b5b758231ebfc1775809d01632d620a2f31 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Mon, 24 Nov 2025 11:37:57 +0700 Subject: [PATCH 255/329] feat/trx-orders: fix doctor_code + id type --- .../antibiotic-src-category/handler.go | 21 +++++++++++-------- .../main-use-case/antibiotic-in-use/helper.go | 4 ++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/internal/interface/main-handler/antibiotic-src-category/handler.go b/internal/interface/main-handler/antibiotic-src-category/handler.go index 7dde9c66..cc4766af 100644 --- a/internal/interface/main-handler/antibiotic-src-category/handler.go +++ b/internal/interface/main-handler/antibiotic-src-category/handler.go @@ -33,39 +33,42 @@ func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + intId := rw.ValidateInt(w, "id", r.PathValue("id")) + if intId <= 0 { return } + id := uint16(intId) dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Id = &id res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + intId := rw.ValidateInt(w, "id", r.PathValue("id")) + if intId <= 0 { return } + id := uint16(intId) dto := e.UpdateDto{} if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint16(id) + dto.Id = &id 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 { + intId := rw.ValidateInt(w, "id", r.PathValue("id")) + if intId <= 0 { return } + id := uint16(intId) dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Id = &id res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/use-case/main-use-case/antibiotic-in-use/helper.go b/internal/use-case/main-use-case/antibiotic-in-use/helper.go index 8f81510e..20741ce1 100644 --- a/internal/use-case/main-use-case/antibiotic-in-use/helper.go +++ b/internal/use-case/main-use-case/antibiotic-in-use/helper.go @@ -30,7 +30,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.AntibioticInUse) { // data.ExaminationDate = inputSrc.ExaminationDate } -func ValidateMcuOrderDoctor(input e.ReadDetailDto, doctorId uint, event *pl.Event, tx *gorm.DB) error { +func ValidateMcuOrderDoctor(input e.ReadDetailDto, doctorCode string, event *pl.Event, tx *gorm.DB) error { pl.SetLogInfo(event, input, "started", "ValidateMcuOrderDoctor") var mcuOrder emo.McuOrder @@ -47,7 +47,7 @@ func ValidateMcuOrderDoctor(input e.ReadDetailDto, doctorId uint, event *pl.Even return pl.SetLogError(event, input) } - if mcuOrder.Doctor_Id == nil || *mcuOrder.Doctor_Id != doctorId { + if mcuOrder.Doctor_Code == nil || *mcuOrder.Doctor_Code != doctorCode { return errors.New("doctor is not authorized for this mcu-order") } From da88637fe9ce23e618b3c3f19ecab82a4b518b00 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 24 Nov 2025 12:21:17 +0700 Subject: [PATCH 256/329] feat (resume): wip --- assets/docs/resume.html | 432 ++++++++++++++++++ .../use-case/main-use-case/resume/case.go | 295 ++++++++++++ .../use-case/main-use-case/resume/helper.go | 22 + internal/use-case/main-use-case/resume/lib.go | 140 ++++++ .../main-use-case/resume/middleware-runner.go | 103 +++++ .../main-use-case/resume/middleware.go | 9 + .../use-case/main-use-case/resume/tycovar.go | 44 ++ .../main-use-case/unit-position/case.go | 2 +- 8 files changed, 1046 insertions(+), 1 deletion(-) create mode 100644 assets/docs/resume.html create mode 100644 internal/use-case/main-use-case/resume/case.go create mode 100644 internal/use-case/main-use-case/resume/helper.go create mode 100644 internal/use-case/main-use-case/resume/lib.go create mode 100644 internal/use-case/main-use-case/resume/middleware-runner.go create mode 100644 internal/use-case/main-use-case/resume/middleware.go create mode 100644 internal/use-case/main-use-case/resume/tycovar.go diff --git a/assets/docs/resume.html b/assets/docs/resume.html new file mode 100644 index 00000000..fdf47a2d --- /dev/null +++ b/assets/docs/resume.html @@ -0,0 +1,432 @@ + + + + + General Consent + + + + + + + + + + +
          + logo + +
          + PEMERINTAH PROVINSI JAWA TIMUR +
          +
          + RUMAH SAKIT UMUM DAERAH Dr. SAIFUL ANWAR +
          +
          + TERAKREDITASI KARS VERSI 2012 TINGKAT PARIPURNA +
          +
          + Jl. Jaksa Agung Suprapto No. 2 MALANG 65111 +
          +
          Telp. (0341) 362101, Fax. (0341) 362110
          +
          Email: rsu-drsaifulanwar@jatimprov.go.id
          +
          Website: www.rsudsaifulanwar.jatimprov.go.id
          +
          + logo +
          + +
          + +
          + IDENTITAS PASIEN +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          + No. RM + : {{ .Repalcable }} + Kelas + : {{ .Repalcable }}
          + NIK + : {{ .Repalcable }} + Ruang/Klinik + : {{ .Repalcable }}
          + Nama + : {{ .Repalcable }} + DPJP + : {{ .Repalcable }}
          + Tempat/Tanggal Lahir + : {{ .Repalcable }}
          + Jenis Kelamin + : {{ .Repalcable }}
          + No. Telepon + : {{ .Repalcable }}
          + +
          +

          + RESUME MEDIS +

          +

          Medical Discharge Summary

          + + +

          (Diisi oleh Dokter Penanggung Jawab Pelayanan)

          + + + + + + + + + + + + + + + + + + + + + +
          + Tanggal Masuk + : {{ .Repalcable }}
          + Tanggal Keluar + : {{ .Repalcable }}
          + Diagnosis Masuk + : {{ .Repalcable }}
          + Diagnosis Keluar + : {{ .Repalcable }}
          + + + + + + + + + + + + + + + + + + + + + + + + + + +
          + No + + Diagnosa + + Dasar Diagnosa + + Kode ICD-10 +
          + 1 + {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          + 2 + {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          + 3 + {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          + + + + + + + +

          Kajian Awal Medis

          +

          (Diisi oleh Dokter Penanggung Jawab Pelayanan)

          + + + + + + + + + + + + + + + + + +
          + Keluhan Utama + : {{ .Repalcable }}
          + Riwayat Penyakit + : {{ .Repalcable }}
          + Pemeriksaan Fisik & Keadaan Umum + : {{ .Repalcable }}
          + +

          Pemeriksaan Penunjang

          + + + + + + +
          + Pemeriksaan + : {{ .Repalcable }}
          + +

          Tindakan Medis

          + + + + + + + + + + + + + + + + + + + + + + + + + +
          + No + + Tindakan + + Dasar Tindakan + + Kode ICD 9-CM +
          + 1 + {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          + 2 + {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          + 3 + {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          + + + + + + + +
          + Keluhan Utama + : {{ .Repalcable }}
          + + + + + +

          Konsultasi

          + + + + + + + + + + + + + + + + + + + + + +
          + No + + Konsultasi + + Jawaban Konsultasi +
          + 1 + {{ .Repalcable }}{{ .Repalcable }}
          + 2 + {{ .Repalcable }}{{ .Repalcable }}
          + 3 + {{ .Repalcable }}{{ .Repalcable }}
          + +

          Terapi

          + + + + + + +
          + Alergi + : + Replace +
          + + + +

          Obat yang diberikan

          + + + + + + + + + + + + + + + + + +
          + Terapi (Farmakologi & Non Farmakologi) Selawa Perawatan + + Terapi (Farmakologi & Non Farmakologi) Selawa Pulang +
          {{ .Repalcable }}{{ .Repalcable }}
          {{ .Repalcable }}{{ .Repalcable }}
          {{ .Repalcable }}{{ .Repalcable }}
          + + + + + + +

          Kondisi saat Pulang

          + + + + + + +
          + Keluhan Utama + : {{ .Repalcable }}
          + +
          + + + \ No newline at end of file diff --git a/internal/use-case/main-use-case/resume/case.go b/internal/use-case/main-use-case/resume/case.go new file mode 100644 index 00000000..79a2adf1 --- /dev/null +++ b/internal/use-case/main-use-case/resume/case.go @@ -0,0 +1,295 @@ +package resume + +import ( + "errors" + "strconv" + + // main entities + e "simrs-vx/internal/domain/main-entities/resume" + + ue "simrs-vx/internal/use-case/main-use-case/encounter" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + "gorm.io/gorm" +) + +const source = "resume" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.Resume{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 + } + + // check if encounter is done + if ue.IsDone(*input.Encounter_Id, &event, tx) { + return errors.New("encounter is already done") + } + + 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.Resume + var dataList []e.Resume + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.Resume + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.Resume + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err + } + + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err + } + + // check if encounter is done + if ue.IsDone(*input.Encounter_Id, &event, tx) { + return errors.New("encounter is already done") + } + + if err := UpdateData(input, data, &event, tx); err != nil { + return err + } + + // Get Updated Data + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: uint(input.Id)} + var data *e.Resume + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/resume/helper.go b/internal/use-case/main-use-case/resume/helper.go new file mode 100644 index 00000000..18ff757c --- /dev/null +++ b/internal/use-case/main-use-case/resume/helper.go @@ -0,0 +1,22 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package resume + +import ( + e "simrs-vx/internal/domain/main-entities/resume" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Resume) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Encounter_Id = inputSrc.Encounter_Id + data.Value = inputSrc.Value +} diff --git a/internal/use-case/main-use-case/resume/lib.go b/internal/use-case/main-use-case/resume/lib.go new file mode 100644 index 00000000..16bb1afd --- /dev/null +++ b/internal/use-case/main-use-case/resume/lib.go @@ -0,0 +1,140 @@ +package resume + +import ( + "errors" + e "simrs-vx/internal/domain/main-entities/resume" + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Resume, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.Resume{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Resume, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.Resume{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.Resume{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Order("\"CreatedAt\" DESC") + + if err := tx.Find(&data).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.Resume, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.Resume{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.First(&data, input.Id).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.Resume, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.Resume, 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 +} diff --git a/internal/use-case/main-use-case/resume/middleware-runner.go b/internal/use-case/main-use-case/resume/middleware-runner.go new file mode 100644 index 00000000..e7f4cade --- /dev/null +++ b/internal/use-case/main-use-case/resume/middleware-runner.go @@ -0,0 +1,103 @@ +package resume + +import ( + e "simrs-vx/internal/domain/main-entities/resume" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.Resume) 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.Resume) 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.Resume) 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.Resume) 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.Resume) 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/main-use-case/resume/middleware.go b/internal/use-case/main-use-case/resume/middleware.go new file mode 100644 index 00000000..dc0aa8c9 --- /dev/null +++ b/internal/use-case/main-use-case/resume/middleware.go @@ -0,0 +1,9 @@ +package resume + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/resume/tycovar.go b/internal/use-case/main-use-case/resume/tycovar.go new file mode 100644 index 00000000..13f36d2a --- /dev/null +++ b/internal/use-case/main-use-case/resume/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 resume + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/resume" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.Resume, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Resume, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Resume, 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/main-use-case/unit-position/case.go b/internal/use-case/main-use-case/unit-position/case.go index 47ea67cd..c472e90c 100644 --- a/internal/use-case/main-use-case/unit-position/case.go +++ b/internal/use-case/main-use-case/unit-position/case.go @@ -290,7 +290,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { func validateForeignKey(input e.CreateDto) error { // validate installation_id - if _, err := uu.ReadDetail(eu.ReadDetailDto{Code: &input.Code}); err != nil { + if _, err := uu.ReadDetail(eu.ReadDetailDto{Code: input.Unit_Code}); err != nil { return err } From 8ea916261466dd0b0488c4a662c210093102e6c0 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 24 Nov 2025 12:28:15 +0700 Subject: [PATCH 257/329] fix (unit-position): wrong validation unit_code --- internal/use-case/main-use-case/unit-position/case.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/use-case/main-use-case/unit-position/case.go b/internal/use-case/main-use-case/unit-position/case.go index 47ea67cd..c472e90c 100644 --- a/internal/use-case/main-use-case/unit-position/case.go +++ b/internal/use-case/main-use-case/unit-position/case.go @@ -290,7 +290,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { func validateForeignKey(input e.CreateDto) error { // validate installation_id - if _, err := uu.ReadDetail(eu.ReadDetailDto{Code: &input.Code}); err != nil { + if _, err := uu.ReadDetail(eu.ReadDetailDto{Code: input.Unit_Code}); err != nil { return err } From a4cc6c63d1396fccc7fe72d3e9f64c334f9b41e1 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 24 Nov 2025 12:29:50 +0700 Subject: [PATCH 258/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 106 ++++++++++++------------ 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 0d9edc98..fb5f05a1 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:4U2KWXwY59v9g8NqCRfUlRU8S0gFHP+2zZo3VIYCy80= +h1:ReP8c8xn+Z0qEbKQYoC5N892gRkq7lhOJNdPtW3HlbA= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,55 +75,55 @@ h1:4U2KWXwY59v9g8NqCRfUlRU8S0gFHP+2zZo3VIYCy80= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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:4gmYBcmga1SBxRwrVaovGVvpRZFMV7vYzce0/IalryY= +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= From d87a54c1112031727626e9cccbe487ff73518414 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 24 Nov 2025 14:18:04 +0700 Subject: [PATCH 259/329] add doctor_code and status into resume --- cmd/main-migration/migrations/20251124071457.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 5 +++-- internal/domain/main-entities/resume/entity.go | 16 +++++++++++----- internal/domain/references/common/common.go | 8 +++++--- 4 files changed, 21 insertions(+), 10 deletions(-) create mode 100644 cmd/main-migration/migrations/20251124071457.sql diff --git a/cmd/main-migration/migrations/20251124071457.sql b/cmd/main-migration/migrations/20251124071457.sql new file mode 100644 index 00000000..0cb4c4e7 --- /dev/null +++ b/cmd/main-migration/migrations/20251124071457.sql @@ -0,0 +1,2 @@ +-- Modify "Resume" table +ALTER TABLE "public"."Resume" ADD COLUMN "Doctor_Code" character varying(10) NULL, ADD COLUMN "Status_Code" character varying(10) NOT NULL, ADD CONSTRAINT "fk_Resume_Doctor" FOREIGN KEY ("Doctor_Code") REFERENCES "public"."Doctor" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 87b0571b..707ee3ca 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:9o177sOy5hbZmLRLBxkW8WN1dveIe0pyAXoU84eeq0Y= +h1:87NyL1nIRuVvOiLbfdC1+PF+v2R/joAnBYyh2CrlGdU= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -127,4 +127,5 @@ h1:9o177sOy5hbZmLRLBxkW8WN1dveIe0pyAXoU84eeq0Y= 20251119072450.sql h1:Xg+bTwqGyKPNFEQhJylvpz1wifdfmDJvcAq6vmNf0Ng= 20251120005512.sql h1:Ek6qpacAI/qVuTYxKno+uJyzn7s5z9pf3t7VA8gTzm4= 20251120074415.sql h1:NNUeJVA03EeBHJhHqPXEZoDv/PnC6yK1/cRhmukyaJo= -20251121033803.sql h1:1s3DvgbqF+lh/or9X6WGN2lwnYCZkP8JH6uJFHql15g= +20251121033803.sql h1:/vfvFX/3pzSCIHnSbMUT9EMBDykOpVkvyfeTEle9Vas= +20251124071457.sql h1:HBaNJQIzUe6wK8CgBxamuKor7ZiAASzgkkXzL6kWsjY= diff --git a/internal/domain/main-entities/resume/entity.go b/internal/domain/main-entities/resume/entity.go index cf756870..70050166 100644 --- a/internal/domain/main-entities/resume/entity.go +++ b/internal/domain/main-entities/resume/entity.go @@ -1,12 +1,18 @@ package resume import ( - "simrs-vx/internal/domain/base-entities/core" + ecore "simrs-vx/internal/domain/base-entities/core" + ed "simrs-vx/internal/domain/main-entities/doctor" + + erc "simrs-vx/internal/domain/references/common" ) type Resume struct { - core.Main - Encounter_Id *uint `json:"encounter_id" gorm:"not null"` - Value *string `json:"value"` - FileUrl *string `json:"fileUrl" gorm:"size:1024"` + ecore.Main + Encounter_Id *uint `json:"encounter_id" gorm:"not null"` + Doctor_Code *string `json:"doctor_code" gorm:"size:10"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"` + Value *string `json:"value"` + FileUrl *string `json:"fileUrl" gorm:"size:1024"` + Status_Code erc.DataVerifiedCode `json:"status_code" gorm:"not null;size:10"` } diff --git a/internal/domain/references/common/common.go b/internal/domain/references/common/common.go index cc466d7b..96febd75 100644 --- a/internal/domain/references/common/common.go +++ b/internal/domain/references/common/common.go @@ -72,9 +72,11 @@ const ( DACAvailable DataAvailabilityCode = "available" // Tersedia DACUnavailable DataAvailabilityCode = "unavailable" // Tidak Tersedia - DVCNew DataVerifiedCode = "new" // Baru - DVCVerified DataVerifiedCode = "verified" // Terverifikasi - DVCRejected DataVerifiedCode = "rejected" // Ditolak + DVCNew DataVerifiedCode = "new" // Baru + DVCVerified DataVerifiedCode = "verified" // Terverifikasi + DVCValidated DataVerifiedCode = "validated" // Tervalidasi + DVCCancelled DataVerifiedCode = "cancelled" // Dibatalkan + DVCRejected DataVerifiedCode = "rejected" // Ditolak USCNew UserStatusCode = "new" // Baru USCActive UserStatusCode = "active" // Aktif From 5322e986e4c7b4cbd19f03c686033915feaf1f86 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 24 Nov 2025 17:13:40 +0700 Subject: [PATCH 260/329] feat (resume): add verify and validate, base value structure --- .../domain/main-entities/encounter/entity.go | 7 + internal/domain/main-entities/resume/dto.go | 119 ++++++++++++++++- .../domain/main-entities/resume/entity.go | 12 ++ .../interface/main-handler/main-handler.go | 10 ++ .../interface/main-handler/resume/handler.go | 121 ++++++++++++++++++ .../use-case/main-use-case/resume/case.go | 97 ++++++++++++++ .../use-case/main-use-case/resume/helper.go | 2 + 7 files changed, 362 insertions(+), 6 deletions(-) create mode 100644 internal/interface/main-handler/resume/handler.go diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index 61496f9e..f8f0c66f 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -82,3 +82,10 @@ type Encounter struct { func (d Encounter) IsDone() bool { return d.Status_Code == erc.DSCDone } + +func (d Encounter) IsSameResponsibleDoctor(input *string) bool { + if input == nil { + return false + } + return d.Responsible_Doctor_Code == input +} diff --git a/internal/domain/main-entities/resume/dto.go b/internal/domain/main-entities/resume/dto.go index ea9485d7..bf505d20 100644 --- a/internal/domain/main-entities/resume/dto.go +++ b/internal/domain/main-entities/resume/dto.go @@ -2,11 +2,19 @@ package resume import ( ecore "simrs-vx/internal/domain/base-entities/core" + "time" + + erc "simrs-vx/internal/domain/references/common" + + pa "simrs-vx/internal/lib/auth" ) type CreateDto struct { - Encounter_Id *uint `json:"encounter_id"` - Value *string `json:"value"` + Encounter_Id *uint `json:"encounter_id"` + Value *string `json:"value"` + Status_Code erc.DataVerifiedCode `json:"status_code"` + + pa.AuthInfo } type ReadListDto struct { @@ -16,7 +24,8 @@ type ReadListDto struct { } type FilterDto struct { - Encounter_Id *uint `json:"encounter-id"` + Encounter_Id *uint `json:"encounter-id"` + Doctor_Code *string `json:"doctor-code"` } type ReadDetailDto struct { @@ -30,6 +39,8 @@ type UpdateDto struct { type DeleteDto struct { Id uint `json:"id"` + + pa.AuthInfo } type MetaDto struct { @@ -40,16 +51,20 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Value *string `json:"value"` - FileUrl *string `json:"fileUrl"` + Encounter_Id *uint `json:"encounter_id"` + Doctor_Code *string `json:"doctor_code"` + Value *string `json:"value"` + FileUrl *string `json:"fileUrl"` + Status_Code erc.DataVerifiedCode `json:"status_code"` } func (d Resume) ToResponse() ResponseDto { resp := ResponseDto{ Encounter_Id: d.Encounter_Id, + Doctor_Code: d.Doctor_Code, Value: d.Value, FileUrl: d.FileUrl, + Status_Code: d.Status_Code, } resp.Main = d.Main return resp @@ -62,3 +77,95 @@ func ToResponseList(data []Resume) []ResponseDto { } return resp } + +// ValueDto is for resume value +type ValueDto struct { + Assessment Assessment `json:"assessment"` + Diagnosis Diagnosis `json:"diagnosis"` + Action Action `json:"action"` + Consultation Consultation `json:"consultation"` + Supporting SupportingExaminations `json:"supporting"` + Pharmacy PharmacyData `json:"pharmacy"` + Discharge DischargeCondition `json:"discharge"` + National NationalProgram `json:"national"` + Management Management `json:"management"` +} + +type Assessment struct { + StartedAt *time.Time `json:"startedAt` + FinishedAt *time.Time `json:"finishedAt` + Doctor_Code string `json:"doctor_code` + DiagnosisIn string `json:"diagnosesIn` + AmbulatoryIndication string `json:"ambulatoryIndication"` + MainComplaint string `json:"mainComplaint"` + PhysicalExamination string `json:"physicalExamination"` + MedicalHistory string `json:"medicalHistory"` + MedicalDiagnosis string `json:"medicalDiagnosis"` +} + +type Diagnosis struct { + PrimaryDiagnosis DiagnosisEntry `json:"primaryDiagnosis"` + SecondaryDiagnoses []DiagnosisEntry `json:"secondaryDiagnoses"` +} + +type DiagnosisEntry struct { + Diagnosis string `json:"diagnosis"` + ICD10 string `json:"icd_10"` + Basis string `json:"basis"` // Clinical basis of diagnosis / dasar diagnosa +} + +type Action struct { + PrimaryAction ActionEntry `json:"primaryAction"` + AdditionalActions []ActionEntry `json:"additionalActions"` + MedicalActions string `json:"medicalActions"` // free-text: "Tindakan Medis" +} + +type ActionEntry struct { + Action string `json:"action"` // Tindakan + ICD9 string `json:"icd_9"` // ICD-9 + Basis string `json:"basis"` // Dasar Tindakan +} + +type Consultation struct { + Consultations []ConsultationEntry `json:"consultations"` +} + +type ConsultationEntry struct { + Consultation string `json:"consultation"` // Konsultasi + ConsultationAnswer string `json:"consultationAnswer"` // Jawaban Konsultasi +} + +type SupportingExaminations struct { + Notes string `json:"notes"` // Free-text list of lab/imaging results +} + +type PharmacyData struct { + AllergySpecialConditions string `json:"allergySpecialConditions"` // Kelainan Khusus Alergi + OtherConditions string `json:"otherConditions"` // Kelainan Lain + TherapyDuringCare string `json:"therapyDuringCare"` // Terapi selama dirawat + TherapyAtDischarge string `json:"therapyAtDischarge"` // Terapi waktu pulang + FollowUpInstructions string `json:"followUpInstructions"` // Edukasi / Anjuran / Follow-up +} + +type DischargeCondition struct { + BloodPressureSystolic float64 `json:"bloodPressureSystolic"` // Tekanan Darah Sistol (mmHg) + BloodPressureDiastolic float64 `json:"bloodPressureDiastolic"` // Tekanan Darah Diastol (mmHg) + RespirationRate float64 `json:"respirationRate"` // Pernafasan (kali/menit) + HeartRate float64 `json:"heartRate"` // Denyut Jantung (kali/menit) + BodyTemperature float64 `json:"bodyTemperature"` // Suhu Tubuh (°C) + + ConsciousnessLevel string `json:"consciousnessLevel"` // Tingkat Kesadaran + PainScale int `json:"painScale"` // Skala Nyeri (0–10) +} + +type NationalProgram struct { + ProgramService string `json:"programService"` // e.g. "Antenatal Care" + ProgramServiceStatus string `json:"programServiceStatus"` // e.g. "Suspected" +} + +type Management struct { + NationalProgramService string `json:"nationalProgramService"` // e.g. selected program + FollowUpManagement string `json:"followUpManagement"` // e.g. further management plan + ConditionOnDischarge string `json:"conditionOnDischarge"` // e.g. "Stable" + DischargeMethod string `json:"dischargeMethod"` // e.g. "Discharged with Doctor's Approval" +} diff --git a/internal/domain/main-entities/resume/entity.go b/internal/domain/main-entities/resume/entity.go index 70050166..93a1d8cd 100644 --- a/internal/domain/main-entities/resume/entity.go +++ b/internal/domain/main-entities/resume/entity.go @@ -16,3 +16,15 @@ type Resume struct { FileUrl *string `json:"fileUrl" gorm:"size:1024"` Status_Code erc.DataVerifiedCode `json:"status_code" gorm:"not null;size:10"` } + +func (d Resume) IsNew() bool { + return d.Status_Code == erc.DVCNew +} + +func (d Resume) IsVerified() bool { + return d.Status_Code == erc.DVCVerified +} + +func (d Resume) IsValidated() bool { + return d.Status_Code == erc.DVCValidated +} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 56811194..1dc4c893 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -34,6 +34,7 @@ import ( prescription "simrs-vx/internal/interface/main-handler/prescription" prescriptionitem "simrs-vx/internal/interface/main-handler/prescription-item" responsibledoctorhist "simrs-vx/internal/interface/main-handler/responsible-doctor-hist" + resume "simrs-vx/internal/interface/main-handler/resume" sbar "simrs-vx/internal/interface/main-handler/sbar" soapi "simrs-vx/internal/interface/main-handler/soapi" uploadfile "simrs-vx/internal/interface/main-handler/upload-file" @@ -288,6 +289,15 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/encounter-document", encounterdocument.O) hc.RegCrud(r, "/v1/general-consent", generalconsent.O) r.HandleFunc("POST /v1/generate-file", generatefile.Generate) + hk.GroupRoutes("/v1/resume", r, auth.GuardMW, hk.MapHandlerFunc{ + "POST /": resume.Create, + "GET /": resume.GetList, + "GET /{id}": resume.GetDetail, + "PATCH /{id}": resume.Update, + "DELETE /{id}": resume.Delete, + "PATCH /{id}/verify": resume.Verify, + "PATCH /{id}/validate": resume.Validate, + }) /******************** actor ********************/ hc.RegCrud(r, "/v1/person", person.O) diff --git a/internal/interface/main-handler/resume/handler.go b/internal/interface/main-handler/resume/handler.go new file mode 100644 index 00000000..5574bc7a --- /dev/null +++ b/internal/interface/main-handler/resume/handler.go @@ -0,0 +1,121 @@ +package resume + +import ( + "net/http" + + d "github.com/karincake/dodol" + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/resume" + u "simrs-vx/internal/use-case/main-use-case/resume" + + erc "simrs-vx/internal/domain/references/common" + + pa "simrs-vx/internal/lib/auth" +) + +func Create(w http.ResponseWriter, r *http.Request) { + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + + dto.AuthInfo = *authInfo + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + sf.UrlQueryParam(&dto, *r.URL) + dto.Id = uint(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint(id) + res, err := u.Update(dto) + rw.DataResponse(w, res, err) +} + +func 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) +} + +func Verify(w http.ResponseWriter, r *http.Request) { + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint(id) + dto.Status_Code = erc.DVCVerified + dto.AuthInfo = *authInfo + res, err := u.UpdateStatusCode(dto) + rw.DataResponse(w, res, err) +} + +func Validate(w http.ResponseWriter, r *http.Request) { + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint(id) + dto.Status_Code = erc.DVCValidated + dto.AuthInfo = *authInfo + res, err := u.UpdateStatusCode(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/use-case/main-use-case/resume/case.go b/internal/use-case/main-use-case/resume/case.go index 79a2adf1..cbc472f9 100644 --- a/internal/use-case/main-use-case/resume/case.go +++ b/internal/use-case/main-use-case/resume/case.go @@ -4,7 +4,10 @@ import ( "errors" "strconv" + erc "simrs-vx/internal/domain/references/common" + // main entities + ee "simrs-vx/internal/domain/main-entities/encounter" e "simrs-vx/internal/domain/main-entities/resume" ue "simrs-vx/internal/use-case/main-use-case/encounter" @@ -31,6 +34,10 @@ func Create(input e.CreateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "create") err := dg.I.Transaction(func(tx *gorm.DB) error { + if !input.AuthInfo.IsDoctor() { + return errors.New("user is not a doctor") + } + mwRunner := newMiddlewareRunner(&event, tx) mwRunner.setMwType(pu.MWTPre) // Run pre-middleware @@ -43,6 +50,7 @@ func Create(input e.CreateDto) (*d.Data, error) { return errors.New("encounter is already done") } + input.Status_Code = erc.DVCNew if resData, err := CreateData(input, &event, tx); err != nil { return err } else { @@ -188,6 +196,10 @@ func Update(input e.UpdateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "update") err = dg.I.Transaction(func(tx *gorm.DB) error { + if !input.AuthInfo.IsDoctor() { + return errors.New("user is not a doctor") + } + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") if data, err = ReadDetailData(rdDto, &event, tx); err != nil { return err @@ -254,6 +266,10 @@ func Delete(input e.DeleteDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "delete") err = dg.I.Transaction(func(tx *gorm.DB) error { + if !input.AuthInfo.IsDoctor() { + return errors.New("user is not a doctor") + } + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") if data, err = ReadDetailData(rdDto, &event, tx); err != nil { return err @@ -293,3 +309,84 @@ func Delete(input e.DeleteDto) (*d.Data, error) { }, nil } + +func UpdateStatusCode(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.Resume + var err error + + event := pl.Event{ + Feature: "UpdateStatusCode", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "updateStatusCode") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + if !input.AuthInfo.IsDoctor() { + return errors.New("user is not a doctor") + } + + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err + } + + enc, err := ue.ReadDetailData(ee.ReadDetailDto{Id: uint16(*data.Encounter_Id)}, &event, tx) + if err != nil { + return err + } + + // check if encounter is done + if enc.IsDone() { + return errors.New("encounter is already done") + } + + switch input.Status_Code { + case erc.DVCValidated: + if !enc.IsSameResponsibleDoctor(input.AuthInfo.Doctor_Code) { + return errors.New("validation doctor is not the same as encounter responsible doctor") + } + + if data.IsNew() { + return errors.New("resume need to be verified first") + } + if data.IsValidated() { + return errors.New("resume already validated") + } + data.Status_Code = erc.DVCValidated + err = tx.Save(&data).Error + if err != nil { + return err + } + case erc.DVCVerified: + if data.IsValidated() { + return errors.New("resume already validated") + } + if data.IsVerified() { + return errors.New("resume already verified") + } + data.Status_Code = erc.DVCVerified + err = tx.Save(&data).Error + if err != nil { + return err + } + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil +} diff --git a/internal/use-case/main-use-case/resume/helper.go b/internal/use-case/main-use-case/resume/helper.go index 18ff757c..edd45222 100644 --- a/internal/use-case/main-use-case/resume/helper.go +++ b/internal/use-case/main-use-case/resume/helper.go @@ -18,5 +18,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Resume) { } data.Encounter_Id = inputSrc.Encounter_Id + data.Doctor_Code = inputSrc.AuthInfo.Doctor_Code data.Value = inputSrc.Value + data.Status_Code = inputSrc.Status_Code } From efb8f12df80829e801b082cb200e1a59a5a2e1a3 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 25 Nov 2025 13:58:38 +0700 Subject: [PATCH 261/329] update soapi conslist --- internal/domain/references/clinical/clinical.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/internal/domain/references/clinical/clinical.go b/internal/domain/references/clinical/clinical.go index f5190297..30a4fe8a 100644 --- a/internal/domain/references/clinical/clinical.go +++ b/internal/domain/references/clinical/clinical.go @@ -117,12 +117,14 @@ const ( MULCPF McuUrgencyLevelCode = "priority-form" // Form Prioritas MULCRT McuUrgencyLevelCode = "routine" // Pemeriksaan Rutin - //STCEarlyNurse SoapiTypeCode = "early-nurse" // Kajian Awal Medis - STCEEarlyMedic SoapiTypeCode = "early-medic" // Kajian Awal Rehab Medis - STCEarlyRehab SoapiTypeCode = "early-rehab" // Kajian Awal Rehab Medik - STCFunc SoapiTypeCode = "function" // Assessment Fungsi - STCProgress SoapiTypeCode = "progress" // CPPT - STCDevRecord SoapiTypeCode = "dev-record" // Catatan Perkembangan + STCEarlyNurse SoapiTypeCode = "early-nursery" // Kajian Awal Keperawatan + STCEEarlyMedic SoapiTypeCode = "early-medic" // Kajian Awal Rehab Medis + STCEarlyRehab SoapiTypeCode = "early-rehab" // Kajian Awal Rehab Medik + STCFunc SoapiTypeCode = "function" // Assessment Fungsi + STCProgress SoapiTypeCode = "progress" // CPPT + STCDevRecord SoapiTypeCode = "dev-record" // Catatan Perkembangan + STCKfrAdm SoapiTypeCode = "kfr-adm" // soapi untuk kfr + STCKfrSeries SoapiTypeCode = "kfr-series" // soapi untuk kfr MATCChemo MedicalActionTypeCode = "chemo" MATCHemo MedicalActionTypeCode = "hemo" From ca0fee997eb5cb671898688cad179083c99a1a46 Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 25 Nov 2025 14:10:01 +0700 Subject: [PATCH 262/329] fix conflict --- README-DB.md | 4 ++-- cmd/main-api/config.yml-example | 2 +- .../new/division/handler.go | 3 ++- .../new/encounter/handler.go | 3 ++- .../new/installation/handler.go | 3 ++- .../new/patient/handler.go | 3 ++- .../new/specialist/handler.go | 3 ++- .../new/subspecialist/handler.go | 2 +- .../simgos-sync-handler/new/unit/handler.go | 3 ++- .../simgos-sync-handler.go | 19 ++++++++++--------- 10 files changed, 26 insertions(+), 19 deletions(-) diff --git a/README-DB.md b/README-DB.md index b99cf08a..c361ca31 100644 --- a/README-DB.md +++ b/README-DB.md @@ -15,7 +15,7 @@
          Example: 1. `User_Id` represents the `User` object and the `Id` attribute 2. `BestProduct_Code` represents the `BestProduct` object and the `Code` attribute - 3. When more than one column has a similar definition, a `prefixnew` can be added to indicate the column's purpose. + 3. When more than one column has a similar definition, a `prefix` can be added to indicate the column's purpose.
          Example: 1. `Admin_User_Id` represents the `Admin` of the `User` object and the `Id` attribute 2. `Operator_User_Id` refers to the `Operator` of the `User` object and the `Id` column. @@ -25,7 +25,7 @@
          Example: 1. `user_id` represents the `User` object and the `Id` attribute. 2. `bestProduct_code` represents the `bestProduct` object and the `code` attribute. - 3. When more than one column has a similar definition, a `prefixnew` can be added to indicate the column's purpose. + 3. When more than one column has a similar definition, a `prefix` can be added to indicate the column's purpose.
          Example: 1. `admin_user_id` refers to the `admin` of the `user` object and `id` attribute 2. `operator_user_id` refers to the `operator` of the `user` object, column `id` diff --git a/cmd/main-api/config.yml-example b/cmd/main-api/config.yml-example index 3f6224ad..30351abf 100644 --- a/cmd/main-api/config.yml-example +++ b/cmd/main-api/config.yml-example @@ -71,7 +71,7 @@ bpjsCfg: syncUrlCfg: enable: false host: - prefixnew: new-to-old + prefix: new-to-old docsCfg: path: ../../assets/docs/ \ No newline at end of file diff --git a/internal/interface/simgos-sync-handler/new/division/handler.go b/internal/interface/simgos-sync-handler/new/division/handler.go index 75059cd8..28920d21 100644 --- a/internal/interface/simgos-sync-handler/new/division/handler.go +++ b/internal/interface/simgos-sync-handler/new/division/handler.go @@ -2,13 +2,14 @@ package division import ( "net/http" - u "simrs-vx/internal/use-case/simgos-sync-use-case/new/division" rw "github.com/karincake/risoles" // ua "github.com/karincake/tumpeng/auth/svc" e "simrs-vx/internal/domain/main-entities/division" esync "simrs-vx/internal/domain/sync-entities/log" + + u "simrs-vx/internal/use-case/simgos-sync-use-case/new/division" ) type myBase struct{} diff --git a/internal/interface/simgos-sync-handler/new/encounter/handler.go b/internal/interface/simgos-sync-handler/new/encounter/handler.go index 1f03c38c..e6b0515a 100644 --- a/internal/interface/simgos-sync-handler/new/encounter/handler.go +++ b/internal/interface/simgos-sync-handler/new/encounter/handler.go @@ -2,13 +2,14 @@ package encounter import ( "net/http" - u "simrs-vx/internal/use-case/simgos-sync-use-case/new/encounter" rw "github.com/karincake/risoles" // ua "github.com/karincake/tumpeng/auth/svc" e "simrs-vx/internal/domain/main-entities/encounter" esync "simrs-vx/internal/domain/sync-entities/log" + + u "simrs-vx/internal/use-case/simgos-sync-use-case/new/encounter" ) type myBase struct{} diff --git a/internal/interface/simgos-sync-handler/new/installation/handler.go b/internal/interface/simgos-sync-handler/new/installation/handler.go index eb5fe09d..3a1eca93 100644 --- a/internal/interface/simgos-sync-handler/new/installation/handler.go +++ b/internal/interface/simgos-sync-handler/new/installation/handler.go @@ -2,13 +2,14 @@ package installation import ( "net/http" - u "simrs-vx/internal/use-case/simgos-sync-use-case/new/installation" rw "github.com/karincake/risoles" // ua "github.com/karincake/tumpeng/auth/svc" e "simrs-vx/internal/domain/main-entities/installation" esync "simrs-vx/internal/domain/sync-entities/log" + + u "simrs-vx/internal/use-case/simgos-sync-use-case/new/installation" ) type myBase struct{} diff --git a/internal/interface/simgos-sync-handler/new/patient/handler.go b/internal/interface/simgos-sync-handler/new/patient/handler.go index d3e6d591..f3c3951b 100644 --- a/internal/interface/simgos-sync-handler/new/patient/handler.go +++ b/internal/interface/simgos-sync-handler/new/patient/handler.go @@ -2,13 +2,14 @@ package patient import ( "net/http" - u "simrs-vx/internal/use-case/simgos-sync-use-case/new/patient" rw "github.com/karincake/risoles" // ua "github.com/karincake/tumpeng/auth/svc" e "simrs-vx/internal/domain/main-entities/patient" esync "simrs-vx/internal/domain/sync-entities/log" + + u "simrs-vx/internal/use-case/simgos-sync-use-case/new/patient" ) type myBase struct{} diff --git a/internal/interface/simgos-sync-handler/new/specialist/handler.go b/internal/interface/simgos-sync-handler/new/specialist/handler.go index b1a31dbb..2afe3f13 100644 --- a/internal/interface/simgos-sync-handler/new/specialist/handler.go +++ b/internal/interface/simgos-sync-handler/new/specialist/handler.go @@ -2,13 +2,14 @@ package specialist import ( "net/http" - u "simrs-vx/internal/use-case/simgos-sync-use-case/new/specialist" rw "github.com/karincake/risoles" // ua "github.com/karincake/tumpeng/auth/svc" e "simrs-vx/internal/domain/main-entities/specialist" esync "simrs-vx/internal/domain/sync-entities/log" + + u "simrs-vx/internal/use-case/simgos-sync-use-case/new/specialist" ) type myBase struct{} diff --git a/internal/interface/simgos-sync-handler/new/subspecialist/handler.go b/internal/interface/simgos-sync-handler/new/subspecialist/handler.go index 4cf6dd13..0bfd2226 100644 --- a/internal/interface/simgos-sync-handler/new/subspecialist/handler.go +++ b/internal/interface/simgos-sync-handler/new/subspecialist/handler.go @@ -2,13 +2,13 @@ package subspecialist import ( "net/http" - u "simrs-vx/internal/use-case/simgos-sync-use-case/new/subspecialist" rw "github.com/karincake/risoles" // ua "github.com/karincake/tumpeng/auth/svc" e "simrs-vx/internal/domain/main-entities/subspecialist" esync "simrs-vx/internal/domain/sync-entities/log" + u "simrs-vx/internal/use-case/simgos-sync-use-case/new/subspecialist" ) type myBase struct{} diff --git a/internal/interface/simgos-sync-handler/new/unit/handler.go b/internal/interface/simgos-sync-handler/new/unit/handler.go index 66479db2..95808728 100644 --- a/internal/interface/simgos-sync-handler/new/unit/handler.go +++ b/internal/interface/simgos-sync-handler/new/unit/handler.go @@ -2,13 +2,14 @@ package unit import ( "net/http" - u "simrs-vx/internal/use-case/simgos-sync-use-case/new/unit" rw "github.com/karincake/risoles" // ua "github.com/karincake/tumpeng/auth/svc" e "simrs-vx/internal/domain/main-entities/unit" esync "simrs-vx/internal/domain/sync-entities/log" + + u "simrs-vx/internal/use-case/simgos-sync-use-case/new/unit" ) type myBase struct{} diff --git a/internal/interface/simgos-sync-handler/simgos-sync-handler.go b/internal/interface/simgos-sync-handler/simgos-sync-handler.go index a82e81e6..0fc0d5b3 100644 --- a/internal/interface/simgos-sync-handler/simgos-sync-handler.go +++ b/internal/interface/simgos-sync-handler/simgos-sync-handler.go @@ -2,20 +2,14 @@ package simgossynchandler import ( "net/http" - "simrs-vx/internal/interface/simgos-sync-handler/new/division" - "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/specialist" - "simrs-vx/internal/interface/simgos-sync-handler/new/subspecialist" - "simrs-vx/internal/interface/simgos-sync-handler/new/unit" - hc "simrs-vx/pkg/handler-crud-helper" /******************** infra ********************/ gs "simrs-vx/internal/infra/gorm-setting" simgosdb "simrs-vx/internal/infra/simgos-db" + /******************** pkg ********************/ cmw "simrs-vx/pkg/cors-manager-mw" + hc "simrs-vx/pkg/handler-crud-helper" lh "simrs-vx/pkg/lang-helper" handlerlogger "simrs-vx/pkg/middleware/handler-logger" zlc "simrs-vx/pkg/zerolog-ctx" @@ -26,6 +20,13 @@ import ( /******************** internal ********************/ "simrs-vx/internal/interface/main-handler/home" + "simrs-vx/internal/interface/simgos-sync-handler/new/division" + "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/specialist" + "simrs-vx/internal/interface/simgos-sync-handler/new/subspecialist" + "simrs-vx/internal/interface/simgos-sync-handler/new/unit" ) func SetRoutes() http.Handler { @@ -56,7 +57,7 @@ func SetRoutes() http.Handler { }) hk.GroupRoutes(prefixnew+"/v1/encounter", r, hk.MapHandlerFunc{ "POST /": encounter.O.Create, - "POST /log": encounter.O.CreateLog, + "POST /log": encounter.O.CreateLog,git ad "PATCH /{id}": encounter.O.Update, "DELETE /{id}": encounter.O.Delete, "PATCH /{id}/checkin": encounter.O.Checkin, From 782d272d91249c3a0a36a76d163a980c92e79c85 Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 25 Nov 2025 14:10:25 +0700 Subject: [PATCH 263/329] fix conflict --- internal/interface/simgos-sync-handler/simgos-sync-handler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/interface/simgos-sync-handler/simgos-sync-handler.go b/internal/interface/simgos-sync-handler/simgos-sync-handler.go index 0fc0d5b3..ccfa6cda 100644 --- a/internal/interface/simgos-sync-handler/simgos-sync-handler.go +++ b/internal/interface/simgos-sync-handler/simgos-sync-handler.go @@ -57,7 +57,7 @@ func SetRoutes() http.Handler { }) hk.GroupRoutes(prefixnew+"/v1/encounter", r, hk.MapHandlerFunc{ "POST /": encounter.O.Create, - "POST /log": encounter.O.CreateLog,git ad + "POST /log": encounter.O.CreateLog, "PATCH /{id}": encounter.O.Update, "DELETE /{id}": encounter.O.Delete, "PATCH /{id}/checkin": encounter.O.Checkin, From 63f9d5512bd4760e2687518a3cffbcd21f53bd0a Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 25 Nov 2025 14:31:03 +0700 Subject: [PATCH 264/329] resume wip --- assets/docs/resume.html | 8 +++--- .../main-use-case/generate-file/tycovar.go | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/assets/docs/resume.html b/assets/docs/resume.html index fdf47a2d..8cdca672 100644 --- a/assets/docs/resume.html +++ b/assets/docs/resume.html @@ -82,7 +82,7 @@
          : {{ .Repalcable }} - Kelas + Ruang/Klinik : {{ .Repalcable }}: {{ .Repalcable }} - Ruang/Klinik + Kelas : {{ .Repalcable }}{{ .Repalcable }}
          diff --git a/internal/use-case/main-use-case/generate-file/tycovar.go b/internal/use-case/main-use-case/generate-file/tycovar.go index 2f6a0ced..2bbe9fbf 100644 --- a/internal/use-case/main-use-case/generate-file/tycovar.go +++ b/internal/use-case/main-use-case/generate-file/tycovar.go @@ -7,6 +7,8 @@ import ( erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" + er "simrs-vx/internal/domain/main-entities/resume" + pu "simrs-vx/pkg/use-case-helper" ) @@ -32,6 +34,31 @@ type ControlLetterPDF struct { PrintDate string } +type ResumePDF struct { + MedicalRecord string + NIK string + Name string + BirthPlaceDate string + Gender string + Phone string + Class string + Unit string + Doctor_Name string + StartedDate string + FinishedDate string + DiagnosisIn string + DiagnosisOut string + Diagnosis []er.DiagnosisEntry + MainComplaint string + MedicalHistory string + PhysicalExamination string + SupportingExamination string + MedicalActions []er.ActionEntry + MedicalAction string + Consultations []er.ConsultationEntry + Allergy string +} + type GenerateDto struct { EntityType_Code ere.EntityTypeCode `json:"entityType_code" validate:"required"` Ref_Id *string `json:"ref_id" validate:"required"` From d6c49b099176d7da178c9a70874c89f5540143b9 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 25 Nov 2025 14:31:48 +0700 Subject: [PATCH 265/329] update doctype conslist resume --- internal/domain/references/encounter/encounter.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/domain/references/encounter/encounter.go b/internal/domain/references/encounter/encounter.go index 1acee75b..e3d78bcd 100644 --- a/internal/domain/references/encounter/encounter.go +++ b/internal/domain/references/encounter/encounter.go @@ -121,6 +121,7 @@ const ( DTCSIPP DocTypeCode = "vclaim-sipp" // SIPP DTCGC DocTypeCode = "general-consent" DTCVSCL DocTypeCode = "vclaim-control-letter" // vclaim control letter + DTCResume DocTypeCode = "resume" // Resume ETCPerson EntityTypeCode = "person" ETCEncounter EntityTypeCode = "encounter" From 8cf750c63f651cfd62e53b2f16d494e5aee73b1c Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 25 Nov 2025 15:52:07 +0700 Subject: [PATCH 266/329] wip --- .../domain/main-entities/person/entity.go | 60 ++++++ internal/domain/main-entities/resume/dto.go | 3 +- .../main-use-case/generate-file/case.go | 128 +---------- .../main-use-case/generate-file/helper.go | 203 ++++++++++++++++++ .../main-use-case/generate-file/tycovar.go | 4 +- internal/use-case/main-use-case/resume/lib.go | 2 +- pkg/conv-helper/conv-helper.go | 26 ++- pkg/use-case-helper/use-case-helper.go | 10 + 8 files changed, 305 insertions(+), 131 deletions(-) diff --git a/internal/domain/main-entities/person/entity.go b/internal/domain/main-entities/person/entity.go index 8d7f79a8..3c7d8629 100644 --- a/internal/domain/main-entities/person/entity.go +++ b/internal/domain/main-entities/person/entity.go @@ -10,6 +10,7 @@ import ( epi "simrs-vx/internal/domain/main-entities/person-insurance" epr "simrs-vx/internal/domain/main-entities/person-relative" er "simrs-vx/internal/domain/main-entities/regency" + "strings" erp "simrs-vx/internal/domain/references/person" @@ -58,3 +59,62 @@ func (d Person) IsSameResidentIdentityNumber(input *string) bool { } return d.ResidentIdentityNumber == input } + +func (d Person) GenderString() string { + if d.Gender_Code == nil { + return "" + } + switch *d.Gender_Code { + case erp.GCMale: + return "Laki-laki(L)" + case erp.GCFemale: + return "Perempuan(P)" + default: + return "" + } +} + +func (d Person) GetPhoneNumber() string { + if d.Contacts == nil { + return "" + } + for _, c := range *d.Contacts { + if c.Type_Code == erp.CTPhone || c.Type_Code == erp.CTMPhone { + return c.Value + } + } + return "" +} + +func (d Person) FullName() string { + name := strings.TrimSpace(d.Name) + if name == "" { + return "" + } + + parts := []string{} + + // Front title (dr., drs., etc) + if d.FrontTitle != nil { + ft := strings.TrimSpace(*d.FrontTitle) + if ft != "" { + parts = append(parts, ft) + } + } + + // Name (always included) + parts = append(parts, name) + + // Join front title + name + full := strings.Join(parts, " ") + + // End title → attach with comma + if d.EndTitle != nil { + et := strings.TrimSpace(*d.EndTitle) + if et != "" { + full = full + ", " + et + } + } + + return full +} diff --git a/internal/domain/main-entities/resume/dto.go b/internal/domain/main-entities/resume/dto.go index bf505d20..884b8e32 100644 --- a/internal/domain/main-entities/resume/dto.go +++ b/internal/domain/main-entities/resume/dto.go @@ -29,7 +29,8 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint `json:"id"` + Id uint `json:"id"` + Includes string `json:"includes"` } type UpdateDto struct { diff --git a/internal/use-case/main-use-case/generate-file/case.go b/internal/use-case/main-use-case/generate-file/case.go index 39cb2f02..7c657640 100644 --- a/internal/use-case/main-use-case/generate-file/case.go +++ b/internal/use-case/main-use-case/generate-file/case.go @@ -1,26 +1,14 @@ package generatefile import ( - "encoding/json" "errors" - evs "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" - evscl "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-control-letter" - egc "simrs-vx/internal/domain/main-entities/general-consent" - - uvs "simrs-vx/internal/use-case/bpjs-use-case/vclaim-sep" - uvscl "simrs-vx/internal/use-case/bpjs-use-case/vclaim-sep-control-letter" - ugc "simrs-vx/internal/use-case/main-use-case/general-consent" - - pc "simrs-vx/pkg/conv-helper" pl "simrs-vx/pkg/logger" - pu "simrs-vx/pkg/use-case-helper" dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" "gorm.io/gorm" - erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" ) @@ -32,133 +20,37 @@ func Generate(input GenerateDto) (*d.Data, error) { Source: source, } - var response ResponseDto + var ( + response *ResponseDto + err error + ) // Start log pl.SetLogInfo(&event, input, "started", "create") - err := dg.I.Transaction(func(tx *gorm.DB) error { + err = dg.I.Transaction(func(tx *gorm.DB) error { switch input.Type_Code { // general-consent case ere.DTCGC: - // get value from general consent by ref_id - gc, err := ugc.ReadDetailData(egc.ReadDetailDto{Id: uint(*pc.StringToUint64(*input.Ref_Id))}, &event) + response, err = generateGC(input, event, tx) if err != nil { return err } - if gc.FileUrl != nil { - if err := removeFile(string(input.EntityType_Code), *gc.FileUrl); err != nil { - return err - } - } - - // map template data - templateData := GeneralConsentPDF{} - if gc.Value != nil { - err := json.Unmarshal([]byte(*gc.Value), &templateData) - if err != nil { - event.ErrInfo = pl.ErrorInfo{ - Code: "data-unmarshal-fail", - Detail: err.Error(), - Raw: err, - } - return err - } - } else { - return errors.New("no value in this general consent") - } - - input.FormatType = erc.DFTCPDF - input.TemplateName = TDNGC - input.Encounter_Id = gc.Encounter_Id - templateData.Date = pu.FormatIndonesianDate(gc.CreatedAt) - - // generate file - urlPub, err := generateFile(input, templateData) - if err != nil { - return err - } - - gc.FileUrl = &urlPub - if err := dg.I.Save(&gc).Error; err != nil { - return err - } - - response = ResponseDto{ - FileUrl: urlPub, - } - // control-letter case ere.DTCVSCL: - // get value from control letter by ref_id - cl, err := uvscl.ReadDetailData(evscl.ReadDetailDto{Number: input.Ref_Id}, &event) - if err != nil { - if !pu.IsDataNotFoundError(err) { - return err - } - } - - if cl != nil && cl.FileUrl != nil { - if err := removeFile(string(input.EntityType_Code), *cl.FileUrl); err != nil { - return err - } - } - - // map template data - clData := VclaimControlLetter{} - if input.Data != nil { - err := json.Unmarshal([]byte(*input.Data), &clData) - if err != nil { - event.ErrInfo = pl.ErrorInfo{ - Code: "data-unmarshal-fail", - Detail: err.Error(), - Raw: err, - } - return err - } - } else { - return errors.New("there is no data to be used") - } - - if cl == nil { - createCL := evscl.CreateDto{ - VclaimSep_Number: &clData.VclaimSep.Number, - Number: &clData.Number, - Value: input.Data, - } - if cl, err = uvscl.CreateData(createCL, &event, tx); err != nil { - return err - } - - } - // get encounter id by vclaim sep number - vs, err := uvs.ReadDetailData(evs.ReadDetailDto{Number: &clData.VclaimSep.Number}, &event) + response, err = generateCL(input, event, tx) if err != nil { return err } - input.FormatType = erc.DFTCPDF - input.TemplateName = TDNCL - input.Encounter_Id = vs.Encounter_Id - input.UseA5Lanscape = true - - templateData := clData.generateTemplateData() - // generate file - urlPub, err := generateFile(input, templateData) + // resume + case ere.DTCResume: + response, err = generateResume(input, event, tx) if err != nil { return err } - cl.FileUrl = &urlPub - if err := tx.Save(&cl).Error; err != nil { - return err - } - - response = ResponseDto{ - FileUrl: urlPub, - } - default: return errors.New("invalid type code") } diff --git a/internal/use-case/main-use-case/generate-file/helper.go b/internal/use-case/main-use-case/generate-file/helper.go index 8cd3543f..e42fc13e 100644 --- a/internal/use-case/main-use-case/generate-file/helper.go +++ b/internal/use-case/main-use-case/generate-file/helper.go @@ -1,19 +1,36 @@ package generatefile import ( + "encoding/json" "errors" "fmt" "mime" "path/filepath" "time" + evs "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" + evscl "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-control-letter" + ee "simrs-vx/internal/domain/main-entities/encounter" + egc "simrs-vx/internal/domain/main-entities/general-consent" + er "simrs-vx/internal/domain/main-entities/resume" + + uvs "simrs-vx/internal/use-case/bpjs-use-case/vclaim-sep" + uvscl "simrs-vx/internal/use-case/bpjs-use-case/vclaim-sep-control-letter" + ue "simrs-vx/internal/use-case/main-use-case/encounter" + ugc "simrs-vx/internal/use-case/main-use-case/general-consent" + ur "simrs-vx/internal/use-case/main-use-case/resume" + erc "simrs-vx/internal/domain/references/common" docscfg "simrs-vx/internal/infra/docs-cfg" + pc "simrs-vx/pkg/conv-helper" pf "simrs-vx/pkg/file-helper" + pl "simrs-vx/pkg/logger" pm "simrs-vx/pkg/minio-helper" pp "simrs-vx/pkg/pdf-helper" pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" ) // generate temporary file, upload to minio, generate public url, delete temporary file @@ -93,3 +110,189 @@ func removeFile(bucket, fileUrl string) error { } return nil } + +// generate general consent +func generateGC(input GenerateDto, event pl.Event, tx *gorm.DB) (*ResponseDto, error) { + // get value from general consent by ref_id + gc, err := ugc.ReadDetailData(egc.ReadDetailDto{Id: uint(*pc.StringToUint64(*input.Ref_Id))}, &event) + if err != nil { + return nil, err + } + + if gc.FileUrl != nil { + if err := removeFile(string(input.EntityType_Code), *gc.FileUrl); err != nil { + return nil, err + } + } + + // map template data + templateData := GeneralConsentPDF{} + if gc.Value != nil { + err := json.Unmarshal([]byte(*gc.Value), &templateData) + if err != nil { + event.ErrInfo = pl.ErrorInfo{ + Code: "data-unmarshal-fail", + Detail: err.Error(), + Raw: err, + } + return nil, err + } + } else { + return nil, errors.New("no value in this general consent") + } + + input.FormatType = erc.DFTCPDF + input.TemplateName = TDNGC + input.Encounter_Id = gc.Encounter_Id + templateData.Date = pu.FormatIndonesianDate(gc.CreatedAt) + + // generate file + urlPub, err := generateFile(input, templateData) + if err != nil { + return nil, err + } + + gc.FileUrl = &urlPub + if err := tx.Save(&gc).Error; err != nil { + return nil, err + } + + response := ResponseDto{ + FileUrl: urlPub, + } + + return &response, nil +} + +func generateCL(input GenerateDto, event pl.Event, tx *gorm.DB) (*ResponseDto, error) { + // get value from control letter by ref_id + cl, err := uvscl.ReadDetailData(evscl.ReadDetailDto{Number: input.Ref_Id}, &event) + if err != nil { + if !pu.IsDataNotFoundError(err) { + return nil, err + } + } + + if cl != nil && cl.FileUrl != nil { + if err := removeFile(string(input.EntityType_Code), *cl.FileUrl); err != nil { + return nil, err + } + } + + // map template data + clData := VclaimControlLetter{} + if input.Data != nil { + err := json.Unmarshal([]byte(*input.Data), &clData) + if err != nil { + event.ErrInfo = pl.ErrorInfo{ + Code: "data-unmarshal-fail", + Detail: err.Error(), + Raw: err, + } + return nil, err + } + } else { + return nil, errors.New("there is no data to be used") + } + + if cl == nil { + createCL := evscl.CreateDto{ + VclaimSep_Number: &clData.VclaimSep.Number, + Number: &clData.Number, + Value: input.Data, + } + if cl, err = uvscl.CreateData(createCL, &event, tx); err != nil { + return nil, err + } + + } + // get encounter id by vclaim sep number + vs, err := uvs.ReadDetailData(evs.ReadDetailDto{Number: &clData.VclaimSep.Number}, &event) + if err != nil { + return nil, err + } + + input.FormatType = erc.DFTCPDF + input.TemplateName = TDNCL + input.Encounter_Id = vs.Encounter_Id + input.UseA5Lanscape = true + + templateData := clData.generateTemplateData() + // generate file + urlPub, err := generateFile(input, templateData) + if err != nil { + return nil, err + } + + cl.FileUrl = &urlPub + if err := tx.Save(&cl).Error; err != nil { + return nil, err + } + + response := ResponseDto{ + FileUrl: urlPub, + } + + return &response, nil +} + +func generateResume(input GenerateDto, event pl.Event, tx *gorm.DB) (*ResponseDto, error) { + // get value from resume by ref_id + includes := "Doctor.Employee.Person" + r, err := ur.ReadDetailData(er.ReadDetailDto{Id: uint(*pc.StringToUint64(*input.Ref_Id)), Includes: includes}, &event) + if err != nil { + return nil, err + } + + if r.FileUrl != nil { + if err := removeFile(string(input.EntityType_Code), *r.FileUrl); err != nil { + return nil, err + } + } + + response := ResponseDto{ + FileUrl: "", + } + + return &response, nil +} + +func generateResumeTemplateData(resume er.Resume, event pl.Event, tx *gorm.DB) (*ResumePDF, error) { + // get encounter + includes := "Patient,Patient.Person,Patient.Person.BirthRegency,Patient.Person.Contacts" + encounter, err := ue.ReadDetailData(ee.ReadDetailDto{Id: uint16(*resume.Encounter_Id), Includes: includes}, &event) + if err != nil { + return nil, err + } + fmt.Println(encounter) + + // map template data + rData := er.ValueDto{} + if resume.Value != nil { + err := json.Unmarshal([]byte(*resume.Value), &rData) + if err != nil { + event.ErrInfo = pl.ErrorInfo{ + Code: "data-unmarshal-fail", + Detail: err.Error(), + Raw: err, + } + return nil, err + } + } else { + return nil, errors.New("there is no data to be used") + } + templateData := ResumePDF{} + templateData.MedicalRecord = *encounter.Patient.Number + templateData.NIK = *encounter.Patient.Person.ResidentIdentityNumber + templateData.Name = encounter.Patient.Person.Name + templateData.BirthPlaceDate = pu.FormatPlaceAndDate(encounter.Patient.Person.BirthRegency.Name, *encounter.Patient.Person.BirthDate) + templateData.Gender = encounter.Patient.Person.GenderString() + templateData.Phone = encounter.Patient.Person.GetPhoneNumber() + // templateData.Class = get from vclaim sep eg. III + // templateData.Unit = get from vclaim sep eg. R.KERINCI - KLS 3 + templateData.Doctor_Name = resume.Doctor.Employee.Person.FullName() + templateData.StartedAt = *pc.TimeToStringWithFormat(encounter.StartedAt, "") + templateData.FinishedAt = *pc.TimeToStringWithFormat(encounter.FinishedAt, "") + + return &templateData, nil +} diff --git a/internal/use-case/main-use-case/generate-file/tycovar.go b/internal/use-case/main-use-case/generate-file/tycovar.go index 2bbe9fbf..1dee32ff 100644 --- a/internal/use-case/main-use-case/generate-file/tycovar.go +++ b/internal/use-case/main-use-case/generate-file/tycovar.go @@ -44,8 +44,8 @@ type ResumePDF struct { Class string Unit string Doctor_Name string - StartedDate string - FinishedDate string + StartedAt string + FinishedAt string DiagnosisIn string DiagnosisOut string Diagnosis []er.DiagnosisEntry diff --git a/internal/use-case/main-use-case/resume/lib.go b/internal/use-case/main-use-case/resume/lib.go index 16bb1afd..02a2e27a 100644 --- a/internal/use-case/main-use-case/resume/lib.go +++ b/internal/use-case/main-use-case/resume/lib.go @@ -81,7 +81,7 @@ 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/pkg/conv-helper/conv-helper.go b/pkg/conv-helper/conv-helper.go index 03063c74..9b9bc44d 100644 --- a/pkg/conv-helper/conv-helper.go +++ b/pkg/conv-helper/conv-helper.go @@ -8,6 +8,8 @@ import ( "gorm.io/gorm" ) +const StandartDateTimeFormat = "2006-01-02 15:04:05" + // check string pointer, if nil return default value func StrConvDefault(f *string, def string) string { if f == nil { @@ -96,20 +98,12 @@ func BoolToString(f *bool) *string { return &t } -func TimeToString(f *time.Time) *string { - if f == nil { - return nil - } - t := f.Format("2006-01-02 15:04:05") - return &t -} - // Handling gorm.DeletedAt func DeletedAtToString(deletedAt *gorm.DeletedAt) *string { if deletedAt == nil || !deletedAt.Valid { return nil } - return TimeToString(&deletedAt.Time) + return TimeToStringWithFormat(&deletedAt.Time, "") } func BoolToFloat64(b bool) float64 { @@ -151,3 +145,17 @@ func StringToUint64(s string) *uint64 { } return &u } + +func TimeToStringWithFormat(t *time.Time, format string) *string { + result := "" + if t == nil || t.IsZero() { + return &result + } + + if format == "" { + format = StandartDateTimeFormat + } + + result = t.Format(format) + return &result +} diff --git a/pkg/use-case-helper/use-case-helper.go b/pkg/use-case-helper/use-case-helper.go index 019f9773..7d0ec17f 100644 --- a/pkg/use-case-helper/use-case-helper.go +++ b/pkg/use-case-helper/use-case-helper.go @@ -208,3 +208,13 @@ func GetLastTwoPathSegments(s string) string { // fallback: return entire string if less than 2 segments return strings.Trim(path, "/") } + +func FormatPlaceAndDate(place string, t time.Time) string { + // Ensure place is uppercase + place = strings.ToUpper(strings.TrimSpace(place)) + + // Format date: DD-MM-YYYY + dateStr := t.Format("02-01-2006") + + return place + ", " + dateStr +} From 4109752121b22fd6220e6d2715873c4ff6128328 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 25 Nov 2025 15:53:24 +0700 Subject: [PATCH 267/329] fix (doctor): wrong code passed --- internal/use-case/main-use-case/doctor/helper.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/use-case/main-use-case/doctor/helper.go b/internal/use-case/main-use-case/doctor/helper.go index 344d1c0e..9ddc2027 100644 --- a/internal/use-case/main-use-case/doctor/helper.go +++ b/internal/use-case/main-use-case/doctor/helper.go @@ -22,6 +22,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Doctor) { data.IHS_Number = inputSrc.IHS_Number data.SIP_Number = inputSrc.SIP_Number data.Unit_Code = inputSrc.Unit_Code - data.Specialist_Code = inputSrc.Code - data.Subspecialist_Code = inputSrc.Code + data.Specialist_Code = inputSrc.Specialist_Code + data.Subspecialist_Code = inputSrc.Subspecialist_Code } From 04312afceeaeb76bdd8c26d550461ffd6630dd85 Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 25 Nov 2025 19:47:47 +0700 Subject: [PATCH 268/329] testing --- .../domain/main-entities/encounter/dto.go | 22 ++--- .../domain/references/encounter/encounter.go | 8 +- .../simgos-entities/m-polihfis/entity.go | 2 +- .../domain/simgos-entities/m-poly/entity.go | 2 +- .../simgos-entities/t-pendaftaran/entity.go | 1 - .../main-handler/encounter/handler.go | 14 +-- .../new/encounter/handler.go | 2 +- .../use-case/main-use-case/doctor/helper.go | 4 +- .../main-use-case/edu-assessment/case.go | 2 +- .../use-case/main-use-case/encounter/case.go | 21 ++-- .../main-use-case/encounter/helper.go | 3 +- .../main-use-case/therapy-protocol/case.go | 2 +- internal/use-case/main-use-case/unit/case.go | 16 +++- .../new/encounter/case.go | 54 +++++------ .../new/encounter/helper.go | 95 ++++++++++++------- .../simgos-sync-use-case/new/encounter/lib.go | 8 +- .../new/patient/helper.go | 15 +-- .../new/specialist/helper.go | 2 +- .../new/specialist/lib.go | 9 +- .../simgos-sync-use-case/new/unit/helper.go | 3 + 20 files changed, 165 insertions(+), 120 deletions(-) diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index 849a5834..d4eeda3f 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -65,15 +65,15 @@ type CreateDto struct { } type TRujukan struct { - NoSep string `json:"noSep"` + NoSep string `json:"noSep"` // Surat Eligibilitas Peserta TglRujukan string `json:"tglRujukan"` - PpkDirujuk string `json:"ppkDirujuk"` - JnsPelayanan string `json:"jnsPelayanan"` + PpkDirujuk string `json:"ppkDirujuk"` // PPK (Provider Pelayanan Kesehatan) -> kode RS tujuan + JnsPelayanan string `json:"jnsPelayanan"` // Jenis pelayanan yang dimintakan; 1 = RawatInap; 2 = RawatJalan Catatan string `json:"catatan"` - DiagRujukan string `json:"diagRujukan"` - TipeRujukan string `json:"tipeRujukan"` - PoliRujukan string `json:"poliRujukan"` - User string `json:"user"` + DiagRujukan string `json:"diagRujukan"` // Kode Diagnosa + TipeRujukan string `json:"tipeRujukan"` // 0 = Rujukan Penuh; 1 = Rujukan Partial (hanya untuk tindakan tertentu); 2 = Balik (dikembalikan ke faskes asal) + PoliRujukan string `json:"poliRujukan"` // Kode Poli Tujuan + User string `json:"user"` // user yang membuat rujukan } type ReadListDto struct { @@ -105,24 +105,24 @@ 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 } type UpdateStatusDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` StatusCode erc.DataStatusCode `json:"status_code"` pa.AuthInfo } type DeleteDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` pa.AuthInfo } diff --git a/internal/domain/references/encounter/encounter.go b/internal/domain/references/encounter/encounter.go index ca600246..a1fc3b31 100644 --- a/internal/domain/references/encounter/encounter.go +++ b/internal/domain/references/encounter/encounter.go @@ -95,10 +95,10 @@ const ( RTCPrivate RefTypeCode = "private" // Swasta RTCBpjs RefTypeCode = "bpjs" // BPJS - APMCJkn AllPaymentMethodCode = "jkn" // JKN - APMCJkmm AllPaymentMethodCode = "jkmm" // JKMM - APMCSpm AllPaymentMethodCode = "spm" // SPM - APMCPks AllPaymentMethodCode = "pks" // PKS + APMCJkn AllPaymentMethodCode = "jkn" // JKN -> Jaminan Kesehatan Nasional -> BPJS Kesehatan + APMCJkmm AllPaymentMethodCode = "jkmm" // JKMM -> Jaminan Kesehatan Masyarakat Miskin -> Dibiayai oleh APBD daerah + APMCSpm AllPaymentMethodCode = "spm" // SPM -> Surat Pernyataan Miskin + APMCPks AllPaymentMethodCode = "pks" // PKS -> Perjanjian Kerjasama -> Pembayaran melalui instansi atau perusahaan yang memiliki kontrak dengan rumah sakit APMCUmum AllPaymentMethodCode = "umum" SRTCInternal SEPRefTypeCode = "internal" // Rujukan Internal diff --git a/internal/domain/simgos-entities/m-polihfis/entity.go b/internal/domain/simgos-entities/m-polihfis/entity.go index b9eb7b56..8bed236d 100644 --- a/internal/domain/simgos-entities/m-polihfis/entity.go +++ b/internal/domain/simgos-entities/m-polihfis/entity.go @@ -1,4 +1,4 @@ -package division +package m_polihfis type MPolihfis struct { Id uint `json:"id" gorm:"primaryKey;autoIncrement;column:id"` diff --git a/internal/domain/simgos-entities/m-poly/entity.go b/internal/domain/simgos-entities/m-poly/entity.go index 52fe20eb..aff4bc1e 100644 --- a/internal/domain/simgos-entities/m-poly/entity.go +++ b/internal/domain/simgos-entities/m-poly/entity.go @@ -1,7 +1,7 @@ package m_poly type MPoly struct { - Kode uint `json:"kode" gorm:"primaryKey;autoIncrement;column:kode"` + Kode uint `json:"kode" gorm:"primaryKey;column:kode"` Nama string `json:"nama" gorm:"column:nama"` Jenispoly uint `json:"jenispoly" gorm:"column:jenispoly"` } diff --git a/internal/domain/simgos-entities/t-pendaftaran/entity.go b/internal/domain/simgos-entities/t-pendaftaran/entity.go index 682aabeb..08222653 100644 --- a/internal/domain/simgos-entities/t-pendaftaran/entity.go +++ b/internal/domain/simgos-entities/t-pendaftaran/entity.go @@ -82,7 +82,6 @@ type TPendaftaran struct { DokterNameHfis *string `json:"dokter_name_hfis" gorm:"column:dokter_name_hfis"` DokterIdHfis *string `json:"dokter_id_hfis" gorm:"column:dokter_id_hfis"` StatusBridging *string `json:"status_bridging" gorm:"column:status_bridging"` - NoSpri *string `json:"no_spri" gorm:"column:no_spri"` } func (TPendaftaran) TableName() string { diff --git a/internal/interface/main-handler/encounter/handler.go b/internal/interface/main-handler/encounter/handler.go index 0c87b7b2..688d6904 100644 --- a/internal/interface/main-handler/encounter/handler.go +++ b/internal/interface/main-handler/encounter/handler.go @@ -64,7 +64,7 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { } dto := e.ReadDetailDto{} sf.UrlQueryParam(&dto, *r.URL) - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } @@ -84,7 +84,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) dto.AuthInfo = *authInfo res, err := u.Update(dto) @@ -103,7 +103,7 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Id = uint(id) dto.AuthInfo = *authInfo res, err := u.Delete(dto) @@ -175,7 +175,7 @@ func (obj myBase) Process(w http.ResponseWriter, r *http.Request) { } dto := e.UpdateStatusDto{ - Id: uint16(id), + Id: uint(id), StatusCode: erc.DSCProcess, } @@ -195,7 +195,7 @@ func (obj myBase) Cancel(w http.ResponseWriter, r *http.Request) { } dto := e.UpdateStatusDto{ - Id: uint16(id), + Id: uint(id), StatusCode: erc.DSCCancel, } @@ -211,7 +211,7 @@ func (obj myBase) Reject(w http.ResponseWriter, r *http.Request) { } dto := e.UpdateStatusDto{ - Id: uint16(id), + Id: uint(id), StatusCode: erc.DSCRejected, } @@ -226,7 +226,7 @@ func (obj myBase) Skip(w http.ResponseWriter, r *http.Request) { } dto := e.UpdateStatusDto{ - Id: uint16(id), + Id: uint(id), StatusCode: erc.DSCSkipped, } diff --git a/internal/interface/simgos-sync-handler/new/encounter/handler.go b/internal/interface/simgos-sync-handler/new/encounter/handler.go index e6b0515a..bec44cd4 100644 --- a/internal/interface/simgos-sync-handler/new/encounter/handler.go +++ b/internal/interface/simgos-sync-handler/new/encounter/handler.go @@ -51,7 +51,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/use-case/main-use-case/doctor/helper.go b/internal/use-case/main-use-case/doctor/helper.go index 344d1c0e..9ddc2027 100644 --- a/internal/use-case/main-use-case/doctor/helper.go +++ b/internal/use-case/main-use-case/doctor/helper.go @@ -22,6 +22,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Doctor) { data.IHS_Number = inputSrc.IHS_Number data.SIP_Number = inputSrc.SIP_Number data.Unit_Code = inputSrc.Unit_Code - data.Specialist_Code = inputSrc.Code - data.Subspecialist_Code = inputSrc.Code + data.Specialist_Code = inputSrc.Specialist_Code + data.Subspecialist_Code = inputSrc.Subspecialist_Code } diff --git a/internal/use-case/main-use-case/edu-assessment/case.go b/internal/use-case/main-use-case/edu-assessment/case.go index 230f0679..525274ca 100644 --- a/internal/use-case/main-use-case/edu-assessment/case.go +++ b/internal/use-case/main-use-case/edu-assessment/case.go @@ -37,7 +37,7 @@ func Create(input e.CreateDto) (*d.Data, error) { } // validate encounter_id - _, err := ue.ReadDetail(ee.ReadDetailDto{Id: uint16(*input.Encounter_Id)}) + _, err := ue.ReadDetail(ee.ReadDetailDto{Id: *input.Encounter_Id}) if err != nil { return err } diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 25d74859..2a8ee1ba 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -118,7 +118,6 @@ func Create(input e.CreateDto) (*d.Data, error) { // insert vclaimReference if vr := input.VclaimReference; vr != nil { t, _ := time.Parse("2006-01-02", vr.TglRujukan) - _, err = uv.CreateData(ev.CreateDto{ Encounter_Id: &data.Id, Date: &t, @@ -136,8 +135,10 @@ func Create(input e.CreateDto) (*d.Data, error) { } dataEncounter, err := ReadDetailData(e.ReadDetailDto{ - Id: uint16(data.Id), - Includes: "Adm_Employee.User,Patient.Person.Relatives,Patient.Person.VclaimMember,VclaimReference"}, + Id: data.Id, + Includes: "Adm_Employee.User,Patient.Person.Relatives," + + "Patient.Person.VclaimMember,VclaimReference," + + "Patient.Person.Contacts,Patient.Person.Addresses"}, &event, tx) if err != nil { return err @@ -311,7 +312,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } dataEncounter, err := ReadDetailData(e.ReadDetailDto{ - Id: uint16(data.Id), + Id: data.Id, Includes: "Adm_Employee.User,Patient.Person.Relatives,Patient.Person.VclaimMember"}, &event, tx) if err != nil { @@ -429,7 +430,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { } func CheckOut(input e.DischargeDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Ambulatory,Rehab"} + rdDto := e.ReadDetailDto{Id: input.Id, Includes: "Ambulatory,Rehab"} var data *e.Encounter var err error @@ -516,7 +517,7 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) { } dataEncounter, err := ReadDetailData(e.ReadDetailDto{ - Id: uint16(data.Id), + Id: data.Id, Includes: "DeathCause"}, &event, tx) if err != nil { @@ -658,7 +659,7 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) { } func CheckIn(input e.CheckinDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Rehab,Ambulatory"} + rdDto := e.ReadDetailDto{Id: input.Id, Includes: "Rehab,Ambulatory"} var data *e.Encounter var err error @@ -743,7 +744,7 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { } dataEncounter, err := ReadDetailData(e.ReadDetailDto{ - Id: uint16(data.Id), + Id: data.Id, Includes: "Adm_Employee.User"}, &event, tx) if err != nil { @@ -776,7 +777,7 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) { } func RequestSwitchUnit(input e.SwitchUnitDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Responsible_Doctor"} + rdDto := e.ReadDetailDto{Id: input.Id, Includes: "Responsible_Doctor"} var data *e.Encounter var err error @@ -865,7 +866,7 @@ func RequestSwitchUnit(input e.SwitchUnitDto) (*d.Data, error) { } func ApproveSwitchUnit(input e.ApproveUnitDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Responsible_Doctor"} + rdDto := e.ReadDetailDto{Id: input.Id, Includes: "Responsible_Doctor"} var data *e.Encounter var err error diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index 3b215c36..73b053e5 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -68,6 +68,7 @@ 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 @@ -90,7 +91,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Encounter) { data.Responsible_Doctor_Code = inputSrc.Responsible_Doctor_Code data.RefSource_Name = inputSrc.RefSource_Name data.Appointment_Id = inputSrc.Appointment_Id - data.Status_Code = erc.DSCProcess data.RefType_Code = &inputSrc.RefTypeCode data.NewStatus = inputSrc.NewStatus } @@ -556,6 +556,7 @@ func getSoapiByResponsibleDoctor(enc e.Encounter, event *pl.Event) (data []es.So Code: "no responsible-doctor found", Detail: "Encounter does not have responsible-doctor", } + return nil, pl.SetLogError(event, enc) } err = dg.I. diff --git a/internal/use-case/main-use-case/therapy-protocol/case.go b/internal/use-case/main-use-case/therapy-protocol/case.go index ed4f3a21..a332d675 100644 --- a/internal/use-case/main-use-case/therapy-protocol/case.go +++ b/internal/use-case/main-use-case/therapy-protocol/case.go @@ -359,7 +359,7 @@ func Verify(input e.VerifyDto) (*d.Data, error) { func validateForeignKey(input e.CreateDto) error { // validate encounter if input.Encounter_Id != nil { - if _, err := ue.ReadDetail(ee.ReadDetailDto{Id: uint16(*input.Encounter_Id)}); err != nil { + if _, err := ue.ReadDetail(ee.ReadDetailDto{Id: *input.Encounter_Id}); err != nil { return err } } diff --git a/internal/use-case/main-use-case/unit/case.go b/internal/use-case/main-use-case/unit/case.go index 1db6fb79..c73c2c1d 100644 --- a/internal/use-case/main-use-case/unit/case.go +++ b/internal/use-case/main-use-case/unit/case.go @@ -1,6 +1,7 @@ package unit import ( + "errors" e "simrs-vx/internal/domain/main-entities/unit" erc "simrs-vx/internal/domain/references/common" esync "simrs-vx/internal/domain/sync-entities/log" @@ -27,9 +28,22 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") + + // validate unit_code + _, err := strconv.Atoi(input.Code) + if err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "invalid_code_format", + Detail: "unit_code must be a valid integer", + Raw: errors.New("invalid unit_code format"), + } + return nil, pl.SetLogError(&event, input) + } + mwRunner := newMiddlewareRunner(&event) - err := dg.I.Transaction(func(tx *gorm.DB) error { + err = dg.I.Transaction(func(tx *gorm.DB) error { if resData, err := CreateData(input, &event, tx); err != nil { return err } else { 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 6b4f7ab4..f9f48c11 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 @@ -12,8 +12,6 @@ import ( etp "simrs-vx/internal/domain/simgos-entities/t-pendaftaran" esync "simrs-vx/internal/domain/sync-entities/encounter" elog "simrs-vx/internal/domain/sync-entities/log" - - up "simrs-vx/internal/use-case/simgos-sync-use-case/new/patient" ) const source = "encounter" @@ -46,14 +44,8 @@ func Create(input e.Encounter) (*d.Data, error) { return err } - // STEP: 3 Get MPasien - dataPatient, err := up.ReadDetailSimgosByNomrData(sgData.Nomr, &event, tx.Simgos) - if err != nil { - return err - } - - // STEP 4: Update MPasien - err = updatePatient(*dataPatient, &event, tx.Simgos) + // STEP 3: Update MPasien + err = updatePatientCaraBayar(*sgData, &event, tx.Simgos) if err != nil { return err } @@ -123,13 +115,13 @@ func Update(input e.Encounter) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "update") // STEP 1: Get Link - syncLink, err := ReadDetailLinkData(uint16(input.Id), &event) + syncLink, err := ReadDetailLinkData(input.Id, &event) if err != nil { return nil, err } // STEP 2: Get Simgos - simgos, err := ReadTPendaftaranDetailData(uint16(syncLink.Simgos_Id), &event) + simgos, err := ReadTPendaftaranDetailData(syncLink.Simgos_Id, &event) if err != nil { return nil, err } @@ -137,7 +129,7 @@ func Update(input e.Encounter) (*d.Data, error) { tx := db.NewTx() err = tx.Simgos.Transaction(func(tx *gorm.DB) error { // Step 2: Update Simgos - if err = UpdateTPendaftaranData(input, *simgos, "update", &event, tx); err != nil { + if err = UpdateTPendaftaranData(input, simgos, "update", &event, tx); err != nil { return err } @@ -173,7 +165,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { } // STEP 2: Get Simgos - sgData, err := ReadTPendaftaranDetailData(uint16(syncLink.Simgos_Id), &event) + sgData, err := ReadTPendaftaranDetailData(syncLink.Simgos_Id, &event) if err != nil { return nil, err } @@ -226,13 +218,13 @@ func CheckIn(input e.Encounter) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "check-in") // STEP 1: Get Link - syncLink, err := ReadDetailLinkData(uint16(input.Id), &event) + syncLink, err := ReadDetailLinkData(input.Id, &event) if err != nil { return nil, err } // STEP 2: Get Simgos - simgos, err := ReadTPendaftaranDetailData(uint16(syncLink.Simgos_Id), &event) + simgos, err := ReadTPendaftaranDetailData(syncLink.Simgos_Id, &event) if err != nil { return nil, err } @@ -240,7 +232,7 @@ func CheckIn(input e.Encounter) (*d.Data, error) { tx := db.NewTx() err = tx.Simgos.Transaction(func(tx *gorm.DB) error { // Step 2: Update Simgos - if err = UpdateTPendaftaranData(input, *simgos, "check-in", &event, tx); err != nil { + if err = UpdateTPendaftaranData(input, simgos, "check-in", &event, tx); err != nil { return err } @@ -268,13 +260,13 @@ func CheckOut(input e.Encounter) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "check-out") // STEP 1: Get Link - syncLink, err := ReadDetailLinkData(uint16(input.Id), &event) + syncLink, err := ReadDetailLinkData(input.Id, &event) if err != nil { return nil, err } // STEP 2: Get Simgos - simgos, err := ReadTPendaftaranDetailData(uint16(syncLink.Simgos_Id), &event) + simgos, err := ReadTPendaftaranDetailData(syncLink.Simgos_Id, &event) if err != nil { return nil, err } @@ -282,7 +274,7 @@ func CheckOut(input e.Encounter) (*d.Data, error) { tx := db.NewTx() err = tx.Simgos.Transaction(func(tx *gorm.DB) error { // Step 2: Update Simgos - if err = UpdateTPendaftaranData(input, *simgos, "check-out", &event, tx); err != nil { + if err = UpdateTPendaftaranData(input, simgos, "check-out", &event, tx); err != nil { return err } @@ -310,13 +302,13 @@ func Cancel(input e.Encounter) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "cancel") // STEP 1: Get Link - syncLink, err := ReadDetailLinkData(uint16(input.Id), &event) + syncLink, err := ReadDetailLinkData(input.Id, &event) if err != nil { return nil, err } // STEP 2: Get Simgos - simgos, err := ReadTPendaftaranDetailData(uint16(syncLink.Simgos_Id), &event) + simgos, err := ReadTPendaftaranDetailData(syncLink.Simgos_Id, &event) if err != nil { return nil, err } @@ -324,7 +316,7 @@ func Cancel(input e.Encounter) (*d.Data, error) { tx := db.NewTx() err = tx.Simgos.Transaction(func(tx *gorm.DB) error { // Step 2: Update Simgos - if err = UpdateTPendaftaranData(input, *simgos, "update-status", &event, tx); err != nil { + if err = UpdateTPendaftaranData(input, simgos, "update-status", &event, tx); err != nil { return err } @@ -352,13 +344,13 @@ func RequestSwitchUnit(input e.Encounter) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "request-switch-unit") // STEP 1: Get Link - syncLink, err := ReadDetailLinkData(uint16(input.Id), &event) + syncLink, err := ReadDetailLinkData(input.Id, &event) if err != nil { return nil, err } // STEP 2: Get Simgos - tpendaftaran, err := ReadTPendaftaranDetailData(uint16(syncLink.Simgos_Id), &event) + tpendaftaran, err := ReadTPendaftaranDetailData(syncLink.Simgos_Id, &event) if err != nil { return nil, err } @@ -366,12 +358,12 @@ func RequestSwitchUnit(input e.Encounter) (*d.Data, error) { tx := db.NewTx() err = tx.Simgos.Transaction(func(tx *gorm.DB) error { // Step 2: Update TPendaftaran - if err = UpdateTPendaftaranData(input, *tpendaftaran, "update-status", &event, tx); err != nil { + if err = UpdateTPendaftaranData(input, tpendaftaran, "update-status", &event, tx); err != nil { return err } // Step 3: Insert TPemeriksaanHist - if _, err := CreateBulkTPemeriksaanHistData(input, *tpendaftaran, &event, tx); err != nil { + if _, err := CreateBulkTPemeriksaanHistData(input, tpendaftaran, &event, tx); err != nil { return err } @@ -399,13 +391,13 @@ func ApproveSwitchUnit(input e.Encounter) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "request-switch-unit") // STEP 1: Get Link - syncLink, err := ReadDetailLinkData(uint16(input.Id), &event) + syncLink, err := ReadDetailLinkData(input.Id, &event) if err != nil { return nil, err } // STEP 2: Get Simgos - tpendaftaran, err := ReadTPendaftaranDetailData(uint16(syncLink.Simgos_Id), &event) + tpendaftaran, err := ReadTPendaftaranDetailData(syncLink.Simgos_Id, &event) if err != nil { return nil, err } @@ -413,12 +405,12 @@ func ApproveSwitchUnit(input e.Encounter) (*d.Data, error) { tx := db.NewTx() err = tx.Simgos.Transaction(func(tx *gorm.DB) error { // Step 2: Update TPendaftaran - if err = UpdateTPendaftaranData(input, *tpendaftaran, "update-status", &event, tx); err != nil { + if err = UpdateTPendaftaranData(input, tpendaftaran, "update-status", &event, tx); err != nil { return err } // Step 3: Insert TPemeriksaanHist - if _, err := CreateBulkTPemeriksaanHistData(input, *tpendaftaran, &event, tx); err != nil { + if _, err := CreateBulkTPemeriksaanHistData(input, tpendaftaran, &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 a64a0c4e..fe1d5b42 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,7 +6,7 @@ package encounter import ( "encoding/json" - epr "simrs-vx/internal/domain/main-entities/person-relative" + epa "simrs-vx/internal/domain/main-entities/person-address" erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" erp "simrs-vx/internal/domain/references/person" @@ -14,6 +14,8 @@ import ( "strconv" e "simrs-vx/internal/domain/main-entities/encounter" + 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" etp "simrs-vx/internal/domain/simgos-entities/t-pendaftaran" @@ -47,20 +49,29 @@ func setDataCreateTPendaftaran(input *e.Encounter) (data etp.TPendaftaran, err e } data.NoKunjung = uint(noKunjung) - setDataTPendaftaran(input, data) + if p := input.Patient.Person; p != nil { + mapRelative(p.Relatives, &data) + + if data.PenanggungjawabNama == "" { + data.PenanggungjawabHubungan = "DIRI SENDIRI" + data.PenanggungjawabNama = p.Name + mapContact(p.Contacts, &data) + mapAddress(p.Addresses, &data) + } + + if bpjs := p.VclaimMember; bpjs != nil { + data.Nokartu = *bpjs.CardNumber + } + } + + setDataTPendaftaran(input, &data) return } -func setDataTPendaftaran(input *e.Encounter, data etp.TPendaftaran) { +func setDataTPendaftaran(input *e.Encounter, data *etp.TPendaftaran) { data.Tglreg = input.RegisteredAt - // set kddokter - if d := input.Appointment_Doctor_Code; d != nil { - kddokter, _ := strconv.Atoi(*input.Appointment_Doctor_Code) - data.Kddokter = uint(kddokter) - } - // set kdpoly if p := input.Unit_Code; p != nil { kdpoly, _ := strconv.Atoi(*input.Unit_Code) @@ -82,22 +93,18 @@ func setDataTPendaftaran(input *e.Encounter, data etp.TPendaftaran) { } } - if ref := input.VclaimReference; ref != nil { - data.Ketrujuk = *ref.SrcCode - data.Norujukan = *ref.Number - data.Tglrujukan = ref.Date + // set data if payment_method bpjs + if input.RefSource_Name != nil { + data.Ketrujuk = *input.RefSource_Name data.Strujukan = 1 } else { data.Ketrujuk = "TR" data.Strujukan = 0 } - if p := input.Patient.Person; p != nil { - mapRelative(p.Relatives, data) - - if bpjs := p.VclaimMember; bpjs != nil { - data.Nokartu = *bpjs.CardNumber - } + if ref := input.VclaimReference; ref != nil { + data.Norujukan = *ref.Number + data.Tglrujukan = ref.Date } data.Jamreg = input.RegisteredAt @@ -107,7 +114,7 @@ func setDataTPendaftaran(input *e.Encounter, data etp.TPendaftaran) { return } -func setDataCheckIn(input e.Encounter, data etp.TPendaftaran) { +func setDataCheckIn(input e.Encounter, data *etp.TPendaftaran) { // set kddokter kddokter, _ := strconv.Atoi(*input.Responsible_Doctor_Code) data.Kddokter = uint(kddokter) @@ -125,7 +132,7 @@ func setDataCheckIn(input e.Encounter, data etp.TPendaftaran) { return } -func setDataRequestSwitchUnit(input e.Encounter, data etp.TPendaftaran) (hist []etph.TPemeriksaanHist) { +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{ @@ -151,7 +158,7 @@ func setDataRequestSwitchUnit(input e.Encounter, data etp.TPendaftaran) (hist [] return } -func setDataCheckOut(input e.Encounter, data etp.TPendaftaran) { +func setDataCheckOut(input e.Encounter, data *etp.TPendaftaran) { data.Keluarpoly = input.Discharge_Date // set status @@ -169,13 +176,13 @@ func setDataCheckOut(input e.Encounter, data etp.TPendaftaran) { return } -func setDataUpdateStatus(input e.Encounter, data etp.TPendaftaran) { +func setDataUpdateStatus(input e.Encounter, data *etp.TPendaftaran) { if input.Status_Code == erc.DSCCancel { data.Status = 11 } } -func setKdrujuk(input *ere.RefTypeCode, data etp.TPendaftaran) { +func setKdrujuk(input *ere.RefTypeCode, data *etp.TPendaftaran) { switch *input { case ere.RTCGov: data.Kdrujuk = 1 @@ -188,7 +195,7 @@ func setKdrujuk(input *ere.RefTypeCode, data etp.TPendaftaran) { } } -func setKdcarabayar(input ere.AllPaymentMethodCode, data etp.TPendaftaran) { +func setKdcarabayar(input ere.AllPaymentMethodCode, data *etp.TPendaftaran) { switch input { case ere.APMCPks: data.Kdcarabayar = 12 @@ -203,7 +210,7 @@ func setKdcarabayar(input ere.AllPaymentMethodCode, data etp.TPendaftaran) { } } -func setStatus(code *ere.DischargeMethodCode, data etp.TPendaftaran) { +func setStatus(code *ere.DischargeMethodCode, data *etp.TPendaftaran) { switch *code { case ere.DMCHome: data.Status = 1 @@ -250,7 +257,7 @@ func setStatus(code *ere.DischargeMethodCode, data etp.TPendaftaran) { } } -func mapRelative(relative *[]epr.PersonRelative, data etp.TPendaftaran) { +func mapRelative(relative *[]epr.PersonRelative, data *etp.TPendaftaran) { if relative == nil || len(*relative) == 0 { return } @@ -322,10 +329,11 @@ func generateNoKunjung() (int, error) { // Lock rows for this prefix → prevents race condition if err := dg.IS["simrs"]. Table("t_pendaftaran"). - Select("COALESCE(MAX(no_kunjung),0)"). + Select("no_kunjung"). Where("tglreg = CURRENT_DATE"). Order("no_kunjung DESC"). Clauses(clause.Locking{Strength: "UPDATE"}). + Limit(1). Scan(&lastNumber).Error; err != nil { return 0, err } @@ -339,7 +347,7 @@ func stringtouint(v string) *uint { return &point } -func updatePatient(patient ep.MPasien, event *pl.Event, dbx ...*gorm.DB) error { +func updatePatientCaraBayar(input etp.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, nil, "started", "DBUpdate") var tx *gorm.DB @@ -350,9 +358,9 @@ func updatePatient(patient ep.MPasien, event *pl.Event, dbx ...*gorm.DB) error { } if err := tx.Model(&ep.MPasien{}). - Where("\"nomr\" = ?", patient.Nomr). + Where("\"nomr\" = ?", input.Nomr). Updates(map[string]interface{}{ - "kdcarabayar": patient.Kdcarabayar, + "kdcarabayar": input.Kdcarabayar, }).Error; err != nil { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ @@ -360,9 +368,30 @@ func updatePatient(patient ep.MPasien, event *pl.Event, dbx ...*gorm.DB) error { Detail: "Failed to update patient", Raw: err, } - return pl.SetLogError(event, patient) + return pl.SetLogError(event, input) } - pl.SetLogInfo(event, patient, "complete") + pl.SetLogInfo(event, input, "complete") return nil } + +func mapContact(contact *[]epc.PersonContact, data *etp.TPendaftaran) { + if contact == nil || len(*contact) == 0 { + return + } + + for _, c := range *contact { + if c.Type_Code == erp.CTPhone || c.Type_Code == erp.CTMPhone { + data.PenanggungjawabPhone = c.Value + break + } + } +} + +func mapAddress(addresses *[]epa.PersonAddress, data *etp.TPendaftaran) { + if addresses == nil || len(*addresses) == 0 { + return + } + a := (*addresses)[0] + data.PenanggungjawabAlamat = a.Address +} 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 064131e5..3312193d 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 @@ -41,7 +41,7 @@ func CreateTPendaftaranData(input e.Encounter, event *pl.Event, dbx ...*gorm.DB) return &data, nil } -func ReadTPendaftaranDetailData(simgosId uint16, event *pl.Event) (*etp.TPendaftaran, error) { +func ReadTPendaftaranDetailData(simgosId uint, event *pl.Event) (*etp.TPendaftaran, error) { pl.SetLogInfo(event, simgosId, "started", "DBReadDetail") data := etp.TPendaftaran{} @@ -59,7 +59,7 @@ func ReadTPendaftaranDetailData(simgosId uint16, event *pl.Event) (*etp.TPendaft return &data, nil } -func UpdateTPendaftaranData(input e.Encounter, data etp.TPendaftaran, method string, event *pl.Event, dbx ...*gorm.DB) error { +func UpdateTPendaftaranData(input e.Encounter, data *etp.TPendaftaran, method string, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, input, "started", "DBUpdate") switch method { @@ -138,7 +138,7 @@ func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*e return &data, nil } -func ReadDetailLinkData(simxId uint16, event *pl.Event) (*esync.EncounterLink, error) { +func ReadDetailLinkData(simxId uint, event *pl.Event) (*esync.EncounterLink, error) { pl.SetLogInfo(event, simxId, "started", "DBReadDetail") data := esync.EncounterLink{} @@ -199,7 +199,7 @@ 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 CreateBulkTPemeriksaanHistData(input e.Encounter, data *etp.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) (hist []etph.TPemeriksaanHist, err error) { pl.SetLogInfo(event, nil, "started", "DBCreate") hist = setDataRequestSwitchUnit(input, data) diff --git a/internal/use-case/simgos-sync-use-case/new/patient/helper.go b/internal/use-case/simgos-sync-use-case/new/patient/helper.go index 14f516d5..532574b2 100644 --- a/internal/use-case/simgos-sync-use-case/new/patient/helper.go +++ b/internal/use-case/simgos-sync-use-case/new/patient/helper.go @@ -37,12 +37,15 @@ func setDataSimgos(input *e.Patient) (data esimgos.MPasien) { mapContact(input.Person.Contacts, &data) } - data.PenanggungjawabHubungan = "DIRI SENDIRI" - data.PenanggungjawabNama = input.Person.Name - data.PenanggungjawabPhone = data.Notelp - data.PenanggungjawabAlamat = data.Alamat - if input.Person != nil || input.Person.Relatives != nil { - mapRelative(input.Person.Relatives, &data) + if input.Person != nil { + data.PenanggungjawabHubungan = "DIRI SENDIRI" + data.PenanggungjawabNama = input.Person.Name + data.PenanggungjawabPhone = data.Notelp + data.PenanggungjawabAlamat = data.Alamat + + if input.Person.Relatives != nil { + mapRelative(input.Person.Relatives, &data) + } } data.Nip = input.RegisteredBy_User_Name diff --git a/internal/use-case/simgos-sync-use-case/new/specialist/helper.go b/internal/use-case/simgos-sync-use-case/new/specialist/helper.go index 4a155496..adce079f 100644 --- a/internal/use-case/simgos-sync-use-case/new/specialist/helper.go +++ b/internal/use-case/simgos-sync-use-case/new/specialist/helper.go @@ -14,7 +14,7 @@ import ( esync "simrs-vx/internal/domain/sync-entities/specialist" ) -func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MPolihfis) { +func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T, data *esimgos.MPolihfis) { var inputSrc *e.CreateDto if inputT, ok := any(input).(*e.CreateDto); ok { inputSrc = inputT diff --git a/internal/use-case/simgos-sync-use-case/new/specialist/lib.go b/internal/use-case/simgos-sync-use-case/new/specialist/lib.go index c796af73..0aee2ceb 100644 --- a/internal/use-case/simgos-sync-use-case/new/specialist/lib.go +++ b/internal/use-case/simgos-sync-use-case/new/specialist/lib.go @@ -20,7 +20,8 @@ var now = time.Now() func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esimgos.MPolihfis, error) { pl.SetLogInfo(event, nil, "started", "DBCreate") - data := setDataSimgos(&input) + data := esimgos.MPolihfis{} + setDataSimgos(&input, &data) var tx *gorm.DB if len(dbx) > 0 { @@ -29,7 +30,7 @@ func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esi tx = dg.IS["simrs"] } - if err := tx.Create(&data).Error; err != nil { + if err := tx.Debug().Create(&data).Error; err != nil { return nil, plh.HandleCreateError(input, event, err) } @@ -58,7 +59,9 @@ func ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.MPolihfis, func UpdateSimgosData(input e.UpdateDto, dataSimgos *esync.SpecialistLink, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, input, "started", "DBUpdate") - data := setDataSimgos(&input) + data := esimgos.MPolihfis{} + + setDataSimgos(&input, &data) data.Id = dataSimgos.Simgos_Id var tx *gorm.DB diff --git a/internal/use-case/simgos-sync-use-case/new/unit/helper.go b/internal/use-case/simgos-sync-use-case/new/unit/helper.go index 667bb7f0..d7dfb1f6 100644 --- a/internal/use-case/simgos-sync-use-case/new/unit/helper.go +++ b/internal/use-case/simgos-sync-use-case/new/unit/helper.go @@ -7,6 +7,7 @@ package unit import ( "encoding/json" erc "simrs-vx/internal/domain/references/common" + "strconv" e "simrs-vx/internal/domain/main-entities/unit" @@ -27,6 +28,8 @@ func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MPoly) data.Nama = inputSrc.Name data.Jenispoly = 0 + kodePoly, _ := strconv.Atoi(inputSrc.Code) + data.Kode = uint(kodePoly) return } From dfce53946bba40a46f8047f6755fe376e914fbc6 Mon Sep 17 00:00:00 2001 From: vanilia Date: Tue, 25 Nov 2025 19:53:37 +0700 Subject: [PATCH 269/329] add nurse in encounter --- cmd/main-migration/migrations/20251125125303.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 5 +++-- internal/domain/main-entities/encounter/entity.go | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 cmd/main-migration/migrations/20251125125303.sql diff --git a/cmd/main-migration/migrations/20251125125303.sql b/cmd/main-migration/migrations/20251125125303.sql new file mode 100644 index 00000000..56d16371 --- /dev/null +++ b/cmd/main-migration/migrations/20251125125303.sql @@ -0,0 +1,2 @@ +-- Modify "Encounter" table +ALTER TABLE "public"."Encounter" ADD COLUMN "Responsible_Nurse_Code" character varying(20) NULL, ADD CONSTRAINT "fk_Encounter_Responsible_Nurse" FOREIGN KEY ("Responsible_Nurse_Code") REFERENCES "public"."Nurse" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 707ee3ca..719dffff 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:87NyL1nIRuVvOiLbfdC1+PF+v2R/joAnBYyh2CrlGdU= +h1:u2pc+PayIbiG5HRFUzun7cApIwlt9SMNTl74DtPz1xg= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -128,4 +128,5 @@ h1:87NyL1nIRuVvOiLbfdC1+PF+v2R/joAnBYyh2CrlGdU= 20251120005512.sql h1:Ek6qpacAI/qVuTYxKno+uJyzn7s5z9pf3t7VA8gTzm4= 20251120074415.sql h1:NNUeJVA03EeBHJhHqPXEZoDv/PnC6yK1/cRhmukyaJo= 20251121033803.sql h1:/vfvFX/3pzSCIHnSbMUT9EMBDykOpVkvyfeTEle9Vas= -20251124071457.sql h1:HBaNJQIzUe6wK8CgBxamuKor7ZiAASzgkkXzL6kWsjY= +20251124071457.sql h1:qg2dhCL9YwD13xnfJ175lW/p6MGfzFKaBqd908FByRc= +20251125125303.sql h1:P94UsZOeo7b0r2yLoSGBfj0+PcMTf4Y10lF+Rl9FxAE= diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index 61496f9e..08f3aa89 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -20,6 +20,7 @@ import ( eip "simrs-vx/internal/domain/main-entities/inpatient" ei "simrs-vx/internal/domain/main-entities/insurance-company" eir "simrs-vx/internal/domain/main-entities/internal-reference" + en "simrs-vx/internal/domain/main-entities/nurse" ep "simrs-vx/internal/domain/main-entities/patient" er "simrs-vx/internal/domain/main-entities/rehab/base" es "simrs-vx/internal/domain/main-entities/specialist" @@ -77,6 +78,8 @@ type Encounter struct { EncounterDocuments *[]eed.EncounterDocument `json:"encounterDocuments,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` GeneralConsents *[]egc.GeneralConsent `json:"generalConsents,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` VclaimReference *evr.VclaimReference `json:"vclaimReference,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + Responsible_Nurse_Code *string `json:"responsible_nurse_code"` + Responsible_Nurse *en.Nurse `json:"responsible_nurse,omitempty" gorm:"foreignKey:Responsible_Nurse_Code;references:Code"` } func (d Encounter) IsDone() bool { From 8360da06c861556b416692e42e7f973ab7c5a2ed Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Tue, 25 Nov 2025 21:04:28 +0700 Subject: [PATCH 270/329] dev: hotfix, soaoi minor filtering --- internal/domain/main-entities/soapi/dto.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/domain/main-entities/soapi/dto.go b/internal/domain/main-entities/soapi/dto.go index 3edc18e3..94094df7 100644 --- a/internal/domain/main-entities/soapi/dto.go +++ b/internal/domain/main-entities/soapi/dto.go @@ -62,7 +62,7 @@ type ResponseDto struct { Employee_Id *uint `json:"employee_id"` Employee *eem.Employee `json:"employee,omitempty"` Time *time.Time `json:"time"` - TypeCode erc.SoapiTypeCode `json:"typeCode"` + TypeCode erc.SoapiTypeCode `json:"type-code"` Value *string `json:"value"` } From 94dbb8624f431daab0b0499fb0a0ffc450752346 Mon Sep 17 00:00:00 2001 From: vanilia Date: Wed, 26 Nov 2025 13:41:26 +0700 Subject: [PATCH 271/329] adjust table internalreference --- .../migrations/20251126064057.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 5 +++-- .../internal-reference/entity.go | 19 +++++++++++++------ internal/domain/references/common/common.go | 1 + 4 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 cmd/main-migration/migrations/20251126064057.sql diff --git a/cmd/main-migration/migrations/20251126064057.sql b/cmd/main-migration/migrations/20251126064057.sql new file mode 100644 index 00000000..fd823ff9 --- /dev/null +++ b/cmd/main-migration/migrations/20251126064057.sql @@ -0,0 +1,2 @@ +-- Modify "InternalReference" table +ALTER TABLE "public"."InternalReference" ADD COLUMN "SrcDoctor_Code" character varying(20) NULL, ADD COLUMN "SrcNurse_Code" character varying(20) NULL, ADD COLUMN "Nurse_Code" character varying(20) NULL, ADD CONSTRAINT "fk_InternalReference_Nurse" FOREIGN KEY ("Nurse_Code") REFERENCES "public"."Nurse" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_InternalReference_SrcDoctor" FOREIGN KEY ("SrcDoctor_Code") REFERENCES "public"."Doctor" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_InternalReference_SrcNurse" FOREIGN KEY ("SrcNurse_Code") REFERENCES "public"."Nurse" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 719dffff..363efe04 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:u2pc+PayIbiG5HRFUzun7cApIwlt9SMNTl74DtPz1xg= +h1:U9vdficFramvwnH40psSuRxzUuq6EPJwLcr9MvVTq7s= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -129,4 +129,5 @@ h1:u2pc+PayIbiG5HRFUzun7cApIwlt9SMNTl74DtPz1xg= 20251120074415.sql h1:NNUeJVA03EeBHJhHqPXEZoDv/PnC6yK1/cRhmukyaJo= 20251121033803.sql h1:/vfvFX/3pzSCIHnSbMUT9EMBDykOpVkvyfeTEle9Vas= 20251124071457.sql h1:qg2dhCL9YwD13xnfJ175lW/p6MGfzFKaBqd908FByRc= -20251125125303.sql h1:P94UsZOeo7b0r2yLoSGBfj0+PcMTf4Y10lF+Rl9FxAE= +20251125125303.sql h1:4JSFv1Pmhbe9tqpLXgO63OwYnGsalStgUXKVWPyc1YE= +20251126064057.sql h1:+lByIo0zAsHVSFzQGVMuymFQajyl7fRNqgs9d/76y+E= diff --git a/internal/domain/main-entities/internal-reference/entity.go b/internal/domain/main-entities/internal-reference/entity.go index ae6307bb..90859710 100644 --- a/internal/domain/main-entities/internal-reference/entity.go +++ b/internal/domain/main-entities/internal-reference/entity.go @@ -5,15 +5,22 @@ import ( ecore "simrs-vx/internal/domain/base-entities/core" ed "simrs-vx/internal/domain/main-entities/doctor" + en "simrs-vx/internal/domain/main-entities/nurse" eu "simrs-vx/internal/domain/main-entities/unit" ) type InternalReference struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Unit_Code *string `json:"unit_code"` - Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` - Doctor_Code *string `json:"doctor_code"` - Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"` - Status_Code *erc.DataApprovalCode `json:"status_code"` + Encounter_Id *uint `json:"encounter_id"` + Unit_Code *string `json:"unit_code"` + Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` + Doctor_Code *string `json:"doctor_code"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"` + Status_Code *erc.DataApprovalCode `json:"status_code"` + SrcDoctor_Code *string `json:"srcDoctor_code"` + SrcDoctor *ed.Doctor `json:"srcDoctor,omitempty" gorm:"foreignKey:SrcDoctor_Code;references:Code"` + SrcNurse_Code *string `json:"srcNurse_code"` + SrcNurse *en.Nurse `json:"srcNurse,omitempty" gorm:"foreignKey:SrcNurse_Code;references:Code"` + Nurse_Code *string `json:"nurse_code"` + Nurse *en.Nurse `json:"nurse,omitempty" gorm:"foreignKey:Nurse_Code;references:Code"` } diff --git a/internal/domain/references/common/common.go b/internal/domain/references/common/common.go index 96febd75..3a449057 100644 --- a/internal/domain/references/common/common.go +++ b/internal/domain/references/common/common.go @@ -106,6 +106,7 @@ const ( DACNew DataApprovalCode = "new" DACApproved DataApprovalCode = "approved" DACRejected DataApprovalCode = "rejected" + DACCanceled DataApprovalCode = "canceled" PSCSuccess ProcessStatusCode = "success" PSCFailed ProcessStatusCode = "failed" From 04add70ac5018780f859b1fd5356a6336e88abf2 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Wed, 26 Nov 2025 17:23:48 +0700 Subject: [PATCH 272/329] feat (generate-file): resume table is done --- assets/docs/resume.html | 531 +++++++++++++----- internal/domain/main-entities/resume/dto.go | 10 +- .../interface/main-handler/resume/handler.go | 10 + .../main-use-case/generate-file/helper.go | 41 +- .../main-use-case/generate-file/tycovar.go | 13 + 5 files changed, 452 insertions(+), 153 deletions(-) diff --git a/assets/docs/resume.html b/assets/docs/resume.html index 8cdca672..db66314d 100644 --- a/assets/docs/resume.html +++ b/assets/docs/resume.html @@ -7,26 +7,40 @@ body { padding: 2rem 3rem; } + table { width: 100%; border-collapse: collapse } + td { vertical-align: top; } - .border-table, .border-table td, .border-table th { + + .border-table, + .border-table td, + .border-table th { border: 1px solid black; } - .section-title { + + .section-title { margin-top: 1rem; margin-bottom: 0rem; } - .data-label { + + .data-label { width: 9rem; } - .data-colon { - width: 0.1234rem; + + .data-colon { + width: 15px; padding-left: 10px; } + + .description-label { + font-size: 0.7rem; + margin: 0; + } + @@ -60,7 +74,7 @@
          - Keluhan Utama + Tindakan Medis : {{ .Repalcable }}

          - +
          : - {{ .Repalcable }} + {{ .MedicalRecord }} Ruang/Klinik : - {{ .Repalcable }} + {{ .Unit }} NIK : - {{ .Repalcable }} + {{ .NIK }} Kelas : - {{ .Repalcable }} + {{ .Class }} Nama : - {{ .Repalcable }} + {{ .Name }} DPJP : - {{ .Repalcable }} + {{ .Doctor_Name }} - + @@ -121,21 +135,21 @@ Tempat/Tanggal Lahir : - {{ .Repalcable }} + {{ .BirthPlaceDate }} Jenis Kelamin : - {{ .Repalcable }} + {{ .Gender }} No. Telepon : - {{ .Repalcable }} + {{ .Phone }} @@ -165,32 +179,33 @@ Tanggal Masuk : - {{ .Repalcable }} + {{ .StartedAt }} Tanggal Keluar : - {{ .Repalcable }} + {{ .FinishedAt }} Diagnosis Masuk : - {{ .Repalcable }} + {{ .DiagnosisIn }} Diagnosis Keluar : - {{ .Repalcable }} + {{ .DiagnosisOut }} - +
          + - - - - - - - - - - - - - - - - - - -
          No @@ -205,31 +220,46 @@ Kode ICD-10
          - 1 - {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          - 2 - {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          - 3 - {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          + + + {{ $dataLen := len .Diagnosis }} + {{ if gt $dataLen 0 }} + + {{ range $index, $diagnosis := .Diagnosis }} + + {{ if eq $index 0 }}1{{ else if eq $index 1 }}2{{ else if eq $index 2 }}3{{ else if eq $index 3 }}4{{ else if eq $index 4 }}5{{ else }}{{ $index }}{{ end }} + {{ $diagnosis.DiagnosisName }} + {{ $diagnosis.Basis }} + {{ $diagnosis.ICD10 }} + + {{ end }} + + + {{ if eq $dataLen 1 }} + + 2 + + + + + {{ end }} + {{ else }} + + + 1 + + + + + + 2 + + + + + {{ end }} + + @@ -237,50 +267,54 @@ -

          Kajian Awal Medis

          +

          Kajian Awal Medis

          (Diisi oleh Dokter Penanggung Jawab Pelayanan)

          - + ">(Diisi oleh Dokter Penanggung Jawab Pelayanan)

          + - + - + - +
          Keluhan Utama : {{ .Repalcable }}{{ .MainComplaint }}
          Riwayat Penyakit : {{ .Repalcable }}{{ .MedicalHistory }}
          Pemeriksaan Fisik & Keadaan Umum : {{ .Repalcable }}{{ .PhysicalExamination }}
          -

          Pemeriksaan Penunjang

          +

          Pemeriksaan Penunjang

          - +
          Pemeriksaan : {{ .Repalcable }}{{ .SupportingExamination }}
          -

          Tindakan Medis

          - +
          + + +

          Tindakan Medis

          + + - - - - - - - - - - - - - - - - - - -
          No @@ -295,31 +329,47 @@ Kode ICD 9-CM
          - 1 - {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          - 2 - {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          - 3 - {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          + + + {{ $dataLen := len .MedicalActions }} + {{ if gt $dataLen 0 }} + + {{ range $index, $action := .MedicalActions }} + + {{ if eq $index 0 }}1{{ else if eq $index 1 }}2{{ else if eq $index 2 }}3{{ else if eq $index 3 }}4{{ else if eq $index 4 }}5{{ else }}{{ $index }}{{ end }} + {{ $action.Action }} + {{ $action.Basis }} + {{ $action.ICD9 }} + + {{ end }} + + + {{ if eq $dataLen 1 }} + + 2 + + + + + {{ end }} + {{ else }} + + + 1 + + + + + + 2 + + + + + {{ end }} + + + @@ -327,51 +377,53 @@ Tindakan Medis - +
          : {{ .Repalcable }}{{ .MedicalAction }}
          + + +
          +

          Konsultasi

          +
          + + + + + + + + + + {{ $dataLen := len .Consultations }} + {{ if gt $dataLen 0 }} + + {{ range $index, $consultation := .Consultations }} + + + + + + {{ end }} + + + {{ if eq $dataLen 1 }} + + {{ end }} + {{ else }} + + + + {{ end }} + +
          NoKonsultasiJawaban Konsultasi
          {{ if eq $index 0 }}1{{ else if eq $index 1 }}2{{ else if eq $index 2 }}3{{ else if eq $index 3 }}4{{ else if eq $index 4 }}5{{ else }}{{ $index }}{{ end }}{{ $consultation.Consultation }}{{ $consultation.ConsultationAnswer }}
          2
          1
          2
          + + -

          Konsultasi

          - - - - - - - - - - - - - - - - - - - - - -
          - No - - Konsultasi - - Jawaban Konsultasi -
          - 1 - {{ .Repalcable }}{{ .Repalcable }}
          - 2 - {{ .Repalcable }}{{ .Repalcable }}
          - 3 - {{ .Repalcable }}{{ .Repalcable }}
          - -

          Terapi

          +

          Terapi

          @@ -379,54 +431,241 @@ : - Replace + {{ .Allergy}}
          - -

          Obat yang diberikan

          - +
          - - - - - - - - - - - - - - + +
          - Terapi (Farmakologi & Non Farmakologi) Selawa Perawatan - - Terapi (Farmakologi & Non Farmakologi) Selawa Pulang -
          {{ .Repalcable }}{{ .Repalcable }}
          {{ .Repalcable }}{{ .Repalcable }}
          {{ .Repalcable }}{{ .Repalcable }} +

          Obat yang diberikan

          + + + + + + + + + + + + + + + + + +
          + Terapi (Farmakologi & Non Farmakologi) Selawa Perawatan + + Terapi (Farmakologi & Non Farmakologi) Selawa Pulang +
          {{ .NIK }}{{ .NIK }}
          {{ .NIK }}{{ .NIK }}
          {{ .NIK }}{{ .NIK }}
          +
          + -

          Kondisi saat Pulang

          +

          Kondisi saat Pulang

          - + - + + + + + + + + + + + + + + + + + + + + +
          - Keluhan Utama - Kesadaran : {{ .Repalcable }}{{ .ConsciousnessLevel }}
          + Tanda Vital +

          Vital sign

          +
          :
          + + + + + + +
          + + + + + + + + + + + + + + + + + + + +
          + Tekanan Darah +

          Blood Pressure

          +
          : {{ .BloodPressure }} mmHg +
          + Suhu +

          Temperatur

          +
          : {{ .BodyTemperature }} C +
          + Nadi +

          Pulse

          +
          : {{ .HeartRate }} x/Menit
          +
          + + + + + + + + + + + + + + +
          + Frekuensi Nafas +

          Respiratory rate

          +
          : {{ .RespirationRate }}
          + Skala Nyeri +

          Pain Scale

          +
          : {{ .PainScale }}
          +
          + +
          Keadaan Keluar: {{ .ConditionOnDischarge }}
          Cara Keluar +

          Patient discharge of hospital

          +
          :{{ .DischargeMethod }}
          + + + + + + + + + + + + + + + + + + + + + + + +
          +

          INSTRUKSI UNTUK TINDAK LANJUT

          +

          Follow up Consultation to

          +
          +

          Kontrol Ke

          +

          Follow up Consultation to

          +
          + + + + + + + + + + + + + + + + +
          Fasyankes: {{ .NIK }}
          Tanggal: {{ .NIK }}
          Klinik: {{ .NIK }}
          +
          +

          Dalam keadaan darurat dapat menghubungi

          +

          In case of emergencycontact

          +
          +

          IGD

          +

          (Accident & Emergency Instalation)

          +
          + + + + + + +
          Telepon +

          Phone

          +
          : (0341) 362101
          +
          +

          EDUKASI & RENCANA TINDAK LANJUT

          +

          Follow up plan (if necessary)

          +
          +

          +

          (bila diperlukan)

          +
          + + + + + + + + + + + + + +
          + Malang, {{ .Date }}
          + Dokter Penanggung Jawab Pelayanan +
          + ({{ .Doctor_Name }}) +
          +
          +

          *) Data dapat berubah setelah pasien pulang sesuai prosedur

          + \ No newline at end of file diff --git a/internal/domain/main-entities/resume/dto.go b/internal/domain/main-entities/resume/dto.go index 884b8e32..76e959e5 100644 --- a/internal/domain/main-entities/resume/dto.go +++ b/internal/domain/main-entities/resume/dto.go @@ -96,7 +96,7 @@ type Assessment struct { StartedAt *time.Time `json:"startedAt` FinishedAt *time.Time `json:"finishedAt` Doctor_Code string `json:"doctor_code` - DiagnosisIn string `json:"diagnosesIn` + DiagnosisIn string `json:"diagnosisIn` AmbulatoryIndication string `json:"ambulatoryIndication"` MainComplaint string `json:"mainComplaint"` PhysicalExamination string `json:"physicalExamination"` @@ -106,13 +106,13 @@ type Assessment struct { type Diagnosis struct { PrimaryDiagnosis DiagnosisEntry `json:"primaryDiagnosis"` - SecondaryDiagnoses []DiagnosisEntry `json:"secondaryDiagnoses"` + SecondaryDiagnosis []DiagnosisEntry `json:"secondaryDiagnosis"` } type DiagnosisEntry struct { - Diagnosis string `json:"diagnosis"` - ICD10 string `json:"icd_10"` - Basis string `json:"basis"` // Clinical basis of diagnosis / dasar diagnosa + DiagnosisName string `json:"diagnosis"` + ICD10 string `json:"icd_10"` + Basis string `json:"basis"` // Clinical basis of diagnosis / dasar diagnosa } type Action struct { diff --git a/internal/interface/main-handler/resume/handler.go b/internal/interface/main-handler/resume/handler.go index 5574bc7a..9a59f5fd 100644 --- a/internal/interface/main-handler/resume/handler.go +++ b/internal/interface/main-handler/resume/handler.go @@ -52,6 +52,10 @@ func GetDetail(w http.ResponseWriter, r *http.Request) { } func Update(w http.ResponseWriter, r *http.Request) { + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } id := rw.ValidateInt(w, "id", r.PathValue("id")) if id <= 0 { return @@ -62,11 +66,16 @@ func Update(w http.ResponseWriter, r *http.Request) { return } dto.Id = uint(id) + dto.AuthInfo = *authInfo res, err := u.Update(dto) rw.DataResponse(w, res, err) } func Delete(w http.ResponseWriter, r *http.Request) { + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } id := rw.ValidateInt(w, "id", r.PathValue("id")) if id <= 0 { return @@ -74,6 +83,7 @@ func Delete(w http.ResponseWriter, r *http.Request) { dto := e.DeleteDto{} dto.Id = uint(id) + dto.AuthInfo = *authInfo res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/use-case/main-use-case/generate-file/helper.go b/internal/use-case/main-use-case/generate-file/helper.go index e42fc13e..02800c3a 100644 --- a/internal/use-case/main-use-case/generate-file/helper.go +++ b/internal/use-case/main-use-case/generate-file/helper.go @@ -250,8 +250,28 @@ func generateResume(input GenerateDto, event pl.Event, tx *gorm.DB) (*ResponseDt } } + templateData, err := generateResumeTemplateData(*r, event, tx) + if err != nil { + return nil, err + } + + input.FormatType = erc.DFTCPDF + input.TemplateName = TDNR + input.Encounter_Id = r.Encounter_Id + + // generate file + urlPub, err := generateFile(input, templateData) + if err != nil { + return nil, err + } + + r.FileUrl = &urlPub + if err := tx.Save(&r).Error; err != nil { + return nil, err + } + response := ResponseDto{ - FileUrl: "", + FileUrl: urlPub, } return &response, nil @@ -264,7 +284,6 @@ func generateResumeTemplateData(resume er.Resume, event pl.Event, tx *gorm.DB) ( if err != nil { return nil, err } - fmt.Println(encounter) // map template data rData := er.ValueDto{} @@ -293,6 +312,24 @@ func generateResumeTemplateData(resume er.Resume, event pl.Event, tx *gorm.DB) ( templateData.Doctor_Name = resume.Doctor.Employee.Person.FullName() templateData.StartedAt = *pc.TimeToStringWithFormat(encounter.StartedAt, "") templateData.FinishedAt = *pc.TimeToStringWithFormat(encounter.FinishedAt, "") + templateData.DiagnosisIn = rData.Assessment.DiagnosisIn + templateData.Diagnosis = rData.Diagnosis.SecondaryDiagnosis + templateData.MainComplaint = rData.Assessment.MainComplaint + templateData.MedicalHistory = rData.Assessment.MedicalHistory + templateData.PhysicalExamination = rData.Assessment.PhysicalExamination + templateData.SupportingExamination = rData.Supporting.Notes + templateData.MedicalActions = rData.Action.AdditionalActions + templateData.MedicalAction = rData.Action.MedicalActions + templateData.Consultations = rData.Consultation.Consultations + templateData.Allergy = rData.Pharmacy.AllergySpecialConditions + templateData.ConsciousnessLevel = rData.Discharge.ConsciousnessLevel + templateData.BloodPressure = fmt.Sprintf("%.0f/%.0f", rData.Discharge.BloodPressureSystolic, rData.Discharge.BloodPressureDiastolic) + templateData.BodyTemperature = rData.Discharge.BodyTemperature + templateData.RespirationRate = rData.Discharge.RespirationRate + templateData.HeartRate = rData.Discharge.HeartRate + templateData.PainScale = rData.Discharge.PainScale + templateData.ConditionOnDischarge = rData.Management.ConditionOnDischarge + templateData.DischargeMethod = rData.Management.DischargeMethod return &templateData, nil } diff --git a/internal/use-case/main-use-case/generate-file/tycovar.go b/internal/use-case/main-use-case/generate-file/tycovar.go index 1dee32ff..d1d1ed6a 100644 --- a/internal/use-case/main-use-case/generate-file/tycovar.go +++ b/internal/use-case/main-use-case/generate-file/tycovar.go @@ -57,6 +57,18 @@ type ResumePDF struct { MedicalAction string Consultations []er.ConsultationEntry Allergy string + ConsciousnessLevel string + BloodPressure string + BodyTemperature float64 + RespirationRate float64 + HeartRate float64 + PainScale int + ConditionOnDischarge string + DischargeMethod string + // fasyankes + // date + // klinik + Date string } type GenerateDto struct { @@ -110,6 +122,7 @@ type TemplateDocsName string const ( TDNGC TemplateDocsName = "general-consent.html" TDNCL TemplateDocsName = "control-letter.html" + TDNR TemplateDocsName = "resume.html" ) func (v VclaimControlLetter) generateTemplateData() ControlLetterPDF { From f2bedd0de88d9506cd67bda027323e5141f40268 Mon Sep 17 00:00:00 2001 From: vanilia Date: Wed, 26 Nov 2025 18:56:30 +0700 Subject: [PATCH 273/329] add internalreference sync --- .../migrations/20251126115527.sql | 36 +++++++++++++++++++ .../migrations/atlas.sum | 7 ++-- .../internal-reference/entity.go | 29 +++++++++++++++ .../migration/simgossync-entities.go | 4 +++ 4 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 cmd/simgos-sync-migration/migrations/20251126115527.sql create mode 100644 internal/domain/sync-entities/internal-reference/entity.go diff --git a/cmd/simgos-sync-migration/migrations/20251126115527.sql b/cmd/simgos-sync-migration/migrations/20251126115527.sql new file mode 100644 index 00000000..49ca1e5c --- /dev/null +++ b/cmd/simgos-sync-migration/migrations/20251126115527.sql @@ -0,0 +1,36 @@ +-- Create "InternalReferenceLink" table +CREATE TABLE "public"."InternalReferenceLink" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Simx_Id" bigint NULL, + "Simgos_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_InternalReferenceLink_Simgos_Id" UNIQUE ("Simgos_Id"), + CONSTRAINT "uni_InternalReferenceLink_Simx_Id" UNIQUE ("Simx_Id") +); +-- Create "InternalReferenceSimgosLog" table +CREATE TABLE "public"."InternalReferenceSimgosLog" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Value" text NULL, + "Date" timestamptz NULL, + "Status" text NULL, + "ErrMessage" text NULL, + PRIMARY KEY ("Id") +); +-- Create "InternalReferenceSimxLog" table +CREATE TABLE "public"."InternalReferenceSimxLog" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Value" text NULL, + "Date" timestamptz NULL, + "Status" text NULL, + "ErrMessage" text NULL, + PRIMARY KEY ("Id") +); diff --git a/cmd/simgos-sync-migration/migrations/atlas.sum b/cmd/simgos-sync-migration/migrations/atlas.sum index 07e5fbaf..497ac414 100644 --- a/cmd/simgos-sync-migration/migrations/atlas.sum +++ b/cmd/simgos-sync-migration/migrations/atlas.sum @@ -1,6 +1,7 @@ -h1:keVmwgYtvwxSqkq+7nB0BA25JFYRAVBpBBu5eA4Q9Hw= +h1:UdPzQZ17yyNN9HVuyrFFHj5KjLj4m6/e7s9frkdpQVU= 20251113035508.sql h1:rjDlu6yDdy5xv6nrCOr7NialrLSLT23pzduYNq29Hf0= 20251114071129.sql h1:Z0GQ5bJo3C+tplaWzxT8n3J9HLkEaVsRVp5nn7bmYow= 20251117041601.sql h1:l/RPG5mObqCSBjO4mzG+wTq2ieSycvlfOSz4czpUdWY= -20251118082246.sql h1:VFnYls2DBC8tJm2aw0iBcbWGLsKezYdOHJJV9iS7MjI= -20251118082915.sql h1:tAm67fXrH+8IJCjKbJroIqc1uQyqCnuGJnQtLmw7D20= +20251118082246.sql h1:xLUwA+EvKWIg3X/TJvu7rqbtBzONiINfag5NJpMV29E= +20251118082915.sql h1:hP6FmUVFuADIN2cDg2Z1l7Wx7PQRb+IYQDvKD7J8VAM= +20251126115527.sql h1:+2bp2nWTTqaPpKKfy5ZYSr6b1nEUXFG3tIw4r3OEnAQ= diff --git a/internal/domain/sync-entities/internal-reference/entity.go b/internal/domain/sync-entities/internal-reference/entity.go new file mode 100644 index 00000000..567e6489 --- /dev/null +++ b/internal/domain/sync-entities/internal-reference/entity.go @@ -0,0 +1,29 @@ +package internal_reference + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + erc "simrs-vx/internal/domain/references/common" + "time" +) + +type InternalReferenceLink struct { + ecore.Main + Simx_Id uint `json:"simx_id" gorm:"unique"` + Simgos_Id uint `json:"simgos_id" gorm:"unique"` +} + +type InternalReferenceSimxLog struct { + ecore.Main + Value *string `json:"value"` + Date *time.Time `json:"date"` + Status erc.ProcessStatusCode `json:"status"` + ErrMessage *string `json:"errMessage"` +} + +type InternalReferenceSimgosLog struct { + ecore.Main + Value *string `json:"value"` + Date *time.Time `json:"date"` + Status erc.ProcessStatusCode `json:"status"` + ErrMessage *string `json:"errMessage"` +} diff --git a/internal/interface/migration/simgossync-entities.go b/internal/interface/migration/simgossync-entities.go index b10c8607..7b37a842 100644 --- a/internal/interface/migration/simgossync-entities.go +++ b/internal/interface/migration/simgossync-entities.go @@ -5,6 +5,7 @@ import ( division "simrs-vx/internal/domain/sync-entities/division" encounter "simrs-vx/internal/domain/sync-entities/encounter" installation "simrs-vx/internal/domain/sync-entities/installation" + internalreference "simrs-vx/internal/domain/sync-entities/internal-reference" patient "simrs-vx/internal/domain/sync-entities/patient" specialist "simrs-vx/internal/domain/sync-entities/specialist" subspecialist "simrs-vx/internal/domain/sync-entities/subspecialist" @@ -34,5 +35,8 @@ func getSyncEntities() []any { &encounter.EncounterLink{}, &encounter.EncounterSimxLog{}, &encounter.EncounterSimgosLog{}, + &internalreference.InternalReferenceLink{}, + &internalreference.InternalReferenceSimxLog{}, + &internalreference.InternalReferenceSimgosLog{}, } } From f13a45119b75446a075e13b8696f60508ac12c73 Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 27 Nov 2025 11:43:42 +0700 Subject: [PATCH 274/329] fix import sequential --- internal/use-case/simgos-sync-use-case/new/encounter/helper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 1d48ea97..bbbc8687 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,7 +6,6 @@ package encounter import ( "encoding/json" - epa "simrs-vx/internal/domain/main-entities/person-address" erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" erp "simrs-vx/internal/domain/references/person" @@ -14,6 +13,7 @@ import ( "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" From 7c454a7c0d2c0803f3244b9b2217eb3b6442daba Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 27 Nov 2025 12:04:52 +0700 Subject: [PATCH 275/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 114 ++++++++++++------------ 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 363efe04..449ff1d4 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:U9vdficFramvwnH40psSuRxzUuq6EPJwLcr9MvVTq7s= +h1:Y8m8OmsumTaAfXfYYXHlZS0+OqbAqFfM3a55nmibOUE= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,59 +75,59 @@ h1:U9vdficFramvwnH40psSuRxzUuq6EPJwLcr9MvVTq7s= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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:+lByIo0zAsHVSFzQGVMuymFQajyl7fRNqgs9d/76y+E= +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= From abfbc568b03efcda6c77768a0924996d382346f4 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 27 Nov 2025 13:30:45 +0700 Subject: [PATCH 276/329] feat (generate-file) hopefully resume.html doesnt make any trouble --- assets/docs/resume.html | 94 +++++++++++++------ internal/domain/main-entities/resume/dto.go | 10 ++ .../main-use-case/generate-file/helper.go | 2 + .../main-use-case/generate-file/tycovar.go | 1 + 4 files changed, 78 insertions(+), 29 deletions(-) diff --git a/assets/docs/resume.html b/assets/docs/resume.html index db66314d..4ad209ff 100644 --- a/assets/docs/resume.html +++ b/assets/docs/resume.html @@ -438,35 +438,55 @@ + + + + + + {{ end }} + {{ else }} + + + + + + + + + + {{ end }} + +
          +

          Obat yang diberikan

          + + + + + + + + + {{ $dataLen := len .Medications }} + + {{ if gt $dataLen 0 }} + + {{ range .Medications }} - + + + {{ end }} -
          + Terapi (Farmakologi & Non Farmakologi) Selama Perawatan + + Terapi (Farmakologi & Non Farmakologi) Waktu Pulang +
          -

          Obat yang diberikan

          - - - - - - - - - - - - - - - - - -
          - Terapi (Farmakologi & Non Farmakologi) Selawa Perawatan - - Terapi (Farmakologi & Non Farmakologi) Selawa Pulang -
          {{ .NIK }}{{ .NIK }}
          {{ .NIK }}{{ .NIK }}
          {{ .NIK }}{{ .NIK }}
          -
          {{ .DuringTreatment }}{{ .AtDischarge }}
          + + {{ if eq $dataLen 1 }} +
            
            
            
          + + + @@ -501,7 +521,11 @@

          Blood Pressure

          : + {{ if and .BloodPressure (ne .BloodPressure "0/0") (ne .BloodPressure "") }} {{ .BloodPressure }} mmHg + {{ else }} + + {{ end }} @@ -512,7 +536,11 @@ : - {{ .BodyTemperature }} C + {{ if ne .BodyTemperature 0.0 }} + {{ .BodyTemperature }} C + {{ else }} + + {{ end }} @@ -521,7 +549,11 @@

          Pulse

          : - {{ .HeartRate }} x/Menit + {{ if ne .HeartRate 0.0 }} + {{ .HeartRate }} x/Menit + {{ else }} + + {{ end }} @@ -535,7 +567,11 @@ : - {{ .RespirationRate }} + {{ if ne .RespirationRate 0.0 }} + {{ .RespirationRate }} x/Menit + {{ else }} + + {{ end }} diff --git a/internal/domain/main-entities/resume/dto.go b/internal/domain/main-entities/resume/dto.go index 76e959e5..e7ddf09b 100644 --- a/internal/domain/main-entities/resume/dto.go +++ b/internal/domain/main-entities/resume/dto.go @@ -90,6 +90,7 @@ type ValueDto struct { Discharge DischargeCondition `json:"discharge"` National NationalProgram `json:"national"` Management Management `json:"management"` + Medication Medication `json:"medication"` } type Assessment struct { @@ -170,3 +171,12 @@ type Management struct { ConditionOnDischarge string `json:"conditionOnDischarge"` // e.g. "Stable" DischargeMethod string `json:"dischargeMethod"` // e.g. "Discharged with Doctor's Approval" } + +type MedicationEntry struct { + DuringTreatment string `json:"duringTreatment"` + AtDischarge string `json:"atDischarge"` +} + +type Medication struct { + Medications []MedicationEntry `json:"medications"` +} diff --git a/internal/use-case/main-use-case/generate-file/helper.go b/internal/use-case/main-use-case/generate-file/helper.go index 02800c3a..1f0d0bfd 100644 --- a/internal/use-case/main-use-case/generate-file/helper.go +++ b/internal/use-case/main-use-case/generate-file/helper.go @@ -330,6 +330,8 @@ func generateResumeTemplateData(resume er.Resume, event pl.Event, tx *gorm.DB) ( templateData.PainScale = rData.Discharge.PainScale templateData.ConditionOnDischarge = rData.Management.ConditionOnDischarge templateData.DischargeMethod = rData.Management.DischargeMethod + templateData.Medications = rData.Medication.Medications + templateData.Date = pu.GetTimeNow().Format("02-01-2006") return &templateData, nil } diff --git a/internal/use-case/main-use-case/generate-file/tycovar.go b/internal/use-case/main-use-case/generate-file/tycovar.go index d1d1ed6a..a242f476 100644 --- a/internal/use-case/main-use-case/generate-file/tycovar.go +++ b/internal/use-case/main-use-case/generate-file/tycovar.go @@ -65,6 +65,7 @@ type ResumePDF struct { PainScale int ConditionOnDischarge string DischargeMethod string + Medications []er.MedicationEntry // fasyankes // date // klinik From 2a393015635f30b428241495ce0ef32ed99fe54e Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Fri, 28 Nov 2025 16:10:35 +0700 Subject: [PATCH 277/329] feat (vclaim-sep): create, read, delete done --- cmd/bpjs-api/config.yml-example | 3 - cmd/main-api/config.yml-example | 3 - .../domain/bpjs-entities/vclaim-sep/dto.go | 141 +++++++++++++++++- .../bpjs-entities/vclaim-sep/entitiy.go | 1 + .../domain/main-entities/encounter/entity.go | 2 +- .../interface/bpjs-handler/bpjs-handler.go | 14 +- .../interface/main-handler/main-handler.go | 48 +++++- .../member/handler.go | 0 .../monitoring/handler.go | 0 .../reference/handler.go | 0 .../interface/main-handler/resume/handler.go | 6 - .../vclaim-sep-hist/handler.go | 0 .../vclaim-sep-print/handler.go | 0 .../vclaim-sep/handler.go | 56 ++++--- .../use-case/bpjs-plugin/vclaim-sep/plugin.go | 81 +++++++++- .../bpjs-plugin/vclaim-sep/tycovar.go | 2 + .../use-case/bpjs-use-case/vclaim-sep/case.go | 22 ++- .../use-case/bpjs-use-case/vclaim-sep/lib.go | 3 + .../vclaim-sep/middleware-runner.go | 2 +- .../bpjs-use-case/vclaim-sep/middleware.go | 7 +- .../bpjs-use-case/vclaim-sep/tycovar.go | 10 +- .../main-use-case/generate-file/helper.go | 4 + .../use-case/main-use-case/resume/case.go | 9 +- .../use-case/main-use-case/resume/helper.go | 4 +- 24 files changed, 343 insertions(+), 75 deletions(-) rename internal/interface/{bpjs-handler => main-handler}/member/handler.go (100%) rename internal/interface/{bpjs-handler => main-handler}/monitoring/handler.go (100%) rename internal/interface/{bpjs-handler => main-handler}/reference/handler.go (100%) rename internal/interface/{bpjs-handler => main-handler}/vclaim-sep-hist/handler.go (100%) rename internal/interface/{bpjs-handler => main-handler}/vclaim-sep-print/handler.go (100%) rename internal/interface/{bpjs-handler => main-handler}/vclaim-sep/handler.go (55%) diff --git a/cmd/bpjs-api/config.yml-example b/cmd/bpjs-api/config.yml-example index 60b1644c..dcea2f07 100644 --- a/cmd/bpjs-api/config.yml-example +++ b/cmd/bpjs-api/config.yml-example @@ -57,9 +57,6 @@ corsCfg: satuSehatCfg: host: localhost:8200 -bpjsCfg: - host: localhost:8200 - corsCfg: allowedOrigins: - http://example.com diff --git a/cmd/main-api/config.yml-example b/cmd/main-api/config.yml-example index 30351abf..3423b5d1 100644 --- a/cmd/main-api/config.yml-example +++ b/cmd/main-api/config.yml-example @@ -57,9 +57,6 @@ corsCfg: satuSehatCfg: host: localhost:8200 -bpjsCfg: - host: localhost:8200 - corsCfg: allowedOrigins: - http://example.com diff --git a/internal/domain/bpjs-entities/vclaim-sep/dto.go b/internal/domain/bpjs-entities/vclaim-sep/dto.go index 8a174688..2f4475b5 100644 --- a/internal/domain/bpjs-entities/vclaim-sep/dto.go +++ b/internal/domain/bpjs-entities/vclaim-sep/dto.go @@ -1,6 +1,7 @@ package vclaimsep import ( + "encoding/json" ecore "simrs-vx/internal/domain/base-entities/core" evsh "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-hist" ) @@ -8,7 +9,7 @@ import ( type CreateDto struct { Encounter_Id *uint `json:"encounter_id"` Number *string `json:"number" validate:"maxLength=19"` - RequestPayload []byte `json:"requestPayload" validate:"maxLength=1024"` + RequestPayload string `json:"requestPayload" validate:"maxLength=1024"` VclaimSepHist evsh.CreateDto } @@ -25,8 +26,9 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint `json:"id"` - Number *string `json:"number"` + Id uint `json:"id"` + Number *string `json:"number"` + Encounter_Id *uint `json:"encounter_id"` } type UpdateDto struct { @@ -47,14 +49,16 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Number *string `json:"number"` + Encounter_Id *uint `json:"encounter_id"` + Number *string `json:"number"` + Detail *SepDetail `json:"detail,omitempty"` } func (d VclaimSep) ToResponse() ResponseDto { resp := ResponseDto{ Encounter_Id: d.Encounter_Id, Number: d.Number, + Detail: d.Detail, } resp.Main = d.Main return resp @@ -71,3 +75,130 @@ func ToResponseList(data []VclaimSep) []ResponseDto { func (c CreateDto) IsMessageSuccess() bool { return c.VclaimSepHist.Message == "Sukses" } + +func (c CreateDto) RequestPayloadIntoJson() ([]byte, error) { + payload := map[string]interface{}{} + err := json.Unmarshal([]byte(c.RequestPayload), &payload) + if err != nil { + return nil, err + } + return json.Marshal(payload) +} + +func (c CreateDto) RequestPayloadWithEncounterId() ([]byte, error) { + payload := map[string]interface{}{} + + err := json.Unmarshal([]byte(c.RequestPayload), &payload) + if err != nil { + return nil, err + } + + payload["encounter_id"] = c.Encounter_Id + + return json.Marshal(payload) +} + +type SepResponse struct { + MetaData MetaData `json:"metaData"` + Response *SepDetail `json:"response"` +} + +type MetaData struct { + Code string `json:"code"` + Message string `json:"message"` +} + +type SepDetail struct { + AssestmenPel AssestmenPel `json:"assestmenPel"` + Catatan string `json:"catatan"` + Cob string `json:"cob"` + Diagnosa string `json:"diagnosa"` + Dpjp Dpjp `json:"dpjp"` + ESep string `json:"eSEP"` + FlagProcedure FlagProcedure `json:"flagProcedure"` + Informasi any `json:"informasi"` // null = interface{} + JnsPelayanan string `json:"jnsPelayanan"` + Katarak string `json:"katarak"` + KdPenunjang KdPenunjang `json:"kdPenunjang"` + KdStatusKecelakaan string `json:"kdStatusKecelakaan"` + KelasRawat string `json:"kelasRawat"` + KlsRawat KlsRawat `json:"klsRawat"` + Kontrol Kontrol `json:"kontrol"` + LokasiKejadian LokasiKejadian `json:"lokasiKejadian"` + NmStatusKecelakaan string `json:"nmstatusKecelakaan"` + NoRujukan string `json:"noRujukan"` + NoSep string `json:"noSep"` + Penjamin any `json:"penjamin"` // null + Peserta Peserta `json:"peserta"` + Poli string `json:"poli"` + PoliEksekutif string `json:"poliEksekutif"` + TglSep string `json:"tglSep"` + TujuanKunj TujuanKunj `json:"tujuanKunj"` +} + +type AssestmenPel struct { + Kode string `json:"kode"` + Nama string `json:"nama"` +} + +type Dpjp struct { + KdDPJP string `json:"kdDPJP"` + NmDPJP string `json:"nmDPJP"` +} + +type FlagProcedure struct { + Kode string `json:"kode"` + Nama string `json:"nama"` +} + +type KdPenunjang struct { + Kode string `json:"kode"` + Nama string `json:"nama"` +} + +type KlsRawat struct { + KlsRawatHak string `json:"klsRawatHak"` + KlsRawatNaik *string `json:"klsRawatNaik"` // nullable + Pembiayaan *string `json:"pembiayaan"` // nullable + PenanggungJawab *string `json:"penanggungJawab"` // nullable +} + +type Kontrol struct { + KdDokter *string `json:"kdDokter"` // null + NmDokter *string `json:"nmDokter"` // null + NoSurat *string `json:"noSurat"` // null +} + +type LokasiKejadian struct { + KdKab *string `json:"kdKab"` + KdKec *string `json:"kdKec"` + KdProp *string `json:"kdProp"` + KetKejadian *string `json:"ketKejadian"` + Lokasi *string `json:"lokasi"` + TglKejadian *string `json:"tglKejadian"` +} + +type Peserta struct { + Asuransi any `json:"asuransi"` + HakKelas string `json:"hakKelas"` + JnsPeserta string `json:"jnsPeserta"` + Kelamin string `json:"kelamin"` + Nama string `json:"nama"` + NoKartu string `json:"noKartu"` + NoMR string `json:"noMr"` + TglLahir string `json:"tglLahir"` +} + +type TujuanKunj struct { + Kode string `json:"kode"` + Nama string `json:"nama"` +} + +type SepDeleteRequest struct { + Request struct { + TSep struct { + NoSep string `json:"noSep"` + User string `json:"user"` + } `json:"t_sep"` + } `json:"request"` +} diff --git a/internal/domain/bpjs-entities/vclaim-sep/entitiy.go b/internal/domain/bpjs-entities/vclaim-sep/entitiy.go index f175e4cb..6948d640 100644 --- a/internal/domain/bpjs-entities/vclaim-sep/entitiy.go +++ b/internal/domain/bpjs-entities/vclaim-sep/entitiy.go @@ -12,4 +12,5 @@ type VclaimSep struct { Number *string `json:"number" gorm:"unique;size:19"` Prints []*evsp.VclaimSepPrint `json:"prints,omitempty" gorm:"foreignKey:VclaimSep_Number;references:Number"` ControlLetters []*evscl.VclaimSepControlLetter `json:"controlLetters,omitempty" gorm:"foreignKey:VclaimSep_Number;references:Number"` + Detail *SepDetail `json:"detail,omitempty" gorm:"-"` } diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index a3908149..5584819b 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -87,5 +87,5 @@ func (d Encounter) IsSameResponsibleDoctor(input *string) bool { if input == nil { return false } - return d.Responsible_Doctor_Code == input + return *d.Responsible_Doctor_Code == *input } diff --git a/internal/interface/bpjs-handler/bpjs-handler.go b/internal/interface/bpjs-handler/bpjs-handler.go index 175bb667..4f000664 100644 --- a/internal/interface/bpjs-handler/bpjs-handler.go +++ b/internal/interface/bpjs-handler/bpjs-handler.go @@ -4,12 +4,12 @@ import ( "net/http" /******************** main / transaction ********************/ - member "simrs-vx/internal/interface/bpjs-handler/member" - monitoring "simrs-vx/internal/interface/bpjs-handler/monitoring" - reference "simrs-vx/internal/interface/bpjs-handler/reference" - vclaimsep "simrs-vx/internal/interface/bpjs-handler/vclaim-sep" - vclaimsephist "simrs-vx/internal/interface/bpjs-handler/vclaim-sep-hist" - vclaimsepprint "simrs-vx/internal/interface/bpjs-handler/vclaim-sep-print" + member "simrs-vx/internal/interface/main-handler/member" + monitoring "simrs-vx/internal/interface/main-handler/monitoring" + reference "simrs-vx/internal/interface/main-handler/reference" + vclaimsep "simrs-vx/internal/interface/main-handler/vclaim-sep" + vclaimsephist "simrs-vx/internal/interface/main-handler/vclaim-sep-hist" + vclaimsepprint "simrs-vx/internal/interface/main-handler/vclaim-sep-print" /******************** actor ********************/ @@ -49,7 +49,7 @@ func SetRoutes() http.Handler { hk.GroupRoutes("/v1/vclaim-sep", r, hk.MapHandlerFunc{ "POST /": vclaimsep.O.Create, - "PATCH /{id}": vclaimsep.O.Update, + "PATCH /{id}": vclaimsep.O.GetDetail, "DELETE /{id}": vclaimsep.O.Delete, }) diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index a4f6e382..d374a8a8 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -120,9 +120,17 @@ import ( regency "simrs-vx/internal/interface/main-handler/regency" village "simrs-vx/internal/interface/main-handler/village" - ///// Internal + /******************** Internal ********************/ validation "simrs-vx/internal/interface/main-handler/helper/validation" "simrs-vx/internal/interface/main-handler/home" + + /******************** BPJS ********************/ + member "simrs-vx/internal/interface/main-handler/member" + monitoring "simrs-vx/internal/interface/main-handler/monitoring" + reference "simrs-vx/internal/interface/main-handler/reference" + vclaimsep "simrs-vx/internal/interface/main-handler/vclaim-sep" + vclaimsephist "simrs-vx/internal/interface/main-handler/vclaim-sep-hist" + vclaimsepprint "simrs-vx/internal/interface/main-handler/vclaim-sep-print" ) // One place route to relatively easier to manage, ESPECIALLY in tracking @@ -138,6 +146,7 @@ func SetRoutes() http.Handler { a.RegisterExtCall(validation.RegisterValidation) a.RegisterExtCall(simgossync.SetConfig) a.RegisterExtCall(docscfg.ParseCfg) + a.RegisterExtCall(ibpjs.SetConfig) r := http.NewServeMux() @@ -371,6 +380,43 @@ func SetRoutes() http.Handler { hc.RegCrudByCode(r, "/v1/province", province.O) hc.RegCrudByCode(r, "/v1/postal-region", postalregion.O) + /******************** BPJS ********************/ + hk.GroupRoutes("/v1/vclaim-sep", r, hk.MapHandlerFunc{ + "POST /": vclaimsep.O.Create, + "GET /{id}": vclaimsep.O.GetDetail, + "DELETE /{id}": vclaimsep.O.Delete, + }) + + hk.GroupRoutes("/v1/vclaim-sep-hist", r, hk.MapHandlerFunc{ + "GET /": vclaimsephist.O.GetList, + }) + + hk.GroupRoutes("/v1/vclaim-sep-print", r, hk.MapHandlerFunc{ + "POST /": vclaimsepprint.O.Create, + }) + + hk.GroupRoutes("/v1/reference", r, hk.MapHandlerFunc{ + "GET /province": reference.GetListProvince, + "GET /regency/{provinceCode}": reference.GetListCities, + "GET /district/{regencyCode}": reference.GetListDistrict, + "GET /diagnose/{keyword}": reference.GetListDiagnose, + "GET /diagnose-prb": reference.GetListDiagnosePrb, + "GET /medicine-prb/{keyword}": reference.GetListMedicinePrb, + "GET /unit/{unitCode}": reference.GetListUnit, + "GET /healthcare/{healthcare}/{healthcareType}": reference.GetListHealthcare, + "GET /responsible-doctor/{serviceType}/{serviceDate}/{specialistCode}": reference.GetListDoctor, + }) + + hk.GroupRoutes("/v1/member", r, hk.MapHandlerFunc{ + "GET /bpjs/{cardNumber}/{sepDate}": member.GetListByBpjsNumber, + "GET /nik/{nik}/{sepDate}": member.GetListByNik, + }) + + hk.GroupRoutes("/v1/monitoring", r, hk.MapHandlerFunc{ + "GET /visit/{date}/{serviceType}": monitoring.GetListVisit, + "GET /hist/{cardNumber}/{startDate}/{endDate}": monitoring.GetListHist, + }) + ///// return cmw.SetCors(handlerlogger.SetLog(r)) } diff --git a/internal/interface/bpjs-handler/member/handler.go b/internal/interface/main-handler/member/handler.go similarity index 100% rename from internal/interface/bpjs-handler/member/handler.go rename to internal/interface/main-handler/member/handler.go diff --git a/internal/interface/bpjs-handler/monitoring/handler.go b/internal/interface/main-handler/monitoring/handler.go similarity index 100% rename from internal/interface/bpjs-handler/monitoring/handler.go rename to internal/interface/main-handler/monitoring/handler.go diff --git a/internal/interface/bpjs-handler/reference/handler.go b/internal/interface/main-handler/reference/handler.go similarity index 100% rename from internal/interface/bpjs-handler/reference/handler.go rename to internal/interface/main-handler/reference/handler.go diff --git a/internal/interface/main-handler/resume/handler.go b/internal/interface/main-handler/resume/handler.go index 9a59f5fd..24ac0b08 100644 --- a/internal/interface/main-handler/resume/handler.go +++ b/internal/interface/main-handler/resume/handler.go @@ -99,9 +99,6 @@ func Verify(w http.ResponseWriter, r *http.Request) { } dto := e.UpdateDto{} - if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { - return - } dto.Id = uint(id) dto.Status_Code = erc.DVCVerified dto.AuthInfo = *authInfo @@ -120,9 +117,6 @@ func Validate(w http.ResponseWriter, r *http.Request) { } dto := e.UpdateDto{} - if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { - return - } dto.Id = uint(id) dto.Status_Code = erc.DVCValidated dto.AuthInfo = *authInfo diff --git a/internal/interface/bpjs-handler/vclaim-sep-hist/handler.go b/internal/interface/main-handler/vclaim-sep-hist/handler.go similarity index 100% rename from internal/interface/bpjs-handler/vclaim-sep-hist/handler.go rename to internal/interface/main-handler/vclaim-sep-hist/handler.go diff --git a/internal/interface/bpjs-handler/vclaim-sep-print/handler.go b/internal/interface/main-handler/vclaim-sep-print/handler.go similarity index 100% rename from internal/interface/bpjs-handler/vclaim-sep-print/handler.go rename to internal/interface/main-handler/vclaim-sep-print/handler.go diff --git a/internal/interface/bpjs-handler/vclaim-sep/handler.go b/internal/interface/main-handler/vclaim-sep/handler.go similarity index 55% rename from internal/interface/bpjs-handler/vclaim-sep/handler.go rename to internal/interface/main-handler/vclaim-sep/handler.go index d40c76e9..ed11e257 100644 --- a/internal/interface/bpjs-handler/vclaim-sep/handler.go +++ b/internal/interface/main-handler/vclaim-sep/handler.go @@ -1,7 +1,6 @@ package vclaimsep import ( - "io" "net/http" rw "github.com/karincake/risoles" @@ -16,14 +15,9 @@ var O myBase func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { dto := e.CreateDto{} - body, err := io.ReadAll(r.Body) - if err != nil { - http.Error(w, "failed to read body", http.StatusBadRequest) + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - defer r.Body.Close() - - dto.RequestPayload = body res, err := u.Create(dto) rw.DataResponse(w, res, err) } @@ -35,39 +29,39 @@ func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { // rw.DataResponse(w, res, err) // } -// func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { -// id := rw.ValidateInt(w, "id", r.PathValue("id")) -// if id <= 0 { +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +// func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { +// number := rw.ValidateString(w, "number", r.PathValue("number")) +// if number != "" { // return // } -// dto := e.ReadDetailDto{} -// dto.Id = uint(id) -// res, err := u.ReadDetail(dto) + +// dto := e.UpdateDto{} +// if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { +// return +// } +// dto.Number = &number +// res, err := u.Update(dto) // rw.DataResponse(w, res, err) // } -func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - number := rw.ValidateString(w, "number", r.PathValue("number")) - if number != "" { - return - } - - dto := e.UpdateDto{} - if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { - return - } - dto.Number = &number - res, err := u.Update(dto) - rw.DataResponse(w, res, err) -} - func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { - number := rw.ValidateString(w, "number", r.PathValue("number")) - if number != "" { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { return } dto := e.DeleteDto{} - dto.Number = &number + dto.Id = uint(id) res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/use-case/bpjs-plugin/vclaim-sep/plugin.go b/internal/use-case/bpjs-plugin/vclaim-sep/plugin.go index fd18763f..70097b74 100644 --- a/internal/use-case/bpjs-plugin/vclaim-sep/plugin.go +++ b/internal/use-case/bpjs-plugin/vclaim-sep/plugin.go @@ -14,7 +14,11 @@ import ( ) func CreateSep(input *e.CreateDto, data *e.VclaimSep, tx *gorm.DB) error { - req, err := http.NewRequest("POST", ibpjs.O.BaseUrl+"/sep", bytes.NewReader(input.RequestPayload)) + payload, err := input.RequestPayloadIntoJson() + if err != nil { + return err + } + req, err := http.NewRequest("POST", ibpjs.O.BaseUrl+"sep", bytes.NewBuffer(payload)) if err != nil { return err } @@ -43,7 +47,11 @@ func CreateSep(input *e.CreateDto, data *e.VclaimSep, tx *gorm.DB) error { } // Save request/response details in DTO for further use - input.VclaimSepHist.RequestPayload = string(input.RequestPayload) + reqPayload, err := input.RequestPayloadWithEncounterId() + if err != nil { + return err + } + input.VclaimSepHist.RequestPayload = string(reqPayload) input.VclaimSepHist.ResponseBody = string(body) input.VclaimSepHist.Message = msg input.Number = func() *string { @@ -56,3 +64,72 @@ func CreateSep(input *e.CreateDto, data *e.VclaimSep, tx *gorm.DB) error { return nil } + +func ReadDetailSep(input *e.ReadDetailDto, data *e.VclaimSep, tx *gorm.DB) error { + endpoint := fmt.Sprintf("sep/%s", *data.Number) + req, err := http.NewRequest("GET", ibpjs.O.BaseUrl+endpoint, nil) + 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() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + var detail e.SepResponse + if err := json.Unmarshal(body, &detail); err != nil { + return fmt.Errorf("failed to parse response JSON: %w", err) + } + + data.Detail = detail.Response + + return nil +} + +func DeleteSep(input *e.DeleteDto, data *e.VclaimSep, tx *gorm.DB) error { + payload := e.SepDeleteRequest{} + payload.Request.TSep.NoSep = *data.Number + payload.Request.TSep.User = "Coba Ws" + + jsonPayload, err := json.Marshal(payload) + if err != nil { + return err + } + + req, err := http.NewRequest("DELETE", ibpjs.O.BaseUrl+"sep", bytes.NewBuffer(jsonPayload)) + 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() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + var detail e.SepResponse + if err := json.Unmarshal(body, &detail); err != nil { + return fmt.Errorf("failed to parse response JSON: %w", err) + } + + if detail.MetaData.Message == SepNotFound { + return fmt.Errorf("sep with number %s not found", *data.Number) + } + + return nil +} diff --git a/internal/use-case/bpjs-plugin/vclaim-sep/tycovar.go b/internal/use-case/bpjs-plugin/vclaim-sep/tycovar.go index f057726e..7c19c44c 100644 --- a/internal/use-case/bpjs-plugin/vclaim-sep/tycovar.go +++ b/internal/use-case/bpjs-plugin/vclaim-sep/tycovar.go @@ -10,3 +10,5 @@ type vclaimResponse struct { } `json:"sep"` } `json:"response"` } + +const SepNotFound = "Data Tidak Ditemukan" diff --git a/internal/use-case/bpjs-use-case/vclaim-sep/case.go b/internal/use-case/bpjs-use-case/vclaim-sep/case.go index ac72d648..1d0e4aab 100644 --- a/internal/use-case/bpjs-use-case/vclaim-sep/case.go +++ b/internal/use-case/bpjs-use-case/vclaim-sep/case.go @@ -1,6 +1,7 @@ package vclaimsep import ( + "fmt" "strconv" e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" @@ -31,6 +32,17 @@ func Create(input e.CreateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "create") err := dg.I.Transaction(func(tx *gorm.DB) error { + rDto := e.ReadDetailDto{Encounter_Id: input.Encounter_Id} + if vSep, err := ReadDetailData(rDto, &event, tx); err != nil { + if !pu.IsDataNotFoundError(err) { + return err + } + + if vSep != nil { + return fmt.Errorf("sep with encounter id %d already exist with number %s", input.Encounter_Id, *vSep.Number) + } + } + mwRunner := newMiddlewareRunner(&event, tx) mwRunner.setMwType(pu.MWTPre) // Run pre-middleware @@ -38,12 +50,12 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } - if _, err := uvsh.CreateData(input.VclaimSepHist, &event, tx); err != nil { + if _, err := uvsh.CreateData(input.VclaimSepHist, &event); err != nil { return err } if !input.IsMessageSuccess() { - return nil + return fmt.Errorf("%s", input.VclaimSepHist.Message) } if resData, err := CreateData(input, &event, tx); err != nil { @@ -234,7 +246,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { } func Delete(input e.DeleteDto) (*d.Data, error) { - rdDto := e.ReadDetailDto{Number: input.Number} + rdDto := e.ReadDetailDto{Id: input.Id} var data *e.VclaimSep var err error @@ -255,7 +267,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { mwRunner := newMiddlewareRunner(&event, tx) mwRunner.setMwType(pu.MWTPre) // Run pre-middleware - if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { + if err := mwRunner.RunDeleteMiddleware(deletePreMw, &e.DeleteDto{}, data); err != nil { return err } @@ -265,7 +277,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { mwRunner.setMwType(pu.MWTPost) // Run post-middleware - if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + if err := mwRunner.RunDeleteMiddleware(deletePostMw, &e.DeleteDto{}, data); err != nil { return err } diff --git a/internal/use-case/bpjs-use-case/vclaim-sep/lib.go b/internal/use-case/bpjs-use-case/vclaim-sep/lib.go index 817c357c..82da0d45 100644 --- a/internal/use-case/bpjs-use-case/vclaim-sep/lib.go +++ b/internal/use-case/bpjs-use-case/vclaim-sep/lib.go @@ -87,6 +87,9 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e if input.Id != 0 { tx = tx.Where("\"Id\" = ?", input.Id) } + if input.Encounter_Id != nil { + tx = tx.Where("\"Encounter_Id\" = ?", *input.Encounter_Id) + } if err := tx.First(&data).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { diff --git a/internal/use-case/bpjs-use-case/vclaim-sep/middleware-runner.go b/internal/use-case/bpjs-use-case/vclaim-sep/middleware-runner.go index dee35276..8e8522a6 100644 --- a/internal/use-case/bpjs-use-case/vclaim-sep/middleware-runner.go +++ b/internal/use-case/bpjs-use-case/vclaim-sep/middleware-runner.go @@ -83,7 +83,7 @@ func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, inpu return nil } -func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.VclaimSep) error { +func (me *middlewareRunner) RunDeleteMiddleware(middlewares []deleteMw, input *e.DeleteDto, data *e.VclaimSep) error { for _, middleware := range middlewares { logData := pu.GetLogData(input, data) diff --git a/internal/use-case/bpjs-use-case/vclaim-sep/middleware.go b/internal/use-case/bpjs-use-case/vclaim-sep/middleware.go index 1ad0a853..08caba00 100644 --- a/internal/use-case/bpjs-use-case/vclaim-sep/middleware.go +++ b/internal/use-case/bpjs-use-case/vclaim-sep/middleware.go @@ -9,5 +9,10 @@ func init() { createPreMw = append(createPreMw, createMw{Name: "create-sep", Func: pvs.CreateSep}, ) - + readDetailPostMw = append(readDetailPostMw, + readDetailMw{Name: "read-detail-sep", Func: pvs.ReadDetailSep}, + ) + deletePreMw = append(deletePreMw, + deleteMw{Name: "delete-sep", Func: pvs.DeleteSep}, + ) } diff --git a/internal/use-case/bpjs-use-case/vclaim-sep/tycovar.go b/internal/use-case/bpjs-use-case/vclaim-sep/tycovar.go index 932bc355..be3b5d11 100644 --- a/internal/use-case/bpjs-use-case/vclaim-sep/tycovar.go +++ b/internal/use-case/bpjs-use-case/vclaim-sep/tycovar.go @@ -29,8 +29,12 @@ type readDetailMw struct { Func func(input *e.ReadDetailDto, data *e.VclaimSep, tx *gorm.DB) error } +type deleteMw struct { + Name string + Func func(input *e.DeleteDto, data *e.VclaimSep, tx *gorm.DB) error +} + type UpdateMw = readDetailMw -type DeleteMw = readDetailMw var createPreMw []createMw // preprocess middleware var createPostMw []createMw // postprocess middleware @@ -40,5 +44,5 @@ var readDetailPreMw []readDetailMw var readDetailPostMw []readDetailMw var updatePreMw []readDetailMw var updatePostMw []readDetailMw -var deletePreMw []readDetailMw -var deletePostMw []readDetailMw +var deletePreMw []deleteMw +var deletePostMw []deleteMw diff --git a/internal/use-case/main-use-case/generate-file/helper.go b/internal/use-case/main-use-case/generate-file/helper.go index 1f0d0bfd..3a6c3480 100644 --- a/internal/use-case/main-use-case/generate-file/helper.go +++ b/internal/use-case/main-use-case/generate-file/helper.go @@ -244,6 +244,10 @@ func generateResume(input GenerateDto, event pl.Event, tx *gorm.DB) (*ResponseDt return nil, err } + if !r.IsValidated() { + return nil, errors.New("resume is not validated") + } + if r.FileUrl != nil { if err := removeFile(string(input.EntityType_Code), *r.FileUrl); err != nil { return nil, err diff --git a/internal/use-case/main-use-case/resume/case.go b/internal/use-case/main-use-case/resume/case.go index cbc472f9..eab70280 100644 --- a/internal/use-case/main-use-case/resume/case.go +++ b/internal/use-case/main-use-case/resume/case.go @@ -50,7 +50,6 @@ func Create(input e.CreateDto) (*d.Data, error) { return errors.New("encounter is already done") } - input.Status_Code = erc.DVCNew if resData, err := CreateData(input, &event, tx); err != nil { return err } else { @@ -345,16 +344,16 @@ func UpdateStatusCode(input e.UpdateDto) (*d.Data, error) { switch input.Status_Code { case erc.DVCValidated: - if !enc.IsSameResponsibleDoctor(input.AuthInfo.Doctor_Code) { - return errors.New("validation doctor is not the same as encounter responsible doctor") - } - if data.IsNew() { return errors.New("resume need to be verified first") } if data.IsValidated() { return errors.New("resume already validated") } + if !enc.IsSameResponsibleDoctor(input.AuthInfo.Doctor_Code) { + return errors.New("validation doctor is not the same as encounter responsible doctor") + } + data.Status_Code = erc.DVCValidated err = tx.Save(&data).Error if err != nil { diff --git a/internal/use-case/main-use-case/resume/helper.go b/internal/use-case/main-use-case/resume/helper.go index edd45222..794ae214 100644 --- a/internal/use-case/main-use-case/resume/helper.go +++ b/internal/use-case/main-use-case/resume/helper.go @@ -6,12 +6,15 @@ package resume import ( e "simrs-vx/internal/domain/main-entities/resume" + + erc "simrs-vx/internal/domain/references/common" ) func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Resume) { var inputSrc *e.CreateDto if inputT, ok := any(input).(*e.CreateDto); ok { inputSrc = inputT + data.Status_Code = erc.DVCNew } else { inputTemp := any(input).(*e.UpdateDto) inputSrc = &inputTemp.CreateDto @@ -20,5 +23,4 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Resume) { data.Encounter_Id = inputSrc.Encounter_Id data.Doctor_Code = inputSrc.AuthInfo.Doctor_Code data.Value = inputSrc.Value - data.Status_Code = inputSrc.Status_Code } From 6c07024eb17c401ef82aa2d066817591a75d1117 Mon Sep 17 00:00:00 2001 From: Andrian Roshandy Date: Sat, 29 Nov 2025 20:50:06 +0700 Subject: [PATCH 278/329] Merge from 'dev' --- internal/infra/sync-consumer-cfg/tycovar.go | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 internal/infra/sync-consumer-cfg/tycovar.go diff --git a/internal/infra/sync-consumer-cfg/tycovar.go b/internal/infra/sync-consumer-cfg/tycovar.go new file mode 100644 index 00000000..d2146c2b --- /dev/null +++ b/internal/infra/sync-consumer-cfg/tycovar.go @@ -0,0 +1,11 @@ +package synccfg + +var O SyncConsumerUrlCfg = SyncConsumerUrlCfg{} // old + +type SyncConsumerUrlCfg struct { + Prefix string `yaml:"prefix"` + TargetHost string `yaml:"targetHost"` + Enable bool `yaml:"enable"` + Source string `yaml:"source"` + SecretKey string `yaml:"secretKey"` +} From 2a979f60a6ba1fe314114efc831cbc9cf752a4fa Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 1 Dec 2025 12:43:23 +0700 Subject: [PATCH 279/329] feat (vclaim/bpjs/jkn): add several endpoint --- .../domain/bpjs-entities/control-plan/dto.go | 7 ++ .../bpjs-entities/control-plan/entity.go | 22 +++++ internal/domain/bpjs-entities/referral/dto.go | 5 + .../domain/bpjs-entities/referral/entity.go | 96 +++++++++++++++++++ .../main-handler/control-plan/handler.go | 32 +++++++ .../interface/main-handler/main-handler.go | 16 +++- .../interface/main-handler/member/handler.go | 8 +- .../main-handler/monitoring/handler.go | 10 +- .../main-handler/reference/handler.go | 20 ++-- .../main-handler/referral/handler.go | 22 +++++ .../main-handler/vclaim-sep/handler.go | 6 +- .../bpjs-plugin/control-plan/helper.go | 11 +++ .../bpjs-plugin/control-plan/plugin.go | 37 +++++++ .../use-case/bpjs-plugin/referral/helper.go | 11 +++ .../use-case/bpjs-plugin/referral/plugin.go | 37 +++++++ .../use-case/bpjs-plugin/vclaim-sep/plugin.go | 4 +- .../bpjs-use-case/control-plan/case.go | 50 ++++++++++ .../control-plan/middleware-runner.go | 42 ++++++++ .../bpjs-use-case/control-plan/middleware.go | 12 +++ .../bpjs-use-case/control-plan/tycovar.go | 18 ++++ .../use-case/bpjs-use-case/referral/case.go | 50 ++++++++++ .../referral/middleware-runner.go | 42 ++++++++ .../bpjs-use-case/referral/middleware.go | 12 +++ .../bpjs-use-case/referral/tycovar.go | 18 ++++ 24 files changed, 561 insertions(+), 27 deletions(-) create mode 100644 internal/domain/bpjs-entities/control-plan/dto.go create mode 100644 internal/domain/bpjs-entities/control-plan/entity.go create mode 100644 internal/domain/bpjs-entities/referral/dto.go create mode 100644 internal/domain/bpjs-entities/referral/entity.go create mode 100644 internal/interface/main-handler/control-plan/handler.go create mode 100644 internal/interface/main-handler/referral/handler.go create mode 100644 internal/use-case/bpjs-plugin/control-plan/helper.go create mode 100644 internal/use-case/bpjs-plugin/control-plan/plugin.go create mode 100644 internal/use-case/bpjs-plugin/referral/helper.go create mode 100644 internal/use-case/bpjs-plugin/referral/plugin.go create mode 100644 internal/use-case/bpjs-use-case/control-plan/case.go create mode 100644 internal/use-case/bpjs-use-case/control-plan/middleware-runner.go create mode 100644 internal/use-case/bpjs-use-case/control-plan/middleware.go create mode 100644 internal/use-case/bpjs-use-case/control-plan/tycovar.go create mode 100644 internal/use-case/bpjs-use-case/referral/case.go create mode 100644 internal/use-case/bpjs-use-case/referral/middleware-runner.go create mode 100644 internal/use-case/bpjs-use-case/referral/middleware.go create mode 100644 internal/use-case/bpjs-use-case/referral/tycovar.go diff --git a/internal/domain/bpjs-entities/control-plan/dto.go b/internal/domain/bpjs-entities/control-plan/dto.go new file mode 100644 index 00000000..2290707d --- /dev/null +++ b/internal/domain/bpjs-entities/control-plan/dto.go @@ -0,0 +1,7 @@ +package controlplan + +type ReadListDto struct { + PathValue1 string `json:"-"` // jenis kontrol + PathValue2 string `json:"-"` // kode poli + PathValue3 string `json:"-"` // tanggal +} diff --git a/internal/domain/bpjs-entities/control-plan/entity.go b/internal/domain/bpjs-entities/control-plan/entity.go new file mode 100644 index 00000000..1a07379a --- /dev/null +++ b/internal/domain/bpjs-entities/control-plan/entity.go @@ -0,0 +1,22 @@ +package controlplan + +type Response struct { + MetaData MetaData `json:"metaData"` + Response *ResponseItems `json:"response"` // nullable +} + +type MetaData struct { + Code string `json:"code"` + Message string `json:"message"` +} + +type ResponseItems struct { + List []DoctorSchedule `json:"list"` +} + +type DoctorSchedule struct { + JadwalPraktek string `json:"jadwalPraktek"` + Kapasitas string `json:"kapasitas"` + KodeDokter string `json:"kodeDokter"` + NamaDokter string `json:"namaDokter"` +} diff --git a/internal/domain/bpjs-entities/referral/dto.go b/internal/domain/bpjs-entities/referral/dto.go new file mode 100644 index 00000000..16113d24 --- /dev/null +++ b/internal/domain/bpjs-entities/referral/dto.go @@ -0,0 +1,5 @@ +package referral + +type ReadDetailDto struct { + Number *string `json:"number"` // nomor rujukan +} diff --git a/internal/domain/bpjs-entities/referral/entity.go b/internal/domain/bpjs-entities/referral/entity.go new file mode 100644 index 00000000..8977ee31 --- /dev/null +++ b/internal/domain/bpjs-entities/referral/entity.go @@ -0,0 +1,96 @@ +package referral + +type Response struct { + MetaData MetaData `json:"metaData"` + Response *ReferralDetail `json:"response"` // nullable +} + +type MetaData struct { + Code string `json:"code"` + Message string `json:"message"` +} + +type ReferralDetail struct { + AsalFaskes string `json:"asalFaskes"` + Rujukan RujukanDetail `json:"rujukan"` +} + +type RujukanDetail struct { + Diagnosa Diagnosa `json:"diagnosa"` + Keluhan *string `json:"keluhan"` // nullable + NoKunjungan string `json:"noKunjungan"` + Pelayanan Pelayanan `json:"pelayanan"` + Peserta Peserta `json:"peserta"` + PoliRujukan Poli `json:"poliRujukan"` + ProvPerujuk Provider `json:"provPerujuk"` + TglKunjungan string `json:"tglKunjungan"` +} + +type Diagnosa struct { + Kode string `json:"kode"` + Nama string `json:"nama"` +} + +type Pelayanan struct { + Kode string `json:"kode"` + Nama string `json:"nama"` +} + +type Peserta struct { + Cob Cob `json:"cob"` + HakKelas KeteranganKode `json:"hakKelas"` + Informasi Informasi `json:"informasi"` + JenisPeserta KeteranganKode `json:"jenisPeserta"` + Mr Mr `json:"mr"` + Nama string `json:"nama"` + Nik string `json:"nik"` + NoKartu string `json:"noKartu"` + Pisa string `json:"pisa"` + ProvUmum Provider `json:"provUmum"` + Sex string `json:"sex"` + StatusPeserta KeteranganKode `json:"statusPeserta"` + TglCetakKartu string `json:"tglCetakKartu"` + TglLahir string `json:"tglLahir"` + TglTAT string `json:"tglTAT"` + TglTMT string `json:"tglTMT"` + Umur Umur `json:"umur"` +} + +type Cob struct { + NmAsuransi *string `json:"nmAsuransi"` // nullable + NoAsuransi *string `json:"noAsuransi"` + TglTAT *string `json:"tglTAT"` + TglTMT *string `json:"tglTMT"` +} + +type KeteranganKode struct { + Keterangan string `json:"keterangan"` + Kode string `json:"kode"` +} + +type Informasi struct { + Dinsos *string `json:"dinsos"` + ESep *string `json:"eSEP"` + NoSKTM *string `json:"noSKTM"` + ProlanisPRB *string `json:"prolanisPRB"` +} + +type Mr struct { + NoMR string `json:"noMR"` + NoTelepon string `json:"noTelepon"` +} + +type Provider struct { + Kode string `json:"kdProvider" json:"kode"` // API sometimes uses different keys + NmProvider string `json:"nmProvider" json:"nama"` +} + +type Poli struct { + Kode string `json:"kode"` + Nama string `json:"nama"` +} + +type Umur struct { + UmurSaatPelayanan string `json:"umurSaatPelayanan"` + UmurSekarang string `json:"umurSekarang"` +} diff --git a/internal/interface/main-handler/control-plan/handler.go b/internal/interface/main-handler/control-plan/handler.go new file mode 100644 index 00000000..382af58d --- /dev/null +++ b/internal/interface/main-handler/control-plan/handler.go @@ -0,0 +1,32 @@ +package controlplan + +import ( + "net/http" + + e "simrs-vx/internal/domain/bpjs-entities/control-plan" + u "simrs-vx/internal/use-case/bpjs-use-case/control-plan" + + d "github.com/karincake/dodol" + rw "github.com/karincake/risoles" +) + +func GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + pValue1 := rw.ValidateString(w, "controlType", r.PathValue("controlType")) + if pValue1 == "" { + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "controlType is required"}, nil) + } + pValue2 := rw.ValidateString(w, "polyCode", r.PathValue("polyCode")) + if pValue2 == "" { + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "polyCode is required"}, nil) + } + pValue3 := rw.ValidateString(w, "date", r.PathValue("date")) + if pValue3 == "" { + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "date is required"}, nil) + } + dto.PathValue1 = pValue1 + dto.PathValue2 = pValue2 + dto.PathValue3 = pValue3 + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index d374a8a8..362a5e8a 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -125,9 +125,11 @@ import ( "simrs-vx/internal/interface/main-handler/home" /******************** BPJS ********************/ + controlplan "simrs-vx/internal/interface/main-handler/control-plan" member "simrs-vx/internal/interface/main-handler/member" monitoring "simrs-vx/internal/interface/main-handler/monitoring" reference "simrs-vx/internal/interface/main-handler/reference" + referral "simrs-vx/internal/interface/main-handler/referral" vclaimsep "simrs-vx/internal/interface/main-handler/vclaim-sep" vclaimsephist "simrs-vx/internal/interface/main-handler/vclaim-sep-hist" vclaimsepprint "simrs-vx/internal/interface/main-handler/vclaim-sep-print" @@ -382,9 +384,9 @@ func SetRoutes() http.Handler { /******************** BPJS ********************/ hk.GroupRoutes("/v1/vclaim-sep", r, hk.MapHandlerFunc{ - "POST /": vclaimsep.O.Create, - "GET /{id}": vclaimsep.O.GetDetail, - "DELETE /{id}": vclaimsep.O.Delete, + "POST /": vclaimsep.O.Create, + "GET /{number}": vclaimsep.O.GetDetail, + "DELETE /{number}": vclaimsep.O.Delete, }) hk.GroupRoutes("/v1/vclaim-sep-hist", r, hk.MapHandlerFunc{ @@ -417,6 +419,14 @@ func SetRoutes() http.Handler { "GET /hist/{cardNumber}/{startDate}/{endDate}": monitoring.GetListHist, }) + hk.GroupRoutes("/v1/control-plan", r, hk.MapHandlerFunc{ + "GET /{controlType}/{polyCode}/{date}": controlplan.GetList, + }) + + hk.GroupRoutes("/v1/referral", r, hk.MapHandlerFunc{ + "GET /{number}": referral.GetList, + }) + ///// return cmw.SetCors(handlerlogger.SetLog(r)) } diff --git a/internal/interface/main-handler/member/handler.go b/internal/interface/main-handler/member/handler.go index 80881ee3..3b4c3ba1 100644 --- a/internal/interface/main-handler/member/handler.go +++ b/internal/interface/main-handler/member/handler.go @@ -14,11 +14,11 @@ func GetListByBpjsNumber(w http.ResponseWriter, r *http.Request) { dto := e.ReadListDto{} pValue1 := rw.ValidateString(w, "cardNumber", r.PathValue("cardNumber")) if pValue1 == "" { - rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "cardNumber is required"}, nil) + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "cardNumber is required"}, nil) } pValue2 := rw.ValidateString(w, "sepDate", r.PathValue("sepDate")) if pValue2 == "" { - rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "sepDate is required"}, nil) + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "sepDate is required"}, nil) } dto.ReferenceType = e.RTBpjs dto.PathValue1 = pValue1 @@ -31,11 +31,11 @@ func GetListByNik(w http.ResponseWriter, r *http.Request) { dto := e.ReadListDto{} pValue1 := rw.ValidateString(w, "nik", r.PathValue("nik")) if pValue1 == "" { - rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "nik is required"}, nil) + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "nik is required"}, nil) } pValue2 := rw.ValidateString(w, "sepDate", r.PathValue("sepDate")) if pValue2 == "" { - rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "sepDate is required"}, nil) + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "sepDate is required"}, nil) } dto.ReferenceType = e.RTNik dto.PathValue1 = pValue1 diff --git a/internal/interface/main-handler/monitoring/handler.go b/internal/interface/main-handler/monitoring/handler.go index cf82a5b9..aa8acdf4 100644 --- a/internal/interface/main-handler/monitoring/handler.go +++ b/internal/interface/main-handler/monitoring/handler.go @@ -14,11 +14,11 @@ func GetListVisit(w http.ResponseWriter, r *http.Request) { dto := e.ReadListDto{} pValue1 := rw.ValidateString(w, "date", r.PathValue("date")) if pValue1 == "" { - rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "date is required"}, nil) + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "date is required"}, nil) } pValue2 := rw.ValidateString(w, "serviceType", r.PathValue("serviceType")) if pValue2 == "" { - rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "serviceType is required"}, nil) + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "serviceType is required"}, nil) } dto.ReferenceType = e.RTVisit dto.PathValue1 = pValue1 @@ -31,15 +31,15 @@ func GetListHist(w http.ResponseWriter, r *http.Request) { dto := e.ReadListDto{} pValue1 := rw.ValidateString(w, "cardNumber", r.PathValue("cardNumber")) if pValue1 == "" { - rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "cardNumber is required"}, nil) + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "cardNumber is required"}, nil) } pValue2 := rw.ValidateString(w, "startDate", r.PathValue("startDate")) if pValue2 == "" { - rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "startDate is required"}, nil) + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "startDate is required"}, nil) } pValue3 := rw.ValidateString(w, "endDate", r.PathValue("endDate")) if pValue3 == "" { - rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "endDate is required"}, nil) + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "endDate is required"}, nil) } dto.ReferenceType = e.RTHist dto.PathValue1 = pValue1 diff --git a/internal/interface/main-handler/reference/handler.go b/internal/interface/main-handler/reference/handler.go index fb972af1..b9948eb3 100644 --- a/internal/interface/main-handler/reference/handler.go +++ b/internal/interface/main-handler/reference/handler.go @@ -21,7 +21,7 @@ func GetListCities(w http.ResponseWriter, r *http.Request) { dto := e.ReadListDto{} pValue := rw.ValidateString(w, "provinceCode", r.PathValue("provinceCode")) if pValue == "" { - rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "provinceCode is required"}, nil) + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "provinceCode is required"}, nil) } dto.ReferenceType = e.RTCities dto.PathValue1 = pValue @@ -33,7 +33,7 @@ func GetListDistrict(w http.ResponseWriter, r *http.Request) { dto := e.ReadListDto{} pValue := rw.ValidateString(w, "regencyCode", r.PathValue("regencyCode")) if pValue == "" { - rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "regencyCode is required"}, nil) + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "regencyCode is required"}, nil) } dto.ReferenceType = e.RTDistrict dto.PathValue1 = pValue @@ -45,7 +45,7 @@ func GetListDiagnose(w http.ResponseWriter, r *http.Request) { dto := e.ReadListDto{} pValue := rw.ValidateString(w, "keyword", r.PathValue("keyword")) if pValue == "" { - rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "keyword is required"}, nil) + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "keyword is required"}, nil) } dto.ReferenceType = e.RTDiagnose dto.PathValue1 = pValue @@ -64,7 +64,7 @@ func GetListMedicinePrb(w http.ResponseWriter, r *http.Request) { dto := e.ReadListDto{} pValue := rw.ValidateString(w, "keyword", r.PathValue("keyword")) if pValue == "" { - rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "keyword is required"}, nil) + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "keyword is required"}, nil) } dto.ReferenceType = e.RTMedicinePrb dto.PathValue1 = pValue @@ -76,7 +76,7 @@ func GetListUnit(w http.ResponseWriter, r *http.Request) { dto := e.ReadListDto{} pValue := rw.ValidateString(w, "unitCode", r.PathValue("unitCode")) if pValue == "" { - rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "unitCode is required"}, nil) + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "unitCode is required"}, nil) } dto.ReferenceType = e.RTUnit dto.PathValue1 = pValue @@ -88,11 +88,11 @@ func GetListHealthcare(w http.ResponseWriter, r *http.Request) { dto := e.ReadListDto{} pValue1 := rw.ValidateString(w, "healthcare", r.PathValue("healthcare")) if pValue1 == "" { - rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "healthcare is required"}, nil) + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "healthcare is required"}, nil) } pValue2 := rw.ValidateString(w, "healthcareType", r.PathValue("healthcareType")) if pValue2 == "" { - rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "healthcareType is required"}, nil) + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "healthcareType is required"}, nil) } dto.ReferenceType = e.RTHealthcare dto.PathValue1 = pValue1 @@ -105,15 +105,15 @@ func GetListDoctor(w http.ResponseWriter, r *http.Request) { dto := e.ReadListDto{} pValue1 := rw.ValidateString(w, "serviceType", r.PathValue("serviceType")) if pValue1 == "" { - rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "serviceType is required"}, nil) + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "serviceType is required"}, nil) } pValue2 := rw.ValidateString(w, "serviceDate", r.PathValue("serviceDate")) if pValue2 == "" { - rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "serviceDate is required"}, nil) + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "serviceDate is required"}, nil) } pValue3 := rw.ValidateString(w, "specialistCode", r.PathValue("specialistCode")) if pValue3 == "" { - rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "specialistCode is required"}, nil) + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "specialistCode is required"}, nil) } dto.PathValue1 = pValue1 dto.PathValue2 = pValue2 diff --git a/internal/interface/main-handler/referral/handler.go b/internal/interface/main-handler/referral/handler.go new file mode 100644 index 00000000..94b66a78 --- /dev/null +++ b/internal/interface/main-handler/referral/handler.go @@ -0,0 +1,22 @@ +package referral + +import ( + "net/http" + + e "simrs-vx/internal/domain/bpjs-entities/referral" + u "simrs-vx/internal/use-case/bpjs-use-case/referral" + + d "github.com/karincake/dodol" + rw "github.com/karincake/risoles" +) + +func GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadDetailDto{} + number := rw.ValidateString(w, "number", r.PathValue("number")) + if number == "" { + rw.WriteJSON(w, http.StatusBadRequest, d.IS{"message": "number is required"}, nil) + } + dto.Number = &number + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/vclaim-sep/handler.go b/internal/interface/main-handler/vclaim-sep/handler.go index ed11e257..1529e2d8 100644 --- a/internal/interface/main-handler/vclaim-sep/handler.go +++ b/internal/interface/main-handler/vclaim-sep/handler.go @@ -30,12 +30,12 @@ func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { // } func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { + number := rw.ValidateString(w, "number", r.PathValue("number")) + if number <= "" { return } dto := e.ReadDetailDto{} - dto.Id = uint(id) + dto.Number = &number res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } diff --git a/internal/use-case/bpjs-plugin/control-plan/helper.go b/internal/use-case/bpjs-plugin/control-plan/helper.go new file mode 100644 index 00000000..15af7238 --- /dev/null +++ b/internal/use-case/bpjs-plugin/control-plan/helper.go @@ -0,0 +1,11 @@ +package controlplan + +import ( + "fmt" + e "simrs-vx/internal/domain/bpjs-entities/control-plan" + ibpjs "simrs-vx/internal/infra/bpjs" +) + +func endpointMapper(input *e.ReadListDto) string { + return fmt.Sprintf("%sRencanaKontrol/jadwalDokter?jeniskontrol=%s&kodepoli=%s&tanggalkontrol=%s", ibpjs.O.BaseUrl, input.PathValue1, input.PathValue2, input.PathValue3) +} diff --git a/internal/use-case/bpjs-plugin/control-plan/plugin.go b/internal/use-case/bpjs-plugin/control-plan/plugin.go new file mode 100644 index 00000000..276750ca --- /dev/null +++ b/internal/use-case/bpjs-plugin/control-plan/plugin.go @@ -0,0 +1,37 @@ +package controlplan + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + e "simrs-vx/internal/domain/bpjs-entities/control-plan" + + "gorm.io/gorm" +) + +func ReadList(input *e.ReadListDto, data *e.Response, tx *gorm.DB) error { + endpoint := endpointMapper(input) + req, err := http.NewRequest("GET", endpoint, nil) + 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() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + if err := json.Unmarshal(body, &data); err != nil { + return fmt.Errorf("failed to parse response JSON: %w", err) + } + + return nil +} diff --git a/internal/use-case/bpjs-plugin/referral/helper.go b/internal/use-case/bpjs-plugin/referral/helper.go new file mode 100644 index 00000000..169834be --- /dev/null +++ b/internal/use-case/bpjs-plugin/referral/helper.go @@ -0,0 +1,11 @@ +package referral + +import ( + "fmt" + e "simrs-vx/internal/domain/bpjs-entities/referral" + ibpjs "simrs-vx/internal/infra/bpjs" +) + +func endpointMapper(input *e.ReadDetailDto) string { + return fmt.Sprintf("%sRujukan/RS/%s", ibpjs.O.BaseUrl, *input.Number) +} diff --git a/internal/use-case/bpjs-plugin/referral/plugin.go b/internal/use-case/bpjs-plugin/referral/plugin.go new file mode 100644 index 00000000..225181e4 --- /dev/null +++ b/internal/use-case/bpjs-plugin/referral/plugin.go @@ -0,0 +1,37 @@ +package referral + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + e "simrs-vx/internal/domain/bpjs-entities/referral" + + "gorm.io/gorm" +) + +func ReadDetail(input *e.ReadDetailDto, data *e.Response, tx *gorm.DB) error { + endpoint := endpointMapper(input) + req, err := http.NewRequest("GET", endpoint, nil) + 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() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + if err := json.Unmarshal(body, &data); err != nil { + return fmt.Errorf("failed to parse response JSON: %w", err) + } + + return nil +} diff --git a/internal/use-case/bpjs-plugin/vclaim-sep/plugin.go b/internal/use-case/bpjs-plugin/vclaim-sep/plugin.go index 70097b74..4588029f 100644 --- a/internal/use-case/bpjs-plugin/vclaim-sep/plugin.go +++ b/internal/use-case/bpjs-plugin/vclaim-sep/plugin.go @@ -66,7 +66,7 @@ func CreateSep(input *e.CreateDto, data *e.VclaimSep, tx *gorm.DB) error { } func ReadDetailSep(input *e.ReadDetailDto, data *e.VclaimSep, tx *gorm.DB) error { - endpoint := fmt.Sprintf("sep/%s", *data.Number) + endpoint := fmt.Sprintf("sep/%s", input.Number) req, err := http.NewRequest("GET", ibpjs.O.BaseUrl+endpoint, nil) if err != nil { return err @@ -96,7 +96,7 @@ func ReadDetailSep(input *e.ReadDetailDto, data *e.VclaimSep, tx *gorm.DB) error func DeleteSep(input *e.DeleteDto, data *e.VclaimSep, tx *gorm.DB) error { payload := e.SepDeleteRequest{} - payload.Request.TSep.NoSep = *data.Number + payload.Request.TSep.NoSep = *input.Number payload.Request.TSep.User = "Coba Ws" jsonPayload, err := json.Marshal(payload) diff --git a/internal/use-case/bpjs-use-case/control-plan/case.go b/internal/use-case/bpjs-use-case/control-plan/case.go new file mode 100644 index 00000000..764ea2ea --- /dev/null +++ b/internal/use-case/bpjs-use-case/control-plan/case.go @@ -0,0 +1,50 @@ +package controlplan + +import ( + e "simrs-vx/internal/domain/bpjs-entities/control-plan" + + dg "github.com/karincake/apem/db-gorm-pg" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "control-plan" + +func ReadList(input e.ReadListDto) (*e.Response, error) { + var data e.Response + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, &data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &data, nil +} diff --git a/internal/use-case/bpjs-use-case/control-plan/middleware-runner.go b/internal/use-case/bpjs-use-case/control-plan/middleware-runner.go new file mode 100644 index 00000000..4c3db3d8 --- /dev/null +++ b/internal/use-case/bpjs-use-case/control-plan/middleware-runner.go @@ -0,0 +1,42 @@ +package controlplan + +import ( + e "simrs-vx/internal/domain/bpjs-entities/control-plan" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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, + } +} + +func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.Response) 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/bpjs-use-case/control-plan/middleware.go b/internal/use-case/bpjs-use-case/control-plan/middleware.go new file mode 100644 index 00000000..3478bb19 --- /dev/null +++ b/internal/use-case/bpjs-use-case/control-plan/middleware.go @@ -0,0 +1,12 @@ +package controlplan + +import ( + pcp "simrs-vx/internal/use-case/bpjs-plugin/control-plan" +) + +func init() { + readListPreMw = append(readListPreMw, + readListMw{Name: "readList-control-plan", Func: pcp.ReadList}, + ) + +} diff --git a/internal/use-case/bpjs-use-case/control-plan/tycovar.go b/internal/use-case/bpjs-use-case/control-plan/tycovar.go new file mode 100644 index 00000000..ea2b39a9 --- /dev/null +++ b/internal/use-case/bpjs-use-case/control-plan/tycovar.go @@ -0,0 +1,18 @@ +/* +member is peserta +*/ +package controlplan + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/bpjs-entities/control-plan" +) + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Response, tx *gorm.DB) error +} + +var readListPreMw []readListMw // .. +var readListPostMw []readListMw // .. diff --git a/internal/use-case/bpjs-use-case/referral/case.go b/internal/use-case/bpjs-use-case/referral/case.go new file mode 100644 index 00000000..8818dc58 --- /dev/null +++ b/internal/use-case/bpjs-use-case/referral/case.go @@ -0,0 +1,50 @@ +package referral + +import ( + e "simrs-vx/internal/domain/bpjs-entities/referral" + + dg "github.com/karincake/apem/db-gorm-pg" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "referral" + +func ReadDetail(input e.ReadDetailDto) (*e.Response, error) { + var data e.Response + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, &data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &data, nil +} diff --git a/internal/use-case/bpjs-use-case/referral/middleware-runner.go b/internal/use-case/bpjs-use-case/referral/middleware-runner.go new file mode 100644 index 00000000..10c26241 --- /dev/null +++ b/internal/use-case/bpjs-use-case/referral/middleware-runner.go @@ -0,0 +1,42 @@ +package referral + +import ( + e "simrs-vx/internal/domain/bpjs-entities/referral" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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, + } +} + +func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Response) 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/bpjs-use-case/referral/middleware.go b/internal/use-case/bpjs-use-case/referral/middleware.go new file mode 100644 index 00000000..0296ae5a --- /dev/null +++ b/internal/use-case/bpjs-use-case/referral/middleware.go @@ -0,0 +1,12 @@ +package referral + +import ( + pr "simrs-vx/internal/use-case/bpjs-plugin/referral" +) + +func init() { + readDetailPreMw = append(readDetailPreMw, + readDetailMw{Name: "read-detail-referral", Func: pr.ReadDetail}, + ) + +} diff --git a/internal/use-case/bpjs-use-case/referral/tycovar.go b/internal/use-case/bpjs-use-case/referral/tycovar.go new file mode 100644 index 00000000..b1950977 --- /dev/null +++ b/internal/use-case/bpjs-use-case/referral/tycovar.go @@ -0,0 +1,18 @@ +/* +member is peserta +*/ +package referral + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/bpjs-entities/referral" +) + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Response, tx *gorm.DB) error +} + +var readDetailPreMw []readDetailMw +var readDetailPostMw []readDetailMw From c3fae2ec52a48c68c83ac00945692ade377f0ba7 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 1 Dec 2025 12:47:57 +0700 Subject: [PATCH 280/329] fix encounter id on read detail --- internal/use-case/main-use-case/generate-file/helper.go | 2 +- internal/use-case/main-use-case/resume/case.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/use-case/main-use-case/generate-file/helper.go b/internal/use-case/main-use-case/generate-file/helper.go index 3a6c3480..6edd34d8 100644 --- a/internal/use-case/main-use-case/generate-file/helper.go +++ b/internal/use-case/main-use-case/generate-file/helper.go @@ -284,7 +284,7 @@ func generateResume(input GenerateDto, event pl.Event, tx *gorm.DB) (*ResponseDt func generateResumeTemplateData(resume er.Resume, event pl.Event, tx *gorm.DB) (*ResumePDF, error) { // get encounter includes := "Patient,Patient.Person,Patient.Person.BirthRegency,Patient.Person.Contacts" - encounter, err := ue.ReadDetailData(ee.ReadDetailDto{Id: uint16(*resume.Encounter_Id), Includes: includes}, &event) + encounter, err := ue.ReadDetailData(ee.ReadDetailDto{Id: *resume.Encounter_Id, Includes: includes}, &event) if err != nil { return nil, err } diff --git a/internal/use-case/main-use-case/resume/case.go b/internal/use-case/main-use-case/resume/case.go index eab70280..8f771794 100644 --- a/internal/use-case/main-use-case/resume/case.go +++ b/internal/use-case/main-use-case/resume/case.go @@ -332,7 +332,7 @@ func UpdateStatusCode(input e.UpdateDto) (*d.Data, error) { return err } - enc, err := ue.ReadDetailData(ee.ReadDetailDto{Id: uint16(*data.Encounter_Id)}, &event, tx) + enc, err := ue.ReadDetailData(ee.ReadDetailDto{Id: *data.Encounter_Id}, &event, tx) if err != nil { return err } From 7a9784b4fb35c3ea64ceebd26af8f1c35623af89 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 1 Dec 2025 14:50:46 +0700 Subject: [PATCH 281/329] add therapy protocol template, not checked yet --- assets/docs/therapy-protocol-1.html | 312 ++++++++++++++++++++++++++++ assets/docs/therapy-protocol-2.html | 217 +++++++++++++++++++ assets/docs/therapy-protocol-3.html | 241 +++++++++++++++++++++ 3 files changed, 770 insertions(+) create mode 100644 assets/docs/therapy-protocol-1.html create mode 100644 assets/docs/therapy-protocol-2.html create mode 100644 assets/docs/therapy-protocol-3.html diff --git a/assets/docs/therapy-protocol-1.html b/assets/docs/therapy-protocol-1.html new file mode 100644 index 00000000..1e3949d8 --- /dev/null +++ b/assets/docs/therapy-protocol-1.html @@ -0,0 +1,312 @@ + + + + + General Consent + + + + + + + + + + +
          + logo + +
          + PEMERINTAH PROVINSI JAWA TIMUR +
          +
          + RUMAH SAKIT UMUM DAERAH Dr. SAIFUL ANWAR +
          +
          + TERAKREDITASI KARS VERSI 2012 TINGKAT PARIPURNA +
          +
          + Jl. Jaksa Agung Suprapto No. 2 MALANG 65111 +
          +
          Telp. (0341) 362101, Fax. (0341) 362110
          +
          Email: rsu-drsaifulanwar@jatimprov.go.id
          +
          Website: www.rsudsaifulanwar.jatimprov.go.id
          +
          + logo +
          + +
          + +
          +

          + Protokol Terapi +

          +

          Layanan Kedokteran Fisik dan Rehabilitasi +

          +
          +Terapi Ke

          +{{ .Repalcable }} +
          +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          + No RM + {{ .Repalcable }}
          + Nama Pasien + {{ .Repalcable }}
          + Tanggal Lahir + {{ .Repalcable }}
          + Diagnosa + {{ .Repalcable }}
          + Permintaan Terapi + {{ .Repalcable }}
          + Frekuensi Terapi + + 2 x Per Minggu       + Evaluasi: 1 Bulan +
          + Target Terapi + {{ .Repalcable }}
          + Waktu Mencapai Target + {{ .Repalcable }}
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          + NO + + Tanggal + + Dokter + + Fisioterapi + + Terapi Wicara + + Okupansi Terapi + + Ortotik Prostetik + + PSM + + TTD Pasien +
          + 1 + {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          + 2 + {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          + 3 + {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          + 4 + {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          + 5 + {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          + 6 + {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          + 7 + {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          + 8 + {{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}{{ .Repalcable }}
          + + + + + + + + + + + +
          + Evaluasi + {{ .Repalcable }}
          + Rencana Selanjutnya + {{ .Repalcable }}
          + + + + + + + + + + + +
          + Malang,
          + Cap dan TTD Dr. SpKFR +
          + (........................................................) +
          + +
          + + + \ No newline at end of file diff --git a/assets/docs/therapy-protocol-2.html b/assets/docs/therapy-protocol-2.html new file mode 100644 index 00000000..b468bd43 --- /dev/null +++ b/assets/docs/therapy-protocol-2.html @@ -0,0 +1,217 @@ + + + + + General Consent + + + + + + + + + +
          + logo + +
          + PEMERINTAH PROVINSI JAWA TIMUR +
          +
          + RUMAH SAKIT UMUM DAERAH Dr. SAIFUL ANWAR +
          +
          + TERAKREDITASI KARS VERSI 2012 TINGKAT PARIPURNA +
          +
          + Jl. Jaksa Agung Suprapto No. 2 MALANG 65111 +
          +
          Telp. (0341) 362101, Fax. (0341) 362110
          +
          Email: rsu-drsaifulanwar@jatimprov.go.id
          +
          Website: www.rsudsaifulanwar.jatimprov.go.id
          +
          + +
          + + + + + + + + + + + + + + + + + + + +
          + No RM: + {{ .Repalcable }}
          + Nama Pasien + {{ .Repalcable }}
          + Diagnosa + {{ .Repalcable }}
          + Permintaan Terapi + {{ .Repalcable }}
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          + PELAKSANAAN PROGRAM + + Tanggal + + TTD +
          + PASIEN + + DOKTER + + TERAPIS +
          1. {{ .Repalcable }}{{ .Repalcable }}
          2. {{ .Repalcable }}{{ .Repalcable }}
          3. {{ .Repalcable }}{{ .Repalcable }}
          4. {{ .Repalcable }}{{ .Repalcable }}
          5. {{ .Repalcable }}{{ .Repalcable }}
          6. {{ .Repalcable }}{{ .Repalcable }}
          7. {{ .Repalcable }}{{ .Repalcable }}
          8. {{ .Repalcable }}{{ .Repalcable }}
          9. {{ .Repalcable }}{{ .Repalcable }}
          10. {{ .Repalcable }}{{ .Repalcable }}
          11. {{ .Repalcable }}{{ .Repalcable }}
          12. {{ .Repalcable }}{{ .Repalcable }}
          13. {{ .Repalcable }}{{ .Repalcable }}
          14. {{ .Repalcable }}{{ .Repalcable }}
          15. {{ .Repalcable }}{{ .Repalcable }}
          16. {{ .Repalcable }}{{ .Repalcable }}
          17. {{ .Repalcable }}{{ .Repalcable }}
          18. {{ .Repalcable }}{{ .Repalcable }}
          19. {{ .Repalcable }}{{ .Repalcable }}
          20. {{ .Repalcable }}{{ .Repalcable }}
          + + + + + + + + + + + + + +
          + Tempat & Tanggal
          + Cap dan TTD Dr. SpKFR +
          + (.................................................) +
          + +
          + + + \ No newline at end of file diff --git a/assets/docs/therapy-protocol-3.html b/assets/docs/therapy-protocol-3.html new file mode 100644 index 00000000..6623fb9e --- /dev/null +++ b/assets/docs/therapy-protocol-3.html @@ -0,0 +1,241 @@ + + + + + General Consent + + + + + + + + + +
          + logo + +
          + PEMERINTAH PROVINSI JAWA TIMUR +
          +
          + RUMAH SAKIT UMUM DAERAH Dr. SAIFUL ANWAR +
          +
          + TERAKREDITASI KARS VERSI 2012 TINGKAT PARIPURNA +
          +
          + Jl. Jaksa Agung Suprapto No. 2 MALANG 65111 +
          +
          Telp. (0341) 362101, Fax. (0341) 362110
          +
          Email: rsu-drsaifulanwar@jatimprov.go.id
          +
          Website: www.rsudsaifulanwar.jatimprov.go.id
          +
          + +
          + +
          +

          + Lembar Formulir Rawat Jalan
          Layanan Kedokteran Fisik dan Rehabilitasi +

          +
          + +
          + + + + + + + +
          I. Identitas PasienNo. RM: {{ .Repalcable }}
          + + + + + + + + + + + + + + + + + + + + + + + +
          + Nama Pasien + : {{ .Repalcable }}
          + Tanggal Lahir + : {{ .Repalcable }}
          + Aalamat + : {{ .Repalcable }}
          + Telp / HP + : {{ .Repalcable }}
          + Hubungan dengan Tertanggung + : + ☑ Suami / Istri +    + ▢ Anak +
          +
          + + +
          + + + + +
          II. Diisi oleh Dokter SpKFR
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          + Tanggal Pelayanan + : {{ .Repalcable }}
          + Anamnesa + : {{ .Repalcable }}
          + Pemeriksaan Fisik dan Uji Fungsi + : {{ .Repalcable }}
          + Diagnosis Medis (ICD-10) + : {{ .Repalcable }}
          + Diagnosis Fungsi (ICD-10) + : {{ .Repalcable }}
          + Pemeriksaan Penunjang + : {{ .Repalcable }}
          + Tata Laksana KFR (ICD 9 CM) + : {{ .Repalcable }}
          + Anjuran + : {{ .Repalcable }}
          + Evaluasi + : {{ .Repalcable }}
          + Suspek Penyakit Akibat Kerja + : + ☑ Ya   ( {{ .Repalcable }} ) + +
          + ▢ Tidak +
          +
          + + + + + + + + + + + +
          + TTD Pasien + + Tempat & Tanggal
          + Cap dan TTD Dr. SpKFR +
          + (........................................................) + + (........................................................) +
          + +
          + + + \ No newline at end of file From ece6a0b7a5d6e7c613c3357b1f574470f3eb7275 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 1 Dec 2025 15:14:20 +0700 Subject: [PATCH 282/329] add screening --- .../migrations/20251201081333.sql | 13 ++ cmd/main-migration/migrations/atlas.sum | 115 +++++++++--------- .../domain/main-entities/screening/dto.go | 86 +++++++++++++ .../domain/main-entities/screening/entity.go | 17 +++ .../domain/references/clinical/clinical.go | 4 + internal/interface/migration/main-entities.go | 2 + 6 files changed, 180 insertions(+), 57 deletions(-) create mode 100644 cmd/main-migration/migrations/20251201081333.sql create mode 100644 internal/domain/main-entities/screening/dto.go create mode 100644 internal/domain/main-entities/screening/entity.go diff --git a/cmd/main-migration/migrations/20251201081333.sql b/cmd/main-migration/migrations/20251201081333.sql new file mode 100644 index 00000000..876b32b7 --- /dev/null +++ b/cmd/main-migration/migrations/20251201081333.sql @@ -0,0 +1,13 @@ +-- Create "Screening" table +CREATE TABLE "public"."Screening" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Employee_Id" bigint NULL, + "Type" text NULL, + "Value" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Screening_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 449ff1d4..5753c626 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:Y8m8OmsumTaAfXfYYXHlZS0+OqbAqFfM3a55nmibOUE= +h1:6lWgIJo0vUBd7Bo4B3YMvyDpJsOTVzVfqRQ03ad9r1s= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,59 +75,60 @@ h1:Y8m8OmsumTaAfXfYYXHlZS0+OqbAqFfM3a55nmibOUE= 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= +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:1946fD7iMnf18FjYzVNoHu6suWSDMfjaF2R7jx5gjo0= diff --git a/internal/domain/main-entities/screening/dto.go b/internal/domain/main-entities/screening/dto.go new file mode 100644 index 00000000..5dfed2c7 --- /dev/null +++ b/internal/domain/main-entities/screening/dto.go @@ -0,0 +1,86 @@ +package screening + +import ( + // std + + // internal - lib + pa "simrs-vx/internal/lib/auth" + + // internal - domain - base-entities + ecore "simrs-vx/internal/domain/base-entities/core" + + // internal - domain - main-entities + eem "simrs-vx/internal/domain/main-entities/employee" + + erc "simrs-vx/internal/domain/references/clinical" +) + +type CreateDto struct { + Encounter_Id *uint `json:"encounter_id"` + Employee_Id *uint `json:"-"` + Type erc.ScreeningFormTypeCode `json:"type"` + Value *string `json:"value"` + + pa.AuthInfo +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Encounter_Id *uint `json:"encounter-id"` + Employee_Id *uint `json:"employee-id"` + Type erc.ScreeningFormTypeCode `json:"type"` + Value *string `json:"value"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` +} + +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 + Encounter_Id *uint `json:"encounter_id"` + Employee_Id *uint `json:"employee_id"` + Employee *eem.Employee `json:"employee,omitempty"` + Type erc.ScreeningFormTypeCode `json:"type"` + Value *string `json:"value"` +} + +func (d Screening) ToResponse() ResponseDto { + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Employee_Id: d.Employee_Id, + Employee: d.Employee, + Type: d.Type, + Value: d.Value, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []Screening) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/screening/entity.go b/internal/domain/main-entities/screening/entity.go new file mode 100644 index 00000000..ebdb735b --- /dev/null +++ b/internal/domain/main-entities/screening/entity.go @@ -0,0 +1,17 @@ +package screening + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + eem "simrs-vx/internal/domain/main-entities/employee" + + erc "simrs-vx/internal/domain/references/clinical" +) + +type Screening struct { + ecore.Main // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Employee_Id *uint `json:"employee_id"` + Employee *eem.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` + Type erc.ScreeningFormTypeCode `json:"type"` + Value *string `json:"value"` +} diff --git a/internal/domain/references/clinical/clinical.go b/internal/domain/references/clinical/clinical.go index 30a4fe8a..4755eea1 100644 --- a/internal/domain/references/clinical/clinical.go +++ b/internal/domain/references/clinical/clinical.go @@ -22,6 +22,7 @@ type ( LearnMethodCode string LangClassCode string TranslatorSrcCode string + ScreeningFormTypeCode string ) const ( @@ -187,6 +188,9 @@ const ( TSCTeam TranslatorSrcCode = "team" // Tim Penerjemah TSCFamily TranslatorSrcCode = "family" // Keluarga + + SFTCA ScreeningFormTypeCode = "form-a" // Formu A + SFTCB ScreeningFormTypeCode = "form-b" // Formu B ) type Soapi struct { diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index 0b4a62fd..a59e9b2e 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -85,6 +85,7 @@ import ( resume "simrs-vx/internal/domain/main-entities/resume" room "simrs-vx/internal/domain/main-entities/room" sbar "simrs-vx/internal/domain/main-entities/sbar" + screening "simrs-vx/internal/domain/main-entities/screening" soapi "simrs-vx/internal/domain/main-entities/soapi" specialist "simrs-vx/internal/domain/main-entities/specialist" specialistintern "simrs-vx/internal/domain/main-entities/specialist-intern" @@ -217,5 +218,6 @@ func getMainEntities() []any { &vclaimsepcontrolletter.VclaimSepControlLetter{}, &resume.Resume{}, &vclaimreference.VclaimReference{}, + &screening.Screening{}, } } From f8f6a88ff6172f3c9e7ebf6b9910a9de3feb9a3e Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 1 Dec 2025 15:36:59 +0700 Subject: [PATCH 283/329] feat (screening): wip --- .../interface/main-handler/main-handler.go | 5 +- .../main-handler/screening/handler.go | 80 +++++ .../use-case/main-use-case/screening/case.go | 307 ++++++++++++++++++ .../main-use-case/screening/helper.go | 24 ++ .../use-case/main-use-case/screening/lib.go | 140 ++++++++ .../screening/middleware-runner.go | 103 ++++++ .../main-use-case/screening/middleware.go | 9 + .../main-use-case/screening/tycovar.go | 44 +++ 8 files changed, 711 insertions(+), 1 deletion(-) create mode 100644 internal/interface/main-handler/screening/handler.go create mode 100644 internal/use-case/main-use-case/screening/case.go create mode 100644 internal/use-case/main-use-case/screening/helper.go create mode 100644 internal/use-case/main-use-case/screening/lib.go create mode 100644 internal/use-case/main-use-case/screening/middleware-runner.go create mode 100644 internal/use-case/main-use-case/screening/middleware.go create mode 100644 internal/use-case/main-use-case/screening/tycovar.go diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 646bf053..93b645ad 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -36,6 +36,7 @@ import ( responsibledoctorhist "simrs-vx/internal/interface/main-handler/responsible-doctor-hist" resume "simrs-vx/internal/interface/main-handler/resume" sbar "simrs-vx/internal/interface/main-handler/sbar" + screening "simrs-vx/internal/interface/main-handler/screening" soapi "simrs-vx/internal/interface/main-handler/soapi" uploadfile "simrs-vx/internal/interface/main-handler/upload-file" @@ -310,7 +311,9 @@ func SetRoutes() http.Handler { "PATCH /{id}/verify": resume.Verify, "PATCH /{id}/validate": resume.Validate, }) - + hk.GroupRoutes("/v1/screening", r, auth.GuardMW, hk.MapHandlerFunc{ + "POST /": screening.O.Create, + }) /******************** actor ********************/ hc.RegCrud(r, "/v1/person", person.O) hc.RegCrud(r, "/v1/person-address", personaddress.O) diff --git a/internal/interface/main-handler/screening/handler.go b/internal/interface/main-handler/screening/handler.go new file mode 100644 index 00000000..28ca7027 --- /dev/null +++ b/internal/interface/main-handler/screening/handler.go @@ -0,0 +1,80 @@ +package screening + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/screening" + u "simrs-vx/internal/use-case/main-use-case/screening" + + pa "simrs-vx/internal/lib/auth" + + d "github.com/karincake/dodol" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.AuthInfo = *authInfo + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint16(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint16(id) + 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 = uint16(id) + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/use-case/main-use-case/screening/case.go b/internal/use-case/main-use-case/screening/case.go new file mode 100644 index 00000000..84ae4727 --- /dev/null +++ b/internal/use-case/main-use-case/screening/case.go @@ -0,0 +1,307 @@ +package screening + +import ( + "errors" + "strconv" + + e "simrs-vx/internal/domain/main-entities/screening" + + erc "simrs-vx/internal/domain/references/clinical" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "screening" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.Screening{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 input.Type == erc.SFTCB { + s, _, err := ReadListData(e.ReadListDto{FilterDto: e.FilterDto{Type: erc.SFTCA}}, &event, tx) + if err != nil { + return err + } + if len(s) != 0 { + return errors.New("screening form type A is not created yet, please create it first") + } + } + + 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.Screening + var dataList []e.Screening + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.Screening + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.Screening + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.Screening + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/screening/helper.go b/internal/use-case/main-use-case/screening/helper.go new file mode 100644 index 00000000..5174d753 --- /dev/null +++ b/internal/use-case/main-use-case/screening/helper.go @@ -0,0 +1,24 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package screening + +import ( + e "simrs-vx/internal/domain/main-entities/screening" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Screening) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Encounter_Id = inputSrc.Encounter_Id + data.Employee_Id = inputSrc.Employee_Id + data.Type = inputSrc.Type + data.Value = inputSrc.Value +} diff --git a/internal/use-case/main-use-case/screening/lib.go b/internal/use-case/main-use-case/screening/lib.go new file mode 100644 index 00000000..413e84d2 --- /dev/null +++ b/internal/use-case/main-use-case/screening/lib.go @@ -0,0 +1,140 @@ +package screening + +import ( + e "simrs-vx/internal/domain/main-entities/screening" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Screening, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.Screening{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Screening, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.Screening{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.Screening{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Order("\"CreatedAt\" DESC") + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.Screening, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.Screening{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.First(&data, input.Id).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.Screening, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.Screening, 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 +} diff --git a/internal/use-case/main-use-case/screening/middleware-runner.go b/internal/use-case/main-use-case/screening/middleware-runner.go new file mode 100644 index 00000000..9eb1b4a2 --- /dev/null +++ b/internal/use-case/main-use-case/screening/middleware-runner.go @@ -0,0 +1,103 @@ +package screening + +import ( + e "simrs-vx/internal/domain/main-entities/screening" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.Screening) 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.Screening) 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.Screening) 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.Screening) 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.Screening) 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/main-use-case/screening/middleware.go b/internal/use-case/main-use-case/screening/middleware.go new file mode 100644 index 00000000..6ec8140c --- /dev/null +++ b/internal/use-case/main-use-case/screening/middleware.go @@ -0,0 +1,9 @@ +package screening + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/screening/tycovar.go b/internal/use-case/main-use-case/screening/tycovar.go new file mode 100644 index 00000000..481f3d3e --- /dev/null +++ b/internal/use-case/main-use-case/screening/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 screening + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/screening" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.Screening, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Screening, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Screening, 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 From 32461141ab6465ec6015bb996f4fe9c850147274 Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 1 Dec 2025 16:26:45 +0700 Subject: [PATCH 284/329] add t_diagnosadanterapi and reference --- .../domain/references/clinical/clinical.go | 31 +++++++++++ .../t-diagnosadanterapi/entity.go | 51 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 internal/domain/simgos-entities/t-diagnosadanterapi/entity.go diff --git a/internal/domain/references/clinical/clinical.go b/internal/domain/references/clinical/clinical.go index 30a4fe8a..25619eab 100644 --- a/internal/domain/references/clinical/clinical.go +++ b/internal/domain/references/clinical/clinical.go @@ -311,3 +311,34 @@ type HeadToToe struct { Neuron string `json:"neuron,omitempty"` BodyOthers string `json:"body-others,omitempty"` } + +type SoapiSrc struct { + Id string `json:"id,omitempty"` + Code string `json:"code,omitempty"` + Name string `json:"name,omitempty"` + IndName string `json:"indName,omitempty"` +} + +type EarlyMedicValue struct { + Vaccinated bool `json:"vaccinated,omitempty"` + CaseStatus string `json:"case-status,omitempty"` + EncounterStatus string `json:"encounter-status,omitempty"` + PrimaryComplain string `json:"pri-complain,omitempty"` + CurrentDiseaseHistory string `json:"cur-disea-hist,omitempty"` + SpO2 int `json:"spo2,omitempty"` + SystolicBloodPressure int `json:"syst-bp,omitempty"` + DiastolicBloodPressure int `json:"diast-bp,omitempty"` + RespiratoryRate int `json:"resp-rate,omitempty"` + Pulse int `json:"pulse,omitempty"` + Weight int `json:"weight,omitempty"` + BloodType string `json:"blood-type,omitempty"` + Temperature int `json:"temp,omitempty"` + Height int `json:"height,omitempty"` + PhysicalExamination string `json:"physical-exam,omitempty"` + DiagnoseSrc []SoapiSrc `json:"diagnoseSrc,omitempty"` + ProcedureSrc []SoapiSrc `json:"procedureSrc,omitempty"` + EarlyMedicDiagnose string `json:"early-med-diag,omitempty"` + EarlyMedicPlan string `json:"early-med-plan,omitempty"` + Therapy string `json:"therapy,omitempty"` + ExpectedOutcome []SoapiSrc `json:"expected-outcome,omitempty"` +} diff --git a/internal/domain/simgos-entities/t-diagnosadanterapi/entity.go b/internal/domain/simgos-entities/t-diagnosadanterapi/entity.go new file mode 100644 index 00000000..76be4c0f --- /dev/null +++ b/internal/domain/simgos-entities/t-diagnosadanterapi/entity.go @@ -0,0 +1,51 @@ +package t_diagnosadanterapi + +import "time" + +type DiagnosaDanTerapi struct { + Idxterapi int64 `gorm:"column:idxterapi;primaryKey"` + Idxdaftar int64 `gorm:"column:idxdaftar"` + Nomr string `gorm:"column:nomr"` + Tanggal time.Time `gorm:"column:tanggal"` + TekananDarah string `gorm:"column:tekanan_darah"` + GolonganDarah string `gorm:"column:golongan_darah"` + TinggiBadan float64 `gorm:"column:tinggi_badan"` + BeratBadan float64 `gorm:"column:berat_badan"` + Diagnosa string `gorm:"column:diagnosa"` + Komplikasi string `gorm:"column:komplikasi"` + Terapi string `gorm:"column:terapi"` + Anamnesa string `gorm:"column:anamnesa"` + Kdpoly int `gorm:"column:kdpoly"` + Kddokter int `gorm:"column:kddokter"` + Kdtujuanrujuk int `gorm:"column:kdtujuanrujuk"` + Nip string `gorm:"column:nip"` + IcdCode string `gorm:"column:icd_code"` + KunjunganBl int16 `gorm:"column:kunjungan_bl"` + KasusBl int16 `gorm:"column:kasus_bl"` + Icdcm string `gorm:"column:icdcm"` + Icd9 string `gorm:"column:icd_9"` + Klb int16 `gorm:"column:klb"` + Bedah int16 `gorm:"column:bedah"` + Jenis int16 `gorm:"column:jenis"` + Perawat string `gorm:"column:perawat"` + Status string `gorm:"column:status"` + PemeriksaanFisik string `gorm:"column:pemeriksaan_fisik"` + RiwayatPasien string `gorm:"column:riwayat_pasien"` + TindakanMedis string `gorm:"column:tindakan_medis"` + Rajal int16 `gorm:"column:rajal"` + UserBatal string `gorm:"column:user_batal"` + TglBatal *time.Time `gorm:"column:tgl_batal"` + SudahVaksin string `gorm:"column:sudah_vaksin"` + CreatedAt time.Time `gorm:"column:created_at"` + DenyutJantung string `gorm:"column:denyut_jantung"` + Pernapasan string `gorm:"column:pernapasan"` + Suhu string `gorm:"column:suhu"` + Sp02 string `gorm:"column:sp02"` + TujuanPerawatan string `gorm:"column:tujuan_perawatan"` + TargetCapaian string `gorm:"column:target_capaian"` +} + +// TableName overrides the table name used by GORM +func (DiagnosaDanTerapi) TableName() string { + return "t_diagnosadanterapi" +} From c98385792a243db01388e98074b818ad701dab5d Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 1 Dec 2025 16:35:20 +0700 Subject: [PATCH 285/329] add sync entities for soapi --- .../migrations/20251201093443.sql | 36 +++++++++++++++++++ .../migrations/atlas.sum | 5 +-- internal/domain/sync-entities/soapi/entity.go | 29 +++++++++++++++ .../migration/simgossync-entities.go | 4 +++ 4 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 cmd/simgos-sync-migration/migrations/20251201093443.sql create mode 100644 internal/domain/sync-entities/soapi/entity.go diff --git a/cmd/simgos-sync-migration/migrations/20251201093443.sql b/cmd/simgos-sync-migration/migrations/20251201093443.sql new file mode 100644 index 00000000..1ecce17e --- /dev/null +++ b/cmd/simgos-sync-migration/migrations/20251201093443.sql @@ -0,0 +1,36 @@ +-- Create "SoapiLink" table +CREATE TABLE "public"."SoapiLink" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Simx_Id" bigint NULL, + "Simgos_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_SoapiLink_Simgos_Id" UNIQUE ("Simgos_Id"), + CONSTRAINT "uni_SoapiLink_Simx_Id" UNIQUE ("Simx_Id") +); +-- Create "SoapiSimgosLog" table +CREATE TABLE "public"."SoapiSimgosLog" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Value" text NULL, + "Date" timestamptz NULL, + "Status" text NULL, + "ErrMessage" text NULL, + PRIMARY KEY ("Id") +); +-- Create "SoapiSimxLog" table +CREATE TABLE "public"."SoapiSimxLog" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Value" text NULL, + "Date" timestamptz NULL, + "Status" text NULL, + "ErrMessage" text NULL, + PRIMARY KEY ("Id") +); diff --git a/cmd/simgos-sync-migration/migrations/atlas.sum b/cmd/simgos-sync-migration/migrations/atlas.sum index 497ac414..e82a5610 100644 --- a/cmd/simgos-sync-migration/migrations/atlas.sum +++ b/cmd/simgos-sync-migration/migrations/atlas.sum @@ -1,7 +1,8 @@ -h1:UdPzQZ17yyNN9HVuyrFFHj5KjLj4m6/e7s9frkdpQVU= +h1:6YZBXq/r79I5tuYyY1+CBzhZsSeukHSs8MyHCC5QuV4= 20251113035508.sql h1:rjDlu6yDdy5xv6nrCOr7NialrLSLT23pzduYNq29Hf0= 20251114071129.sql h1:Z0GQ5bJo3C+tplaWzxT8n3J9HLkEaVsRVp5nn7bmYow= 20251117041601.sql h1:l/RPG5mObqCSBjO4mzG+wTq2ieSycvlfOSz4czpUdWY= 20251118082246.sql h1:xLUwA+EvKWIg3X/TJvu7rqbtBzONiINfag5NJpMV29E= 20251118082915.sql h1:hP6FmUVFuADIN2cDg2Z1l7Wx7PQRb+IYQDvKD7J8VAM= -20251126115527.sql h1:+2bp2nWTTqaPpKKfy5ZYSr6b1nEUXFG3tIw4r3OEnAQ= +20251126115527.sql h1:Bvg+Y7k+h5s+/UaezUyJb7J7uzEJS7U5Z/RoCixcUtI= +20251201093443.sql h1:m18tksKG3OzbkxXkhfKUUqbkxnJ0VBPi3Cw34Tbywyc= diff --git a/internal/domain/sync-entities/soapi/entity.go b/internal/domain/sync-entities/soapi/entity.go new file mode 100644 index 00000000..0a1315c7 --- /dev/null +++ b/internal/domain/sync-entities/soapi/entity.go @@ -0,0 +1,29 @@ +package Soapi + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + erc "simrs-vx/internal/domain/references/common" + "time" +) + +type SoapiLink struct { + ecore.Main + Simx_Id uint `json:"simx_id" gorm:"unique"` + Simgos_Id uint `json:"simgos_id" gorm:"unique"` +} + +type SoapiSimxLog struct { + ecore.Main + Value *string `json:"value"` + Date *time.Time `json:"date"` + Status erc.ProcessStatusCode `json:"status"` + ErrMessage *string `json:"errMessage"` +} + +type SoapiSimgosLog struct { + ecore.Main + Value *string `json:"value"` + Date *time.Time `json:"date"` + Status erc.ProcessStatusCode `json:"status"` + ErrMessage *string `json:"errMessage"` +} diff --git a/internal/interface/migration/simgossync-entities.go b/internal/interface/migration/simgossync-entities.go index 7b37a842..2c479521 100644 --- a/internal/interface/migration/simgossync-entities.go +++ b/internal/interface/migration/simgossync-entities.go @@ -7,6 +7,7 @@ import ( installation "simrs-vx/internal/domain/sync-entities/installation" internalreference "simrs-vx/internal/domain/sync-entities/internal-reference" patient "simrs-vx/internal/domain/sync-entities/patient" + soapi "simrs-vx/internal/domain/sync-entities/soapi" specialist "simrs-vx/internal/domain/sync-entities/specialist" subspecialist "simrs-vx/internal/domain/sync-entities/subspecialist" unit "simrs-vx/internal/domain/sync-entities/unit" @@ -38,5 +39,8 @@ func getSyncEntities() []any { &internalreference.InternalReferenceLink{}, &internalreference.InternalReferenceSimxLog{}, &internalreference.InternalReferenceSimgosLog{}, + &soapi.SoapiLink{}, + &soapi.SoapiSimxLog{}, + &soapi.SoapiSimgosLog{}, } } From df3ed7919e53c491851ea926f46ac9cdb85cf194 Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 1 Dec 2025 17:03:24 +0700 Subject: [PATCH 286/329] adjust diagnosaandterapi entity --- .../t-diagnosadanterapi/entity.go | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/internal/domain/simgos-entities/t-diagnosadanterapi/entity.go b/internal/domain/simgos-entities/t-diagnosadanterapi/entity.go index 76be4c0f..3c3c3e59 100644 --- a/internal/domain/simgos-entities/t-diagnosadanterapi/entity.go +++ b/internal/domain/simgos-entities/t-diagnosadanterapi/entity.go @@ -3,8 +3,8 @@ package t_diagnosadanterapi import "time" type DiagnosaDanTerapi struct { - Idxterapi int64 `gorm:"column:idxterapi;primaryKey"` - Idxdaftar int64 `gorm:"column:idxdaftar"` + Idxterapi uint `gorm:"column:idxterapi;primaryKey"` + Idxdaftar uint `gorm:"column:idxdaftar"` Nomr string `gorm:"column:nomr"` Tanggal time.Time `gorm:"column:tanggal"` TekananDarah string `gorm:"column:tekanan_darah"` @@ -15,24 +15,24 @@ type DiagnosaDanTerapi struct { Komplikasi string `gorm:"column:komplikasi"` Terapi string `gorm:"column:terapi"` Anamnesa string `gorm:"column:anamnesa"` - Kdpoly int `gorm:"column:kdpoly"` - Kddokter int `gorm:"column:kddokter"` - Kdtujuanrujuk int `gorm:"column:kdtujuanrujuk"` + Kdpoly uint `gorm:"column:kdpoly"` + Kddokter uint `gorm:"column:kddokter"` + Kdtujuanrujuk uint `gorm:"column:kdtujuanrujuk"` Nip string `gorm:"column:nip"` IcdCode string `gorm:"column:icd_code"` - KunjunganBl int16 `gorm:"column:kunjungan_bl"` - KasusBl int16 `gorm:"column:kasus_bl"` + KunjunganBl uint `gorm:"column:kunjungan_bl"` + KasusBl uint `gorm:"column:kasus_bl"` Icdcm string `gorm:"column:icdcm"` Icd9 string `gorm:"column:icd_9"` - Klb int16 `gorm:"column:klb"` - Bedah int16 `gorm:"column:bedah"` - Jenis int16 `gorm:"column:jenis"` + Klb uint `gorm:"column:klb"` + Bedah uint `gorm:"column:bedah"` + Jenis uint `gorm:"column:jenis"` Perawat string `gorm:"column:perawat"` Status string `gorm:"column:status"` PemeriksaanFisik string `gorm:"column:pemeriksaan_fisik"` RiwayatPasien string `gorm:"column:riwayat_pasien"` TindakanMedis string `gorm:"column:tindakan_medis"` - Rajal int16 `gorm:"column:rajal"` + Rajal uint `gorm:"column:rajal"` UserBatal string `gorm:"column:user_batal"` TglBatal *time.Time `gorm:"column:tgl_batal"` SudahVaksin string `gorm:"column:sudah_vaksin"` From 8306e1217e2db071f433d52fa7ce1090d13a9104 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Mon, 1 Dec 2025 17:47:59 +0700 Subject: [PATCH 287/329] feat/action-report: done --- .../migrations/20251201104439.sql | 19 ++ cmd/main-migration/migrations/atlas.sum | 5 +- .../domain/main-entities/action-report/dto.go | 89 ++++++ .../main-entities/action-report/entity.go | 45 +++ .../domain/references/clinical/clinical.go | 66 ++++ .../references/organization/organization.go | 5 + .../main-handler/action-report/handler.go | 80 +++++ .../interface/main-handler/main-handler.go | 2 + internal/interface/migration/main-entities.go | 2 + .../main-use-case/action-report/case.go | 295 ++++++++++++++++++ .../main-use-case/action-report/helper.go | 28 ++ .../main-use-case/action-report/lib.go | 140 +++++++++ .../action-report/middleware-runner.go | 103 ++++++ .../main-use-case/action-report/middleware.go | 9 + .../main-use-case/action-report/tycovar.go | 44 +++ 15 files changed, 930 insertions(+), 2 deletions(-) create mode 100644 cmd/main-migration/migrations/20251201104439.sql create mode 100644 internal/domain/main-entities/action-report/dto.go create mode 100644 internal/domain/main-entities/action-report/entity.go create mode 100644 internal/interface/main-handler/action-report/handler.go create mode 100644 internal/use-case/main-use-case/action-report/case.go create mode 100644 internal/use-case/main-use-case/action-report/helper.go create mode 100644 internal/use-case/main-use-case/action-report/lib.go create mode 100644 internal/use-case/main-use-case/action-report/middleware-runner.go create mode 100644 internal/use-case/main-use-case/action-report/middleware.go create mode 100644 internal/use-case/main-use-case/action-report/tycovar.go diff --git a/cmd/main-migration/migrations/20251201104439.sql b/cmd/main-migration/migrations/20251201104439.sql new file mode 100644 index 00000000..50f60b6b --- /dev/null +++ b/cmd/main-migration/migrations/20251201104439.sql @@ -0,0 +1,19 @@ +-- Create "ActionReport" table +CREATE TABLE "public"."ActionReport" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Date" character varying(20) NOT NULL, + "Doctor_Code" character varying(10) NULL, + "Operator_Employe_Id" bigint NULL, + "Assistant_Employe_Id" bigint NULL, + "Instrumentor_Employe_Id" bigint NULL, + "Diagnose" character varying(1024) NULL, + "Procedures" character varying(10240) NULL, + "Nurse_Code" character varying(10) NULL, + "Value" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_ActionReport_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 5753c626..c02dc2b8 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:6lWgIJo0vUBd7Bo4B3YMvyDpJsOTVzVfqRQ03ad9r1s= +h1:oIkzjGilKCqqfLGlvMc2I2WwJ8zQgdMeTWy25k1uaLI= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -131,4 +131,5 @@ h1:6lWgIJo0vUBd7Bo4B3YMvyDpJsOTVzVfqRQ03ad9r1s= 20251124071457.sql h1:qg2dhCL9YwD13xnfJ175lW/p6MGfzFKaBqd908FByRc= 20251125125303.sql h1:4JSFv1Pmhbe9tqpLXgO63OwYnGsalStgUXKVWPyc1YE= 20251126064057.sql h1:vAdhz5Nn/gGJy0UKZAEldeXv8HpHtJU/t8ygDVIbTsU= -20251201081333.sql h1:1946fD7iMnf18FjYzVNoHu6suWSDMfjaF2R7jx5gjo0= +20251201081333.sql h1:PoC8ADRdwDuohDTB74yW/DaB42igdYa4B6humbrEJBk= +20251201104439.sql h1:EIBP67qeQWEYMdMOM/gouXzkAM4R3vSkmuw4Fe8usOs= diff --git a/internal/domain/main-entities/action-report/dto.go b/internal/domain/main-entities/action-report/dto.go new file mode 100644 index 00000000..1edb4a73 --- /dev/null +++ b/internal/domain/main-entities/action-report/dto.go @@ -0,0 +1,89 @@ +package actionreport + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/encounter" + + pa "simrs-vx/internal/lib/auth" +) + +type CreateDto struct { + Encounter_Id uint64 `json:"encounter_id"` + Date string `json:"date"` + Doctor_Code string `json:"doctor_code"` + Operator_Employe_Id *uint `json:"operator_employe_id"` + Assistant_Employe_Id *uint `json:"assistant_employe_id"` + Instrumentor_Employe_Id *uint `json:"instrumentor_employe_id"` + Diagnose *string `json:"diagnose"` + Nurse_Code *string `json:"nurse_code"` + Value string `json:"value"` + + pa.AuthInfo +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Encounter_Id *uint `json:"encounter-id"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` +} + +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 + Encounter_Id uint64 `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty"` + Date string `json:"date"` + Doctor_Code string `json:"doctor_code"` + Operator_Employe_Id *uint `json:"operator_employe_id"` + Assistant_Employe_Id *uint `json:"assistant_employe_id"` + Instrumentor_Employe_Id *uint `json:"instrumentor_employe_id"` + Diagnose *string `json:"diagnose"` + Nurse_Code *string `json:"nurse_code"` + Value *string `json:"value"` +} + +func (d ActionReport) ToResponse() ResponseDto { + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Encounter: d.Encounter, + Date: d.Date, + Doctor_Code: d.Doctor_Code, + Operator_Employe_Id: d.Operator_Employe_Id, + Assistant_Employe_Id: d.Assistant_Employe_Id, + Instrumentor_Employe_Id: d.Instrumentor_Employe_Id, + Nurse_Code: d.Nurse_Code, + Value: &d.Value, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []ActionReport) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/action-report/entity.go b/internal/domain/main-entities/action-report/entity.go new file mode 100644 index 00000000..3437136e --- /dev/null +++ b/internal/domain/main-entities/action-report/entity.go @@ -0,0 +1,45 @@ +package actionreport + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/encounter" +) + +type ActionReport struct { + ecore.Main // adjust this according to the needs + Encounter_Id uint64 `json:"encounter_id" gorm:"foreignKey"` + Encounter *ee.Encounter `json:"doctor,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + Date string `json:"date" gorm:"not null;size:20"` + Doctor_Code string `json:"doctor_code" gorm:"size:10"` + Operator_Employe_Id *uint `json:"operator_employe_id"` + Assistant_Employe_Id *uint `json:"assistant_employe_id"` + Instrumentor_Employe_Id *uint `json:"instrumentor_employe_id"` + Diagnose *string `json:"diagnose" gorm:"size:1024"` + Procedures *string `json:"procedures" gorm:"size:10240"` + Nurse_Code *string `json:"nurse_code" gorm:"size:10"` + + Value string `json:"value"` + // SurgerySize_Code *string `json:"surgerySize_code" gorm:"size:10"` + // Billing_Code *string `json:"billing_code" gorm:"size:10"` + // SurgerySystem_Code *string `json:"surgerySystem_code" gorm:"size:10"` + // StartAt *string `json:"startAt" gorm:"size:20"` + // EndAt *string `json:"endAt" gorm:"size:20"` + // AnesthesiaStartAt *string `json:"anesthesiaStartAt" gorm:"size:20"` + // AnesthesiaEndAt *string `json:"anesthesiaEndAt" gorm:"size:20"` + // SurgeryType_Code *string `json:"surgeryType_code" gorm:"size:10"` + // SurgeryStage_Code *string `json:"surgeryStage_code" gorm:"size:10"` + // BornMortality_Code *string `json:"bornMortality_code" gorm:"size:10"` + // BornLocation_Code *string `json:"bornLocation_code" gorm:"size:10"` + // Weight *string `json:"weight" gorm:"size:10"` + // BornNotes *string `json:"bornNotes" gorm:"size:1024"` + // Description *string `json:"notes" gorm:"size:1024"` + // BleedingAmount *uint16 `json:"bleedingAmount" gorm:"size:10"` + // BloodInType_Code *string `json:"bloodInType_code" gorm:"size:10"` + // BloodInAmount *uint16 `json:"bloodInAmount" gorm:"size:10"` + // Brand *string `json:"brand" gorm:"size:100"` + // ImplantName *string `json:"implantName" gorm:"size:100"` + // ImplantRegisterNumber *string `json:"implantRegisterNumber" gorm:"size:100"` + // ImplantCompanionName *string `json:"implantCompanionName" gorm:"size:100"` + // SpecimentDest_Code *string `json:"specimentDest" gorm:"size:100"` + // TissueInfo *string `json:"tissueInfo" gorm:"size:100"` +} diff --git a/internal/domain/references/clinical/clinical.go b/internal/domain/references/clinical/clinical.go index 4755eea1..7a3a2ec1 100644 --- a/internal/domain/references/clinical/clinical.go +++ b/internal/domain/references/clinical/clinical.go @@ -23,6 +23,13 @@ type ( LangClassCode string TranslatorSrcCode string ScreeningFormTypeCode string + SurgerySizeCode string + SurgerySystemCode string + SurgeryTypeCode string + SurgeryStageCode string + BornMortalityCode string + BornLocationCode string + SpecimentDestCode string ) const ( @@ -191,6 +198,38 @@ const ( SFTCA ScreeningFormTypeCode = "form-a" // Formu A SFTCB ScreeningFormTypeCode = "form-b" // Formu B + + SSCSmall SurgerySizeCode = "" + SSCMedium SurgerySizeCode = "" + SSCLarge SurgerySizeCode = "" + SSCSpecial SurgerySizeCode = "" + + SSyCCito SurgerySystemCode = "" + SSyCUrgent SurgerySystemCode = "" + SSyCEfective SurgerySystemCode = "" + SSyCSpecial SurgerySystemCode = "" + + STCClean SurgeryTypeCode = "" + STCCleanCtm SurgeryTypeCode = "" + STCUncleanCtm SurgeryTypeCode = "" + STCUnclean SurgeryTypeCode = "" + + SStCFirst SurgeryStageCode = "" + SStCRepeat SurgeryStageCode = "" + + BMCAlive BornMortalityCode = "" + BMCDead BornMortalityCode = "" + + BLCExtMiw BornLocationCode = "" + BLCExtDoc BornLocationCode = "" + BLCTradMiw BornLocationCode = "" + BLCLocalMed BornLocationCode = "" + BLCExtParamedic BornLocationCode = "" + + SDCAp SpecimentDestCode = "" + SDCMicro SpecimentDestCode = "" + SDCLab SpecimentDestCode = "" + SDCNone SpecimentDestCode = "" ) type Soapi struct { @@ -315,3 +354,30 @@ type HeadToToe struct { Neuron string `json:"neuron,omitempty"` BodyOthers string `json:"body-others,omitempty"` } + +type RecordAction struct { + Procedures []string `json:"procedures"` + SurgerySize_Code *string `json:"surgerySize_code"` + Billing_Code *string `json:"billing_code"` + SurgerySystem_Code *string `json:"surgerySystem_code"` + StartAt *string `json:"startAt"` + EndAt *string `json:"endAt"` + AnesthesiaStartAt *string `json:"anesthesiaStartAt"` + AnesthesiaEndAt *string `json:"anesthesiaEndAt"` + SurgeryType_Code *string `json:"surgeryType_code"` + SurgeryStage_Code *string `json:"surgeryStage_code"` + BornMortality_Code *string `json:"bornMortality_code"` + BornLocation_Code *string `json:"bornLocation_code"` + Weight *string `json:"weight"` + BornNotes *string `json:"bornNotes" gorm:"size:1024"` + Description *string `json:"notes" gorm:"size:1024"` + BleedingAmount *uint16 `json:"bleedingAmount"` + BloodInType_Code *string `json:"bloodInType_code"` + BloodInAmount *uint16 `json:"bloodInAmount"` + Brand *string `json:"brand" gorm:"size:100"` + ImplantName *string `json:"implantName" gorm:"size:100"` + ImplantRegisterNumber *string `json:"implantRegisterNumber" gorm:"size:100"` + ImplantCompanionName *string `json:"implantCompanionName" gorm:"size:100"` + SpecimentDest_Code *string `json:"specimentDest" gorm:"size:100"` + TissueInfo []string `json:"tissueInfo" gorm:"size:100"` +} diff --git a/internal/domain/references/organization/organization.go b/internal/domain/references/organization/organization.go index e12531cd..5b2b4343 100644 --- a/internal/domain/references/organization/organization.go +++ b/internal/domain/references/organization/organization.go @@ -8,6 +8,7 @@ type ( InfraGroupCode string UnitTypeCode string DoctorFeeTypeCode string + ActionBillingCode string ) const ( @@ -62,4 +63,8 @@ const ( DFTCInp DoctorFeeTypeCode = "inpatient" // Rawat Inap DFTCEme DoctorFeeTypeCode = "emergency" // Darurat DFTCReh DoctorFeeTypeCode = "medic-rehab" // Rehab Medik + + ABCGeneral ActionBillingCode = "general" + ABCRegional ActionBillingCode = "regional" + ABCLocal ActionBillingCode = "local" ) diff --git a/internal/interface/main-handler/action-report/handler.go b/internal/interface/main-handler/action-report/handler.go new file mode 100644 index 00000000..0fdd1851 --- /dev/null +++ b/internal/interface/main-handler/action-report/handler.go @@ -0,0 +1,80 @@ +package soapi + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/action-report" + u "simrs-vx/internal/use-case/main-use-case/action-report" + + pa "simrs-vx/internal/lib/auth" + + d "github.com/karincake/dodol" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.AuthInfo = *authInfo + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint16(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint16(id) + 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 = uint16(id) + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 646bf053..dd025d0e 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -4,6 +4,7 @@ import ( "net/http" /******************** main / transaction ********************/ + actionreport "simrs-vx/internal/interface/main-handler/action-report" adime "simrs-vx/internal/interface/main-handler/adime" admemployeehist "simrs-vx/internal/interface/main-handler/adm-employee-hist" ambulancetransportrequest "simrs-vx/internal/interface/main-handler/ambulance-transport-req" @@ -171,6 +172,7 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/sbar", auth.GuardMW, sbar.O) hc.RegCrud(r, "/v1/prescription-item", prescriptionitem.O) hc.RegCrud(r, "/v1/device-order-item", deviceorderitem.O) + hc.RegCrud(r, "/v1/action-report", auth.GuardMW, actionreport.O) hc.RegCrud(r, "/v1/material-order-item", materialorderitem.O) hk.GroupRoutes("/v1/encounter", r, auth.GuardMW, hk.MapHandlerFunc{ diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index a59e9b2e..bed0c18c 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -1,6 +1,7 @@ package migration import ( + actionreport "simrs-vx/internal/domain/main-entities/action-report" adime "simrs-vx/internal/domain/main-entities/adime" admemployeehist "simrs-vx/internal/domain/main-entities/adm-employee-hist" ambulancetransportreq "simrs-vx/internal/domain/main-entities/ambulance-transport-req" @@ -219,5 +220,6 @@ func getMainEntities() []any { &resume.Resume{}, &vclaimreference.VclaimReference{}, &screening.Screening{}, + &actionreport.ActionReport{}, } } diff --git a/internal/use-case/main-use-case/action-report/case.go b/internal/use-case/main-use-case/action-report/case.go new file mode 100644 index 00000000..2ae0f268 --- /dev/null +++ b/internal/use-case/main-use-case/action-report/case.go @@ -0,0 +1,295 @@ +package actionreport + +import ( + "errors" + "strconv" + + e "simrs-vx/internal/domain/main-entities/action-report" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "action-report" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.ActionReport{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.ActionReport + var dataList []e.ActionReport + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.ActionReport + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.ActionReport + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.ActionReport + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/action-report/helper.go b/internal/use-case/main-use-case/action-report/helper.go new file mode 100644 index 00000000..efe4532e --- /dev/null +++ b/internal/use-case/main-use-case/action-report/helper.go @@ -0,0 +1,28 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package actionreport + +import ( + e "simrs-vx/internal/domain/main-entities/action-report" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.ActionReport) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Encounter_Id = inputSrc.Encounter_Id + data.Date = inputSrc.Date + data.Doctor_Code = inputSrc.Doctor_Code + data.Operator_Employe_Id = inputSrc.Operator_Employe_Id + data.Assistant_Employe_Id = inputSrc.Assistant_Employe_Id + data.Instrumentor_Employe_Id = inputSrc.Instrumentor_Employe_Id + data.Nurse_Code = inputSrc.Nurse_Code + data.Value = inputSrc.Value +} diff --git a/internal/use-case/main-use-case/action-report/lib.go b/internal/use-case/main-use-case/action-report/lib.go new file mode 100644 index 00000000..5a272cce --- /dev/null +++ b/internal/use-case/main-use-case/action-report/lib.go @@ -0,0 +1,140 @@ +package actionreport + +import ( + e "simrs-vx/internal/domain/main-entities/action-report" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.ActionReport, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.ActionReport{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.ActionReport, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.ActionReport{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.ActionReport{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Order("\"CreatedAt\" DESC") + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.ActionReport, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.ActionReport{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.First(&data, input.Id).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.ActionReport, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.ActionReport, 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 +} diff --git a/internal/use-case/main-use-case/action-report/middleware-runner.go b/internal/use-case/main-use-case/action-report/middleware-runner.go new file mode 100644 index 00000000..e2544169 --- /dev/null +++ b/internal/use-case/main-use-case/action-report/middleware-runner.go @@ -0,0 +1,103 @@ +package actionreport + +import ( + e "simrs-vx/internal/domain/main-entities/action-report" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.ActionReport) 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.ActionReport) 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.ActionReport) 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.ActionReport) 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.ActionReport) 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/main-use-case/action-report/middleware.go b/internal/use-case/main-use-case/action-report/middleware.go new file mode 100644 index 00000000..50254de2 --- /dev/null +++ b/internal/use-case/main-use-case/action-report/middleware.go @@ -0,0 +1,9 @@ +package actionreport + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/action-report/tycovar.go b/internal/use-case/main-use-case/action-report/tycovar.go new file mode 100644 index 00000000..9eebfabd --- /dev/null +++ b/internal/use-case/main-use-case/action-report/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 actionreport + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/action-report" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.ActionReport, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.ActionReport, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.ActionReport, 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 From 50db75e014b64cdda8a3df5176d61697ef2b2eb3 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 1 Dec 2025 15:14:20 +0700 Subject: [PATCH 288/329] add screening --- .../migrations/20251201081333.sql | 13 ++ cmd/main-migration/migrations/atlas.sum | 115 +++++++++--------- .../domain/main-entities/screening/dto.go | 86 +++++++++++++ .../domain/main-entities/screening/entity.go | 17 +++ .../domain/references/clinical/clinical.go | 4 + internal/interface/migration/main-entities.go | 2 + 6 files changed, 180 insertions(+), 57 deletions(-) create mode 100644 cmd/main-migration/migrations/20251201081333.sql create mode 100644 internal/domain/main-entities/screening/dto.go create mode 100644 internal/domain/main-entities/screening/entity.go diff --git a/cmd/main-migration/migrations/20251201081333.sql b/cmd/main-migration/migrations/20251201081333.sql new file mode 100644 index 00000000..876b32b7 --- /dev/null +++ b/cmd/main-migration/migrations/20251201081333.sql @@ -0,0 +1,13 @@ +-- Create "Screening" table +CREATE TABLE "public"."Screening" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Employee_Id" bigint NULL, + "Type" text NULL, + "Value" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Screening_Employee" FOREIGN KEY ("Employee_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 449ff1d4..b4c4fe05 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:Y8m8OmsumTaAfXfYYXHlZS0+OqbAqFfM3a55nmibOUE= +h1:fkwkWe2PSYaTNxdTEmwe747+bhXV+kOcly/gC7dq/Q8= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,59 +75,60 @@ h1:Y8m8OmsumTaAfXfYYXHlZS0+OqbAqFfM3a55nmibOUE= 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= +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= diff --git a/internal/domain/main-entities/screening/dto.go b/internal/domain/main-entities/screening/dto.go new file mode 100644 index 00000000..5dfed2c7 --- /dev/null +++ b/internal/domain/main-entities/screening/dto.go @@ -0,0 +1,86 @@ +package screening + +import ( + // std + + // internal - lib + pa "simrs-vx/internal/lib/auth" + + // internal - domain - base-entities + ecore "simrs-vx/internal/domain/base-entities/core" + + // internal - domain - main-entities + eem "simrs-vx/internal/domain/main-entities/employee" + + erc "simrs-vx/internal/domain/references/clinical" +) + +type CreateDto struct { + Encounter_Id *uint `json:"encounter_id"` + Employee_Id *uint `json:"-"` + Type erc.ScreeningFormTypeCode `json:"type"` + Value *string `json:"value"` + + pa.AuthInfo +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Encounter_Id *uint `json:"encounter-id"` + Employee_Id *uint `json:"employee-id"` + Type erc.ScreeningFormTypeCode `json:"type"` + Value *string `json:"value"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` +} + +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 + Encounter_Id *uint `json:"encounter_id"` + Employee_Id *uint `json:"employee_id"` + Employee *eem.Employee `json:"employee,omitempty"` + Type erc.ScreeningFormTypeCode `json:"type"` + Value *string `json:"value"` +} + +func (d Screening) ToResponse() ResponseDto { + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Employee_Id: d.Employee_Id, + Employee: d.Employee, + Type: d.Type, + Value: d.Value, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []Screening) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/screening/entity.go b/internal/domain/main-entities/screening/entity.go new file mode 100644 index 00000000..ebdb735b --- /dev/null +++ b/internal/domain/main-entities/screening/entity.go @@ -0,0 +1,17 @@ +package screening + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + eem "simrs-vx/internal/domain/main-entities/employee" + + erc "simrs-vx/internal/domain/references/clinical" +) + +type Screening struct { + ecore.Main // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Employee_Id *uint `json:"employee_id"` + Employee *eem.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` + Type erc.ScreeningFormTypeCode `json:"type"` + Value *string `json:"value"` +} diff --git a/internal/domain/references/clinical/clinical.go b/internal/domain/references/clinical/clinical.go index 30a4fe8a..4755eea1 100644 --- a/internal/domain/references/clinical/clinical.go +++ b/internal/domain/references/clinical/clinical.go @@ -22,6 +22,7 @@ type ( LearnMethodCode string LangClassCode string TranslatorSrcCode string + ScreeningFormTypeCode string ) const ( @@ -187,6 +188,9 @@ const ( TSCTeam TranslatorSrcCode = "team" // Tim Penerjemah TSCFamily TranslatorSrcCode = "family" // Keluarga + + SFTCA ScreeningFormTypeCode = "form-a" // Formu A + SFTCB ScreeningFormTypeCode = "form-b" // Formu B ) type Soapi struct { diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index 0b4a62fd..a59e9b2e 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -85,6 +85,7 @@ import ( resume "simrs-vx/internal/domain/main-entities/resume" room "simrs-vx/internal/domain/main-entities/room" sbar "simrs-vx/internal/domain/main-entities/sbar" + screening "simrs-vx/internal/domain/main-entities/screening" soapi "simrs-vx/internal/domain/main-entities/soapi" specialist "simrs-vx/internal/domain/main-entities/specialist" specialistintern "simrs-vx/internal/domain/main-entities/specialist-intern" @@ -217,5 +218,6 @@ func getMainEntities() []any { &vclaimsepcontrolletter.VclaimSepControlLetter{}, &resume.Resume{}, &vclaimreference.VclaimReference{}, + &screening.Screening{}, } } From 4f6bc8da314809802b07305f851c8e2ebd59f12f Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Mon, 1 Dec 2025 18:02:20 +0700 Subject: [PATCH 289/329] feat/action-report: migrated + finishing --- cmd/main-migration/migrations/atlas.sum | 7 ++----- internal/domain/main-entities/mcu-order-item/entity.go | 4 +++- internal/domain/references/clinical/clinical.go | 6 ------ 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index bdc2efaf..8f71fcc5 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,8 +1,4 @@ -<<<<<<< HEAD -h1:oIkzjGilKCqqfLGlvMc2I2WwJ8zQgdMeTWy25k1uaLI= -======= -h1:fkwkWe2PSYaTNxdTEmwe747+bhXV+kOcly/gC7dq/Q8= ->>>>>>> migration +h1:NUsCmkoiBso9yZsv4HWrn3+woqMcFRFtgXKln5rY4pQ= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -136,3 +132,4 @@ h1:fkwkWe2PSYaTNxdTEmwe747+bhXV+kOcly/gC7dq/Q8= 20251125125303.sql h1:4JSFv1Pmhbe9tqpLXgO63OwYnGsalStgUXKVWPyc1YE= 20251126064057.sql h1:vAdhz5Nn/gGJy0UKZAEldeXv8HpHtJU/t8ygDVIbTsU= 20251201081333.sql h1:PoC8ADRdwDuohDTB74yW/DaB42igdYa4B6humbrEJBk= +20251201104439.sql h1:tpqdrOf9d2aGwZshqm62nG6SXnfVaO/g6A7z0efPS14= diff --git a/internal/domain/main-entities/mcu-order-item/entity.go b/internal/domain/main-entities/mcu-order-item/entity.go index 48a57bac..7d4d757d 100644 --- a/internal/domain/main-entities/mcu-order-item/entity.go +++ b/internal/domain/main-entities/mcu-order-item/entity.go @@ -4,12 +4,14 @@ import ( emo "simrs-vx/internal/domain/main-entities/mcu-order" emoib "simrs-vx/internal/domain/main-entities/mcu-order-item/base" + emosi "simrs-vx/internal/domain/main-entities/mcu-order-sub-item/base" erc "simrs-vx/internal/domain/references/common" ) type McuOrderItem struct { emoib.McuOrderItem - McuOrder *emo.McuOrder `json:"mcuOrder,omitempty" gorm:"foreignKey:McuOrder_Id;references:Id"` + McuOrder *emo.McuOrder `json:"mcuOrder,omitempty" gorm:"foreignKey:McuOrder_Id;references:Id"` + Items []*emosi.McuOrderSubItem `json:"items" gorm:"foreignKey:McuOrderItem_Id;references:Id"` } func (d McuOrderItem) IsCompleted() bool { diff --git a/internal/domain/references/clinical/clinical.go b/internal/domain/references/clinical/clinical.go index f6c1b572..7a3a2ec1 100644 --- a/internal/domain/references/clinical/clinical.go +++ b/internal/domain/references/clinical/clinical.go @@ -23,7 +23,6 @@ type ( LangClassCode string TranslatorSrcCode string ScreeningFormTypeCode string -<<<<<<< HEAD SurgerySizeCode string SurgerySystemCode string SurgeryTypeCode string @@ -31,8 +30,6 @@ type ( BornMortalityCode string BornLocationCode string SpecimentDestCode string -======= ->>>>>>> migration ) const ( @@ -201,7 +198,6 @@ const ( SFTCA ScreeningFormTypeCode = "form-a" // Formu A SFTCB ScreeningFormTypeCode = "form-b" // Formu B -<<<<<<< HEAD SSCSmall SurgerySizeCode = "" SSCMedium SurgerySizeCode = "" @@ -234,8 +230,6 @@ const ( SDCMicro SpecimentDestCode = "" SDCLab SpecimentDestCode = "" SDCNone SpecimentDestCode = "" -======= ->>>>>>> migration ) type Soapi struct { From b65c86750ab673866c46b21e7980e4d6c78e561d Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Mon, 1 Dec 2025 18:39:28 +0700 Subject: [PATCH 290/329] feat/action-report: new migration --- .../migrations/20251201113804.sql | 2 ++ .../migrations/20251201113858.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 4 ++- .../domain/main-entities/action-report/dto.go | 29 ++++++++++--------- .../main-entities/action-report/entity.go | 12 ++++---- 5 files changed, 28 insertions(+), 21 deletions(-) create mode 100644 cmd/main-migration/migrations/20251201113804.sql create mode 100644 cmd/main-migration/migrations/20251201113858.sql diff --git a/cmd/main-migration/migrations/20251201113804.sql b/cmd/main-migration/migrations/20251201113804.sql new file mode 100644 index 00000000..0f5c5123 --- /dev/null +++ b/cmd/main-migration/migrations/20251201113804.sql @@ -0,0 +1,2 @@ +-- Modify "ActionReport" table +ALTER TABLE "public"."ActionReport" DROP COLUMN "Date", DROP COLUMN "Procedures"; diff --git a/cmd/main-migration/migrations/20251201113858.sql b/cmd/main-migration/migrations/20251201113858.sql new file mode 100644 index 00000000..fd6fddc9 --- /dev/null +++ b/cmd/main-migration/migrations/20251201113858.sql @@ -0,0 +1,2 @@ +-- Modify "ActionReport" table +ALTER TABLE "public"."ActionReport" ADD COLUMN "Date" timestamptz NOT NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 8f71fcc5..db6de529 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:NUsCmkoiBso9yZsv4HWrn3+woqMcFRFtgXKln5rY4pQ= +h1:EpEYOCY46tEg91o5Y4scmFj3/yIyR311HaP95Ts3vus= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -133,3 +133,5 @@ h1:NUsCmkoiBso9yZsv4HWrn3+woqMcFRFtgXKln5rY4pQ= 20251126064057.sql h1:vAdhz5Nn/gGJy0UKZAEldeXv8HpHtJU/t8ygDVIbTsU= 20251201081333.sql h1:PoC8ADRdwDuohDTB74yW/DaB42igdYa4B6humbrEJBk= 20251201104439.sql h1:tpqdrOf9d2aGwZshqm62nG6SXnfVaO/g6A7z0efPS14= +20251201113804.sql h1:pR0nbmjJNDLi929vmGm2W9RKxLJ2iECzf2otO+JpKWA= +20251201113858.sql h1:JciS3xbCF94huB0qkGJ24YtS1a+nqV26hxzeKh2AOj0= diff --git a/internal/domain/main-entities/action-report/dto.go b/internal/domain/main-entities/action-report/dto.go index 1edb4a73..45c26d17 100644 --- a/internal/domain/main-entities/action-report/dto.go +++ b/internal/domain/main-entities/action-report/dto.go @@ -3,20 +3,21 @@ package actionreport import ( ecore "simrs-vx/internal/domain/base-entities/core" ee "simrs-vx/internal/domain/main-entities/encounter" + "time" pa "simrs-vx/internal/lib/auth" ) type CreateDto struct { - Encounter_Id uint64 `json:"encounter_id"` - Date string `json:"date"` - Doctor_Code string `json:"doctor_code"` - Operator_Employe_Id *uint `json:"operator_employe_id"` - Assistant_Employe_Id *uint `json:"assistant_employe_id"` - Instrumentor_Employe_Id *uint `json:"instrumentor_employe_id"` - Diagnose *string `json:"diagnose"` - Nurse_Code *string `json:"nurse_code"` - Value string `json:"value"` + Encounter_Id uint64 `json:"encounter_id" validate:"required"` + Date *time.Time `json:"date" validate:"required"` + Doctor_Code string `json:"doctor_code" validate:"required"` + Operator_Employe_Id uint `json:"operator_employe_id" validate:"required"` + Assistant_Employe_Id uint `json:"assistant_employe_id" validate:"required"` + Instrumentor_Employe_Id uint `json:"instrumentor_employe_id" validate:"required"` + Diagnose *string `json:"diagnose"` + Nurse_Code string `json:"nurse_code" validate:"required"` + Value string `json:"value" validate:"required"` pa.AuthInfo } @@ -54,13 +55,13 @@ type ResponseDto struct { ecore.Main Encounter_Id uint64 `json:"encounter_id"` Encounter *ee.Encounter `json:"encounter,omitempty"` - Date string `json:"date"` + Date *time.Time `json:"date"` Doctor_Code string `json:"doctor_code"` - Operator_Employe_Id *uint `json:"operator_employe_id"` - Assistant_Employe_Id *uint `json:"assistant_employe_id"` - Instrumentor_Employe_Id *uint `json:"instrumentor_employe_id"` + Operator_Employe_Id uint `json:"operator_employe_id"` + Assistant_Employe_Id uint `json:"assistant_employe_id"` + Instrumentor_Employe_Id uint `json:"instrumentor_employe_id"` Diagnose *string `json:"diagnose"` - Nurse_Code *string `json:"nurse_code"` + Nurse_Code string `json:"nurse_code"` Value *string `json:"value"` } diff --git a/internal/domain/main-entities/action-report/entity.go b/internal/domain/main-entities/action-report/entity.go index 3437136e..b3fc1956 100644 --- a/internal/domain/main-entities/action-report/entity.go +++ b/internal/domain/main-entities/action-report/entity.go @@ -3,20 +3,20 @@ package actionreport import ( ecore "simrs-vx/internal/domain/base-entities/core" ee "simrs-vx/internal/domain/main-entities/encounter" + "time" ) type ActionReport struct { ecore.Main // adjust this according to the needs Encounter_Id uint64 `json:"encounter_id" gorm:"foreignKey"` Encounter *ee.Encounter `json:"doctor,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Date string `json:"date" gorm:"not null;size:20"` + Date *time.Time `json:"date" gorm:"not null;size:20"` Doctor_Code string `json:"doctor_code" gorm:"size:10"` - Operator_Employe_Id *uint `json:"operator_employe_id"` - Assistant_Employe_Id *uint `json:"assistant_employe_id"` - Instrumentor_Employe_Id *uint `json:"instrumentor_employe_id"` + Operator_Employe_Id uint `json:"operator_employe_id"` + Assistant_Employe_Id uint `json:"assistant_employe_id"` + Instrumentor_Employe_Id uint `json:"instrumentor_employe_id"` Diagnose *string `json:"diagnose" gorm:"size:1024"` - Procedures *string `json:"procedures" gorm:"size:10240"` - Nurse_Code *string `json:"nurse_code" gorm:"size:10"` + Nurse_Code string `json:"nurse_code" gorm:"size:10"` Value string `json:"value"` // SurgerySize_Code *string `json:"surgerySize_code" gorm:"size:10"` From 47d2e427c0d75a4e5f937291e4911194625530ea Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Mon, 1 Dec 2025 18:49:54 +0700 Subject: [PATCH 291/329] feat/action-report: adjust table structure --- cmd/main-migration/migrations/20251201114751.sql | 2 ++ cmd/main-migration/migrations/20251201114913.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 8 +++++--- .../domain/main-entities/action-report/entity.go | 12 +++++++++--- 4 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 cmd/main-migration/migrations/20251201114751.sql create mode 100644 cmd/main-migration/migrations/20251201114913.sql diff --git a/cmd/main-migration/migrations/20251201114751.sql b/cmd/main-migration/migrations/20251201114751.sql new file mode 100644 index 00000000..6611b811 --- /dev/null +++ b/cmd/main-migration/migrations/20251201114751.sql @@ -0,0 +1,2 @@ +-- Modify "ActionReport" table +ALTER TABLE "public"."ActionReport" ADD CONSTRAINT "fk_ActionReport_Instrumentor_Employe" FOREIGN KEY ("Instrumentor_Employe_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_ActionReport_Nurse" FOREIGN KEY ("Nurse_Code") REFERENCES "public"."Nurse" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_ActionReport_Operator_Employe" FOREIGN KEY ("Operator_Employe_Id") REFERENCES "public"."Employee" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/20251201114913.sql b/cmd/main-migration/migrations/20251201114913.sql new file mode 100644 index 00000000..5155ed37 --- /dev/null +++ b/cmd/main-migration/migrations/20251201114913.sql @@ -0,0 +1,2 @@ +-- Modify "ActionReport" table +ALTER TABLE "public"."ActionReport" ADD CONSTRAINT "fk_ActionReport_Doctor" FOREIGN KEY ("Doctor_Code") REFERENCES "public"."Doctor" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index db6de529..51161909 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:EpEYOCY46tEg91o5Y4scmFj3/yIyR311HaP95Ts3vus= +h1:bYhAmgY4p8jgE8JpZ6YeJyS1iYCH2LEvDXW2PE+iZpc= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -133,5 +133,7 @@ h1:EpEYOCY46tEg91o5Y4scmFj3/yIyR311HaP95Ts3vus= 20251126064057.sql h1:vAdhz5Nn/gGJy0UKZAEldeXv8HpHtJU/t8ygDVIbTsU= 20251201081333.sql h1:PoC8ADRdwDuohDTB74yW/DaB42igdYa4B6humbrEJBk= 20251201104439.sql h1:tpqdrOf9d2aGwZshqm62nG6SXnfVaO/g6A7z0efPS14= -20251201113804.sql h1:pR0nbmjJNDLi929vmGm2W9RKxLJ2iECzf2otO+JpKWA= -20251201113858.sql h1:JciS3xbCF94huB0qkGJ24YtS1a+nqV26hxzeKh2AOj0= +20251201113804.sql h1:kIEmVoETJXBkab2Q+b3y/pP84eF8W2BdQ47amHCnc+c= +20251201113858.sql h1:KLXKZO5XTQPoEU0YLHE8Fhg9WPKpSN3wNgYPJ+RGFcg= +20251201114751.sql h1:QMcFLz4vr6lwQ03k0Wthhosce743DW9A3w6WJzfqjoU= +20251201114913.sql h1:GvRLyn62Z5CIckonFhtHOZKbJK43yyoCXUfFiADLiAo= diff --git a/internal/domain/main-entities/action-report/entity.go b/internal/domain/main-entities/action-report/entity.go index b3fc1956..8447a2e5 100644 --- a/internal/domain/main-entities/action-report/entity.go +++ b/internal/domain/main-entities/action-report/entity.go @@ -2,23 +2,29 @@ package actionreport import ( ecore "simrs-vx/internal/domain/base-entities/core" + ed "simrs-vx/internal/domain/main-entities/doctor" + eem "simrs-vx/internal/domain/main-entities/employee" ee "simrs-vx/internal/domain/main-entities/encounter" + en "simrs-vx/internal/domain/main-entities/nurse" "time" ) type ActionReport struct { ecore.Main // adjust this according to the needs Encounter_Id uint64 `json:"encounter_id" gorm:"foreignKey"` - Encounter *ee.Encounter `json:"doctor,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Date *time.Time `json:"date" gorm:"not null;size:20"` Doctor_Code string `json:"doctor_code" gorm:"size:10"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"` Operator_Employe_Id uint `json:"operator_employe_id"` + Operator_Employe *eem.Employee `json:"operator_employe,omitempty" gorm:"foreignKey:Operator_Employe_Id;references:Id"` Assistant_Employe_Id uint `json:"assistant_employe_id"` Instrumentor_Employe_Id uint `json:"instrumentor_employe_id"` + Instrumentor_Employe *eem.Employee `json:"instrumentor_employe,omitempty" gorm:"foreignKey:Instrumentor_Employe_Id;references:Id"` Diagnose *string `json:"diagnose" gorm:"size:1024"` Nurse_Code string `json:"nurse_code" gorm:"size:10"` - - Value string `json:"value"` + Nurse *en.Nurse `json:"nurse,omitempty" gorm:"foreignKey:Nurse_Code;references:Code"` + Value string `json:"value"` // SurgerySize_Code *string `json:"surgerySize_code" gorm:"size:10"` // Billing_Code *string `json:"billing_code" gorm:"size:10"` // SurgerySystem_Code *string `json:"surgerySystem_code" gorm:"size:10"` From 17bf6cd2ae0c3280435cf72c2fbf211c6dff3d20 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Mon, 1 Dec 2025 20:12:13 +0700 Subject: [PATCH 292/329] feat/mcu-order: wip --- .../mcu-order-sub-item/base/entity.go | 17 +++++++++++++++++ .../main-entities/mcu-order-sub-item/entity.go | 12 ++++-------- .../main-entities/mcu-src-category/dto.go | 10 +++++----- .../main-entities/mcu-src-category/entity.go | 2 +- internal/domain/references/clinical/clinical.go | 8 ++++++-- 5 files changed, 33 insertions(+), 16 deletions(-) create mode 100644 internal/domain/main-entities/mcu-order-sub-item/base/entity.go diff --git a/internal/domain/main-entities/mcu-order-sub-item/base/entity.go b/internal/domain/main-entities/mcu-order-sub-item/base/entity.go new file mode 100644 index 00000000..fea105a4 --- /dev/null +++ b/internal/domain/main-entities/mcu-order-sub-item/base/entity.go @@ -0,0 +1,17 @@ +package mcuordersubitem + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + emss "simrs-vx/internal/domain/main-entities/mcu-sub-src" + + erc "simrs-vx/internal/domain/references/common" +) + +type McuOrderSubItem struct { + ecore.Main // adjust this according to the needs + McuSubSrc_Code *string `json:"mcuSubSrc_code" gorm:"uniqueIndex:idx_order_sub_src"` + McuSubSrc *emss.McuSubSrc `json:"mcuSubSrc,omitempty" gorm:"foreignKey:McuSubSrc_Code;references:Code"` + McuOrderItem_Id *uint `json:"mcuOrderItem_id" gorm:"uniqueIndex:idx_order_sub_src"` + Result *string `json:"result"` + Status_Code erc.DataStatusCode `json:"status_code"` +} diff --git a/internal/domain/main-entities/mcu-order-sub-item/entity.go b/internal/domain/main-entities/mcu-order-sub-item/entity.go index a9bde496..990cd048 100644 --- a/internal/domain/main-entities/mcu-order-sub-item/entity.go +++ b/internal/domain/main-entities/mcu-order-sub-item/entity.go @@ -3,19 +3,15 @@ package mcuordersubitem import ( ecore "simrs-vx/internal/domain/base-entities/core" emoi "simrs-vx/internal/domain/main-entities/mcu-order-item" - emss "simrs-vx/internal/domain/main-entities/mcu-sub-src" + eb "simrs-vx/internal/domain/main-entities/mcu-order-sub-item/base" erc "simrs-vx/internal/domain/references/common" ) type McuOrderSubItem struct { - ecore.Main // adjust this according to the needs - McuSubSrc_Code *string `json:"mcuSubSrc_code" gorm:"uniqueIndex:idx_order_sub_src"` - McuSubSrc *emss.McuSubSrc `json:"mcuSubSrc,omitempty" gorm:"foreignKey:McuSubSrc_Code;references:Code"` - McuOrderItem_Id *uint `json:"mcuOrderItem_id" gorm:"uniqueIndex:idx_order_sub_src"` - McuOrderItem *emoi.McuOrderItem `json:"mcuOrderItem,omitempty" gorm:"foreignKey:McuOrderItem_Id;references:Id"` - Result *string `json:"result"` - Status_Code erc.DataStatusCode `json:"status_code"` + ecore.Main // adjust this according to the needs + eb.McuOrderSubItem + McuOrderItem *emoi.McuOrderItem `json:"mcuOrderItem,omitempty" gorm:"foreignKey:McuOrderItem_Id;references:Id"` } func (d McuOrderSubItem) IsCompleted() bool { diff --git a/internal/domain/main-entities/mcu-src-category/dto.go b/internal/domain/main-entities/mcu-src-category/dto.go index f9bb7d00..e1ef57d9 100644 --- a/internal/domain/main-entities/mcu-src-category/dto.go +++ b/internal/domain/main-entities/mcu-src-category/dto.go @@ -1,4 +1,4 @@ -package division +package mcusrccategory import ( ecore "simrs-vx/internal/domain/base-entities/core" @@ -20,10 +20,10 @@ type ReadListDto struct { } type FilterDto struct { - Code string `json:"code"` - Name string `json:"name"` - Scope_Code *erc.McuScopeCode `json:"scope-code"` - Search string `json:"search" gormhelper:"searchColumns=Code,Name"` + Code *string `json:"code"` + Name *string `json:"name"` + Scope_Code *string `json:"scope-code"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` } type ReadDetailDto struct { diff --git a/internal/domain/main-entities/mcu-src-category/entity.go b/internal/domain/main-entities/mcu-src-category/entity.go index 8fc801b9..2175552c 100644 --- a/internal/domain/main-entities/mcu-src-category/entity.go +++ b/internal/domain/main-entities/mcu-src-category/entity.go @@ -1,4 +1,4 @@ -package division +package mcusrccategory import ( ecore "simrs-vx/internal/domain/base-entities/core" diff --git a/internal/domain/references/clinical/clinical.go b/internal/domain/references/clinical/clinical.go index 7a3a2ec1..43305a99 100644 --- a/internal/domain/references/clinical/clinical.go +++ b/internal/domain/references/clinical/clinical.go @@ -196,8 +196,12 @@ const ( TSCTeam TranslatorSrcCode = "team" // Tim Penerjemah TSCFamily TranslatorSrcCode = "family" // Keluarga - SFTCA ScreeningFormTypeCode = "form-a" // Formu A - SFTCB ScreeningFormTypeCode = "form-b" // Formu B + SFTCA ScreeningFormTypeCode = "form-a" // Formu A + SFTCB ScreeningFormTypeCode = "form-b" // Formu B + MSCRadiology McuScopeCode = "radiology" + MSCCpLab McuScopeCode = "cp-lab" + MSCMicroLab McuScopeCode = "micro-lab" + MSCApLab McuScopeCode = "ap-lab" SSCSmall SurgerySizeCode = "" SSCMedium SurgerySizeCode = "" From 5aa558e189439de3720db9023239e6ea6c3262b6 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Tue, 2 Dec 2025 09:34:51 +0700 Subject: [PATCH 293/329] dev: hotfix, doctor getdetail --- internal/domain/main-entities/doctor/dto.go | 1 + .../mcu-order-sub-item/base/entity.go | 15 +++++++++++++++ .../main-entities/mcu-order-sub-item/entity.go | 12 +++++------- internal/interface/main-handler/doctor/handler.go | 1 + internal/use-case/main-use-case/doctor/lib.go | 4 +++- 5 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 internal/domain/main-entities/mcu-order-sub-item/base/entity.go diff --git a/internal/domain/main-entities/doctor/dto.go b/internal/domain/main-entities/doctor/dto.go index e3d1f3ee..c7eb0f6b 100644 --- a/internal/domain/main-entities/doctor/dto.go +++ b/internal/domain/main-entities/doctor/dto.go @@ -43,6 +43,7 @@ type ReadDetailDto struct { Employee_Id *uint `json:"employee_id"` IHS_Number *string `json:"ihs_number"` SIP_Number *string `json:"sip_number"` + Includes string `json:"includes"` } type UpdateDto struct { diff --git a/internal/domain/main-entities/mcu-order-sub-item/base/entity.go b/internal/domain/main-entities/mcu-order-sub-item/base/entity.go new file mode 100644 index 00000000..0022744b --- /dev/null +++ b/internal/domain/main-entities/mcu-order-sub-item/base/entity.go @@ -0,0 +1,15 @@ +package mcuordersubitem + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + + erc "simrs-vx/internal/domain/references/common" +) + +type McuOrderSubItem struct { + ecore.Main // adjust this according to the needs + McuSubSrc_Code *string `json:"mcuSubSrc_code" gorm:"uniqueIndex:idx_order_sub_src"` + McuOrderItem_Id *uint `json:"mcuOrderItem_id" gorm:"uniqueIndex:idx_order_sub_src"` + Result *string `json:"result"` + Status_Code erc.DataStatusCode `json:"status_code"` +} diff --git a/internal/domain/main-entities/mcu-order-sub-item/entity.go b/internal/domain/main-entities/mcu-order-sub-item/entity.go index a9bde496..b594a91b 100644 --- a/internal/domain/main-entities/mcu-order-sub-item/entity.go +++ b/internal/domain/main-entities/mcu-order-sub-item/entity.go @@ -5,17 +5,15 @@ import ( emoi "simrs-vx/internal/domain/main-entities/mcu-order-item" emss "simrs-vx/internal/domain/main-entities/mcu-sub-src" + emosi "simrs-vx/internal/domain/main-entities/mcu-order-sub-item/base" erc "simrs-vx/internal/domain/references/common" ) type McuOrderSubItem struct { - ecore.Main // adjust this according to the needs - McuSubSrc_Code *string `json:"mcuSubSrc_code" gorm:"uniqueIndex:idx_order_sub_src"` - McuSubSrc *emss.McuSubSrc `json:"mcuSubSrc,omitempty" gorm:"foreignKey:McuSubSrc_Code;references:Code"` - McuOrderItem_Id *uint `json:"mcuOrderItem_id" gorm:"uniqueIndex:idx_order_sub_src"` - McuOrderItem *emoi.McuOrderItem `json:"mcuOrderItem,omitempty" gorm:"foreignKey:McuOrderItem_Id;references:Id"` - Result *string `json:"result"` - Status_Code erc.DataStatusCode `json:"status_code"` + ecore.Main // adjust this according to the needs + McuSubSrc *emss.McuSubSrc `json:"mcuSubSrc,omitempty" gorm:"foreignKey:McuSubSrc_Code;references:Code"` + McuOrderItem *emoi.McuOrderItem `json:"mcuOrderItem,omitempty" gorm:"foreignKey:McuOrderItem_Id;references:Id"` + emosi.McuOrderSubItem } func (d McuOrderSubItem) IsCompleted() bool { diff --git a/internal/interface/main-handler/doctor/handler.go b/internal/interface/main-handler/doctor/handler.go index f62495d6..b700103a 100644 --- a/internal/interface/main-handler/doctor/handler.go +++ b/internal/interface/main-handler/doctor/handler.go @@ -38,6 +38,7 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { return } dto := e.ReadDetailDto{} + sf.UrlQueryParam(&dto, *r.URL) dto.Code = &code res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) diff --git a/internal/use-case/main-use-case/doctor/lib.go b/internal/use-case/main-use-case/doctor/lib.go index 827802fa..9efe2239 100644 --- a/internal/use-case/main-use-case/doctor/lib.go +++ b/internal/use-case/main-use-case/doctor/lib.go @@ -1,6 +1,7 @@ package doctor import ( + "fmt" e "simrs-vx/internal/domain/main-entities/doctor" plh "simrs-vx/pkg/lib-helper" @@ -90,7 +91,8 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e if input.Code != nil { tx = tx.Where("\"Code\" = ?", input.Code) } - if err := tx.First(&data).Error; err != nil { + fmt.Println(input.Includes) + if err := tx.Scopes(gh.Preload(input.Includes)).First(&data).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { return nil, processedErr } From 29d11c0e0089214cc8acbb5b184f0f3250b9a9e0 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 2 Dec 2025 10:07:31 +0700 Subject: [PATCH 294/329] (screening): add file-url and status --- cmd/main-migration/migrations/20251202030445.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 5 +++-- internal/domain/main-entities/screening/entity.go | 3 +++ internal/domain/references/organization/organization.go | 1 + 4 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 cmd/main-migration/migrations/20251202030445.sql diff --git a/cmd/main-migration/migrations/20251202030445.sql b/cmd/main-migration/migrations/20251202030445.sql new file mode 100644 index 00000000..6026dd58 --- /dev/null +++ b/cmd/main-migration/migrations/20251202030445.sql @@ -0,0 +1,2 @@ +-- Modify "Screening" table +ALTER TABLE "public"."Screening" ADD COLUMN "Status" text NULL, ADD COLUMN "FileUrl" character varying(1024) NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 5753c626..806ee054 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:6lWgIJo0vUBd7Bo4B3YMvyDpJsOTVzVfqRQ03ad9r1s= +h1:XoKMjGA4FCg2pZKaGZmX61liDEkRUDnYo+NyFKmtikw= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -131,4 +131,5 @@ h1:6lWgIJo0vUBd7Bo4B3YMvyDpJsOTVzVfqRQ03ad9r1s= 20251124071457.sql h1:qg2dhCL9YwD13xnfJ175lW/p6MGfzFKaBqd908FByRc= 20251125125303.sql h1:4JSFv1Pmhbe9tqpLXgO63OwYnGsalStgUXKVWPyc1YE= 20251126064057.sql h1:vAdhz5Nn/gGJy0UKZAEldeXv8HpHtJU/t8ygDVIbTsU= -20251201081333.sql h1:1946fD7iMnf18FjYzVNoHu6suWSDMfjaF2R7jx5gjo0= +20251201081333.sql h1:PoC8ADRdwDuohDTB74yW/DaB42igdYa4B6humbrEJBk= +20251202030445.sql h1:9VbV03AMtKKPagtLKl4+hZrE6mMFV6DG78Gn7QOsFXI= diff --git a/internal/domain/main-entities/screening/entity.go b/internal/domain/main-entities/screening/entity.go index ebdb735b..a6284c16 100644 --- a/internal/domain/main-entities/screening/entity.go +++ b/internal/domain/main-entities/screening/entity.go @@ -5,6 +5,7 @@ import ( eem "simrs-vx/internal/domain/main-entities/employee" erc "simrs-vx/internal/domain/references/clinical" + erco "simrs-vx/internal/domain/references/common" ) type Screening struct { @@ -13,5 +14,7 @@ type Screening struct { Employee_Id *uint `json:"employee_id"` Employee *eem.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` Type erc.ScreeningFormTypeCode `json:"type"` + Status erco.DataVerifiedCode `json:"status"` Value *string `json:"value"` + FileUrl *string `json:"fileUrl" gorm:"size:1024"` } diff --git a/internal/domain/references/organization/organization.go b/internal/domain/references/organization/organization.go index e12531cd..e522a35e 100644 --- a/internal/domain/references/organization/organization.go +++ b/internal/domain/references/organization/organization.go @@ -24,6 +24,7 @@ const ( EPCLab EmployeePositionCode = "lab" // Laboran EPCPha EmployeePositionCode = "pha" // Farmasi EPCNom EmployeePositionCode = "nom" // Non Medic + EPCScr EmployeePositionCode = "scr" // Screening MPP // EPCPay EmployeePositionCode = "pay" // Pembayaran // EPCHur EmployeePositionCode = "hue" // Sumber Daya Manusia // EPCGea EmployeePositionCode = "gea" // Bagian Umum From 7e454b0a2d72b55a6aba982f71401a8d66f5fb5e Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 2 Dec 2025 10:17:06 +0700 Subject: [PATCH 295/329] feat (user): add screening role --- internal/use-case/main-use-case/user/case.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/internal/use-case/main-use-case/user/case.go b/internal/use-case/main-use-case/user/case.go index 50b676af..f6faec22 100644 --- a/internal/use-case/main-use-case/user/case.go +++ b/internal/use-case/main-use-case/user/case.go @@ -166,7 +166,7 @@ func Create(input e.CreateDto) (*d.Data, error) { if _, err := umw.CreateData(createMidWife, &event, tx); err != nil { return err } - case ero.EPCReg: + case ero.EPCReg, ero.EPCScr: // do nothing default: return errors.New("invalid employee position") @@ -523,6 +523,8 @@ func Update(input e.UpdateDto) (*d.Data, error) { if _, err := umw.CreateData(createMidWife, &event, tx); err != nil { return err } + case ero.EPCReg, ero.EPCScr: + // do nothing default: return errors.New("invalid employee position") } From f4f47118824bf1b6fbb3a21ec78d204c3b509404 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Tue, 2 Dec 2025 11:46:02 +0700 Subject: [PATCH 296/329] feat/mcu-order: adjust entity --- cmd/main-migration/migrations/20251202044430.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 8 +++++--- internal/domain/main-entities/item/dto.go | 4 ++++ internal/domain/main-entities/item/entity.go | 2 ++ 4 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 cmd/main-migration/migrations/20251202044430.sql diff --git a/cmd/main-migration/migrations/20251202044430.sql b/cmd/main-migration/migrations/20251202044430.sql new file mode 100644 index 00000000..308b72a7 --- /dev/null +++ b/cmd/main-migration/migrations/20251202044430.sql @@ -0,0 +1,2 @@ +-- Modify "Item" table +ALTER TABLE "public"."Item" ADD COLUMN "BuyingPrice" numeric NULL, ADD COLUMN "SellingPrice" numeric NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 51161909..871cc312 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:bYhAmgY4p8jgE8JpZ6YeJyS1iYCH2LEvDXW2PE+iZpc= +h1:Ha8JZHXBp6W+fzzWOIT8TuDGwBAPu7d/JQa4hxKMCRw= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -135,5 +135,7 @@ h1:bYhAmgY4p8jgE8JpZ6YeJyS1iYCH2LEvDXW2PE+iZpc= 20251201104439.sql h1:tpqdrOf9d2aGwZshqm62nG6SXnfVaO/g6A7z0efPS14= 20251201113804.sql h1:kIEmVoETJXBkab2Q+b3y/pP84eF8W2BdQ47amHCnc+c= 20251201113858.sql h1:KLXKZO5XTQPoEU0YLHE8Fhg9WPKpSN3wNgYPJ+RGFcg= -20251201114751.sql h1:QMcFLz4vr6lwQ03k0Wthhosce743DW9A3w6WJzfqjoU= -20251201114913.sql h1:GvRLyn62Z5CIckonFhtHOZKbJK43yyoCXUfFiADLiAo= +20251201114751.sql h1:HM17diiPknfSHAmP+kJGP6GzToaPU9/NT+KQBpf3Jq0= +20251201114913.sql h1:gqucFgHFFLA6n/Rdz486cZH5xkaJuwefESLJMJLDue8= +20251202030445.sql h1:QWBVfTepT7DaXP5E0BYoxNM0JwKIQ2qIMXzI4kbz/qE= +20251202044430.sql h1:OC5NTh0Jf8NNLVTRIvNImPiaMqJfDWkksxWcKq3UjDE= diff --git a/internal/domain/main-entities/item/dto.go b/internal/domain/main-entities/item/dto.go index f20ce217..686a5c17 100644 --- a/internal/domain/main-entities/item/dto.go +++ b/internal/domain/main-entities/item/dto.go @@ -62,6 +62,8 @@ type ResponseDto struct { Uom *eu.Uom `json:"uom,omitempty"` Infra_Code *string `json:"infra_code"` Stock *int `json:"stock"` + BuyingPrice *float64 `json:"buyingPrice"` + SellingPrice *float64 `json:"sellingPrice"` } func (d Item) ToResponse() ResponseDto { @@ -73,6 +75,8 @@ func (d Item) ToResponse() ResponseDto { Uom: d.Uom, Infra_Code: d.Infra_Code, Stock: d.Stock, + BuyingPrice: d.BuyingPrice, + SellingPrice: d.SellingPrice, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/item/entity.go b/internal/domain/main-entities/item/entity.go index fc721713..55ca2d18 100644 --- a/internal/domain/main-entities/item/entity.go +++ b/internal/domain/main-entities/item/entity.go @@ -16,4 +16,6 @@ type Item struct { Uom *eu.Uom `json:"uom,omitempty" gorm:"foreignKey:Uom_Code;references:Code"` Infra_Code *string `json:"infra_code" gorm:"size:10"` Stock *int `json:"stock"` + BuyingPrice *float64 `json:"buyingPrice"` + SellingPrice *float64 `json:"settlingPrice"` } From 5adb4e566699ce02177d08f9e227cbcea250c81f Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 2 Dec 2025 13:37:26 +0700 Subject: [PATCH 297/329] wip --- assets/docs/screening-form-a.html | 131 ++++++++++++++++++ assets/docs/screening-form-b.html | 127 +++++++++++++++++ .../domain/main-entities/screening/dto.go | 36 +++++ .../domain/main-entities/screening/entity.go | 2 + .../main-handler/screening/handler.go | 80 +++++------ internal/lib/auth/tycovar.go | 7 + .../use-case/main-use-case/screening/case.go | 19 ++- .../main-use-case/screening/helper.go | 2 + 8 files changed, 361 insertions(+), 43 deletions(-) create mode 100644 assets/docs/screening-form-a.html create mode 100644 assets/docs/screening-form-b.html diff --git a/assets/docs/screening-form-a.html b/assets/docs/screening-form-a.html new file mode 100644 index 00000000..768eb183 --- /dev/null +++ b/assets/docs/screening-form-a.html @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          + Tanggal Terbit + : {{ .Repalcable }}
          + No. RM + : {{ .Repalcable }}
          + Nama + : {{ .Repalcable }}
          + Tanggal Lahir + : {{ .Repalcable }}
          + +
          +

          + FORM A +

          + +
          +

          Kajian Awal Medis:

          + + + + + + + +
          + ☑ Kasus Dengan Penyakit Kronis, Katastropik (memerlukan Pembiayaan Tinggi), Terminal +
          + ▢ Status Fungsional Rendah, Kebutuhan Bantuan ADL(Activity Daily Living) Yang Tinggi +
          +
          + +
          +

          ASSESMEN:

          + + +
          +
          + +
          +

          IDENTIFIKASI MASALAH:

          + + +
          +
          + +
          +

          PERENCANAAN:

          + + +
          +
          + + + + + + + + + + +
          + 2025-10-08 16:06:22 +
          + GATOT SUBROTO,AMd.Kep +
          + +
          + + + \ No newline at end of file diff --git a/assets/docs/screening-form-b.html b/assets/docs/screening-form-b.html new file mode 100644 index 00000000..1ae8a07c --- /dev/null +++ b/assets/docs/screening-form-b.html @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          + Tanggal Terbit + : {{ .Repalcable }}
          + No. RM + : {{ .Repalcable }}
          + Nama + : {{ .Repalcable }}
          + Tanggal Lahir + : {{ .Repalcable }}
          + +
          +

          + FORM B +

          + + + + + + + + + + + + + + +
          + NO + + Tanggal/jam + + Implementasi, Monitoring, Fasilitasi, koordinasi, komunikasi dan kolaborasi, advokasi, hasil pelayanan, + Terminasi + + MPP +
          + 1 + + 2025-10-08 16:08:18 + +
            +
          • Implementasi: Pemantauan harian terhadap penggunaan alat medis (oksigen dan alat bantu + jalan) serta kepatuhan terapi.
          • +
          • Monitoring: Observasi respon pasien terhadap terapi dan edukasi keluarga untuk perawatan + mandiri di rumah.
          • +
          • Fasilitasi: Menyediakan alat bantu sesuai kebutuhan dan menghubungkan pasien dengan + layanan rehabilitasi medik.
          • +
          • Koordinasi: Melibatkan dokter penanggung jawab, perawat, dan keluarga dalam penyusunan + rencana tindak lanjut.
          • +
          • Komunikasi dan Kolaborasi: Diskusi rutin antar profesi untuk evaluasi perkembangan + pasien.
          • +
          • Advokasi: Memberikan dukungan informasi dan hak pasien terkait rencana pulang dan + kesinambungan terapi.
          • +
          • Hasil Pelayanan: Pasien menunjukkan perbaikan fungsi mobilitas, tingkat kepatuhan terapi + meningkat.
          • +
          +
          + GATOT SUBROTO,AMd.Kep +
          + +
          + + + \ No newline at end of file diff --git a/internal/domain/main-entities/screening/dto.go b/internal/domain/main-entities/screening/dto.go index 5dfed2c7..cdcc96dc 100644 --- a/internal/domain/main-entities/screening/dto.go +++ b/internal/domain/main-entities/screening/dto.go @@ -84,3 +84,39 @@ func ToResponseList(data []Screening) []ResponseDto { } return resp } + +type FormA struct { + AgeAtRisk bool `json:"ageAtRisk"` // Usia Dengan Risiko + LowCognitiveFunction bool `json:"lowCognitiveFunction"` // Pasien Dengan Fungsi Kognitif Rendah + HighRiskPatient bool `json:"highRiskPatient"` // Pasien Dengan Risiko Tinggi + HighComplaintPotential bool `json:"highComplaintPotential"` // Potensi Komplain Tinggi (Medik dan Non Medik) + ChronicOrCatastrophicOrTerminal bool `json:"chronicOrCatastrophicOrTerminal"` // Kasus Dengan Penyakit Kronis, Katastropik, Terminal + LowFunctionalStatus bool `json:"lowFunctionalStatus"` // Status Fungsional Rendah, Kebutuhan Bantuan ADL Tinggi + HistoryOfMedicalDeviceUse bool `json:"historyOfMedicalDeviceUse"` // Pasien Dengan Riwayat Penggunaan Peralatan Medis Masa Lalu + MentalOrSocialIssues bool `json:"mentalOrSocialIssues"` // Riwayat Gangguan Mental, Bunuh Diri, Krisis Keluarga, Isu Sosial + FrequentERVisitsOrReadmission bool `json:"frequentERVisitsOrReadmission"` // Sering Masuk IGD, Readmisi RS + HighCareCostEstimate bool `json:"highCareCostEstimate"` // Perkiraan Asuhan Dengan Biaya Tinggi + ComplexFinancingSystem bool `json:"complexFinancingSystem"` // Kemungkinan Sistem Pembiayaan Yang Kompleks + AboveAverageLengthOfStay bool `json:"aboveAverageLengthOfStay"` // Kasus Yang Melebihi Rata-Rata Lama Dirawat + ImportantOrHighRiskDischargePlanning bool `json:"importantOrHighRiskDischargePlanning"` // Rencana Pemulangan Penting / Kontinuitas Pelayanan + Stagnation bool `json:"stagnation"` // Stagnasi +} + +type ProblemIdentification struct { + CareNotFollowingGuidelines bool `json:"careNotFollowingGuidelines"` // Tingkat Asuhan Tidak Sesuai Panduan/ Norma + OverUtilization bool `json:"overUtilization"` // Over Utilization Pelayanan + UnderUtilization bool `json:"underUtilization"` // Under Utilization Pelayanan + PatientNonCompliance bool `json:"patientNonCompliance"` // Ketidakpatuhan Pasien + InadequateEducation bool `json:"inadequateEducation"` // Edukasi Kurang Memadai + LackOfFamilySupport bool `json:"lackOfFamilySupport"` // Kurang Dukungan Keluarga + DecreasedDetermination bool `json:"decreasedDetermination"` // Penurunan Determinasi Ketika Komplikasi Meningkat + FinancialDifficultyDuringComplications bool `json:"financialDifficultyDuringComplications"` // Kendala Keuangan Ketika Komplikasi Meningkat + DischargeCriteriaNotMetOrDelayed bool `json:"dischargeCriteriaNotMetOrDelayed"` // Pemulangan/ Rujukan Belum Memenuhi Kriteria/ Ditunda +} + +type AssessmentForm struct { + Screening Screening `json:"screening"` + AssessmentDetail string `json:"assessmentDetail"` // Masukkan detail assesmen + ProblemIdentification ProblemIdentification `json:"problemIdentification"` + PlanningDetail string `json:"planningDetail"` // Masukkan detail perencanaan +} diff --git a/internal/domain/main-entities/screening/entity.go b/internal/domain/main-entities/screening/entity.go index a6284c16..fa650165 100644 --- a/internal/domain/main-entities/screening/entity.go +++ b/internal/domain/main-entities/screening/entity.go @@ -18,3 +18,5 @@ type Screening struct { Value *string `json:"value"` FileUrl *string `json:"fileUrl" gorm:"size:1024"` } + +// func (d Screening) UnMarshal(data []byte) (error {} diff --git a/internal/interface/main-handler/screening/handler.go b/internal/interface/main-handler/screening/handler.go index 28ca7027..29ea5c73 100644 --- a/internal/interface/main-handler/screening/handler.go +++ b/internal/interface/main-handler/screening/handler.go @@ -4,7 +4,7 @@ import ( "net/http" rw "github.com/karincake/risoles" - sf "github.com/karincake/semprit" + // sf "github.com/karincake/semprit" // ua "github.com/karincake/tumpeng/auth/svc" @@ -34,47 +34,47 @@ func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { rw.DataResponse(w, res, err) } -func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { - dto := e.ReadListDto{} - sf.UrlQueryParam(&dto, *r.URL) - res, err := u.ReadList(dto) - rw.DataResponse(w, res, err) -} +// func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { +// dto := e.ReadListDto{} +// sf.UrlQueryParam(&dto, *r.URL) +// res, err := u.ReadList(dto) +// rw.DataResponse(w, res, err) +// } -func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { - return - } - dto := e.ReadDetailDto{} - dto.Id = uint16(id) - res, err := u.ReadDetail(dto) - rw.DataResponse(w, res, err) -} +// func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { +// id := rw.ValidateInt(w, "id", r.PathValue("id")) +// if id <= 0 { +// return +// } +// dto := e.ReadDetailDto{} +// dto.Id = uint16(id) +// res, err := u.ReadDetail(dto) +// rw.DataResponse(w, res, err) +// } -func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { - id := rw.ValidateInt(w, "id", r.PathValue("id")) - if id <= 0 { - return - } +// func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { +// id := rw.ValidateInt(w, "id", r.PathValue("id")) +// if id <= 0 { +// return +// } - dto := e.UpdateDto{} - if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { - return - } - dto.Id = uint16(id) - res, err := u.Update(dto) - rw.DataResponse(w, res, err) -} +// dto := e.UpdateDto{} +// if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { +// return +// } +// dto.Id = uint16(id) +// 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 - } +// 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 = uint16(id) - res, err := u.Delete(dto) - rw.DataResponse(w, res, err) -} +// dto := e.DeleteDto{} +// dto.Id = uint16(id) +// res, err := u.Delete(dto) +// rw.DataResponse(w, res, err) +// } diff --git a/internal/lib/auth/tycovar.go b/internal/lib/auth/tycovar.go index 117d0c73..c673eb04 100644 --- a/internal/lib/auth/tycovar.go +++ b/internal/lib/auth/tycovar.go @@ -65,6 +65,13 @@ func (a AuthInfo) IsPharmacist() bool { return *a.Employee_Position_Code == string(ero.EPCPha) } +func (a AuthInfo) IsScreener() bool { // MPP, petugas skrining + if a.Employee_Position_Code == nil { + return false + } + return *a.Employee_Position_Code == string(ero.EPCScr) +} + // func (a AuthInfo) IsPayment() bool { // if a.Employee_Position_Code == nil { // return false diff --git a/internal/use-case/main-use-case/screening/case.go b/internal/use-case/main-use-case/screening/case.go index 84ae4727..f6673450 100644 --- a/internal/use-case/main-use-case/screening/case.go +++ b/internal/use-case/main-use-case/screening/case.go @@ -38,7 +38,11 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } - if !input.AuthInfo.IsDoctor() && !input.AuthInfo.IsNurse() { + if !pu.Contains([]erc.ScreeningFormTypeCode{erc.SFTCB, erc.SFTCA}, input.Type) { + return errors.New("invalid screening form type") + } + + if !input.AuthInfo.IsScreener() { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "auth-forbidden", @@ -55,12 +59,21 @@ func Create(input e.CreateDto) (*d.Data, error) { input.Employee_Id = nil } - if input.Type == erc.SFTCB { + switch input.Type { + case erc.SFTCA: s, _, err := ReadListData(e.ReadListDto{FilterDto: e.FilterDto{Type: erc.SFTCA}}, &event, tx) if err != nil { return err } - if len(s) != 0 { + if len(s) > 0 { + return errors.New("screening form type A is already created for this encounter") + } + case erc.SFTCB: + s, _, err := ReadListData(e.ReadListDto{FilterDto: e.FilterDto{Type: erc.SFTCA}}, &event, tx) + if err != nil { + return err + } + if len(s) < 1 { return errors.New("screening form type A is not created yet, please create it first") } } diff --git a/internal/use-case/main-use-case/screening/helper.go b/internal/use-case/main-use-case/screening/helper.go index 5174d753..94692281 100644 --- a/internal/use-case/main-use-case/screening/helper.go +++ b/internal/use-case/main-use-case/screening/helper.go @@ -6,12 +6,14 @@ package screening import ( e "simrs-vx/internal/domain/main-entities/screening" + erc "simrs-vx/internal/domain/references/common" ) func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Screening) { var inputSrc *e.CreateDto if inputT, ok := any(input).(*e.CreateDto); ok { inputSrc = inputT + data.Status = erc.DVCValidated } else { inputTemp := any(input).(*e.UpdateDto) inputSrc = &inputTemp.CreateDto From 050ba953e1df7fcedc3f1b352b5a3c3f31d579d7 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 2 Dec 2025 13:42:55 +0700 Subject: [PATCH 298/329] update size type soapi --- cmd/main-migration/migrations/20251202064000.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 5 +++-- internal/domain/main-entities/soapi/entity.go | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 cmd/main-migration/migrations/20251202064000.sql diff --git a/cmd/main-migration/migrations/20251202064000.sql b/cmd/main-migration/migrations/20251202064000.sql new file mode 100644 index 00000000..7fed5f08 --- /dev/null +++ b/cmd/main-migration/migrations/20251202064000.sql @@ -0,0 +1,2 @@ +-- Modify "Soapi" table +ALTER TABLE "public"."Soapi" ALTER COLUMN "TypeCode" TYPE character varying(15); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 871cc312..8db69226 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:Ha8JZHXBp6W+fzzWOIT8TuDGwBAPu7d/JQa4hxKMCRw= +h1:uY633gN3JQVVq1z4wKVtoTt3D/bOrBmBqSgjzNxIY7U= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -138,4 +138,5 @@ h1:Ha8JZHXBp6W+fzzWOIT8TuDGwBAPu7d/JQa4hxKMCRw= 20251201114751.sql h1:HM17diiPknfSHAmP+kJGP6GzToaPU9/NT+KQBpf3Jq0= 20251201114913.sql h1:gqucFgHFFLA6n/Rdz486cZH5xkaJuwefESLJMJLDue8= 20251202030445.sql h1:QWBVfTepT7DaXP5E0BYoxNM0JwKIQ2qIMXzI4kbz/qE= -20251202044430.sql h1:OC5NTh0Jf8NNLVTRIvNImPiaMqJfDWkksxWcKq3UjDE= +20251202044430.sql h1:4QZH9lz0GrQ9rzP1AJ+hJgGalNpp+8FCRckNK7xaTbU= +20251202064000.sql h1:CcrTalr9bg48srSwCzcswS/erCTD93y72+cINyrHp2o= diff --git a/internal/domain/main-entities/soapi/entity.go b/internal/domain/main-entities/soapi/entity.go index 7e457ca9..d67f692a 100644 --- a/internal/domain/main-entities/soapi/entity.go +++ b/internal/domain/main-entities/soapi/entity.go @@ -17,6 +17,6 @@ type Soapi struct { Employee_Id *uint `json:"employee_id"` Employee *eem.Employee `json:"employee,omitempty" gorm:"foreignKey:Employee_Id;references:Id"` Time *time.Time `json:"time"` - TypeCode erc.SoapiTypeCode `json:"type_code" gorm:"size:11"` + TypeCode erc.SoapiTypeCode `json:"type_code" gorm:"size:15"` Value *string `json:"value"` } From 3797ac1d67ea7268481ebc6aa81c38cb2f7a642a Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 2 Dec 2025 13:43:36 +0700 Subject: [PATCH 299/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 118 ++++++++++++------------ 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 8f71fcc5..b4a7e6f2 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:NUsCmkoiBso9yZsv4HWrn3+woqMcFRFtgXKln5rY4pQ= +h1:y6ZxOFgue76FuQnVVJeCnHfBjvQkiDP2SCEd0qQkRE8= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,61 +75,61 @@ h1:NUsCmkoiBso9yZsv4HWrn3+woqMcFRFtgXKln5rY4pQ= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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= +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= From 2ebe23f943f50cfb5a4d7573729edf82918bce67 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Tue, 2 Dec 2025 11:46:02 +0700 Subject: [PATCH 300/329] feat/order-things: adjust mcu-order to pricing --- cmd/main-migration/migrations/20251202044430.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 8 +++++--- internal/domain/main-entities/item/dto.go | 4 ++++ internal/domain/main-entities/item/entity.go | 2 ++ .../use-case/main-use-case/mcu-order-item/case.go | 11 +++++------ 5 files changed, 18 insertions(+), 9 deletions(-) create mode 100644 cmd/main-migration/migrations/20251202044430.sql diff --git a/cmd/main-migration/migrations/20251202044430.sql b/cmd/main-migration/migrations/20251202044430.sql new file mode 100644 index 00000000..308b72a7 --- /dev/null +++ b/cmd/main-migration/migrations/20251202044430.sql @@ -0,0 +1,2 @@ +-- Modify "Item" table +ALTER TABLE "public"."Item" ADD COLUMN "BuyingPrice" numeric NULL, ADD COLUMN "SellingPrice" numeric NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 51161909..871cc312 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:bYhAmgY4p8jgE8JpZ6YeJyS1iYCH2LEvDXW2PE+iZpc= +h1:Ha8JZHXBp6W+fzzWOIT8TuDGwBAPu7d/JQa4hxKMCRw= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -135,5 +135,7 @@ h1:bYhAmgY4p8jgE8JpZ6YeJyS1iYCH2LEvDXW2PE+iZpc= 20251201104439.sql h1:tpqdrOf9d2aGwZshqm62nG6SXnfVaO/g6A7z0efPS14= 20251201113804.sql h1:kIEmVoETJXBkab2Q+b3y/pP84eF8W2BdQ47amHCnc+c= 20251201113858.sql h1:KLXKZO5XTQPoEU0YLHE8Fhg9WPKpSN3wNgYPJ+RGFcg= -20251201114751.sql h1:QMcFLz4vr6lwQ03k0Wthhosce743DW9A3w6WJzfqjoU= -20251201114913.sql h1:GvRLyn62Z5CIckonFhtHOZKbJK43yyoCXUfFiADLiAo= +20251201114751.sql h1:HM17diiPknfSHAmP+kJGP6GzToaPU9/NT+KQBpf3Jq0= +20251201114913.sql h1:gqucFgHFFLA6n/Rdz486cZH5xkaJuwefESLJMJLDue8= +20251202030445.sql h1:QWBVfTepT7DaXP5E0BYoxNM0JwKIQ2qIMXzI4kbz/qE= +20251202044430.sql h1:OC5NTh0Jf8NNLVTRIvNImPiaMqJfDWkksxWcKq3UjDE= diff --git a/internal/domain/main-entities/item/dto.go b/internal/domain/main-entities/item/dto.go index f20ce217..686a5c17 100644 --- a/internal/domain/main-entities/item/dto.go +++ b/internal/domain/main-entities/item/dto.go @@ -62,6 +62,8 @@ type ResponseDto struct { Uom *eu.Uom `json:"uom,omitempty"` Infra_Code *string `json:"infra_code"` Stock *int `json:"stock"` + BuyingPrice *float64 `json:"buyingPrice"` + SellingPrice *float64 `json:"sellingPrice"` } func (d Item) ToResponse() ResponseDto { @@ -73,6 +75,8 @@ func (d Item) ToResponse() ResponseDto { Uom: d.Uom, Infra_Code: d.Infra_Code, Stock: d.Stock, + BuyingPrice: d.BuyingPrice, + SellingPrice: d.SellingPrice, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/item/entity.go b/internal/domain/main-entities/item/entity.go index fc721713..55ca2d18 100644 --- a/internal/domain/main-entities/item/entity.go +++ b/internal/domain/main-entities/item/entity.go @@ -16,4 +16,6 @@ type Item struct { Uom *eu.Uom `json:"uom,omitempty" gorm:"foreignKey:Uom_Code;references:Code"` Infra_Code *string `json:"infra_code" gorm:"size:10"` Stock *int `json:"stock"` + BuyingPrice *float64 `json:"buyingPrice"` + SellingPrice *float64 `json:"settlingPrice"` } diff --git a/internal/use-case/main-use-case/mcu-order-item/case.go b/internal/use-case/main-use-case/mcu-order-item/case.go index 9037b771..e04feded 100644 --- a/internal/use-case/main-use-case/mcu-order-item/case.go +++ b/internal/use-case/main-use-case/mcu-order-item/case.go @@ -4,11 +4,7 @@ import ( "errors" "strconv" - e "simrs-vx/internal/domain/main-entities/mcu-order-item" - - umo "simrs-vx/internal/use-case/main-use-case/mcu-order" - - erc "simrs-vx/internal/domain/references/common" + "gorm.io/gorm" dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -16,7 +12,10 @@ import ( pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" - "gorm.io/gorm" + e "simrs-vx/internal/domain/main-entities/mcu-order-item" + erc "simrs-vx/internal/domain/references/common" + + umo "simrs-vx/internal/use-case/main-use-case/mcu-order" ) const source = "mcu-order-item" From a4155e4ef1c3a86e3b32866083fda43cb5ea880d Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 2 Dec 2025 14:10:40 +0700 Subject: [PATCH 301/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 132 ++++++++++++------------ 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 8db69226..f7e6e583 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:uY633gN3JQVVq1z4wKVtoTt3D/bOrBmBqSgjzNxIY7U= +h1:gwV43DB5Cr+YkOe2Y2ywd4ySwyrsK4y1yZ9nfSrSf7Q= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,68 +75,68 @@ h1:uY633gN3JQVVq1z4wKVtoTt3D/bOrBmBqSgjzNxIY7U= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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:CcrTalr9bg48srSwCzcswS/erCTD93y72+cINyrHp2o= +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= From fd7609b080ee2e687f3da9145898627b546d06c6 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 2 Dec 2025 14:14:05 +0700 Subject: [PATCH 302/329] add amb-resume into soapitypecode --- internal/domain/references/clinical/clinical.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/domain/references/clinical/clinical.go b/internal/domain/references/clinical/clinical.go index 43305a99..91642b1e 100644 --- a/internal/domain/references/clinical/clinical.go +++ b/internal/domain/references/clinical/clinical.go @@ -133,6 +133,7 @@ const ( STCDevRecord SoapiTypeCode = "dev-record" // Catatan Perkembangan STCKfrAdm SoapiTypeCode = "kfr-adm" // soapi untuk kfr STCKfrSeries SoapiTypeCode = "kfr-series" // soapi untuk kfr + STCAmbResume SoapiTypeCode = "amb-resume" // Rajal resume MATCChemo MedicalActionTypeCode = "chemo" MATCHemo MedicalActionTypeCode = "hemo" From ce8f3c35a097b22eaebd9eb21c524c429cf7fce5 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 2 Dec 2025 14:17:52 +0700 Subject: [PATCH 303/329] migration from server --- cmd/main-migration/migrations/atlas.sum | 132 ++++++++++++------------ 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 8db69226..f7e6e583 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:uY633gN3JQVVq1z4wKVtoTt3D/bOrBmBqSgjzNxIY7U= +h1:gwV43DB5Cr+YkOe2Y2ywd4ySwyrsK4y1yZ9nfSrSf7Q= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,68 +75,68 @@ h1:uY633gN3JQVVq1z4wKVtoTt3D/bOrBmBqSgjzNxIY7U= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -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:CcrTalr9bg48srSwCzcswS/erCTD93y72+cINyrHp2o= +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= From 821c99833eb78c3cc687a486553f33cd905172f4 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Tue, 2 Dec 2025 16:12:13 +0700 Subject: [PATCH 304/329] fix template screening form a --- assets/docs/screening-form-a.html | 110 ++++++++++++------ .../domain/main-entities/screening/dto.go | 89 +++++++++++++- .../main-use-case/generate-file/helper.go | 40 +++++++ .../main-use-case/generate-file/tycovar.go | 15 +++ 4 files changed, 214 insertions(+), 40 deletions(-) diff --git a/assets/docs/screening-form-a.html b/assets/docs/screening-form-a.html index 768eb183..a838c111 100644 --- a/assets/docs/screening-form-a.html +++ b/assets/docs/screening-form-a.html @@ -32,34 +32,43 @@ - + +
          + Tanggal Terbit : {{ .IssuedDate }} +
          + + +
          - - - + + + - - - + + + - - - - - - - - + + +
          - Tanggal Terbit - : {{ .Repalcable }}No. RM:{{ .MedicalRecord }}
          - No. RM - : {{ .Repalcable }}Nama:{{ .Name }}
          - Nama - : {{ .Repalcable }}
          - Tanggal Lahir - : {{ .Repalcable }}Tanggal Lahir:{{ .BirthDate }}
          @@ -69,58 +78,85 @@ font-weight: bold; font-size: 1rem; margin: 0; - "> + "> FORM A

          Kajian Awal Medis:

          + + {{ if gt (len .EarlyMedic) 0 }} + {{ range .EarlyMedic }} + {{ end }} + {{ else }} - + -
          - ☑ Kasus Dengan Penyakit Kronis, Katastropik (memerlukan Pembiayaan Tinggi), Terminal + ☑ {{ . }}
          - ▢ Status Fungsional Rendah, Kebutuhan Bantuan ADL(Activity Daily Living) Yang Tinggi -
          + {{ end }} + +

          ASSESMEN:

          - + + +
          + {{ .Assessment }} +

          IDENTIFIKASI MASALAH:

          - -
          + {{ if gt (len .ProblemIdentification) 0 }} + {{ range .ProblemIdentification }} + + + ☑ {{ . }} + + + {{ end }} + {{ else }} + + + + {{ end }} + +

          PERENCANAAN:

          - + + +
          + {{ .Planning }} +
          - + -
          - 2025-10-08 16:06:22 + + {{ .Date }}
          - GATOT SUBROTO,AMd.Kep + + ({{ .Employee_Name }})
          diff --git a/internal/domain/main-entities/screening/dto.go b/internal/domain/main-entities/screening/dto.go index cdcc96dc..b001af39 100644 --- a/internal/domain/main-entities/screening/dto.go +++ b/internal/domain/main-entities/screening/dto.go @@ -85,7 +85,7 @@ func ToResponseList(data []Screening) []ResponseDto { return resp } -type FormA struct { +type ScreeningEntry struct { AgeAtRisk bool `json:"ageAtRisk"` // Usia Dengan Risiko LowCognitiveFunction bool `json:"lowCognitiveFunction"` // Pasien Dengan Fungsi Kognitif Rendah HighRiskPatient bool `json:"highRiskPatient"` // Pasien Dengan Risiko Tinggi @@ -114,9 +114,92 @@ type ProblemIdentification struct { DischargeCriteriaNotMetOrDelayed bool `json:"dischargeCriteriaNotMetOrDelayed"` // Pemulangan/ Rujukan Belum Memenuhi Kriteria/ Ditunda } -type AssessmentForm struct { - Screening Screening `json:"screening"` +type FormA struct { + Screening ScreeningEntry `json:"screening"` AssessmentDetail string `json:"assessmentDetail"` // Masukkan detail assesmen ProblemIdentification ProblemIdentification `json:"problemIdentification"` PlanningDetail string `json:"planningDetail"` // Masukkan detail perencanaan } + +func (s ScreeningEntry) SelectedScreeningLabels() []string { + result := []string{} + + if s.AgeAtRisk { + result = append(result, "Usia Dengan Risiko") + } + if s.LowCognitiveFunction { + result = append(result, "Pasien Dengan Fungsi Kognitif Rendah") + } + if s.HighRiskPatient { + result = append(result, "Pasien Dengan Risiko Tinggi") + } + if s.HighComplaintPotential { + result = append(result, "Potensi Komplain Tinggi (Medik dan Non Medik)") + } + if s.ChronicOrCatastrophicOrTerminal { + result = append(result, "Kasus Dengan Penyakit Kronis, Katastropik, Terminal") + } + if s.LowFunctionalStatus { + result = append(result, "Status Fungsional Rendah, Kebutuhan Bantuan ADL Tinggi") + } + if s.HistoryOfMedicalDeviceUse { + result = append(result, "Pasien Dengan Riwayat Penggunaan Peralatan Medis Masa Lalu") + } + if s.MentalOrSocialIssues { + result = append(result, "Riwayat Gangguan Mental, Bunuh Diri, Krisis Keluarga, Isu Sosial") + } + if s.FrequentERVisitsOrReadmission { + result = append(result, "Sering Masuk IGD, Readmisi RS") + } + if s.HighCareCostEstimate { + result = append(result, "Perkiraan Asuhan Dengan Biaya Tinggi") + } + if s.ComplexFinancingSystem { + result = append(result, "Kemungkinan Sistem Pembiayaan Yang Kompleks") + } + if s.AboveAverageLengthOfStay { + result = append(result, "Kasus Yang Melebihi Rata-Rata Lama Dirawat") + } + if s.ImportantOrHighRiskDischargePlanning { + result = append(result, "Rencana Pemulangan Penting / Kontinuitas Pelayanan") + } + if s.Stagnation { + result = append(result, "Stagnasi") + } + + return result +} + +func (p ProblemIdentification) SelectedProblemLabels() []string { + result := []string{} + + if p.CareNotFollowingGuidelines { + result = append(result, "Tingkat Asuhan Tidak Sesuai Panduan/ Norma") + } + if p.OverUtilization { + result = append(result, "Over Utilization Pelayanan") + } + if p.UnderUtilization { + result = append(result, "Under Utilization Pelayanan") + } + if p.PatientNonCompliance { + result = append(result, "Ketidakpatuhan Pasien") + } + if p.InadequateEducation { + result = append(result, "Edukasi Kurang Memadai") + } + if p.LackOfFamilySupport { + result = append(result, "Kurang Dukungan Keluarga") + } + if p.DecreasedDetermination { + result = append(result, "Penurunan Determinasi Ketika Komplikasi Meningkat") + } + if p.FinancialDifficultyDuringComplications { + result = append(result, "Kendala Keuangan Ketika Komplikasi Meningkat") + } + if p.DischargeCriteriaNotMetOrDelayed { + result = append(result, "Pemulangan/ Rujukan Belum Memenuhi Kriteria/ Ditunda") + } + + return result +} diff --git a/internal/use-case/main-use-case/generate-file/helper.go b/internal/use-case/main-use-case/generate-file/helper.go index 6edd34d8..76e4f5ee 100644 --- a/internal/use-case/main-use-case/generate-file/helper.go +++ b/internal/use-case/main-use-case/generate-file/helper.go @@ -13,6 +13,7 @@ import ( ee "simrs-vx/internal/domain/main-entities/encounter" egc "simrs-vx/internal/domain/main-entities/general-consent" er "simrs-vx/internal/domain/main-entities/resume" + es "simrs-vx/internal/domain/main-entities/screening" uvs "simrs-vx/internal/use-case/bpjs-use-case/vclaim-sep" uvscl "simrs-vx/internal/use-case/bpjs-use-case/vclaim-sep-control-letter" @@ -339,3 +340,42 @@ func generateResumeTemplateData(resume er.Resume, event pl.Event, tx *gorm.DB) ( return &templateData, nil } + +func generateScreeningFormATemplateData(screening es.Screening, event pl.Event, tx *gorm.DB) (*ScreeningPDF, error) { + // get encounter + includes := "Patient,Patient.Person" + encounter, err := ue.ReadDetailData(ee.ReadDetailDto{Id: *screening.Encounter_Id, Includes: includes}, &event) + if err != nil { + return nil, err + } + + // map template data + sData := es.FormA{} + if screening.Value != nil { + err := json.Unmarshal([]byte(*screening.Value), &sData) + if err != nil { + event.ErrInfo = pl.ErrorInfo{ + Code: "data-unmarshal-fail", + Detail: err.Error(), + Raw: err, + } + return nil, err + } + } else { + return nil, errors.New("there is no data to be used") + } + + templateData := ScreeningPDF{} + templateData.IssuedDate = pu.GetTimeNow().Format("2006-01-02 15:04:05") + templateData.MedicalRecord = *encounter.Patient.Number + templateData.Name = encounter.Patient.Person.FullName() + templateData.BirthDate = encounter.Patient.Person.BirthDate.Format("2006-01-02 15:04:05") + templateData.Employee_Name = screening.Employee.Person.FullName() + templateData.EarlyMedic = sData.Screening.SelectedScreeningLabels() + templateData.Assessment = sData.AssessmentDetail + templateData.ProblemIdentification = sData.ProblemIdentification.SelectedProblemLabels() + templateData.Planning = sData.PlanningDetail + templateData.Date = screening.CreatedAt.Format("2006-01-02 15:04:05") + + return &templateData, nil +} diff --git a/internal/use-case/main-use-case/generate-file/tycovar.go b/internal/use-case/main-use-case/generate-file/tycovar.go index a242f476..d5a7220e 100644 --- a/internal/use-case/main-use-case/generate-file/tycovar.go +++ b/internal/use-case/main-use-case/generate-file/tycovar.go @@ -72,6 +72,19 @@ type ResumePDF struct { Date string } +type ScreeningPDF struct { + IssuedDate string + Date string + MedicalRecord string + Name string + BirthDate string + Employee_Name string + EarlyMedic []string + Assessment string + ProblemIdentification []string + Planning string +} + type GenerateDto struct { EntityType_Code ere.EntityTypeCode `json:"entityType_code" validate:"required"` Ref_Id *string `json:"ref_id" validate:"required"` @@ -124,6 +137,8 @@ const ( TDNGC TemplateDocsName = "general-consent.html" TDNCL TemplateDocsName = "control-letter.html" TDNR TemplateDocsName = "resume.html" + TDNSA TemplateDocsName = "screening-form-a.html" + TDNSB TemplateDocsName = "screening-form-b.html" ) func (v VclaimControlLetter) generateTemplateData() ControlLetterPDF { From 9698210fb2e2bbc4df73c21c55a651d66bd511c2 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Tue, 2 Dec 2025 20:16:42 +0700 Subject: [PATCH 305/329] feat/order-things: adjust entities --- .../migrations/20251202130629.sql | 101 ++++++++++++++++++ cmd/main-migration/migrations/atlas.sum | 4 +- .../device-package-item/device-package/dto.go | 63 +++++++++++ .../device-package/entity.go | 11 ++ .../main-entities/device-package-item/dto.go | 69 ++++++++++++ .../device-package-item/entity.go | 15 +++ .../main-entities/device-package/dto.go | 63 +++++++++++ .../main-entities/device-package/entity.go | 11 ++ internal/domain/main-entities/infra/dto.go | 29 ++--- internal/domain/main-entities/infra/entity.go | 22 ++-- .../main-entities/installation/entity.go | 2 +- .../material-package-item/dto.go | 69 ++++++++++++ .../material-package-item/entity.go | 15 +++ .../main-entities/material-package/dto.go | 63 +++++++++++ .../main-entities/material-package/entity.go | 11 ++ .../main-entities/procedure-room-order/dto.go | 70 ++++++++++++ .../procedure-room-order/entity.go | 13 +++ .../procedure-room/base/entity.go | 21 ++++ .../{room => procedure-room}/dto.go | 10 +- .../main-entities/procedure-room/entity.go | 17 +++ .../domain/main-entities/room/base/entity.go | 23 ---- internal/domain/main-entities/room/entity.go | 11 -- .../domain/main-entities/specialist/entity.go | 4 +- .../subspecialist/base/entity.go | 4 +- internal/domain/main-entities/unit/entity.go | 4 +- .../references/organization/organization.go | 20 ++-- internal/interface/migration/main-entities.go | 16 ++- 27 files changed, 680 insertions(+), 81 deletions(-) create mode 100644 cmd/main-migration/migrations/20251202130629.sql create mode 100644 internal/domain/main-entities/device-package-item/device-package/dto.go create mode 100644 internal/domain/main-entities/device-package-item/device-package/entity.go create mode 100644 internal/domain/main-entities/device-package-item/dto.go create mode 100644 internal/domain/main-entities/device-package-item/entity.go create mode 100644 internal/domain/main-entities/device-package/dto.go create mode 100644 internal/domain/main-entities/device-package/entity.go create mode 100644 internal/domain/main-entities/material-package-item/dto.go create mode 100644 internal/domain/main-entities/material-package-item/entity.go create mode 100644 internal/domain/main-entities/material-package/dto.go create mode 100644 internal/domain/main-entities/material-package/entity.go create mode 100644 internal/domain/main-entities/procedure-room-order/dto.go create mode 100644 internal/domain/main-entities/procedure-room-order/entity.go create mode 100644 internal/domain/main-entities/procedure-room/base/entity.go rename internal/domain/main-entities/{room => procedure-room}/dto.go (86%) create mode 100644 internal/domain/main-entities/procedure-room/entity.go delete mode 100644 internal/domain/main-entities/room/base/entity.go delete mode 100644 internal/domain/main-entities/room/entity.go diff --git a/cmd/main-migration/migrations/20251202130629.sql b/cmd/main-migration/migrations/20251202130629.sql new file mode 100644 index 00000000..88b685fe --- /dev/null +++ b/cmd/main-migration/migrations/20251202130629.sql @@ -0,0 +1,101 @@ +-- Modify "Consultation" table +ALTER TABLE "public"."Consultation" ALTER COLUMN "DstUnit_Code" TYPE character varying(20); +-- Modify "ControlLetter" table +ALTER TABLE "public"."ControlLetter" ALTER COLUMN "Unit_Code" TYPE character varying(20), ALTER COLUMN "Specialist_Code" TYPE character varying(20), ALTER COLUMN "Subspecialist_Code" TYPE character varying(20); +-- Modify "Encounter" table +ALTER TABLE "public"."Encounter" ALTER COLUMN "Specialist_Code" TYPE character varying(20), ALTER COLUMN "Subspecialist_Code" TYPE character varying(20), ALTER COLUMN "Unit_Code" TYPE character varying(20); +-- Modify "Chemo" table +ALTER TABLE "public"."Chemo" ALTER COLUMN "SrcUnit_Code" TYPE character varying(20); +-- Modify "Installation" table +ALTER TABLE "public"."Installation" ALTER COLUMN "Code" TYPE character varying(20); +-- Modify "InternalReference" table +ALTER TABLE "public"."InternalReference" ALTER COLUMN "Unit_Code" TYPE character varying(20); +-- Modify "PracticeSchedule" table +ALTER TABLE "public"."PracticeSchedule" ALTER COLUMN "Unit_Code" TYPE character varying(20); +-- Create "DevicePackage" table +CREATE TABLE "public"."DevicePackage" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(20) NOT NULL, + "Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_DevicePackage_Code" UNIQUE ("Code") +); +-- Create "DevicePackageItem" table +CREATE TABLE "public"."DevicePackageItem" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "DevicePackage_Code" character varying(20) NOT NULL, + "Device_Code" character varying(20) NOT NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_DevicePackageItem_Device" FOREIGN KEY ("Device_Code") REFERENCES "public"."Device" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_DevicePackageItem_DevicePackage" FOREIGN KEY ("DevicePackage_Code") REFERENCES "public"."DevicePackage" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "MaterialPackage" table +CREATE TABLE "public"."MaterialPackage" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(20) NOT NULL, + "Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_MaterialPackage_Code" UNIQUE ("Code") +); +-- Create "MaterialPackageItem" table +CREATE TABLE "public"."MaterialPackageItem" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "MaterialPackage_Code" character varying(20) NOT NULL, + "Material_Code" character varying(20) NOT NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_MaterialPackageItem_Material" FOREIGN KEY ("Material_Code") REFERENCES "public"."Material" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_MaterialPackageItem_MaterialPackage" FOREIGN KEY ("MaterialPackage_Code") REFERENCES "public"."MaterialPackage" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Modify "Infra" table +ALTER TABLE "public"."Infra" ALTER COLUMN "Code" TYPE character varying(20), ALTER COLUMN "InfraGroup_Code" TYPE character varying(20), ALTER COLUMN "Parent_Code" TYPE character varying(20); +-- Modify "Specialist" table +ALTER TABLE "public"."Specialist" ALTER COLUMN "Code" TYPE character varying(20), ALTER COLUMN "Unit_Code" TYPE character varying(20); +-- Modify "Subspecialist" table +ALTER TABLE "public"."Subspecialist" ALTER COLUMN "Code" TYPE character varying(20), ALTER COLUMN "Specialist_Code" TYPE character varying(20); +-- Modify "Unit" table +ALTER TABLE "public"."Unit" ALTER COLUMN "Code" TYPE character varying(20), ALTER COLUMN "Installation_Code" TYPE character varying(20); +-- Create "ProcedureRoom" table +CREATE TABLE "public"."ProcedureRoom" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(20) NULL, + "Infra_Code" character varying(20) NULL, + "Type_Code" character varying(10) NULL, + "Unit_Code" character varying(20) NULL, + "Specialist_Code" character varying(20) NULL, + "Subspecialist_Code" character varying(20) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_ProcedureRoom_Code" UNIQUE ("Code"), + CONSTRAINT "uni_ProcedureRoom_Infra_Code" UNIQUE ("Infra_Code"), + CONSTRAINT "fk_ProcedureRoom_Infra" FOREIGN KEY ("Infra_Code") REFERENCES "public"."Infra" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_ProcedureRoom_Specialist" FOREIGN KEY ("Specialist_Code") REFERENCES "public"."Specialist" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_ProcedureRoom_Subspecialist" FOREIGN KEY ("Subspecialist_Code") REFERENCES "public"."Subspecialist" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_ProcedureRoom_Unit" FOREIGN KEY ("Unit_Code") REFERENCES "public"."Unit" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "ProcedureRoomOrder" table +CREATE TABLE "public"."ProcedureRoomOrder" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Infra_Code" character varying(20) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_ProcedureRoomOrder_ProcedureRoom" FOREIGN KEY ("Infra_Code") REFERENCES "public"."ProcedureRoom" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Drop "Room" table +DROP TABLE "public"."Room"; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 11fba5b8..54858b7b 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:NjMnBBzNKOW7RxpS7I5LqVv+o/CxGkxhHt/B7CV4/tQ= +h1:cyae1SX3YSMX1LZLEsCFxcRKbVxpnp46BqFxWXJqKjs= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -140,4 +140,4 @@ h1:NjMnBBzNKOW7RxpS7I5LqVv+o/CxGkxhHt/B7CV4/tQ= 20251202030445.sql h1:QWBVfTepT7DaXP5E0BYoxNM0JwKIQ2qIMXzI4kbz/qE= 20251202044430.sql h1:4QZH9lz0GrQ9rzP1AJ+hJgGalNpp+8FCRckNK7xaTbU= 20251202064000.sql h1:/EN7sT1ol/91qW1aXWrzX+Mc3XOC/7f/LtfA0JRHpbg= -20251202122413.sql h1:uZpx6oC8BLTECZdMN69u+WTAAzdSWF70RGVB/pIxC84= +20251202130629.sql h1:LjBgQS8tKEwpC3WA0wGeO2Fs2L20kEOB6e5ljO4EdLM= diff --git a/internal/domain/main-entities/device-package-item/device-package/dto.go b/internal/domain/main-entities/device-package-item/device-package/dto.go new file mode 100644 index 00000000..26aad58a --- /dev/null +++ b/internal/domain/main-entities/device-package-item/device-package/dto.go @@ -0,0 +1,63 @@ +package devicepackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type CreateDto struct { + Code string `json:"code" validate:"maxLength=20"` + Name string `json:"name" validate:"maxLength=50"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Code string `json:"code"` + Name string `json:"name"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` +} + +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.SmallMain + Code string `json:"code"` + Name string `json:"name"` +} + +func (d DevicePackage) ToResponse() ResponseDto { + resp := ResponseDto{ + Code: d.Code, + Name: d.Name, + } + resp.SmallMain = d.SmallMain + return resp +} + +func ToResponseList(data []DevicePackage) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/device-package-item/device-package/entity.go b/internal/domain/main-entities/device-package-item/device-package/entity.go new file mode 100644 index 00000000..1c03b44d --- /dev/null +++ b/internal/domain/main-entities/device-package-item/device-package/entity.go @@ -0,0 +1,11 @@ +package devicepackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type DevicePackage struct { + ecore.SmallMain + Code string `json:"code" gorm:"unique;size:20;not null"` + Name string `json:"name" gorm:"size:50"` +} diff --git a/internal/domain/main-entities/device-package-item/dto.go b/internal/domain/main-entities/device-package-item/dto.go new file mode 100644 index 00000000..a0a224ba --- /dev/null +++ b/internal/domain/main-entities/device-package-item/dto.go @@ -0,0 +1,69 @@ +package devicepackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ed "simrs-vx/internal/domain/main-entities/device" + edp "simrs-vx/internal/domain/main-entities/device-package" +) + +type CreateDto struct { + DevicePackage_Code string `json:"devicePackage_code" validate:"maxLength=20"` + Device_Code string `json:"code" validate:"maxLength=20"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + DevicePackage_Code string `json:"devicePackage-code"` + Device_Code string `json:"code"` +} + +type ReadDetailDto struct { + Id uint `json:"id"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + DevicePackage_Code string `json:"devicePackage_code"` + DevicePackage *edp.DevicePackage `json:"devicePackage,omitempty"` + Device_Code string `json:"code"` + Device *ed.Device `json:"device,omitempty"` +} + +func (d DevicePackageItem) ToResponse() ResponseDto { + resp := ResponseDto{ + DevicePackage_Code: d.DevicePackage_Code, + DevicePackage: d.DevicePackage, + Device_Code: d.Device_Code, + Device: d.Device, + } + resp.Id = d.Id + return resp +} + +func ToResponseList(data []DevicePackageItem) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/device-package-item/entity.go b/internal/domain/main-entities/device-package-item/entity.go new file mode 100644 index 00000000..476e24e2 --- /dev/null +++ b/internal/domain/main-entities/device-package-item/entity.go @@ -0,0 +1,15 @@ +package devicepackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ed "simrs-vx/internal/domain/main-entities/device" + edp "simrs-vx/internal/domain/main-entities/device-package" +) + +type DevicePackageItem struct { + ecore.Main + DevicePackage_Code string `json:"devicePackage_code" gorm:"size:20;not null"` + DevicePackage *edp.DevicePackage `json:"devicePackage" gorm:"foreignKey:DevicePackage_Code;references:Code"` + Device_Code string `json:"code" gorm:"size:20;not null"` + Device *ed.Device `json:"device" gorm:"foreignKey:Device_Code;references:Code"` +} diff --git a/internal/domain/main-entities/device-package/dto.go b/internal/domain/main-entities/device-package/dto.go new file mode 100644 index 00000000..26aad58a --- /dev/null +++ b/internal/domain/main-entities/device-package/dto.go @@ -0,0 +1,63 @@ +package devicepackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type CreateDto struct { + Code string `json:"code" validate:"maxLength=20"` + Name string `json:"name" validate:"maxLength=50"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Code string `json:"code"` + Name string `json:"name"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` +} + +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.SmallMain + Code string `json:"code"` + Name string `json:"name"` +} + +func (d DevicePackage) ToResponse() ResponseDto { + resp := ResponseDto{ + Code: d.Code, + Name: d.Name, + } + resp.SmallMain = d.SmallMain + return resp +} + +func ToResponseList(data []DevicePackage) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/device-package/entity.go b/internal/domain/main-entities/device-package/entity.go new file mode 100644 index 00000000..1c03b44d --- /dev/null +++ b/internal/domain/main-entities/device-package/entity.go @@ -0,0 +1,11 @@ +package devicepackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type DevicePackage struct { + ecore.SmallMain + Code string `json:"code" gorm:"unique;size:20;not null"` + Name string `json:"name" gorm:"size:50"` +} diff --git a/internal/domain/main-entities/infra/dto.go b/internal/domain/main-entities/infra/dto.go index dfe271e5..d12a0b89 100644 --- a/internal/domain/main-entities/infra/dto.go +++ b/internal/domain/main-entities/infra/dto.go @@ -3,7 +3,8 @@ package infra import ( ecore "simrs-vx/internal/domain/base-entities/core" ei "simrs-vx/internal/domain/main-entities/item" - erb "simrs-vx/internal/domain/main-entities/room/base" + + erb "simrs-vx/internal/domain/main-entities/procedure-room/base" ero "simrs-vx/internal/domain/references/organization" ) @@ -61,15 +62,15 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain - Code string `json:"code"` - Name string `json:"name"` - InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code"` - Parent_Code *string `json:"parent_code"` - Parent *Infra `json:"parent,omitempty"` - Childrens []Infra `json:"childrens,omitempty"` - Item_Code *string `json:"item_code"` - Item *ei.Item `json:"item,omitempty"` - Rooms []erb.Basic `json:"rooms,omitempty"` + Code string `json:"code"` + Name string `json:"name"` + InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code"` + Parent_Code *string `json:"parent_code"` + Parent *Infra `json:"parent,omitempty"` + Childrens []Infra `json:"childrens,omitempty"` + Item_Code *string `json:"item_code"` + Item *ei.Item `json:"item,omitempty"` + ProcedureRooms []erb.ProcedureRoom `json:"rooms,omitempty"` } func (d Infra) ToResponse() ResponseDto { @@ -79,10 +80,10 @@ func (d Infra) ToResponse() ResponseDto { InfraGroup_Code: d.InfraGroup_Code, Parent_Code: d.Parent_Code, // Parent: d.Parent, - Childrens: d.Childrens, - Item_Code: d.Item_Code, - Item: d.Item, - Rooms: d.Rooms, + Childrens: d.Childrens, + Item_Code: d.Item_Code, + Item: d.Item, + ProcedureRooms: d.ProcedureRooms, } resp.SmallMain = d.SmallMain return resp diff --git a/internal/domain/main-entities/infra/entity.go b/internal/domain/main-entities/infra/entity.go index 51cc8eaa..8fe5cb52 100644 --- a/internal/domain/main-entities/infra/entity.go +++ b/internal/domain/main-entities/infra/entity.go @@ -4,20 +4,20 @@ import ( ecore "simrs-vx/internal/domain/base-entities/core" ei "simrs-vx/internal/domain/main-entities/item" - erb "simrs-vx/internal/domain/main-entities/room/base" + erb "simrs-vx/internal/domain/main-entities/procedure-room/base" ero "simrs-vx/internal/domain/references/organization" ) type Infra struct { - ecore.SmallMain // adjust this according to the needs - Code string `json:"code" gorm:"uniqueIndex;size:10;not null"` - Name string `json:"name" gorm:"size:50"` - InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code" gorm:"size:15"` - Parent_Code *string `json:"parent_code" gorm:"size:10"` - Parent *Infra `json:"parent" gorm:"foreignKey:Parent_Code;references:Code"` - Childrens []Infra `json:"childrens" gorm:"foreignKey:Parent_Code;references:Code"` - Item_Code *string `json:"item_code" gorm:"size:50"` - Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Code;references:Code"` - Rooms []erb.Basic `json:"rooms" gorm:"foreignKey:Infra_Code;references:Code"` + ecore.SmallMain // adjust this according to the needs + Code string `json:"code" gorm:"uniqueIndex;size:20;not null"` + Name string `json:"name" gorm:"size:50"` + InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code" gorm:"size:20"` + Parent_Code *string `json:"parent_code" gorm:"size:20"` + Parent *Infra `json:"parent" gorm:"foreignKey:Parent_Code;references:Code"` + Childrens []Infra `json:"childrens" gorm:"foreignKey:Parent_Code;references:Code"` + Item_Code *string `json:"item_code" gorm:"size:50"` + Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Code;references:Code"` + ProcedureRooms []erb.ProcedureRoom `json:"rooms" gorm:"foreignKey:Infra_Code;references:Code"` } diff --git a/internal/domain/main-entities/installation/entity.go b/internal/domain/main-entities/installation/entity.go index 5cc82430..6c3c0ecf 100644 --- a/internal/domain/main-entities/installation/entity.go +++ b/internal/domain/main-entities/installation/entity.go @@ -8,7 +8,7 @@ import ( type Installation struct { ecore.SmallMain // adjust this according to the needs - Code string `json:"code" gorm:"unique;size:10"` + Code string `json:"code" gorm:"unique;size:20"` Name string `json:"name" gorm:"size:50"` EncounterClass_Code ere.EncounterClassCode `json:"encounterClass_code" gorm:"size:10"` InstallationPositions []eipb.Basic `json:"installationPositions,omitempty" gorm:"foreignKey:Installation_Code;references:Code"` diff --git a/internal/domain/main-entities/material-package-item/dto.go b/internal/domain/main-entities/material-package-item/dto.go new file mode 100644 index 00000000..a9b11be6 --- /dev/null +++ b/internal/domain/main-entities/material-package-item/dto.go @@ -0,0 +1,69 @@ +package materialpackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + em "simrs-vx/internal/domain/main-entities/material" + emp "simrs-vx/internal/domain/main-entities/material-package" +) + +type CreateDto struct { + MaterialPackage_Code string `json:"materialPackage_code" validate:"maxLength=20"` + Material_Code string `json:"code" validate:"maxLength=20"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + MaterialPackage_Code string `json:"materialPackage-code"` + Material_Code string `json:"code"` +} + +type ReadDetailDto struct { + Id uint `json:"id"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + MaterialPackage_Code string `json:"materialPackage_code"` + MaterialPackage *emp.MaterialPackage `json:"materialPackage,omitempty"` + Material_Code string `json:"code"` + Material *em.Material `json:"material,omitempty"` +} + +func (d MaterialPackageItem) ToResponse() ResponseDto { + resp := ResponseDto{ + MaterialPackage_Code: d.MaterialPackage_Code, + MaterialPackage: d.MaterialPackage, + Material_Code: d.Material_Code, + Material: d.Material, + } + resp.Id = d.Id + return resp +} + +func ToResponseList(data []MaterialPackageItem) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/material-package-item/entity.go b/internal/domain/main-entities/material-package-item/entity.go new file mode 100644 index 00000000..76378dc8 --- /dev/null +++ b/internal/domain/main-entities/material-package-item/entity.go @@ -0,0 +1,15 @@ +package materialpackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + em "simrs-vx/internal/domain/main-entities/material" + emp "simrs-vx/internal/domain/main-entities/material-package" +) + +type MaterialPackageItem struct { + ecore.Main + MaterialPackage_Code string `json:"materialPackage_code" gorm:"size:20;not null"` + MaterialPackage *emp.MaterialPackage `json:"materialPackage" gorm:"foreignKey:MaterialPackage_Code;references:Code"` + Material_Code string `json:"code" gorm:"size:20;not null"` + Material *em.Material `json:"material" gorm:"foreignKey:Material_Code;references:Code"` +} diff --git a/internal/domain/main-entities/material-package/dto.go b/internal/domain/main-entities/material-package/dto.go new file mode 100644 index 00000000..b81212e9 --- /dev/null +++ b/internal/domain/main-entities/material-package/dto.go @@ -0,0 +1,63 @@ +package materialpackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type CreateDto struct { + Code string `json:"code" validate:"maxLength=20"` + Name string `json:"name" validate:"maxLength=50"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Code string `json:"code"` + Name string `json:"name"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` +} + +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.SmallMain + Code string `json:"code"` + Name string `json:"name"` +} + +func (d MaterialPackage) ToResponse() ResponseDto { + resp := ResponseDto{ + Code: d.Code, + Name: d.Name, + } + resp.SmallMain = d.SmallMain + return resp +} + +func ToResponseList(data []MaterialPackage) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/material-package/entity.go b/internal/domain/main-entities/material-package/entity.go new file mode 100644 index 00000000..4f3feeab --- /dev/null +++ b/internal/domain/main-entities/material-package/entity.go @@ -0,0 +1,11 @@ +package materialpackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type MaterialPackage struct { + ecore.SmallMain + Code string `json:"code" gorm:"unique;size:20;not null"` + Name string `json:"name" gorm:"size:50"` +} diff --git a/internal/domain/main-entities/procedure-room-order/dto.go b/internal/domain/main-entities/procedure-room-order/dto.go new file mode 100644 index 00000000..d202f031 --- /dev/null +++ b/internal/domain/main-entities/procedure-room-order/dto.go @@ -0,0 +1,70 @@ +package procedureroomorder + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ec "simrs-vx/internal/domain/main-entities/encounter" + epr "simrs-vx/internal/domain/main-entities/procedure-room" +) + +type CreateDto struct { + Encounter_Id uint64 `json:"encounter_id"` + Infra_Code string `json:"procedure"` + ProcedureRoom string `json:"procedureRoom"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Encounter_Id uint64 `json:"encounter-id"` + Infra_Code string `json:"procedure-code"` + ProcedureRoom string `json:"procedure-room"` +} + +type ReadDetailDto struct { + Id uint `json:"id"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + Encounter_Id uint64 `json:"encounter_id"` + Encounter *ec.Encounter `json:"encounter,omitempty"` + Infra_Code string `json:"procedure"` + ProcedureRoom *epr.ProcedureRoom `json:"procedureRoom,omitempty"` +} + +func (d ProcedureRoomOrder) ToResponse() ResponseDto { + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Infra_Code: d.Infra_Code, + // ProcedureRoom: d.ProcedureRoom, + } + resp.Id = d.Id + return resp +} + +func ToResponseList(data []ProcedureRoomOrder) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/procedure-room-order/entity.go b/internal/domain/main-entities/procedure-room-order/entity.go new file mode 100644 index 00000000..7e453410 --- /dev/null +++ b/internal/domain/main-entities/procedure-room-order/entity.go @@ -0,0 +1,13 @@ +package procedureroomorder + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + epr "simrs-vx/internal/domain/main-entities/procedure-room" +) + +type ProcedureRoomOrder struct { + ecore.Main + Encounter_Id uint64 `json:"encounter_id"` + Infra_Code string `json:"infra_code" gorm:"size:20"` + ProcedureRoom *epr.ProcedureRoom `json:"procedureRoom,omitempty" gorm:"foreignKey:Infra_Code;references:Code"` +} diff --git a/internal/domain/main-entities/procedure-room/base/entity.go b/internal/domain/main-entities/procedure-room/base/entity.go new file mode 100644 index 00000000..981dd4f2 --- /dev/null +++ b/internal/domain/main-entities/procedure-room/base/entity.go @@ -0,0 +1,21 @@ +package procedureroombase + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ero "simrs-vx/internal/domain/references/organization" +) + +type ProcedureRoom struct { + ecore.SmallMain + Code string `json:"code" gorm:"unique;size:20"` // copied from infra code + Infra_Code *string `json:"infra_code" gorm:"size:20;unique"` + Type_Code *ero.ProdcedureRoomTypeCode `json:"type_code" gorm:"size:10"` + Unit_Code *string `json:"unit_code" gorm:"size:20"` + Specialist_Code *string `json:"specialist_code" gorm:"size:20"` + Subspecialist_Code *string `json:"subspecialist_code" gorm:"size:20"` +} + +// THIS IS ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ +// func (ProcedureRoom) TableName() string { +// return "Room" +// } diff --git a/internal/domain/main-entities/room/dto.go b/internal/domain/main-entities/procedure-room/dto.go similarity index 86% rename from internal/domain/main-entities/room/dto.go rename to internal/domain/main-entities/procedure-room/dto.go index 2ff41c3a..74320f3f 100644 --- a/internal/domain/main-entities/room/dto.go +++ b/internal/domain/main-entities/procedure-room/dto.go @@ -1,4 +1,4 @@ -package room +package procedureroom import ( ecore "simrs-vx/internal/domain/base-entities/core" @@ -10,6 +10,7 @@ import ( type CreateDto struct { Infra_Code *string `json:"infra_code"` + Type_Code string `json:"type_code"` Unit_Code *string `json:"unit_code"` Specialist_Code *string `json:"specialist_code"` Subspecialist_Code *string `json:"subspecialist_code"` @@ -23,6 +24,7 @@ type ReadListDto struct { type FilterDto struct { Infra_Code *string `json:"infra-code"` + Type_Code string `json:"type_code"` Unit_Code *string `json:"unit-code"` Specialist_Code *string `json:"specialist-code"` Subspecialist_Code *string `json:"subspecialist-code"` @@ -49,6 +51,7 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain + Type_Code *string `json:"type_code"` Infra_Code *string `json:"infra_code"` Infra *ei.Infra `json:"infra,omitempty"` Unit_Code *string `json:"unit_code"` @@ -59,10 +62,11 @@ type ResponseDto struct { Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty"` } -func (d Room) ToResponse() ResponseDto { +func (d ProcedureRoom) ToResponse() ResponseDto { resp := ResponseDto{ Infra_Code: d.Infra_Code, Infra: d.Infra, + Type_Code: (*string)(d.Type_Code), Unit_Code: d.Unit_Code, Unit: d.Unit, Specialist_Code: d.Specialist_Code, @@ -74,7 +78,7 @@ func (d Room) ToResponse() ResponseDto { return resp } -func ToResponseList(data []Room) []ResponseDto { +func ToResponseList(data []ProcedureRoom) []ResponseDto { resp := make([]ResponseDto, len(data)) for i, u := range data { resp[i] = u.ToResponse() diff --git a/internal/domain/main-entities/procedure-room/entity.go b/internal/domain/main-entities/procedure-room/entity.go new file mode 100644 index 00000000..9be3ac69 --- /dev/null +++ b/internal/domain/main-entities/procedure-room/entity.go @@ -0,0 +1,17 @@ +package procedureroom + +import ( + ei "simrs-vx/internal/domain/main-entities/infra" + ebase "simrs-vx/internal/domain/main-entities/procedure-room/base" + es "simrs-vx/internal/domain/main-entities/specialist" + ess "simrs-vx/internal/domain/main-entities/subspecialist" + eu "simrs-vx/internal/domain/main-entities/unit" +) + +type ProcedureRoom struct { + ebase.ProcedureRoom + Infra *ei.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Code;references:Code"` + Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` + Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Code;references:Code"` + Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Code;references:Code"` +} diff --git a/internal/domain/main-entities/room/base/entity.go b/internal/domain/main-entities/room/base/entity.go deleted file mode 100644 index d5651ac9..00000000 --- a/internal/domain/main-entities/room/base/entity.go +++ /dev/null @@ -1,23 +0,0 @@ -package base - -import ( - ecore "simrs-vx/internal/domain/base-entities/core" - es "simrs-vx/internal/domain/main-entities/specialist" - ess "simrs-vx/internal/domain/main-entities/subspecialist" - eu "simrs-vx/internal/domain/main-entities/unit" -) - -type Basic struct { - ecore.SmallMain // adjust this according to the needs - Infra_Code *string `json:"infra_code" gorm:"size:10"` - Unit_Code *string `json:"unit_code" gorm:"size:10"` - Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` - Specialist_Code *string `json:"specialist_code" gorm:"size:10"` - Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Code;references:Code"` - Subspecialist_Code *string `json:"subspecialist_code" gorm:"size:10"` - Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Code;references:Code"` -} - -func (Basic) TableName() string { - return "Room" -} diff --git a/internal/domain/main-entities/room/entity.go b/internal/domain/main-entities/room/entity.go deleted file mode 100644 index 49fb8cc6..00000000 --- a/internal/domain/main-entities/room/entity.go +++ /dev/null @@ -1,11 +0,0 @@ -package room - -import ( - ei "simrs-vx/internal/domain/main-entities/infra" - ebase "simrs-vx/internal/domain/main-entities/room/base" -) - -type Room struct { - ebase.Basic - Infra *ei.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Code;references:Code"` -} diff --git a/internal/domain/main-entities/specialist/entity.go b/internal/domain/main-entities/specialist/entity.go index 4fef90a5..0b5b7a5d 100644 --- a/internal/domain/main-entities/specialist/entity.go +++ b/internal/domain/main-entities/specialist/entity.go @@ -9,9 +9,9 @@ import ( type Specialist struct { ecore.SmallMain // adjust this according to the needs - Code string `json:"code" gorm:"unique;size:10"` + Code string `json:"code" gorm:"unique;size:20"` Name string `json:"name" gorm:"size:50"` - Unit_Code *string `json:"unit_code" gorm:"size:10"` + Unit_Code *string `json:"unit_code" gorm:"size:20"` Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` SpecialistPositions []eub.Basic `json:"specialistPositions,omitempty" gorm:"foreignKey:Specialist_Code;references:Code"` Subspecialists []essb.Basic `json:"subspecialists,omitempty" gorm:"foreignKey:Specialist_Code;references:Code"` diff --git a/internal/domain/main-entities/subspecialist/base/entity.go b/internal/domain/main-entities/subspecialist/base/entity.go index a94fb76d..9fe77039 100644 --- a/internal/domain/main-entities/subspecialist/base/entity.go +++ b/internal/domain/main-entities/subspecialist/base/entity.go @@ -6,9 +6,9 @@ import ( type Basic struct { ecore.SmallMain // adjust this according to the needs - Code string `json:"code" gorm:"unique;size:10"` + Code string `json:"code" gorm:"unique;size:20"` Name string `json:"name" gorm:"size:50"` - Specialist_Code *string `json:"specialist_code" gorm:"size:10"` + Specialist_Code *string `json:"specialist_code" gorm:"size:20"` } func (Basic) TableName() string { diff --git a/internal/domain/main-entities/unit/entity.go b/internal/domain/main-entities/unit/entity.go index 97db9885..e8110db3 100644 --- a/internal/domain/main-entities/unit/entity.go +++ b/internal/domain/main-entities/unit/entity.go @@ -9,9 +9,9 @@ import ( type Unit struct { ecore.SmallMain // adjust this according to the needs - Installation_Code *string `json:"installation_code" gorm:"size:10"` + Installation_Code *string `json:"installation_code" gorm:"size:20"` Installation *ei.Installation `json:"installation" gorm:"foreignKey:Installation_Code;references:Code"` - Code string `json:"code" gorm:"unique;size:10"` + Code string `json:"code" gorm:"unique;size:20"` Name string `json:"name" gorm:"size:50"` Type_Code *ero.UnitTypeCode `json:"type_code"` UnitPositions []eub.Basic `json:"unitPositions,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` diff --git a/internal/domain/references/organization/organization.go b/internal/domain/references/organization/organization.go index b39752d5..8ca55c93 100644 --- a/internal/domain/references/organization/organization.go +++ b/internal/domain/references/organization/organization.go @@ -1,14 +1,15 @@ package organization type ( - ContractPositionCode string - EmployeePositionCode string - InternPosisitionCode string - ItemGroupCode string - InfraGroupCode string - UnitTypeCode string - DoctorFeeTypeCode string - ActionBillingCode string + ContractPositionCode string + EmployeePositionCode string + InternPosisitionCode string + ItemGroupCode string + InfraGroupCode string + ProdcedureRoomTypeCode string + UnitTypeCode string + DoctorFeeTypeCode string + ActionBillingCode string ) const ( @@ -53,6 +54,9 @@ const ( IFGCCounter InfraGroupCode = "counter" // Counter IFGCPubScreen InfraGroupCode = "public-screen" // Public Screen + PRTLight ProdcedureRoomTypeCode = "light" // Ringan + PRTSurgery ProdcedureRoomTypeCode = "roomed" // Dikamarkan + UTCReg UnitTypeCode = "reg" // Registrasi UTCExa UnitTypeCode = "exa" // Pemeriksaan UTCPay UnitTypeCode = "pay" // Pembayaran diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index bed0c18c..0d118fae 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -19,6 +19,8 @@ import ( device "simrs-vx/internal/domain/main-entities/device" deviceorder "simrs-vx/internal/domain/main-entities/device-order" deviceorderitem "simrs-vx/internal/domain/main-entities/device-order-item" + devicepackage "simrs-vx/internal/domain/main-entities/device-package" + devicepackageitem "simrs-vx/internal/domain/main-entities/device-package-item" diagnosesrc "simrs-vx/internal/domain/main-entities/diagnose-src" district "simrs-vx/internal/domain/main-entities/district" division "simrs-vx/internal/domain/main-entities/division" @@ -46,6 +48,8 @@ import ( material "simrs-vx/internal/domain/main-entities/material" materialorder "simrs-vx/internal/domain/main-entities/material-order" materialorderitem "simrs-vx/internal/domain/main-entities/material-order-item" + materialpackage "simrs-vx/internal/domain/main-entities/material-package" + materialpackageitem "simrs-vx/internal/domain/main-entities/material-package-item" mcuorder "simrs-vx/internal/domain/main-entities/mcu-order" mcuorderitem "simrs-vx/internal/domain/main-entities/mcu-order-item" mcuordersubitem "simrs-vx/internal/domain/main-entities/mcu-order-sub-item" @@ -78,13 +82,14 @@ import ( practiceschedule "simrs-vx/internal/domain/main-entities/practice-schedule" prescription "simrs-vx/internal/domain/main-entities/prescription" prescriptionitem "simrs-vx/internal/domain/main-entities/prescription-item" + procedureroom "simrs-vx/internal/domain/main-entities/procedure-room" + procedureroomorder "simrs-vx/internal/domain/main-entities/procedure-room-order" proceduresrc "simrs-vx/internal/domain/main-entities/procedure-src" province "simrs-vx/internal/domain/main-entities/province" regency "simrs-vx/internal/domain/main-entities/regency" rehab "simrs-vx/internal/domain/main-entities/rehab" responsibledoctorhist "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" resume "simrs-vx/internal/domain/main-entities/resume" - room "simrs-vx/internal/domain/main-entities/room" sbar "simrs-vx/internal/domain/main-entities/sbar" screening "simrs-vx/internal/domain/main-entities/screening" soapi "simrs-vx/internal/domain/main-entities/soapi" @@ -144,6 +149,7 @@ func getMainEntities() []any { &item.Item{}, &itemprice.ItemPrice{}, &infra.Infra{}, + &procedureroom.ProcedureRoom{}, &medicinegroup.MedicineGroup{}, &medicinemethod.MedicineMethod{}, &mcusrccategory.McuSrcCategory{}, @@ -163,13 +169,17 @@ func getMainEntities() []any { &personrelative.PersonRelative{}, &patient.Patient{}, &appointment.Appointment{}, + &devicepackage.DevicePackage{}, + &devicepackageitem.DevicePackageItem{}, + &materialpackage.MaterialPackage{}, + &materialpackageitem.MaterialPackageItem{}, + &vclaimsep.VclaimSep{}, &encounter.Encounter{}, &laborant.Laborant{}, &specialist.Specialist{}, &subspecialist.Subspecialist{}, &specialistintern.SpecialistIntern{}, - &room.Room{}, &soapi.Soapi{}, &sbar.Sbar{}, &adime.Adime{}, @@ -196,6 +206,8 @@ func getMainEntities() []any { &midwife.Midwife{}, &postalregion.PostalRegion{}, &internalreference.InternalReference{}, + &procedureroomorder.ProcedureRoomOrder{}, + &vclaimsephist.VclaimSepHist{}, &vclaimsepprint.VclaimSepPrint{}, &vehicle.Vehicle{}, From 51e25279854ee209d492f6d6e2d0034d73cf6e87 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Tue, 2 Dec 2025 20:16:42 +0700 Subject: [PATCH 306/329] feat/order-things: adjust entities --- .../migrations/20251202130629.sql | 101 ++++++++++++++++++ cmd/main-migration/migrations/atlas.sum | 4 +- .../device-package-item/device-package/dto.go | 63 +++++++++++ .../device-package/entity.go | 11 ++ .../main-entities/device-package-item/dto.go | 69 ++++++++++++ .../device-package-item/entity.go | 15 +++ .../main-entities/device-package/dto.go | 63 +++++++++++ .../main-entities/device-package/entity.go | 11 ++ internal/domain/main-entities/infra/dto.go | 33 +++--- internal/domain/main-entities/infra/entity.go | 22 ++-- .../domain/main-entities/installation/dto.go | 4 +- .../main-entities/installation/entity.go | 2 +- .../material-package-item/dto.go | 69 ++++++++++++ .../material-package-item/entity.go | 15 +++ .../main-entities/material-package/dto.go | 66 ++++++++++++ .../main-entities/material-package/entity.go | 11 ++ .../main-entities/procedure-room-order/dto.go | 70 ++++++++++++ .../procedure-room-order/entity.go | 13 +++ .../procedure-room/base/entity.go | 21 ++++ .../{room => procedure-room}/dto.go | 13 ++- .../main-entities/procedure-room/entity.go | 17 +++ .../domain/main-entities/room/base/entity.go | 23 ---- internal/domain/main-entities/room/entity.go | 11 -- .../domain/main-entities/specialist/entity.go | 4 +- .../subspecialist-position/dto.go | 2 +- .../subspecialist/base/entity.go | 4 +- .../domain/main-entities/subspecialist/dto.go | 2 +- internal/domain/main-entities/unit/dto.go | 2 +- internal/domain/main-entities/unit/entity.go | 4 +- .../references/organization/organization.go | 36 ++++--- internal/interface/migration/main-entities.go | 16 ++- 31 files changed, 701 insertions(+), 96 deletions(-) create mode 100644 cmd/main-migration/migrations/20251202130629.sql create mode 100644 internal/domain/main-entities/device-package-item/device-package/dto.go create mode 100644 internal/domain/main-entities/device-package-item/device-package/entity.go create mode 100644 internal/domain/main-entities/device-package-item/dto.go create mode 100644 internal/domain/main-entities/device-package-item/entity.go create mode 100644 internal/domain/main-entities/device-package/dto.go create mode 100644 internal/domain/main-entities/device-package/entity.go create mode 100644 internal/domain/main-entities/material-package-item/dto.go create mode 100644 internal/domain/main-entities/material-package-item/entity.go create mode 100644 internal/domain/main-entities/material-package/dto.go create mode 100644 internal/domain/main-entities/material-package/entity.go create mode 100644 internal/domain/main-entities/procedure-room-order/dto.go create mode 100644 internal/domain/main-entities/procedure-room-order/entity.go create mode 100644 internal/domain/main-entities/procedure-room/base/entity.go rename internal/domain/main-entities/{room => procedure-room}/dto.go (82%) create mode 100644 internal/domain/main-entities/procedure-room/entity.go delete mode 100644 internal/domain/main-entities/room/base/entity.go delete mode 100644 internal/domain/main-entities/room/entity.go diff --git a/cmd/main-migration/migrations/20251202130629.sql b/cmd/main-migration/migrations/20251202130629.sql new file mode 100644 index 00000000..88b685fe --- /dev/null +++ b/cmd/main-migration/migrations/20251202130629.sql @@ -0,0 +1,101 @@ +-- Modify "Consultation" table +ALTER TABLE "public"."Consultation" ALTER COLUMN "DstUnit_Code" TYPE character varying(20); +-- Modify "ControlLetter" table +ALTER TABLE "public"."ControlLetter" ALTER COLUMN "Unit_Code" TYPE character varying(20), ALTER COLUMN "Specialist_Code" TYPE character varying(20), ALTER COLUMN "Subspecialist_Code" TYPE character varying(20); +-- Modify "Encounter" table +ALTER TABLE "public"."Encounter" ALTER COLUMN "Specialist_Code" TYPE character varying(20), ALTER COLUMN "Subspecialist_Code" TYPE character varying(20), ALTER COLUMN "Unit_Code" TYPE character varying(20); +-- Modify "Chemo" table +ALTER TABLE "public"."Chemo" ALTER COLUMN "SrcUnit_Code" TYPE character varying(20); +-- Modify "Installation" table +ALTER TABLE "public"."Installation" ALTER COLUMN "Code" TYPE character varying(20); +-- Modify "InternalReference" table +ALTER TABLE "public"."InternalReference" ALTER COLUMN "Unit_Code" TYPE character varying(20); +-- Modify "PracticeSchedule" table +ALTER TABLE "public"."PracticeSchedule" ALTER COLUMN "Unit_Code" TYPE character varying(20); +-- Create "DevicePackage" table +CREATE TABLE "public"."DevicePackage" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(20) NOT NULL, + "Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_DevicePackage_Code" UNIQUE ("Code") +); +-- Create "DevicePackageItem" table +CREATE TABLE "public"."DevicePackageItem" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "DevicePackage_Code" character varying(20) NOT NULL, + "Device_Code" character varying(20) NOT NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_DevicePackageItem_Device" FOREIGN KEY ("Device_Code") REFERENCES "public"."Device" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_DevicePackageItem_DevicePackage" FOREIGN KEY ("DevicePackage_Code") REFERENCES "public"."DevicePackage" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "MaterialPackage" table +CREATE TABLE "public"."MaterialPackage" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(20) NOT NULL, + "Name" character varying(50) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_MaterialPackage_Code" UNIQUE ("Code") +); +-- Create "MaterialPackageItem" table +CREATE TABLE "public"."MaterialPackageItem" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "MaterialPackage_Code" character varying(20) NOT NULL, + "Material_Code" character varying(20) NOT NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_MaterialPackageItem_Material" FOREIGN KEY ("Material_Code") REFERENCES "public"."Material" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_MaterialPackageItem_MaterialPackage" FOREIGN KEY ("MaterialPackage_Code") REFERENCES "public"."MaterialPackage" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Modify "Infra" table +ALTER TABLE "public"."Infra" ALTER COLUMN "Code" TYPE character varying(20), ALTER COLUMN "InfraGroup_Code" TYPE character varying(20), ALTER COLUMN "Parent_Code" TYPE character varying(20); +-- Modify "Specialist" table +ALTER TABLE "public"."Specialist" ALTER COLUMN "Code" TYPE character varying(20), ALTER COLUMN "Unit_Code" TYPE character varying(20); +-- Modify "Subspecialist" table +ALTER TABLE "public"."Subspecialist" ALTER COLUMN "Code" TYPE character varying(20), ALTER COLUMN "Specialist_Code" TYPE character varying(20); +-- Modify "Unit" table +ALTER TABLE "public"."Unit" ALTER COLUMN "Code" TYPE character varying(20), ALTER COLUMN "Installation_Code" TYPE character varying(20); +-- Create "ProcedureRoom" table +CREATE TABLE "public"."ProcedureRoom" ( + "Id" serial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Code" character varying(20) NULL, + "Infra_Code" character varying(20) NULL, + "Type_Code" character varying(10) NULL, + "Unit_Code" character varying(20) NULL, + "Specialist_Code" character varying(20) NULL, + "Subspecialist_Code" character varying(20) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "uni_ProcedureRoom_Code" UNIQUE ("Code"), + CONSTRAINT "uni_ProcedureRoom_Infra_Code" UNIQUE ("Infra_Code"), + CONSTRAINT "fk_ProcedureRoom_Infra" FOREIGN KEY ("Infra_Code") REFERENCES "public"."Infra" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_ProcedureRoom_Specialist" FOREIGN KEY ("Specialist_Code") REFERENCES "public"."Specialist" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_ProcedureRoom_Subspecialist" FOREIGN KEY ("Subspecialist_Code") REFERENCES "public"."Subspecialist" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_ProcedureRoom_Unit" FOREIGN KEY ("Unit_Code") REFERENCES "public"."Unit" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "ProcedureRoomOrder" table +CREATE TABLE "public"."ProcedureRoomOrder" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Infra_Code" character varying(20) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_ProcedureRoomOrder_ProcedureRoom" FOREIGN KEY ("Infra_Code") REFERENCES "public"."ProcedureRoom" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Drop "Room" table +DROP TABLE "public"."Room"; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 11fba5b8..54858b7b 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:NjMnBBzNKOW7RxpS7I5LqVv+o/CxGkxhHt/B7CV4/tQ= +h1:cyae1SX3YSMX1LZLEsCFxcRKbVxpnp46BqFxWXJqKjs= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -140,4 +140,4 @@ h1:NjMnBBzNKOW7RxpS7I5LqVv+o/CxGkxhHt/B7CV4/tQ= 20251202030445.sql h1:QWBVfTepT7DaXP5E0BYoxNM0JwKIQ2qIMXzI4kbz/qE= 20251202044430.sql h1:4QZH9lz0GrQ9rzP1AJ+hJgGalNpp+8FCRckNK7xaTbU= 20251202064000.sql h1:/EN7sT1ol/91qW1aXWrzX+Mc3XOC/7f/LtfA0JRHpbg= -20251202122413.sql h1:uZpx6oC8BLTECZdMN69u+WTAAzdSWF70RGVB/pIxC84= +20251202130629.sql h1:LjBgQS8tKEwpC3WA0wGeO2Fs2L20kEOB6e5ljO4EdLM= diff --git a/internal/domain/main-entities/device-package-item/device-package/dto.go b/internal/domain/main-entities/device-package-item/device-package/dto.go new file mode 100644 index 00000000..26aad58a --- /dev/null +++ b/internal/domain/main-entities/device-package-item/device-package/dto.go @@ -0,0 +1,63 @@ +package devicepackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type CreateDto struct { + Code string `json:"code" validate:"maxLength=20"` + Name string `json:"name" validate:"maxLength=50"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Code string `json:"code"` + Name string `json:"name"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` +} + +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.SmallMain + Code string `json:"code"` + Name string `json:"name"` +} + +func (d DevicePackage) ToResponse() ResponseDto { + resp := ResponseDto{ + Code: d.Code, + Name: d.Name, + } + resp.SmallMain = d.SmallMain + return resp +} + +func ToResponseList(data []DevicePackage) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/device-package-item/device-package/entity.go b/internal/domain/main-entities/device-package-item/device-package/entity.go new file mode 100644 index 00000000..1c03b44d --- /dev/null +++ b/internal/domain/main-entities/device-package-item/device-package/entity.go @@ -0,0 +1,11 @@ +package devicepackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type DevicePackage struct { + ecore.SmallMain + Code string `json:"code" gorm:"unique;size:20;not null"` + Name string `json:"name" gorm:"size:50"` +} diff --git a/internal/domain/main-entities/device-package-item/dto.go b/internal/domain/main-entities/device-package-item/dto.go new file mode 100644 index 00000000..a0a224ba --- /dev/null +++ b/internal/domain/main-entities/device-package-item/dto.go @@ -0,0 +1,69 @@ +package devicepackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ed "simrs-vx/internal/domain/main-entities/device" + edp "simrs-vx/internal/domain/main-entities/device-package" +) + +type CreateDto struct { + DevicePackage_Code string `json:"devicePackage_code" validate:"maxLength=20"` + Device_Code string `json:"code" validate:"maxLength=20"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + DevicePackage_Code string `json:"devicePackage-code"` + Device_Code string `json:"code"` +} + +type ReadDetailDto struct { + Id uint `json:"id"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + DevicePackage_Code string `json:"devicePackage_code"` + DevicePackage *edp.DevicePackage `json:"devicePackage,omitempty"` + Device_Code string `json:"code"` + Device *ed.Device `json:"device,omitempty"` +} + +func (d DevicePackageItem) ToResponse() ResponseDto { + resp := ResponseDto{ + DevicePackage_Code: d.DevicePackage_Code, + DevicePackage: d.DevicePackage, + Device_Code: d.Device_Code, + Device: d.Device, + } + resp.Id = d.Id + return resp +} + +func ToResponseList(data []DevicePackageItem) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/device-package-item/entity.go b/internal/domain/main-entities/device-package-item/entity.go new file mode 100644 index 00000000..476e24e2 --- /dev/null +++ b/internal/domain/main-entities/device-package-item/entity.go @@ -0,0 +1,15 @@ +package devicepackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ed "simrs-vx/internal/domain/main-entities/device" + edp "simrs-vx/internal/domain/main-entities/device-package" +) + +type DevicePackageItem struct { + ecore.Main + DevicePackage_Code string `json:"devicePackage_code" gorm:"size:20;not null"` + DevicePackage *edp.DevicePackage `json:"devicePackage" gorm:"foreignKey:DevicePackage_Code;references:Code"` + Device_Code string `json:"code" gorm:"size:20;not null"` + Device *ed.Device `json:"device" gorm:"foreignKey:Device_Code;references:Code"` +} diff --git a/internal/domain/main-entities/device-package/dto.go b/internal/domain/main-entities/device-package/dto.go new file mode 100644 index 00000000..26aad58a --- /dev/null +++ b/internal/domain/main-entities/device-package/dto.go @@ -0,0 +1,63 @@ +package devicepackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type CreateDto struct { + Code string `json:"code" validate:"maxLength=20"` + Name string `json:"name" validate:"maxLength=50"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Code string `json:"code"` + Name string `json:"name"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` +} + +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.SmallMain + Code string `json:"code"` + Name string `json:"name"` +} + +func (d DevicePackage) ToResponse() ResponseDto { + resp := ResponseDto{ + Code: d.Code, + Name: d.Name, + } + resp.SmallMain = d.SmallMain + return resp +} + +func ToResponseList(data []DevicePackage) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/device-package/entity.go b/internal/domain/main-entities/device-package/entity.go new file mode 100644 index 00000000..1c03b44d --- /dev/null +++ b/internal/domain/main-entities/device-package/entity.go @@ -0,0 +1,11 @@ +package devicepackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type DevicePackage struct { + ecore.SmallMain + Code string `json:"code" gorm:"unique;size:20;not null"` + Name string `json:"name" gorm:"size:50"` +} diff --git a/internal/domain/main-entities/infra/dto.go b/internal/domain/main-entities/infra/dto.go index dfe271e5..f5cf5444 100644 --- a/internal/domain/main-entities/infra/dto.go +++ b/internal/domain/main-entities/infra/dto.go @@ -3,15 +3,16 @@ package infra import ( ecore "simrs-vx/internal/domain/base-entities/core" ei "simrs-vx/internal/domain/main-entities/item" - erb "simrs-vx/internal/domain/main-entities/room/base" + + erb "simrs-vx/internal/domain/main-entities/procedure-room/base" ero "simrs-vx/internal/domain/references/organization" ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=10"` + Code string `json:"code" validate:"maxLength=20"` Name string `json:"name" validate:"maxLength=50"` - InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code" validate:"maxLength=15"` + InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code" validate:"maxLength=20"` Parent_Code *string `json:"parent_code"` Item_Code *string `json:"-"` Unit_Code *string `json:"unit_code"` @@ -61,15 +62,15 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain - Code string `json:"code"` - Name string `json:"name"` - InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code"` - Parent_Code *string `json:"parent_code"` - Parent *Infra `json:"parent,omitempty"` - Childrens []Infra `json:"childrens,omitempty"` - Item_Code *string `json:"item_code"` - Item *ei.Item `json:"item,omitempty"` - Rooms []erb.Basic `json:"rooms,omitempty"` + Code string `json:"code"` + Name string `json:"name"` + InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code"` + Parent_Code *string `json:"parent_code"` + Parent *Infra `json:"parent,omitempty"` + Childrens []Infra `json:"childrens,omitempty"` + Item_Code *string `json:"item_code"` + Item *ei.Item `json:"item,omitempty"` + ProcedureRooms []erb.ProcedureRoom `json:"rooms,omitempty"` } func (d Infra) ToResponse() ResponseDto { @@ -79,10 +80,10 @@ func (d Infra) ToResponse() ResponseDto { InfraGroup_Code: d.InfraGroup_Code, Parent_Code: d.Parent_Code, // Parent: d.Parent, - Childrens: d.Childrens, - Item_Code: d.Item_Code, - Item: d.Item, - Rooms: d.Rooms, + Childrens: d.Childrens, + Item_Code: d.Item_Code, + Item: d.Item, + ProcedureRooms: d.ProcedureRooms, } resp.SmallMain = d.SmallMain return resp diff --git a/internal/domain/main-entities/infra/entity.go b/internal/domain/main-entities/infra/entity.go index 51cc8eaa..8fe5cb52 100644 --- a/internal/domain/main-entities/infra/entity.go +++ b/internal/domain/main-entities/infra/entity.go @@ -4,20 +4,20 @@ import ( ecore "simrs-vx/internal/domain/base-entities/core" ei "simrs-vx/internal/domain/main-entities/item" - erb "simrs-vx/internal/domain/main-entities/room/base" + erb "simrs-vx/internal/domain/main-entities/procedure-room/base" ero "simrs-vx/internal/domain/references/organization" ) type Infra struct { - ecore.SmallMain // adjust this according to the needs - Code string `json:"code" gorm:"uniqueIndex;size:10;not null"` - Name string `json:"name" gorm:"size:50"` - InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code" gorm:"size:15"` - Parent_Code *string `json:"parent_code" gorm:"size:10"` - Parent *Infra `json:"parent" gorm:"foreignKey:Parent_Code;references:Code"` - Childrens []Infra `json:"childrens" gorm:"foreignKey:Parent_Code;references:Code"` - Item_Code *string `json:"item_code" gorm:"size:50"` - Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Code;references:Code"` - Rooms []erb.Basic `json:"rooms" gorm:"foreignKey:Infra_Code;references:Code"` + ecore.SmallMain // adjust this according to the needs + Code string `json:"code" gorm:"uniqueIndex;size:20;not null"` + Name string `json:"name" gorm:"size:50"` + InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code" gorm:"size:20"` + Parent_Code *string `json:"parent_code" gorm:"size:20"` + Parent *Infra `json:"parent" gorm:"foreignKey:Parent_Code;references:Code"` + Childrens []Infra `json:"childrens" gorm:"foreignKey:Parent_Code;references:Code"` + Item_Code *string `json:"item_code" gorm:"size:50"` + Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Code;references:Code"` + ProcedureRooms []erb.ProcedureRoom `json:"rooms" gorm:"foreignKey:Infra_Code;references:Code"` } diff --git a/internal/domain/main-entities/installation/dto.go b/internal/domain/main-entities/installation/dto.go index 5cc0ed5c..bd6fcc0e 100644 --- a/internal/domain/main-entities/installation/dto.go +++ b/internal/domain/main-entities/installation/dto.go @@ -9,9 +9,9 @@ import ( type CreateDto struct { Id *uint `json:"id"` - Code *string `json:"code" validate:"maxLength=10"` + Code *string `json:"code" validate:"maxLength=20"` Name string `json:"name" validate:"maxLength=50"` - EncounterClass_Code ere.EncounterClassCode `json:"encounterClass_code" validate:"maxLength=10"` + EncounterClass_Code ere.EncounterClassCode `json:"encounterClass_code" validate:"maxLength=20"` } type ReadListDto struct { diff --git a/internal/domain/main-entities/installation/entity.go b/internal/domain/main-entities/installation/entity.go index 5cc82430..6c3c0ecf 100644 --- a/internal/domain/main-entities/installation/entity.go +++ b/internal/domain/main-entities/installation/entity.go @@ -8,7 +8,7 @@ import ( type Installation struct { ecore.SmallMain // adjust this according to the needs - Code string `json:"code" gorm:"unique;size:10"` + Code string `json:"code" gorm:"unique;size:20"` Name string `json:"name" gorm:"size:50"` EncounterClass_Code ere.EncounterClassCode `json:"encounterClass_code" gorm:"size:10"` InstallationPositions []eipb.Basic `json:"installationPositions,omitempty" gorm:"foreignKey:Installation_Code;references:Code"` diff --git a/internal/domain/main-entities/material-package-item/dto.go b/internal/domain/main-entities/material-package-item/dto.go new file mode 100644 index 00000000..a9b11be6 --- /dev/null +++ b/internal/domain/main-entities/material-package-item/dto.go @@ -0,0 +1,69 @@ +package materialpackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + em "simrs-vx/internal/domain/main-entities/material" + emp "simrs-vx/internal/domain/main-entities/material-package" +) + +type CreateDto struct { + MaterialPackage_Code string `json:"materialPackage_code" validate:"maxLength=20"` + Material_Code string `json:"code" validate:"maxLength=20"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + MaterialPackage_Code string `json:"materialPackage-code"` + Material_Code string `json:"code"` +} + +type ReadDetailDto struct { + Id uint `json:"id"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + MaterialPackage_Code string `json:"materialPackage_code"` + MaterialPackage *emp.MaterialPackage `json:"materialPackage,omitempty"` + Material_Code string `json:"code"` + Material *em.Material `json:"material,omitempty"` +} + +func (d MaterialPackageItem) ToResponse() ResponseDto { + resp := ResponseDto{ + MaterialPackage_Code: d.MaterialPackage_Code, + MaterialPackage: d.MaterialPackage, + Material_Code: d.Material_Code, + Material: d.Material, + } + resp.Id = d.Id + return resp +} + +func ToResponseList(data []MaterialPackageItem) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/material-package-item/entity.go b/internal/domain/main-entities/material-package-item/entity.go new file mode 100644 index 00000000..76378dc8 --- /dev/null +++ b/internal/domain/main-entities/material-package-item/entity.go @@ -0,0 +1,15 @@ +package materialpackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + em "simrs-vx/internal/domain/main-entities/material" + emp "simrs-vx/internal/domain/main-entities/material-package" +) + +type MaterialPackageItem struct { + ecore.Main + MaterialPackage_Code string `json:"materialPackage_code" gorm:"size:20;not null"` + MaterialPackage *emp.MaterialPackage `json:"materialPackage" gorm:"foreignKey:MaterialPackage_Code;references:Code"` + Material_Code string `json:"code" gorm:"size:20;not null"` + Material *em.Material `json:"material" gorm:"foreignKey:Material_Code;references:Code"` +} diff --git a/internal/domain/main-entities/material-package/dto.go b/internal/domain/main-entities/material-package/dto.go new file mode 100644 index 00000000..51dc1ab1 --- /dev/null +++ b/internal/domain/main-entities/material-package/dto.go @@ -0,0 +1,66 @@ +package materialpackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type CreateDto struct { + Code string `json:"code" validate:"maxLength=20"` + Name string `json:"name" validate:"maxLength=50"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination + Sort string `json:"sort"` +} + +type FilterDto struct { + Code string `json:"code"` + Name string `json:"name"` +} + +type ReadDetailDto struct { + Id *uint16 `json:"id"` + Code *string `json:"code"` +} + +type UpdateDto struct { + Id uint16 `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id *uint16 `json:"id"` + Code *string `json:"code"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.SmallMain + Code string `json:"code"` + Name string `json:"name"` +} + +func (d MaterialPackage) ToResponse() ResponseDto { + resp := ResponseDto{ + Code: d.Code, + Name: d.Name, + } + resp.SmallMain = d.SmallMain + return resp +} + +func ToResponseList(data []MaterialPackage) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/material-package/entity.go b/internal/domain/main-entities/material-package/entity.go new file mode 100644 index 00000000..4f3feeab --- /dev/null +++ b/internal/domain/main-entities/material-package/entity.go @@ -0,0 +1,11 @@ +package materialpackage + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type MaterialPackage struct { + ecore.SmallMain + Code string `json:"code" gorm:"unique;size:20;not null"` + Name string `json:"name" gorm:"size:50"` +} diff --git a/internal/domain/main-entities/procedure-room-order/dto.go b/internal/domain/main-entities/procedure-room-order/dto.go new file mode 100644 index 00000000..d202f031 --- /dev/null +++ b/internal/domain/main-entities/procedure-room-order/dto.go @@ -0,0 +1,70 @@ +package procedureroomorder + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ec "simrs-vx/internal/domain/main-entities/encounter" + epr "simrs-vx/internal/domain/main-entities/procedure-room" +) + +type CreateDto struct { + Encounter_Id uint64 `json:"encounter_id"` + Infra_Code string `json:"procedure"` + ProcedureRoom string `json:"procedureRoom"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Encounter_Id uint64 `json:"encounter-id"` + Infra_Code string `json:"procedure-code"` + ProcedureRoom string `json:"procedure-room"` +} + +type ReadDetailDto struct { + Id uint `json:"id"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + Encounter_Id uint64 `json:"encounter_id"` + Encounter *ec.Encounter `json:"encounter,omitempty"` + Infra_Code string `json:"procedure"` + ProcedureRoom *epr.ProcedureRoom `json:"procedureRoom,omitempty"` +} + +func (d ProcedureRoomOrder) ToResponse() ResponseDto { + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Infra_Code: d.Infra_Code, + // ProcedureRoom: d.ProcedureRoom, + } + resp.Id = d.Id + return resp +} + +func ToResponseList(data []ProcedureRoomOrder) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/procedure-room-order/entity.go b/internal/domain/main-entities/procedure-room-order/entity.go new file mode 100644 index 00000000..7e453410 --- /dev/null +++ b/internal/domain/main-entities/procedure-room-order/entity.go @@ -0,0 +1,13 @@ +package procedureroomorder + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + epr "simrs-vx/internal/domain/main-entities/procedure-room" +) + +type ProcedureRoomOrder struct { + ecore.Main + Encounter_Id uint64 `json:"encounter_id"` + Infra_Code string `json:"infra_code" gorm:"size:20"` + ProcedureRoom *epr.ProcedureRoom `json:"procedureRoom,omitempty" gorm:"foreignKey:Infra_Code;references:Code"` +} diff --git a/internal/domain/main-entities/procedure-room/base/entity.go b/internal/domain/main-entities/procedure-room/base/entity.go new file mode 100644 index 00000000..981dd4f2 --- /dev/null +++ b/internal/domain/main-entities/procedure-room/base/entity.go @@ -0,0 +1,21 @@ +package procedureroombase + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ero "simrs-vx/internal/domain/references/organization" +) + +type ProcedureRoom struct { + ecore.SmallMain + Code string `json:"code" gorm:"unique;size:20"` // copied from infra code + Infra_Code *string `json:"infra_code" gorm:"size:20;unique"` + Type_Code *ero.ProdcedureRoomTypeCode `json:"type_code" gorm:"size:10"` + Unit_Code *string `json:"unit_code" gorm:"size:20"` + Specialist_Code *string `json:"specialist_code" gorm:"size:20"` + Subspecialist_Code *string `json:"subspecialist_code" gorm:"size:20"` +} + +// THIS IS ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ +// func (ProcedureRoom) TableName() string { +// return "Room" +// } diff --git a/internal/domain/main-entities/room/dto.go b/internal/domain/main-entities/procedure-room/dto.go similarity index 82% rename from internal/domain/main-entities/room/dto.go rename to internal/domain/main-entities/procedure-room/dto.go index 2ff41c3a..373e6cd9 100644 --- a/internal/domain/main-entities/room/dto.go +++ b/internal/domain/main-entities/procedure-room/dto.go @@ -1,4 +1,4 @@ -package room +package procedureroom import ( ecore "simrs-vx/internal/domain/base-entities/core" @@ -9,7 +9,9 @@ import ( ) type CreateDto struct { + Code *string `json:"code"` Infra_Code *string `json:"infra_code"` + Type_Code string `json:"type_code"` Unit_Code *string `json:"unit_code"` Specialist_Code *string `json:"specialist_code"` Subspecialist_Code *string `json:"subspecialist_code"` @@ -23,6 +25,7 @@ type ReadListDto struct { type FilterDto struct { Infra_Code *string `json:"infra-code"` + Type_Code string `json:"type_code"` Unit_Code *string `json:"unit-code"` Specialist_Code *string `json:"specialist-code"` Subspecialist_Code *string `json:"subspecialist-code"` @@ -49,6 +52,8 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain + Code string `json:"code"` + Type_Code *string `json:"type_code"` Infra_Code *string `json:"infra_code"` Infra *ei.Infra `json:"infra,omitempty"` Unit_Code *string `json:"unit_code"` @@ -59,10 +64,12 @@ type ResponseDto struct { Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty"` } -func (d Room) ToResponse() ResponseDto { +func (d ProcedureRoom) ToResponse() ResponseDto { resp := ResponseDto{ + Code: d.Code, Infra_Code: d.Infra_Code, Infra: d.Infra, + Type_Code: (*string)(d.Type_Code), Unit_Code: d.Unit_Code, Unit: d.Unit, Specialist_Code: d.Specialist_Code, @@ -74,7 +81,7 @@ func (d Room) ToResponse() ResponseDto { return resp } -func ToResponseList(data []Room) []ResponseDto { +func ToResponseList(data []ProcedureRoom) []ResponseDto { resp := make([]ResponseDto, len(data)) for i, u := range data { resp[i] = u.ToResponse() diff --git a/internal/domain/main-entities/procedure-room/entity.go b/internal/domain/main-entities/procedure-room/entity.go new file mode 100644 index 00000000..9be3ac69 --- /dev/null +++ b/internal/domain/main-entities/procedure-room/entity.go @@ -0,0 +1,17 @@ +package procedureroom + +import ( + ei "simrs-vx/internal/domain/main-entities/infra" + ebase "simrs-vx/internal/domain/main-entities/procedure-room/base" + es "simrs-vx/internal/domain/main-entities/specialist" + ess "simrs-vx/internal/domain/main-entities/subspecialist" + eu "simrs-vx/internal/domain/main-entities/unit" +) + +type ProcedureRoom struct { + ebase.ProcedureRoom + Infra *ei.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Code;references:Code"` + Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` + Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Code;references:Code"` + Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Code;references:Code"` +} diff --git a/internal/domain/main-entities/room/base/entity.go b/internal/domain/main-entities/room/base/entity.go deleted file mode 100644 index d5651ac9..00000000 --- a/internal/domain/main-entities/room/base/entity.go +++ /dev/null @@ -1,23 +0,0 @@ -package base - -import ( - ecore "simrs-vx/internal/domain/base-entities/core" - es "simrs-vx/internal/domain/main-entities/specialist" - ess "simrs-vx/internal/domain/main-entities/subspecialist" - eu "simrs-vx/internal/domain/main-entities/unit" -) - -type Basic struct { - ecore.SmallMain // adjust this according to the needs - Infra_Code *string `json:"infra_code" gorm:"size:10"` - Unit_Code *string `json:"unit_code" gorm:"size:10"` - Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` - Specialist_Code *string `json:"specialist_code" gorm:"size:10"` - Specialist *es.Specialist `json:"specialist,omitempty" gorm:"foreignKey:Specialist_Code;references:Code"` - Subspecialist_Code *string `json:"subspecialist_code" gorm:"size:10"` - Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty" gorm:"foreignKey:Subspecialist_Code;references:Code"` -} - -func (Basic) TableName() string { - return "Room" -} diff --git a/internal/domain/main-entities/room/entity.go b/internal/domain/main-entities/room/entity.go deleted file mode 100644 index 49fb8cc6..00000000 --- a/internal/domain/main-entities/room/entity.go +++ /dev/null @@ -1,11 +0,0 @@ -package room - -import ( - ei "simrs-vx/internal/domain/main-entities/infra" - ebase "simrs-vx/internal/domain/main-entities/room/base" -) - -type Room struct { - ebase.Basic - Infra *ei.Infra `json:"infra,omitempty" gorm:"foreignKey:Infra_Code;references:Code"` -} diff --git a/internal/domain/main-entities/specialist/entity.go b/internal/domain/main-entities/specialist/entity.go index 4fef90a5..0b5b7a5d 100644 --- a/internal/domain/main-entities/specialist/entity.go +++ b/internal/domain/main-entities/specialist/entity.go @@ -9,9 +9,9 @@ import ( type Specialist struct { ecore.SmallMain // adjust this according to the needs - Code string `json:"code" gorm:"unique;size:10"` + Code string `json:"code" gorm:"unique;size:20"` Name string `json:"name" gorm:"size:50"` - Unit_Code *string `json:"unit_code" gorm:"size:10"` + Unit_Code *string `json:"unit_code" gorm:"size:20"` Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` SpecialistPositions []eub.Basic `json:"specialistPositions,omitempty" gorm:"foreignKey:Specialist_Code;references:Code"` Subspecialists []essb.Basic `json:"subspecialists,omitempty" gorm:"foreignKey:Specialist_Code;references:Code"` diff --git a/internal/domain/main-entities/subspecialist-position/dto.go b/internal/domain/main-entities/subspecialist-position/dto.go index 1c37a859..4918a8fe 100644 --- a/internal/domain/main-entities/subspecialist-position/dto.go +++ b/internal/domain/main-entities/subspecialist-position/dto.go @@ -8,7 +8,7 @@ import ( type CreateDto struct { Subspecialist_Code *string `json:"subspecialist_code" validate:"required"` - Code string `json:"code" validate:"maxLength=10;required"` + Code string `json:"code" validate:"maxLength=20;required"` Name string `json:"name" validate:"maxLength=30;required"` HeadStatus bool `json:"headStatus"` Employee_Id *uint `json:"employee_id"` diff --git a/internal/domain/main-entities/subspecialist/base/entity.go b/internal/domain/main-entities/subspecialist/base/entity.go index a94fb76d..9fe77039 100644 --- a/internal/domain/main-entities/subspecialist/base/entity.go +++ b/internal/domain/main-entities/subspecialist/base/entity.go @@ -6,9 +6,9 @@ import ( type Basic struct { ecore.SmallMain // adjust this according to the needs - Code string `json:"code" gorm:"unique;size:10"` + Code string `json:"code" gorm:"unique;size:20"` Name string `json:"name" gorm:"size:50"` - Specialist_Code *string `json:"specialist_code" gorm:"size:10"` + Specialist_Code *string `json:"specialist_code" gorm:"size:20"` } func (Basic) TableName() string { diff --git a/internal/domain/main-entities/subspecialist/dto.go b/internal/domain/main-entities/subspecialist/dto.go index 72959023..303da04f 100644 --- a/internal/domain/main-entities/subspecialist/dto.go +++ b/internal/domain/main-entities/subspecialist/dto.go @@ -8,7 +8,7 @@ import ( type CreateDto struct { Id *uint `json:"id"` - Code string `json:"code" validate:"maxLength=10"` + Code string `json:"code" validate:"maxLength=20"` Name string `json:"name" validate:"maxLength=50"` Specialist_Code *string `json:"specialist_code"` } diff --git a/internal/domain/main-entities/unit/dto.go b/internal/domain/main-entities/unit/dto.go index 7b071a84..76151cb7 100644 --- a/internal/domain/main-entities/unit/dto.go +++ b/internal/domain/main-entities/unit/dto.go @@ -9,7 +9,7 @@ import ( type CreateDto struct { Id *uint `json:"id"` Installation_Code *string `json:"installation_code"` - Code string `json:"code" validate:"maxLength=10"` + Code string `json:"code" validate:"maxLength=20"` Name string `json:"name" validate:"maxLength=50"` } diff --git a/internal/domain/main-entities/unit/entity.go b/internal/domain/main-entities/unit/entity.go index 97db9885..e8110db3 100644 --- a/internal/domain/main-entities/unit/entity.go +++ b/internal/domain/main-entities/unit/entity.go @@ -9,9 +9,9 @@ import ( type Unit struct { ecore.SmallMain // adjust this according to the needs - Installation_Code *string `json:"installation_code" gorm:"size:10"` + Installation_Code *string `json:"installation_code" gorm:"size:20"` Installation *ei.Installation `json:"installation" gorm:"foreignKey:Installation_Code;references:Code"` - Code string `json:"code" gorm:"unique;size:10"` + Code string `json:"code" gorm:"unique;size:20"` Name string `json:"name" gorm:"size:50"` Type_Code *ero.UnitTypeCode `json:"type_code"` UnitPositions []eub.Basic `json:"unitPositions,omitempty" gorm:"foreignKey:Unit_Code;references:Code"` diff --git a/internal/domain/references/organization/organization.go b/internal/domain/references/organization/organization.go index b39752d5..0647f88f 100644 --- a/internal/domain/references/organization/organization.go +++ b/internal/domain/references/organization/organization.go @@ -1,14 +1,15 @@ package organization type ( - ContractPositionCode string - EmployeePositionCode string - InternPosisitionCode string - ItemGroupCode string - InfraGroupCode string - UnitTypeCode string - DoctorFeeTypeCode string - ActionBillingCode string + ContractPositionCode string + EmployeePositionCode string + InternPosisitionCode string + ItemGroupCode string + InfraGroupCode string + ProdcedureRoomTypeCode string + UnitTypeCode string + DoctorFeeTypeCode string + ActionBillingCode string ) const ( @@ -44,14 +45,17 @@ const ( ITGCDocFee ItemGroupCode = "doctor-fee" ITGCMedAct ItemGroupCode = "medical-action" - IFGCBuilding InfraGroupCode = "building" // Bangunan - IFGCFloor InfraGroupCode = "floor" // Lantai - IFGCRoom InfraGroupCode = "room" // Ruang - IFGCChamber InfraGroupCode = "chamber" // Kamar - IFGCBed InfraGroupCode = "bed" // Ranjang - IFGCWarehouse InfraGroupCode = "warehouse" // Gudang/Depo - IFGCCounter InfraGroupCode = "counter" // Counter - IFGCPubScreen InfraGroupCode = "public-screen" // Public Screen + IFGCBuilding InfraGroupCode = "building" // Bangunan + IFGCFloor InfraGroupCode = "floor" // Lantai + IFGCProcedureRoom InfraGroupCode = "procedure-room" // Ruang Tindakan + IFGCChamber InfraGroupCode = "chamber" // Kamar + IFGCBed InfraGroupCode = "bed" // Ranjang + IFGCWarehouse InfraGroupCode = "warehouse" // Gudang/Depo + IFGCCounter InfraGroupCode = "counter" // Counter + IFGCPubScreen InfraGroupCode = "public-screen" // Public Screen + + PRTLight ProdcedureRoomTypeCode = "light" // Ringan + PRTSurgery ProdcedureRoomTypeCode = "roomed" // Dikamarkan UTCReg UnitTypeCode = "reg" // Registrasi UTCExa UnitTypeCode = "exa" // Pemeriksaan diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index bed0c18c..0d118fae 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -19,6 +19,8 @@ import ( device "simrs-vx/internal/domain/main-entities/device" deviceorder "simrs-vx/internal/domain/main-entities/device-order" deviceorderitem "simrs-vx/internal/domain/main-entities/device-order-item" + devicepackage "simrs-vx/internal/domain/main-entities/device-package" + devicepackageitem "simrs-vx/internal/domain/main-entities/device-package-item" diagnosesrc "simrs-vx/internal/domain/main-entities/diagnose-src" district "simrs-vx/internal/domain/main-entities/district" division "simrs-vx/internal/domain/main-entities/division" @@ -46,6 +48,8 @@ import ( material "simrs-vx/internal/domain/main-entities/material" materialorder "simrs-vx/internal/domain/main-entities/material-order" materialorderitem "simrs-vx/internal/domain/main-entities/material-order-item" + materialpackage "simrs-vx/internal/domain/main-entities/material-package" + materialpackageitem "simrs-vx/internal/domain/main-entities/material-package-item" mcuorder "simrs-vx/internal/domain/main-entities/mcu-order" mcuorderitem "simrs-vx/internal/domain/main-entities/mcu-order-item" mcuordersubitem "simrs-vx/internal/domain/main-entities/mcu-order-sub-item" @@ -78,13 +82,14 @@ import ( practiceschedule "simrs-vx/internal/domain/main-entities/practice-schedule" prescription "simrs-vx/internal/domain/main-entities/prescription" prescriptionitem "simrs-vx/internal/domain/main-entities/prescription-item" + procedureroom "simrs-vx/internal/domain/main-entities/procedure-room" + procedureroomorder "simrs-vx/internal/domain/main-entities/procedure-room-order" proceduresrc "simrs-vx/internal/domain/main-entities/procedure-src" province "simrs-vx/internal/domain/main-entities/province" regency "simrs-vx/internal/domain/main-entities/regency" rehab "simrs-vx/internal/domain/main-entities/rehab" responsibledoctorhist "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" resume "simrs-vx/internal/domain/main-entities/resume" - room "simrs-vx/internal/domain/main-entities/room" sbar "simrs-vx/internal/domain/main-entities/sbar" screening "simrs-vx/internal/domain/main-entities/screening" soapi "simrs-vx/internal/domain/main-entities/soapi" @@ -144,6 +149,7 @@ func getMainEntities() []any { &item.Item{}, &itemprice.ItemPrice{}, &infra.Infra{}, + &procedureroom.ProcedureRoom{}, &medicinegroup.MedicineGroup{}, &medicinemethod.MedicineMethod{}, &mcusrccategory.McuSrcCategory{}, @@ -163,13 +169,17 @@ func getMainEntities() []any { &personrelative.PersonRelative{}, &patient.Patient{}, &appointment.Appointment{}, + &devicepackage.DevicePackage{}, + &devicepackageitem.DevicePackageItem{}, + &materialpackage.MaterialPackage{}, + &materialpackageitem.MaterialPackageItem{}, + &vclaimsep.VclaimSep{}, &encounter.Encounter{}, &laborant.Laborant{}, &specialist.Specialist{}, &subspecialist.Subspecialist{}, &specialistintern.SpecialistIntern{}, - &room.Room{}, &soapi.Soapi{}, &sbar.Sbar{}, &adime.Adime{}, @@ -196,6 +206,8 @@ func getMainEntities() []any { &midwife.Midwife{}, &postalregion.PostalRegion{}, &internalreference.InternalReference{}, + &procedureroomorder.ProcedureRoomOrder{}, + &vclaimsephist.VclaimSepHist{}, &vclaimsepprint.VclaimSepPrint{}, &vehicle.Vehicle{}, From 118aa098cecfc264f7c4620ca3569f62fb9db3fe Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Tue, 2 Dec 2025 20:56:00 +0700 Subject: [PATCH 307/329] feat/order-things: adjust package-room case --- internal/use-case/main-use-case/infra/case.go | 6 ++--- .../use-case/main-use-case/infra/helper.go | 7 +++--- internal/use-case/main-use-case/infra/lib.go | 2 +- .../{room => procedure-room}/case.go | 16 +++++++------- .../{room => procedure-room}/helper.go | 7 +++--- .../{room => procedure-room}/lib.go | 22 +++++++++---------- .../middleware-runner.go | 14 ++++++------ .../{room => procedure-room}/middleware.go | 2 +- .../{room => procedure-room}/tycovar.go | 10 ++++----- 9 files changed, 44 insertions(+), 42 deletions(-) rename internal/use-case/main-use-case/{room => procedure-room}/case.go (95%) rename internal/use-case/main-use-case/{room => procedure-room}/helper.go (70%) rename internal/use-case/main-use-case/{room => procedure-room}/lib.go (84%) rename internal/use-case/main-use-case/{room => procedure-room}/middleware-runner.go (86%) rename internal/use-case/main-use-case/{room => procedure-room}/middleware.go (90%) rename internal/use-case/main-use-case/{room => procedure-room}/tycovar.go (74%) diff --git a/internal/use-case/main-use-case/infra/case.go b/internal/use-case/main-use-case/infra/case.go index 4771f3cb..f3ba3854 100644 --- a/internal/use-case/main-use-case/infra/case.go +++ b/internal/use-case/main-use-case/infra/case.go @@ -37,7 +37,7 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } - if input.InfraGroup_Code == ero.IFGCRoom { + if input.InfraGroup_Code == ero.IFGCProcedureRoom { if input.Parent_Code == nil { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ @@ -58,9 +58,9 @@ func Create(input e.CreateDto) (*d.Data, error) { data = *resData } - if input.InfraGroup_Code == ero.IFGCRoom { + if input.InfraGroup_Code == ero.IFGCProcedureRoom { input.Infra_Code = &data.Code - if err := createRoom(&input, &event, tx); err != nil { + if err := createProcedureRoom(&input, &event, tx); err != nil { return err } } diff --git a/internal/use-case/main-use-case/infra/helper.go b/internal/use-case/main-use-case/infra/helper.go index 81de5389..27c5442c 100644 --- a/internal/use-case/main-use-case/infra/helper.go +++ b/internal/use-case/main-use-case/infra/helper.go @@ -7,10 +7,10 @@ package infra import ( e "simrs-vx/internal/domain/main-entities/infra" ei "simrs-vx/internal/domain/main-entities/item" - er "simrs-vx/internal/domain/main-entities/room" + er "simrs-vx/internal/domain/main-entities/procedure-room" ero "simrs-vx/internal/domain/references/organization" ui "simrs-vx/internal/use-case/main-use-case/item" - ur "simrs-vx/internal/use-case/main-use-case/room" + ur "simrs-vx/internal/use-case/main-use-case/procedure-room" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -53,8 +53,9 @@ func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { return nil } -func createRoom(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { +func createProcedureRoom(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { roomCreate := er.CreateDto{ + Code: input.Infra_Code, Infra_Code: input.Infra_Code, Unit_Code: input.Unit_Code, Specialist_Code: input.Specialist_Code, diff --git a/internal/use-case/main-use-case/infra/lib.go b/internal/use-case/main-use-case/infra/lib.go index 5e0592c3..cd97d735 100644 --- a/internal/use-case/main-use-case/infra/lib.go +++ b/internal/use-case/main-use-case/infra/lib.go @@ -129,7 +129,7 @@ func UpdateData(input e.UpdateDto, data *e.Infra, event *pl.Event, dbx ...*gorm. // data.Parent = nil data.Childrens = nil data.Item = nil - data.Rooms = nil + data.ProcedureRooms = nil if err := tx.Save(&data).Error; err != nil { event.Status = "failed" diff --git a/internal/use-case/main-use-case/room/case.go b/internal/use-case/main-use-case/procedure-room/case.go similarity index 95% rename from internal/use-case/main-use-case/room/case.go rename to internal/use-case/main-use-case/procedure-room/case.go index eeb1cce1..0378b759 100644 --- a/internal/use-case/main-use-case/room/case.go +++ b/internal/use-case/main-use-case/procedure-room/case.go @@ -1,7 +1,7 @@ -package room +package procedureroom import ( - e "simrs-vx/internal/domain/main-entities/room" + e "simrs-vx/internal/domain/main-entities/procedure-room" "strconv" dg "github.com/karincake/apem/db-gorm-pg" @@ -16,7 +16,7 @@ import ( const source = "specialist" func Create(input e.CreateDto) (*d.Data, error) { - data := e.Room{} + data := e.ProcedureRoom{} event := pl.Event{ Feature: "Create", @@ -66,8 +66,8 @@ func Create(input e.CreateDto) (*d.Data, error) { } func ReadList(input e.ReadListDto) (*d.Data, error) { - var data *e.Room - var dataList []e.Room + var data *e.ProcedureRoom + var dataList []e.ProcedureRoom var metaList *e.MetaDto var err error @@ -119,7 +119,7 @@ func ReadList(input e.ReadListDto) (*d.Data, error) { } func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { - var data *e.Room + var data *e.ProcedureRoom var err error event := pl.Event{ @@ -167,7 +167,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { func Update(input e.UpdateDto) (*d.Data, error) { rdDto := e.ReadDetailDto{Id: uint16(input.Id)} - var data *e.Room + var data *e.ProcedureRoom var err error event := pl.Event{ @@ -223,7 +223,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { func Delete(input e.DeleteDto) (*d.Data, error) { rdDto := e.ReadDetailDto{Id: uint16(input.Id)} - var data *e.Room + var data *e.ProcedureRoom var err error event := pl.Event{ diff --git a/internal/use-case/main-use-case/room/helper.go b/internal/use-case/main-use-case/procedure-room/helper.go similarity index 70% rename from internal/use-case/main-use-case/room/helper.go rename to internal/use-case/main-use-case/procedure-room/helper.go index 5e97a653..0101efef 100644 --- a/internal/use-case/main-use-case/room/helper.go +++ b/internal/use-case/main-use-case/procedure-room/helper.go @@ -2,13 +2,13 @@ DESCRIPTION: Any functions that are used internally by the use-case */ -package room +package procedureroom import ( - e "simrs-vx/internal/domain/main-entities/room" + e "simrs-vx/internal/domain/main-entities/procedure-room" ) -func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Room) { +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.ProcedureRoom) { var inputSrc *e.CreateDto if inputT, ok := any(input).(*e.CreateDto); ok { inputSrc = inputT @@ -17,6 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Room) { inputSrc = &inputTemp.CreateDto } + data.Code = *inputSrc.Infra_Code data.Infra_Code = inputSrc.Infra_Code data.Unit_Code = inputSrc.Unit_Code data.Specialist_Code = inputSrc.Specialist_Code diff --git a/internal/use-case/main-use-case/room/lib.go b/internal/use-case/main-use-case/procedure-room/lib.go similarity index 84% rename from internal/use-case/main-use-case/room/lib.go rename to internal/use-case/main-use-case/procedure-room/lib.go index 5e586248..f9e46d17 100644 --- a/internal/use-case/main-use-case/room/lib.go +++ b/internal/use-case/main-use-case/procedure-room/lib.go @@ -1,7 +1,7 @@ -package room +package procedureroom import ( - e "simrs-vx/internal/domain/main-entities/room" + e "simrs-vx/internal/domain/main-entities/procedure-room" plh "simrs-vx/pkg/lib-helper" pl "simrs-vx/pkg/logger" @@ -12,10 +12,10 @@ import ( "gorm.io/gorm" ) -func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Room, error) { +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.ProcedureRoom, error) { pl.SetLogInfo(event, nil, "started", "DBCreate") - data := e.Room{} + data := e.ProcedureRoom{} setData(&input, &data) var tx *gorm.DB @@ -33,9 +33,9 @@ func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Room, e return &data, nil } -func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Room, *e.MetaDto, error) { +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.ProcedureRoom, *e.MetaDto, error) { pl.SetLogInfo(event, input, "started", "DBReadList") - data := []e.Room{} + data := []e.ProcedureRoom{} pagination := gh.Pagination{} count := int64(0) meta := e.MetaDto{} @@ -48,7 +48,7 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Ro } tx = tx. - Model(&e.Room{}). + Model(&e.ProcedureRoom{}). Scopes(gh.Preload(input.Includes)). Scopes(gh.Filter(input.FilterDto)). Count(&count). @@ -70,9 +70,9 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Ro return data, &meta, nil } -func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.Room, error) { +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.ProcedureRoom, error) { pl.SetLogInfo(event, input, "started", "DBReadDetail") - data := e.Room{} + data := e.ProcedureRoom{} var tx *gorm.DB if len(dbx) > 0 { @@ -91,7 +91,7 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e return &data, nil } -func UpdateData(input e.UpdateDto, data *e.Room, event *pl.Event, dbx ...*gorm.DB) error { +func UpdateData(input e.UpdateDto, data *e.ProcedureRoom, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, data, "started", "DBUpdate") setData(&input, data) @@ -116,7 +116,7 @@ func UpdateData(input e.UpdateDto, data *e.Room, event *pl.Event, dbx ...*gorm.D return nil } -func DeleteData(data *e.Room, event *pl.Event, dbx ...*gorm.DB) error { +func DeleteData(data *e.ProcedureRoom, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, data, "started", "DBDelete") var tx *gorm.DB if len(dbx) > 0 { diff --git a/internal/use-case/main-use-case/room/middleware-runner.go b/internal/use-case/main-use-case/procedure-room/middleware-runner.go similarity index 86% rename from internal/use-case/main-use-case/room/middleware-runner.go rename to internal/use-case/main-use-case/procedure-room/middleware-runner.go index eaeb46fd..bc96f5c6 100644 --- a/internal/use-case/main-use-case/room/middleware-runner.go +++ b/internal/use-case/main-use-case/procedure-room/middleware-runner.go @@ -1,7 +1,7 @@ -package room +package procedureroom import ( - e "simrs-vx/internal/domain/main-entities/room" + e "simrs-vx/internal/domain/main-entities/procedure-room" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -23,7 +23,7 @@ func newMiddlewareRunner(event *pl.Event, tx *gorm.DB) *middlewareRunner { } // ExecuteCreateMiddleware executes create middleware -func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.Room) error { +func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.ProcedureRoom) error { for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -38,7 +38,7 @@ func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e return nil } -func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.Room) error { +func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.ProcedureRoom) error { for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -53,7 +53,7 @@ func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, inpu return nil } -func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Room) error { +func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.ProcedureRoom) error { for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -68,7 +68,7 @@ func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, return nil } -func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Room) error { +func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.ProcedureRoom) error { for _, middleware := range middlewares { logData := pu.GetLogData(input, data) @@ -83,7 +83,7 @@ func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, inpu return nil } -func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Room) error { +func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.ProcedureRoom) error { for _, middleware := range middlewares { logData := pu.GetLogData(input, data) diff --git a/internal/use-case/main-use-case/room/middleware.go b/internal/use-case/main-use-case/procedure-room/middleware.go similarity index 90% rename from internal/use-case/main-use-case/room/middleware.go rename to internal/use-case/main-use-case/procedure-room/middleware.go index 668f18e2..c30fa7b1 100644 --- a/internal/use-case/main-use-case/room/middleware.go +++ b/internal/use-case/main-use-case/procedure-room/middleware.go @@ -1,4 +1,4 @@ -package room +package procedureroom // example of middleware // func init() { diff --git a/internal/use-case/main-use-case/room/tycovar.go b/internal/use-case/main-use-case/procedure-room/tycovar.go similarity index 74% rename from internal/use-case/main-use-case/room/tycovar.go rename to internal/use-case/main-use-case/procedure-room/tycovar.go index 789e3f6f..ab9f660b 100644 --- a/internal/use-case/main-use-case/room/tycovar.go +++ b/internal/use-case/main-use-case/procedure-room/tycovar.go @@ -6,27 +6,27 @@ 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 room +package procedureroom import ( "gorm.io/gorm" - e "simrs-vx/internal/domain/main-entities/room" + e "simrs-vx/internal/domain/main-entities/procedure-room" ) type createMw struct { Name string - Func func(input *e.CreateDto, data *e.Room, tx *gorm.DB) error + Func func(input *e.CreateDto, data *e.ProcedureRoom, tx *gorm.DB) error } type readListMw struct { Name string - Func func(input *e.ReadListDto, data *e.Room, tx *gorm.DB) error + Func func(input *e.ReadListDto, data *e.ProcedureRoom, tx *gorm.DB) error } type readDetailMw struct { Name string - Func func(input *e.ReadDetailDto, data *e.Room, tx *gorm.DB) error + Func func(input *e.ReadDetailDto, data *e.ProcedureRoom, tx *gorm.DB) error } type UpdateMw = readDetailMw From 7d7c0aee1840ebc9f4c933d2bea836d96e13ed0b Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Tue, 2 Dec 2025 21:35:08 +0700 Subject: [PATCH 308/329] order-things: added material-package flow --- .../interface/main-handler/main-handler.go | 2 + .../main-handler/material-package/handler.go | 71 +++++ .../main-use-case/material-package/case.go | 276 ++++++++++++++++++ .../main-use-case/material-package/helper.go | 22 ++ .../main-use-case/material-package/lib.go | 146 +++++++++ .../material-package/middleware-runner.go | 103 +++++++ .../material-package/middleware.go | 9 + .../main-use-case/material-package/tycovar.go | 44 +++ 8 files changed, 673 insertions(+) create mode 100644 internal/interface/main-handler/material-package/handler.go create mode 100644 internal/use-case/main-use-case/material-package/case.go create mode 100644 internal/use-case/main-use-case/material-package/helper.go create mode 100644 internal/use-case/main-use-case/material-package/lib.go create mode 100644 internal/use-case/main-use-case/material-package/middleware-runner.go create mode 100644 internal/use-case/main-use-case/material-package/middleware.go create mode 100644 internal/use-case/main-use-case/material-package/tycovar.go diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index dd025d0e..31b238ac 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -93,6 +93,7 @@ import ( itemprice "simrs-vx/internal/interface/main-handler/item-price" language "simrs-vx/internal/interface/main-handler/language" material "simrs-vx/internal/interface/main-handler/material" + materialpackage "simrs-vx/internal/interface/main-handler/material-package" mcusrc "simrs-vx/internal/interface/main-handler/mcu-src" mcusrccategory "simrs-vx/internal/interface/main-handler/mcu-src-category" mcusubsrc "simrs-vx/internal/interface/main-handler/mcu-sub-src" @@ -370,6 +371,7 @@ func SetRoutes() http.Handler { hc.RegCrudByCode(r, "/v1/medicine", medicine.O) hc.RegCrudByCode(r, "/v1/device", device.O) hc.RegCrudByCode(r, "/v1/material", material.O) + hc.RegCrudByCode(r, "/v1/material-package", materialpackage.O) hc.RegCrud(r, "/v1/doctor-fee", doctorfee.O) hc.RegCrudByCode(r, "/v1/medical-action-src", medicalactionsrc.O) hc.RegCrud(r, "/v1/medical-action-src-item", medicalactionsrcitem.O) diff --git a/internal/interface/main-handler/material-package/handler.go b/internal/interface/main-handler/material-package/handler.go new file mode 100644 index 00000000..609d983e --- /dev/null +++ b/internal/interface/main-handler/material-package/handler.go @@ -0,0 +1,71 @@ +package material + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/material-package" + u "simrs-vx/internal/use-case/main-use-case/material-package" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { + return + } + dto := e.ReadDetailDto{} + dto.Code = &code + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Code = code + res, err := u.Update(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { + code := rw.ValidateString(w, "code", r.PathValue("code")) + if code == "" { + return + } + + dto := e.DeleteDto{} + dto.Code = &code + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/use-case/main-use-case/material-package/case.go b/internal/use-case/main-use-case/material-package/case.go new file mode 100644 index 00000000..5e56517b --- /dev/null +++ b/internal/use-case/main-use-case/material-package/case.go @@ -0,0 +1,276 @@ +package materialpackage + +import ( + e "simrs-vx/internal/domain/main-entities/material-package" + "strconv" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "material" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.MaterialPackage{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.MaterialPackage + var dataList []e.MaterialPackage + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.MaterialPackage + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Code: &input.Code} + var data *e.MaterialPackage + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Code: input.Code} + var data *e.MaterialPackage + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/material-package/helper.go b/internal/use-case/main-use-case/material-package/helper.go new file mode 100644 index 00000000..7d8e7a9a --- /dev/null +++ b/internal/use-case/main-use-case/material-package/helper.go @@ -0,0 +1,22 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package materialpackage + +import ( + e "simrs-vx/internal/domain/main-entities/material-package" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.MaterialPackage) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Code = inputSrc.Code + data.Name = inputSrc.Name +} diff --git a/internal/use-case/main-use-case/material-package/lib.go b/internal/use-case/main-use-case/material-package/lib.go new file mode 100644 index 00000000..d4d6ac50 --- /dev/null +++ b/internal/use-case/main-use-case/material-package/lib.go @@ -0,0 +1,146 @@ +package materialpackage + +import ( + e "simrs-vx/internal/domain/main-entities/material-package" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.MaterialPackage, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.MaterialPackage{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.MaterialPackage, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.MaterialPackage{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.MaterialPackage{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.MaterialPackage, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.MaterialPackage{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } else { + tx = tx.Where("\"Id\" = ?", *input.Id) + } + + if err := tx.First(&data).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.MaterialPackage, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.MaterialPackage, 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 +} diff --git a/internal/use-case/main-use-case/material-package/middleware-runner.go b/internal/use-case/main-use-case/material-package/middleware-runner.go new file mode 100644 index 00000000..b1ea182c --- /dev/null +++ b/internal/use-case/main-use-case/material-package/middleware-runner.go @@ -0,0 +1,103 @@ +package materialpackage + +import ( + e "simrs-vx/internal/domain/main-entities/material-package" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.MaterialPackage) 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.MaterialPackage) 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.MaterialPackage) 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.MaterialPackage) 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.MaterialPackage) 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/main-use-case/material-package/middleware.go b/internal/use-case/main-use-case/material-package/middleware.go new file mode 100644 index 00000000..85020e68 --- /dev/null +++ b/internal/use-case/main-use-case/material-package/middleware.go @@ -0,0 +1,9 @@ +package materialpackage + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/material-package/tycovar.go b/internal/use-case/main-use-case/material-package/tycovar.go new file mode 100644 index 00000000..67aa3174 --- /dev/null +++ b/internal/use-case/main-use-case/material-package/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 materialpackage + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/material-package" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.MaterialPackage, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.MaterialPackage, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.MaterialPackage, 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 From 83cdfcf0f846003685d67cb58a7a8223dbeef2d1 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Tue, 2 Dec 2025 22:30:03 +0700 Subject: [PATCH 309/329] feat/order-things: added material-package-item flow --- .../material-package-item/dto.go | 9 +- .../interface/main-handler/main-handler.go | 2 + .../material-package-item/handler.go | 71 +++++ .../material-package-item/case.go | 276 ++++++++++++++++++ .../material-package-item/helper.go | 22 ++ .../material-package-item/lib.go | 140 +++++++++ .../middleware-runner.go | 103 +++++++ .../material-package-item/middleware.go | 9 + .../material-package-item/tycovar.go | 44 +++ 9 files changed, 672 insertions(+), 4 deletions(-) create mode 100644 internal/interface/main-handler/material-package-item/handler.go create mode 100644 internal/use-case/main-use-case/material-package-item/case.go create mode 100644 internal/use-case/main-use-case/material-package-item/helper.go create mode 100644 internal/use-case/main-use-case/material-package-item/lib.go create mode 100644 internal/use-case/main-use-case/material-package-item/middleware-runner.go create mode 100644 internal/use-case/main-use-case/material-package-item/middleware.go create mode 100644 internal/use-case/main-use-case/material-package-item/tycovar.go diff --git a/internal/domain/main-entities/material-package-item/dto.go b/internal/domain/main-entities/material-package-item/dto.go index a9b11be6..fd282873 100644 --- a/internal/domain/main-entities/material-package-item/dto.go +++ b/internal/domain/main-entities/material-package-item/dto.go @@ -8,18 +8,19 @@ import ( type CreateDto struct { MaterialPackage_Code string `json:"materialPackage_code" validate:"maxLength=20"` - Material_Code string `json:"code" validate:"maxLength=20"` + Material_Code string `json:"material_code" validate:"maxLength=20"` } type ReadListDto struct { FilterDto Includes string `json:"includes"` Pagination ecore.Pagination + Sort string `json:"sort"` } type FilterDto struct { - MaterialPackage_Code string `json:"materialPackage-code"` - Material_Code string `json:"code"` + MaterialPackage_Code string `json:"material-package-code"` + Material_Code string `json:"material_code"` } type ReadDetailDto struct { @@ -45,7 +46,7 @@ type ResponseDto struct { ecore.Main MaterialPackage_Code string `json:"materialPackage_code"` MaterialPackage *emp.MaterialPackage `json:"materialPackage,omitempty"` - Material_Code string `json:"code"` + Material_Code string `json:"material_code"` Material *em.Material `json:"material,omitempty"` } diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 31b238ac..8444aafc 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -94,6 +94,7 @@ import ( language "simrs-vx/internal/interface/main-handler/language" material "simrs-vx/internal/interface/main-handler/material" materialpackage "simrs-vx/internal/interface/main-handler/material-package" + materialpackageitem "simrs-vx/internal/interface/main-handler/material-package-item" mcusrc "simrs-vx/internal/interface/main-handler/mcu-src" mcusrccategory "simrs-vx/internal/interface/main-handler/mcu-src-category" mcusubsrc "simrs-vx/internal/interface/main-handler/mcu-sub-src" @@ -372,6 +373,7 @@ func SetRoutes() http.Handler { hc.RegCrudByCode(r, "/v1/device", device.O) hc.RegCrudByCode(r, "/v1/material", material.O) hc.RegCrudByCode(r, "/v1/material-package", materialpackage.O) + hc.RegCrud(r, "/v1/material-package-item", materialpackageitem.O) hc.RegCrud(r, "/v1/doctor-fee", doctorfee.O) hc.RegCrudByCode(r, "/v1/medical-action-src", medicalactionsrc.O) hc.RegCrud(r, "/v1/medical-action-src-item", medicalactionsrcitem.O) diff --git a/internal/interface/main-handler/material-package-item/handler.go b/internal/interface/main-handler/material-package-item/handler.go new file mode 100644 index 00000000..11deb6d9 --- /dev/null +++ b/internal/interface/main-handler/material-package-item/handler.go @@ -0,0 +1,71 @@ +package material + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/material-package-item" + u "simrs-vx/internal/use-case/main-use-case/material-package-item" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id == 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id == 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint(id) + 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/use-case/main-use-case/material-package-item/case.go b/internal/use-case/main-use-case/material-package-item/case.go new file mode 100644 index 00000000..ecd891a6 --- /dev/null +++ b/internal/use-case/main-use-case/material-package-item/case.go @@ -0,0 +1,276 @@ +package materialpackageorder + +import ( + e "simrs-vx/internal/domain/main-entities/material-package-item" + "strconv" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "material" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.MaterialPackageItem{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.MaterialPackageItem + var dataList []e.MaterialPackageItem + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.MaterialPackageItem + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.MaterialPackageItem + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.MaterialPackageItem + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/material-package-item/helper.go b/internal/use-case/main-use-case/material-package-item/helper.go new file mode 100644 index 00000000..c175f776 --- /dev/null +++ b/internal/use-case/main-use-case/material-package-item/helper.go @@ -0,0 +1,22 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package materialpackageorder + +import ( + e "simrs-vx/internal/domain/main-entities/material-package-item" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.MaterialPackageItem) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.MaterialPackage_Code = inputSrc.MaterialPackage_Code + data.Material_Code = inputSrc.Material_Code +} diff --git a/internal/use-case/main-use-case/material-package-item/lib.go b/internal/use-case/main-use-case/material-package-item/lib.go new file mode 100644 index 00000000..fc469249 --- /dev/null +++ b/internal/use-case/main-use-case/material-package-item/lib.go @@ -0,0 +1,140 @@ +package materialpackageorder + +import ( + e "simrs-vx/internal/domain/main-entities/material-package-item" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.MaterialPackageItem, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.MaterialPackageItem{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.MaterialPackageItem, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.MaterialPackageItem{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.MaterialPackageItem{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.MaterialPackageItem, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.MaterialPackageItem{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.First(&data, input.Id).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.MaterialPackageItem, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.MaterialPackageItem, 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 +} diff --git a/internal/use-case/main-use-case/material-package-item/middleware-runner.go b/internal/use-case/main-use-case/material-package-item/middleware-runner.go new file mode 100644 index 00000000..09dfb39b --- /dev/null +++ b/internal/use-case/main-use-case/material-package-item/middleware-runner.go @@ -0,0 +1,103 @@ +package materialpackageorder + +import ( + e "simrs-vx/internal/domain/main-entities/material-package-item" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.MaterialPackageItem) 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.MaterialPackageItem) 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.MaterialPackageItem) 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.MaterialPackageItem) 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.MaterialPackageItem) 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/main-use-case/material-package-item/middleware.go b/internal/use-case/main-use-case/material-package-item/middleware.go new file mode 100644 index 00000000..1d1186af --- /dev/null +++ b/internal/use-case/main-use-case/material-package-item/middleware.go @@ -0,0 +1,9 @@ +package materialpackageorder + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/material-package-item/tycovar.go b/internal/use-case/main-use-case/material-package-item/tycovar.go new file mode 100644 index 00000000..a7e239f1 --- /dev/null +++ b/internal/use-case/main-use-case/material-package-item/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 materialpackageorder + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/material-package-item" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.MaterialPackageItem, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.MaterialPackageItem, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.MaterialPackageItem, 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 From aa79933dd91ff7a3594e39e4214dc333e12f2f91 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Tue, 2 Dec 2025 23:09:26 +0700 Subject: [PATCH 310/329] feat/order-things: adjust procedure-room order --- cmd/main-migration/migrations/20251202160848.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 5 +++-- .../domain/main-entities/procedure-room-order/entity.go | 9 ++++++--- 3 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 cmd/main-migration/migrations/20251202160848.sql diff --git a/cmd/main-migration/migrations/20251202160848.sql b/cmd/main-migration/migrations/20251202160848.sql new file mode 100644 index 00000000..8d77fe04 --- /dev/null +++ b/cmd/main-migration/migrations/20251202160848.sql @@ -0,0 +1,2 @@ +-- Modify "ProcedureRoomOrder" table +ALTER TABLE "public"."ProcedureRoomOrder" ADD COLUMN "MaterialPackage_Code" character varying(20) NULL, ADD CONSTRAINT "fk_ProcedureRoomOrder_MaterialPackage" FOREIGN KEY ("MaterialPackage_Code") REFERENCES "public"."MaterialPackage" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 54858b7b..d7d84cc6 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:cyae1SX3YSMX1LZLEsCFxcRKbVxpnp46BqFxWXJqKjs= +h1:Gt8/vjlUshOzs/MWOnRZfDnDn2lrMZE4rcVk5k41R+Y= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -140,4 +140,5 @@ h1:cyae1SX3YSMX1LZLEsCFxcRKbVxpnp46BqFxWXJqKjs= 20251202030445.sql h1:QWBVfTepT7DaXP5E0BYoxNM0JwKIQ2qIMXzI4kbz/qE= 20251202044430.sql h1:4QZH9lz0GrQ9rzP1AJ+hJgGalNpp+8FCRckNK7xaTbU= 20251202064000.sql h1:/EN7sT1ol/91qW1aXWrzX+Mc3XOC/7f/LtfA0JRHpbg= -20251202130629.sql h1:LjBgQS8tKEwpC3WA0wGeO2Fs2L20kEOB6e5ljO4EdLM= +20251202130629.sql h1:9mvalqfhqGCdkcJepJDzHprU2xb0i5sYys1Htf62ioo= +20251202160848.sql h1:TTy6DM7FI2+AyxY7mAFDEYVHE0484WKreRM4898rvOk= diff --git a/internal/domain/main-entities/procedure-room-order/entity.go b/internal/domain/main-entities/procedure-room-order/entity.go index 7e453410..c0fb846e 100644 --- a/internal/domain/main-entities/procedure-room-order/entity.go +++ b/internal/domain/main-entities/procedure-room-order/entity.go @@ -2,12 +2,15 @@ package procedureroomorder import ( ecore "simrs-vx/internal/domain/base-entities/core" + emp "simrs-vx/internal/domain/main-entities/material-package" epr "simrs-vx/internal/domain/main-entities/procedure-room" ) type ProcedureRoomOrder struct { ecore.Main - Encounter_Id uint64 `json:"encounter_id"` - Infra_Code string `json:"infra_code" gorm:"size:20"` - ProcedureRoom *epr.ProcedureRoom `json:"procedureRoom,omitempty" gorm:"foreignKey:Infra_Code;references:Code"` + Encounter_Id uint64 `json:"encounter_id"` + Infra_Code string `json:"infra_code" gorm:"size:20"` + ProcedureRoom *epr.ProcedureRoom `json:"procedureRoom,omitempty" gorm:"foreignKey:Infra_Code;references:Code"` + MaterialPackage_Code string `json:"materialPackageCode" gorm:"size:20"` + MaterialPackage *emp.MaterialPackage `json:"materialPackage,omitempty" gorm:"foreignKey:MaterialPackage_Code;references:Code"` } From cbff83e4dec35eca226e48a5adfae21334a43fe4 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Tue, 2 Dec 2025 23:14:53 +0700 Subject: [PATCH 311/329] feat/other-things: adjust const --- cmd/main-migration/migrations/atlas.sum | 4 ++-- internal/domain/references/organization/organization.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index d7d84cc6..72d356db 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:Gt8/vjlUshOzs/MWOnRZfDnDn2lrMZE4rcVk5k41R+Y= +h1:2q1xxtaiHIoZtVnG80kXG6u4BZVgy44lTmW3zd6freo= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -141,4 +141,4 @@ h1:Gt8/vjlUshOzs/MWOnRZfDnDn2lrMZE4rcVk5k41R+Y= 20251202044430.sql h1:4QZH9lz0GrQ9rzP1AJ+hJgGalNpp+8FCRckNK7xaTbU= 20251202064000.sql h1:/EN7sT1ol/91qW1aXWrzX+Mc3XOC/7f/LtfA0JRHpbg= 20251202130629.sql h1:9mvalqfhqGCdkcJepJDzHprU2xb0i5sYys1Htf62ioo= -20251202160848.sql h1:TTy6DM7FI2+AyxY7mAFDEYVHE0484WKreRM4898rvOk= +20251202160848.sql h1:Kd2/TziKSMezrt4XgbjQcYvY/Lo9rX0qw7/Lz0/oyKk= diff --git a/internal/domain/references/organization/organization.go b/internal/domain/references/organization/organization.go index 0647f88f..d20b828e 100644 --- a/internal/domain/references/organization/organization.go +++ b/internal/domain/references/organization/organization.go @@ -54,8 +54,8 @@ const ( IFGCCounter InfraGroupCode = "counter" // Counter IFGCPubScreen InfraGroupCode = "public-screen" // Public Screen - PRTLight ProdcedureRoomTypeCode = "light" // Ringan - PRTSurgery ProdcedureRoomTypeCode = "roomed" // Dikamarkan + PRTCProcedure ProdcedureRoomTypeCode = "procedure" // Ringan + PRTCOperating ProdcedureRoomTypeCode = "operating" // Dikamarkan UTCReg UnitTypeCode = "reg" // Registrasi UTCExa UnitTypeCode = "exa" // Pemeriksaan From aa5a3d898a9f7367e94163ad71bc0fa03c8013fc Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Tue, 2 Dec 2025 23:47:15 +0700 Subject: [PATCH 312/329] feat/order-things: adjust structure + tags --- .../migrations/20251202180207.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 3 ++- internal/domain/main-entities/infra/dto.go | 20 +++++++++---------- internal/domain/main-entities/infra/entity.go | 20 +++++++++---------- .../procedure-room-order/entity.go | 5 ++++- 5 files changed, 28 insertions(+), 22 deletions(-) create mode 100644 cmd/main-migration/migrations/20251202180207.sql diff --git a/cmd/main-migration/migrations/20251202180207.sql b/cmd/main-migration/migrations/20251202180207.sql new file mode 100644 index 00000000..32c5b1dc --- /dev/null +++ b/cmd/main-migration/migrations/20251202180207.sql @@ -0,0 +1,2 @@ +-- Modify "ProcedureRoomOrder" table +ALTER TABLE "public"."ProcedureRoomOrder" ADD COLUMN "Status_Code" character varying(20) NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 72d356db..26c2bca0 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:2q1xxtaiHIoZtVnG80kXG6u4BZVgy44lTmW3zd6freo= +h1:fDxiVQJUurcI/J078Wz7tEKkfNwnI92Cs75Z34Eo9ZQ= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -142,3 +142,4 @@ h1:2q1xxtaiHIoZtVnG80kXG6u4BZVgy44lTmW3zd6freo= 20251202064000.sql h1:/EN7sT1ol/91qW1aXWrzX+Mc3XOC/7f/LtfA0JRHpbg= 20251202130629.sql h1:9mvalqfhqGCdkcJepJDzHprU2xb0i5sYys1Htf62ioo= 20251202160848.sql h1:Kd2/TziKSMezrt4XgbjQcYvY/Lo9rX0qw7/Lz0/oyKk= +20251202180207.sql h1:5WXemmJfgaV3BPuciiDhstKjjhSRCCxIxuPB8c7nc74= diff --git a/internal/domain/main-entities/infra/dto.go b/internal/domain/main-entities/infra/dto.go index f5cf5444..63c5d4a4 100644 --- a/internal/domain/main-entities/infra/dto.go +++ b/internal/domain/main-entities/infra/dto.go @@ -32,7 +32,7 @@ type ReadListDto struct { type FilterDto struct { Code string `json:"code"` Name string `json:"name"` - InfraGroup_Code ero.InfraGroupCode `json:"infraGroup-code"` + InfraGroup_Code ero.InfraGroupCode `json:"infra-group-code"` Parent_Code *string `json:"parent-code"` Item_Id *string `json:"item-code"` Search string `json:"search" gormhelper:"searchColumns=Code,Name"` @@ -62,15 +62,15 @@ type MetaDto struct { type ResponseDto struct { ecore.SmallMain - Code string `json:"code"` - Name string `json:"name"` - InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code"` - Parent_Code *string `json:"parent_code"` - Parent *Infra `json:"parent,omitempty"` - Childrens []Infra `json:"childrens,omitempty"` - Item_Code *string `json:"item_code"` - Item *ei.Item `json:"item,omitempty"` - ProcedureRooms []erb.ProcedureRoom `json:"rooms,omitempty"` + Code string `json:"code"` + Name string `json:"name"` + InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code"` + Parent_Code *string `json:"parent_code"` + Parent *Infra `json:"parent,omitempty"` + Childrens []Infra `json:"childrens,omitempty"` + Item_Code *string `json:"item_code"` + Item *ei.Item `json:"item,omitempty"` + ProcedureRooms *erb.ProcedureRoom `json:"rooms,omitempty"` } func (d Infra) ToResponse() ResponseDto { diff --git a/internal/domain/main-entities/infra/entity.go b/internal/domain/main-entities/infra/entity.go index 8fe5cb52..b9840db4 100644 --- a/internal/domain/main-entities/infra/entity.go +++ b/internal/domain/main-entities/infra/entity.go @@ -10,14 +10,14 @@ import ( ) type Infra struct { - ecore.SmallMain // adjust this according to the needs - Code string `json:"code" gorm:"uniqueIndex;size:20;not null"` - Name string `json:"name" gorm:"size:50"` - InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code" gorm:"size:20"` - Parent_Code *string `json:"parent_code" gorm:"size:20"` - Parent *Infra `json:"parent" gorm:"foreignKey:Parent_Code;references:Code"` - Childrens []Infra `json:"childrens" gorm:"foreignKey:Parent_Code;references:Code"` - Item_Code *string `json:"item_code" gorm:"size:50"` - Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Code;references:Code"` - ProcedureRooms []erb.ProcedureRoom `json:"rooms" gorm:"foreignKey:Infra_Code;references:Code"` + ecore.SmallMain // adjust this according to the needs + Code string `json:"code" gorm:"uniqueIndex;size:20;not null"` + Name string `json:"name" gorm:"size:50"` + InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code" gorm:"size:20"` + Parent_Code *string `json:"parent_code" gorm:"size:20"` + Parent *Infra `json:"parent" gorm:"foreignKey:Parent_Code;references:Code"` + Childrens []Infra `json:"childrens" gorm:"foreignKey:Parent_Code;references:Code"` + Item_Code *string `json:"item_code" gorm:"size:50"` + Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Code;references:Code"` + ProcedureRooms *erb.ProcedureRoom `json:"rooms" gorm:"foreignKey:Infra_Code;references:Code"` } diff --git a/internal/domain/main-entities/procedure-room-order/entity.go b/internal/domain/main-entities/procedure-room-order/entity.go index c0fb846e..7cb79120 100644 --- a/internal/domain/main-entities/procedure-room-order/entity.go +++ b/internal/domain/main-entities/procedure-room-order/entity.go @@ -1,6 +1,8 @@ package procedureroomorder import ( + erc "simrs-vx/internal/domain/references/common" + ecore "simrs-vx/internal/domain/base-entities/core" emp "simrs-vx/internal/domain/main-entities/material-package" epr "simrs-vx/internal/domain/main-entities/procedure-room" @@ -11,6 +13,7 @@ type ProcedureRoomOrder struct { Encounter_Id uint64 `json:"encounter_id"` Infra_Code string `json:"infra_code" gorm:"size:20"` ProcedureRoom *epr.ProcedureRoom `json:"procedureRoom,omitempty" gorm:"foreignKey:Infra_Code;references:Code"` - MaterialPackage_Code string `json:"materialPackageCode" gorm:"size:20"` + MaterialPackage_Code string `json:"materialPackage_code" gorm:"size:20"` MaterialPackage *emp.MaterialPackage `json:"materialPackage,omitempty" gorm:"foreignKey:MaterialPackage_Code;references:Code"` + Status_Code erc.DataStatusCode `json:"status_code" gorm:"size:20"` } From 9b8110f8fa95375254d49c83af1bf42cef9e96d0 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Wed, 3 Dec 2025 06:06:56 +0700 Subject: [PATCH 313/329] feat/order-things: entities adjustment --- .../material-package-item/dto.go | 3 + .../material-package-item/entity.go | 1 + .../procedure-room-order-item/dto.go | 68 +++++++++++++++++++ .../procedure-room-order-item/entity.go | 14 ++++ .../main-entities/procedure-room-order/dto.go | 38 ++++++----- .../procedure-room-order/entity.go | 2 +- 6 files changed, 108 insertions(+), 18 deletions(-) create mode 100644 internal/domain/main-entities/procedure-room-order-item/dto.go create mode 100644 internal/domain/main-entities/procedure-room-order-item/entity.go diff --git a/internal/domain/main-entities/material-package-item/dto.go b/internal/domain/main-entities/material-package-item/dto.go index fd282873..e642a015 100644 --- a/internal/domain/main-entities/material-package-item/dto.go +++ b/internal/domain/main-entities/material-package-item/dto.go @@ -9,6 +9,7 @@ import ( type CreateDto struct { MaterialPackage_Code string `json:"materialPackage_code" validate:"maxLength=20"` Material_Code string `json:"material_code" validate:"maxLength=20"` + Count uint16 `json:"count" validate:"required"` } type ReadListDto struct { @@ -48,6 +49,7 @@ type ResponseDto struct { MaterialPackage *emp.MaterialPackage `json:"materialPackage,omitempty"` Material_Code string `json:"material_code"` Material *em.Material `json:"material,omitempty"` + Count uint16 `json:"count"` } func (d MaterialPackageItem) ToResponse() ResponseDto { @@ -56,6 +58,7 @@ func (d MaterialPackageItem) ToResponse() ResponseDto { MaterialPackage: d.MaterialPackage, Material_Code: d.Material_Code, Material: d.Material, + Count: d.Count, } resp.Id = d.Id return resp diff --git a/internal/domain/main-entities/material-package-item/entity.go b/internal/domain/main-entities/material-package-item/entity.go index 76378dc8..52960935 100644 --- a/internal/domain/main-entities/material-package-item/entity.go +++ b/internal/domain/main-entities/material-package-item/entity.go @@ -12,4 +12,5 @@ type MaterialPackageItem struct { MaterialPackage *emp.MaterialPackage `json:"materialPackage" gorm:"foreignKey:MaterialPackage_Code;references:Code"` Material_Code string `json:"code" gorm:"size:20;not null"` Material *em.Material `json:"material" gorm:"foreignKey:Material_Code;references:Code"` + Count uint16 `json:"count" gorm:"not null"` } diff --git a/internal/domain/main-entities/procedure-room-order-item/dto.go b/internal/domain/main-entities/procedure-room-order-item/dto.go new file mode 100644 index 00000000..4e01fea9 --- /dev/null +++ b/internal/domain/main-entities/procedure-room-order-item/dto.go @@ -0,0 +1,68 @@ +package procedureroomorder + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + epr "simrs-vx/internal/domain/main-entities/procedure-room" +) + +type CreateDto struct { + Encounter_Id uint64 `json:"encounter_id" validate:"required"` + Infra_Code string `json:"infra_code" validate:"required"` + MaterialPackage_Code string `json:"materialPackage_code" validate:"required"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Encounter_Id uint64 `json:"encounter-id"` +} + +type ReadDetailDto struct { + Id uint64 `json:"id"` +} + +type UpdateDto struct { + Id uint64 `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint64 `json:"id"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.BigMain + ProcedureRoomOrder_Id uint64 `json:"procedureRoomOrder_id"` + ProcedureRoom_Code string `json:"procedureRoom_code"` + ProcedureRoom *epr.ProcedureRoom `json:"procedureRoom,omitempty"` + Note string `json:"note"` +} + +func (d ProcedureRoomOrderItem) ToResponse() ResponseDto { + resp := ResponseDto{ + ProcedureRoomOrder_Id: d.ProcedureRoomOrder_Id, + ProcedureRoom_Code: d.ProcedureRoom_Code, + ProcedureRoom: d.ProcedureRoom, + Note: d.Note, + } + resp.Id = d.Id + return resp +} + +func ToResponseList(data []ProcedureRoomOrderItem) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/procedure-room-order-item/entity.go b/internal/domain/main-entities/procedure-room-order-item/entity.go new file mode 100644 index 00000000..4a737048 --- /dev/null +++ b/internal/domain/main-entities/procedure-room-order-item/entity.go @@ -0,0 +1,14 @@ +package procedureroomorder + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + epr "simrs-vx/internal/domain/main-entities/procedure-room" +) + +type ProcedureRoomOrderItem struct { + ecore.BigMain + ProcedureRoomOrder_Id uint64 `json:"procedureRoomOrder_id"` + ProcedureRoom_Code string `json:"procedureRoom_code" gorm:"size:20"` + ProcedureRoom *epr.ProcedureRoom `json:"procedureRoom,omitempty" gorm:"foreignKey:ProcedureRoom_Code;references:Code"` + Note string `json:"note" gorm:"size:255"` +} diff --git a/internal/domain/main-entities/procedure-room-order/dto.go b/internal/domain/main-entities/procedure-room-order/dto.go index d202f031..5810e756 100644 --- a/internal/domain/main-entities/procedure-room-order/dto.go +++ b/internal/domain/main-entities/procedure-room-order/dto.go @@ -3,13 +3,15 @@ package procedureroomorder import ( ecore "simrs-vx/internal/domain/base-entities/core" ec "simrs-vx/internal/domain/main-entities/encounter" + emp "simrs-vx/internal/domain/main-entities/material-package" epr "simrs-vx/internal/domain/main-entities/procedure-room" + erc "simrs-vx/internal/domain/references/common" ) type CreateDto struct { - Encounter_Id uint64 `json:"encounter_id"` - Infra_Code string `json:"procedure"` - ProcedureRoom string `json:"procedureRoom"` + Encounter_Id uint64 `json:"encounter_id" validate:"required"` + Infra_Code string `json:"infra_code" validate:"required"` + MaterialPackage_Code string `json:"materialPackage_code" validate:"required"` } type ReadListDto struct { @@ -19,22 +21,20 @@ type ReadListDto struct { } type FilterDto struct { - Encounter_Id uint64 `json:"encounter-id"` - Infra_Code string `json:"procedure-code"` - ProcedureRoom string `json:"procedure-room"` + Encounter_Id uint64 `json:"encounter-id"` } type ReadDetailDto struct { - Id uint `json:"id"` + Id uint64 `json:"id"` } type UpdateDto struct { - Id uint `json:"id"` + Id uint64 `json:"id"` CreateDto } type DeleteDto struct { - Id uint `json:"id"` + Id uint64 `json:"id"` } type MetaDto struct { @@ -44,18 +44,22 @@ type MetaDto struct { } type ResponseDto struct { - ecore.Main - Encounter_Id uint64 `json:"encounter_id"` - Encounter *ec.Encounter `json:"encounter,omitempty"` - Infra_Code string `json:"procedure"` - ProcedureRoom *epr.ProcedureRoom `json:"procedureRoom,omitempty"` + ecore.BigMain + Encounter_Id uint64 `json:"encounter_id"` + Encounter *ec.Encounter `json:"encounter,omitempty"` + Infra_Code string `json:"procedure"` + MaterialPackage_Code string `json:"materialPackage_code"` + Status_Code erc.DataStatusCode `json:"status_code"` + ProcedureRoom *epr.ProcedureRoom `json:"procedureRoom,omitempty"` + MaterialPackage *emp.MaterialPackage `json:"materialPackage,omitempty"` } func (d ProcedureRoomOrder) ToResponse() ResponseDto { resp := ResponseDto{ - Encounter_Id: d.Encounter_Id, - Infra_Code: d.Infra_Code, - // ProcedureRoom: d.ProcedureRoom, + Encounter_Id: d.Encounter_Id, + Infra_Code: d.Infra_Code, + MaterialPackage_Code: d.MaterialPackage_Code, + Status_Code: d.Status_Code, } resp.Id = d.Id return resp diff --git a/internal/domain/main-entities/procedure-room-order/entity.go b/internal/domain/main-entities/procedure-room-order/entity.go index 7cb79120..1ef7c178 100644 --- a/internal/domain/main-entities/procedure-room-order/entity.go +++ b/internal/domain/main-entities/procedure-room-order/entity.go @@ -9,7 +9,7 @@ import ( ) type ProcedureRoomOrder struct { - ecore.Main + ecore.BigMain Encounter_Id uint64 `json:"encounter_id"` Infra_Code string `json:"infra_code" gorm:"size:20"` ProcedureRoom *epr.ProcedureRoom `json:"procedureRoom,omitempty" gorm:"foreignKey:Infra_Code;references:Code"` From fd338d59fb2bc96f04461596488c9e0199136f08 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Wed, 3 Dec 2025 08:34:44 +0700 Subject: [PATCH 314/329] feat/order-things: added flows + procedure-room-order + procedure-room-order-item --- .../interface/main-handler/main-handler.go | 4 + .../procedure-room-order-item/handler.go | 71 +++++ .../procedure-room-order/handler.go | 71 +++++ .../procedure-room-order-item/case.go | 276 ++++++++++++++++++ .../procedure-room-order-item/helper.go | 23 ++ .../procedure-room-order-item/lib.go | 151 ++++++++++ .../middleware-runner.go | 103 +++++++ .../procedure-room-order-item/middleware.go | 9 + .../procedure-room-order-item/tycovar.go | 44 +++ .../procedure-room-order/case.go | 276 ++++++++++++++++++ .../procedure-room-order/helper.go | 25 ++ .../main-use-case/procedure-room-order/lib.go | 140 +++++++++ .../procedure-room-order/middleware-runner.go | 103 +++++++ .../procedure-room-order/middleware.go | 9 + .../procedure-room-order/tycovar.go | 44 +++ 15 files changed, 1349 insertions(+) create mode 100644 internal/interface/main-handler/procedure-room-order-item/handler.go create mode 100644 internal/interface/main-handler/procedure-room-order/handler.go create mode 100644 internal/use-case/main-use-case/procedure-room-order-item/case.go create mode 100644 internal/use-case/main-use-case/procedure-room-order-item/helper.go create mode 100644 internal/use-case/main-use-case/procedure-room-order-item/lib.go create mode 100644 internal/use-case/main-use-case/procedure-room-order-item/middleware-runner.go create mode 100644 internal/use-case/main-use-case/procedure-room-order-item/middleware.go create mode 100644 internal/use-case/main-use-case/procedure-room-order-item/tycovar.go create mode 100644 internal/use-case/main-use-case/procedure-room-order/case.go create mode 100644 internal/use-case/main-use-case/procedure-room-order/helper.go create mode 100644 internal/use-case/main-use-case/procedure-room-order/lib.go create mode 100644 internal/use-case/main-use-case/procedure-room-order/middleware-runner.go create mode 100644 internal/use-case/main-use-case/procedure-room-order/middleware.go create mode 100644 internal/use-case/main-use-case/procedure-room-order/tycovar.go diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 8444aafc..d7c482e0 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -34,6 +34,8 @@ import ( practiceschedule "simrs-vx/internal/interface/main-handler/practice-schedule" prescription "simrs-vx/internal/interface/main-handler/prescription" prescriptionitem "simrs-vx/internal/interface/main-handler/prescription-item" + procedureroomorder "simrs-vx/internal/interface/main-handler/procedure-room-order" + procedureroomorderitem "simrs-vx/internal/interface/main-handler/procedure-room-order-item" responsibledoctorhist "simrs-vx/internal/interface/main-handler/responsible-doctor-hist" resume "simrs-vx/internal/interface/main-handler/resume" sbar "simrs-vx/internal/interface/main-handler/sbar" @@ -269,6 +271,8 @@ func SetRoutes() http.Handler { "DELETE /{id}": materialorder.O.Delete, "PATCH /{id}/complete": materialorder.O.Complete, }) + hc.RegCrud(r, "/v1/procedure-room-order", procedureroomorder.O) + hc.RegCrud(r, "/v1/procedure-room-order-item", procedureroomorderitem.O) hk.GroupRoutes("/v1/consultation", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": consultation.O.GetList, "GET /{id}": consultation.O.GetDetail, diff --git a/internal/interface/main-handler/procedure-room-order-item/handler.go b/internal/interface/main-handler/procedure-room-order-item/handler.go new file mode 100644 index 00000000..0caed63d --- /dev/null +++ b/internal/interface/main-handler/procedure-room-order-item/handler.go @@ -0,0 +1,71 @@ +package procedureroomorder + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/procedure-room-order-item" + u "simrs-vx/internal/use-case/main-use-case/procedure-room-order-item" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id == 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint64(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id == 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint64(id) + 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 = uint64(id) + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/procedure-room-order/handler.go b/internal/interface/main-handler/procedure-room-order/handler.go new file mode 100644 index 00000000..e50247a1 --- /dev/null +++ b/internal/interface/main-handler/procedure-room-order/handler.go @@ -0,0 +1,71 @@ +package procedureroomorder + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/procedure-room-order" + u "simrs-vx/internal/use-case/main-use-case/procedure-room-order" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id == 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint64(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id == 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint64(id) + 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 = uint64(id) + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/use-case/main-use-case/procedure-room-order-item/case.go b/internal/use-case/main-use-case/procedure-room-order-item/case.go new file mode 100644 index 00000000..3351c737 --- /dev/null +++ b/internal/use-case/main-use-case/procedure-room-order-item/case.go @@ -0,0 +1,276 @@ +package procedureroomorderitem + +import ( + e "simrs-vx/internal/domain/main-entities/procedure-room-order-item" + "strconv" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "procedure-room-order-item" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.ProcedureRoomOrderItem{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.ProcedureRoomOrderItem + var dataList []e.ProcedureRoomOrderItem + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.ProcedureRoomOrderItem + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.ProcedureRoomOrderItem + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.ProcedureRoomOrderItem + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/procedure-room-order-item/helper.go b/internal/use-case/main-use-case/procedure-room-order-item/helper.go new file mode 100644 index 00000000..b7ca1a4f --- /dev/null +++ b/internal/use-case/main-use-case/procedure-room-order-item/helper.go @@ -0,0 +1,23 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package procedureroomorderitem + +import ( + e "simrs-vx/internal/domain/main-entities/procedure-room-order-item" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.ProcedureRoomOrderItem) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.ProcedureRoomOrder_Id = inputSrc.ProcedureRoomOrder_Id + data.ProcedureRoom_Code = inputSrc.ProcedureRoom_Code + data.Note = inputSrc.Note +} diff --git a/internal/use-case/main-use-case/procedure-room-order-item/lib.go b/internal/use-case/main-use-case/procedure-room-order-item/lib.go new file mode 100644 index 00000000..d5dd8b05 --- /dev/null +++ b/internal/use-case/main-use-case/procedure-room-order-item/lib.go @@ -0,0 +1,151 @@ +package procedureroomorderitem + +import ( + e "simrs-vx/internal/domain/main-entities/procedure-room-order-item" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.ProcedureRoomOrderItem, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + deletedData := e.ProcedureRoomOrderItem{} + tx.Unscoped(). + Where("\"ProcedureRoomOrder_Id\" = ? AND \"ProcedureRoom_Code\" = ?", input.ProcedureRoomOrder_Id, input.ProcedureRoom_Code). + First(&deletedData) + if deletedData.Id != 0 { + if err := tx.Unscoped().Model(e.ProcedureRoomOrderItem{}).Where("\"Id\" = ?", deletedData.Id).Update("\"DeletedAt\"", nil).Error; err != nil { + return nil, plh.HandleCreateError(input, event, err) + } + return &deletedData, nil + } + + data := e.ProcedureRoomOrderItem{} + setData(&input, &data) + + if err := tx.Create(&data).Error; err != nil { + return nil, plh.HandleCreateError(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.ProcedureRoomOrderItem, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.ProcedureRoomOrderItem{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.ProcedureRoomOrderItem{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Order("\"CreatedAt\" DESC") + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.ProcedureRoomOrderItem, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.ProcedureRoomOrderItem{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.ProcedureRoomOrderItem, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.ProcedureRoomOrderItem, 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 +} diff --git a/internal/use-case/main-use-case/procedure-room-order-item/middleware-runner.go b/internal/use-case/main-use-case/procedure-room-order-item/middleware-runner.go new file mode 100644 index 00000000..f0edfe87 --- /dev/null +++ b/internal/use-case/main-use-case/procedure-room-order-item/middleware-runner.go @@ -0,0 +1,103 @@ +package procedureroomorderitem + +import ( + e "simrs-vx/internal/domain/main-entities/procedure-room-order-item" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.ProcedureRoomOrderItem) 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.ProcedureRoomOrderItem) 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.ProcedureRoomOrderItem) 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.ProcedureRoomOrderItem) 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.ProcedureRoomOrderItem) 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/main-use-case/procedure-room-order-item/middleware.go b/internal/use-case/main-use-case/procedure-room-order-item/middleware.go new file mode 100644 index 00000000..0d6c70f7 --- /dev/null +++ b/internal/use-case/main-use-case/procedure-room-order-item/middleware.go @@ -0,0 +1,9 @@ +package procedureroomorderitem + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/procedure-room-order-item/tycovar.go b/internal/use-case/main-use-case/procedure-room-order-item/tycovar.go new file mode 100644 index 00000000..bcc4bf17 --- /dev/null +++ b/internal/use-case/main-use-case/procedure-room-order-item/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 procedureroomorderitem + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/procedure-room-order-item" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.ProcedureRoomOrderItem, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.ProcedureRoomOrderItem, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.ProcedureRoomOrderItem, 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/main-use-case/procedure-room-order/case.go b/internal/use-case/main-use-case/procedure-room-order/case.go new file mode 100644 index 00000000..0724ce94 --- /dev/null +++ b/internal/use-case/main-use-case/procedure-room-order/case.go @@ -0,0 +1,276 @@ +package procedureroomorder + +import ( + e "simrs-vx/internal/domain/main-entities/procedure-room-order" + "strconv" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "procedure-room-order" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.ProcedureRoomOrder{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.ProcedureRoomOrder + var dataList []e.ProcedureRoomOrder + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.ProcedureRoomOrder + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.ProcedureRoomOrder + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.ProcedureRoomOrder + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + 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 { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/procedure-room-order/helper.go b/internal/use-case/main-use-case/procedure-room-order/helper.go new file mode 100644 index 00000000..6e91b7e3 --- /dev/null +++ b/internal/use-case/main-use-case/procedure-room-order/helper.go @@ -0,0 +1,25 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package procedureroomorder + +import ( + e "simrs-vx/internal/domain/main-entities/procedure-room-order" + erc "simrs-vx/internal/domain/references/common" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.ProcedureRoomOrder) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Encounter_Id = inputSrc.Encounter_Id + data.Infra_Code = inputSrc.Infra_Code + data.MaterialPackage_Code = inputSrc.MaterialPackage_Code + data.Status_Code = erc.DSCNew +} diff --git a/internal/use-case/main-use-case/procedure-room-order/lib.go b/internal/use-case/main-use-case/procedure-room-order/lib.go new file mode 100644 index 00000000..50775d7c --- /dev/null +++ b/internal/use-case/main-use-case/procedure-room-order/lib.go @@ -0,0 +1,140 @@ +package procedureroomorder + +import ( + e "simrs-vx/internal/domain/main-entities/procedure-room-order" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.ProcedureRoomOrder, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.ProcedureRoomOrder{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.ProcedureRoomOrder, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.ProcedureRoomOrder{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.ProcedureRoomOrder{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Order("\"CreatedAt\" DESC") + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.ProcedureRoomOrder, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.ProcedureRoomOrder{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.First(&data, input.Id).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.ProcedureRoomOrder, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.ProcedureRoomOrder, 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 +} diff --git a/internal/use-case/main-use-case/procedure-room-order/middleware-runner.go b/internal/use-case/main-use-case/procedure-room-order/middleware-runner.go new file mode 100644 index 00000000..0fb20eaf --- /dev/null +++ b/internal/use-case/main-use-case/procedure-room-order/middleware-runner.go @@ -0,0 +1,103 @@ +package procedureroomorder + +import ( + e "simrs-vx/internal/domain/main-entities/procedure-room-order" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.ProcedureRoomOrder) 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.ProcedureRoomOrder) 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.ProcedureRoomOrder) 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.ProcedureRoomOrder) 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.ProcedureRoomOrder) 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/main-use-case/procedure-room-order/middleware.go b/internal/use-case/main-use-case/procedure-room-order/middleware.go new file mode 100644 index 00000000..cd9a687d --- /dev/null +++ b/internal/use-case/main-use-case/procedure-room-order/middleware.go @@ -0,0 +1,9 @@ +package procedureroomorder + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/procedure-room-order/tycovar.go b/internal/use-case/main-use-case/procedure-room-order/tycovar.go new file mode 100644 index 00000000..5113ce03 --- /dev/null +++ b/internal/use-case/main-use-case/procedure-room-order/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 procedureroomorder + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/procedure-room-order" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.ProcedureRoomOrder, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.ProcedureRoomOrder, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.ProcedureRoomOrder, 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 From 495549dcf1d4bacd9bfeebbc15f8cb06aac69eee Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Wed, 3 Dec 2025 08:41:44 +0700 Subject: [PATCH 315/329] feat/order-things: just refersh migration hash --- cmd/main-migration/migrations/atlas.sum | 136 ++++++++-------- cmd/main-migration/migrations/atlas.sumy | 198 ----------------------- 2 files changed, 70 insertions(+), 264 deletions(-) delete mode 100644 cmd/main-migration/migrations/atlas.sumy diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index f7e6e583..341a35d3 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:gwV43DB5Cr+YkOe2Y2ywd4ySwyrsK4y1yZ9nfSrSf7Q= +h1:DgMML95zGYI7JMvZaIb/gySCvncMu62CANOIXNX0A6w= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,68 +75,72 @@ h1:gwV43DB5Cr+YkOe2Y2ywd4ySwyrsK4y1yZ9nfSrSf7Q= 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= +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= diff --git a/cmd/main-migration/migrations/atlas.sumy b/cmd/main-migration/migrations/atlas.sumy deleted file mode 100644 index f215f997..00000000 --- a/cmd/main-migration/migrations/atlas.sumy +++ /dev/null @@ -1,198 +0,0 @@ -20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= -20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= -20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= -20250908062323.sql h1:oXl6Z143tOpIl4EfP4B8JNU8LrMvVmHEtCgAfiB4gs8= -20250908073811.sql h1:m2aNXfnGxnLq1+rVWrh4f60q7fhyhV3gEwNu/OIqQlE= -20250908073839.sql h1:cPk54xjLdMs26uY8ZHjNWLuyfAMzV7Zb0/9oJQrsw04= -20250910055902.sql h1:5xwjAV6QbtZT9empTJKfhyAjdknbHzb15B0Ku5dzqtQ= -20250915123412.sql h1:D83xaU2YlDEd21HLup/YQpQ2easMToYCyy/oK6AFgQs= -20250916043819.sql h1:ekoTJsBqQZ8G8n0qJ03d13+eoNoc7sAUEQGA5D/CCxk= -20250917040616.sql h1:zoCnmcXuM7AVv85SmN7RmFglCgJnoDmpRWExH0LAc9Q= -20250917040751.sql h1:J1xyRrh32y1+lezwAyNwPcUQ6ABBSgbvzNLva4SVdQU= -20250917045138.sql h1:jKe1Z0uOLG4SGBYM+S/3P+/zMPztmgoderD5swnMuCg= -20250917093645.sql h1:cNI3Pbz1R3LxvIXLuexafJFCXUXrmuFCgXXJ2sG+FW0= -20250918073552.sql h1:RJ1SvMzP6aeWnoPVD3eVAmIQOkcp6Php8z3QRri6v4g= -20250918073742.sql h1:+cEsnJTJFybe2fR69ZoOiX2R6c6iITl4m6WTZ1hjyzY= -20250918074745.sql h1:2hNVQCXF/dVYXAh+T/7oBFgERGWxzVb2FXJjwkFWGCI= -20250923025134.sql h1:Ykz/qpHiGDXPsCsWTjydQFVSibZP2D+h2fIeb2h2JGA= -20250924051317.sql h1:yQuW6SwJxIOM5fcxeAaie5lSm1oLysU/C2hH2xNCVoQ= -20250929034321.sql h1:101FJ8VH12mrZWlt/X1gvKUGOhoiF8tFbjiapAjnHzg= -20250929034428.sql h1:i+pROD9p+g5dOmmZma6WF/0Hw5g3Ha28NN85iTo1K34= -20250930025550.sql h1:+F+CsCUXD/ql0tHGEow70GhPBX1ZybVn+bh/T4YMh7Y= -20250930140351.sql h1:9AAEG1AnOAH+o0+oHL5G7I8vqlWOhwRlCGyyCpT/y1Q= -20251002085604.sql h1:3xZ68eYp4urXRnvotNH1XvG2mYOSDV/j3zHEZ/txg5E= -20251003032030.sql h1:HB+mQ2lXMNomHDpaRhB/9IwYI9/YiDO5eOJ+nAQH/jw= -20251005060450.sql h1:LbtCE2b+8osM3CvnmQJH1uCPtn+d7WchsslBOz8bL3Q= -20251006041122.sql h1:MlS7f21z06sutnf9dIekt5fuHJr4lgcQ4uCuCXAGsfc= -20251006045658.sql h1:3FmGCPCzjgMPdWDRodZTsx3KVaodd9zB9ilib69aewk= -20251006045928.sql h1:Z5g31PmnzNwk/OKdODcxZGm8fjJQdMFK32Xfnt3bRHg= -20251007022859.sql h1:FO03zEfaNEk/aXwY81d5Lp3MoBB9kPQuXlXJ4BPiSR8= -20251008031337.sql h1:l+sxUAGvcTfj3I6kAFHo+T6AYodC9k9GkR+jaKO2xXc= -20251008031554.sql h1:AqrVfIhSzY3PCy8ZlP5W91wn2iznfIuj5qQfubp6/94= -20251008052346.sql h1:nxnXmooIJ6r1mmzwnw+6efxLfc/k9h2aE6RMptPRons= -20251008073620.sql h1:6YsJp1W4SmQJ1lxpqF27BBlDC1zqhw7Yhc7pLzQTY6M= -20251009042854.sql h1:nkBV+R6j0fg7/JY6wH3eb5Vv0asJLnXmb6lINfT/GLQ= -20251009052657.sql h1:EPvdsib5rzCGPryd10HShGKvFPwM/R5S2lIVwtYxpms= -20251010031743.sql h1:T8IZmx8/btRFKLzTe78MzcBsPJNodnLvB0tby9QkirQ= -20251010070721.sql h1:5NQUk/yOV6sABLCB7swx++YIOyJe6MnU+yt1nRzde5w= -20251010072711.sql h1:ZJNqR2piyu8xJhBvVABSlnGEoKSKae3wuEs+wshPe4k= -20251013044536.sql h1:0Xjw8fNILiT8nnfrJDZgQnPf3dntmIoilbapnih8AE4= -20251013051438.sql h1:lfSuw5mgJnePBJamvhZ81osFIouXeiIEiSZ/evdwo48= -20251013081808.sql h1:ijgjNX08G6GBjA/ks8EKtb7P7Y7Cg7zbhqEOruGnv6M= -20251014060047.sql h1:0jqj49WTtneEIMQDBoo4c095ZGi8sCrA8NnHBrPU6D8= -20251014063537.sql h1:VZLXol0PTsTW21Epg6vBPsztWkDtcxup9F/z88EGgIg= -20251014063720.sql h1:2HVUyCV0ud3BJJDH2GEKZN/+IWLFPCsN1KqhP6csO14= -20251015045455.sql h1:MeLWmMhAOAz8b15Dd7IAQnt6JxjSml02XCXK22C0Lpg= -20251016010845.sql h1:4BncQdDOasRZJkzVJrSJJA7091A9VPNVx/faUCUPhBM= -20251016011023.sql h1:9JB9eFZKURK5RoCVDKR6glSvdJ8NTXrN7K/4q51zkz4= -20251016062912.sql h1:ACNn0fe+EMqUt3hoY+Dr3uqAV/QICBa1+mIW7fUc9Fk= -20251017060617.sql h1:4T3t9ifWrEQTPMSM0XJ98pF7Qdt+UfgtMui17bhrnWI= -20251017082207.sql h1:8vLG1l/saRRMHXkyA4nelJyjaSddhZd6r7R+Uo4JS/c= -20251018032635.sql h1:2xey5gnO3y2XSOrU8MLlIfoylPKbRGDRtHDD07B3MbQ= -20251018040322.sql h1:k/pdNiSoT8zFPqNQ/avOD0vYkNh3BTD64IlHrfVXr7I= -20251019093915.sql h1:hFcQE0y+p5dZiVwePGsRGto9m/q6kJNiUZbVDd5Rnjk= -20251020062553.sql h1:Iw7hulcm5iRQlfW+ygA4iTPxLqkxx6h9vXMXEwUAHKs= -20251021041042.sql h1:wMgSivBV2A0NDcsLmKGIp0kMcVh2IODSG9b4dgzCaOM= -20251021075552.sql h1:8gfSMAglflNO6L0sSzxFNEubYN8/O4thT7OQT+WH+3M= -20251023044432.sql h1:MkvajJs3bfk9+wHvQ43/ccAluJEBARm1gWr1u92ccLA= -20251024034832.sql h1:x3s3VEVYLOSKLAFxJGb2+c1FyTMMvPE+9k4Ew7rKQaI= -20251024074315.sql h1:EjAjelgi5qAfcRq/8vPTlGGYHvAKxNTllm8f0SzZDns= -20251025013451.sql h1:6hnuIiwYiG+6nLhOY/+Yyn+I6ZCFNRZxrJNqBV6HLqE= -20251025013609.sql h1:evPJaTD8WxYRMOJZHkSr7ONLx9PYxT+ankzQt9c/sJ0= -20251027075128.sql h1:/iFQBM1sytjqpyQSOx61q33gnorMgxTiFVSuL6bQqsM= -20251027091406.sql h1:eCZGtUkxAzEAqpC9UsGpP8Df9mS0DEOqSl885LgqpvM= -20251102002037.sql h1:lFJbuoZ2LMQnUNGdcwHVY3Xlfslgzu9t2WByT8yfOZI= -20251102091932.sql h1:rmdhb5m+P+fU8jROBZNyeYgZKuQvucsuljXv4ZVzvks= -20251103081637.sql h1:tf3BcwTeIw+oxMEisKDDfyKnBfalTLs8b0PJA8JWYxY= -20251104042334.sql h1:7PDMWOhmJywolAPKFZ14XaDBeMvcxShaXFN2IemNtzk= -20251104043530.sql h1:qvYVp3ysPf27f1BcoRNCFGovxuVE12lg9d6Xzda6zWU= -20251104080952.sql h1:avghpv1n3yaCDR/TA0X+hgxDGoLBQGu/GJUwj4VT/Ic= -20251104084135.sql h1:rg+eRE5/5sYWR7z+Xyn0zKw8rr8P/oWxF0xhcNVnNec= -20251105044629.sql h1:4NU27HeKUNFsV82LacnwmnCSAH0pSbZR9J9/ZESRs6M= -20251105121808.sql h1:fii6LjqWYjrm/pEIqttfvJI6QEUL49gque8wYHh1+yI= -20251106035305.sql h1:oQ7BwnxPuwY2q98adIVc+lNwL/Sz1OceLJeClDo9/TI= -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 -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:CcrTalr9bg48srSwCzcswS/erCTD93y72+cINyrHp2o= From cc16b6f1cb5fe564aa71557a4d045dbd1aaa50dc Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Wed, 3 Dec 2025 10:19:36 +0700 Subject: [PATCH 316/329] add doctype screening --- internal/domain/references/encounter/encounter.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/domain/references/encounter/encounter.go b/internal/domain/references/encounter/encounter.go index 231baa9b..ad6abe05 100644 --- a/internal/domain/references/encounter/encounter.go +++ b/internal/domain/references/encounter/encounter.go @@ -123,6 +123,7 @@ const ( DTCGC DocTypeCode = "general-consent" DTCVSCL DocTypeCode = "vclaim-control-letter" // vclaim control letter DTCResume DocTypeCode = "resume" // Resume + DTCScreening DocTypeCode = "screening" // Screening ETCPerson EntityTypeCode = "person" ETCEncounter EntityTypeCode = "encounter" From da2bea83080eb67eea0c394c92674df71d3dbc71 Mon Sep 17 00:00:00 2001 From: vanilia Date: Wed, 3 Dec 2025 10:25:11 +0700 Subject: [PATCH 317/329] add t-rekammedik --- .../simgos-entities/t-rekammedik/entity.go | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 internal/domain/simgos-entities/t-rekammedik/entity.go diff --git a/internal/domain/simgos-entities/t-rekammedik/entity.go b/internal/domain/simgos-entities/t-rekammedik/entity.go new file mode 100644 index 00000000..5df0ec83 --- /dev/null +++ b/internal/domain/simgos-entities/t-rekammedik/entity.go @@ -0,0 +1,22 @@ +package t_rekammedik + +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"` + 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"` +} + +func (TRekammedik) TableName() string { + return "t_rekammedik" +} From a44ba9ab1cd133c8fa1c250c68f5ad2a4272208e Mon Sep 17 00:00:00 2001 From: vanilia Date: Wed, 3 Dec 2025 14:20:28 +0700 Subject: [PATCH 318/329] add partial index for patient number --- cmd/main-migration/migrations/atlas.sum | 4 ++-- internal/domain/main-entities/patient/entity.go | 13 ++++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index c949eadc..341a35d3 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:MO6ze6e6ClW/WxUyiZxT6Lmhz8BDgXmmYeLDSN4xEJw= +h1:DgMML95zGYI7JMvZaIb/gySCvncMu62CANOIXNX0A6w= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -143,4 +143,4 @@ h1:MO6ze6e6ClW/WxUyiZxT6Lmhz8BDgXmmYeLDSN4xEJw= 20251202130629.sql h1:9mvalqfhqGCdkcJepJDzHprU2xb0i5sYys1Htf62ioo= 20251202160848.sql h1:Kd2/TziKSMezrt4XgbjQcYvY/Lo9rX0qw7/Lz0/oyKk= 20251202180207.sql h1:IHmSMIO3ia+YV5GULixbdlV1joaUAWtnjQHPd8+HKiM= -20251202231005.sql h1:iVzsqbqmfncDXPPXoRqCQdcvgvLBv57TbzdbzQAmSVc= +20251202231005.sql h1:lua0KKoeBptSfs/6ehZE6Azo6YUlNkOJwGFyb1HQWkY= diff --git a/internal/domain/main-entities/patient/entity.go b/internal/domain/main-entities/patient/entity.go index 83afa6ce..9ad63ce8 100644 --- a/internal/domain/main-entities/patient/entity.go +++ b/internal/domain/main-entities/patient/entity.go @@ -15,7 +15,14 @@ type Patient struct { RegisteredAt *time.Time `json:"registeredAt"` RegisteredBy_User_Name *string `json:"registeredBy_user_name" gorm:"size:100"` Status_Code erc.ActiveStatusCode `json:"status_code" gorm:"not null;size:10"` - Number *string `json:"number" gorm:"unique;size:15"` - Parent_Number *string `json:"parent_number"` - Parent *Patient `json:"parent,omitempty" gorm:"foreignKey:Parent_Number;references:Number"` + + // Normal UNIQUE index — required for the foreign key reference + Number *string `json:"number" gorm:"size:15;unique"` + + // Partial unique index — keeps Number unique only for non–soft-deleted records. + // Allows duplicate Number values when previous records are soft-deleted. + _ struct{} `gorm:"uniqueIndex:idx_number_active,where:\"DeletedAt\" IS NULL"` + + Parent_Number *string `json:"parent_number"` + Parent *Patient `json:"parent,omitempty" gorm:"foreignKey:Parent_Number;references:Number"` } From 09068877878c7712bae83357badccf807d3554c1 Mon Sep 17 00:00:00 2001 From: vanilia Date: Wed, 3 Dec 2025 15:24:28 +0700 Subject: [PATCH 319/329] rollback patient --- internal/domain/main-entities/patient/entity.go | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/internal/domain/main-entities/patient/entity.go b/internal/domain/main-entities/patient/entity.go index 9ad63ce8..fc6d8833 100644 --- a/internal/domain/main-entities/patient/entity.go +++ b/internal/domain/main-entities/patient/entity.go @@ -15,14 +15,7 @@ type Patient struct { RegisteredAt *time.Time `json:"registeredAt"` RegisteredBy_User_Name *string `json:"registeredBy_user_name" gorm:"size:100"` Status_Code erc.ActiveStatusCode `json:"status_code" gorm:"not null;size:10"` - - // Normal UNIQUE index — required for the foreign key reference - Number *string `json:"number" gorm:"size:15;unique"` - - // Partial unique index — keeps Number unique only for non–soft-deleted records. - // Allows duplicate Number values when previous records are soft-deleted. - _ struct{} `gorm:"uniqueIndex:idx_number_active,where:\"DeletedAt\" IS NULL"` - - Parent_Number *string `json:"parent_number"` - Parent *Patient `json:"parent,omitempty" gorm:"foreignKey:Parent_Number;references:Number"` + Number *string `json:"number" gorm:"size:15;unique"` + Parent_Number *string `json:"parent_number"` + Parent *Patient `json:"parent,omitempty" gorm:"foreignKey:Parent_Number;references:Number"` } From 5975721daf1defff62cbb93efce8b23025a27c7d Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Wed, 3 Dec 2025 16:10:23 +0700 Subject: [PATCH 320/329] feat (generate-file): screening form a tested and ok, form b not fully tested --- assets/docs/screening-form-a.html | 8 +- assets/docs/screening-form-b.html | 142 ++++++++---------- .../domain/main-entities/screening/dto.go | 8 +- .../domain/main-entities/screening/entity.go | 4 +- .../interface/main-handler/main-handler.go | 4 +- .../main-handler/screening/handler.go | 34 ++--- .../main-use-case/generate-file/case.go | 6 + .../main-use-case/generate-file/helper.go | 139 ++++++++++++++--- .../main-use-case/generate-file/tycovar.go | 8 + .../use-case/main-use-case/screening/lib.go | 4 +- pkg/pdf-helper/pdf-helper.go | 3 + 11 files changed, 228 insertions(+), 132 deletions(-) diff --git a/assets/docs/screening-form-a.html b/assets/docs/screening-form-a.html index a838c111..4f34b876 100644 --- a/assets/docs/screening-form-a.html +++ b/assets/docs/screening-form-a.html @@ -56,17 +56,17 @@ " > - No. RM + No. RM : - {{ .MedicalRecord }} + {{ .MedicalRecord }} - Nama + Nama : {{ .Name }} - Tanggal Lahir + Tanggal Lahir : {{ .BirthDate }} diff --git a/assets/docs/screening-form-b.html b/assets/docs/screening-form-b.html index 1ae8a07c..9abc94ce 100644 --- a/assets/docs/screening-form-b.html +++ b/assets/docs/screening-form-b.html @@ -33,94 +33,76 @@ - - - - - - - - - - - - - - - - - - - - - -
          - Tanggal Terbit - : {{ .Repalcable }}
          - No. RM - : {{ .Repalcable }}
          - Nama - : {{ .Repalcable }}
          - Tanggal Lahir - : {{ .Repalcable }}
          - -
          -

          - FORM B -

          + Tanggal Terbit : {{ .IssuedDate }} +
          - + +
          - - - - + + + - - - - + + + + + + + +
          - NO - - Tanggal/jam - - Implementasi, Monitoring, Fasilitasi, koordinasi, komunikasi dan kolaborasi, advokasi, hasil pelayanan, - Terminasi - - MPP - No. RM:{{ .MedicalRecord }}
          - 1 - - 2025-10-08 16:08:18 - -
            -
          • Implementasi: Pemantauan harian terhadap penggunaan alat medis (oksigen dan alat bantu - jalan) serta kepatuhan terapi.
          • -
          • Monitoring: Observasi respon pasien terhadap terapi dan edukasi keluarga untuk perawatan - mandiri di rumah.
          • -
          • Fasilitasi: Menyediakan alat bantu sesuai kebutuhan dan menghubungkan pasien dengan - layanan rehabilitasi medik.
          • -
          • Koordinasi: Melibatkan dokter penanggung jawab, perawat, dan keluarga dalam penyusunan - rencana tindak lanjut.
          • -
          • Komunikasi dan Kolaborasi: Diskusi rutin antar profesi untuk evaluasi perkembangan - pasien.
          • -
          • Advokasi: Memberikan dukungan informasi dan hak pasien terkait rencana pulang dan - kesinambungan terapi.
          • -
          • Hasil Pelayanan: Pasien menunjukkan perbaikan fungsi mobilitas, tingkat kepatuhan terapi - meningkat.
          • -
          -
          - GATOT SUBROTO,AMd.Kep - Nama:{{ .Name }}
          Tanggal Lahir:{{ .BirthDate }}
          + + + + + + + + + + {{ range .FormB }} + + + + + + + + + {{ end }} + +
          NOTanggal/jam + Implementasi, Monitoring, Fasilitasi, koordinasi, komunikasi dan kolaborasi, + advokasi, hasil pelayanan, Terminasi + MPP
          {{ .Number }}{{ .Date }} + {{ .Value }} + + {{ .Employee_Name }} +
          +
          diff --git a/internal/domain/main-entities/screening/dto.go b/internal/domain/main-entities/screening/dto.go index b001af39..0c4310ed 100644 --- a/internal/domain/main-entities/screening/dto.go +++ b/internal/domain/main-entities/screening/dto.go @@ -27,6 +27,7 @@ type CreateDto struct { type ReadListDto struct { FilterDto Includes string `json:"includes"` + Sort string `json:"sort"` Pagination ecore.Pagination } @@ -38,16 +39,17 @@ 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 } type DeleteDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` } type MetaDto struct { diff --git a/internal/domain/main-entities/screening/entity.go b/internal/domain/main-entities/screening/entity.go index fa650165..007573c4 100644 --- a/internal/domain/main-entities/screening/entity.go +++ b/internal/domain/main-entities/screening/entity.go @@ -19,4 +19,6 @@ type Screening struct { FileUrl *string `json:"fileUrl" gorm:"size:1024"` } -// func (d Screening) UnMarshal(data []byte) (error {} +func (d Screening) IsFormA() bool { + return d.Type == erc.SFTCA +} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 8864fcbb..55342b0f 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -316,7 +316,9 @@ func SetRoutes() http.Handler { "PATCH /{id}/validate": resume.Validate, }) hk.GroupRoutes("/v1/screening", r, auth.GuardMW, hk.MapHandlerFunc{ - "POST /": screening.O.Create, + "POST /": screening.O.Create, + "GET /": screening.O.GetList, + "GET /{id}": screening.O.GetDetail, }) /******************** actor ********************/ hc.RegCrud(r, "/v1/person", person.O) diff --git a/internal/interface/main-handler/screening/handler.go b/internal/interface/main-handler/screening/handler.go index 29ea5c73..a6866cc9 100644 --- a/internal/interface/main-handler/screening/handler.go +++ b/internal/interface/main-handler/screening/handler.go @@ -4,7 +4,7 @@ import ( "net/http" rw "github.com/karincake/risoles" - // sf "github.com/karincake/semprit" + sf "github.com/karincake/semprit" // ua "github.com/karincake/tumpeng/auth/svc" @@ -34,23 +34,23 @@ func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { rw.DataResponse(w, res, err) } -// func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { -// dto := e.ReadListDto{} -// sf.UrlQueryParam(&dto, *r.URL) -// res, err := u.ReadList(dto) -// rw.DataResponse(w, res, err) -// } +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} -// func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { -// id := rw.ValidateInt(w, "id", r.PathValue("id")) -// if id <= 0 { -// return -// } -// dto := e.ReadDetailDto{} -// dto.Id = uint16(id) -// res, err := u.ReadDetail(dto) -// rw.DataResponse(w, res, err) -// } +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} // func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { // id := rw.ValidateInt(w, "id", r.PathValue("id")) diff --git a/internal/use-case/main-use-case/generate-file/case.go b/internal/use-case/main-use-case/generate-file/case.go index 7c657640..b5103746 100644 --- a/internal/use-case/main-use-case/generate-file/case.go +++ b/internal/use-case/main-use-case/generate-file/case.go @@ -51,6 +51,12 @@ func Generate(input GenerateDto) (*d.Data, error) { return err } + // screening + case ere.DTCScreening: + response, err = generateScreening(input, event, tx) + if err != nil { + return err + } default: return errors.New("invalid type code") } diff --git a/internal/use-case/main-use-case/generate-file/helper.go b/internal/use-case/main-use-case/generate-file/helper.go index 76e4f5ee..a0e7c1e2 100644 --- a/internal/use-case/main-use-case/generate-file/helper.go +++ b/internal/use-case/main-use-case/generate-file/helper.go @@ -20,7 +20,9 @@ import ( ue "simrs-vx/internal/use-case/main-use-case/encounter" ugc "simrs-vx/internal/use-case/main-use-case/general-consent" ur "simrs-vx/internal/use-case/main-use-case/resume" + us "simrs-vx/internal/use-case/main-use-case/screening" + ercl "simrs-vx/internal/domain/references/clinical" erc "simrs-vx/internal/domain/references/common" docscfg "simrs-vx/internal/infra/docs-cfg" @@ -341,41 +343,130 @@ func generateResumeTemplateData(resume er.Resume, event pl.Event, tx *gorm.DB) ( return &templateData, nil } -func generateScreeningFormATemplateData(screening es.Screening, event pl.Event, tx *gorm.DB) (*ScreeningPDF, error) { +func generateScreeningTemplateData(screenings []es.Screening, event pl.Event, tx *gorm.DB) (*ScreeningPDF, error) { // get encounter includes := "Patient,Patient.Person" - encounter, err := ue.ReadDetailData(ee.ReadDetailDto{Id: *screening.Encounter_Id, Includes: includes}, &event) + encounter, err := ue.ReadDetailData(ee.ReadDetailDto{Id: *screenings[0].Encounter_Id, Includes: includes}, &event) if err != nil { return nil, err } - // map template data - sData := es.FormA{} - if screening.Value != nil { - err := json.Unmarshal([]byte(*screening.Value), &sData) - if err != nil { - event.ErrInfo = pl.ErrorInfo{ - Code: "data-unmarshal-fail", - Detail: err.Error(), - Raw: err, + switch screenings[0].Type { + case ercl.SFTCA: + // map template data + sData := es.FormA{} + if screenings[0].Value != nil { + err := json.Unmarshal([]byte(*screenings[0].Value), &sData) + if err != nil { + event.ErrInfo = pl.ErrorInfo{ + Code: "data-unmarshal-fail", + Detail: err.Error(), + Raw: err, + } + return nil, err } + } else { + return nil, errors.New("there is no data to be used") + } + + templateData := ScreeningPDF{} + templateData.IssuedDate = pu.GetTimeNow().Format("2006-01-02 15:04:05") + templateData.MedicalRecord = *encounter.Patient.Number + templateData.Name = encounter.Patient.Person.FullName() + templateData.BirthDate = encounter.Patient.Person.BirthDate.Format("2006-01-02 15:04:05") + templateData.Employee_Name = screenings[0].Employee.Person.FullName() + templateData.EarlyMedic = sData.Screening.SelectedScreeningLabels() + templateData.Assessment = sData.AssessmentDetail + templateData.ProblemIdentification = sData.ProblemIdentification.SelectedProblemLabels() + templateData.Planning = sData.PlanningDetail + templateData.Date = screenings[0].CreatedAt.Format("2006-01-02 15:04:05") + + return &templateData, nil + case ercl.SFTCB: + // map template data + templateData := ScreeningPDF{} + templateData.IssuedDate = pu.GetTimeNow().Format("2006-01-02 15:04:05") + templateData.MedicalRecord = *encounter.Patient.Number + templateData.Name = encounter.Patient.Person.FullName() + templateData.BirthDate = encounter.Patient.Person.BirthDate.Format("2006-01-02 15:04:05") + for k, v := range screenings { + templateData.FormB = append(templateData.FormB, ScreeningFormBPDF{ + Number: k + 1, + Date: v.CreatedAt.Format("2006-01-02 15:04:05"), + Employee_Name: v.Employee.Person.FullName(), + Value: *v.Value, + }) + } + + return &templateData, nil + } + return nil, errors.New("invalid screening type") +} + +func generateScreening(input GenerateDto, event pl.Event, tx *gorm.DB) (*ResponseDto, error) { + // get value from resume by ref_id + includes := "Employee.Person" + s, err := us.ReadDetailData(es.ReadDetailDto{Id: uint(*pc.StringToUint64(*input.Ref_Id)), Includes: includes}, &event) + if err != nil { + return nil, err + } + + var screenings []es.Screening + var templateData *ScreeningPDF + if s.IsFormA() { + if s.FileUrl != nil { + if err := removeFile(string(input.EntityType_Code), *s.FileUrl); err != nil { + return nil, err + } + } + screenings = append(screenings, *s) + input.FormatType = erc.DFTCPDF + input.TemplateName = TDNSA + input.Encounter_Id = s.Encounter_Id + templateData, err = generateScreeningTemplateData(screenings, event, tx) + if err != nil { return nil, err } } else { - return nil, errors.New("there is no data to be used") + includes := "Employee.Person" + sort := "CreatedAt:ASC" + ss, _, err := us.ReadListData(es.ReadListDto{FilterDto: es.FilterDto{Encounter_Id: s.Encounter_Id, Type: ercl.SFTCB}, Includes: includes, Sort: sort}, &event, tx) + if err != nil { + return nil, err + } + screenings = append(screenings, ss...) + input.FormatType = erc.DFTCPDF + input.TemplateName = TDNSB + input.Encounter_Id = s.Encounter_Id + templateData, err = generateScreeningTemplateData(screenings, event, tx) + if err != nil { + return nil, err + } } - templateData := ScreeningPDF{} - templateData.IssuedDate = pu.GetTimeNow().Format("2006-01-02 15:04:05") - templateData.MedicalRecord = *encounter.Patient.Number - templateData.Name = encounter.Patient.Person.FullName() - templateData.BirthDate = encounter.Patient.Person.BirthDate.Format("2006-01-02 15:04:05") - templateData.Employee_Name = screening.Employee.Person.FullName() - templateData.EarlyMedic = sData.Screening.SelectedScreeningLabels() - templateData.Assessment = sData.AssessmentDetail - templateData.ProblemIdentification = sData.ProblemIdentification.SelectedProblemLabels() - templateData.Planning = sData.PlanningDetail - templateData.Date = screening.CreatedAt.Format("2006-01-02 15:04:05") + // generate file + urlPub, err := generateFile(input, templateData) + if err != nil { + return nil, err + } - return &templateData, nil + if len(screenings) > 1 { + for i := range screenings { + screenings[i].FileUrl = &urlPub + } + if err := tx.Save(&screenings).Error; err != nil { + return nil, err + } + } else { + s.FileUrl = &urlPub + if err := tx.Save(&s).Error; err != nil { + return nil, err + } + } + + response := ResponseDto{ + FileUrl: urlPub, + } + + return &response, nil } diff --git a/internal/use-case/main-use-case/generate-file/tycovar.go b/internal/use-case/main-use-case/generate-file/tycovar.go index d5a7220e..a8fd5ef5 100644 --- a/internal/use-case/main-use-case/generate-file/tycovar.go +++ b/internal/use-case/main-use-case/generate-file/tycovar.go @@ -83,6 +83,14 @@ type ScreeningPDF struct { Assessment string ProblemIdentification []string Planning string + FormB []ScreeningFormBPDF +} + +type ScreeningFormBPDF struct { + Number int + Date string + Employee_Name string + Value string } type GenerateDto struct { diff --git a/internal/use-case/main-use-case/screening/lib.go b/internal/use-case/main-use-case/screening/lib.go index 413e84d2..31ed6ee1 100644 --- a/internal/use-case/main-use-case/screening/lib.go +++ b/internal/use-case/main-use-case/screening/lib.go @@ -53,7 +53,7 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Sc Scopes(gh.Filter(input.FilterDto)). Count(&count). Scopes(gh.Paginate(input, &pagination)). - Order("\"CreatedAt\" DESC") + Scopes(gh.Sort(input.Sort)) if err := tx.Find(&data).Error; err != nil { if err == gorm.ErrRecordNotFound { @@ -81,7 +81,7 @@ 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/pkg/pdf-helper/pdf-helper.go b/pkg/pdf-helper/pdf-helper.go index 9878ecbd..9b1dc129 100644 --- a/pkg/pdf-helper/pdf-helper.go +++ b/pkg/pdf-helper/pdf-helper.go @@ -33,6 +33,9 @@ func (r *RequestPdf) ParseTemplate(templatePath string, data interface{}) error "nl2br": func(text string) template.HTML { return template.HTML(strings.Replace(template.HTMLEscapeString(text), "\n", "
          ", -1)) }, + "safeHTML": func(text string) template.HTML { + return template.HTML(text) + }, } t, err := template.New(fileName).Funcs(funcs).ParseFiles(templatePath) if err != nil { From 203b6f51d5a046246ab504d78aac94c792861bd0 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Wed, 3 Dec 2025 17:32:36 +0700 Subject: [PATCH 321/329] feat (encounter): add filter by range registered at, and patient name --- internal/domain/main-entities/encounter/dto.go | 7 +++++-- internal/use-case/main-use-case/encounter/lib.go | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index 8dd9a0a1..c039fc0c 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -78,8 +78,11 @@ type TRujukan struct { type ReadListDto struct { FilterDto - Includes string `json:"includes"` - Pagination ecore.Pagination + Includes string `json:"includes"` + Pagination ecore.Pagination + Person_Name *string `json:"person-name"` + StartDate *string `json:"start-date"` + EndDate *string `json:"end-date"` pa.AuthInfo } diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index 0b14b925..0ea8988d 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -65,7 +65,20 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.En tx.Where("\"Responsible_Doctor_Code\" = ?", *input.AuthInfo.Doctor_Code) // } - tx.Scopes(gh.Preload(input.Includes)). + if input.StartDate != nil && input.EndDate != nil { + tx = tx.Where( + "DATE(\"RegisteredAt\") >= DATE(?) AND DATE(\"RegisteredAt\") <= DATE(?)", + input.StartDate, + input.EndDate, + ) + } + + if input.Person_Name != nil { + tx = tx.Joins("JOIN \"Patient\" ON \"Patient\".\"Id\" = \"Encounter\".\"Patient_Id\""). + Joins("JOIN \"Person\" ON \"Person\".\"Id\" = \"Patient\".\"Person_Id\"").Where("\"Person\".\"Name\" ILIKE ?", "%"+*input.Person_Name+"%") + } + + tx = tx.Debug().Scopes(gh.Preload(input.Includes)). Scopes(gh.Filter(input.FilterDto)). Count(&count). Scopes(gh.Paginate(input, &pagination)). From 8dba52cc176d0292ddeff5d5734efc7ba3f03778 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Thu, 4 Dec 2025 03:52:51 +0700 Subject: [PATCH 322/329] feat/order-things: adjust table structure --- cmd/main-migration/migrations/20251203205052.sql | 4 ++++ cmd/main-migration/migrations/atlas.sum | 3 ++- .../procedure-room-order-item/base/entity.go | 12 ++++++++++++ .../procedure-room-order-item/entity.go | 11 +++++------ .../main-entities/procedure-room-order/dto.go | 12 ++++++------ .../main-entities/procedure-room-order/entity.go | 15 ++++++++------- .../domain/main-entities/procedure-room/dto.go | 2 +- 7 files changed, 38 insertions(+), 21 deletions(-) create mode 100644 cmd/main-migration/migrations/20251203205052.sql create mode 100644 internal/domain/main-entities/procedure-room-order-item/base/entity.go diff --git a/cmd/main-migration/migrations/20251203205052.sql b/cmd/main-migration/migrations/20251203205052.sql new file mode 100644 index 00000000..831497a2 --- /dev/null +++ b/cmd/main-migration/migrations/20251203205052.sql @@ -0,0 +1,4 @@ +-- Modify "ProcedureRoomOrder" table +ALTER TABLE "public"."ProcedureRoomOrder" DROP COLUMN "Infra_Code"; +-- Modify "ProcedureRoomOrderItem" table +ALTER TABLE "public"."ProcedureRoomOrderItem" ADD CONSTRAINT "fk_ProcedureRoomOrderItem_ProcedureRoomOrder" FOREIGN KEY ("ProcedureRoomOrder_Id") REFERENCES "public"."ProcedureRoomOrder" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 341a35d3..3ec1b876 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:DgMML95zGYI7JMvZaIb/gySCvncMu62CANOIXNX0A6w= +h1:qjr3k9/ymXjw1nopw49c6+fWtu0n+H8sQgsioqUC9Fo= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -144,3 +144,4 @@ h1:DgMML95zGYI7JMvZaIb/gySCvncMu62CANOIXNX0A6w= 20251202160848.sql h1:Kd2/TziKSMezrt4XgbjQcYvY/Lo9rX0qw7/Lz0/oyKk= 20251202180207.sql h1:IHmSMIO3ia+YV5GULixbdlV1joaUAWtnjQHPd8+HKiM= 20251202231005.sql h1:lua0KKoeBptSfs/6ehZE6Azo6YUlNkOJwGFyb1HQWkY= +20251203205052.sql h1:az/hGpk7u4YKT7gU+UuEw9guqB9AqdckPF1cYavQ3CA= diff --git a/internal/domain/main-entities/procedure-room-order-item/base/entity.go b/internal/domain/main-entities/procedure-room-order-item/base/entity.go new file mode 100644 index 00000000..cd54e456 --- /dev/null +++ b/internal/domain/main-entities/procedure-room-order-item/base/entity.go @@ -0,0 +1,12 @@ +package procedureroomorder + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type ProcedureRoomOrderItem struct { + ecore.BigMain + ProcedureRoomOrder_Id uint64 `json:"procedureRoomOrder_id"` + ProcedureRoom_Code string `json:"procedureRoom_code" gorm:"size:20"` + Note string `json:"note" gorm:"size:255"` +} diff --git a/internal/domain/main-entities/procedure-room-order-item/entity.go b/internal/domain/main-entities/procedure-room-order-item/entity.go index 4a737048..13b4978b 100644 --- a/internal/domain/main-entities/procedure-room-order-item/entity.go +++ b/internal/domain/main-entities/procedure-room-order-item/entity.go @@ -1,14 +1,13 @@ package procedureroomorder import ( - ecore "simrs-vx/internal/domain/base-entities/core" epr "simrs-vx/internal/domain/main-entities/procedure-room" + epro "simrs-vx/internal/domain/main-entities/procedure-room-order" + eb "simrs-vx/internal/domain/main-entities/procedure-room-order-item/base" ) type ProcedureRoomOrderItem struct { - ecore.BigMain - ProcedureRoomOrder_Id uint64 `json:"procedureRoomOrder_id"` - ProcedureRoom_Code string `json:"procedureRoom_code" gorm:"size:20"` - ProcedureRoom *epr.ProcedureRoom `json:"procedureRoom,omitempty" gorm:"foreignKey:ProcedureRoom_Code;references:Code"` - Note string `json:"note" gorm:"size:255"` + eb.ProcedureRoomOrderItem + ProcedureRoomOrder *epro.ProcedureRoomOrder `json:"procedureRoomOrder,omitempty" gorm:"foreignKey:ProcedureRoomOrder_Id;references:Id"` + ProcedureRoom *epr.ProcedureRoom `json:"procedureRoom,omitempty" gorm:"foreignKey:ProcedureRoom_Code;references:Code"` } diff --git a/internal/domain/main-entities/procedure-room-order/dto.go b/internal/domain/main-entities/procedure-room-order/dto.go index 5810e756..4482081c 100644 --- a/internal/domain/main-entities/procedure-room-order/dto.go +++ b/internal/domain/main-entities/procedure-room-order/dto.go @@ -9,9 +9,9 @@ import ( ) type CreateDto struct { - Encounter_Id uint64 `json:"encounter_id" validate:"required"` - Infra_Code string `json:"infra_code" validate:"required"` - MaterialPackage_Code string `json:"materialPackage_code" validate:"required"` + Encounter_Id uint64 `json:"encounter_id" validate:"required"` + // Infra_Code string `json:"infra_code" validate:"required"` + MaterialPackage_Code *string `json:"materialPackage_code"` } type ReadListDto struct { @@ -48,7 +48,7 @@ type ResponseDto struct { Encounter_Id uint64 `json:"encounter_id"` Encounter *ec.Encounter `json:"encounter,omitempty"` Infra_Code string `json:"procedure"` - MaterialPackage_Code string `json:"materialPackage_code"` + MaterialPackage_Code *string `json:"materialPackage_code"` Status_Code erc.DataStatusCode `json:"status_code"` ProcedureRoom *epr.ProcedureRoom `json:"procedureRoom,omitempty"` MaterialPackage *emp.MaterialPackage `json:"materialPackage,omitempty"` @@ -56,8 +56,8 @@ type ResponseDto struct { func (d ProcedureRoomOrder) ToResponse() ResponseDto { resp := ResponseDto{ - Encounter_Id: d.Encounter_Id, - Infra_Code: d.Infra_Code, + Encounter_Id: d.Encounter_Id, + // Infra_Code: d.Infra_Code, MaterialPackage_Code: d.MaterialPackage_Code, Status_Code: d.Status_Code, } diff --git a/internal/domain/main-entities/procedure-room-order/entity.go b/internal/domain/main-entities/procedure-room-order/entity.go index 1ef7c178..5d2c8ba7 100644 --- a/internal/domain/main-entities/procedure-room-order/entity.go +++ b/internal/domain/main-entities/procedure-room-order/entity.go @@ -5,15 +5,16 @@ import ( ecore "simrs-vx/internal/domain/base-entities/core" emp "simrs-vx/internal/domain/main-entities/material-package" - epr "simrs-vx/internal/domain/main-entities/procedure-room" + eproi "simrs-vx/internal/domain/main-entities/procedure-room-order-item/base" ) type ProcedureRoomOrder struct { ecore.BigMain - Encounter_Id uint64 `json:"encounter_id"` - Infra_Code string `json:"infra_code" gorm:"size:20"` - ProcedureRoom *epr.ProcedureRoom `json:"procedureRoom,omitempty" gorm:"foreignKey:Infra_Code;references:Code"` - MaterialPackage_Code string `json:"materialPackage_code" gorm:"size:20"` - MaterialPackage *emp.MaterialPackage `json:"materialPackage,omitempty" gorm:"foreignKey:MaterialPackage_Code;references:Code"` - Status_Code erc.DataStatusCode `json:"status_code" gorm:"size:20"` + Encounter_Id uint64 `json:"encounter_id"` + // Infra_Code string `json:"infra_code" gorm:"size:20"` + // ProcedureRoom *epr.ProcedureRoom `json:"procedureRoom,omitempty" gorm:"foreignKey:Infra_Code;references:Code"` + MaterialPackage_Code *string `json:"materialPackage_code" gorm:"size:20"` + MaterialPackage *emp.MaterialPackage `json:"materialPackage,omitempty" gorm:"foreignKey:MaterialPackage_Code;references:Code"` + Status_Code erc.DataStatusCode `json:"status_code" gorm:"size:20"` + Items []eproi.ProcedureRoomOrderItem `json:"items,omitempty" gorm:"foreignKey:ProcedureRoomOrder_Id;references:Id"` } diff --git a/internal/domain/main-entities/procedure-room/dto.go b/internal/domain/main-entities/procedure-room/dto.go index 373e6cd9..b3812db2 100644 --- a/internal/domain/main-entities/procedure-room/dto.go +++ b/internal/domain/main-entities/procedure-room/dto.go @@ -25,7 +25,7 @@ type ReadListDto struct { type FilterDto struct { Infra_Code *string `json:"infra-code"` - Type_Code string `json:"type_code"` + Type_Code string `json:"type-code"` Unit_Code *string `json:"unit-code"` Specialist_Code *string `json:"specialist-code"` Subspecialist_Code *string `json:"subspecialist-code"` From 2fdb5fc9e08061f41a04a9db31a6b3d4cd049030 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Thu, 4 Dec 2025 03:54:19 +0700 Subject: [PATCH 323/329] feat/order-things: added procedure-room flow --- .../interface/main-handler/main-handler.go | 2 + .../main-handler/procedure-room/handler.go | 71 +++++++++++++++++++ .../procedure-room-order/helper.go | 1 - 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 internal/interface/main-handler/procedure-room/handler.go diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index d7c482e0..b5ef823b 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -34,6 +34,7 @@ import ( practiceschedule "simrs-vx/internal/interface/main-handler/practice-schedule" prescription "simrs-vx/internal/interface/main-handler/prescription" prescriptionitem "simrs-vx/internal/interface/main-handler/prescription-item" + procedureroom "simrs-vx/internal/interface/main-handler/procedure-room" procedureroomorder "simrs-vx/internal/interface/main-handler/procedure-room-order" procedureroomorderitem "simrs-vx/internal/interface/main-handler/procedure-room-order-item" responsibledoctorhist "simrs-vx/internal/interface/main-handler/responsible-doctor-hist" @@ -271,6 +272,7 @@ func SetRoutes() http.Handler { "DELETE /{id}": materialorder.O.Delete, "PATCH /{id}/complete": materialorder.O.Complete, }) + hc.RegCrud(r, "/v1/procedure-room", procedureroom.O) hc.RegCrud(r, "/v1/procedure-room-order", procedureroomorder.O) hc.RegCrud(r, "/v1/procedure-room-order-item", procedureroomorderitem.O) hk.GroupRoutes("/v1/consultation", r, auth.GuardMW, hk.MapHandlerFunc{ diff --git a/internal/interface/main-handler/procedure-room/handler.go b/internal/interface/main-handler/procedure-room/handler.go new file mode 100644 index 00000000..6d6aeb1c --- /dev/null +++ b/internal/interface/main-handler/procedure-room/handler.go @@ -0,0 +1,71 @@ +package procedureroom + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/procedure-room" + u "simrs-vx/internal/use-case/main-use-case/procedure-room" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id == 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint16(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id == 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint16(id) + 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 = uint16(id) + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/use-case/main-use-case/procedure-room-order/helper.go b/internal/use-case/main-use-case/procedure-room-order/helper.go index 6e91b7e3..9f47d54d 100644 --- a/internal/use-case/main-use-case/procedure-room-order/helper.go +++ b/internal/use-case/main-use-case/procedure-room-order/helper.go @@ -19,7 +19,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.ProcedureRoomOrder) } data.Encounter_Id = inputSrc.Encounter_Id - data.Infra_Code = inputSrc.Infra_Code data.MaterialPackage_Code = inputSrc.MaterialPackage_Code data.Status_Code = erc.DSCNew } From b79c36ed0e3d613d6c484426a32a05152340cafe Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Thu, 4 Dec 2025 10:32:51 +0700 Subject: [PATCH 324/329] feat/order-things: adjust procedure-room-order --- .../procedure-room-order-item/dto.go | 3 +- .../procedure-room-order/entity.go | 4 ++ .../interface/main-handler/main-handler.go | 9 ++- .../procedure-room-order/handler.go | 12 ++++ .../procedure-room-order/case.go | 66 ++++++++++++++++++- 5 files changed, 90 insertions(+), 4 deletions(-) diff --git a/internal/domain/main-entities/procedure-room-order-item/dto.go b/internal/domain/main-entities/procedure-room-order-item/dto.go index 4b564ce6..83c4d094 100644 --- a/internal/domain/main-entities/procedure-room-order-item/dto.go +++ b/internal/domain/main-entities/procedure-room-order-item/dto.go @@ -18,7 +18,8 @@ type ReadListDto struct { } type FilterDto struct { - Encounter_Id uint64 `json:"encounter-id"` + Encounter_Id uint64 `json:"encounter-id"` + ProcedureRoomOrder_Id uint64 `json:"procedure-room-order-id"` } type ReadDetailDto struct { diff --git a/internal/domain/main-entities/procedure-room-order/entity.go b/internal/domain/main-entities/procedure-room-order/entity.go index 5d2c8ba7..5a4a8542 100644 --- a/internal/domain/main-entities/procedure-room-order/entity.go +++ b/internal/domain/main-entities/procedure-room-order/entity.go @@ -18,3 +18,7 @@ type ProcedureRoomOrder struct { Status_Code erc.DataStatusCode `json:"status_code" gorm:"size:20"` Items []eproi.ProcedureRoomOrderItem `json:"items,omitempty" gorm:"foreignKey:ProcedureRoomOrder_Id;references:Id"` } + +func (d ProcedureRoomOrder) IsNotNew() bool { + return d.Status_Code != erc.DSCNew +} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index b5ef823b..0e637137 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -273,7 +273,14 @@ func SetRoutes() http.Handler { "PATCH /{id}/complete": materialorder.O.Complete, }) hc.RegCrud(r, "/v1/procedure-room", procedureroom.O) - hc.RegCrud(r, "/v1/procedure-room-order", procedureroomorder.O) + hk.GroupRoutes("/v1/procedure-room-order", r, auth.GuardMW, hk.MapHandlerFunc{ + "GET /": procedureroomorder.O.GetList, + "GET /{id}": procedureroomorder.O.GetDetail, + "POST /": procedureroomorder.O.Create, + "PATCH /{id}": procedureroomorder.O.Update, + "DELETE /{id}": procedureroomorder.O.Delete, + "PATCH /{id}/submit": procedureroomorder.O.Submit, + }) hc.RegCrud(r, "/v1/procedure-room-order-item", procedureroomorderitem.O) hk.GroupRoutes("/v1/consultation", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": consultation.O.GetList, diff --git a/internal/interface/main-handler/procedure-room-order/handler.go b/internal/interface/main-handler/procedure-room-order/handler.go index e50247a1..58c2c80b 100644 --- a/internal/interface/main-handler/procedure-room-order/handler.go +++ b/internal/interface/main-handler/procedure-room-order/handler.go @@ -69,3 +69,15 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { res, err := u.Delete(dto) rw.DataResponse(w, res, err) } + +func (obj myBase) Submit(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.ReadDetailDto{} + dto.Id = uint64(id) + res, err := u.Submit(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/use-case/main-use-case/procedure-room-order/case.go b/internal/use-case/main-use-case/procedure-room-order/case.go index 0724ce94..7e9e1952 100644 --- a/internal/use-case/main-use-case/procedure-room-order/case.go +++ b/internal/use-case/main-use-case/procedure-room-order/case.go @@ -1,16 +1,19 @@ package procedureroomorder import ( - e "simrs-vx/internal/domain/main-entities/procedure-room-order" + "errors" "strconv" + "gorm.io/gorm" + dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" - "gorm.io/gorm" + e "simrs-vx/internal/domain/main-entities/procedure-room-order" + erc "simrs-vx/internal/domain/references/common" ) const source = "procedure-room-order" @@ -274,3 +277,62 @@ func Delete(input e.DeleteDto) (*d.Data, error) { }, nil } + +func Submit(input e.ReadDetailDto) (*d.Data, error) { + var data *e.ProcedureRoomOrder + var err error + + event := pl.Event{ + Feature: "Process", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "process") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + data, err = ReadDetailData(input, &event, tx) + if err != nil { + return err + } + + if data.IsNotNew() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-state-mismatch", + Detail: source + " is not in new state", + Raw: errors.New(source + " is not in new state"), + } + return pl.SetLogError(&event, input) + } + + data.Status_Code = erc.DSCSubmited + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "submited", + }, + Data: data.ToResponse(), + }, nil + +} From 521dbdd0a436f13e2d2be2e33a32bf730c6a5c2c Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 4 Dec 2025 11:13:08 +0700 Subject: [PATCH 325/329] fix (encounter): fix list --- internal/use-case/main-use-case/encounter/lib.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index 0ea8988d..a9a5a307 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -67,7 +67,7 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.En if input.StartDate != nil && input.EndDate != nil { tx = tx.Where( - "DATE(\"RegisteredAt\") >= DATE(?) AND DATE(\"RegisteredAt\") <= DATE(?)", + "DATE(\"Encounter\".\"RegisteredAt\") >= DATE(?) AND DATE(\"Encounter\".\"RegisteredAt\") <= DATE(?)", input.StartDate, input.EndDate, ) From 91e40cc2b747babde0af59f8156e2371542a3654 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 4 Dec 2025 13:11:54 +0700 Subject: [PATCH 326/329] fix (referral): typo json --- internal/domain/bpjs-entities/referral/entity.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/domain/bpjs-entities/referral/entity.go b/internal/domain/bpjs-entities/referral/entity.go index 8977ee31..680400b6 100644 --- a/internal/domain/bpjs-entities/referral/entity.go +++ b/internal/domain/bpjs-entities/referral/entity.go @@ -81,8 +81,8 @@ type Mr struct { } type Provider struct { - Kode string `json:"kdProvider" json:"kode"` // API sometimes uses different keys - NmProvider string `json:"nmProvider" json:"nama"` + Kode string `son:"kode"` + NmProvider string `json:"nama"` } type Poli struct { From 935cc8aef5a3cde6f107be73d70a84fa685338da Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Fri, 5 Dec 2025 14:04:56 +0700 Subject: [PATCH 327/329] feat (encounter): add more filter for list --- .../domain/main-entities/encounter/dto.go | 14 +++++----- .../use-case/main-use-case/encounter/lib.go | 26 ++++++++++++++++--- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index c039fc0c..9b007097 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -78,11 +78,14 @@ type TRujukan struct { type ReadListDto struct { FilterDto - Includes string `json:"includes"` - Pagination ecore.Pagination - Person_Name *string `json:"person-name"` - StartDate *string `json:"start-date"` - EndDate *string `json:"end-date"` + Includes string `json:"includes"` + Pagination ecore.Pagination + Patient_Identifier *string `json:"patient-identifier"` + StartDate *string `json:"start-date"` + EndDate *string `json:"end-date"` + PaymentMethod_Code *string `json:"paymentMethod-code"` + Status_Code *string `json:"status-code"` + Unit_Code *string `json:"unit-code"` pa.AuthInfo } @@ -92,7 +95,6 @@ type FilterDto struct { Patient *ep.Patient `json:"patient,omitempty"` RegisteredAt *time.Time `json:"registeredAt"` Class_Code ere.EncounterClassCode `json:"class-code" validate:"maxLength=10"` - Unit_Code *string `json:"unit-code"` Specialist_Code *string `json:"specialist-code"` Subspecialist_Code *string `json:"subspecialist-code"` VisitDate time.Time `json:"visitDate"` diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index a9a5a307..3baec23a 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -73,17 +73,35 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.En ) } - if input.Person_Name != nil { + if input.Patient_Identifier != nil { tx = tx.Joins("JOIN \"Patient\" ON \"Patient\".\"Id\" = \"Encounter\".\"Patient_Id\""). - Joins("JOIN \"Person\" ON \"Person\".\"Id\" = \"Patient\".\"Person_Id\"").Where("\"Person\".\"Name\" ILIKE ?", "%"+*input.Person_Name+"%") + Joins("JOIN \"Person\" ON \"Person\".\"Id\" = \"Patient\".\"Person_Id\"").Where("\"Person\".\"Name\" ILIKE ? OR \"Patient\".\"Number\" = ?", "%"+*input.Patient_Identifier+"%", *input.Patient_Identifier) } - tx = tx.Debug().Scopes(gh.Preload(input.Includes)). - Scopes(gh.Filter(input.FilterDto)). + // TODO: getuk lib need to be updated to support this + if input.Status_Code != nil { + tx = tx.Where("\"Encounter\".\"Status_Code\" = ?", *input.Status_Code) + } + + if input.Unit_Code != nil { + tx = tx.Where("\"Encounter\".\"Unit_Code\" = ?", *input.Unit_Code) + } + + if input.PaymentMethod_Code != nil { + tx = tx.Where("\"Encounter\".\"PaymentMethod_Code\" = ?", *input.PaymentMethod_Code) + } + + tx = tx.Scopes(gh.Preload(input.Includes)). Count(&count). Scopes(gh.Paginate(input, &pagination)). Order("\"CreatedAt\" DESC") + // tx.Debug().Scopes(gh.Preload(input.Includes)). + // Scopes(gh.Filter(input.FilterDto)). + // Count(&count). + // Scopes(gh.Paginate(input, &pagination)). + // Order("\"CreatedAt\" DESC") + if err := tx.Find(&data).Error; err != nil { if err == gorm.ErrRecordNotFound { return nil, &meta, nil From 6c13b1ad517447c95bc1cf8cf9381749c224b8a2 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Fri, 5 Dec 2025 14:18:39 +0700 Subject: [PATCH 328/329] feat (item): fix get-detail by code --- internal/domain/main-entities/item/dto.go | 2 +- internal/use-case/main-use-case/item/lib.go | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/internal/domain/main-entities/item/dto.go b/internal/domain/main-entities/item/dto.go index 686a5c17..53e3c763 100644 --- a/internal/domain/main-entities/item/dto.go +++ b/internal/domain/main-entities/item/dto.go @@ -33,7 +33,7 @@ type FilterDto struct { } type ReadDetailDto struct { - Id *uint16 `json:"id"` + Id *uint `json:"id"` Code *string `json:"code"` } diff --git a/internal/use-case/main-use-case/item/lib.go b/internal/use-case/main-use-case/item/lib.go index 56c4c915..a58a956b 100644 --- a/internal/use-case/main-use-case/item/lib.go +++ b/internal/use-case/main-use-case/item/lib.go @@ -81,7 +81,15 @@ 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 input.Code != nil { + tx = tx.Where("\"Code\" = ?", *input.Code) + } + + if input.Id != nil { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { return nil, processedErr } From 5bc3c8783ee012e5999ba0cd7a2ba01104a758b9 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Fri, 5 Dec 2025 16:08:22 +0700 Subject: [PATCH 329/329] feat (item): update handle buying price and selling price --- internal/domain/main-entities/item/dto.go | 2 ++ internal/use-case/main-use-case/item/helper.go | 2 ++ 2 files changed, 4 insertions(+) diff --git a/internal/domain/main-entities/item/dto.go b/internal/domain/main-entities/item/dto.go index 53e3c763..a25c5a7a 100644 --- a/internal/domain/main-entities/item/dto.go +++ b/internal/domain/main-entities/item/dto.go @@ -13,6 +13,8 @@ type CreateDto struct { Uom_Code *string `json:"uom_code" validate:"maxLength=10"` Infra_Code *string `json:"infra_code"` Stock *int `json:"stock"` + BuyingPrice *float64 `json:"buyingPrice"` + SellingPrice *float64 `json:"sellingPrice"` } type ReadListDto struct { diff --git a/internal/use-case/main-use-case/item/helper.go b/internal/use-case/main-use-case/item/helper.go index 6f7e0c57..2de4c1bd 100644 --- a/internal/use-case/main-use-case/item/helper.go +++ b/internal/use-case/main-use-case/item/helper.go @@ -23,4 +23,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Item) { data.Uom_Code = inputSrc.Uom_Code data.Infra_Code = inputSrc.Infra_Code data.Stock = inputSrc.Stock + data.BuyingPrice = inputSrc.BuyingPrice + data.SellingPrice = inputSrc.SellingPrice }