liwei 2 жил өмнө
parent
commit
58ae3ea76c

+ 129 - 0
boxcost/api/bill-produce.go

@@ -0,0 +1,129 @@
+package api
+
+import (
+	"box-cost/db/model"
+	"box-cost/db/repo"
+	"box-cost/log"
+	"errors"
+	"fmt"
+	"time"
+
+	"github.com/gin-gonic/gin"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+// 单据管理
+func BillProduce(r *GinRouter) {
+
+	// 创建单据
+	r.POST("/bill/produce/create", CreateProduceBill)
+
+	// 获取单据详情
+	r.GET("/bill/produce/detail/:id", GetProduceBill)
+
+	// 获取单据列表
+	r.GET("/bill/produce/list", GetProduceBills)
+
+	// 更新单据
+	r.POST("/bill/purchase/update", UpdateProduceBill)
+
+	// 删除单据
+	r.POST("/bill/purchase/delete/:id", DelProduceBill)
+}
+
+// 创建生产加工单据
+func CreateProduceBill(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+
+	bill := &model.ProduceBill{}
+	err := c.ShouldBindJSON(bill)
+	if err != nil {
+		fmt.Println(err)
+		return nil, errors.New("参数错误!")
+	}
+	ctx := apictx.CreateRepoCtx()
+
+	if bill.PackId.Hex() == "" {
+		return nil, errors.New("包装产品id为空")
+	}
+	if bill.PlanId.Hex() == "" {
+		return nil, errors.New("生产计划id为空")
+	}
+	if bill.Type == "" {
+		return nil, errors.New("类型为空")
+	}
+
+	bill.Status = "created"
+	bill.CreateTime = time.Now()
+	bill.UpdateTime = time.Now()
+
+	result, err := repo.RepoAddDoc(ctx, repo.CollectionBillProduce, &bill)
+	return result, err
+}
+
+// 获取单据信息
+func GetProduceBill(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	billId := c.Param("id")
+	id, err := primitive.ObjectIDFromHex(billId)
+	if err != nil {
+		return nil, errors.New("非法id")
+	}
+	var bill model.ProduceBill
+	option := &repo.DocSearchOptions{
+		CollectName: repo.CollectionBillProduce,
+		Query:       repo.Map{"_id": id},
+	}
+	found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), option, &bill)
+	if !found || err != nil {
+		log.Info(err)
+		return nil, errors.New("数据未找到")
+	}
+
+	return bill, nil
+}
+
+// 获取单据列表
+func GetProduceBills(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+
+	page, size, query := UtilQueryPageSize(c)
+
+	if query["packId"] != nil {
+		query["packId"], _ = primitive.ObjectIDFromHex(query["packId"].(string))
+	}
+	if query["planId"] != nil {
+		query["planId"], _ = primitive.ObjectIDFromHex(query["planId"].(string))
+	}
+
+	option := &repo.PageSearchOptions{
+		CollectName: repo.CollectionBillProduce,
+		Query:       query,
+		Page:        page,
+		Size:        size,
+		Sort:        bson.M{"createTime": -1},
+	}
+	return repo.RepoPageSearch(apictx.CreateRepoCtx(), option)
+}
+
+// 更新单据
+func UpdateProduceBill(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	var bill model.ProduceBill
+	err := c.ShouldBindJSON(&bill)
+	if err != nil {
+		return nil, errors.New("参数错误")
+	}
+	if bill.Id.Hex() == "" {
+		return nil, errors.New("id的为空")
+	}
+	bill.UpdateTime = time.Now()
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionBillProduce, bill.Id.Hex(), &bill)
+}
+
+// 删除单据
+func DelProduceBill(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	billId := c.Param("id")
+	if billId == "" {
+		return nil, errors.New("id为空")
+	}
+
+	return repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionBillProduce, billId)
+}

+ 43 - 19
boxcost/api/bill.go

