diff --git a/cmd/api/main.go b/cmd/api/main.go index e9d894f..bceb268 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -1,16 +1,36 @@ package main import ( + "context" "log" "net/http" + "os" "time" + "gitea.starryskymeow.cn/B309/datamarket/internal/handler" + "gitea.starryskymeow.cn/B309/datamarket/internal/repository" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" - "github.com/go-chi/render" + "github.com/jackc/pgx/v5/pgxpool" ) func main() { + // db connect + ctx := context.Background() + + pool, err := pgxpool.New(ctx, os.Getenv("DATABASE_URL")) + if err != nil { + log.Fatal(err) + } + defer pool.Close() + + if err := pool.Ping(ctx); err != nil { + log.Fatal(err) + } + + queries := repository.New(pool) + + // route r := chi.NewRouter() r.Use(middleware.RequestID) @@ -19,15 +39,15 @@ func main() { r.Use(middleware.Recoverer) r.Use(middleware.Timeout(60 * time.Second)) - r.Get("/", func(w http.ResponseWriter, r *http.Request) { - render.JSON(w, r, map[string]interface{}{ - "code": 0, - "message": "Hello World", - "data": struct{}{}, + r.Route("/api", func(r chi.Router) { + r.Route("/assets", func(r chi.Router) { + r.Post("/", handler.CreateDataAsset(queries)) + r.Get("/", handler.ListDataAssets(queries)) + r.Get("/{id}", handler.GetDataAsset(queries)) }) }) - err := http.ListenAndServe(":8080", r) + err = http.ListenAndServe(":8080", r) if err != nil { log.Fatal(err) } diff --git a/db/migration/000001_init.down.sql b/db/migration/000001_init.down.sql new file mode 100644 index 0000000..5abf2ed --- /dev/null +++ b/db/migration/000001_init.down.sql @@ -0,0 +1,5 @@ +DROP TABLE IF EXISTS "orders"; +DROP TABLE IF EXISTS "validations"; +DROP TABLE IF EXISTS "pricing_results"; +DROP TABLE IF EXISTS "buyer_requests"; +DROP TABLE IF EXISTS "data_assets"; diff --git a/db/migration/000001_init.up.sql b/db/migration/000001_init.up.sql new file mode 100644 index 0000000..f9808f1 --- /dev/null +++ b/db/migration/000001_init.up.sql @@ -0,0 +1,95 @@ +CREATE TABLE IF NOT EXISTS "data_assets" +( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + asset_name TEXT NOT NULL, + asset_type TEXT NOT NULL, + domain TEXT NOT NULL, + application_scene TEXT, + data_description TEXT NOT NULL, + data_scale TEXT NOT NULL, + collection_method TEXT NOT NULL, + labeling_status TEXT, + update_frequency TEXT, + privacy_level TEXT NOT NULL, + permission_mode TEXT NOT NULL, + supports_validation BOOLEAN NOT NULL, + seller_expected_price_min NUMERIC(20, 2), + seller_expected_price_max NUMERIC(20, 2), + quality_level TEXT, + scarcity_level TEXT, + base_value_score NUMERIC(20, 2), + base_price_min NUMERIC(20, 2), + base_price_max NUMERIC(20, 2), + asset_status TEXT NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +CREATE TABLE IF NOT EXISTS "buyer_requests" +( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + asset_id UUID NOT NULL REFERENCES data_assets (id), + task_type TEXT NOT NULL, + model_type TEXT NOT NULL, + buyer_budget_min NUMERIC(20, 2), + buyer_budget_max NUMERIC(20, 2), + privacy_requirement TEXT, + usage_purpose TEXT, + request_note TEXT, + request_status TEXT NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +CREATE TABLE IF NOT EXISTS "pricing_results" +( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + asset_id UUID NOT NULL REFERENCES data_assets (id), + request_id UUID REFERENCES buyer_requests (id), + scenario_value_score NUMERIC(20, 2), + scenario_price_min NUMERIC(20, 2), + scenario_price_max NUMERIC(20, 2), + suggested_price NUMERIC(20, 2), + success_probability NUMERIC(5, 4), + pricing_reason_1 TEXT, + pricing_reason_2 TEXT, + pricing_reason_3 TEXT, + verification_suggestion TEXT, + pricing_status TEXT NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +CREATE TABLE IF NOT EXISTS "validations" +( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + asset_id UUID NOT NULL REFERENCES data_assets (id), + request_id UUID REFERENCES buyer_requests (id), + validation_type TEXT, + validation_requested BOOLEAN NOT NULL, + validation_status TEXT NOT NULL, + validation_signal TEXT, + validation_score NUMERIC(5, 4), + risk_warning TEXT, + continue_recommendation TEXT, + validation_created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + validation_finished_at TIMESTAMPTZ +); + +CREATE TABLE IF NOT EXISTS "orders" +( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + asset_id UUID NOT NULL REFERENCES data_assets (id), + request_id UUID REFERENCES buyer_requests (id), + pricing_id UUID REFERENCES pricing_results (id), + validation_id UUID REFERENCES validations (id), + asset_name TEXT NOT NULL, + current_price NUMERIC(20, 2) NOT NULL, + negotiation_min NUMERIC(20, 2), + negotiation_max NUMERIC(20, 2), + validation_used BOOLEAN NOT NULL, + delivery_mode TEXT NOT NULL, + order_status TEXT NOT NULL, + order_created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + order_updated_at TIMESTAMPTZ NOT NULL DEFAULT now() +); diff --git a/db/query/market.sql b/db/query/market.sql new file mode 100644 index 0000000..69219e8 --- /dev/null +++ b/db/query/market.sql @@ -0,0 +1,87 @@ +-- name: CreateDataAsset :one +INSERT INTO data_assets (asset_name, asset_type, domain, application_scene, + data_description, data_scale, collection_method, labeling_status, + update_frequency, privacy_level, permission_mode, supports_validation, + seller_expected_price_min, seller_expected_price_max, asset_status) +VALUES ($1, $2, $3, $4, + $5, $6, $7, $8, + $9, $10, $11, $12, + $13, $14, $15) +RETURNING *; + + +-- name: GetDataAsset :one +SELECT * +FROM data_assets +WHERE id = $1; + +-- name: ListDataAssets :many +SELECT * +FROM data_assets +WHERE ( + NULLIF(sqlc.narg(keyword)::text, '') IS NULL + OR asset_name ILIKE '%' || sqlc.narg(keyword)::text || '%' + OR data_description ILIKE '%' || sqlc.narg(keyword)::text || '%' + ) + AND ( + NULLIF(sqlc.narg(asset_type)::text, '') IS NULL + OR asset_type = sqlc.narg(asset_type)::text + ) + AND ( + NULLIF(sqlc.narg(domain)::text, '') IS NULL + OR domain = sqlc.narg(domain)::text + ) + AND ( + NULLIF(sqlc.narg(privacy_level)::text, '') IS NULL + OR privacy_level = sqlc.narg(privacy_level)::text + ) + AND ( + sqlc.narg(supports_validation)::boolean IS NULL + OR supports_validation = sqlc.narg(supports_validation)::boolean + ) +ORDER BY created_at DESC, id DESC +LIMIT $1 OFFSET $2; + +-- name: GetBuyerRequest :one +SELECT * +FROM buyer_requests +WHERE id = $1; + +-- name: ListBuyerRequests :many +SELECT * +FROM buyer_requests +ORDER BY created_at DESC, id DESC +LIMIT $1 OFFSET $2; + +-- name: GetPricingResult :one +SELECT * +FROM pricing_results +WHERE id = $1; + +-- name: ListPricingResults :many +SELECT * +FROM pricing_results +ORDER BY created_at DESC, id DESC +LIMIT $1 OFFSET $2; + +-- name: GetValidation :one +SELECT * +FROM validations +WHERE id = $1; + +-- name: ListValidations :many +SELECT * +FROM validations +ORDER BY validation_created_at DESC, id DESC +LIMIT $1 OFFSET $2; + +-- name: GetOrder :one +SELECT * +FROM orders +WHERE id = $1; + +-- name: ListOrders :many +SELECT * +FROM orders +ORDER BY order_created_at DESC, id DESC +LIMIT $1 OFFSET $2; diff --git a/go.mod b/go.mod index 9719d5c..3471912 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,15 @@ go 1.26.1 require ( github.com/go-chi/chi/v5 v5.2.5 github.com/go-chi/render v1.0.3 + github.com/gorilla/schema v1.4.1 + github.com/jackc/pgx/v5 v5.9.1 ) -require github.com/ajg/form v1.5.1 // indirect +require ( + github.com/ajg/form v1.5.1 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect + github.com/jackc/puddle/v2 v2.2.2 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/text v0.29.0 // indirect +) diff --git a/go.sum b/go.sum index c358be3..515e9ca 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,34 @@ github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= +github.com/gorilla/schema v1.4.1 h1:jUg5hUjCSDZpNGLuXQOgIWGdlgrIdYvgQ0wZtdK1M3E= +github.com/gorilla/schema v1.4.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.9.1 h1:uwrxJXBnx76nyISkhr33kQLlUqjv7et7b9FjCen/tdc= +github.com/jackc/pgx/v5 v5.9.1/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= +github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= +github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/handler/data_assets.go b/internal/handler/data_assets.go new file mode 100644 index 0000000..e8657d1 --- /dev/null +++ b/internal/handler/data_assets.go @@ -0,0 +1,140 @@ +package handler + +import ( + "log" + "net/http" + + "gitea.starryskymeow.cn/B309/datamarket/internal/repository" + "github.com/go-chi/chi/v5" + "github.com/go-chi/render" + "github.com/jackc/pgx/v5/pgtype" +) + +type CreateDataAssetRequest struct { + AssetName string `json:"asset_name"` + AssetType string `json:"asset_type"` + Domain string `json:"domain"` + ApplicationScene pgtype.Text `json:"application_scene"` + DataDescription string `json:"data_description"` + DataScale string `json:"data_scale"` + CollectionMethod string `json:"collection_method"` + LabelingStatus pgtype.Text `json:"labeling_status"` + UpdateFrequency pgtype.Text `json:"update_frequency"` + PrivacyLevel string `json:"privacy_level"` + PermissionMode string `json:"permission_mode"` + SupportsValidation bool `json:"supports_validation"` + SellerExpectedPriceMin pgtype.Numeric `json:"seller_expected_price_min"` + SellerExpectedPriceMax pgtype.Numeric `json:"seller_expected_price_max"` +} + +func (req *CreateDataAssetRequest) Bind(r *http.Request) error { + return nil +} + +type ListDataAssetsParams struct { + Limit *int32 `json:"limit" schema:"limit"` + Offset *int32 `json:"offset" schema:"offset"` + Keyword *string `json:"keyword" schema:"keyword"` + AssetType *string `json:"asset_type" schema:"asset_type"` + Domain *string `json:"domain" schema:"domain"` + PrivacyLevel *string `json:"privacy_level" schema:"privacy_level"` + SupportsValidation *bool `json:"supports_validation" schema:"supports_validation"` +} + +// CreateDataAsset POST /api/assets +func CreateDataAsset(queries *repository.Queries) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + req := &CreateDataAssetRequest{} + err := render.Bind(r, req) + if err != nil { + render.Status(r, http.StatusBadRequest) + render.JSON(w, r, Response[any]{ + Code: http.StatusBadRequest, + Message: "request data error: " + err.Error(), + }) + return + } + + dataAsset, err := queries.CreateDataAsset(r.Context(), repository.CreateDataAssetParams{ + AssetName: req.AssetName, + AssetType: req.AssetType, + Domain: req.Domain, + ApplicationScene: req.ApplicationScene, + DataDescription: req.DataDescription, + DataScale: req.DataScale, + CollectionMethod: req.CollectionMethod, + LabelingStatus: req.LabelingStatus, + UpdateFrequency: req.UpdateFrequency, + PrivacyLevel: req.PrivacyLevel, + PermissionMode: req.PermissionMode, + SupportsValidation: req.SupportsValidation, + SellerExpectedPriceMin: req.SellerExpectedPriceMin, + SellerExpectedPriceMax: req.SellerExpectedPriceMax, + AssetStatus: "已上架", + }) + + render.Status(r, http.StatusCreated) + render.JSON(w, r, Response[repository.DataAsset]{ + Code: 0, + Message: "create assets successfully", + Data: dataAsset, + }) + } +} + +// GetDataAsset GET /api/assets/{id} +func GetDataAsset(queries *repository.Queries) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var id pgtype.UUID + err := id.Scan(chi.URLParam(r, "id")) + if err != nil { + render.Status(r, http.StatusBadRequest) + render.JSON(w, r, Response[any]{ + Code: http.StatusBadRequest, + Message: "request data error: " + err.Error(), + }) + return + } + + dataAsset, err := queries.GetDataAsset(r.Context(), id) + if err != nil { + if err.Error() == "no rows in result set" { + render.Status(r, http.StatusNotFound) + render.JSON(w, r, Response[any]{ + Code: http.StatusNotFound, + Message: "data_asset not found", + }) + } else { + render.Status(r, http.StatusInternalServerError) + render.JSON(w, r, Response[any]{ + Code: http.StatusInternalServerError, + Message: "internal server error", + }) + } + return + } + + render.Status(r, http.StatusOK) + render.JSON(w, r, Response[repository.DataAsset]{ + Code: 0, + Message: "get asset successfully", + Data: dataAsset, + }) + } +} + +// ListDataAssets GET /api/assets +func ListDataAssets(queries *repository.Queries) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + params := &ListDataAssetsParams{} + if err := decoder.Decode(params, r.URL.Query()); err != nil { + render.Status(r, http.StatusBadRequest) + render.JSON(w, r, Response[any]{ + Code: http.StatusBadRequest, + Message: "request data error: " + err.Error(), + }) + return + } + log.Println(params) + } +} diff --git a/internal/handler/handler.go b/internal/handler/handler.go new file mode 100644 index 0000000..30cd8d1 --- /dev/null +++ b/internal/handler/handler.go @@ -0,0 +1,11 @@ +package handler + +import "github.com/gorilla/schema" + +type Response[T any] struct { + Code int `json:"code"` + Message string `json:"message"` + Data T `json:"data,omitempty"` +} + +var decoder = schema.NewDecoder() diff --git a/internal/repository/db.go b/internal/repository/db.go new file mode 100644 index 0000000..b196af2 --- /dev/null +++ b/internal/repository/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 + +package repository + +import ( + "context" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgconn" +) + +type DBTX interface { + Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error) + Query(context.Context, string, ...interface{}) (pgx.Rows, error) + QueryRow(context.Context, string, ...interface{}) pgx.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx pgx.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/repository/market.sql.go b/internal/repository/market.sql.go new file mode 100644 index 0000000..4ad7226 --- /dev/null +++ b/internal/repository/market.sql.go @@ -0,0 +1,510 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 +// source: market.sql + +package repository + +import ( + "context" + + "github.com/jackc/pgx/v5/pgtype" +) + +const createDataAsset = `-- name: CreateDataAsset :one +INSERT INTO data_assets (asset_name, asset_type, domain, application_scene, + data_description, data_scale, collection_method, labeling_status, + update_frequency, privacy_level, permission_mode, supports_validation, + seller_expected_price_min, seller_expected_price_max, asset_status) +VALUES ($1, $2, $3, $4, + $5, $6, $7, $8, + $9, $10, $11, $12, + $13, $14, $15) +RETURNING id, asset_name, asset_type, domain, application_scene, data_description, data_scale, collection_method, labeling_status, update_frequency, privacy_level, permission_mode, supports_validation, seller_expected_price_min, seller_expected_price_max, quality_level, scarcity_level, base_value_score, base_price_min, base_price_max, asset_status, created_at, updated_at +` + +type CreateDataAssetParams struct { + AssetName string `json:"asset_name"` + AssetType string `json:"asset_type"` + Domain string `json:"domain"` + ApplicationScene pgtype.Text `json:"application_scene"` + DataDescription string `json:"data_description"` + DataScale string `json:"data_scale"` + CollectionMethod string `json:"collection_method"` + LabelingStatus pgtype.Text `json:"labeling_status"` + UpdateFrequency pgtype.Text `json:"update_frequency"` + PrivacyLevel string `json:"privacy_level"` + PermissionMode string `json:"permission_mode"` + SupportsValidation bool `json:"supports_validation"` + SellerExpectedPriceMin pgtype.Numeric `json:"seller_expected_price_min"` + SellerExpectedPriceMax pgtype.Numeric `json:"seller_expected_price_max"` + AssetStatus string `json:"asset_status"` +} + +func (q *Queries) CreateDataAsset(ctx context.Context, arg CreateDataAssetParams) (DataAsset, error) { + row := q.db.QueryRow(ctx, createDataAsset, + arg.AssetName, + arg.AssetType, + arg.Domain, + arg.ApplicationScene, + arg.DataDescription, + arg.DataScale, + arg.CollectionMethod, + arg.LabelingStatus, + arg.UpdateFrequency, + arg.PrivacyLevel, + arg.PermissionMode, + arg.SupportsValidation, + arg.SellerExpectedPriceMin, + arg.SellerExpectedPriceMax, + arg.AssetStatus, + ) + var i DataAsset + err := row.Scan( + &i.ID, + &i.AssetName, + &i.AssetType, + &i.Domain, + &i.ApplicationScene, + &i.DataDescription, + &i.DataScale, + &i.CollectionMethod, + &i.LabelingStatus, + &i.UpdateFrequency, + &i.PrivacyLevel, + &i.PermissionMode, + &i.SupportsValidation, + &i.SellerExpectedPriceMin, + &i.SellerExpectedPriceMax, + &i.QualityLevel, + &i.ScarcityLevel, + &i.BaseValueScore, + &i.BasePriceMin, + &i.BasePriceMax, + &i.AssetStatus, + &i.CreatedAt, + &i.UpdatedAt, + ) + return i, err +} + +const getBuyerRequest = `-- name: GetBuyerRequest :one +SELECT id, asset_id, task_type, model_type, buyer_budget_min, buyer_budget_max, privacy_requirement, usage_purpose, request_note, request_status, created_at, updated_at +FROM buyer_requests +WHERE id = $1 +` + +func (q *Queries) GetBuyerRequest(ctx context.Context, id pgtype.UUID) (BuyerRequest, error) { + row := q.db.QueryRow(ctx, getBuyerRequest, id) + var i BuyerRequest + err := row.Scan( + &i.ID, + &i.AssetID, + &i.TaskType, + &i.ModelType, + &i.BuyerBudgetMin, + &i.BuyerBudgetMax, + &i.PrivacyRequirement, + &i.UsagePurpose, + &i.RequestNote, + &i.RequestStatus, + &i.CreatedAt, + &i.UpdatedAt, + ) + return i, err +} + +const getDataAsset = `-- name: GetDataAsset :one +SELECT id, asset_name, asset_type, domain, application_scene, data_description, data_scale, collection_method, labeling_status, update_frequency, privacy_level, permission_mode, supports_validation, seller_expected_price_min, seller_expected_price_max, quality_level, scarcity_level, base_value_score, base_price_min, base_price_max, asset_status, created_at, updated_at +FROM data_assets +WHERE id = $1 +` + +func (q *Queries) GetDataAsset(ctx context.Context, id pgtype.UUID) (DataAsset, error) { + row := q.db.QueryRow(ctx, getDataAsset, id) + var i DataAsset + err := row.Scan( + &i.ID, + &i.AssetName, + &i.AssetType, + &i.Domain, + &i.ApplicationScene, + &i.DataDescription, + &i.DataScale, + &i.CollectionMethod, + &i.LabelingStatus, + &i.UpdateFrequency, + &i.PrivacyLevel, + &i.PermissionMode, + &i.SupportsValidation, + &i.SellerExpectedPriceMin, + &i.SellerExpectedPriceMax, + &i.QualityLevel, + &i.ScarcityLevel, + &i.BaseValueScore, + &i.BasePriceMin, + &i.BasePriceMax, + &i.AssetStatus, + &i.CreatedAt, + &i.UpdatedAt, + ) + return i, err +} + +const getOrder = `-- name: GetOrder :one +SELECT id, asset_id, request_id, pricing_id, validation_id, asset_name, current_price, negotiation_min, negotiation_max, validation_used, delivery_mode, order_status, order_created_at, order_updated_at +FROM orders +WHERE id = $1 +` + +func (q *Queries) GetOrder(ctx context.Context, id pgtype.UUID) (Order, error) { + row := q.db.QueryRow(ctx, getOrder, id) + var i Order + err := row.Scan( + &i.ID, + &i.AssetID, + &i.RequestID, + &i.PricingID, + &i.ValidationID, + &i.AssetName, + &i.CurrentPrice, + &i.NegotiationMin, + &i.NegotiationMax, + &i.ValidationUsed, + &i.DeliveryMode, + &i.OrderStatus, + &i.OrderCreatedAt, + &i.OrderUpdatedAt, + ) + return i, err +} + +const getPricingResult = `-- name: GetPricingResult :one +SELECT id, asset_id, request_id, scenario_value_score, scenario_price_min, scenario_price_max, suggested_price, success_probability, pricing_reason_1, pricing_reason_2, pricing_reason_3, verification_suggestion, pricing_status, created_at, updated_at +FROM pricing_results +WHERE id = $1 +` + +func (q *Queries) GetPricingResult(ctx context.Context, id pgtype.UUID) (PricingResult, error) { + row := q.db.QueryRow(ctx, getPricingResult, id) + var i PricingResult + err := row.Scan( + &i.ID, + &i.AssetID, + &i.RequestID, + &i.ScenarioValueScore, + &i.ScenarioPriceMin, + &i.ScenarioPriceMax, + &i.SuggestedPrice, + &i.SuccessProbability, + &i.PricingReason1, + &i.PricingReason2, + &i.PricingReason3, + &i.VerificationSuggestion, + &i.PricingStatus, + &i.CreatedAt, + &i.UpdatedAt, + ) + return i, err +} + +const getValidation = `-- name: GetValidation :one +SELECT id, asset_id, request_id, validation_type, validation_requested, validation_status, validation_signal, validation_score, risk_warning, continue_recommendation, validation_created_at, validation_finished_at +FROM validations +WHERE id = $1 +` + +func (q *Queries) GetValidation(ctx context.Context, id pgtype.UUID) (Validation, error) { + row := q.db.QueryRow(ctx, getValidation, id) + var i Validation + err := row.Scan( + &i.ID, + &i.AssetID, + &i.RequestID, + &i.ValidationType, + &i.ValidationRequested, + &i.ValidationStatus, + &i.ValidationSignal, + &i.ValidationScore, + &i.RiskWarning, + &i.ContinueRecommendation, + &i.ValidationCreatedAt, + &i.ValidationFinishedAt, + ) + return i, err +} + +const listBuyerRequests = `-- name: ListBuyerRequests :many +SELECT id, asset_id, task_type, model_type, buyer_budget_min, buyer_budget_max, privacy_requirement, usage_purpose, request_note, request_status, created_at, updated_at +FROM buyer_requests +ORDER BY created_at DESC, id DESC +LIMIT $1 OFFSET $2 +` + +type ListBuyerRequestsParams struct { + Limit int32 `json:"limit"` + Offset int32 `json:"offset"` +} + +func (q *Queries) ListBuyerRequests(ctx context.Context, arg ListBuyerRequestsParams) ([]BuyerRequest, error) { + rows, err := q.db.Query(ctx, listBuyerRequests, arg.Limit, arg.Offset) + if err != nil { + return nil, err + } + defer rows.Close() + var items []BuyerRequest + for rows.Next() { + var i BuyerRequest + if err := rows.Scan( + &i.ID, + &i.AssetID, + &i.TaskType, + &i.ModelType, + &i.BuyerBudgetMin, + &i.BuyerBudgetMax, + &i.PrivacyRequirement, + &i.UsagePurpose, + &i.RequestNote, + &i.RequestStatus, + &i.CreatedAt, + &i.UpdatedAt, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const listDataAssets = `-- name: ListDataAssets :many +SELECT id, asset_name, asset_type, domain, application_scene, data_description, data_scale, collection_method, labeling_status, update_frequency, privacy_level, permission_mode, supports_validation, seller_expected_price_min, seller_expected_price_max, quality_level, scarcity_level, base_value_score, base_price_min, base_price_max, asset_status, created_at, updated_at +FROM data_assets +WHERE ( + NULLIF($3::text, '') IS NULL + OR asset_name ILIKE '%' || $3::text || '%' + OR data_description ILIKE '%' || $3::text || '%' + ) + AND ( + NULLIF($4::text, '') IS NULL + OR asset_type = $4::text + ) + AND ( + NULLIF($5::text, '') IS NULL + OR domain = $5::text + ) + AND ( + NULLIF($6::text, '') IS NULL + OR privacy_level = $6::text + ) + AND ( + $7::boolean IS NULL + OR supports_validation = $7::boolean + ) +ORDER BY created_at DESC, id DESC +LIMIT $1 OFFSET $2 +` + +type ListDataAssetsParams struct { + Limit int32 `json:"limit"` + Offset int32 `json:"offset"` + Keyword pgtype.Text `json:"keyword"` + AssetType pgtype.Text `json:"asset_type"` + Domain pgtype.Text `json:"domain"` + PrivacyLevel pgtype.Text `json:"privacy_level"` + SupportsValidation pgtype.Bool `json:"supports_validation"` +} + +func (q *Queries) ListDataAssets(ctx context.Context, arg ListDataAssetsParams) ([]DataAsset, error) { + rows, err := q.db.Query(ctx, listDataAssets, + arg.Limit, + arg.Offset, + arg.Keyword, + arg.AssetType, + arg.Domain, + arg.PrivacyLevel, + arg.SupportsValidation, + ) + if err != nil { + return nil, err + } + defer rows.Close() + var items []DataAsset + for rows.Next() { + var i DataAsset + if err := rows.Scan( + &i.ID, + &i.AssetName, + &i.AssetType, + &i.Domain, + &i.ApplicationScene, + &i.DataDescription, + &i.DataScale, + &i.CollectionMethod, + &i.LabelingStatus, + &i.UpdateFrequency, + &i.PrivacyLevel, + &i.PermissionMode, + &i.SupportsValidation, + &i.SellerExpectedPriceMin, + &i.SellerExpectedPriceMax, + &i.QualityLevel, + &i.ScarcityLevel, + &i.BaseValueScore, + &i.BasePriceMin, + &i.BasePriceMax, + &i.AssetStatus, + &i.CreatedAt, + &i.UpdatedAt, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const listOrders = `-- name: ListOrders :many +SELECT id, asset_id, request_id, pricing_id, validation_id, asset_name, current_price, negotiation_min, negotiation_max, validation_used, delivery_mode, order_status, order_created_at, order_updated_at +FROM orders +ORDER BY order_created_at DESC, id DESC +LIMIT $1 OFFSET $2 +` + +type ListOrdersParams struct { + Limit int32 `json:"limit"` + Offset int32 `json:"offset"` +} + +func (q *Queries) ListOrders(ctx context.Context, arg ListOrdersParams) ([]Order, error) { + rows, err := q.db.Query(ctx, listOrders, arg.Limit, arg.Offset) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Order + for rows.Next() { + var i Order + if err := rows.Scan( + &i.ID, + &i.AssetID, + &i.RequestID, + &i.PricingID, + &i.ValidationID, + &i.AssetName, + &i.CurrentPrice, + &i.NegotiationMin, + &i.NegotiationMax, + &i.ValidationUsed, + &i.DeliveryMode, + &i.OrderStatus, + &i.OrderCreatedAt, + &i.OrderUpdatedAt, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const listPricingResults = `-- name: ListPricingResults :many +SELECT id, asset_id, request_id, scenario_value_score, scenario_price_min, scenario_price_max, suggested_price, success_probability, pricing_reason_1, pricing_reason_2, pricing_reason_3, verification_suggestion, pricing_status, created_at, updated_at +FROM pricing_results +ORDER BY created_at DESC, id DESC +LIMIT $1 OFFSET $2 +` + +type ListPricingResultsParams struct { + Limit int32 `json:"limit"` + Offset int32 `json:"offset"` +} + +func (q *Queries) ListPricingResults(ctx context.Context, arg ListPricingResultsParams) ([]PricingResult, error) { + rows, err := q.db.Query(ctx, listPricingResults, arg.Limit, arg.Offset) + if err != nil { + return nil, err + } + defer rows.Close() + var items []PricingResult + for rows.Next() { + var i PricingResult + if err := rows.Scan( + &i.ID, + &i.AssetID, + &i.RequestID, + &i.ScenarioValueScore, + &i.ScenarioPriceMin, + &i.ScenarioPriceMax, + &i.SuggestedPrice, + &i.SuccessProbability, + &i.PricingReason1, + &i.PricingReason2, + &i.PricingReason3, + &i.VerificationSuggestion, + &i.PricingStatus, + &i.CreatedAt, + &i.UpdatedAt, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const listValidations = `-- name: ListValidations :many +SELECT id, asset_id, request_id, validation_type, validation_requested, validation_status, validation_signal, validation_score, risk_warning, continue_recommendation, validation_created_at, validation_finished_at +FROM validations +ORDER BY validation_created_at DESC, id DESC +LIMIT $1 OFFSET $2 +` + +type ListValidationsParams struct { + Limit int32 `json:"limit"` + Offset int32 `json:"offset"` +} + +func (q *Queries) ListValidations(ctx context.Context, arg ListValidationsParams) ([]Validation, error) { + rows, err := q.db.Query(ctx, listValidations, arg.Limit, arg.Offset) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Validation + for rows.Next() { + var i Validation + if err := rows.Scan( + &i.ID, + &i.AssetID, + &i.RequestID, + &i.ValidationType, + &i.ValidationRequested, + &i.ValidationStatus, + &i.ValidationSignal, + &i.ValidationScore, + &i.RiskWarning, + &i.ContinueRecommendation, + &i.ValidationCreatedAt, + &i.ValidationFinishedAt, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/internal/repository/models.go b/internal/repository/models.go new file mode 100644 index 0000000..59eb1f9 --- /dev/null +++ b/internal/repository/models.go @@ -0,0 +1,100 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 + +package repository + +import ( + "github.com/jackc/pgx/v5/pgtype" +) + +type BuyerRequest struct { + ID pgtype.UUID `json:"id"` + AssetID pgtype.UUID `json:"asset_id"` + TaskType string `json:"task_type"` + ModelType string `json:"model_type"` + BuyerBudgetMin pgtype.Numeric `json:"buyer_budget_min"` + BuyerBudgetMax pgtype.Numeric `json:"buyer_budget_max"` + PrivacyRequirement pgtype.Text `json:"privacy_requirement"` + UsagePurpose pgtype.Text `json:"usage_purpose"` + RequestNote pgtype.Text `json:"request_note"` + RequestStatus string `json:"request_status"` + CreatedAt pgtype.Timestamptz `json:"created_at"` + UpdatedAt pgtype.Timestamptz `json:"updated_at"` +} + +type DataAsset struct { + ID pgtype.UUID `json:"id"` + AssetName string `json:"asset_name"` + AssetType string `json:"asset_type"` + Domain string `json:"domain"` + ApplicationScene pgtype.Text `json:"application_scene"` + DataDescription string `json:"data_description"` + DataScale string `json:"data_scale"` + CollectionMethod string `json:"collection_method"` + LabelingStatus pgtype.Text `json:"labeling_status"` + UpdateFrequency pgtype.Text `json:"update_frequency"` + PrivacyLevel string `json:"privacy_level"` + PermissionMode string `json:"permission_mode"` + SupportsValidation bool `json:"supports_validation"` + SellerExpectedPriceMin pgtype.Numeric `json:"seller_expected_price_min"` + SellerExpectedPriceMax pgtype.Numeric `json:"seller_expected_price_max"` + QualityLevel pgtype.Text `json:"quality_level"` + ScarcityLevel pgtype.Text `json:"scarcity_level"` + BaseValueScore pgtype.Numeric `json:"base_value_score"` + BasePriceMin pgtype.Numeric `json:"base_price_min"` + BasePriceMax pgtype.Numeric `json:"base_price_max"` + AssetStatus string `json:"asset_status"` + CreatedAt pgtype.Timestamptz `json:"created_at"` + UpdatedAt pgtype.Timestamptz `json:"updated_at"` +} + +type Order struct { + ID pgtype.UUID `json:"id"` + AssetID pgtype.UUID `json:"asset_id"` + RequestID pgtype.UUID `json:"request_id"` + PricingID pgtype.UUID `json:"pricing_id"` + ValidationID pgtype.UUID `json:"validation_id"` + AssetName string `json:"asset_name"` + CurrentPrice pgtype.Numeric `json:"current_price"` + NegotiationMin pgtype.Numeric `json:"negotiation_min"` + NegotiationMax pgtype.Numeric `json:"negotiation_max"` + ValidationUsed bool `json:"validation_used"` + DeliveryMode string `json:"delivery_mode"` + OrderStatus string `json:"order_status"` + OrderCreatedAt pgtype.Timestamptz `json:"order_created_at"` + OrderUpdatedAt pgtype.Timestamptz `json:"order_updated_at"` +} + +type PricingResult struct { + ID pgtype.UUID `json:"id"` + AssetID pgtype.UUID `json:"asset_id"` + RequestID pgtype.UUID `json:"request_id"` + ScenarioValueScore pgtype.Numeric `json:"scenario_value_score"` + ScenarioPriceMin pgtype.Numeric `json:"scenario_price_min"` + ScenarioPriceMax pgtype.Numeric `json:"scenario_price_max"` + SuggestedPrice pgtype.Numeric `json:"suggested_price"` + SuccessProbability pgtype.Numeric `json:"success_probability"` + PricingReason1 pgtype.Text `json:"pricing_reason_1"` + PricingReason2 pgtype.Text `json:"pricing_reason_2"` + PricingReason3 pgtype.Text `json:"pricing_reason_3"` + VerificationSuggestion pgtype.Text `json:"verification_suggestion"` + PricingStatus string `json:"pricing_status"` + CreatedAt pgtype.Timestamptz `json:"created_at"` + UpdatedAt pgtype.Timestamptz `json:"updated_at"` +} + +type Validation struct { + ID pgtype.UUID `json:"id"` + AssetID pgtype.UUID `json:"asset_id"` + RequestID pgtype.UUID `json:"request_id"` + ValidationType pgtype.Text `json:"validation_type"` + ValidationRequested bool `json:"validation_requested"` + ValidationStatus string `json:"validation_status"` + ValidationSignal pgtype.Text `json:"validation_signal"` + ValidationScore pgtype.Numeric `json:"validation_score"` + RiskWarning pgtype.Text `json:"risk_warning"` + ContinueRecommendation pgtype.Text `json:"continue_recommendation"` + ValidationCreatedAt pgtype.Timestamptz `json:"validation_created_at"` + ValidationFinishedAt pgtype.Timestamptz `json:"validation_finished_at"` +} diff --git a/sqlc.yaml b/sqlc.yaml new file mode 100644 index 0000000..635be07 --- /dev/null +++ b/sqlc.yaml @@ -0,0 +1,11 @@ +version: "2" +sql: + - engine: "postgresql" + queries: "db/query" + schema: "db/migration" + gen: + go: + package: "repository" + out: "internal/repository" + sql_package: "pgx/v5" + emit_json_tags: true \ No newline at end of file