作者 Administrator

合并分支 'test' 到 'master'

Test



查看合并请求 !5
正在显示 58 个修改的文件 包含 1534 行增加504 行删除
POSTGRESQL_DB_NAME = allied_creation_dev
POSTGRESQL_HOST = 114.55.200.59
POSTGRESQL_PORT = 31543
POSTGRESQL_USER = postgres
POSTGRESQL_PASSWORD = eagle1010
DISABLE_SQL_GENERATE_COMMENT = false
SERVICE_ENV = test
HTTP_PORT = 8081
ENABLE_KAFKA_LOG11 = true
HTTPS_PORT = 8143
ALLIED_CREATION_USER_HOST = http://allied-creation-user-dev.fjmaimaimai.com
... ...
-- 表product_calendar 增加字段 break_time_periods
ALTER TABLE manufacture.product_calendar ADD COLUMN break_time_periods jsonb;
-- 表product_attendance_record 增加字段 product_date
alter table manufacture.product_attendance_record add COLUMN product_date timestamptz;
update manufacture.product_attendance_record set product_date = sign_in where product_date is null ;
\ No newline at end of file
... ...
... ... @@ -24,7 +24,6 @@ require (
github.com/onsi/gomega v1.11.0
github.com/sergi/go-diff v1.2.0 // indirect
github.com/shopspring/decimal v1.2.0
github.com/sirupsen/logrus v1.8.0
github.com/smartystreets/goconvey v1.7.2 // indirect
github.com/stretchr/testify v1.7.0
github.com/tidwall/gjson v1.13.0
... ... @@ -37,4 +36,4 @@ require (
golang.org/x/text v0.3.6
)
replace github.com/linmadan/egglib-go v0.0.0-20210313060205-8b5e456b11f7 => github.com/tiptok/egglib-go v0.0.0-20220120032512-24dfab2b4987
replace github.com/linmadan/egglib-go v0.0.0-20210313060205-8b5e456b11f7 => github.com/tiptok/egglib-go v0.0.0-20220421085958-9682d0ac42c1
... ...
... ... @@ -380,8 +380,8 @@ github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tiptok/egglib-go v0.0.0-20220120032512-24dfab2b4987 h1:0e2hOSL+//5AL7e1r3xCGEugsOPsw2POAm82VZvWLe4=
github.com/tiptok/egglib-go v0.0.0-20220120032512-24dfab2b4987/go.mod h1:xl9i83IKNUkwlobRF6XLKn1RRbZsT+7yhCicpTGWTKc=
github.com/tiptok/egglib-go v0.0.0-20220421085958-9682d0ac42c1 h1:mUikg1B4YHx79eAqj17OoyfLvOfYCiXmhtHd6ywu6Rc=
github.com/tiptok/egglib-go v0.0.0-20220421085958-9682d0ac42c1/go.mod h1:jfeZYXCWwE7u3bUeyJlfhlzC25b9699lUMURP7pdE3I=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
... ...
... ... @@ -3,7 +3,6 @@ package main
import (
"fmt"
"github.com/beego/beego/v2/server/web"
"github.com/linmadan/egglib-go/log/logrus"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/constant"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/redis"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log"
... ... @@ -19,22 +18,19 @@ import (
_ "gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/port/beego"
)
//func init(){
// constant.Configurator = utils.BeegoAppConfigurator{}
// web.LoadAppConfig("ini","config/app.conf")
//}
func main() {
defer func() {
if r := recover(); r != nil {
log.Logger.Error(fmt.Sprintf("%v", r))
}
}()
if constant.ENABLE_KAFKA_LOG {
w, _ := logrus.NewKafkaWriter(constant.KAFKA_HOST, constant.TOPIC_LOG_STASH, false)
log.Logger.AddHook(w)
}
bw := log.NewBeegoLogWriter(log.LoggerConfig{
Filename: constant.LOG_FILE,
Level: 7,
MaxSize: 1024 * 1024 * 2,
})
log.Logger.AddHook(bw)
log.InitLogHook(constant.ENABLE_KAFKA_LOG, true)
redis.InitRedis()
log.Logger.Info("server start ....")
log.Logger.Debug(fmt.Sprintf("ENABLE_KAFKA_LOG:%v", constant.ENABLE_KAFKA_LOG))
... ...
... ... @@ -2,38 +2,53 @@ package command
import (
"fmt"
"github.com/beego/beego/v2/core/validation"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
"reflect"
"strings"
"time"
"github.com/beego/beego/v2/core/validation"
)
type CreateAttendanceCommand struct {
// 考勤记录ID
//ProductAttendanceId int `cname:"考勤记录ID" json:"productAttendanceId" valid:"Required"`
// 考勤类型 1.正常 2.支援
AttendanceType int `json:"attendanceType,omitempty"`
AttendanceType int `cname:"考勤类型" json:"attendanceType,omitempty"`
// 生产班组Id
ProductGroupId int `json:"productGroupId,omitempty" valid:"Required"`
ProductGroupId int `cname:"生产班组Id" json:"productGroupId,omitempty" valid:"Required"`
// 生产工人
ProductWorkerId int `json:"productWorkerId,omitempty" valid:"Required"`
ProductWorkerId int `cname:"生产工人" json:"productWorkerId,omitempty" valid:"Required"`
// 车间ID
WorkshopId int `cname:"车间ID" json:"workshopId" valid:"Required"`
// 生产线ID
LineId int `cname:"生产线ID" json:"lineId" valid:"Required"`
// 工段ID
SectionId int `cname:"工段ID" json:"sectionId" valid:"Required"`
// 生产日期
ProductDate string `cname:"生产日期" json:"productDate,omitempty" valid:"Required"`
// 签到
SignIn time.Time `json:"signIn,omitempty"`
SignIn string `cname:"上岗时间" json:"signIn,omitempty" valid:"Required"`
// 签退
SignOut time.Time `json:"signOut,omitempty"`
// 考勤状态 1.未审核 2:已审核 3.自动审核
//AttendanceStatus int `json:"attendanceStatus,omitempty"`
SignOut string `cname:"下岗时间" json:"signOut,omitempty" valid:"Required"`
// 考勤状态 1.未审核 2:审核
AttendanceStatus int `cname:"考勤状态" json:"attendanceStatus,omitempty"`
// 休息时长
BreakTime float64 `cname:"休息时长" json:"breakTime"`
// 工时
WorkTime float64 `cname:"工时" json:"workTime"`
// 准备(true:准备完毕 false:进行预查)
Prepared bool `json:"prepared"`
}
func (createAttendanceCommand *CreateAttendanceCommand) Valid(validation *validation.Validation) {
//validation.SetError("CustomValid", "未实现的自定义认证")
if err := utils.ValidWorkTime(createAttendanceCommand.SignIn); err != nil {
validation.Error(err.Error())
return
}
if err := utils.ValidWorkTime(createAttendanceCommand.SignOut); err != nil {
validation.Error(err.Error())
return
}
validation.Range(createAttendanceCommand.AttendanceStatus, 1, 2, "attendanceStatus")
}
func (createAttendanceCommand *CreateAttendanceCommand) ValidateCommand() error {
... ...
... ... @@ -31,6 +31,10 @@ type AttendanceRecordDto struct {
SignOut string `json:"signOut"`
// 考勤状态 1.未审核 2:已审核 3.自动审核
AttendanceStatus int `json:"attendanceStatus"`
// 打卡工时
WorkTime float64 `json:"workTime"`
// 休息工时
BreakTime float64 `json:"breakTime"`
// 工时(审核前)
WorkTimeBefore float64 `json:"workTimeBefore"`
// 工时(审核后)
... ... @@ -50,7 +54,7 @@ func (d *AttendanceRecordDto) LoadDto(m *domain.ProductAttendanceRecord, orgId i
d.WorkStation = m.WorkStation
if !m.SignIn.IsZero() {
d.SignIn = m.SignIn.Local().Format("15:04:05")
d.SignDate = m.SignIn.Local().Format("2006-01-02")
d.SignDate = m.ProductTime().Local().Format("2006-01-02")
}
if !m.SignOut.IsZero() {
d.SignOut = m.SignOut.Local().Format("15:04:05")
... ... @@ -59,23 +63,16 @@ func (d *AttendanceRecordDto) LoadDto(m *domain.ProductAttendanceRecord, orgId i
d.WorkTimeAfter = m.WorkTimeAfter
d.AttendanceStatus = m.AttendanceStatus
d.AuthFlag = domain.CheckOrgAuth(orgId, m.OrgId)
if m.Ext != nil {
d.OrgName = m.Ext.OrgName
//d.ProductAttendanceRecordExt = m.Ext.AttendanceExt
//if
if m.Ext.AttendanceExt != nil {
if m.Ext.AttendanceExt.ApproveUserId > 0 {
d.ApproveUser = &domain.User{
UserId: m.Ext.AttendanceExt.ApproveUserId,
UserName: m.Ext.AttendanceExt.ApproveUserName,
}
}
if m.Ext.AttendanceExt.ApproveAt > 0 {
t := time.Unix(m.Ext.AttendanceExt.ApproveAt, 0)
d.ApproveAt = t.Local().Format("2006-01-02 15:04:05")
}
d.GroupName = m.Ext.AttendanceExt.GroupName
d.OrgName = m.Ext.OrgName
d.ApproveUser = m.ApproveUser()
d.GroupName = m.GroupName()
if m.Ext != nil && m.Ext.AttendanceExt != nil {
if m.Ext.AttendanceExt.ApproveAt > 0 {
t := time.Unix(m.Ext.AttendanceExt.ApproveAt, 0)
d.ApproveAt = t.Local().Format("2006-01-02 15:04:05")
}
d.WorkTime = m.WorkTimeBefore + m.Ext.AttendanceExt.BreakTime
d.BreakTime = m.Ext.AttendanceExt.BreakTime
}
return d
}
... ...
... ... @@ -40,10 +40,7 @@ func (d *EmployeeAttendanceRecordDto) LoadDto(m *domain.ProductAttendanceRecord,
d.AttendanceType = m.AttendanceType
d.ProductWorker = m.ProductWorker
d.WorkStation = m.WorkStation
if !m.SignIn.IsZero() {
//d.SignIn = m.SignIn.Format("15:04:05")
d.SignDate = m.SignIn.Local().Format("2006-01-02")
}
d.SignDate = m.ProductTime().Local().Format("2006-01-02")
d.WorkTime = utils.Round(m.WorkTimeAfter, 1)
//d.WorkTimeAfter = m.WorkTimeAfter
d.AttendanceStatus = m.AttendanceStatus
... ... @@ -51,12 +48,7 @@ func (d *EmployeeAttendanceRecordDto) LoadDto(m *domain.ProductAttendanceRecord,
d.EmployeeTypeDescription = domain.EmployeeTypeDescription(m.ProductWorker.EmployeeType)
d.AttendanceStatusDescription = domain.AttendanceStatusDescription(m.AttendanceStatus)
d.AuthFlag = domain.CheckOrgAuth(orgId, m.OrgId)
if m.Ext != nil {
d.OrgName = m.Ext.OrgName
//d.ProductAttendanceRecordExt = m.Ext.AttendanceExt
if m.Ext.AttendanceExt != nil {
d.GroupName = m.Ext.AttendanceExt.GroupName
}
}
d.OrgName = m.Ext.OrgName
d.GroupName = m.GroupName()
return d
}
... ...
... ... @@ -34,9 +34,6 @@ func (d *WorkshopWorkTimeRecordDto) LoadDto(m *domain.WorkshopWorkTimeRecord, or
d.WorkStation = m.WorkStation
d.RecordDate = m.RecordDate.Local().Format("2006-01-02")
d.AuthFlag = domain.CheckOrgAuth(orgId, m.OrgId)
if m.Ext != nil {
d.OrgName = m.Ext.OrgName
//d.ProductAttendanceRecordExt = m.Ext.AttendanceExt
}
d.OrgName = m.Ext.OrgName
return d
}
... ...
... ... @@ -55,21 +55,22 @@ func (cmd *SearchEmployeeAttendanceQuery) Valid(validation *validation.Validatio
cmd.Offset, cmd.Limit = domain.Pagination(cmd.PageNumber, cmd.PageSize)
var err error
if len(cmd.BeginTime) > 0 {
if cmd.SignBeginTime, err = time.ParseInLocation("2006-01-02 15:04:05", cmd.BeginTime, time.Local); err != nil {
if cmd.SignBeginTime, err = time.ParseInLocation("2006-01-02", cmd.BeginTime, time.Local); err != nil {
log.Logger.Error(err.Error())
validation.Error("开始时间有误")
return
}
}
if len(cmd.EndTime) > 0 {
if cmd.SignEndTime, err = time.ParseInLocation("2006-01-02 15:04:05", cmd.EndTime, time.Local); err != nil {
if cmd.SignEndTime, err = time.ParseInLocation("2006-01-02", cmd.EndTime, time.Local); err != nil {
log.Logger.Error(err.Error())
validation.Error("结束时间有误")
return
}
if cmd.SignBeginTime.Equal(cmd.SignEndTime) {
cmd.SignEndTime = cmd.SignEndTime.Add(time.Hour * 24)
}
cmd.SignEndTime = cmd.SignEndTime.AddDate(0, 0, 1)
//if cmd.SignBeginTime.Equal(cmd.SignEndTime) {
// cmd.SignEndTime = cmd.SignEndTime.Add(time.Hour * 24)
//}
}
//cmd.AttendanceStatus = 6 // 审核 + 自动审核
cmd.InAttendanceStatus = []int{2, 3}
... ...
package service
import (
"fmt"
"github.com/linmadan/egglib-go/core/application"
"github.com/linmadan/egglib-go/transaction/pg"
"github.com/linmadan/egglib-go/utils/xtime"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/attendance/command"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/attendance/dto"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/attendance/query"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/factory"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/dao"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/domainService"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
"time"
... ... @@ -100,6 +104,26 @@ func (attendanceService *AttendanceService) CreateAttendance(operateInfo *domain
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
//var workTime float64 = 0
//if cmd.WorkTime-cmd.BreakTime > 0 {
// workTime = cmd.WorkTime - cmd.BreakTime
//}
signIn, err := xtime.ParseInLocation(time.Local, fmt.Sprintf("%v %v:00", cmd.ProductDate, cmd.SignIn))
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
signOut, err := xtime.ParseInLocation(time.Local, fmt.Sprintf("%v %v:00", cmd.ProductDate, cmd.SignOut))
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
productDate, err := xtime.ParseInLocation(time.Local, cmd.ProductDate)
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
if !xtime.BeforeEqual(productDate, time.Now()) {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, fmt.Sprintf("日期需要小于等于%v", time.Now().Format("2006-01-02")))
}
newAttendance := &domain.ProductAttendanceRecord{
//ProductAttendanceId: cmd.ProductAttendanceId,
CompanyId: operateInfo.CompanyId,
... ... @@ -107,30 +131,52 @@ func (attendanceService *AttendanceService) CreateAttendance(operateInfo *domain
AttendanceType: cmd.AttendanceType,
ProductWorker: user,
WorkStation: workStation,
SignIn: cmd.SignIn,
SignOut: cmd.SignOut,
AttendanceStatus: domain.AttendanceNotApprove,
WorkTimeBefore: 0,
SignIn: signIn,
SignOut: signOut,
AttendanceStatus: cmd.AttendanceStatus,
WorkTimeBefore: cmd.WorkTime,
WorkTimeAfter: 0,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
Ext: domain.NewExt(org.OrgName).WithAttendanceExt(&domain.ProductAttendanceRecordExt{
GroupName: productGroup.GroupName,
ProductGroupId: productGroup.ProductGroupId,
BreakTime: cmd.BreakTime,
}),
ProductDate: productDate,
}
newAttendance.WorkTimeBefore = newAttendance.ComputeWorkTimeBefore()
var attendanceRepository domain.ProductAttendanceRecordRepository
if cmd.AttendanceStatus == domain.AttendanceApproved {
newAttendance.WorkTimeAfter = domain.AttendanceApproved
newAttendance.WorkTimeAfter = cmd.WorkTime
}
var (
attendanceRepository domain.ProductAttendanceRecordRepository
attendanceRecordDao *dao.AttendanceRecordDao
)
attendanceRecordDao, _ = dao.NewAttendanceRecordDao(transactionContext.(*pg.TransactionContext))
attendanceRepository, _, _ = factory.FastPgAttendance(transactionContext, 0)
if !cmd.Prepared {
// 检查时间段内是否有重复的打卡记录
count, _, err := attendanceRecordDao.WorkerAttendanceRecordsByProductDate(operateInfo.CompanyId, operateInfo.OrgId, cmd.ProductWorkerId, newAttendance.ProductDate, newAttendance.SignIn, newAttendance.SignIn)
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
if count > 0 {
return map[string]interface{}{
"message": fmt.Sprintf("已存在员工%v的工时记录,是否继续新增", user.UserName),
"needConfirm": true,
}, nil
}
}
if attendance, err := attendanceRepository.Save(newAttendance); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
} else {
domainService.SendWorkshopWorkTimeStaticJob(attendance)
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return attendance, nil
return struct{}{}, nil
}
}
... ...
... ... @@ -2,6 +2,7 @@ package command
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
"reflect"
"strings"
... ... @@ -23,7 +24,7 @@ type CreateProductCalendarCommand struct {
// 上班班次 1:全天 2:白班 4:中班 8:夜班
WorkOn int `cname:"上班班次 1:全天 2:白班 4:中班 8:夜班" json:"workOn" valid:"Required"`
// 日历选择
CalendarSelected []int `cname:"日历选择" json:"calendarSelected" valid:"Required"`
CalendarSelected []int `cname:"日历选择" json:"calendarSelected" ` // valid:"Required"
// 上岗时间
InWorkAt string `cname:"上岗时间" json:"inWorkAt" valid:"Required"`
// 下岗时间
... ... @@ -32,6 +33,8 @@ type CreateProductCalendarCommand struct {
BreakTime float64 `cname:"休息时间 (单位 h)" json:"breakTime" valid:"Required"`
// 工时 (单位 h)
WorkTime float64 `cname:"工时 (单位 h)" json:"workTime" valid:"Required"`
// 休息时间周期列表
BreakTimePeriods []*domain.ProductCalendarBreakTimePeriod `json:"breakTimePeriods"`
}
func (createProductCalendarCommand *CreateProductCalendarCommand) Valid(validation *validation.Validation) {
... ... @@ -44,6 +47,16 @@ func (createProductCalendarCommand *CreateProductCalendarCommand) Valid(validati
validation.Error(err.Error())
return
}
for _, v := range createProductCalendarCommand.BreakTimePeriods {
if err := utils.ValidWorkTime(v.BeginAt); err != nil {
validation.Error(err.Error() + " " + v.BeginAt)
return
}
if err := utils.ValidWorkTime(v.EndAt); err != nil {
validation.Error(err.Error() + " " + v.EndAt)
return
}
}
}
func (createProductCalendarCommand *CreateProductCalendarCommand) ValidateCommand() error {
... ...
... ... @@ -2,6 +2,8 @@ package command
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
"reflect"
"strings"
... ... @@ -19,8 +21,8 @@ type UpdateProductCalendarCommand struct {
SectionId int `cname:"工段ID" json:"sectionId" valid:"Required"`
// 上班班次 1:全天 2:白班 4:中班 8:夜班
WorkOn int `cname:"上班班次 1:全天 2:白班 4:中班 8:夜班" json:"workOn" valid:"Required"`
// 日历选择
CalendarSelected []int `cname:"日历选择" json:"calendarSelected" valid:"Required"`
// 日历选择 valid:"Required"
CalendarSelected []int `cname:"日历选择" json:"calendarSelected" `
// 上岗时间
InWorkAt string `cname:"上岗时间" json:"inWorkAt" valid:"Required"`
// 下岗时间
... ... @@ -29,10 +31,21 @@ type UpdateProductCalendarCommand struct {
BreakTime float64 `cname:"休息时间 (单位 h)" json:"breakTime" valid:"Required"`
// 工时 (单位 h)
WorkTime float64 `cname:"工时 (单位 h)" json:"workTime" valid:"Required"`
// 休息时间周期列表
BreakTimePeriods []*domain.ProductCalendarBreakTimePeriod `json:"breakTimePeriods"`
}
func (updateProductCalendarCommand *UpdateProductCalendarCommand) Valid(validation *validation.Validation) {
//validation.SetError("CustomValid", "未实现的自定义认证")
for _, v := range updateProductCalendarCommand.BreakTimePeriods {
if err := utils.ValidWorkTime(v.BeginAt); err != nil {
validation.Error(err.Error() + " " + v.BeginAt)
return
}
if err := utils.ValidWorkTime(v.EndAt); err != nil {
validation.Error(err.Error() + " " + v.EndAt)
return
}
}
}
func (updateProductCalendarCommand *UpdateProductCalendarCommand) ValidateCommand() error {
... ...
... ... @@ -32,6 +32,10 @@ type ProductCalendarDto struct {
OrgName string `json:"orgName"`
// 权限标识 (当前登录组织匹配为true,否则false)
AuthFlag bool `json:"authFlag"`
// 休息时间周期列表
BreakTimePeriods []*domain.ProductCalendarBreakTimePeriod `json:"breakTimePeriods"`
// 累计休息时间 (单位 h)
// TotalBreakTime float64 `json:"totalBreakTime"`
}
func (d *ProductCalendarDto) LoadDto(m *domain.ProductCalendar, orgId int) *ProductCalendarDto {
... ... @@ -48,5 +52,9 @@ func (d *ProductCalendarDto) LoadDto(m *domain.ProductCalendar, orgId int) *Prod
if m.Ext != nil {
d.OrgName = m.Ext.OrgName
}
d.BreakTimePeriods = m.BreakTimePeriods
//for _, v := range d.BreakTimePeriods {
// d.TotalBreakTime += v.BreakTime
//}
return d
}
... ...
package query
import (
"fmt"
"reflect"
"strings"
"github.com/beego/beego/v2/core/validation"
)
type GetProductGroupCalendarQuery struct {
// 生产班组ID
ProductGroupId int `cname:"工厂日历ID" json:"productGroupId" valid:"Required"`
}
func (getProductCalendarQuery *GetProductGroupCalendarQuery) Valid(validation *validation.Validation) {
//validation.SetError("CustomValid", "未实现的自定义认证")
}
func (getProductCalendarQuery *GetProductGroupCalendarQuery) ValidateQuery() error {
valid := validation.Validation{}
b, err := valid.Valid(getProductCalendarQuery)
if err != nil {
return err
}
if !b {
elem := reflect.TypeOf(getProductCalendarQuery).Elem()
for _, validErr := range valid.Errors {
field, isExist := elem.FieldByName(validErr.Field)
if isExist {
return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
} else {
return fmt.Errorf(validErr.Message)
}
}
}
return nil
}
... ...
... ... @@ -71,9 +71,10 @@ func (productCalendarService *ProductCalendarService) CreateProductCalendar(oper
OutWorkAt: cmd.OutWorkAt,
BreakTime: cmd.BreakTime,
//WorkTime: cmd.WorkTime,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
Ext: domain.NewExt(org.OrgName),
BreakTimePeriods: cmd.BreakTimePeriods,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
Ext: domain.NewExt(org.OrgName),
}
if err = newProductCalendar.ResetWorkTime(cmd.WorkTime); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
... ... @@ -306,6 +307,7 @@ func (productCalendarService *ProductCalendarService) UpdateProductCalendar(cmd
productCalendar.InWorkAt = cmd.InWorkAt
productCalendar.OutWorkAt = cmd.OutWorkAt
productCalendar.BreakTime = cmd.BreakTime
productCalendar.BreakTimePeriods = cmd.BreakTimePeriods
productCalendar.Ext = domain.NewExt(org.OrgName)
if err = productCalendar.ResetWorkTime(cmd.WorkTime); err != nil {
return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
... ... @@ -370,6 +372,43 @@ func (productCalendarService *ProductCalendarService) SearchProductCalendar(oper
return count, result, nil
}
// 返回生产班组的工厂日历
func (productCalendarService *ProductCalendarService) GetProductGroupCalendar(getProductCalendarQuery *query.GetProductGroupCalendarQuery) (interface{}, error) {
if err := getProductCalendarQuery.ValidateQuery(); err != nil {
return nil, application.ThrowError(application.ARG_ERROR, err.Error())
}
transactionContext, err := factory.CreateTransactionContext(nil)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
if err := transactionContext.StartTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
defer func() {
transactionContext.RollbackTransaction()
}()
productCalendarRepository, _, _ := factory.FastPgProductCalendar(transactionContext, 0)
_, productGroup, err := factory.FastPgProductGroup(transactionContext, getProductCalendarQuery.ProductGroupId)
if err != nil {
return nil, nil
}
_, productCalendar, err := productCalendarRepository.Find(map[string]interface{}{"workStationId": productGroup.WorkStation.WorkStationId, "workOn": productGroup.WorkOn, "limit": 1})
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
if len(productCalendar) == 0 {
return nil, nil
}
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
result := &dto.ProductCalendarDto{}
result.LoadDto(productCalendar[0], 0)
return result, nil
}
func NewProductCalendarService(options map[string]interface{}) *ProductCalendarService {
newProductCalendarService := &ProductCalendarService{}
return newProductCalendarService
... ...
package dto
import (
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
)
// 生产班组
type ProductGroupSelectorDto struct {
// 生产小组ID
ProductGroupId int `json:"productGroupId,omitempty"`
// 班组名称
GroupName string `json:"groupName,omitempty"`
// 班组长
GroupLeader *domain.User `json:"groupLeader"`
// 帮组成员列表
GroupMembers []*domain.User `json:"groupMembers"`
}
func (d *ProductGroupSelectorDto) LoadDto(m *domain.ProductGroup, orgId int) *ProductGroupSelectorDto {
d.ProductGroupId = m.ProductGroupId
d.GroupName = m.GroupName
d.GroupLeader = m.GroupLeader
d.GroupMembers = m.GroupMembers
return d
}
... ...
... ... @@ -30,6 +30,12 @@ type SearchProductGroupQuery struct {
WorkshopName string `cname:"车间名称" json:"workshopName,omitempty"`
// 生产线名称
LineName string `cname:"生产线名称" json:"lineName,omitempty"`
// 车间ID
WorkshopId int `cname:"车间ID" json: workshopId,omitempty"`
// 生产线ID
LineId int `cname:"生产线ID" json:"lineId,omitempty"`
// 工段ID
SectionId int `json:"sectionId,omitempty"`
}
func (cmd *SearchProductGroupQuery) Valid(validation *validation.Validation) {
... ...
... ... @@ -543,6 +543,44 @@ func (productGroupService *ProductGroupService) GetSignEmployee(cmd *query.GetSi
}, nil
}
// 返回生产班组服务列表
func (productGroupService *ProductGroupService) SelectorProductGroup(operateInfo *domain.OperateInfo, cmd *query.SearchProductGroupQuery) (interface{}, error) {
if err := cmd.ValidateQuery(); err != nil {
return nil, application.ThrowError(application.ARG_ERROR, err.Error())
}
transactionContext, err := factory.CreateTransactionContext(nil)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
if err := transactionContext.StartTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
defer func() {
transactionContext.RollbackTransaction()
}()
workshops, _ := factory.FastPgWorkshops(transactionContext, operateInfo.CompanyId)
queryOptions := utils.ObjectToMap(cmd)
queryOptions = workshops.FindByNameWithQuery(queryOptions, cmd.WorkshopName, cmd.LineName, "")
var productGroupRepository domain.ProductGroupRepository
productGroupRepository, _, _ = factory.FastPgProductGroup(transactionContext, 0)
_, productGroups, err := productGroupRepository.Find(queryOptions)
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
var results = make([]*dto.ProductGroupSelectorDto, 0)
for i := range productGroups {
newItem := &dto.ProductGroupSelectorDto{}
newItem.LoadDto(productGroups[i], operateInfo.OrgId)
results = append(results, newItem)
}
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return results, nil
}
func NewProductGroupService(options map[string]interface{}) *ProductGroupService {
newProductGroupService := &ProductGroupService{}
return newProductGroupService
... ...
... ... @@ -2,10 +2,11 @@ package constant
import (
"fmt"
"os"
"strconv"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
)
var Configurator utils.Configurator = utils.EnvConfigurator{} //utils.NewConfig("ini","config/app_test.conf")
var SERVICE_NAME = "allied-creation-manufacture"
var SERVICE_ENV = "dev"
var HTTP_PORT int = 8081
... ... @@ -35,46 +36,13 @@ const HeaderOrgId = "orgId"
const HeaderOrgIds = "orgIds"
func init() {
if os.Getenv("LOG_LEVEL") != "" {
LOG_LEVEL = os.Getenv("LOG_LEVEL")
}
//if os.Getenv("CUSTOMER_ACCOUNT") != "" {
// account := os.Getenv("CUSTOMER_ACCOUNT")
// accounts := strings.Split(account, CUSTOMER_ACCOUNT_DELIMITER)
// var tmpAccounts []int64
// for i := range accounts {
// v, err := strconv.ParseInt(accounts[i], 10, 64)
// if err != nil {
// panic(err)
// }
// tmpAccounts = append(tmpAccounts, v)
// }
// if len(tmpAccounts) > 0 {
// CUSTOMER_ACCOUNT = tmpAccounts
// }
//}
if os.Getenv("ALLIED_CREATION_BASIC_HOST") != "" {
ALLIED_CREATION_BASIC_HOST = os.Getenv("ALLIED_CREATION_BASIC_HOST")
}
if os.Getenv("ALLIED_CREATION_USER_HOST") != "" {
ALLIED_CREATION_USER_HOST = os.Getenv("ALLIED_CREATION_USER_HOST")
}
if os.Getenv("ALLIED_CREATION_COOPERATION_HOST") != "" {
ALLIED_CREATION_COOPERATION_HOST = os.Getenv("ALLIED_CREATION_COOPERATION_HOST")
}
//if os.Getenv("SMS_SERVE_HOST") != "" {
// SMS_SERVE_HOST = os.Getenv("SMS_SERVE_HOST")
//}
if os.Getenv("MMM_BYTE_BANK_HOST") != "" {
MMM_BYTE_BANK_HOST = os.Getenv("MMM_BYTE_BANK_HOST")
}
if os.Getenv("SERVICE_ENV") != "" {
SERVICE_ENV = os.Getenv("SERVICE_ENV")
}
if os.Getenv("HTTP_PORT") != "" {
HTTP_PORT, _ = strconv.Atoi(os.Getenv("HTTP_PORT"))
}
LOG_LEVEL = Configurator.DefaultString("LOG_LEVEL", LOG_LEVEL)
ALLIED_CREATION_BASIC_HOST = Configurator.DefaultString("ALLIED_CREATION_BASIC_HOST", ALLIED_CREATION_BASIC_HOST)
ALLIED_CREATION_USER_HOST = Configurator.DefaultString("ALLIED_CREATION_USER_HOST", ALLIED_CREATION_USER_HOST)
ALLIED_CREATION_COOPERATION_HOST = Configurator.DefaultString("ALLIED_CREATION_COOPERATION_HOST", ALLIED_CREATION_COOPERATION_HOST)
MMM_BYTE_BANK_HOST = Configurator.DefaultString("MMM_BYTE_BANK_HOST", MMM_BYTE_BANK_HOST)
SERVICE_ENV = Configurator.DefaultString("SERVICE_ENV", SERVICE_ENV)
HTTP_PORT = Configurator.DefaultInt("HTTP_PORT", HTTP_PORT)
SERVICE_NAME = fmt.Sprintf("%v-%v", SERVICE_NAME, SERVICE_ENV)
CACHE_PREFIX = SERVICE_NAME
}
... ...
package constant
import "os"
var (
// kafka 地址
KAFKA_HOST = "192.168.0.250:9092,192.168.0.251:9092,192.168.0.252:9092" //"106.75.231.90:9092"
... ... @@ -14,13 +12,6 @@ var (
)
func init() {
if os.Getenv("KAFKA_HOST") != "" {
KAFKA_HOST = os.Getenv("KAFKA_HOST")
}
//if os.Getenv("TOPIC_LOG_STASH") != "" {
// POSTGRESQL_PORT = os.Getenv("TOPIC_LOG_STASH")
//}
if os.Getenv("ENABLE_KAFKA_LOG") != "" {
ENABLE_KAFKA_LOG = true
}
KAFKA_HOST = Configurator.DefaultString("KAFKA_HOST", KAFKA_HOST)
ENABLE_KAFKA_LOG = Configurator.DefaultBool("ENABLE_KAFKA_LOG", ENABLE_KAFKA_LOG)
}
... ...
package constant
import (
"os"
"strconv"
"strings"
)
... ... @@ -20,18 +18,10 @@ var (
)
func init() {
if os.Getenv("MANUFACTURE_DEFAULT_COMPANYID") != "" {
MANUFACTURE_DEFAULT_COMPANYID, _ = strconv.Atoi(os.Getenv("MANUFACTURE_DEFAULT_COMPANYID"))
}
if os.Getenv("MANUFACTURE_DEFAULT_ORGID") != "" {
MANUFACTURE_DEFAULT_ORGID, _ = strconv.Atoi(os.Getenv("MANUFACTURE_DEFAULT_ORGID"))
}
if os.Getenv("MANUFACTURE_DEFAULT_WORKSHOPID") != "" {
MANUFACTURE_DEFAULT_WORKSHOPID, _ = strconv.Atoi(os.Getenv("MANUFACTURE_DEFAULT_WORKSHOPID"))
}
if os.Getenv("MANUFACTURE_PRODUCT_TYPE") != "" {
MANUFACTURE_PRODUCT_TYPE = os.Getenv("MANUFACTURE_PRODUCT_TYPE")
}
MANUFACTURE_DEFAULT_COMPANYID = Configurator.DefaultInt("MANUFACTURE_DEFAULT_COMPANYID", MANUFACTURE_DEFAULT_COMPANYID)
MANUFACTURE_DEFAULT_ORGID = Configurator.DefaultInt("MANUFACTURE_DEFAULT_ORGID", MANUFACTURE_DEFAULT_ORGID)
MANUFACTURE_DEFAULT_WORKSHOPID = Configurator.DefaultInt("MANUFACTURE_DEFAULT_WORKSHOPID", MANUFACTURE_DEFAULT_WORKSHOPID)
MANUFACTURE_PRODUCT_TYPE = Configurator.DefaultString("MANUFACTURE_PRODUCT_TYPE", MANUFACTURE_PRODUCT_TYPE)
productTypes := strings.Split(MANUFACTURE_PRODUCT_TYPE, ",")
for i, v := range productTypes {
MapProductType[i+1] = v
... ...
package constant
import "os"
var MQTT_TOPIC = "/MQTT"
//设备商提供的测试地址
... ... @@ -32,16 +30,8 @@ var MQTT_USER = "admin"
var MQTT_PASSWORD = "123456"
func init() {
if os.Getenv("MQTT_HOST") != "" {
MQTT_HOST = os.Getenv("MQTT_HOST")
}
if os.Getenv("MQTT_PORT") != "" {
MQTT_PORT = os.Getenv("MQTT_PORT")
}
if os.Getenv("MQTT_USER") != "" {
MQTT_USER = os.Getenv("MQTT_USER")
}
if os.Getenv("MQTT_PASSWORD") != "" {
MQTT_PASSWORD = os.Getenv("MQTT_PASSWORD")
}
MQTT_HOST = Configurator.DefaultString("MQTT_HOST", MQTT_HOST)
MQTT_PORT = Configurator.DefaultString("MQTT_PORT", MQTT_PORT)
MQTT_USER = Configurator.DefaultString("MQTT_USER", MQTT_USER)
MQTT_PASSWORD = Configurator.DefaultString("MQTT_PASSWORD", MQTT_PASSWORD)
}
... ...
... ... @@ -3,10 +3,6 @@
package constant
import (
"os"
)
var POSTGRESQL_DB_NAME = "terms"
var POSTGRESQL_USER = "postgres"
var POSTGRESQL_PASSWORD = "123456"
... ... @@ -17,25 +13,12 @@ var DISABLE_SQL_GENERATE_PRINT = false
var DISABLE_SQL_GENERATE_COMMENT = true
func init() {
if os.Getenv("POSTGRESQL_DB_NAME") != "" {
POSTGRESQL_DB_NAME = os.Getenv("POSTGRESQL_DB_NAME")
}
if os.Getenv("POSTGRESQL_USER") != "" {
POSTGRESQL_USER = os.Getenv("POSTGRESQL_USER")
}
if os.Getenv("POSTGRESQL_PASSWORD") != "" {
POSTGRESQL_PASSWORD = os.Getenv("POSTGRESQL_PASSWORD")
}
if os.Getenv("POSTGRESQL_HOST") != "" {
POSTGRESQL_HOST = os.Getenv("POSTGRESQL_HOST")
}
if os.Getenv("POSTGRESQL_PORT") != "" {
POSTGRESQL_PORT = os.Getenv("POSTGRESQL_PORT")
}
if os.Getenv("DISABLE_CREATE_TABLE") != "" {
DISABLE_CREATE_TABLE = true
}
if os.Getenv("DISABLE_SQL_GENERATE_PRINT") != "" {
DISABLE_SQL_GENERATE_PRINT = true
}
POSTGRESQL_HOST = Configurator.DefaultString("POSTGRESQL_HOST", POSTGRESQL_HOST)
POSTGRESQL_PORT = Configurator.DefaultString("POSTGRESQL_PORT", POSTGRESQL_PORT)
POSTGRESQL_DB_NAME = Configurator.DefaultString("POSTGRESQL_DB_NAME", POSTGRESQL_DB_NAME)
POSTGRESQL_USER = Configurator.DefaultString("POSTGRESQL_USER", POSTGRESQL_USER)
POSTGRESQL_PASSWORD = Configurator.DefaultString("POSTGRESQL_PASSWORD", POSTGRESQL_PASSWORD)
DISABLE_CREATE_TABLE = Configurator.DefaultBool("DISABLE_CREATE_TABLE", DISABLE_CREATE_TABLE)
DISABLE_SQL_GENERATE_PRINT = Configurator.DefaultBool("DISABLE_SQL_GENERATE_PRINT", DISABLE_SQL_GENERATE_PRINT)
}
... ...
package constant
import "os"
var (
REDIS_HOST = "127.0.0.1"
REDIS_PORT = "6379"
REDIS_AUTH = ""
REDIS_HOST = "127.0.0.1"
REDIS_PORT = "6379"
REDIS_AUTH = ""
REDIS_ADDRESS = ""
// 是否关闭仓储层缓存
DISABLE_REPOSITORY_CACHE = false
ENABLE_REPOSITORY_CACHE = true
// 缓存过期时间 单位秒
REPOSITORY_CACHE_EXPIRE = 30 * 60
REDIS_ADDRESS = ""
// redis 考勤机打卡消息队列
REDIS_ZKTECO_KEY = "allied-creation-zkteco"
// redis 车间数据消息队列
... ... @@ -19,21 +17,9 @@ var (
)
func init() {
if os.Getenv("REDIS_HOST") != "" {
REDIS_HOST = os.Getenv("REDIS_HOST")
REDIS_AUTH = os.Getenv("REDIS_AUTH")
}
if os.Getenv("REDIS_PORT") != "" {
REDIS_PORT = os.Getenv("REDIS_PORT")
}
if _, ok := os.LookupEnv("REDIS_AUTH"); ok {
REDIS_AUTH = os.Getenv("REDIS_AUTH")
}
if os.Getenv("ENABLE_REPOSITORY_CACHE") != "" {
DISABLE_REPOSITORY_CACHE = false
}
if os.Getenv("DISABLE_REPOSITORY_CACHE") != "" {
DISABLE_REPOSITORY_CACHE = true
}
REDIS_HOST = Configurator.DefaultString("REDIS_HOST", REDIS_HOST)
REDIS_PORT = Configurator.DefaultString("REDIS_PORT", REDIS_PORT)
REDIS_AUTH = Configurator.DefaultString("REDIS_AUTH", REDIS_AUTH)
ENABLE_REPOSITORY_CACHE = Configurator.DefaultBool("ENABLE_REPOSITORY_CACHE", ENABLE_REPOSITORY_CACHE)
REDIS_ADDRESS = REDIS_HOST + ":" + REDIS_PORT
}
... ...
... ... @@ -2,7 +2,10 @@ package domain
import (
"errors"
"fmt"
"github.com/linmadan/egglib-go/utils/xtime"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log"
"time"
)
... ... @@ -44,6 +47,8 @@ type ProductAttendanceRecord struct {
DeletedAt time.Time `json:"deletedAt,omitempty"`
// 扩展数据
Ext *Ext `json:"ext,omitempty"`
// 生产日期
ProductDate time.Time `json:"productDate,omitempty"`
}
type ProductAttendanceRecordRepository interface {
... ... @@ -65,7 +70,7 @@ func (productAttendanceRecord *ProductAttendanceRecord) Update(data map[string]i
}
// 计算审核前工时
func (productAttendanceRecord *ProductAttendanceRecord) ComputeWorkTimeBefore() float64 {
func (productAttendanceRecord *ProductAttendanceRecord) ComputeWorkTimeBefore(productCalendar *ProductCalendar) float64 {
if productAttendanceRecord.SignIn.IsZero() {
return 0
}
... ... @@ -75,7 +80,32 @@ func (productAttendanceRecord *ProductAttendanceRecord) ComputeWorkTimeBefore()
if !productAttendanceRecord.SignOut.After(productAttendanceRecord.SignIn) {
return 0
}
return utils.Round(productAttendanceRecord.SignOut.Sub(productAttendanceRecord.SignIn).Hours(), 1)
wt := utils.Round(productAttendanceRecord.SignOut.Sub(productAttendanceRecord.SignIn).Hours(), 1)
if productCalendar == nil {
return wt
}
wt = wt - productAttendanceRecord.AttendanceBreakTime(productCalendar)
if wt < 0 {
return 0
}
return wt
}
func (productAttendanceRecord *ProductAttendanceRecord) SetProductTimeByProductCalendar(productCalendar *ProductCalendar) error {
now := xtime.New(productAttendanceRecord.SignIn)
productAttendanceRecord.ProductDate = now.BeginningOfDay()
if productCalendar == nil {
return nil
}
overDay, err := productCalendar.CheckOverDay(productAttendanceRecord.SignIn)
if err != nil {
return nil
}
newNow := now.BeginningOfDay().Add(-time.Hour * 24)
if overDay { //&& productCalendar.MatchCalendarSelected(newNow)
productAttendanceRecord.ProductDate = newNow
}
return nil
}
func (productAttendanceRecord *ProductAttendanceRecord) Approve(approveUser *User, workTimeAfter float64, status int) error {
... ... @@ -94,3 +124,76 @@ func (productAttendanceRecord *ProductAttendanceRecord) Approve(approveUser *Use
}
return nil
}
func (productAttendanceRecord *ProductAttendanceRecord) ProductTime() time.Time {
attendanceExt := productAttendanceRecord.Ext.AttendanceExt
if attendanceExt != nil && !xtime.IsZero(productAttendanceRecord.ProductDate) {
return productAttendanceRecord.ProductDate
}
return productAttendanceRecord.SignIn
}
func (productAttendanceRecord *ProductAttendanceRecord) GroupName() string {
if productAttendanceRecord.Ext == nil {
return ""
}
if productAttendanceRecord.Ext.AttendanceExt == nil {
return ""
}
return productAttendanceRecord.Ext.AttendanceExt.GroupName
}
func (productAttendanceRecord *ProductAttendanceRecord) ApproveUser() *User {
if productAttendanceRecord.Ext == nil {
return nil
}
if productAttendanceRecord.Ext.AttendanceExt == nil {
return nil
}
if productAttendanceRecord.Ext.AttendanceExt.ApproveUserId == 0 {
return nil
}
return &User{
UserId: productAttendanceRecord.Ext.AttendanceExt.ApproveUserId,
UserName: productAttendanceRecord.Ext.AttendanceExt.ApproveUserName,
}
}
// 计算考勤休息时间
//
// 考勤打卡时间内有休息时间进行累计
func (productAttendanceRecord *ProductAttendanceRecord) AttendanceBreakTime(productCalendar *ProductCalendar) float64 {
var (
signIn = productAttendanceRecord.SignIn
signOut = productAttendanceRecord.SignOut
)
if signIn.IsZero() {
return 0
}
if signOut.IsZero() {
return 0
}
if productCalendar == nil {
return 0
}
var bt float64
for _, v := range productCalendar.BreakTimePeriods {
var (
checkSignIn, checkSignOut time.Time
)
checkSignIn = v.GetCheckBeginTime(signIn.Local())
checkSignOut = v.GetCheckEndTime(signIn.Local())
if xtime.BeforeEqual(signIn.Local(), checkSignIn) && xtime.AfterEqual(signOut.Local(), checkSignIn) {
if xtime.AfterEqual(signOut.Local(), checkSignOut) {
bt += v.BreakTime
} else {
bt += utils.Round(signOut.Local().Sub(checkSignIn).Hours(), 2)
}
}
log.Logger.Debug(fmt.Sprintf("range(%v,%v) actual(%v,%v) break_time:%v", checkSignIn, checkSignOut, signIn.Local(), signOut.Local(), bt))
}
if productAttendanceRecord.Ext != nil && productAttendanceRecord.Ext.AttendanceExt != nil {
productAttendanceRecord.Ext.AttendanceExt.BreakTime = bt
}
return bt
}
... ...
... ... @@ -6,10 +6,14 @@ type ProductAttendanceRecordExt struct {
ProductGroupId int `json:"productGroupId,omitempty"`
// 班组名称
GroupName string `json:"groupName,omitempty"`
// 生产日期
//ProductTime int64 `json:"productTime,omitempty"`
// 审核人Id
ApproveUserId int `json:"approveUserId,omitempty"`
// 审核人名称
ApproveUserName string `json:"approveUserName,omitempty"`
// 审核时间
ApproveAt int64 `json:"approveAt,omitempty"`
// 休息时间
BreakTime float64 `json:"breakTime"`
}
... ...
package domain
import (
"fmt"
"github.com/linmadan/egglib-go/utils/xtime"
"github.com/stretchr/testify/assert"
"testing"
)
func TestComputeWorkTimeBefore(t *testing.T) {
var input = []struct {
name string
begin string
end string
overDay bool
breakTime float64
records []*ProductAttendanceRecord
}{
{
"normal",
"11:00",
"12:00",
false,
1,
[]*ProductAttendanceRecord{
{
SignIn: xtime.MustParse("2022-05-05 09:00:00"),
SignOut: xtime.MustParse("2022-05-05 13:00:00"),
WorkTimeBefore: 3,
},
{
SignIn: xtime.MustParse("2022-05-05 12:00:00"),
SignOut: xtime.MustParse("2022-05-05 17:00:00"),
WorkTimeBefore: 5,
},
{
SignIn: xtime.MustParse("2022-05-05 17:00:00"),
SignOut: xtime.MustParse("2022-05-06 07:00:00"),
WorkTimeBefore: 14,
},
},
},
{
"over day",
"23:45",
"00:45",
true,
1,
[]*ProductAttendanceRecord{
{
SignIn: xtime.MustParse("2022-05-05 09:00:00"),
SignOut: xtime.MustParse("2022-05-05 12:00:00"),
WorkTimeBefore: 3,
},
{
SignIn: xtime.MustParse("2022-05-05 12:00:00"),
SignOut: xtime.MustParse("2022-05-05 17:00:00"),
WorkTimeBefore: 5,
},
{
SignIn: xtime.MustParse("2022-05-05 17:00:00"),
SignOut: xtime.MustParse("2022-05-06 07:00:00"),
WorkTimeBefore: 13,
},
},
},
}
for _, v := range input {
p := NewProductCalendarBreakTimePeriod(v.begin, v.end, v.breakTime)
for _, r := range v.records {
t.Run(v.name, func(t *testing.T) {
wt := r.ComputeWorkTimeBefore(&ProductCalendar{
BreakTimePeriods: []*ProductCalendarBreakTimePeriod{p},
})
assert.Equal(t, r.WorkTimeBefore, wt, fmt.Sprintf("except work time %v got :%v", r.WorkTimeBefore, wt))
})
}
}
}
... ...
... ... @@ -2,6 +2,8 @@ package domain
import (
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
"strconv"
"strings"
"time"
)
... ... @@ -35,6 +37,8 @@ type ProductCalendar struct {
DeletedAt time.Time `json:"deletedAt,omitempty"`
// 扩展数据
Ext *Ext `json:"ext,omitempty"`
// 休息时间周期列表
BreakTimePeriods []*ProductCalendarBreakTimePeriod `json:"breakTimePeriods"`
}
type ProductCalendarRepository interface {
... ... @@ -73,3 +77,66 @@ func (productCalendar *ProductCalendar) ResetWorkTime(v float64) error {
productCalendar.WorkTime = td.Hours() - productCalendar.BreakTime
return nil
}
func (productCalendar *ProductCalendar) MatchCalendarSelected(t time.Time) bool {
weekdays := productCalendar.CalendarSelectedToWeekDays()
for _, v := range weekdays {
if v == t.Weekday() {
return true
}
}
return false
}
func (productCalendar *ProductCalendar) CalendarSelectedToWeekDays() []time.Weekday {
weekdays := make([]time.Weekday, 0)
for _, v := range productCalendar.CalendarSelected {
switch v {
case "7": //周日
weekdays = append(weekdays, time.Sunday)
break
case "1": //"周一":
weekdays = append(weekdays, time.Monday)
break
case "2": //"周二":
weekdays = append(weekdays, time.Tuesday)
break
case "3": //"周三":
weekdays = append(weekdays, time.Wednesday)
break
case "4": //"周四":
weekdays = append(weekdays, time.Thursday)
break
case "5": //"周五":
weekdays = append(weekdays, time.Friday)
break
case "6": //"周六":
weekdays = append(weekdays, time.Saturday)
break
}
}
return weekdays
}
// 检查时间是否跨天
func (productCalendar *ProductCalendar) CheckOverDay(t time.Time) (bool, error) {
th := t.Hour()
inHour, parseInHourErr := strconv.Atoi(strings.Split(productCalendar.InWorkAt, ":")[0])
if parseInHourErr != nil {
return false, parseInHourErr
}
outHour, parseOutHourErr := strconv.Atoi(strings.Split(productCalendar.OutWorkAt, ":")[0])
if parseOutHourErr != nil {
return false, parseOutHourErr
}
if inHour < outHour {
return false, nil // eg: 7:00 17:00 t 9:00
}
if th >= inHour && th < 24 {
return false, nil // eg: 7:00 24:00 t 20:00
}
if th >= 0 && th < outHour {
return true, nil
}
return false, nil
}
... ...
package domain
import (
"strconv"
"strings"
"time"
)
type ProductCalendarBreakTimePeriod struct {
// 开始时间 eg: 11:00
BeginAt string `json:"beginAt,omitempty"`
// 结束时间 eg: 11:30
EndAt string `json:"endAt,omitempty"`
// 休息时间 (单位 h) eg:0.5
BreakTime float64 `json:"breakTime,omitempty"`
// 备注 eg:午饭
Remark string `json:"remark,omitempty"`
}
func (period *ProductCalendarBreakTimePeriod) CheckOverDay() (bool, error) {
inHour, parseInHourErr := strconv.Atoi(strings.Split(period.BeginAt, ":")[0])
if parseInHourErr != nil {
return false, parseInHourErr
}
outHour, parseOutHourErr := strconv.Atoi(strings.Split(period.EndAt, ":")[0])
if parseOutHourErr != nil {
return false, parseOutHourErr
}
if inHour <= outHour {
return false, nil // eg: 7:00 17:00 t 9:00
}
return true, nil
}
func (period *ProductCalendarBreakTimePeriod) GetCheckBeginTime(t time.Time) time.Time {
y, m, d := t.Date()
inHour, _ := strconv.ParseInt(strings.Split(period.BeginAt, ":")[0], 10, 64)
inMinuter, _ := strconv.ParseInt(strings.Split(period.BeginAt, ":")[1], 10, 64)
return time.Date(y, m, d, int(inHour), int(inMinuter), 0, 0, time.Local)
}
func (period *ProductCalendarBreakTimePeriod) GetCheckEndTime(t time.Time) time.Time {
y, m, d := t.Date()
inHour, _ := strconv.ParseInt(strings.Split(period.EndAt, ":")[0], 10, 64)
inMinuter, _ := strconv.ParseInt(strings.Split(period.EndAt, ":")[1], 10, 64)
checkTime := time.Date(y, m, d, int(inHour), int(inMinuter), 0, 0, time.Local)
if overDay, err := period.CheckOverDay(); overDay && err == nil {
return checkTime.AddDate(0, 0, 1)
}
return checkTime
}
func NewProductCalendarBreakTimePeriod(begin, end string, breakTime float64) *ProductCalendarBreakTimePeriod {
return &ProductCalendarBreakTimePeriod{
BeginAt: begin,
EndAt: end,
BreakTime: breakTime,
}
}
... ...
package domain
import (
"fmt"
"github.com/stretchr/testify/assert"
"testing"
"time"
)
func TestCheckOverDay(t *testing.T) {
var input = []struct {
name string
begin string
end string
overDay bool
}{
{
"normal",
"11:00",
"12:00",
false,
},
{
"over day",
"23:45",
"00:45",
true,
},
}
for _, v := range input {
p := NewProductCalendarBreakTimePeriod(v.begin, v.end, 0)
t.Run(v.name, func(t *testing.T) {
ok, err := p.CheckOverDay()
assert.Equal(t, v.overDay, ok)
assert.Nil(t, err)
})
}
}
func TestGetCheckTime(t *testing.T) {
var input = []struct {
name string
begin string
end string
overDay bool
in time.Time
}{
{
"normal",
"11:00",
"12:00",
false,
time.Date(2022, 5, 5, 9, 0, 0, 0, time.Local),
},
{
"over day",
"23:45",
"00:45",
true,
time.Date(2022, 5, 5, 23, 0, 0, 0, time.Local),
},
}
for _, v := range input {
p := NewProductCalendarBreakTimePeriod(v.begin, v.end, 0)
t.Run(v.name, func(t *testing.T) {
begin := p.GetCheckBeginTime(time.Now())
end := p.GetCheckEndTime(time.Now())
overDay := begin.Day() != end.Day()
assert.Equal(t, v.overDay, overDay, fmt.Sprintf("begin:%v end:%v", begin, end))
})
}
}
... ...
... ... @@ -123,3 +123,35 @@ func (dao *AttendanceRecordDao) WorkerAttendanceRecords(companyId, orgId, worker
return int64(count), productAttendanceRecords, nil
}
}
func (dao *AttendanceRecordDao) WorkerAttendanceRecordsByProductDate(companyId, orgId, workerId int, productDate, beginTime, endTime time.Time) (int64, []*domain.ProductAttendanceRecord, error) {
tx := dao.transactionContext.PgTx
//endTime := time.Now()
//beginTime := endTime.Add(-(time.Hour * time.Duration(recentDay*24)))
var productAttendanceRecordModels []*models.ProductAttendanceRecord
productAttendanceRecords := make([]*domain.ProductAttendanceRecord, 0)
query := sqlbuilder.BuildQuery(tx.Model(&productAttendanceRecordModels), map[string]interface{}{})
query.Where("company_id =?", companyId)
query.Where("org_id =?", orgId)
query.Where("product_worker ->>'userId' = '?'", workerId)
query.Where("product_date = ?", productDate)
query.Where("sign_in >= ?", beginTime)
query.WhereGroup(func(query *orm.Query) (*orm.Query, error) {
query.Where("sign_out is null")
query.WhereOr("sign_out>?", endTime)
return query, nil
})
query.SetOrderDirect("product_attendance_id", "DESC")
if count, err := query.SelectAndCount(); err != nil {
return 0, productAttendanceRecords, err
} else {
for _, productAttendanceRecordModel := range productAttendanceRecordModels {
if productAttendanceRecord, err := transform.TransformToProductAttendanceRecordDomainModelFromPgModels(productAttendanceRecordModel); err != nil {
return 0, productAttendanceRecords, err
} else {
productAttendanceRecords = append(productAttendanceRecords, productAttendanceRecord)
}
}
return int64(count), productAttendanceRecords, nil
}
}
... ...
... ... @@ -21,7 +21,7 @@ func NewDeviceDailyRunningRecordDao(transactionContext *pgTransaction.Transactio
}
// 时段产能
func (dao *DeviceDailyRunningRecordDao) TimeSectionRunningRecord(companyId, orgId, workshopId int, lineId int, sectionName string, beginTime time.Time, result interface{}) error {
func (dao *DeviceDailyRunningRecordDao) TimeSectionRunningRecord(companyId, orgId, workshopId int, lineId int, sectionName string, beginTime time.Time, endTime time.Time, result interface{}) error {
tx := dao.transactionContext.PgTx
sql := fmt.Sprintf(`
... ... @@ -39,6 +39,7 @@ WITH ts_product as(
and work_station->>'lineId'='?'
and work_station->>'sectionName'=?
and created_at >?
and created_at <?
) a
group by a.ts
order by ts
... ... @@ -47,20 +48,20 @@ WITH ts_product as(
, ts_product_list as (
select d.ts,ts_product.total from (
select to_char(c.ts::timestamp,'mm-dd') ts from (
select generate_series(now() - interval '6 day',now(),'1 day') ts
select generate_series(to_timestamp(?),to_timestamp(?),'1 day') ts
) c ) d left join ts_product on d.ts = ts_product.ts
)
SELECT ts, coalesce(total,0) total
from ts_product_list
`)
if _, err := tx.Query(result, sql, companyId, orgId, workshopId, lineId, sectionName, beginTime); err != nil {
if _, err := tx.Query(result, sql, companyId, orgId, workshopId, lineId, sectionName, beginTime, endTime, beginTime.Unix(), endTime.Unix()); err != nil {
return err
}
return nil
}
// 车间性能
func (dao *DeviceDailyRunningRecordDao) WorkshopProductionEfficiencyStatistics(companyId, orgId, workshopId int, beginTime time.Time, result interface{}) error {
func (dao *DeviceDailyRunningRecordDao) WorkshopProductionEfficiencyStatistics(companyId, orgId, workshopId int, beginTime time.Time, endTime time.Time, result interface{}) error {
tx := dao.transactionContext.PgTx
sql := fmt.Sprintf(`
... ... @@ -76,10 +77,11 @@ company_id = ?
and org_id = ?
and work_station->>'workshopId'='?'
and created_at>=?
and created_at<?
)
select round(avg(oee),1) oee,round(avg(tu),1) tu,round(avg(pu),1)pu, round(avg(qu),1) qu from device_running
`)
if _, err := tx.Query(result, sql, companyId, orgId, workshopId, beginTime); err != nil {
if _, err := tx.Query(result, sql, companyId, orgId, workshopId, beginTime, endTime); err != nil {
return err
}
return nil
... ...
... ... @@ -100,7 +100,7 @@ from ts_product_list
}
// 二级品比重
func (dao *ProductRecordDao) ProportionOfSecondLevelRecord(companyId, orgId, workshopId int, beginTime time.Time, result interface{}) error {
func (dao *ProductRecordDao) ProportionOfSecondLevelRecord(companyId, orgId, workshopId int, beginTime time.Time, endTime time.Time, result interface{}) error {
tx := dao.transactionContext.PgTx
sql := fmt.Sprintf(`
... ... @@ -116,6 +116,7 @@ select sum(a.weight) item_total,max(sname) sname from (
and product_record_type = 8
and product_record_info->>'approveStatus'='2'
and created_at >=?
and created_at <?
and work_station->>'sectionName' in ('打料','成型','穿串','包装')
) a
group by a.workStationId
... ... @@ -128,7 +129,7 @@ select sname,round(item_total/(select sum(item_total) from item_product)*100, 0)
select a.sname, coalesce(b.rate,0) rate from (
select unnest(ARRAY ['打料','成型','穿串','包装']) sname
) a left join item_product_rate b on a.sname=b.sname`)
if _, err := tx.Query(result, sql, companyId, orgId, workshopId, beginTime); err != nil {
if _, err := tx.Query(result, sql, companyId, orgId, workshopId, beginTime, endTime); err != nil {
return err
}
return nil
... ...
... ... @@ -3,6 +3,7 @@ package domainService
import (
"fmt"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"github.com/linmadan/egglib-go/utils/xtime"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/constant"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/dao"
... ... @@ -122,9 +123,10 @@ func (ptr *PGCommonStatisticsService) HourProductiveStatistics(queryOptions map[
}
type HourProductiveStatisticsRequest struct {
CompanyId int `json:"companyId" valid:"Required"`
OrgId int `json:"orgId" valid:"Required"`
WorkshopId int `json:"workshopId" valid:"Required"`
CompanyId int `json:"companyId" valid:"Required"`
OrgId int `json:"orgId" valid:"Required"`
WorkshopId int `json:"workshopId" valid:"Required"`
Date time.Time `json:"date"`
}
func NewXYData(xData []string, values interface{}) interface{} {
... ... @@ -151,7 +153,10 @@ func (ptr *PGCommonStatisticsService) DailyProductiveStatistics(queryOptions map
Ts string `json:"ts"`
Total float64 `json:"total"`
}
var date = time.Now()
if !xtime.IsZero(request.Date) {
date = request.Date
}
workshop, err := workshopRepository.FindOne(map[string]interface{}{"workshopId": request.WorkshopId})
if err != nil || workshop == nil {
return nil, nil
... ... @@ -163,7 +168,7 @@ func (ptr *PGCommonStatisticsService) DailyProductiveStatistics(queryOptions map
for _, v := range workshop.GetProductLines(domain.NotDeleted) {
var result = make([]*record, 0)
if err := productRecordDao.TimeSectionRunningRecord(request.CompanyId, request.OrgId, request.WorkshopId, v.LineId, SectionNameCCJ, time.Now().Add(-time.Hour*24*7), &result); err != nil {
if err := productRecordDao.TimeSectionRunningRecord(request.CompanyId, request.OrgId, request.WorkshopId, v.LineId, SectionNameCCJ, date.Add(-time.Hour*24*7), date, &result); err != nil {
log.Logger.Error(err.Error())
continue
}
... ... @@ -207,20 +212,24 @@ func (ptr *PGCommonStatisticsService) ProportionOfSecondLevelStatistics(queryOpt
return nil, nil
}
productRecordDao, _ := dao.NewProductRecordDao(ptr.transactionContext)
var date = time.Now()
if !xtime.IsZero(request.Date) {
date = request.Date
}
var input = []struct {
name string
t time.Time
name string
begin time.Time
end time.Time
}{
{"today", utils.GetZeroTime(time.Now())},
{"current_week", utils.GetCurrentWeekFirstDay(time.Now())},
{"current_month", utils.GetCurrentMonthFirstDay(time.Now())},
{"today", utils.GetZeroTime(date), utils.GetZeroTime(date.AddDate(0, 0, 1))},
{"current_week", utils.GetCurrentWeekFirstDay(date), utils.GetCurrentWeekFirstDay(date.AddDate(0, 0, 7))},
{"current_month", utils.GetCurrentMonthFirstDay(date), utils.GetCurrentMonthFirstDay(date.AddDate(0, 1, 0))},
}
var response = make(map[string]interface{})
for _, v := range input {
var result = make([]*record, 0)
if err := productRecordDao.ProportionOfSecondLevelRecord(request.CompanyId, request.OrgId, request.WorkshopId, v.t, &result); err != nil {
if err := productRecordDao.ProportionOfSecondLevelRecord(request.CompanyId, request.OrgId, request.WorkshopId, v.begin, v.end, &result); err != nil {
log.Logger.Error(err.Error())
return nil, err
}
... ... @@ -252,20 +261,24 @@ func (ptr *PGCommonStatisticsService) WorkshopProductionEfficiencyStatistics(que
return nil, nil
}
productRecordDao, _ := dao.NewDeviceDailyRunningRecordDao(ptr.transactionContext)
var date = time.Now()
if !xtime.IsZero(request.Date) {
date = request.Date
}
var input = []struct {
name string
t time.Time
name string
begin time.Time
end time.Time
}{
{"today", utils.GetZeroTime(time.Now())},
{"current_week", utils.GetCurrentWeekFirstDay(time.Now())},
{"current_month", utils.GetCurrentMonthFirstDay(time.Now())},
{"today", utils.GetZeroTime(date), utils.GetZeroTime(date.AddDate(0, 0, 1))},
{"current_week", utils.GetCurrentWeekFirstDay(date), utils.GetCurrentWeekFirstDay(date.AddDate(0, 0, 7))},
{"current_month", utils.GetCurrentMonthFirstDay(date), utils.GetCurrentMonthFirstDay(date.AddDate(0, 1, 0))},
}
var response = make(map[string]interface{})
for _, v := range input {
var result = record{}
if err := productRecordDao.WorkshopProductionEfficiencyStatistics(request.CompanyId, request.OrgId, request.WorkshopId, v.t, &result); err != nil {
if err := productRecordDao.WorkshopProductionEfficiencyStatistics(request.CompanyId, request.OrgId, request.WorkshopId, v.begin, v.end, &result); err != nil {
log.Logger.Error(err.Error())
return nil, err
}
... ...
... ... @@ -168,6 +168,23 @@ func FindGroupMembers(productGroupRepository domain.ProductGroupRepository, comp
return result, keyFunc
}
// 查询组成员属于的分组
func FindMemberBelongToProductGroup(productGroupRepository domain.ProductGroupRepository, companyId, orgId int, workStationId string, member *domain.User) (*domain.ProductGroup, error) {
_, groups, err := productGroupRepository.Find(map[string]interface{}{"companyId": companyId, "orgId": orgId, "workStationId": workStationId})
if err != nil {
return nil, err
}
for i := range groups {
for j := range groups[i].GroupMembers {
u := groups[i].GroupMembers[j]
if u.UserId == member.UserId {
return groups[i], nil
}
}
}
return nil, nil
}
// 个人生产记录统计
func (ptr *PGProductRecordService) personalProductStatics(productPlan *domain.ProductPlan, productRecord *domain.ProductRecord) (interface{}, error) {
var (
... ...
... ... @@ -21,13 +21,14 @@ func (ptr *PGWorkerAttendanceReportService) Report(cid, oid int, report *domain.
var (
attendanceRecordDao, _ = dao.NewAttendanceRecordDao(ptr.transactionContext)
attendanceRecordRepository, _ = repository.NewProductAttendanceRecordRepository(ptr.transactionContext)
productGroupRepository, _ = repository.NewProductGroupRepository(ptr.transactionContext)
productCalendarRepository, _ = repository.NewProductCalendarRepository(ptr.transactionContext)
isSignIn = true
record *domain.ProductAttendanceRecord
//workStationId string //具体工位
workStation *domain.WorkStation
attendanceType int = domain.ParticipateSupport
worker *domain.User
org *domain.Org
workStation *domain.WorkStation
attendanceType int = domain.ParticipateSupport
worker *domain.User
org *domain.Org
)
if err := report.Valid(); err != nil {
... ... @@ -35,11 +36,10 @@ func (ptr *PGWorkerAttendanceReportService) Report(cid, oid int, report *domain.
}
var (
device *domain.Device
err error
productGroupRepository, _ = repository.NewProductGroupRepository(ptr.transactionContext)
groupId = 0
groupName = ""
device *domain.Device
err error
groupId = 0
groupName = ""
)
deviceRepository, _ := dao.NewDeviceDao(ptr.transactionContext)
if device, err = deviceRepository.FindDeviceByDeviceCode(cid, oid, report.Sn); err != nil {
... ... @@ -58,15 +58,17 @@ func (ptr *PGWorkerAttendanceReportService) Report(cid, oid int, report *domain.
return nil, err
}
groupMembers, groupMembersKeyFunc := FindGroupMembers(productGroupRepository, cid, oid, workStation.WorkStationId)
if v, ok := groupMembers[groupMembersKeyFunc(worker.UserId)]; ok {
var productCalendar *domain.ProductCalendar
productGroup, _ := FindMemberBelongToProductGroup(productGroupRepository, cid, oid, workStation.WorkStationId, worker)
if productGroup != nil {
attendanceType = domain.ParticipateNormal
groupId = v.GroupId
groupName = v.GroupName
groupId = productGroup.ProductGroupId
groupName = productGroup.GroupName
productCalendar, _ = productCalendarRepository.FindOne(map[string]interface{}{"companyId": cid, "orgId": oid, "workStationId": workStation.WorkStationId})
}
beginTime := utils.GetZeroTime(report.ActionTime)
endTime := time.Now()
beginTime := report.ActionTime.Add(-time.Hour * 13)
endTime := report.ActionTime
_, records, _ := attendanceRecordDao.WorkerAttendanceRecords(cid, oid, worker.UserId, "", beginTime, endTime)
for i := 0; i < len(records); i++ {
r := records[i]
... ... @@ -76,7 +78,7 @@ func (ptr *PGWorkerAttendanceReportService) Report(cid, oid int, report *domain.
if !utils.TimeIsZero(r.SignIn) && utils.TimeIsZero(r.SignOut) {
if utils.TimeAfterEqual(report.ActionTime, r.SignIn) {
r.SignOut = report.ActionTime
r.WorkTimeBefore = r.ComputeWorkTimeBefore()
r.WorkTimeBefore = r.ComputeWorkTimeBefore(productCalendar)
log.Logger.Debug(fmt.Sprintf("【考勤汇报】 用户:%v(%v) 在其他工段打卡 下线当前工段:%v 签退 %v", worker.UserName, worker.UserId, r.WorkStation.SectionName, report))
if _, err = attendanceRecordRepository.Save(r); err != nil {
return nil, err
... ... @@ -148,10 +150,11 @@ func (ptr *PGWorkerAttendanceReportService) Report(cid, oid int, report *domain.
ProductGroupId: groupId,
}),
}
record.SetProductTimeByProductCalendar(productCalendar)
log.Logger.Debug(fmt.Sprintf("【考勤汇报】 用户:%v(%v) 签到 %v", worker.UserName, worker.UserId, report))
} else {
record.SignOut = report.ActionTime
record.WorkTimeBefore = record.ComputeWorkTimeBefore()
record.WorkTimeBefore = record.ComputeWorkTimeBefore(productCalendar)
log.Logger.Debug(fmt.Sprintf("【考勤汇报】 用户:%v(%v) 签退 %v", worker.UserName, worker.UserId, report))
}
... ...
... ... @@ -6,7 +6,6 @@ import (
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/repository"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
"time"
)
... ... @@ -21,7 +20,7 @@ func (ptr *PGWorkshopWorkTimeStaticService) WorkshopWorkTimeStatic(productRecord
"companyId": productRecord.CompanyId,
"orgId": productRecord.OrgId,
"workStationId": productRecord.WorkStation.WorkStationId,
"recordDate": utils.GetZeroTime(productRecord.SignIn),
"recordDate": productRecord.ProductDate,
})
if err != nil && errors.Is(err, domain.ErrorNotFound) {
err = nil
... ... @@ -31,7 +30,7 @@ func (ptr *PGWorkshopWorkTimeStaticService) WorkshopWorkTimeStatic(productRecord
CompanyId: productRecord.CompanyId,
OrgId: productRecord.OrgId,
Ext: productRecord.Ext,
RecordDate: utils.GetZeroTime(productRecord.SignIn),
RecordDate: productRecord.ProductDate, // utils.GetZeroTime(productRecord.SignIn),
WorkshopWorkTimeRecordInfo: &domain.WorkshopWorkTimeRecordInfo{},
}
}
... ...
... ... @@ -37,4 +37,6 @@ type ProductAttendanceRecord struct {
DeletedAt time.Time `pg:",soft_delete" comment:"删除时间"`
// 扩展数据
Ext *domain.Ext `comment:"扩展数据"`
// 生产日期
ProductDate time.Time `comment:"生产日期"`
}
... ...
... ... @@ -35,4 +35,6 @@ type ProductCalendar struct {
DeletedAt time.Time `pg:",soft_delete" comment:"删除时间"`
// 扩展数据
Ext *domain.Ext `comment:"扩展数据"`
// 休息时间周期列表
BreakTimePeriods []*domain.ProductCalendarBreakTimePeriod `comment:"休息时间周期列表"`
}
... ...
... ... @@ -22,5 +22,6 @@ func TransformToProductAttendanceRecordDomainModelFromPgModels(productAttendance
UpdatedAt: productAttendanceRecordModel.UpdatedAt,
DeletedAt: productAttendanceRecordModel.DeletedAt,
Ext: productAttendanceRecordModel.Ext,
ProductDate: productAttendanceRecordModel.ProductDate,
}, nil
}
... ...
... ... @@ -21,5 +21,6 @@ func TransformToProductCalendarDomainModelFromPgModels(productCalendarModel *mod
UpdatedAt: productCalendarModel.UpdatedAt,
DeletedAt: productCalendarModel.DeletedAt,
Ext: productCalendarModel.Ext,
BreakTimePeriods: productCalendarModel.BreakTimePeriods,
}, nil
}
... ...
... ... @@ -6,7 +6,6 @@ import (
"github.com/go-redis/redis"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/constant"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log"
"time"
)
... ... @@ -15,7 +14,7 @@ func GetDeviceDailyRunningRecord(t time.Time, deviceCode string) (*domain.Device
client := GetRedis()
key := DeviceDailyRunningRecordKey(t, deviceCode)
record, err := getDeviceDailyRunningRecord(client, key)
log.Logger.Debug(fmt.Sprintf("Redis Device:%v GET Key:%v Value:%v", deviceCode, key, record))
//log.Logger.Debug(fmt.Sprintf("Redis Device:%v GET Key:%v Value:%v", deviceCode, key, record))
return record, err
}
... ... @@ -50,7 +49,7 @@ func SaveDeviceDailyRunningRecordByKey(key string, record *domain.DeviceDailyRun
if err != nil {
return err
}
log.Logger.Debug(fmt.Sprintf("Redis Device:%v SET Key:%v Value:%v", record.DeviceCode, key, record))
//log.Logger.Debug(fmt.Sprintf("Redis Device:%v SET Key:%v Value:%v", record.DeviceCode, key, record))
result := client.Set(key, recordData, time.Hour*24*5)
_, err = result.Result()
return err
... ...
... ... @@ -42,6 +42,7 @@ func (repository *ProductAttendanceRecordRepository) Save(productAttendanceRecor
"updated_at",
"deleted_at",
"ext",
"product_date",
}
insertFieldsSnippet := sqlbuilder.SqlFieldsSnippet(sqlbuilder.RemoveSqlFields(sqlBuildFields, "product_attendance_id", "deleted_at"))
insertPlaceHoldersSnippet := sqlbuilder.SqlPlaceHoldersSnippet(sqlbuilder.RemoveSqlFields(sqlBuildFields, "product_attendance_id", "deleted_at"))
... ... @@ -67,6 +68,7 @@ func (repository *ProductAttendanceRecordRepository) Save(productAttendanceRecor
&productAttendanceRecord.UpdatedAt,
&productAttendanceRecord.DeletedAt,
&productAttendanceRecord.Ext,
&productAttendanceRecord.ProductDate,
),
fmt.Sprintf("INSERT INTO manufacture.product_attendance_record (%s) VALUES (%s) RETURNING %s", insertFieldsSnippet, insertPlaceHoldersSnippet, returningFieldsSnippet),
//productAttendanceRecord.ProductAttendanceId,
... ... @@ -84,6 +86,7 @@ func (repository *ProductAttendanceRecordRepository) Save(productAttendanceRecor
productAttendanceRecord.UpdatedAt,
//productAttendanceRecord.DeletedAt,
productAttendanceRecord.Ext,
productAttendanceRecord.ProductDate,
); err != nil {
return productAttendanceRecord, err
}
... ... @@ -105,6 +108,7 @@ func (repository *ProductAttendanceRecordRepository) Save(productAttendanceRecor
&productAttendanceRecord.UpdatedAt,
&productAttendanceRecord.DeletedAt,
&productAttendanceRecord.Ext,
&productAttendanceRecord.ProductDate,
),
fmt.Sprintf("UPDATE manufacture.product_attendance_record SET %s WHERE product_attendance_id=? RETURNING %s", updateFieldsSnippet, returningFieldsSnippet),
//productAttendanceRecord.ProductAttendanceId,
... ... @@ -122,6 +126,7 @@ func (repository *ProductAttendanceRecordRepository) Save(productAttendanceRecor
productAttendanceRecord.UpdatedAt,
//productAttendanceRecord.DeletedAt,
productAttendanceRecord.Ext,
productAttendanceRecord.ProductDate,
productAttendanceRecord.Identify(),
); err != nil {
return productAttendanceRecord, err
... ... @@ -189,10 +194,10 @@ func (repository *ProductAttendanceRecordRepository) Find(queryOptions map[strin
query.Where(fmt.Sprintf(`work_station->>'sectionName' like '%%%v%%'`, v))
}
if v, ok := queryOptions["signBeginTime"]; ok && !((v.(time.Time)).IsZero()) {
query.Where("created_at>=?", v.(time.Time))
query.Where("product_date>=?", v.(time.Time))
}
if v, ok := queryOptions["signEndTime"]; ok && !((v.(time.Time)).IsZero()) {
query.Where("created_at<?", v.(time.Time))
query.Where("product_date<?", v.(time.Time))
}
if v, ok := queryOptions["employeeType"]; ok && (v.(int)) > 0 {
query.Where("product_worker->>'employeeType'='?'", v.(int))
... ...
... ... @@ -41,6 +41,7 @@ func (repository *ProductCalendarRepository) Save(productCalendar *domain.Produc
"updated_at",
"deleted_at",
"ext",
"break_time_periods",
}
insertFieldsSnippet := sqlbuilder.SqlFieldsSnippet(sqlbuilder.RemoveSqlFields(sqlBuildFields, "product_calendar_id", "deleted_at"))
insertPlaceHoldersSnippet := sqlbuilder.SqlPlaceHoldersSnippet(sqlbuilder.RemoveSqlFields(sqlBuildFields, "product_calendar_id", "deleted_at"))
... ... @@ -65,6 +66,7 @@ func (repository *ProductCalendarRepository) Save(productCalendar *domain.Produc
&productCalendar.UpdatedAt,
&productCalendar.DeletedAt,
&productCalendar.Ext,
&productCalendar.BreakTimePeriods,
),
fmt.Sprintf("INSERT INTO manufacture.product_calendar (%s) VALUES (%s) RETURNING %s", insertFieldsSnippet, insertPlaceHoldersSnippet, returningFieldsSnippet),
productCalendar.CompanyId,
... ... @@ -79,6 +81,7 @@ func (repository *ProductCalendarRepository) Save(productCalendar *domain.Produc
productCalendar.CreatedAt,
productCalendar.UpdatedAt,
productCalendar.Ext,
productCalendar.BreakTimePeriods,
); err != nil {
return productCalendar, err
}
... ... @@ -99,6 +102,7 @@ func (repository *ProductCalendarRepository) Save(productCalendar *domain.Produc
&productCalendar.UpdatedAt,
&productCalendar.DeletedAt,
&productCalendar.Ext,
&productCalendar.BreakTimePeriods,
),
fmt.Sprintf("UPDATE manufacture.product_calendar SET %s WHERE product_calendar_id=? RETURNING %s", updateFieldsSnippet, returningFieldsSnippet),
productCalendar.CompanyId,
... ... @@ -113,6 +117,7 @@ func (repository *ProductCalendarRepository) Save(productCalendar *domain.Produc
productCalendar.CreatedAt,
productCalendar.UpdatedAt,
productCalendar.Ext,
productCalendar.BreakTimePeriods,
productCalendar.Identify(),
); err != nil {
return productCalendar, err
... ... @@ -133,6 +138,9 @@ func (repository *ProductCalendarRepository) FindOne(queryOptions map[string]int
tx := repository.transactionContext.PgTx
productCalendarModel := new(models.ProductCalendar)
query := sqlbuilder.BuildQuery(tx.Model(productCalendarModel), queryOptions)
query.SetWhereByQueryOption("company_id = ?", "companyId")
query.SetWhereByQueryOption("org_id = ?", "orgId")
query.SetWhereByQueryOption("work_station->>'workStationId'=?", "workStationId")
query.SetWhereByQueryOption("product_calendar.product_calendar_id = ?", "productCalendarId")
if v, ok := queryOptions["includeDeleted"]; ok && v.(bool) {
query.AllWithDeleted()
... ...
... ... @@ -123,11 +123,14 @@ func (repository *ProductGroupRepository) FindOne(queryOptions map[string]interf
tx := repository.transactionContext.PgTx
productGroupModel := new(models.ProductGroup)
query := sqlbuilder.BuildQuery(tx.Model(productGroupModel), queryOptions)
query.SetWhereByQueryOption("company_id = ?", "companyId")
query.SetWhereByQueryOption("org_id = ?", "orgId")
query.SetWhereByQueryOption("product_group.product_group_id = ?", "productGroupId")
query.SetWhereByQueryOption("group_name=?", "groupName")
query.SetWhereByQueryOption("work_station->>'workStationId'=?", "workStationId")
query.SetWhereByQueryOption("work_station->>'workshopId'='?'", "workshopId")
query.SetWhereByQueryOption("work_station->>'lineId'='?'", "lineId")
query.SetWhereByQueryOption("work_station->>'sectionId'='?'", "sectionId")
if v, ok := queryOptions["includeDeleted"]; ok && v.(bool) {
query.AllWithDeleted()
}
... ...
package utils
import (
"github.com/beego/beego/v2/core/config"
"github.com/beego/beego/v2/server/web"
"os"
"strconv"
)
type Configurator interface {
DefaultString(key string, defaultVal string) string
DefaultInt(key string, defaultVal int) int
DefaultInt64(key string, defaultVal int64) int64
DefaultBool(key string, defaultVal bool) bool
DefaultFloat(key string, defaultVal float64) float64
}
// EnvConfigurator read config from env param with default value
type EnvConfigurator struct{}
func (c EnvConfigurator) DefaultString(key string, defaultVal string) string {
if os.Getenv(key) != "" {
return os.Getenv(key)
}
return defaultVal
}
func (c EnvConfigurator) DefaultInt(key string, defaultVal int) int {
if os.Getenv(key) == "" {
return defaultVal
}
v, err := strconv.Atoi(os.Getenv(key))
if err != nil {
return defaultVal
}
return v
}
func (c EnvConfigurator) DefaultInt64(key string, defaultVal int64) int64 {
if os.Getenv(key) == "" {
return defaultVal
}
v, err := strconv.ParseInt(os.Getenv(key), 10, 64)
if err != nil {
return defaultVal
}
return v
}
func (c EnvConfigurator) DefaultBool(key string, defaultVal bool) bool {
if os.Getenv(key) == "" {
return defaultVal
}
v, err := strconv.ParseBool(os.Getenv(key))
if err != nil {
return defaultVal
}
return v
}
func (c EnvConfigurator) DefaultFloat(key string, defaultVal float64) float64 {
if os.Getenv(key) == "" {
return defaultVal
}
v, err := strconv.ParseFloat(os.Getenv(key), 64)
if err != nil {
return defaultVal
}
return v
}
// BeegoAppConfigurator read config from beego config file with default value
type BeegoAppConfigurator struct {
}
func (c BeegoAppConfigurator) DefaultString(key string, defaultVal string) string {
return web.AppConfig.DefaultString(key, defaultVal)
}
func (c BeegoAppConfigurator) DefaultInt(key string, defaultVal int) int {
return web.AppConfig.DefaultInt(key, defaultVal)
}
func (c BeegoAppConfigurator) DefaultInt64(key string, defaultVal int64) int64 {
return web.AppConfig.DefaultInt64(key, defaultVal)
}
func (c BeegoAppConfigurator) DefaultBool(key string, defaultVal bool) bool {
return web.AppConfig.DefaultBool(key, defaultVal)
}
func (c BeegoAppConfigurator) DefaultFloat(key string, defaultVal float64) float64 {
return web.AppConfig.DefaultFloat(key, defaultVal)
}
func NewConfig(adapterName, filename string) Configurator {
config, err := config.NewConfig(adapterName, filename)
if err != nil {
panic(err)
}
return config
}
... ...
package utils
import (
"github.com/stretchr/testify/assert"
"os"
"testing"
)
func TestEnvConfigurator(t *testing.T) {
os.Setenv("bool", "true")
os.Setenv("hello", "world")
os.Setenv("number", "10")
var config Configurator = EnvConfigurator{}
assert.Equal(t, "world", config.DefaultString("hello", "w"))
assert.Equal(t, "w", config.DefaultString("unknown", "w"))
assert.Equal(t, true, config.DefaultBool("bool", false))
assert.Equal(t, true, config.DefaultBool("unknown", true))
assert.Equal(t, 10, config.DefaultInt("number", 5))
assert.Equal(t, 5, config.DefaultInt("unknown", 5))
assert.Equal(t, int64(10), config.DefaultInt64("number", 5))
assert.Equal(t, int64(5), config.DefaultInt64("unknown", 5))
assert.Equal(t, float64(10), config.DefaultFloat("number", 5))
assert.Equal(t, float64(5), config.DefaultFloat("unknown", 5))
}
... ...
package utils
type TreeNode interface {
PID() string
ID() string
}
type Tree struct {
Node TreeNode `json:"node"`
Nodes []*Tree `json:"nodes"`
}
func NewTree(nodes []TreeNode) *Tree {
var tree = &Tree{
Node: nil,
Nodes: make([]*Tree, 0),
}
for i := range nodes {
match := traverseAdd(tree, nodes[i])
if !match {
tree.Nodes = append(tree.Nodes, newTree(nodes[i]))
}
}
return tree
}
func newTree(node TreeNode) *Tree {
return &Tree{
Node: node,
Nodes: make([]*Tree, 0),
}
}
func (tree *Tree) Root() TreeNode {
if tree.Node != nil {
return tree.Node
}
if len(tree.Nodes) > 0 {
return tree.Nodes[0].Node
}
return nil
}
// TreeNodePaths returns all the parents of the current node 1->5->7 , use time n*O(n)(need performance optimization)
func (tree *Tree) TreeNodePaths(node TreeNode) []TreeNode {
treeNode := node
result := make([]TreeNode, 0)
for {
if treeNode == nil {
break
}
tmp := tree.find(treeNode, func(a, b TreeNode) bool {
if a.ID() == b.PID() {
return true
}
return false
})
result = append(result, treeNode)
if tmp == nil {
break
}
treeNode = tmp.Node
}
reserveResult := make([]TreeNode, 0)
for i := len(result) - 1; i >= 0; i-- {
reserveResult = append(reserveResult, result[i])
}
return reserveResult
}
// Add adds a node to the first matching parent tree if add success it return true
func (tree *Tree) Add(node TreeNode) bool {
return traverseAdd(tree, node)
}
// AllChildNode returns all child nodes under Node, including itself
func (tree *Tree) AllChildNode(node TreeNode) []TreeNode {
treeNode := tree.find(node, nil)
if treeNode == nil {
return []TreeNode{}
}
return tree.allChildNode(treeNode, nil)
}
//AllLeafNode returns all leaf node under Node ,if node is nil returns all leaf node under tree
func (tree *Tree) AllLeafNode(node TreeNode) []TreeNode {
treeNode := tree
if node != nil {
treeNode = tree.find(node, nil)
}
if treeNode == nil {
return []TreeNode{}
}
return tree.allChildNode(treeNode, func(node *Tree) bool {
if len(node.Nodes) == 0 {
return true
}
return false
})
}
// find query the node in this tree
func (tree *Tree) find(node TreeNode, compared func(a, b TreeNode) bool) *Tree {
var stack []*Tree
stack = append(stack, tree)
var find *Tree
for {
if len(stack) == 0 {
break
}
pop := stack[0]
stack = stack[1:]
stack = append(stack, pop.Nodes...)
if pop == nil || pop.Node == nil {
continue
}
if compared != nil {
if compared(pop.Node, node) {
find = pop
break
}
continue
}
if pop.Node.ID() == node.ID() {
find = pop
break
}
}
return find
}
// allChildNode 返回treeNode下所有子节点
func (tree *Tree) allChildNode(treeNode *Tree, filter func(node *Tree) bool) []TreeNode {
var stack []*Tree
stack = append(stack, treeNode)
var res []TreeNode
for {
if len(stack) == 0 {
break
}
pop := stack[0]
stack = stack[1:]
stack = append(stack, pop.Nodes...)
if filter != nil && !filter(pop) {
continue
}
res = append(res, pop.Node)
}
return res
}
// traverseAdd 递归添加
//
// tree 当前树
// node 判断的节点
func traverseAdd(tree *Tree, node TreeNode) bool {
list := tree.Nodes
var match bool = false
for i := range list {
id, pid := list[i].Node.ID(), node.PID()
if pid == id {
list[i].Nodes = append(list[i].Nodes, newTree(node))
return true
}
if match || traverseAdd(list[i], node) {
match = true
break
}
}
return match
}
... ...
package utils
import (
"github.com/stretchr/testify/assert"
"strconv"
"testing"
)
func Test_Tree(t *testing.T) {
table := []struct {
Input []TreeNode
Text string
Except []string
Except2 []string
}{
{
Input: []TreeNode{
&st{Id: 1, Pid: 0},
&st{Id: 2, Pid: 1}, &st{Id: 3, Pid: 1}, &st{Id: 4, Pid: 1},
&st{Id: 5, Pid: 3},
&st{Id: 6, Pid: 5}, &st{Id: 7, Pid: 5}},
Text: `
树形结构:
1
2 3 4
5
6 7
`,
Except: []string{"5", "6", "7"},
Except2: []string{"2", "4", "6", "7"},
},
}
for i := range table {
tree := NewTree(table[i].Input)
out := tree.AllChildNode(&st{Id: 5, Pid: 3})
var res []string = treeNodeResults(out)
assert.Equal(t, res, table[i].Except)
out = tree.AllLeafNode(nil) //tree.Root()
res = treeNodeResults(out)
assert.Equal(t, res, table[i].Except2)
root := tree.Root()
assert.Equal(t, root.ID(), "1")
//tree.Add(&st{Id:10,Pid: 7})
//
//out = tree.AllLeafNode(tree.Root())
//res = treeNodeResults(out)
//assert.Equal(t, res, []string{"2", "4", "6", "10"})
out = tree.TreeNodePaths(&st{Id: 7, Pid: 5})
res = treeNodeResults(out)
assert.Equal(t, res, []string{"1", "3", "5", "7"})
}
}
type st struct {
Id int
Pid int
}
func (t *st) PID() string {
return strconv.Itoa(t.Pid)
}
func (t *st) ID() string {
return strconv.Itoa(t.Id)
}
func treeNodeResults(nodes []TreeNode) []string {
var res []string
for i := range nodes {
res = append(res, nodes[i].ID())
}
return res
}
... ...
package log
import (
"github.com/linmadan/egglib-go/log"
"github.com/linmadan/egglib-go/log/logrus"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/constant"
"io"
)
//var Logger log.Logger
//
//func init() {
// Logger = logrus.NewLogrusLogger()
// Logger.SetServiceName(constant.SERVICE_NAME)
// Logger.SetLevel(constant.LOG_LEVEL)
//}
var Logger *LogrusLogger
var Logger log.Logger
func init() {
Logger = NewLogrusLogger()
Logger = logrus.NewLogrusLogger()
Logger.SetServiceName(constant.SERVICE_NAME)
Logger.SetLevel(constant.LOG_LEVEL)
}
func InitLogHook(enableKafka bool, enableBeeLog bool) {
if enableKafka {
if w, err := logrus.NewKafkaWriter(constant.KAFKA_HOST, constant.TOPIC_LOG_STASH, false); err == nil {
Logger.AddHook(w)
} else {
Logger.Error(err.Error())
}
}
if enableBeeLog {
if w, err := logrus.NewWrapHook(true, func() (io.Writer, error) {
return logrus.NewBeegoLogWriter("", `{"filename":"app.log","maxsize":2048000}`)
}); err == nil {
Logger.AddHook(w)
} else {
Logger.Error(err.Error())
}
}
}
//var Logger *LogrusLogger
//
//func init() {
// Logger = NewLogrusLogger()
// Logger.SetServiceName(constant.SERVICE_NAME)
// Logger.SetLevel(constant.LOG_LEVEL)
//}
... ...
package log
import (
"github.com/linmadan/egglib-go/log"
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus/hooks/writer"
"io"
"os"
)
func init() {
logrus.SetFormatter(&logrus.JSONFormatter{})
logrus.SetOutput(os.Stdout)
logrus.SetLevel(logrus.WarnLevel)
}
type LogrusLogger struct {
serviceName string
logrus *logrus.Logger
}
func (logger *LogrusLogger) SetServiceName(serviceName string) {
logger.serviceName = serviceName
}
func (logger *LogrusLogger) SetLevel(level string) {
switch level {
case "trace":
logger.logrus.Level = logrus.TraceLevel
case "debug":
logger.logrus.Level = logrus.DebugLevel
case "info":
logger.logrus.Level = logrus.InfoLevel
case "warn":
logger.logrus.Level = logrus.WarnLevel
case "error":
logger.logrus.Level = logrus.ErrorLevel
case "fatal":
logger.logrus.Level = logrus.FatalLevel
case "panic":
logger.logrus.Level = logrus.PanicLevel
default:
logger.logrus.Level = logrus.DebugLevel
}
}
func (logger *LogrusLogger) AddHook(w io.Writer) {
level := logger.logrus.Level
var levels []logrus.Level
// 默认已经添加了一个当前log level的hook,所以此处 level+1
for i := 0; i <= (int(level)); i++ {
levels = append(levels, logrus.Level(i))
}
logger.logrus.AddHook(&writer.Hook{
Writer: w,
LogLevels: levels,
})
}
func (logger *LogrusLogger) Trace(msg string, appends ...map[string]interface{}) {
contextLogger := logger.logrus.WithFields(logrus.Fields{"serviceName": logger.serviceName})
for _, append := range appends {
contextLogger = contextLogger.WithFields(append)
}
contextLogger.Trace(msg)
}
func (logger *LogrusLogger) Debug(msg string, appends ...map[string]interface{}) {
contextLogger := logger.logrus.WithFields(logrus.Fields{"serviceName": logger.serviceName})
for _, append := range appends {
contextLogger = contextLogger.WithFields(append)
}
contextLogger.Debug(msg)
}
func (logger *LogrusLogger) Info(msg string, appends ...map[string]interface{}) {
contextLogger := logger.logrus.WithFields(logrus.Fields{"serviceName": logger.serviceName})
for _, append := range appends {
contextLogger = contextLogger.WithFields(append)
}
contextLogger.Info(msg)
}
func (logger *LogrusLogger) Warn(msg string, appends ...map[string]interface{}) {
contextLogger := logger.logrus.WithFields(logrus.Fields{"serviceName": logger.serviceName})
for _, append := range appends {
contextLogger = contextLogger.WithFields(append)
}
contextLogger.Warn(msg)
}
func (logger *LogrusLogger) Error(msg string, appends ...map[string]interface{}) {
contextLogger := logger.logrus.WithFields(logrus.Fields{"serviceName": logger.serviceName})
for _, append := range appends {
contextLogger = contextLogger.WithFields(append)
}
contextLogger.Error(msg)
}
func (logger *LogrusLogger) Fatal(msg string, appends ...map[string]interface{}) {
contextLogger := logger.logrus.WithFields(logrus.Fields{"serviceName": logger.serviceName})
for _, append := range appends {
contextLogger = contextLogger.WithFields(append)
}
contextLogger.Fatal(msg)
}
func (logger *LogrusLogger) Panic(msg string, appends ...map[string]interface{}) {
contextLogger := logger.logrus.WithFields(logrus.Fields{"serviceName": logger.serviceName})
for _, append := range appends {
contextLogger = contextLogger.WithFields(append)
}
contextLogger.Panic(msg)
}
func NewLogrusLogger() *LogrusLogger {
logger := logrus.New()
logger.Formatter = &logrus.JSONFormatter{}
logger.Out = os.Stdout
return &LogrusLogger{
logrus: logger,
}
}
var _ log.Logger = (*LogrusLogger)(nil)
//func init() {
// logrus.SetFormatter(&logrus.JSONFormatter{})
// logrus.SetOutput(os.Stdout)
// logrus.SetLevel(logrus.WarnLevel)
//}
//
//type LogrusLogger struct {
// serviceName string
// logrus *logrus.Logger
//}
//
//func (logger *LogrusLogger) SetServiceName(serviceName string) {
// logger.serviceName = serviceName
//}
//
//func (logger *LogrusLogger) SetLevel(level string) {
// switch level {
// case "trace":
// logger.logrus.Level = logrus.TraceLevel
// case "debug":
// logger.logrus.Level = logrus.DebugLevel
// case "info":
// logger.logrus.Level = logrus.InfoLevel
// case "warn":
// logger.logrus.Level = logrus.WarnLevel
// case "error":
// logger.logrus.Level = logrus.ErrorLevel
// case "fatal":
// logger.logrus.Level = logrus.FatalLevel
// case "panic":
// logger.logrus.Level = logrus.PanicLevel
// default:
// logger.logrus.Level = logrus.DebugLevel
// }
//}
//
//func (logger *LogrusLogger) AddHook(w io.Writer) {
// level := logger.logrus.Level
// var levels []logrus.Level
// // 默认已经添加了一个当前log level的hook,所以此处 level+1
// for i := 0; i <= (int(level)); i++ {
// levels = append(levels, logrus.Level(i))
// }
// logger.logrus.AddHook(&writer.Hook{
// Writer: w,
// LogLevels: levels,
// })
//}
//
//func (logger *LogrusLogger) Trace(msg string, appends ...map[string]interface{}) {
// contextLogger := logger.logrus.WithFields(logrus.Fields{"serviceName": logger.serviceName})
// for _, append := range appends {
// contextLogger = contextLogger.WithFields(append)
// }
// contextLogger.Trace(msg)
//}
//
//func (logger *LogrusLogger) Debug(msg string, appends ...map[string]interface{}) {
// contextLogger := logger.logrus.WithFields(logrus.Fields{"serviceName": logger.serviceName})
// for _, append := range appends {
// contextLogger = contextLogger.WithFields(append)
// }
// contextLogger.Debug(msg)
//}
//
//func (logger *LogrusLogger) Info(msg string, appends ...map[string]interface{}) {
// contextLogger := logger.logrus.WithFields(logrus.Fields{"serviceName": logger.serviceName})
// for _, append := range appends {
// contextLogger = contextLogger.WithFields(append)
// }
// contextLogger.Info(msg)
//}
//
//func (logger *LogrusLogger) Warn(msg string, appends ...map[string]interface{}) {
// contextLogger := logger.logrus.WithFields(logrus.Fields{"serviceName": logger.serviceName})
// for _, append := range appends {
// contextLogger = contextLogger.WithFields(append)
// }
// contextLogger.Warn(msg)
//}
//
//func (logger *LogrusLogger) Error(msg string, appends ...map[string]interface{}) {
// contextLogger := logger.logrus.WithFields(logrus.Fields{"serviceName": logger.serviceName})
// for _, append := range appends {
// contextLogger = contextLogger.WithFields(append)
// }
// contextLogger.Error(msg)
//}
//
//func (logger *LogrusLogger) Fatal(msg string, appends ...map[string]interface{}) {
// contextLogger := logger.logrus.WithFields(logrus.Fields{"serviceName": logger.serviceName})
// for _, append := range appends {
// contextLogger = contextLogger.WithFields(append)
// }
// contextLogger.Fatal(msg)
//}
//
//func (logger *LogrusLogger) Panic(msg string, appends ...map[string]interface{}) {
// contextLogger := logger.logrus.WithFields(logrus.Fields{"serviceName": logger.serviceName})
// for _, append := range appends {
// contextLogger = contextLogger.WithFields(append)
// }
// contextLogger.Panic(msg)
//}
//
//func NewLogrusLogger() *LogrusLogger {
// logger := logrus.New()
// logger.Formatter = &logrus.JSONFormatter{}
// logger.Out = os.Stdout
// return &LogrusLogger{
// logrus: logger,
// }
//}
//
//var _ log.Logger = (*LogrusLogger)(nil)
... ...
package log
import (
"encoding/json"
"errors"
"fmt"
"github.com/beego/beego/v2/core/logs"
"io"
"sync/atomic"
)
var errOutOfMaxSize = errors.New("msg size is out of limit ")
type BaseHook struct {
syncWrite bool
msgChan chan []byte
maxSize int32
currentSize int32
closeChan chan struct{}
w io.Writer
}
func (b *BaseHook) Write(p []byte) (n int, err error) {
if b.syncWrite {
return b.w.Write(p)
}
if b.currentSize >= b.maxSize {
fmt.Println(errOutOfMaxSize.Error(), b.currentSize)
return 0, errOutOfMaxSize
}
b.msgChan <- p
atomic.AddInt32(&b.currentSize, 1)
return len(p), nil
}
// NewBaseHook
// syncWriteFlag 同步写标识 true:同步写 false:异步写
func NewBaseHook(syncWriteFlag bool, internalIo io.WriteCloser) (*BaseHook, error) {
writer := &BaseHook{
syncWrite: syncWriteFlag,
maxSize: 10000,
msgChan: make(chan []byte, 10000),
closeChan: make(chan struct{}),
w: internalIo,
}
go writer.ConsumeMsg()
return writer, nil
}
func (b *BaseHook) ConsumeMsg() {
for {
select {
case <-b.closeChan:
return
case m, ok := <-b.msgChan:
if ok {
atomic.AddInt32(&b.currentSize, -1)
if _, err := b.w.Write(m); err != nil {
fmt.Println(err)
}
}
}
}
}
func (b *BaseHook) Close() {
close(b.msgChan)
b.closeChan <- struct{}{}
//b.wc.Close()
}
type LoggerConfig struct {
Level int `json:"level,omitempty"`
Filename string `json:"filename,omitempty"`
MaxSize int `json:"maxsize,omitempty"`
//MaxBackups int `json:"max_backups,omitempty"`
//MaxAge int `json:"max_age,omitempty"`
//Compress bool `json:"compress,omitempty"`
//文件最多保存多少天,默认保存 7 天
//MaxDays int `json:"maxdays"`
}
type internalLog struct {
*logs.BeeLogger
}
func NewBeegoLogWriter(conf LoggerConfig) io.Writer {
logger := logs.GetBeeLogger()
logger.SetLevel(conf.Level)
logger.EnableFuncCallDepth(true)
logger.SetLogFuncCallDepth(2)
confByte, _ := json.Marshal(conf)
err := logger.SetLogger(logs.AdapterFile, string(confByte))
if err != nil {
fmt.Println(err.Error())
}
return &internalLog{logger}
}
func (l *internalLog) Write(p []byte) (n int, err error) {
l.Debug(string(p))
return len(p), nil
}
//import (
// "encoding/json"
// "errors"
// "fmt"
// "github.com/beego/beego/v2/core/logs"
// "io"
// "sync/atomic"
//)
//
//var errOutOfMaxSize = errors.New("msg size is out of limit ")
//
//type BaseHook struct {
// syncWrite bool
// msgChan chan []byte
// maxSize int32
// currentSize int32
// closeChan chan struct{}
// w io.Writer
//}
//
//func (b *BaseHook) Write(p []byte) (n int, err error) {
// if b.syncWrite {
// return b.w.Write(p)
// }
// if b.currentSize >= b.maxSize {
// fmt.Println(errOutOfMaxSize.Error(), b.currentSize)
// return 0, errOutOfMaxSize
// }
// b.msgChan <- p
// atomic.AddInt32(&b.currentSize, 1)
//
// return len(p), nil
//}
//
//// NewBaseHook
//// syncWriteFlag 同步写标识 true:同步写 false:异步写
//func NewBaseHook(syncWriteFlag bool, internalIo io.WriteCloser) (*BaseHook, error) {
// writer := &BaseHook{
// syncWrite: syncWriteFlag,
// maxSize: 10000,
// msgChan: make(chan []byte, 10000),
// closeChan: make(chan struct{}),
// w: internalIo,
// }
// go writer.ConsumeMsg()
// return writer, nil
//}
//
//func (b *BaseHook) ConsumeMsg() {
// for {
// select {
// case <-b.closeChan:
// return
// case m, ok := <-b.msgChan:
// if ok {
// atomic.AddInt32(&b.currentSize, -1)
// if _, err := b.w.Write(m); err != nil {
// fmt.Println(err)
// }
// }
// }
// }
//}
//
//func (b *BaseHook) Close() {
// close(b.msgChan)
// b.closeChan <- struct{}{}
// //b.wc.Close()
//}
//
//type LoggerConfig struct {
// Level int `json:"level,omitempty"`
// Filename string `json:"filename,omitempty"`
// MaxSize int `json:"maxsize,omitempty"`
// //MaxBackups int `json:"max_backups,omitempty"`
// //MaxAge int `json:"max_age,omitempty"`
// //Compress bool `json:"compress,omitempty"`
// //文件最多保存多少天,默认保存 7 天
// //MaxDays int `json:"maxdays"`
//}
//
//type internalLog struct {
// *logs.BeeLogger
//}
//
//func NewBeegoLogWriter(conf LoggerConfig) io.Writer {
// logger := logs.GetBeeLogger()
// logger.SetLevel(conf.Level)
// logger.EnableFuncCallDepth(true)
// logger.SetLogFuncCallDepth(2)
// confByte, _ := json.Marshal(conf)
// err := logger.SetLogger(logs.AdapterFile, string(confByte))
// if err != nil {
// fmt.Println(err.Error())
// }
// return &internalLog{logger}
//}
//
//func (l *internalLog) Write(p []byte) (n int, err error) {
// l.Debug(string(p))
// return len(p), nil
//}
... ...
... ... @@ -78,3 +78,11 @@ func (controller *ProductCalendarController) SearchProductCalendar() {
total, data, err := productCalendarService.SearchProductCalendar(ParseOperateInfo(controller.BaseController), cmd)
ResponseGrid(controller.BaseController, total, data, err)
}
func (controller *ProductCalendarController) GetProductGroupCalendar() {
productCalendarService := service.NewProductCalendarService(nil)
cmd := &query.GetProductGroupCalendarQuery{}
Must(controller.Unmarshal(cmd))
data, err := productCalendarService.GetProductGroupCalendar(cmd)
controller.Response(data, err)
}
... ...
... ... @@ -100,3 +100,15 @@ func (controller *ProductGroupController) GetSignInEmployeeQuery() {
data, err := productGroupService.GetSignEmployee(cmd)
controller.Response(data, err)
}
func (controller *ProductGroupController) SelectorProductGroups() {
productGroupService := service.NewProductGroupService(nil)
cmd := &query.SearchProductGroupQuery{}
Must(controller.Unmarshal(cmd))
operateInfo := ParseOperateInfo(controller.BaseController)
//cmd.OrgId = operateInfo.OrgId
cmd.CompanyId = operateInfo.CompanyId
cmd.InOrgIds = operateInfo.OrgIds
data, err := productGroupService.SelectorProductGroup(ParseOperateInfo(controller.BaseController), cmd)
controller.Response(data, err)
}
... ...
... ... @@ -14,4 +14,5 @@ func init() {
web.Router("/product-calendars/", &controllers.ProductCalendarController{}, "Get:ListProductCalendar")
web.Router("/product-calendars/search", &controllers.ProductCalendarController{}, "Post:SearchProductCalendar")
web.Router("/product-calendars/product-group-calendar", &controllers.ProductCalendarController{}, "Post:GetProductGroupCalendar")
}
... ...
... ... @@ -15,4 +15,5 @@ func init() {
web.Router("/product-groups/search", &controllers.ProductGroupController{}, "Post:SearchProductGroup")
web.Router("/product-groups/employees", &controllers.ProductGroupController{}, "Post:SearchProductGroupEmployees")
web.Router("/product-groups/employee-signing", &controllers.ProductGroupController{}, "Post:GetSignInEmployeeQuery")
web.Router("/product-groups/selector", &controllers.ProductGroupController{}, "Post:SelectorProductGroups")
}
... ...
... ... @@ -30,13 +30,14 @@ func OnReceiveData(client pahomqtt.Client, message pahomqtt.Message) {
}
if workShop, ok := payload["WorkShop"]; ok {
if t, ok := payload["UpTime"]; ok {
collectionTime, _ = time.ParseInLocation("2006-01-02 - 15:04:05", t.(string), time.Local)
}
if collectionTime.IsZero() {
log.Logger.Error(fmt.Sprintf("采集时间有误:%v ", collectionTime), map[string]interface{}{"data": message})
return
}
//if t, ok := payload["UpTime"]; ok {
// collectionTime, _ = time.ParseInLocation("2006-01-02 - 15:04:05", t.(string), time.Local)
//}
//if collectionTime.IsZero() {
// log.Logger.Error(fmt.Sprintf("采集时间有误:%v ", collectionTime), map[string]interface{}{"data": message})
// return
//}
collectionTime = time.Now()
var mBytes []byte
for key, item := range payload {
if key == "WorkShop" || key == "UpTime" {
... ...