作者 庄敏学

解决冲突

正在显示 100 个修改的文件 包含 3324 行增加219 行删除

要显示太多修改。

为保证性能只显示 100 of 100+ 个文件。

#project
\ No newline at end of file
# 生产制造项目说明
## 1.数据导入导出模块
### 1.1.Excel导入流程
- 原型说明
选择模板下载、文件上传
![](https://doc-press.fjmaimaimai.com/team/frontend/plugins/data-transfer-upload.png)
导入数据检验有错,显示具体错误
![](https://timeless-world.oss-cn-shenzhen.aliyuncs.com/opportunity/dev_online/20220225/object/1645791913_Rz2JJkkx6xEXtAFdXDH5eH6NTjfhtjxf.jpg)
- [导入接口文档地址](https://doc-press.fjmaimaimai.com/team/frontend/plugins/business/import.html)
```
POST/v1/web/file-import
Content-Type multipart/form-data
params:
file 文件
code 对应导入模块的编码
```
- ``对接步骤``以导入公司用户模块为例
1.定义接口导入的``code``为``ADMIN_SYSTEM-MANAGE_BASE_USER``
2.根据接口解析导入文件的数据
3.调用基础库解析数据并传到后台
```go
// 1.解析列
excelImport := excel.NewExcelImport()
excelImport.RowBegin = 3 //第二行开始读取
excelImport.DataFields = []excel.DataField{
{EnName: "userCode", CnName: "*用户编码"},
{EnName: "userName", CnName: "*用户姓名"},
{EnName: "org", CnName: "*组织机构"},
{EnName: "department", CnName: "*所属部门"},
{EnName: "enableStatus", CnName: "*用户状态"},
{EnName: "phone", CnName: "*手机号"},
{EnName: "employeeType", CnName: "*员工类型"},
{EnName: "icCardNumber", CnName: "IC卡号"},
{EnName: "email", CnName: "邮箱"},
}
excelData, err := excelImport.OpenExcelFromIoReader(importDataCommand.Reader)
if err != nil {
return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
}
users := make([]allied_creation_user.BatchAddUserItem, 0)
for _, v := range excelData {
if srv.fieldValueAllEmpty(v) {
continue
}
item := allied_creation_user.BatchAddUserItem{
CompanyId: importDataCommand.Operator.CompanyId,
UserType: domain.UserTypeEmployee,
UserCode: strings.TrimSpace(v["userCode"]),
Org: strings.TrimSpace(v["org"]),
Department: strings.TrimSpace(v["department"]),
UserName: strings.TrimSpace(v["userName"]),
Phone: strings.TrimSpace(v["phone"]),
Email: strings.TrimSpace(v["email"]),
EnableStatus: strings.TrimSpace(v["enableStatus"]),
EmployeeType: strings.TrimSpace(v["employeeType"]),
IcCardNumber: strings.TrimSpace(v["icCardNumber"]),
}
users = append(users, item)
}
// 2.向后台服务发起批量添加请求
userGateway := allied_creation_user.NewHttplibAlliedCreationUser(importDataCommand.Operator)
result, err := userGateway.UserBatchAdd(allied_creation_user.ReqBatchAddUser{
Users: users,
Password: initPassword,
})
```
```go
```
### 2.2 Excel导出流程
- 功能原型说明
实现可以自定义选择列进行导出,以及选择导出格式,导出格式有 ``xlsx``\\``csv``,功能如下图所示:
![](https://timeless-world.oss-cn-shenzhen.aliyuncs.com/opportunity/dev_online/20220225/object/1645789890_JbTa22EtANsD3fm2nJ4aH6FJkHzXaHJB.png)
- 前后端交互说明
``接口定义``
导出接口
```shell
POST /v1/web/file-export
// request 请求参数
{
// 业务编码
"code":"string"
// 选择的导出的列
"fields":[]
// 导出文件格式
"format":"xlsx"
// 业务查询条件
"where":{}
}
```
导出列查询接口
```shell
GET/v1/web/file-export/fields/:code
// response 应答数据
{
"fields":[
{
"enName":"字段键名",
"cnName":"字段展示名称",
"selected":true // 默认勾选
}
]
}
```
- 交互流程
1.前台根据 ``导出列查询接口`` 获取可以导出的列;
2.勾选需要导出的列、文件格式,调用 ``导出接口`` 向后台发起导出数据请求;
#### 2.2.1 后端导出实现
1. 导出数据实现接口
```
type ExcelMaker interface {
DataFieldList() []DataField //字段元数据列表
CellValue(index int, enName string) (value interface{}) //获取单元格字段值
DataListLen() int //数据列表大小
TableTitle() []string //列表顶部自定义内容
}
```
如下所示
```go
//ExportCooperationUserData 导出共创用户数据
type ExportCooperationUserData struct {
SourceData []allied_creation_user.UserDetail //具体数据
SelectedField []string
}
var _ excel.ExcelMaker = (*ExportCooperationUserData)(nil)
func (data ExportCooperationUserData) AllFields() []DataFieldOptions {
return []DataFieldOptions{
{EnName: "UserCode", CnName: "用户编码"},
{EnName: "UserName", CnName: "用户姓名"},
{EnName: "Phone", CnName: "手机号"},
{EnName: "CooperationCompany", CnName: "共创公司"},
{EnName: "CooperationDeadline", CnName: "共创到期"},
{EnName: "EnableStatus", CnName: "状态"},
}
}
func (data ExportCooperationUserData) DataFieldList() []excel.DataField {
fields := []excel.DataField{}
allFields := data.AllFields()
for _, value2 := range allFields {
if len(data.SelectedField) == 0 || value2.IsDefault {
fields = append(fields, excel.DataField{EnName: value2.EnName, CnName: value2.CnName})
continue
}
for _, value3 := range data.SelectedField {
if value2.EnName == value3 {
fields = append(fields, excel.DataField{EnName: value2.EnName, CnName: value2.CnName})
}
}
}
return fields
}
func (data ExportCooperationUserData) CellValue(index int, enName string) (value interface{}) {
if index > data.DataListLen() {
return ""
}
switch enName {
case "UserCode":
return data.SourceData[index].UserCode
case "UserName":
return data.SourceData[index].UserInfo.UserName
case "CooperationCompany":
return data.SourceData[index].CooperationInfo.CooperationCompany
case "CooperationDeadline":
if data.SourceData[index].CooperationInfo.CooperationDeadline.IsZero() || data.SourceData[index].CooperationInfo.CooperationDeadline.Unix() == 0 {
return ""
}
return data.SourceData[index].CooperationInfo.CooperationDeadline.Format("2006-01-02")
case "Phone":
return data.SourceData[index].UserInfo.Phone
case "Email":
return data.SourceData[index].UserInfo.Email
case "EnableStatus":
status := data.SourceData[index].EnableStatus
statusName := ""
// 状态(1:启用 2:禁用 3:注销)
switch status {
case 1:
statusName = "启用"
case 2:
statusName = "禁用"
case 3:
statusName = "注销"
}
return statusName
}
return nil
}
func (data ExportCooperationUserData) DataListLen() int {
return len(data.SourceData)
}
func (data ExportCooperationUserData) TableTitle() []string {
return nil
}
```
2. 返回文件
```go
//返回文件
excelTool := excel.NewExcelExport()
err = excelTool.ExportData(data, "")
controller.responseExcelByFile(controller.Ctx, excelTool, filename)
func (controller *ExcelDataController) responseExcelByFile(ctx *context.Context, excelExport *excel.ExcelExport, fileName string) error {
ctx.Output.Header("Content-Disposition", "attachment; filename="+fileName)
ctx.Output.Header("Content-Description", "File Transfer")
ctx.Output.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
ctx.Output.Header("Content-Transfer-Encoding", "binary")
ctx.Output.Header("Expires", "0")
ctx.Output.Header("Cache-Control", "must-revalidate")
ctx.Output.Header("Pragma", "public")
//跳过保存文件,直接写入ctx.ResponseWriter
excelExport.ExcelFile.Write(ctx.ResponseWriter)
return nil
}
```
... ...
... ... @@ -22,6 +22,7 @@ require (
github.com/onsi/ginkgo v1.15.2
github.com/onsi/gomega v1.11.0
github.com/sergi/go-diff v1.2.0 // indirect
github.com/shopspring/decimal v1.2.0
github.com/smartystreets/goconvey v1.7.2 // indirect
github.com/stretchr/testify v1.7.0
github.com/tidwall/gjson v1.13.0
... ... @@ -31,7 +32,6 @@ require (
github.com/yudai/gojsondiff v1.0.0 // indirect
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
github.com/yudai/pp v2.0.1+incompatible // indirect
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1
golang.org/x/text v0.3.6
)
... ...
... ... @@ -339,6 +339,8 @@ github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKzU3qCuvj/tPnimWSsZZzvk9qvkvrIL5naVBPh5s=
... ...
... ... @@ -2,6 +2,7 @@ package main
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/port/mqtt"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/port/task"
"github.com/beego/beego/v2/server/web"
... ... @@ -9,7 +10,6 @@ import (
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/constant"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/redis"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/port/mqtt"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/crontab"
_ "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/constant"
... ...
... ... @@ -2,6 +2,8 @@ package dto
import (
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
"time"
)
type AttendanceRecordDto struct {
... ... @@ -15,7 +17,10 @@ type AttendanceRecordDto struct {
AttendanceType int `json:"attendanceType,omitempty"`
// 生产工人
ProductWorker *domain.User `json:"productWorker,omitempty"`
*domain.ProductAttendanceRecordExt
// 审核人
ApproveUser *domain.User `json:"approveUser"`
//*domain.ProductAttendanceRecordExt
ApproveAt string `json:"approveAt"`
// 工作位置
*domain.WorkStation
// 签到
... ... @@ -42,19 +47,32 @@ func (d *AttendanceRecordDto) LoadDto(m *domain.ProductAttendanceRecord, orgId i
d.ProductWorker = m.ProductWorker
d.WorkStation = m.WorkStation
if !m.SignIn.IsZero() {
d.SignIn = m.SignIn.Format("15:04:05")
d.SignDate = m.SignIn.Format("2006-01-02")
d.SignIn = m.SignIn.Local().Format("15:04:05")
d.SignDate = m.SignIn.Local().Format("2006-01-02")
}
if !m.SignOut.IsZero() {
d.SignOut = m.SignOut.Format("15:04:05")
d.SignOut = m.SignOut.Local().Format("15:04:05")
}
d.WorkTimeBefore = m.WorkTimeBefore
d.WorkTimeBefore = utils.Round(m.WorkTimeBefore, 1)
d.WorkTimeAfter = m.WorkTimeAfter
d.AttendanceStatus = m.AttendanceStatus
d.AuthFlag = domain.CheckOrgAuth(orgId, m.OrgId)
if m.Ext != nil {
d.OrgName = m.Ext.OrgName
d.ProductAttendanceRecordExt = m.Ext.AttendanceExt
//d.ProductAttendanceRecordExt = m.Ext.AttendanceExt
//if
if m.Ext.AttendanceExt != nil {
if m.Ext.AttendanceExt.ApproveUserId > 0 {
d.ApproveUser = &domain.User{
UserId: m.Ext.AttendanceExt.ApproveUserId,
UserName: m.Ext.AttendanceExt.ApproveUserName,
}
}
if m.Ext.AttendanceExt.ApproveAt > 0 {
t := time.Unix(m.Ext.AttendanceExt.ApproveAt, 0)
d.ApproveAt = t.Local().Format("2006-01-02 15:04:05")
}
}
}
return d
}
... ...
... ... @@ -2,6 +2,7 @@ package dto
import (
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
)
type EmployeeAttendanceRecordDto struct {
... ... @@ -39,9 +40,9 @@ func (d *EmployeeAttendanceRecordDto) LoadDto(m *domain.ProductAttendanceRecord,
d.WorkStation = m.WorkStation
if !m.SignIn.IsZero() {
//d.SignIn = m.SignIn.Format("15:04:05")
d.SignDate = m.SignIn.Format("2006-01-02")
d.SignDate = m.SignIn.Local().Format("2006-01-02")
}
d.WorkTime = m.WorkTimeAfter
d.WorkTime = utils.Round(m.WorkTimeAfter, 1)
//d.WorkTimeAfter = m.WorkTimeAfter
d.AttendanceStatus = m.AttendanceStatus
d.AttendanceTypeDescription = domain.ParticipateTypeDescription(m.AttendanceType)
... ...
... ... @@ -2,6 +2,7 @@ package dto
import (
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
)
type WorkshopWorkTimeRecordDto struct {
... ... @@ -24,9 +25,14 @@ type WorkshopWorkTimeRecordDto struct {
func (d *WorkshopWorkTimeRecordDto) LoadDto(m *domain.WorkshopWorkTimeRecord, orgId int) *WorkshopWorkTimeRecordDto {
d.WorkshopWorkTimeRecordId = m.WorkshopWorkTimeRecordId
d.WorkStation = m.WorkStation
d.WorkshopWorkTimeRecordInfo = m.WorkshopWorkTimeRecordInfo
if m.WorkshopWorkTimeRecordInfo != nil {
d.WorkshopWorkTimeRecordInfo = &domain.WorkshopWorkTimeRecordInfo{}
d.WorkshopWorkTimeRecordInfo.EPTWorkTime = utils.Round(m.WorkshopWorkTimeRecordInfo.EPTWorkTime, 1)
d.WorkshopWorkTimeRecordInfo.EDWorkTime = utils.Round(m.WorkshopWorkTimeRecordInfo.EDWorkTime, 1)
d.WorkshopWorkTimeRecordInfo.EFTWorkTime = utils.Round(m.WorkshopWorkTimeRecordInfo.EFTWorkTime, 1)
}
d.WorkStation = m.WorkStation
d.RecordDate = m.RecordDate.Format("2006-01-02")
d.RecordDate = m.RecordDate.Local().Format("2006-01-02")
d.AuthFlag = domain.CheckOrgAuth(orgId, m.OrgId)
if m.Ext != nil {
d.OrgName = m.Ext.OrgName
... ...
... ... @@ -34,8 +34,10 @@ type SearchEmployeeAttendanceQuery struct {
SectionName string `cname:"工段名称" json:"sectionName,omitempty"`
// 姓名
UserName string `cname:"姓名" json:"userName,omitempty"`
// 考勤状态 1.未审核 2:已审核 4.自动审核
AttendanceStatus int `cname:"考勤状态 1.未审核 2:已审核 4.自动审核" json:"attendanceStatus,omitempty"`
// 考勤状态 1.未审核 2:已审核 3.自动审核
AttendanceStatus int `cname:"考勤状态 1.未审核 2:已审核 3.自动审核" json:"attendanceStatus,omitempty"`
// 员工类型 1:固定 2:派遣 3.临时
EmployeeType int `cname:"1:固定 2:派遣 3.临时" json:"employeeType,omitempty"`
// 开始时间
BeginTime string `cname:"开始时间" json:"beginTime"`
// 结束时间
... ...
... ... @@ -30,7 +30,7 @@ func (attendanceService *AttendanceService) WorkerAttendanceReport(cmd *command.
// return nil, err
//}
attendanceReportService, _ := domainService.NewPGWorkerAttendanceReportService(transactionContext.(*pgTransaction.TransactionContext))
if _, err := attendanceReportService.Report(constant.MANUFACTURE_DEFAULT_COMPANYID, constant.MANUFACTURE_DEFAULT_COMPANYID, cmd.DeviceZkTeco); err != nil {
if _, err := attendanceReportService.Report(constant.MANUFACTURE_DEFAULT_COMPANYID, constant.MANUFACTURE_DEFAULT_ORGID, cmd.DeviceZkTeco); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
if err := transactionContext.CommitTransaction(); err != nil {
... ...
... ... @@ -18,20 +18,20 @@ func NewCrontabService(options map[string]interface{}) *CrontabService {
}
func (crontabService *CrontabService) initTask() {
//拉取物料数据 晚上0时10分执行
pullMaterialK3cloud := task.NewTask("pullMaterialK3cloud", "0 10 0 * * *", func(ctx context.Context) error {
//拉取物料数据 每5分执行
pullMaterialK3cloud := task.NewTask("pullMaterialK3cloud", "0 */5 0 * * *", func(ctx context.Context) error {
srv := syncdata.PullDataK3CloudService{}
return srv.PullMaterialNewest()
})
task.AddTask("pullMaterialK3cloud", pullMaterialK3cloud)
//拉取物料分组数据 晚上0时10分执行
pullMaterialGroupK3cloud := task.NewTask("pullMaterialGroupK3cloud", "0 10 0 * * *", func(ctx context.Context) error {
//拉取物料分组数据 每5分执行
pullMaterialGroupK3cloud := task.NewTask("pullMaterialGroupK3cloud", "0 */5 0 * * *", func(ctx context.Context) error {
srv := syncdata.PullDataK3CloudService{}
return srv.PullMaterialGroup()
})
task.AddTask("pullMaterialGroupK3cloud", pullMaterialGroupK3cloud)
//拉取订生产订单数据 晚上0时10分执行
PullPrdMoK3cloud := task.NewTask("PullPrdMoK3cloud", "0 10 0 * * *", func(ctx context.Context) error {
//拉取订生产订单数据 每5分执行
PullPrdMoK3cloud := task.NewTask("PullPrdMoK3cloud", "0 */5 0 * * *", func(ctx context.Context) error {
srv := syncdata.PullDataK3CloudService{}
return srv.PullPrdMoNewest()
})
... ... @@ -42,6 +42,12 @@ func (crontabService *CrontabService) initTask() {
autoApproveRecord := task.NewTask("autoApproveRecord", "0 */2 * * * *", AutoApproveProductRecord)
task.AddTask("autoApproveRecord", autoApproveRecord)
autoFlushDeviceDailyRunningRecord := task.NewTask("autoFlushDeviceDailyRunningRecord", "0 */1 * * * *", AutoFlushDeviceDailyRunningRecord)
task.AddTask("autoFlushDeviceDailyRunningRecord", autoFlushDeviceDailyRunningRecord)
autoWorkshopPlanCompletionRecord := task.NewTask("autoFlushDeviceDailyRunningRecord", "0 1 1-10/3 * * *", AutoWorkshopPlanCompletionRecord)
task.AddTask("autoWorkshopPlanCompletionRecord", autoWorkshopPlanCompletionRecord)
}
func (crontabService *CrontabService) StartCrontabTask() {
... ...
package crontab
import (
"context"
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/factory"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/redis"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log"
"time"
)
// 定时刷新设备每日运行记录
func AutoFlushDeviceDailyRunningRecord(ctx context.Context) error {
defer func() {
if r := recover(); r != nil {
log.Logger.Error(fmt.Sprintf("%v", r))
}
}()
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("【定时刷新设备每日运行记录】 启动")
deviceDailyRunningRecordRepository, _, _ := factory.FastPgDeviceDailyRunningRecord(transactionContext, 0)
// 获取redis里当天的记录
span := time.Duration(20)
t := time.Now().Add(-time.Minute * span)
records, err := redis.GetDeviceDailyAllRecord(t)
if err != nil {
log.Logger.Error(err.Error())
return err
}
for _, v := range records {
if v.UpdatedAt.Add(time.Minute * 5).Before(time.Now()) {
log.Logger.Debug(fmt.Sprintf("【定时刷新设备每日运行记录】 跳过记录 %v 最后更新时间:%v", v, v.UpdatedAt))
continue
}
// 更新设备效率 OEE = tu * pu * qu
if _, err := deviceDailyRunningRecordRepository.Save(v); err != nil {
log.Logger.Error(err.Error())
continue
} else {
log.Logger.Debug(fmt.Sprintf("【定时刷新设备每日运行记录】 刷新记录 %v", v))
}
}
if err = transactionContext.CommitTransaction(); err != nil {
return err
}
return nil
}
... ...
package crontab
import (
"context"
"fmt"
pgTransaction "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/infrastructure/domainService"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log"
"time"
)
// 定时刷新车间计划完成纪录
func AutoWorkshopPlanCompletionRecord(ctx context.Context) error {
defer func() {
if r := recover(); r != nil {
log.Logger.Error(fmt.Sprintf("%v", r))
}
}()
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("【定时刷新设备每日运行记录】 启动")
end := utils.GetZeroTime(time.Now())
begin := utils.GetZeroTime(end.Add(-time.Second))
approveAttendanceRecordsService, _ := domainService.NewPGWorkshopPlanCompletionRecordService(transactionContext.(*pgTransaction.TransactionContext))
if err = approveAttendanceRecordsService.WorkshopPlanCompletion(begin, end); err != nil {
return err
}
if err = transactionContext.CommitTransaction(); err != nil {
return err
}
return nil
}
... ...
... ... @@ -26,7 +26,7 @@ type UpdateDeviceCommand struct {
// 工段ID
SectionId int `cname:"工段ID" json:"sectionId"`
// 品牌
Brand string `cname:"品牌" json:"brand" valid:"Required"`
Brand string `cname:"品牌" json:"brand"`
// 设备状态 1:正常 2:封存 3:报废
DeviceStatus int `cname:"设备状态 1:正常 2:封存 3:报废" json:"deviceStatus" valid:"Required"`
// 风险等级 1:高 2:中 3:低
... ...
package dto
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
)
... ... @@ -24,7 +25,7 @@ type DeviceDto struct {
// 所属位置
*domain.WorkStation
// 生产单个产品的时间(单位:秒)
UnitProductionSecTime int `json:"unitProductionSecTime"`
UnitProductionSecTime string `json:"unitProductionSecTime"`
// 组织名称
OrgName string `json:"orgName"`
... ... @@ -47,7 +48,9 @@ func (d *DeviceDto) LoadDto(m *domain.Device, orgId int) *DeviceDto {
d.OrgName = m.Ext.OrgName
}
if m.Ext != nil && m.Ext.DeviceExt != nil {
d.UnitProductionSecTime = m.Ext.DeviceExt.UnitProductionSecTime
if m.Ext.DeviceExt.UnitProductionSecTime > 0 {
d.UnitProductionSecTime = fmt.Sprintf("%v", m.Ext.DeviceExt.UnitProductionSecTime)
}
}
return d
}
... ...
... ... @@ -350,7 +350,9 @@ func (deviceService *DeviceService) SearchDevice(operateInfo *domain.OperateInfo
for i := range devices {
item := devices[i]
newJobDto := &dto.DeviceDto{}
newJobDto.WorkStation = workshops.FindWorkStation(item.WorkStation.WorkshopId, item.WorkStation.LineId, item.WorkStation.SectionId)
if item.WorkStation != nil && item.WorkStation.WorkshopId > 0 {
newJobDto.WorkStation = workshops.FindWorkStationOrNil(item.WorkStation.WorkshopId, item.WorkStation.LineId, item.WorkStation.SectionId)
}
newJobDto.LoadDto(item, operateInfo.OrgId)
result = append(result, newJobDto)
}
... ...
... ... @@ -387,6 +387,32 @@ func FastPgWorkshopWorkTimeRecord(transactionContext application.TransactionCont
return rep, mod, err
}
// FastPgDeviceDailyRunningRecord 快速返回设备每日运行记录
//
// transactionContext 事务
// id 对象唯一标识
func FastPgDeviceDailyRunningRecord(transactionContext application.TransactionContext, id int, options ...option) (domain.DeviceDailyRunningRecordRepository, *domain.DeviceDailyRunningRecord, error) {
var rep domain.DeviceDailyRunningRecordRepository
var mod *domain.DeviceDailyRunningRecord
var err error
if value, err := CreateDeviceDailyRunningRecordRepository(map[string]interface{}{
"transactionContext": transactionContext,
}); err != nil {
return nil, nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
} else {
rep = value
}
if id > 0 {
if mod, err = rep.FindOne(map[string]interface{}{"deviceDailyRunningRecordId": id}); err != nil {
if err == domain.ErrorNotFound {
return nil, nil, application.ThrowError(application.RES_NO_FIND_ERROR, "该记录不存在")
}
return nil, nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
}
return rep, mod, err
}
/***** 2.配置 *****/
type FastOptions struct {
... ...
... ... @@ -125,3 +125,19 @@ func CreateDeviceCollectionRepository(options map[string]interface{}) (domain.De
}
return repository.NewDeviceCollectionRepository(transactionContext)
}
func CreateDeviceRunningRecordRepository(options map[string]interface{}) (domain.DeviceRunningRecordRepository, error) {
var transactionContext *pg.TransactionContext
if value, ok := options["transactionContext"]; ok {
transactionContext = value.(*pg.TransactionContext)
}
return repository.NewDeviceRunningRecordRepository(transactionContext)
}
func CreateDeviceDailyRunningRecordRepository(options map[string]interface{}) (domain.DeviceDailyRunningRecordRepository, error) {
var transactionContext *pg.TransactionContext
if value, ok := options["transactionContext"]; ok {
transactionContext = value.(*pg.TransactionContext)
}
return repository.NewDeviceDailyRunningRecordRepository(transactionContext)
}
... ...
... ... @@ -25,7 +25,7 @@ type CreateProductGroupCommand struct {
// 班组长Id
GroupLeaderId int `cname:"班组长" json:"groupLeaderId,omitempty"`
// 帮组成员列表
GroupMembers []int `cname:"帮组成员列表" json:"groupMembers" valid:"Required"`
GroupMembers []int `cname:"帮组成员列表" json:"groupMembers"`
// 上班班次 1:全天 2:白班 4:中班 8:夜班
WorkOn int `cname:"上班班次 1:全天 2:白班 4:中班 8:夜班" json:"workOn" valid:"Required"`
}
... ...
... ... @@ -22,7 +22,7 @@ type UpdateProductGroupCommand struct {
// 班组长Id
GroupLeaderId int `cname:"班组长" json:"groupLeaderId,omitempty"`
// 帮组成员列表
GroupMembers []int `cname:"帮组成员列表" json:"groupMembers" valid:"Required"`
GroupMembers []int `cname:"帮组成员列表" json:"groupMembers"`
// 上班班次 1:全天 2:白班 4:中班 8:夜班
WorkOn int `cname:"上班班次 1:全天 2:白班 4:中班 8:夜班" json:"workOn" valid:"Required"`
}
... ...
... ... @@ -16,9 +16,9 @@ type ProductGroupDto struct {
// 班组名称
GroupName string `json:"groupName,omitempty"`
// 班组长
GroupLeader string `json:"groupLeader,omitempty"`
GroupLeader string `json:"groupLeader"`
// 帮组成员列表
GroupMembers string `json:"groupMembers,omitempty"`
GroupMembers string `json:"groupMembers"`
// 上班班次 1:全天 2:白班 4:中班 8:夜班
WorkOn int `json:"workOn,omitempty"`
// 工作位置
... ... @@ -32,7 +32,9 @@ type ProductGroupDto struct {
func (d *ProductGroupDto) LoadDto(m *domain.ProductGroup, orgId int) *ProductGroupDto {
d.ProductGroupId = m.ProductGroupId
d.GroupName = m.GroupName
d.GroupLeader = m.GroupLeader.UserName
if m.GroupLeader != nil {
d.GroupLeader = m.GroupLeader.UserName
}
var members []string
for i := range m.GroupMembers {
members = append(members, m.GroupMembers[i].UserName)
... ...
... ... @@ -71,6 +71,31 @@ func (d *ProductGroupEmployeesDtos) LoadDto(groups ...*domain.ProductGroup) {
}
}
func (d *ProductGroupEmployeesDtos) LoadDtoV2(list []*domain.ProductAttendanceRecord, mapGroupUser map[string]*domain.User, keyFunc func(int) string) {
var mapUser = make(map[int]int)
for _, v := range list {
item := &ProductGroupEmployeesDto{}
item.UserId = v.ProductWorker.UserId
item.UserName = v.ProductWorker.UserName
item.ProductGroupId = 0
item.GroupName = ""
if v, ok := mapGroupUser[keyFunc(item.UserId)]; ok {
item.GroupName = v.GroupName
item.ProductGroupId = v.GroupId
item.WorkOnDescription = domain.WorkOnDescriptions(v.WorkOn)
}
if len(item.UserName) > 0 {
item.UserNamePinyin = converter.ToPinYin(item.UserName, "")
}
if _, ok := mapUser[item.UserId]; ok {
continue
} else {
mapUser[item.UserId] = item.UserId
}
d.Append(item)
}
}
func NewProductGroupEmployeesDtos() *ProductGroupEmployeesDtos {
return &ProductGroupEmployeesDtos{
Result: make([]*ProductGroupEmployeesDto, 0),
... ...
package query
import (
"fmt"
"github.com/beego/beego/v2/core/validation"
"reflect"
"strings"
)
type GetSignInEmployeeQuery struct {
// 查询偏离量
//Offset int `cname:"查询偏离量" json:"offset"`
// 查询限制
//Limit int `cname:"查询限制" json:"limit"`
// 页码
//PageNumber int `cname:"页码" json:"pageNumber,omitempty"`
// 页数
//PageSize int `cname:"页数" json:"pageSize,omitempty"`
// 当前公司
CompanyId int `cname:"当前公司" json:"companyId,omitempty" valid:"Required"`
// 当前登录的组织
OrgId int `cname:"当前登录的组织" json:"orgId,omitempty"`
// IC卡号
IcCardNumber string `cname:"IC卡号" json:"icCardNumber,omitempty"`
}
func (listProductGroupQuery *GetSignInEmployeeQuery) Valid(validation *validation.Validation) {
//validation.SetError("CustomValid", "未实现的自定义认证")
}
func (listProductGroupQuery *GetSignInEmployeeQuery) ValidateQuery() error {
valid := validation.Validation{}
b, err := valid.Valid(listProductGroupQuery)
if err != nil {
return err
}
if !b {
elem := reflect.TypeOf(listProductGroupQuery).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
}
... ...
... ... @@ -45,15 +45,19 @@ func (productGroupService *ProductGroupService) CreateProductGroup(operateInfo *
}
var leader *domain.User
var members []*domain.User
var members = make([]*domain.User, 0)
userService := domainService.NewUserService()
leader, err = userService.User(cmd.GroupLeaderId)
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
if cmd.GroupLeaderId > 0 {
leader, err = userService.User(cmd.GroupLeaderId)
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
}
members, err = userService.Users(cmd.GroupMembers)
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
if len(cmd.GroupMembers) > 0 {
members, err = userService.Users(cmd.GroupMembers)
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
}
var org *domain.Org
... ... @@ -130,6 +134,9 @@ func (productGroupService *ProductGroupService) GetProductGroup(getProductGroupQ
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
//if productGroup.GroupLeader==nil{
// productGroup.GroupLeader = &domain.User{}
//}
return productGroup, nil
}
... ... @@ -292,15 +299,19 @@ func (productGroupService *ProductGroupService) UpdateProductGroup(cmd *command.
}
var leader *domain.User
var members []*domain.User
var members = make([]*domain.User, 0)
userService := domainService.NewUserService()
leader, err = userService.User(cmd.GroupLeaderId)
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
if cmd.GroupLeaderId > 0 {
leader, err = userService.User(cmd.GroupLeaderId)
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
}
members, err = userService.Users(cmd.GroupMembers)
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
if len(cmd.GroupMembers) > 0 {
members, err = userService.Users(cmd.GroupMembers)
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
}
productGroup.GroupLeader = leader
productGroup.GroupMembers = members
... ... @@ -384,9 +395,7 @@ func (productGroupService *ProductGroupService) SearchProductGroupEmployees(oper
transactionContext.RollbackTransaction()
}()
//workshops, _ := factory.FastPgWorkshops(transactionContext, operateInfo.CompanyId)
queryOptions := utils.ObjectToMap(cmd)
//queryOptions = workshops.FindByNameWithQuery(queryOptions, cmd.WorkshopName, cmd.LineName, "")
var productGroupRepository domain.ProductGroupRepository
productGroupRepository, _, _ = factory.FastPgProductGroup(transactionContext, 0)
... ... @@ -411,6 +420,86 @@ func (productGroupService *ProductGroupService) SearchProductGroupEmployees(oper
}, nil
}
// 返回在当前工段上打卡的所有用户
func (productGroupService *ProductGroupService) SearchProductGroupEmployeesV2(operateInfo *domain.OperateInfo, cmd *query.SearchProductGroupEmployeesQuery) (int64, interface{}, error) {
if err := cmd.ValidateQuery(); err != nil {
return 0, nil, application.ThrowError(application.ARG_ERROR, err.Error())
}
transactionContext, err := factory.CreateTransactionContext(nil)
if err != nil {
return 0, nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
if err := transactionContext.StartTransaction(); err != nil {
return 0, nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
defer func() {
transactionContext.RollbackTransaction()
}()
queryOptions := utils.ObjectToMap(cmd)
queryOptions["signBeginTime"] = utils.GetZeroTime(time.Now())
var attendanceRecordRepository domain.ProductAttendanceRecordRepository
attendanceRecordRepository, _, _ = factory.FastPgAttendance(transactionContext, 0)
_, productGroups, err := attendanceRecordRepository.Find(queryOptions)
if err != nil {
return 0, nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
productGroupRepository, _, _ := factory.FastPgProductGroup(transactionContext, 0)
mapUser, keyFunc := domainService.FindGroupMembers(productGroupRepository, cmd.CompanyId, cmd.OrgId, domain.WorkstationKey(cmd.WorkshopId, cmd.LineId, cmd.SectionId))
var results = dto.NewProductGroupEmployeesDtos()
results.LoadDtoV2(productGroups, mapUser, keyFunc)
sort.Stable(results)
if err := transactionContext.CommitTransaction(); err != nil {
return 0, nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return int64(len(results.Result)), map[string]interface{}{
"employees": results.Result,
}, nil
}
// 返回生产班组服务列表
func (productGroupService *ProductGroupService) GetSignEmployee(cmd *query.GetSignInEmployeeQuery) (interface{}, error) {
if err := cmd.ValidateQuery(); err != nil {
return nil, application.ThrowError(application.ARG_ERROR, err.Error())
}
transactionContext, err := factory.CreateTransactionContext(nil)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
if err := transactionContext.StartTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
defer func() {
transactionContext.RollbackTransaction()
}()
var userService = domainService.NewUserService()
worker, err := userService.UserByICCode(cmd.CompanyId, cmd.OrgId, cmd.IcCardNumber)
if err != nil || worker == nil || worker.UserId == 0 {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "用户不存在")
}
result := map[string]interface{}{
"userId": worker.UserId,
"userName": worker.UserName,
}
productGroupRepository, _, _ := factory.FastPgProductGroup(transactionContext, 0)
mapUser, keyFunc := domainService.FindGroupMembers(productGroupRepository, cmd.CompanyId, cmd.OrgId, "")
if v, ok := mapUser[keyFunc(worker.UserId)]; ok {
result["productGroupId"] = v.GroupId
result["groupName"] = v.GroupName
result["workOn"] = domain.WorkOnDescriptions(v.WorkOn)
}
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return map[string]interface{}{
"employee": result,
}, nil
}
func NewProductGroupService(options map[string]interface{}) *ProductGroupService {
newProductGroupService := &ProductGroupService{}
return newProductGroupService
... ...
... ... @@ -338,8 +338,8 @@ func (productJobService *ProductJobService) SearchProductJob(operateInfo *domain
newJobDto := &dto.ProductJobDto{}
newJobDto.LoadDto(item, operateInfo.OrgId)
newJobDto.WorkStation = workshops.FindWorkStation(item.WorkStation.WorkshopId, item.WorkStation.LineId, item.WorkStation.SectionId)
newJobDto.WorkStation.Principal = item.WorkStation.Principal
newJobDto.WorkStation = workshops.FindWorkStation(item.WorkStation.WorkshopId, item.WorkStation.LineId, item.WorkStation.SectionId, 1)
//newJobDto.WorkStation.Principal = item.WorkStation.Principal
result = append(result, newJobDto)
}
return count, result, nil
... ...
... ... @@ -42,9 +42,11 @@ type CreateProductPlanCommand struct {
func (createProductPlanCommand *CreateProductPlanCommand) Valid(validation *validation.Validation) {
//validation.SetError("CustomValid", "未实现的自定义认证")
if err := domain.ValidWorkOn(createProductPlanCommand.WorkOn); err != nil {
validation.Error(err.Error())
return
if createProductPlanCommand.WorkOn > 0 {
if err := domain.ValidWorkOn(createProductPlanCommand.WorkOn); err != nil {
validation.Error(err.Error())
return
}
}
if t, err := time.Parse("2006-01-02", createProductPlanCommand.ProductDate); err != nil {
validation.Error("时间格式有误" + createProductPlanCommand.ProductDate)
... ...
... ... @@ -22,7 +22,7 @@ type ReceiveMaterialCommand struct {
// 工段ID
SectionId int `cname:"工段" json:"sectionId" valid:"Required"`
// 生产小组ID
ProductGroupId int `cname:"生产小组" json:"productGroupId" valid:"Required"`
ProductGroupId int `cname:"生产小组" json:"productGroupId"`
// 员工Id 用户唯一标识
EmployeeId int `cname:"员工" json:"employeeId" valid:"Required"`
// 物料ID
... ...
... ... @@ -22,7 +22,7 @@ type ReturnMaterialCommand struct {
// 工段ID
SectionId int `cname:"工段" json:"sectionId" valid:"Required"`
// 生产小组ID
ProductGroupId int `cname:"生产小组" json:"productGroupId" valid:"Required"`
ProductGroupId int `cname:"生产小组" json:"productGroupId"`
// 员工Id 用户唯一标识
EmployeeId int `cname:"员工" json:"employeeId" valid:"Required"`
// 物料ID
... ...
... ... @@ -12,7 +12,7 @@ type SetOnlineCommand struct {
// 生产计划ID
ProductPlanId int `cname:"生产计划ID" json:"productPlanId" valid:"Required"`
// 车间ID
WorkshopId int `cname:"车间ID" json:"workshopId" valid:"Required"`
WorkshopId int `cname:"车间ID" json:"workshopId" `
// 生产线ID
LineId int `cname:"生产线ID" json:"lineId" valid:"Required"`
// 工段ID
... ...
... ... @@ -22,11 +22,11 @@ type SubmitProductRecordCommand struct {
// 工段ID
SectionId int `cname:"工段" json:"sectionId" valid:"Required"`
// 生产小组ID
ProductGroupId int `cname:"生产小组" json:"productGroupId" valid:"Required"`
ProductGroupId int `cname:"生产小组" json:"productGroupId"`
// 员工Id 用户唯一标识
EmployeeId int `cname:"员工" json:"employeeId" valid:"Required"`
// 物料ID
UnitConversionId int `cname:"物料ID" json:"unitConversionId" valid:"Required"`
UnitConversionId int `cname:"物料ID" json:"unitConversionId"`
// 重量
Weigh float64 `cname:"重量" json:"weigh" valid:"Required"`
}
... ...
... ... @@ -9,10 +9,10 @@ import (
)
type SwitchCommand struct {
// 下线计划调度ID
FromProductPlanDispatchRecordId int `cname:"下线计划ID" json:"fromProductPlanId,omitempty"`
// 上线计划ID
ToProductPlanId int `cname:"上线计划ID" json:"toProductPlanId,omitempty"`
// 已上线计划ID
FromProductPlanDispatchRecordId int `cname:"已上线计划ID" json:"productPlanDispatchRecordId,omitempty" valid:"Required"`
// 计划ID
ToProductPlanId int `cname:"计划ID" json:"productPlanId,omitempty" valid:"Required"`
}
func (switchCommand *SwitchCommand) Valid(validation *validation.Validation) {
... ...
... ... @@ -47,9 +47,11 @@ type UpdateProductPlanCommand struct {
}
func (updateProductPlanCommand *UpdateProductPlanCommand) Valid(validation *validation.Validation) {
if err := domain.ValidWorkOn(updateProductPlanCommand.WorkOn); err != nil {
validation.Error(err.Error())
return
if updateProductPlanCommand.WorkOn > 0 {
if err := domain.ValidWorkOn(updateProductPlanCommand.WorkOn); err != nil {
validation.Error(err.Error())
return
}
}
if t, err := time.Parse("2006-01-02", updateProductPlanCommand.ProductDate); err != nil {
validation.Error("时间格式有误")
... ...
... ... @@ -7,7 +7,7 @@ import (
type ProductPlanDispatchRecordDto struct {
// 生产计划ID
ProductPlanId int `json:"productPlanId,omitempty"`
ProductPlanId int `json:"productPlanDispatchRecordId,omitempty"`
// 批号
BatchNumber string `json:"batchNumber,omitempty"`
// 生产日期
... ... @@ -42,7 +42,7 @@ type ProductPlanDispatchRecordDto struct {
func (d *ProductPlanDispatchRecordDto) LoadDto(m *domain.ProductPlanDispatchRecord, orgId int) *ProductPlanDispatchRecordDto {
d.ProductPlanId = m.ProductPlanDispatchRecordId
d.BatchNumber = m.BatchNumber
d.ProductDate = m.ProductDate.Format("2006/01/02")
d.ProductDate = m.ProductDate.Local().Format("2006-01-02")
d.WorkStation = m.WorkStation
d.WorkOn = m.PlanDispatchRecordExt.WorkOn
d.PlanProductName = m.PlanDispatchRecordExt.PlanProductName
... ...
... ... @@ -28,6 +28,8 @@ type SearchProductPlanQuery struct {
BatchNumber string `cname:"批号" json:"batchNumber"`
// 车间名称
WorkshopName string `cname:"车间名称" json:"workshopName"`
// 车间ID
WorkshopId int `cname:"车间ID" json:"workshopId"`
}
func (cmd *SearchProductPlanQuery) Valid(validation *validation.Validation) {
... ...
... ... @@ -395,6 +395,7 @@ func (productPlanService *ProductPlanService) SetOnline(cmd *command.SetOnlineCo
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
cmd.WorkshopId = productPlan.Workshop.WorkshopId
var workStation *domain.WorkStation
_, workStation, err = factory.FastPgWorkstation(transactionContext, cmd.WorkshopId, cmd.LineId, cmd.SectionId)
if err != nil {
... ... @@ -575,7 +576,9 @@ func (productPlanService *ProductPlanService) SearchProductPlanOnlineDispatchRec
} else {
productPlanRepository = value
}
count, productPlans, err := productPlanRepository.Find(utils.ObjectToMap(cmd))
queryOptions := utils.ObjectToMap(cmd)
queryOptions["planDispatchStatus"] = 1
count, productPlans, err := productPlanRepository.Find(queryOptions)
if err != nil {
return 0, nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
... ...
... ... @@ -16,7 +16,7 @@ type ApproveProductRecordCommand struct {
// 审核后重量
WeighAfter float64 `cname:"审核后重量" json:"weighAfter" valid:"Required"`
// 审核时间
ApproveAt string `cname:"审核时间" json:"approveAt" valid:"Required"`
//ApproveAt string `cname:"审核时间" json:"approveAt" valid:"Required"`
}
func (approveProductRecordCommand *ApproveProductRecordCommand) Valid(validation *validation.Validation) {
... ...
... ... @@ -8,6 +8,8 @@ type EmployeeProductRecordDto struct {
// 生产工人
ProductWorker *domain.User `json:"productWorker,omitempty"`
*domain.WorkStation
// 上班班次 1:全天 2:白班 4:中班 8:夜班
WorkOn int `json:"workOn"`
// 生产日期
//ProductDate string `json:"productDate"`
// 计划的产品名称
... ... @@ -29,15 +31,19 @@ type EmployeeProductRecordDto struct {
// 合格率 百分比
QualificationRate int `json:"qualificationRate"`
// 考勤类型 1.正常 2.支援
ParticipateTypeDescription string `json:"participateTypeDescription,omitempty"`
ParticipateTypeDescription string `json:"participateTypeDescription"`
// 员工类型描述 1:固定 2:派遣 3.临时
EmployeeTypeDescription string `json:"employeeTypeDescription,omitempty"`
EmployeeTypeDescription string `json:"employeeTypeDescription"`
// 上班班次 1:全天 2:白班 4:中班 8:夜班
WorkOnDescription string `json:"workOnDescription,omitempty"`
}
func (d *EmployeeProductRecordDto) LoadDto(m *domain.EmployeeProductRecord, orgId int) *EmployeeProductRecordDto {
d.EmployeeProductRecordId = m.EmployeeProductRecordId
d.ProductWorker = m.ProductWorker
d.WorkStation = m.WorkStation
d.WorkOn = m.WorkOn
d.PlanProductName = m.ProductRecordInfo.PlanProductName
d.BatchNumber = m.ProductRecordInfo.BatchNumber
d.ParticipateType = m.ParticipateType
... ... @@ -47,6 +53,7 @@ func (d *EmployeeProductRecordDto) LoadDto(m *domain.EmployeeProductRecord, orgI
d.CreatedAt = m.CreatedAt.Format("2006-01-02")
d.ParticipateTypeDescription = domain.ParticipateTypeDescription(m.ParticipateType)
d.EmployeeTypeDescription = domain.EmployeeTypeDescription(m.ProductWorker.EmployeeType)
d.WorkOnDescription = domain.WorkOnDescriptions(m.WorkOn)
d.AuthFlag = domain.CheckOrgAuth(orgId, m.OrgId)
if m.Ext != nil {
d.OrgName = m.Ext.OrgName
... ...
... ... @@ -15,11 +15,13 @@ type ProductLevelTwoRecord struct {
// 上班班次 1:全天 2:白班 4:中班 8:夜班
WorkOn int `json:"workOn"`
// 产能 - 审核前
WeighBefore float64 `json:"weighBefore"`
WeighBefore float64 `json:"weightBefore"`
// 产能-审核后
WeighAfter float64 `json:"weighAfter"`
WeighAfter float64 `json:"weightAfter"`
// 审核状态 1:未审核 2:已审核
ApproveStatus int `json:"approveStatus"`
// 审核人
ApproveUser *domain.User `json:"approveUser"`
// 审核时间
ApproveAt string `json:"approveAt"`
// 计划的产品名称
... ... @@ -45,12 +47,13 @@ func (d *ProductLevelTwoRecord) LoadDto(m *domain.ProductRecord, orgId int) *Pro
d.WeighAfter = m.ProductRecordInfo.WeighAfter
d.ApproveStatus = m.ProductRecordInfo.ApproveStatus
if m.ProductRecordInfo.ApproveAt > 0 {
d.ApproveAt = time.Unix(m.ProductRecordInfo.ApproveAt, 0).Format("2006-01-02 15:04:05")
d.ApproveAt = time.Unix(m.ProductRecordInfo.ApproveAt, 0).Local().Format("2006-01-02 15:04:05")
d.ApproveUser = m.ProductRecordInfo.ApproveUser
}
d.PlanProductName = m.ProductRecordInfo.PlanProductName
d.BatchNumber = m.ProductRecordInfo.BatchNumber
d.CreatedDate = m.CreatedAt.Format("2006-01-02")
d.CreatedAt = m.CreatedAt.Format("2006-01-02 15:04:05")
d.CreatedDate = m.CreatedAt.Local().Format("2006-01-02")
d.CreatedAt = m.CreatedAt.Local().Format("2006-01-02 15:04:05")
d.AuthFlag = domain.CheckOrgAuth(orgId, m.OrgId)
if m.Ext != nil {
d.OrgName = m.Ext.OrgName
... ...
package query
import (
"fmt"
"reflect"
"strings"
"github.com/beego/beego/v2/core/validation"
)
type CommonStatisticsQuery struct {
Action string `cname:"查询类别" json:"actionType" valid:"Required"`
QueryOptions map[string]interface{} `json:"queryOptions"`
}
func (checkUndertakerQuery *CommonStatisticsQuery) Valid(validation *validation.Validation) {
//validation.SetError("CustomValid", "未实现的自定义认证")
}
func (checkUndertakerQuery *CommonStatisticsQuery) ValidateQuery() error {
valid := validation.Validation{}
b, err := valid.Valid(checkUndertakerQuery)
if err != nil {
return err
}
if !b {
elem := reflect.TypeOf(checkUndertakerQuery).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
}
... ...
package service
import (
"github.com/linmadan/egglib-go/core/application"
"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/statistics/query"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/domainService"
)
// CommonStatisticsService 通用的统计服务
type CommonStatisticsService struct {
}
// CommonStatisticsService 通用的统计服务
func (svr *CommonStatisticsService) CommonStatisticsService(cmd *query.CommonStatisticsQuery) (interface{}, error) {
if err := cmd.ValidateQuery(); err != nil {
return nil, application.ThrowError(application.ARG_ERROR, err.Error())
}
var err error
transactionContext, err := factory.CreateTransactionContext(nil)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
if err := transactionContext.StartTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
defer func() {
_ = transactionContext.RollbackTransaction()
}()
statisticsService, _ := domainService.NewPGCommonStatisticsService(transactionContext.(*pg.TransactionContext))
response, err := statisticsService.CommonStatistics(cmd.Action, cmd.QueryOptions)
if err != nil {
return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
}
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return response, nil
}
func NewCommonStatisticsService(options map[string]interface{}) *CommonStatisticsService {
newProductSectionService := &CommonStatisticsService{}
return newProductSectionService
}
... ...
package command
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"reflect"
"strings"
"github.com/beego/beego/v2/core/validation"
)
type WorkshopDataConsumeCommand struct {
*domain.DeviceCollection
// 企业id
CompanyId int `cname:"企业id" json:"companyId" valid:"Required"`
// 组织ID
OrgId int `cname:"组织ID" json:"orgId" valid:"Required"`
}
func (updateWorkshopCommand *WorkshopDataConsumeCommand) Valid(validation *validation.Validation) {
}
func (updateWorkshopCommand *WorkshopDataConsumeCommand) ValidateCommand() error {
valid := validation.Validation{}
b, err := valid.Valid(updateWorkshopCommand)
if err != nil {
return err
}
if !b {
elem := reflect.TypeOf(updateWorkshopCommand).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
}
... ...
... ... @@ -98,6 +98,13 @@ func (workshopService *WorkshopService) GetWorkshop(getWorkshopQuery *query.GetW
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
userService := domainService.NewUserService()
if workshop.Principal.UserId > 0 {
u, _ := userService.User(workshop.Principal.UserId)
if u != nil {
workshop.Principal = u
}
}
if workshop == nil {
return nil, application.ThrowError(application.RES_NO_FIND_ERROR, fmt.Sprintf("%s", string(getWorkshopQuery.WorkshopId)))
} else {
... ...
package service
import (
"github.com/linmadan/egglib-go/core/application"
"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/workshop/command"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/domainService"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log"
)
func (workshopService *WorkshopService) WorkshopConsume(cmd *command.WorkshopDataConsumeCommand) (interface{}, error) {
if err := cmd.ValidateCommand(); err != nil {
return nil, application.ThrowError(application.ARG_ERROR, err.Error())
}
transactionContext, err := factory.CreateTransactionContext(nil)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
if err := transactionContext.StartTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
defer func() {
transactionContext.RollbackTransaction()
}()
consumeService, _ := domainService.NewPGWorkshopDataConsumeService(transactionContext.(*pg.TransactionContext))
if _, err := consumeService.Consume(cmd.CompanyId, cmd.OrgId, cmd.DeviceCollection); err != nil {
log.Logger.Error(err.Error())
return nil, err
}
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return struct{}{}, nil
}
... ...
... ... @@ -3,6 +3,7 @@ package constant
import "os"
var MQTT_TOPIC = "/MQTT"
//设备商提供的测试地址
//var MQTT_HOST = "175.24.122.87"
//var MQTT_PORT = "1883"
... ... @@ -14,13 +15,23 @@ var MQTT_TOPIC = "/MQTT"
//var MQTT_USER = "admin"
//var MQTT_PASSWORD = "123456"
var MQTT_HOST = "192.168.31.51"
//var MQTT_HOST = "192.168.31.51"
//var MQTT_PORT = "1883"
//var MQTT_USER = ""
//var MQTT_PASSWORD = ""
var MQTT_HOST = "175.24.122.87"
var MQTT_PORT = "1883"
var MQTT_USER = ""
var MQTT_PASSWORD = ""
var MQTT_USER = "user111"
var MQTT_PASSWORD = "user111"
//内网测试地址
//var MQTT_HOST = "192.168.100.222"
//var MQTT_PORT = "1883"
//var MQTT_USER = "admin"
//var MQTT_PASSWORD = "123456"
func init(){
func init() {
if os.Getenv("MQTT_HOST") != "" {
MQTT_HOST = os.Getenv("MQTT_HOST")
}
... ... @@ -33,4 +44,4 @@ func init(){
if os.Getenv("MQTT_PASSWORD") != "" {
MQTT_PASSWORD = os.Getenv("MQTT_PASSWORD")
}
}
\ No newline at end of file
}
... ...
... ... @@ -127,6 +127,16 @@ func (device *Device) Valid() error {
return nil
}
// 标记为生产设备
func (device *Device) MarkAsProductDevice() bool {
if device.Ext.DeviceExt.IsProductDevice == 1 {
return false
}
device.Ext.DeviceExt.IsProductDevice = 1
device.UpdatedAt = time.Now()
return true
}
// 导入设备数据体
type ImportDeviceItem struct {
// 设备编号
... ... @@ -183,3 +193,13 @@ func (item *ImportDeviceItem) Valid() error {
}
return nil
}
type Devices []*Device
func (devices Devices) ToMap() map[string]*Device {
var resp = make(map[string]*Device)
for _, v := range devices {
resp[v.DeviceCode] = v
}
return resp
}
... ...
package domain
import "time"
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/constant"
"time"
)
// 设备采集数据
type DeviceCollection struct {
... ... @@ -79,3 +83,7 @@ func (deviceCollection *DeviceCollection) Update(data map[string]interface{}) er
}
return nil
}
func TaskDeviceCollection() string {
return fmt.Sprintf("%v:task:device-collection:report", constant.CACHE_PREFIX)
}
... ...
... ... @@ -2,49 +2,49 @@ package domain
// 包馅机
type DeviceBaoXianJi struct {
InterSpeed int64 `json:"InterSpeed"` // 内包材速度:内包材运行速率
ExterSpeed int64 `json:"ExterSpeed"` // 外包材速度:内包材运行速率
KnifeSpeed int64 `json:"KnifeSpeed"` // 切刀速度:切刀运行速率
TransSpeed int64 `json:"TransSpeed"` // 输送速度:输送带运行速率
Count int64 `json:"Count"` // 生产计数:生产统计数量
InterSpeed int64 `json:"InterSpeed"` // 内包材速度:内包材运行速率
ExterSpeed int64 `json:"ExterSpeed"` // 外包材速度:内包材运行速率
KnifeSpeed int64 `json:"KnifeSpeed"` // 切刀速度:切刀运行速率
TransSpeed int64 `json:"TransSpeed"` // 输送速度:输送带运行速率
Count int64 `json:"Count"` // 生产计数:生产统计数量
}
// 油炸机
type DeviceYouZhaJi struct {
FrontTemp float64 `json:"FontTemp"` // 炸机前段温度:炸机前段当前温度
BackTemp float64 `json:"BackTemp"` // 炸机后段温度:炸机后段当前温度
TankTemp float64 `json:"TankTemp"` // 储油罐温度 :储油罐当前温度
TubeTemp float64 `json:"TubeTemp"` // 管路温度:管路当前温度
FrontTemp float64 `json:"FontTemp"` // 炸机前段温度:炸机前段当前温度
BackTemp float64 `json:"BackTemp"` // 炸机后段温度:炸机后段当前温度
TankTemp float64 `json:"TankTemp"` // 储油罐温度 :储油罐当前温度
TubeTemp float64 `json:"TubeTemp"` // 管路温度:管路当前温度
}
// 串串机
type DeviceChuanChuanJi struct {
Count int64 `json:"Count"` // 生产计数:生产统计数量
Year string `json:"Year"` // 年
Month string `json:"Month"` // 月
Day string `json:"Day"` // 日
ProductType string `json:"ProductType"` // 产品类型:当前产品种类
Count int64 `json:"Count"` // 生产计数:生产统计数量
Year string `json:"Year"` // 年
Month string `json:"Month"` // 月
Day string `json:"Day"` // 日
ProductType string `json:"ProductType"` // 产品类型:当前产品种类
}
// 速冻线
type DeviceSuDongXian struct {
CurrTemp float64 `json:"CurrTemp"` // 当前温度:当前温度
CurrTemp float64 `json:"CurrTemp"` // 当前温度:当前温度
}
// 封口机
type DeviceFengKouJi struct {
Count int64 `json:"Count"` // 生产计数:生产统计数量
Year string `json:"Year"` // 年
Month string `json:"Month"` // 月
Day string `json:"Day"` // 日
ProductType string `json:"ProductType"` // 产品类型:当前产品种类
Count int64 `json:"Count"` // 生产计数:生产统计数量
Year string `json:"Year"` // 年
Month string `json:"Month"` // 月
Day string `json:"Day"` // 日
ProductType string `json:"ProductType"` // 产品类型:当前产品种类
}
// 封箱机
type DeviceFengXiangJi struct {
Count int64 `json:"Count"` // 生产计数:生产统计数量
Year string `json:"Year"` // 年
Month string `json:"Month"` // 月
Day string `json:"Day"` // 日
ProductType string `json:"ProductType"` // 产品类型:当前产品种类
}
\ No newline at end of file
Count int64 `json:"Count"` // 生产计数:生产统计数量
Year string `json:"Year"` // 年
Month string `json:"Month"` // 月
Day string `json:"Day"` // 日
ProductType string `json:"ProductType"` // 产品类型:当前产品种类
}
... ...
package domain
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
"time"
)
const DefaultTimeWindow = 1
// 设备每日运行记录(汇总)
type DeviceDailyRunningRecord struct {
// 设备每日运行记录ID
DeviceDailyRunningRecordId int `json:"deviceDailyRunningRecordId"`
// 企业id
CompanyId int `json:"companyId"`
// 组织ID
OrgId int `json:"orgId"`
// 工作位置
WorkStation *WorkStation `json:"workStation"`
// 设备Id
DeviceId int `json:"deviceId"`
// 设备编号
DeviceCode string `json:"deviceCode"`
// 生产日期
ProductDate time.Time `json:"productDate"`
// 设备运行记录信息
DeviceRunningRecordInfo *DeviceRunningRecordInfo `json:"deviceRunningRecordInfo"`
// 创建时间
CreatedAt time.Time `json:"createdAt"`
// 更新时间
UpdatedAt time.Time `json:"updatedAt"`
// 删除时间
DeletedAt time.Time `json:"deletedAt"`
}
type DeviceDailyRunningRecordRepository interface {
Save(deviceDailyRunningRecord *DeviceDailyRunningRecord) (*DeviceDailyRunningRecord, error)
Remove(deviceDailyRunningRecord *DeviceDailyRunningRecord) (*DeviceDailyRunningRecord, error)
FindOne(queryOptions map[string]interface{}) (*DeviceDailyRunningRecord, error)
Find(queryOptions map[string]interface{}) (int64, []*DeviceDailyRunningRecord, error)
}
func (deviceDailyRunningRecord *DeviceDailyRunningRecord) Identify() interface{} {
if deviceDailyRunningRecord.DeviceDailyRunningRecordId == 0 {
return nil
}
return deviceDailyRunningRecord.DeviceDailyRunningRecordId
}
func (deviceDailyRunningRecord *DeviceDailyRunningRecord) Update(data map[string]interface{}) error {
return nil
}
func (deviceDailyRunningRecord *DeviceDailyRunningRecord) AddDeviceRunningData(t time.Time, data *DeviceRunningData) {
deviceDailyRunningRecord.DeviceRunningRecordInfo.AddDeviceRunningData(t, data)
deviceDailyRunningRecord.UpdatedAt = time.Now()
}
func (deviceDailyRunningRecord *DeviceDailyRunningRecord) String() string {
return fmt.Sprintf("记录ID:%v 工段:%v 设备:%v",
deviceDailyRunningRecord.DeviceDailyRunningRecordId,
deviceDailyRunningRecord.WorkStation.SectionName,
deviceDailyRunningRecord.DeviceCode,
)
}
// 设备运行记录信息
type DeviceRunningRecordInfo struct {
// 当前状态
// bit0: 运行、停止
// bit1: 正常、故障
CurrentStatus int `json:"currentStatus"`
// 设备OEE = tu * pu * qu
OEE float64 `json:"oee"`
// 时间利用率 TimeUtilization 运行时间 / (当前时间-当日零时)
TimeUtilization float64 `json:"tu"`
// 性能利用率 PerformanceUtilization
// 1. 当前设备实际产出数量/理论数量(理论数量=60*60*12/标准工时)
// 2. 没有数量100%
PerformanceUtilization float64 `json:"pu"`
// 合格率 QualificationUtilization ?设备提交的二级品事串 、 机器上报的是kg
// 1.按工段的合格率
// 2.默认100%
QualificationUtilization float64 `json:"qu"`
// 运行时长 单位:分钟
UpTime float64 `json:"upTime"`
// 生成数量
Count int `json:"count"`
// 设备温度 单位:摄氏度
Temp float64 `json:"temp"`
// 时间点
//TimeLine []string `json:"timeLine"`
// 时间点对应的设备状态 按小时 1
TimeLineDeviceStatus map[string]*HourDeviceStatus `json:"timeLineDeviceStatus"`
// 批次数据
// 生产计划ID
ProductPlanId int `json:"productPlanId,omitempty"`
// 设备名称
DeviceName string `json:"deviceName"`
// 组织名称
OrgName string `json:"orgName"`
}
func NewDeviceRunningRecordInfo() *DeviceRunningRecordInfo {
return &DeviceRunningRecordInfo{
TimeLineDeviceStatus: make(map[string]*HourDeviceStatus),
}
}
func (d *DeviceRunningRecordInfo) AddDeviceRunningData(t time.Time, data *DeviceRunningData) {
d.CurrentStatus = data.StartupStatus | (1 << data.ComStatus)
d.ResetUpTime()
d.Count += data.Count
//d.Temp = data.FrontTemp
d.Temp = data.Temp1
d.AddTimeLineDeviceStatus(t, data)
//d.OEE
d.TimeUtilization = utils.Round(d.UpTime*100/(time.Now().Sub(utils.GetZeroTime(time.Now())).Minutes()), 2)
//d.PerformanceUtilization
//d.QualificationUtilization
}
// 添加新的设备状态
func (d *DeviceRunningRecordInfo) AddTimeLineDeviceStatus(t time.Time, data *DeviceRunningData) {
if t.IsZero() {
return
}
key := fmt.Sprintf("%v", t.Hour())
var v *HourDeviceStatus
var ok bool
if v, ok = d.TimeLineDeviceStatus[key]; !ok {
v = NewHourDeviceStatus()
d.TimeLineDeviceStatus[key] = v
}
v.UpdateUp(t, data.StartupStatus)
v.UpdateCom(t, data.ComStatus)
}
// 重置运行时长
func (d *DeviceRunningRecordInfo) ResetUpTime() float64 {
var upTime float64
for _, v := range d.TimeLineDeviceStatus {
t := v.CountTime(v.Up)
upTime += t.Minutes()
}
d.UpTime = upTime
return upTime
}
// 重置设备运行OEE
func (d *DeviceRunningRecordInfo) ResetOEE(pu, qu float64) float64 {
d.PerformanceUtilization = pu
d.QualificationUtilization = qu
d.OEE = (d.TimeUtilization + d.PerformanceUtilization + d.QualificationUtilization) / 3
return d.OEE
}
// 详细的小时设备数据
// 0:00 1
// 0:59 2
// 23:00 1
// 23:59 2
// [{"min":1,"time":"00:01","status":1}]
func (d *DeviceRunningRecordInfo) HourDeviceStatusDetail(endTime int) map[string]interface{} {
on := make([][]int, 0)
off := make([][]int, 0)
err := make([][]int, 0)
var begin, end int = 0, 0
/*
1.故障: 1 0 \ 0 0
2.正常: 1 1
3.停机:0 1
*/
var status = 1
// 添加数据
addToStatus := func(s []int, status int) {
switch status {
case 1:
err = append(err, s)
break
case 2:
on = append(on, s)
break
case 3:
off = append(off, s)
break
}
}
// 计算当前状态
computeStatus := func(up, com int, index int) int {
var val = 0
if up&index > 0 {
val |= 1
}
if com&index > 0 {
val |= 2
}
if val == 1 || val == 0 {
return 1 //故障
}
if val == 3 {
return 2 //正常
}
if val == 2 {
return 3 //停机
}
return 3 // 停机
}
for i := 0; i < 24; i++ {
var index = 1
var hds *HourDeviceStatus
var ok bool
if hds, ok = d.TimeLineDeviceStatus[fmt.Sprintf("%v", i)]; !ok {
hds = &HourDeviceStatus{Window: DefaultTimeWindow}
}
if i == 0 {
status = computeStatus(hds.Up, hds.Com, index) // 状态初始化
}
if end >= endTime {
break
}
if hds.Up == 0 && hds.Com == 0 {
end += 60 / hds.Window
continue
}
for j := 1; j < 60; j++ {
curStatus := computeStatus(hds.Up, hds.Com, index)
if curStatus == status {
end += 1
} else {
addToStatus([]int{begin, end}, status)
status = curStatus
begin = end + 1
end = begin
}
index = index << 1
}
}
addToStatus([]int{begin, end}, status)
return map[string]interface{}{
"on": on,
"off": off,
"err": err,
}
}
// 单个小时内的设备状态
type HourDeviceStatus struct {
// 时间窗口 1-60 代表时间段范围
// 例如: w=1 则标识下面的状态按1分钟记录一次状态
// up 启动 bit0-bit59的位用来存启动状态 1:启动 0:关闭
// com通讯 bit0-bit59的位用来存通讯状态 1:正常 0:故障
// 如果 w=5 表示按5分钟记录一次状态 使用到 bit0-bit11
Window int `json:"w"`
// 启动
// bit0:1 代表
Up int `json:"up"`
// 通讯
Com int `json:"com"`
}
// 更新启动状态
func (d *HourDeviceStatus) UpdateUp(t time.Time, up int) {
m := t.Minute()
bit := 1 << (m / d.Window)
if up&1 == 0 {
return
}
if d.Up&bit > 0 {
return
}
d.Up |= bit
return
}
// 更新通讯状态
func (d *HourDeviceStatus) UpdateCom(t time.Time, c int) {
m := t.Minute()
bit := 1 << (m / d.Window)
if c&1 == 0 {
return
}
if d.Com&bit > 0 {
return
}
d.Com |= bit
return
}
// 计算状态持续的时间
func (d *HourDeviceStatus) CountTime(v int) time.Duration {
l := 60 / d.Window
count := 0
index := 1
for i := 0; i < l; i++ {
if index > v {
break
}
if index&v > 0 {
count++
}
index <<= 1
}
return time.Duration(d.Window*count) * time.Minute
}
func NewHourDeviceStatus() *HourDeviceStatus {
return &HourDeviceStatus{
Window: DefaultTimeWindow,
Up: 0,
Com: 0,
}
}
... ...
... ... @@ -4,4 +4,6 @@ package domain
type DeviceExt struct {
// 生产单个产品的时间(单位:秒)
UnitProductionSecTime int `json:"unitProductionSecTime"`
// 是否是车间设备,如果这个设备有上报过数据,标记 1 默认0
IsProductDevice int `json:"isProductDevice"`
}
... ...
package domain
import "time"
// 设备运行数据
type DeviceRunningData struct {
// 数据采集ID
DeviceCollectionId int64 `json:"deviceCollectionId,string"`
// 车间名
WorkShopName string `json:"workShopName"`
// 采集时间
CollectionTime time.Time `json:"collectionTime"`
// 设备名
//DeviceSn string `json:"deviceSn"`
// 设备编号
DeviceCode string `json:"deviceCode"`
// 设备类型
DeviceType string `json:"deviceType"`
// 启动状态:1:启动,0:停止
StartupStatus int `json:"startupStatus"`
// 通讯状态:1:通讯正常,0:设备未上电或与采集端通讯故障
ComStatus int `json:"comStatus"`
// 附加数据
// 匹配数目
Count int `json:"count"`
// 炸机前段温度:炸机前段当前温度 YZJ1 油炸机
//FrontTemp float64 `json:"frontTemp"`
// 炸机前段温度:炸机前段当前温度 YZJ2 油炸机
Temp1 float64 `json:"temp1"`
// 当前产品种类(产品编号)
ProductType string `json:"productType"`
// 日期
Date string `json:"date"`
// 额外数据
// 单位数据 比如:1串/0.1kg weight = count * unitQuantity
UnitQuantity float64 `json:"unitQuantity"`
}
... ...
package domain
import "time"
// 设备运行记录
type DeviceRunningRecord struct {
// 设备运行记录ID
DeviceRunningRecordId int `json:"deviceRunningRecordId"`
// 企业id
CompanyId int `json:"companyId"`
// 组织ID
OrgId int `json:"orgId"`
// 工作位置
WorkStation *WorkStation `json:"workStation"`
// 设备Id
DeviceId int `json:"deviceId"`
// 设备编号
DeviceCode string `json:"deviceCode"`
// 设备运行记录信息
DeviceRunningRecordInfo *DeviceRunningData `json:"deviceRunningRecordInfo"`
// 创建时间
CreatedAt time.Time `json:"createdAt"`
}
type DeviceRunningRecordRepository interface {
Save(deviceRunningRecord *DeviceRunningRecord) (*DeviceRunningRecord, error)
Remove(deviceRunningRecord *DeviceRunningRecord) (*DeviceRunningRecord, error)
FindOne(queryOptions map[string]interface{}) (*DeviceRunningRecord, error)
Find(queryOptions map[string]interface{}) (int64, []*DeviceRunningRecord, error)
}
func (deviceRunningRecord *DeviceRunningRecord) Identify() interface{} {
if deviceRunningRecord.DeviceRunningRecordId == 0 {
return nil
}
return deviceRunningRecord.DeviceRunningRecordId
}
func (deviceRunningRecord *DeviceRunningRecord) Update(data map[string]interface{}) error {
return nil
}
... ...
package domain
import "fmt"
import (
"fmt"
"strings"
)
const MaxQueryRow = 10000
... ... @@ -121,6 +124,11 @@ func WorkOnDescription(workOn int) []string {
return result
}
func WorkOnDescriptions(workOn int) string {
r := WorkOnDescription(workOn)
return strings.Join(r, ",")
}
func EmployeeTypeDescription(employeeType int) string {
if employeeType == 1 {
return "固定"
... ...
... ... @@ -2,6 +2,7 @@ package domain
import (
"errors"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
"time"
)
... ... @@ -74,7 +75,7 @@ func (productAttendanceRecord *ProductAttendanceRecord) ComputeWorkTimeBefore()
if !productAttendanceRecord.SignOut.After(productAttendanceRecord.SignIn) {
return 0
}
return productAttendanceRecord.SignOut.Sub(productAttendanceRecord.SignIn).Hours()
return utils.Round(productAttendanceRecord.SignOut.Sub(productAttendanceRecord.SignIn).Hours(), 1)
}
func (productAttendanceRecord *ProductAttendanceRecord) Approve(approveUser *User, workTimeAfter float64, status int) error {
... ... @@ -83,7 +84,10 @@ func (productAttendanceRecord *ProductAttendanceRecord) Approve(approveUser *Use
}
productAttendanceRecord.AttendanceStatus = status
productAttendanceRecord.WorkTimeAfter = workTimeAfter
if productAttendanceRecord.Ext != nil && productAttendanceRecord.Ext.AttendanceExt != nil {
if productAttendanceRecord.Ext != nil {
if productAttendanceRecord.Ext.AttendanceExt == nil {
productAttendanceRecord.Ext.AttendanceExt = &ProductAttendanceRecordExt{}
}
productAttendanceRecord.Ext.AttendanceExt.ApproveUserId = approveUser.UserId
productAttendanceRecord.Ext.AttendanceExt.ApproveUserName = approveUser.UserName
productAttendanceRecord.Ext.AttendanceExt.ApproveAt = time.Now().Unix()
... ...
... ... @@ -39,6 +39,8 @@ type PlanDispatchRecordExt struct {
ProductPlanId int `json:"productPlanId,omitempty"`
// 计划的产品名称
PlanProductName string `json:"planProductName,omitempty"`
// 产品编号 编码规则为“CP”+2 位年+2 位月+2 位日+3 位流水码,如 CP211229001
ProductCode string `json:"productCode,omitempty"`
// 上班班次 1:全天 2:白班 4:中班 8:夜班
WorkOn int `json:"workOn,omitempty"`
// 机台 (A、B、C、D 区分机器大小)
... ... @@ -80,7 +82,7 @@ func (productPlanDispatchRecord *ProductPlanDispatchRecord) ChangeStatus(status
}
func NewProductPlanDispatchRecord(productPlan *ProductPlan, workStation *WorkStation) *ProductPlanDispatchRecord {
return &ProductPlanDispatchRecord{
record := &ProductPlanDispatchRecord{
CompanyId: productPlan.CompanyId,
OrgId: productPlan.OrgId,
BatchNumber: productPlan.BatchNumber,
... ... @@ -92,10 +94,16 @@ func NewProductPlanDispatchRecord(productPlan *ProductPlan, workStation *WorkSta
PlanDispatchRecordExt: &PlanDispatchRecordExt{
ProductPlanId: productPlan.ProductPlanId,
PlanProductName: productPlan.PlanProductName,
WorkOn: productPlan.WorkOn,
Machine: productPlan.Machine,
Remark: productPlan.Remark,
//ProductCode: productPlan.Ext.ProductPlanExt.ProductCode,
WorkOn: productPlan.WorkOn,
Machine: productPlan.Machine,
Remark: productPlan.Remark,
},
Ext: productPlan.Ext,
}
if productPlan.Ext != nil && productPlan.Ext.ProductPlanExt != nil {
record.PlanDispatchRecordExt.ProductCode = productPlan.Ext.ProductPlanExt.ProductCode
}
return record
}
... ...
... ... @@ -86,7 +86,10 @@ func (employeeProductRecord *EmployeeProductRecord) UpdateProductWeigh(weigh flo
if productRecordType == RecordTypeReturnMaterial {
employeeProductRecord.ProductWeigh -= weigh
}
employeeProductRecord.ProductRecordInfo.PreStatistics(employeeProductRecord.ProductWeigh, employeeProductRecord.SecondLevelWeigh, 0, 0)
if productRecordType == RecordTypeWeigh {
employeeProductRecord.ProductWeigh += weigh
}
employeeProductRecord.ProductRecordInfo.PreStatistics(employeeProductRecord.ProductWeigh, employeeProductRecord.SecondLevelWeigh, yesterdayWeight, bestWeight)
employeeProductRecord.UpdatedAt = time.Now()
employeeProductRecord.Version += 1
}
... ...
... ... @@ -4,8 +4,8 @@ package domain
type ProductRecordInfo struct {
// 生产日期
ProductDate string `json:"productDate"`
// 原始上报数据
OriginalWeigh float64 `json:"originalWeigh,omitempty"`
// 原始上报数据(kg,串)
Original float64 `json:"original,omitempty"`
// 换算后的产能
Weigh float64 `json:"weigh"`
// 产能 - 审核前
... ...
... ... @@ -58,8 +58,10 @@ func (info *ProductRecordStaticInfo) PreStatistics(productWeight float64, second
info.InputWeight = productWeight - totalOtherSecondLevelWeigh
info.OutputWeight = info.InputWeight - secondWeight
info.SecondLevelWeight = secondWeight
info.YesterdayOutputWeight = yesterdayWeight
info.BestOutputWeight = bestWeight
if info.YesterdayOutputWeight == 0 && info.BestOutputWeight == 0 {
info.YesterdayOutputWeight = yesterdayWeight
info.BestOutputWeight = bestWeight
}
if bestWeight <= info.InputWeight {
info.BestOutputWeight = info.OutputWeight
}
... ...
... ... @@ -68,6 +68,9 @@ func (employeeProductRecord *WorkshopProductRecord) UpdateProductWeigh(weigh flo
if productRecordType == RecordTypeReturnMaterial {
employeeProductRecord.ProductWeigh -= weigh
}
if productRecordType == RecordTypeWeigh {
employeeProductRecord.ProductWeigh += weigh
}
employeeProductRecord.ProductRecordInfo.PreStatistics(employeeProductRecord.ProductWeigh, employeeProductRecord.SecondLevelWeigh, 0, 0)
employeeProductRecord.UpdatedAt = time.Now()
employeeProductRecord.Version += 1
... ...
... ... @@ -9,9 +9,9 @@ const (
// 用户对象
type User struct {
// 用户Id 用户唯一标识
UserId int `json:"userId,omitempty"`
UserId int `json:"userId"`
// 用户姓名
UserName string `json:"userName,omitempty"`
UserName string `json:"userName"`
// 员工类型 1:固定 2:派遣 3.临时
EmployeeType int `json:"employeeType,omitempty"`
// IC卡号
... ... @@ -24,4 +24,5 @@ type User struct {
// 额外扩展的参数
GroupId int `json:"-"`
GroupName string `json:"-"`
WorkOn int `json:"-"`
}
... ...
... ... @@ -23,14 +23,33 @@ type WorkStation struct {
}
func NewWorkStation(w *Workshop, l *ProductLine, s *ProductSection) *WorkStation {
return &WorkStation{
WorkStationId: fmt.Sprintf("%v.%v.%v", w.WorkshopId, l.LineId, s.SectionId),
WorkshopId: w.WorkshopId,
WorkshopName: w.WorkshopName,
LineId: l.LineId,
LineName: l.LineName,
SectionId: s.SectionId,
SectionName: s.SectionName,
item := &WorkStation{
//WorkshopId: w.WorkshopId,
//WorkshopName: w.WorkshopName,
//LineId: l.LineId,
//LineName: l.LineName,
//SectionId: s.SectionId,
//SectionName: s.SectionName,
//Principal: w.Principal,
}
if w != nil && l != nil && s != nil {
item.WorkStationId = WorkstationKey(w.WorkshopId, l.LineId, s.SectionId)
}
if w != nil {
item.WorkshopId = w.WorkshopId
item.WorkshopName = w.WorkshopName
}
if l != nil {
item.LineId = l.LineId
item.LineName = l.LineName
}
if s != nil {
item.SectionId = s.SectionId
item.SectionName = s.SectionName
}
return item
}
func WorkstationKey(workshopId, lineId, sectionId int) string {
return fmt.Sprintf("%v.%v.%v", workshopId, lineId, sectionId)
}
... ...
... ... @@ -88,6 +88,10 @@ func (workshop *Workshop) RemoveLine(lineId int) (*ProductLine, error) {
if err != nil {
return nil, err
}
sections := line.GetProductSections(NotDeleted)
if len(sections) > 0 {
return nil, fmt.Errorf("生产线:%v下存在工段,不可删除", line.LineName)
}
if line.Removed == Deleted {
return nil, fmt.Errorf("生产线:%v已删除", line.LineName)
}
... ...
... ... @@ -5,10 +5,24 @@ import "strings"
/*车间列表*/
type Workshops []*Workshop
func (m Workshops) FindWorkStation(workshopId, lineId, sectionId int) *WorkStation {
func (m Workshops) FindWorkStation(workshopId, lineId, sectionId int, flag ...int) *WorkStation {
for i := range m {
item := m[i]
workstation, err := item.FindWorkStation(workshopId, lineId, sectionId)
if len(flag) > 0 && flag[0] == 1 && workstation != nil {
workstation.Principal = item.Principal
}
if err == nil && workstation != nil {
return workstation
}
}
return &WorkStation{} //返回空的对象
}
func (m Workshops) FindWorkStationOrNil(workshopId, lineId, sectionId int) *WorkStation {
for i := range m {
item := m[i]
workstation, err := item.FindWorkStationOrNil(workshopId, lineId, sectionId)
if err == nil && workstation != nil {
return workstation
}
... ...
... ... @@ -39,6 +39,16 @@ func (gateway HttpLibAlliedCreationUser) UserByCode(companyId, orgId int, userCo
}
return users[0], nil
}
func (gateway HttpLibAlliedCreationUser) UserByICCode(companyId, orgId int, icCode string) (*models.User, error) {
_, users, err := gateway.UserSearch(ReqUserSearch{CompanyId: int64(companyId), OrganizationId: int64(orgId), IcCardNumber: icCode, Limit: 1, PullRealTime: true})
if err != nil {
return nil, err
}
if len(users) == 0 {
return nil, fmt.Errorf("用户不存在")
}
return users[0], nil
}
func (gateway HttpLibAlliedCreationUser) Users(userIds []int) ([]*models.User, error) {
var list = make([]*models.User, 0)
for i := range userIds {
... ...
... ... @@ -42,6 +42,8 @@ type (
InCompanyIds []interface{} `json:"inCompanyIds,omitempty"`
// 用户编号 企业内标识
UserCode string `cname:"用户编号" json:"userCode,omitempty"`
// IC卡号
IcCardNumber string `cname:"IC卡号" json:"icCardNumber,omitempty"`
// 自定义高级查询
AdvancedQuery string `json:"advancedQuery"`
... ...
... ... @@ -2,6 +2,7 @@ package dao
import (
"fmt"
"github.com/go-pg/pg/v10/orm"
"github.com/linmadan/egglib-go/persistent/pg/sqlbuilder"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
... ... @@ -34,9 +35,15 @@ func (dao *AttendanceRecordDao) ProductWorkStationAttendanceRecord(companyId, or
query.Where("org_id = ?", orgId)
query.Where("work_station->>'workStationId' = ?", workStationId)
query.Where("sign_in <= ?", productTime)
query.Where("sign_out >= ?", productTime)
query.WhereGroup(func(q *orm.Query) (*orm.Query, error) {
query.WhereOr("sign_out >= ?", productTime)
query.WhereOr("sign_out=?", time.Time{})
return q, nil
})
query.DistinctOn("product_worker->>'userId',work_station->>'workStationId'")
query.SetOffsetAndLimit(domain.MaxQueryRow)
query.SetOrderDirect("product_attendance_id", "DESC")
query.OrderExpr("product_worker->>'userId' asc ,work_station->>'workStationId' asc")
if count, err := query.SelectAndCount(); err != nil {
return 0, productAttendanceRecords, err
} else {
... ... @@ -94,6 +101,9 @@ func (dao *AttendanceRecordDao) WorkerAttendanceRecords(companyId, orgId, worker
query.Where("sign_in >= ?", beginTime)
query.Where("sign_in <= ?", endTime)
query.Where("attendance_status = ?", domain.AttendanceNotApprove)
if len(workStationId) > 0 {
query.Where("work_station ->>'workStationId' = ?", workStationId)
}
query.SetOffsetAndLimit(domain.MaxQueryRow)
query.SetOrderDirect("product_attendance_id", "DESC")
if count, err := query.SelectAndCount(); err != nil {
... ...
package dao
import (
"fmt"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"time"
)
type DeviceDailyRunningRecordDao struct {
transactionContext *pgTransaction.TransactionContext
}
func NewDeviceDailyRunningRecordDao(transactionContext *pgTransaction.TransactionContext) (*DeviceDailyRunningRecordDao, error) {
if transactionContext == nil {
return nil, fmt.Errorf("transactionContext参数不能为nil")
} else {
return &DeviceDailyRunningRecordDao{
transactionContext: transactionContext,
}, nil
}
}
// 时段产能
func (dao *DeviceDailyRunningRecordDao) TimeSectionRunningRecord(companyId, orgId, workshopId int, lineId int, sectionName string, beginTime time.Time, result interface{}) error {
tx := dao.transactionContext.PgTx
sql := fmt.Sprintf(`
WITH ts_product as(
select sum(a.weight) total,a.ts from (
select
cast(device_running_record_info->>'count' as DECIMAL) weight,
to_char(product_date at time ZONE 'Asia/shanghai', 'mm-dd') ts
from manufacture.device_daily_running_record
where
company_id = ?
and org_id = ?
and work_station->>'workshopId'='?'
and work_station->>'lineId'='?'
and work_station->>'sectionName'=?
and created_at >?
) a
group by a.ts
order by ts
)
-- select * from ts_product
, ts_product_list as (
select d.ts,ts_product.total from (
select to_char(c.ts::timestamp,'mm-dd') ts from (
select generate_series(now() - interval '6 day',now(),'1 day') ts
) c ) d left join ts_product on d.ts = ts_product.ts
)
SELECT ts, coalesce(total,0) total
from ts_product_list
`)
if _, err := tx.Query(result, sql, companyId, orgId, workshopId, lineId, sectionName, beginTime); err != nil {
return err
}
return nil
}
func (dao *DeviceDailyRunningRecordDao) WorkshopProductionEfficiencyStatistics(companyId, orgId, workshopId int, beginTime time.Time, result interface{}) error {
tx := dao.transactionContext.PgTx
sql := fmt.Sprintf(`
with device_running as(
select
cast(device_running_record_info->>'oee' as DECIMAL) oee,
cast(device_running_record_info->>'tu' as DECIMAL) tu,
cast(device_running_record_info->>'pu' as DECIMAL) pu,
cast(device_running_record_info->>'qu' as DECIMAL) qu
from manufacture.device_daily_running_record
where
company_id = ?
and org_id = ?
and work_station->>'workshopId'='?'
and created_at>=?
)
select round(avg(oee),1) oee,round(avg(tu),1) tu,round(avg(pu),1)pu, round(avg(qu),1) qu from device_running
`)
if _, err := tx.Query(result, sql, companyId, orgId, workshopId, beginTime); err != nil {
return err
}
return nil
}
// 时段产能
func (dao *DeviceDailyRunningRecordDao) TimeSectionProductRecord(companyId, orgId, workshopId int, lineId int, sectionName string, beginTime time.Time, result interface{}) error {
tx := dao.transactionContext.PgTx
sql := fmt.Sprintf(`
WITH ts_product as(
select sum(a.weight) total,a.ts from (
select
cast(device_running_record_info->>'count' as DECIMAL) weight,
"replace"(to_char(created_at at time ZONE 'Asia/shanghai', 'HH24:') || cast(date_part('minute',created_at) as integer)/30*30, ':0', ':00') ts
from manufacture.device_running_record
where
company_id = ?
and org_id = ?
and work_station->>'workshopId'='?'
and work_station->>'lineId'='?'
and work_station->>'sectionName'=?
and device_running_record_info->>'deviceType'='CCJ'
and created_at >?
) a
group by a.ts
order by ts
)
-- select * from ts_product
, ts_product_list as (
select d.ts,ts_product.total from (
select to_char(c.ts::timestamp,'HH24:MI') ts from (
select generate_series(a.end - interval '5 hour',
"replace"(to_char(a.end, 'yyyy-mm-dd HH24:') || cast(date_part('minute',a.end) as integer)/30*30+30, ':0', ':00')::timestamp,
'30 minute') ts from (
select to_timestamp(to_char(now() at time ZONE 'Asia/shanghai','yyyy-mm-dd HH24'),'yyyy-mm-dd HH24') as end
) a
) c
) d left join ts_product on d.ts = ts_product.ts
)
SELECT ts, coalesce(total,0) total
from ts_product_list
`)
if _, err := tx.Query(result, sql, companyId, orgId, workshopId, lineId, sectionName, beginTime); err != nil {
return err
}
return nil
}
... ...
... ... @@ -58,7 +58,8 @@ func (dao *EmployeeProductRecordDao) WorkerBestOutputRecord(companyId, orgId, pl
query.Where("org_id = ?", orgId)
query.Where("product_worker ->>'userId' = '?'", workerId)
query.Where("product_record_info ->>'productPlanId' = '?'", planId)
query.Order("product_record_info ->>'outputWeight' DESC")
query.OrderExpr("product_record_info ->>'outputWeight' DESC")
query.Limit(1)
if err := query.First(); err != nil {
if err.Error() == "pg: no rows in result set" {
return nil, domain.ErrorNotFound
... ...
... ... @@ -2,10 +2,11 @@ package dao
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/constant"
"strconv"
"strings"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/constant"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/pg/models"
)
... ... @@ -115,7 +116,7 @@ func (d *MaterialK3cloudDao) SyncDataProudct(version int64, orgName string) erro
)
SELECT %v,%v,"join_product_id","number","name","material_group_name",
json_build_object('unit',specification),now(),now(),json_build_object('orgName','%v')
FROM "manufacture"."material_k3cloud" WHERE "data_version"=? AND "material_group_number" LIKE '05%%'
FROM "manufacture"."material_k3cloud" WHERE "data_version">=? AND "material_group_number" LIKE '05%%'
ON conflict ( product_id ) DO
UPDATE
SET (
... ...
package dao
import (
"fmt"
"github.com/linmadan/egglib-go/persistent/pg/sqlbuilder"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/pg/models"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/pg/transform"
"time"
)
type ProductPlanDispatchRecordDao struct {
transactionContext *pgTransaction.TransactionContext
}
func NewProductPlanDispatchRecord(transactionContext *pgTransaction.TransactionContext) (*ProductPlanDispatchRecordDao, error) {
if transactionContext == nil {
return nil, fmt.Errorf("transactionContext参数不能为nil")
} else {
return &ProductPlanDispatchRecordDao{
transactionContext: transactionContext,
}, nil
}
}
// 生产计划对应的批次
// 工段
// 日期
// 产品编号
// 调度状态 status
func (dao *ProductPlanDispatchRecordDao) DeviceProductPlan(companyId, orgId int, workStationId string, date time.Time, productCode string, status int) (*domain.ProductPlanDispatchRecord, error) {
tx := dao.transactionContext.PgTx
productPlanDispatchRecordModel := new(models.ProductPlanDispatchRecord)
query := sqlbuilder.BuildQuery(tx.Model(productPlanDispatchRecordModel), map[string]interface{}{})
query.Where("company_id = ?", companyId)
query.Where("org_id = ?", orgId)
query.Where("work_station->>'workStationId'=?", workStationId)
query.Where("product_date = ?", date)
query.Where("plan_dispatch_status = ?", status)
query.Where("plan_dispatch_record_ext->>'productCode'=?", productCode)
query.Order("updated_at desc")
if err := query.First(); err != nil {
if err.Error() == "pg: no rows in result set" {
return nil, domain.ErrorNotFound
} else {
return nil, err
}
}
if productPlanDispatchRecordModel.ProductPlanDispatchRecordId == 0 {
return nil, nil
} else {
return transform.TransformToProductPlanDispatchRecordDomainModelFromPgModels(productPlanDispatchRecordModel)
}
}
... ...
... ... @@ -124,15 +124,15 @@ func (d *PrdMoK3cloudDao) SyncDataProductPlan(version int64) error {
)
SELECT prd_mo_k3cloud."join_product_plan_id",prd_mo_k3cloud."bill_no",
prd_mo_k3cloud."plan_start_date",
json_build_object('workshopId',"workshop"."workshop_id",'workshopName',prd_mo_k3cloud."work_shop_name"),
json_build_object('workshopId',COALESCE("workshop"."workshop_id",0),'workshopName',prd_mo_k3cloud."work_shop_name"),
prd_mo_k3cloud."material_name", json_build_object('unit',prd_mo_k3cloud."unit_name",'quantity',prd_mo_k3cloud."qty"),
2,prd_mo_k3cloud."description",
json_build_object('productPlanExt',json_build_object('productId',prd_mo_k3cloud."join_product_plan_id",'productCode',prd_mo_k3cloud."material_number",'productName',prd_mo_k3cloud."material_name")),
now(),now()
FROM "manufacture"."prd_mo_k3cloud"
LEFT JOIN "material_k3cloud" ON "prd_mo_k3cloud"."material_number"="material_k3cloud"."number"
LEFT JOIN "workshop" ON "workshop"."workshop_name" = "prd_mo_k3cloud"."work_shop_name"
WHERE prd_mo_k3cloud."data_version"=?
LEFT JOIN "manufacture"."material_k3cloud" ON "prd_mo_k3cloud"."material_id"="material_k3cloud"."material_id"
LEFT JOIN "manufacture"."workshop" ON "workshop"."workshop_name" = "prd_mo_k3cloud"."work_shop_name"
WHERE prd_mo_k3cloud."data_version">=?
ON conflict ("product_plan_id") DO
UPDATE
SET (
... ...
... ... @@ -54,3 +54,82 @@ func (dao *ProductRecordDao) RecentUnApprovedProductRecord(fromLastHour int, rec
return int64(count), productAttendanceRecords, nil
}
}
// 时段产能
func (dao *ProductRecordDao) TimeSectionProductRecord(companyId, orgId, workshopId int, lineId int, sectionName string, beginTime time.Time, result interface{}) error {
tx := dao.transactionContext.PgTx
sql := fmt.Sprintf(`
WITH ts_product as(
select sum(a.weight) total,a.ts from (
select
cast(product_record_info->>'weigh' as DECIMAL) weight,
"replace"(to_char(created_at at time ZONE 'Asia/shanghai', 'HH24:') || cast(date_part('minute',created_at) as integer)/30*30, ':0', ':00') ts
from manufacture.product_records
where
company_id = ?
and org_id = ?
and work_station->>'workshopId'='?'
and work_station->>'lineId'='?'
and work_station->>'sectionName'=?
and product_record_type = 8
and created_at >?
) a
group by a.ts
order by ts
)
-- select * from ts_product
, ts_product_list as (
select d.ts,ts_product.total from (
select to_char(c.ts::timestamp,'HH24:MI') ts from (
select generate_series(a.end - interval '5 hour',
"replace"(to_char(a.end, 'yyyy-mm-dd HH24:') || cast(date_part('minute',a.end) as integer)/30*30+30, ':0', ':00')::timestamp,
'30 minute') ts from (
select to_timestamp(to_char(now() at time ZONE 'Asia/shanghai','yyyy-mm-dd HH24'),'yyyy-mm-dd HH24') as end
) a
) c
) d left join ts_product on d.ts = ts_product.ts
)
SELECT ts, coalesce(total,0) total
from ts_product_list
`)
if _, err := tx.Query(result, sql, companyId, orgId, workshopId, lineId, sectionName, beginTime); err != nil {
return err
}
return nil
}
// 二级品比重
func (dao *ProductRecordDao) ProportionOfSecondLevelRecord(companyId, orgId, workshopId int, beginTime time.Time, result interface{}) error {
tx := dao.transactionContext.PgTx
sql := fmt.Sprintf(`
with item_product as (
select sum(a.weight) item_total,max(sname) sname from (
select cast(product_record_info->>'weigh' as DECIMAL) weight
,work_station->>'sectionName' sname
,work_station->>'workStationId' workStationId
from manufacture.product_records
where company_id = ?
and org_id = ?
and work_station->>'workshopId'='?'
and product_record_type = 8
and product_record_info->>'approveStatus'='2'
and created_at >=?
and work_station->>'sectionName' in ('打料','成型','穿串','包装')
) a
group by a.workStationId
)
--select * from item_product
,item_product_rate as(
select sname,round(item_total/(select sum(item_total) from item_product)*100, 0) as rate from item_product
)
--select * from item_product_rate
select a.sname, coalesce(b.rate,0) rate from (
select unnest(ARRAY ['打料','成型','穿串','包装']) sname
) a left join item_product_rate b on a.sname=b.sname`)
if _, err := tx.Query(result, sql, companyId, orgId, workshopId, beginTime); err != nil {
return err
}
return nil
}
... ...
package dao
import (
"fmt"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/pg/models"
"time"
)
type WorkshopPlanCompletionRecordDao struct {
transactionContext *pgTransaction.TransactionContext
}
func (dao *WorkshopPlanCompletionRecordDao) Records(companyId, orgId int, workshopId int, begin, end time.Time, records interface{}) error {
tx := dao.transactionContext.PgTx
sql := fmt.Sprintf(`
with product_record as (
select
(case when product_record_type=1 then cast(product_record_info->>'weigh' as DECIMAL)
ELSE -(cast(product_record_info->>'weigh' as DECIMAL))
END) as weight,
cast(product_record_info->>'productPlanId' as INTEGER) plan_id
--,created_at
from manufacture.product_records
where company_id = ?
and org_id =?
and work_station->>'workshopId'='?'
and product_record_type in (1,2)
and created_at>=?
and created_at<?
), product_record_sum as(
select sum(weight) weight,plan_id from product_record
GROUP BY plan_id
)
select
plan_devoted->>'weight' plan_weight -- 计划重量
, coalesce(b.weight,0) real_weight --批次实际产能
,a.product_plan_id
from manufacture.product_plan a left join product_record_sum b on a.product_plan_id = b.plan_id
where company_id = ?
and org_id =?
and workshop->>'workshopId'='?'
and created_at >=?
and created_at<?
order by created_at desc`)
if _, err := tx.Query(records, sql,
companyId, orgId, workshopId, begin, end,
companyId, orgId, workshopId, begin, end); err != nil {
return err
}
return nil
}
func (dao *WorkshopPlanCompletionRecordDao) FindOne(companyId, orgId int, workshopId int, begin time.Time) (*models.WorkshopPlanCompletionRecord, error) {
tx := dao.transactionContext.PgTx
var record = new(models.WorkshopPlanCompletionRecord)
q := tx.Model(record)
q.Where("company_id=?", companyId)
q.Where("org_id=?", orgId)
q.Where("workshop_id=?", workshopId)
q.Where("created_at=?", begin)
err := q.First()
if err != nil {
if err.Error() == "pg: no rows in result set" {
return nil, domain.ErrorNotFound
} else {
return nil, err
}
}
return record, nil
}
func (dao *WorkshopPlanCompletionRecordDao) Save(record *models.WorkshopPlanCompletionRecord) error {
tx := dao.transactionContext.PgTx
if _, err := tx.Model(record).Insert(); err != nil {
return err
}
return nil
}
func NewWorkshopPlanCompletionRecordDao(transactionContext *pgTransaction.TransactionContext) (*WorkshopPlanCompletionRecordDao, error) {
if transactionContext == nil {
return nil, fmt.Errorf("transactionContext参数不能为nil")
} else {
return &WorkshopPlanCompletionRecordDao{
transactionContext: transactionContext,
}, nil
}
}
... ...
... ... @@ -32,7 +32,7 @@ func (dao *WorkshopProductRecordDao) WorkshopProductRecord(companyId, orgId, pla
query := sqlbuilder.BuildQuery(tx.Model(employeeProductRecordModel), map[string]interface{}{})
query.Where("company_id = ?", companyId)
query.Where("org_id = ?", orgId)
query.Where("product_date = ?", productTime.Format("2006-01-02"))
query.Where("product_date = ?", productTime.Local().Format("2006-01-02"))
query.Where("product_record_info ->>'productPlanId' = '?'", planId)
if err := query.First(); err != nil {
if err.Error() == "pg: no rows in result set" {
... ...
... ... @@ -27,6 +27,14 @@ func (svr *UserService) UserByCode(companyId, orgId int, userCode string) (*doma
return svr.ToUser(rsp), nil
}
func (svr *UserService) UserByICCode(companyId, orgId int, userCode string) (*domain.User, error) {
rsp, err := svr.internalUserService.UserByICCode(companyId, orgId, userCode)
if err != nil {
return nil, err
}
return svr.ToUser(rsp), nil
}
func (svr *UserService) Users(id []int) ([]*domain.User, error) {
rsp, err := svr.internalUserService.Users(id)
if err != nil {
... ...
package domainService
import (
"github.com/hibiken/asynq"
"github.com/linmadan/egglib-go/utils/json"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/constant"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
)
func SendWorkshopWorkTimeStaticJob(productRecord *domain.ProductAttendanceRecord) error {
return SendAsyncJob(domain.TaskKeyWorkshopWorkTimeRecordStatics(), productRecord)
}
func SendProductRecordStaticsJob(productRecord *domain.ProductRecord) error {
task := asynq.NewTask(domain.TaskKeyPatternProductRecordStatics(), []byte(json.MarshalToString(productRecord)))
client := asynq.NewClient(asynq.RedisClientOpt{Addr: constant.REDIS_ADDRESS})
_, err := client.Enqueue(task)
return err
}
func SendDeviceZkTecoReportJob(productRecord *domain.DeviceZkTeco) error {
return SendAsyncJob(domain.TaskDeviceZkTecoReport(), productRecord)
}
func SendWorkshopDeviceData(productRecord *domain.DeviceCollection) error {
return SendAsyncJob(domain.TaskDeviceCollection(), productRecord)
}
func SendAsyncJob(queueName string, job interface{}) error {
task := asynq.NewTask(queueName, []byte(json.MarshalToString(job)))
client := asynq.NewClient(asynq.RedisClientOpt{Addr: constant.REDIS_ADDRESS})
_, err := client.Enqueue(task)
return err
}
... ...
... ... @@ -17,7 +17,7 @@ func (ptr *PGApproveAttendanceRecordsService) BatchApproveAttendanceRecords(opt
var productAttendanceRecordRepository, _ = repository.NewProductAttendanceRecordRepository(ptr.transactionContext)
var attendance *domain.ProductAttendanceRecord
var err error
log.Logger.Info("【自动审核考勤记录任务】 启动")
log.Logger.Debug("【自动审核考勤记录任务】 启动")
var user *domain.User = &domain.User{}
userService := NewUserService()
if approveUserId > 0 {
... ...
package domainService
import (
"fmt"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/dao"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/repository"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log"
"time"
)
const (
// 时段产能统计
HourProductiveStatistics = "HourProductiveStatistics"
// 产能对比
DailyProductiveStatistics = "DailyProductiveStatistics"
// 二级品比重
ProportionOfSecondLevelStatistics = "ProportionOfSecondLevelStatistics"
// 车间生产效率
WorkshopProductionEfficiencyStatistics = "WorkshopProductionEfficiencyStatistics"
// 设备运行统计
DeviceRunningStatistics = "DeviceRunningStatistics"
)
const (
SectionNameCCJ = "穿串"
)
type PGCommonStatisticsService struct {
transactionContext *pgTransaction.TransactionContext
}
func (ptr *PGCommonStatisticsService) CommonStatistics(actionType string, queryOptions map[string]interface{}) (interface{}, error) {
var result interface{}
var err error
switch actionType {
case HourProductiveStatistics:
result, err = ptr.HourProductiveStatistics(queryOptions)
break
case DailyProductiveStatistics:
result, err = ptr.DailyProductiveStatistics(queryOptions)
break
case ProportionOfSecondLevelStatistics:
result, err = ptr.ProportionOfSecondLevelStatistics(queryOptions)
break
case WorkshopProductionEfficiencyStatistics:
result, err = ptr.WorkshopProductionEfficiencyStatistics(queryOptions)
break
case DeviceRunningStatistics:
result, err = ptr.DeviceRunningStatistics(queryOptions)
break
}
return result, err
}
// 时段产能-统计 (传串设备)
func (ptr *PGCommonStatisticsService) HourProductiveStatistics(queryOptions map[string]interface{}) (interface{}, error) {
var request = &HourProductiveStatisticsRequest{}
if err := utils.LoadQueryObject(queryOptions, request); err != nil {
return nil, err
}
workshopRepository, _ := repository.NewWorkshopRepository(ptr.transactionContext)
type record struct {
Ts string `json:"ts"`
Total float64 `json:"total"`
}
workshop, err := workshopRepository.FindOne(map[string]interface{}{"workshopId": request.WorkshopId})
if err != nil || workshop == nil {
return nil, nil
}
productRecordDao, _ := dao.NewDeviceDailyRunningRecordDao(ptr.transactionContext)
var response = make([]interface{}, 0)
var tmpXData = make([]string, 0)
for _, v := range workshop.GetProductLines(domain.NotDeleted) {
var result = make([]*record, 0)
if err := productRecordDao.TimeSectionProductRecord(request.CompanyId, request.OrgId, request.WorkshopId, v.LineId, SectionNameCCJ, time.Now().Add(-time.Hour*5), &result); err != nil {
log.Logger.Error(err.Error())
continue
}
var xData []string = make([]string, 0)
var values []interface{} = make([]interface{}, 0)
for _, r := range result {
xData = append(xData, r.Ts)
values = append(values, r.Total)
}
if len(tmpXData) == 0 {
tmpXData = xData
}
response = append(response, map[string]interface{}{
"lineName": v.LineName,
"data": NewXYData(xData, values),
})
}
return map[string]interface{}{
"xAxis": tmpXData,
"list": response,
}, nil
}
type HourProductiveStatisticsRequest struct {
CompanyId int `json:"companyId" valid:"Required"`
OrgId int `json:"orgId" valid:"Required"`
WorkshopId int `json:"workshopId" valid:"Required"`
}
func NewXYData(xData []string, values interface{}) interface{} {
//return map[string]interface{}{
//"xAxis": map[string]interface{}{
// "data": xData,
//},
//"source": map[string]interface{}{
// "value": values,
//},
//}
return values
}
// 时段产能-统计 (传串设备)
func (ptr *PGCommonStatisticsService) DailyProductiveStatistics(queryOptions map[string]interface{}) (interface{}, error) {
var request = &HourProductiveStatisticsRequest{}
if err := utils.LoadQueryObject(queryOptions, request); err != nil {
return nil, err
}
workshopRepository, _ := repository.NewWorkshopRepository(ptr.transactionContext)
type record struct {
Ts string `json:"ts"`
Total float64 `json:"total"`
}
workshop, err := workshopRepository.FindOne(map[string]interface{}{"workshopId": request.WorkshopId})
if err != nil || workshop == nil {
return nil, nil
}
productRecordDao, _ := dao.NewDeviceDailyRunningRecordDao(ptr.transactionContext)
var response = make([]interface{}, 0)
var tmpXData = make([]string, 0)
for _, v := range workshop.GetProductLines(domain.NotDeleted) {
var result = make([]*record, 0)
if err := productRecordDao.TimeSectionRunningRecord(request.CompanyId, request.OrgId, request.WorkshopId, v.LineId, SectionNameCCJ, time.Now().Add(-time.Hour*24*7), &result); err != nil {
log.Logger.Error(err.Error())
continue
}
var xData []string = make([]string, 0)
var values []interface{} = make([]interface{}, 0)
for _, r := range result {
xData = append(xData, r.Ts)
values = append(values, r.Total)
}
if len(tmpXData) == 0 {
tmpXData = xData
}
response = append(response, map[string]interface{}{
"lineName": v.LineName,
"data": NewXYData(xData, values),
})
}
return map[string]interface{}{
"recent_7_day": map[string]interface{}{
"xAxis": tmpXData,
"list": response,
},
}, nil
}
// 二级品占比
func (ptr *PGCommonStatisticsService) ProportionOfSecondLevelStatistics(queryOptions map[string]interface{}) (interface{}, error) {
var request = &HourProductiveStatisticsRequest{}
if err := utils.LoadQueryObject(queryOptions, request); err != nil {
return nil, err
}
workshopRepository, _ := repository.NewWorkshopRepository(ptr.transactionContext)
type record struct {
Sname string `json:"sname"`
Rate float64 `json:"rate"`
}
workshop, err := workshopRepository.FindOne(map[string]interface{}{"workshopId": request.WorkshopId})
if err != nil || workshop == nil {
return nil, nil
}
productRecordDao, _ := dao.NewProductRecordDao(ptr.transactionContext)
var input = []struct {
name string
t time.Time
}{
{"today", utils.GetZeroTime(time.Now())},
{"current_week", utils.GetCurrentWeekFirstDay(time.Now())},
{"current_month", utils.GetCurrentMonthFirstDay(time.Now())},
}
var response = make(map[string]interface{})
for _, v := range input {
var result = make([]*record, 0)
if err := productRecordDao.ProportionOfSecondLevelRecord(request.CompanyId, request.OrgId, request.WorkshopId, v.t, &result); err != nil {
log.Logger.Error(err.Error())
return nil, err
}
response[v.name] = result
}
return response, nil
}
// 车间生产效率统计
func (ptr *PGCommonStatisticsService) WorkshopProductionEfficiencyStatistics(queryOptions map[string]interface{}) (interface{}, error) {
var request = &HourProductiveStatisticsRequest{}
if err := utils.LoadQueryObject(queryOptions, request); err != nil {
return nil, err
}
workshopRepository, _ := repository.NewWorkshopRepository(ptr.transactionContext)
type record struct {
Oee float64 `json:"oee"`
Pu float64 `json:"pu"`
Tu float64 `json:"tu"`
Qu float64 `json:"qu"`
}
workshop, err := workshopRepository.FindOne(map[string]interface{}{"workshopId": request.WorkshopId})
if err != nil || workshop == nil {
return nil, nil
}
productRecordDao, _ := dao.NewDeviceDailyRunningRecordDao(ptr.transactionContext)
var input = []struct {
name string
t time.Time
}{
{"today", utils.GetZeroTime(time.Now())},
{"current_week", utils.GetCurrentWeekFirstDay(time.Now())},
{"current_month", utils.GetCurrentMonthFirstDay(time.Now())},
}
var response = make(map[string]interface{})
for _, v := range input {
var result = record{}
if err := productRecordDao.WorkshopProductionEfficiencyStatistics(request.CompanyId, request.OrgId, request.WorkshopId, v.t, &result); err != nil {
log.Logger.Error(err.Error())
return nil, err
}
response[v.name] = result
}
return response, nil
}
// 设备运行统计
func (ptr *PGCommonStatisticsService) DeviceRunningStatistics(queryOptions map[string]interface{}) (interface{}, error) {
var request = &DeviceRunningStatisticRequest{}
if err := utils.LoadQueryObject(queryOptions, request); err != nil {
return nil, err
}
deviceRepository, _ := repository.NewDeviceRepository(ptr.transactionContext)
deviceRunningRecordRepository, _ := repository.NewDeviceDailyRunningRecordRepository(ptr.transactionContext)
var t time.Time
var err error
if len(request.Date) > 0 {
t, err = time.ParseInLocation("2006-01-02", request.Date, time.Local)
if err != nil {
log.Logger.Error(err.Error())
}
}
_, devices, err := deviceRepository.Find(map[string]interface{}{"companyId": request.CompanyId, "orgId": request.OrgId, "workshopId": request.WorkshopId, "lineId": request.LineId})
if err != nil {
return nil, err
}
var response = make([]interface{}, 0)
_, dailyRecords, err := deviceRunningRecordRepository.Find(map[string]interface{}{"companyId": request.CompanyId, "orgId": request.OrgId, "productDate": t})
for i := 0; i < len(devices); i++ {
d := devices[i]
if d.Ext == nil || d.Ext.DeviceExt == nil || d.Ext.DeviceExt.IsProductDevice == 0 {
continue
}
var r *domain.DeviceDailyRunningRecord
item := make(map[string]interface{})
//item["id"] = uuid.New().String()
item["orgName"] = d.Ext.OrgName
if d.WorkStation != nil {
item["workshopName"] = d.WorkStation.WorkshopName
item["lineName"] = d.WorkStation.LineName
item["deviceName"] = d.DeviceName
item["oee"] = 0
item["status"] = []struct{}{}
}
for j := 0; j < len(dailyRecords); j++ {
if d.DeviceCode == dailyRecords[j].DeviceCode {
r = dailyRecords[j]
item["oee"] = r.DeviceRunningRecordInfo.OEE
break
}
}
if r != nil {
m := r.UpdatedAt.Local().Hour()*60 + r.UpdatedAt.Minute()
if r.UpdatedAt.Before(utils.GetZeroTime(time.Now())) {
m = 60 * 24
}
item["status"] = r.DeviceRunningRecordInfo.HourDeviceStatusDetail(m)
item["status_info"] = r.DeviceRunningRecordInfo.TimeLineDeviceStatus
}
response = append(response, item)
}
return map[string]interface{}{
"devices": response,
}, nil
}
type DeviceRunningStatisticRequest struct {
CompanyId int `json:"companyId" valid:"Required"`
OrgId int `json:"orgId" valid:"Required"`
WorkshopId int `json:"workshopId"`
LineId int `json:"lineId""`
Date string `json:"date"`
}
func NewPGCommonStatisticsService(transactionContext *pgTransaction.TransactionContext) (*PGCommonStatisticsService, error) {
if transactionContext == nil {
return nil, fmt.Errorf("transactionContext参数不能为nil")
} else {
return &PGCommonStatisticsService{
transactionContext: transactionContext,
}, nil
}
}
... ...
package domainService
import (
"errors"
"fmt"
"github.com/hibiken/asynq"
"github.com/linmadan/egglib-go/core/application"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"github.com/linmadan/egglib-go/utils/json"
"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/repository"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
... ... @@ -32,11 +30,11 @@ type SubmitOptions struct {
// 工段ID
SectionId int `cname:"工段" json:"sectionId" valid:"Required"`
// 生产小组ID
ProductGroupId int `cname:"生产小组" json:"productGroupId" valid:"Required"`
ProductGroupId int `cname:"生产小组" json:"productGroupId"`
// 员工Id 用户唯一标识
EmployeeId int `cname:"员工" json:"employeeId" valid:"Required"`
// 物料ID
UnitConversionId int `cname:"物料ID" json:"unitConversionId" valid:"Required"`
UnitConversionId int `cname:"物料ID" json:"unitConversionId"`
// 重量
Weigh float64 `cname:"重量" json:"weigh" valid:"Required"`
}
... ... @@ -73,8 +71,10 @@ func (ptr *PGProductRecordService) SubmitProductRecord(productRecordType int, qu
if workshop, err = workshopRepository.FindOne(map[string]interface{}{"workshopId": request.WorkshopId}); err != nil {
return nil, err
}
if uc, err = unitConversionRepository.FindOne(map[string]interface{}{"unitConversionId": request.UnitConversionId}); err != nil {
return nil, err
if request.UnitConversionId > 0 {
if uc, err = unitConversionRepository.FindOne(map[string]interface{}{"unitConversionId": request.UnitConversionId}); err != nil {
return nil, err
}
}
if workstation, err = workshop.FindWorkStation(request.WorkshopId, request.LineId, request.SectionId); err != nil {
return nil, err
... ... @@ -97,6 +97,12 @@ func (ptr *PGProductRecordService) SubmitProductRecord(productRecordType int, qu
if productRecordType == domain.RecordTypeReceiveMaterial || productRecordType == domain.RecordTypeReturnMaterial {
weight = (weight / uc.FromUnitQuantity.Quantity) * uc.ToUnitQuantity.Quantity
}
// 退料、需要判断用户是否有领过料
if productRecordType == domain.RecordTypeReturnMaterial {
if _, records, err := productRecordRepository.Find(map[string]interface{}{"companyId": request.CompanyId, "orgId": request.OrgId, "employeeId": user.UserId, "productPlanId": plan.ProductPlanId, "productRecordType": domain.RecordTypeReceiveMaterial, "limit": 1}); err == nil && len(records) == 0 {
return nil, errors.New("当前批次未进行领料,无法退料")
}
}
record := &domain.ProductRecord{
CompanyId: request.CompanyId,
... ... @@ -107,8 +113,8 @@ func (ptr *PGProductRecordService) SubmitProductRecord(productRecordType int, qu
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
ProductRecordInfo: &domain.ProductRecordInfo{
ProductDate: plan.ProductDate.Format("2006-01-02"),
OriginalWeigh: request.Weigh,
ProductDate: plan.ProductDate.Local().Format("2006-01-02"),
Original: request.Weigh,
Weigh: weight,
WeighBefore: weight,
UnitConversionId: request.UnitConversionId,
... ... @@ -168,7 +174,7 @@ func (ptr *PGProductRecordService) BatchApprove(list []*domain.ProductRecord, ap
var productRecordRepository, _ = repository.NewProductRecordRepository(ptr.transactionContext)
var record *domain.ProductRecord
var err error
log.Logger.Info("【自动审核二级品记录任务】 启动")
log.Logger.Debug("【自动审核二级品记录任务】 启动")
var user *domain.User = &domain.User{}
userService := NewUserService()
if approveUserId > 0 {
... ... @@ -207,14 +213,6 @@ func (ptr *PGProductRecordService) BatchApprove(list []*domain.ProductRecord, ap
return struct{}{}, nil
}
func SendProductRecordStaticsJob(productRecord *domain.ProductRecord) error {
task := asynq.NewTask(domain.TaskKeyPatternProductRecordStatics(), []byte(json.MarshalToString(productRecord)))
client := asynq.NewClient(asynq.RedisClientOpt{Addr: constant.REDIS_ADDRESS})
_, err := client.Enqueue(task)
return err
}
func NewPGProductRecordService(transactionContext *pgTransaction.TransactionContext) (*PGProductRecordService, error) {
if transactionContext == nil {
return nil, fmt.Errorf("transactionContext参数不能为nil")
... ...
... ... @@ -16,6 +16,10 @@ const (
ProductSection4 = "包装"
)
const (
DefaultCCJUnitQuantity = 0.2 //kg 穿串机默认的换算数量 1串/0.1千克
)
//EmployeeProductStatics 员工产能统计
func (ptr *PGProductRecordService) EmployeeProductStatics(productRecord *domain.ProductRecord) (interface{}, error) {
... ... @@ -56,7 +60,10 @@ func (ptr *PGProductRecordService) EmployeeProductStatics(productRecord *domain.
default:
return nil, nil //ptr.personalProductStatics(productRecord)
}
if planId == 0 {
log.Logger.Debug(fmt.Sprintf("工段:%v product_record 编号:%v 批次为0", productRecord.WorkStation.WorkStationId, productRecord.ProductRecordId))
return nil, nil
}
productPlan, err = productPlanRepository.FindOne(map[string]interface{}{"productPlanId": planId})
if err != nil {
return nil, err
... ... @@ -66,7 +73,7 @@ func (ptr *PGProductRecordService) EmployeeProductStatics(productRecord *domain.
// 1.查询员工 -》 员工打卡记录 工位+打卡日期
// 2.打卡记录的时间区间 在生产记录上报的时间范围内
attendanceRecordDao, _ := dao.NewAttendanceRecordDao(ptr.transactionContext)
_, attendanceRecords, err := attendanceRecordDao.ProductWorkStationAttendanceRecord(cid, oid, productRecord.WorkStation.WorkStationId, productRecord.CreatedAt)
_, attendanceRecords, err := attendanceRecordDao.ProductWorkStationAttendanceRecord(cid, oid, productRecord.WorkStation.WorkStationId, time.Now()) //, productRecord.CreatedAt
if err != nil || len(attendanceRecords) == 0 {
return nil, err
}
... ... @@ -97,13 +104,15 @@ func (ptr *PGProductRecordService) EmployeeProductStatics(productRecord *domain.
yesterdayOutputWeight float64 = 0
bestOutputWeight float64 = 0
)
if record, e := employeeProductRecordDao.WorkerProductRecord(cid, oid, planId, r.ProductWorker.UserId, productRecord.CreatedAt.AddDate(0, 0, -1)); e == nil && record != nil {
yesterdayOutputWeight = record.ProductRecordInfo.OutputWeight
bestOutputWeight = record.ProductRecordInfo.BestOutputWeight
} else {
if record, e := employeeProductRecordDao.WorkerBestOutputRecord(cid, oid, planId, r.ProductWorker.UserId); e == nil && record != nil {
if employeeProductRecord.ProductRecordInfo.BestOutputWeight > 0 {
if record, e := employeeProductRecordDao.WorkerProductRecord(cid, oid, planId, r.ProductWorker.UserId, productRecord.CreatedAt.AddDate(0, 0, -1)); e == nil && record != nil {
yesterdayOutputWeight = record.ProductRecordInfo.OutputWeight
bestOutputWeight = record.ProductRecordInfo.BestOutputWeight
} else {
if record, e := employeeProductRecordDao.WorkerBestOutputRecord(cid, oid, planId, r.ProductWorker.UserId); e == nil && record != nil {
yesterdayOutputWeight = record.ProductRecordInfo.OutputWeight
}
}
}
... ... @@ -139,7 +148,7 @@ func newEmployeeProductRecord(productRecord *domain.ProductRecord, participateTy
Ext: productPlan.Ext,
Version: 1,
ProductRecordInfo: &domain.ProductRecordStaticInfo{
ProductDate: productRecord.CreatedAt.Format("2006-01-02"),
ProductDate: productRecord.CreatedAt.Local().Format("2006-01-02"),
ProductPlanId: productRecord.ProductRecordInfo.ProductPlanId,
PlanProductName: productRecord.ProductRecordInfo.PlanProductName,
BatchNumber: productRecord.ProductRecordInfo.BatchNumber,
... ... @@ -191,6 +200,7 @@ func FindGroupMembers(productGroupRepository domain.ProductGroupRepository, comp
u := groups[i].GroupMembers[j]
u.GroupId = groups[i].ProductGroupId
u.GroupName = groups[i].GroupName
u.WorkOn = groups[i].WorkOn
result[keyFunc(u.UserId)] = u
}
}
... ... @@ -236,13 +246,15 @@ func (ptr *PGProductRecordService) personalProductStatics(productRecord *domain.
yesterdayOutputWeight float64 = 0
bestOutputWeight float64 = 0
)
if record, e := employeeProductRecordDao.WorkerProductRecord(cid, oid, planId, productRecord.ProductWorker.UserId, productRecord.CreatedAt.AddDate(0, 0, -1)); e == nil && record != nil {
yesterdayOutputWeight = record.ProductRecordInfo.OutputWeight
bestOutputWeight = record.ProductRecordInfo.BestOutputWeight
} else {
if record, e := employeeProductRecordDao.WorkerBestOutputRecord(cid, oid, planId, productRecord.ProductWorker.UserId); e == nil && record != nil {
if employeeProductRecord.ProductRecordInfo.BestOutputWeight == 0 {
if record, e := employeeProductRecordDao.WorkerProductRecord(cid, oid, planId, productRecord.ProductWorker.UserId, productRecord.CreatedAt.AddDate(0, 0, -1)); e == nil && record != nil {
yesterdayOutputWeight = record.ProductRecordInfo.OutputWeight
bestOutputWeight = record.ProductRecordInfo.BestOutputWeight
} else {
if record, e := employeeProductRecordDao.WorkerBestOutputRecord(cid, oid, planId, productRecord.ProductWorker.UserId); e == nil && record != nil {
yesterdayOutputWeight = record.ProductRecordInfo.OutputWeight
}
}
}
... ... @@ -271,7 +283,10 @@ func (ptr *PGProductRecordService) WorkshopProductStatics(productRecord *domain.
productPlan *domain.ProductPlan
err error
)
if planId == 0 {
log.Logger.Debug(fmt.Sprintf("工段:%v product_record 编号:%v 批次为0", productRecord.WorkStation.WorkStationId, productRecord.ProductRecordId))
return nil, nil
}
productPlan, err = productPlanRepository.FindOne(map[string]interface{}{"productPlanId": planId})
if err != nil {
return nil, err
... ... @@ -320,7 +335,7 @@ func newWorkshopProductRecord(productRecord *domain.ProductRecord, productPlan *
WorkStation: productRecord.WorkStation,
//WorkOn: productPlan.WorkOn,
//ParticipateType: participateType,
ProductDate: productRecord.CreatedAt.Format("2006-01-02"),
ProductDate: productRecord.CreatedAt.Local().Format("2006-01-02"),
ProductWeigh: 0,
SecondLevelWeigh: 0,
CreatedAt: time.Now(),
... ... @@ -328,7 +343,7 @@ func newWorkshopProductRecord(productRecord *domain.ProductRecord, productPlan *
Ext: productPlan.Ext,
Version: 1,
ProductRecordInfo: &domain.ProductRecordStaticInfo{
ProductDate: productRecord.CreatedAt.Format("2006-01-02"),
ProductDate: productRecord.CreatedAt.Local().Format("2006-01-02"),
ProductPlanId: productRecord.ProductRecordInfo.ProductPlanId,
PlanProductName: productRecord.ProductRecordInfo.PlanProductName,
BatchNumber: productRecord.ProductRecordInfo.BatchNumber,
... ...
... ... @@ -23,11 +23,11 @@ func (ptr *PGWorkerAttendanceReportService) Report(cid, oid int, report *domain.
attendanceRecordRepository, _ = repository.NewProductAttendanceRecordRepository(ptr.transactionContext)
isSignIn = true
record *domain.ProductAttendanceRecord
workStationId string //具体工位
workStation *domain.WorkStation
attendanceType int = domain.ParticipateNormal
worker *domain.User
org *domain.Org
//workStationId string //具体工位
workStation *domain.WorkStation
attendanceType int = domain.ParticipateNormal
worker *domain.User
org *domain.Org
)
if err := report.Valid(); err != nil {
... ... @@ -68,19 +68,42 @@ func (ptr *PGWorkerAttendanceReportService) Report(cid, oid int, report *domain.
beginTime := utils.GetZeroTime(report.ActionTime)
endTime := report.ActionTime
_, records, _ := attendanceRecordDao.WorkerAttendanceRecords(cid, oid, worker.UserId, workStationId, beginTime, endTime)
_, records, _ := attendanceRecordDao.WorkerAttendanceRecords(cid, oid, worker.UserId, "", beginTime, endTime)
for i := 0; i < len(records); i++ {
r := records[i]
if workStation.WorkStationId == r.WorkStation.WorkStationId {
continue
}
if !utils.TimeIsZero(r.SignIn) && utils.TimeIsZero(r.SignOut) {
if utils.TimeAfterEqual(report.ActionTime, r.SignIn) {
r.SignOut = report.ActionTime
r.WorkTimeBefore = r.ComputeWorkTimeBefore()
log.Logger.Debug(fmt.Sprintf("【考勤汇报】 用户:%v(%v) 在其他工段打卡 下线当前工段:%v 签退 %v", worker.UserName, worker.UserId, r.WorkStation.SectionName, report))
if _, err = attendanceRecordRepository.Save(r); err != nil {
return nil, err
}
} else {
log.Logger.Debug(fmt.Sprintf("【考勤汇报】 考勤记录不合法,操作时间小于签到时间 考勤ID:%v 用户:%v 打卡时间:%v", r.ProductAttendanceId, worker.UserId, report.ActionTime))
return struct{}{}, nil
}
break
}
}
for i := 0; i < len(records); i++ {
r := records[i]
if workStation.WorkStationId != r.WorkStation.WorkStationId {
continue
}
// 操作时间 < 签到时间
if utils.TimeAfterEqual(r.SignIn, report.ActionTime) {
log.Logger.Info(fmt.Sprintf("【考勤汇报】 考勤记录不合法,操作时间小于签到时间 考勤ID:%v 用户:%v 打卡时间:%v", r.ProductAttendanceId, worker.UserId, report.ActionTime))
log.Logger.Debug(fmt.Sprintf("【考勤汇报】 考勤记录不合法,操作时间小于签到时间 考勤ID:%v 用户:%v 打卡时间:%v", r.ProductAttendanceId, worker.UserId, report.ActionTime))
return struct{}{}, nil
}
// 存在完整打卡记录
// 1. 如果在区间内,退出
if !utils.TimeIsZero(r.SignIn) && !utils.TimeIsZero(r.SignOut) {
if utils.TimeBeforeEqual(r.SignIn, report.ActionTime) && utils.TimeAfterEqual(r.SignOut, report.ActionTime) {
log.Logger.Info(fmt.Sprintf("【考勤汇报】 已存在同一时间段的考勤记录 考勤ID:%v 用户:%v 打卡时间:%v", r.ProductAttendanceId, worker.UserId, report.ActionTime))
log.Logger.Debug(fmt.Sprintf("【考勤汇报】 已存在同一时间段的考勤记录 考勤ID:%v 用户:%v 打卡时间:%v", r.ProductAttendanceId, worker.UserId, report.ActionTime))
return struct{}{}, nil
}
continue
... ... @@ -88,6 +111,11 @@ func (ptr *PGWorkerAttendanceReportService) Report(cid, oid int, report *domain.
// 存在未结束的打卡记录
// 1.满足条件-签退
if !utils.TimeIsZero(r.SignIn) && utils.TimeIsZero(r.SignOut) {
// 五分钟内重复打卡不算数
if r.SignIn.Add(time.Minute * 5).After(report.ActionTime) {
log.Logger.Debug(fmt.Sprintf("【考勤汇报】 打卡未满五分钟 考勤ID:%v 用户:%v 打卡时间:%v", r.ProductAttendanceId, worker.UserId, report.ActionTime))
return struct{}{}, nil
}
if utils.TimeBeforeEqual(r.SignIn, report.ActionTime) {
isSignIn = false
record = r
... ... @@ -115,11 +143,11 @@ func (ptr *PGWorkerAttendanceReportService) Report(cid, oid int, report *domain.
ProductGroupId: groupId,
}),
}
log.Logger.Info(fmt.Sprintf("【考勤汇报】 用户:%v(%v) 签到 %v", worker.UserName, worker.UserId, report))
log.Logger.Debug(fmt.Sprintf("【考勤汇报】 用户:%v(%v) 签到 %v", worker.UserName, worker.UserId, report))
} else {
record.SignOut = report.ActionTime
record.WorkTimeBefore = record.ComputeWorkTimeBefore()
log.Logger.Info(fmt.Sprintf("【考勤汇报】 用户:%v(%v) 签退 %v", worker.UserName, worker.UserId, report))
log.Logger.Debug(fmt.Sprintf("【考勤汇报】 用户:%v(%v) 签退 %v", worker.UserName, worker.UserId, report))
}
if _, err = attendanceRecordRepository.Save(record); err != nil {
... ...
package domainService
import (
"encoding/json"
"fmt"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/dao"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/redis"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/repository"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log"
"strconv"
"time"
)
type PGWorkshopDataConsumeService struct {
transactionContext *pgTransaction.TransactionContext
}
// 消费设备生产数据
func (ptr *PGWorkshopDataConsumeService) Consume(companyId, orgId int, record *domain.DeviceCollection) (interface{}, error) {
var (
deviceRunningData *domain.DeviceRunningData
deviceRunningRecord *domain.DeviceRunningRecord
deviceDailyRecord *domain.DeviceDailyRunningRecord
workStation *domain.WorkStation
device *domain.Device
planId int
err error
plan *domain.ProductPlanDispatchRecord
datetime time.Time
)
var (
deviceRepository, _ = repository.NewDeviceRepository(ptr.transactionContext)
deviceRunningRecordRepository, _ = repository.NewDeviceRunningRecordRepository(ptr.transactionContext)
)
if deviceRunningData, err = ptr.newDeviceRunningData(record); err != nil {
return nil, err
}
// 0.初始化 从缓存捞数据、没取到查询库
deviceDailyRecord, err = redis.GetDeviceDailyRunningRecord(time.Now(), deviceRunningData.DeviceCode)
if err == domain.ErrorNotFound {
err = nil
}
if err != nil {
return nil, err
}
if deviceDailyRecord != nil {
workStation = deviceDailyRecord.WorkStation
planId = deviceDailyRecord.DeviceRunningRecordInfo.ProductPlanId
device = &domain.Device{
DeviceId: deviceDailyRecord.DeviceId,
DeviceCode: deviceDailyRecord.DeviceCode,
}
} else {
// 0.1.查询记录对应的工段、批次
// 0.2.保存一天当日记录
if device, err = deviceRepository.FindOne(map[string]interface{}{"companyId": companyId, "orgId": orgId, "deviceCode": deviceRunningData.DeviceCode}); err != nil {
log.Logger.Error(fmt.Sprintf("【设备数据-消费】 未找到设备:%v 数据数据", deviceRunningData.DeviceCode))
return nil, nil
}
workStation = device.WorkStation
var saveErr error
if deviceDailyRecord, saveErr = ptr.saveDeviceDailyRunningRecord(companyId, orgId, workStation, device, planId, deviceRunningData); err != nil {
return nil, err
}
defer func() {
if saveErr != nil {
redis.RemoveDeviceDailyRunningRecord(time.Now(), deviceRunningData.DeviceCode)
}
}()
}
// 封箱机、串串机需要定位到批次
if record.DeviceType == domain.DeviceTypeFengXiangJi || record.DeviceType == domain.DeviceTypeChuanChuanJi {
datetime, _ = time.Parse("2006-01-02", deviceRunningData.Date)
if plan, err = ptr.findDeviceProductPlan(companyId, orgId, workStation.WorkStationId, datetime, deviceRunningData.ProductType); err != nil {
log.Logger.Error(err.Error())
} else {
planId = plan.PlanDispatchRecordExt.ProductPlanId
}
}
// 1.保存设备运行记录
deviceRunningRecord, _ = ptr.newDeviceRunningRecord(companyId, orgId, workStation, device, deviceRunningData)
if _, err = deviceRunningRecordRepository.Save(deviceRunningRecord); err != nil {
return nil, err
}
// 2.保存设备生产记录
if record.DeviceType == domain.DeviceTypeChuanChuanJi && plan != nil {
productRecord, _ := ptr.newProductRecord(companyId, orgId, workStation, device, deviceRunningData, plan)
//if _, err = deviceRunningRecordRepository.Save(deviceRunningRecord); err != nil {
// return nil, err
//}
SendProductRecordStaticsJob(productRecord)
}
// 3.更新 设备每日运行记录(汇总) - redis更新 十分钟异步刷库
deviceDailyRecord.AddDeviceRunningData(deviceRunningData.CollectionTime, deviceRunningData)
if err = redis.SaveDeviceDailyRunningRecord(deviceDailyRecord); err != nil {
return nil, err
}
return nil, nil
}
func (ptr *PGWorkshopDataConsumeService) newDeviceRunningData(record *domain.DeviceCollection) (*domain.DeviceRunningData, error) {
var err error
var unitQuantity float64 = DefaultCCJUnitQuantity // 单位数量
var data = &domain.DeviceRunningData{
DeviceCollectionId: record.DeviceCollectionId,
WorkShopName: record.WorkShopName,
CollectionTime: record.CollectionTime,
DeviceCode: record.DeviceSn,
DeviceType: record.DeviceType,
StartupStatus: int(record.StartupStatus),
ComStatus: int(record.ComStatus),
//UnitQuantity: unitQuantity,
}
var mBytes []byte
if mBytes, err = json.Marshal(record.Values); err != nil {
return nil, err
}
var formatDate = func(y, m, d string) (string, error) {
yd, _ := strconv.Atoi(y)
md, _ := strconv.Atoi(m)
dd, _ := strconv.Atoi(d)
t := time.Date(yd, time.Month(md), dd, 0, 0, 0, 0, time.Local)
return t.Local().Format("2006-01-02"), nil
}
switch record.DeviceType {
//包馅机
case domain.DeviceTypeBaoXianJi:
deviceBaoXianJi := &domain.DeviceBaoXianJi{}
err = json.Unmarshal(mBytes, deviceBaoXianJi)
if err != nil {
break
}
data.Count = int(deviceBaoXianJi.Count)
break
//油炸机
case domain.DeviceTypeYouZhaJi:
deviceYouZhaJi := &domain.DeviceYouZhaJi{}
err = json.Unmarshal(mBytes, deviceYouZhaJi)
if err != nil {
break
}
data.Temp1 = deviceYouZhaJi.FrontTemp
break
//串串机
case domain.DeviceTypeChuanChuanJi:
deviceChuanChuanJi := &domain.DeviceChuanChuanJi{}
err = json.Unmarshal(mBytes, deviceChuanChuanJi)
if err != nil {
break
}
data.Count = int(deviceChuanChuanJi.Count)
data.ProductType = deviceChuanChuanJi.ProductType
if data.Date, err = formatDate(deviceChuanChuanJi.Year, deviceChuanChuanJi.Month, deviceChuanChuanJi.Day); err != nil {
return nil, err
}
data.UnitQuantity = unitQuantity
break
//速冻线
case domain.DeviceTypeSuDongXian:
deviceSuDongXian := &domain.DeviceSuDongXian{}
err = json.Unmarshal(mBytes, deviceSuDongXian)
if err != nil {
break
}
data.Temp1 = deviceSuDongXian.CurrTemp
break
//封口机
case domain.DeviceTypeFengKouJi:
deviceFengKouJi := &domain.DeviceFengKouJi{}
err = json.Unmarshal(mBytes, deviceFengKouJi)
if err != nil {
break
}
data.Count = int(deviceFengKouJi.Count)
data.ProductType = deviceFengKouJi.ProductType
if data.Date, err = formatDate(deviceFengKouJi.Year, deviceFengKouJi.Month, deviceFengKouJi.Day); err != nil {
return nil, err
}
break
//封箱机
case domain.DeviceTypeFengXiangJi:
deviceFengXiangJi := &domain.DeviceFengXiangJi{}
err = json.Unmarshal(mBytes, deviceFengXiangJi)
if err != nil {
break
}
data.Count = int(deviceFengXiangJi.Count)
data.ProductType = deviceFengXiangJi.ProductType
if data.Date, err = formatDate(deviceFengXiangJi.Year, deviceFengXiangJi.Month, deviceFengXiangJi.Day); err != nil {
return nil, err
}
break
//打浆机
case domain.DeviceTypeDaJiangJi:
default:
}
return data, nil
}
func (ptr *PGWorkshopDataConsumeService) newDeviceRunningRecord(companyId, orgId int, workStation *domain.WorkStation, device *domain.Device, data *domain.DeviceRunningData) (*domain.DeviceRunningRecord, error) {
return &domain.DeviceRunningRecord{
CompanyId: companyId,
OrgId: orgId,
WorkStation: workStation,
DeviceId: device.DeviceId,
DeviceCode: device.DeviceCode,
DeviceRunningRecordInfo: data,
CreatedAt: time.Now(),
}, nil
}
func (ptr *PGWorkshopDataConsumeService) newProductRecord(companyId int, orgId int, workStation *domain.WorkStation, device *domain.Device, data *domain.DeviceRunningData, plan *domain.ProductPlanDispatchRecord) (*domain.ProductRecord, error) {
result := &domain.ProductRecord{
CompanyId: companyId,
OrgId: orgId,
WorkStation: workStation,
ProductRecordType: domain.RecordTypeWeigh,
ProductWorker: &domain.User{},
CreatedAt: data.CollectionTime,
UpdatedAt: time.Now(),
ProductRecordInfo: &domain.ProductRecordInfo{
ProductDate: data.CollectionTime.Local().Format("2006-01-02"),
Original: float64(data.Count),
Weigh: float64(data.Count) * DefaultCCJUnitQuantity,
WeighBefore: float64(data.Count) * DefaultCCJUnitQuantity,
ApproveStatus: domain.AttendanceNotApprove,
ProductPlanId: plan.PlanDispatchRecordExt.ProductPlanId,
PlanProductName: plan.PlanDispatchRecordExt.PlanProductName,
BatchNumber: plan.BatchNumber,
},
Ext: domain.NewExt(""),
}
if device.Ext != nil {
result.Ext = domain.NewExt(device.Ext.OrgName)
}
return result, nil
}
func (ptr *PGWorkshopDataConsumeService) saveDeviceDailyRunningRecord(companyId, orgId int, workStation *domain.WorkStation, device *domain.Device, planId int, data *domain.DeviceRunningData) (*domain.DeviceDailyRunningRecord, error) {
var (
record *domain.DeviceDailyRunningRecord
err error
)
deviceDailyRunningRecordRepository, _ := repository.NewDeviceDailyRunningRecordRepository(ptr.transactionContext)
if record, err = deviceDailyRunningRecordRepository.FindOne(map[string]interface{}{
"workStationId": workStation.WorkStationId,
"deviceCode": data.DeviceCode,
"productDate": utils.GetZeroTime(time.Now()),
}); err != nil {
if err != domain.ErrorNotFound {
return nil, err
}
}
if record != nil {
return record, nil
}
recordInfo := domain.NewDeviceRunningRecordInfo()
recordInfo.ProductPlanId = planId
recordInfo.DeviceName = device.DeviceName
recordInfo.OrgName = device.Ext.OrgName
record = &domain.DeviceDailyRunningRecord{
CompanyId: companyId,
OrgId: orgId,
WorkStation: workStation,
DeviceId: device.DeviceId,
DeviceCode: device.DeviceCode,
ProductDate: utils.GetZeroTime(time.Now()),
DeviceRunningRecordInfo: recordInfo,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
if record, err = deviceDailyRunningRecordRepository.Save(record); err != nil {
return nil, err
}
if device.MarkAsProductDevice() {
deviceRepository, _ := repository.NewDeviceRepository(ptr.transactionContext)
if device, err = deviceRepository.Save(device); err != nil {
return nil, err
}
}
return record, nil
}
// 查找设备的生产计划,如果计划没有上线的话将他上线
func (ptr *PGWorkshopDataConsumeService) findDeviceProductPlan(companyId, orgId int, workStationId string, date time.Time, productCode string) (*domain.ProductPlanDispatchRecord, error) {
planDispatchRecordDao, _ := dao.NewProductPlanDispatchRecord(ptr.transactionContext)
planDispatchRecordRepository, _ := repository.NewProductPlanDispatchRecordRepository(ptr.transactionContext)
var setPlanOnline = false
record, err := planDispatchRecordDao.DeviceProductPlan(companyId, orgId, workStationId, date, productCode, domain.PlanOnline)
if err == domain.ErrorNotFound {
if record, err = planDispatchRecordDao.DeviceProductPlan(companyId, orgId, workStationId, date, productCode, domain.PlanOffline); err != nil {
return nil, err
} else {
setPlanOnline = true
}
}
if setPlanOnline {
record.ChangeStatus(domain.PlanOnline)
if record, err = planDispatchRecordRepository.Save(record); err != nil {
return nil, err
}
}
return record, nil
}
func NewPGWorkshopDataConsumeService(transactionContext *pgTransaction.TransactionContext) (*PGWorkshopDataConsumeService, error) {
if transactionContext == nil {
return nil, fmt.Errorf("transactionContext参数不能为nil")
} else {
return &PGWorkshopDataConsumeService{
transactionContext: transactionContext,
}, nil
}
}
... ...
package domainService
import (
"fmt"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"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/dao"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/pg/models"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/repository"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log"
"time"
)
type PGWorkshopPlanCompletionRecordService struct {
transactionContext *pgTransaction.TransactionContext
}
func NewPGWorkshopPlanCompletionRecordService(transactionContext *pgTransaction.TransactionContext) (*PGWorkshopPlanCompletionRecordService, error) {
if transactionContext == nil {
return nil, fmt.Errorf("transactionContext参数不能为nil")
} else {
return &PGWorkshopPlanCompletionRecordService{
transactionContext: transactionContext,
}, nil
}
}
// 车间完成统计
func (ptr *PGWorkshopPlanCompletionRecordService) WorkshopPlanCompletion(begin time.Time, end time.Time) error {
type record struct {
PlanWeight float64 `json:"plan_weight"`
RealWeight float64 `json:"real_weight"`
ProductPlanId float64 `json:"product_plan_id"`
}
cid := constant.MANUFACTURE_DEFAULT_COMPANYID
oid := constant.MANUFACTURE_DEFAULT_ORGID
workshopRepository, _ := repository.NewWorkshopRepository(ptr.transactionContext)
_, workshops, err := workshopRepository.Find(map[string]interface{}{"companyId": cid, "orgId": oid})
if err != nil {
return err
}
if len(workshops) == 0 {
return nil
}
workshopProductRecordDao, _ := dao.NewWorkshopPlanCompletionRecordDao(ptr.transactionContext)
for i := range workshops {
var result = make([]*record, 0)
if err := workshopProductRecordDao.Records(cid, oid, workshops[i].WorkshopId, begin, end, &result); err != nil {
log.Logger.Error(err.Error())
continue
}
var totalPlan float64 = 0
var totalReal float64 = 0
for _, v := range result {
totalPlan += v.PlanWeight
totalReal += v.RealWeight
}
var completionRate float64
if !(totalPlan == 0 || totalReal == 0) {
completionRate = utils.Round(totalReal*100.0/totalPlan, 0)
}
var record *models.WorkshopPlanCompletionRecord
if record, err = workshopProductRecordDao.FindOne(cid, oid, workshops[i].WorkshopId, begin); err == domain.ErrorNotFound && record == nil {
record = &models.WorkshopPlanCompletionRecord{
CompanyId: cid,
OrgId: oid,
WorkshopId: workshops[i].WorkshopId,
WorkshopName: workshops[i].WorkshopName,
CreatedAt: begin,
Plan: totalPlan,
Real: totalReal,
Rate: completionRate,
}
if err := workshopProductRecordDao.Save(record); err != nil {
return err
}
}
}
return nil
}
... ...
... ... @@ -3,10 +3,7 @@ package domainService
import (
"errors"
"fmt"
"github.com/hibiken/asynq"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"github.com/linmadan/egglib-go/utils/json"
"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/repository"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
... ... @@ -58,22 +55,6 @@ func (ptr *PGWorkshopWorkTimeStaticService) WorkshopWorkTimeStatic(productRecord
return record, nil
}
func SendWorkshopWorkTimeStaticJob(productRecord *domain.ProductAttendanceRecord) error {
return SendAsyncJob(domain.TaskKeyWorkshopWorkTimeRecordStatics(), productRecord)
}
func SenDeviceZkTecoReportJob(productRecord *domain.DeviceZkTeco) error {
return SendAsyncJob(domain.TaskDeviceZkTecoReport(), productRecord)
}
func SendAsyncJob(queueName string, job interface{}) error {
task := asynq.NewTask(queueName, []byte(json.MarshalToString(job)))
client := asynq.NewClient(asynq.RedisClientOpt{Addr: constant.REDIS_ADDRESS})
_, err := client.Enqueue(task)
return err
}
func NewPGWorkshopWorkTimeStaticService(transactionContext *pgTransaction.TransactionContext) (*PGWorkshopWorkTimeStaticService, error) {
if transactionContext == nil {
return nil, fmt.Errorf("transactionContext参数不能为nil")
... ...
... ... @@ -4,6 +4,7 @@ import (
"fmt"
pahomqtt "github.com/eclipse/paho.mqtt.golang"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/constant"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log"
"time"
)
... ... @@ -26,21 +27,26 @@ func (subscribeClient *SubscribeClient) options() *pahomqtt.ClientOptions {
opts.SetKeepAlive(2 * time.Second)
opts.SetPingTimeout(1 * time.Second)
opts.CleanSession = false
opts.SetClientID("test")
//opts.SetClientID("test")
//opts.Order = true
return opts
}
func (subscribeClient *SubscribeClient) Connect() *SubscribeClient{
func (subscribeClient *SubscribeClient) Connect() *SubscribeClient {
opts := subscribeClient.options()
fmt.Println("start connect......")
opts.OnConnectionLost = func(c pahomqtt.Client, err error) {
defer func() {
if r := recover(); r != nil {
log.Logger.Error(fmt.Sprintf("%v", r))
}
}()
fmt.Println("Connect error:", err)
for {
fmt.Println("reconnect server")
token := subscribeClient.client.Connect()
token.Wait()
fmt.Println("server Connect status:",subscribeClient.client.IsConnectionOpen())
fmt.Println("server Connect status:", subscribeClient.client.IsConnectionOpen())
if subscribeClient.client.IsConnectionOpen() {
break
}
... ... @@ -48,7 +54,7 @@ func (subscribeClient *SubscribeClient) Connect() *SubscribeClient{
}
}
opts.OnConnect = func(c pahomqtt.Client) {
c.Subscribe(subscribeClient.topic,0,subscribeClient.handler)
c.Subscribe(subscribeClient.topic, 0, subscribeClient.handler)
}
subscribeClient.client = pahomqtt.NewClient(opts)
token := subscribeClient.client.Connect()
... ... @@ -56,21 +62,21 @@ func (subscribeClient *SubscribeClient) Connect() *SubscribeClient{
return subscribeClient
}
func (subscribeClient *SubscribeClient) Subscribe(topic string, messageHandler pahomqtt.MessageHandler){
func (subscribeClient *SubscribeClient) Subscribe(topic string, messageHandler pahomqtt.MessageHandler) {
subscribeClient.topic = topic
subscribeClient.handler = messageHandler
token := subscribeClient.client.Subscribe(topic,0,messageHandler)
token := subscribeClient.client.Subscribe(topic, 0, messageHandler)
token.Wait()
token.Done()
}
func StartSubscribe(topic string,handler MessageHandler){
func StartSubscribe(topic string, handler MessageHandler) {
defer func() {
if err := recover();err != nil {
if err := recover(); err != nil {
fmt.Println(err)
StartSubscribe(topic,handler)
StartSubscribe(topic, handler)
}
}()
fmt.Println("start subscribe...")
NewSubscribeClient().Connect().Subscribe(topic,pahomqtt.MessageHandler(handler))
}
\ No newline at end of file
NewSubscribeClient().Connect().Subscribe(topic, pahomqtt.MessageHandler(handler))
}
... ...
... ... @@ -45,6 +45,9 @@ func init() {
(*models.WorkshopProductRecord)(nil),
(*models.WorkshopWorkTimeRecord)(nil),
(*models.ProductPlanDispatchRecord)(nil),
(*models.DeviceDailyRunningRecord)(nil),
(*models.DeviceRunningRecord)(nil),
(*models.WorkshopPlanCompletionRecord)(nil),
} {
err := DB.Model(model).CreateTable(&orm.CreateTableOptions{
Temp: false,
... ...
package models
import (
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"time"
)
type DeviceDailyRunningRecord struct {
tableName string `comment:"设备每日运行记录(汇总)" pg:"manufacture.device_daily_running_record"`
// 设备每日运行记录ID
DeviceDailyRunningRecordId int `comment:"设备每日运行记录ID" pg:"pk:device_daily_running_record_id"`
// 企业id
CompanyId int `comment:"企业id"`
// 组织ID
OrgId int `comment:"组织ID"`
// 工作位置
WorkStation *domain.WorkStation `comment:"工作位置"`
// 设备Id
DeviceId int `comment:"设备Id"`
// 设备编号
DeviceCode string `comment:"设备编号"`
// 生产日期
ProductDate time.Time `json:"productDate"`
// 设备运行记录信息
DeviceRunningRecordInfo *domain.DeviceRunningRecordInfo `comment:"设备运行记录信息"`
// 创建时间
CreatedAt time.Time `comment:"创建时间"`
// 更新时间
UpdatedAt time.Time `comment:"更新时间"`
// 删除时间
DeletedAt time.Time `comment:"删除时间"`
}
... ...
package models
import (
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"time"
)
type DeviceRunningRecord struct {
tableName string `comment:"设备运行记录" pg:"manufacture.device_running_record"`
// 设备运行记录ID
DeviceRunningRecordId int `comment:"设备运行记录ID" pg:"pk:device_running_record_id"`
// 企业id
CompanyId int `comment:"企业id"`
// 组织ID
OrgId int `comment:"组织ID"`
// 工作位置
WorkStation *domain.WorkStation `comment:"工作位置"`
// 设备Id
DeviceId int `comment:"设备Id"`
// 设备编号
DeviceCode string `comment:"设备编号"`
// 设备运行记录信息
DeviceRunningRecordInfo *domain.DeviceRunningData `comment:"设备运行记录信息"`
// 创建时间
CreatedAt time.Time `comment:"创建时间"`
}
... ...
package models
import (
"time"
)
// 车间计划完成记录
type WorkshopPlanCompletionRecord struct {
tableName string `comment:"车间" pg:"manufacture.workshop_plan_completion_record"`
WorkshopPlanCompletionRecordId int `comment:"车间计划完成记录ID" pg:"pk:workshop_plan_completion_record_id"`
// 企业id
CompanyId int `comment:"企业id"`
// 组织ID
OrgId int `comment:"组织ID"`
// 生产计划ID
//ProductPlanId int `comment:"生产计划ID" pg:"pk:product_plan_id"`
// 工作位置
//WorkStation *domain.WorkStation `comment:"工作位置"`
// 车间ID
WorkshopId int `comment:"车间"`
// 车间名称
WorkshopName string `comment:"车间名称"`
// 创建时间
CreatedAt time.Time `comment:"创建时间"`
// 计划生成
Plan float64 `comment:"计划生成" pg:",use_zero"`
// 计划生成
Real float64 `comment:"实际生产" pg:",use_zero"`
// 完成率
Rate float64 `comment:"完成率" pg:",use_zero"`
}
... ...
package transform
import (
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/pg/models"
)
func TransformToDeviceDailyRunningRecordDomainModelFromPgModels(deviceDailyRunningRecordModel *models.DeviceDailyRunningRecord) (*domain.DeviceDailyRunningRecord, error) {
return &domain.DeviceDailyRunningRecord{
DeviceDailyRunningRecordId: deviceDailyRunningRecordModel.DeviceDailyRunningRecordId,
CompanyId: deviceDailyRunningRecordModel.CompanyId,
OrgId: deviceDailyRunningRecordModel.OrgId,
WorkStation: deviceDailyRunningRecordModel.WorkStation,
DeviceId: deviceDailyRunningRecordModel.DeviceId,
DeviceCode: deviceDailyRunningRecordModel.DeviceCode,
ProductDate: deviceDailyRunningRecordModel.ProductDate,
DeviceRunningRecordInfo: deviceDailyRunningRecordModel.DeviceRunningRecordInfo,
CreatedAt: deviceDailyRunningRecordModel.CreatedAt,
UpdatedAt: deviceDailyRunningRecordModel.UpdatedAt,
DeletedAt: deviceDailyRunningRecordModel.DeletedAt,
}, nil
}
... ...
package transform
import (
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/pg/models"
)
func TransformToDeviceRunningRecordDomainModelFromPgModels(deviceRunningRecordModel *models.DeviceRunningRecord) (*domain.DeviceRunningRecord, error) {
return &domain.DeviceRunningRecord{
DeviceRunningRecordId: deviceRunningRecordModel.DeviceRunningRecordId,
CompanyId: deviceRunningRecordModel.CompanyId,
OrgId: deviceRunningRecordModel.OrgId,
WorkStation: deviceRunningRecordModel.WorkStation,
DeviceId: deviceRunningRecordModel.DeviceId,
DeviceCode: deviceRunningRecordModel.DeviceCode,
DeviceRunningRecordInfo: deviceRunningRecordModel.DeviceRunningRecordInfo,
CreatedAt: deviceRunningRecordModel.CreatedAt,
}, nil
}
... ...
package redis
import (
"encoding/json"
"fmt"
"github.com/go-redis/redis"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/constant"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"time"
)
// 获取每日设备运行数据
func GetDeviceDailyRunningRecord(t time.Time, deviceCode string) (*domain.DeviceDailyRunningRecord, error) {
client := GetRedis()
key := DeviceDailyRunningRecordKey(t, deviceCode)
return getDeviceDailyRunningRecord(client, key)
}
func getDeviceDailyRunningRecord(client *redis.Client, key string) (*domain.DeviceDailyRunningRecord, error) {
result := client.Get(key)
data, err := result.Bytes()
if err == redis.Nil {
return nil, domain.ErrorNotFound
}
var record = &domain.DeviceDailyRunningRecord{}
if err = json.Unmarshal(data, record); err != nil {
return nil, err
}
return record, nil
}
// 保存每日设备运行数据
func SaveDeviceDailyRunningRecord(record *domain.DeviceDailyRunningRecord) error {
client := GetRedis()
key := DeviceDailyRunningRecordKey(record.CreatedAt, record.DeviceCode)
recordData, err := json.Marshal(record)
result := client.Set(key, recordData, time.Hour*24*5)
_, err = result.Result()
return err
}
// 保存每日设备运行数据
func RemoveDeviceDailyRunningRecord(t time.Time, deviceCode string) error {
client := GetRedis()
key := DeviceDailyRunningRecordKey(t, deviceCode)
result := client.Del(key)
_, err := result.Result()
return err
}
func DeviceDailyRunningRecordKey(t time.Time, deviceCode string) string {
str := fmt.Sprintf("%v:device-daily-record:%v-%v:%v:%v", constant.CACHE_PREFIX, constant.MANUFACTURE_DEFAULT_COMPANYID, constant.MANUFACTURE_DEFAULT_ORGID, t.Format("2006-01-02"), deviceCode)
return str
}
// 获取设备每日所有数据记录
func GetDeviceDailyAllRecord(t time.Time) ([]*domain.DeviceDailyRunningRecord, error) {
client := GetRedis()
sliceResult := client.Keys(DeviceDailyAllRecordKey(t))
keys, err := sliceResult.Result()
var records = make([]*domain.DeviceDailyRunningRecord, 0)
if err != nil {
return nil, err
}
for _, v := range keys {
record, err := getDeviceDailyRunningRecord(client, v)
if err != nil {
return nil, err
}
records = append(records, record)
}
return records, nil
}
func DeviceDailyAllRecordKey(t time.Time) string {
str := fmt.Sprintf("%v:device-daily-record:%v-%v:%v:*", constant.CACHE_PREFIX, constant.MANUFACTURE_DEFAULT_COMPANYID, constant.MANUFACTURE_DEFAULT_ORGID, t.Format("2006-01-02"))
return str
}
... ...
package repository
import (
"fmt"
"github.com/go-pg/pg/v10"
"time"
"github.com/linmadan/egglib-go/persistent/pg/sqlbuilder"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"github.com/linmadan/egglib-go/utils/snowflake"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/pg/models"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/pg/transform"
)
type DeviceDailyRunningRecordRepository struct {
transactionContext *pgTransaction.TransactionContext
}
func (repository *DeviceDailyRunningRecordRepository) nextIdentify() (int64, error) {
IdWorker, err := snowflake.NewIdWorker(1)
if err != nil {
return 0, err
}
id, err := IdWorker.NextId()
return id, err
}
func (repository *DeviceDailyRunningRecordRepository) Save(deviceDailyRunningRecord *domain.DeviceDailyRunningRecord) (*domain.DeviceDailyRunningRecord, error) {
sqlBuildFields := []string{
"device_daily_running_record_id",
"company_id",
"org_id",
"work_station",
"device_id",
"device_code",
"product_date",
"device_running_record_info",
"created_at",
"updated_at",
"deleted_at",
}
insertFieldsSnippet := sqlbuilder.SqlFieldsSnippet(sqlbuilder.RemoveSqlFields(sqlBuildFields, "device_daily_running_record_id", "deleted_at"))
insertPlaceHoldersSnippet := sqlbuilder.SqlPlaceHoldersSnippet(sqlbuilder.RemoveSqlFields(sqlBuildFields, "device_daily_running_record_id", "deleted_at"))
returningFieldsSnippet := sqlbuilder.SqlFieldsSnippet(sqlBuildFields)
updateFields := sqlbuilder.RemoveSqlFields(sqlBuildFields, "device_daily_running_record_id", "deleted_at")
updateFieldsSnippet := sqlbuilder.SqlUpdateFieldsSnippet(updateFields)
tx := repository.transactionContext.PgTx
if deviceDailyRunningRecord.Identify() == nil {
if _, err := tx.QueryOne(
pg.Scan(
&deviceDailyRunningRecord.DeviceDailyRunningRecordId,
&deviceDailyRunningRecord.CompanyId,
&deviceDailyRunningRecord.OrgId,
&deviceDailyRunningRecord.WorkStation,
&deviceDailyRunningRecord.DeviceId,
&deviceDailyRunningRecord.DeviceCode,
&deviceDailyRunningRecord.ProductDate,
&deviceDailyRunningRecord.DeviceRunningRecordInfo,
&deviceDailyRunningRecord.CreatedAt,
&deviceDailyRunningRecord.UpdatedAt,
&deviceDailyRunningRecord.DeletedAt,
),
fmt.Sprintf("INSERT INTO manufacture.device_daily_running_record (%s) VALUES (%s) RETURNING %s", insertFieldsSnippet, insertPlaceHoldersSnippet, returningFieldsSnippet),
//deviceDailyRunningRecord.DeviceDailyRunningRecordId,
deviceDailyRunningRecord.CompanyId,
deviceDailyRunningRecord.OrgId,
deviceDailyRunningRecord.WorkStation,
deviceDailyRunningRecord.DeviceId,
deviceDailyRunningRecord.DeviceCode,
deviceDailyRunningRecord.ProductDate,
deviceDailyRunningRecord.DeviceRunningRecordInfo,
deviceDailyRunningRecord.CreatedAt,
deviceDailyRunningRecord.UpdatedAt,
//deviceDailyRunningRecord.DeletedAt,
); err != nil {
return deviceDailyRunningRecord, err
}
} else {
if _, err := tx.QueryOne(
pg.Scan(
&deviceDailyRunningRecord.DeviceDailyRunningRecordId,
&deviceDailyRunningRecord.CompanyId,
&deviceDailyRunningRecord.OrgId,
&deviceDailyRunningRecord.WorkStation,
&deviceDailyRunningRecord.DeviceId,
&deviceDailyRunningRecord.DeviceCode,
&deviceDailyRunningRecord.ProductDate,
&deviceDailyRunningRecord.DeviceRunningRecordInfo,
&deviceDailyRunningRecord.CreatedAt,
&deviceDailyRunningRecord.UpdatedAt,
&deviceDailyRunningRecord.DeletedAt,
),
fmt.Sprintf("UPDATE manufacture.device_daily_running_record SET %s WHERE device_daily_running_record_id=? RETURNING %s", updateFieldsSnippet, returningFieldsSnippet),
//deviceDailyRunningRecord.DeviceDailyRunningRecordId,
deviceDailyRunningRecord.CompanyId,
deviceDailyRunningRecord.OrgId,
deviceDailyRunningRecord.WorkStation,
deviceDailyRunningRecord.DeviceId,
deviceDailyRunningRecord.DeviceCode,
deviceDailyRunningRecord.ProductDate,
deviceDailyRunningRecord.DeviceRunningRecordInfo,
deviceDailyRunningRecord.CreatedAt,
deviceDailyRunningRecord.UpdatedAt,
//deviceDailyRunningRecord.DeletedAt,
deviceDailyRunningRecord.Identify(),
); err != nil {
return deviceDailyRunningRecord, err
}
}
return deviceDailyRunningRecord, nil
}
func (repository *DeviceDailyRunningRecordRepository) Remove(deviceDailyRunningRecord *domain.DeviceDailyRunningRecord) (*domain.DeviceDailyRunningRecord, error) {
tx := repository.transactionContext.PgTx
deviceDailyRunningRecordModel := new(models.DeviceDailyRunningRecord)
deviceDailyRunningRecordModel.DeviceDailyRunningRecordId = deviceDailyRunningRecord.Identify().(int)
if _, err := tx.Model(deviceDailyRunningRecordModel).WherePK().Delete(); err != nil {
return deviceDailyRunningRecord, err
}
return deviceDailyRunningRecord, nil
}
func (repository *DeviceDailyRunningRecordRepository) FindOne(queryOptions map[string]interface{}) (*domain.DeviceDailyRunningRecord, error) {
tx := repository.transactionContext.PgTx
deviceDailyRunningRecordModel := new(models.DeviceDailyRunningRecord)
query := sqlbuilder.BuildQuery(tx.Model(deviceDailyRunningRecordModel), queryOptions)
query.SetWhereByQueryOption("work_station->>'workStationId'=?", "workStationId")
query.SetWhereByQueryOption("device_code=? ", "deviceCode")
query.SetWhereByQueryOption("product_date=? ", "productDate")
query.SetWhereByQueryOption("device_daily_running_record.device_daily_running_record_id = ?", "deviceDailyRunningRecordId")
if err := query.First(); err != nil {
if err.Error() == "pg: no rows in result set" {
return nil, domain.ErrorNotFound
} else {
return nil, err
}
}
if deviceDailyRunningRecordModel.DeviceDailyRunningRecordId == 0 {
return nil, nil
} else {
return transform.TransformToDeviceDailyRunningRecordDomainModelFromPgModels(deviceDailyRunningRecordModel)
}
}
func (repository *DeviceDailyRunningRecordRepository) Find(queryOptions map[string]interface{}) (int64, []*domain.DeviceDailyRunningRecord, error) {
tx := repository.transactionContext.PgTx
var deviceDailyRunningRecordModels []*models.DeviceDailyRunningRecord
deviceDailyRunningRecords := make([]*domain.DeviceDailyRunningRecord, 0)
query := sqlbuilder.BuildQuery(tx.Model(&deviceDailyRunningRecordModels), queryOptions)
query.SetWhereByQueryOption("company_id = ?", "companyId")
query.SetWhereByQueryOption("org_id = ?", "orgId")
if v, ok := queryOptions["productDate"]; ok && !(v.(time.Time)).IsZero() {
query.Where(`product_date = ?`, v)
}
query.SetOffsetAndLimit(20)
query.SetOrderDirect("device_daily_running_record_id", "DESC")
if count, err := query.SelectAndCount(); err != nil {
return 0, deviceDailyRunningRecords, err
} else {
for _, deviceDailyRunningRecordModel := range deviceDailyRunningRecordModels {
if deviceDailyRunningRecord, err := transform.TransformToDeviceDailyRunningRecordDomainModelFromPgModels(deviceDailyRunningRecordModel); err != nil {
return 0, deviceDailyRunningRecords, err
} else {
deviceDailyRunningRecords = append(deviceDailyRunningRecords, deviceDailyRunningRecord)
}
}
return int64(count), deviceDailyRunningRecords, nil
}
}
func NewDeviceDailyRunningRecordRepository(transactionContext *pgTransaction.TransactionContext) (*DeviceDailyRunningRecordRepository, error) {
if transactionContext == nil {
return nil, fmt.Errorf("transactionContext参数不能为nil")
} else {
return &DeviceDailyRunningRecordRepository{
transactionContext: transactionContext,
}, nil
}
}
... ...
... ... @@ -174,6 +174,12 @@ func (repository *DeviceRepository) Find(queryOptions map[string]interface{}) (i
if v, ok := queryOptions["inDeviceId"]; ok && len(v.([]int)) > 0 {
query.Where(`device_id in (?)`, pg.In(v))
}
if v, ok := queryOptions["workshopId"]; ok && (v.(int)) > 0 {
query.Where(`work_station->>'workshopId'='?'`, v)
}
if v, ok := queryOptions["lineId"]; ok && (v.(int)) > 0 {
query.Where(`work_station->>'lineId'='?'`, v)
}
query.SetWhereByQueryOption("device_code = ?", "deviceCode")
query.SetWhereByQueryOption("device_status = ?", "deviceStatus")
if v, ok := queryOptions["deviceName"]; ok && len(v.(string)) > 0 {
... ...
package repository
import (
"fmt"
"github.com/go-pg/pg/v10"
"github.com/linmadan/egglib-go/persistent/pg/sqlbuilder"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"github.com/linmadan/egglib-go/utils/snowflake"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/pg/models"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/pg/transform"
)
type DeviceRunningRecordRepository struct {
transactionContext *pgTransaction.TransactionContext
}
func (repository *DeviceRunningRecordRepository) nextIdentify() (int64, error) {
IdWorker, err := snowflake.NewIdWorker(1)
if err != nil {
return 0, err
}
id, err := IdWorker.NextId()
return id, err
}
func (repository *DeviceRunningRecordRepository) Save(deviceRunningRecord *domain.DeviceRunningRecord) (*domain.DeviceRunningRecord, error) {
sqlBuildFields := []string{
"device_running_record_id",
"company_id",
"org_id",
"work_station",
"device_id",
"device_code",
"device_running_record_info",
"created_at",
}
insertFieldsSnippet := sqlbuilder.SqlFieldsSnippet(sqlbuilder.RemoveSqlFields(sqlBuildFields, "device_running_record_id"))
insertPlaceHoldersSnippet := sqlbuilder.SqlPlaceHoldersSnippet(sqlbuilder.RemoveSqlFields(sqlBuildFields, "device_running_record_id"))
returningFieldsSnippet := sqlbuilder.SqlFieldsSnippet(sqlBuildFields)
updateFields := sqlbuilder.RemoveSqlFields(sqlBuildFields, "device_running_record_id")
updateFieldsSnippet := sqlbuilder.SqlUpdateFieldsSnippet(updateFields)
tx := repository.transactionContext.PgTx
if deviceRunningRecord.Identify() == nil {
if _, err := tx.QueryOne(
pg.Scan(
&deviceRunningRecord.DeviceRunningRecordId,
&deviceRunningRecord.CompanyId,
&deviceRunningRecord.OrgId,
&deviceRunningRecord.WorkStation,
&deviceRunningRecord.DeviceId,
&deviceRunningRecord.DeviceCode,
&deviceRunningRecord.DeviceRunningRecordInfo,
&deviceRunningRecord.CreatedAt,
),
fmt.Sprintf("INSERT INTO manufacture.device_running_record (%s) VALUES (%s) RETURNING %s", insertFieldsSnippet, insertPlaceHoldersSnippet, returningFieldsSnippet),
//deviceRunningRecord.DeviceRunningRecordId,
deviceRunningRecord.CompanyId,
deviceRunningRecord.OrgId,
deviceRunningRecord.WorkStation,
deviceRunningRecord.DeviceId,
deviceRunningRecord.DeviceCode,
deviceRunningRecord.DeviceRunningRecordInfo,
deviceRunningRecord.CreatedAt,
); err != nil {
return deviceRunningRecord, err
}
} else {
if _, err := tx.QueryOne(
pg.Scan(
&deviceRunningRecord.DeviceRunningRecordId,
&deviceRunningRecord.CompanyId,
&deviceRunningRecord.OrgId,
&deviceRunningRecord.WorkStation,
&deviceRunningRecord.DeviceId,
&deviceRunningRecord.DeviceCode,
&deviceRunningRecord.DeviceRunningRecordInfo,
&deviceRunningRecord.CreatedAt,
),
fmt.Sprintf("UPDATE manufacture.device_running_record SET %s WHERE device_running_record_id=? RETURNING %s", updateFieldsSnippet, returningFieldsSnippet),
//deviceRunningRecord.DeviceRunningRecordId,
deviceRunningRecord.CompanyId,
deviceRunningRecord.OrgId,
deviceRunningRecord.WorkStation,
deviceRunningRecord.DeviceId,
deviceRunningRecord.DeviceCode,
deviceRunningRecord.DeviceRunningRecordInfo,
deviceRunningRecord.CreatedAt,
deviceRunningRecord.Identify(),
); err != nil {
return deviceRunningRecord, err
}
}
return deviceRunningRecord, nil
}
func (repository *DeviceRunningRecordRepository) Remove(deviceRunningRecord *domain.DeviceRunningRecord) (*domain.DeviceRunningRecord, error) {
tx := repository.transactionContext.PgTx
deviceRunningRecordModel := new(models.DeviceRunningRecord)
deviceRunningRecordModel.DeviceRunningRecordId = deviceRunningRecord.Identify().(int)
if _, err := tx.Model(deviceRunningRecordModel).WherePK().Delete(); err != nil {
return deviceRunningRecord, err
}
return deviceRunningRecord, nil
}
func (repository *DeviceRunningRecordRepository) FindOne(queryOptions map[string]interface{}) (*domain.DeviceRunningRecord, error) {
tx := repository.transactionContext.PgTx
deviceRunningRecordModel := new(models.DeviceRunningRecord)
query := sqlbuilder.BuildQuery(tx.Model(deviceRunningRecordModel), queryOptions)
query.SetWhereByQueryOption("device_running_record.device_running_record_id = ?", "deviceRunningRecordId")
if err := query.First(); err != nil {
if err.Error() == "pg: no rows in result set" {
return nil, fmt.Errorf("没有此资源")
} else {
return nil, err
}
}
if deviceRunningRecordModel.DeviceRunningRecordId == 0 {
return nil, nil
} else {
return transform.TransformToDeviceRunningRecordDomainModelFromPgModels(deviceRunningRecordModel)
}
}
func (repository *DeviceRunningRecordRepository) Find(queryOptions map[string]interface{}) (int64, []*domain.DeviceRunningRecord, error) {
tx := repository.transactionContext.PgTx
var deviceRunningRecordModels []*models.DeviceRunningRecord
deviceRunningRecords := make([]*domain.DeviceRunningRecord, 0)
query := sqlbuilder.BuildQuery(tx.Model(&deviceRunningRecordModels), queryOptions)
query.SetOffsetAndLimit(20)
query.SetOrderDirect("device_running_record_id", "DESC")
if count, err := query.SelectAndCount(); err != nil {
return 0, deviceRunningRecords, err
} else {
for _, deviceRunningRecordModel := range deviceRunningRecordModels {
if deviceRunningRecord, err := transform.TransformToDeviceRunningRecordDomainModelFromPgModels(deviceRunningRecordModel); err != nil {
return 0, deviceRunningRecords, err
} else {
deviceRunningRecords = append(deviceRunningRecords, deviceRunningRecord)
}
}
return int64(count), deviceRunningRecords, nil
}
}
func NewDeviceRunningRecordRepository(transactionContext *pgTransaction.TransactionContext) (*DeviceRunningRecordRepository, error) {
if transactionContext == nil {
return nil, fmt.Errorf("transactionContext参数不能为nil")
} else {
return &DeviceRunningRecordRepository{
transactionContext: transactionContext,
}, nil
}
}
... ...
... ... @@ -166,6 +166,9 @@ func (repository *ProductAttendanceRecordRepository) Find(queryOptions map[strin
query := sqlbuilder.BuildQuery(tx.Model(&productAttendanceRecordModels), queryOptions)
query.SetWhereByQueryOption("company_id = ?", "companyId")
query.SetWhereByQueryOption("org_id = ?", "orgId")
query.SetWhereByQueryOption("work_station->>'workshopId'='?'", "workshopId")
query.SetWhereByQueryOption("work_station->>'lineId'='?'", "lineId")
query.SetWhereByQueryOption("work_station->>'sectionId'='?'", "sectionId")
query.SetWhereByQueryOption("attendance_status & ? >0", "attendanceStatus")
if v, ok := queryOptions["inOrgIds"]; ok && len(v.([]int)) > 0 {
query.Where(`org_id in (?)`, pg.In(v))
... ... @@ -188,6 +191,9 @@ func (repository *ProductAttendanceRecordRepository) Find(queryOptions map[strin
if v, ok := queryOptions["signEndTime"]; ok && !((v.(time.Time)).IsZero()) {
query.Where("created_at<?", v.(time.Time))
}
if v, ok := queryOptions["employeeType"]; ok && (v.(int)) > 0 {
query.Where("product_worker->>'employeeType'='?'", v.(int))
}
query.SetOffsetAndLimit(domain.MaxQueryRow)
query.SetOrderDirect("product_attendance_id", "DESC")
if count, err := query.SelectAndCount(); err != nil {
... ...
... ... @@ -150,6 +150,16 @@ func (repository *ProductPlanDispatchRecordRepository) Find(queryOptions map[str
var productPlanDispatchRecordModels []*models.ProductPlanDispatchRecord
productPlanDispatchRecords := make([]*domain.ProductPlanDispatchRecord, 0)
query := sqlbuilder.BuildQuery(tx.Model(&productPlanDispatchRecordModels), queryOptions)
query.SetWhereByQueryOption("company_id = ?", "companyId")
query.SetWhereByQueryOption("org_id = ?", "orgId")
query.SetWhereByQueryOption("work_station->>'workshopId'='?'", "workshopId")
if v, ok := queryOptions["batchNumber"]; ok && len(v.(string)) > 0 {
query.Where(fmt.Sprintf(`batch_number like '%%%v%%'`, v))
}
if v, ok := queryOptions["workshopName"]; ok && len(v.(string)) > 0 {
query.Where(fmt.Sprintf(`work_station->>'workshopName' like '%%%v%%'`, v))
}
query.SetWhereByQueryOption("plan_dispatch_status=?", "planDispatchStatus")
query.SetOffsetAndLimit(domain.MaxQueryRow)
query.SetOrderDirect("product_plan_dispatch_record_id", "DESC")
if count, err := query.SelectAndCount(); err != nil {
... ...
... ... @@ -174,7 +174,7 @@ func (repository *ProductPlanRepository) Find(queryOptions map[string]interface{
query := sqlbuilder.BuildQuery(tx.Model(&productPlanModels), queryOptions)
query.SetWhereByQueryOption("company_id = ?", "companyId")
query.SetWhereByQueryOption("org_id = ?", "orgId")
query.SetWhereByQueryOption("work_station->>'workshopId'='?'", "workshopId")
if v, ok := queryOptions["batchNumber"]; ok && len(v.(string)) > 0 {
query.Where(fmt.Sprintf(`batch_number like '%%%v%%'`, v))
}
... ...
... ... @@ -174,6 +174,12 @@ func (repository *ProductRecordRepository) Find(queryOptions map[string]interfac
if v, ok := queryOptions["batchNumber"]; ok && len(v.(string)) > 0 {
query.Where(fmt.Sprintf(`product_record_info->>'batchNumber' like '%%%v%%'`, v))
}
if v, ok := queryOptions["employeeId"]; ok && v.(int) > 0 {
query.Where(fmt.Sprintf(`product_worker->>'userId' = '%v'`, v))
}
if v, ok := queryOptions["productPlanId"]; ok && v.(int) > 0 {
query.Where(fmt.Sprintf(`product_record_info->>'productPlanId' = '%v'`, v))
}
query.SetOffsetAndLimit(domain.MaxQueryRow)
query.SetOrderDirect("product_record_id", "DESC")
if count, err := query.SelectAndCount(); err != nil {
... ...
... ... @@ -107,6 +107,14 @@ func (repository *WorkshopWorkTimeRecordRepository) FindOne(queryOptions map[str
tx := repository.transactionContext.PgTx
workshopWorkTimeRecordModel := new(models.WorkshopWorkTimeRecord)
query := sqlbuilder.BuildQuery(tx.Model(workshopWorkTimeRecordModel), queryOptions)
query.SetWhereByQueryOption("company_id = ?", "companyId")
query.SetWhereByQueryOption("org_id = ?", "orgId")
if v, ok := queryOptions["workStationId"]; ok && len(v.(string)) > 0 {
query.Where(`work_station->>'workStationId' = ?`, v)
}
if v, ok := queryOptions["recordDate"]; ok {
query.Where("record_date=?", v)
}
query.SetWhereByQueryOption("workshop_work_time_record.workshop_work_time_record_id = ?", "workshopWorkTimeRecordId")
if err := query.First(); err != nil {
if err.Error() == "pg: no rows in result set" {
... ...
... ... @@ -29,6 +29,24 @@ func GetNextMonthFirstDay(d time.Time) time.Time {
return GetZeroTime(d)
}
// GetNextMonthFirstDay 获取传入的时间所在月份的最后一天,即某月最后一天的23:59:59。如传入time.Now(), 返回当前月份的最后一天的23:59:59。
func GetCurrentMonthFirstDay(t time.Time) time.Time {
y, m, d := t.Date()
result := time.Date(y, m, d, 0, 0, 0, 0, time.Local)
return result
}
func GetCurrentWeekFirstDay(t time.Time) time.Time {
d := t.Weekday()
result := GetZeroTime(t)
if d == time.Sunday {
result = result.Add(-time.Hour * 24 * 6)
} else {
result = result.Add(-time.Hour * 24 * (time.Duration(d) - 1))
}
return result
}
// GetZeroTime 获取某一天的0点时间
func GetZeroTime(d time.Time) time.Time {
return time.Date(d.Year(), d.Month(), d.Day(), 0, 0, 0, 0, time.Local)
... ...
... ... @@ -7,6 +7,7 @@ import (
"github.com/beego/beego/v2/core/validation"
"github.com/bwmarrin/snowflake"
jsonlib "github.com/linmadan/egglib-go/utils/json"
"github.com/shopspring/decimal"
"io"
"reflect"
"strconv"
... ... @@ -381,6 +382,7 @@ func SubStr(str string, start, length int) string {
return string(rs[start:end])
}
//生成新ID
var snowFlakeNode *snowflake.Node
... ... @@ -395,4 +397,12 @@ func NewSnowflakeId() (int64, error) {
// Generate a snowflake ID.
id := snowFlakeNode.Generate()
return id.Int64(), nil
}
\ No newline at end of file
}
func Round(value float64, places int32) float64 {
quantity := decimal.NewFromFloat(value)
d := quantity.Round(places)
rsp, _ := d.Float64()
return rsp
}
... ...