作者 yangfu

refactor: 计划管理、工位

... ... @@ -16,6 +16,7 @@ require (
github.com/imkira/go-interpol v1.1.0 // indirect
github.com/linmadan/egglib-go v0.0.0-20210313060205-8b5e456b11f7
github.com/moul/http2curl v1.0.0 // indirect
github.com/mozillazg/go-pinyin v0.19.0
github.com/onsi/ginkgo v1.15.2
github.com/onsi/gomega v1.11.0
github.com/sergi/go-diff v1.2.0 // indirect
... ...
... ... @@ -249,6 +249,8 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs=
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
github.com/mozillazg/go-pinyin v0.19.0 h1:p+J8/kjJ558KPvVGYLvqBhxf8jbZA2exSLCs2uUVN8c=
github.com/mozillazg/go-pinyin v0.19.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
... ...
package query
import (
"fmt"
"reflect"
"strings"
"github.com/beego/beego/v2/core/validation"
)
type GenProductCodeQuery struct {
// 企业id
CompanyId int `cname:"企业id" json:"companyId" valid:"Required"`
}
func (getProductQuery *GenProductCodeQuery) Valid(validation *validation.Validation) {
//validation.SetError("CustomValid", "未实现的自定义认证")
}
func (getProductQuery *GenProductCodeQuery) ValidateQuery() error {
valid := validation.Validation{}
b, err := valid.Valid(getProductQuery)
if err != nil {
return err
}
if !b {
elem := reflect.TypeOf(getProductQuery).Elem()
for _, validErr := range valid.Errors {
field, isExist := elem.FieldByName(validErr.Field)
if isExist {
return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
} else {
return fmt.Errorf(validErr.Message)
}
}
}
return nil
}
... ...
... ... @@ -362,6 +362,23 @@ func (productService *ProductService) BatchAddProduct(opt *domain.OperateInfo, l
return failRows, nil
}
// 创建产品服务
func (productService *ProductService) GenProductCode(createProductCommand *query.GenProductCodeQuery) (interface{}, error) {
if err := createProductCommand.ValidateQuery(); err != nil {
return nil, application.ThrowError(application.ARG_ERROR, err.Error())
}
generator := redis.NewProductCodeCache(createProductCommand.CompanyId)
code, err := redis.GenCode(generator)
if err != nil {
log.Logger.Error(err.Error())
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "服务器异常")
}
return map[string]interface{}{
"code": code,
}, nil
}
func NewProductService(options map[string]interface{}) *ProductService {
newProductService := &ProductService{}
return newProductService
... ...
... ... @@ -13,6 +13,8 @@ type UpdateProductJobCommand struct {
ProductJobId int `cname:"工位ID" json:"productJobId" valid:"Required"`
// 工位名称
JobName string `cname:"工位名称" json:"jobName" valid:"Required"`
// 工位名称
ProcessName string `cname:"工序名称" json:"processName" valid:"Required"`
// 车间ID
WorkshopId int `cname:"车间ID" json:"workshopId" valid:"Required"`
// 生产线ID
... ...
... ... @@ -31,7 +31,9 @@ type ProductJobDto struct {
// 权限标识 (当前登录组织匹配为true,否则false)
//AuthFlag bool `json:"authFlag"`
// 关联设备列表
RelatedDevices []DeviceDto `json:"relatedDevices,omitempty"`
RelatedDevices []int `json:"relatedDevices,omitempty"`
// 关联设备列表
RelatedDeviceList []DeviceDto `json:"relatedDevicesList,omitempty"`
}
type DeviceDto struct {
... ... @@ -48,15 +50,16 @@ func (d *ProductJobDto) LoadDto(job *domain.ProductJob, orgId int) {
d.JobName = job.JobName
d.ProcessName = job.ProcessName
d.WorkStation = job.WorkStation
d.RelatedDevices = job.RelatedDevices
//d.AuthFlag = domain.CheckOrgAuth(orgId, job.OrgId)
//if job.Ext != nil {
// d.OrgName = job.Ext.OrgName
//}
}
func (d *ProductJobDto) WithRelatedDevices(devices []*domain.Device) *ProductJobDto {
func (d *ProductJobDto) WithRelatedDevicesList(devices []*domain.Device) *ProductJobDto {
for i := range devices {
d.RelatedDevices = append(d.RelatedDevices, DeviceDto{
d.RelatedDeviceList = append(d.RelatedDeviceList, DeviceDto{
DeviceName: devices[i].DeviceName,
DeviceId: devices[i].DeviceId,
DeviceCode: devices[i].DeviceCode,
... ...
... ... @@ -101,18 +101,18 @@ func (productJobService *ProductJobService) GetProductJob(getProductJobQuery *qu
newJobDto := &dto.ProductJobDto{}
newJobDto.LoadDto(productJob, 0)
if len(productJob.RelatedDevices) > 0 {
deviceRepository, _, _ := factory.FastPgDevice(transactionContext, 0)
_, devices, err := deviceRepository.Find(map[string]interface{}{
"companyId": productJob.CompanyId,
"orgId": productJob.OrgId,
"inDeviceId": productJob.RelatedDevices,
})
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
newJobDto.WithRelatedDevices(devices)
}
//if len(productJob.RelatedDevices) > 0 {
// deviceRepository, _, _ := factory.FastPgDevice(transactionContext, 0)
// _, devices, err := deviceRepository.Find(map[string]interface{}{
// "companyId": productJob.CompanyId,
// "orgId": productJob.OrgId,
// "inDeviceId": productJob.RelatedDevices,
// })
// if err != nil {
// return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
// }
// newJobDto.WithRelatedDevicesList(devices)
//}
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
... ... @@ -289,6 +289,7 @@ func (productJobService *ProductJobService) UpdateProductJob(cmd *command.Update
productJob.JobName = cmd.JobName
productJob.RelatedDevices = cmd.RelatedDevices
productJob.UpdatedAt = time.Now()
productJob.ProcessName = cmd.ProcessName
if productJob, err := productJobRepository.Save(productJob); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
... ...
... ... @@ -21,15 +21,17 @@ type CreateProductPlanCommand struct {
// 生产日期
ProductDate string `cname:"生产日期" json:"productDate" valid:"Required"`
// 上班班次 1:全天 2:白班 4:中班 8:夜班
WorkOn int `cname:"上班班次 1:全天 2:白班 4:中班 8:夜班" json:"workOn" valid:"Required"`
WorkOn int `cname:"上班班次 1:全天 2:白班 4:中班 8:夜班" json:"workOn"`
// 机台 (A、B、C、D 区分机器大小)
Machine string `cname:"机台 (A、B、C、D 区分机器大小)" json:"machine" valid:"Required"`
Machine string `cname:"机台 (A、B、C、D 区分机器大小)" json:"machine"`
// 计划的产品名称
PlanProductName string `cname:"计划的产品名称" json:"planProductName" valid:"Required"`
//PlanProductName string `cname:"计划的产品名称" json:"planProductName"`
// 产品ID
ProductId int `cname:"产品ID" json:"productId" valid:"Required"`
// 数量(保留两位小数)
Quantity float64 `cname:"数量(保留两位小数)" json:"quantity" valid:"Required"`
// 单位
Unit string `cname:"单位" json:"unit" valid:"Required"`
//Unit string `cname:"单位" json:"unit" `
// 单份重量(原材料)
//nitWeight float64 `cname:"单份重量(原材料)" json:"unitWeight" valid:"Required"`
// 重量
... ...
... ... @@ -23,19 +23,21 @@ type UpdateProductPlanCommand struct {
// 生产日期
ProductDate string `cname:"生产日期" json:"productDate" valid:"Required"`
// 上班班次 1:全天 2:白班 4:中班 8:夜班
WorkOn int `cname:"上班班次 1:全天 2:白班 4:中班 8:夜班" json:"workOn" valid:"Required"`
WorkOn int `cname:"上班班次 1:全天 2:白班 4:中班 8:夜班" json:"workOn"`
// 机台 (A、B、C、D 区分机器大小)
Machine string `cname:"机台 (A、B、C、D 区分机器大小)" json:"machine" valid:"Required"`
Machine string `cname:"机台 (A、B、C、D 区分机器大小)" json:"machine"`
// 计划的产品名称
PlanProductName string `cname:"计划的产品名称" json:"planProductName" valid:"Required"`
PlanProductName string `cname:"计划的产品名称" json:"planProductName"`
// 产品ID
ProductId int `cname:"产品ID" json:"productId" valid:"Required"`
// 数量(保留两位小数)
Quantity float64 `cname:"数量(保留两位小数)" json:"quantity" valid:"Required"`
// 单位
Unit string `cname:"单位" json:"unit" valid:"Required"`
Unit string `cname:"单位" json:"unit"`
// 单份重量(原材料)
//UnitWeight float64 `cname:"单份重量(原材料)" json:"unitWeight" valid:"Required"`
// 重量
Weight float64 `cname:"重量" json:"weight" valid:"Required"`
Weight float64 `cname:"重量" json:"weight"`
// 备注
Remark string `cname:"备注" json:"remark" valid:"Required"`
// 生产日期
... ...
... ... @@ -53,6 +53,12 @@ func (productPlanService *ProductPlanService) CreateProductPlan(cmd *command.Cre
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
var product *domain.Product
_, product, err = factory.FastPgProduct(transactionContext, cmd.ProductId)
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
newProductPlan := &domain.ProductPlan{
CompanyId: cmd.CompanyId,
OrgId: cmd.OrgId,
... ... @@ -61,18 +67,27 @@ func (productPlanService *ProductPlanService) CreateProductPlan(cmd *command.Cre
Workshop: workshop.CloneSample(),
WorkOn: cmd.WorkOn,
Machine: cmd.Machine,
PlanProductName: cmd.PlanProductName,
PlanProductName: product.ProductName,
PlanDevoted: &domain.UnitQuantity{
Unit: cmd.Unit,
Unit: product.ProductSpec.Unit,
Quantity: cmd.Quantity,
Weight: cmd.Weight,
Weight: product.ProductWeigh(cmd.Quantity),
UnitWeight: product.ProductSpec.UnitWeight,
},
PlanStatus: domain.PlanOffline,
WorkStation: &domain.WorkStation{},
Remark: cmd.Remark,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
Ext: domain.NewExt(org.OrgName),
Ext: domain.NewExt(org.OrgName).WithProductPlanExt(&domain.ProductPlanExt{
ProductId: product.ProductId,
ProductCode: product.ProductCode,
ProductName: product.ProductName,
//ProductSpec: product.ProductSpec,
}),
}
if cmd.Weight > 0 {
newProductPlan.PlanDevoted.Weight = cmd.Weight
}
if productPlan, err = productPlanRepository.Save(newProductPlan); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
... ... @@ -232,7 +247,26 @@ func (productPlanService *ProductPlanService) UpdateProductPlan(cmd *command.Upd
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
var product *domain.Product
_, product, err = factory.FastPgProduct(transactionContext, cmd.ProductId)
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
productPlan.Workshop = workshop.CloneSample()
productPlan.Ext.WithProductPlanExt(&domain.ProductPlanExt{
ProductId: product.ProductId,
ProductCode: product.ProductCode,
ProductName: product.ProductName,
//ProductSpec: product.ProductSpec,
})
productPlan.PlanDevoted.UnitWeight = product.ProductSpec.UnitWeight
cmd.PlanProductName = product.ProductName
cmd.Unit = product.ProductSpec.Unit
if cmd.Weight == 0 {
cmd.Weight = product.ProductWeigh(cmd.Quantity)
}
if err := productPlan.Update(tool_funs.SimpleStructToMap(cmd)); err != nil {
return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
... ...
//go:build !local
//+build !local
package constant
... ...
... ... @@ -10,6 +10,9 @@ type Ext struct {
// 考勤记录扩展
AttendanceExt *ProductAttendanceRecordExt `json:"attendanceExt,omitempty"`
// 生产计划扩展
ProductPlanExt *ProductPlanExt `json:"productPlanExt,omitempty"`
}
func NewExt(orgName string) *Ext {
... ... @@ -27,3 +30,8 @@ func (e *Ext) WithAttendanceExt(ext *ProductAttendanceRecordExt) *Ext {
e.AttendanceExt = ext
return e
}
func (e *Ext) WithProductPlanExt(ext *ProductPlanExt) *Ext {
e.ProductPlanExt = ext
return e
}
... ...
... ... @@ -75,6 +75,13 @@ func (product *Product) Update(data map[string]interface{}) error {
return nil
}
func (item *Product) ProductWeigh(quality float64) float64 {
if quality <= 0 {
return 0
}
return item.ProductSpec.UnitWeight * quality
}
// 导入数据体
type ImportProductItem struct {
// 产品编号 编码规则为“CP”+2 位年+2 位月+2 位日+3 位流水码,如 CP211229001
... ...
package domain
// 生产计划扩展
type ProductPlanExt struct {
// 产品ID
ProductId int `json:"productId,omitempty"`
// 产品编号 编码规则为“CP”+2 位年+2 位月+2 位日+3 位流水码,如 CP211229001
ProductCode string `json:"productCode,omitempty"`
// 产品名称
ProductName string `json:"productName,omitempty"`
// 产品规格
//ProductSpec *UnitQuantity `json:"productSpec,omitempty"`
}
... ...
... ... @@ -8,4 +8,10 @@ type ProductRecordInfo struct {
Material *UnitConversion `json:"material,omitempty"`
// 生产计划信息(批次)
ProductPlan *ProductPlan `json:"productPlan,omitempty"`
// 生产计划ID
ProductPlanId int `json:"productPlanId,omitempty"`
// 生产小组ID
ProductGroupId int `json:"productGroupId,omitempty"`
}
... ...
package converter
import (
"github.com/mozillazg/go-pinyin"
"strings"
)
func ToPinYin(hans string, sep string) string {
a := pinyin.NewArgs()
tmp := pinyin.Pinyin(hans, a)
result := make([]string, 0)
for i := range tmp {
result = append(result, tmp[i]...)
}
return strings.Join(result, sep)
}
... ...
package converter
import "testing"
func TestToPinYin(t *testing.T) {
inputs := []struct {
hans string
}{
{
"杨超越",
},
{
"陈阿鸡",
},
}
for i := range inputs {
got := ToPinYin(inputs[i].hans, " ")
t.Log(got)
}
}
... ...
... ... @@ -92,3 +92,13 @@ func (controller *ProductController) BatchAddProduct() {
data, err := productService.BatchAddProduct(ParseOperateInfo(controller.BaseController), cmd.List)
controller.Response(data, err)
}
func (controller *ProductController) GenProductCode() {
productService := service.NewProductService(nil)
cmd := &query.GenProductCodeQuery{}
Must(controller.Unmarshal(cmd))
op := ParseOperateInfo(controller.BaseController)
cmd.CompanyId = op.CompanyId
data, err := productService.GenProductCode(cmd)
controller.Response(data, err)
}
... ...
... ... @@ -14,4 +14,5 @@ func init() {
web.Router("/products/", &controllers.ProductController{}, "Get:ListProduct")
web.Router("/products/search", &controllers.ProductController{}, "Post:SearchProduct")
web.Router("/products/batch-add", &controllers.ProductController{}, "Post:BatchAddProduct")
web.Router("/products/generate-code", &controllers.ProductController{}, "Post:GenProductCode")
}
... ...