pg_task_repository.go 14.8 KB
package repository

import (
	"fmt"
	"github.com/go-pg/pg"
	"github.com/go-pg/pg/orm"
	pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
	"github.com/linmadan/egglib-go/utils/snowflake"
	"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/domain"
	"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/infrastructure/pg/models"
	"time"
)

type TaskRepository struct {
	transactionContext *pgTransaction.TransactionContext
}

func (repository *TaskRepository) nextIdentify() (int64, error) {
	IdWorker, err := snowflake.NewIdWorker(1)
	if err != nil {
		return 0, err
	}
	id, err := IdWorker.NextId()
	return id, err
}
func (repository *TaskRepository) Save(task *domain.Task) (*domain.Task, error) {
	tx := repository.transactionContext.PgTx
	if task.Identify() == nil {
		takeId, err := repository.nextIdentify()
		if err != nil {
			return task, err
		}
		if _, err := tx.QueryOne(
			pg.Scan(&task.TaskId, &task.CompanyId, &task.TaskName, &task.TaskType, &task.Sponsor, &task.TaskStatus, &task.ReferenceResource, pg.Array(&task.CustomerValue), &task.TaskNature, &task.SuMoney, &task.AcceptanceStandard, &task.TaskDescription, pg.Array(&task.TaskPictureUrls), &task.IsRewardTake, &task.CreateTime, &task.ReleaseTime, &task.Participators, &task.TaskPercentage, &task.SolveReport, pg.Array(&task.SolvePictureUrls)),
			"INSERT INTO tasks (id, company_id, task_name, task_type, sponsor, task_status, reference_resource, customer_value, task_nature, su_money, acceptance_standard, task_description, task_picture_urls, is_reward_take, create_time, release_time, participators, task_percentage, solve_report, solve_picture_urls) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING id, company_id, task_name, task_type, sponsor, task_status, reference_resource, customer_value, task_nature, su_money, acceptance_standard, task_description, task_picture_urls, is_reward_take, create_time, release_time, participators, task_percentage, solve_report, solve_picture_urls",
			takeId, task.CompanyId, task.TaskName, task.TaskType, task.Sponsor, task.TaskStatus, task.ReferenceResource, pg.Array(task.CustomerValue), task.TaskNature, task.SuMoney, task.AcceptanceStandard, task.TaskDescription, pg.Array(task.TaskPictureUrls), task.IsRewardTake, task.CreateTime, task.ReleaseTime, task.Participators, task.TaskPercentage, task.SolveReport, pg.Array(task.SolvePictureUrls)); err != nil {
			return task, err
		}
	} else {
		var taskReceiverUid int64
		if task.RobInfo != nil && task.RobInfo.Receiver != nil {
			taskReceiverUid = task.RobInfo.Receiver.Uid
		}
		if task.BidInfo != nil && task.BidInfo.SuccessfulBidder != nil {
			taskReceiverUid = task.BidInfo.SuccessfulBidder.Uid
		}
		if _, err := tx.QueryOne(
			pg.Scan(&task.TaskId, &task.CompanyId, &task.TaskName, &task.TaskType, &task.Sponsor, &task.TaskStatus, &task.ReferenceResource, pg.Array(&task.CustomerValue), &task.TaskNature, &task.SuMoney, &task.AcceptanceStandard, &task.TaskDescription, pg.Array(&task.TaskPictureUrls), &task.IsRewardTake, &task.CreateTime, &task.ReleaseTime, &task.Participators, &task.TaskPercentage, &task.SolveReport, pg.Array(&task.SolvePictureUrls)),
			"UPDATE tasks SET company_id=?, task_name=?, task_type=?, sponsor=?, task_status=?, reference_resource=?, customer_value=?, task_nature=?, su_money=?, acceptance_standard=?, task_description=?, task_picture_urls=?, is_reward_take=?, receiver_uid=?, create_time=?, release_time=?, participators=?, task_percentage=?, solve_report=?, solve_picture_urls=?, receive_time=?, complete_time=?, acceptance_time=? WHERE id=? RETURNING id, company_id, task_name, task_type, sponsor, task_status, reference_resource, customer_value, task_nature, su_money, acceptance_standard, task_description, task_picture_urls, is_reward_take, create_time, release_time, participators, task_percentage, solve_report, solve_picture_urls",
			task.CompanyId, task.TaskName, task.TaskType, task.Sponsor, task.TaskStatus, task.ReferenceResource, pg.Array(task.CustomerValue), task.TaskNature, task.SuMoney, task.AcceptanceStandard, task.TaskDescription, pg.Array(task.TaskPictureUrls), task.IsRewardTake, taskReceiverUid, task.CreateTime, task.ReleaseTime, task.Participators, task.TaskPercentage, task.SolveReport, pg.Array(task.SolvePictureUrls), task.ReceiveTime, task.CompleteTime, task.AcceptanceTime, task.Identify()); err != nil {
			return task, err
		}
	}
	return task, nil
}
func (repository *TaskRepository) Remove(task *domain.Task) (*domain.Task, error) {
	tx := repository.transactionContext.PgTx
	taskModel := new(models.Task)
	taskModel.Id = task.Identify().(int64)
	if _, err := tx.Model(taskModel).WherePK().Delete(); err != nil {
		return task, err
	}
	return task, nil
}
func (repository *TaskRepository) FindOne(queryOptions map[string]interface{}) (*domain.Task, error) {
	tx := repository.transactionContext.PgTx
	taskModel := new(models.Task)
	query := tx.Model(taskModel).Relation("RobInfo").Relation("BidInfo")
	if taskId, ok := queryOptions["taskId"]; ok {
		query = query.Where("task.id = ?", taskId)

	}
	if err := query.First(); err != nil {
		if err.Error() == "pg: no rows in result set" {
			return nil, fmt.Errorf("没有此任务")
		} else {
			return nil, err
		}
	}
	if taskModel.Id == 0 {
		return nil, nil
	} else {
		if taskModel.BidInfo != nil {
			var bidderInfoModels []*models.BidderInfo
			bidderInfoQuery := tx.Model(&bidderInfoModels)
			if err := bidderInfoQuery.Where("task_id = ?", taskModel.Id).Select(); err != nil {
				return nil, err
			}
			taskModel.BidInfo.BidderInfos = bidderInfoModels
		}
		return repository.transformPgModelToDomainModel(taskModel)
	}
}
func (repository *TaskRepository) Find(queryOptions map[string]interface{}) (int64, []*domain.Task, error) {
	tx := repository.transactionContext.PgTx
	var taskModels []*models.Task
	tasks := make([]*domain.Task, 0)
	query := tx.Model(&taskModels).Relation("RobInfo").Relation("BidInfo")
	if companyId, ok := queryOptions["companyId"]; ok {
		query = query.Where("task.company_id = ?", companyId)
	}
	if isFilterCloseStatus, ok := queryOptions["isFilterCloseStatus"]; ok && isFilterCloseStatus.(bool) != false {
		query = query.Where("task.task_status <> ? ", domain.TASK_STATUS_CLOSED)
	}
	if isFilterUnReleasedStatus, ok := queryOptions["isFilterUnReleasedStatus"]; ok && isFilterUnReleasedStatus.(bool) != false {
		query = query.Where("task.task_status <> ? ", domain.TASK_STATUS_UNRELEASED)
	}
	if sponsor, ok := queryOptions["sponsor"]; ok && (sponsor != int64(0)) {
		query = query.Where(`task.sponsor @> '{"uid":?}'`, sponsor)
	}
	if taskStatus, ok := queryOptions["taskStatus"]; ok && (taskStatus != 0) {
		query = query.Where(`task.task_status = ?`, taskStatus)
	}
	if taskType, ok := queryOptions["taskType"]; ok && (taskType != 0) {
		query = query.Where(`task.task_type = ?`, taskType)
	}
	if taskNature, ok := queryOptions["taskNature"]; ok && (taskNature != "") {
		query = query.Where(`task.task_nature = ?`, taskNature)
	}
	if customerValue, ok := queryOptions["customerValue"]; ok && len(customerValue.([]string)) != 0 {
		query = query.WhereGroup(func(q *orm.Query) (*orm.Query, error) {
			for _, value := range customerValue.([]string) {
				q = q.WhereOr("task.customer_value @> ?", pg.Array([]string{value}))
			}
			return q, nil
		})
	}
	if taskContentMatch, ok := queryOptions["taskContentMatch"]; ok && (taskContentMatch != "") {
		query = query.WhereGroup(func(q *orm.Query) (*orm.Query, error) {
			q = q.WhereOr("task.task_name LIKE ?", fmt.Sprintf("%%%s%%", taskContentMatch.(string))).
				WhereOr("task.task_nature = ?", taskContentMatch.(string)).
				WhereOr("task.customer_value @> ?", pg.Array([]string{taskContentMatch.(string)}))
			return q, nil
		})
	}
	if isRewardTake, ok := queryOptions["isRewardTake"]; ok && (isRewardTake != false) {
		query = query.Where(`task.is_reward_take = ?`, isRewardTake)
	}
	if bidTimeMatch, ok := queryOptions["bidTimeMatch"]; ok && (bidTimeMatch != 0) {
		if bidTimeMatch == 2 {
			query = query.Where("bid_info.bid_end_time < ?", time.Now())
		}
		if bidTimeMatch == 3 {
			query = query.Where("bid_info.bid_end_time > ?", time.Now())
		}
	}
	if bidder, ok := queryOptions["bidder"]; ok && (bidder != int64(0)) {
		query = query.Join("JOIN bidder_infos AS bidder_info ON bidder_info.task_id = task.id")
		query = query.Where(`bidder_info.bidder @> '{"uid":?}'`, bidder)
	}
	if receiver, ok := queryOptions["receiver"]; ok && (receiver != int64(0)) {
		query = query.Where(`task.receiver_uid = ?`, receiver)
	}
	if participator, ok := queryOptions["participator"]; ok && (participator != int64(0)) {
		query = query.Where(`task.participators @> '[{"uid":?}]'`, participator)
	}
	if taskIds, ok := queryOptions["taskIds"]; ok {
		query = query.Where(`task.id IN (?)`, pg.In(taskIds.([]int64)))
	}
	if offRangTime, ok := queryOptions["offRangTime"]; ok {
		query = query.Join("JOIN off_task_records ON off_task_record.task_id = task.id")
		if offStartTime, ok := offRangTime.(map[string]time.Time)["offStartTime"]; ok {
			query = query.Where("off_task_record.create_time > ?", offStartTime)
		}
		if offEndTime, ok := offRangTime.(map[string]time.Time)["offEndTime"]; ok {
			query = query.Where("off_task_record.create_time < ?", offEndTime)
		}
	}
	if referenceResourceIds, ok := queryOptions["referenceResourceIds"]; ok && len(referenceResourceIds.([]int64)) != 0 {
		query = query.WhereGroup(func(q *orm.Query) (*orm.Query, error) {
			for _, value := range referenceResourceIds.([]int64) {
				q = q.WhereOr(`task.reference_resource @> '{"referenceResourceItems":[{"referenceResourceId":?}]}'`, value)
			}
			return q, nil
		})
	}
	if offset, ok := queryOptions["offset"]; ok {
		offset := offset.(int)
		if offset > -1 {
			query = query.Offset(offset)
		}
	} else {
		query = query.Offset(0)
	}
	if limit, ok := queryOptions["limit"]; ok {
		limit := limit.(int)
		if limit > -1 {
			query = query.Limit(limit)
		}
	} else {
		query = query.Limit(20)
	}
	if sortByCreateTime, ok := queryOptions["sortByCreateTime"]; ok && (sortByCreateTime == "ASC" || sortByCreateTime == "DESC") {
		query = query.Order(fmt.Sprintf("task.create_time %s", sortByCreateTime.(string)))
	} else if sortByReleaseTime, ok := queryOptions["sortByReleaseTime"]; ok && (sortByReleaseTime == "ASC" || sortByReleaseTime == "DESC") {
		query = query.Order(fmt.Sprintf("task.release_time %s", sortByReleaseTime.(string)))
	} else if sortByReceiveTime, ok := queryOptions["sortByReceiveTime"]; ok && (sortByReceiveTime == "ASC" || sortByReceiveTime == "DESC") {
		query = query.Order(fmt.Sprintf("task.receive_time %s", sortByReceiveTime.(string)))
	} else if sortByCompleteTime, ok := queryOptions["sortByCompleteTime"]; ok && (sortByCompleteTime == "ASC" || sortByCompleteTime == "DESC") {
		query = query.Order(fmt.Sprintf("task.complete_time %s", sortByCompleteTime.(string)))
	} else if sortByAcceptanceTime, ok := queryOptions["sortByAcceptanceTime"]; ok && (sortByAcceptanceTime == "ASC" || sortByAcceptanceTime == "DESC") {
		query = query.Order(fmt.Sprintf("task.acceptance_time %s", sortByAcceptanceTime.(string)))
	} else if sortByBidTime, ok := queryOptions["sortByBidTime"]; ok && (sortByBidTime == "ASC" || sortByBidTime == "DESC") {
		if bidder, ok := queryOptions["bidder"]; ok && (bidder != int64(0)) {
			query = query.Order(fmt.Sprintf("bidder_info.bid_time %s", sortByBidTime.(string)))
		}
	} else {
		query = query.Order("task.id DESC")
	}
	if count, err := query.SelectAndCount(); err != nil {
		return 0, tasks, err
	} else {
		for _, taskModel := range taskModels {
			if taskModel.BidInfo != nil {
				var bidderInfoModels []*models.BidderInfo
				bidderInfoQuery := tx.Model(&bidderInfoModels)
				if err := bidderInfoQuery.Where("task_id = ?", taskModel.Id).Select(); err != nil {
					return int64(count), tasks, nil
				}
				taskModel.BidInfo.BidderInfos = bidderInfoModels
			}
			if take, err := repository.transformPgModelToDomainModel(taskModel); err == nil {
				tasks = append(tasks, take)
			} else {
				return 0, tasks, err
			}
		}
		return int64(count), tasks, nil
	}
}

