Merge pull request #12 from anxi0uz/feature/back-12
geocoding added, but working so-so, need to fix some lines
This commit is contained in:
1
go.mod
1
go.mod
@@ -28,6 +28,7 @@ require (
|
|||||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
|
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
|
github.com/doppiogancio/go-nominatim v2.0.1+incompatible // indirect
|
||||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||||
github.com/gosimple/unidecode v1.0.1 // indirect
|
github.com/gosimple/unidecode v1.0.1 // indirect
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -13,6 +13,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||||
|
github.com/doppiogancio/go-nominatim v2.0.1+incompatible h1:S0PYXIVKwV6vF+JNBSO6T7BdvH4Ktuaf5HVL51i0lyQ=
|
||||||
|
github.com/doppiogancio/go-nominatim v2.0.1+incompatible/go.mod h1:lePiHgediF5zQ6qRyynsDoilUOBVFSpOpsWiDd21Dic=
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||||
|
|||||||
@@ -258,21 +258,16 @@ components:
|
|||||||
|
|
||||||
WarehouseCreate:
|
WarehouseCreate:
|
||||||
type: object
|
type: object
|
||||||
required: [name, address]
|
required: [name, address, city]
|
||||||
properties:
|
properties:
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
address:
|
address:
|
||||||
type: string
|
type: string
|
||||||
|
description: Улица и номер дома
|
||||||
city:
|
city:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
description: Город — используется вместе с address для геокодинга
|
||||||
latitude:
|
|
||||||
type: number
|
|
||||||
nullable: true
|
|
||||||
longitude:
|
|
||||||
type: number
|
|
||||||
nullable: true
|
|
||||||
|
|
||||||
WarehouseUpdate:
|
WarehouseUpdate:
|
||||||
type: object
|
type: object
|
||||||
|
|||||||
@@ -314,10 +314,11 @@ type VehicleUpdateStatus string
|
|||||||
|
|
||||||
// WarehouseCreate defines model for WarehouseCreate.
|
// WarehouseCreate defines model for WarehouseCreate.
|
||||||
type WarehouseCreate struct {
|
type WarehouseCreate struct {
|
||||||
|
// Address Улица и номер дома
|
||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
City *string `json:"city,omitempty"`
|
|
||||||
Latitude *float32 `json:"latitude,omitempty"`
|
// City Город — используется вместе с address для геокодинга
|
||||||
Longitude *float32 `json:"longitude,omitempty"`
|
City string `json:"city"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,152 @@
|
|||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/anxi0uz/logiflow/internal/api"
|
"github.com/anxi0uz/logiflow/internal/api"
|
||||||
|
"github.com/anxi0uz/logiflow/internal/models"
|
||||||
|
storage "github.com/anxi0uz/logiflow/pkg"
|
||||||
|
"github.com/google/uuid"
|
||||||
openapi_types "github.com/oapi-codegen/runtime/types"
|
openapi_types "github.com/oapi-codegen/runtime/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) ListOrders(w http.ResponseWriter, r *http.Request, params api.ListOrdersParams) {}
|
func (s *Server) ListOrders(w http.ResponseWriter, r *http.Request, params api.ListOrdersParams) {}
|
||||||
|
|
||||||
func (s *Server) CreateOrder(w http.ResponseWriter, r *http.Request) {}
|
func (s *Server) CreateOrder(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
claims, ok := ctx.Value("user").(*Claims)
|
||||||
|
if !ok {
|
||||||
|
slog.ErrorContext(ctx, "error while casting claims")
|
||||||
|
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var req api.OrderCreate
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||||
|
s.JSON(w, r, http.StatusBadRequest, MsgInvalidBody, RespError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
originLat, originLon, err := s.geocode(ctx, *req.OriginAddress)
|
||||||
|
if err != nil {
|
||||||
|
slog.ErrorContext(ctx, "Failed to geocode origin", slog.String("error", err.Error()))
|
||||||
|
s.JSON(w, r, http.StatusBadRequest, "Не удалось определить координаты адреса отправки", RespError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
destLat, destLon, err := s.geocode(ctx, req.DestinationAddress)
|
||||||
|
if err != nil {
|
||||||
|
slog.ErrorContext(ctx, "Failed to geocode destination", slog.String("error", err.Error()))
|
||||||
|
s.JSON(w, r, http.StatusBadRequest, "Не удалось определить координаты адреса назначения", RespError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
osrmURL := fmt.Sprintf(
|
||||||
|
"http://router.project-osrm.org/route/v1/driving/%f,%f;%f,%f?overview=full&geometries=geojson",
|
||||||
|
originLon, originLat, destLon, destLat,
|
||||||
|
)
|
||||||
|
osrmReq, _ := http.NewRequestWithContext(ctx, http.MethodGet, osrmURL, nil)
|
||||||
|
osrmReq.Header.Set("User-Agent", "logiflow/1.0")
|
||||||
|
|
||||||
|
osrmResp, err := http.DefaultClient.Do(osrmReq)
|
||||||
|
if err != nil {
|
||||||
|
slog.ErrorContext(ctx, "OSRM request failed", slog.String("error", err.Error()))
|
||||||
|
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer osrmResp.Body.Close()
|
||||||
|
|
||||||
|
var osrmResult struct {
|
||||||
|
Routes []struct {
|
||||||
|
Geometry struct {
|
||||||
|
Coordinates [][]float64 `json:"coordinates"`
|
||||||
|
} `json:"geometry"`
|
||||||
|
Distance float64 `json:"distance"`
|
||||||
|
Duration float64 `json:"duration"`
|
||||||
|
} `json:"routes"`
|
||||||
|
}
|
||||||
|
if err := json.NewDecoder(osrmResp.Body).Decode(&osrmResult); err != nil || len(osrmResult.Routes) == 0 {
|
||||||
|
s.JSON(w, r, http.StatusBadRequest, "Не удалось построить маршрут", RespError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
route := osrmResult.Routes[0]
|
||||||
|
distanceKm := route.Distance / 1000
|
||||||
|
|
||||||
|
var weightKm, volumeM3 float64
|
||||||
|
if req.WeightKg != nil {
|
||||||
|
weightKm = float64(*req.WeightKg)
|
||||||
|
}
|
||||||
|
if req.VolumeM3 != nil {
|
||||||
|
volumeM3 = float64(*req.VolumeM3)
|
||||||
|
}
|
||||||
|
price := s.Config.Pricing.BaseFee + distanceKm*s.Config.Pricing.PerKg + weightKm*s.Config.Pricing.PerKg + volumeM3*s.Config.Pricing.PerM3
|
||||||
|
|
||||||
|
now := time.Now
|
||||||
|
orderID := uuid.New()
|
||||||
|
order := models.Order{
|
||||||
|
ID: orderID,
|
||||||
|
CreatedByID: &claims.ID,
|
||||||
|
DestinationAddress: req.DestinationAddress,
|
||||||
|
Status: "pending",
|
||||||
|
TotalPrice: price,
|
||||||
|
CreatedAt: now(),
|
||||||
|
}
|
||||||
|
if *req.OriginAddress != "" {
|
||||||
|
order.OriginAddress = *req.OriginAddress
|
||||||
|
}
|
||||||
|
if req.CargoDescription != nil {
|
||||||
|
order.CargoDescription = *req.CargoDescription
|
||||||
|
}
|
||||||
|
if req.WeightKg != nil {
|
||||||
|
order.WeightKg = float64(*req.WeightKg)
|
||||||
|
}
|
||||||
|
if req.VolumeM3 != nil {
|
||||||
|
order.VolumeM3 = volumeM3
|
||||||
|
}
|
||||||
|
coordsJSON, err := json.Marshal(route.Geometry.Coordinates)
|
||||||
|
if err != nil {
|
||||||
|
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
routeModel := models.Route{
|
||||||
|
ID: uuid.New(),
|
||||||
|
OrderID: orderID,
|
||||||
|
Coordinates: coordsJSON,
|
||||||
|
DurationSec: int(route.Duration),
|
||||||
|
Status: "pending",
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := s.DB.Begin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer tx.Rollback(ctx)
|
||||||
|
|
||||||
|
if err := storage.Create(ctx, "orders", order, tx); err != nil {
|
||||||
|
slog.ErrorContext(ctx, "Failed to create order", slog.String("error", err.Error()))
|
||||||
|
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := storage.Create(ctx, "routes", routeModel, tx); err != nil {
|
||||||
|
slog.ErrorContext(ctx, "Failed to create route", slog.String("error", err.Error()))
|
||||||
|
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Commit(ctx); err != nil {
|
||||||
|
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s.JSON(w, r, http.StatusCreated, map[string]any{
|
||||||
|
"order": order,
|
||||||
|
"route": routeModel,
|
||||||
|
}, "order")
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) GetOrder(w http.ResponseWriter, r *http.Request, id openapi_types.UUID) {}
|
func (s *Server) GetOrder(w http.ResponseWriter, r *http.Request, id openapi_types.UUID) {}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
neturl "net/url"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/anxi0uz/logiflow/internal/api"
|
"github.com/anxi0uz/logiflow/internal/api"
|
||||||
@@ -234,3 +236,36 @@ func (s *Server) validateAccessToken(ctx context.Context, tokenStr string) (*Cla
|
|||||||
|
|
||||||
return claims, nil
|
return claims, nil
|
||||||
}
|
}
|
||||||
|
func (s *Server) geocode(ctx context.Context, address string) (lat, lon float64, err error) {
|
||||||
|
url := fmt.Sprintf(
|
||||||
|
"https://nominatim.openstreetmap.org/search?q=%s&format=json&limit=1",
|
||||||
|
neturl.QueryEscape(address),
|
||||||
|
)
|
||||||
|
|
||||||
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
req.Header.Set("User-Agent", "logiflow/1.0")
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
var results []struct {
|
||||||
|
Lat string `json:"lat"`
|
||||||
|
Lon string `json:"lon"`
|
||||||
|
}
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&results); err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
if len(results) == 0 {
|
||||||
|
return 0, 0, fmt.Errorf("address not found: %s", address)
|
||||||
|
}
|
||||||
|
|
||||||
|
lat, _ = strconv.ParseFloat(results[0].Lat, 64)
|
||||||
|
lon, _ = strconv.ParseFloat(results[0].Lon, 64)
|
||||||
|
return lat, lon, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package handler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
@@ -11,9 +13,20 @@ import (
|
|||||||
storage "github.com/anxi0uz/logiflow/pkg"
|
storage "github.com/anxi0uz/logiflow/pkg"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/gosimple/slug"
|
"github.com/gosimple/slug"
|
||||||
|
"github.com/huandu/go-sqlbuilder"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) ListWarehouses(w http.ResponseWriter, r *http.Request) {}
|
func (s *Server) ListWarehouses(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
|
||||||
|
warehouses, err := storage.GetAll[models.Warehouse](ctx, "warehouses", s.DB)
|
||||||
|
if err != nil {
|
||||||
|
slog.ErrorContext(ctx, "Error while getting all warehouses", slog.String("error", err.Error()))
|
||||||
|
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.JSON(w, r, http.StatusOK, warehouses, RespSuccess)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) CreateWarehouse(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) CreateWarehouse(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
@@ -24,16 +37,24 @@ func (s *Server) CreateWarehouse(w http.ResponseWriter, r *http.Request) {
|
|||||||
s.JSON(w, r, http.StatusBadRequest, MsgInvalidBody, RespError)
|
s.JSON(w, r, http.StatusBadRequest, MsgInvalidBody, RespError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
fullAddress := fmt.Sprintf("%s, %s", req.City, req.Address)
|
||||||
|
lat, lon, err := s.geocode(ctx, fullAddress)
|
||||||
|
if err != nil {
|
||||||
|
slog.ErrorContext(ctx, "Failed to geocode address", slog.String("address", req.Address), slog.String("error", err.Error()))
|
||||||
|
s.JSON(w, r, http.StatusBadRequest, "Не удалось определить координаты по адресу", RespError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
id := uuid.New()
|
id := uuid.New()
|
||||||
warehouse := models.Warehouse{
|
warehouse := models.Warehouse{
|
||||||
ID: id,
|
ID: id,
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
Address: req.Address,
|
Address: req.Address,
|
||||||
City: *req.City,
|
City: req.City,
|
||||||
Slug: slug.Make(req.Name),
|
Slug: slug.Make(req.Name),
|
||||||
Latitude: float64(*req.Latitude),
|
Latitude: lat,
|
||||||
Longitude: float64(*req.Longitude),
|
Longitude: lon,
|
||||||
CreatedAt: now,
|
CreatedAt: now,
|
||||||
}
|
}
|
||||||
if err := storage.Create(ctx, "warehouses", warehouse, s.DB); err != nil {
|
if err := storage.Create(ctx, "warehouses", warehouse, s.DB); err != nil {
|
||||||
@@ -44,8 +65,74 @@ func (s *Server) CreateWarehouse(w http.ResponseWriter, r *http.Request) {
|
|||||||
s.JSON(w, r, http.StatusCreated, warehouse, RespSuccess)
|
s.JSON(w, r, http.StatusCreated, warehouse, RespSuccess)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) GetWarehouse(w http.ResponseWriter, r *http.Request, slug string) {}
|
func (s *Server) GetWarehouse(w http.ResponseWriter, r *http.Request, slug string) {
|
||||||
|
ctx := r.Context()
|
||||||
|
|
||||||
func (s *Server) UpdateWarehouse(w http.ResponseWriter, r *http.Request, slug string) {}
|
warehouse, err := storage.GetOne[models.Warehouse](ctx, s.DB, "warehouses", func(sb *sqlbuilder.SelectBuilder) {
|
||||||
|
sb.Where(sb.EQ("slug", slug))
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, storage.ErrNotFound) {
|
||||||
|
slog.WarnContext(ctx, "No warehouse with that slug was found", slog.String("slug", slug))
|
||||||
|
s.JSON(w, r, http.StatusNotFound, MsgNotFound, RespNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
slog.ErrorContext(ctx, "Error while getting warehouse", slog.String("slug", slug), slog.String("error", err.Error()))
|
||||||
|
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.JSON(w, r, http.StatusOK, warehouse, RespSuccess)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) DeleteWarehouse(w http.ResponseWriter, r *http.Request, slug string) {}
|
func (s *Server) UpdateWarehouse(w http.ResponseWriter, r *http.Request, slug string) {
|
||||||
|
ctx := r.Context()
|
||||||
|
var req api.WarehouseUpdate
|
||||||
|
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||||
|
slog.ErrorContext(ctx, "Invalid json body", slog.String("error", err.Error()))
|
||||||
|
s.JSON(w, r, http.StatusBadRequest, MsgInvalidBody, RespError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
warehouse, err := storage.GetOne[models.Warehouse](ctx, s.DB, "warehouses", func(sb *sqlbuilder.SelectBuilder) {
|
||||||
|
sb.Where(sb.Equal("slug", slug))
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, storage.ErrNotFound) {
|
||||||
|
slog.WarnContext(ctx, "No warehouse with that slug was found", slog.String("slug", slug), slog.String("error", err.Error()))
|
||||||
|
s.JSON(w, r, http.StatusNotFound, MsgNotFound, RespNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
slog.ErrorContext(ctx, "Error while getting warehouse with that slug", slog.String("slug", slug), slog.String("error", err.Error()))
|
||||||
|
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
warehouse.Address = *req.Address
|
||||||
|
warehouse.City = *req.City
|
||||||
|
warehouse.Latitude = float64(*req.Latitude)
|
||||||
|
warehouse.Longitude = float64(*req.Longitude)
|
||||||
|
warehouse.Status = string(*req.Status)
|
||||||
|
warehouse.Name = *req.Name
|
||||||
|
if err := storage.Update(ctx, "warehouses", warehouse, s.DB, func(sb *sqlbuilder.UpdateBuilder) {
|
||||||
|
sb.Where(sb.Equal("slug", slug))
|
||||||
|
}); err != nil {
|
||||||
|
slog.ErrorContext(ctx, "Error while updating warehouse with that slug", slog.String("slug", slug), slog.String("error", err.Error()))
|
||||||
|
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.JSON(w, r, http.StatusOK, warehouse, RespSuccess)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) DeleteWarehouse(w http.ResponseWriter, r *http.Request, slug string) {
|
||||||
|
ctx := r.Context()
|
||||||
|
|
||||||
|
if err := storage.Delete[models.Warehouse](ctx, "warehouses", s.DB, func(sb *sqlbuilder.DeleteBuilder) {
|
||||||
|
sb.Where(sb.EQ("slug", slug))
|
||||||
|
}); err != nil {
|
||||||
|
slog.ErrorContext(ctx, "Error while deleting warehoue", slog.String("slug", slug), slog.String("error", err.Error()))
|
||||||
|
s.JSON(w, r, http.StatusInternalServerError, MsgInternalError, RespError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s.JSON(w, r, http.StatusOK, slug, RespSuccess)
|
||||||
|
}
|
||||||
|
|||||||
@@ -85,15 +85,11 @@ func GetOne[T any](ctx context.Context, db Querier, table string, opts ...func(*
|
|||||||
func Create[T any](ctx context.Context, table string, item T, db Querier, opts ...func(*sqlbuilder.SelectBuilder)) error {
|
func Create[T any](ctx context.Context, table string, item T, db Querier, opts ...func(*sqlbuilder.SelectBuilder)) error {
|
||||||
structs := sqlbuilder.NewStruct(new(T))
|
structs := sqlbuilder.NewStruct(new(T))
|
||||||
|
|
||||||
slog.Info("Items", slog.Any("Item", item))
|
|
||||||
|
|
||||||
sb := structs.WithoutTag("db", "-").InsertInto(table, item)
|
sb := structs.WithoutTag("db", "-").InsertInto(table, item)
|
||||||
sb.SetFlavor(sqlbuilder.PostgreSQL)
|
sb.SetFlavor(sqlbuilder.PostgreSQL)
|
||||||
|
|
||||||
query, args := sb.Build()
|
query, args := sb.Build()
|
||||||
|
|
||||||
slog.Info("Query", slog.String("query", query), slog.Any("args", args))
|
|
||||||
|
|
||||||
if _, err := db.Exec(ctx, query, args...); err != nil {
|
if _, err := db.Exec(ctx, query, args...); err != nil {
|
||||||
slog.ErrorContext(ctx, "cannot create item",
|
slog.ErrorContext(ctx, "cannot create item",
|
||||||
slog.String("query", query),
|
slog.String("query", query),
|
||||||
|
|||||||
Reference in New Issue
Block a user