作者 Administrator

合并分支 'test' 到 'master'

Test



查看合并请求 !9
@@ -11,6 +11,7 @@ require ( @@ -11,6 +11,7 @@ require (
11 github.com/gavv/httpexpect v2.0.0+incompatible 11 github.com/gavv/httpexpect v2.0.0+incompatible
12 github.com/go-pg/pg/v10 v10.9.0 12 github.com/go-pg/pg/v10 v10.9.0
13 github.com/google/go-querystring v1.1.0 // indirect 13 github.com/google/go-querystring v1.1.0 // indirect
  14 + github.com/gookit/event v1.0.6
14 github.com/imkira/go-interpol v1.1.0 // indirect 15 github.com/imkira/go-interpol v1.1.0 // indirect
15 github.com/linmadan/egglib-go v0.0.0-20210313060205-8b5e456b11f7 16 github.com/linmadan/egglib-go v0.0.0-20210313060205-8b5e456b11f7
16 github.com/mattn/go-colorable v0.1.8 // indirect 17 github.com/mattn/go-colorable v0.1.8 // indirect
@@ -19,7 +20,7 @@ require ( @@ -19,7 +20,7 @@ require (
19 github.com/onsi/gomega v1.11.0 20 github.com/onsi/gomega v1.11.0
20 github.com/sergi/go-diff v1.2.0 // indirect 21 github.com/sergi/go-diff v1.2.0 // indirect
21 github.com/smartystreets/goconvey v1.6.4 // indirect 22 github.com/smartystreets/goconvey v1.6.4 // indirect
22 - github.com/stretchr/testify v1.7.0 23 + github.com/stretchr/testify v1.7.1
23 github.com/tal-tech/go-queue v1.0.5 24 github.com/tal-tech/go-queue v1.0.5
24 github.com/tal-tech/go-zero v1.0.27 25 github.com/tal-tech/go-zero v1.0.27
25 github.com/valyala/fasthttp v1.23.0 // indirect 26 github.com/valyala/fasthttp v1.23.0 // indirect
@@ -164,6 +164,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 @@ -164,6 +164,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4
164 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 164 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
165 github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= 165 github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
166 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 166 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
  167 +github.com/gookit/event v1.0.6 h1:/U95T1tBzt9RSSi23pg4VR3B9VWkyM4xv8TXAGi60IQ=
  168 +github.com/gookit/event v1.0.6/go.mod h1:7Udf/q/HQcrK9XE4JZUvbqi46rI1V8r/Pvao2NbPajA=
167 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= 169 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
168 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 170 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
169 github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 171 github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
@@ -348,8 +350,9 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV @@ -348,8 +350,9 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
348 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 350 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
349 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 351 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
350 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 352 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
351 -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=  
352 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 353 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
  354 +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
  355 +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
353 github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= 356 github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
354 github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= 357 github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
355 github.com/tal-tech/go-queue v1.0.5 h1:cd2o0lPjAFJKIXuEbQvsGypUhzz6FLib4FVVAyxsMtY= 358 github.com/tal-tech/go-queue v1.0.5 h1:cd2o0lPjAFJKIXuEbQvsGypUhzz6FLib4FVVAyxsMtY=
  1 +package command
  2 +
  3 +import (
  4 + "fmt"
  5 + "reflect"
  6 + "strings"
  7 +
  8 + "github.com/beego/beego/v2/core/validation"
  9 +)
  10 +
  11 +type TerminalReportCommand struct {
  12 + TerminalType string `json:"terminalType"`
  13 + TerminalId string `json:"terminalId"`
  14 + Command string `json:"command"`
  15 + Content string `json:"content"`
  16 + Table string `json:"table"`
  17 +
  18 + CompanyId int64 `json:"companyId"`
  19 + OrgId int64 `json:"orgId"`
  20 +}
  21 +
  22 +func (terminalReportCommand *TerminalReportCommand) Valid(validation *validation.Validation) {
  23 +
  24 +}
  25 +
  26 +func (terminalReportCommand *TerminalReportCommand) ValidateCommand() error {
  27 + valid := validation.Validation{}
  28 + b, err := valid.Valid(terminalReportCommand)
  29 + if err != nil {
  30 + return err
  31 + }
  32 + if !b {
  33 + elem := reflect.TypeOf(terminalReportCommand).Elem()
  34 + for _, validErr := range valid.Errors {
  35 + field, isExist := elem.FieldByName(validErr.Field)
  36 + if isExist {
  37 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  38 + } else {
  39 + return fmt.Errorf(validErr.Message)
  40 + }
  41 + }
  42 + }
  43 + return nil
  44 +}
  1 +package service
  2 +
  3 +import (
  4 + "bytes"
  5 + "fmt"
  6 + "github.com/beego/beego/v2/adapter/utils"
  7 + "github.com/gookit/event"
  8 + "github.com/linmadan/egglib-go/core/application"
  9 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/factory"
  10 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/terminal/command"
  11 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain"
  12 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/log"
  13 + "io"
  14 +)
  15 +
  16 +var GlobalTerminalManager *TerminalManager
  17 +
  18 +func init() {
  19 + GlobalTerminalManager = NewTerminalManager()
  20 + event.On(domain.UserCreateEvent, event.ListenerFunc(GlobalTerminalManager.SyncUser))
  21 + event.On(domain.UserUpdateEvent, event.ListenerFunc(GlobalTerminalManager.SyncUser))
  22 + event.On(domain.UserEnableEvent, event.ListenerFunc(GlobalTerminalManager.EnableUser))
  23 + event.On(domain.UserSyncEvent, event.ListenerFunc(GlobalTerminalManager.SyncUser))
  24 + event.On(DownEntityEvent, event.ListenerFunc(GlobalTerminalManager.DownEntityEvent))
  25 +}
  26 +
  27 +type TerminalService struct {
  28 +}
  29 +
  30 +func NewTerminalService(options map[string]interface{}) *TerminalService {
  31 + newUserService := &TerminalService{}
  32 + return newUserService
  33 +}
  34 +
  35 +func (svr *TerminalService) TerminalReport(cmd *command.TerminalReportCommand) (interface{}, error) {
  36 + if err := cmd.ValidateCommand(); err != nil {
  37 + return nil, application.ThrowError(application.ARG_ERROR, err.Error())
  38 + }
  39 + transactionContext, err := factory.CreateTransactionContext(nil)
  40 + if err != nil {
  41 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  42 + }
  43 + if err := transactionContext.StartTransaction(); err != nil {
  44 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  45 + }
  46 + defer func() {
  47 + transactionContext.RollbackTransaction()
  48 + }()
  49 + response, err := terminalReport(cmd, transactionContext)
  50 + if err != nil {
  51 + log.Logger.Error(err.Error())
  52 + return nil, err
  53 + }
  54 + if err := transactionContext.CommitTransaction(); err != nil {
  55 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  56 + }
  57 + return response, nil
  58 +}
  59 +
  60 +func terminalReport(cmd *command.TerminalReportCommand, transactionContext application.TransactionContext) (interface{}, error) {
  61 + var (
  62 + response string = "OK"
  63 + )
  64 + log.Logger.Debug(fmt.Sprintf("【TerminalManager】 收到上行命令 command:%v table:%v content:%v", cmd.Command, cmd.Table, cmd.Content))
  65 + switch cmd.Command {
  66 + case "getrequest":
  67 + device, ok := GlobalTerminalManager.GetDevice(cmd.TerminalId, cmd.CompanyId)
  68 + if !ok || device == nil {
  69 + break
  70 + }
  71 + if downEntity, ok := device.PopDownEntity(); ok && downEntity != nil {
  72 + response = downEntity.DownCommand()
  73 + }
  74 + break
  75 + case "cdata":
  76 + parseEntities := ParseData(cmd)
  77 + var (
  78 + down DownEntity
  79 + err error
  80 + handler Handler = ZKClockHandler{TransactionContext: transactionContext}
  81 + )
  82 + for _, entity := range parseEntities {
  83 + switch TableType(cmd.Table) {
  84 + case AttLOG:
  85 + down, err = handler.Attendance(entity.(AttLOGUpEntity))
  86 + case BIODATA:
  87 + down, err = handler.BioData(entity.(BIODATAEntity))
  88 + case OPERLOG:
  89 + //if v, ok := entity.(USEREntity); ok {
  90 + // down, err = handler.ReportUser(v)
  91 + //}
  92 + if v, ok := entity.(BIODATAEntity); ok {
  93 + down, err = handler.BioData(v)
  94 + }
  95 + }
  96 + if err != nil {
  97 + log.Logger.Error(err.Error())
  98 + continue
  99 + }
  100 + if down != nil {
  101 + response = down.DownCommand()
  102 + }
  103 + break
  104 + }
  105 + case "devicecmd":
  106 + }
  107 +
  108 + return map[string]interface{}{
  109 + "response": response,
  110 + }, nil
  111 +}
  112 +
  113 +func ParseData(cmd *command.TerminalReportCommand) []interface{} {
  114 + result := make([]interface{}, 0)
  115 + buf := bytes.NewBufferString(cmd.Content)
  116 + for {
  117 + line, err := buf.ReadBytes('\n')
  118 + if err == io.EOF {
  119 + break
  120 + }
  121 + if err != nil {
  122 + log.Logger.Error(err.Error())
  123 + break
  124 + }
  125 +
  126 + switch TableType(cmd.Table) {
  127 + case AttLOG:
  128 + columns := bytes.Split(line, ([]byte)("\t"))
  129 + if len(columns) != 11 { //10 + 1 空格
  130 + continue
  131 + }
  132 + result = append(result, AttLOGUpEntity{
  133 + Pin: string(columns[0]),
  134 + CompanyId: cmd.CompanyId,
  135 + OrgId: cmd.OrgId,
  136 + })
  137 + case BIODATA:
  138 + /*BIODATA Pin=3\tNo=0\tIndex=0\tValid=1\tDuress=0\tType=9\tMajorVer=39\tMinorVer=1\tFormat=
  139 + 0\tTmp=apUBEBABQo4JACcBAWiOADA7dP4pU9F31Uxom7NAGjM4eO/8X5Ee4uahkIT11c3188+VguMsd3oCO0O29efRyxofdLiohI4QL7woK3U*/
  140 + columns := readLineToMap(line, "BIODATA")
  141 + result = append(result, BIODATAEntity{
  142 + Pin: columns["Pin"],
  143 + No: columns["No"],
  144 + Index: columns["Index"],
  145 + Duress: columns["Duress"],
  146 + Type: columns["Type"],
  147 + MinorVer: columns["MinorVer"],
  148 + MajorVer: columns["MajorVer"],
  149 + Format: columns["Format"],
  150 + Tmp: columns["Tmp"],
  151 + CompanyId: cmd.CompanyId,
  152 + OrgId: cmd.OrgId,
  153 + })
  154 + case OPERLOG:
  155 + if bytes.HasPrefix(line, []byte("FP")) {
  156 + /*
  157 + FP PIN=3 FID=6 Size=1336 Valid=1 TMP=SqtTUzIxAAAD6O8ECA
  158 + */
  159 + columns := readLineToMap(line, "FP")
  160 + result = append(result, BIODATAEntity{
  161 + Pin: columns["PIN"],
  162 + Type: fmt.Sprintf("%v", BioDataType1),
  163 + Tmp: columns["TMP"],
  164 + CompanyId: cmd.CompanyId,
  165 + OrgId: cmd.OrgId,
  166 + })
  167 + } else if bytes.HasPrefix(line, []byte("USER")) {
  168 + /*
  169 + USER PIN=3 Name=杨xx Pri=14 Passwd= Card=3731588478 Grp=1 TZ=0000000100000000 Verify=-1 ViceCard= StartDatetime=0 EndDatetime=0
  170 + */
  171 + columns := readLineToMap(line, "USER")
  172 + name := columns["Name"] //GbkToUtf8(columns["Name"])
  173 + result = append(result, USEREntity{
  174 + OPERLOGType: "USER",
  175 + Pin: columns["PIN"],
  176 + Name: name,
  177 + CompanyId: cmd.CompanyId,
  178 + OrgId: cmd.OrgId,
  179 + })
  180 + }
  181 + }
  182 + }
  183 + return result
  184 +}
  185 +
  186 +func readLineToMap(line []byte, prefix string) map[string]string {
  187 + var result = make(map[string]string)
  188 + line = bytes.TrimLeft(line, prefix)
  189 + line = bytes.TrimSpace(line)
  190 + columns := bytes.Fields(line)
  191 + for i := range columns {
  192 + kv := bytes.SplitN(columns[i], []byte("="), 2)
  193 + if len(kv) < 2 {
  194 + continue
  195 + }
  196 + //if string(kv[0]) == "Name" {
  197 + // log.Logger.Debug(fmt.Sprintf("%x", kv[1]))
  198 + // log.Logger.Debug(fmt.Sprintf("%v", kv[1]))
  199 + // log.Logger.Debug(fmt.Sprintf("%s", string(kv[1])))
  200 + //}
  201 + result[string(kv[0])] = string(kv[1])
  202 + }
  203 + return result
  204 +}
  205 +
  206 +type Handler interface {
  207 + Attendance(entity AttLOGUpEntity) (DownEntity, error)
  208 + BioData(entity BIODATAEntity) (DownEntity, error)
  209 + ReportUser(entity USEREntity) (DownEntity, error)
  210 +}
  211 +
  212 +type ZKClockHandler struct {
  213 + TransactionContext application.TransactionContext
  214 +}
  215 +
  216 +func (handler ZKClockHandler) Attendance(entity AttLOGUpEntity) (DownEntity, error) {
  217 + var (
  218 + userRepository, _, _ = factory.FastPgUser(handler.TransactionContext, 0)
  219 + userBaseRepository, _, _ = factory.FastPgUserBase(handler.TransactionContext, 0)
  220 + user *domain.User
  221 + userBase *domain.UserBase
  222 + err error
  223 + )
  224 + if user, err = userRepository.FindOne(map[string]interface{}{"companyId": entity.CompanyId, "orgId": entity.OrgId, "icCardNumber": entity.Pin}); err != nil {
  225 + return nil, err
  226 + }
  227 + if userBase, err = userBaseRepository.FindOne(map[string]interface{}{"userBaseId": user.UserBaseId}); err != nil {
  228 + return nil, err
  229 + }
  230 + var sendQuery bool
  231 + // 请求 人脸识别-用户画像
  232 + if len(userBase.UserInfo.FacePortrait) == 0 {
  233 + sendQuery = true
  234 + //event.Fire(DownEntityEvent, map[string]interface{}{"entity": NewQueryBIODATADownEntity(generateSn(), entity.Pin, BioDataType2)})
  235 + }
  236 + // 请求 人脸识别-指纹
  237 + if len(userBase.UserInfo.FingerprintPortrait) == 0 {
  238 + // sendQuery = true
  239 + }
  240 + if sendQuery {
  241 + event.Fire(DownEntityEvent, map[string]interface{}{"entity": NewQueryUserInfoDownEntity(generateSn(), entity.Pin, entity.CompanyId)})
  242 + }
  243 + return nil, nil
  244 +}
  245 +
  246 +func (handler ZKClockHandler) BioData(entity BIODATAEntity) (DownEntity, error) {
  247 + var (
  248 + userRepository, _, _ = factory.FastPgUser(handler.TransactionContext, 0)
  249 + userBaseRepository, _, _ = factory.FastPgUserBase(handler.TransactionContext, 0)
  250 + user *domain.User
  251 + userBase *domain.UserBase
  252 + err error
  253 + updateFlag bool
  254 + )
  255 + if user, err = userRepository.FindOne(map[string]interface{}{"companyId": entity.CompanyId, "orgId": entity.OrgId, "icCardNumber": entity.Pin}); err != nil {
  256 + return nil, err
  257 + }
  258 + if userBase, err = userBaseRepository.FindOne(map[string]interface{}{"userBaseId": user.UserBaseId}); err != nil {
  259 + return nil, err
  260 + }
  261 + // 请求 人脸识别-用户画像
  262 + if len(entity.Tmp) > 0 && entity.Type == "9" {
  263 + userBase.UserInfo.FacePortrait = entity.Tmp
  264 + updateFlag = true
  265 + if len(GlobalTerminalManager.TerminalDeviceList) >= 1 { //TODO:后期移除掉,多台设备时才进行广播
  266 + event.Fire(DownEntityEvent, map[string]interface{}{"entity": NewUpdateUserFacePortraitDownEntity(generateSn(), entity.Pin, entity.Tmp, entity.CompanyId)})
  267 + }
  268 + }
  269 + // 请求 人脸识别-指纹
  270 + if len(entity.Tmp) > 0 && entity.Type == "1" {
  271 + userBase.UserInfo.FingerprintPortrait = entity.Tmp
  272 + updateFlag = true
  273 + if len(GlobalTerminalManager.TerminalDeviceList) >= 1 {
  274 + event.Fire(DownEntityEvent, map[string]interface{}{"entity": NewUpdateUserFingerprintPortraitDownEntity(generateSn(), entity.Pin, entity.Tmp, entity.CompanyId)})
  275 + }
  276 + }
  277 + if updateFlag {
  278 + _, err = userBaseRepository.Save(userBase)
  279 + if err != nil {
  280 + log.Logger.Error(err.Error())
  281 + }
  282 + }
  283 + return nil, err
  284 +}
  285 +
  286 +func (handler ZKClockHandler) ReportUser(entity USEREntity) (DownEntity, error) {
  287 + var (
  288 + userRepository, _, _ = factory.FastPgUser(handler.TransactionContext, 0)
  289 + userBaseRepository, _, _ = factory.FastPgUserBase(handler.TransactionContext, 0)
  290 + user *domain.User
  291 + userBase *domain.UserBase
  292 + err error
  293 + updateFlag bool
  294 + )
  295 + if user, err = userRepository.FindOne(map[string]interface{}{"companyId": entity.CompanyId, "orgId": entity.OrgId, "icCardNumber": entity.Pin}); err != nil {
  296 + return nil, err
  297 + }
  298 + if userBase, err = userBaseRepository.FindOne(map[string]interface{}{"userBaseId": user.UserBaseId}); err != nil {
  299 + return nil, err
  300 + }
  301 + // 请求 人脸识别-用户画像
  302 + //if len(entity.Pin) > 0 && userBase.UserInfo.Pin != entity.Pin {
  303 + // updateFlag = true
  304 + // userBase.UserInfo.Pin = entity.Pin
  305 + //}
  306 + if updateFlag {
  307 + _, err = userBaseRepository.Save(userBase)
  308 + }
  309 + return nil, err
  310 +}
  311 +
  312 +func generateSn() string {
  313 + return string(utils.RandomCreateBytes(10))
  314 +}
  1 +package service
  2 +
  3 +import (
  4 + "container/list"
  5 + "fmt"
  6 + "github.com/gookit/event"
  7 + "github.com/linmadan/egglib-go/utils/json"
  8 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain"
  9 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/log"
  10 + "sync"
  11 +)
  12 +
  13 +var (
  14 + DownEntityEvent = "down_entity"
  15 +)
  16 +
  17 +type TerminalManager struct {
  18 + TerminalDeviceList []*TerminalDevice
  19 + TerminalDevices sync.Map
  20 +}
  21 +
  22 +func NewTerminalManager() *TerminalManager {
  23 + return &TerminalManager{
  24 + TerminalDeviceList: make([]*TerminalDevice, 0),
  25 + TerminalDevices: sync.Map{},
  26 + }
  27 +}
  28 +
  29 +func (term *TerminalManager) GetDevice(terminalId string, params ...interface{}) (*TerminalDevice, bool) {
  30 + device, ok := term.TerminalDevices.Load(terminalId)
  31 + if !ok {
  32 + var companyId int64
  33 + if len(params) > 0 {
  34 + companyId = params[0].(int64)
  35 + }
  36 + device := NewTerminalDevice(terminalId, companyId)
  37 + term.TerminalDevices.Store(terminalId, device)
  38 + log.Logger.Debug(fmt.Sprintf("【TerminalManager】 终端上线 add new device:%v", terminalId), map[string]interface{}{"device": device})
  39 + term.TerminalDeviceList = append(term.TerminalDeviceList, device)
  40 + return nil, false
  41 + }
  42 + if v, ok := device.(*TerminalDevice); ok {
  43 + return v, ok
  44 + }
  45 + return nil, false
  46 +}
  47 +func (term *TerminalManager) PopDownEntityByDevice(sn string) (DownEntity, bool) {
  48 + device, ok := term.GetDevice(sn)
  49 + if !ok {
  50 + return nil, false
  51 + }
  52 + return device.PopDownEntity()
  53 +}
  54 +
  55 +func (term *TerminalManager) AddDownEntityByDevice(sn string, entity interface{}) bool {
  56 + device, ok := term.GetDevice(sn)
  57 + if !ok {
  58 + return false
  59 + }
  60 + device.AddDownEntity(entity)
  61 + return true
  62 +}
  63 +
  64 +func (term *TerminalManager) BroadcastDownEntity(downEntity interface{}) {
  65 + if len(term.TerminalDeviceList) == 0 {
  66 + log.Logger.Debug("【TerminalManager】 当前在线终端:0 广播命令退出")
  67 + return
  68 + }
  69 + for i := range term.TerminalDeviceList {
  70 + term.TerminalDeviceList[i].AddDownEntity(downEntity)
  71 + }
  72 +}
  73 +
  74 +// Listen Event
  75 +
  76 +func (term *TerminalManager) DownEntityEvent(e event.Event) error {
  77 + entity := e.Get("entity")
  78 + if entity != nil {
  79 + term.BroadcastDownEntity(entity)
  80 + }
  81 + return nil
  82 +}
  83 +
  84 +func (term *TerminalManager) SyncUser(e event.Event) error {
  85 + user := e.Get("user")
  86 + userBase := e.Get("userBase")
  87 + if user != nil && userBase != nil {
  88 + assertUser := user.(*domain.User)
  89 + assertUserBase := userBase.(*domain.UserBase)
  90 + if len(assertUser.Ext.IcCardNumber) == 0 {
  91 + log.Logger.Debug("【TerminalManager】 当前用户ICCard未设置 不进行同步", map[string]interface{}{"user": user})
  92 + return nil
  93 + }
  94 + term.BroadcastDownEntity(NewUpdateUserDownEntity(generateSn(), assertUser.Ext.IcCardNumber, assertUserBase.UserInfo.UserName))
  95 + if len(assertUserBase.UserInfo.FacePortrait) > 0 {
  96 + term.BroadcastDownEntity(NewUpdateUserFacePortraitDownEntity(generateSn(), assertUser.Ext.IcCardNumber, assertUserBase.UserInfo.FacePortrait, assertUser.CompanyId))
  97 + }
  98 + if len(assertUserBase.UserInfo.FingerprintPortrait) > 0 {
  99 + term.BroadcastDownEntity(NewUpdateUserFingerprintPortraitDownEntity(generateSn(), assertUser.Ext.IcCardNumber, assertUserBase.UserInfo.FingerprintPortrait, assertUser.CompanyId))
  100 + }
  101 + }
  102 + return nil
  103 +}
  104 +
  105 +func (term *TerminalManager) EnableUser(e event.Event) error {
  106 + user := e.Get("user")
  107 + if user != nil {
  108 + assertUser := user.(*domain.User)
  109 + if assertUser.EnableStatus == int(domain.UserStatusEnable) {
  110 + term.SyncUser(e)
  111 + } else if assertUser.EnableStatus == int(domain.UserStatusDisable) {
  112 + term.BroadcastDownEntity(NewDeleteDownEntity(generateSn(), assertUser.Ext.IcCardNumber, string(UserInfo), assertUser.CompanyId))
  113 + }
  114 + }
  115 + return nil
  116 +}
  117 +
  118 +func (term *TerminalManager) CreateUser(e event.Event) error {
  119 + return term.SyncUser(e)
  120 +}
  121 +
  122 +func (term *TerminalManager) UpdateUser(e event.Event) error {
  123 + return term.EnableUser(e)
  124 +}
  125 +
  126 +type TerminalDevice struct {
  127 + Id string
  128 + CompanyId int64
  129 + DownEntityList *list.List
  130 +}
  131 +
  132 +func NewTerminalDevice(terminalId string, companyId int64) *TerminalDevice {
  133 + return &TerminalDevice{
  134 + Id: terminalId,
  135 + CompanyId: companyId,
  136 + DownEntityList: list.New(),
  137 + }
  138 +}
  139 +
  140 +func (device *TerminalDevice) PopDownEntity() (DownEntity, bool) {
  141 + element := device.DownEntityList.Front()
  142 + if element == nil {
  143 + return nil, false
  144 + }
  145 + device.DownEntityList.Remove(element)
  146 + if v, ok := element.Value.(DownEntity); ok {
  147 + log.Logger.Debug("【TerminalManager】 发送命令 pop down entity to Sender cmd:"+v.DownCommand(), map[string]interface{}{"entity": v})
  148 + return v, ok
  149 + }
  150 + return nil, false
  151 +}
  152 +
  153 +func (device *TerminalDevice) AddDownEntity(downEntity interface{}) {
  154 + v, ok := downEntity.(DownEntity)
  155 + var cmd string
  156 + if !ok {
  157 + return
  158 + }
  159 + cmd = v.DownCommand()
  160 + options := objectJsonToMap(downEntity)
  161 + if v, ok := options["CompanyId"]; ok {
  162 + companyId, ok := v.(int64)
  163 + if ok && device.CompanyId != companyId {
  164 + log.Logger.Debug("【TerminalManager】 丢弃命令(公司不匹配) cmd:"+cmd, map[string]interface{}{"entity": downEntity, "device": device})
  165 + return
  166 + }
  167 + }
  168 + log.Logger.Debug("【TerminalManager】 添加命令 add down entity to Profile cmd:"+cmd, map[string]interface{}{"entity": downEntity})
  169 + device.DownEntityList.PushBack(downEntity)
  170 +}
  171 +
  172 +func objectJsonToMap(v interface{}) map[string]interface{} {
  173 + result := make(map[string]interface{})
  174 + data := json.MarshalToString(v)
  175 + json.UnmarshalFromString(data, &result)
  176 + return result
  177 +}
  1 +package service
  2 +
  3 +import "fmt"
  4 +
  5 +type TableType string
  6 +
  7 +var (
  8 + AttLOG TableType = "ATTLOG" // AttLOG 打卡记录
  9 + UserInfo TableType = "USERINFO" // 用户信息
  10 + FingerTMP TableType = "FINGERTMP" //指纹
  11 + Face TableType = "FACE" //脸部
  12 + OPERLOG TableType = "OPERLOG" //操作记录
  13 + BIODATA TableType = "BIODATA" //一体化数据 (人脸识别等)
  14 +)
  15 +
  16 +type BioDataType int
  17 +
  18 +var (
  19 + BioDataType0 BioDataType = 0 //通用
  20 + BioDataType1 BioDataType = 1 //指纹
  21 + BioDataType2 BioDataType = 0 //面部
  22 + BioDataType3 BioDataType = 3 //声纹
  23 + BioDataType4 BioDataType = 4 //虹膜
  24 + BioDataType5 BioDataType = 5 //视网膜
  25 + BioDataType6 BioDataType = 6 //掌纹
  26 + BioDataType7 BioDataType = 7 //指静脉
  27 + BioDataType8 BioDataType = 8 //手掌
  28 + BioDataType9 BioDataType = 9 //可见光面部
  29 +)
  30 +
  31 +// AttLOGUpEntity 打卡记录实体 - 上行命令
  32 +type AttLOGUpEntity struct {
  33 + Pin string
  34 + Time string
  35 + Status string
  36 + Verify string
  37 + Workcode string
  38 + Reserved1 string
  39 + Reserved2 string
  40 + MaskFlag string
  41 + Temperature string
  42 + ConvTemperature string
  43 +
  44 + CompanyId int64 `json:"companyId"`
  45 + OrgId int64 `json:"orgId"`
  46 +}
  47 +
  48 +// FPEntity 指纹 - 上行命令 OPERLOG
  49 +type FPEntity struct {
  50 + OPERLOGType string //"FP" "USER" "BIODATA"
  51 + Pin string
  52 + TFID string
  53 + TSize string
  54 + TValid string
  55 + TTMP string
  56 +
  57 + CompanyId int64 `json:"companyId"`
  58 + OrgId int64 `json:"orgId"`
  59 +}
  60 +
  61 +// USEREntity 用户 - 上行命令 OPERLOG
  62 +type USEREntity struct {
  63 + OPERLOGType string //"FP" "USER" "BIODATA"
  64 + Pin string `json:"pin"`
  65 + Name string `json:"Name"`
  66 + Pri string `json:"Pri"`
  67 + Passwd string `json:"Passwd"`
  68 + Grp string `json:"Grp"`
  69 + TZ string `json:"TZ"`
  70 + Verify string `json:"Verify"`
  71 + ViceCard string `json:"ViceCard"`
  72 + StartDatetime string `json:"StartDatetime"`
  73 + EndDatetime string `json:"EndDatetime"`
  74 +
  75 + CompanyId int64 `json:"companyId"`
  76 + OrgId int64 `json:"orgId"`
  77 +}
  78 +
  79 +// BIODATAEntity 一体化数据实体 - 上行命令 BIODATA
  80 +type BIODATAEntity struct {
  81 + Pin string `json:"pin"`
  82 + No string `json:"tNo"`
  83 + Index string `json:"tIndex"`
  84 + Valid string `json:"tValid"`
  85 + Duress string `json:"tDuress"`
  86 + Type string `json:"tType"`
  87 + MajorVer string `json:"tMajorVer"`
  88 + MinorVer string `json:"tMinorVer"`
  89 + Format string `json:"tFormat"`
  90 + Tmp string `json:"Tmp"`
  91 +
  92 + CompanyId int64 `json:"companyId"`
  93 + OrgId int64 `json:"orgId"`
  94 +}
  95 +
  96 +type DownEntity interface {
  97 + DownCommand() string
  98 +}
  99 +
  100 +func QueryUserInfoRequest(sn string, entity AttLOGUpEntity) string {
  101 + return fmt.Sprintf("C:%v:DATA QUERY USERINFO PIN=%v", sn, entity.Pin)
  102 +}
  103 +
  104 +// QueryUserInfoDownEntity 查询用户信息-下行命令
  105 +type QueryUserInfoDownEntity struct {
  106 + Sn string
  107 + Pin string
  108 +
  109 + CompanyId int64
  110 +}
  111 +
  112 +func (entity QueryUserInfoDownEntity) DownCommand() string {
  113 + return fmt.Sprintf("C:%v:DATA QUERY USERINFO PIN=%v", entity.Sn, entity.Pin)
  114 +}
  115 +
  116 +func NewQueryUserInfoDownEntity(sn string, pin string, companyId int64) QueryUserInfoDownEntity {
  117 + return QueryUserInfoDownEntity{
  118 + Sn: sn,
  119 + Pin: pin,
  120 + CompanyId: companyId,
  121 + }
  122 +}
  123 +
  124 +// QueryBioDataDownEntity 查询一体化-下行命令
  125 +type QueryBioDataDownEntity struct {
  126 + Sn string
  127 + Pin string
  128 + Type BioDataType
  129 +
  130 + CompanyId int64
  131 +}
  132 +
  133 +func (entity QueryBioDataDownEntity) DownCommand() string {
  134 + return fmt.Sprintf("C:%v:DATA QUERY BIODATA Type=%v PIN=%v", entity.Sn, entity.Type, entity.Pin)
  135 +}
  136 +
  137 +func NewQueryBIODATADownEntity(sn string, pin string, t BioDataType) QueryBioDataDownEntity {
  138 + return QueryBioDataDownEntity{
  139 + Sn: sn,
  140 + Pin: pin,
  141 + Type: t,
  142 + }
  143 +}
  144 +
  145 +// DeleteDownEntity 删除-下行命令
  146 +type DeleteDownEntity struct {
  147 + Sn string
  148 + Pin string
  149 + Table string
  150 +
  151 + CompanyId int64
  152 +}
  153 +
  154 +func (entity DeleteDownEntity) DownCommand() string {
  155 + return fmt.Sprintf("C:%v:DATA DELETE %v PIN=%v", entity.Sn, entity.Table, entity.Pin)
  156 +}
  157 +
  158 +func NewDeleteDownEntity(sn string, pin string, t string, companyId int64) DeleteDownEntity {
  159 + return DeleteDownEntity{
  160 + Sn: sn,
  161 + Pin: pin,
  162 + Table: t,
  163 + }
  164 +}
  165 +
  166 +// UpdateUserDownEntity 更新用户-下行命令
  167 +type UpdateUserDownEntity struct {
  168 + Sn string
  169 + Pin string
  170 + Name string
  171 + Card string
  172 +
  173 + CompanyId int64
  174 +}
  175 +
  176 +func (entity UpdateUserDownEntity) DownCommand() string {
  177 + return fmt.Sprintf("C:%v:DATA UPDATE USERINFO PIN=%v\tName=%v\tCard=%v", entity.Sn, entity.Pin, entity.Name, entity.Pin)
  178 +}
  179 +
  180 +func NewUpdateUserDownEntity(sn string, pin string, name string) UpdateUserDownEntity {
  181 + return UpdateUserDownEntity{
  182 + Sn: sn,
  183 + Pin: pin,
  184 + Name: name,
  185 + }
  186 +}
  187 +
  188 +// UpdateUserFacePortraitDownEntity 更新用户-人脸识别 -下行命令
  189 +type UpdateUserFacePortraitDownEntity struct {
  190 + Sn string
  191 + Pin string
  192 + FacePortrait string
  193 +
  194 + CompanyId int64
  195 +}
  196 +
  197 +func (entity UpdateUserFacePortraitDownEntity) DownCommand() string {
  198 + 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)
  199 +}
  200 +
  201 +func NewUpdateUserFacePortraitDownEntity(sn string, pin string, facePortrait string, companyId int64) UpdateUserFacePortraitDownEntity {
  202 + return UpdateUserFacePortraitDownEntity{
  203 + Sn: sn,
  204 + Pin: pin,
  205 + FacePortrait: facePortrait,
  206 + }
  207 +}
  208 +
  209 +// UpdateUserFingerprintPortraitDownEntity 更新用户-指纹 -下行命令
  210 +type UpdateUserFingerprintPortraitDownEntity struct {
  211 + Sn string
  212 + Pin string
  213 + FingerprintPortrait string
  214 +
  215 + CompanyId int64
  216 +}
  217 +
  218 +func (entity UpdateUserFingerprintPortraitDownEntity) DownCommand() string {
  219 + 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)
  220 +}
  221 +
  222 +func NewUpdateUserFingerprintPortraitDownEntity(sn string, pin string, fingerprintPortrait string, companyId int64) UpdateUserFingerprintPortraitDownEntity {
  223 + return UpdateUserFingerprintPortraitDownEntity{
  224 + Sn: sn,
  225 + Pin: pin,
  226 + FingerprintPortrait: fingerprintPortrait,
  227 + }
  228 +}
  1 +package command
  2 +
  3 +import (
  4 + "fmt"
  5 + "github.com/beego/beego/v2/core/validation"
  6 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain"
  7 + "reflect"
  8 + "strings"
  9 +)
  10 +
  11 +type SyncToAttendanceMachineCommand struct {
  12 + OperateInfo *domain.OperateInfo `json:"-"`
  13 + // 用户关联的角色
  14 + Users []string `cname:"用户关联的角色" json:"userIds"`
  15 +}
  16 +
  17 +func (syncToAttendance *SyncToAttendanceMachineCommand) Valid(validation *validation.Validation) {
  18 + //validation.SetError("CustomValid", "未实现的自定义认证")
  19 +}
  20 +
  21 +func (syncToAttendance *SyncToAttendanceMachineCommand) ValidateCommand() error {
  22 + valid := validation.Validation{}
  23 + b, err := valid.Valid(syncToAttendance)
  24 + if err != nil {
  25 + return err
  26 + }
  27 + if !b {
  28 + elem := reflect.TypeOf(syncToAttendance).Elem()
  29 + for _, validErr := range valid.Errors {
  30 + field, isExist := elem.FieldByName(validErr.Field)
  31 + if isExist {
  32 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  33 + } else {
  34 + return fmt.Errorf(validErr.Message)
  35 + }
  36 + }
  37 + }
  38 + return nil
  39 +}
  1 +package service
  2 +
  3 +import (
  4 + "github.com/gookit/event"
  5 + "github.com/linmadan/egglib-go/core/application"
  6 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/factory"
  7 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/user/command"
  8 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain"
  9 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/infrastructure/utils"
  10 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/log"
  11 +)
  12 +
  13 +func (userService *UserService) SyncToAttendanceMachine(cmd *command.SyncToAttendanceMachineCommand) (interface{}, error) {
  14 + if err := cmd.ValidateCommand(); err != nil {
  15 + return nil, application.ThrowError(application.ARG_ERROR, err.Error())
  16 + }
  17 + transactionContext, err := factory.CreateTransactionContext(nil)
  18 + if err != nil {
  19 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  20 + }
  21 + if err := transactionContext.StartTransaction(); err != nil {
  22 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  23 + }
  24 + defer func() {
  25 + transactionContext.RollbackTransaction()
  26 + }()
  27 + userRepository, _, _ := factory.FastPgUser(transactionContext, 0)
  28 + //orgRepository, _, _ := factory.FastPgOrg(transactionContext, 0)
  29 + var users []*domain.User
  30 + // 指定用户进行同步
  31 + if len(cmd.Users) > 0 {
  32 + _, users, err = userRepository.Find(map[string]interface{}{"companyId": cmd.OperateInfo.CompanyId, "inUserIds": utils.ToArrayInt64(cmd.Users)})
  33 + if err != nil {
  34 + return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
  35 + }
  36 + } else {
  37 + //org, _ := orgRepository.FindOne(map[string]interface{}{"companyId": cmd.OperateInfo.CompanyId, "orgName": "制造中心"})
  38 + //if org == nil {
  39 + // return nil, nil
  40 + //}
  41 + _, users, err = userRepository.Find(map[string]interface{}{"companyId": cmd.OperateInfo.CompanyId, "icCardNumberNotEqual": ""})
  42 + if err != nil {
  43 + return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
  44 + }
  45 + }
  46 +
  47 + for i := range users {
  48 + _, userBase, err := factory.FastPgUserBase(transactionContext, users[i].UserBaseId)
  49 + if err != nil {
  50 + return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
  51 + }
  52 + if err, _ := event.Fire(domain.UserSyncEvent, event.M{"user": users[i], "userBase": userBase}); err != nil {
  53 + log.Logger.Error(err.Error())
  54 + return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
  55 + }
  56 + }
  57 +
  58 + if err := transactionContext.CommitTransaction(); err != nil {
  59 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  60 + }
  61 + return struct{}{}, nil
  62 +}
@@ -2,6 +2,7 @@ package service @@ -2,6 +2,7 @@ package service
2 2
3 import ( 3 import (
4 "fmt" 4 "fmt"
  5 + "github.com/gookit/event"
5 "github.com/linmadan/egglib-go/core/application" 6 "github.com/linmadan/egglib-go/core/application"
6 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/factory" 7 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/factory"
7 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/user/command" 8 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/user/command"
@@ -101,15 +102,25 @@ func (userService *UserService) BatchEnable(batchEnableCommand *command.BatchEna @@ -101,15 +102,25 @@ func (userService *UserService) BatchEnable(batchEnableCommand *command.BatchEna
101 } 102 }
102 103
103 for i := 0; i < len(batchEnableCommand.UserIds); i++ { 104 for i := 0; i < len(batchEnableCommand.UserIds); i++ {
104 - if user, err := userRepository.FindOne(map[string]interface{}{"userId": batchEnableCommand.UserIds[i]}); err != nil { 105 + var (
  106 + user *domain.User
  107 + userBase *domain.UserBase
  108 + )
  109 + user, err = userRepository.FindOne(map[string]interface{}{"userId": batchEnableCommand.UserIds[i]})
  110 + if err != nil {
  111 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  112 + }
  113 + if err := user.SetEnableStatus(batchEnableCommand.EnableStatus); err != nil {
  114 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  115 + }
  116 + if _, err := userRepository.Save(user); err != nil {
  117 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  118 + }
  119 + if _, userBase, err = factory.FastPgUserBase(transactionContext, user.UserBaseId); err != nil {
  120 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  121 + }
  122 + if err, _ := event.Fire(domain.UserEnableEvent, map[string]interface{}{"user": user, "userBase": userBase}); err != nil {
105 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 123 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
106 - } else {  
107 - if err := user.SetEnableStatus(batchEnableCommand.EnableStatus); err != nil {  
108 - return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())  
109 - }  
110 - if _, err := userRepository.Save(user); err != nil {  
111 - return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())  
112 - }  
113 } 124 }
114 } 125 }
115 126
@@ -26,6 +26,14 @@ const ( @@ -26,6 +26,14 @@ const (
26 UserStatusDestroy UserStatus = 3 26 UserStatusDestroy UserStatus = 3
27 ) 27 )
28 28
  29 +const (
  30 + UserUpdateEvent = "user_update"
  31 + UserDeleteEvent = "user_delete"
  32 + UserCreateEvent = "user_create"
  33 + UserEnableEvent = "user_enable" //禁用启用事件
  34 + UserSyncEvent = "user_sync" // 用户同步
  35 +)
  36 +
29 // 用户 37 // 用户
30 type User struct { 38 type User struct {
31 // 用户Id 用户唯一标识 39 // 用户Id 用户唯一标识
@@ -13,9 +13,16 @@ type UserInfo struct { @@ -13,9 +13,16 @@ type UserInfo struct {
13 13
14 // 员工类型 1:固定 2:派遣 3.临时 14 // 员工类型 1:固定 2:派遣 3.临时
15 EmployeeType int `json:"employeeType,omitempty"` 15 EmployeeType int `json:"employeeType,omitempty"`
16 - // IC卡号 16 + // IC卡号 = Pin
17 IcCardNumber string `json:"icCardNumber,omitempty"` 17 IcCardNumber string `json:"icCardNumber,omitempty"`
18 18
  19 + // 面部识别
  20 + FacePortrait string `json:"facePortrait,omitempty"`
  21 + // 指纹识别
  22 + FingerprintPortrait string `json:"fingerprintPortrait,omitempty"`
  23 + // 打卡机标识
  24 + // Pin string `json:"pin"`
  25 +
19 Referer string `json:"-"` 26 Referer string `json:"-"`
20 // 部门 27 // 部门
21 DepartmentName string `cname:"部门" json:"-"` 28 DepartmentName string `cname:"部门" json:"-"`
@@ -2,6 +2,7 @@ package domainService @@ -2,6 +2,7 @@ package domainService
2 2
3 import ( 3 import (
4 "fmt" 4 "fmt"
  5 + "github.com/gookit/event"
5 pgTransaction "github.com/linmadan/egglib-go/transaction/pg" 6 pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
6 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain" 7 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain"
7 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/infrastructure/repository" 8 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/infrastructure/repository"
@@ -96,6 +97,10 @@ func (ptr *PgCreateUserService) CreateUser(optUser *domain.User, newUser *domain @@ -96,6 +97,10 @@ func (ptr *PgCreateUserService) CreateUser(optUser *domain.User, newUser *domain
96 return nil, err 97 return nil, err
97 } 98 }
98 } 99 }
  100 + // 新建用户事件
  101 + if err, _ := event.Fire(domain.UserCreateEvent, event.M{"user": newUser, "userBase": userBase}); err != nil {
  102 + return nil, err
  103 + }
99 return user, nil 104 return user, nil
100 } 105 }
101 106
@@ -2,6 +2,7 @@ package domainService @@ -2,6 +2,7 @@ package domainService
2 2
3 import ( 3 import (
4 "fmt" 4 "fmt"
  5 + "github.com/gookit/event"
5 pgTransaction "github.com/linmadan/egglib-go/transaction/pg" 6 pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
6 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain" 7 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain"
7 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/infrastructure/repository" 8 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/infrastructure/repository"
@@ -108,6 +109,10 @@ func (ptr *PgUpdateUserService) UpdateUser(optUser *domain.OperateInfo, user *do @@ -108,6 +109,10 @@ func (ptr *PgUpdateUserService) UpdateUser(optUser *domain.OperateInfo, user *do
108 if user, err = userRepository.Save(user); err != nil { 109 if user, err = userRepository.Save(user); err != nil {
109 return nil, err 110 return nil, err
110 } 111 }
  112 + // 新建用户事件
  113 + if err, _ := event.Fire(domain.UserUpdateEvent, event.M{"user": user, "userBase": userBase}); err != nil {
  114 + return nil, err
  115 + }
111 return user, nil 116 return user, nil
112 } 117 }
113 118
@@ -204,12 +204,18 @@ func (repository *UserRepository) Find(queryOptions map[string]interface{}) (int @@ -204,12 +204,18 @@ func (repository *UserRepository) Find(queryOptions map[string]interface{}) (int
204 } 204 }
205 query.SetWhereByQueryOption("company_id=?", "companyId") 205 query.SetWhereByQueryOption("company_id=?", "companyId")
206 query.SetWhereByQueryOption("organization_id=?", "organizationId") 206 query.SetWhereByQueryOption("organization_id=?", "organizationId")
  207 + if v, ok := queryOptions["inUserIds"]; ok && len(v.([]int64)) > 0 {
  208 + query.Where(`user_id in (?)`, pg.In(v))
  209 + }
207 if v, ok := queryOptions["inOrgIds"]; ok && len(v.([]int64)) > 0 { 210 if v, ok := queryOptions["inOrgIds"]; ok && len(v.([]int64)) > 0 {
208 query.Where(`organization_id in (?)`, pg.In(v)) 211 query.Where(`organization_id in (?)`, pg.In(v))
209 } 212 }
210 if v, ok := queryOptions["inCompanyIds"]; ok && len(v.([]int64)) > 0 { 213 if v, ok := queryOptions["inCompanyIds"]; ok && len(v.([]int64)) > 0 {
211 query.Where(`company_id in (?)`, pg.In(v)) 214 query.Where(`company_id in (?)`, pg.In(v))
212 } 215 }
  216 + if v, ok := queryOptions["inDepartmentIds"]; ok && len(v.([]int64)) > 0 {
  217 + query.Where(`department_id in (?)`, pg.In(v))
  218 + }
213 query.SetWhereByQueryOption("user_code = ?", "userCode") 219 query.SetWhereByQueryOption("user_code = ?", "userCode")
214 query.SetWhereByQueryOption("ext->>'icCardNumber' = ?", "icCardNumber") 220 query.SetWhereByQueryOption("ext->>'icCardNumber' = ?", "icCardNumber")
215 query.SetWhereByQueryOption("user_base_id=?", "userBaseId") 221 query.SetWhereByQueryOption("user_base_id=?", "userBaseId")
@@ -231,6 +237,9 @@ func (repository *UserRepository) Find(queryOptions map[string]interface{}) (int @@ -231,6 +237,9 @@ func (repository *UserRepository) Find(queryOptions map[string]interface{}) (int
231 if v, ok := queryOptions["cooperationCompany"]; ok && len(v.(string)) > 0 { 237 if v, ok := queryOptions["cooperationCompany"]; ok && len(v.(string)) > 0 {
232 query.Where(fmt.Sprintf(`cooperation_info->>'cooperationCompany' like '%%%v%%'`, v)) 238 query.Where(fmt.Sprintf(`cooperation_info->>'cooperationCompany' like '%%%v%%'`, v))
233 } 239 }
  240 + if _, ok := queryOptions["icCardNumberNotEqual"]; ok {
  241 + query.Where(fmt.Sprintf(`ext->>'icCardNumber' <> '%v'`, ""))
  242 + }
234 query.SetOffsetAndLimit(domain.MaxQueryRow) 243 query.SetOffsetAndLimit(domain.MaxQueryRow)
235 query.SetOrderDirect("user_id", "DESC") 244 query.SetOrderDirect("user_id", "DESC")
236 if count, err := query.SelectAndCount(); err != nil { 245 if count, err := query.SelectAndCount(); err != nil {
@@ -262,3 +262,12 @@ func CopyObject(src, dst interface{}) { @@ -262,3 +262,12 @@ func CopyObject(src, dst interface{}) {
262 } 262 }
263 } 263 }
264 } 264 }
  265 +
  266 +func ToArrayInt64(inputs []string) []int64 {
  267 + result := make([]int64, 0)
  268 + for i := range inputs {
  269 + v, _ := strconv.ParseInt(inputs[i], 10, 64)
  270 + result = append(result, v)
  271 + }
  272 + return result
  273 +}
  1 +package controllers
  2 +
  3 +import (
  4 + "github.com/linmadan/egglib-go/web/beego"
  5 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/terminal/command"
  6 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/terminal/service"
  7 +)
  8 +
  9 +type TerminalController struct {
  10 + beego.BaseController
  11 +}
  12 +
  13 +func (controller *TerminalController) TerminalReport() {
  14 + service := service.NewTerminalService(nil)
  15 + terminalReportCommand := &command.TerminalReportCommand{}
  16 + controller.Unmarshal(terminalReportCommand)
  17 + data, err := service.TerminalReport(terminalReportCommand)
  18 + controller.Response(data, err)
  19 +}
@@ -179,3 +179,12 @@ func (controller *UserController) UpdateAdminUser() { @@ -179,3 +179,12 @@ func (controller *UserController) UpdateAdminUser() {
179 data, err := userService.UpdateAdminUser(updateUserCommand) 179 data, err := userService.UpdateAdminUser(updateUserCommand)
180 controller.Response(data, err) 180 controller.Response(data, err)
181 } 181 }
  182 +
  183 +func (controller *UserController) SyncToAttendanceMachine() {
  184 + userService := service.NewUserService(nil)
  185 + cmd := &command.SyncToAttendanceMachineCommand{}
  186 + Must(controller.Unmarshal(cmd))
  187 + cmd.OperateInfo = ParseOperateInfo(controller.BaseController)
  188 + data, err := userService.SyncToAttendanceMachine(cmd)
  189 + controller.Response(data, err)
  190 +}
  1 +package routers
  2 +
  3 +import (
  4 + "github.com/beego/beego/v2/server/web"
  5 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/port/beego/controllers"
  6 +)
  7 +
  8 +func init() {
  9 + web.Router("/terminal/report", &controllers.TerminalController{}, "Post:TerminalReport")
  10 +}
@@ -21,6 +21,8 @@ func init() { @@ -21,6 +21,8 @@ func init() {
21 web.Router("/user/cooperator", &controllers.UserController{}, "Post:CreateCooperator") 21 web.Router("/user/cooperator", &controllers.UserController{}, "Post:CreateCooperator")
22 web.Router("/user/cooperator/:userId", &controllers.UserController{}, "Put:UpdateCooperator") 22 web.Router("/user/cooperator/:userId", &controllers.UserController{}, "Put:UpdateCooperator")
23 23
  24 + web.Router("/user/sync-to-attendance-machine", &controllers.UserController{}, "Post:SyncToAttendanceMachine")
  25 +
24 web.Router("/admin-user/", &controllers.UserController{}, "Post:CreateAdminUser") 26 web.Router("/admin-user/", &controllers.UserController{}, "Post:CreateAdminUser")
25 web.Router("/admin-user/:userId", &controllers.UserController{}, "Put:UpdateAdminUser") 27 web.Router("/admin-user/:userId", &controllers.UserController{}, "Put:UpdateAdminUser")
26 } 28 }