SJA APS后端代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

528 lines
14 KiB

package service
import (
"fmt"
"github.com/go-xorm/xorm"
"leit.com/leit_seat_aps/common"
"leit.com/leit_seat_aps/db"
"reflect"
"strconv"
"strings"
"time"
)
// 车型业务对象
type BL_Carmodel struct {
Carmodelid string
Cm_pf_dict map[string]string // 车型分配的零件族
Cm_sg_dict map[string]string // 车型分配的供应组
Cm_attr_dict map[int]BL_Carmodel_Atcod // 车型分配的属性字典
Carmodeltab db.Me_carmodel
SpecDict map[int]BL_Carmodel_Spec // 用于存储当前车型的各种配置
}
// 车型分配的属性对象
type BL_Carmodel_Atcod struct {
Carmodelid string // 车型ID
Attrcode int // 属性ID
Mandatory int // 是否强制需要
Verifyrule string // 验证规则
Carmodel_attrtab db.Me_carmodel_atcodlst
}
// 车型版本规格
type BL_Carmodel_Spec struct {
Carmodelid string // 车型ID
Version int
Cmvtab db.Me_carmodel_ver
SGPartDict map[string]db.Me_carmodel_ver_partlst
Partlst []db.Me_carmodel_ver_partlst
AttrDict map[int]BL_OrdAttribute
VerrorDict map[string]BL_VerifyError // 校验报错信息
}
// 车型显示属性
type BL_Carmodel_Display struct {
Pos int
Attrcode int // 属性ID
Attrval string // 属性值
AttrvalDesc string // 值描述
AttrShortCode string // 值短码
}
// 验证OEM订单当前是否满足车型匹配需求:即零件族是否符合规范
func (bl_cm *BL_Carmodel) IsBelongToThisModel(cotablst []db.Pln_custorder) (belong bool) {
var (
i, j int
pfdict, sgdict map[string]string
pf, sg string
ok bool
)
// 获取客户订单集的零件族清单和供应组清单
pfdict = make(map[string]string)
sgdict = make(map[string]string)
for i = 0; i < len(cotablst); i++ {
pfdict[cotablst[i].Partfamilyid] = cotablst[i].Partfamilyid
for j = 0; j < len(cotablst[i].Sgpartlst); j++ {
sgdict[cotablst[i].Sgpartlst[j].Supplygroupid] = cotablst[i].Sgpartlst[j].Supplygroupid
}
}
// 判断零件族数量是否一致,一个客户订单对应一个零件族
if len(pfdict) != len(bl_cm.Cm_pf_dict) {
belong = false
return
}
// 判断各零件族ID是否一致
for pf, _ = range pfdict {
if _, ok = bl_cm.Cm_pf_dict[pf]; !ok {
belong = false
return
}
}
// 判断供应组数量是否一致
if len(sgdict) != len(bl_cm.Cm_sg_dict) {
belong = false
return
}
// 判断各供应组ID是否一致
for sg, _ = range sgdict {
if _, ok = bl_cm.Cm_sg_dict[sg]; !ok {
belong = false
return
}
}
belong = true
return
}
// 判断给定的客户订单清单是否属于当前车型规格
func (bl_cmspec *BL_Carmodel_Spec) IsBelongToThisSpec(cotablst []db.Pln_custorder) (belong bool) {
var (
i, j, sumqty int
key string
cmpartab db.Me_carmodel_ver_partlst
ok bool
)
// 判断零件数是否一致
sumqty = 0
for i = 0; i < len(cotablst); i++ {
sumqty = sumqty + len(cotablst[i].Sgpartlst)
}
if sumqty != len(bl_cmspec.SGPartDict) {
belong = false
return
}
// 逐个零件判断:SG_Partid
for i = 0; i < len(cotablst); i++ {
for j = 0; j < len(cotablst[i].Sgpartlst); j++ {
// 判断 供应组_零件ID 是否存在
key = cotablst[i].Sgpartlst[j].Supplygroupid + "_" + cotablst[i].Sgpartlst[j].Partid
if cmpartab, ok = bl_cmspec.SGPartDict[key]; !ok {
belong = false
return
}
// 存在则判断零件数量是否一致
if cotablst[i].Sgpartlst[j].Partqty != cmpartab.Partqty {
belong = false
return
}
}
}
belong = true
return
}
// 验证OEM订单当前是否满足车型匹配需求:即零件族是否符合规范
func (bl_cm *BL_Carmodel) IsNewSpecToThisModel(cotablst []db.Pln_custorder) (isnew bool, ver int) {
var (
bl_cmspec BL_Carmodel_Spec
)
isnew = true
for _, bl_cmspec = range bl_cm.SpecDict {
if bl_cmspec.IsBelongToThisSpec(cotablst) {
isnew = false
ver = bl_cmspec.Version
return
}
}
return
}
// 创建新车型规格
func (bl_cm *BL_Carmodel) CreateNewCarmodel(cotablst []db.Pln_custorder, bl_proj *BL_Project, session *xorm.Session) (bl_cmspec BL_Carmodel_Spec, err error) {
var (
ver int
cmvtab db.Me_carmodel_ver
)
// 初始化
cmvtab = db.Me_carmodel_ver{}
if ver, err = cmvtab.GetLatestCarmodelVersion(bl_cm.Carmodelid); err != nil {
return
}
// 新版本号+1
ver = ver + 1
bl_cmspec = BL_Carmodel_Spec{Carmodelid: bl_cm.Carmodelid, Version: ver}
// 获取车型版本的属性
bl_cmspec.GetSpecAtcodList(cotablst, bl_proj)
// 验证车型版本属性
bl_cmspec.ValidateSpecAttribute(bl_cm)
// 保存车型版本相关数据
if err = bl_cmspec.Save(bl_cm, bl_proj, session); err != nil {
return
}
return
}
// 获取车型规格的零件清单和属性清单
func (bl_cmspec *BL_Carmodel_Spec) GetSpecAtcodList(cotablst []db.Pln_custorder, bl_proj *BL_Project) {
var (
i, j int
cmvpttab db.Me_carmodel_ver_partlst
bl_part BL_Part
bl_attr BL_OrdAttribute
bl_partattr BL_PartAttribute
key string
ok bool
)
bl_cmspec.Partlst = []db.Me_carmodel_ver_partlst{}
bl_cmspec.AttrDict = make(map[int]BL_OrdAttribute)
bl_cmspec.SGPartDict = make(map[string]db.Me_carmodel_ver_partlst)
// 获取零件清单和属性清单
for i = 0; i < len(cotablst); i++ {
for j = 0; j < len(cotablst[i].Sgpartlst); j++ {
cmvpttab = db.Me_carmodel_ver_partlst{Finr: db.G_FINR}
cmvpttab.Carmodelid = bl_cmspec.Carmodelid
cmvpttab.Version = bl_cmspec.Version
cmvpttab.Supplygroupid = cotablst[i].Sgpartlst[j].Supplygroupid
cmvpttab.Partid = cotablst[i].Sgpartlst[j].Partid
cmvpttab.Partqty = cotablst[i].Sgpartlst[j].Partqty
bl_cmspec.Partlst = append(bl_cmspec.Partlst, cmvpttab)
// 填充型号规格的零件字典
key = cmvpttab.Supplygroupid + "_" + cmvpttab.Partid
bl_cmspec.SGPartDict[key] = cmvpttab
// 获取零件对象,从而获取属性对象
if bl_part, ok = bl_proj.Partdict[cmvpttab.Partid]; !ok {
// 日志记录错误
continue
}
// 填充型号规格的属性字典
for _, bl_partattr = range bl_part.AtcodDict {
if bl_attr, ok = bl_cmspec.AttrDict[bl_partattr.Attrcode]; !ok {
bl_attr = BL_OrdAttribute{Attrcode: bl_partattr.Attrcode}
bl_attr.Attrvaldict = make(map[string]string)
bl_attr.Attrvaldict[bl_partattr.Attrvalue] = bl_partattr.Attrvalue
}
bl_attr.Attrvaldict[bl_partattr.Attrvalue] = bl_partattr.Attrvalue
bl_cmspec.AttrDict[bl_attr.Attrcode] = bl_attr
}
}
}
return
}
// 验证车型规格属性
func (bl_cmspec *BL_Carmodel_Spec) ValidateSpecAttribute(bl_cm *BL_Carmodel) {
var (
bl_cmatcod BL_Carmodel_Atcod
bl_attr BL_OrdAttribute
verr BL_VerifyError
ok bool
)
// 初始化
bl_cmspec.VerrorDict = make(map[string]BL_VerifyError)
// 遍历车型的验证属性
for _, bl_cmatcod = range bl_cm.Cm_attr_dict {
// 属性必须存在
if bl_cmatcod.Carmodel_attrtab.Mandatory > 0 {
if _, ok = bl_cmspec.AttrDict[bl_cmatcod.Attrcode]; !ok {
verr = BL_VerifyError{}
verr.Errortype = common.CO_VERIFY_ATCOD_NOTEXIST
verr.Attrcode = bl_cmatcod.Attrcode
verr.Errorinfo = fmt.Sprintf("强制要求的属性: %d 不存在!", bl_cmatcod.Attrcode)
bl_cmspec.VerrorDict[verr.GetDictKey()] = verr
}
}
// 校验属性值
switch bl_cmatcod.Carmodel_attrtab.Verifyrule {
// 属性值唯一
case common.VERIFY_RULE_ATVAL_UNIQ:
if bl_attr, ok = bl_cmspec.AttrDict[bl_cmatcod.Attrcode]; ok {
if len(bl_attr.Attrvaldict) > 1 {
verr = BL_VerifyError{}
verr.Errortype = common.CO_VERIFY_ATCOD_VALUE_CONFLICT
verr.Attrcode = bl_cmatcod.Attrcode
verr.Errorinfo = fmt.Sprintf("属性: %d 存在多个冲突值!", bl_cmatcod.Attrcode)
bl_cmspec.VerrorDict[verr.GetDictKey()] = verr
}
}
}
}
return
}
// 获取车型规格的显示属性
func (bl_cmspec *BL_Carmodel_Spec) GenerateSpecDescr(bl_cm *BL_Carmodel, bl_proj *BL_Project) (spec string) {
var (
bl_cmatcod BL_Carmodel_Atcod
bl_cmdisp BL_Carmodel_Display
inter interface{}
bl_cmdisplst []interface{}
bl_attr BL_Attribute
bl_ordattr BL_OrdAttribute
valst []string
val string
i, pos, idx int
err error
ok bool
)
// 遍历车型指定属性
bl_cmdisplst = []interface{}{}
for _, bl_cmatcod = range bl_cm.Cm_attr_dict {
if bl_cmatcod.Carmodel_attrtab.Attrvalue2 != "" {
valst = strings.Split(bl_cmatcod.Carmodel_attrtab.Attrvalue2, ":")
if len(valst) >= 2 && valst[0] == "DISPLAY" {
if pos, err = strconv.Atoi(valst[1]); err != nil {
continue
}
// 获取属性
if bl_attr, ok = bl_proj.Attrdict[bl_cmatcod.Attrcode]; !ok {
continue
}
// 在当前spec中获取属性(值必须是唯一)
if bl_ordattr, ok = bl_cmspec.AttrDict[bl_cmatcod.Attrcode]; !ok {
continue
}
// 生成显示属性
for _, val = range bl_ordattr.Attrvaldict {
}
idx = bl_attr.GetValPos(val)
if idx < 0 {
continue
}
bl_cmdisp = BL_Carmodel_Display{}
bl_cmdisp.Pos = pos
bl_cmdisp.Attrcode = bl_cmatcod.Carmodel_attrtab.Attrcode
bl_cmdisp.Attrval = bl_attr.Atvaltablst[idx].Attrvalue
bl_cmdisp.AttrvalDesc = bl_attr.Atvaltablst[idx].Descr
bl_cmdisp.AttrShortCode = bl_attr.Atvaltablst[idx].Shortcode
bl_cmdisplst = append(bl_cmdisplst, bl_cmdisp)
}
}
}
// 指定pos字段排序
common.SortBody(bl_cmdisplst, func(p, q *interface{}) bool {
v := reflect.ValueOf(*p)
i := v.FieldByName("Pos")
v = reflect.ValueOf(*q)
j := v.FieldByName("Pos")
return i.Int() < j.Int()
})
// 拼接值返回
spec = ""
for i, inter = range bl_cmdisplst {
// 断言转换类型
if bl_cmdisp, ok = inter.(BL_Carmodel_Display); !ok {
continue
}
if i == 0 {
spec = bl_cmdisp.Attrval
} else {
spec = spec + " " + bl_cmdisp.Attrval
}
}
// 超长处理,自动截取
if len(spec) > 160 {
return spec[:160]
}
return
}
// 获取车型规格的显示属性
func (bl_cmspec *BL_Carmodel_Spec) GenerateSpecDescrNew(bl_cm *BL_Carmodel, bl_proj *BL_Project) (spec string) {
var (
bl_cmatcod BL_Carmodel_Atcod
bl_cmdisp BL_Carmodel_Display
inter interface{}
bl_cmdisplst []interface{}
bl_attr BL_Attribute
bl_ordattr BL_OrdAttribute
val string
iAtcod int
i, idx int
ok bool
)
bl_cmdisplst = []interface{}{}
// 遍历车型指定属性
for i = 0; i < len(bl_cm.Carmodeltab.Atcodlst); i++ {
switch bl_cm.Carmodeltab.Atcodlst[i].Verifyrule {
// 显示属性
case common.VERIFY_RULE_ATVAL_DISP:
iAtcod = bl_cm.Carmodeltab.Atcodlst[i].Attrcode
// 获取属性
if bl_attr, ok = bl_proj.Attrdict[iAtcod]; !ok {
continue
}
bl_cmdisp = BL_Carmodel_Display{}
bl_cmdisp.Pos = bl_cm.Carmodeltab.Atcodlst[i].Pos
bl_cmdisp.Attrcode = bl_cmatcod.Carmodel_attrtab.Attrcode
// 如果属性不存在则取-
if bl_ordattr, ok = bl_cmspec.AttrDict[iAtcod]; !ok {
bl_cmdisp.AttrShortCode = "-"
bl_cmdisplst = append(bl_cmdisplst, bl_cmdisp)
continue
}
// 生成显示属性
for _, val = range bl_ordattr.Attrvaldict {
idx = bl_attr.GetValPos(val)
if idx < 0 {
bl_cmdisp.AttrShortCode = "-"
bl_cmdisplst = append(bl_cmdisplst, bl_cmdisp)
continue
}
}
bl_cmdisp.Attrval = bl_attr.Atvaltablst[idx].Attrvalue
bl_cmdisp.AttrvalDesc = bl_attr.Atvaltablst[idx].Descr
if strings.TrimSpace(bl_attr.Atvaltablst[idx].Shortcode) == "" {
bl_cmdisp.AttrShortCode = "-"
} else {
bl_cmdisp.AttrShortCode = bl_attr.Atvaltablst[idx].Shortcode
}
bl_cmdisplst = append(bl_cmdisplst, bl_cmdisp)
}
}
// 指定pos字段排序
common.SortBody(bl_cmdisplst, func(p, q *interface{}) bool {
v := reflect.ValueOf(*p)
i := v.FieldByName("Pos")
v = reflect.ValueOf(*q)
j := v.FieldByName("Pos")
return i.Int() < j.Int()
})
// 拼接值返回
spec = ""
for i, inter = range bl_cmdisplst {
// 断言转换类型
if bl_cmdisp, ok = inter.(BL_Carmodel_Display); !ok {
continue
}
if i == 0 {
spec = bl_cmdisp.AttrShortCode
} else {
spec = spec + bl_cmdisp.AttrShortCode
}
}
// 超长处理,自动截取
if len(spec) > 160 {
return spec[:160]
}
return
}
// 保存车型规格
func (bl_cmspec *BL_Carmodel_Spec) Save(bl_cm *BL_Carmodel, bl_proj *BL_Project, session *xorm.Session) (err error) {
var (
i int
bl_attr BL_OrdAttribute
bl_verr BL_VerifyError
attrval string
cmvattab db.Me_carmodel_ver_atcodlst
cmvertab db.Me_carmodel_ver_errorlst
)
// 保存版本头
bl_cmspec.Cmvtab = db.Me_carmodel_ver{Finr: db.G_FINR}
bl_cmspec.Cmvtab.Carmodelid = bl_cmspec.Carmodelid
bl_cmspec.Cmvtab.Version = bl_cmspec.Version
bl_cmspec.Cmvtab.Status = common.CM_SPEC_UNAPPROVED
if len(bl_cmspec.VerrorDict) > 0 {
bl_cmspec.Cmvtab.Handlestatus = common.CM_PARSE_ERROR
} else {
bl_cmspec.Cmvtab.Handlestatus = common.CM_PARSE_OK
}
bl_cmspec.Cmvtab.Spec = bl_cmspec.GenerateSpecDescrNew(bl_cm, bl_proj)
bl_cmspec.Cmvtab.Credatuz = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
bl_cmspec.Cmvtab.Lastuser = "cm_service"
if err = bl_cmspec.Cmvtab.Insert(session); err != nil {
return
}
// 保存零件清单
for i = 0; i < len(bl_cmspec.Partlst); i++ {
bl_cmspec.Partlst[i].Credatuz = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
bl_cmspec.Partlst[i].Lastuser = "cm_service"
if err = bl_cmspec.Partlst[i].Insert(session); err != nil {
return
}
}
// 保存属性清单
i = 1
for _, bl_attr = range bl_cmspec.AttrDict {
cmvattab = db.Me_carmodel_ver_atcodlst{Finr: db.G_FINR}
cmvattab.Carmodelid = bl_cmspec.Carmodelid
cmvattab.Version = bl_cmspec.Version
cmvattab.Attrcode = bl_attr.Attrcode
for _, attrval = range bl_attr.Attrvaldict {
cmvattab.Pos = i
cmvattab.Attrvalue = attrval
cmvattab.Credatuz = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
cmvattab.Lastuser = "cm_service"
if err = cmvattab.Insert(session); err != nil {
return
}
i++
}
}
// 保存验证错误
i = 1
for _, bl_verr = range bl_cmspec.VerrorDict {
cmvertab = db.Me_carmodel_ver_errorlst{Finr: db.G_FINR}
cmvertab.Carmodelid = bl_cmspec.Carmodelid
cmvertab.Version = bl_cmspec.Version
cmvertab.Pos = i
cmvertab.Attrcode = bl_verr.Attrcode
cmvertab.Errortype = bl_verr.Errortype
cmvertab.Errorinfo = bl_verr.Errorinfo
cmvertab.Errorstatus = "O"
cmvertab.Credatuz = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
cmvertab.Lastuser = "cm_service"
if err = cmvertab.Insert(session); err != nil {
return
}
i++
}
return
}