作者 yangfu

feat:

1.生产信息查询、设备运行监控
@@ -34,8 +34,10 @@ type SearchEmployeeAttendanceQuery struct { @@ -34,8 +34,10 @@ type SearchEmployeeAttendanceQuery struct {
34 SectionName string `cname:"工段名称" json:"sectionName,omitempty"` 34 SectionName string `cname:"工段名称" json:"sectionName,omitempty"`
35 // 姓名 35 // 姓名
36 UserName string `cname:"姓名" json:"userName,omitempty"` 36 UserName string `cname:"姓名" json:"userName,omitempty"`
37 - // 考勤状态 1.未审核 2:已审核 4.自动审核  
38 - AttendanceStatus int `cname:"考勤状态 1.未审核 2:已审核 4.自动审核" json:"attendanceStatus,omitempty"` 37 + // 考勤状态 1.未审核 2:已审核 3.自动审核
  38 + AttendanceStatus int `cname:"考勤状态 1.未审核 2:已审核 3.自动审核" json:"attendanceStatus,omitempty"`
  39 + // 员工类型 1:固定 2:派遣 3.临时
  40 + EmployeeType int `cname:"1:固定 2:派遣 3.临时" json:"employeeType,omitempty"`
39 // 开始时间 41 // 开始时间
40 BeginTime string `cname:"开始时间" json:"beginTime"` 42 BeginTime string `cname:"开始时间" json:"beginTime"`
41 // 结束时间 43 // 结束时间
@@ -26,7 +26,7 @@ type SubmitProductRecordCommand struct { @@ -26,7 +26,7 @@ type SubmitProductRecordCommand struct {
26 // 员工Id 用户唯一标识 26 // 员工Id 用户唯一标识
27 EmployeeId int `cname:"员工" json:"employeeId" valid:"Required"` 27 EmployeeId int `cname:"员工" json:"employeeId" valid:"Required"`
28 // 物料ID 28 // 物料ID
29 - UnitConversionId int `cname:"物料ID" json:"unitConversionId" valid:"Required"` 29 + UnitConversionId int `cname:"物料ID" json:"unitConversionId"`
30 // 重量 30 // 重量
31 Weigh float64 `cname:"重量" json:"weigh" valid:"Required"` 31 Weigh float64 `cname:"重量" json:"weigh" valid:"Required"`
32 } 32 }
@@ -8,6 +8,8 @@ type EmployeeProductRecordDto struct { @@ -8,6 +8,8 @@ type EmployeeProductRecordDto struct {
8 // 生产工人 8 // 生产工人
9 ProductWorker *domain.User `json:"productWorker,omitempty"` 9 ProductWorker *domain.User `json:"productWorker,omitempty"`
10 *domain.WorkStation 10 *domain.WorkStation
  11 + // 上班班次 1:全天 2:白班 4:中班 8:夜班
  12 + WorkOn int `json:"workOn"`
11 // 生产日期 13 // 生产日期
12 //ProductDate string `json:"productDate"` 14 //ProductDate string `json:"productDate"`
13 // 计划的产品名称 15 // 计划的产品名称
@@ -29,15 +31,19 @@ type EmployeeProductRecordDto struct { @@ -29,15 +31,19 @@ type EmployeeProductRecordDto struct {
29 // 合格率 百分比 31 // 合格率 百分比
30 QualificationRate int `json:"qualificationRate"` 32 QualificationRate int `json:"qualificationRate"`
31 // 考勤类型 1.正常 2.支援 33 // 考勤类型 1.正常 2.支援
32 - ParticipateTypeDescription string `json:"participateTypeDescription,omitempty"` 34 + ParticipateTypeDescription string `json:"participateTypeDescription"`
33 // 员工类型描述 1:固定 2:派遣 3.临时 35 // 员工类型描述 1:固定 2:派遣 3.临时
34 - EmployeeTypeDescription string `json:"employeeTypeDescription,omitempty"` 36 + EmployeeTypeDescription string `json:"employeeTypeDescription"`
  37 + // 上班班次 1:全天 2:白班 4:中班 8:夜班
  38 + WorkOnDescription string `json:"workOnDescription,omitempty"`
35 } 39 }
36 40
37 func (d *EmployeeProductRecordDto) LoadDto(m *domain.EmployeeProductRecord, orgId int) *EmployeeProductRecordDto { 41 func (d *EmployeeProductRecordDto) LoadDto(m *domain.EmployeeProductRecord, orgId int) *EmployeeProductRecordDto {
38 d.EmployeeProductRecordId = m.EmployeeProductRecordId 42 d.EmployeeProductRecordId = m.EmployeeProductRecordId
39 d.ProductWorker = m.ProductWorker 43 d.ProductWorker = m.ProductWorker
40 d.WorkStation = m.WorkStation 44 d.WorkStation = m.WorkStation
  45 + d.WorkOn = m.WorkOn
  46 +
41 d.PlanProductName = m.ProductRecordInfo.PlanProductName 47 d.PlanProductName = m.ProductRecordInfo.PlanProductName
42 d.BatchNumber = m.ProductRecordInfo.BatchNumber 48 d.BatchNumber = m.ProductRecordInfo.BatchNumber
43 d.ParticipateType = m.ParticipateType 49 d.ParticipateType = m.ParticipateType
@@ -47,6 +53,7 @@ func (d *EmployeeProductRecordDto) LoadDto(m *domain.EmployeeProductRecord, orgI @@ -47,6 +53,7 @@ func (d *EmployeeProductRecordDto) LoadDto(m *domain.EmployeeProductRecord, orgI
47 d.CreatedAt = m.CreatedAt.Format("2006-01-02") 53 d.CreatedAt = m.CreatedAt.Format("2006-01-02")
48 d.ParticipateTypeDescription = domain.ParticipateTypeDescription(m.ParticipateType) 54 d.ParticipateTypeDescription = domain.ParticipateTypeDescription(m.ParticipateType)
49 d.EmployeeTypeDescription = domain.EmployeeTypeDescription(m.ProductWorker.EmployeeType) 55 d.EmployeeTypeDescription = domain.EmployeeTypeDescription(m.ProductWorker.EmployeeType)
  56 + d.WorkOnDescription = domain.WorkOnDescriptions(m.WorkOn)
50 d.AuthFlag = domain.CheckOrgAuth(orgId, m.OrgId) 57 d.AuthFlag = domain.CheckOrgAuth(orgId, m.OrgId)
51 if m.Ext != nil { 58 if m.Ext != nil {
52 d.OrgName = m.Ext.OrgName 59 d.OrgName = m.Ext.OrgName
@@ -127,6 +127,16 @@ func (device *Device) Valid() error { @@ -127,6 +127,16 @@ func (device *Device) Valid() error {
127 return nil 127 return nil
128 } 128 }
129 129
  130 +// 标记为生产设备
  131 +func (device *Device) MarkAsProductDevice() bool {
  132 + if device.Ext.DeviceExt.IsProductDevice == 1 {
  133 + return false
  134 + }
  135 + device.Ext.DeviceExt.IsProductDevice = 1
  136 + device.UpdatedAt = time.Now()
  137 + return true
  138 +}
  139 +
130 // 导入设备数据体 140 // 导入设备数据体
131 type ImportDeviceItem struct { 141 type ImportDeviceItem struct {
132 // 设备编号 142 // 设备编号
@@ -183,3 +193,13 @@ func (item *ImportDeviceItem) Valid() error { @@ -183,3 +193,13 @@ func (item *ImportDeviceItem) Valid() error {
183 } 193 }
184 return nil 194 return nil
185 } 195 }
  196 +
  197 +type Devices []*Device
  198 +
  199 +func (devices Devices) ToMap() map[string]*Device {
  200 + var resp = make(map[string]*Device)
  201 + for _, v := range devices {
  202 + resp[v.DeviceCode] = v
  203 + }
  204 + return resp
  205 +}
@@ -98,6 +98,11 @@ type DeviceRunningRecordInfo struct { @@ -98,6 +98,11 @@ type DeviceRunningRecordInfo struct {
98 // 批次数据 98 // 批次数据
99 // 生产计划ID 99 // 生产计划ID
100 ProductPlanId int `json:"productPlanId,omitempty"` 100 ProductPlanId int `json:"productPlanId,omitempty"`
  101 +
  102 + // 设备名称
  103 + DeviceName string `json:"deviceName"`
  104 + // 组织名称
  105 + OrgName string `json:"orgName"`
101 } 106 }
102 107
103 func NewDeviceRunningRecordInfo() *DeviceRunningRecordInfo { 108 func NewDeviceRunningRecordInfo() *DeviceRunningRecordInfo {
@@ -155,6 +160,18 @@ func (d *DeviceRunningRecordInfo) ResetOEE(pu, qu float64) float64 { @@ -155,6 +160,18 @@ func (d *DeviceRunningRecordInfo) ResetOEE(pu, qu float64) float64 {
155 return d.OEE 160 return d.OEE
156 } 161 }
157 162
  163 +// 详细的小时设备数据
  164 +// 0:00 1
  165 +// 0:59 2
  166 +// 23:00 1
  167 +// 23:59 2
  168 +// [{"min":1,"time":"00:01","status":1}]
  169 +func (d *DeviceRunningRecordInfo) HourDeviceStatusDetail() {
  170 + for i := 0; i < 24; i++ {
  171 +
  172 + }
  173 +}
  174 +
158 // 单个小时内的设备状态 175 // 单个小时内的设备状态
159 type HourDeviceStatus struct { 176 type HourDeviceStatus struct {
160 // 时间窗口 1-60 代表时间段范围 177 // 时间窗口 1-60 代表时间段范围
@@ -4,4 +4,6 @@ package domain @@ -4,4 +4,6 @@ package domain
4 type DeviceExt struct { 4 type DeviceExt struct {
5 // 生产单个产品的时间(单位:秒) 5 // 生产单个产品的时间(单位:秒)
6 UnitProductionSecTime int `json:"unitProductionSecTime"` 6 UnitProductionSecTime int `json:"unitProductionSecTime"`
  7 + // 是否是车间设备,如果这个设备有上报过数据,标记 1 默认0
  8 + IsProductDevice int `json:"isProductDevice"`
7 } 9 }
1 package domain 1 package domain
2 2
3 -import "fmt" 3 +import (
  4 + "fmt"
  5 + "strings"
  6 +)
4 7
5 const MaxQueryRow = 10000 8 const MaxQueryRow = 10000
6 9
@@ -121,6 +124,11 @@ func WorkOnDescription(workOn int) []string { @@ -121,6 +124,11 @@ func WorkOnDescription(workOn int) []string {
121 return result 124 return result
122 } 125 }
123 126
  127 +func WorkOnDescriptions(workOn int) string {
  128 + r := WorkOnDescription(workOn)
  129 + return strings.Join(r, ",")
  130 +}
  131 +
124 func EmployeeTypeDescription(employeeType int) string { 132 func EmployeeTypeDescription(employeeType int) string {
125 if employeeType == 1 { 133 if employeeType == 1 {
126 return "固定" 134 return "固定"
  1 +package dao
  2 +
  3 +import (
  4 + "fmt"
  5 + pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
  6 + "time"
  7 +)
  8 +
  9 +type DeviceDailyRunningRecordDao struct {
  10 + transactionContext *pgTransaction.TransactionContext
  11 +}
  12 +
  13 +func NewDeviceDailyRunningRecordDao(transactionContext *pgTransaction.TransactionContext) (*DeviceDailyRunningRecordDao, error) {
  14 + if transactionContext == nil {
  15 + return nil, fmt.Errorf("transactionContext参数不能为nil")
  16 + } else {
  17 + return &DeviceDailyRunningRecordDao{
  18 + transactionContext: transactionContext,
  19 + }, nil
  20 + }
  21 +}
  22 +
  23 +// 时段产能
  24 +func (dao *DeviceDailyRunningRecordDao) TimeSectionRunningRecord(companyId, orgId, workshopId int, lineId int, sectionName string, beginTime time.Time, result interface{}) error {
  25 +
  26 + tx := dao.transactionContext.PgTx
  27 + sql := fmt.Sprintf(`
  28 +
  29 +WITH ts_product as(
  30 + select sum(a.weight) total,a.ts from (
  31 + select
  32 + cast(device_running_record_info->>'count' as DECIMAL) weight,
  33 + to_char(product_date at time ZONE 'Asia/shanghai', 'mm:dd') ts
  34 + from manufacture.device_daily_running_record
  35 + where
  36 + company_id = ?
  37 + and org_id = ?
  38 + and work_station->>'workshopId'='?'
  39 + and work_station->>'lineId'='?'
  40 + and work_station->>'sectionName'=?
  41 + and created_at >?
  42 + ) a
  43 + group by a.ts
  44 + order by ts
  45 +)
  46 +-- select * from ts_product
  47 +, ts_product_list as (
  48 + select d.ts,ts_product.total from (
  49 + select to_char(c.ts::timestamp,'mm:dd') ts from (
  50 + select generate_series(now() - interval '6 day',now(),'1 day') ts
  51 + ) c ) d left join ts_product on d.ts = ts_product.ts
  52 +)
  53 +SELECT ts, coalesce(total,0) total
  54 +from ts_product_list
  55 +`)
  56 + if _, err := tx.Query(result, sql, companyId, orgId, workshopId, lineId, sectionName, beginTime); err != nil {
  57 + return err
  58 + }
  59 + return nil
  60 +}
  61 +
  62 +func (dao *DeviceDailyRunningRecordDao) WorkshopProductionEfficiencyStatistics(companyId, orgId, workshopId int, beginTime time.Time, result interface{}) error {
  63 +
  64 + tx := dao.transactionContext.PgTx
  65 + sql := fmt.Sprintf(`
  66 +with device_running as(
  67 +select
  68 +cast(device_running_record_info->>'oee' as DECIMAL) oee,
  69 +cast(device_running_record_info->>'tu' as DECIMAL) tu,
  70 +cast(device_running_record_info->>'pu' as DECIMAL) pu,
  71 +cast(device_running_record_info->>'qu' as DECIMAL) qu
  72 +from manufacture.device_daily_running_record
  73 +where
  74 +company_id = ?
  75 +and org_id = ?
  76 +and work_station->>'workshopId'='?'
  77 +and created_at>=?
  78 +)
  79 +select round(avg(oee),1) oee,round(avg(tu),1) tu,round(avg(pu),1)pu, round(avg(qu),1) qu from device_running
  80 + `)
  81 + if _, err := tx.Query(result, sql, companyId, orgId, workshopId, beginTime); err != nil {
  82 + return err
  83 + }
  84 + return nil
  85 +}
@@ -56,7 +56,7 @@ func (dao *ProductRecordDao) RecentUnApprovedProductRecord(fromLastHour int, rec @@ -56,7 +56,7 @@ func (dao *ProductRecordDao) RecentUnApprovedProductRecord(fromLastHour int, rec
56 } 56 }
57 57
58 // 时段产能 58 // 时段产能
59 -func (dao *ProductRecordDao) TimeSectionProductRecord(companyId, orgId, workshopId int, lineId int, beginTime time.Time, result interface{}) error { 59 +func (dao *ProductRecordDao) TimeSectionProductRecord(companyId, orgId, workshopId int, lineId int, sectionName string, beginTime time.Time, result interface{}) error {
60 60
61 tx := dao.transactionContext.PgTx 61 tx := dao.transactionContext.PgTx
62 sql := fmt.Sprintf(` 62 sql := fmt.Sprintf(`
@@ -71,6 +71,7 @@ WITH ts_product as( @@ -71,6 +71,7 @@ WITH ts_product as(
71 and org_id = ? 71 and org_id = ?
72 and work_station->>'workshopId'='?' 72 and work_station->>'workshopId'='?'
73 and work_station->>'lineId'='?' 73 and work_station->>'lineId'='?'
  74 + and work_station->>'sectionName'=?
74 and product_record_type = 8 75 and product_record_type = 8
75 and created_at >? 76 and created_at >?
76 ) a 77 ) a
@@ -92,7 +93,42 @@ WITH ts_product as( @@ -92,7 +93,42 @@ WITH ts_product as(
92 SELECT ts, coalesce(total,0) total 93 SELECT ts, coalesce(total,0) total
93 from ts_product_list 94 from ts_product_list
94 `) 95 `)
95 - if _, err := tx.Query(result, sql, companyId, orgId, workshopId, lineId, beginTime); err != nil { 96 + if _, err := tx.Query(result, sql, companyId, orgId, workshopId, lineId, sectionName, beginTime); err != nil {
  97 + return err
  98 + }
  99 + return nil
  100 +}
  101 +
  102 +// 二级品比重
  103 +func (dao *ProductRecordDao) ProportionOfSecondLevelRecord(companyId, orgId, workshopId int, beginTime time.Time, result interface{}) error {
  104 +
  105 + tx := dao.transactionContext.PgTx
  106 + sql := fmt.Sprintf(`
  107 +with item_product as (
  108 +select sum(a.weight) item_total,max(sname) sname from (
  109 + select cast(product_record_info->>'weigh' as DECIMAL) weight
  110 + ,work_station->>'sectionName' sname
  111 + ,work_station->>'workStationId' workStationId
  112 + from manufacture.product_records
  113 + where company_id = ?
  114 + and org_id = ?
  115 + and work_station->>'workshopId'='?'
  116 + and product_record_type = 8
  117 + and product_record_info->>'approveStatus'='2'
  118 + and created_at >=?
  119 + and work_station->>'sectionName' in ('打料','成型','穿串','包装')
  120 +) a
  121 +group by a.workStationId
  122 +)
  123 +--select * from item_product
  124 +,item_product_rate as(
  125 +select sname,round(item_total/(select sum(item_total) from item_product)*100, 0) as rate from item_product
  126 +)
  127 +--select * from item_product_rate
  128 +select a.sname, coalesce(b.rate,0) rate from (
  129 + select unnest(ARRAY ['打料','成型','穿串','包装']) sname
  130 +) a left join item_product_rate b on a.sname=b.sname`)
  131 + if _, err := tx.Query(result, sql, companyId, orgId, workshopId, beginTime); err != nil {
96 return err 132 return err
97 } 133 }
98 return nil 134 return nil
@@ -14,6 +14,18 @@ import ( @@ -14,6 +14,18 @@ import (
14 const ( 14 const (
15 // 时段产能统计 15 // 时段产能统计
16 HourProductiveStatistics = "HourProductiveStatistics" 16 HourProductiveStatistics = "HourProductiveStatistics"
  17 + // 产能对比
  18 + DailyProductiveStatistics = "DailyProductiveStatistics"
  19 + // 二级品比重
  20 + ProportionOfSecondLevelStatistics = "ProportionOfSecondLevelStatistics"
  21 + // 车间生产效率
  22 + WorkshopProductionEfficiencyStatistics = "WorkshopProductionEfficiencyStatistics"
  23 + // 设备运行统计
  24 + DeviceRunningStatistics = "DeviceRunningStatistics"
  25 +)
  26 +
  27 +const (
  28 + SectionNameCCJ = "穿串"
17 ) 29 )
18 30
19 type PGCommonStatisticsService struct { 31 type PGCommonStatisticsService struct {
@@ -27,6 +39,18 @@ func (ptr *PGCommonStatisticsService) CommonStatistics(actionType string, queryO @@ -27,6 +39,18 @@ func (ptr *PGCommonStatisticsService) CommonStatistics(actionType string, queryO
27 case HourProductiveStatistics: 39 case HourProductiveStatistics:
28 result, err = ptr.HourProductiveStatistics(queryOptions) 40 result, err = ptr.HourProductiveStatistics(queryOptions)
29 break 41 break
  42 + case DailyProductiveStatistics:
  43 + result, err = ptr.DailyProductiveStatistics(queryOptions)
  44 + break
  45 + case ProportionOfSecondLevelStatistics:
  46 + result, err = ptr.ProportionOfSecondLevelStatistics(queryOptions)
  47 + break
  48 + case WorkshopProductionEfficiencyStatistics:
  49 + result, err = ptr.WorkshopProductionEfficiencyStatistics(queryOptions)
  50 + break
  51 + case DeviceRunningStatistics:
  52 + result, err = ptr.DeviceRunningStatistics(queryOptions)
  53 + break
30 } 54 }
31 return result, err 55 return result, err
32 } 56 }
@@ -53,7 +77,7 @@ func (ptr *PGCommonStatisticsService) HourProductiveStatistics(queryOptions map[ @@ -53,7 +77,7 @@ func (ptr *PGCommonStatisticsService) HourProductiveStatistics(queryOptions map[
53 var response = make([]interface{}, 0) 77 var response = make([]interface{}, 0)
54 for _, v := range workshop.GetProductLines(domain.NotDeleted) { 78 for _, v := range workshop.GetProductLines(domain.NotDeleted) {
55 var result = make([]*record, 0) 79 var result = make([]*record, 0)
56 - if err := productRecordDao.TimeSectionProductRecord(request.CompanyId, request.OrgId, request.WorkshopId, v.LineId, time.Now().Add(-time.Hour*5), &result); err != nil { 80 + if err := productRecordDao.TimeSectionProductRecord(request.CompanyId, request.OrgId, request.WorkshopId, v.LineId, SectionNameCCJ, time.Now().Add(-time.Hour*5), &result); err != nil {
57 log.Logger.Error(err.Error()) 81 log.Logger.Error(err.Error())
58 continue 82 continue
59 } 83 }
@@ -88,6 +112,195 @@ func NewXYData(xData []string, values interface{}) interface{} { @@ -88,6 +112,195 @@ func NewXYData(xData []string, values interface{}) interface{} {
88 } 112 }
89 } 113 }
90 114
  115 +// 时段产能-统计 (传串设备)
  116 +func (ptr *PGCommonStatisticsService) DailyProductiveStatistics(queryOptions map[string]interface{}) (interface{}, error) {
  117 + var request = &HourProductiveStatisticsRequest{}
  118 + if err := utils.LoadQueryObject(queryOptions, request); err != nil {
  119 + return nil, err
  120 + }
  121 +
  122 + workshopRepository, _ := repository.NewWorkshopRepository(ptr.transactionContext)
  123 + type record struct {
  124 + Ts string `json:"ts"`
  125 + Total float64 `json:"total"`
  126 + }
  127 +
  128 + workshop, err := workshopRepository.FindOne(map[string]interface{}{"workshopId": request.WorkshopId})
  129 + if err != nil || workshop == nil {
  130 + return nil, nil
  131 + }
  132 + productRecordDao, _ := dao.NewDeviceDailyRunningRecordDao(ptr.transactionContext)
  133 +
  134 + var response = make([]interface{}, 0)
  135 + for _, v := range workshop.GetProductLines(domain.NotDeleted) {
  136 + var result = make([]*record, 0)
  137 + if err := productRecordDao.TimeSectionRunningRecord(request.CompanyId, request.OrgId, request.WorkshopId, v.LineId, SectionNameCCJ, time.Now().Add(-time.Hour*24*7), &result); err != nil {
  138 + log.Logger.Error(err.Error())
  139 + continue
  140 + }
  141 + var xData []string = make([]string, 0)
  142 + var values []interface{} = make([]interface{}, 0)
  143 + for _, r := range result {
  144 + xData = append(xData, r.Ts)
  145 + values = append(values, r.Total)
  146 + }
  147 + response = append(response, map[string]interface{}{
  148 + "lineName": v.LineName,
  149 + "data": NewXYData(xData, values),
  150 + })
  151 + }
  152 + return map[string]interface{}{
  153 + "recent_7_day": response,
  154 + }, nil
  155 +}
  156 +
  157 +// 二级品占比
  158 +func (ptr *PGCommonStatisticsService) ProportionOfSecondLevelStatistics(queryOptions map[string]interface{}) (interface{}, error) {
  159 + var request = &HourProductiveStatisticsRequest{}
  160 + if err := utils.LoadQueryObject(queryOptions, request); err != nil {
  161 + return nil, err
  162 + }
  163 +
  164 + workshopRepository, _ := repository.NewWorkshopRepository(ptr.transactionContext)
  165 + type record struct {
  166 + Sname string `json:"sname"`
  167 + Rate float64 `json:"rate"`
  168 + }
  169 +
  170 + workshop, err := workshopRepository.FindOne(map[string]interface{}{"workshopId": request.WorkshopId})
  171 + if err != nil || workshop == nil {
  172 + return nil, nil
  173 + }
  174 + productRecordDao, _ := dao.NewProductRecordDao(ptr.transactionContext)
  175 +
  176 + var input = []struct {
  177 + name string
  178 + t time.Time
  179 + }{
  180 + {"today", utils.GetZeroTime(time.Now())},
  181 + {"current_week", utils.GetCurrentWeekFirstDay(time.Now())},
  182 + {"current_month", utils.GetCurrentMonthFirstDay(time.Now())},
  183 + }
  184 +
  185 + var response = make(map[string]interface{})
  186 + for _, v := range input {
  187 + var result = make([]*record, 0)
  188 + if err := productRecordDao.ProportionOfSecondLevelRecord(request.CompanyId, request.OrgId, request.WorkshopId, v.t, &result); err != nil {
  189 + log.Logger.Error(err.Error())
  190 + return nil, err
  191 + }
  192 + response[v.name] = result
  193 + }
  194 +
  195 + return response, nil
  196 +}
  197 +
  198 +// 车间生产效率统计
  199 +func (ptr *PGCommonStatisticsService) WorkshopProductionEfficiencyStatistics(queryOptions map[string]interface{}) (interface{}, error) {
  200 + var request = &HourProductiveStatisticsRequest{}
  201 + if err := utils.LoadQueryObject(queryOptions, request); err != nil {
  202 + return nil, err
  203 + }
  204 +
  205 + workshopRepository, _ := repository.NewWorkshopRepository(ptr.transactionContext)
  206 + type record struct {
  207 + Oee float64 `json:"oee"`
  208 + Pu float64 `json:"pu"`
  209 + Tu float64 `json:"tu"`
  210 + Qu float64 `json:"qu"`
  211 + }
  212 +
  213 + workshop, err := workshopRepository.FindOne(map[string]interface{}{"workshopId": request.WorkshopId})
  214 + if err != nil || workshop == nil {
  215 + return nil, nil
  216 + }
  217 + productRecordDao, _ := dao.NewDeviceDailyRunningRecordDao(ptr.transactionContext)
  218 +
  219 + var input = []struct {
  220 + name string
  221 + t time.Time
  222 + }{
  223 + {"today", utils.GetZeroTime(time.Now())},
  224 + {"current_week", utils.GetCurrentWeekFirstDay(time.Now())},
  225 + {"current_month", utils.GetCurrentMonthFirstDay(time.Now())},
  226 + }
  227 +
  228 + var response = make(map[string]interface{})
  229 + for _, v := range input {
  230 + var result = make([]*record, 0)
  231 + if err := productRecordDao.WorkshopProductionEfficiencyStatistics(request.CompanyId, request.OrgId, request.WorkshopId, v.t, &result); err != nil {
  232 + log.Logger.Error(err.Error())
  233 + return nil, err
  234 + }
  235 + response[v.name] = result
  236 + }
  237 +
  238 + return response, nil
  239 +}
  240 +
  241 +// 设备运行统计
  242 +func (ptr *PGCommonStatisticsService) DeviceRunningStatistics(queryOptions map[string]interface{}) (interface{}, error) {
  243 + var request = &DeviceRunningStatisticRequest{}
  244 + if err := utils.LoadQueryObject(queryOptions, request); err != nil {
  245 + return nil, err
  246 + }
  247 +
  248 + workshopRepository, _ := repository.NewWorkshopRepository(ptr.transactionContext)
  249 + deviceRepository, _ := repository.NewDeviceRepository(ptr.transactionContext)
  250 + deviceRunningRecordRepository, _ := repository.NewDeviceDailyRunningRecordRepository(ptr.transactionContext)
  251 +
  252 + workshop, err := workshopRepository.FindOne(map[string]interface{}{"workshopId": request.WorkshopId})
  253 + if err != nil || workshop == nil {
  254 + return nil, nil
  255 + }
  256 +
  257 + _, devices, err := deviceRepository.Find(map[string]interface{}{"companyId": request.CompanyId, "orgId": request.OrgId, "workshopId": request.WorkshopId, "lineId": request.LineId})
  258 + if err != nil {
  259 + return nil, err
  260 + }
  261 +
  262 + var response = make([]interface{}, 0)
  263 + _, dailyRecords, err := deviceRunningRecordRepository.Find(map[string]interface{}{"companyId": request.CompanyId, "orgId": request.OrgId, "productDate": request.Date})
  264 + for i := 0; i < len(devices); i++ {
  265 + d := devices[i]
  266 + if d.Ext == nil || d.Ext.DeviceExt == nil || d.Ext.DeviceExt.IsProductDevice == 0 {
  267 + continue
  268 + }
  269 + var r *domain.DeviceDailyRunningRecord
  270 + item := make(map[string]interface{})
  271 + item["orgName"] = d.Ext.OrgName
  272 + if d.WorkStation != nil {
  273 + item["workshopName"] = d.WorkStation.WorkshopName
  274 + item["lineName"] = d.WorkStation.LineName
  275 + item["deviceName"] = d.DeviceName
  276 + item["oee"] = 0
  277 + item["status"] = []struct{}{}
  278 + }
  279 + for j := 0; j < len(dailyRecords); j++ {
  280 + if d.DeviceCode == dailyRecords[j].DeviceCode {
  281 + r = dailyRecords[j]
  282 + item["oee"] = r.DeviceRunningRecordInfo.OEE
  283 + break
  284 + }
  285 + }
  286 + if r != nil {
  287 + item["status"] = r.DeviceRunningRecordInfo.TimeLineDeviceStatus
  288 + }
  289 + response = append(response, item)
  290 + }
  291 + return map[string]interface{}{
  292 + "devices": response,
  293 + }, nil
  294 +}
  295 +
  296 +type DeviceRunningStatisticRequest struct {
  297 + CompanyId int `json:"companyId" valid:"Required"`
  298 + OrgId int `json:"orgId" valid:"Required"`
  299 + WorkshopId int `json:"workshopId" valid:"Required"`
  300 + LineId int `json:"lineId""`
  301 + Date string `json:"date"`
  302 +}
  303 +
91 func NewPGCommonStatisticsService(transactionContext *pgTransaction.TransactionContext) (*PGCommonStatisticsService, error) { 304 func NewPGCommonStatisticsService(transactionContext *pgTransaction.TransactionContext) (*PGCommonStatisticsService, error) {
92 if transactionContext == nil { 305 if transactionContext == nil {
93 return nil, fmt.Errorf("transactionContext参数不能为nil") 306 return nil, fmt.Errorf("transactionContext参数不能为nil")
@@ -36,7 +36,7 @@ type SubmitOptions struct { @@ -36,7 +36,7 @@ type SubmitOptions struct {
36 // 员工Id 用户唯一标识 36 // 员工Id 用户唯一标识
37 EmployeeId int `cname:"员工" json:"employeeId" valid:"Required"` 37 EmployeeId int `cname:"员工" json:"employeeId" valid:"Required"`
38 // 物料ID 38 // 物料ID
39 - UnitConversionId int `cname:"物料ID" json:"unitConversionId" valid:"Required"` 39 + UnitConversionId int `cname:"物料ID" json:"unitConversionId"`
40 // 重量 40 // 重量
41 Weigh float64 `cname:"重量" json:"weigh" valid:"Required"` 41 Weigh float64 `cname:"重量" json:"weigh" valid:"Required"`
42 } 42 }
@@ -73,8 +73,10 @@ func (ptr *PGProductRecordService) SubmitProductRecord(productRecordType int, qu @@ -73,8 +73,10 @@ func (ptr *PGProductRecordService) SubmitProductRecord(productRecordType int, qu
73 if workshop, err = workshopRepository.FindOne(map[string]interface{}{"workshopId": request.WorkshopId}); err != nil { 73 if workshop, err = workshopRepository.FindOne(map[string]interface{}{"workshopId": request.WorkshopId}); err != nil {
74 return nil, err 74 return nil, err
75 } 75 }
76 - if uc, err = unitConversionRepository.FindOne(map[string]interface{}{"unitConversionId": request.UnitConversionId}); err != nil {  
77 - return nil, err 76 + if request.UnitConversionId > 0 {
  77 + if uc, err = unitConversionRepository.FindOne(map[string]interface{}{"unitConversionId": request.UnitConversionId}); err != nil {
  78 + return nil, err
  79 + }
78 } 80 }
79 if workstation, err = workshop.FindWorkStation(request.WorkshopId, request.LineId, request.SectionId); err != nil { 81 if workstation, err = workshop.FindWorkStation(request.WorkshopId, request.LineId, request.SectionId); err != nil {
80 return nil, err 82 return nil, err
@@ -248,6 +248,8 @@ func (ptr *PGWorkshopDataConsumeService) saveDeviceDailyRunningRecord(companyId, @@ -248,6 +248,8 @@ func (ptr *PGWorkshopDataConsumeService) saveDeviceDailyRunningRecord(companyId,
248 } 248 }
249 recordInfo := domain.NewDeviceRunningRecordInfo() 249 recordInfo := domain.NewDeviceRunningRecordInfo()
250 recordInfo.ProductPlanId = planId 250 recordInfo.ProductPlanId = planId
  251 + recordInfo.DeviceName = device.DeviceName
  252 + recordInfo.OrgName = device.Ext.OrgName
251 record = &domain.DeviceDailyRunningRecord{ 253 record = &domain.DeviceDailyRunningRecord{
252 CompanyId: companyId, 254 CompanyId: companyId,
253 OrgId: orgId, 255 OrgId: orgId,
@@ -262,6 +264,13 @@ func (ptr *PGWorkshopDataConsumeService) saveDeviceDailyRunningRecord(companyId, @@ -262,6 +264,13 @@ func (ptr *PGWorkshopDataConsumeService) saveDeviceDailyRunningRecord(companyId,
262 if record, err = deviceDailyRunningRecordRepository.Save(record); err != nil { 264 if record, err = deviceDailyRunningRecordRepository.Save(record); err != nil {
263 return nil, err 265 return nil, err
264 } 266 }
  267 +
  268 + if device.MarkAsProductDevice() {
  269 + deviceRepository, _ := repository.NewDeviceRepository(ptr.transactionContext)
  270 + if device, err = deviceRepository.Save(device); err != nil {
  271 + return nil, err
  272 + }
  273 + }
265 return record, nil 274 return record, nil
266 } 275 }
267 276
@@ -143,6 +143,11 @@ func (repository *DeviceDailyRunningRecordRepository) Find(queryOptions map[stri @@ -143,6 +143,11 @@ func (repository *DeviceDailyRunningRecordRepository) Find(queryOptions map[stri
143 var deviceDailyRunningRecordModels []*models.DeviceDailyRunningRecord 143 var deviceDailyRunningRecordModels []*models.DeviceDailyRunningRecord
144 deviceDailyRunningRecords := make([]*domain.DeviceDailyRunningRecord, 0) 144 deviceDailyRunningRecords := make([]*domain.DeviceDailyRunningRecord, 0)
145 query := sqlbuilder.BuildQuery(tx.Model(&deviceDailyRunningRecordModels), queryOptions) 145 query := sqlbuilder.BuildQuery(tx.Model(&deviceDailyRunningRecordModels), queryOptions)
  146 + query.SetWhereByQueryOption("company_id = ?", "companyId")
  147 + query.SetWhereByQueryOption("org_id = ?", "orgId")
  148 + if v, ok := queryOptions["productDate"]; ok && len(v.(string)) > 0 {
  149 + query.Where(`product_date = ?`, v)
  150 + }
146 query.SetOffsetAndLimit(20) 151 query.SetOffsetAndLimit(20)
147 query.SetOrderDirect("device_daily_running_record_id", "DESC") 152 query.SetOrderDirect("device_daily_running_record_id", "DESC")
148 if count, err := query.SelectAndCount(); err != nil { 153 if count, err := query.SelectAndCount(); err != nil {
@@ -188,6 +188,9 @@ func (repository *ProductAttendanceRecordRepository) Find(queryOptions map[strin @@ -188,6 +188,9 @@ func (repository *ProductAttendanceRecordRepository) Find(queryOptions map[strin
188 if v, ok := queryOptions["signEndTime"]; ok && !((v.(time.Time)).IsZero()) { 188 if v, ok := queryOptions["signEndTime"]; ok && !((v.(time.Time)).IsZero()) {
189 query.Where("created_at<?", v.(time.Time)) 189 query.Where("created_at<?", v.(time.Time))
190 } 190 }
  191 + if v, ok := queryOptions["employeeType"]; ok && (v.(int)) > 0 {
  192 + query.Where("product_worker->>'employeeType'='?'", v.(int))
  193 + }
191 query.SetOffsetAndLimit(domain.MaxQueryRow) 194 query.SetOffsetAndLimit(domain.MaxQueryRow)
192 query.SetOrderDirect("product_attendance_id", "DESC") 195 query.SetOrderDirect("product_attendance_id", "DESC")
193 if count, err := query.SelectAndCount(); err != nil { 196 if count, err := query.SelectAndCount(); err != nil {
@@ -29,6 +29,24 @@ func GetNextMonthFirstDay(d time.Time) time.Time { @@ -29,6 +29,24 @@ func GetNextMonthFirstDay(d time.Time) time.Time {
29 return GetZeroTime(d) 29 return GetZeroTime(d)
30 } 30 }
31 31
  32 +// GetNextMonthFirstDay 获取传入的时间所在月份的最后一天,即某月最后一天的23:59:59。如传入time.Now(), 返回当前月份的最后一天的23:59:59。
  33 +func GetCurrentMonthFirstDay(t time.Time) time.Time {
  34 + y, m, d := t.Date()
  35 + result := time.Date(y, m, d, 0, 0, 0, 0, time.Local)
  36 + return result
  37 +}
  38 +
  39 +func GetCurrentWeekFirstDay(t time.Time) time.Time {
  40 + d := t.Weekday()
  41 + result := GetZeroTime(t)
  42 + if d == time.Sunday {
  43 + result = result.Add(-time.Hour * 24 * 6)
  44 + } else {
  45 + result = result.Add(-time.Hour * 24 * (time.Duration(d) - 1))
  46 + }
  47 + return result
  48 +}
  49 +
32 // GetZeroTime 获取某一天的0点时间 50 // GetZeroTime 获取某一天的0点时间
33 func GetZeroTime(d time.Time) time.Time { 51 func GetZeroTime(d time.Time) time.Time {
34 return time.Date(d.Year(), d.Month(), d.Day(), 0, 0, 0, 0, time.Local) 52 return time.Date(d.Year(), d.Month(), d.Day(), 0, 0, 0, 0, time.Local)
@@ -9,4 +9,8 @@ func init() { @@ -9,4 +9,8 @@ func init() {
9 web.Router("/statistics", &controllers.StatisticsController{}, "Post:CommonStatisticsService") 9 web.Router("/statistics", &controllers.StatisticsController{}, "Post:CommonStatisticsService")
10 c := &controllers.StatisticsController{} 10 c := &controllers.StatisticsController{}
11 web.Post("/statistics/hour-productive", c.CommonStatisticsHandler("HourProductiveStatistics")) 11 web.Post("/statistics/hour-productive", c.CommonStatisticsHandler("HourProductiveStatistics"))
  12 + web.Post("/statistics/daily-productive-statistics", c.CommonStatisticsHandler("DailyProductiveStatistics"))
  13 + web.Post("/statistics/proportion-of-second-level-statistics", c.CommonStatisticsHandler("ProportionOfSecondLevelStatistics"))
  14 + web.Post("/statistics/workshop-production-efficiency-statistics", c.CommonStatisticsHandler("WorkshopProductionEfficiencyStatistics"))
  15 + web.Post("/statistics/device-running-statistics", c.CommonStatisticsHandler("DeviceRunningStatistics"))
12 } 16 }