Files
cpone_midleware/internal/http/paket.go

187 lines
5.3 KiB
Go

package http
import (
"net/http"
"net/url"
"strconv"
"strings"
"time"
"primaya-api/cpone-middleware/internal/repository"
)
type PaketValidationResponse struct {
Success bool `json:"success"`
Status string `json:"status"`
Message string `json:"message"`
Data any `json:"data"`
}
type PaketPaginationResponse struct {
CurrentPage int `json:"current_page"`
Data []repository.PaketSummary `json:"data"`
FirstPageURL string `json:"first_page_url"`
From *int `json:"from"`
LastPage int `json:"last_page"`
LastPageURL string `json:"last_page_url"`
Links map[string]any `json:"links"`
NextPageURL *string `json:"next_page_url"`
Total int `json:"total"`
PerPage int `json:"per_page"`
}
func (h Handler) ListPaket(w http.ResponseWriter, r *http.Request) {
params, message := parsePaketListParams(r)
if message != "" {
writePaketValidationError(w, message)
return
}
page, err := h.paketRepository(r.Context()).ListPaket(r.Context(), params)
if err != nil {
WriteJSON(w, http.StatusInternalServerError, Response{
Success: false, Message: "internal server error", Data: nil,
})
return
}
lastPage := (page.Total + params.PerPage - 1) / params.PerPage
if lastPage < 1 {
lastPage = 1
}
var from *int
if len(page.Items) > 0 {
value := (params.Page-1)*params.PerPage + 1
from = &value
}
var nextPageURL *string
if params.Page < lastPage {
value := currentRequestURL(r, params.Page+1)
nextPageURL = &value
}
WriteJSON(w, http.StatusOK, PaketPaginationResponse{
CurrentPage: params.Page,
Data: page.Items,
FirstPageURL: "",
From: from,
LastPage: lastPage,
LastPageURL: "",
Links: map[string]any{},
NextPageURL: nextPageURL,
Total: page.Total,
PerPage: params.PerPage,
})
}
func (h Handler) GetPaket(w http.ResponseWriter, r *http.Request) {
id := strings.TrimSpace(r.PathValue("id"))
paket, err := h.paketRepository(r.Context()).GetPaket(r.Context(), id)
if err != nil {
WriteJSON(w, http.StatusInternalServerError, Response{
Success: false, Message: "internal server error", Data: nil,
})
return
}
if paket == nil {
WriteJSON(w, http.StatusNotFound, Response{
Success: false, Message: "Data tidak ditemukan", Data: nil,
})
return
}
WriteJSON(w, http.StatusOK, Response{Success: true, Message: "ok", Data: paket})
}
func parsePaketListParams(r *http.Request) (repository.PaketListParams, string) {
query := r.URL.Query()
params := repository.PaketListParams{
Search: query.Get("search"), Code: query.Get("code"),
CareType: query.Get("care_type"), Active: query.Get("active"),
StartDate: query.Get("start_date"), EndDate: query.Get("end_date"),
Status: 2, Page: 1, PerPage: 15,
}
if params.CareType != "" && params.CareType != "RI" && params.CareType != "RJ" {
return params, "The selected care type is invalid."
}
if raw, exists := firstQueryValue(r, "status"); exists && raw != "" {
value, err := strconv.Atoi(raw)
if err != nil {
return params, "The status must be an integer."
}
if value < -1 || value > 2 {
return params, "The selected status is invalid."
}
params.Status = value
}
if params.Active != "" && params.Active != "N" && params.Active != "Y" {
return params, "The selected active is invalid."
}
if params.StartDate != "" {
if _, err := time.Parse("2006-01-02", params.StartDate); err != nil {
return params, "The start date does not match the format Y-m-d."
}
}
if params.EndDate != "" {
end, err := time.Parse("2006-01-02", params.EndDate)
if err != nil {
return params, "The end date does not match the format Y-m-d."
}
if params.StartDate != "" {
start, _ := time.Parse("2006-01-02", params.StartDate)
if end.Before(start) {
return params, "The end date must be a date after or equal to start date."
}
}
}
if raw, exists := firstQueryValue(r, "page"); exists && raw != "" {
value, err := strconv.Atoi(raw)
if err != nil {
return params, "The page must be an integer."
}
if value < 1 {
return params, "The page must be at least 1."
}
params.Page = value
}
if raw, exists := firstQueryValue(r, "per_page"); exists && raw != "" {
value, err := strconv.Atoi(raw)
if err != nil {
return params, "The per page must be an integer."
}
if value < 1 || value > 100 {
return params, "The per page must be between 1 and 100."
}
params.PerPage = value
}
return params, ""
}
func currentRequestURL(r *http.Request, page int) string {
scheme := "http"
if r.TLS != nil {
scheme = "https"
}
if forwarded := r.Header.Get("X-Forwarded-Proto"); forwarded != "" {
scheme = strings.TrimSpace(strings.Split(forwarded, ",")[0])
}
host := r.Host
if host == "" {
host = "localhost"
}
query := url.Values{}
if code := r.URL.Query().Get("kode_rs"); code != "" {
query.Set("kode_rs", code)
}
query.Set("page", strconv.Itoa(page))
return (&url.URL{Scheme: scheme, Host: host, Path: r.URL.Path, RawQuery: query.Encode()}).String()
}
func writePaketValidationError(w http.ResponseWriter, message string) {
WriteJSON(w, http.StatusUnprocessableEntity, PaketValidationResponse{
Success: false, Status: "validation_error", Message: message, Data: nil,
})
}