合并分支 'test' 到 'master'
Test 查看合并请求 !9
正在显示
19 个修改的文件
包含
973 行增加
和
11 行删除
@@ -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 | +} |
pkg/application/terminal/service/terminal.go
0 → 100644
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 | +} |
pkg/application/terminal/service/types.go
0 → 100644
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 | +} |
pkg/application/user/service/attendance.go
0 → 100644
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 | +} |
pkg/port/beego/routers/terminal_router.go
0 → 100644
@@ -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 | } |
-
请 注册 或 登录 后发表评论