作者 yangfu

feat: 物料分组同步

-- 表product_material_group 增加唯一索引 idx_unq_product_material_group_company_id_org_id_material_group_number
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);
\ No newline at end of file
... ...
... ... @@ -60,6 +60,9 @@ func (crontabService *CrontabService) initTask() {
syncProductPlan := task.NewTask("定时同步车间计划", "0 5 * * * *", SyncProductPlan)
task.AddTask("SyncProductPlan", syncProductPlan)
syncMaterialGroup := task.NewTask("定时同步物料分组", "0 0 0/2 * * *", SyncMaterialGroup)
task.AddTask("syncMaterialGroup", syncMaterialGroup)
}
func (crontabService *CrontabService) StartCrontabTask() {
... ...
package crontab
import (
"context"
"fmt"
"github.com/linmadan/egglib-go/transaction/pg"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/factory"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/syncdata"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log"
"runtime/debug"
)
// SyncMaterialGroup 定时同步物料分组
func SyncMaterialGroup(ctx context.Context) error {
defer func() {
if r := recover(); r != nil {
log.Logger.Error(fmt.Sprintf("%v", r), map[string]interface{}{"task": "定时同步物料分组", "stack": string(debug.Stack())})
}
}()
transactionContext, err := factory.CreateTransactionContext(nil)
if err != nil {
return err
}
if err := transactionContext.StartTransaction(); err != nil {
return err
}
defer func() {
if err != nil {
log.Logger.Error("【定时同步物料分组】 失败:" + err.Error())
}
transactionContext.RollbackTransaction()
}()
log.Logger.Debug("【定时同步物料分组】 启动")
pullK3CloudService := syncdata.PullDataK3CloudService{}
if err := pullK3CloudService.SyncDataMaterialGroup(transactionContext.(*pg.TransactionContext)); err != nil {
log.Logger.Error(err.Error(), map[string]interface{}{"task": "定时同步物料分组"})
return nil
}
if err = transactionContext.CommitTransaction(); err != nil {
return err
}
return nil
}
... ...
package syncdata
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/constant"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/domainService"
... ... @@ -612,3 +613,71 @@ func (srv *PullDataK3CloudService) SyncDataProductPlan(ptr *pgTransaction.Transa
}
return nil
}
// 同步产品
func (srv *PullDataK3CloudService) SyncDataMaterialGroup(ptr *pgTransaction.TransactionContext) error {
prdMoDao, err := dao.NewMaterialK3cloudDao(ptr)
if err != nil {
return err
}
var userService = domainService.NewUserService()
org, err := userService.Organization(constant.MANUFACTURE_DEFAULT_ORGID)
if err != nil {
return application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
fromMaterialGroups, err := prdMoDao.SearchMaterialGroup() // 默认企业名称素天下、或者使用组织ID
if err != nil {
return application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
var (
cid = constant.MANUFACTURE_DEFAULT_COMPANYID
oid = constant.MANUFACTURE_DEFAULT_ORGID
)
productMaterialGroupRepository, _, _ := factory.FastProductMaterialGroup(ptr, 0)
_, materialGroups, err := productMaterialGroupRepository.Find(map[string]interface{}{"companyId": cid})
if err != nil {
return err
}
mapMaterialGroups := domain.ProductMaterialGroups(materialGroups).ToMapByGroupNumber()
mapFromMaterialGroups := models.MaterialGroupK3clouds(fromMaterialGroups).ToMapId()
for _, from := range fromMaterialGroups {
to, ok := mapMaterialGroups[from.Number]
if ok {
// 更新
if to.MaterialGroupName != from.Name {
log.Logger.Info(fmt.Sprintf("更新物料分组 old:%v new:%v", to.MaterialGroupName, from.Name), map[string]interface{}{"material": to})
to.MaterialGroupName = from.Name
}
continue
}
var parentId int
if from.ParentId > 0 {
parent, ok := mapFromMaterialGroups[from.ParentId]
if !ok {
log.Logger.Warn("parent node not exits", map[string]interface{}{"material": to})
continue
}
toParent, ok := mapMaterialGroups[parent.Number]
if !ok {
log.Logger.Warn("to parent node not exits", map[string]interface{}{"material": to})
continue
}
parentId = toParent.ProductMaterialGroupId
}
productMaterialGroup := &domain.ProductMaterialGroup{
CompanyId: cid,
OrgId: oid,
Pid: parentId,
MaterialGroupName: from.Name,
MaterialGroupNumber: from.Number,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
Ext: domain.NewExt(org.OrgName),
}
if productMaterialGroup, err = productMaterialGroupRepository.Save(productMaterialGroup); err != nil {
return err
}
mapMaterialGroups[productMaterialGroup.MaterialGroupNumber] = productMaterialGroup
}
return nil
}
... ...
... ... @@ -77,3 +77,11 @@ func (tree ProductMaterialGroups) Less(i, j int) bool {
func (tree ProductMaterialGroups) Swap(i, j int) {
tree[i], tree[j] = tree[j], tree[i]
}
func (tree ProductMaterialGroups) ToMapByGroupNumber() map[string]*ProductMaterialGroup {
var result = make(map[string]*ProductMaterialGroup)
for i := range tree {
result[tree[i].MaterialGroupNumber] = tree[i]
}
return result
}
... ...
... ... @@ -178,3 +178,13 @@ func (d *MaterialK3cloudDao) GetLastVersion() (int64, error) {
}
return materialData[0].DataVersion, nil
}
func (d *MaterialK3cloudDao) SearchMaterialGroup() ([]*models.MaterialGroupK3cloud, error) {
var materialData []*models.MaterialGroupK3cloud
query := d.transactionContext.PgTx.Model(&materialData)
query.OrderExpr("number asc")
if err := query.Select(); err != nil {
return nil, err
}
return materialData, nil
}
... ...
... ... @@ -9,3 +9,13 @@ type MaterialGroupK3cloud struct {
ParentId int `comment:"父级id" pg:"parent_id"`
DataVersion int64 `comment:"数据版本" pg:"data_version"`
}
type MaterialGroupK3clouds []*MaterialGroupK3cloud
func (materialGroupK3clouds MaterialGroupK3clouds) ToMapId() map[int]*MaterialGroupK3cloud {
var result = make(map[int]*MaterialGroupK3cloud)
for i := range materialGroupK3clouds {
result[materialGroupK3clouds[i].Id] = materialGroupK3clouds[i]
}
return result
}
... ...
... ... @@ -139,6 +139,7 @@ func (repository *ProductMaterialGroupRepository) Find(queryOptions map[string]i
productMaterialGroups := make([]*domain.ProductMaterialGroup, 0)
query := sqlbuilder.BuildQuery(tx.Model(&productMaterialGroupModels), queryOptions)
query.SetOffsetAndLimit(domain.MaxQueryRow)
query.SetWhereByQueryOption("company_id = ?", "companyId")
if v, ok := queryOptions["orderByProductMaterialGroupId"]; ok {
query.SetOrderDirect("product_material_group_id", v.(string))
} else {
... ...
... ... @@ -24,6 +24,20 @@ func NewTree(nodes []TreeNode) *Tree {
return tree
}
func NewTreeWithNodes(nodes ...TreeNode) *Tree {
var tree = &Tree{
Node: nil,
Nodes: make([]*Tree, 0),
}
for i := range nodes {
match := traverseAdd(tree, nodes[i])
if !match {
tree.Nodes = append(tree.Nodes, newTree(nodes[i]))
}
}
return tree
}
func newTree(node TreeNode) *Tree {
return &Tree{
Node: node,
... ...
... ... @@ -144,6 +144,8 @@ func (controller *StatisticsController) TaskHandler() func(ctx *context.Context)
})
}
}
case "11":
crontab.SyncMaterialGroup(nil)
}
Response(ctx, nil, nil)
}
... ...