@@ -17,32 +17,39 @@ import (
 func Bill(r *GinRouter) {
 
 	// 创建单据
-	r.POST("/bill", CreateBill)
+	r.POST("/bill/purchase/create", CreateBill)
 
 	// 获取单据详情
-	r.GET("/bill/:id", GetBill)
+	r.GET("/bill/purchase/detail/:id", GetBill)
 
 	// 获取单据列表
-	r.GET("/bills", GetBills)
+	r.GET("/bill/purchase/list", GetBills)
 
 	// 更新单据
-	r.POST("/bill/update", UpdateBill)
+	r.POST("/bill/purchase/update", UpdateBill)
 
 	// 删除单据
-	r.POST("/bill/delete/:id", DelBill)
+	r.POST("/bill/purchase/delete/:id", DelBill)
+}
+
+type MatBillReq struct {
+	Bill      *model.PurchaseBill
+	CompIndex *int
+	MatIndex  *int
+	//MatKey    string //components.0.mats.0.billId
 }
 
 // 创建单据
 func CreateBill(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 
-	var bill model.Bill
-
-	err := c.ShouldBindJSON(&bill)
-	if err != nil {
+	req := &MatBillReq{}
+	err := c.ShouldBindJSON(req)
+	if err != nil || req.Bill == nil || req.CompIndex == nil || req.MatIndex == nil {
 		fmt.Println(err)
-		return nil, errors.New("参数错误!")
+		return nil, errors.New("参数错误!compIndex, matIndex 不能为空")
 	}
 	ctx := apictx.CreateRepoCtx()
+	bill := req.Bill
 
 	if bill.PackId.Hex() == "" {
 		return nil, errors.New("包装产品id为空")
@@ -58,8 +65,19 @@ func CreateBill(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 	bill.CreateTime = time.Now()
 	bill.UpdateTime = time.Now()
 
-	result, err := repo.RepoAddDoc(ctx, repo.CollectionBill, &bill)
-	return result, err
+	result, err := repo.RepoAddDoc(ctx, repo.CollectionBillPurchase, &bill)
+	if err != nil {
+		return nil, err
+	}
+
+	updat := bson.M{}
+	matkey := fmt.Sprintf("pack.components.%d.mats.%d.billId", *req.CompIndex, *req.MatIndex)
+	updat[matkey] = result
+	ret, err := repo.RepoUpdateSetDocProps(apictx.CreateRepoCtx(), repo.CollectionProductPlan, bill.PlanId.Hex(), bson.M{"$set": updat})
+	if ret.ModifiedCount == 1 && err == nil {
+		return result, nil
+	}
+	return nil, fmt.Errorf("创建失败")
 }
 
 // 获取单据信息
@@ -69,12 +87,11 @@ func GetBill(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 	if err != nil {
 		return nil, errors.New("非法id")
 	}
-	var bill model.Bill
+	var bill model.PurchaseBill
 	option := &repo.DocSearchOptions{
-		CollectName: repo.CollectionBill,
+		CollectName: repo.CollectionBillPurchase,
 		Query:       repo.Map{"_id": id},
 	}
-
 	found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), option, &bill)
 	if !found || err != nil {
 		log.Info(err)
@@ -89,8 +106,15 @@ func GetBills(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 
 	page, size, query := UtilQueryPageSize(c)
 
+	if query["packId"] != nil {
+		query["packId"], _ = primitive.ObjectIDFromHex(query["packId"].(string))
+	}
+	if query["planId"] != nil {
+		query["planId"], _ = primitive.ObjectIDFromHex(query["planId"].(string))
+	}
+
 	option := &repo.PageSearchOptions{
-		CollectName: repo.CollectionBill,
+		CollectName: repo.CollectionBillPurchase,
 		Query:       query,
 		Page:        page,
 		Size:        size,
@@ -101,7 +125,7 @@ func GetBills(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 
 // 更新单据
 func UpdateBill(c *gin.Context, apictx *ApiSession) (interface{}, error) {
-	var bill model.Bill
+	var bill model.PurchaseBill
 	err := c.ShouldBindJSON(&bill)
 	if err != nil {
 		return nil, errors.New("参数错误")
@@ -110,7 +134,7 @@ func UpdateBill(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 		return nil, errors.New("id的为空")
 	}
 	bill.UpdateTime = time.Now()
-	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionBill, bill.Id.Hex(), &bill)
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionBillPurchase, bill.Id.Hex(), &bill)
 }
 
 // 删除单据
@@ -120,5 +144,5 @@ func DelBill(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 		return nil, errors.New("id为空")
 	}
 
-	return repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionBill, billId)
+	return repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionBillPurchase, billId)
 }

+ 370 - 0
boxcost/api/obs.go

@@ -0,0 +1,370 @@
+package api
+
+import (
+	"box-cost/conf"
+	"box-cost/db/model"
+	"box-cost/log"
+	"fmt"
+	"os"
+	"path"
+	"strings"
+	"time"
+
+	"github.com/gin-gonic/gin"
+	"github.com/huaweicloud/huaweicloud-sdk-go-obs/obs"
+)
+
+func CreateObsClient() (*obs.ObsClient, error) {
+	obsConf := conf.AppConfig.Obs
+	return obs.New(obsConf.AccessKeyId, obsConf.SecrateKey, obsConf.Endpoint)
+}
+
+// u/xxx/img/up/timps.png
+func ServiceObsCreateImagePolicy(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	body := struct {
+		Ext string
+	}{}
+
+	err := c.ShouldBindJSON(&body)
+	if err != nil {
+		return nil, NewError("参数解析错误!")
+	}
+	if len(body.Ext) < 1 {
+		return nil, NewError("上传文件的扩展名不能为空")
+	}
+
+	fkey := fmt.Sprintf("u/%s/images/uploads/%v.%s", apictx.User.Parent, time.Now().UnixNano(), body.Ext)
+
+	client, err := CreateObsClient()
+	if err != nil {
+		return nil, NewError("创建ObsClient 失败!")
+	}
+
+	defer func() {
+		client.Close()
+	}()
+
+	// 除key,policy,signature外,表单上传时的其他参数,支持的值:
+	// 	acl
+	// 	cache-control
+	// 	content-type
+	// 	content-disposition
+	// 	content-encoding
+	// 	expires
+	bucketName := apictx.Svc.Conf.Obs.Bucket
+
+	result, err := client.CreateBrowserBasedSignature(&obs.CreateBrowserBasedSignatureInput{
+		Bucket:  bucketName,
+		Key:     fkey,
+		Expires: 300,
+		FormParams: map[string]string{
+			"x-obs-acl": "public-read",
+		},
+	})
+
+	if err != nil {
+		return nil, NewLogWithError(err)
+	}
+
+	obsConf := conf.AppConfig.Obs
+
+	out := map[string]interface{}{
+		"accessKeyId":  obsConf.AccessKeyId,
+		"originPolicy": result.OriginPolicy,
+		"policy":       result.Policy,
+		"signature":    result.Signature,
+		"host":         fmt.Sprintf("//%s.%s", bucketName, obsConf.Endpoint),
+		"key":          fkey,
+	}
+	return out, nil
+}
+
+func ServiceObsList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+
+	prefix := c.Query("prefix")
+
+	if len(prefix) < 1 {
+		return nil, NewError("prefix不能为空")
+	}
+
+	client, err := CreateObsClient()
+	if err != nil {
+		return nil, NewError("创建ObsClient 失败!")
+	}
+
+	defer func() {
+		client.Close()
+	}()
+
+	bucketName := apictx.Svc.Conf.Obs.Bucket
+	result, err := client.ListObjects(&obs.ListObjectsInput{
+		Bucket: bucketName,
+		ListObjsInput: obs.ListObjsInput{
+			Prefix:    prefix,
+			Delimiter: "/",
+		},
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	fmt.Println("result=>", prefix)
+	fmt.Println(result.CommonPrefixes, result.IsTruncated)
+	out := []*model.ObsItem{}
+
+	imgExts := map[string]bool{".jpeg": true, ".jpg": true, ".gif": true, ".png": true, ".svg": true, ".bmp": true}
+
+	for k, v := range result.Contents {
+		fmt.Println(k, v.Key, v.LastModified, v.Size)
+		if prefix == v.Key {
+			continue
+		}
+		isDirSuffix := strings.HasSuffix(v.Key, "/")
+		isDir := (isDirSuffix && v.Size == 0)
+		isImage := false
+
+		originKey := strings.ToLower(v.Key)
+		if !isDir && imgExts[path.Ext(originKey)] {
+			isImage = true
+		}
+
+		keys := strings.Split(v.Key, "/")
+		name := ""
+		if isDir {
+			name = keys[len(keys)-2]
+		} else {
+			name = keys[len(keys)-1]
+		}
+		obsConf := conf.AppConfig.Obs
+		url := ""
+		if !isDir {
+			url = fmt.Sprintf("//%s.%s/%s", bucketName, obsConf.Endpoint, v.Key)
+		}
+
+		out = append(out, &model.ObsItem{
+			Name:         name,
+			Size:         uint64(v.Size),
+			IsImage:      isImage,
+			Url:          url,
+			IsDir:        isDir,
+			LastModified: v.LastModified,
+		})
+	}
+
+	for _, v := range result.CommonPrefixes {
+		keys := strings.Split(v, "/")
+		name := keys[len(keys)-2]
+
+		out = append(out, &model.ObsItem{
+			Name:    name,
+			IsImage: false,
+			IsDir:   true,
+		})
+	}
+
+	outMap := map[string]interface{}{
+		"list":        out,
+		"isTruncated": result.IsTruncated,
+	}
+	return outMap, nil
+}
+
+// 管理后台上传文件
+func ServiceObsUploadPolicy(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+
+	body := struct {
+		Key string
+	}{}
+
+	err := c.ShouldBindJSON(&body)
+	if err != nil {
+		return nil, NewError("参数解析错误!")
+	}
+	if len(body.Key) < 1 {
+		return nil, NewError("上传文件的key不能为空")
+	}
+	client, err := CreateObsClient()
+	if err != nil {
+		return nil, NewError("创建ObsClient 失败!")
+	}
+	defer func() {
+		client.Close()
+	}()
+	bucketName := apictx.Svc.Conf.Obs.Bucket
+
+	result, err := client.CreateBrowserBasedSignature(&obs.CreateBrowserBasedSignatureInput{
+		Bucket:  bucketName,
+		Key:     body.Key,
+		Expires: 600,
+		FormParams: map[string]string{
+			"x-obs-acl": "public-read",
+		},
+	})
+
+	if err != nil {
+		return nil, NewLogWithError(err)
+	}
+	obsConf := conf.AppConfig.Obs
+	out := map[string]interface{}{
+		"accessKeyId":  obsConf.AccessKeyId,
+		"originPolicy": result.OriginPolicy,
+		"policy":       result.Policy,
+		"signature":    result.Signature,
+		"host":         fmt.Sprintf("https://%s.%s", bucketName, obsConf.Endpoint),
+		"key":          body.Key,
+		"saveType":     conf.SaveType_Obs,
+	}
+	return out, nil
+}
+
+func ServiceObsRemove(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+
+	body := struct {
+		Key string
+	}{}
+	err := c.ShouldBindJSON(&body)
+	if err != nil {
+		return nil, NewError("参数解析错误!")
+	}
+	if len(body.Key) < 1 {
+		return nil, NewError("文件的key不能为空")
+	}
+
+	client, err := CreateObsClient()
+	if err != nil {
+		return nil, NewError("创建ObsClient 失败!")
+	}
+
+	defer func() {
+		client.Close()
+	}()
+
+	bucketName := apictx.Svc.Conf.Obs.Bucket
+	result, err := client.DeleteObject(&obs.DeleteObjectInput{
+		Bucket: bucketName,
+		Key:    body.Key,
+	})
+
+	if err != nil {
+		return nil, err
+	}
+
+	return result, nil
+}
+
+func ServiceObsCreateFolder(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	body := struct {
+		Key string
+	}{}
+	err := c.ShouldBindJSON(&body)
+	if err != nil {
+		return nil, NewError("参数解析错误!")
+	}
+	if len(body.Key) < 1 {
+		return nil, NewError("文件的key不能为空")
+	}
+
+	client, err := CreateObsClient()
+	if err != nil {
+		return nil, NewError("创建ObsClient 失败!")
+	}
+
+	defer func() {
+		client.Close()
+	}()
+
+	bucketName := apictx.Svc.Conf.Obs.Bucket
+	result, err := client.PutObject(&obs.PutObjectInput{
+		PutObjectBasicInput: obs.PutObjectBasicInput{
+			ObjectOperationInput: obs.ObjectOperationInput{
+				Bucket: bucketName,
+				Key:    body.Key,
+				ACL:    obs.AclPublicRead,
+			},
+		},
+	})
+
+	if err != nil {
+		return nil, err
+	}
+
+	return result, nil
+}
+
+func UploadFile(obsClient *obs.ObsClient, bucketName string, fpath string, obsDir string) *model.OssType {
+
+	_, obsname := path.Split(fpath)
+	keyFormat := "%s/%s"
+	if strings.HasSuffix(obsDir, "/") {
+		keyFormat = "%s%s"
+	}
+	obsKey := fmt.Sprintf(keyFormat, obsDir, obsname)
+
+	input := &obs.PutFileInput{}
+	input.Bucket = bucketName
+	input.Key = obsKey
+	input.SourceFile = fpath
+
+	fpathExt := path.Ext(fpath)
+	isGzFile := fpathExt == ".gz"
+	if isGzFile {
+		input.ContentType = "text/plain"
+		input.Metadata = map[string]string{"Content-Encoding": "gzip"}
+	}
+	result, err := obsClient.PutFile(input)
+
+	isUploadOk := true
+
+	if err != nil {
+		log.Errorf("upload obs fail %s", fpath)
+		log.Error(err)
+		isUploadOk = false
+	}
+
+	if result.StatusCode != 200 {
+		isUploadOk = false
+	}
+
+	if !isUploadOk {
+		result, err = obsClient.PutFile(input)
+
+		if err != nil {
+			log.Errorf("upload obs fail2 %s", fpath)
+			log.Error(err)
+			return &model.OssType{}
+		}
+		if result.StatusCode != 200 {
+			return &model.OssType{}
+		}
+	}
+
+	if isGzFile {
+		metaRet, err := obsClient.SetObjectMetadata(&obs.SetObjectMetadataInput{
+			Bucket:          bucketName,
+			Key:             obsKey,
+			ContentEncoding: "gzip",
+			ContentType:     "text/plain",
+		})
+		fmt.Println(metaRet, err)
+
+		if err != nil {
+			metaRet, err = obsClient.SetObjectMetadata(&obs.SetObjectMetadataInput{
+				Bucket:          bucketName,
+				Key:             obsKey,
+				ContentEncoding: "gzip",
+				ContentType:     "text/plain",
+			})
+			fmt.Println(metaRet, err)
+		}
+	}
+
+	fi, err := os.Stat(fpath)
+	size := int64(1)
+	if err == nil {
+		size = fi.Size()
+	}
+
+	obsConf := conf.AppConfig.Obs
+
+	return &model.OssType{Url: fmt.Sprintf("//%s.%s/%s", bucketName, obsConf.Endpoint, obsKey), Size: int64(size)}
+}

+ 3 - 3
boxcost/api/pack.go

@@ -17,13 +17,13 @@ import (
 func Pack(r *GinRouter) {
 
 	// 创建包装
-	r.POST("/pack", CreatePack)
+	r.POST("/pack/create", CreatePack)
 
 	// 获取包装详情
-	r.GET("/pack/:id", GetPack)
+	r.GET("/pack/detail/:id", GetPack)
 
 	// 获取包装列表
-	r.GET("/packs", GetPacks)
+	r.GET("/pack/list", GetPacks)
 
 	// 更新包装
 	r.POST("/pack/update", UpdatePack)

+ 3 - 3
boxcost/api/plan.go

@@ -17,13 +17,13 @@ import (
 func ProductPlan(r *GinRouter) {
 
 	// 创建生产计划
-	r.POST("/plan", CreateProductPlan)
+	r.POST("/plan/create", CreateProductPlan)
 
 	// 获取生产计划详情
-	r.GET("/plan/:id", GetProductPlan)
+	r.GET("/plan/detail/:id", GetProductPlan)
 
 	// 获取生产计划列表
-	r.GET("/plans", GetProductPlans)
+	r.GET("/plan/list", GetProductPlans)
 
 	// 更新生产计划
 	r.POST("/plan/update", UpdateProductPlan)

+ 3 - 0
boxcost/api/router.go

@@ -13,6 +13,9 @@ func RegRouters(svc *Service) {
 	boxcost.group.Use(Logger())
 	boxcost.GET("/printr", Printr)
 
+	//数据存储
+	boxcost.POST("/save/policy", ServiceObsUploadPolicy)
+
 	// 材料管理
 	Material(boxcost)
 

+ 30 - 0
boxcost/api/setting.go

@@ -2,9 +2,11 @@ package api
 
 import (
 	"box-cost/db/model"
+	"box-cost/db/repo"
 	"time"
 
 	"github.com/gin-gonic/gin"
+	"go.mongodb.org/mongo-driver/bson"
 )
 
 func Setting(router *GinRouter) {
@@ -38,4 +40,32 @@ func Setting(router *GinRouter) {
 		JWT:           true,
 		SearchProject: []string{"name", "createTime"},
 	})
+
+	//计价策略
+	CreateCRUD(router, "/calc", &CRUDOption{
+		Collection: "calcs",
+		NewModel: func(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+			entity := &model.PriceCalc{}
+			c.ShouldBindJSON(entity)
+			entity.CreateTime = time.Now()
+			entity.UpdateTime = time.Now()
+			return entity, nil
+		},
+		EmtyModel: func(c *gin.Context, apictx *ApiSession) interface{} {
+			return &model.PriceCalc{}
+		},
+		JWT: true,
+		OnUpdate: func(c *gin.Context, apictx *ApiSession, entity interface{}) {
+			calc := entity.(*model.PriceCalc)
+			calc.UpdateTime = time.Now()
+			if calc.IsDefault != nil && *calc.IsDefault { //设为默认把其他的所有默认清除
+				repo.RepoUpdateSetDocsProps(apictx.CreateRepoCtx(),
+					&repo.DocFilterOptions{
+						CollectName: "calcs",
+						Query:       repo.Map{"category": calc.Category},
+					}, bson.M{"isDefault": false})
+			}
+		},
+		SearchProject: []string{"name", "updateTime", "isDefault", "category", "remark", "param1", "param2", "param3", "param4", "param5"},
+	})
 }

+ 144 - 20
boxcost/api/supplier-price.go

@@ -16,20 +16,144 @@ import (
 // 供应商价格管理
 func SupplierPrice(r *GinRouter) {
 
-	// 创建供应商价格
-	r.POST("/supplierPrice", CreateSupplierPrice)
-
-	// 获取供应商价格详情
-	r.GET("/supplierPrice/:id", GetSupplierPrice)
-
-	// 获取供应商价格列表
-	r.GET("/supplierPrices", GetSupplierPrices)
-
-	// 更新供应商价格
-	r.POST("/supplierPrice/update", UpdateSupplierPrice)
-
-	// 删除供应商价格
-	r.POST("/supplierPrice/delete/:id", DelSupplierPrice)
+	// // 创建供应商价格
+	// r.POST("/supplier/mat/create", CreateSupplierPrice)
+
+	// // 获取供应商价格列表
+	// r.GET("/supplier/mat/list", GetSupplierPrices)
+
+	// // 更新供应商价格
+	// r.POST("/supplier/mat/update", UpdateSupplierPrice)
+
+	// // 删除供应商价格
+	// r.POST("/supplier/mat/delete/:id", DelSupplierPrice)
+
+	//材料供应
+	CreateCRUD(r, "/supplier/mat", &CRUDOption{
+		Collection: "supplier-mats",
+		NewModel: func(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+			entity := &model.SupplierPrice{}
+			c.ShouldBindJSON(entity)
+			entity.CreateTime = time.Now()
+			entity.UpdateTime = time.Now()
+			return entity, nil
+		},
+		EmtyModel: func(c *gin.Context, apictx *ApiSession) interface{} {
+			return &model.SupplierPrice{}
+		},
+		JWT: true,
+		OnUpdate: func(c *gin.Context, apictx *ApiSession, entity interface{}) {
+			calc := entity.(*model.SupplierPrice)
+			calc.UpdateTime = time.Now()
+		},
+		SearchFilter: func(c *gin.Context, apictx *ApiSession, query map[string]interface{}) map[string]interface{} {
+			if query["supplierId"] != nil {
+				query["supplierId"], _ = primitive.ObjectIDFromHex(query["supplierId"].(string))
+			}
+			return query
+		},
+
+		SearchPostProcess: func(page *repo.PageResult, c *gin.Context, apictx *ApiSession, query map[string]interface{}) (interface{}, error) {
+			//查询材料对应的材料信息
+			for _, mat := range page.List {
+				_id, _ := mat["_id"].(primitive.ObjectID)
+
+				matInfo := &model.Material{}
+				repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
+					CollectName: repo.CollectionMaterial,
+					Query:       repo.Map{"_id": _id},
+				}, matInfo)
+				mat["matInfo"] = matInfo
+			}
+			return page, nil
+		},
+
+		SearchProject: []string{"price", "supplierId", "updateTime", "_id"},
+	})
+
+	CreateCRUD(r, "/supplier/craft", &CRUDOption{
+		Collection: "supplier-crafts",
+		NewModel: func(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+			entity := &model.SupplierPrice{}
+			c.ShouldBindJSON(entity)
+			entity.CreateTime = time.Now()
+			entity.UpdateTime = time.Now()
+			return entity, nil
+		},
+		EmtyModel: func(c *gin.Context, apictx *ApiSession) interface{} {
+			return &model.SupplierPrice{}
+		},
+		JWT: true,
+		OnUpdate: func(c *gin.Context, apictx *ApiSession, entity interface{}) {
+			calc := entity.(*model.SupplierPrice)
+			calc.UpdateTime = time.Now()
+		},
+		SearchFilter: func(c *gin.Context, apictx *ApiSession, query map[string]interface{}) map[string]interface{} {
+			if query["supplierId"] != nil {
+				query["supplierId"], _ = primitive.ObjectIDFromHex(query["supplierId"].(string))
+			}
+			return query
+		},
+		SearchPostProcess: func(page *repo.PageResult, c *gin.Context, apictx *ApiSession, query map[string]interface{}) (interface{}, error) {
+			//查询材料对应的材料信息
+			for _, mat := range page.List {
+				_id, _ := mat["_id"].(primitive.ObjectID)
+
+				matInfo := &model.Material{}
+				repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
+					CollectName: repo.CollectionCraft,
+					Query:       repo.Map{"_id": _id},
+				}, matInfo)
+				mat["craftInfo"] = matInfo
+			}
+			return page, nil
+		},
+		SearchProject: []string{"price", "supplierId", "updateTime", "_id"},
+	})
+
+	//添加计价方案
+	SupplierCalcPriceColl := "supplier-calcprice"
+	CreateCRUD(r, "/supplier/calc", &CRUDOption{
+		Collection: SupplierCalcPriceColl,
+		NewModel: func(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+			entity := &model.SupplierCalcPrice{}
+			c.ShouldBindJSON(entity)
+			if entity.SupplierId == primitive.NilObjectID {
+				return nil, fmt.Errorf("供应商Id不能为空")
+			}
+			if entity.Calc == nil || len(entity.Calc.Category) < 1 {
+				return nil, fmt.Errorf("计价方案参数错误")
+			}
+			calc := &model.SupplierCalcPrice{}
+			ok, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(),
+				&repo.DocSearchOptions{CollectName: SupplierCalcPriceColl,
+					Query: repo.Map{"calc.category": entity.Calc.Category}}, calc)
+			if err != nil {
+				return nil, err
+			}
+			if ok {
+				return nil, fmt.Errorf("相同的分类计价方案只能有一个")
+			}
+			entity.CreateTime = time.Now()
+			entity.UpdateTime = time.Now()
+			return entity, nil
+		},
+		EmtyModel: func(c *gin.Context, apictx *ApiSession) interface{} {
+			return &model.SupplierCalcPrice{}
+		},
+		JWT: true,
+		OnUpdate: func(c *gin.Context, apictx *ApiSession, entity interface{}) {
+			calc := entity.(*model.SupplierCalcPrice)
+			calc.UpdateTime = time.Now()
+		},
+		SearchFilter: func(c *gin.Context, apictx *ApiSession, query map[string]interface{}) map[string]interface{} {
+			if query["supplierId"] != nil {
+				query["supplierId"], _ = primitive.ObjectIDFromHex(query["supplierId"].(string))
+			}
+			return query
+		},
+		SearchProject: []string{"calc", "supplierId", "updateTime", "_id"},
+	})
 }
 
 // 创建供应商价格
@@ -47,12 +171,12 @@ func CreateSupplierPrice(c *gin.Context, apictx *ApiSession) (interface{}, error
 	if supplierprice.SupplierId.Hex() == "" {
 		return nil, errors.New("供应商id为空")
 	}
-	if supplierprice.ProductId.Hex() == "" {
-		return nil, errors.New("供应产品id为空")
-	}
-	if supplierprice.PriceStrategy == nil {
-		return nil, errors.New("供应商价格策略为空")
-	}
+	// if supplierprice.ProductId.Hex() == "" {
+	// 	return nil, errors.New("供应产品id为空")
+	// }
+	// if supplierprice.PriceStrategy == nil {
+	// 	return nil, errors.New("供应商价格策略为空")
+	// }
 
 	supplierprice.CreateTime = time.Now()
 	supplierprice.UpdateTime = time.Now()

+ 10 - 2
boxcost/app.yaml

@@ -1,6 +1,14 @@
 port: 8888
 name: boxcost
 version: 1.0.0
+saveType: obs
+
+obs:
+  bucket: sku3d-test
+  accessKeyId: "RA1D7CFVCVKUFX1FHHPB"
+  secrateKey: "cDrR2NgAF2KaA4MRkcK19r93P3P6hLKOPhHvPu9p"
+  endpoint: "obs.cn-east-3.myhuaweicloud.com"
+
 jwt: 
   timeoutHour: 24
   realm: spu3d
@@ -20,7 +28,7 @@ debug:
   UserRole: string
 
 nats:
-  #url: nats://124.71.139.24:14300
-  url: nats://127.0.0.1:14300
+  url: nats://124.71.139.24:14300
+  #url: nats://127.0.0.1:14300
   maxReconnect: 1000
   reconnDelaySecond: 5

+ 16 - 2
boxcost/conf/app.go

@@ -9,9 +9,16 @@ import (
 	"github.com/spf13/viper"
 )
 
+const (
+	SaveType_Obs   = "obs"
+	SaveType_OSS   = "oss"
+	SaveType_Minio = "minio"
+)
+
 type AppConf struct {
-	Name    string
-	Version string
+	Name     string
+	Version  string
+	SaveType string //obs, oss, minio
 
 	Jwt struct {
 		Realm       string
@@ -46,6 +53,13 @@ type AppConf struct {
 		MaxReconnect      int
 		ReconnDelaySecond int
 	}
+
+	Obs struct {
+		Bucket      string
+		AccessKeyId string
+		SecrateKey  string
+		Endpoint    string
+	}
 }
 
 func LoadConfFile(filepath string) (*AppConf, error) {

+ 64 - 4
boxcost/db/model/bill.go

@@ -6,17 +6,77 @@ import (
 	"go.mongodb.org/mongo-driver/bson/primitive"
 )
 
-type Bill struct {
+// 采购单
+type PaperBill struct {
+	//名字
+	Name string `bson:"name,omitempty" json:"name"`
+	//规格
+	Norm string `bson:"norm,omitempty" json:"norm"`
+
+	//宽
+	Width string `bson:"width,omitempty" json:"width"`
+
+	//长
+	Height string `bson:"height,omitempty" json:"height"`
+
+	Price  string `bson:"price,omitempty" json:"price"`
+	Price2 string `bson:"price2,omitempty" json:"price2"`
+
+	//数量
+	Count int `bson:"count,omitempty" json:"count"`
+
+	//交货时间
+	DeliveryTime time.Time `bson:"deliveryTime,omitempty" json:"deliveryTime"`
+}
+
+type PurchaseBill struct {
+	Id     primitive.ObjectID `bson:"_id,omitempty" json:"_id"`
+	PackId primitive.ObjectID `bson:"packId,omitempty" json:"packId"`
+	PlanId primitive.ObjectID `bson:"planId,omitempty" json:"planId"`
+
+	//类别
+	Type string `bson:"type,omitempty" json:"type"`
+
+	//created complete
+	Status     string    `bson:"status,omitempty" json:"status"`
+	CreateTime time.Time `bson:"createTime,omitempty" json:"createTime"`
+	UpdateTime time.Time `bson:"updateTime,omitempty" json:"updateTime"`
+
+	//供应商
+	Supplier string `bson:"supplier,omitempty" json:"supplier"`
+
+	//送货地址
+	SendTo string `bson:"sendTo,omitempty" json:"sendTo"`
+
+	//商品名字
+	ProductName string `bson:"productName,omitempty" json:"productName"`
+
+	//纸张类采购
+	Paper []*PaperBill `bson:"papers,omitempty" json:"papers"`
+}
+
+type ProduceBill struct {
 	Id     primitive.ObjectID `bson:"_id,omitempty" json:"_id"`
 	PackId primitive.ObjectID `bson:"packId,omitempty" json:"packId"`
 	PlanId primitive.ObjectID `bson:"planId,omitempty" json:"planId"`
-	// mat craft
+
+	//类别
 	Type string `bson:"type,omitempty" json:"type"`
-	//多个工序
-	ProductUnit []*ProductUnit `bson:"productUnit,omitempty" json:"productUnit"`
 
 	//created complete
 	Status     string    `bson:"status,omitempty" json:"status"`
 	CreateTime time.Time `bson:"createTime,omitempty" json:"createTime"`
 	UpdateTime time.Time `bson:"updateTime,omitempty" json:"updateTime"`
+
+	//供应商
+	Supplier string `bson:"supplier,omitempty" json:"supplier"`
+
+	//送货地址
+	SendTo string `bson:"sendTo,omitempty" json:"sendTo"`
+
+	//商品名字
+	ProductName string `bson:"productName,omitempty" json:"productName"`
+
+	//纸张类采购
+	Paper []*PaperBill `bson:"papers,omitempty" json:"papers"`
 }

+ 17 - 0
boxcost/db/model/obs.go

@@ -0,0 +1,17 @@
+package model
+
+import "time"
+
+type ObsItem struct {
+	Name         string    `json:"name"`
+	LastModified time.Time `json:"lastModified"`
+	Size         uint64    `json:"size"`
+	IsImage      bool      `json:"isImage"`
+	Url          string    `json:"url"`
+	IsDir        bool      `json:"isDir"`
+}
+
+type OssType struct {
+	Url  string `bson:"url" json:"url"`
+	Size int64  `bson:"size" json:"size"`
+}

+ 39 - 1
boxcost/db/model/pack.go

@@ -38,6 +38,28 @@ type PackComponent struct {
 	Mats []*PackComponentMat `bson:"mats,omitempty" json:"mats"`
 
 	Remark string `bson:"remark,omitempty" json:"remark"`
+
+	//部件总价
+	TotalPrice float64 `bson:"totalPrice,omitempty" json:"totalPrice"`
+}
+
+type SupplierPriceVo struct {
+	Calc *PriceCalc `bson:"calc,omitempty" json:"calc"` //计价策略
+
+	//交货时间
+	DeliveryTime *time.Time `bson:"deliveryTime,omitempty" json:"deliveryTime"`
+
+	//订单单价
+	OrderPrice float64 `bson:"orderPrice,omitempty" json:"orderPrice"`
+
+	//订单数据量
+	OrderCount float64 `bson:"orderCount,omitempty" json:"orderCount"`
+
+	//订单实际金额
+	OrderRealPrice float32 `bson:"orderRealPrice,omitempty" json:"orderRealPrice"`
+
+	//供应商信息
+	SupplierInfo *Supplier `bson:"supplierInfo,omitempty" json:"supplierInfo"`
 }
 
 type PackComponentMat struct {
@@ -46,7 +68,15 @@ type PackComponentMat struct {
 	//所有工艺
 	Crafts []*PackComponentMatCraft `bson:"crafts,omitempty" json:"crafts"`
 
-	MatInfo *Material `bson:"matInfo,omitempty" json:"matInfo"` //材料Id
+	MatInfo *Material `bson:"matInfo,omitempty" json:"matInfo"`
+
+	Supplier *SupplierPriceVo `bson:"supplier,omitempty" json:"supplier"`
+
+	BatchCount      int `bson:"batchCount,omitempty" json:"batchCount"`           //拼版数量
+	BatchSizeWidth  int `bson:"batchSizeWidth,omitempty" json:"batchSizeWidth"`   //平板尺寸
+	BatchSizeHeight int `bson:"batchSizeHeight,omitempty" json:"batchSizeHeight"` //平板尺寸
+
+	BillId string `bson:"billId,omitempty" json:"billId"`
 }
 
 type PackComponentMatCraft struct {
@@ -60,4 +90,12 @@ type PackComponentMatCraft struct {
 
 	//工艺信息
 	CraftInfo *Craft `bson:"craftInfo,omitempty" json:"craftInfo"` //材料Id
+
+	Supplier *SupplierPriceVo `bson:"supplier,omitempty" json:"supplier"`
+
+	BatchCount      int `bson:"batchCount,omitempty" json:"batchCount"`           //拼版数量
+	BatchSizeWidth  int `bson:"batchSizeWidth,omitempty" json:"batchSizeWidth"`   //平板尺寸
+	BatchSizeHeight int `bson:"batchSizeHeight,omitempty" json:"batchSizeHeight"` //平板尺寸
+
+	BillId string `bson:"billId,omitempty" json:"billId"`
 }

+ 3 - 65
boxcost/db/model/plan.go

@@ -14,6 +14,7 @@ type ProductPlan struct {
 	Pack       *Pack  `bson:"pack,omitempty" json:"pack"`
 	Thumbnail  string `bson:"thumbnail,omitempty" json:"thumbnail"`
 	CreateUser string `bson:"createUser,omitempty" json:"createUser"`
+
 	//生产数量
 	Total int `bson:"total,omitempty" json:"total"`
 
@@ -22,71 +23,8 @@ type ProductPlan struct {
 
 	//总价
 	TotalPrice float64 `bson:"totalPrice,omitempty" json:"totalPrice"`
-	//所有包装部件的工序
-	Components []*PackComp `bson:"components,omitempty" json:"components"`
-	UpdateTime time.Time   `bson:"updteTime,omitempty" json:"updateTime"`
-	CreateTime time.Time   `bson:"createTime,omitempty" json:"createTime"`
-}
-
-type PackComp struct {
-	//包装部件Id
-	Id    primitive.ObjectID `bson:"id,omitempty" json:"id"`
-	Steps []*ProductUnit     `bson:"steps,omitempty" json:"steps"`
-	//生产的工序列表
-}
-
-// 工序单位
-type ProductUnit struct {
-	//工序Id
-	Id string `bson:"id,omitempty" json:"id"`
-
-	//mat craft process
-	Type string `bson:"type,omitempty" json:"type"`
-
-	//type类型对应的Id
-	TypeId string `bson:"typeId,omitempty" json:"typeId"`
-
-	//生产工艺的规格要求
-	CraftNorm *CraftNorm `bson:"craftNorm,omitempty" json:"craftNorm"`
-	MatNorm   *MatNorm   `bson:"matNorm,omitempty" json:"matNorm"`
-
-	//生产数量
-	PlanCount float64 `bson:"planCount,omitempty" json:"planCount"`
-
-	//最终数量
-	FinalCount float64 `bson:"finalCount,omitempty" json:"finalCount"`
-
-	//总价 需要计算
-	TotalPrice float64 `bson:"totalPrice,omitempty" json:"totalPrice"`
-
-	//交货时间 需要处理
-	DeliveryTime time.Time `bson:"deliveryTime,omitempty" json:"deliveryTime"`
-
-	//单价
-	Price float64 `bson:"price,omitempty" json:"price"`
-
-	//供应商
-	SupplierId primitive.ObjectID `bson:"supplierId,omitempty" json:"supplierId"`
-
-	//计价
-	PriceStrategy *PriceStrategy `bson:"priceStrategy,omitempty" json:"priceStrategy"`
 
-	//单据Id
-	BillId primitive.ObjectID `bson:"billId,omitempty" json:"billId"`
-}
-
-type MatNorm struct {
-	//下纸尺寸
-	PaperWidth  string `bson:"paperWidth,omitempty" json:"paperWidth"`
-	PaperHeight string `bson:"paperHeight,omitempty" json:"paperHeight"`
-}
-
-type CraftNorm struct {
-	//印刷尺寸
-	PrintWidth  string `bson:"printWidth,omitempty" json:"printWidth"`
-	PrintHeight string `bson:"printHeight,omitempty" json:"printHeight"`
-}
+	UpdateTime time.Time `bson:"updteTime,omitempty" json:"updateTime"`
 
-type ProcessNorm struct {
-	Norm string `bson:"norm,omitempty" json:"norm"`
+	CreateTime time.Time `bson:"createTime,omitempty" json:"createTime"`
 }

+ 28 - 9
boxcost/db/model/price.go

@@ -1,13 +1,32 @@
 package model
 
+import (
+	"time"
+
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
 type PriceCalc struct {
-	Id       string `bson:"id,omitempty" json:"id"`
-	Category string `bson:"category,omitempty" json:"category"`
-	Name     string `bson:"name,omitempty" json:"name"`     //印刷通用计价
-	Remark   string `bson:"remark,omitempty" json:"remark"` //备注 板子(60)+起价(普通1200,逆向油1600)+超过10000份减板费
-
-	Pamam1 string
-	Pamam2 string
-	Pamam3 string
-	Pamam4 string
+	Id       primitive.ObjectID `bson:"_id,omitempty" json:"_id"`
+	Category string             `bson:"category,omitempty" json:"category"` //普通印刷
+	Name     string             `bson:"name,omitempty" json:"name"`         //印刷计价方案1
+	//备注
+	// 板费(60)
+	// 起价(普通1200,逆向油1600)
+	// 超过10000份减板费
+	Remark string `bson:"remark,omitempty" json:"remark"`
+
+	Param1 string `bson:"param1,omitempty" json:"param1"`
+	Param2 string `bson:"param2,omitempty" json:"param2"`
+	Param3 string `bson:"param3,omitempty" json:"param3"`
+	Param4 string `bson:"param4,omitempty" json:"param4"`
+	Param5 string `bson:"param5,omitempty" json:"param5"`
+
+	CreateTime time.Time `bson:"createTime,omitempty" json:"createTime"`
+	UpdateTime time.Time `bson:"updateTime,omitempty" json:"updateTime"`
+
+	//是否默认
+	IsDefault *bool `bson:"isDefault,omitempty" json:"isDefault"`
 }
+
+//供应商价格管理

+ 22 - 6
boxcost/db/model/supplier-price.go

@@ -8,10 +8,26 @@ import (
 
 // 供应商价格
 type SupplierPrice struct {
-	Id            primitive.ObjectID `bson:"_id,omitempty" json:"_id"`
-	SupplierId    primitive.ObjectID `bson:"supplierId,omitempty" json:"supplierId"`
-	ProductId     primitive.ObjectID `bson:"productId,omitempty" json:"productId"`
-	PriceStrategy *PriceStrategy     `bson:"priceStrategy,omitempty" json:"priceStrategy"`
-	CreateTime    time.Time          `bson:"createTime,omitempty" json:"createTime"`
-	UpdateTime    time.Time          `bson:"updateTime,omitempty" json:"updateTime"`
+	Id primitive.ObjectID `bson:"_id,omitempty" json:"_id"` //商品Id
+
+	SupplierId primitive.ObjectID `bson:"supplierId,omitempty" json:"supplierId"`
+
+	Price float64 `bson:"price,omitempty" json:"price"` //价格
+
+	CreateTime time.Time `bson:"createTime,omitempty" json:"createTime"`
+
+	UpdateTime time.Time `bson:"updateTime,omitempty" json:"updateTime"`
+}
+
+// 供应商价格
+type SupplierCalcPrice struct {
+	Id primitive.ObjectID `bson:"_id,omitempty" json:"_id"` //商品Id
+
+	SupplierId primitive.ObjectID `bson:"supplierId,omitempty" json:"supplierId"`
+
+	Calc *PriceCalc `bson:"calc,omitempty" json:"calc"` //计价方案
+
+	CreateTime time.Time `bson:"createTime,omitempty" json:"createTime"`
+
+	UpdateTime time.Time `bson:"updateTime,omitempty" json:"updateTime"`
 }

+ 33 - 1
boxcost/db/repo/repo.go

@@ -25,7 +25,8 @@ const (
 	CollectionSupplierPrice = "supplier-price"
 	CollectionPack          = "pack"
 	CollectionProductPlan   = "product-plan"
-	CollectionBill          = "bill"
+	CollectionBillPurchase  = "bill-purchase"
+	CollectionBillProduce   = "bill-produce"
 )
 
 type Map map[string]interface{}
@@ -54,6 +55,11 @@ type DocSearchOptions struct {
 	Project     []string
 	Sort        bson.M
 }
+type DocFilterOptions struct {
+	Db          string
+	CollectName string
+	Query       Map
+}
 
 func NewDocSearchOptions(filter Map, project []string) *DocSearchOptions {
 	return &DocSearchOptions{
@@ -131,9 +137,35 @@ func RepoUpdateSetDocProps(ctx *RepoSession, collectName string, idstr string, u
 	colls := ctx.Client.GetCollection(collectName)
 	// update := bson.M{"$set": model}
 	uid, _ := primitive.ObjectIDFromHex(idstr)
+
 	return colls.UpdateByID(ctx.Ctx, uid, update)
 }
 
+func RepoUpdateSetDocsProps(ctx *RepoSession, filter *DocFilterOptions, model interface{}) (*mongo.UpdateResult, error) {
+
+	colls := ctx.Client.GetCollection(filter.CollectName)
+	if len(filter.Db) > 0 {
+		colls = ctx.Client.GetDbCollection(filter.Db, filter.CollectName)
+	}
+	update := bson.M{"$set": model}
+
+	filterParams := bson.M{}
+	if len(filter.Query) > 0 {
+		for k, v := range filter.Query {
+			if k == "_id" {
+				if uid, ok := v.(string); ok {
+					docId, _ := primitive.ObjectIDFromHex(uid)
+					filterParams["_id"] = docId
+					continue
+				}
+			}
+			filterParams[k] = v
+		}
+	}
+
+	return colls.UpdateMany(ctx.Ctx, filterParams, update)
+}
+
 func RepoUpdateSetDbDocProps(ctx *RepoSession, db string, collectName string, idstr string, update interface{}) (*mongo.UpdateResult, error) {
 
 	colls := ctx.Client.GetDbCollection(db, collectName)

+ 1 - 0
boxcost/go.mod

@@ -33,6 +33,7 @@ require (
 	github.com/gorilla/securecookie v1.1.1 // indirect
 	github.com/gorilla/sessions v1.1.3 // indirect
 	github.com/hashicorp/hcl v1.0.0 // indirect
+	github.com/huaweicloud/huaweicloud-sdk-go-obs v3.21.12+incompatible // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/klauspost/compress v1.14.4 // indirect
 	github.com/kr/text v0.2.0 // indirect

+ 2 - 0
boxcost/go.sum

@@ -228,6 +228,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
 github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
 github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
 github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
+github.com/huaweicloud/huaweicloud-sdk-go-obs v3.21.12+incompatible h1:tANYIteuFrosKbRYUk1Yo/OGJjbt4x3OVg211Qc60M0=
+github.com/huaweicloud/huaweicloud-sdk-go-obs v3.21.12+incompatible/go.mod h1:l7VUhRbTKCzdOacdT4oWCwATKyvZqUOlOqr0Ous3k4s=
 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=