作者 linmadan

添加个人消息统计,重构任务查询与标签删除功能

@@ -181,6 +181,23 @@ func (customerValueService *CustomerValueService) RemoveCustomerValue(removeCust @@ -181,6 +181,23 @@ func (customerValueService *CustomerValueService) RemoveCustomerValue(removeCust
181 if customerValue == nil { 181 if customerValue == nil {
182 return nil, application.ThrowError(application.RES_NO_FIND_ERROR, fmt.Sprintf("%s", string(removeCustomerValueCommand.CustomerValueId))) 182 return nil, application.ThrowError(application.RES_NO_FIND_ERROR, fmt.Sprintf("%s", string(removeCustomerValueCommand.CustomerValueId)))
183 } 183 }
  184 + var taskRepository domain.TaskRepository
  185 + if value, err := factory.CreateTaskRepository(map[string]interface{}{
  186 + "transactionContext": transactionContext,
  187 + }); err != nil {
  188 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  189 + } else {
  190 + taskRepository = value
  191 + }
  192 + if count, _, err := taskRepository.Find(map[string]interface{}{
  193 + "customerValues": []int{customerValue.CustomerValueId},
  194 + }); err != nil {
  195 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  196 + } else {
  197 + if count > 0 {
  198 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "该标签已被使用,不可删除")
  199 + }
  200 + }
184 if customerValue, err := customerValueRepository.Remove(customerValue); err != nil { 201 if customerValue, err := customerValueRepository.Remove(customerValue); err != nil {
185 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 202 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
186 } else { 203 } else {
@@ -181,6 +181,23 @@ func (projectBelongService *ProjectBelongService) RemoveProjectBelong(removeProj @@ -181,6 +181,23 @@ func (projectBelongService *ProjectBelongService) RemoveProjectBelong(removeProj
181 if projectBelong == nil { 181 if projectBelong == nil {
182 return nil, application.ThrowError(application.RES_NO_FIND_ERROR, fmt.Sprintf("%s", string(removeProjectBelongCommand.ProjectBelongId))) 182 return nil, application.ThrowError(application.RES_NO_FIND_ERROR, fmt.Sprintf("%s", string(removeProjectBelongCommand.ProjectBelongId)))
183 } 183 }
  184 + var taskRepository domain.TaskRepository
  185 + if value, err := factory.CreateTaskRepository(map[string]interface{}{
  186 + "transactionContext": transactionContext,
  187 + }); err != nil {
  188 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  189 + } else {
  190 + taskRepository = value
  191 + }
  192 + if count, _, err := taskRepository.Find(map[string]interface{}{
  193 + "projectBelongs": []int{projectBelong.ProjectBelongId},
  194 + }); err != nil {
  195 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  196 + } else {
  197 + if count > 0 {
  198 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "该标签已被使用,不可删除")
  199 + }
  200 + }
184 if projectBelong, err := projectBelongRepository.Remove(projectBelong); err != nil { 201 if projectBelong, err := projectBelongRepository.Remove(projectBelong); err != nil {
185 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 202 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
186 } else { 203 } else {
  1 +package command
  2 +
  3 +import (
  4 + "fmt"
  5 +
  6 + "github.com/astaxie/beego/validation"
  7 +)
  8 +
  9 +type PersonNotificationStatisticsCommand struct {
  10 + // 统一用户UID
  11 + Uid int64 `json:"uid" valid:"Required"`
  12 +}
  13 +
  14 +func (personNotificationStatisticsCommand *PersonNotificationStatisticsCommand) ValidateCommand() error {
  15 + valid := validation.Validation{}
  16 + b, err := valid.Valid(personNotificationStatisticsCommand)
  17 + if err != nil {
  18 + return err
  19 + }
  20 + if !b {
  21 + for _, validErr := range valid.Errors {
  22 + return fmt.Errorf("%s %s", validErr.Key, validErr.Message)
  23 + }
  24 + }
  25 + return nil
  26 +}
@@ -12,6 +12,56 @@ import ( @@ -12,6 +12,56 @@ import (
12 type StatisticsService struct { 12 type StatisticsService struct {
13 } 13 }
14 14
  15 +// 获取个人消息通知统计
  16 +func (statisticsService *StatisticsService) PersonNotificationStatistics(personNotificationStatisticsCommand *command.PersonNotificationStatisticsCommand) (interface{}, error) {
  17 + if err := personNotificationStatisticsCommand.ValidateCommand(); err != nil {
  18 + return nil, application.ThrowError(application.ARG_ERROR, err.Error())
  19 + }
  20 + transactionContext, err := factory.CreateTransactionContext(nil)
  21 + if err != nil {
  22 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  23 + }
  24 + if err := transactionContext.StartTransaction(); err != nil {
  25 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  26 + }
  27 + defer func() {
  28 + transactionContext.RollbackTransaction()
  29 + }()
  30 + var employeeDao *dao.EmployeeDao
  31 + if value, err := factory.CreateEmployeeDao(map[string]interface{}{
  32 + "transactionContext": transactionContext,
  33 + }); err != nil {
  34 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  35 + } else {
  36 + employeeDao = value
  37 + }
  38 + var employeeRepository domain.EmployeeRepository
  39 + if value, err := factory.CreateEmployeeRepository(map[string]interface{}{
  40 + "transactionContext": transactionContext,
  41 + }); err != nil {
  42 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  43 + } else {
  44 + employeeRepository = value
  45 + }
  46 + employee, err := employeeRepository.FindOne(map[string]interface{}{
  47 + "uid": personNotificationStatisticsCommand.Uid,
  48 + })
  49 + if err != nil {
  50 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  51 + }
  52 + if employee == nil {
  53 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "无效的企业员工")
  54 + }
  55 + if personNotificationStatistics, err := employeeDao.CalculatePersonUnReadNotification(personNotificationStatisticsCommand.Uid); err != nil {
  56 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  57 + } else {
  58 + if err := transactionContext.CommitTransaction(); err != nil {
  59 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  60 + }
  61 + return personNotificationStatistics, nil
  62 + }
  63 +}
  64 +
15 // 获取系统任务统计 65 // 获取系统任务统计
16 func (statisticsService *StatisticsService) SystemTaskStatistics(systemTaskStatisticsCommand *command.SystemTaskStatisticsCommand) (interface{}, error) { 66 func (statisticsService *StatisticsService) SystemTaskStatistics(systemTaskStatisticsCommand *command.SystemTaskStatisticsCommand) (interface{}, error) {
17 if err := systemTaskStatisticsCommand.ValidateCommand(); err != nil { 67 if err := systemTaskStatisticsCommand.ValidateCommand(); err != nil {
@@ -15,6 +15,8 @@ type SearchTaskCommand struct { @@ -15,6 +15,8 @@ type SearchTaskCommand struct {
15 TaskContentMatch string `json:"taskContentMatch,omitempty"` 15 TaskContentMatch string `json:"taskContentMatch,omitempty"`
16 // 任务类型 16 // 任务类型
17 TaskType int `json:"taskType,omitempty"` 17 TaskType int `json:"taskType,omitempty"`
  18 + // 任务类型ID列表
  19 + TaskTypes []int `json:"taskTypes,omitempty"`
18 // 任务状态 20 // 任务状态
19 TaskStatus int `json:"taskStatus,omitempty"` 21 TaskStatus int `json:"taskStatus,omitempty"`
20 // 项目归属 22 // 项目归属
@@ -181,6 +181,23 @@ func (taskNatureService *TaskNatureService) RemoveTaskNature(removeTaskNatureCom @@ -181,6 +181,23 @@ func (taskNatureService *TaskNatureService) RemoveTaskNature(removeTaskNatureCom
181 if taskNature == nil { 181 if taskNature == nil {
182 return nil, application.ThrowError(application.RES_NO_FIND_ERROR, fmt.Sprintf("%s", string(removeTaskNatureCommand.TaskNatureId))) 182 return nil, application.ThrowError(application.RES_NO_FIND_ERROR, fmt.Sprintf("%s", string(removeTaskNatureCommand.TaskNatureId)))
183 } 183 }
  184 + var taskRepository domain.TaskRepository
  185 + if value, err := factory.CreateTaskRepository(map[string]interface{}{
  186 + "transactionContext": transactionContext,
  187 + }); err != nil {
  188 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  189 + } else {
  190 + taskRepository = value
  191 + }
  192 + if count, _, err := taskRepository.Find(map[string]interface{}{
  193 + "taskNatures": []int{taskNature.TaskNatureId},
  194 + }); err != nil {
  195 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  196 + } else {
  197 + if count > 0 {
  198 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "该标签已被使用,不可删除")
  199 + }
  200 + }
184 if taskNature, err := taskNatureRepository.Remove(taskNature); err != nil { 201 if taskNature, err := taskNatureRepository.Remove(taskNature); err != nil {
185 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 202 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
186 } else { 203 } else {
@@ -4,6 +4,7 @@ import ( @@ -4,6 +4,7 @@ import (
4 "fmt" 4 "fmt"
5 "github.com/go-pg/pg" 5 "github.com/go-pg/pg"
6 pgTransaction "github.com/linmadan/egglib-go/transaction/pg" 6 pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
  7 + "gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/domain"
7 "gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/infrastructure/pg/models" 8 "gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/infrastructure/pg/models"
8 "time" 9 "time"
9 ) 10 )
@@ -56,6 +57,33 @@ func (dao *EmployeeDao) TransferSuMoney(uid int64, suMoney float64) error { @@ -56,6 +57,33 @@ func (dao *EmployeeDao) TransferSuMoney(uid int64, suMoney float64) error {
56 return err 57 return err
57 } 58 }
58 59
  60 +func (dao *EmployeeDao) CalculatePersonUnReadNotification(uid int64) (map[string]int, error) {
  61 + var unReadSystemNotification int
  62 + var unReadInteractionNotification int
  63 + tx := dao.transactionContext.PgTx
  64 + sentNotificationModel := new(models.SentNotification)
  65 + if count, err := tx.Model(sentNotificationModel).Relation("Notification").
  66 + Where(`sent_notification.receiver @> '{"uid":?}'`, uid).
  67 + Where("notification.notification_type = ?", domain.NOTIFICATION_TYPE_SYSTEM).
  68 + Count(); err != nil {
  69 + return nil, err
  70 + } else {
  71 + unReadSystemNotification = count
  72 + }
  73 + if count, err := tx.Model(sentNotificationModel).Relation("Notification").
  74 + Where(`sent_notification.receiver @> '{"uid":?}'`, uid).
  75 + Where("notification.notification_type = ?", domain.NOTIFICATION_TYPE_INTERACTION).
  76 + Count(); err != nil {
  77 + return nil, err
  78 + } else {
  79 + unReadInteractionNotification = count
  80 + }
  81 + return map[string]int{
  82 + "unReadSystemNotification": unReadSystemNotification,
  83 + "unReadInteractionNotification": unReadInteractionNotification,
  84 + }, nil
  85 +}
  86 +
59 func (dao *EmployeeDao) CalculatePersonSuMoney(uid int64) (map[string]interface{}, error) { 87 func (dao *EmployeeDao) CalculatePersonSuMoney(uid int64) (map[string]interface{}, error) {
60 var incomeSuMoney float64 88 var incomeSuMoney float64
61 var incomeSuMoneyOfYesterday float64 89 var incomeSuMoneyOfYesterday float64
@@ -118,6 +118,14 @@ func (repository *TaskRepository) Find(queryOptions map[string]interface{}) (int @@ -118,6 +118,14 @@ func (repository *TaskRepository) Find(queryOptions map[string]interface{}) (int
118 if taskType, ok := queryOptions["taskType"]; ok && (taskType != 0) { 118 if taskType, ok := queryOptions["taskType"]; ok && (taskType != 0) {
119 query = query.Where(`task.task_type = ?`, taskType) 119 query = query.Where(`task.task_type = ?`, taskType)
120 } 120 }
  121 + if taskTypes, ok := queryOptions["taskTypes"]; ok && len(taskTypes.([]int)) != 0 {
  122 + query = query.WhereGroup(func(q *orm.Query) (*orm.Query, error) {
  123 + for _, value := range taskTypes.([]int) {
  124 + q = q.WhereOr("task.task_type = ?", value)
  125 + }
  126 + return q, nil
  127 + })
  128 + }
121 if projectBelongs, ok := queryOptions["projectBelongs"]; ok && len(projectBelongs.([]int)) != 0 { 129 if projectBelongs, ok := queryOptions["projectBelongs"]; ok && len(projectBelongs.([]int)) != 0 {
122 query = query.WhereGroup(func(q *orm.Query) (*orm.Query, error) { 130 query = query.WhereGroup(func(q *orm.Query) (*orm.Query, error) {
123 for _, value := range projectBelongs.([]int) { 131 for _, value := range projectBelongs.([]int) {
@@ -57,3 +57,18 @@ func (controller *StatisticsController) PersonSuMoneyStatistics() { @@ -57,3 +57,18 @@ func (controller *StatisticsController) PersonSuMoneyStatistics() {
57 controller.Data["json"] = response 57 controller.Data["json"] = response
58 controller.ServeJSON() 58 controller.ServeJSON()
59 } 59 }
  60 +
  61 +func (controller *StatisticsController) PersonNotificationStatistics() {
  62 + statisticsService := service.NewStatisticsService(nil)
  63 + personNotificationStatisticsCommand := &command.PersonNotificationStatisticsCommand{}
  64 + json.Unmarshal(controller.Ctx.Input.GetData("requestBody").([]byte), personNotificationStatisticsCommand)
  65 + data, err := statisticsService.PersonNotificationStatistics(personNotificationStatisticsCommand)
  66 + var response utils.JsonResponse
  67 + if err != nil {
  68 + response = utils.ResponseError(controller.Ctx, err)
  69 + } else {
  70 + response = utils.ResponseData(controller.Ctx, data)
  71 + }
  72 + controller.Data["json"] = response
  73 + controller.ServeJSON()
  74 +}
@@ -9,4 +9,5 @@ func init() { @@ -9,4 +9,5 @@ func init() {
9 beego.Router("/statistics/system-task", &controllers.StatisticsController{}, "Post:SystemTaskStatistics") 9 beego.Router("/statistics/system-task", &controllers.StatisticsController{}, "Post:SystemTaskStatistics")
10 beego.Router("/statistics/person-task", &controllers.StatisticsController{}, "Post:PersonTaskStatistics") 10 beego.Router("/statistics/person-task", &controllers.StatisticsController{}, "Post:PersonTaskStatistics")
11 beego.Router("/statistics/person-su-money", &controllers.StatisticsController{}, "Post:PersonSuMoneyStatistics") 11 beego.Router("/statistics/person-su-money", &controllers.StatisticsController{}, "Post:PersonSuMoneyStatistics")
  12 + beego.Router("/statistics/person-notification", &controllers.StatisticsController{}, "Post:PersonNotificationStatistics")
12 } 13 }
  1 +package statistics
  2 +
  3 +import (
  4 + "gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/domain"
  5 + "net/http"
  6 + "time"
  7 +
  8 + "github.com/gavv/httpexpect"
  9 + "github.com/go-pg/pg"
  10 + . "github.com/onsi/ginkgo"
  11 + . "github.com/onsi/gomega"
  12 + pG "gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/infrastructure/pg"
  13 +)
  14 +
  15 +var _ = Describe("获取个人消息通知统计", func() {
  16 + var notificationId int64
  17 + var sentNotificationId int64
  18 + BeforeEach(func() {
  19 + _, err := pG.DB.QueryOne(
  20 + pg.Scan(&notificationId),
  21 + "INSERT INTO notifications (id, notification_type, notification_title, notification_content, notification_time, external_resource_type, external_resource) VALUES (?, ?, ?, ?, ?, ?, ?) RETURNING id",
  22 + 1, 1, "testNotificationTitle", "testNotificationContent", time.Now(), 1, 1)
  23 + Expect(err).NotTo(HaveOccurred())
  24 + _, err1 := pG.DB.QueryOne(
  25 + pg.Scan(&sentNotificationId),
  26 + "INSERT INTO sent_notifications (id, notification_id, receiver, is_read, read_time) VALUES (?, ?, ?, ?, ?) RETURNING id",
  27 + 1, notificationId, &domain.EmployeeInfo{
  28 + Uid: 2499036607974745088,
  29 + }, false, time.Time{})
  30 + Expect(err1).NotTo(HaveOccurred())
  31 + _, err2 := pG.DB.QueryOne(
  32 + pg.Scan(),
  33 + "INSERT INTO employees (id, company_id, uid, employee_name, employee_account, su_money) VALUES (?, ?, ?, ?, ?, ?)",
  34 + 1, 101, 2499036607974745088, "testEmployeeName", "testEmployeeAccount", 0)
  35 + Expect(err2).NotTo(HaveOccurred())
  36 + })
  37 + Describe("获取个人消息通知统计", func() {
  38 + Context("", func() {
  39 + It("", func() {
  40 + httpExpect := httpexpect.New(GinkgoT(), server.URL)
  41 + body := map[string]interface{}{
  42 + "uid": 2499036607974745088,
  43 + }
  44 + httpExpect.POST("/statistics/person-notification").
  45 + WithJSON(body).
  46 + Expect().
  47 + Status(http.StatusOK).
  48 + JSON().
  49 + Object().
  50 + ContainsKey("code").ValueEqual("code", 0).
  51 + ContainsKey("msg").ValueEqual("msg", "ok").
  52 + ContainsKey("data").Value("data").Object()
  53 + })
  54 + })
  55 + })
  56 + AfterEach(func() {
  57 + _, err := pG.DB.Exec("DELETE FROM sent_notifications WHERE true")
  58 + Expect(err).NotTo(HaveOccurred())
  59 + _, err1 := pG.DB.Exec("DELETE FROM notifications WHERE true")
  60 + Expect(err1).NotTo(HaveOccurred())
  61 + _, err2 := pG.DB.Exec("DELETE FROM employees WHERE true")
  62 + Expect(err2).NotTo(HaveOccurred())
  63 + })
  64 +})