正在显示
13 个修改的文件
包含
311 行增加
和
66 行删除
@@ -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 | +} |
pkg/port/beego/routers/statistics_router.go
0 → 100644
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 | +} |
-
请 注册 或 登录 后发表评论