From 097e25f0701b864ac5b312f83082dc410f5b41b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=B6=9B?= Date: Fri, 2 Jun 2023 15:51:08 +0800 Subject: [PATCH] =?UTF-8?q?feat(user):=E5=AE=8C=E6=88=90=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E9=83=A8=E5=88=86=E6=89=80=E6=9C=89=E6=8E=A5=E5=8F=A3=E7=9A=84?= =?UTF-8?q?=E8=BF=81=E7=A7=BB=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controller/user.go | 211 +++++++++++++++++++++++++++++++++++++- go.mod | 24 +++-- go.sum | 54 ++++++++++ model/types.go | 48 +++------ repository/user.go | 20 ++-- response/base_response.go | 18 ++-- service/user.go | 4 +- tools/time/time.go | 10 +- vo/user.go | 126 +++++++++++++++++++++++ 9 files changed, 447 insertions(+), 68 deletions(-) create mode 100644 vo/user.go diff --git a/controller/user.go b/controller/user.go index 22c958c..c79385e 100644 --- a/controller/user.go +++ b/controller/user.go @@ -9,6 +9,8 @@ import ( "electricity_bill_calc/response" "electricity_bill_calc/security" "electricity_bill_calc/service" + "electricity_bill_calc/tools" + "electricity_bill_calc/vo" "net/http" "strconv" @@ -22,7 +24,15 @@ func InitializeUserHandlers(router *fiber.App) { router.Delete("/login", security.MustAuthenticated, doLogout) router.Post("/login", doLogin) router.Get("/account", security.OPSAuthorize, searchUsers) + router.Post("/account", security.OPSAuthorize, createOPSAccount) + router.Get("/account/:uid", security.MustAuthenticated, fetchUserInformation) + router.Put("/account/:uid", security.OPSAuthorize, modifyUserInformation) + router.Put("/account/enabled/state", security.OPSAuthorize, changeUserState) router.Get("/expiration", security.EnterpriseAuthorize, getAccountExpiration) + router.Post("/enterprise", security.OPSAuthorize, createEnterpriseAccount) + router.Get("/enterprise/quick/search", security.OPSAuthorize, quickSearchEnterprise) + router.Put("/password", resetUserPassword) + router.Delete("/password/:uid", security.OPSAuthorize, invalidUserPassword) } type _LoginForm struct { @@ -103,8 +113,7 @@ func searchUsers(c *fiber.Ctx) error { if err != nil { return result.NotFound(err.Error()) } - return result.Json( - http.StatusOK, + return result.Success( "已取得符合条件的用户集合。", response.NewPagedResponse(requestPage, total).ToMap(), fiber.Map{"accounts": users}, @@ -122,9 +131,203 @@ func getAccountExpiration(c *fiber.Ctx) error { if err != nil { return result.NotFound("未找到指定的用户档案") } - return result.Json( - http.StatusOK, + return result.Success( "已经取得用户的服务期限信息", fiber.Map{"expiration": userDetail.ServiceExpiration.Format("2006-01-02")}, ) } + +func createOPSAccount(c *fiber.Ctx) error { + userLog.Info("请求创建运维或监管账户。") + result := response.NewResult(c) + creationForm := new(vo.MGTAndOPSAccountCreationForm) + if err := c.BodyParser(creationForm); err != nil { + userLog.Error("表单解析失败!", zap.Error(err)) + return result.UnableToParse("无法解析提交的数据。") + } + exists, err := repository.UserRepository.IsUsernameExists(creationForm.Username) + if err != nil { + userLog.Error("检查用户名是否已经被使用时发生错误!", zap.Error(err)) + return result.Error(http.StatusInternalServerError, err.Error()) + } + if exists { + return result.Conflict("指定的用户名已经被使用了。") + } + verifyCode, err := service.UserService.CreateUserAccount(creationForm.IntoUser(), creationForm.IntoUserDetail()) + if err != nil { + userLog.Error("创建用户账户时发生错误!", zap.Error(err)) + return result.Error(http.StatusInternalServerError, err.Error()) + } + return result.Created("用户已经成功创建。", fiber.Map{"verify": verifyCode}) +} + +func fetchUserInformation(c *fiber.Ctx) error { + userLog.Info("请求获取用户详细信息。") + result := response.NewResult(c) + targetUserId := c.Params("uid") + exists, err := repository.UserRepository.IsUserExists(targetUserId) + if err != nil { + return result.Error(http.StatusInternalServerError, err.Error()) + } + if !exists { + return result.NotFound("指定的用户不存在。") + } + userDetail, err := repository.UserRepository.FindUserDetailById(targetUserId) + if err != nil { + return result.Error(http.StatusInternalServerError, err.Error()) + } + return result.Success("用户详细信息已获取到。", fiber.Map{"user": userDetail}) +} + +func modifyUserInformation(c *fiber.Ctx) error { + userLog.Info("请求修改用户详细信息。") + session, _ := _retreiveSession(c) + result := response.NewResult(c) + targetUserId := c.Params("uid") + exists, err := repository.UserRepository.IsUserExists(targetUserId) + if err != nil { + userLog.Error("检查用户是否存在时发生错误!", zap.Error(err)) + return result.Error(http.StatusInternalServerError, err.Error()) + } + if !exists { + return result.NotFound("指定的用户不存在。") + } + modificationForm := new(vo.UserDetailModificationForm) + if err := c.BodyParser(modificationForm); err != nil { + userLog.Error("表单解析失败!", zap.Error(err)) + return result.UnableToParse("无法解析提交的数据。") + } + userLog.Debug("用户服务费修改表单:", zap.Any("form", modificationForm)) + detailFormForUpdate, err := modificationForm.IntoModificationModel() + if err != nil { + userLog.Error("用户服务费解析转换失败!", zap.Error(err)) + return result.UnableToParse("无法解析提交的数据,服务费格式不正确。") + } + if ok, err := repository.UserRepository.UpdateDetail(targetUserId, *detailFormForUpdate, &session.Uid); err != nil || !ok { + userLog.Error("更新用户详细信息失败!", zap.Error(err)) + return result.Error(http.StatusInternalServerError, err.Error()) + } + return result.Updated("指定用户的信息已经更新。") +} + +func changeUserState(c *fiber.Ctx) error { + userLog.Info("请求修改用户状态。") + result := response.NewResult(c) + modificationForm := new(vo.UserStateChangeForm) + if err := c.BodyParser(modificationForm); err != nil { + userLog.Error("表单解析失败!", zap.Error(err)) + return result.UnableToParse("无法解析提交的数据。") + } + exists, err := repository.UserRepository.IsUserExists(modificationForm.Uid) + if err != nil { + userLog.Error("检查用户是否存在时发生错误!", zap.Error(err)) + return result.Error(http.StatusInternalServerError, err.Error()) + } + if !exists { + return result.NotFound("指定的用户不存在。") + } + if ok, err := repository.UserRepository.ChangeState(modificationForm.Uid, modificationForm.Enabled); err != nil || !ok { + userLog.Error("更新用户状态失败!", zap.Error(err)) + return result.NotAccept("无法更新用户状态。") + } + return result.Updated("用户的状态已经更新。") +} + +func createEnterpriseAccount(c *fiber.Ctx) error { + userLog.Info("请求创建企业账户。") + result := response.NewResult(c) + creationForm := new(vo.EnterpriseAccountCreationForm) + if err := c.BodyParser(creationForm); err != nil { + userLog.Error("表单解析失败!", zap.Error(err)) + return result.UnableToParse("无法解析提交的数据。") + } + exists, err := repository.UserRepository.IsUsernameExists(creationForm.Username) + if err != nil { + userLog.Error("检查用户名是否已经被使用时发生错误!", zap.Error(err)) + return result.Error(http.StatusInternalServerError, err.Error()) + } + if exists { + return result.Conflict("指定的用户名已经被使用了。") + } + userDetail, err := creationForm.IntoUserDetail() + if err != nil { + userLog.Error("转换用户详细档案时发生错误!", zap.Error(err)) + return result.UnableToParse("无法解析提交的数据,服务费格式不正确。") + } + verifyCode, err := service.UserService.CreateUserAccount(creationForm.IntoUser(), userDetail) + if err != nil { + userLog.Error("创建用户账户时发生错误!", zap.Error(err)) + return result.Error(http.StatusInternalServerError, err.Error()) + } + return result.Created("用户已经成功创建。", fiber.Map{"verify": verifyCode}) +} + +func quickSearchEnterprise(c *fiber.Ctx) error { + userLog.Info("请求快速查询企业账户。") + result := response.NewResult(c) + keyword := c.Query("keyword") + limit := c.QueryInt("limit", 6) + if limit < 1 { + limit = 6 + } + users, err := repository.UserRepository.SearchUsersWithLimit(nil, &keyword, uint(limit)) + if err != nil { + userLog.Error("查询用户时发生错误!", zap.Error(err)) + return result.Error(http.StatusInternalServerError, err.Error()) + } + return result.Success("已查询到存在符合条件的企业", fiber.Map{"users": users}) +} + +func resetUserPassword(c *fiber.Ctx) error { + userLog.Info("请求重置用户密码。") + result := response.NewResult(c) + repasswordForm := new(vo.RepasswordForm) + if err := c.BodyParser(repasswordForm); err != nil { + userLog.Error("表单解析失败!", zap.Error(err)) + return result.UnableToParse("无法解析提交的数据。") + } + user, err := repository.UserRepository.FindUserByUsername(repasswordForm.Username) + if err != nil { + userLog.Error("检查用户是否存在时发生错误!", zap.Error(err)) + return result.Error(http.StatusInternalServerError, err.Error()) + } + if user == nil { + return result.NotFound("指定的用户不存在。") + } + if !service.UserService.MatchUserPassword(user.Password, repasswordForm.VerifyCode) { + return result.Unauthorized("验证码不正确。") + } + ok, err := repository.UserRepository.UpdatePassword(user.Id, repasswordForm.NewPassword, false) + if err != nil { + userLog.Error("更新用户凭据时发生错误!", zap.Error(err)) + return result.Error(http.StatusInternalServerError, err.Error()) + } + if !ok { + return result.NotAccept("无法更新用户凭据。") + } + return result.Updated("用户凭据已经更新。") +} + +func invalidUserPassword(c *fiber.Ctx) error { + userLog.Info("请求使用户凭据失效。") + result := response.NewResult(c) + uid := c.Params("uid") + exists, err := repository.UserRepository.IsUserExists(uid) + if err != nil { + userLog.Error("检查用户是否存在时发生错误!", zap.Error(err)) + return result.Error(http.StatusInternalServerError, err.Error()) + } + if !exists { + return result.NotFound("指定的用户不存在。") + } + verifyCode := tools.RandStr(10) + ok, err := repository.UserRepository.UpdatePassword(uid, verifyCode, true) + if err != nil { + userLog.Error("更新用户凭据时发生错误!", zap.Error(err)) + return result.Error(http.StatusInternalServerError, err.Error()) + } + if !ok { + return result.NotAccept("未能更新用户凭据。") + } + return result.Updated("用户凭据已经更新。", fiber.Map{"verify": verifyCode}) +} diff --git a/go.mod b/go.mod index 83046ec..3b0e108 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.19 require ( github.com/deckarep/golang-set/v2 v2.1.0 github.com/fufuok/utils v0.7.13 - github.com/gofiber/fiber/v2 v2.38.1 + github.com/gofiber/fiber/v2 v2.46.0 github.com/google/uuid v1.3.0 github.com/jinzhu/copier v0.3.5 github.com/liamylian/jsontime/v2 v2.0.0 @@ -14,14 +14,14 @@ require ( github.com/samber/lo v1.27.0 github.com/shopspring/decimal v1.3.1 github.com/spf13/viper v1.12.0 - github.com/valyala/fasthttp v1.40.0 + github.com/valyala/fasthttp v1.47.0 github.com/xuri/excelize/v2 v2.6.1 go.uber.org/zap v1.23.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0 ) require ( - github.com/andybalholm/brotli v1.0.4 // indirect + github.com/andybalholm/brotli v1.0.5 // indirect github.com/georgysavva/scany/v2 v2.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect @@ -29,8 +29,16 @@ require ( github.com/jackc/puddle/v2 v2.2.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jmoiron/sqlx v1.3.5 // indirect - github.com/klauspost/compress v1.15.0 // indirect + github.com/klauspost/compress v1.16.5 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/philhofer/fwd v1.1.2 // indirect + github.com/rivo/uniseg v0.4.4 // indirect github.com/rogpeppe/go-internal v1.9.0 // indirect + github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 // indirect + github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect + github.com/tinylib/msgp v1.1.8 // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect @@ -67,11 +75,11 @@ require ( github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.8.0 // indirect - golang.org/x/crypto v0.6.0 // indirect + golang.org/x/crypto v0.7.0 // indirect golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect - golang.org/x/net v0.6.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect + golang.org/x/net v0.8.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/text v0.8.0 // indirect gopkg.in/ini.v1 v1.66.4 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index f733226..08a121d 100644 --- a/go.sum +++ b/go.sum @@ -42,6 +42,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -78,6 +80,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2 github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/gofiber/fiber/v2 v2.38.1 h1:GEQ/Yt3Wsf2a30iTqtLXlBYJZso0JXPovt/tmj5H9jU= github.com/gofiber/fiber/v2 v2.38.1/go.mod h1:t0NlbaXzuGH7I+7M4paE848fNWInZ7mfxI/Er1fTth8= +github.com/gofiber/fiber/v2 v2.46.0 h1:wkkWotblsGVlLjXj2dpgKQAYHtXumsK/HyFugQM68Ns= +github.com/gofiber/fiber/v2 v2.46.0/go.mod h1:DNl0/c37WLe0g92U6lx1VMQuxGUQY5V7EIaVoEsUffc= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -165,6 +169,8 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.15.0 h1:xqfchp4whNFxn5A4XFyyYtitiWI8Hy5EW59jEwcyL6U= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= +github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -178,6 +184,13 @@ github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -197,6 +210,9 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw= github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI= +github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= +github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -209,6 +225,9 @@ github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7 github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM= github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= @@ -218,6 +237,11 @@ github.com/rueian/rueidis v0.0.73 h1:+r0Z6C6HMnkquPgY3zaHVpTqmCyJL56Z36GSlyBrufk github.com/rueian/rueidis v0.0.73/go.mod h1:FwnfDILF2GETrvXcYFlhIiru/7NmSIm1f+7C5kutO0I= github.com/samber/lo v1.27.0 h1:GOyDWxsblvqYobqsmUuMddPa2/mMzkKyojlXol4+LaQ= github.com/samber/lo v1.27.0/go.mod h1:it33p9UtPMS7z72fP4gw/EIfQB2eI8ke7GR2wc6+Rhg= +github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 h1:rmMl4fXJhKMNWl+K+r/fq4FbbKI+Ia2m9hYBLm2h4G4= +github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94/go.mod h1:90zrgN3D/WJsDd1iXHT96alCoN2KJo6/4x1DZC3wZs8= +github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4= +github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk= +github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= @@ -244,6 +268,9 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs github.com/subosito/gotenv v1.3.0 h1:mjC+YW8QpAdXibNi+vNWgzmgBH4+5l5dCXv8cNysBLI= github.com/subosito/gotenv v1.3.0/go.mod h1:YzJjq/33h7nrwdY+iHMhEOEEbW0ovIz0tB6t6PwAXzs= github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M= +github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= +github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0= +github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs= github.com/uptrace/bun v1.1.8 h1:slxuaP4LYWFbPRUmTtQhfJN+6eX/6ar2HDKYTcI50SA= @@ -256,6 +283,8 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.40.0 h1:CRq/00MfruPGFLTQKY8b+8SfdK60TxNztjRMnH0t1Yc= github.com/valyala/fasthttp v1.40.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I= +github.com/valyala/fasthttp v1.47.0 h1:y7moDoxYzMooFpT5aHgNgVOQDrS3qlkfiP9mDtGGK9c= +github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= @@ -272,6 +301,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -293,6 +323,7 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -302,6 +333,8 @@ golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5 golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -339,6 +372,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -372,10 +407,14 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E= golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -395,6 +434,7 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -435,13 +475,21 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220907062415-87db552b00fd h1:AZeIEzg+8RCELJYq8w+ODLVxFgLMMigSwO/ffKPEd9U= golang.org/x/sys v0.0.0-20220907062415-87db552b00fd/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -451,8 +499,11 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -497,12 +548,15 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/model/types.go b/model/types.go index 90f5713..7a74be8 100644 --- a/model/types.go +++ b/model/types.go @@ -6,6 +6,8 @@ import ( "encoding/json" "fmt" "time" + + et "electricity_bill_calc/tools/time" ) type Date struct { @@ -13,32 +15,24 @@ type Date struct { } func NewDate(t time.Time) Date { - loc, err := time.LoadLocation("Asia/Shanghai") - if err != nil { - panic(err) - } - t = t.In(loc) + t = t.In(et.Loc) return Date{ - Time: time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, loc), + Time: time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, et.Loc), } } +func SpecificDate(year int, month time.Month, date int) Date { + return NewDate(et.Time(year, month, date, 0, 0, 0, 0)) +} + func NewEmptyDate() Date { - loc, err := time.LoadLocation("Asia/Shanghai") - if err != nil { - panic(err) - } return Date{ - Time: time.Time{}.In(loc), + Time: time.Time{}.In(et.Loc), } } func ParseDate(t string) (Date, error) { - loc, err := time.LoadLocation("Asia/Shanghai") - if err != nil { - return NewEmptyDate(), fmt.Errorf("unable to load time zone, %w", err) - } - d, err := time.ParseInLocation("2006-01-02", t, loc) + d, err := time.ParseInLocation("2006-01-02", t, et.Loc) if err != nil { return NewEmptyDate(), fmt.Errorf("unable to parse given time, %w", err) } @@ -62,30 +56,22 @@ func (d Date) ToString() string { var _ driver.Valuer = (*Date)(nil) func (d Date) Value() (driver.Value, error) { - loc, err := time.LoadLocation("Asia/Shanghai") - if err != nil { - panic(err) - } - return d.In(loc).Format("2006-01-02"), nil + return d.In(et.Loc).Format("2006-01-02"), nil } var _ sql.Scanner = (*Date)(nil) // Scan scans the time parsing it if necessary using timeFormat. func (d *Date) Scan(src interface{}) (err error) { - loc, err := time.LoadLocation("Asia/Shanghai") - if err != nil { - panic(err) - } switch src := src.(type) { case time.Time: *d = NewDate(src) return nil case string: - d.Time, err = time.ParseInLocation("2006-01-02", src, loc) + d.Time, err = time.ParseInLocation("2006-01-02", src, et.Loc) return err case []byte: - d.Time, err = time.ParseInLocation("2006-01-02", string(src), loc) + d.Time, err = time.ParseInLocation("2006-01-02", string(src), et.Loc) return err case nil: d.Time = time.Time{} @@ -104,15 +90,11 @@ func (d Date) MarshalJSON() ([]byte, error) { var _ json.Unmarshaler = (*Date)(nil) func (d *Date) UnmarshalJSON(raw []byte) error { - loc, err := time.LoadLocation("Asia/Shanghai") - if err != nil { - return fmt.Errorf("unable to load time zone, %w", err) - } var s string - err = json.Unmarshal(raw, &s) + err := json.Unmarshal(raw, &s) if err != nil { return fmt.Errorf("unable to unmarshal value, %w", err) } - d.Time, err = time.ParseInLocation("2006-01-02", s, loc) + d.Time, err = time.ParseInLocation("2006-01-02", s, et.Loc) return err } diff --git a/repository/user.go b/repository/user.go index 8d59a85..8d49ce6 100644 --- a/repository/user.go +++ b/repository/user.go @@ -16,6 +16,7 @@ import ( _ "github.com/doug-martin/goqu/v9/dialect/postgres" "github.com/fufuok/utils" "github.com/georgysavva/scany/v2/pgxscan" + "github.com/samber/lo" "go.uber.org/zap" ) @@ -325,19 +326,20 @@ func (ur _UserRepository) UpdateDetail(uid string, userDetail model.UserModifica ctx, cancel := global.TimeoutContext() defer cancel() + updates := goqu.Record{ + "name": userDetail.Name, "abbr": tools.PinyinAbbr(userDetail.Name), "region": userDetail.Region, + "address": userDetail.Address, "contact": userDetail.Contact, "phone": userDetail.Phone, + "last_modified_at": time.Now(), "last_modified_by": operator, + } + if userDetail.UnitServiceFee != nil { + updates = lo.Assign(updates, goqu.Record{"unit_service_fee": userDetail.UnitServiceFee}) + } + userDetailUpdateQuery := ur.ds. Update("user_detail"). - Set(goqu.Record{ - "name": userDetail.Name, "abbr": tools.PinyinAbbr(userDetail.Name), "region": userDetail.Region, - "address": userDetail.Address, "contact": userDetail.Contact, "phone": userDetail.Phone, - "last_modified_at": time.Now(), "last_modified_by": operator, - }). + Set(updates). Where(goqu.Ex{"id": uid}) - if userDetail.UnitServiceFee != nil { - userDetailUpdateQuery = userDetailUpdateQuery.Set(goqu.Record{"unit_service_fee": userDetail.UnitServiceFee}) - } - userDetailSql, userDetailParams, _ := userDetailUpdateQuery. Prepared(true).ToSQL() diff --git a/response/base_response.go b/response/base_response.go index 01ce30b..54e1b9f 100644 --- a/response/base_response.go +++ b/response/base_response.go @@ -61,7 +61,7 @@ func (r Result) UnableToParse(msg string) error { // 用户未获得授权)响应 func (r *Result) Unauthorized(msg string) error { - return r.response(fiber.StatusOK, fiber.StatusUnauthorized, msg) + return r.response(fiber.StatusUnauthorized, fiber.StatusUnauthorized, msg) } // 简易操作成功信息 @@ -71,37 +71,37 @@ func (r *Result) Success(msg string, payloads ...map[string]interface{}) error { // 数据成功创建 func (r Result) Created(msg string, payloads ...map[string]interface{}) error { - return r.response(fiber.StatusOK, fiber.StatusCreated, msg, payloads...) + return r.response(fiber.StatusCreated, fiber.StatusCreated, msg, payloads...) } // 数据成功更新 -func (r Result) Updated(msg string) error { - return r.response(fiber.StatusOK, fiber.StatusAccepted, msg) +func (r Result) Updated(msg string, payloads ...map[string]interface{}) error { + return r.response(fiber.StatusAccepted, fiber.StatusAccepted, msg, payloads...) } // 数据已成功删除 func (r Result) Deleted(msg string) error { - return r.response(fiber.StatusOK, fiber.StatusNoContent, msg) + return r.response(fiber.StatusNoContent, fiber.StatusNoContent, msg) } // 指定操作未被接受 func (r Result) BadRequest(msg string) error { - return r.response(fiber.StatusOK, fiber.StatusBadRequest, msg) + return r.response(fiber.StatusBadRequest, fiber.StatusBadRequest, msg) } // 指定操作未被接受 func (r Result) NotAccept(msg string) error { - return r.response(fiber.StatusOK, fiber.StatusNotAcceptable, msg) + return r.response(fiber.StatusNotAcceptable, fiber.StatusNotAcceptable, msg) } // 数据未找到 func (r Result) NotFound(msg string) error { - return r.response(fiber.StatusOK, fiber.StatusNotFound, msg) + return r.response(fiber.StatusNotFound, fiber.StatusNotFound, msg) } // 数据存在冲突 func (r Result) Conflict(msg string) error { - return r.response(fiber.StatusOK, fiber.StatusConflict, msg) + return r.response(fiber.StatusConflict, fiber.StatusConflict, msg) } // 快速自由JSON格式响应 diff --git a/service/user.go b/service/user.go index d528222..4dc36fc 100644 --- a/service/user.go +++ b/service/user.go @@ -25,7 +25,7 @@ var UserService = _UserService{ log: logger.Named("Service", "User"), } -func matchUserPassword(controlCode, testCode string) bool { +func (us _UserService) MatchUserPassword(controlCode, testCode string) bool { hashedCode := utils.Sha512Hex(testCode) return controlCode == hashedCode } @@ -56,7 +56,7 @@ func (us _UserService) processUserLogin(username, password string, userType []in authErr.NeedReset = true return nil, nil, authErr } - if !matchUserPassword(user.Password, password) { + if !us.MatchUserPassword(user.Password, password) { us.log.Warn("处理用户登录失败,密码错误。", zap.String("username", username)) return nil, nil, exceptions.NewAuthenticationError(402, "用户凭据不正确。") } diff --git a/tools/time/time.go b/tools/time/time.go index 5bbd36b..b3c3fe4 100644 --- a/tools/time/time.go +++ b/tools/time/time.go @@ -4,14 +4,18 @@ import ( "time" ) -var loc *time.Location = time.FixedZone("+0800", 8*60*60) +var Loc *time.Location = time.FixedZone("+0800", 8*60*60) func Now() time.Time { - return time.Now().In(loc) + return time.Now().In(Loc) +} + +func Time(year int, month time.Month, date, hours, min, sec, nsec int) time.Time { + return time.Date(year, month, date, hours, min, sec, nsec, Loc) } func Timestamp() int64 { - startline := time.Date(2022, 2, 22, 22, 22, 22, 0, loc).Unix() + startline := time.Date(2022, 2, 22, 22, 22, 22, 0, Loc).Unix() return Now().Unix() - startline } diff --git a/vo/user.go b/vo/user.go new file mode 100644 index 0000000..b09051e --- /dev/null +++ b/vo/user.go @@ -0,0 +1,126 @@ +package vo + +import ( + "electricity_bill_calc/model" + "electricity_bill_calc/tools/time" + st "time" + + "github.com/shopspring/decimal" +) + +type MGTAndOPSAccountCreationForm struct { + Username string `json:"username"` + Name string `json:"name"` + Contact *string `json:"contact"` + Phone *string `json:"phone"` + UserType int16 `json:"type"` +} + +func (u MGTAndOPSAccountCreationForm) IntoUser() *model.User { + return &model.User{ + Username: u.Username, + Password: "", + ResetNeeded: false, + UserType: u.UserType, + Enabled: true, + CreatedAt: nil, + } +} + +func (u MGTAndOPSAccountCreationForm) IntoUserDetail() *model.UserDetail { + return &model.UserDetail{ + Name: &u.Name, + Abbr: nil, + Region: nil, + Address: nil, + Contact: u.Contact, + Phone: u.Phone, + UnitServiceFee: decimal.Zero, + ServiceExpiration: model.SpecificDate(2099, st.December, 31), + CreatedAt: time.Now(), + CreatedBy: nil, + LastModifiedAt: time.Now(), + LastModifiedBy: nil, + DeletedAt: nil, + DeletedBy: nil, + } +} + +type EnterpriseAccountCreationForm struct { + Username string `json:"username"` + Name string `json:"name"` + Region *string `json:"region"` + Address *string `json:"address"` + Contact *string `json:"contact"` + Phone *string `json:"phone"` + UnitServiceFee string `json:"unitServiceFee"` +} + +func (u EnterpriseAccountCreationForm) IntoUser() *model.User { + return &model.User{ + Username: u.Username, + Password: "", + ResetNeeded: false, + UserType: model.USER_TYPE_ENT, + Enabled: true, + CreatedAt: nil, + } +} + +func (u EnterpriseAccountCreationForm) IntoUserDetail() (*model.UserDetail, error) { + unitServiceFee, err := decimal.NewFromString(u.UnitServiceFee) + if err != nil { + return nil, err + } + return &model.UserDetail{ + Name: &u.Name, + Abbr: nil, + Region: u.Region, + Address: u.Address, + Contact: u.Contact, + Phone: u.Phone, + UnitServiceFee: unitServiceFee, + ServiceExpiration: model.SpecificDate(2000, st.January, 1), + CreatedAt: time.Now(), + CreatedBy: nil, + LastModifiedAt: time.Now(), + LastModifiedBy: nil, + DeletedAt: nil, + DeletedBy: nil, + }, nil +} + +type UserDetailModificationForm struct { + Name string `json:"name"` + Region *string `json:"region"` + Address *string `json:"address"` + Contact *string `json:"contact"` + Phone *string `json:"phone"` + UnitServiceFee *string `json:"unitServiceFee"` +} + +func (u UserDetailModificationForm) IntoModificationModel() (*model.UserModificationForm, error) { + unitServiceFee, err := decimal.NewFromString(*u.UnitServiceFee) + if err != nil { + return nil, err + } + return &model.UserModificationForm{ + Name: u.Name, + Region: u.Region, + Address: u.Address, + Contact: u.Contact, + Phone: u.Phone, + UnitServiceFee: &unitServiceFee, + }, nil +} + +type UserStateChangeForm struct { + Uid string `json:"uid"` + Enabled bool `json:"enabled"` +} + +type RepasswordForm struct { + VerifyCode string `json:"verifyCode"` + Username string `json:"uname"` + NewPassword string `json:"newPass"` +}