forked from ebhomengo/niki
feat(niki): add benefactor edit address
This commit is contained in:
parent
ec81297f98
commit
ba905cf334
|
@ -19,4 +19,6 @@ func (h Handler) SetRoutes(e *echo.Echo) {
|
|||
middleware.BenefactorAuthorization(entity.UserBenefactorRole))
|
||||
r.DELETE("/:id", h.DeleteAddress, middleware.Auth(h.authSvc, h.authConfig),
|
||||
middleware.BenefactorAuthorization(entity.UserBenefactorRole))
|
||||
r.PATCH("/:id", h.UpdateAddress, middleware.Auth(h.authSvc, h.authConfig),
|
||||
middleware.BenefactorAuthorization(entity.UserBenefactorRole))
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
package benefactoraddresshandler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
param "git.gocasts.ir/ebhomengo/niki/param/benefactor/address"
|
||||
"git.gocasts.ir/ebhomengo/niki/pkg/claim"
|
||||
httpmsg "git.gocasts.ir/ebhomengo/niki/pkg/http_msg"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// UpdateAddress godoc
|
||||
// @Summary Edit benefactor address
|
||||
// @Tags Address
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "Address ID"
|
||||
// @Param Request body param.UpdateAddressRequest true "Edit address details"
|
||||
// @Success 204
|
||||
// @Failure 400 {string} "Bad request"
|
||||
// @Security AuthBearerBenefactor
|
||||
// @Router /address/{id} [patch]
|
||||
func (h Handler) UpdateAddress(c echo.Context) error {
|
||||
var req param.UpdateAddressRequest
|
||||
if bErr := c.Bind(&req); bErr != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest)
|
||||
}
|
||||
fmt.Println(req)
|
||||
if bErr := echo.PathParamsBinder(c).Uint("id", &req.ID).BindError(); bErr != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest)
|
||||
}
|
||||
|
||||
claims := claim.GetClaimsFromEchoContext(c)
|
||||
req.BenefactorID = claims.UserID
|
||||
|
||||
if fieldErrors, err := h.addressVld.ValidateUpdateAddress(req); err != nil {
|
||||
msg, code := httpmsg.Error(err)
|
||||
|
||||
return c.JSON(code, echo.Map{
|
||||
"message": msg,
|
||||
"errors": fieldErrors,
|
||||
})
|
||||
}
|
||||
sErr := h.addressSvc.Update(c.Request().Context(), req)
|
||||
|
||||
if sErr != nil {
|
||||
msg, code := httpmsg.Error(sErr)
|
||||
|
||||
return echo.NewHTTPError(code, msg)
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusNoContent, nil)
|
||||
}
|
77
docs/docs.go
77
docs/docs.go
|
@ -221,6 +221,54 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/address/{id}": {
|
||||
"patch": {
|
||||
"security": [
|
||||
{
|
||||
"AuthBearerBenefactor": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Address"
|
||||
],
|
||||
"summary": "Edit benefactor address",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Address ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Edit address details",
|
||||
"name": "Request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/addressparam.UpdateAddressRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No Content"
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/admin/kindboxreqs": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
@ -942,6 +990,35 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"addressparam.UpdateAddressRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address": {
|
||||
"type": "string",
|
||||
"example": "Zanjan Province, Zanjan, Etemadieh, 6th St, Iran"
|
||||
},
|
||||
"city_id": {
|
||||
"type": "integer",
|
||||
"example": 163
|
||||
},
|
||||
"lat": {
|
||||
"type": "number",
|
||||
"example": 123.456
|
||||
},
|
||||
"lon": {
|
||||
"type": "number",
|
||||
"example": 123.456
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"example": "Home"
|
||||
},
|
||||
"postal_code": {
|
||||
"type": "string",
|
||||
"example": "1234567890"
|
||||
}
|
||||
}
|
||||
},
|
||||
"adminkindboxreqparam.AssignSenderRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
@ -210,6 +210,54 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/address/{id}": {
|
||||
"patch": {
|
||||
"security": [
|
||||
{
|
||||
"AuthBearerBenefactor": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Address"
|
||||
],
|
||||
"summary": "Edit benefactor address",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Address ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Edit address details",
|
||||
"name": "Request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/addressparam.UpdateAddressRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No Content"
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/admin/kindboxreqs": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
@ -931,6 +979,35 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"addressparam.UpdateAddressRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address": {
|
||||
"type": "string",
|
||||
"example": "Zanjan Province, Zanjan, Etemadieh, 6th St, Iran"
|
||||
},
|
||||
"city_id": {
|
||||
"type": "integer",
|
||||
"example": 163
|
||||
},
|
||||
"lat": {
|
||||
"type": "number",
|
||||
"example": 123.456
|
||||
},
|
||||
"lon": {
|
||||
"type": "number",
|
||||
"example": 123.456
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"example": "Home"
|
||||
},
|
||||
"postal_code": {
|
||||
"type": "string",
|
||||
"example": "1234567890"
|
||||
}
|
||||
}
|
||||
},
|
||||
"adminkindboxreqparam.AssignSenderRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
@ -51,6 +51,27 @@ definitions:
|
|||
$ref: '#/definitions/entity.Province'
|
||||
type: array
|
||||
type: object
|
||||
addressparam.UpdateAddressRequest:
|
||||
properties:
|
||||
address:
|
||||
example: Zanjan Province, Zanjan, Etemadieh, 6th St, Iran
|
||||
type: string
|
||||
city_id:
|
||||
example: 163
|
||||
type: integer
|
||||
lat:
|
||||
example: 123.456
|
||||
type: number
|
||||
lon:
|
||||
example: 123.456
|
||||
type: number
|
||||
name:
|
||||
example: Home
|
||||
type: string
|
||||
postal_code:
|
||||
example: "1234567890"
|
||||
type: string
|
||||
type: object
|
||||
adminkindboxreqparam.AssignSenderRequest:
|
||||
properties:
|
||||
sender_agent_id:
|
||||
|
@ -620,6 +641,36 @@ paths:
|
|||
summary: Get a benefactor address
|
||||
tags:
|
||||
- Address
|
||||
/address/{id}:
|
||||
patch:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: Address ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
- description: Edit address details
|
||||
in: body
|
||||
name: Request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/addressparam.UpdateAddressRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
"400":
|
||||
description: Bad request
|
||||
schema:
|
||||
type: string
|
||||
security:
|
||||
- AuthBearerBenefactor: []
|
||||
summary: Edit benefactor address
|
||||
tags:
|
||||
- Address
|
||||
/address/cities:
|
||||
get:
|
||||
consumes:
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package addressparam
|
||||
|
||||
type UpdateAddressRequest struct {
|
||||
ID uint `json:"-"`
|
||||
PostalCode string `json:"postal_code" example:"1234567890"`
|
||||
Address string `json:"address" example:"Zanjan Province, Zanjan, Etemadieh, 6th St, Iran"`
|
||||
Name string `json:"name" example:"Home"`
|
||||
Lat float64 `json:"lat" example:"123.456"`
|
||||
Lon float64 `json:"lon" example:"123.456"`
|
||||
CityID uint `json:"city_id" example:"163"`
|
||||
BenefactorID uint `json:"-"`
|
||||
}
|
|
@ -21,7 +21,10 @@ const (
|
|||
ErrorMsgAssignSenderAgentKindBoxReqStatus = "only accepted kind_box_reqs will have the ability to be assign sender agent"
|
||||
ErrorMsgDeliverKindBoxReqStatus = "only assigned requests will have the ability to be delivered"
|
||||
ErrorMsgAdminIsNotAgent = "admin is not agent"
|
||||
ErrorMsgCountAcceptedOverflow = "count accepted is greather than count requested"
|
||||
ErrorMsgCountAcceptedOverflow = "count accepted is greater than count requested"
|
||||
ErrorMsgCantInsertRecord = "can't insert record"
|
||||
ErrorMsgCantRetrieveLastInsertID = "can't retrieve last insert id"
|
||||
ErrorMsgCantUpdateRecord = "can't update record"
|
||||
ErrorMsgReferTimeNotFound = "refer time not found"
|
||||
ErrorMsgReferTimeIsNotActive = "refer time is not active"
|
||||
ErrorMsgKindBoxReqDoesntBelongToBenefactor = "kind box req doesnt belong to benefactor"
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package querybuilder
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// BuildUpdateQuery constructs a dynamic SQL update query based on the provided fields
|
||||
func BuildUpdateQuery(table string, fields map[string]interface{}, idField string, idValue interface{}) (string, []interface{}) {
|
||||
var setClauses []string
|
||||
var args []interface{}
|
||||
|
||||
for field, value := range fields {
|
||||
setClauses = append(setClauses, fmt.Sprintf("%s = ?", field))
|
||||
args = append(args, value)
|
||||
}
|
||||
|
||||
query := fmt.Sprintf("UPDATE %s SET %s WHERE %s = ?", table, strings.Join(setClauses, ", "), idField)
|
||||
args = append(args, idValue)
|
||||
|
||||
return query, args
|
||||
}
|
|
@ -10,14 +10,11 @@ import (
|
|||
)
|
||||
|
||||
func (d *DB) CreateBenefactorAddress(ctx context.Context, address entity.Address) (entity.Address, error) {
|
||||
const op = "mysqlbenefactor.createBenefactorAddress"
|
||||
const op = "mysqladdress.createBenefactorAddress"
|
||||
|
||||
// Get Province ID by City ID
|
||||
var provinceID uint
|
||||
pErr := d.conn.Conn().QueryRowContext(ctx, `SELECT province_id FROM cities WHERE id = ?`, address.CityID).Scan(&provinceID)
|
||||
if pErr != nil && pErr != sql.ErrNoRows {
|
||||
return entity.Address{}, richerror.New(op).WithErr(pErr).
|
||||
WithMessage("error querying for existing main address").WithKind(richerror.KindUnexpected)
|
||||
provinceID, err := d.getProvinceIDByCityID(ctx, address.CityID)
|
||||
if err != nil {
|
||||
return entity.Address{}, err
|
||||
}
|
||||
address.ProvinceID = provinceID
|
||||
|
||||
|
@ -26,16 +23,29 @@ func (d *DB) CreateBenefactorAddress(ctx context.Context, address entity.Address
|
|||
address.PostalCode, address.Address, address.Lat, address.Lon, address.Name, address.CityID, provinceID, address.BenefactorID)
|
||||
if err != nil {
|
||||
return entity.Address{}, richerror.New(op).WithErr(err).
|
||||
WithMessage(errmsg.ErrorMsgNotFound).WithKind(richerror.KindUnexpected)
|
||||
WithMessage(errmsg.ErrorMsgCantInsertRecord).WithKind(richerror.KindUnexpected)
|
||||
}
|
||||
|
||||
// Get the ID of the newly inserted record
|
||||
id, err := res.LastInsertId()
|
||||
if err != nil {
|
||||
return entity.Address{}, richerror.New(op).WithErr(err).
|
||||
WithMessage("error retrieving last insert id").WithKind(richerror.KindUnexpected)
|
||||
WithMessage(errmsg.ErrorMsgCantRetrieveLastInsertID).WithKind(richerror.KindUnexpected)
|
||||
}
|
||||
address.ID = uint(id)
|
||||
|
||||
return address, nil
|
||||
}
|
||||
|
||||
func (d *DB) getProvinceIDByCityID(ctx context.Context, cityID uint) (uint, error) {
|
||||
const op = "mysqladdress.getProvinceIDByCityID"
|
||||
|
||||
var provinceID uint
|
||||
pErr := d.conn.Conn().QueryRowContext(ctx, `SELECT province_id FROM cities WHERE id = ?`, cityID).Scan(&provinceID)
|
||||
if pErr != nil && pErr != sql.ErrNoRows {
|
||||
return 0, richerror.New(op).WithErr(pErr).
|
||||
WithMessage(errmsg.ErrorMsgCantScanQueryResult).WithKind(richerror.KindUnexpected)
|
||||
}
|
||||
|
||||
return provinceID, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
package mysqladdress
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.gocasts.ir/ebhomengo/niki/entity"
|
||||
errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
|
||||
querybuilder "git.gocasts.ir/ebhomengo/niki/pkg/query_builder"
|
||||
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||
)
|
||||
|
||||
func (d *DB) UpdateAddress(ctx context.Context, address entity.Address) error {
|
||||
const op = "mysqladdress.UpdateAddress"
|
||||
|
||||
fields := make(map[string]interface{})
|
||||
|
||||
if address.PostalCode != "" {
|
||||
fields["postal_code"] = address.PostalCode
|
||||
}
|
||||
if address.Address != "" {
|
||||
fields["address"] = address.Address
|
||||
}
|
||||
if address.Name != "" {
|
||||
fields["name"] = address.Name
|
||||
}
|
||||
if address.Lat != 0 {
|
||||
fields["lat"] = address.Lat
|
||||
}
|
||||
if address.Lon != 0 {
|
||||
fields["lon"] = address.Lon
|
||||
}
|
||||
if address.CityID != 0 {
|
||||
provinceID, err := d.getProvinceIDByCityID(ctx, address.CityID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fields["province_id"] = provinceID
|
||||
fields["city_id"] = address.CityID
|
||||
}
|
||||
|
||||
query, values := querybuilder.BuildUpdateQuery("addresses", fields, "id", address.ID)
|
||||
query += " and benefactor_id = ?"
|
||||
values = append(values, address.BenefactorID)
|
||||
_, err := d.conn.Conn().ExecContext(ctx, query, values...)
|
||||
if err != nil {
|
||||
return richerror.New(op).WithErr(err).WithMessage(errmsg.ErrorMsgCantUpdateRecord).
|
||||
WithKind(richerror.KindUnexpected)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -10,6 +10,7 @@ type Repository interface {
|
|||
GetAddressByID(ctx context.Context, id uint) (*entity.Address, error)
|
||||
GetAllProvinces(ctx context.Context) ([]entity.Province, error)
|
||||
GetAllCities(ctx context.Context) ([]entity.City, error)
|
||||
UpdateAddress(ctx context.Context, address entity.Address) error
|
||||
GetAddress(ctx context.Context, addressID uint, benefactorID uint) (entity.Address, error)
|
||||
GetAddresses(ctx context.Context, benefactorID uint) ([]entity.Address, error)
|
||||
DeleteBenefactorAddress(ctx context.Context, addressID uint, benefactorID uint) error
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package benefactoraddressservice
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.gocasts.ir/ebhomengo/niki/entity"
|
||||
param "git.gocasts.ir/ebhomengo/niki/param/benefactor/address"
|
||||
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||
)
|
||||
|
||||
func (s Service) Update(ctx context.Context, req param.UpdateAddressRequest) error {
|
||||
const op = "benefactoraddressservice.Update"
|
||||
|
||||
err := s.repo.UpdateAddress(ctx, entity.Address{
|
||||
ID: req.ID,
|
||||
PostalCode: req.PostalCode,
|
||||
Address: req.Address,
|
||||
Name: req.Name,
|
||||
Lat: req.Lat,
|
||||
Lon: req.Lon,
|
||||
CityID: req.CityID,
|
||||
BenefactorID: req.BenefactorID,
|
||||
})
|
||||
if err != nil {
|
||||
return richerror.New(op).WithErr(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package benefactoraddressvalidator
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
param "git.gocasts.ir/ebhomengo/niki/param/benefactor/address"
|
||||
errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
|
||||
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||
validation "github.com/go-ozzo/ozzo-validation/v4"
|
||||
)
|
||||
|
||||
func (v Validator) ValidateUpdateAddress(req param.UpdateAddressRequest) (map[string]string, error) {
|
||||
const op = "benefactoraddressvalidator.ValidateUpdateAddress"
|
||||
|
||||
if req.PostalCode == "" && req.Address == "" && req.Name == "" &&
|
||||
req.Lat == 0 && req.Lon == 0 && req.CityID == 0 {
|
||||
|
||||
return map[string]string{"update": "at least one field should be provided"}, richerror.New(op).
|
||||
WithMessage(errmsg.ErrorMsgInvalidInput).
|
||||
WithKind(richerror.KindInvalid).
|
||||
WithMeta(map[string]interface{}{"req": req}).
|
||||
WithErr(errors.New("at least one field should be provided"))
|
||||
}
|
||||
|
||||
if err := validation.ValidateStruct(&req,
|
||||
validation.Field(&req.BenefactorID, validation.Required,
|
||||
validation.By(v.doesBenefactorExist)),
|
||||
|
||||
validation.Field(&req.ID, validation.Required,
|
||||
validation.By(v.doesAddressExist(req.BenefactorID))),
|
||||
|
||||
validation.Field(&req.CityID,
|
||||
validation.When(req.CityID != 0, validation.By(v.doesCityExist))),
|
||||
); err != nil {
|
||||
fieldErrors := make(map[string]string)
|
||||
|
||||
var errV validation.Errors
|
||||
if errors.As(err, &errV) {
|
||||
for key, value := range errV {
|
||||
if value != nil {
|
||||
fieldErrors[key] = value.Error()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fieldErrors, richerror.New(op).
|
||||
WithMessage(errmsg.ErrorMsgInvalidInput).
|
||||
WithKind(richerror.KindInvalid).
|
||||
WithMeta(map[string]interface{}{"req": req}).
|
||||
WithErr(err)
|
||||
}
|
||||
|
||||
return map[string]string{}, nil
|
||||
}
|
Loading…
Reference in New Issue