add warehouse_request_source and warehouse_request_source_2 fields to deliveries table with validation and normalization logic
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE deliveries DROP COLUMN warehouse_request_source_2;
|
||||||
|
ALTER TABLE deliveries DROP COLUMN warehouse_request_source;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE deliveries ADD COLUMN warehouse_request_source varchar(20);
|
||||||
|
ALTER TABLE deliveries ADD COLUMN warehouse_request_source_2 varchar(20);
|
||||||
@@ -30,11 +30,11 @@ SELECT * FROM deliveries WHERE date = $1;
|
|||||||
|
|
||||||
-- name: CreateDelivery :one
|
-- name: CreateDelivery :one
|
||||||
INSERT INTO deliveries (
|
INSERT INTO deliveries (
|
||||||
date, pickup_location, pickup_location_2, product_name, product_name_2,
|
date, pickup_location, pickup_location_2, warehouse_request_source, warehouse_request_source_2, product_name, product_name_2,
|
||||||
customer_name, address, street, house, apartment, entrance, floor,
|
customer_name, address, street, house, apartment, entrance, floor,
|
||||||
phone, additional_phone, has_elevator, service_info, comment
|
phone, additional_phone, has_elevator, service_info, comment
|
||||||
)
|
)
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)
|
||||||
RETURNING *;
|
RETURNING *;
|
||||||
|
|
||||||
-- name: GetDeliveryByID :one
|
-- name: GetDeliveryByID :one
|
||||||
@@ -48,22 +48,24 @@ UPDATE deliveries SET
|
|||||||
date = $1,
|
date = $1,
|
||||||
pickup_location = $2,
|
pickup_location = $2,
|
||||||
pickup_location_2 = $3,
|
pickup_location_2 = $3,
|
||||||
product_name = $4,
|
warehouse_request_source = $4,
|
||||||
product_name_2 = $5,
|
warehouse_request_source_2 = $5,
|
||||||
customer_name = $6,
|
product_name = $6,
|
||||||
address = $7,
|
product_name_2 = $7,
|
||||||
street = $8,
|
customer_name = $8,
|
||||||
house = $9,
|
address = $9,
|
||||||
apartment = $10,
|
street = $10,
|
||||||
entrance = $11,
|
house = $11,
|
||||||
floor = $12,
|
apartment = $12,
|
||||||
phone = $13,
|
entrance = $13,
|
||||||
additional_phone = $14,
|
floor = $14,
|
||||||
has_elevator = $15,
|
phone = $15,
|
||||||
service_info = $16,
|
additional_phone = $16,
|
||||||
comment = $17,
|
has_elevator = $17,
|
||||||
|
service_info = $18,
|
||||||
|
comment = $19,
|
||||||
updated_at = NOW()
|
updated_at = NOW()
|
||||||
WHERE id = $18;
|
WHERE id = $20;
|
||||||
|
|
||||||
-- name: GetDeliveryCount :many
|
-- name: GetDeliveryCount :many
|
||||||
SELECT COUNT(*) as count, date FROM deliveries
|
SELECT COUNT(*) as count, date FROM deliveries
|
||||||
|
|||||||
@@ -9,27 +9,29 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Delivery struct {
|
type Delivery struct {
|
||||||
ID pgtype.UUID `db:"id" json:"id"`
|
ID pgtype.UUID `db:"id" json:"id"`
|
||||||
Date pgtype.Date `db:"date" json:"date"`
|
Date pgtype.Date `db:"date" json:"date"`
|
||||||
PickupLocation string `db:"pickup_location" json:"pickup_location"`
|
PickupLocation string `db:"pickup_location" json:"pickup_location"`
|
||||||
ProductName string `db:"product_name" json:"product_name"`
|
ProductName string `db:"product_name" json:"product_name"`
|
||||||
Address string `db:"address" json:"address"`
|
Address string `db:"address" json:"address"`
|
||||||
Phone string `db:"phone" json:"phone"`
|
Phone string `db:"phone" json:"phone"`
|
||||||
AdditionalPhone pgtype.Text `db:"additional_phone" json:"additional_phone"`
|
AdditionalPhone pgtype.Text `db:"additional_phone" json:"additional_phone"`
|
||||||
HasElevator bool `db:"has_elevator" json:"has_elevator"`
|
HasElevator bool `db:"has_elevator" json:"has_elevator"`
|
||||||
Comment pgtype.Text `db:"comment" json:"comment"`
|
Comment pgtype.Text `db:"comment" json:"comment"`
|
||||||
Status string `db:"status" json:"status"`
|
Status string `db:"status" json:"status"`
|
||||||
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
||||||
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
||||||
CustomerName string `db:"customer_name" json:"customer_name"`
|
CustomerName string `db:"customer_name" json:"customer_name"`
|
||||||
ServiceInfo pgtype.Text `db:"service_info" json:"service_info"`
|
ServiceInfo pgtype.Text `db:"service_info" json:"service_info"`
|
||||||
PickupLocation2 pgtype.Text `db:"pickup_location_2" json:"pickup_location_2"`
|
PickupLocation2 pgtype.Text `db:"pickup_location_2" json:"pickup_location_2"`
|
||||||
ProductName2 pgtype.Text `db:"product_name_2" json:"product_name_2"`
|
ProductName2 pgtype.Text `db:"product_name_2" json:"product_name_2"`
|
||||||
Street string `db:"street" json:"street"`
|
Street string `db:"street" json:"street"`
|
||||||
House string `db:"house" json:"house"`
|
House string `db:"house" json:"house"`
|
||||||
Apartment pgtype.Text `db:"apartment" json:"apartment"`
|
Apartment pgtype.Text `db:"apartment" json:"apartment"`
|
||||||
Entrance pgtype.Text `db:"entrance" json:"entrance"`
|
Entrance pgtype.Text `db:"entrance" json:"entrance"`
|
||||||
Floor pgtype.Text `db:"floor" json:"floor"`
|
Floor pgtype.Text `db:"floor" json:"floor"`
|
||||||
|
WarehouseRequestSource pgtype.Text `db:"warehouse_request_source" json:"warehouse_request_source"`
|
||||||
|
WarehouseRequestSource2 pgtype.Text `db:"warehouse_request_source_2" json:"warehouse_request_source_2"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
|
|||||||
@@ -13,32 +13,34 @@ import (
|
|||||||
|
|
||||||
const createDelivery = `-- name: CreateDelivery :one
|
const createDelivery = `-- name: CreateDelivery :one
|
||||||
INSERT INTO deliveries (
|
INSERT INTO deliveries (
|
||||||
date, pickup_location, pickup_location_2, product_name, product_name_2,
|
date, pickup_location, pickup_location_2, warehouse_request_source, warehouse_request_source_2, product_name, product_name_2,
|
||||||
customer_name, address, street, house, apartment, entrance, floor,
|
customer_name, address, street, house, apartment, entrance, floor,
|
||||||
phone, additional_phone, has_elevator, service_info, comment
|
phone, additional_phone, has_elevator, service_info, comment
|
||||||
)
|
)
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)
|
||||||
RETURNING id, date, pickup_location, product_name, address, phone, additional_phone, has_elevator, comment, status, created_at, updated_at, customer_name, service_info, pickup_location_2, product_name_2, street, house, apartment, entrance, floor
|
RETURNING id, date, pickup_location, product_name, address, phone, additional_phone, has_elevator, comment, status, created_at, updated_at, customer_name, service_info, pickup_location_2, product_name_2, street, house, apartment, entrance, floor, warehouse_request_source, warehouse_request_source_2
|
||||||
`
|
`
|
||||||
|
|
||||||
type CreateDeliveryParams struct {
|
type CreateDeliveryParams struct {
|
||||||
Date pgtype.Date `db:"date" json:"date"`
|
Date pgtype.Date `db:"date" json:"date"`
|
||||||
PickupLocation string `db:"pickup_location" json:"pickup_location"`
|
PickupLocation string `db:"pickup_location" json:"pickup_location"`
|
||||||
PickupLocation2 pgtype.Text `db:"pickup_location_2" json:"pickup_location_2"`
|
PickupLocation2 pgtype.Text `db:"pickup_location_2" json:"pickup_location_2"`
|
||||||
ProductName string `db:"product_name" json:"product_name"`
|
WarehouseRequestSource pgtype.Text `db:"warehouse_request_source" json:"warehouse_request_source"`
|
||||||
ProductName2 pgtype.Text `db:"product_name_2" json:"product_name_2"`
|
WarehouseRequestSource2 pgtype.Text `db:"warehouse_request_source_2" json:"warehouse_request_source_2"`
|
||||||
CustomerName string `db:"customer_name" json:"customer_name"`
|
ProductName string `db:"product_name" json:"product_name"`
|
||||||
Address string `db:"address" json:"address"`
|
ProductName2 pgtype.Text `db:"product_name_2" json:"product_name_2"`
|
||||||
Street string `db:"street" json:"street"`
|
CustomerName string `db:"customer_name" json:"customer_name"`
|
||||||
House string `db:"house" json:"house"`
|
Address string `db:"address" json:"address"`
|
||||||
Apartment pgtype.Text `db:"apartment" json:"apartment"`
|
Street string `db:"street" json:"street"`
|
||||||
Entrance pgtype.Text `db:"entrance" json:"entrance"`
|
House string `db:"house" json:"house"`
|
||||||
Floor pgtype.Text `db:"floor" json:"floor"`
|
Apartment pgtype.Text `db:"apartment" json:"apartment"`
|
||||||
Phone string `db:"phone" json:"phone"`
|
Entrance pgtype.Text `db:"entrance" json:"entrance"`
|
||||||
AdditionalPhone pgtype.Text `db:"additional_phone" json:"additional_phone"`
|
Floor pgtype.Text `db:"floor" json:"floor"`
|
||||||
HasElevator bool `db:"has_elevator" json:"has_elevator"`
|
Phone string `db:"phone" json:"phone"`
|
||||||
ServiceInfo pgtype.Text `db:"service_info" json:"service_info"`
|
AdditionalPhone pgtype.Text `db:"additional_phone" json:"additional_phone"`
|
||||||
Comment pgtype.Text `db:"comment" json:"comment"`
|
HasElevator bool `db:"has_elevator" json:"has_elevator"`
|
||||||
|
ServiceInfo pgtype.Text `db:"service_info" json:"service_info"`
|
||||||
|
Comment pgtype.Text `db:"comment" json:"comment"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) CreateDelivery(ctx context.Context, arg CreateDeliveryParams) (Delivery, error) {
|
func (q *Queries) CreateDelivery(ctx context.Context, arg CreateDeliveryParams) (Delivery, error) {
|
||||||
@@ -46,6 +48,8 @@ func (q *Queries) CreateDelivery(ctx context.Context, arg CreateDeliveryParams)
|
|||||||
arg.Date,
|
arg.Date,
|
||||||
arg.PickupLocation,
|
arg.PickupLocation,
|
||||||
arg.PickupLocation2,
|
arg.PickupLocation2,
|
||||||
|
arg.WarehouseRequestSource,
|
||||||
|
arg.WarehouseRequestSource2,
|
||||||
arg.ProductName,
|
arg.ProductName,
|
||||||
arg.ProductName2,
|
arg.ProductName2,
|
||||||
arg.CustomerName,
|
arg.CustomerName,
|
||||||
@@ -84,6 +88,8 @@ func (q *Queries) CreateDelivery(ctx context.Context, arg CreateDeliveryParams)
|
|||||||
&i.Apartment,
|
&i.Apartment,
|
||||||
&i.Entrance,
|
&i.Entrance,
|
||||||
&i.Floor,
|
&i.Floor,
|
||||||
|
&i.WarehouseRequestSource,
|
||||||
|
&i.WarehouseRequestSource2,
|
||||||
)
|
)
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
@@ -123,7 +129,7 @@ func (q *Queries) DeleteDelivery(ctx context.Context, id pgtype.UUID) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const getDeliveriesByDate = `-- name: GetDeliveriesByDate :many
|
const getDeliveriesByDate = `-- name: GetDeliveriesByDate :many
|
||||||
SELECT id, date, pickup_location, product_name, address, phone, additional_phone, has_elevator, comment, status, created_at, updated_at, customer_name, service_info, pickup_location_2, product_name_2, street, house, apartment, entrance, floor FROM deliveries WHERE date = $1
|
SELECT id, date, pickup_location, product_name, address, phone, additional_phone, has_elevator, comment, status, created_at, updated_at, customer_name, service_info, pickup_location_2, product_name_2, street, house, apartment, entrance, floor, warehouse_request_source, warehouse_request_source_2 FROM deliveries WHERE date = $1
|
||||||
`
|
`
|
||||||
|
|
||||||
func (q *Queries) GetDeliveriesByDate(ctx context.Context, date pgtype.Date) ([]Delivery, error) {
|
func (q *Queries) GetDeliveriesByDate(ctx context.Context, date pgtype.Date) ([]Delivery, error) {
|
||||||
@@ -157,6 +163,8 @@ func (q *Queries) GetDeliveriesByDate(ctx context.Context, date pgtype.Date) ([]
|
|||||||
&i.Apartment,
|
&i.Apartment,
|
||||||
&i.Entrance,
|
&i.Entrance,
|
||||||
&i.Floor,
|
&i.Floor,
|
||||||
|
&i.WarehouseRequestSource,
|
||||||
|
&i.WarehouseRequestSource2,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -169,7 +177,7 @@ func (q *Queries) GetDeliveriesByDate(ctx context.Context, date pgtype.Date) ([]
|
|||||||
}
|
}
|
||||||
|
|
||||||
const getDeliveryByID = `-- name: GetDeliveryByID :one
|
const getDeliveryByID = `-- name: GetDeliveryByID :one
|
||||||
SELECT id, date, pickup_location, product_name, address, phone, additional_phone, has_elevator, comment, status, created_at, updated_at, customer_name, service_info, pickup_location_2, product_name_2, street, house, apartment, entrance, floor FROM deliveries WHERE id = $1
|
SELECT id, date, pickup_location, product_name, address, phone, additional_phone, has_elevator, comment, status, created_at, updated_at, customer_name, service_info, pickup_location_2, product_name_2, street, house, apartment, entrance, floor, warehouse_request_source, warehouse_request_source_2 FROM deliveries WHERE id = $1
|
||||||
`
|
`
|
||||||
|
|
||||||
func (q *Queries) GetDeliveryByID(ctx context.Context, id pgtype.UUID) (Delivery, error) {
|
func (q *Queries) GetDeliveryByID(ctx context.Context, id pgtype.UUID) (Delivery, error) {
|
||||||
@@ -197,6 +205,8 @@ func (q *Queries) GetDeliveryByID(ctx context.Context, id pgtype.UUID) (Delivery
|
|||||||
&i.Apartment,
|
&i.Apartment,
|
||||||
&i.Entrance,
|
&i.Entrance,
|
||||||
&i.Floor,
|
&i.Floor,
|
||||||
|
&i.WarehouseRequestSource,
|
||||||
|
&i.WarehouseRequestSource2,
|
||||||
)
|
)
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
@@ -293,43 +303,47 @@ UPDATE deliveries SET
|
|||||||
date = $1,
|
date = $1,
|
||||||
pickup_location = $2,
|
pickup_location = $2,
|
||||||
pickup_location_2 = $3,
|
pickup_location_2 = $3,
|
||||||
product_name = $4,
|
warehouse_request_source = $4,
|
||||||
product_name_2 = $5,
|
warehouse_request_source_2 = $5,
|
||||||
customer_name = $6,
|
product_name = $6,
|
||||||
address = $7,
|
product_name_2 = $7,
|
||||||
street = $8,
|
customer_name = $8,
|
||||||
house = $9,
|
address = $9,
|
||||||
apartment = $10,
|
street = $10,
|
||||||
entrance = $11,
|
house = $11,
|
||||||
floor = $12,
|
apartment = $12,
|
||||||
phone = $13,
|
entrance = $13,
|
||||||
additional_phone = $14,
|
floor = $14,
|
||||||
has_elevator = $15,
|
phone = $15,
|
||||||
service_info = $16,
|
additional_phone = $16,
|
||||||
comment = $17,
|
has_elevator = $17,
|
||||||
|
service_info = $18,
|
||||||
|
comment = $19,
|
||||||
updated_at = NOW()
|
updated_at = NOW()
|
||||||
WHERE id = $18
|
WHERE id = $20
|
||||||
`
|
`
|
||||||
|
|
||||||
type UpdateDeliveryParams struct {
|
type UpdateDeliveryParams struct {
|
||||||
Date pgtype.Date `db:"date" json:"date"`
|
Date pgtype.Date `db:"date" json:"date"`
|
||||||
PickupLocation string `db:"pickup_location" json:"pickup_location"`
|
PickupLocation string `db:"pickup_location" json:"pickup_location"`
|
||||||
PickupLocation2 pgtype.Text `db:"pickup_location_2" json:"pickup_location_2"`
|
PickupLocation2 pgtype.Text `db:"pickup_location_2" json:"pickup_location_2"`
|
||||||
ProductName string `db:"product_name" json:"product_name"`
|
WarehouseRequestSource pgtype.Text `db:"warehouse_request_source" json:"warehouse_request_source"`
|
||||||
ProductName2 pgtype.Text `db:"product_name_2" json:"product_name_2"`
|
WarehouseRequestSource2 pgtype.Text `db:"warehouse_request_source_2" json:"warehouse_request_source_2"`
|
||||||
CustomerName string `db:"customer_name" json:"customer_name"`
|
ProductName string `db:"product_name" json:"product_name"`
|
||||||
Address string `db:"address" json:"address"`
|
ProductName2 pgtype.Text `db:"product_name_2" json:"product_name_2"`
|
||||||
Street string `db:"street" json:"street"`
|
CustomerName string `db:"customer_name" json:"customer_name"`
|
||||||
House string `db:"house" json:"house"`
|
Address string `db:"address" json:"address"`
|
||||||
Apartment pgtype.Text `db:"apartment" json:"apartment"`
|
Street string `db:"street" json:"street"`
|
||||||
Entrance pgtype.Text `db:"entrance" json:"entrance"`
|
House string `db:"house" json:"house"`
|
||||||
Floor pgtype.Text `db:"floor" json:"floor"`
|
Apartment pgtype.Text `db:"apartment" json:"apartment"`
|
||||||
Phone string `db:"phone" json:"phone"`
|
Entrance pgtype.Text `db:"entrance" json:"entrance"`
|
||||||
AdditionalPhone pgtype.Text `db:"additional_phone" json:"additional_phone"`
|
Floor pgtype.Text `db:"floor" json:"floor"`
|
||||||
HasElevator bool `db:"has_elevator" json:"has_elevator"`
|
Phone string `db:"phone" json:"phone"`
|
||||||
ServiceInfo pgtype.Text `db:"service_info" json:"service_info"`
|
AdditionalPhone pgtype.Text `db:"additional_phone" json:"additional_phone"`
|
||||||
Comment pgtype.Text `db:"comment" json:"comment"`
|
HasElevator bool `db:"has_elevator" json:"has_elevator"`
|
||||||
ID pgtype.UUID `db:"id" json:"id"`
|
ServiceInfo pgtype.Text `db:"service_info" json:"service_info"`
|
||||||
|
Comment pgtype.Text `db:"comment" json:"comment"`
|
||||||
|
ID pgtype.UUID `db:"id" json:"id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) UpdateDelivery(ctx context.Context, arg UpdateDeliveryParams) error {
|
func (q *Queries) UpdateDelivery(ctx context.Context, arg UpdateDeliveryParams) error {
|
||||||
@@ -337,6 +351,8 @@ func (q *Queries) UpdateDelivery(ctx context.Context, arg UpdateDeliveryParams)
|
|||||||
arg.Date,
|
arg.Date,
|
||||||
arg.PickupLocation,
|
arg.PickupLocation,
|
||||||
arg.PickupLocation2,
|
arg.PickupLocation2,
|
||||||
|
arg.WarehouseRequestSource,
|
||||||
|
arg.WarehouseRequestSource2,
|
||||||
arg.ProductName,
|
arg.ProductName,
|
||||||
arg.ProductName2,
|
arg.ProductName2,
|
||||||
arg.CustomerName,
|
arg.CustomerName,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package delivery
|
package delivery
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -16,23 +17,25 @@ type Handler struct {
|
|||||||
|
|
||||||
// DeliveryRequest represents the request body for creating or updating a delivery
|
// DeliveryRequest represents the request body for creating or updating a delivery
|
||||||
type DeliveryRequest struct {
|
type DeliveryRequest struct {
|
||||||
Date string `json:"date" binding:"required"` // DD-MM-YYYY
|
Date string `json:"date" binding:"required"` // DD-MM-YYYY
|
||||||
PickupLocation string `json:"pickup_location" binding:"required,oneof=warehouse symbat nursaya galaktika"`
|
PickupLocation string `json:"pickup_location" binding:"required,oneof=warehouse symbat nursaya galaktika"`
|
||||||
PickupLocation2 *string `json:"pickup_location_2" binding:"omitempty,oneof=warehouse symbat nursaya galaktika"`
|
PickupLocation2 *string `json:"pickup_location_2" binding:"omitempty,oneof=warehouse symbat nursaya galaktika"`
|
||||||
ProductName string `json:"product_name" binding:"required"`
|
WarehouseRequestSource *string `json:"warehouse_request_source" binding:"omitempty,oneof=symbat nursaya galaktika"`
|
||||||
ProductName2 *string `json:"product_name_2"`
|
WarehouseRequestSource2 *string `json:"warehouse_request_source_2" binding:"omitempty,oneof=symbat nursaya galaktika"`
|
||||||
CustomerName string `json:"customer_name" binding:"required"`
|
ProductName string `json:"product_name" binding:"required"`
|
||||||
Address string `json:"address" binding:"required"`
|
ProductName2 *string `json:"product_name_2"`
|
||||||
Street string `json:"street" binding:"required"`
|
CustomerName string `json:"customer_name" binding:"required"`
|
||||||
House string `json:"house" binding:"required"`
|
Address string `json:"address" binding:"required"`
|
||||||
Apartment *string `json:"apartment"`
|
Street string `json:"street" binding:"required"`
|
||||||
Entrance *string `json:"entrance"`
|
House string `json:"house" binding:"required"`
|
||||||
Floor *string `json:"floor"`
|
Apartment *string `json:"apartment"`
|
||||||
Phone string `json:"phone" binding:"required"`
|
Entrance *string `json:"entrance"`
|
||||||
AdditionalPhone *string `json:"additional_phone"`
|
Floor *string `json:"floor"`
|
||||||
HasElevator bool `json:"has_elevator"`
|
Phone string `json:"phone" binding:"required"`
|
||||||
ServiceInfo *string `json:"service_info"`
|
AdditionalPhone *string `json:"additional_phone"`
|
||||||
Comment string `json:"comment"`
|
HasElevator bool `json:"has_elevator"`
|
||||||
|
ServiceInfo *string `json:"service_info"`
|
||||||
|
Comment string `json:"comment"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandler(queries *sqlc.Queries) *Handler {
|
func NewHandler(queries *sqlc.Queries) *Handler {
|
||||||
@@ -97,6 +100,10 @@ func (h *Handler) CreateDelivery(c *gin.Context) {
|
|||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body", "details": err.Error()})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body", "details": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if err := normalizeWarehouseRequestSources(&req); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Parse date from DD-MM-YYYY
|
// Parse date from DD-MM-YYYY
|
||||||
t, err := parseDate(req.Date)
|
t, err := parseDate(req.Date)
|
||||||
@@ -106,23 +113,25 @@ func (h *Handler) CreateDelivery(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
params := sqlc.CreateDeliveryParams{
|
params := sqlc.CreateDeliveryParams{
|
||||||
Date: pgtype.Date{Time: t, Valid: true},
|
Date: pgtype.Date{Time: t, Valid: true},
|
||||||
PickupLocation: req.PickupLocation,
|
PickupLocation: req.PickupLocation,
|
||||||
PickupLocation2: pgtype.Text{String: derefString(req.PickupLocation2), Valid: req.PickupLocation2 != nil},
|
PickupLocation2: pgtype.Text{String: derefString(req.PickupLocation2), Valid: req.PickupLocation2 != nil},
|
||||||
ProductName: req.ProductName,
|
WarehouseRequestSource: pgtype.Text{String: derefString(req.WarehouseRequestSource), Valid: req.WarehouseRequestSource != nil},
|
||||||
ProductName2: pgtype.Text{String: derefString(req.ProductName2), Valid: req.ProductName2 != nil},
|
WarehouseRequestSource2: pgtype.Text{String: derefString(req.WarehouseRequestSource2), Valid: req.WarehouseRequestSource2 != nil},
|
||||||
CustomerName: req.CustomerName,
|
ProductName: req.ProductName,
|
||||||
Address: req.Address,
|
ProductName2: pgtype.Text{String: derefString(req.ProductName2), Valid: req.ProductName2 != nil},
|
||||||
Street: req.Street,
|
CustomerName: req.CustomerName,
|
||||||
House: req.House,
|
Address: req.Address,
|
||||||
Apartment: pgtype.Text{String: derefString(req.Apartment), Valid: req.Apartment != nil},
|
Street: req.Street,
|
||||||
Entrance: pgtype.Text{String: derefString(req.Entrance), Valid: req.Entrance != nil},
|
House: req.House,
|
||||||
Floor: pgtype.Text{String: derefString(req.Floor), Valid: req.Floor != nil},
|
Apartment: pgtype.Text{String: derefString(req.Apartment), Valid: req.Apartment != nil},
|
||||||
Phone: req.Phone,
|
Entrance: pgtype.Text{String: derefString(req.Entrance), Valid: req.Entrance != nil},
|
||||||
AdditionalPhone: pgtype.Text{String: derefString(req.AdditionalPhone), Valid: req.AdditionalPhone != nil},
|
Floor: pgtype.Text{String: derefString(req.Floor), Valid: req.Floor != nil},
|
||||||
HasElevator: req.HasElevator,
|
Phone: req.Phone,
|
||||||
ServiceInfo: pgtype.Text{String: derefString(req.ServiceInfo), Valid: req.ServiceInfo != nil},
|
AdditionalPhone: pgtype.Text{String: derefString(req.AdditionalPhone), Valid: req.AdditionalPhone != nil},
|
||||||
Comment: pgtype.Text{String: req.Comment, Valid: true},
|
HasElevator: req.HasElevator,
|
||||||
|
ServiceInfo: pgtype.Text{String: derefString(req.ServiceInfo), Valid: req.ServiceInfo != nil},
|
||||||
|
Comment: pgtype.Text{String: req.Comment, Valid: true},
|
||||||
}
|
}
|
||||||
res, err := h.queries.CreateDelivery(c.Request.Context(), params)
|
res, err := h.queries.CreateDelivery(c.Request.Context(), params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -141,6 +150,10 @@ func (h *Handler) UpdateDelivery(c *gin.Context) {
|
|||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body", "details": err.Error()})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body", "details": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if err := normalizeWarehouseRequestSources(&req); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
|
|
||||||
@@ -161,24 +174,26 @@ func (h *Handler) UpdateDelivery(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := h.queries.UpdateDelivery(c.Request.Context(), sqlc.UpdateDeliveryParams{
|
if err := h.queries.UpdateDelivery(c.Request.Context(), sqlc.UpdateDeliveryParams{
|
||||||
ID: pgtype.UUID{Bytes: parsedID, Valid: true},
|
ID: pgtype.UUID{Bytes: parsedID, Valid: true},
|
||||||
Date: pgtype.Date{Time: t, Valid: true},
|
Date: pgtype.Date{Time: t, Valid: true},
|
||||||
PickupLocation: req.PickupLocation,
|
PickupLocation: req.PickupLocation,
|
||||||
PickupLocation2: pgtype.Text{String: derefString(req.PickupLocation2), Valid: req.PickupLocation2 != nil},
|
PickupLocation2: pgtype.Text{String: derefString(req.PickupLocation2), Valid: req.PickupLocation2 != nil},
|
||||||
ProductName: req.ProductName,
|
WarehouseRequestSource: pgtype.Text{String: derefString(req.WarehouseRequestSource), Valid: req.WarehouseRequestSource != nil},
|
||||||
ProductName2: pgtype.Text{String: derefString(req.ProductName2), Valid: req.ProductName2 != nil},
|
WarehouseRequestSource2: pgtype.Text{String: derefString(req.WarehouseRequestSource2), Valid: req.WarehouseRequestSource2 != nil},
|
||||||
CustomerName: req.CustomerName,
|
ProductName: req.ProductName,
|
||||||
Address: req.Address,
|
ProductName2: pgtype.Text{String: derefString(req.ProductName2), Valid: req.ProductName2 != nil},
|
||||||
Street: req.Street,
|
CustomerName: req.CustomerName,
|
||||||
House: req.House,
|
Address: req.Address,
|
||||||
Apartment: pgtype.Text{String: derefString(req.Apartment), Valid: req.Apartment != nil},
|
Street: req.Street,
|
||||||
Entrance: pgtype.Text{String: derefString(req.Entrance), Valid: req.Entrance != nil},
|
House: req.House,
|
||||||
Floor: pgtype.Text{String: derefString(req.Floor), Valid: req.Floor != nil},
|
Apartment: pgtype.Text{String: derefString(req.Apartment), Valid: req.Apartment != nil},
|
||||||
Phone: req.Phone,
|
Entrance: pgtype.Text{String: derefString(req.Entrance), Valid: req.Entrance != nil},
|
||||||
AdditionalPhone: pgtype.Text{String: derefString(req.AdditionalPhone), Valid: req.AdditionalPhone != nil},
|
Floor: pgtype.Text{String: derefString(req.Floor), Valid: req.Floor != nil},
|
||||||
HasElevator: req.HasElevator,
|
Phone: req.Phone,
|
||||||
ServiceInfo: pgtype.Text{String: derefString(req.ServiceInfo), Valid: req.ServiceInfo != nil},
|
AdditionalPhone: pgtype.Text{String: derefString(req.AdditionalPhone), Valid: req.AdditionalPhone != nil},
|
||||||
Comment: pgtype.Text{String: req.Comment, Valid: true},
|
HasElevator: req.HasElevator,
|
||||||
|
ServiceInfo: pgtype.Text{String: derefString(req.ServiceInfo), Valid: req.ServiceInfo != nil},
|
||||||
|
Comment: pgtype.Text{String: req.Comment, Valid: true},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update delivery", "details": err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update delivery", "details": err.Error()})
|
||||||
return
|
return
|
||||||
@@ -266,3 +281,19 @@ func derefString(s *string) string {
|
|||||||
}
|
}
|
||||||
return *s
|
return *s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func normalizeWarehouseRequestSources(req *DeliveryRequest) error {
|
||||||
|
if req.PickupLocation == "warehouse" && req.WarehouseRequestSource == nil {
|
||||||
|
return errors.New("warehouse_request_source is required when pickup_location is warehouse")
|
||||||
|
}
|
||||||
|
if req.PickupLocation != "warehouse" {
|
||||||
|
req.WarehouseRequestSource = nil
|
||||||
|
}
|
||||||
|
if req.PickupLocation2 != nil && *req.PickupLocation2 == "warehouse" && req.WarehouseRequestSource2 == nil {
|
||||||
|
return errors.New("warehouse_request_source_2 is required when pickup_location_2 is warehouse")
|
||||||
|
}
|
||||||
|
if req.PickupLocation2 == nil || *req.PickupLocation2 != "warehouse" {
|
||||||
|
req.WarehouseRequestSource2 = nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { api } from './client';
|
import { api } from './client';
|
||||||
import { backendDateToFrontend } from '../utils/date';
|
import { backendDateToFrontend } from '../utils/date';
|
||||||
import type { Delivery, PickupLocation, DeliveryStatus } from '../types';
|
import type { Delivery, DeliveryRequestSource, PickupLocation, DeliveryStatus } from '../types';
|
||||||
|
|
||||||
// Types matching backend responses
|
// Types matching backend responses
|
||||||
interface BackendDelivery {
|
interface BackendDelivery {
|
||||||
@@ -8,6 +8,8 @@ interface BackendDelivery {
|
|||||||
date: string; // YYYY-MM-DD from pgtype.Date
|
date: string; // YYYY-MM-DD from pgtype.Date
|
||||||
pickup_location: PickupLocation;
|
pickup_location: PickupLocation;
|
||||||
pickup_location_2: PickupLocation | null;
|
pickup_location_2: PickupLocation | null;
|
||||||
|
warehouse_request_source: DeliveryRequestSource | null;
|
||||||
|
warehouse_request_source_2: DeliveryRequestSource | null;
|
||||||
product_name: string;
|
product_name: string;
|
||||||
product_name_2: string | null;
|
product_name_2: string | null;
|
||||||
customer_name: string;
|
customer_name: string;
|
||||||
@@ -61,6 +63,8 @@ function mapBackendToFrontend(backend: BackendDelivery): Delivery {
|
|||||||
date: backendDateToFrontend(backend.date),
|
date: backendDateToFrontend(backend.date),
|
||||||
pickupLocation: backend.pickup_location,
|
pickupLocation: backend.pickup_location,
|
||||||
pickupLocation2: backend.pickup_location_2 || undefined,
|
pickupLocation2: backend.pickup_location_2 || undefined,
|
||||||
|
warehouseRequestSource: backend.warehouse_request_source || undefined,
|
||||||
|
warehouseRequestSource2: backend.warehouse_request_source_2 || undefined,
|
||||||
productName: backend.product_name,
|
productName: backend.product_name,
|
||||||
productName2: backend.product_name_2 || undefined,
|
productName2: backend.product_name_2 || undefined,
|
||||||
customerName: backend.customer_name,
|
customerName: backend.customer_name,
|
||||||
@@ -115,6 +119,8 @@ export const deliveriesApi = {
|
|||||||
date: data.date,
|
date: data.date,
|
||||||
pickup_location: data.pickupLocation,
|
pickup_location: data.pickupLocation,
|
||||||
pickup_location_2: data.pickupLocation2 || null,
|
pickup_location_2: data.pickupLocation2 || null,
|
||||||
|
warehouse_request_source: data.pickupLocation === 'warehouse' ? data.warehouseRequestSource || null : null,
|
||||||
|
warehouse_request_source_2: data.pickupLocation2 === 'warehouse' ? data.warehouseRequestSource2 || null : null,
|
||||||
product_name: data.productName,
|
product_name: data.productName,
|
||||||
product_name_2: data.productName2 || null,
|
product_name_2: data.productName2 || null,
|
||||||
customer_name: data.customerName,
|
customer_name: data.customerName,
|
||||||
@@ -143,6 +149,8 @@ export const deliveriesApi = {
|
|||||||
date: data.date,
|
date: data.date,
|
||||||
pickup_location: data.pickupLocation,
|
pickup_location: data.pickupLocation,
|
||||||
pickup_location_2: data.pickupLocation2 || null,
|
pickup_location_2: data.pickupLocation2 || null,
|
||||||
|
warehouse_request_source: data.pickupLocation === 'warehouse' ? data.warehouseRequestSource || null : null,
|
||||||
|
warehouse_request_source_2: data.pickupLocation2 === 'warehouse' ? data.warehouseRequestSource2 || null : null,
|
||||||
product_name: data.productName,
|
product_name: data.productName,
|
||||||
product_name_2: data.productName2 || null,
|
product_name_2: data.productName2 || null,
|
||||||
customer_name: data.customerName,
|
customer_name: data.customerName,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { MapPin, Phone, Store, Calendar, MessageSquare, CheckCircle2, Circle, CheckSquare, User, Wrench } from 'lucide-react';
|
import { MapPin, Phone, Store, Calendar, MessageSquare, CheckCircle2, Circle, CheckSquare, User, Wrench } from 'lucide-react';
|
||||||
import type { Delivery } from '../../types';
|
import type { Delivery } from '../../types';
|
||||||
import { pickupLocationLabels } from '../../types';
|
import { formatPickupLocation } from '../../types';
|
||||||
import { StatusBadge } from './StatusBadge';
|
import { StatusBadge } from './StatusBadge';
|
||||||
import { Card } from '../ui/Card';
|
import { Card } from '../ui/Card';
|
||||||
|
|
||||||
@@ -63,13 +63,13 @@ export const DeliveryCard = memo(({ delivery, onStatusChange, onEdit, onDelete }
|
|||||||
<Store size={16} className="text-[#75777d] mt-0.5 shrink-0" />
|
<Store size={16} className="text-[#75777d] mt-0.5 shrink-0" />
|
||||||
<div className="flex flex-col gap-1 min-w-0">
|
<div className="flex flex-col gap-1 min-w-0">
|
||||||
<div className="flex items-baseline gap-2 flex-wrap">
|
<div className="flex items-baseline gap-2 flex-wrap">
|
||||||
<span className="text-[#1b1b1d] font-medium">{pickupLocationLabels[delivery.pickupLocation]}</span>
|
<span className="text-[#1b1b1d] font-medium">{formatPickupLocation(delivery.pickupLocation, delivery.warehouseRequestSource)}</span>
|
||||||
<span className="text-[#75777d]">—</span>
|
<span className="text-[#75777d]">—</span>
|
||||||
<span className="text-[#1b1b1d]">{delivery.productName}</span>
|
<span className="text-[#1b1b1d]">{delivery.productName}</span>
|
||||||
</div>
|
</div>
|
||||||
{delivery.pickupLocation2 && (
|
{delivery.pickupLocation2 && (
|
||||||
<div className="flex items-baseline gap-2 flex-wrap">
|
<div className="flex items-baseline gap-2 flex-wrap">
|
||||||
<span className="text-[#1b1b1d] font-medium">{pickupLocationLabels[delivery.pickupLocation2]}</span>
|
<span className="text-[#1b1b1d] font-medium">{formatPickupLocation(delivery.pickupLocation2, delivery.warehouseRequestSource2)}</span>
|
||||||
<span className="text-[#75777d]">—</span>
|
<span className="text-[#75777d]">—</span>
|
||||||
<span className="text-[#1b1b1d]">{delivery.productName2 || '—'}</span>
|
<span className="text-[#1b1b1d]">{delivery.productName2 || '—'}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { useState, useEffect, useCallback } from 'react';
|
import { useState, useEffect, useCallback } from 'react';
|
||||||
import { Button, Input, Select, Modal } from '../ui';
|
import { Button, Input, Select, Modal } from '../ui';
|
||||||
import { pickupOptions } from '../../constants/pickup';
|
import { deliveryRequestSourceOptions, pickupOptions } from '../../constants/pickup';
|
||||||
import { formatDateForInput, parseDateFromInput, getTodayFrontend } from '../../utils/date';
|
import { formatDateForInput, parseDateFromInput, getTodayFrontend } from '../../utils/date';
|
||||||
import type { Delivery, PickupLocation, DeliveryStatus } from '../../types';
|
import type { Delivery, DeliveryRequestSource, PickupLocation, DeliveryStatus } from '../../types';
|
||||||
|
|
||||||
interface DeliveryFormProps {
|
interface DeliveryFormProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@@ -18,6 +18,10 @@ const PHONE_REGEX = /^\+7\s?\(?\d{3}\)?\s?\d{3}[\s-]?\d{2}[\s-]?\d{2}$/;
|
|||||||
|
|
||||||
// City is not shown in UI but is included in the saved address (used for 2GIS search).
|
// City is not shown in UI but is included in the saved address (used for 2GIS search).
|
||||||
const CITY_LABEL = 'Кокшетау';
|
const CITY_LABEL = 'Кокшетау';
|
||||||
|
const requestSourceOptions = [
|
||||||
|
{ value: '', label: 'Выберите источник заявки' },
|
||||||
|
...deliveryRequestSourceOptions,
|
||||||
|
];
|
||||||
|
|
||||||
const buildAddressString = (
|
const buildAddressString = (
|
||||||
street: string,
|
street: string,
|
||||||
@@ -38,6 +42,8 @@ export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDa
|
|||||||
date: defaultDate || getTodayFrontend(),
|
date: defaultDate || getTodayFrontend(),
|
||||||
pickupLocation: 'warehouse' as PickupLocation,
|
pickupLocation: 'warehouse' as PickupLocation,
|
||||||
pickupLocation2: null as PickupLocation | null,
|
pickupLocation2: null as PickupLocation | null,
|
||||||
|
warehouseRequestSource: null as DeliveryRequestSource | null,
|
||||||
|
warehouseRequestSource2: null as DeliveryRequestSource | null,
|
||||||
productName: '',
|
productName: '',
|
||||||
productName2: '',
|
productName2: '',
|
||||||
customerName: '',
|
customerName: '',
|
||||||
@@ -62,6 +68,8 @@ export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDa
|
|||||||
date: initialData.date,
|
date: initialData.date,
|
||||||
pickupLocation: initialData.pickupLocation,
|
pickupLocation: initialData.pickupLocation,
|
||||||
pickupLocation2: initialData.pickupLocation2 || null,
|
pickupLocation2: initialData.pickupLocation2 || null,
|
||||||
|
warehouseRequestSource: initialData.warehouseRequestSource || null,
|
||||||
|
warehouseRequestSource2: initialData.warehouseRequestSource2 || null,
|
||||||
productName: initialData.productName,
|
productName: initialData.productName,
|
||||||
productName2: initialData.productName2 || '',
|
productName2: initialData.productName2 || '',
|
||||||
customerName: initialData.customerName,
|
customerName: initialData.customerName,
|
||||||
@@ -91,7 +99,25 @@ export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDa
|
|||||||
|
|
||||||
const isPhoneValid = !formData.phone || validatePhone(formData.phone);
|
const isPhoneValid = !formData.phone || validatePhone(formData.phone);
|
||||||
const isAdditionalPhoneValid = !formData.additionalPhone || validatePhone(formData.additionalPhone);
|
const isAdditionalPhoneValid = !formData.additionalPhone || validatePhone(formData.additionalPhone);
|
||||||
const isFormValid = formData.productName && formData.phone && isPhoneValid && formData.customerName && formData.street && formData.house;
|
const isWarehouseRequestSourceValid = formData.pickupLocation !== 'warehouse' || !!formData.warehouseRequestSource;
|
||||||
|
const isWarehouseRequestSource2Valid = !showSecondPickup || formData.pickupLocation2 !== 'warehouse' || !!formData.warehouseRequestSource2;
|
||||||
|
const isFormValid = formData.productName && formData.phone && isPhoneValid && formData.customerName && formData.street && formData.house && isWarehouseRequestSourceValid && isWarehouseRequestSource2Valid;
|
||||||
|
|
||||||
|
const handlePickupLocationChange = (pickupLocation: PickupLocation) => {
|
||||||
|
setFormData({
|
||||||
|
...formData,
|
||||||
|
pickupLocation,
|
||||||
|
warehouseRequestSource: pickupLocation === 'warehouse' ? formData.warehouseRequestSource : null,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePickupLocation2Change = (pickupLocation2: PickupLocation) => {
|
||||||
|
setFormData({
|
||||||
|
...formData,
|
||||||
|
pickupLocation2,
|
||||||
|
warehouseRequestSource2: pickupLocation2 === 'warehouse' ? formData.warehouseRequestSource2 : null,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleSubmit = async (e: React.FormEvent) => {
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -107,6 +133,8 @@ export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDa
|
|||||||
date: defaultDate || getTodayFrontend(),
|
date: defaultDate || getTodayFrontend(),
|
||||||
pickupLocation: 'warehouse',
|
pickupLocation: 'warehouse',
|
||||||
pickupLocation2: null,
|
pickupLocation2: null,
|
||||||
|
warehouseRequestSource: null,
|
||||||
|
warehouseRequestSource2: null,
|
||||||
productName: '',
|
productName: '',
|
||||||
productName2: '',
|
productName2: '',
|
||||||
customerName: '',
|
customerName: '',
|
||||||
@@ -165,10 +193,21 @@ export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDa
|
|||||||
<Select
|
<Select
|
||||||
label="Место загрузки"
|
label="Место загрузки"
|
||||||
value={formData.pickupLocation}
|
value={formData.pickupLocation}
|
||||||
onChange={(e) => setFormData({ ...formData, pickupLocation: e.target.value as PickupLocation })}
|
onChange={(e) => handlePickupLocationChange(e.target.value as PickupLocation)}
|
||||||
options={pickupOptions}
|
options={pickupOptions}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{formData.pickupLocation === 'warehouse' && (
|
||||||
|
<Select
|
||||||
|
label="От кого заявка *"
|
||||||
|
value={formData.warehouseRequestSource || ''}
|
||||||
|
onChange={(e) => setFormData({ ...formData, warehouseRequestSource: e.target.value ? e.target.value as DeliveryRequestSource : null })}
|
||||||
|
options={requestSourceOptions}
|
||||||
|
required
|
||||||
|
error={!isWarehouseRequestSourceValid ? 'Выберите, от кого исходит заявка' : undefined}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
label="Название товара"
|
label="Название товара"
|
||||||
value={formData.productName}
|
value={formData.productName}
|
||||||
@@ -287,10 +326,14 @@ export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDa
|
|||||||
id="hasSecondPickup"
|
id="hasSecondPickup"
|
||||||
checked={showSecondPickup}
|
checked={showSecondPickup}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setShowSecondPickup(e.target.checked);
|
const checked = e.target.checked;
|
||||||
if (!e.target.checked) {
|
setShowSecondPickup(checked);
|
||||||
setFormData({ ...formData, pickupLocation2: null, productName2: '' });
|
setFormData({
|
||||||
}
|
...formData,
|
||||||
|
pickupLocation2: checked ? formData.pickupLocation2 || 'warehouse' : null,
|
||||||
|
warehouseRequestSource2: checked ? formData.warehouseRequestSource2 : null,
|
||||||
|
productName2: checked ? formData.productName2 : '',
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
className="w-4 h-4 text-[#1B263B] border-[#c5c6cd] rounded focus:ring-[#1B263B]"
|
className="w-4 h-4 text-[#1B263B] border-[#c5c6cd] rounded focus:ring-[#1B263B]"
|
||||||
/>
|
/>
|
||||||
@@ -305,9 +348,19 @@ export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDa
|
|||||||
<Select
|
<Select
|
||||||
label="Место загрузки 2"
|
label="Место загрузки 2"
|
||||||
value={formData.pickupLocation2 || ''}
|
value={formData.pickupLocation2 || ''}
|
||||||
onChange={(e) => setFormData({ ...formData, pickupLocation2: e.target.value as PickupLocation })}
|
onChange={(e) => handlePickupLocation2Change(e.target.value as PickupLocation)}
|
||||||
options={pickupOptions}
|
options={pickupOptions}
|
||||||
/>
|
/>
|
||||||
|
{formData.pickupLocation2 === 'warehouse' && (
|
||||||
|
<Select
|
||||||
|
label="От кого заявка 2 *"
|
||||||
|
value={formData.warehouseRequestSource2 || ''}
|
||||||
|
onChange={(e) => setFormData({ ...formData, warehouseRequestSource2: e.target.value ? e.target.value as DeliveryRequestSource : null })}
|
||||||
|
options={requestSourceOptions}
|
||||||
|
required
|
||||||
|
error={!isWarehouseRequestSource2Valid ? 'Выберите, от кого исходит заявка' : undefined}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<Input
|
<Input
|
||||||
label="Название товара 2"
|
label="Название товара 2"
|
||||||
value={formData.productName2}
|
value={formData.productName2}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { MapPin, Phone } from 'lucide-react';
|
import { MapPin, Phone } from 'lucide-react';
|
||||||
import type { Delivery } from '../../types';
|
import type { Delivery } from '../../types';
|
||||||
import { pickupLocationLabels } from '../../types';
|
import { formatPickupLocation } from '../../types';
|
||||||
import { StatusBadge } from './StatusBadge';
|
import { StatusBadge } from './StatusBadge';
|
||||||
|
|
||||||
const CITY = 'kokshetau';
|
const CITY = 'kokshetau';
|
||||||
@@ -37,8 +37,8 @@ export const DeliveryRow = memo(({ delivery, onStatusChange, onEdit, onDelete }:
|
|||||||
<td className="px-4 py-3 text-sm text-[#1b1b1d]">{delivery.date}</td>
|
<td className="px-4 py-3 text-sm text-[#1b1b1d]">{delivery.date}</td>
|
||||||
<td className="px-4 py-3 text-sm text-[#1b1b1d]">
|
<td className="px-4 py-3 text-sm text-[#1b1b1d]">
|
||||||
{delivery.pickupLocation2
|
{delivery.pickupLocation2
|
||||||
? `${pickupLocationLabels[delivery.pickupLocation]} + ${pickupLocationLabels[delivery.pickupLocation2]}`
|
? `${formatPickupLocation(delivery.pickupLocation, delivery.warehouseRequestSource)} + ${formatPickupLocation(delivery.pickupLocation2, delivery.warehouseRequestSource2)}`
|
||||||
: pickupLocationLabels[delivery.pickupLocation]}
|
: formatPickupLocation(delivery.pickupLocation, delivery.warehouseRequestSource)}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-4 py-3 text-sm text-[#1b1b1d]">
|
<td className="px-4 py-3 text-sm text-[#1b1b1d]">
|
||||||
{delivery.productName}
|
{delivery.productName}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { PickupLocation } from '../types';
|
import type { DeliveryRequestSource, PickupLocation } from '../types';
|
||||||
import { pickupLocationLabels } from '../types';
|
import { deliveryRequestSourceLabels, pickupLocationLabels } from '../types';
|
||||||
|
|
||||||
export const pickupOptions: { value: PickupLocation; label: string }[] = [
|
export const pickupOptions: { value: PickupLocation; label: string }[] = [
|
||||||
{ value: 'warehouse', label: pickupLocationLabels.warehouse },
|
{ value: 'warehouse', label: pickupLocationLabels.warehouse },
|
||||||
@@ -12,3 +12,9 @@ export const pickupFilterOptions: { value: PickupLocation | 'all'; label: string
|
|||||||
{ value: 'all', label: 'Все места загрузки' },
|
{ value: 'all', label: 'Все места загрузки' },
|
||||||
...pickupOptions,
|
...pickupOptions,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const deliveryRequestSourceOptions: { value: DeliveryRequestSource; label: string }[] = [
|
||||||
|
{ value: 'symbat', label: deliveryRequestSourceLabels.symbat },
|
||||||
|
{ value: 'nursaya', label: deliveryRequestSourceLabels.nursaya },
|
||||||
|
{ value: 'galaktika', label: deliveryRequestSourceLabels.galaktika },
|
||||||
|
];
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { format, startOfMonth, endOfMonth, eachDayOfInterval, isToday, getDay }
|
|||||||
import { ru } from 'date-fns/locale';
|
import { ru } from 'date-fns/locale';
|
||||||
import { useDeliveryStore } from '../stores/deliveryStore';
|
import { useDeliveryStore } from '../stores/deliveryStore';
|
||||||
import type { Delivery } from '../types';
|
import type { Delivery } from '../types';
|
||||||
import { pickupLocationLabels } from '../types';
|
import { formatPickupLocation } from '../types';
|
||||||
import { Button } from '../components/ui/Button';
|
import { Button } from '../components/ui/Button';
|
||||||
import { Card } from '../components/ui/Card';
|
import { Card } from '../components/ui/Card';
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ const Dashboard = ({ onDateSelect, onAddDelivery }: DashboardProps) => {
|
|||||||
</tr>
|
</tr>
|
||||||
${dayDeliveries.map((d: Delivery) => `
|
${dayDeliveries.map((d: Delivery) => `
|
||||||
<tr>
|
<tr>
|
||||||
<td>${d.pickupLocation2 ? pickupLocationLabels[d.pickupLocation] + ' + ' + pickupLocationLabels[d.pickupLocation2] : pickupLocationLabels[d.pickupLocation]}</td>
|
<td>${d.pickupLocation2 ? formatPickupLocation(d.pickupLocation, d.warehouseRequestSource) + ' + ' + formatPickupLocation(d.pickupLocation2, d.warehouseRequestSource2) : formatPickupLocation(d.pickupLocation, d.warehouseRequestSource)}</td>
|
||||||
<td>${d.productName}${d.productName2 ? '<br><small>+ ' + d.productName2 + '</small>' : ''}</td>
|
<td>${d.productName}${d.productName2 ? '<br><small>+ ' + d.productName2 + '</small>' : ''}</td>
|
||||||
<td>${d.customerName}</td>
|
<td>${d.customerName}</td>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export type PickupLocation = 'warehouse' | 'symbat' | 'nursaya' | 'galaktika';
|
export type PickupLocation = 'warehouse' | 'symbat' | 'nursaya' | 'galaktika';
|
||||||
|
export type DeliveryRequestSource = 'symbat' | 'nursaya' | 'galaktika';
|
||||||
export type DeliveryStatus = 'new' | 'delivered';
|
export type DeliveryStatus = 'new' | 'delivered';
|
||||||
|
|
||||||
export interface Delivery {
|
export interface Delivery {
|
||||||
@@ -6,6 +7,8 @@ export interface Delivery {
|
|||||||
date: string; // DD-MM-YYYY
|
date: string; // DD-MM-YYYY
|
||||||
pickupLocation: PickupLocation;
|
pickupLocation: PickupLocation;
|
||||||
pickupLocation2?: PickupLocation | null;
|
pickupLocation2?: PickupLocation | null;
|
||||||
|
warehouseRequestSource?: DeliveryRequestSource | null;
|
||||||
|
warehouseRequestSource2?: DeliveryRequestSource | null;
|
||||||
productName: string;
|
productName: string;
|
||||||
productName2?: string | null;
|
productName2?: string | null;
|
||||||
customerName: string;
|
customerName: string;
|
||||||
@@ -32,6 +35,21 @@ export const pickupLocationLabels: Record<PickupLocation, string> = {
|
|||||||
galaktika: 'Галактика',
|
galaktika: 'Галактика',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const deliveryRequestSourceLabels: Record<DeliveryRequestSource, string> = {
|
||||||
|
symbat: 'Сымбат',
|
||||||
|
nursaya: 'Нурсая',
|
||||||
|
galaktika: 'Галактика',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const formatPickupLocation = (
|
||||||
|
pickupLocation: PickupLocation,
|
||||||
|
warehouseRequestSource?: DeliveryRequestSource | null,
|
||||||
|
): string => {
|
||||||
|
if (pickupLocation !== 'warehouse' || !warehouseRequestSource) {
|
||||||
|
return pickupLocationLabels[pickupLocation];
|
||||||
|
}
|
||||||
|
return `${pickupLocationLabels[pickupLocation]} · от ${deliveryRequestSourceLabels[warehouseRequestSource]}`;
|
||||||
|
};
|
||||||
|
|
||||||
export const statusLabels: Record<DeliveryStatus, string> = {
|
export const statusLabels: Record<DeliveryStatus, string> = {
|
||||||
new: 'Новое',
|
new: 'Новое',
|
||||||
|
|||||||
Reference in New Issue
Block a user