作者 yangfu

feat:

1.每日设备数据定时落库
2.时段产能
@@ -21,6 +21,7 @@ require ( @@ -21,6 +21,7 @@ require (
21 github.com/onsi/ginkgo v1.15.2 21 github.com/onsi/ginkgo v1.15.2
22 github.com/onsi/gomega v1.11.0 22 github.com/onsi/gomega v1.11.0
23 github.com/sergi/go-diff v1.2.0 // indirect 23 github.com/sergi/go-diff v1.2.0 // indirect
  24 + github.com/shopspring/decimal v1.2.0
24 github.com/smartystreets/goconvey v1.7.2 // indirect 25 github.com/smartystreets/goconvey v1.7.2 // indirect
25 github.com/stretchr/testify v1.7.0 26 github.com/stretchr/testify v1.7.0
26 github.com/tidwall/gjson v1.13.0 27 github.com/tidwall/gjson v1.13.0
@@ -30,7 +31,6 @@ require ( @@ -30,7 +31,6 @@ require (
30 github.com/yudai/gojsondiff v1.0.0 // indirect 31 github.com/yudai/gojsondiff v1.0.0 // indirect
31 github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect 32 github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
32 github.com/yudai/pp v2.0.1+incompatible // indirect 33 github.com/yudai/pp v2.0.1+incompatible // indirect
33 - golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1  
34 golang.org/x/text v0.3.6 34 golang.org/x/text v0.3.6
35 ) 35 )
36 36
@@ -337,6 +337,8 @@ github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI @@ -337,6 +337,8 @@ github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI
337 github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg= 337 github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
338 github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= 338 github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
339 github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= 339 github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
  340 +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
  341 +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
340 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 342 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
341 github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw= 343 github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
342 github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKzU3qCuvj/tPnimWSsZZzvk9qvkvrIL5naVBPh5s= 344 github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKzU3qCuvj/tPnimWSsZZzvk9qvkvrIL5naVBPh5s=
@@ -42,6 +42,9 @@ func (crontabService *CrontabService) initTask() { @@ -42,6 +42,9 @@ func (crontabService *CrontabService) initTask() {
42 42
43 autoApproveRecord := task.NewTask("autoApproveRecord", "0 */2 * * * *", AutoApproveProductRecord) 43 autoApproveRecord := task.NewTask("autoApproveRecord", "0 */2 * * * *", AutoApproveProductRecord)
44 task.AddTask("autoApproveRecord", autoApproveRecord) 44 task.AddTask("autoApproveRecord", autoApproveRecord)
  45 +
  46 + autoFlushDeviceDailyRunningRecord := task.NewTask("autoFlushDeviceDailyRunningRecord", "0 */1 * * * *", AutoFlushDeviceDailyRunningRecord)
  47 + task.AddTask("autoFlushDeviceDailyRunningRecord", autoFlushDeviceDailyRunningRecord)
45 } 48 }
46 49
47 func (crontabService *CrontabService) StartCrontabTask() { 50 func (crontabService *CrontabService) StartCrontabTask() {
@@ -4,11 +4,13 @@ import ( @@ -4,11 +4,13 @@ import (
4 "context" 4 "context"
5 "fmt" 5 "fmt"
6 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/factory" 6 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/factory"
  7 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/redis"
7 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log" 8 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log"
  9 + "time"
8 ) 10 )
9 11
10 // 定时刷新设备每日运行记录 12 // 定时刷新设备每日运行记录
11 -func AutoFreshDeviceDailyRunningRecord(ctx context.Context) error { 13 +func AutoFlushDeviceDailyRunningRecord(ctx context.Context) error {
12 defer func() { 14 defer func() {
13 if r := recover(); r != nil { 15 if r := recover(); r != nil {
14 log.Logger.Error(fmt.Sprintf("%v", r)) 16 log.Logger.Error(fmt.Sprintf("%v", r))
@@ -28,10 +30,32 @@ func AutoFreshDeviceDailyRunningRecord(ctx context.Context) error { @@ -28,10 +30,32 @@ func AutoFreshDeviceDailyRunningRecord(ctx context.Context) error {
28 transactionContext.RollbackTransaction() 30 transactionContext.RollbackTransaction()
29 }() 31 }()
30 32
31 - //deviceDailyRunningRecordRepository,_,_:= factory.FastPgDeviceDailyRunningRecord(transactionContext,0)  
32 - //  
33 - //// 获取redis里当天的记录  
34 - //t :=time.Now().Add(-time.Minute*20) 33 + log.Logger.Info("【定时刷新设备每日运行记录】 启动")
  34 + deviceDailyRunningRecordRepository, _, _ := factory.FastPgDeviceDailyRunningRecord(transactionContext, 0)
  35 + // 获取redis里当天的记录
  36 + span := time.Duration(20)
  37 + t := time.Now().Add(-time.Minute * span)
  38 + records, err := redis.GetDeviceDailyAllRecord(t)
  39 + if err != nil {
  40 + log.Logger.Error(err.Error())
  41 + return err
  42 + }
  43 +
  44 + for _, v := range records {
  45 + if v.UpdatedAt.Add(time.Minute * 5).Before(time.Now()) {
  46 + log.Logger.Info(fmt.Sprintf("【定时刷新设备每日运行记录】 跳过记录 %v 最后更新时间:%v", v, v.UpdatedAt))
  47 + continue
  48 + }
  49 +
  50 + // 更新设备效率 OEE = tu * pu * qu
  51 +
  52 + if _, err := deviceDailyRunningRecordRepository.Save(v); err != nil {
  53 + log.Logger.Error(err.Error())
  54 + continue
  55 + } else {
  56 + log.Logger.Info(fmt.Sprintf("【定时刷新设备每日运行记录】 刷新记录 %v", v))
  57 + }
  58 + }
35 59
36 if err = transactionContext.CommitTransaction(); err != nil { 60 if err = transactionContext.CommitTransaction(); err != nil {
37 return err 61 return err
@@ -2,8 +2,10 @@ package service @@ -2,8 +2,10 @@ package service
2 2
3 import ( 3 import (
4 "github.com/linmadan/egglib-go/core/application" 4 "github.com/linmadan/egglib-go/core/application"
  5 + "github.com/linmadan/egglib-go/transaction/pg"
5 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/factory" 6 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/factory"
6 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/statistics/query" 7 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/statistics/query"
  8 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/domainService"
7 ) 9 )
8 10
9 // CommonStatisticsService 通用的统计服务 11 // CommonStatisticsService 通用的统计服务
@@ -11,8 +13,8 @@ type CommonStatisticsService struct { @@ -11,8 +13,8 @@ type CommonStatisticsService struct {
11 } 13 }
12 14
13 // CommonStatisticsService 通用的统计服务 15 // CommonStatisticsService 通用的统计服务
14 -func (svr *CommonStatisticsService) CommonStatisticsService(contractStatisticsQuery *query.CommonStatisticsQuery) (interface{}, error) {  
15 - if err := contractStatisticsQuery.ValidateQuery(); err != nil { 16 +func (svr *CommonStatisticsService) CommonStatisticsService(cmd *query.CommonStatisticsQuery) (interface{}, error) {
  17 + if err := cmd.ValidateQuery(); err != nil {
16 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 18 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
17 } 19 }
18 var err error 20 var err error
@@ -27,58 +29,18 @@ func (svr *CommonStatisticsService) CommonStatisticsService(contractStatisticsQu @@ -27,58 +29,18 @@ func (svr *CommonStatisticsService) CommonStatisticsService(contractStatisticsQu
27 _ = transactionContext.RollbackTransaction() 29 _ = transactionContext.RollbackTransaction()
28 }() 30 }()
29 31
30 - //statisticsService, err := factory.CreateCooperationStatisticsService(map[string]interface{}{  
31 - // "transactionContext": transactionContext,  
32 - //})  
33 - //var res interface{}  
34 - //switch contractStatisticsQuery.Action {  
35 - //case domain_service.SearchContractDividends:  
36 - // res, err = statisticsService.SearchContractDividends(contractStatisticsQuery.QueryOptions)  
37 - //case domain_service.GetContractDividends:  
38 - // res, err = statisticsService.GetContractDividends(contractStatisticsQuery.QueryOptions)  
39 - //case domain_service.CooperationGoodsStatistics:  
40 - // res, err = statisticsService.CooperationGoodsStatistics(contractStatisticsQuery.QueryOptions)  
41 - //case domain_service.CooperationModeStatistics:  
42 - // res, err = statisticsService.CooperationModeStatistics(contractStatisticsQuery.QueryOptions)  
43 - //case domain_service.CompanyDividendsStatistics:  
44 - // res, err = statisticsService.CompanyDividendsStatistics(contractStatisticsQuery.QueryOptions)  
45 - //case domain_service.CompanyCooperationUsersStatistics:  
46 - // res, err = statisticsService.CompanyCooperationUsersStatistics(contractStatisticsQuery.QueryOptions)  
47 - //case domain_service.CompanyPaymentHistoryStatistics:  
48 - // res, err = statisticsService.CompanyPaymentHistoryStatistics(contractStatisticsQuery.QueryOptions)  
49 - //case domain_service.CompanyCooperationProjectContracts:  
50 - // res, err = statisticsService.CompanyCooperationProjectContracts(contractStatisticsQuery.QueryOptions)  
51 - //case domain_service.PaymentHistoryHistogramStatistics:  
52 - // res, err = statisticsService.PaymentHistoryHistogramStatistics(contractStatisticsQuery.QueryOptions)  
53 - //case domain_service.CooperationUserModeStatistics:  
54 - // res, err = statisticsService.CooperationUserModeStatistics(contractStatisticsQuery.QueryOptions)  
55 - //case domain_service.DividendsStatistics:  
56 - // res, err = statisticsService.DividendsStatistics(contractStatisticsQuery.QueryOptions)  
57 - //case domain_service.SearchDividendsEstimates:  
58 - // res, err = statisticsService.SearchDividendsEstimates(contractStatisticsQuery.QueryOptions)  
59 - //case domain_service.CooperationCompanyStatistics:  
60 - // res, err = statisticsService.CooperationCompanyStatistics(contractStatisticsQuery.QueryOptions)  
61 - //case domain_service.PersonCooperationContractStatistics:  
62 - // res, err = statisticsService.PersonCooperationContractStatistics(contractStatisticsQuery.QueryOptions)  
63 - //case domain_service.PersonCompanyPaymentHistoryStatistics:  
64 - // res, err = statisticsService.PersonCompanyPaymentHistoryStatistics(contractStatisticsQuery.QueryOptions)  
65 - //case domain_service.PersonCooperationProjectSharedInfo:  
66 - // res, err = statisticsService.PersonCooperationProjectSharedInfo(contractStatisticsQuery.QueryOptions)  
67 - //case domain_service.PersonCooperationProjectSharedInfoAttachment:  
68 - // res, err = statisticsService.PersonCooperationProjectSharedInfoAttachment(contractStatisticsQuery.QueryOptions)  
69 - //case domain_service.PersonCooperationCompany:  
70 - // res, err = statisticsService.PersonCooperationCompany(contractStatisticsQuery.QueryOptions)  
71 - //case domain_service.CreditAccountStatistics:  
72 - // res, err = statisticsService.CreditAccountStatistics(contractStatisticsQuery.QueryOptions)  
73 - //case domain_service.RelevantCooperationContractNumbers:  
74 - // res, err = statisticsService.RelevantCooperationContractNumbers(contractStatisticsQuery.QueryOptions)  
75 - //} 32 + statisticsService, _ := domainService.NewPGCommonStatisticsService(transactionContext.(*pg.TransactionContext))
  33 + response, err := statisticsService.CommonStatistics(cmd.Action, cmd.QueryOptions)
76 if err != nil { 34 if err != nil {
77 return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error()) 35 return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
78 } 36 }
79 if err := transactionContext.CommitTransaction(); err != nil { 37 if err := transactionContext.CommitTransaction(); err != nil {
80 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) 38 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
81 } 39 }
82 - return struct {  
83 - }{}, nil 40 + return response, nil
  41 +}
  42 +
  43 +func NewCommonStatisticsService(options map[string]interface{}) *CommonStatisticsService {
  44 + newProductSectionService := &CommonStatisticsService{}
  45 + return newProductSectionService
84 } 46 }
@@ -52,6 +52,19 @@ func (deviceDailyRunningRecord *DeviceDailyRunningRecord) Update(data map[string @@ -52,6 +52,19 @@ func (deviceDailyRunningRecord *DeviceDailyRunningRecord) Update(data map[string
52 return nil 52 return nil
53 } 53 }
54 54
  55 +func (deviceDailyRunningRecord *DeviceDailyRunningRecord) AddDeviceRunningData(t time.Time, data *DeviceRunningData) {
  56 + deviceDailyRunningRecord.DeviceRunningRecordInfo.AddDeviceRunningData(t, data)
  57 + deviceDailyRunningRecord.UpdatedAt = time.Now()
  58 +}
  59 +
  60 +func (deviceDailyRunningRecord *DeviceDailyRunningRecord) String() string {
  61 + return fmt.Sprintf("记录ID:%v 工段:%v 设备:%v",
  62 + deviceDailyRunningRecord.DeviceDailyRunningRecordId,
  63 + deviceDailyRunningRecord.WorkStation.SectionName,
  64 + deviceDailyRunningRecord.DeviceCode,
  65 + )
  66 +}
  67 +
55 // 设备运行记录信息 68 // 设备运行记录信息
56 type DeviceRunningRecordInfo struct { 69 type DeviceRunningRecordInfo struct {
57 // 当前状态 70 // 当前状态
@@ -66,11 +79,11 @@ type DeviceRunningRecordInfo struct { @@ -66,11 +79,11 @@ type DeviceRunningRecordInfo struct {
66 // 1. 当前设备实际产出数量/理论数量(理论数量=60*60*12/标准工时) 79 // 1. 当前设备实际产出数量/理论数量(理论数量=60*60*12/标准工时)
67 // 2. 没有数量100% 80 // 2. 没有数量100%
68 PerformanceUtilization float64 `json:"pu"` 81 PerformanceUtilization float64 `json:"pu"`
69 - // 合格率 QualificationUtilization 82 + // 合格率 QualificationUtilization ?设备提交的二级品事串 、 机器上报的是kg
70 // 1.按工段的合格率 83 // 1.按工段的合格率
71 // 2.默认100% 84 // 2.默认100%
72 QualificationUtilization float64 `json:"qu"` 85 QualificationUtilization float64 `json:"qu"`
73 - // 运行时长 单位:h 86 + // 运行时长 单位:分钟
74 UpTime float64 `json:"upTime"` 87 UpTime float64 `json:"upTime"`
75 // 生成数量 88 // 生成数量
76 Count int `json:"count"` 89 Count int `json:"count"`
@@ -102,7 +115,7 @@ func (d *DeviceRunningRecordInfo) AddDeviceRunningData(t time.Time, data *Device @@ -102,7 +115,7 @@ func (d *DeviceRunningRecordInfo) AddDeviceRunningData(t time.Time, data *Device
102 d.AddTimeLineDeviceStatus(t, data) 115 d.AddTimeLineDeviceStatus(t, data)
103 116
104 //d.OEE 117 //d.OEE
105 - d.TimeUtilization = d.UpTime * 100 / (time.Now().Sub(utils.GetZeroTime(time.Now())).Hours()) 118 + d.TimeUtilization = utils.Round(d.UpTime*100/(time.Now().Sub(utils.GetZeroTime(time.Now())).Minutes()), 2)
106 //d.PerformanceUtilization 119 //d.PerformanceUtilization
107 //d.QualificationUtilization 120 //d.QualificationUtilization
108 } 121 }
@@ -128,7 +141,7 @@ func (d *DeviceRunningRecordInfo) ResetUpTime() float64 { @@ -128,7 +141,7 @@ func (d *DeviceRunningRecordInfo) ResetUpTime() float64 {
128 var upTime float64 141 var upTime float64
129 for _, v := range d.TimeLineDeviceStatus { 142 for _, v := range d.TimeLineDeviceStatus {
130 t := v.CountTime(v.Up) 143 t := v.CountTime(v.Up)
131 - upTime += t.Hours() 144 + upTime += t.Minutes()
132 } 145 }
133 d.UpTime = upTime 146 d.UpTime = upTime
134 return upTime 147 return upTime
@@ -191,12 +204,15 @@ func (d *HourDeviceStatus) CountTime(v int) time.Duration { @@ -191,12 +204,15 @@ func (d *HourDeviceStatus) CountTime(v int) time.Duration {
191 count := 0 204 count := 0
192 index := 1 205 index := 1
193 for i := 0; i < l; i++ { 206 for i := 0; i < l; i++ {
  207 + if index > v {
  208 + break
  209 + }
194 if index&v > 0 { 210 if index&v > 0 {
195 count++ 211 count++
196 } 212 }
197 index <<= 1 213 index <<= 1
198 } 214 }
199 - return time.Duration(d.Window*count) * time.Minute / time.Hour 215 + return time.Duration(d.Window*count) * time.Minute
200 } 216 }
201 217
202 func NewHourDeviceStatus() *HourDeviceStatus { 218 func NewHourDeviceStatus() *HourDeviceStatus {
@@ -54,3 +54,46 @@ func (dao *ProductRecordDao) RecentUnApprovedProductRecord(fromLastHour int, rec @@ -54,3 +54,46 @@ func (dao *ProductRecordDao) RecentUnApprovedProductRecord(fromLastHour int, rec
54 return int64(count), productAttendanceRecords, nil 54 return int64(count), productAttendanceRecords, nil
55 } 55 }
56 } 56 }
  57 +
  58 +// 时段产能
  59 +func (dao *ProductRecordDao) TimeSectionProductRecord(companyId, orgId, workshopId int, lineId int, beginTime time.Time, result interface{}) error {
  60 +
  61 + tx := dao.transactionContext.PgTx
  62 + sql := fmt.Sprintf(`
  63 +WITH ts_product as(
  64 + select sum(a.weight) total,a.ts from (
  65 + select
  66 + cast(product_record_info->>'weigh' as DECIMAL) weight,
  67 + "replace"(to_char(created_at at time ZONE 'Asia/shanghai', 'HH24:') || cast(date_part('minute',created_at) as integer)/30*30, ':0', ':00') ts
  68 + from manufacture.product_records
  69 + where
  70 + company_id = ?
  71 + and org_id = ?
  72 + and work_station->>'workshopId'='?'
  73 + and work_station->>'lineId'='?'
  74 + and product_record_type = 8
  75 + and created_at >?
  76 + ) a
  77 + group by a.ts
  78 + order by ts
  79 +)
  80 +-- select * from ts_product
  81 +, ts_product_list as (
  82 + select d.ts,ts_product.total from (
  83 + select to_char(c.ts::timestamp,'HH24:MI') ts from (
  84 + select generate_series(a.end - interval '5 hour',
  85 + "replace"(to_char(a.end, 'yyyy-mm-dd HH24:') || cast(date_part('minute',a.end) as integer)/30*30+30, ':0', ':00')::timestamp,
  86 + '30 minute') ts from (
  87 + select to_timestamp(to_char(now() at time ZONE 'Asia/shanghai','yyyy-mm-dd HH24'),'yyyy-mm-dd HH24') as end
  88 + ) a
  89 + ) c
  90 + ) d left join ts_product on d.ts = ts_product.ts
  91 +)
  92 +SELECT ts, coalesce(total,0) total
  93 +from ts_product_list
  94 +`)
  95 + if _, err := tx.Query(result, sql, companyId, orgId, workshopId, lineId, beginTime); err != nil {
  96 + return err
  97 + }
  98 + return nil
  99 +}
@@ -3,7 +3,12 @@ package domainService @@ -3,7 +3,12 @@ package domainService
3 import ( 3 import (
4 "fmt" 4 "fmt"
5 pgTransaction "github.com/linmadan/egglib-go/transaction/pg" 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/dao"
  8 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/repository"
6 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils" 9 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
  10 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log"
  11 + "time"
7 ) 12 )
8 13
9 const ( 14 const (
@@ -15,20 +20,55 @@ type PGCommonStatisticsService struct { @@ -15,20 +20,55 @@ type PGCommonStatisticsService struct {
15 transactionContext *pgTransaction.TransactionContext 20 transactionContext *pgTransaction.TransactionContext
16 } 21 }
17 22
18 -func (ptr *PGCommonStatisticsService) CommonStatistics(actionType, queryOptions map[string]interface{}) (interface{}, error) { 23 +func (ptr *PGCommonStatisticsService) CommonStatistics(actionType string, queryOptions map[string]interface{}) (interface{}, error) {
  24 + var result interface{}
  25 + var err error
19 switch actionType { 26 switch actionType {
20 - 27 + case HourProductiveStatistics:
  28 + result, err = ptr.HourProductiveStatistics(queryOptions)
  29 + break
21 } 30 }
22 - return nil, nil 31 + return result, err
23 } 32 }
24 33
25 // 时段产能-统计 (传串设备) 34 // 时段产能-统计 (传串设备)
26 func (ptr *PGCommonStatisticsService) HourProductiveStatistics(queryOptions map[string]interface{}) (interface{}, error) { 35 func (ptr *PGCommonStatisticsService) HourProductiveStatistics(queryOptions map[string]interface{}) (interface{}, error) {
27 var request = &HourProductiveStatisticsRequest{} 36 var request = &HourProductiveStatisticsRequest{}
28 - if err := utils.LoadQueryObject(queryOptions, &request); err != nil { 37 + if err := utils.LoadQueryObject(queryOptions, request); err != nil {
29 return nil, err 38 return nil, err
30 } 39 }
  40 +
  41 + workshopRepository, _ := repository.NewWorkshopRepository(ptr.transactionContext)
  42 + type record struct {
  43 + Ts string `json:"ts"`
  44 + Total float64 `json:"total"`
  45 + }
  46 +
  47 + workshop, err := workshopRepository.FindOne(map[string]interface{}{"workshopId": request.WorkshopId})
  48 + if err != nil || workshop == nil {
31 return nil, nil 49 return nil, nil
  50 + }
  51 + productRecordDao, _ := dao.NewProductRecordDao(ptr.transactionContext)
  52 +
  53 + var response = make([]interface{}, 0)
  54 + for _, v := range workshop.GetProductLines(domain.NotDeleted) {
  55 + 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 {
  57 + log.Logger.Error(err.Error())
  58 + continue
  59 + }
  60 + var xData []string = make([]string, 0)
  61 + var values []interface{} = make([]interface{}, 0)
  62 + for _, r := range result {
  63 + xData = append(xData, r.Ts)
  64 + values = append(values, r.Total)
  65 + }
  66 + response = append(response, map[string]interface{}{
  67 + "lineName": v.LineName,
  68 + "data": NewXYData(xData, values),
  69 + })
  70 + }
  71 + return response, nil
32 } 72 }
33 73
34 type HourProductiveStatisticsRequest struct { 74 type HourProductiveStatisticsRequest struct {
@@ -37,6 +77,17 @@ type HourProductiveStatisticsRequest struct { @@ -37,6 +77,17 @@ type HourProductiveStatisticsRequest struct {
37 WorkshopId int `json:"workshopId" valid:"Required"` 77 WorkshopId int `json:"workshopId" valid:"Required"`
38 } 78 }
39 79
  80 +func NewXYData(xData []string, values interface{}) interface{} {
  81 + return map[string]interface{}{
  82 + "xAxis": map[string]interface{}{
  83 + "data": xData,
  84 + },
  85 + "source": map[string]interface{}{
  86 + "value": values,
  87 + },
  88 + }
  89 +}
  90 +
40 func NewPGCommonStatisticsService(transactionContext *pgTransaction.TransactionContext) (*PGCommonStatisticsService, error) { 91 func NewPGCommonStatisticsService(transactionContext *pgTransaction.TransactionContext) (*PGCommonStatisticsService, error) {
41 if transactionContext == nil { 92 if transactionContext == nil {
42 return nil, fmt.Errorf("transactionContext参数不能为nil") 93 return nil, fmt.Errorf("transactionContext参数不能为nil")
@@ -92,7 +92,7 @@ func (ptr *PGWorkshopDataConsumeService) Consume(companyId, orgId int, record *d @@ -92,7 +92,7 @@ func (ptr *PGWorkshopDataConsumeService) Consume(companyId, orgId int, record *d
92 // 2.保存设备生产记录 92 // 2.保存设备生产记录
93 93
94 // 3.更新 设备每日运行记录(汇总) - redis更新 十分钟异步刷库 94 // 3.更新 设备每日运行记录(汇总) - redis更新 十分钟异步刷库
95 - deviceDailyRecord.DeviceRunningRecordInfo.AddDeviceRunningData(deviceRunningData.CollectionTime, deviceRunningData) 95 + deviceDailyRecord.AddDeviceRunningData(deviceRunningData.CollectionTime, deviceRunningData)
96 if err = redis.SaveDeviceDailyRunningRecord(deviceDailyRecord); err != nil { 96 if err = redis.SaveDeviceDailyRunningRecord(deviceDailyRecord); err != nil {
97 return nil, err 97 return nil, err
98 } 98 }
@@ -13,6 +13,10 @@ import ( @@ -13,6 +13,10 @@ import (
13 func GetDeviceDailyRunningRecord(t time.Time, deviceCode string) (*domain.DeviceDailyRunningRecord, error) { 13 func GetDeviceDailyRunningRecord(t time.Time, deviceCode string) (*domain.DeviceDailyRunningRecord, error) {
14 client := GetRedis() 14 client := GetRedis()
15 key := DeviceDailyRunningRecordKey(t, deviceCode) 15 key := DeviceDailyRunningRecordKey(t, deviceCode)
  16 + return getDeviceDailyRunningRecord(client, key)
  17 +}
  18 +
  19 +func getDeviceDailyRunningRecord(client *redis.Client, key string) (*domain.DeviceDailyRunningRecord, error) {
16 result := client.Get(key) 20 result := client.Get(key)
17 data, err := result.Bytes() 21 data, err := result.Bytes()
18 if err == redis.Nil { 22 if err == redis.Nil {
@@ -48,3 +52,27 @@ func DeviceDailyRunningRecordKey(t time.Time, deviceCode string) string { @@ -48,3 +52,27 @@ func DeviceDailyRunningRecordKey(t time.Time, deviceCode string) string {
48 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) 52 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)
49 return str 53 return str
50 } 54 }
  55 +
  56 +// 获取设备每日所有数据记录
  57 +func GetDeviceDailyAllRecord(t time.Time) ([]*domain.DeviceDailyRunningRecord, error) {
  58 + client := GetRedis()
  59 + sliceResult := client.Keys(DeviceDailyAllRecordKey(t))
  60 + keys, err := sliceResult.Result()
  61 + var records = make([]*domain.DeviceDailyRunningRecord, 0)
  62 + if err != nil {
  63 + return nil, err
  64 + }
  65 + for _, v := range keys {
  66 + record, err := getDeviceDailyRunningRecord(client, v)
  67 + if err != nil {
  68 + return nil, err
  69 + }
  70 + records = append(records, record)
  71 + }
  72 + return records, nil
  73 +}
  74 +
  75 +func DeviceDailyAllRecordKey(t time.Time) string {
  76 + 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"))
  77 + return str
  78 +}
@@ -6,6 +6,7 @@ import ( @@ -6,6 +6,7 @@ import (
6 "fmt" 6 "fmt"
7 "github.com/beego/beego/v2/core/validation" 7 "github.com/beego/beego/v2/core/validation"
8 jsonlib "github.com/linmadan/egglib-go/utils/json" 8 jsonlib "github.com/linmadan/egglib-go/utils/json"
  9 + "github.com/shopspring/decimal"
9 "io" 10 "io"
10 "reflect" 11 "reflect"
11 "strconv" 12 "strconv"
@@ -379,3 +380,10 @@ func SubStr(str string, start, length int) string { @@ -379,3 +380,10 @@ func SubStr(str string, start, length int) string {
379 } 380 }
380 return string(rs[start:end]) 381 return string(rs[start:end])
381 } 382 }
  383 +
  384 +func Round(value float64, places int32) float64 {
  385 + quantity := decimal.NewFromFloat(value)
  386 + d := quantity.Round(places)
  387 + rsp, _ := d.Float64()
  388 + return rsp
  389 +}
  1 +package controllers
  2 +
  3 +import (
  4 + "github.com/beego/beego/v2/server/web/context"
  5 + "github.com/linmadan/egglib-go/utils/json"
  6 + "github.com/linmadan/egglib-go/web/beego"
  7 + "github.com/linmadan/egglib-go/web/beego/utils"
  8 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/statistics/query"
  9 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/statistics/service"
  10 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/constant"
  11 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
  12 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log"
  13 + "net/http"
  14 + "strconv"
  15 + "strings"
  16 +)
  17 +
  18 +type StatisticsController struct {
  19 + beego.BaseController
  20 +}
  21 +
  22 +func (controller *StatisticsController) CommonStatisticsService() {
  23 + attendanceService := service.NewCommonStatisticsService(nil)
  24 + cmd := &query.CommonStatisticsQuery{}
  25 + controller.Unmarshal(cmd)
  26 + operateInfo := ParseOperateInfo(controller.BaseController)
  27 + cmd.QueryOptions["companyId"] = operateInfo.CompanyId
  28 + cmd.QueryOptions["orgId"] = operateInfo.OrgId
  29 + data, err := attendanceService.CommonStatisticsService(cmd)
  30 + controller.Response(data, err)
  31 +}
  32 +
  33 +func (controller *StatisticsController) CommonStatisticsHandler(actionType string) func(ctx *context.Context) {
  34 + return func(ctx *context.Context) {
  35 + attendanceService := service.NewCommonStatisticsService(nil)
  36 + cmd := &query.CommonStatisticsQuery{}
  37 + options := make(map[string]interface{})
  38 + Unmarshal(ctx, &options)
  39 + operateInfo := ContextParseOperateInfo(ctx)
  40 + options["companyId"] = operateInfo.CompanyId
  41 + options["orgId"] = operateInfo.OrgId
  42 + cmd.Action = actionType
  43 + cmd.QueryOptions = options
  44 + data, err := attendanceService.CommonStatisticsService(cmd)
  45 + Response(ctx, data, err)
  46 + }
  47 +}
  48 +
  49 +func Response(ctx *context.Context, data interface{}, err error) {
  50 + var response utils.JsonResponse
  51 + if err != nil {
  52 + response = utils.ResponseError(ctx, err)
  53 + } else {
  54 + response = utils.ResponseData(ctx, data)
  55 + }
  56 + ctx.Output.SetStatus(http.StatusOK)
  57 + ctx.Output.JSON(response, false, false)
  58 +}
  59 +
  60 +func Unmarshal(ctx *context.Context, v interface{}) error {
  61 + body := ctx.Input.RequestBody
  62 + if len(body) == 0 {
  63 + body = []byte("{}")
  64 + }
  65 + return json.Unmarshal(body, v)
  66 +}
  67 +
  68 +// ParseOperateInfo 从头部解析操作对象信息
  69 +func ContextParseOperateInfo(c *context.Context) *domain.OperateInfo {
  70 + opt := &domain.OperateInfo{}
  71 + opt.UserId = ContextHeader(c, constant.HeaderUserId)
  72 + opt.CompanyId = ContextHeader(c, constant.HeaderCompanyId)
  73 + opt.OrgId = ContextHeader(c, constant.HeaderOrgId)
  74 + orgIdList := c.Input.Header(constant.HeaderOrgIds)
  75 + splitOrgIdList := strings.Split(orgIdList, constant.CUSTOMER_ACCOUNT_DELIMITER)
  76 + for i := range splitOrgIdList {
  77 + orgId, _ := strconv.Atoi(splitOrgIdList[i])
  78 + if orgId == 0 {
  79 + continue
  80 + }
  81 + opt.OrgIds = append(opt.OrgIds, orgId)
  82 + }
  83 + return opt
  84 +}
  85 +
  86 +func ContextHeader(c *context.Context, key string) int {
  87 + if len(c.Input.Header(key)) == 0 {
  88 + return 0
  89 + }
  90 + res, err := strconv.Atoi(c.Input.Header(key))
  91 + if err != nil {
  92 + log.Logger.Error(err.Error())
  93 + return 0
  94 + }
  95 + return res
  96 +}
  1 +package routers
  2 +
  3 +import (
  4 + "github.com/beego/beego/v2/server/web"
  5 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/port/beego/controllers"
  6 +)
  7 +
  8 +func init() {
  9 + web.Router("/statistics", &controllers.StatisticsController{}, "Post:CommonStatisticsService")
  10 + c := &controllers.StatisticsController{}
  11 + web.Post("/statistics/hour-productive", c.CommonStatisticsHandler("HourProductiveStatistics"))
  12 +}