add update method #5
			
				
			
		
		
		
	| 
						 | 
				
			
			@ -37,10 +37,7 @@ func (s Service) Create(payload CreateOptions) error {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// New device data from payload
 | 
			
		||||
	deviceData, err := payload.newDevice()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	deviceData := payload.newDevice()
 | 
			
		||||
 | 
			
		||||
	// Find deviceID existed or not
 | 
			
		||||
	if s.isDeviceIDExisted(ctx, deviceData.DeviceID) {
 | 
			
		||||
| 
						 | 
				
			
			@ -60,13 +57,17 @@ func (s Service) Create(payload CreateOptions) error {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (payload CreateOptions) newDevice() (result Device, err error) {
 | 
			
		||||
func (payload CreateOptions) newDevice() Device {
 | 
			
		||||
	timeNow := now()
 | 
			
		||||
	device := Device{
 | 
			
		||||
 | 
			
		||||
	// Get userAgent data
 | 
			
		||||
	osName, osVersion, isMobile := getUserAgentData(payload.UserAgent)
 | 
			
		||||
 | 
			
		||||
	return Device{
 | 
			
		||||
		ID:              mongodb.NewObjectID(),
 | 
			
		||||
		DeviceID:        payload.DeviceID,
 | 
			
		||||
		OSName:          getOSName(payload.UserAgent),
 | 
			
		||||
		OSVersion:       getOSVersion(payload.UserAgent),
 | 
			
		||||
		OSName:          osName,
 | 
			
		||||
		OSVersion:       osVersion,
 | 
			
		||||
		IP:              payload.IP,
 | 
			
		||||
		Language:        getLanguage(payload.Language),
 | 
			
		||||
		AuthToken:       payload.AuthToken,
 | 
			
		||||
| 
						 | 
				
			
			@ -76,14 +77,7 @@ func (payload CreateOptions) newDevice() (result Device, err error) {
 | 
			
		|||
		Model:           payload.Model,
 | 
			
		||||
		Manufacturer:    payload.Manufacturer,
 | 
			
		||||
		UserID:          payload.UserID,
 | 
			
		||||
		IsMobile:        isMobile,
 | 
			
		||||
		AppVersion:      payload.AppVersion,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// App version
 | 
			
		||||
	if payload.AppVersion != "" {
 | 
			
		||||
		device.AppVersion = payload.AppVersion
 | 
			
		||||
		device.IsMobile = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	result = device
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,70 @@
 | 
			
		|||
| 
					
 | 
			||||
package devicemngmt
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
import (
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	"context"
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	"fmt"
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	"github.com/Selly-Modules/logger"
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	"go.mongodb.org/mongo-driver/bson"
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
)
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
// UpdateOptions ...
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
type UpdateOptions struct {
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	UserAgent    string
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	AppVersion   string
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	IP           string
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	FCMToken     string
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	AuthToken    string
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	Language     string
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	Model        string
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	Manufacturer string
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
}
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
// UpdateByDeviceID ...
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
func (s Service) UpdateByDeviceID(deviceID string, payload UpdateOptions) error {
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	var (
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
		ctx  = context.Background()
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
		col  = s.getDeviceCollection()
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
		cond = bson.M{
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
			"deviceID": deviceID,
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
		}
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	)
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	// Validate payload
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	err := payload.validate()
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	if err != nil {
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
		return err
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	}
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	// Get userAgent data
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	osName, osVersion, isMobile := getUserAgentData(payload.UserAgent)
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	// Setup update data
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	updateData := bson.M{
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
		"$set": bson.M{
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
			"osName":          osName,
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
			"osVersion":       osVersion,
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
			"ip":              payload.IP,
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
			"language":        getLanguage(payload.Language),
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
			"authToken":       payload.AuthToken,
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
			"fcmToken":        payload.FCMToken,
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
			"model":           payload.Model,
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
			"manufacturer":    payload.Manufacturer,
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
			"appVersion":      payload.AppVersion,
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
			"isMobile":        isMobile,
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
			"lastActivatedAt": now(),
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
		},
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	}
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	// Update
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	_, err = col.UpdateOne(ctx, cond, updateData)
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	if err != nil {
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
		logger.Error("devicemngt - updateByDeviceID", logger.LogData{
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
			"deviceID": deviceID,
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
			"err":      err.Error(),
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
		})
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
		return fmt.Errorf("error when update device: %s", err.Error())
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	}
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
	return nil
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
}
 | 
			
		||||
| 
					
 cái này phải lấy từ userAgent chớ sao so sánh như vậy được cái này phải lấy từ userAgent chớ sao so sánh như vậy được 
			
		mấy cái này nên viết 1 func trả về  
			
			mấy cái này nên viết 1 func trả về `name, version, isMobile` rồi dùng thôi
```go
osName, osVersion, isMobile := getUserAgentData(ua)
``` 
			
		done done 
			
		done done 
			
		 | 
			||||
| 
						 | 
				
			
			@ -31,14 +31,9 @@ func (s Service) isDeviceIDExisted(ctx context.Context, deviceID string) bool {
 | 
			
		|||
	return !device.ID.IsZero()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getOSName(userAgent string) string {
 | 
			
		||||
func getUserAgentData(userAgent string) (string, string, bool) {
 | 
			
		||||
	uaData := ua.New(userAgent)
 | 
			
		||||
	return uaData.OSInfo().Name
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getOSVersion(userAgent string) string {
 | 
			
		||||
	uaData := ua.New(userAgent)
 | 
			
		||||
	return uaData.OSInfo().Version
 | 
			
		||||
	return uaData.OSInfo().Name, uaData.OSInfo().Version, uaData.Mobile()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getLanguage(lang string) string {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										28
									
								
								validate.go
								
								
								
								
							
							
						
						| 
						 | 
				
			
			@ -49,3 +49,31 @@ func (co CreateOptions) validate() error {
 | 
			
		|||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (uo UpdateOptions) validate() error {
 | 
			
		||||
	// UserAgent
 | 
			
		||||
	if uo.UserAgent == "" {
 | 
			
		||||
		logger.Error("devicemngt - Update: no userAgent data", logger.LogData{
 | 
			
		||||
			"payload": uo,
 | 
			
		||||
		})
 | 
			
		||||
		return errors.New("no userAgent data")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// IP
 | 
			
		||||
	if uo.IP == "" {
 | 
			
		||||
		logger.Error("devicemngt - Update: no ip data", logger.LogData{
 | 
			
		||||
			"payload": uo,
 | 
			
		||||
		})
 | 
			
		||||
		return errors.New("no ip data")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// AuthToken
 | 
			
		||||
	if uo.AuthToken == "" {
 | 
			
		||||
		logger.Error("devicemngt - Update: no authToken data", logger.LogData{
 | 
			
		||||
			"payload": uo,
 | 
			
		||||
		})
 | 
			
		||||
		return errors.New("no authToken data")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
cái này phải lấy từ userAgent chớ sao so sánh như vậy được
cái này phải lấy từ userAgent chớ sao so sánh như vậy được
mấy cái này nên viết 1 func trả về
name, version, isMobilerồi dùng thôimấy cái này nên viết 1 func trả về
name, version, isMobilerồi dùng thôidone
done
done
done