func (repository *TaskRepository) transformPgModelToDomainModel(taskModel *models.Task) (*domain.Task, error) {
	var robInfo *domain.RobInfo
	if taskModel.RobInfo == nil {
		robInfo = nil
	} else {
		robInfo = &domain.RobInfo{
			Receiver:    taskModel.RobInfo.Receiver,
			ReceiveTime: taskModel.RobInfo.ReceiveTime,
		}
	}
	var bidInfo *domain.BidInfo
	if taskModel.BidInfo == nil {
		bidInfo = nil
	} else {
		bidderInfos := make([]*domain.BidderInfo, 0)
		for _, bidderInfo := range taskModel.BidInfo.BidderInfos {
			bidderInfos = append(bidderInfos, &domain.BidderInfo{
				Bidder:  bidderInfo.Bidder,
				BidTime: bidderInfo.BidTime,
			})
		}
		bidInfo = &domain.BidInfo{
			BidderInfos:      bidderInfos,
			BidStartTime:     taskModel.BidInfo.BidStartTime,
			BidEndTime:       taskModel.BidInfo.BidEndTime,
			SuccessfulBidder: taskModel.BidInfo.SuccessfulBidder,
			WinBidTime:       taskModel.BidInfo.WinBidTime,
		}
	}
	var currentStatus domain.TaskStatus
	switch taskModel.TaskStatus {
	case domain.TASK_STATUS_UNRELEASED:
		currentStatus = &domain.UnReleasedStatus{}
		break
	case domain.TASK_STATUS_UNCLAIMED:
		currentStatus = &domain.UnClaimedStatus{}
		break
	case domain.TASK_STATUS_UNDERWAY:
		currentStatus = &domain.UnderwayStatus{}
		break
	case domain.TASK_STATUS_UNACCEPTANCE:
		currentStatus = &domain.UnAcceptanceStatus{}
		break
	case domain.TASK_STATUS_COMPLETED:
		currentStatus = &domain.CompletedStatus{}
		break
	case domain.TASK_STATUS_CLOSED:
		currentStatus = &domain.ClosedStatus{}
		break
	}
	return &domain.Task{
		TaskId:             taskModel.Id,
		CompanyId:          taskModel.CompanyId,
		TaskName:           taskModel.TaskName,
		TaskType:           taskModel.TaskType,
		Sponsor:            taskModel.Sponsor,
		TaskStatus:         taskModel.TaskStatus,
		ReferenceResource:  taskModel.ReferenceResource,
		CustomerValue:      taskModel.CustomerValue,
		TaskNature:         taskModel.TaskNature,
		SuMoney:            taskModel.SuMoney,
		AcceptanceStandard: taskModel.AcceptanceStandard,
		TaskDescription:    taskModel.TaskDescription,
		TaskPictureUrls:    taskModel.TaskPictureUrls,
		IsRewardTake:       taskModel.IsRewardTake,
		CreateTime:         taskModel.CreateTime,
		ReleaseTime:        taskModel.ReleaseTime,
		ReceiveTime:        taskModel.ReceiveTime,
		CompleteTime:       taskModel.CompleteTime,
		AcceptanceTime:     taskModel.AcceptanceTime,
		RobInfo:            robInfo,
		BidInfo:            bidInfo,
		Participators:      taskModel.Participators,
		TaskPercentage:     taskModel.TaskPercentage,
		SolveReport:        taskModel.SolveReport,
		SolvePictureUrls:   taskModel.SolvePictureUrls,
		CurrentStatus:      currentStatus,
	}, nil
}

func NewTaskRepository(transactionContext *pgTransaction.TransactionContext) (*TaskRepository, error) {
	if transactionContext == nil {
		return nil, fmt.Errorf("transactionContext参数不能为nil")
	} else {
		return &TaskRepository{
			transactionContext: transactionContext,
		}, nil
	}
}