正在显示
29 个修改的文件
包含
469 行增加
和
98 行删除
| @@ -18,6 +18,12 @@ type EmployeeAttendanceRecordDto struct { | @@ -18,6 +18,12 @@ type EmployeeAttendanceRecordDto struct { | ||
| 18 | //*domain.ProductAttendanceRecordExt | 18 | //*domain.ProductAttendanceRecordExt |
| 19 | // 考勤状态 1.未审核 2:已审核 4.自动审核 | 19 | // 考勤状态 1.未审核 2:已审核 4.自动审核 |
| 20 | AttendanceStatus int `json:"attendanceStatus"` | 20 | AttendanceStatus int `json:"attendanceStatus"` |
| 21 | + // 考勤类型 1.正常 2.支援 | ||
| 22 | + AttendanceTypeDescription string `json:"attendanceTypeDescription,omitempty"` | ||
| 23 | + // 员工类型描述 1:固定 2:派遣 3.临时 | ||
| 24 | + EmployeeTypeDescription string `json:"employeeTypeDescription,omitempty"` | ||
| 25 | + // 考勤状态 1.未审核 2:已审核 4.自动审核 | ||
| 26 | + AttendanceStatusDescription string `json:"attendanceStatusDescription"` | ||
| 21 | // 工时 | 27 | // 工时 |
| 22 | WorkTime float64 `json:"workTime"` | 28 | WorkTime float64 `json:"workTime"` |
| 23 | // 组织名称 | 29 | // 组织名称 |
| @@ -38,6 +44,9 @@ func (d *EmployeeAttendanceRecordDto) LoadDto(m *domain.ProductAttendanceRecord, | @@ -38,6 +44,9 @@ func (d *EmployeeAttendanceRecordDto) LoadDto(m *domain.ProductAttendanceRecord, | ||
| 38 | d.WorkTime = m.WorkTimeAfter | 44 | d.WorkTime = m.WorkTimeAfter |
| 39 | //d.WorkTimeAfter = m.WorkTimeAfter | 45 | //d.WorkTimeAfter = m.WorkTimeAfter |
| 40 | d.AttendanceStatus = m.AttendanceStatus | 46 | d.AttendanceStatus = m.AttendanceStatus |
| 47 | + d.AttendanceTypeDescription = domain.ParticipateTypeDescription(m.AttendanceType) | ||
| 48 | + d.EmployeeTypeDescription = domain.EmployeeTypeDescription(m.ProductWorker.EmployeeType) | ||
| 49 | + d.AttendanceStatusDescription = domain.AttendanceStatusDescription(m.AttendanceStatus) | ||
| 41 | d.AuthFlag = domain.CheckOrgAuth(orgId, m.OrgId) | 50 | d.AuthFlag = domain.CheckOrgAuth(orgId, m.OrgId) |
| 42 | if m.Ext != nil { | 51 | if m.Ext != nil { |
| 43 | d.OrgName = m.Ext.OrgName | 52 | d.OrgName = m.Ext.OrgName |
| @@ -44,7 +44,7 @@ func (attendanceService *AttendanceService) ApproveAttendance(cmd *command.Appro | @@ -44,7 +44,7 @@ func (attendanceService *AttendanceService) ApproveAttendance(cmd *command.Appro | ||
| 44 | return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) | 44 | return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | - if err = attendance.Approve(user, cmd.WorkTimeAfter); err != nil { | 47 | + if err = attendance.Approve(user, cmd.WorkTimeAfter, domain.AttendanceApproved); err != nil { |
| 48 | return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) | 48 | return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) |
| 49 | } | 49 | } |
| 50 | 50 | ||
| @@ -119,6 +119,7 @@ func (attendanceService *AttendanceService) CreateAttendance(operateInfo *domain | @@ -119,6 +119,7 @@ func (attendanceService *AttendanceService) CreateAttendance(operateInfo *domain | ||
| 119 | ProductGroupId: productGroup.ProductGroupId, | 119 | ProductGroupId: productGroup.ProductGroupId, |
| 120 | }), | 120 | }), |
| 121 | } | 121 | } |
| 122 | + newAttendance.WorkTimeBefore = newAttendance.ComputeWorkTimeBefore() | ||
| 122 | var attendanceRepository domain.ProductAttendanceRecordRepository | 123 | var attendanceRepository domain.ProductAttendanceRecordRepository |
| 123 | 124 | ||
| 124 | attendanceRepository, _, _ = factory.FastPgAttendance(transactionContext, 0) | 125 | attendanceRepository, _, _ = factory.FastPgAttendance(transactionContext, 0) |
| @@ -36,6 +36,9 @@ func (crontabService *CrontabService) initTask() { | @@ -36,6 +36,9 @@ func (crontabService *CrontabService) initTask() { | ||
| 36 | return srv.PullPrdMoNewest() | 36 | return srv.PullPrdMoNewest() |
| 37 | }) | 37 | }) |
| 38 | task.AddTask("PullPrdMoK3cloud", PullPrdMoK3cloud) | 38 | task.AddTask("PullPrdMoK3cloud", PullPrdMoK3cloud) |
| 39 | + | ||
| 40 | + autoApproveAttendanceRecord := task.NewTask("autoApproveAttendanceRecord", "0 */1 * * * *", AutoApproveProductAttendanceRecord) | ||
| 41 | + task.AddTask("autoApproveAttendanceRecord", autoApproveAttendanceRecord) | ||
| 39 | } | 42 | } |
| 40 | 43 | ||
| 41 | func (crontabService *CrontabService) StartCrontabTask() { | 44 | func (crontabService *CrontabService) StartCrontabTask() { |
| 1 | +package crontab | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "context" | ||
| 5 | + "fmt" | ||
| 6 | + pgTransaction "github.com/linmadan/egglib-go/transaction/pg" | ||
| 7 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/factory" | ||
| 8 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain" | ||
| 9 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/dao" | ||
| 10 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/domainService" | ||
| 11 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log" | ||
| 12 | +) | ||
| 13 | + | ||
| 14 | +// 定时审核生产考勤记录 | ||
| 15 | +func AutoApproveProductAttendanceRecord(ctx context.Context) error { | ||
| 16 | + defer func() { | ||
| 17 | + if r := recover(); r != nil { | ||
| 18 | + log.Logger.Error(fmt.Sprintf("%v", r)) | ||
| 19 | + } | ||
| 20 | + }() | ||
| 21 | + transactionContext, err := factory.CreateTransactionContext(nil) | ||
| 22 | + if err != nil { | ||
| 23 | + return err | ||
| 24 | + } | ||
| 25 | + if err := transactionContext.StartTransaction(); err != nil { | ||
| 26 | + return err | ||
| 27 | + } | ||
| 28 | + defer func() { | ||
| 29 | + if err != nil { | ||
| 30 | + log.Logger.Error("【定时审核生产考勤记录】 失败:" + err.Error()) | ||
| 31 | + } | ||
| 32 | + transactionContext.RollbackTransaction() | ||
| 33 | + }() | ||
| 34 | + | ||
| 35 | + attendanceRecordDao, _ := dao.NewAttendanceRecordDao(transactionContext.(*pgTransaction.TransactionContext)) | ||
| 36 | + var records []*domain.ProductAttendanceRecord | ||
| 37 | + _, records, err = attendanceRecordDao.RecentUnApprovedAttendanceRecord(24, 2) | ||
| 38 | + if err != nil { | ||
| 39 | + return err | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + approveAttendanceRecordsService, _ := domainService.NewPGApproveAttendanceRecordsService(transactionContext.(*pgTransaction.TransactionContext)) | ||
| 43 | + | ||
| 44 | + if _, err = approveAttendanceRecordsService.BatchApproveAttendanceRecords(nil, records, 0, 0, domain.AttendanceAutoApproved); err != nil { | ||
| 45 | + return err | ||
| 46 | + } | ||
| 47 | + if err = transactionContext.CommitTransaction(); err != nil { | ||
| 48 | + return err | ||
| 49 | + } | ||
| 50 | + return nil | ||
| 51 | +} |
| 1 | +package crontab | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "context" | ||
| 5 | + "fmt" | ||
| 6 | + pgTransaction "github.com/linmadan/egglib-go/transaction/pg" | ||
| 7 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/factory" | ||
| 8 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain" | ||
| 9 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/dao" | ||
| 10 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/domainService" | ||
| 11 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log" | ||
| 12 | +) | ||
| 13 | + | ||
| 14 | +// 定时审核生产记录 | ||
| 15 | +func AutoApproveProductRecord(ctx context.Context) error { | ||
| 16 | + defer func() { | ||
| 17 | + if r := recover(); r != nil { | ||
| 18 | + log.Logger.Error(fmt.Sprintf("%v", r)) | ||
| 19 | + } | ||
| 20 | + }() | ||
| 21 | + transactionContext, err := factory.CreateTransactionContext(nil) | ||
| 22 | + if err != nil { | ||
| 23 | + return err | ||
| 24 | + } | ||
| 25 | + if err := transactionContext.StartTransaction(); err != nil { | ||
| 26 | + return err | ||
| 27 | + } | ||
| 28 | + defer func() { | ||
| 29 | + if err != nil { | ||
| 30 | + log.Logger.Error("【定时审核生产考勤记录】 失败:" + err.Error()) | ||
| 31 | + } | ||
| 32 | + transactionContext.RollbackTransaction() | ||
| 33 | + }() | ||
| 34 | + | ||
| 35 | + attendanceRecordDao, _ := dao.NewProductRecordDao(transactionContext.(*pgTransaction.TransactionContext)) | ||
| 36 | + var records []*domain.ProductRecord | ||
| 37 | + _, records, err = attendanceRecordDao.RecentUnApprovedProductRecord(24, 2, domain.RecordTypeSecondLevelWeigh) | ||
| 38 | + if err != nil { | ||
| 39 | + return err | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + approveAttendanceRecordsService, _ := domainService.NewPGProductRecordService(transactionContext.(*pgTransaction.TransactionContext)) | ||
| 43 | + | ||
| 44 | + if _, err = approveAttendanceRecordsService.BatchApprove(records, 0, 0, domain.AttendanceAutoApproved); err != nil { | ||
| 45 | + return err | ||
| 46 | + } | ||
| 47 | + if err = transactionContext.CommitTransaction(); err != nil { | ||
| 48 | + return err | ||
| 49 | + } | ||
| 50 | + return nil | ||
| 51 | +} |
| @@ -23,7 +23,7 @@ type CreateProductCalendarCommand struct { | @@ -23,7 +23,7 @@ type CreateProductCalendarCommand struct { | ||
| 23 | // 上班班次 1:全天 2:白班 4:中班 8:夜班 | 23 | // 上班班次 1:全天 2:白班 4:中班 8:夜班 |
| 24 | WorkOn int `cname:"上班班次 1:全天 2:白班 4:中班 8:夜班" json:"workOn" valid:"Required"` | 24 | WorkOn int `cname:"上班班次 1:全天 2:白班 4:中班 8:夜班" json:"workOn" valid:"Required"` |
| 25 | // 日历选择 | 25 | // 日历选择 |
| 26 | - CalendarSelected []string `cname:"日历选择" json:"calendarSelected" valid:"Required"` | 26 | + CalendarSelected []int `cname:"日历选择" json:"calendarSelected" valid:"Required"` |
| 27 | // 上岗时间 | 27 | // 上岗时间 |
| 28 | InWorkAt string `cname:"上岗时间" json:"inWorkAt" valid:"Required"` | 28 | InWorkAt string `cname:"上岗时间" json:"inWorkAt" valid:"Required"` |
| 29 | // 下岗时间 | 29 | // 下岗时间 |
| @@ -2,7 +2,7 @@ package dto | @@ -2,7 +2,7 @@ package dto | ||
| 2 | 2 | ||
| 3 | import ( | 3 | import ( |
| 4 | "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain" | 4 | "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain" |
| 5 | - "strings" | 5 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils" |
| 6 | ) | 6 | ) |
| 7 | 7 | ||
| 8 | type ProductCalendarDto struct { | 8 | type ProductCalendarDto struct { |
| @@ -17,7 +17,7 @@ type ProductCalendarDto struct { | @@ -17,7 +17,7 @@ type ProductCalendarDto struct { | ||
| 17 | // 上班班次 1:全天 2:白班 4:中班 8:夜班 | 17 | // 上班班次 1:全天 2:白班 4:中班 8:夜班 |
| 18 | WorkOn int `json:"workOn,omitempty"` | 18 | WorkOn int `json:"workOn,omitempty"` |
| 19 | // 日历选择 | 19 | // 日历选择 |
| 20 | - CalendarSelected []string `json:"calendarSelected,omitempty"` | 20 | + CalendarSelected []int `json:"calendarSelected,omitempty"` |
| 21 | // 上岗时间 | 21 | // 上岗时间 |
| 22 | InWorkAt string `json:"inWorkAt,omitempty"` | 22 | InWorkAt string `json:"inWorkAt,omitempty"` |
| 23 | // 下岗时间 | 23 | // 下岗时间 |
| @@ -27,7 +27,7 @@ type ProductCalendarDto struct { | @@ -27,7 +27,7 @@ type ProductCalendarDto struct { | ||
| 27 | // 工时 (单位 h) | 27 | // 工时 (单位 h) |
| 28 | WorkTime float64 `json:"workTime,omitempty"` | 28 | WorkTime float64 `json:"workTime,omitempty"` |
| 29 | // 已选择日历 | 29 | // 已选择日历 |
| 30 | - CalendarSelectedString string `json:"calendarSelectedString,omitempty"` | 30 | + //CalendarSelectedString string `json:"calendarSelectedString,omitempty"` |
| 31 | // 组织名称 | 31 | // 组织名称 |
| 32 | OrgName string `json:"orgName"` | 32 | OrgName string `json:"orgName"` |
| 33 | // 权限标识 (当前登录组织匹配为true,否则false) | 33 | // 权限标识 (当前登录组织匹配为true,否则false) |
| @@ -38,12 +38,12 @@ func (d *ProductCalendarDto) LoadDto(m *domain.ProductCalendar, orgId int) *Prod | @@ -38,12 +38,12 @@ func (d *ProductCalendarDto) LoadDto(m *domain.ProductCalendar, orgId int) *Prod | ||
| 38 | d.ProductCalendarId = m.ProductCalendarId | 38 | d.ProductCalendarId = m.ProductCalendarId |
| 39 | d.WorkStation = m.WorkStation | 39 | d.WorkStation = m.WorkStation |
| 40 | d.WorkOn = m.WorkOn | 40 | d.WorkOn = m.WorkOn |
| 41 | - d.CalendarSelected = m.CalendarSelected | 41 | + d.CalendarSelected = utils.ToArrayInt(m.CalendarSelected) |
| 42 | d.InWorkAt = m.InWorkAt | 42 | d.InWorkAt = m.InWorkAt |
| 43 | d.OutWorkAt = m.OutWorkAt | 43 | d.OutWorkAt = m.OutWorkAt |
| 44 | d.BreakTime = m.BreakTime | 44 | d.BreakTime = m.BreakTime |
| 45 | d.WorkTime = m.WorkTime | 45 | d.WorkTime = m.WorkTime |
| 46 | - d.CalendarSelectedString = strings.Join(m.CalendarSelected, "/") | 46 | + //d.CalendarSelectedString = strings.Join(m.CalendarSelected, "/") |
| 47 | d.AuthFlag = domain.CheckOrgAuth(orgId, m.OrgId) | 47 | d.AuthFlag = domain.CheckOrgAuth(orgId, m.OrgId) |
| 48 | if m.Ext != nil { | 48 | if m.Ext != nil { |
| 49 | d.OrgName = m.Ext.OrgName | 49 | d.OrgName = m.Ext.OrgName |
| @@ -66,7 +66,7 @@ func (productCalendarService *ProductCalendarService) CreateProductCalendar(oper | @@ -66,7 +66,7 @@ func (productCalendarService *ProductCalendarService) CreateProductCalendar(oper | ||
| 66 | OrgId: cmd.OrgId, | 66 | OrgId: cmd.OrgId, |
| 67 | WorkStation: workStation, | 67 | WorkStation: workStation, |
| 68 | WorkOn: cmd.WorkOn, | 68 | WorkOn: cmd.WorkOn, |
| 69 | - CalendarSelected: cmd.CalendarSelected, | 69 | + CalendarSelected: utils.ToArrayString(cmd.CalendarSelected), |
| 70 | InWorkAt: cmd.InWorkAt, | 70 | InWorkAt: cmd.InWorkAt, |
| 71 | OutWorkAt: cmd.OutWorkAt, | 71 | OutWorkAt: cmd.OutWorkAt, |
| 72 | BreakTime: cmd.BreakTime, | 72 | BreakTime: cmd.BreakTime, |
| @@ -85,7 +85,10 @@ func (productCalendarService *ProductCalendarService) CreateProductCalendar(oper | @@ -85,7 +85,10 @@ func (productCalendarService *ProductCalendarService) CreateProductCalendar(oper | ||
| 85 | if err := transactionContext.CommitTransaction(); err != nil { | 85 | if err := transactionContext.CommitTransaction(); err != nil { |
| 86 | return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | 86 | return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) |
| 87 | } | 87 | } |
| 88 | - return productCalendar, nil | 88 | + |
| 89 | + result := &dto.ProductCalendarDto{} | ||
| 90 | + result.LoadDto(productCalendar, 0) | ||
| 91 | + return result, nil | ||
| 89 | } | 92 | } |
| 90 | } | 93 | } |
| 91 | 94 | ||
| @@ -317,7 +320,10 @@ func (productCalendarService *ProductCalendarService) UpdateProductCalendar(cmd | @@ -317,7 +320,10 @@ func (productCalendarService *ProductCalendarService) UpdateProductCalendar(cmd | ||
| 317 | if err := transactionContext.CommitTransaction(); err != nil { | 320 | if err := transactionContext.CommitTransaction(); err != nil { |
| 318 | return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | 321 | return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) |
| 319 | } | 322 | } |
| 320 | - return productCalendar, nil | 323 | + |
| 324 | + result := &dto.ProductCalendarDto{} | ||
| 325 | + result.LoadDto(productCalendar, 0) | ||
| 326 | + return result, nil | ||
| 321 | } | 327 | } |
| 322 | } | 328 | } |
| 323 | 329 |
| @@ -28,6 +28,10 @@ type EmployeeProductRecordDto struct { | @@ -28,6 +28,10 @@ type EmployeeProductRecordDto struct { | ||
| 28 | AuthFlag bool `json:"authFlag"` | 28 | AuthFlag bool `json:"authFlag"` |
| 29 | // 合格率 百分比 | 29 | // 合格率 百分比 |
| 30 | QualificationRate int `json:"qualificationRate"` | 30 | QualificationRate int `json:"qualificationRate"` |
| 31 | + // 考勤类型 1.正常 2.支援 | ||
| 32 | + ParticipateTypeDescription string `json:"participateTypeDescription,omitempty"` | ||
| 33 | + // 员工类型描述 1:固定 2:派遣 3.临时 | ||
| 34 | + EmployeeTypeDescription string `json:"employeeTypeDescription,omitempty"` | ||
| 31 | } | 35 | } |
| 32 | 36 | ||
| 33 | func (d *EmployeeProductRecordDto) LoadDto(m *domain.EmployeeProductRecord, orgId int) *EmployeeProductRecordDto { | 37 | func (d *EmployeeProductRecordDto) LoadDto(m *domain.EmployeeProductRecord, orgId int) *EmployeeProductRecordDto { |
| @@ -41,6 +45,8 @@ func (d *EmployeeProductRecordDto) LoadDto(m *domain.EmployeeProductRecord, orgI | @@ -41,6 +45,8 @@ func (d *EmployeeProductRecordDto) LoadDto(m *domain.EmployeeProductRecord, orgI | ||
| 41 | d.SecondLevelWeigh = m.SecondLevelWeigh | 45 | d.SecondLevelWeigh = m.SecondLevelWeigh |
| 42 | d.QualificationRate = m.QualificationRate() | 46 | d.QualificationRate = m.QualificationRate() |
| 43 | d.CreatedAt = m.CreatedAt.Format("2006-01-02") | 47 | d.CreatedAt = m.CreatedAt.Format("2006-01-02") |
| 48 | + d.ParticipateTypeDescription = domain.ParticipateTypeDescription(m.ParticipateType) | ||
| 49 | + d.EmployeeTypeDescription = domain.EmployeeTypeDescription(m.ProductWorker.EmployeeType) | ||
| 44 | d.AuthFlag = domain.CheckOrgAuth(orgId, m.OrgId) | 50 | d.AuthFlag = domain.CheckOrgAuth(orgId, m.OrgId) |
| 45 | if m.Ext != nil { | 51 | if m.Ext != nil { |
| 46 | d.OrgName = m.Ext.OrgName | 52 | d.OrgName = m.Ext.OrgName |
| @@ -19,7 +19,7 @@ type ProductLevelTwoRecord struct { | @@ -19,7 +19,7 @@ type ProductLevelTwoRecord struct { | ||
| 19 | // 产能-审核后 | 19 | // 产能-审核后 |
| 20 | WeighAfter float64 `json:"weighAfter"` | 20 | WeighAfter float64 `json:"weighAfter"` |
| 21 | // 审核状态 1:未审核 2:已审核 | 21 | // 审核状态 1:未审核 2:已审核 |
| 22 | - ApproveStatus int64 `json:"approveStatus"` | 22 | + ApproveStatus int `json:"approveStatus"` |
| 23 | // 审核时间 | 23 | // 审核时间 |
| 24 | ApproveAt string `json:"approveAt"` | 24 | ApproveAt string `json:"approveAt"` |
| 25 | // 计划的产品名称 | 25 | // 计划的产品名称 |
| @@ -27,6 +27,8 @@ type ProductLevelTwoRecord struct { | @@ -27,6 +27,8 @@ type ProductLevelTwoRecord struct { | ||
| 27 | // 批号 | 27 | // 批号 |
| 28 | BatchNumber string `json:"batchNumber,omitempty"` | 28 | BatchNumber string `json:"batchNumber,omitempty"` |
| 29 | 29 | ||
| 30 | + // 创建日期 | ||
| 31 | + CreatedDate string `json:"createdDate,omitempty"` | ||
| 30 | // 创建时间 | 32 | // 创建时间 |
| 31 | CreatedAt string `json:"createdAt,omitempty"` | 33 | CreatedAt string `json:"createdAt,omitempty"` |
| 32 | // 组织名称 | 34 | // 组织名称 |
| @@ -47,8 +49,8 @@ func (d *ProductLevelTwoRecord) LoadDto(m *domain.ProductRecord, orgId int) *Pro | @@ -47,8 +49,8 @@ func (d *ProductLevelTwoRecord) LoadDto(m *domain.ProductRecord, orgId int) *Pro | ||
| 47 | } | 49 | } |
| 48 | d.PlanProductName = m.ProductRecordInfo.PlanProductName | 50 | d.PlanProductName = m.ProductRecordInfo.PlanProductName |
| 49 | d.BatchNumber = m.ProductRecordInfo.BatchNumber | 51 | d.BatchNumber = m.ProductRecordInfo.BatchNumber |
| 50 | - | ||
| 51 | - d.CreatedAt = m.CreatedAt.Format("2006-01-02") | 52 | + d.CreatedDate = m.CreatedAt.Format("2006-01-02") |
| 53 | + d.CreatedAt = m.CreatedAt.Format("2006-01-02 15:04:05") | ||
| 52 | d.AuthFlag = domain.CheckOrgAuth(orgId, m.OrgId) | 54 | d.AuthFlag = domain.CheckOrgAuth(orgId, m.OrgId) |
| 53 | if m.Ext != nil { | 55 | if m.Ext != nil { |
| 54 | d.OrgName = m.Ext.OrgName | 56 | d.OrgName = m.Ext.OrgName |
| @@ -35,7 +35,7 @@ type SearchEmployeeProductRecordQuery struct { | @@ -35,7 +35,7 @@ type SearchEmployeeProductRecordQuery struct { | ||
| 35 | // 姓名 | 35 | // 姓名 |
| 36 | UserName string `cname:"姓名" json:"userName"` | 36 | UserName string `cname:"姓名" json:"userName"` |
| 37 | // 员工类型 1:固定 2:派遣 3.临时 | 37 | // 员工类型 1:固定 2:派遣 3.临时 |
| 38 | - EmployeeType string `cname:"员工类型 1:固定 2:派遣 3.临时" json:"employeeType"` | 38 | + EmployeeType int `cname:"员工类型 1:固定 2:派遣 3.临时" json:"employeeType"` |
| 39 | // 开始时间 | 39 | // 开始时间 |
| 40 | BeginTime string `cname:"开始时间" json:"beginTime"` | 40 | BeginTime string `cname:"开始时间" json:"beginTime"` |
| 41 | // 结束时间 | 41 | // 结束时间 |
| @@ -3,8 +3,10 @@ package query | @@ -3,8 +3,10 @@ package query | ||
| 3 | import ( | 3 | import ( |
| 4 | "fmt" | 4 | "fmt" |
| 5 | "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain" | 5 | "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain" |
| 6 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log" | ||
| 6 | "reflect" | 7 | "reflect" |
| 7 | "strings" | 8 | "strings" |
| 9 | + "time" | ||
| 8 | 10 | ||
| 9 | "github.com/beego/beego/v2/core/validation" | 11 | "github.com/beego/beego/v2/core/validation" |
| 10 | ) | 12 | ) |
| @@ -30,10 +32,43 @@ type SearchProductRecordQuery struct { | @@ -30,10 +32,43 @@ type SearchProductRecordQuery struct { | ||
| 30 | BatchNumber string `cname:"批号" json:"batchNumber"` | 32 | BatchNumber string `cname:"批号" json:"batchNumber"` |
| 31 | // 姓名 | 33 | // 姓名 |
| 32 | UserName string `cname:"姓名" json:"userName"` | 34 | UserName string `cname:"姓名" json:"userName"` |
| 35 | + // 生产记录类型:1:领料 2:退料 4:称重 8:二级品称重 | ||
| 36 | + ProductRecordType int `cname:"生产记录类型:1:领料 2:退料 4:称重 8:二级品称重"` | ||
| 37 | + // 生产线名称 | ||
| 38 | + LineName string `cname:"生产线名称" json:"lineName,omitempty"` | ||
| 39 | + // 工段名称 | ||
| 40 | + SectionName string `cname:"工段名称" json:"sectionName,omitempty"` | ||
| 41 | + // 员工类型 1:固定 2:派遣 3.临时 | ||
| 42 | + EmployeeType int `cname:"员工类型 1:固定 2:派遣 3.临时" json:"employeeType"` | ||
| 43 | + // 开始时间 | ||
| 44 | + BeginTime string `cname:"开始时间" json:"beginTime"` | ||
| 45 | + // 结束时间 | ||
| 46 | + EndTime string `cname:"结束时间" json:"endTime"` | ||
| 47 | + | ||
| 48 | + // 开始时间 | ||
| 49 | + ProductBeginTime time.Time `cname:"开始时间" json:"productBeginTime"` | ||
| 50 | + // 结束时间 | ||
| 51 | + ProductEndTime time.Time `cname:"结束时间" json:"productEndTime"` | ||
| 33 | } | 52 | } |
| 34 | 53 | ||
| 35 | func (cmd *SearchProductRecordQuery) Valid(validation *validation.Validation) { | 54 | func (cmd *SearchProductRecordQuery) Valid(validation *validation.Validation) { |
| 36 | cmd.Offset, cmd.Limit = domain.Pagination(cmd.PageNumber, cmd.PageSize) | 55 | cmd.Offset, cmd.Limit = domain.Pagination(cmd.PageNumber, cmd.PageSize) |
| 56 | + | ||
| 57 | + var err error | ||
| 58 | + if len(cmd.BeginTime) > 0 { | ||
| 59 | + if cmd.ProductBeginTime, err = time.Parse("2006-01-02 15:04:05", cmd.BeginTime); err != nil { | ||
| 60 | + log.Logger.Error(err.Error()) | ||
| 61 | + validation.Error("开始时间有误") | ||
| 62 | + return | ||
| 63 | + } | ||
| 64 | + } | ||
| 65 | + if len(cmd.EndTime) > 0 { | ||
| 66 | + if cmd.ProductEndTime, err = time.Parse("2006-01-02 15:04:05", cmd.EndTime); err != nil { | ||
| 67 | + log.Logger.Error(err.Error()) | ||
| 68 | + validation.Error("结束时间有误") | ||
| 69 | + return | ||
| 70 | + } | ||
| 71 | + } | ||
| 37 | } | 72 | } |
| 38 | 73 | ||
| 39 | func (cmd *SearchProductRecordQuery) ValidateQuery() error { | 74 | func (cmd *SearchProductRecordQuery) ValidateQuery() error { |
| @@ -120,3 +120,39 @@ func WorkOnDescription(workOn int) []string { | @@ -120,3 +120,39 @@ func WorkOnDescription(workOn int) []string { | ||
| 120 | } | 120 | } |
| 121 | return result | 121 | return result |
| 122 | } | 122 | } |
| 123 | + | ||
| 124 | +func EmployeeTypeDescription(employeeType int) string { | ||
| 125 | + if employeeType == 1 { | ||
| 126 | + return "固定" | ||
| 127 | + } | ||
| 128 | + if employeeType == 2 { | ||
| 129 | + return "派遣" | ||
| 130 | + } | ||
| 131 | + if employeeType == 3 { | ||
| 132 | + return "临时" | ||
| 133 | + } | ||
| 134 | + return "固定" | ||
| 135 | +} | ||
| 136 | + | ||
| 137 | +func ParticipateTypeDescription(participateType int) string { | ||
| 138 | + if participateType == 1 { | ||
| 139 | + return "正常" | ||
| 140 | + } | ||
| 141 | + if participateType == 2 { | ||
| 142 | + return "支援" | ||
| 143 | + } | ||
| 144 | + return "正常" | ||
| 145 | +} | ||
| 146 | + | ||
| 147 | +func AttendanceStatusDescription(status int) string { | ||
| 148 | + if status == 1 { | ||
| 149 | + return "未审核" | ||
| 150 | + } | ||
| 151 | + if status == 2 { | ||
| 152 | + return "已审核" | ||
| 153 | + } | ||
| 154 | + if status == 4 { | ||
| 155 | + return "自动审核" | ||
| 156 | + } | ||
| 157 | + return "已审核" | ||
| 158 | +} |
| @@ -6,8 +6,9 @@ import ( | @@ -6,8 +6,9 @@ import ( | ||
| 6 | ) | 6 | ) |
| 7 | 7 | ||
| 8 | const ( | 8 | const ( |
| 9 | - AttendanceNotApprove = 1 // 未审核 | ||
| 10 | - AttendanceApproved = 2 // 已审核 | 9 | + AttendanceNotApprove = 1 // 未审核 |
| 10 | + AttendanceApproved = 2 // 已审核 | ||
| 11 | + AttendanceAutoApproved = 3 // 自动审核 | ||
| 11 | ) | 12 | ) |
| 12 | 13 | ||
| 13 | // 生产考勤记录 | 14 | // 生产考勤记录 |
| @@ -59,86 +60,28 @@ func (productAttendanceRecord *ProductAttendanceRecord) Identify() interface{} { | @@ -59,86 +60,28 @@ func (productAttendanceRecord *ProductAttendanceRecord) Identify() interface{} { | ||
| 59 | } | 60 | } |
| 60 | 61 | ||
| 61 | func (productAttendanceRecord *ProductAttendanceRecord) Update(data map[string]interface{}) error { | 62 | func (productAttendanceRecord *ProductAttendanceRecord) Update(data map[string]interface{}) error { |
| 62 | - if productAttendanceId, ok := data["productAttendanceId"]; ok { | ||
| 63 | - productAttendanceRecord.ProductAttendanceId = productAttendanceId.(int) | ||
| 64 | - } | ||
| 65 | - if orgId, ok := data["orgId"]; ok { | ||
| 66 | - productAttendanceRecord.OrgId = orgId.(int) | ||
| 67 | - } | ||
| 68 | - if attendanceType, ok := data["attendanceType"]; ok { | ||
| 69 | - productAttendanceRecord.AttendanceType = attendanceType.(int) | ||
| 70 | - } | ||
| 71 | - if userId, ok := data["userId"]; ok { | ||
| 72 | - productAttendanceRecord.ProductWorker.UserId = userId.(int) | ||
| 73 | - } | ||
| 74 | - if userName, ok := data["userName"]; ok { | ||
| 75 | - productAttendanceRecord.ProductWorker.UserName = userName.(string) | ||
| 76 | - } | ||
| 77 | - if employeeType, ok := data["employeeType"]; ok { | ||
| 78 | - productAttendanceRecord.ProductWorker.EmployeeType = employeeType.(int) | ||
| 79 | - } | ||
| 80 | - if icCardNumber, ok := data["icCardNumber"]; ok { | ||
| 81 | - productAttendanceRecord.ProductWorker.IcCardNumber = icCardNumber.(string) | ||
| 82 | - } | ||
| 83 | - if avatar, ok := data["avatar"]; ok { | ||
| 84 | - productAttendanceRecord.ProductWorker.Avatar = avatar.(string) | ||
| 85 | - } | ||
| 86 | - if phone, ok := data["phone"]; ok { | ||
| 87 | - productAttendanceRecord.ProductWorker.Phone = phone.(string) | ||
| 88 | - } | ||
| 89 | - if workStationId, ok := data["workStationId"]; ok { | ||
| 90 | - productAttendanceRecord.WorkStation.WorkStationId = workStationId.(string) | ||
| 91 | - } | ||
| 92 | - if workshopId, ok := data["workshopId"]; ok { | ||
| 93 | - productAttendanceRecord.WorkStation.WorkshopId = workshopId.(int) | ||
| 94 | - } | ||
| 95 | - if workshopName, ok := data["workshopName"]; ok { | ||
| 96 | - productAttendanceRecord.WorkStation.WorkshopName = workshopName.(string) | ||
| 97 | - } | ||
| 98 | - if lineId, ok := data["lineId"]; ok { | ||
| 99 | - productAttendanceRecord.WorkStation.LineId = lineId.(int) | ||
| 100 | - } | ||
| 101 | - if lineName, ok := data["lineName"]; ok { | ||
| 102 | - productAttendanceRecord.WorkStation.LineName = lineName.(string) | ||
| 103 | - } | ||
| 104 | - if sectionId, ok := data["sectionId"]; ok { | ||
| 105 | - productAttendanceRecord.WorkStation.SectionId = sectionId.(int) | ||
| 106 | - } | ||
| 107 | - if sectionName, ok := data["sectionName"]; ok { | ||
| 108 | - productAttendanceRecord.WorkStation.SectionName = sectionName.(string) | ||
| 109 | - } | ||
| 110 | - if signIn, ok := data["signIn"]; ok { | ||
| 111 | - productAttendanceRecord.SignIn = signIn.(time.Time) | ||
| 112 | - } | ||
| 113 | - if signOut, ok := data["signOut"]; ok { | ||
| 114 | - productAttendanceRecord.SignOut = signOut.(time.Time) | ||
| 115 | - } | ||
| 116 | - if attendanceStatus, ok := data["attendanceStatus"]; ok { | ||
| 117 | - productAttendanceRecord.AttendanceStatus = attendanceStatus.(int) | ||
| 118 | - } | ||
| 119 | - if workTimeBefore, ok := data["workTimeBefore"]; ok { | ||
| 120 | - productAttendanceRecord.WorkTimeBefore = workTimeBefore.(float64) | ||
| 121 | - } | ||
| 122 | - if workTimeAfter, ok := data["workTimeAfter"]; ok { | ||
| 123 | - productAttendanceRecord.WorkTimeAfter = workTimeAfter.(float64) | ||
| 124 | - } | ||
| 125 | - if createdAt, ok := data["createdAt"]; ok { | ||
| 126 | - productAttendanceRecord.CreatedAt = createdAt.(time.Time) | 63 | + return nil |
| 64 | +} | ||
| 65 | + | ||
| 66 | +// 计算审核前工时 | ||
| 67 | +func (productAttendanceRecord *ProductAttendanceRecord) ComputeWorkTimeBefore() float64 { | ||
| 68 | + if productAttendanceRecord.SignIn.IsZero() { | ||
| 69 | + return 0 | ||
| 127 | } | 70 | } |
| 128 | - if updatedAt, ok := data["updatedAt"]; ok { | ||
| 129 | - productAttendanceRecord.UpdatedAt = updatedAt.(time.Time) | 71 | + if productAttendanceRecord.SignOut.IsZero() { |
| 72 | + return 0 | ||
| 130 | } | 73 | } |
| 131 | - if deletedAt, ok := data["deletedAt"]; ok { | ||
| 132 | - productAttendanceRecord.DeletedAt = deletedAt.(time.Time) | 74 | + if !productAttendanceRecord.SignOut.After(productAttendanceRecord.SignIn) { |
| 75 | + return 0 | ||
| 133 | } | 76 | } |
| 134 | - return nil | 77 | + return productAttendanceRecord.SignOut.Sub(productAttendanceRecord.SignIn).Hours() |
| 135 | } | 78 | } |
| 136 | 79 | ||
| 137 | -func (productAttendanceRecord *ProductAttendanceRecord) Approve(approveUser *User, workTimeAfter float64) error { | ||
| 138 | - if productAttendanceRecord.AttendanceStatus == AttendanceApproved { | 80 | +func (productAttendanceRecord *ProductAttendanceRecord) Approve(approveUser *User, workTimeAfter float64, status int) error { |
| 81 | + if productAttendanceRecord.AttendanceStatus == AttendanceApproved || productAttendanceRecord.AttendanceStatus == AttendanceAutoApproved { | ||
| 139 | return errors.New("已审核") | 82 | return errors.New("已审核") |
| 140 | } | 83 | } |
| 141 | - productAttendanceRecord.AttendanceStatus = AttendanceApproved | 84 | + productAttendanceRecord.AttendanceStatus = status |
| 142 | productAttendanceRecord.WorkTimeAfter = workTimeAfter | 85 | productAttendanceRecord.WorkTimeAfter = workTimeAfter |
| 143 | if productAttendanceRecord.Ext != nil && productAttendanceRecord.Ext.AttendanceExt != nil { | 86 | if productAttendanceRecord.Ext != nil && productAttendanceRecord.Ext.AttendanceExt != nil { |
| 144 | productAttendanceRecord.Ext.AttendanceExt.ApproveUserId = approveUser.UserId | 87 | productAttendanceRecord.Ext.AttendanceExt.ApproveUserId = approveUser.UserId |
| @@ -63,7 +63,7 @@ func (productRecord *ProductRecord) Update(data map[string]interface{}) error { | @@ -63,7 +63,7 @@ func (productRecord *ProductRecord) Update(data map[string]interface{}) error { | ||
| 63 | return nil | 63 | return nil |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | -func (productRecord *ProductRecord) Approve(approveUser *User, weighAfter float64, approveAt time.Time) error { | 66 | +func (productRecord *ProductRecord) Approve(approveUser *User, weighAfter float64, approveAt time.Time, status int) error { |
| 67 | if productRecord.ProductRecordInfo.ApproveAt > 0 { | 67 | if productRecord.ProductRecordInfo.ApproveAt > 0 { |
| 68 | return errors.New("已审核") | 68 | return errors.New("已审核") |
| 69 | } | 69 | } |
| @@ -71,7 +71,7 @@ func (productRecord *ProductRecord) Approve(approveUser *User, weighAfter float6 | @@ -71,7 +71,7 @@ func (productRecord *ProductRecord) Approve(approveUser *User, weighAfter float6 | ||
| 71 | return errors.New("审核后重量必须大于0") | 71 | return errors.New("审核后重量必须大于0") |
| 72 | } | 72 | } |
| 73 | productRecord.ProductRecordInfo.ApproveAt = approveAt.Unix() | 73 | productRecord.ProductRecordInfo.ApproveAt = approveAt.Unix() |
| 74 | - productRecord.ProductRecordInfo.ApproveStatus = ProductRecordApproved | 74 | + productRecord.ProductRecordInfo.ApproveStatus = status |
| 75 | productRecord.ProductRecordInfo.ApproveUser = approveUser | 75 | productRecord.ProductRecordInfo.ApproveUser = approveUser |
| 76 | productRecord.ProductRecordInfo.WeighAfter = weighAfter | 76 | productRecord.ProductRecordInfo.WeighAfter = weighAfter |
| 77 | productRecord.ProductRecordInfo.Weigh = weighAfter | 77 | productRecord.ProductRecordInfo.Weigh = weighAfter |
| @@ -81,6 +81,7 @@ func (employeeProductRecord *EmployeeProductRecord) UpdateProductWeigh(weigh flo | @@ -81,6 +81,7 @@ func (employeeProductRecord *EmployeeProductRecord) UpdateProductWeigh(weigh flo | ||
| 81 | employeeProductRecord.ProductRecordInfo.OtherSectionSecondLevelWeigh[sectionName] = weigh | 81 | employeeProductRecord.ProductRecordInfo.OtherSectionSecondLevelWeigh[sectionName] = weigh |
| 82 | } | 82 | } |
| 83 | } | 83 | } |
| 84 | + employeeProductRecord.ProductRecordInfo.TotalOtherSecondLevelWeigh = employeeProductRecord.ProductRecordInfo.OtherSecondLevelWeigh() // 预先统计其他二级品占比 | ||
| 84 | } | 85 | } |
| 85 | if productRecordType == RecordTypeReceiveMaterial { | 86 | if productRecordType == RecordTypeReceiveMaterial { |
| 86 | employeeProductRecord.ProductWeigh += weigh | 87 | employeeProductRecord.ProductWeigh += weigh |
| @@ -13,7 +13,7 @@ type ProductRecordInfo struct { | @@ -13,7 +13,7 @@ type ProductRecordInfo struct { | ||
| 13 | // 产能-审核后 | 13 | // 产能-审核后 |
| 14 | WeighAfter float64 `json:"weighAfter"` | 14 | WeighAfter float64 `json:"weighAfter"` |
| 15 | // 审核状态 1:未审核 2:已审核 | 15 | // 审核状态 1:未审核 2:已审核 |
| 16 | - ApproveStatus int64 `json:"approveStatus"` | 16 | + ApproveStatus int `json:"approveStatus"` |
| 17 | // 审核时间 | 17 | // 审核时间 |
| 18 | ApproveAt int64 `json:"approveAt"` | 18 | ApproveAt int64 `json:"approveAt"` |
| 19 | // 审核人 | 19 | // 审核人 |
| @@ -13,6 +13,7 @@ type ProductRecordStaticInfo struct { | @@ -13,6 +13,7 @@ type ProductRecordStaticInfo struct { | ||
| 13 | // 生产小组ID | 13 | // 生产小组ID |
| 14 | ProductGroupId int `json:"productGroupId,omitempty"` | 14 | ProductGroupId int `json:"productGroupId,omitempty"` |
| 15 | 15 | ||
| 16 | + TotalOtherSecondLevelWeigh float64 `json:"otherSecondLevelWeigh"` | ||
| 16 | // 保存其他工段二级品的重量 | 17 | // 保存其他工段二级品的重量 |
| 17 | OtherSectionSecondLevelWeigh map[string]float64 `json:"sectionSecondLevelWeigh"` | 18 | OtherSectionSecondLevelWeigh map[string]float64 `json:"sectionSecondLevelWeigh"` |
| 18 | } | 19 | } |
| @@ -63,6 +63,7 @@ func (employeeProductRecord *WorkshopProductRecord) UpdateProductWeigh(weigh flo | @@ -63,6 +63,7 @@ func (employeeProductRecord *WorkshopProductRecord) UpdateProductWeigh(weigh flo | ||
| 63 | } else { | 63 | } else { |
| 64 | employeeProductRecord.ProductRecordInfo.OtherSectionSecondLevelWeigh[sectionName] = weigh | 64 | employeeProductRecord.ProductRecordInfo.OtherSectionSecondLevelWeigh[sectionName] = weigh |
| 65 | } | 65 | } |
| 66 | + employeeProductRecord.ProductRecordInfo.TotalOtherSecondLevelWeigh = employeeProductRecord.ProductRecordInfo.OtherSecondLevelWeigh() // 预先统计其他二级品占比 | ||
| 66 | } | 67 | } |
| 67 | } | 68 | } |
| 68 | if productRecordType == RecordTypeReceiveMaterial { | 69 | if productRecordType == RecordTypeReceiveMaterial { |
| @@ -50,3 +50,33 @@ func (dao *AttendanceRecordDao) ProductWorkStationAttendanceRecord(companyId, or | @@ -50,3 +50,33 @@ func (dao *AttendanceRecordDao) ProductWorkStationAttendanceRecord(companyId, or | ||
| 50 | return int64(count), productAttendanceRecords, nil | 50 | return int64(count), productAttendanceRecords, nil |
| 51 | } | 51 | } |
| 52 | } | 52 | } |
| 53 | + | ||
| 54 | +// 近n天未审核的考勤记录 | ||
| 55 | +// fromLastHour 从前 n小时开始 | ||
| 56 | +// recentDay 近 n天未审核的数据 | ||
| 57 | +func (dao *AttendanceRecordDao) RecentUnApprovedAttendanceRecord(fromLastHour int, recentDay int) (int64, []*domain.ProductAttendanceRecord, error) { | ||
| 58 | + tx := dao.transactionContext.PgTx | ||
| 59 | + endTime := time.Now().Add(-(time.Hour * time.Duration(fromLastHour))) | ||
| 60 | + beginTime := endTime.Add(-(time.Hour * time.Duration(recentDay*24))) | ||
| 61 | + var productAttendanceRecordModels []*models.ProductAttendanceRecord | ||
| 62 | + productAttendanceRecords := make([]*domain.ProductAttendanceRecord, 0) | ||
| 63 | + query := sqlbuilder.BuildQuery(tx.Model(&productAttendanceRecordModels), map[string]interface{}{}) | ||
| 64 | + query.Where("sign_in <= ?", endTime) | ||
| 65 | + query.Where("sign_in >= ?", beginTime) | ||
| 66 | + query.Where("attendance_status = ?", domain.AttendanceNotApprove) | ||
| 67 | + query.Where("work_time_before>0") | ||
| 68 | + query.SetOffsetAndLimit(domain.MaxQueryRow) | ||
| 69 | + query.SetOrderDirect("product_attendance_id", "DESC") | ||
| 70 | + if count, err := query.SelectAndCount(); err != nil { | ||
| 71 | + return 0, productAttendanceRecords, err | ||
| 72 | + } else { | ||
| 73 | + for _, productAttendanceRecordModel := range productAttendanceRecordModels { | ||
| 74 | + if productAttendanceRecord, err := transform.TransformToProductAttendanceRecordDomainModelFromPgModels(productAttendanceRecordModel); err != nil { | ||
| 75 | + return 0, productAttendanceRecords, err | ||
| 76 | + } else { | ||
| 77 | + productAttendanceRecords = append(productAttendanceRecords, productAttendanceRecord) | ||
| 78 | + } | ||
| 79 | + } | ||
| 80 | + return int64(count), productAttendanceRecords, nil | ||
| 81 | + } | ||
| 82 | +} |
| @@ -71,7 +71,7 @@ func (dao *EmployeeProductRecordDao) SearchEmployeeProductRecord(queryOptions ma | @@ -71,7 +71,7 @@ func (dao *EmployeeProductRecordDao) SearchEmployeeProductRecord(queryOptions ma | ||
| 71 | if v, ok := queryOptions["userName"]; ok && len(v.(string)) > 0 { | 71 | if v, ok := queryOptions["userName"]; ok && len(v.(string)) > 0 { |
| 72 | query.Where(fmt.Sprintf(`product_worker->>'userName' like '%%%v%%'`, v)) | 72 | query.Where(fmt.Sprintf(`product_worker->>'userName' like '%%%v%%'`, v)) |
| 73 | } | 73 | } |
| 74 | - if v, ok := queryOptions["employeeType"]; ok && len(v.(string)) > 0 { | 74 | + if v, ok := queryOptions["employeeType"]; ok && v.(int) > 0 { |
| 75 | query.Where(fmt.Sprintf(`product_worker->>'employeeType' = '%v'`, v)) | 75 | query.Where(fmt.Sprintf(`product_worker->>'employeeType' = '%v'`, v)) |
| 76 | } | 76 | } |
| 77 | if v, ok := queryOptions["productBeginTime"]; ok && !((v.(time.Time)).IsZero()) { | 77 | if v, ok := queryOptions["productBeginTime"]; ok && !((v.(time.Time)).IsZero()) { |
pkg/infrastructure/dao/product_record_dao.go
0 → 100644
| 1 | +package dao | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "fmt" | ||
| 5 | + "github.com/linmadan/egglib-go/persistent/pg/sqlbuilder" | ||
| 6 | + pgTransaction "github.com/linmadan/egglib-go/transaction/pg" | ||
| 7 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain" | ||
| 8 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/pg/models" | ||
| 9 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/pg/transform" | ||
| 10 | + "time" | ||
| 11 | +) | ||
| 12 | + | ||
| 13 | +type ProductRecordDao struct { | ||
| 14 | + transactionContext *pgTransaction.TransactionContext | ||
| 15 | +} | ||
| 16 | + | ||
| 17 | +func NewProductRecordDao(transactionContext *pgTransaction.TransactionContext) (*ProductRecordDao, error) { | ||
| 18 | + if transactionContext == nil { | ||
| 19 | + return nil, fmt.Errorf("transactionContext参数不能为nil") | ||
| 20 | + } else { | ||
| 21 | + return &ProductRecordDao{ | ||
| 22 | + transactionContext: transactionContext, | ||
| 23 | + }, nil | ||
| 24 | + } | ||
| 25 | +} | ||
| 26 | + | ||
| 27 | +// 近n天未审核的考勤记录 | ||
| 28 | +// fromLastHour 从前 n小时开始 | ||
| 29 | +// recentDay 近 n天未审核的数据 | ||
| 30 | +func (dao *ProductRecordDao) RecentUnApprovedProductRecord(fromLastHour int, recentDay int, recordType int) (int64, []*domain.ProductRecord, error) { | ||
| 31 | + tx := dao.transactionContext.PgTx | ||
| 32 | + endTime := time.Now().Add(-(time.Hour * time.Duration(fromLastHour))) | ||
| 33 | + beginTime := endTime.Add(-(time.Hour * time.Duration(recentDay*24))) | ||
| 34 | + var productAttendanceRecordModels []*models.ProductRecord | ||
| 35 | + productAttendanceRecords := make([]*domain.ProductRecord, 0) | ||
| 36 | + query := sqlbuilder.BuildQuery(tx.Model(&productAttendanceRecordModels), map[string]interface{}{}) | ||
| 37 | + query.Where("created_at <= ?", endTime) | ||
| 38 | + query.Where("created_at >= ?", beginTime) | ||
| 39 | + query.Where("product_record_type & ? >0", recordType) | ||
| 40 | + query.Where("product_record_info->>approveStatus = '?'", domain.AttendanceNotApprove) | ||
| 41 | + query.Where("product_record_info->>'weighBefore'<>'0'") | ||
| 42 | + query.SetOffsetAndLimit(domain.MaxQueryRow) | ||
| 43 | + query.SetOrderDirect("product_record_id", "DESC") | ||
| 44 | + if count, err := query.SelectAndCount(); err != nil { | ||
| 45 | + return 0, productAttendanceRecords, err | ||
| 46 | + } else { | ||
| 47 | + for _, productAttendanceRecordModel := range productAttendanceRecordModels { | ||
| 48 | + if productAttendanceRecord, err := transform.TransformToProductRecordDomainModelFromPgModels(productAttendanceRecordModel); err != nil { | ||
| 49 | + return 0, productAttendanceRecords, err | ||
| 50 | + } else { | ||
| 51 | + productAttendanceRecords = append(productAttendanceRecords, productAttendanceRecord) | ||
| 52 | + } | ||
| 53 | + } | ||
| 54 | + return int64(count), productAttendanceRecords, nil | ||
| 55 | + } | ||
| 56 | +} |
| 1 | +package domainService | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "fmt" | ||
| 5 | + pgTransaction "github.com/linmadan/egglib-go/transaction/pg" | ||
| 6 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain" | ||
| 7 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/repository" | ||
| 8 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log" | ||
| 9 | +) | ||
| 10 | + | ||
| 11 | +type PGApproveAttendanceRecordsService struct { | ||
| 12 | + transactionContext *pgTransaction.TransactionContext | ||
| 13 | +} | ||
| 14 | + | ||
| 15 | +func (ptr *PGApproveAttendanceRecordsService) BatchApproveAttendanceRecords(opt *domain.OperateInfo, list []*domain.ProductAttendanceRecord, approveUserId int, workTime float64, status int) (interface{}, error) { | ||
| 16 | + var productAttendanceRecordRepository, _ = repository.NewProductAttendanceRecordRepository(ptr.transactionContext) | ||
| 17 | + var attendance *domain.ProductAttendanceRecord | ||
| 18 | + var err error | ||
| 19 | + log.Logger.Info("【自动审核考勤记录任务】 启动") | ||
| 20 | + var user *domain.User = &domain.User{} | ||
| 21 | + userService := NewUserService() | ||
| 22 | + if approveUserId > 0 { | ||
| 23 | + user, err = userService.User(approveUserId) | ||
| 24 | + if err != nil { | ||
| 25 | + return nil, err | ||
| 26 | + } | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + for i := range list { | ||
| 30 | + attendance = list[i] | ||
| 31 | + t := attendance.WorkTimeBefore | ||
| 32 | + if workTime > 0 { | ||
| 33 | + t = workTime | ||
| 34 | + } | ||
| 35 | + if t <= 0 && status == domain.AttendanceAutoApproved { | ||
| 36 | + continue | ||
| 37 | + } | ||
| 38 | + if err = attendance.Approve(user, t, status); err != nil { | ||
| 39 | + return nil, err | ||
| 40 | + } | ||
| 41 | + if _, err := productAttendanceRecordRepository.Save(attendance); err != nil { | ||
| 42 | + return nil, err | ||
| 43 | + } | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + for i := range list { | ||
| 47 | + attendance = list[i] | ||
| 48 | + if e := SendWorkshopWorkTimeStaticJob(attendance); e != nil { | ||
| 49 | + log.Logger.Error("【发送工时统计任务失败】" + e.Error()) | ||
| 50 | + } | ||
| 51 | + } | ||
| 52 | + return struct{}{}, nil | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +func NewPGApproveAttendanceRecordsService(transactionContext *pgTransaction.TransactionContext) (*PGApproveAttendanceRecordsService, error) { | ||
| 56 | + if transactionContext == nil { | ||
| 57 | + return nil, fmt.Errorf("transactionContext参数不能为nil") | ||
| 58 | + } else { | ||
| 59 | + return &PGApproveAttendanceRecordsService{ | ||
| 60 | + transactionContext: transactionContext, | ||
| 61 | + }, nil | ||
| 62 | + } | ||
| 63 | +} |
| @@ -10,6 +10,7 @@ import ( | @@ -10,6 +10,7 @@ import ( | ||
| 10 | "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain" | 10 | "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain" |
| 11 | "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/repository" | 11 | "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/repository" |
| 12 | "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils" | 12 | "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils" |
| 13 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log" | ||
| 13 | "time" | 14 | "time" |
| 14 | ) | 15 | ) |
| 15 | 16 | ||
| @@ -150,7 +151,7 @@ func (ptr *PGProductRecordService) Approve(productRecordId int, approveUserId in | @@ -150,7 +151,7 @@ func (ptr *PGProductRecordService) Approve(productRecordId int, approveUserId in | ||
| 150 | return nil, err | 151 | return nil, err |
| 151 | } | 152 | } |
| 152 | 153 | ||
| 153 | - if err = productRecord.Approve(user, weighAfter, approveAt); err != nil { | 154 | + if err = productRecord.Approve(user, weighAfter, approveAt, domain.ProductRecordApproved); err != nil { |
| 154 | return nil, err | 155 | return nil, err |
| 155 | } | 156 | } |
| 156 | if _, err = productRecordRepository.Save(productRecord); err != nil { | 157 | if _, err = productRecordRepository.Save(productRecord); err != nil { |
| @@ -163,6 +164,49 @@ func (ptr *PGProductRecordService) Approve(productRecordId int, approveUserId in | @@ -163,6 +164,49 @@ func (ptr *PGProductRecordService) Approve(productRecordId int, approveUserId in | ||
| 163 | return struct{}{}, nil | 164 | return struct{}{}, nil |
| 164 | } | 165 | } |
| 165 | 166 | ||
| 167 | +func (ptr *PGProductRecordService) BatchApprove(list []*domain.ProductRecord, approveUserId int, weight float64, status int) (interface{}, error) { | ||
| 168 | + var productRecordRepository, _ = repository.NewProductRecordRepository(ptr.transactionContext) | ||
| 169 | + var record *domain.ProductRecord | ||
| 170 | + var err error | ||
| 171 | + log.Logger.Info("【自动审核二级品记录任务】 启动") | ||
| 172 | + var user *domain.User = &domain.User{} | ||
| 173 | + userService := NewUserService() | ||
| 174 | + if approveUserId > 0 { | ||
| 175 | + user, err = userService.User(approveUserId) | ||
| 176 | + if err != nil { | ||
| 177 | + return nil, err | ||
| 178 | + } | ||
| 179 | + } | ||
| 180 | + | ||
| 181 | + for i := range list { | ||
| 182 | + record = list[i] | ||
| 183 | + t := record.ProductRecordInfo.WeighBefore | ||
| 184 | + if weight > 0 { | ||
| 185 | + t = weight | ||
| 186 | + } | ||
| 187 | + if t <= 0 && status == domain.AttendanceAutoApproved { | ||
| 188 | + continue | ||
| 189 | + } | ||
| 190 | + if err = record.Approve(user, t, time.Now(), status); err != nil { | ||
| 191 | + return nil, err | ||
| 192 | + } | ||
| 193 | + if _, err := productRecordRepository.Save(record); err != nil { | ||
| 194 | + return nil, err | ||
| 195 | + } | ||
| 196 | + } | ||
| 197 | + | ||
| 198 | + for i := range list { | ||
| 199 | + record = list[i] | ||
| 200 | + if record.ProductRecordInfo.WeighBefore <= 0 && status == domain.AttendanceAutoApproved { | ||
| 201 | + continue | ||
| 202 | + } | ||
| 203 | + if e := SendProductRecordStaticsJob(record); e != nil { | ||
| 204 | + log.Logger.Error("【发送产量统计任务失败】" + e.Error()) | ||
| 205 | + } | ||
| 206 | + } | ||
| 207 | + return struct{}{}, nil | ||
| 208 | +} | ||
| 209 | + | ||
| 166 | func SendProductRecordStaticsJob(productRecord *domain.ProductRecord) error { | 210 | func SendProductRecordStaticsJob(productRecord *domain.ProductRecord) error { |
| 167 | task := asynq.NewTask(domain.TaskKeyPatternProductRecordStatics(), []byte(json.MarshalToString(productRecord))) | 211 | task := asynq.NewTask(domain.TaskKeyPatternProductRecordStatics(), []byte(json.MarshalToString(productRecord))) |
| 168 | 212 |
| @@ -85,8 +85,10 @@ func (ptr *PGProductRecordService) EmployeeProductStatics(productRecord *domain. | @@ -85,8 +85,10 @@ func (ptr *PGProductRecordService) EmployeeProductStatics(productRecord *domain. | ||
| 85 | if err == domain.ErrorNotFound { | 85 | if err == domain.ErrorNotFound { |
| 86 | employeeProductRecord = newEmployeeProductRecord(productRecord, participateType, productPlan, r.ProductWorker) | 86 | employeeProductRecord = newEmployeeProductRecord(productRecord, participateType, productPlan, r.ProductWorker) |
| 87 | } else { | 87 | } else { |
| 88 | - log.Logger.Error(err.Error()) | ||
| 89 | - continue | 88 | + if err != nil { |
| 89 | + log.Logger.Error(err.Error()) | ||
| 90 | + continue | ||
| 91 | + } | ||
| 90 | } | 92 | } |
| 91 | employeeProductRecord.UpdateProductWeigh(productRecord.ProductRecordInfo.Weigh, productRecord.ProductRecordType, productRecord.WorkStation.SectionName) | 93 | employeeProductRecord.UpdateProductWeigh(productRecord.ProductRecordInfo.Weigh, productRecord.ProductRecordType, productRecord.WorkStation.SectionName) |
| 92 | 94 | ||
| @@ -261,8 +263,10 @@ func (ptr *PGProductRecordService) WorkshopProductStatics(productRecord *domain. | @@ -261,8 +263,10 @@ func (ptr *PGProductRecordService) WorkshopProductStatics(productRecord *domain. | ||
| 261 | if err == domain.ErrorNotFound { | 263 | if err == domain.ErrorNotFound { |
| 262 | employeeProductRecord = newWorkshopProductRecord(productRecord, productPlan) | 264 | employeeProductRecord = newWorkshopProductRecord(productRecord, productPlan) |
| 263 | } else { | 265 | } else { |
| 264 | - log.Logger.Error(err.Error()) | ||
| 265 | - return nil, nil | 266 | + if err != nil { |
| 267 | + log.Logger.Error(err.Error()) | ||
| 268 | + return nil, nil | ||
| 269 | + } | ||
| 266 | } | 270 | } |
| 267 | employeeProductRecord.UpdateProductWeigh(productRecord.ProductRecordInfo.Weigh, productRecord.ProductRecordType, productRecord.WorkStation.SectionName) | 271 | employeeProductRecord.UpdateProductWeigh(productRecord.ProductRecordInfo.Weigh, productRecord.ProductRecordType, productRecord.WorkStation.SectionName) |
| 268 | 272 |
| @@ -6,6 +6,7 @@ import ( | @@ -6,6 +6,7 @@ import ( | ||
| 6 | "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain" | 6 | "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain" |
| 7 | "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/pg/models" | 7 | "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/pg/models" |
| 8 | "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/pg/transform" | 8 | "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/pg/transform" |
| 9 | + "time" | ||
| 9 | 10 | ||
| 10 | "github.com/linmadan/egglib-go/persistent/pg/sqlbuilder" | 11 | "github.com/linmadan/egglib-go/persistent/pg/sqlbuilder" |
| 11 | pgTransaction "github.com/linmadan/egglib-go/transaction/pg" | 12 | pgTransaction "github.com/linmadan/egglib-go/transaction/pg" |
| @@ -145,6 +146,7 @@ func (repository *ProductRecordRepository) Find(queryOptions map[string]interfac | @@ -145,6 +146,7 @@ func (repository *ProductRecordRepository) Find(queryOptions map[string]interfac | ||
| 145 | query := sqlbuilder.BuildQuery(tx.Model(&productRecordModels), queryOptions) | 146 | query := sqlbuilder.BuildQuery(tx.Model(&productRecordModels), queryOptions) |
| 146 | query.SetWhereByQueryOption("company_id = ?", "companyId") | 147 | query.SetWhereByQueryOption("company_id = ?", "companyId") |
| 147 | query.SetWhereByQueryOption("org_id = ?", "orgId") | 148 | query.SetWhereByQueryOption("org_id = ?", "orgId") |
| 149 | + query.SetWhereByQueryOption("product_record_type & ? >0", "productRecordType") | ||
| 148 | if v, ok := queryOptions["inOrgIds"]; ok && len(v.([]int)) > 0 { | 150 | if v, ok := queryOptions["inOrgIds"]; ok && len(v.([]int)) > 0 { |
| 149 | query.Where(`org_id in (?)`, pg.In(v)) | 151 | query.Where(`org_id in (?)`, pg.In(v)) |
| 150 | } | 152 | } |
| @@ -154,6 +156,21 @@ func (repository *ProductRecordRepository) Find(queryOptions map[string]interfac | @@ -154,6 +156,21 @@ func (repository *ProductRecordRepository) Find(queryOptions map[string]interfac | ||
| 154 | if v, ok := queryOptions["workshopName"]; ok && len(v.(string)) > 0 { | 156 | if v, ok := queryOptions["workshopName"]; ok && len(v.(string)) > 0 { |
| 155 | query.Where(fmt.Sprintf(`work_station->>'workshopName' like '%%%v%%'`, v)) | 157 | query.Where(fmt.Sprintf(`work_station->>'workshopName' like '%%%v%%'`, v)) |
| 156 | } | 158 | } |
| 159 | + if v, ok := queryOptions["lineName"]; ok && len(v.(string)) > 0 { | ||
| 160 | + query.Where(fmt.Sprintf(`work_station->>'lineName' like '%%%v%%'`, v)) | ||
| 161 | + } | ||
| 162 | + if v, ok := queryOptions["sectionName"]; ok && len(v.(string)) > 0 { | ||
| 163 | + query.Where(fmt.Sprintf(`work_station->>'sectionName' like '%%%v%%'`, v)) | ||
| 164 | + } | ||
| 165 | + if v, ok := queryOptions["employeeType"]; ok && v.(int) > 0 { | ||
| 166 | + query.Where(fmt.Sprintf(`product_worker->>'employeeType' = '%v'`, v)) | ||
| 167 | + } | ||
| 168 | + if v, ok := queryOptions["productBeginTime"]; ok && !((v.(time.Time)).IsZero()) { | ||
| 169 | + query.Where("created_at>=?", v.(time.Time)) | ||
| 170 | + } | ||
| 171 | + if v, ok := queryOptions["productEndTime"]; ok && !((v.(time.Time)).IsZero()) { | ||
| 172 | + query.Where("created_at<?", v.(time.Time)) | ||
| 173 | + } | ||
| 157 | if v, ok := queryOptions["batchNumber"]; ok && len(v.(string)) > 0 { | 174 | if v, ok := queryOptions["batchNumber"]; ok && len(v.(string)) > 0 { |
| 158 | query.Where(fmt.Sprintf(`product_record_info->>'batchNumber' like '%%%v%%'`, v)) | 175 | query.Where(fmt.Sprintf(`product_record_info->>'batchNumber' like '%%%v%%'`, v)) |
| 159 | } | 176 | } |
| @@ -334,6 +334,15 @@ func ToArrayString(inputs []int) []string { | @@ -334,6 +334,15 @@ func ToArrayString(inputs []int) []string { | ||
| 334 | return result | 334 | return result |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | +func ToArrayInt(inputs []string) []int { | ||
| 338 | + result := make([]int, 0) | ||
| 339 | + for i := range inputs { | ||
| 340 | + v, _ := strconv.Atoi(inputs[i]) | ||
| 341 | + result = append(result, v) | ||
| 342 | + } | ||
| 343 | + return result | ||
| 344 | +} | ||
| 345 | + | ||
| 337 | func LoadQueryObject(queryOption map[string]interface{}, obj interface{}) error { | 346 | func LoadQueryObject(queryOption map[string]interface{}, obj interface{}) error { |
| 338 | jsonlib.UnmarshalFromString(jsonlib.MarshalToString(queryOption), obj) | 347 | jsonlib.UnmarshalFromString(jsonlib.MarshalToString(queryOption), obj) |
| 339 | validation := validation.Validation{} | 348 | validation := validation.Validation{} |
| @@ -75,6 +75,7 @@ func (controller *ProductRecordController) SearchProductRecord() { | @@ -75,6 +75,7 @@ func (controller *ProductRecordController) SearchProductRecord() { | ||
| 75 | //cmd.OrgId = operateInfo.OrgId | 75 | //cmd.OrgId = operateInfo.OrgId |
| 76 | cmd.CompanyId = operateInfo.CompanyId | 76 | cmd.CompanyId = operateInfo.CompanyId |
| 77 | cmd.InOrgIds = operateInfo.OrgIds | 77 | cmd.InOrgIds = operateInfo.OrgIds |
| 78 | + cmd.ProductRecordType = 8 | ||
| 78 | total, data, err := productPlanService.SearchProductRecord(ParseOperateInfo(controller.BaseController), cmd) | 79 | total, data, err := productPlanService.SearchProductRecord(ParseOperateInfo(controller.BaseController), cmd) |
| 79 | ResponseGrid(controller.BaseController, total, data, err) | 80 | ResponseGrid(controller.BaseController, total, data, err) |
| 80 | } | 81 | } |
| @@ -13,6 +13,7 @@ func init() { | @@ -13,6 +13,7 @@ func init() { | ||
| 13 | web.Router("/product-records/", &controllers.ProductRecordController{}, "Get:ListProductRecord") | 13 | web.Router("/product-records/", &controllers.ProductRecordController{}, "Get:ListProductRecord") |
| 14 | web.Router("/product-records/approve", &controllers.ProductRecordController{}, "Post:ApproveProductRecord") | 14 | web.Router("/product-records/approve", &controllers.ProductRecordController{}, "Post:ApproveProductRecord") |
| 15 | web.Router("/product-records/search", &controllers.ProductRecordController{}, "Post:SearchProductRecord") | 15 | web.Router("/product-records/search", &controllers.ProductRecordController{}, "Post:SearchProductRecord") |
| 16 | + web.Router("/product-records/second-level-record/search", &controllers.ProductRecordController{}, "Post:SearchProductRecord") | ||
| 16 | web.Router("/product-records/employee-productive/search", &controllers.ProductRecordController{}, "Post:SearchEmployeeProductRecord") | 17 | web.Router("/product-records/employee-productive/search", &controllers.ProductRecordController{}, "Post:SearchEmployeeProductRecord") |
| 17 | web.Router("/product-records/workshop-productive/search", &controllers.ProductRecordController{}, "Post:SearchWorkshopProductRecord") | 18 | web.Router("/product-records/workshop-productive/search", &controllers.ProductRecordController{}, "Post:SearchWorkshopProductRecord") |
| 18 | } | 19 | } |
-
请 注册 或 登录 后发表评论