From b597b76092b58c3aa8f92efe4fca2941023895e1 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 6 Nov 2025 15:24:42 +0700 Subject: [PATCH] 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 }