feat: add orders
This commit is contained in:
25
backend/app/http/admin/orders.go
Normal file
25
backend/app/http/admin/orders.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"quyun/app/models"
|
||||
"quyun/app/requests"
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
)
|
||||
|
||||
type OrderListQuery struct {
|
||||
OrderNumber *string `query:"order_number"`
|
||||
UserID *int64 `query:"user_id"`
|
||||
}
|
||||
|
||||
// @provider
|
||||
type orders struct{}
|
||||
|
||||
// List users
|
||||
// @Router /v1/admin/orders [get]
|
||||
// @Bind pagination query
|
||||
// @Bind query query
|
||||
func (ctl *orders) List(ctx fiber.Ctx, pagination *requests.Pagination, query *OrderListQuery) (*requests.Pager, error) {
|
||||
cond := models.Orders.BuildConditionWithKey(query.OrderNumber, query.UserID)
|
||||
return models.Orders.List(ctx.Context(), pagination, cond)
|
||||
}
|
||||
@@ -18,6 +18,13 @@ func Provide(opts ...opt.Option) error {
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := container.Container.Provide(func() (*orders, error) {
|
||||
obj := &orders{}
|
||||
|
||||
return obj, nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := container.Container.Provide(func() (*posts, error) {
|
||||
obj := &posts{}
|
||||
|
||||
@@ -27,12 +34,14 @@ func Provide(opts ...opt.Option) error {
|
||||
}
|
||||
if err := container.Container.Provide(func(
|
||||
medias *medias,
|
||||
orders *orders,
|
||||
posts *posts,
|
||||
uploads *uploads,
|
||||
users *users,
|
||||
) (contracts.HttpRoute, error) {
|
||||
obj := &Routes{
|
||||
medias: medias,
|
||||
orders: orders,
|
||||
posts: posts,
|
||||
uploads: uploads,
|
||||
users: users,
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
type Routes struct {
|
||||
log *log.Entry `inject:"false"`
|
||||
medias *medias
|
||||
orders *orders
|
||||
posts *posts
|
||||
uploads *uploads
|
||||
users *users
|
||||
@@ -38,6 +39,13 @@ func (r *Routes) Register(router fiber.Router) {
|
||||
Query[ListQuery]("query"),
|
||||
))
|
||||
|
||||
// 注册路由组: orders
|
||||
router.Get("/v1/admin/orders", DataFunc2(
|
||||
r.orders.List,
|
||||
Query[requests.Pagination]("pagination"),
|
||||
Query[OrderListQuery]("query"),
|
||||
))
|
||||
|
||||
// 注册路由组: posts
|
||||
router.Get("/v1/admin/posts", DataFunc2(
|
||||
r.posts.List,
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
var db *sql.DB
|
||||
var Medias *mediasModel
|
||||
var Orders *ordersModel
|
||||
var Posts *postsModel
|
||||
var Users *usersModel
|
||||
|
||||
@@ -16,6 +17,7 @@ var Users *usersModel
|
||||
type models struct {
|
||||
db *sql.DB
|
||||
medias *mediasModel
|
||||
orders *ordersModel
|
||||
posts *postsModel
|
||||
users *usersModel
|
||||
}
|
||||
@@ -23,6 +25,7 @@ type models struct {
|
||||
func (m *models) Prepare() error {
|
||||
db = m.db
|
||||
Medias = m.medias
|
||||
Orders = m.orders
|
||||
Posts = m.posts
|
||||
Users = m.users
|
||||
return nil
|
||||
|
||||
168
backend/app/models/orders.go
Normal file
168
backend/app/models/orders.go
Normal file
@@ -0,0 +1,168 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"quyun/app/requests"
|
||||
"quyun/database/fields"
|
||||
"quyun/database/schemas/public/model"
|
||||
"quyun/database/schemas/public/table"
|
||||
|
||||
. "github.com/go-jet/jet/v2/postgres"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// @provider
|
||||
type ordersModel struct {
|
||||
log *logrus.Entry `inject:"false"`
|
||||
}
|
||||
|
||||
func (m *ordersModel) Prepare() error {
|
||||
m.log = logrus.WithField("model", "ordersModel")
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetByID returns an order by ID
|
||||
func (m *ordersModel) GetByID(ctx context.Context, id int64) (*model.Orders, error) {
|
||||
tbl := table.Orders
|
||||
|
||||
stmt := tbl.
|
||||
SELECT(tbl.AllColumns).
|
||||
WHERE(
|
||||
tbl.ID.EQ(Int64(id)),
|
||||
)
|
||||
m.log.Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
var order model.Orders
|
||||
err := stmt.QueryContext(ctx, db, &order)
|
||||
if err != nil {
|
||||
m.log.Errorf("error querying order by ID: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &order, nil
|
||||
}
|
||||
|
||||
// BuildConditionWithKey builds the WHERE clause for order queries
|
||||
func (m *ordersModel) BuildConditionWithKey(orderNumber *string, userID *int64) BoolExpression {
|
||||
tbl := table.Orders
|
||||
|
||||
cond := Bool(true)
|
||||
|
||||
if orderNumber != nil && *orderNumber != "" {
|
||||
cond = cond.AND(
|
||||
tbl.OrderNo.LIKE(String("%" + *orderNumber + "%")),
|
||||
)
|
||||
}
|
||||
|
||||
if userID != nil {
|
||||
cond = cond.AND(
|
||||
tbl.UserID.EQ(Int(*userID)),
|
||||
)
|
||||
}
|
||||
|
||||
return cond
|
||||
}
|
||||
|
||||
// countByCondition counts orders matching the given condition
|
||||
func (m *ordersModel) countByCondition(ctx context.Context, expr BoolExpression) (int64, error) {
|
||||
var cnt struct {
|
||||
Cnt int64
|
||||
}
|
||||
|
||||
tbl := table.Orders
|
||||
stmt := SELECT(COUNT(tbl.ID).AS("cnt")).FROM(tbl).WHERE(expr)
|
||||
m.log.Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
err := stmt.QueryContext(ctx, db, &cnt)
|
||||
if err != nil {
|
||||
m.log.Errorf("error counting orders: %v", err)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return cnt.Cnt, nil
|
||||
}
|
||||
|
||||
// List returns a paginated list of orders
|
||||
func (m *ordersModel) List(ctx context.Context, pagination *requests.Pagination, cond BoolExpression) (*requests.Pager, error) {
|
||||
pagination.Format()
|
||||
|
||||
tbl := table.Orders
|
||||
stmt := tbl.
|
||||
SELECT(tbl.AllColumns).
|
||||
WHERE(cond).
|
||||
ORDER_BY(tbl.ID.DESC()).
|
||||
LIMIT(pagination.Limit).
|
||||
OFFSET(pagination.Offset)
|
||||
m.log.Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
var orders []model.Orders = make([]model.Orders, 0)
|
||||
err := stmt.QueryContext(ctx, db, &orders)
|
||||
if err != nil {
|
||||
m.log.Errorf("error querying orders: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
count, err := m.countByCondition(ctx, cond)
|
||||
if err != nil {
|
||||
m.log.Errorf("error getting order count: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &requests.Pager{
|
||||
Items: orders,
|
||||
Total: count,
|
||||
Pagination: *pagination,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Create creates a new order
|
||||
func (m *ordersModel) Create(ctx context.Context, userId, postId int64) (*model.Orders, error) {
|
||||
post, err := Posts.GetByID(ctx, postId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get post")
|
||||
}
|
||||
|
||||
model := &model.Orders{}
|
||||
model.CreatedAt = time.Now()
|
||||
model.UpdatedAt = time.Now()
|
||||
model.Status = fields.OrderStatusPending
|
||||
model.OrderNo = fmt.Sprintf("%s", time.Now().Format("20060102150405"))
|
||||
model.SubOrderNo = model.OrderNo
|
||||
model.UserID = userId
|
||||
model.PostID = postId
|
||||
model.Meta = fields.ToJson(fields.OrderMeta{})
|
||||
model.Price = post.Price
|
||||
model.Discount = post.Discount
|
||||
|
||||
tbl := table.Orders
|
||||
stmt := tbl.INSERT(tbl.MutableColumns).MODEL(model)
|
||||
m.log.Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
if _, err := stmt.ExecContext(ctx, db); err != nil {
|
||||
m.log.Errorf("error creating order: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return model, nil
|
||||
}
|
||||
|
||||
// DeleteByID soft deletes an order by ID
|
||||
func (m *ordersModel) SetStatus(ctx context.Context, orderNo string, status fields.OrderStatus) error {
|
||||
tbl := table.Orders
|
||||
stmt := tbl.
|
||||
UPDATE(tbl.Status).
|
||||
SET(status).
|
||||
WHERE(
|
||||
tbl.OrderNo.EQ(String(orderNo)),
|
||||
)
|
||||
m.log.Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
if _, err := stmt.ExecContext(ctx, db); err != nil {
|
||||
m.log.Errorf("error set order status: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
47
backend/app/models/orders_test.go
Normal file
47
backend/app/models/orders_test.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"quyun/app/service/testx"
|
||||
"quyun/database"
|
||||
"quyun/database/schemas/public/table"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"go.ipao.vip/atom/contracts"
|
||||
|
||||
// . "github.com/go-jet/jet/v2/postgres"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"go.uber.org/dig"
|
||||
)
|
||||
|
||||
type OrdersInjectParams struct {
|
||||
dig.In
|
||||
Initials []contracts.Initial `group:"initials"`
|
||||
}
|
||||
|
||||
type OrdersTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
OrdersInjectParams
|
||||
}
|
||||
|
||||
func Test_Orders(t *testing.T) {
|
||||
providers := testx.Default().With(Provide)
|
||||
testx.Serve(providers, t, func(params OrdersInjectParams) {
|
||||
suite.Run(t, &OrdersTestSuite{
|
||||
OrdersInjectParams: params,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func (s *OrdersTestSuite) Test_Create() {
|
||||
Convey("Test_Create", s.T(), func() {
|
||||
database.Truncate(context.Background(), db, table.Orders.TableName())
|
||||
|
||||
order, err := Orders.Create(context.Background(), 1, 1)
|
||||
So(err, ShouldBeNil)
|
||||
s.T().Logf("order: %v", order)
|
||||
})
|
||||
}
|
||||
@@ -23,12 +23,14 @@ func Provide(opts ...opt.Option) error {
|
||||
if err := container.Container.Provide(func(
|
||||
db *sql.DB,
|
||||
medias *mediasModel,
|
||||
orders *ordersModel,
|
||||
posts *postsModel,
|
||||
users *usersModel,
|
||||
) (contracts.Initial, error) {
|
||||
obj := &models{
|
||||
db: db,
|
||||
medias: medias,
|
||||
orders: orders,
|
||||
posts: posts,
|
||||
users: users,
|
||||
}
|
||||
@@ -40,6 +42,16 @@ func Provide(opts ...opt.Option) error {
|
||||
}, atom.GroupInitial); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := container.Container.Provide(func() (*ordersModel, error) {
|
||||
obj := &ordersModel{}
|
||||
if err := obj.Prepare(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj, nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := container.Container.Provide(func() (*postsModel, error) {
|
||||
obj := &postsModel{}
|
||||
if err := obj.Prepare(); err != nil {
|
||||
|
||||
259
backend/database/fields/orders.gen.go
Normal file
259
backend/database/fields/orders.gen.go
Normal file
@@ -0,0 +1,259 @@
|
||||
// Code generated by go-enum DO NOT EDIT.
|
||||
// Version: -
|
||||
// Revision: -
|
||||
// Build Date: -
|
||||
// Built By: -
|
||||
|
||||
package fields
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// OrderStatusPending is a OrderStatus of type Pending.
|
||||
OrderStatusPending OrderStatus = iota
|
||||
// OrderStatusPaid is a OrderStatus of type Paid.
|
||||
OrderStatusPaid
|
||||
// OrderStatusRefunding is a OrderStatus of type Refunding.
|
||||
OrderStatusRefunding
|
||||
// OrderStatusRefunded is a OrderStatus of type Refunded.
|
||||
OrderStatusRefunded
|
||||
// OrderStatusCancelled is a OrderStatus of type Cancelled.
|
||||
OrderStatusCancelled
|
||||
// OrderStatusCompleted is a OrderStatus of type Completed.
|
||||
OrderStatusCompleted
|
||||
)
|
||||
|
||||
var ErrInvalidOrderStatus = fmt.Errorf("not a valid OrderStatus, try [%s]", strings.Join(_OrderStatusNames, ", "))
|
||||
|
||||
const _OrderStatusName = "pendingpaidrefundingrefundedcancelledcompleted"
|
||||
|
||||
var _OrderStatusNames = []string{
|
||||
_OrderStatusName[0:7],
|
||||
_OrderStatusName[7:11],
|
||||
_OrderStatusName[11:20],
|
||||
_OrderStatusName[20:28],
|
||||
_OrderStatusName[28:37],
|
||||
_OrderStatusName[37:46],
|
||||
}
|
||||
|
||||
// OrderStatusNames returns a list of possible string values of OrderStatus.
|
||||
func OrderStatusNames() []string {
|
||||
tmp := make([]string, len(_OrderStatusNames))
|
||||
copy(tmp, _OrderStatusNames)
|
||||
return tmp
|
||||
}
|
||||
|
||||
// OrderStatusValues returns a list of the values for OrderStatus
|
||||
func OrderStatusValues() []OrderStatus {
|
||||
return []OrderStatus{
|
||||
OrderStatusPending,
|
||||
OrderStatusPaid,
|
||||
OrderStatusRefunding,
|
||||
OrderStatusRefunded,
|
||||
OrderStatusCancelled,
|
||||
OrderStatusCompleted,
|
||||
}
|
||||
}
|
||||
|
||||
var _OrderStatusMap = map[OrderStatus]string{
|
||||
OrderStatusPending: _OrderStatusName[0:7],
|
||||
OrderStatusPaid: _OrderStatusName[7:11],
|
||||
OrderStatusRefunding: _OrderStatusName[11:20],
|
||||
OrderStatusRefunded: _OrderStatusName[20:28],
|
||||
OrderStatusCancelled: _OrderStatusName[28:37],
|
||||
OrderStatusCompleted: _OrderStatusName[37:46],
|
||||
}
|
||||
|
||||
// String implements the Stringer interface.
|
||||
func (x OrderStatus) String() string {
|
||||
if str, ok := _OrderStatusMap[x]; ok {
|
||||
return str
|
||||
}
|
||||
return fmt.Sprintf("OrderStatus(%d)", x)
|
||||
}
|
||||
|
||||
// IsValid provides a quick way to determine if the typed value is
|
||||
// part of the allowed enumerated values
|
||||
func (x OrderStatus) IsValid() bool {
|
||||
_, ok := _OrderStatusMap[x]
|
||||
return ok
|
||||
}
|
||||
|
||||
var _OrderStatusValue = map[string]OrderStatus{
|
||||
_OrderStatusName[0:7]: OrderStatusPending,
|
||||
_OrderStatusName[7:11]: OrderStatusPaid,
|
||||
_OrderStatusName[11:20]: OrderStatusRefunding,
|
||||
_OrderStatusName[20:28]: OrderStatusRefunded,
|
||||
_OrderStatusName[28:37]: OrderStatusCancelled,
|
||||
_OrderStatusName[37:46]: OrderStatusCompleted,
|
||||
}
|
||||
|
||||
// ParseOrderStatus attempts to convert a string to a OrderStatus.
|
||||
func ParseOrderStatus(name string) (OrderStatus, error) {
|
||||
if x, ok := _OrderStatusValue[name]; ok {
|
||||
return x, nil
|
||||
}
|
||||
return OrderStatus(0), fmt.Errorf("%s is %w", name, ErrInvalidOrderStatus)
|
||||
}
|
||||
|
||||
var errOrderStatusNilPtr = errors.New("value pointer is nil") // one per type for package clashes
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (x *OrderStatus) Scan(value interface{}) (err error) {
|
||||
if value == nil {
|
||||
*x = OrderStatus(0)
|
||||
return
|
||||
}
|
||||
|
||||
// A wider range of scannable types.
|
||||
// driver.Value values at the top of the list for expediency
|
||||
switch v := value.(type) {
|
||||
case int64:
|
||||
*x = OrderStatus(v)
|
||||
case string:
|
||||
*x, err = ParseOrderStatus(v)
|
||||
if err != nil {
|
||||
// try parsing the integer value as a string
|
||||
if val, verr := strconv.Atoi(v); verr == nil {
|
||||
*x, err = OrderStatus(val), nil
|
||||
}
|
||||
}
|
||||
case []byte:
|
||||
*x, err = ParseOrderStatus(string(v))
|
||||
if err != nil {
|
||||
// try parsing the integer value as a string
|
||||
if val, verr := strconv.Atoi(string(v)); verr == nil {
|
||||
*x, err = OrderStatus(val), nil
|
||||
}
|
||||
}
|
||||
case OrderStatus:
|
||||
*x = v
|
||||
case int:
|
||||
*x = OrderStatus(v)
|
||||
case *OrderStatus:
|
||||
if v == nil {
|
||||
return errOrderStatusNilPtr
|
||||
}
|
||||
*x = *v
|
||||
case uint:
|
||||
*x = OrderStatus(v)
|
||||
case uint64:
|
||||
*x = OrderStatus(v)
|
||||
case *int:
|
||||
if v == nil {
|
||||
return errOrderStatusNilPtr
|
||||
}
|
||||
*x = OrderStatus(*v)
|
||||
case *int64:
|
||||
if v == nil {
|
||||
return errOrderStatusNilPtr
|
||||
}
|
||||
*x = OrderStatus(*v)
|
||||
case float64: // json marshals everything as a float64 if it's a number
|
||||
*x = OrderStatus(v)
|
||||
case *float64: // json marshals everything as a float64 if it's a number
|
||||
if v == nil {
|
||||
return errOrderStatusNilPtr
|
||||
}
|
||||
*x = OrderStatus(*v)
|
||||
case *uint:
|
||||
if v == nil {
|
||||
return errOrderStatusNilPtr
|
||||
}
|
||||
*x = OrderStatus(*v)
|
||||
case *uint64:
|
||||
if v == nil {
|
||||
return errOrderStatusNilPtr
|
||||
}
|
||||
*x = OrderStatus(*v)
|
||||
case *string:
|
||||
if v == nil {
|
||||
return errOrderStatusNilPtr
|
||||
}
|
||||
*x, err = ParseOrderStatus(*v)
|
||||
if err != nil {
|
||||
// try parsing the integer value as a string
|
||||
if val, verr := strconv.Atoi(*v); verr == nil {
|
||||
*x, err = OrderStatus(val), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (x OrderStatus) Value() (driver.Value, error) {
|
||||
return int64(x), nil
|
||||
}
|
||||
|
||||
// Set implements the Golang flag.Value interface func.
|
||||
func (x *OrderStatus) Set(val string) error {
|
||||
v, err := ParseOrderStatus(val)
|
||||
*x = v
|
||||
return err
|
||||
}
|
||||
|
||||
// Get implements the Golang flag.Getter interface func.
|
||||
func (x *OrderStatus) Get() interface{} {
|
||||
return *x
|
||||
}
|
||||
|
||||
// Type implements the github.com/spf13/pFlag Value interface.
|
||||
func (x *OrderStatus) Type() string {
|
||||
return "OrderStatus"
|
||||
}
|
||||
|
||||
type NullOrderStatus struct {
|
||||
OrderStatus OrderStatus
|
||||
Valid bool
|
||||
}
|
||||
|
||||
func NewNullOrderStatus(val interface{}) (x NullOrderStatus) {
|
||||
x.Scan(val) // yes, we ignore this error, it will just be an invalid value.
|
||||
return
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (x *NullOrderStatus) Scan(value interface{}) (err error) {
|
||||
if value == nil {
|
||||
x.OrderStatus, x.Valid = OrderStatus(0), false
|
||||
return
|
||||
}
|
||||
|
||||
err = x.OrderStatus.Scan(value)
|
||||
x.Valid = (err == nil)
|
||||
return
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (x NullOrderStatus) Value() (driver.Value, error) {
|
||||
if !x.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
// driver.Value accepts int64 for int values.
|
||||
return int64(x.OrderStatus), nil
|
||||
}
|
||||
|
||||
type NullOrderStatusStr struct {
|
||||
NullOrderStatus
|
||||
}
|
||||
|
||||
func NewNullOrderStatusStr(val interface{}) (x NullOrderStatusStr) {
|
||||
x.Scan(val) // yes, we ignore this error, it will just be an invalid value.
|
||||
return
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (x NullOrderStatusStr) Value() (driver.Value, error) {
|
||||
if !x.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return x.OrderStatus.String(), nil
|
||||
}
|
||||
7
backend/database/fields/orders.go
Normal file
7
backend/database/fields/orders.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package fields
|
||||
|
||||
// swagger:enum OrderStatus
|
||||
// ENUM( pending, paid, refunding, refunded, cancelled, completed)
|
||||
type OrderStatus int16
|
||||
|
||||
type OrderMeta struct{}
|
||||
26
backend/database/migrations/20250410130530_create_orders.sql
Normal file
26
backend/database/migrations/20250410130530_create_orders.sql
Normal file
@@ -0,0 +1,26 @@
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE orders(
|
||||
id SERIAL8 PRIMARY KEY,
|
||||
created_at timestamp NOT NULL DEFAULT now(),
|
||||
updated_at timestamp NOT NULL DEFAULT now(),
|
||||
order_no varchar(64) NOT NULL,
|
||||
sub_order_no varchar(64) NOT NULL DEFAULT '',
|
||||
transaction_id varchar(64) NOT NULL DEFAULT '',
|
||||
refund_transaction_id varchar(64) NOT NULL DEFAULT '',
|
||||
price int8 NOT NULL DEFAULT 0,
|
||||
discount int2 NOT NULL DEFAULT 100,
|
||||
currency varchar(10) NOT NULL DEFAULT 'CNY',
|
||||
payment_method varchar(50) NOT NULL DEFAULT 'wechatpay',
|
||||
post_id int8 NOT NULL,
|
||||
user_id int8 NOT NULL,
|
||||
status int2 NOT NULL,
|
||||
meta jsonb NOT NULL DEFAULT '{}' ::jsonb
|
||||
);
|
||||
|
||||
-- +goose StatementEnd
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DROP TABLE orders;
|
||||
|
||||
-- +goose StatementEnd
|
||||
31
backend/database/schemas/public/model/orders.go
Normal file
31
backend/database/schemas/public/model/orders.go
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// Code generated by go-jet DO NOT EDIT.
|
||||
//
|
||||
// WARNING: Changes to this file may cause incorrect behavior
|
||||
// and will be lost if the code is regenerated
|
||||
//
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"quyun/database/fields"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Orders struct {
|
||||
ID int64 `sql:"primary_key" json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
OrderNo string `json:"order_no"`
|
||||
SubOrderNo string `json:"sub_order_no"`
|
||||
TransactionID string `json:"transaction_id"`
|
||||
RefundTransactionID string `json:"refund_transaction_id"`
|
||||
Price int64 `json:"price"`
|
||||
Discount int16 `json:"discount"`
|
||||
Currency string `json:"currency"`
|
||||
PaymentMethod string `json:"payment_method"`
|
||||
PostID int64 `json:"post_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Status fields.OrderStatus `json:"status"`
|
||||
Meta fields.Json[fields.OrderMeta] `json:"meta"`
|
||||
}
|
||||
117
backend/database/schemas/public/table/orders.go
Normal file
117
backend/database/schemas/public/table/orders.go
Normal file
@@ -0,0 +1,117 @@
|
||||
//
|
||||
// Code generated by go-jet DO NOT EDIT.
|
||||
//
|
||||
// WARNING: Changes to this file may cause incorrect behavior
|
||||
// and will be lost if the code is regenerated
|
||||
//
|
||||
|
||||
package table
|
||||
|
||||
import (
|
||||
"github.com/go-jet/jet/v2/postgres"
|
||||
)
|
||||
|
||||
var Orders = newOrdersTable("public", "orders", "")
|
||||
|
||||
type ordersTable struct {
|
||||
postgres.Table
|
||||
|
||||
// Columns
|
||||
ID postgres.ColumnInteger
|
||||
CreatedAt postgres.ColumnTimestamp
|
||||
UpdatedAt postgres.ColumnTimestamp
|
||||
OrderNo postgres.ColumnString
|
||||
SubOrderNo postgres.ColumnString
|
||||
TransactionID postgres.ColumnString
|
||||
RefundTransactionID postgres.ColumnString
|
||||
Price postgres.ColumnInteger
|
||||
Discount postgres.ColumnInteger
|
||||
Currency postgres.ColumnString
|
||||
PaymentMethod postgres.ColumnString
|
||||
PostID postgres.ColumnInteger
|
||||
UserID postgres.ColumnInteger
|
||||
Status postgres.ColumnInteger
|
||||
Meta postgres.ColumnString
|
||||
|
||||
AllColumns postgres.ColumnList
|
||||
MutableColumns postgres.ColumnList
|
||||
}
|
||||
|
||||
type OrdersTable struct {
|
||||
ordersTable
|
||||
|
||||
EXCLUDED ordersTable
|
||||
}
|
||||
|
||||
// AS creates new OrdersTable with assigned alias
|
||||
func (a OrdersTable) AS(alias string) *OrdersTable {
|
||||
return newOrdersTable(a.SchemaName(), a.TableName(), alias)
|
||||
}
|
||||
|
||||
// Schema creates new OrdersTable with assigned schema name
|
||||
func (a OrdersTable) FromSchema(schemaName string) *OrdersTable {
|
||||
return newOrdersTable(schemaName, a.TableName(), a.Alias())
|
||||
}
|
||||
|
||||
// WithPrefix creates new OrdersTable with assigned table prefix
|
||||
func (a OrdersTable) WithPrefix(prefix string) *OrdersTable {
|
||||
return newOrdersTable(a.SchemaName(), prefix+a.TableName(), a.TableName())
|
||||
}
|
||||
|
||||
// WithSuffix creates new OrdersTable with assigned table suffix
|
||||
func (a OrdersTable) WithSuffix(suffix string) *OrdersTable {
|
||||
return newOrdersTable(a.SchemaName(), a.TableName()+suffix, a.TableName())
|
||||
}
|
||||
|
||||
func newOrdersTable(schemaName, tableName, alias string) *OrdersTable {
|
||||
return &OrdersTable{
|
||||
ordersTable: newOrdersTableImpl(schemaName, tableName, alias),
|
||||
EXCLUDED: newOrdersTableImpl("", "excluded", ""),
|
||||
}
|
||||
}
|
||||
|
||||
func newOrdersTableImpl(schemaName, tableName, alias string) ordersTable {
|
||||
var (
|
||||
IDColumn = postgres.IntegerColumn("id")
|
||||
CreatedAtColumn = postgres.TimestampColumn("created_at")
|
||||
UpdatedAtColumn = postgres.TimestampColumn("updated_at")
|
||||
OrderNoColumn = postgres.StringColumn("order_no")
|
||||
SubOrderNoColumn = postgres.StringColumn("sub_order_no")
|
||||
TransactionIDColumn = postgres.StringColumn("transaction_id")
|
||||
RefundTransactionIDColumn = postgres.StringColumn("refund_transaction_id")
|
||||
PriceColumn = postgres.IntegerColumn("price")
|
||||
DiscountColumn = postgres.IntegerColumn("discount")
|
||||
CurrencyColumn = postgres.StringColumn("currency")
|
||||
PaymentMethodColumn = postgres.StringColumn("payment_method")
|
||||
PostIDColumn = postgres.IntegerColumn("post_id")
|
||||
UserIDColumn = postgres.IntegerColumn("user_id")
|
||||
StatusColumn = postgres.IntegerColumn("status")
|
||||
MetaColumn = postgres.StringColumn("meta")
|
||||
allColumns = postgres.ColumnList{IDColumn, CreatedAtColumn, UpdatedAtColumn, OrderNoColumn, SubOrderNoColumn, TransactionIDColumn, RefundTransactionIDColumn, PriceColumn, DiscountColumn, CurrencyColumn, PaymentMethodColumn, PostIDColumn, UserIDColumn, StatusColumn, MetaColumn}
|
||||
mutableColumns = postgres.ColumnList{CreatedAtColumn, UpdatedAtColumn, OrderNoColumn, SubOrderNoColumn, TransactionIDColumn, RefundTransactionIDColumn, PriceColumn, DiscountColumn, CurrencyColumn, PaymentMethodColumn, PostIDColumn, UserIDColumn, StatusColumn, MetaColumn}
|
||||
)
|
||||
|
||||
return ordersTable{
|
||||
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
|
||||
|
||||
//Columns
|
||||
ID: IDColumn,
|
||||
CreatedAt: CreatedAtColumn,
|
||||
UpdatedAt: UpdatedAtColumn,
|
||||
OrderNo: OrderNoColumn,
|
||||
SubOrderNo: SubOrderNoColumn,
|
||||
TransactionID: TransactionIDColumn,
|
||||
RefundTransactionID: RefundTransactionIDColumn,
|
||||
Price: PriceColumn,
|
||||
Discount: DiscountColumn,
|
||||
Currency: CurrencyColumn,
|
||||
PaymentMethod: PaymentMethodColumn,
|
||||
PostID: PostIDColumn,
|
||||
UserID: UserIDColumn,
|
||||
Status: StatusColumn,
|
||||
Meta: MetaColumn,
|
||||
|
||||
AllColumns: allColumns,
|
||||
MutableColumns: mutableColumns,
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ package table
|
||||
func UseSchema(schema string) {
|
||||
Medias = Medias.FromSchema(schema)
|
||||
Migrations = Migrations.FromSchema(schema)
|
||||
Orders = Orders.FromSchema(schema)
|
||||
Posts = Posts.FromSchema(schema)
|
||||
UserPosts = UserPosts.FromSchema(schema)
|
||||
Users = Users.FromSchema(schema)
|
||||
|
||||
@@ -16,7 +16,11 @@ types:
|
||||
status: PostStatus
|
||||
assets: Json[[]MediaAsset]
|
||||
tags: Json[[]string]
|
||||
meta: PostMeta
|
||||
meta: Json[PostMeta]
|
||||
|
||||
users:
|
||||
status: UserStatus
|
||||
|
||||
orders:
|
||||
status: OrderStatus
|
||||
meta: Json[OrderMeta]
|
||||
|
||||
@@ -50,4 +50,8 @@ DELETE {{host}}/v1/admin/posts/103 HTTP/1.1
|
||||
|
||||
### get users
|
||||
GET {{host}}/v1/admin/users HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
### get orders
|
||||
GET {{host}}/v1/admin/orders HTTP/1.1
|
||||
Content-Type: application/json
|
||||
Reference in New Issue
Block a user