package api import ( "box-cost/db/model" "box-cost/db/repo" "box-cost/log" "errors" "fmt" "sync" "time" "github.com/gin-gonic/gin" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) // 供应商管理 func Supplier(r *GinRouter) { // 创建供应商 r.POSTJWT("/supplier/create", CreateSupplier) // 获取供应商详情 r.GETJWT("/supplier/detail/:id", GetSupplier) // 获取供应商列表 r.GETJWT("/supplier/list", GetSuppliers) // 更新供应商 r.POSTJWT("/supplier/update", UpdateSupplier) // 删除供应商 r.POSTJWT("/supplier/delete/:id", DelSupplier) // 获取供应商列表 r.GETJWT("/plan/supplier/list", GetPlanSuppliers) // 供应商获取自己的单据列表 r.GETJWT("/supplier/bill/list", SupplierBillList) // 供应商接单 r.POSTJWT("/supplier/bill/ack", SupplierBillAck) // 单据分配给供应商 r.GETJWT("/supplier/bill/alloc", SupplierBillAlloc) } const ( PURCHASE_BILL_TYPE = "purchase" PRODUCE_BILL_TYPE = "produce" PRODUCT_BILL_TYPE = "product" ) type SupplierSmsTempInfo struct { Product string // 产品名+数量 SerialNumber string Phone string } func genSupplierSmsTemp(billId primitive.ObjectID, billType string, apictx *ApiSession) (*SupplierSmsTempInfo, error) { productName := "" supplierId := primitive.NilObjectID serialNumber := "" if billType == PURCHASE_BILL_TYPE { purchase := &model.PurchaseBill{} found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{ CollectName: repo.CollectionBillPurchase, Query: repo.Map{"_id": billId}, Project: []string{"productName", "supplierId", "serialNumber", "isAck"}, }, purchase) if !found || err != nil { return nil, errors.New("未找到该订单") } // 已经接单不发送提醒 if *purchase.IsAck { return nil, errors.New("该供应商已经接单") } serialNumber = purchase.SerialNumber productName = purchase.ProductName supplierId = purchase.SupplierId } if billType == PRODUCE_BILL_TYPE { produce := &model.ProduceBill{} found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{ CollectName: repo.CollectionBillProduce, Query: repo.Map{"_id": billId}, Project: []string{"productName", "supplierId", "serialNumber", "isAck"}, }, produce) if !found || err != nil { return nil, errors.New("未找到该订单") } // 已经接单不发送提醒 if *produce.IsAck { return nil, errors.New("该供应商已经接单") } serialNumber = produce.SerialNumber productName = produce.ProductName supplierId = produce.SupplierId } if billType == PRODUCT_BILL_TYPE { product := &model.ProductBill{} found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{ CollectName: repo.CollectionBillProduct, Query: repo.Map{"_id": billId}, Project: []string{"productName", "supplierId", "serialNumber", "isAck"}, }, product) if !found || err != nil { return nil, errors.New("未找到该订单") } // 已经接单不发送提醒 if *product.IsAck { return nil, errors.New("该供应商已经接单") } serialNumber = product.SerialNumber productName = product.ProductName supplierId = product.SupplierId } // 查询供应商信息 user, err := getUserById(apictx, supplierId) if user == nil || err != nil { return nil, errors.New("未找到该供应商信息") } if len(user.Phone) != 11 { return nil, errors.New("手机号信息错误") } return &SupplierSmsTempInfo{ Product: fmt.Sprintf("%s。<%s>", productName, "成都永红印务"), SerialNumber: serialNumber, Phone: user.Phone, }, nil } // 把订单分配给供应商 // purchase produce product // id为订单id // /supplier/bill/alloc?id=xxx&type=purchase func SupplierBillAlloc(c *gin.Context, apictx *ApiSession) (interface{}, error) { // ?验证当前账户是否可发送订单 userId, _ := primitive.ObjectIDFromHex(apictx.User.Parent) user, err1 := getUserById(apictx, userId) if err1 != nil { return nil, errors.New("用户错误") } if !isSender(user.Roles) { return nil, errors.New("没有发送权限") } billId, _ := primitive.ObjectIDFromHex(c.Query("id")) if billId.IsZero() { return nil, errors.New("订单id不正确") } billType := c.Query("type") billTypes := []string{"purchase", "produce", "product"} flagType := false for _, bt := range billTypes { if bt == billType { flagType = true break } } if !flagType { return nil, errors.New("订单类型错误") } _isSend := true result := &mongo.UpdateResult{} var err error switch billType { case PURCHASE_BILL_TYPE: // result, err = repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionBillPurchase, billId.Hex(), &model.PurchaseBill{IsSend: true, SendTime: time.Now()}) result, err = repo.RepoUpdateSetDoc1(apictx.CreateRepoCtx(), repo.CollectionBillPurchase, billId.Hex(), &model.PurchaseBill{IsSend: &_isSend, SendTime: time.Now()}, &repo.RecordLogReq{ Path: c.Request.URL.Path, UserInfo: user, TargetId: billId.Hex(), Type: "send", }) case PRODUCE_BILL_TYPE: // result, err = repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionBillProduce, billId.Hex(), &model.ProduceBill{IsSend: true, SendTime: time.Now()}) result, err = repo.RepoUpdateSetDoc1(apictx.CreateRepoCtx(), repo.CollectionBillProduce, billId.Hex(), &model.ProduceBill{IsSend: &_isSend, SendTime: time.Now()}, &repo.RecordLogReq{ Path: c.Request.URL.Path, UserInfo: user, TargetId: billId.Hex(), Type: "send", }) case PRODUCT_BILL_TYPE: // result, err = repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionBillProduct, billId.Hex(), &model.ProductBill{IsSend: true, SendTime: time.Now()}) result, err = repo.RepoUpdateSetDoc1(apictx.CreateRepoCtx(), repo.CollectionBillProduct, billId.Hex(), &model.ProductBill{IsSend: &_isSend, SendTime: time.Now()}, &repo.RecordLogReq{ Path: c.Request.URL.Path, UserInfo: user, TargetId: billId.Hex(), Type: "send", }) default: return result, nil } if err == nil { // 给供应商发送通知短信 smsInfo, err := genSupplierSmsTemp(billId, billType, apictx) fmt.Println(smsInfo) if err == nil { var wg sync.WaitGroup wg.Add(1) go SendSmsNotify(smsInfo.Phone, &SupplierSmsReq{smsInfo.Product, smsInfo.SerialNumber}, &wg) // err = SendSmsNotify1(smsInfo.Phone, &SupplierSmsReq{smsInfo.Product, smsInfo.SerialNumber}) wg.Wait() } } return result, err } // 供应商-接单 // purchase produce product // POST /supplier/bill/ack // {"id":xxxx,"type":"purchase"} type SupplierBillAckReq struct { Type string Id primitive.ObjectID } func SupplierBillAck(c *gin.Context, apictx *ApiSession) (interface{}, error) { userId, _ := primitive.ObjectIDFromHex(apictx.User.Parent) form := SupplierBillAckReq{} err := c.ShouldBindJSON(&form) if err != nil { return nil, errors.New("参数错误") } billType := form.Type id := form.Id _id := form.Id.Hex() if id.IsZero() { return nil, errors.New("id为空") } if userId.IsZero() { return nil, errors.New("非法用户") } // purchase produce product billTypes := []string{"purchase", "produce", "product"} flagType := false for _, bt := range billTypes { if bt == billType { flagType = true break } } if !flagType { return nil, errors.New("订单类型错误") } user, _ := getUserById(apictx, userId) isAck := true switch billType { case "purchase": // return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionBillPurchase, _id, &model.PurchaseBill{IsAck: &isAck, AckTime: time.Now()}) return repo.RepoUpdateSetDoc1(apictx.CreateRepoCtx(), repo.CollectionBillPurchase, _id, &model.PurchaseBill{IsAck: &isAck, AckTime: time.Now()}, &repo.RecordLogReq{ Path: c.Request.URL.Path, UserInfo: user, TargetId: _id, Type: "take", }) case "produce": // return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionBillProduce, _id, &model.ProduceBill{IsAck: &isAck, AckTime: time.Now()}) return repo.RepoUpdateSetDoc1(apictx.CreateRepoCtx(), repo.CollectionBillProduce, _id, &model.ProduceBill{IsAck: &isAck, AckTime: time.Now()}, &repo.RecordLogReq{ Path: c.Request.URL.Path, UserInfo: user, TargetId: _id, Type: "take", }) case "product": // return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionBillProduct, _id, &model.ProductBill{IsAck: &isAck, AckTime: time.Now()}) return repo.RepoUpdateSetDoc1(apictx.CreateRepoCtx(), repo.CollectionBillProduct, _id, &model.ProductBill{IsAck: &isAck, AckTime: time.Now()}, &repo.RecordLogReq{ Path: c.Request.URL.Path, UserInfo: user, TargetId: _id, Type: "take", }) default: return nil, errors.New("更新类型错误") } } // 供应商-订单列表 // purchase produce product // /supplier/bill/list?type=purchase&query={"status":"created"} func SupplierBillList(c *gin.Context, apictx *ApiSession) (interface{}, error) { userId, _ := primitive.ObjectIDFromHex(apictx.User.Parent) billType := c.Query("type") page, size, query := UtilQueryPageSize(c) if userId.IsZero() { return nil, errors.New("非法用户") } // purchase produce product billTypes := []string{"purchase", "produce", "product"} flagType := false for _, bt := range billTypes { if bt == billType { flagType = true break } } if !flagType { return nil, errors.New("订单类型错误") } query["supplierId"] = userId query["isSend"] = true if _productName, ok := query["productName"]; ok { delete(query, "productName") query["productName"] = bson.M{"$regex": _productName.(string)} } collectName := "" switch billType { case "purchase": collectName = repo.CollectionBillPurchase case "produce": collectName = repo.CollectionBillProduce case "product": collectName = repo.CollectionBillProduct default: return []map[string]interface{}{}, nil } return repo.RepoPageSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{ CollectName: collectName, Page: page, Size: size, Query: query, Sort: bson.D{{Key: "sendTime", Value: -1}, {Key: "createTime", Value: -1}}, }) } // 创建供应商 func CreateSupplier(c *gin.Context, apictx *ApiSession) (interface{}, error) { var supplier model.Supplier err := c.ShouldBindJSON(&supplier) if err != nil { fmt.Println(err) return nil, errors.New("参数错误!") } ctx := apictx.CreateRepoCtx() if supplier.Name == "" { return nil, errors.New("供应商名为空") } if supplier.Address == "" { return nil, errors.New("供应商地址为空") } if supplier.Phone == "" { return nil, errors.New("供应商联系电话为空") } supplier.CreateTime = time.Now() supplier.UpdateTime = time.Now() result, err := repo.RepoAddDoc(ctx, repo.CollectionSupplier, &supplier) return result, err } // 获取供应商信息 func GetSupplier(c *gin.Context, apictx *ApiSession) (interface{}, error) { supplierId := c.Param("id") id, err := primitive.ObjectIDFromHex(supplierId) if err != nil { return nil, errors.New("非法id") } var supplier model.Supplier option := &repo.DocSearchOptions{ CollectName: repo.CollectionSupplier, Query: repo.Map{"_id": id}, } found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), option, &supplier) if !found || err != nil { log.Info(err) return nil, errors.New("数据未找到") } return supplier, nil } // 获取供应商列表 func GetSuppliers(c *gin.Context, apictx *ApiSession) (interface{}, error) { page, size, query := UtilQueryPageSize(c) if _name, ok := query["name"]; ok { delete(query, "name") query["name"] = bson.M{"$regex": _name.(string)} } if cate, ok := query["category"]; ok { delete(query, "category") query["categorys"] = bson.M{"$in": []string{cate.(string)}} } option := &repo.PageSearchOptions{ CollectName: repo.CollectionSupplier, Query: query, Page: page, Size: size, Sort: bson.M{"createTime": -1}, } return repo.RepoPageSearch(apictx.CreateRepoCtx(), option) } // !暂时弃用 func GetPlanSuppliers(c *gin.Context, apictx *ApiSession) (interface{}, error) { page, size, query := UtilQueryPageSize(c) emtyPage := &repo.PageResult{ Total: 0, Size: size, Page: page, List: []map[string]interface{}{}, } listOut := []map[string]interface{}{} flag := false if query["matId"] != nil || query["craftId"] != nil || query["productId"] != nil { flag = true } filtter := repo.Map{} if _name, ok := query["name"]; ok { filtter["name"] = bson.M{"$regex": _name.(string)} } if cate, ok := query["category"]; ok { filtter["categorys"] = bson.M{"$in": []string{cate.(string)}} } if !flag { option := &repo.PageSearchOptions{ CollectName: repo.CollectionSupplier, // Query: repo.Map{"categorys": bson.M{"$in": []string{cate.(string)}}}, Query: filtter, Page: page, Size: size, Sort: bson.M{"createTime": -1}, } return repo.RepoPageSearch(apictx.CreateRepoCtx(), option) } //category =>根据内容查询 供应对应内容的供应商 if query["matId"] != nil { matId := query["matId"].(string) if len(matId) < 1 { return nil, fmt.Errorf("matId(string)为空") } id, _ := primitive.ObjectIDFromHex(matId) ok, list := repo.RepoSeachDocsMap(apictx.CreateRepoCtx(), &repo.DocsSearchOptions{ CollectName: repo.CollectionSupplierMatprice, Query: repo.Map{"productId": id}, Project: []string{"supplierId"}, }) if !ok { return emtyPage, nil } listOut = list } if query["craftId"] != nil { cratf := &model.Craft{} ok, _ := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{ Query: repo.Map{"_id": query["craftId"].(string)}, CollectName: repo.CollectionCraft, }, cratf) if !ok { return nil, fmt.Errorf("没有对应的工艺信息") } //查询工艺分类 pipleLine := []bson.M{ { "$lookup": bson.M{ "from": repo.CollectionCraft, "localField": "productId", "foreignField": "_id", "as": "craft_docs", }, }, { "$match": bson.M{ "craft_docs.0.category": cratf.Category, }, }, { "$project": bson.M{ "craft_docs": 0, "createTime": 0, "price": 0, "productId": 0, "updateTime": 0, }, }, } ctx := apictx.CreateRepoCtx() colls := ctx.Client.GetCollection(repo.CollectionSupplierCraftprice) findoptions := &options.AggregateOptions{} cur, err := colls.Aggregate(ctx.Ctx, pipleLine, findoptions) if err != nil { return nil, err } defer cur.Close(ctx.Ctx) err = cur.All(ctx.Ctx, &listOut) if err != nil { return nil, err } if len(listOut) < 1 { return emtyPage, nil } return listOut, nil // cratfId := query["craftId"].(string) // if len(cratfId) < 1 { // return nil, fmt.Errorf("cratfId(string)为空") // } // id, _ := primitive.ObjectIDFromHex(cratfId) // ok, list := repo.RepoSeachDocsMap(apictx.CreateRepoCtx(), &repo.DocsSearchOptions{ // CollectName: repo.CollectionSupplierCraftprice, // Query: repo.Map{"craftId": id}, // Project: []string{"supplierId"}, // }) // if !ok { // return emtyPage, nil // } // listOut = list } if query["productId"] != nil { productId := query["productId"].(string) if len(productId) < 1 { return nil, fmt.Errorf("productId(string)为空") } id, _ := primitive.ObjectIDFromHex(productId) ok, list := repo.RepoSeachDocsMap(apictx.CreateRepoCtx(), &repo.DocsSearchOptions{ CollectName: repo.CollectionSupplierProductprice, Query: repo.Map{"productId": id}, Project: []string{"supplierId"}, }) if !ok { return emtyPage, nil } listOut = list } //获取供应商列表 suppliers := []primitive.ObjectID{} suppliersMap := map[string]bool{} for _, item := range listOut { if item["supplierId"] != nil { id, ok := item["supplierId"].(primitive.ObjectID) if !ok { continue } if !suppliersMap[id.Hex()] { suppliers = append(suppliers, id) suppliersMap[id.Hex()] = true } } } if len(suppliers) < 1 { return emtyPage, nil } filtter["_id"] = bson.M{"$in": suppliers} option := &repo.PageSearchOptions{ CollectName: repo.CollectionSupplier, Query: filtter, // Query: repo.Map{"_id": bson.M{"$in": suppliers}}, Page: page, Size: size, Sort: bson.M{"createTime": -1}, } return repo.RepoPageSearch(apictx.CreateRepoCtx(), option) } // 更新供应商 func UpdateSupplier(c *gin.Context, apictx *ApiSession) (interface{}, error) { var supplier model.Supplier err := c.ShouldBindJSON(&supplier) if err != nil { return nil, errors.New("参数错误") } if supplier.Id.Hex() == "" { return nil, errors.New("id的为空") } supplier.UpdateTime = time.Now() return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionSupplier, supplier.Id.Hex(), &supplier) } // 删除供应商 func DelSupplier(c *gin.Context, apictx *ApiSession) (interface{}, error) { supplierId := c.Param("id") if supplierId == "" { return nil, errors.New("id为空") } return repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionSupplier, supplierId) }