feat: go lint

This commit is contained in:
王性驊 2025-04-06 10:08:46 +08:00
parent c4617956e5
commit 7951f4b98a
24 changed files with 151 additions and 70 deletions

View File

@ -3,4 +3,18 @@ syntax = "proto3";
package product; package product;
option go_package="./product"; option go_package="./product";
service Product {}
// OKResp
message OKResp {}
// NoneReq
message NoneReq {}
message CreateCategoryReq {
string name = 1;
}
service Product {
// CreateCategory product
rpc CreateCategory(CreateCategoryReq) returns(OKResp);
}

View File

@ -1,9 +1,10 @@
package repository package repository
import ( import (
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"context" "context"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo"
) )

View File

@ -1,8 +1,9 @@
package repository package repository
import ( import (
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"context" "context"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
) )
// KYCKnow Your Customer // KYCKnow Your Customer

View File

@ -1,8 +1,9 @@
package usecase package usecase
import ( import (
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"context" "context"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
) )
type CategoryUseCase interface { type CategoryUseCase interface {

View File

@ -1,8 +1,9 @@
package usecase package usecase
import ( import (
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"context" "context"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
) )
type KYCUseCase interface { type KYCUseCase interface {

View File

@ -1,16 +1,13 @@
package usecase package usecase
import ( import (
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product"
"context" "context"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product"
) )
type ProductUseCase interface { type ProductUseCase interface {
Create(ctx context.Context, product *Product) error Base
Update(ctx context.Context, id string, product *Product) error
Delete(ctx context.Context, id string) error
Get(ctx context.Context, id string) (*ProductResp, error)
List(ctx context.Context, data ProductQueryParams) ([]*ProductResp, int64, error)
// IncOrders 新增訂單數 // IncOrders 新增訂單數
IncOrders(ctx context.Context, productID string, count int64) error IncOrders(ctx context.Context, productID string, count int64) error
// DecOrders 減少訂單數。-> 退貨時專用 // DecOrders 減少訂單數。-> 退貨時專用
@ -30,6 +27,13 @@ type ProductUseCase interface {
// ListTagBinding 根據查詢條件取得 tag binding 的資料列表 // ListTagBinding 根據查詢條件取得 tag binding 的資料列表
ListTagBinding(ctx context.Context, params TagBindingQueryParams) ([]TagsBindingTableResp, int64, error) ListTagBinding(ctx context.Context, params TagBindingQueryParams) ([]TagsBindingTableResp, int64, error)
} }
type Base interface {
Create(ctx context.Context, product *Product) error
Update(ctx context.Context, id string, product *Product) error
Delete(ctx context.Context, id string) error
Get(ctx context.Context, id string) (*ProductResp, error)
List(ctx context.Context, data ProductQueryParams) ([]*ProductResp, int64, error)
}
type Product struct { type Product struct {
UID *string // 專案擁有者 UID UID *string // 專案擁有者 UID

View File

@ -1,8 +1,9 @@
package usecase package usecase
import ( import (
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product"
"context" "context"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product"
) )
type ProductItemUseCase interface { type ProductItemUseCase interface {

View File

@ -1,9 +1,10 @@
package usecase package usecase
import ( import (
"context"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product"
"context"
) )
type ProductBaseTags interface { type ProductBaseTags interface {

View File

@ -1,12 +1,13 @@
package repository package repository
import ( import (
"context"
"errors"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
mgo "code.30cm.net/digimon/library-go/mongo" mgo "code.30cm.net/digimon/library-go/mongo"
"context"
"errors"
"time" "time"

View File

@ -1,19 +1,20 @@
package repository package repository
import ( import (
"context"
"fmt"
"testing"
"time"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
mgo "code.30cm.net/digimon/library-go/mongo" mgo "code.30cm.net/digimon/library-go/mongo"
"context"
"fmt"
"github.com/alicebob/miniredis/v2" "github.com/alicebob/miniredis/v2"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/zeromicro/go-zero/core/stores/cache" "github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/mon" "github.com/zeromicro/go-zero/core/stores/mon"
"github.com/zeromicro/go-zero/core/stores/redis" "github.com/zeromicro/go-zero/core/stores/redis"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
"testing"
"time"
) )
func SetupTestCategoryRepository(db string) (repository.CategoryRepository, func(), error) { func SetupTestCategoryRepository(db string) (repository.CategoryRepository, func(), error) {

View File

@ -1,18 +1,19 @@
package repository package repository
import ( import (
"context"
"errors"
"time"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
mgo "code.30cm.net/digimon/library-go/mongo" mgo "code.30cm.net/digimon/library-go/mongo"
"context"
"errors"
"github.com/zeromicro/go-zero/core/stores/cache" "github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/mon" "github.com/zeromicro/go-zero/core/stores/mon"
"go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/options"
"time"
) )
type KYCRepositoryParam struct { type KYCRepositoryParam struct {
@ -60,15 +61,17 @@ func (repo *KYCRepository) Create(ctx context.Context, data *entity.KYC) error {
func (repo *KYCRepository) FindLatestByUID(ctx context.Context, uid string) (*entity.KYC, error) { func (repo *KYCRepository) FindLatestByUID(ctx context.Context, uid string) (*entity.KYC, error) {
filter := bson.M{"uid": uid} filter := bson.M{"uid": uid}
var result entity.KYC var result entity.KYC
opts := options.FindOne().SetSort(bson.D{{"created_at", -1}}) // 用 SetSort 加入排序 opts := options.FindOne().SetSort(bson.D{{Key: "created_at", Value: -1}}) // 用 SetSort 加入排序
err := repo.DB.GetClient().FindOne(ctx, &result, filter, opts) err := repo.DB.GetClient().FindOne(ctx, &result, filter, opts)
if err != nil { if err != nil {
if errors.Is(err, mongo.ErrNoDocuments) { if errors.Is(err, mongo.ErrNoDocuments) {
return nil, ErrNotFound return nil, ErrNotFound
} }
return nil, err return nil, err
} }
return &result, nil return &result, nil
} }
@ -83,6 +86,7 @@ func (repo *KYCRepository) FindByID(ctx context.Context, id string) (*entity.KYC
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &result, nil return &result, nil
} }
@ -97,15 +101,14 @@ func (repo *KYCRepository) List(ctx context.Context, params repository.KYCQueryP
if params.Status != nil { if params.Status != nil {
filter["status"] = *params.Status filter["status"] = *params.Status
} }
sort := bson.D{}
if params.SortByDate {
sort = append(sort, bson.E{Key: "created_at", Value: -1})
}
// 設置排序選項 // 設置排序選項
opts := options.Find().SetSkip((params.PageIndex - 1) * params.PageSize).SetLimit(params.PageSize) opts := options.Find().SetSkip((params.PageIndex - 1) * params.PageSize).SetLimit(params.PageSize)
opts.SetSort(bson.D{{Key: "updated_at", Value: -1}}) if params.SortByDate {
opts.SetSort(bson.E{Key: "created_at", Value: -1})
} else {
opts.SetSort(bson.D{{Key: "updated_at", Value: -1}})
}
// 查詢符合條件的總數 // 查詢符合條件的總數
total, err := repo.DB.GetClient().CountDocuments(ctx, filter) total, err := repo.DB.GetClient().CountDocuments(ctx, filter)
if err != nil { if err != nil {
@ -136,6 +139,7 @@ func (repo *KYCRepository) UpdateStatus(ctx context.Context, id string, status s
}, },
} }
_, err = repo.DB.GetClient().UpdateOne(ctx, filter, update) _, err = repo.DB.GetClient().UpdateOne(ctx, filter, update)
return err return err
} }
@ -194,5 +198,6 @@ func (repo *KYCRepository) UpdateKYCInfo(ctx context.Context, id string, update
filter := bson.M{"_id": oid, "status": "PENDING"} // 僅允許更新尚未審核的 filter := bson.M{"_id": oid, "status": "PENDING"} // 僅允許更新尚未審核的
updateDoc := bson.M{"$set": setFields} updateDoc := bson.M{"$set": setFields}
_, err = repo.DB.GetClient().UpdateOne(ctx, filter, updateDoc) _, err = repo.DB.GetClient().UpdateOne(ctx, filter, updateDoc)
return err return err
} }

View File

@ -1,20 +1,21 @@
package repository package repository
import ( import (
"context"
"fmt"
"testing"
"time"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/kyc" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/kyc"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
mgo "code.30cm.net/digimon/library-go/mongo" mgo "code.30cm.net/digimon/library-go/mongo"
"context"
"fmt"
"github.com/alicebob/miniredis/v2" "github.com/alicebob/miniredis/v2"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/zeromicro/go-zero/core/stores/cache" "github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/mon" "github.com/zeromicro/go-zero/core/stores/mon"
"github.com/zeromicro/go-zero/core/stores/redis" "github.com/zeromicro/go-zero/core/stores/redis"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
"testing"
"time"
) )
func SetupTestKYCRepository(db string) (repository.KYCRepository, func(), error) { func SetupTestKYCRepository(db string) (repository.KYCRepository, func(), error) {

View File

@ -1,13 +1,16 @@
package repository package repository
import ( import (
"context"
"errors"
"fmt"
"testing"
"time"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
mgo "code.30cm.net/digimon/library-go/mongo" mgo "code.30cm.net/digimon/library-go/mongo"
"context"
"errors"
"fmt"
"github.com/alicebob/miniredis/v2" "github.com/alicebob/miniredis/v2"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -15,8 +18,6 @@ import (
"github.com/zeromicro/go-zero/core/stores/mon" "github.com/zeromicro/go-zero/core/stores/mon"
"github.com/zeromicro/go-zero/core/stores/redis" "github.com/zeromicro/go-zero/core/stores/redis"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
"testing"
"time"
) )
func SetupTestProductTagsRepo(db string) (repository.TagRepo, func(), error) { func SetupTestProductTagsRepo(db string) (repository.TagRepo, func(), error) {

View File

@ -1,12 +1,13 @@
package usecase package usecase
import ( import (
"context"
"errors"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase"
"code.30cm.net/digimon/library-go/errs" "code.30cm.net/digimon/library-go/errs"
"context"
"errors"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/mon" "github.com/zeromicro/go-zero/core/stores/mon"
) )

View File

@ -1,18 +1,19 @@
package usecase package usecase
import ( import (
"context"
"errors"
"testing"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase"
"code.30cm.net/digimon/library-go/errs" "code.30cm.net/digimon/library-go/errs"
"context"
"errors"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/mon" "github.com/zeromicro/go-zero/core/stores/mon"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
"go.uber.org/mock/gomock" "go.uber.org/mock/gomock"
"testing"
mockRepository "code.30cm.net/digimon/app-cloudep-product-service/pkg/mock/repository" mockRepository "code.30cm.net/digimon/app-cloudep-product-service/pkg/mock/repository"
) )

View File

@ -1,15 +1,16 @@
package usecase package usecase
import ( import (
"context"
"errors"
"fmt"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/kyc" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/kyc"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase"
repo "code.30cm.net/digimon/app-cloudep-product-service/pkg/repository" repo "code.30cm.net/digimon/app-cloudep-product-service/pkg/repository"
"code.30cm.net/digimon/library-go/errs" "code.30cm.net/digimon/library-go/errs"
"context"
"errors"
"fmt"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
) )

View File

@ -1,6 +1,11 @@
package usecase package usecase
import ( import (
"context"
"errors"
"fmt"
"testing"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/kyc" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/kyc"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
@ -8,15 +13,11 @@ import (
mockRepository "code.30cm.net/digimon/app-cloudep-product-service/pkg/mock/repository" mockRepository "code.30cm.net/digimon/app-cloudep-product-service/pkg/mock/repository"
repo "code.30cm.net/digimon/app-cloudep-product-service/pkg/repository" repo "code.30cm.net/digimon/app-cloudep-product-service/pkg/repository"
"code.30cm.net/digimon/library-go/errs" "code.30cm.net/digimon/library-go/errs"
"context"
"errors"
"fmt"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
"go.uber.org/mock/gomock" "go.uber.org/mock/gomock"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
"testing"
) )
func TestKYCUseCase_Create(t *testing.T) { func TestKYCUseCase_Create(t *testing.T) {

View File

@ -1,14 +1,15 @@
package usecase package usecase
import ( import (
"context"
"errors"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase"
repo "code.30cm.net/digimon/app-cloudep-product-service/pkg/repository" repo "code.30cm.net/digimon/app-cloudep-product-service/pkg/repository"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/utils" "code.30cm.net/digimon/app-cloudep-product-service/pkg/utils"
"code.30cm.net/digimon/library-go/errs" "code.30cm.net/digimon/library-go/errs"
"context"
"errors"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/options"
@ -36,6 +37,7 @@ func (use *ProductUseCase) Create(ctx context.Context, product *usecase.Product)
insert := convertUseCaseToEntity(product) insert := convertUseCaseToEntity(product)
// Transaction 設定:只做必要寫入 // Transaction 設定:只做必要寫入
opts := options.Transaction().SetReadConcern(readconcern.Local()) opts := options.Transaction().SetReadConcern(readconcern.Local())
//nolint:contextcheck
err := use.ProductRepo.Transaction(ctx, func(sessCtx mongo.SessionContext) (any, error) { err := use.ProductRepo.Transaction(ctx, func(sessCtx mongo.SessionContext) (any, error) {
if err := use.ProductRepo.Insert(sessCtx, insert); err != nil { if err := use.ProductRepo.Insert(sessCtx, insert); err != nil {
return nil, logDBError(ctx, "ProductRepo.Insert", []logx.LogField{{Key: "req", Value: product}}, err, "failed to create product") return nil, logDBError(ctx, "ProductRepo.Insert", []logx.LogField{{Key: "req", Value: product}}, err, "failed to create product")
@ -58,7 +60,7 @@ func (use *ProductUseCase) Create(ctx context.Context, product *usecase.Product)
return nil, logDBError(ctx, "TagBinding.BindTags", []logx.LogField{{Key: "ReferenceID", Value: insert.ID.Hex()}, {Key: "tags", Value: product.Tags}}, err, "failed to bind product tags") return nil, logDBError(ctx, "TagBinding.BindTags", []logx.LogField{{Key: "ReferenceID", Value: insert.ID.Hex()}, {Key: "tags", Value: product.Tags}}, err, "failed to bind product tags")
} }
return nil, nil return struct{}{}, nil
}, opts) }, opts)
if err != nil { if err != nil {
@ -73,18 +75,21 @@ func (use *ProductUseCase) Update(ctx context.Context, id string, product *useca
tagsBinding := buildTagsBinding(id, product.Tags) tagsBinding := buildTagsBinding(id, product.Tags)
opts := options.Transaction().SetReadConcern(readconcern.Local()) opts := options.Transaction().SetReadConcern(readconcern.Local())
err := use.ProductRepo.Transaction(ctx, func(sessCtx mongo.SessionContext) (any, error) { err := use.ProductRepo.Transaction(ctx, func(sessCtx mongo.SessionContext) (any, error) {
//nolint:contextcheck
_, err := use.ProductRepo.Update(sessCtx, id, update) _, err := use.ProductRepo.Update(sessCtx, id, update)
if err != nil { if err != nil {
return nil, logDBError(ctx, "ProductRepo.Update", []logx.LogField{{Key: "req", Value: product}}, err, "failed to update product") return nil, logDBError(ctx, "ProductRepo.Update", []logx.LogField{{Key: "req", Value: product}}, err, "failed to update product")
} }
//nolint:contextcheck
if err := use.TagBinding.UnbindTagByReferenceID(sessCtx, id); err != nil { if err := use.TagBinding.UnbindTagByReferenceID(sessCtx, id); err != nil {
return nil, logDBError(ctx, "TagBinding.UnbindTagByReferenceID", []logx.LogField{{Key: "ReferenceID", Value: id}}, err, "failed to unbind tags") return nil, logDBError(ctx, "TagBinding.UnbindTagByReferenceID", []logx.LogField{{Key: "ReferenceID", Value: id}}, err, "failed to unbind tags")
} }
//nolint:contextcheck
if err := use.TagBinding.BindTags(sessCtx, tagsBinding); err != nil { if err := use.TagBinding.BindTags(sessCtx, tagsBinding); err != nil {
return nil, logDBError(ctx, "TagBinding.BindTags", []logx.LogField{{Key: "ReferenceID", Value: id}, {Key: "tags", Value: product.Tags}}, err, "failed to bind tags") return nil, logDBError(ctx, "TagBinding.BindTags", []logx.LogField{{Key: "ReferenceID", Value: id}, {Key: "tags", Value: product.Tags}}, err, "failed to bind tags")
} }
return nil, nil return struct{}{}, nil
}, opts) }, opts)
return err return err
@ -94,6 +99,7 @@ func (use *ProductUseCase) Delete(ctx context.Context, id string) error {
// Transaction 設定:只做必要寫入 // Transaction 設定:只做必要寫入
opts := options.Transaction().SetReadConcern(readconcern.Local()) opts := options.Transaction().SetReadConcern(readconcern.Local())
err := use.ProductRepo.Transaction(ctx, func(sessCtx mongo.SessionContext) (any, error) { err := use.ProductRepo.Transaction(ctx, func(sessCtx mongo.SessionContext) (any, error) {
//nolint:contextcheck
err := use.ProductRepo.Delete(sessCtx, id) err := use.ProductRepo.Delete(sessCtx, id)
if err != nil { if err != nil {
e := errs.DBErrorL(logx.WithContext(ctx), e := errs.DBErrorL(logx.WithContext(ctx),
@ -105,7 +111,7 @@ func (use *ProductUseCase) Delete(ctx context.Context, id string) error {
return nil, e return nil, e
} }
//nolint:contextcheck
err = use.TagRepo.UnbindTagByReferenceID(sessCtx, id) err = use.TagRepo.UnbindTagByReferenceID(sessCtx, id)
if err != nil { if err != nil {
e := errs.DBErrorL(logx.WithContext(ctx), e := errs.DBErrorL(logx.WithContext(ctx),
@ -118,7 +124,7 @@ func (use *ProductUseCase) Delete(ctx context.Context, id string) error {
return nil, e return nil, e
} }
return nil, nil return struct{}{}, nil
}, opts) }, opts)
if err != nil { if err != nil {
return err return err
@ -465,6 +471,7 @@ func buildTagsBinding(referenceID string, tags []string) []*entity.TagsBindingTa
TagID: tag, TagID: tag,
}) })
} }
return binding return binding
} }
@ -571,6 +578,7 @@ func convertUseCaseToUpdateParams(product *usecase.Product) *repository.ProductU
} }
update.CustomFields = cf update.CustomFields = cf
} }
return update return update
} }

View File

@ -1,13 +1,15 @@
package usecase package usecase
import ( import (
"context"
"math"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/utils" "code.30cm.net/digimon/app-cloudep-product-service/pkg/utils"
"code.30cm.net/digimon/library-go/errs" "code.30cm.net/digimon/library-go/errs"
"context"
"github.com/shopspring/decimal" "github.com/shopspring/decimal"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
) )
@ -36,6 +38,7 @@ func toEntity(u *usecase.ProductItems) (entity.ProductItems, error) {
if err != nil { if err != nil {
return entity.ProductItems{}, err return entity.ProductItems{}, err
} }
return entity.ProductItems{ return entity.ProductItems{
// ID 在新增時通常由資料庫自動產生 // ID 在新增時通常由資料庫自動產生
ReferenceID: u.ReferenceID, ReferenceID: u.ReferenceID,
@ -89,6 +92,7 @@ func convertMediaToEntity(meds []usecase.Media) []entity.Media {
URL: m.URL, URL: m.URL,
} }
} }
return res return res
} }
@ -102,6 +106,7 @@ func convertEntityMedia(meds []entity.Media) []usecase.Media {
URL: m.URL, URL: m.URL,
} }
} }
return res return res
} }
@ -114,6 +119,7 @@ func convertCustomFieldsToEntity(cfs []usecase.CustomFields) []entity.CustomFiel
Value: cf.Value, Value: cf.Value,
} }
} }
return res return res
} }
@ -126,6 +132,7 @@ func convertEntityCustomFields(cfs []entity.CustomFields) []usecase.CustomFields
Value: cf.Value, Value: cf.Value,
} }
} }
return res return res
} }
@ -166,6 +173,7 @@ func (use *ProductItemUseCase) Get(ctx context.Context, id string) (*usecase.Pro
{Key: "err", Value: err.Error()}, {Key: "err", Value: err.Error()},
}, "failed to create product items") }, "failed to create product items")
} }
return fromEntity(ent), nil return fromEntity(ent), nil
} }
@ -188,6 +196,13 @@ func (use *ProductItemUseCase) Update(ctx context.Context, id string, data *usec
update.IsFree = data.IsFree update.IsFree = data.IsFree
} }
if data.Stock != nil { if data.Stock != nil {
if *data.Stock > math.MaxInt64 {
return errs.InvalidFormatL(logx.WithContext(ctx),
[]logx.LogField{
{Key: "id", Value: id},
{Key: "data.Stock ", Value: *data.Stock},
}, "data.Stock too large to convert to int64")
}
// data.Stock 為 *uint64需先解引用再轉換為 int64 // data.Stock 為 *uint64需先解引用再轉換為 int64
s := int64(*data.Stock) s := int64(*data.Stock)
update.Stock = &s update.Stock = &s
@ -245,6 +260,13 @@ func (use *ProductItemUseCase) UpdateStatus(ctx context.Context, id string, stat
} }
func (use *ProductItemUseCase) IncSalesCount(ctx context.Context, id string, saleCount uint64) error { func (use *ProductItemUseCase) IncSalesCount(ctx context.Context, id string, saleCount uint64) error {
if saleCount > math.MaxInt64 {
return errs.InvalidFormatL(logx.WithContext(ctx),
[]logx.LogField{
{Key: "id", Value: id},
{Key: "saleCount", Value: saleCount},
}, "saleCount too large to convert to int64")
}
// repository 方法使用 int64故需轉型 // repository 方法使用 int64故需轉型
if err := use.ProductItemUseCaseParam.ProductItems.IncSalesCount(ctx, id, int64(saleCount)); err != nil { if err := use.ProductItemUseCaseParam.ProductItems.IncSalesCount(ctx, id, int64(saleCount)); err != nil {
return errs.DBErrorL(logx.WithContext(ctx), return errs.DBErrorL(logx.WithContext(ctx),
@ -260,7 +282,14 @@ func (use *ProductItemUseCase) IncSalesCount(ctx context.Context, id string, sal
} }
func (use *ProductItemUseCase) DecSalesCount(ctx context.Context, id string, saleCount uint64) error { func (use *ProductItemUseCase) DecSalesCount(ctx context.Context, id string, saleCount uint64) error {
// repository 方法使用 int64故需轉型 if saleCount > math.MaxInt64 {
return errs.InvalidFormatL(logx.WithContext(ctx),
[]logx.LogField{
{Key: "id", Value: id},
{Key: "saleCount", Value: saleCount},
}, "saleCount too large to convert to int64")
}
if err := use.ProductItemUseCaseParam.ProductItems.DecSalesCount(ctx, id, int64(saleCount)); err != nil { if err := use.ProductItemUseCaseParam.ProductItems.DecSalesCount(ctx, id, int64(saleCount)); err != nil {
return errs.DBErrorL(logx.WithContext(ctx), return errs.DBErrorL(logx.WithContext(ctx),
[]logx.LogField{ []logx.LogField{
@ -306,10 +335,11 @@ func (use *ProductItemUseCase) List(ctx context.Context, filter usecase.QueryPro
{Key: "err", Value: err.Error()}, {Key: "err", Value: err.Error()},
}, "failed to list product item") }, "failed to list product item")
} }
var result []*usecase.ProductItems result := make([]*usecase.ProductItems, 0, len(entities))
for i := range entities { for i := range entities {
// 逐筆轉換 entity -> usecase 型別 // 逐筆轉換 entity -> usecase 型別
result = append(result, fromEntity(&entities[i])) result = append(result, fromEntity(&entities[i]))
} }
return result, total, nil return result, total, nil
} }

View File

@ -1,18 +1,19 @@
package usecase package usecase
import ( import (
"context"
"errors"
"testing"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase"
mockRepository "code.30cm.net/digimon/app-cloudep-product-service/pkg/mock/repository" mockRepository "code.30cm.net/digimon/app-cloudep-product-service/pkg/mock/repository"
"context"
"errors"
"github.com/shopspring/decimal" "github.com/shopspring/decimal"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
"go.uber.org/mock/gomock" "go.uber.org/mock/gomock"
"testing"
) )
func TestProductItemUseCase_Create(t *testing.T) { func TestProductItemUseCase_Create(t *testing.T) {

View File

@ -1,20 +1,21 @@
package usecase package usecase
import ( import (
"context"
"errors"
"testing"
"time"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase"
mockRepository "code.30cm.net/digimon/app-cloudep-product-service/pkg/mock/repository" mockRepository "code.30cm.net/digimon/app-cloudep-product-service/pkg/mock/repository"
repo "code.30cm.net/digimon/app-cloudep-product-service/pkg/repository" repo "code.30cm.net/digimon/app-cloudep-product-service/pkg/repository"
"context"
"errors"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/options"
"go.uber.org/mock/gomock" "go.uber.org/mock/gomock"
"testing"
"time"
) )
func TestProductUseCase_Create(t *testing.T) { func TestProductUseCase_Create(t *testing.T) {

View File

@ -1,11 +1,12 @@
package usecase package usecase
import ( import (
"context"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
repo "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository" repo "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase"
"code.30cm.net/digimon/library-go/errs" "code.30cm.net/digimon/library-go/errs"
"context"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
) )

View File

@ -1,17 +1,18 @@
package usecase package usecase
import ( import (
"context"
"errors"
"testing"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product"
repo "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository" repo "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase" "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase"
mockRepository "code.30cm.net/digimon/app-cloudep-product-service/pkg/mock/repository" mockRepository "code.30cm.net/digimon/app-cloudep-product-service/pkg/mock/repository"
"context"
"errors"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
"go.uber.org/mock/gomock" "go.uber.org/mock/gomock"
"testing"
) )
func TestTagsUseCase_Create(t *testing.T) { func TestTagsUseCase_Create(t *testing.T) {

View File

@ -22,7 +22,9 @@ func Rfc3339ToUnix(rfc3339 string) int64 {
func ToValue[T any](ptr *T) T { func ToValue[T any](ptr *T) T {
if ptr == nil { if ptr == nil {
var zero T var zero T
return zero return zero
} }
return *ptr return *ptr
} }