作者 yangfu

feat: 同步用户数据到打卡机

... ... @@ -4,7 +4,6 @@ go 1.16
require (
github.com/ajg/form v1.5.1 // indirect
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394
github.com/beego/beego/v2 v2.0.1
github.com/emirpasic/gods v1.12.0
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072 // indirect
... ...
... ... @@ -21,8 +21,6 @@ github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+Dx
github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc=
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg=
github.com/beanstalkd/go-beanstalk v0.1.0/go.mod h1:/G8YTyChOtpOArwLTQPY1CHB+i212+av35bkPXXj56Y=
github.com/beego/beego/v2 v2.0.1 h1:07a7Z0Ok5vbqyqh+q53sDPl9LdhKh0ZDy3gbyGrhFnE=
github.com/beego/beego/v2 v2.0.1/go.mod h1:8zyHi1FnWO1mZLwTn62aKRIZF/aIKvkCBB2JYs+eqQI=
... ... @@ -312,8 +310,6 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/qiniu/iconv v1.2.0 h1:2LJKwoF+4LJ3lNM+7cE3P1kNQzAI/HMZuWhkmFoY2U8=
github.com/qiniu/iconv v1.2.0/go.mod h1:5bxb2h9lptZt2eHLgY+Jw4X06TMtKb6tvvok0DwSwGA=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
... ...
... ... @@ -3,7 +3,6 @@ package service
import (
"bytes"
"fmt"
"github.com/axgle/mahonia"
"github.com/beego/beego/v2/adapter/utils"
"github.com/gookit/event"
"github.com/linmadan/egglib-go/core/application"
... ... @@ -18,26 +17,10 @@ var GlobalTerminalManager *TerminalManager
func init() {
GlobalTerminalManager = NewTerminalManager()
event.On(domain.UserCreateEvent, event.ListenerFunc(func(e event.Event) error {
return nil
}))
event.On(domain.UserUpdateEvent, event.ListenerFunc(func(e event.Event) error {
return nil
}))
event.On(domain.UserDeleteEvent, event.ListenerFunc(func(e event.Event) error {
return nil
}))
event.On(domain.UserEnableEvent, event.ListenerFunc(func(e event.Event) error {
return nil
}))
event.On(domain.UserEnableEvent, event.ListenerFunc(func(e event.Event) error {
return nil
}))
event.On(domain.UserCreateEvent, event.ListenerFunc(GlobalTerminalManager.SyncUser))
event.On(domain.UserUpdateEvent, event.ListenerFunc(GlobalTerminalManager.SyncUser))
event.On(domain.UserEnableEvent, event.ListenerFunc(GlobalTerminalManager.EnableUser))
event.On(domain.UserSyncEvent, event.ListenerFunc(GlobalTerminalManager.SyncUser))
event.On(DownEntityEvent, event.ListenerFunc(GlobalTerminalManager.DownEntityEvent))
}
... ... @@ -119,6 +102,8 @@ func terminalReport(cmd *command.TerminalReportCommand, transactionContext appli
}
break
}
case "devicecmd":
log.Logger.Debug("【TerminalManager】 收到命令应答 cmd : " + cmd.Content)
}
return map[string]interface{}{
... ... @@ -252,7 +237,6 @@ func (handler ZKClockHandler) Attendance(entity AttLOGUpEntity) (DownEntity, err
// 请求 人脸识别-指纹
if len(userBase.UserInfo.FingerprintPortrait) == 0 {
sendQuery = true
//event.Fire(DownEntityEvent, map[string]interface{}{"entity": NewQueryBIODATADownEntity(generateSn(), entity.Pin, BioDataType1)})
}
if sendQuery {
event.Fire(DownEntityEvent, map[string]interface{}{"entity": NewQueryUserInfoDownEntity(generateSn(), entity.Pin)})
... ... @@ -323,33 +307,3 @@ func (handler ZKClockHandler) ReportUser(entity USEREntity) (DownEntity, error)
func generateSn() string {
return string(utils.RandomCreateBytes(10))
}
// GbkToUtf8 GBK 转 UTF-8
func GbkToUtf8(s string) string {
decoder := mahonia.NewDecoder("gbk")
_, data, _ := decoder.Translate([]byte(s), true)
//return decoder.ConvertString(s)
return string(data)
}
// Utf8ToGbk UTF-8 转 GBK
func Utf8ToGbk(s string) string {
encoder := mahonia.NewEncoder("gbk")
return encoder.ConvertString(s)
}
func ConvertToString(src string, srcCode string, tagCode string) string {
srcCoder := mahonia.NewDecoder(srcCode)
srcResult := srcCoder.ConvertString(src)
tagCoder := mahonia.NewDecoder(tagCode)
_, cdata, _ := tagCoder.Translate([]byte(srcResult), true)
result := string(cdata)
return result
}
... ...
... ... @@ -3,6 +3,7 @@ package service
import (
"container/list"
"github.com/gookit/event"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/log"
"sync"
)
... ... @@ -28,7 +29,7 @@ func (term *TerminalManager) GetDevice(terminalId string) (*TerminalDevice, bool
if !ok {
device := NewTerminalDevice(terminalId)
term.TerminalDevices.Store(terminalId, device)
log.Logger.Debug("【TerminalManager】 add new device:"+terminalId, map[string]interface{}{"device": device})
log.Logger.Debug("【TerminalManager】 终端上线 add new device:"+terminalId, map[string]interface{}{"device": device})
term.TerminalDeviceList = append(term.TerminalDeviceList, device)
return nil, false
}
... ... @@ -56,6 +57,10 @@ func (term *TerminalManager) AddDownEntityByDevice(sn string, entity interface{}
}
func (term *TerminalManager) BroadcastDownEntity(downEntity interface{}) {
if len(term.TerminalDeviceList) == 0 {
log.Logger.Debug("【TerminalManager】 当前在线终端:0 广播命令退出")
return
}
for i := range term.TerminalDeviceList {
term.TerminalDeviceList[i].AddDownEntity(downEntity)
}
... ... @@ -64,7 +69,6 @@ func (term *TerminalManager) BroadcastDownEntity(downEntity interface{}) {
// Listen Event
func (term *TerminalManager) DownEntityEvent(e event.Event) error {
//fmt.Printf("handle down entity event: %s\n", e.Name())
entity := e.Get("entity")
if entity != nil {
term.BroadcastDownEntity(entity)
... ... @@ -72,6 +76,60 @@ func (term *TerminalManager) DownEntityEvent(e event.Event) error {
return nil
}
func (term *TerminalManager) SyncUser(e event.Event) error {
user := e.Get("user")
userBase := e.Get("userBase")
if user != nil && userBase == nil {
assertUser := user.(*domain.User)
if assertUser.Ext.DepName != "制造中心" {
log.Logger.Debug("【TerminalManager】 当前用户部门不是 [制造中心] 不进行同步", map[string]interface{}{"user": user})
return nil
}
term.BroadcastDownEntity(NewUpdateUserDownEntity(generateSn(), assertUser.Ext.IcCardNumber, assertUser.Ext.UserName))
return nil
}
if user != nil && userBase != nil {
assertUser := user.(*domain.User)
assertUserBase := userBase.(*domain.UserBase)
if assertUser.Ext.DepName != "制造中心" {
log.Logger.Debug("【TerminalManager】 当前用户部门不是 [制造中心] 不进行同步", map[string]interface{}{"user": user})
return nil
}
if len(assertUser.Ext.IcCardNumber) == 0 {
return nil
}
if len(assertUserBase.UserInfo.FacePortrait) > 0 {
term.BroadcastDownEntity(NewUpdateUserFacePortraitDownEntity(generateSn(), assertUser.Ext.IcCardNumber, assertUserBase.UserInfo.FacePortrait))
}
if len(assertUserBase.UserInfo.FingerprintPortrait) > 0 {
term.BroadcastDownEntity(NewUpdateUserFingerprintPortraitDownEntity(generateSn(), assertUser.Ext.IcCardNumber, assertUserBase.UserInfo.FingerprintPortrait))
}
term.BroadcastDownEntity(NewUpdateUserDownEntity(generateSn(), assertUser.Ext.IcCardNumber, assertUserBase.UserInfo.UserName))
}
return nil
}
func (term *TerminalManager) EnableUser(e event.Event) error {
user := e.Get("user")
if user != nil {
assertUser := user.(*domain.User)
if assertUser.EnableStatus == int(domain.UserStatusEnable) {
term.SyncUser(e)
} else if assertUser.EnableStatus == int(domain.UserStatusDisable) {
term.BroadcastDownEntity(NewDeleteDownEntity(generateSn(), assertUser.Ext.IcCardNumber, string(UserInfo)))
}
}
return nil
}
func (term *TerminalManager) CreateUser(e event.Event) error {
return term.SyncUser(e)
}
func (term *TerminalManager) UpdateUser(e event.Event) error {
return term.EnableUser(e)
}
type TerminalDevice struct {
Id string
DownEntityList *list.List
... ... @@ -91,13 +149,18 @@ func (device *TerminalDevice) PopDownEntity() (DownEntity, bool) {
}
device.DownEntityList.Remove(element)
if v, ok := element.Value.(DownEntity); ok {
log.Logger.Debug("【TerminalManager】 pop down entity to Sender", map[string]interface{}{"entity": v})
log.Logger.Debug("【TerminalManager】 发送命令 pop down entity to Sender cmd:"+v.DownCommand(), map[string]interface{}{"entity": v})
return v, ok
}
return nil, false
}
func (device *TerminalDevice) AddDownEntity(downEntity interface{}) {
log.Logger.Debug("【TerminalManager】 add down entity to Profile", map[string]interface{}{"entity": downEntity})
v, ok := downEntity.(DownEntity)
var cmd string
if ok {
cmd = v.DownCommand()
}
log.Logger.Debug("【TerminalManager】 添加命令 add down entity to Profile cmd:"+cmd, map[string]interface{}{"entity": downEntity})
device.DownEntityList.PushBack(downEntity)
}
... ...
package service
import (
"fmt"
"github.com/stretchr/testify/assert"
"testing"
)
func TestGbkToUtf8(t *testing.T) {
input := "刘"
out := Utf8ToGbk(input)
t.Log("gbk:" + out)
//"efbfbdeeb8a3"
t.Log(fmt.Sprintf("%v", []byte(out)))
out = GbkToUtf8(out)
t.Log("utf8:" + out)
t.Log("utf8:" + fmt.Sprintf("%v", []byte(out)))
assert.Equal(t, input, out)
}
... ... @@ -137,21 +137,79 @@ func NewQueryBIODATADownEntity(sn string, pin string, t BioDataType) QueryBioDat
}
}
// DeleteUserDownEntity 删除用户-下行命令
type DeleteUserDownEntity struct {
// DeleteDownEntity 删除-下行命令
type DeleteDownEntity struct {
Sn string
Pin string
Table string
}
func (entity DeleteUserDownEntity) DownCommand() string {
func (entity DeleteDownEntity) DownCommand() string {
return fmt.Sprintf("C:%v:DATA DELETE %v PIN=%v", entity.Sn, entity.Table, entity.Pin)
}
func NewClearUserDownEntity(sn string, pin string, t string) DeleteUserDownEntity {
return DeleteUserDownEntity{
func NewDeleteDownEntity(sn string, pin string, t string) DeleteDownEntity {
return DeleteDownEntity{
Sn: sn,
Pin: pin,
Table: t,
}
}
// UpdateUserDownEntity 更新用户-下行命令
type UpdateUserDownEntity struct {
Sn string
Pin string
Name string
Card string
}
func (entity UpdateUserDownEntity) DownCommand() string {
return fmt.Sprintf("C:%v:DATA UPDATE USERINFO PIN=%v\tName=%v\tCard=%v", entity.Sn, entity.Pin, entity.Name, entity.Pin)
}
func NewUpdateUserDownEntity(sn string, pin string, name string) UpdateUserDownEntity {
return UpdateUserDownEntity{
Sn: sn,
Pin: pin,
Name: name,
}
}
// UpdateUserFacePortraitDownEntity 更新用户-人脸识别 -下行命令
type UpdateUserFacePortraitDownEntity struct {
Sn string
Pin string
FacePortrait string
}
func (entity UpdateUserFacePortraitDownEntity) DownCommand() string {
return fmt.Sprintf("C:%v:DATA UPDATE BIODATA Pin=%v\tNo=0\tType=9\tMajorVer=39\tMinorVer=1\tFormat=0\tIndex=0\tValid=1\tDuress=0\tTmp=%v", entity.Sn, entity.Pin, entity.FacePortrait)
}
func NewUpdateUserFacePortraitDownEntity(sn string, pin string, facePortrait string) UpdateUserFacePortraitDownEntity {
return UpdateUserFacePortraitDownEntity{
Sn: sn,
Pin: pin,
FacePortrait: facePortrait,
}
}
// UpdateUserFingerprintPortraitDownEntity 更新用户-指纹 -下行命令
type UpdateUserFingerprintPortraitDownEntity struct {
Sn string
Pin string
FingerprintPortrait string
}
func (entity UpdateUserFingerprintPortraitDownEntity) DownCommand() string {
return fmt.Sprintf("C:%v:DATA UPDATE FINGERTMP PIN=%v\tFID=5\tSize=%v\tValid=1\tTMP=%v", entity.Sn, entity.Pin, len([]byte(entity.FingerprintPortrait)), entity.FingerprintPortrait)
}
func NewUpdateUserFingerprintPortraitDownEntity(sn string, pin string, fingerprintPortrait string) UpdateUserFingerprintPortraitDownEntity {
return UpdateUserFingerprintPortraitDownEntity{
Sn: sn,
Pin: pin,
FingerprintPortrait: fingerprintPortrait,
}
}
... ...
package command
import (
"fmt"
"github.com/beego/beego/v2/core/validation"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain"
"reflect"
"strings"
)
type SyncToAttendanceMachineCommand struct {
OperateInfo *domain.OperateInfo `json:"-"`
// 用户关联的角色
Users []int64 `cname:"用户关联的角色" json:"userIds" valid:"Required"`
}
func (syncToAttendance *SyncToAttendanceMachineCommand) Valid(validation *validation.Validation) {
//validation.SetError("CustomValid", "未实现的自定义认证")
}
func (syncToAttendance *SyncToAttendanceMachineCommand) ValidateCommand() error {
valid := validation.Validation{}
b, err := valid.Valid(syncToAttendance)
if err != nil {
return err
}
if !b {
elem := reflect.TypeOf(syncToAttendance).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
}
... ...
package service
import (
"github.com/gookit/event"
"github.com/linmadan/egglib-go/core/application"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/factory"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/user/command"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/log"
)
func (userService *UserService) SyncToAttendanceMachine(cmd *command.SyncToAttendanceMachineCommand) (interface{}, error) {
if err := cmd.ValidateCommand(); 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()
}()
userRepository, _, _ := factory.FastPgUser(transactionContext, 0)
_, users, err := userRepository.Find(map[string]interface{}{"companyId": cmd.OperateInfo.CompanyId, "inUserIds": cmd.Users})
if err != nil {
return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
}
for i := range users {
_, userBase, err := factory.FastPgUserBase(transactionContext, users[i].UserBaseId)
if err != nil {
return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
}
if err, _ := event.Fire(domain.UserSyncEvent, event.M{"user": users[i], "userBase": userBase}); err != nil {
log.Logger.Error(err.Error())
return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
}
}
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return struct{}{}, nil
}
... ...
... ... @@ -2,6 +2,7 @@ package service
import (
"fmt"
"github.com/gookit/event"
"github.com/linmadan/egglib-go/core/application"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/factory"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/user/command"
... ... @@ -110,6 +111,9 @@ func (userService *UserService) BatchEnable(batchEnableCommand *command.BatchEna
if _, err := userRepository.Save(user); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
if err, _ := event.Fire(domain.UserEnableEvent, map[string]interface{}{"user": user}); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
}
}
... ...
... ... @@ -2,6 +2,7 @@ package domainService
import (
"fmt"
"github.com/gookit/event"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/infrastructure/repository"
... ... @@ -96,6 +97,10 @@ func (ptr *PgCreateUserService) CreateUser(optUser *domain.User, newUser *domain
return nil, err
}
}
// 新建用户事件
if err, _ := event.Fire(domain.UserCreateEvent, event.M{"user": newUser, "userBase": userBase}); err != nil {
return nil, err
}
return user, nil
}
... ...
... ... @@ -2,6 +2,7 @@ package domainService
import (
"fmt"
"github.com/gookit/event"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/infrastructure/repository"
... ... @@ -108,6 +109,10 @@ func (ptr *PgUpdateUserService) UpdateUser(optUser *domain.OperateInfo, user *do
if user, err = userRepository.Save(user); err != nil {
return nil, err
}
// 新建用户事件
if err, _ := event.Fire(domain.UserUpdateEvent, event.M{"user": user, "userBase": userBase}); err != nil {
return nil, err
}
return user, nil
}
... ...
... ... @@ -204,6 +204,9 @@ func (repository *UserRepository) Find(queryOptions map[string]interface{}) (int
}
query.SetWhereByQueryOption("company_id=?", "companyId")
query.SetWhereByQueryOption("organization_id=?", "organizationId")
if v, ok := queryOptions["inUserIds"]; ok && len(v.([]int64)) > 0 {
query.Where(`user_id in (?)`, pg.In(v))
}
if v, ok := queryOptions["inOrgIds"]; ok && len(v.([]int64)) > 0 {
query.Where(`organization_id in (?)`, pg.In(v))
}
... ...
... ... @@ -179,3 +179,12 @@ func (controller *UserController) UpdateAdminUser() {
data, err := userService.UpdateAdminUser(updateUserCommand)
controller.Response(data, err)
}
func (controller *UserController) SyncToAttendanceMachine() {
userService := service.NewUserService(nil)
cmd := &command.SyncToAttendanceMachineCommand{}
Must(controller.Unmarshal(cmd))
cmd.OperateInfo = ParseOperateInfo(controller.BaseController)
data, err := userService.SyncToAttendanceMachine(cmd)
controller.Response(data, err)
}
... ...
... ... @@ -21,6 +21,8 @@ func init() {
web.Router("/user/cooperator", &controllers.UserController{}, "Post:CreateCooperator")
web.Router("/user/cooperator/:userId", &controllers.UserController{}, "Put:UpdateCooperator")
web.Router("/user/sync-to-attendance-machine", &controllers.UserController{}, "Post:SyncToAttendanceMachine")
web.Router("/admin-user/", &controllers.UserController{}, "Post:CreateAdminUser")
web.Router("/admin-user/:userId", &controllers.UserController{}, "Put:UpdateAdminUser")
}
... ...