feat (patient): rework search

This commit is contained in:
dpurbosakti
2025-10-24 16:21:57 +07:00
parent 8a9e0c7b7f
commit 4ebeee02f0
5 changed files with 103 additions and 29 deletions
+2 -2
View File
@@ -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 {
@@ -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,
})
@@ -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)
}
@@ -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
+52 -19
View File
@@ -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
}