Files
cpone_midleware/internal/http/medrec.go

242 lines
7.8 KiB
Go

package http
import (
"errors"
"net/http"
"regexp"
"strings"
"time"
"primaya-api/cpone-middleware/internal/repository"
)
var (
spaces = regexp.MustCompile(`\s+`)
nonAlphaNumber = regexp.MustCompile(`[^A-Za-z0-9]`)
nonDigit = regexp.MustCompile(`\D`)
ktpNumber = regexp.MustCompile(`^\d{16}$`)
emailAddress = regexp.MustCompile(`^[^\s@]+@[^\s@]+\.[^\s@]+$`)
)
type MedrecResponse struct {
Success bool `json:"success"`
Status string `json:"status"`
Message string `json:"message"`
Data any `json:"data"`
}
func (h Handler) StoreMedrec(w http.ResponseWriter, r *http.Request) {
payload, _ := decodeJSONObject(r)
params, message := validateMedrec(payload)
if message != "" {
writeMedrecResponse(w, http.StatusUnprocessableEntity, false, "validation_error", message, nil)
return
}
params.HospitalCode = h.hospitalCode
outcome, err := h.patientRepository(r.Context()).StoreMedrec(r.Context(), params)
if err != nil {
var validationErr repository.ValidationError
if errors.As(err, &validationErr) {
writeMedrecResponse(w, http.StatusUnprocessableEntity, false, "validation_error", validationErr.Message, nil)
return
}
writeMedrecResponse(w, http.StatusInternalServerError, false, "error", err.Error(), nil)
return
}
writeMedrecResponse(w, outcome.HTTPStatus, outcome.Success, outcome.Status, outcome.Message, outcome.Data)
}
func validateMedrec(payload map[string]any) (repository.MedrecParams, string) {
name, message := requiredString(payload, "nama", 255, "Nama pasien wajib diisi")
if message != "" {
return repository.MedrecParams{}, message
}
gender, message := requiredString(payload, "jenis_kelamin", 0, "Jenis kelamin wajib diisi")
if message != "" {
return repository.MedrecParams{}, message
}
if gender != "L" && gender != "P" && gender != "l" && gender != "p" {
return repository.MedrecParams{}, "Jenis kelamin harus L atau P"
}
dateOfBirth, message := requiredString(payload, "tgl_lahir", 0, "Tanggal lahir wajib diisi")
if message != "" {
return repository.MedrecParams{}, message
}
jakarta, err := time.LoadLocation("Asia/Jakarta")
if err != nil {
return repository.MedrecParams{}, err.Error()
}
birthDate, err := time.ParseInLocation("2006-01-02", dateOfBirth, jakarta)
if err != nil || birthDate.Format("2006-01-02") != dateOfBirth {
return repository.MedrecParams{}, "Tanggal lahir harus format Y-m-d"
}
now := time.Now().In(jakarta)
today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, jakarta)
if birthDate.After(today) {
return repository.MedrecParams{}, "Tanggal lahir tidak boleh lebih dari hari ini"
}
identityType, present, message := optionalString(payload, "jenis_nomer_sosial", 20)
if message != "" {
return repository.MedrecParams{}, message
}
if !present || identityType == "" {
identityType = "KTP"
}
identityNumber, identityPresent, message := optionalString(payload, "nomer_sosial", 50)
if message != "" {
return repository.MedrecParams{}, message
}
nik, nikPresent, message := optionalString(payload, "nik", 50)
if message != "" {
return repository.MedrecParams{}, message
}
if !identityPresent || identityNumber == "" {
if nikPresent {
identityNumber = nik
}
}
phone, phonePresent, message := optionalString(payload, "telepon", 30)
if message != "" {
return repository.MedrecParams{}, message
}
mobile, mobilePresent, message := optionalString(payload, "ponsel", 30)
if message != "" {
return repository.MedrecParams{}, message
}
if !phonePresent && !mobilePresent {
return repository.MedrecParams{}, "Telepon atau ponsel wajib diisi"
}
email, _, message := optionalString(payload, "email", 255)
if message != "" {
return repository.MedrecParams{}, message
}
if email != "" && !emailAddress.MatchString(strings.TrimSpace(email)) {
return repository.MedrecParams{}, "The email must be a valid email address."
}
placeOfBirth, message := optionalMedrecString(payload, "tempat_lahir", 100)
if message != "" {
return repository.MedrecParams{}, message
}
address, message := optionalMedrecString(payload, "alamat", 500)
if message != "" {
return repository.MedrecParams{}, message
}
province, message := optionalMedrecString(payload, "propinsi", 50)
if message != "" {
return repository.MedrecParams{}, message
}
city, message := optionalMedrecString(payload, "kabupaten", 50)
if message != "" {
return repository.MedrecParams{}, message
}
district, message := optionalMedrecString(payload, "kecamatan", 50)
if message != "" {
return repository.MedrecParams{}, message
}
village, message := optionalMedrecString(payload, "kelurahan", 50)
if message != "" {
return repository.MedrecParams{}, message
}
postalCode, message := optionalMedrecString(payload, "kode_pos", 20)
if message != "" {
return repository.MedrecParams{}, message
}
companyID, message := optionalMedrecString(payload, "perusahaan_id", 50)
if message != "" {
return repository.MedrecParams{}, message
}
employeeID, message := optionalMedrecString(payload, "nik_karyawan", 50)
if message != "" {
return repository.MedrecParams{}, message
}
dependantID, message := optionalMedrecString(payload, "dependant_id", 4)
if message != "" {
return repository.MedrecParams{}, message
}
employeeName, message := optionalMedrecString(payload, "nama_karyawan", 100)
if message != "" {
return repository.MedrecParams{}, message
}
channel, channelPresent, message := optionalString(payload, "channel", 50)
if message != "" {
return repository.MedrecParams{}, message
}
if !channelPresent || channel == "" {
channel = "CPONE"
}
identityType = normalizeText(identityType)
identityNumber = normalizeIdentity(identityNumber)
if identityNumber == "" {
return repository.MedrecParams{}, "NIK/nomer_sosial wajib diisi"
}
if identityType == "KTP" && !ktpNumber.MatchString(identityNumber) {
return repository.MedrecParams{}, "NIK/KTP harus 16 digit angka"
}
phone = normalizePhone(phone)
mobile = normalizePhone(mobile)
if phone == "" && mobile == "" {
return repository.MedrecParams{}, "Telepon atau ponsel wajib diisi"
}
return repository.MedrecParams{
Name: normalizeName(name),
Gender: normalizeText(gender),
DateOfBirth: birthDate,
IdentityType: identityType,
IdentityNumber: identityNumber,
Phone: phone,
Mobile: mobile,
Email: strings.ToLower(strings.TrimSpace(email)),
PlaceOfBirth: normalizeName(placeOfBirth),
Address: strings.TrimSpace(address),
Province: strings.TrimSpace(province),
City: strings.TrimSpace(city),
District: strings.TrimSpace(district),
Village: strings.TrimSpace(village),
PostalCode: strings.TrimSpace(postalCode),
CompanyID: strings.TrimSpace(companyID),
EmployeeID: strings.TrimSpace(employeeID),
DependantID: strings.TrimSpace(dependantID),
EmployeeName: strings.TrimSpace(employeeName),
Channel: normalizeText(channel),
}, ""
}
func optionalMedrecString(payload map[string]any, key string, maxLength int) (string, string) {
value, _, message := optionalString(payload, key, maxLength)
return value, message
}
func normalizeName(value string) string {
return strings.ToUpper(strings.TrimSpace(spaces.ReplaceAllString(value, " ")))
}
func normalizeText(value string) string {
return strings.ToUpper(strings.TrimSpace(value))
}
func normalizeIdentity(value string) string {
return strings.ToUpper(nonAlphaNumber.ReplaceAllString(value, ""))
}
func normalizePhone(value string) string {
phone := nonDigit.ReplaceAllString(value, "")
if strings.HasPrefix(phone, "62") {
return "0" + strings.TrimPrefix(phone, "62")
}
return phone
}
func writeMedrecResponse(w http.ResponseWriter, statusCode int, success bool, status, message string, data any) {
WriteJSON(w, statusCode, MedrecResponse{Success: success, Status: status, Message: message, Data: data})
}