作者 yangfu

feat: 物料分组同步

  1 +
  2 +-- 表product_material_group 增加唯一索引 idx_unq_product_material_group_company_id_org_id_material_group_number
  3 +
  4 +create UNIQUE INDEX idx_unq_product_material_group_company_id_org_id_material_group_number on manufacture.product_material_group using btree(company_id,org_id,material_group_number);
@@ -60,6 +60,9 @@ func (crontabService *CrontabService) initTask() { @@ -60,6 +60,9 @@ func (crontabService *CrontabService) initTask() {
60 60
61 syncProductPlan := task.NewTask("定时同步车间计划", "0 5 * * * *", SyncProductPlan) 61 syncProductPlan := task.NewTask("定时同步车间计划", "0 5 * * * *", SyncProductPlan)
62 task.AddTask("SyncProductPlan", syncProductPlan) 62 task.AddTask("SyncProductPlan", syncProductPlan)
  63 +
  64 + syncMaterialGroup := task.NewTask("定时同步物料分组", "0 0 0/2 * * *", SyncMaterialGroup)
  65 + task.AddTask("syncMaterialGroup", syncMaterialGroup)
63 } 66 }
64 67
65 func (crontabService *CrontabService) StartCrontabTask() { 68 func (crontabService *CrontabService) StartCrontabTask() {
  1 +package crontab
  2 +
  3 +import (
  4 + "context"
  5 + "fmt"
  6 + "github.com/linmadan/egglib-go/transaction/pg"
  7 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/factory"
  8 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/syncdata"
  9 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log"
  10 + "runtime/debug"
  11 +)
  12 +
  13 +// SyncMaterialGroup 定时同步物料分组
  14 +func SyncMaterialGroup(ctx context.Context) error {
  15 + defer func() {
  16 + if r := recover(); r != nil {
  17 + log.Logger.Error(fmt.Sprintf("%v", r), map[string]interface{}{"task": "定时同步物料分组", "stack": string(debug.Stack())})
  18 + }
  19 + }()
  20 + transactionContext, err := factory.CreateTransactionContext(nil)
  21 + if err != nil {
  22 + return err
  23 + }
  24 + if err := transactionContext.StartTransaction(); err != nil {
  25 + return err
  26 + }
  27 + defer func() {
  28 + if err != nil {
  29 + log.Logger.Error("【定时同步物料分组】 失败:" + err.Error())
  30 + }
  31 + transactionContext.RollbackTransaction()
  32 + }()
  33 +
  34 + log.Logger.Debug("【定时同步物料分组】 启动")
  35 + pullK3CloudService := syncdata.PullDataK3CloudService{}
  36 + if err := pullK3CloudService.SyncDataMaterialGroup(transactionContext.(*pg.TransactionContext)); err != nil {
  37 + log.Logger.Error(err.Error(), map[string]interface{}{"task": "定时同步物料分组"})
  38 + return nil
  39 + }
  40 + if err = transactionContext.CommitTransaction(); err != nil {
  41 + return err
  42 + }
  43 + return nil
  44 +}
1 package syncdata 1 package syncdata
2 2
3 import ( 3 import (
  4 + "fmt"
4 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/constant" 5 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/constant"
5 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain" 6 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
6 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/domainService" 7 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/domainService"
@@ -612,3 +613,71 @@ func (srv *PullDataK3CloudService) SyncDataProductPlan(ptr *pgTransaction.Transa @@ -612,3 +613,71 @@ func (srv *PullDataK3CloudService) SyncDataProductPlan(ptr *pgTransaction.Transa
612 } 613 }
613 return nil 614 return nil
614 } 615 }
  616 +
  617 +// 同步产品
  618 +func (srv *PullDataK3CloudService) SyncDataMaterialGroup(ptr *pgTransaction.TransactionContext) error {
  619 + prdMoDao, err := dao.NewMaterialK3cloudDao(ptr)
  620 + if err != nil {
  621 + return err
  622 + }
  623 + var userService = domainService.NewUserService()
  624 + org, err := userService.Organization(constant.MANUFACTURE_DEFAULT_ORGID)
  625 + if err != nil {
  626 + return application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  627 + }
  628 + fromMaterialGroups, err := prdMoDao.SearchMaterialGroup() // 默认企业名称素天下、或者使用组织ID
  629 + if err != nil {
  630 + return application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  631 + }
  632 + var (
  633 + cid = constant.MANUFACTURE_DEFAULT_COMPANYID
  634 + oid = constant.MANUFACTURE_DEFAULT_ORGID
  635 + )
  636 + productMaterialGroupRepository, _, _ := factory.FastProductMaterialGroup(ptr, 0)
  637 + _, materialGroups, err := productMaterialGroupRepository.Find(map[string]interface{}{"companyId": cid})
  638 + if err != nil {
  639 + return err
  640 + }
  641 + mapMaterialGroups := domain.ProductMaterialGroups(materialGroups).ToMapByGroupNumber()
  642 + mapFromMaterialGroups := models.MaterialGroupK3clouds(fromMaterialGroups).ToMapId()
  643 + for _, from := range fromMaterialGroups {
  644 + to, ok := mapMaterialGroups[from.Number]
  645 + if ok {
  646 + // 更新
  647 + if to.MaterialGroupName != from.Name {
  648 + log.Logger.Info(fmt.Sprintf("更新物料分组 old:%v new:%v", to.MaterialGroupName, from.Name), map[string]interface{}{"material": to})
  649 + to.MaterialGroupName = from.Name
  650 + }
  651 + continue
  652 + }
  653 + var parentId int
  654 + if from.ParentId > 0 {
  655 + parent, ok := mapFromMaterialGroups[from.ParentId]
  656 + if !ok {
  657 + log.Logger.Warn("parent node not exits", map[string]interface{}{"material": to})
  658 + continue
  659 + }
  660 + toParent, ok := mapMaterialGroups[parent.Number]
  661 + if !ok {
  662 + log.Logger.Warn("to parent node not exits", map[string]interface{}{"material": to})
  663 + continue
  664 + }
  665 + parentId = toParent.ProductMaterialGroupId
  666 + }
  667 + productMaterialGroup := &domain.ProductMaterialGroup{
  668 + CompanyId: cid,
  669 + OrgId: oid,
  670 + Pid: parentId,
  671 + MaterialGroupName: from.Name,
  672 + MaterialGroupNumber: from.Number,
  673 + CreatedAt: time.Now(),
  674 + UpdatedAt: time.Now(),
  675 + Ext: domain.NewExt(org.OrgName),
  676 + }
  677 + if productMaterialGroup, err = productMaterialGroupRepository.Save(productMaterialGroup); err != nil {
  678 + return err
  679 + }
  680 + mapMaterialGroups[productMaterialGroup.MaterialGroupNumber] = productMaterialGroup
  681 + }
  682 + return nil
  683 +}
@@ -77,3 +77,11 @@ func (tree ProductMaterialGroups) Less(i, j int) bool { @@ -77,3 +77,11 @@ func (tree ProductMaterialGroups) Less(i, j int) bool {
77 func (tree ProductMaterialGroups) Swap(i, j int) { 77 func (tree ProductMaterialGroups) Swap(i, j int) {
78 tree[i], tree[j] = tree[j], tree[i] 78 tree[i], tree[j] = tree[j], tree[i]
79 } 79 }
  80 +
  81 +func (tree ProductMaterialGroups) ToMapByGroupNumber() map[string]*ProductMaterialGroup {
  82 + var result = make(map[string]*ProductMaterialGroup)
  83 + for i := range tree {
  84 + result[tree[i].MaterialGroupNumber] = tree[i]
  85 + }
  86 + return result
  87 +}
@@ -178,3 +178,13 @@ func (d *MaterialK3cloudDao) GetLastVersion() (int64, error) { @@ -178,3 +178,13 @@ func (d *MaterialK3cloudDao) GetLastVersion() (int64, error) {
178 } 178 }
179 return materialData[0].DataVersion, nil 179 return materialData[0].DataVersion, nil
180 } 180 }
  181 +
  182 +func (d *MaterialK3cloudDao) SearchMaterialGroup() ([]*models.MaterialGroupK3cloud, error) {
  183 + var materialData []*models.MaterialGroupK3cloud
  184 + query := d.transactionContext.PgTx.Model(&materialData)
  185 + query.OrderExpr("number asc")
  186 + if err := query.Select(); err != nil {
  187 + return nil, err
  188 + }
  189 + return materialData, nil
  190 +}
@@ -9,3 +9,13 @@ type MaterialGroupK3cloud struct { @@ -9,3 +9,13 @@ type MaterialGroupK3cloud struct {
9 ParentId int `comment:"父级id" pg:"parent_id"` 9 ParentId int `comment:"父级id" pg:"parent_id"`
10 DataVersion int64 `comment:"数据版本" pg:"data_version"` 10 DataVersion int64 `comment:"数据版本" pg:"data_version"`
11 } 11 }
  12 +
  13 +type MaterialGroupK3clouds []*MaterialGroupK3cloud
  14 +
  15 +func (materialGroupK3clouds MaterialGroupK3clouds) ToMapId() map[int]*MaterialGroupK3cloud {
  16 + var result = make(map[int]*MaterialGroupK3cloud)
  17 + for i := range materialGroupK3clouds {
  18 + result[materialGroupK3clouds[i].Id] = materialGroupK3clouds[i]
  19 + }
  20 + return result
  21 +}
@@ -139,6 +139,7 @@ func (repository *ProductMaterialGroupRepository) Find(queryOptions map[string]i @@ -139,6 +139,7 @@ func (repository *ProductMaterialGroupRepository) Find(queryOptions map[string]i
139 productMaterialGroups := make([]*domain.ProductMaterialGroup, 0) 139 productMaterialGroups := make([]*domain.ProductMaterialGroup, 0)
140 query := sqlbuilder.BuildQuery(tx.Model(&productMaterialGroupModels), queryOptions) 140 query := sqlbuilder.BuildQuery(tx.Model(&productMaterialGroupModels), queryOptions)
141 query.SetOffsetAndLimit(domain.MaxQueryRow) 141 query.SetOffsetAndLimit(domain.MaxQueryRow)
  142 + query.SetWhereByQueryOption("company_id = ?", "companyId")
142 if v, ok := queryOptions["orderByProductMaterialGroupId"]; ok { 143 if v, ok := queryOptions["orderByProductMaterialGroupId"]; ok {
143 query.SetOrderDirect("product_material_group_id", v.(string)) 144 query.SetOrderDirect("product_material_group_id", v.(string))
144 } else { 145 } else {
@@ -24,6 +24,20 @@ func NewTree(nodes []TreeNode) *Tree { @@ -24,6 +24,20 @@ func NewTree(nodes []TreeNode) *Tree {
24 return tree 24 return tree
25 } 25 }
26 26
  27 +func NewTreeWithNodes(nodes ...TreeNode) *Tree {
  28 + var tree = &Tree{
  29 + Node: nil,
  30 + Nodes: make([]*Tree, 0),
  31 + }
  32 + for i := range nodes {
  33 + match := traverseAdd(tree, nodes[i])
  34 + if !match {
  35 + tree.Nodes = append(tree.Nodes, newTree(nodes[i]))
  36 + }
  37 + }
  38 + return tree
  39 +}
  40 +
27 func newTree(node TreeNode) *Tree { 41 func newTree(node TreeNode) *Tree {
28 return &Tree{ 42 return &Tree{
29 Node: node, 43 Node: node,
@@ -144,6 +144,8 @@ func (controller *StatisticsController) TaskHandler() func(ctx *context.Context) @@ -144,6 +144,8 @@ func (controller *StatisticsController) TaskHandler() func(ctx *context.Context)
144 }) 144 })
145 } 145 }
146 } 146 }
  147 + case "11":
  148 + crontab.SyncMaterialGroup(nil)
147 } 149 }
148 Response(ctx, nil, nil) 150 Response(ctx, nil, nil)
149 } 151 }