pg_cooperation_statistics_service.go 14.0 KB
package domain_service

import (
	"encoding/json"
	"fmt"
	"github.com/go-pg/pg/v10"
	pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
	"github.com/linmadan/egglib-go/utils/tool_funs"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-cooperation/pkg/domain"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-cooperation/pkg/infrastructure/dao"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-cooperation/pkg/infrastructure/repository"
	"strconv"
	"time"
)

const (
	// 合约分红列表查询
	SearchContractDividends = "SearchContractDividends"
	// 获取分红合约详情
	GetContractDividends = "GetContractDividends"
	// 分红统计(分红明细)
	DividendsStatistics = "DividendsStatistics"

	// 企业-商品统计
	CooperationGoodsStatistics = "cooperationGoodsStatistics"
	// 企业-共创模式统计
	CooperationModeStatistics = "CooperationModeStatistics"
	// 企业-分红统计
	CompanyDividendsStatistics = "CompanyDividendsStatistics"
	// 企业、个人 - 分红预算列表
	SearchDividendsEstimates = "SearchDividendsEstimates"
	// 公司 - 共创用户统计
	CompanyCooperationUsersStatistics = "CompanyCooperationUsersStatistics"

	// 个人 - 共创企业统计
	CooperationCompanyStatistics = "CooperationCompanyStatistics"
	// 个人 - 用户合约统计
	PersonCooperationContractStatistics = "PersonCooperationContractStatistics"
)

//  CooperationStatisticsService 共创统计服务
type CooperationStatisticsService struct {
	transactionContext *pgTransaction.TransactionContext
}

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

/*****   1.合约分红模块  *****/

/*1.1 分红合约搜索*/

// 分红合约搜索
//
// queryOptions 查询参数
func (ptr *CooperationStatisticsService) SearchContractDividends(queryOptions map[string]interface{}) (interface{}, error) {
	var request = struct {
		//企业
		CompanyId int64 `json:"companyId"`
		OrgId     int64 `json:"orgId"`
		//个人
		UserBaseId int64 `json:"userBaseId"`
		Offset     int   `json:"offset"`
		Limit      int   `json:"limit"`
	}{}
	if err := LoadQueryObject(queryOptions, &request); err != nil {
		return nil, err
	}
	queryOptions = tool_funs.SimpleStructToMap(&request)

	// 1.根据个人、企业查询合约列表
	var contracts []*domain.CooperationContract
	var err error
	if _, ok := queryOptions["userBaseId"]; ok {
		contracts, err = ptr.getUserContracts(queryOptions)
	} else if v, ok := queryOptions["orgId"]; ok {
		queryOptions["orgId"], _ = (v.(json.Number)).Int64()
		contracts, err = ptr.getCompanyContracts(queryOptions)
	}
	if err != nil {
		return nil, err
	}

	// 2.根据合约查询分红预算
	var numbers []string
	var results = make([]*searchContractDividendsResult, 0)
	for i := range contracts {
		item := contracts[i]
		resultItem := &searchContractDividendsResult{
			CooperationContractId:     item.CooperationContractId,
			CooperationContractName:   item.CooperationContractName,
			CooperationContractNumber: item.CooperationContractNumber,
			Status:                    item.Status,
			CreatedAt:                 item.CreatedAt.Unix() * 1000,
		}
		results = append(results, resultItem)
		numbers = append(numbers, item.CooperationContractNumber)
	}
	mapEstimate, err := ptr.getContractsDividendsEstimate(numbers)
	if err != nil {
		return nil, err
	}
	for i := range results {
		if v, ok := mapEstimate[results[i].CooperationContractNumber]; ok {
			results[i].DividendsAmount = v.DividendsAmount
		}
	}

	// TODO: 3.根据合约查询订单金额
	//for i:=range results{
	//	queryOptions["cooperationContractNumber"] =results[i].CooperationContractNumber
	//	results[i].DividendsOrderAmount = ptr.CalculateOrderAmount(queryOptions)
	//}
	return results, nil
}

// getUserContracts  获取用户的合约列表
//
// p1 p1_desc
func (ptr *CooperationStatisticsService) getUserContracts(queryOptions map[string]interface{}) ([]*domain.CooperationContract, error) {
	undertakerRepository, _ := repository.NewCooperationContractUndertakerRepository(ptr.transactionContext)
	_, undertakers, err := undertakerRepository.Find(queryOptions)
	var numbers []string
	for i := range undertakers {
		numbers = append(numbers, undertakers[i].CooperationContractNumber)
	}
	if len(numbers) == 0 {
		return []*domain.CooperationContract{}, nil
	}
	queryOptions["inCooperationContractNumber"] = numbers
	contractRepository, _ := repository.NewCooperationContractRepository(ptr.transactionContext)
	_, contracts, err := contractRepository.Find(queryOptions)
	return contracts, err
}

// getCompanyContracts  获取组织合约列表
//
// p1 p1_desc
func (ptr *CooperationStatisticsService) getCompanyContracts(queryOptions map[string]interface{}) ([]*domain.CooperationContract, error) {
	contractRepository, _ := repository.NewCooperationContractRepository(ptr.transactionContext)
	// TODO:  参数查询条件
	_, contracts, err := contractRepository.Find(queryOptions)
	return contracts, err
}

// getContractsDividendsEstimate 合约分红预算
func (ptr *CooperationStatisticsService) getContractsDividendsEstimate(numbers []string) (map[string]*domain.DividendsEstimate, error) {
	var estimates []*domain.DividendsEstimate
	var resMap = make(map[string]*domain.DividendsEstimate)
	if len(numbers) == 0 {
		return resMap, nil
	}
	_, err := ptr.transactionContext.PgDd.Query(&estimates, `select cooperation_contract_number,sum(dividends_amount) dividends_amount from dividends_estimates 
where cooperation_contract_number in (?)
group by cooperation_contract_number
`, pg.In(numbers))
	if err != nil {
		return nil, err
	}

	for i := range estimates {
		resMap[estimates[i].CooperationContractNumber] = estimates[i]
	}
	return resMap, nil
}

type searchContractDividendsResult struct {
	// 共创合约ID
	CooperationContractId int64 `json:"cooperationContractId,string"`
	// 共创合约名称
	CooperationContractName string `json:"cooperationContractName"`
	// 共创合约编号
	CooperationContractNumber string `json:"cooperationContractNumber"`
	// 合约状态,1恢复,2暂停
	Status int32 `json:"cooperationContractStatus"`
	// 分红预算
	DividendsAmount float64 `json:"dividendsAmount"`
	// 分红订单金额
	DividendsOrderAmount float64 `json:"dividendsOrderAmount"`
	// 创建时间
	CreatedAt int64 `json:"createdAt"`
}

/*1.2 分红合约详情*/

//GetContractDividends 分红合约详情
//
// queryOptions 查询参数
func (ptr *CooperationStatisticsService) GetContractDividends(queryOptions map[string]interface{}) (interface{}, error) {
	// 1.合约详情
	contractRepository, _ := repository.NewCooperationContractRepository(ptr.transactionContext)
	if _, ok := queryOptions["contractId"]; !ok {
		return nil, fmt.Errorf("合约ID(contractId)不能为空")
	}
	var res = make(map[string]interface{})
	contract, err := contractRepository.FindOne(map[string]interface{}{"cooperationContractId": queryOptions["contractId"]})
	if err != nil {
		return nil, err
	}
	res["cooperationContract"] = map[string]interface{}{
		"cooperationContractDescription": contract.CooperationContractDescription,
		"cooperationContractId":          contract.CooperationContractId,
		"cooperationContractName":        contract.CooperationContractName,
		"cooperationContractNumber":      contract.CooperationContractNumber,
		"createdAt":                      contract.CreatedAt.Unix() * 1000,
		"status":                         contract.Status,
	}

	// 2.合约分红列表
	creditAccountRepository, _ := repository.NewCreditAccountRepository(ptr.transactionContext)
	queryOptions["cooperationContractNumber"] = contract.CooperationContractNumber
	_, creditAccounts, err := creditAccountRepository.Find(queryOptions)
	if err != nil {
		return res, err
	}
	var dividends = make([]interface{}, 0)
	for i := range creditAccounts {
		a := creditAccounts[i]
		for j := range a.AccountDetail {
			participateType, _ := strconv.Atoi(a.ParticipateType)
			item := map[string]interface{}{
				"creditAccountId": a.CreditAccountId,
				"orderGoodName":   "",
				"dividendsType":   0,
				"dividendsRatio":  0,
				"dividendsAmount": a.AccountDetail[j].DividendsAmount,
				"dividendsUser": map[string]interface{}{
					"userInfo": a.Participator.UserInfo,
					"userId":   a.Participator.UserId,
				},
				"dividendsParticipateType": participateType,
				"dividendsAccountStatus":   a.PaymentStatus,
				"dividendsEstimateTime":    a.CreatedAt.Unix() * 1000,
				"orderOrReturnedOrderNum":  a.CreditAccountOrderNum,
			}
			item["dividendsType"] = a.AccountDetail[j].DividendsType
			dividends = append(dividends, item)
		}

	}
	res["dividends"] = dividends
	return res, nil
}

// 分红统计(分红明细)
func (ptr *CooperationStatisticsService) DividendsStatistics(queryOptions map[string]interface{}) (interface{}, error) {
	// 参数验证
	var request = struct {
		//企业
		CompanyId int64 `json:"companyId"`
		OrgId     int64 `json:"orgId"`
		//个人
		UserBaseId int64 `json:"userBaseId"`
	}{}
	if err := LoadQueryObject(queryOptions, &request); err != nil {
		return nil, err
	}
	queryOptions = tool_funs.SimpleStructToMap(&request)

	type response struct {
		Total      float64 `json:"total"`
		Accounting float64 `json:"accounting"`
		Accounted  float64 `json:"accounted"`
		Paid       float64 `json:"paid"`
	}
	creditAccountDao, _ := dao.NewCreditAccountDao(ptr.transactionContext)

	var allDividends = &response{}
	if err := creditAccountDao.DividendsStatistics(queryOptions, allDividends); err != nil {
		return nil, err
	}
	allDividends.Accounting = allDividends.Total - allDividends.Accounted

	var annualDividends = &response{}
	queryOptions["beginTime"] = time.Date(time.Now().Year(), 1, 1, 0, 0, 0, 0, time.Local)
	queryOptions["endTime"] = time.Date(time.Now().Year(), 1, 1, 0, 0, 0, 0, time.Local).AddDate(1, 0, 0)
	if err := creditAccountDao.DividendsStatistics(queryOptions, annualDividends); err != nil {
		return nil, err
	}
	annualDividends.Accounting = annualDividends.Total - annualDividends.Accounted

	var quarterDividends = &response{}
	queryOptions["beginTime"], queryOptions["endTime"] = quarterBeginEnd()
	if err := creditAccountDao.DividendsStatistics(queryOptions, quarterDividends); err != nil {
		return nil, err
	}
	quarterDividends.Accounting = quarterDividends.Total - quarterDividends.Accounted

	ret := map[string]interface{}{
		"allDividends":     allDividends,
		"annualDividends":  annualDividends,
		"quarterDividends": quarterDividends,
	}
	return ret, nil
}

func quarterBeginEnd() (time.Time, time.Time) {
	y := time.Now().Year()
	m := time.Now().Month()
	var mBegin, mEnd int
	var begin, end time.Time
	switch m {
	case 4, 5, 6:
		mBegin = 4
		mEnd = 6
	case 7, 8, 9:
		mBegin = 7
		mEnd = 9
	case 10, 11, 12:
		mBegin = 10
		mEnd = 12
	case 1, 2, 3:
		mBegin = 1
		mEnd = 3
	}
	begin = time.Date(y, time.Month(mBegin), 1, 0, 0, 0, 0, time.Local)
	end = time.Date(y, time.Month(mEnd), 1, 0, 0, 0, 0, time.Local)
	return begin, end
}

// 分红预算列表
func (ptr *CooperationStatisticsService) SearchDividendsEstimates(queryOptions map[string]interface{}) (interface{}, error) {
	// 参数验证
	var request = struct {
		CompanyId              int64 `json:"companyId"`
		OrgId                  int64 `json:"orgId"`
		UserBaseId             int64 `json:"userBaseId"`
		DividendsAccountStatus int32 `json:"dividendsAccountStatus"` // 分红结算状态
		Offset                 int64 `json:"offset"`
		Limit                  int64 `json:"limit"`
	}{}
	if err := LoadQueryObject(queryOptions, &request); err != nil {
		return nil, err
	}
	queryOptions = tool_funs.SimpleStructToMap(&request)

	dividendsEstimateRepository, _ := repository.NewDividendsEstimateRepository(ptr.transactionContext)
	_, estimates, err := dividendsEstimateRepository.Find(queryOptions)
	if err != nil {
		return nil, err
	}
	type response struct {
		// 承接人分红预算记录ID
		DividendsEstimateId int64 `json:"dividendsEstimateId,string"`
		// 分红结算状态,1待结算,2已结算
		DividendsAccountStatus int32 `json:"dividendsAccountStatus"`
		// 分红金额
		DividendsAmount float64 `json:"dividendsAmount"`
		// 参与分红类型,1承接人,2推荐人,3关联业务员
		DividendsParticipateType int32 `json:"dividendsParticipateType"`
		// 分红类型,1订单分红,2退货冲销,3金额激励
		DividendsType int32 `json:"dividendsType"`
		// 分红用户(共创参与)
		DividendsUser *domain.User `json:"dividendsUser"`
		// 分红订单金额
		DividendsOrderAmount float64 `json:"dividendsOrderAmount"`
		//OrderGoodName string `json:"orderGoodName"`
		CustomerName string `json:"customerName"`
	}
	var results = make([]response, 0)
	dividendsOrderRepository, _ := repository.NewDividendsOrderRepository(ptr.transactionContext)
	dividendsReturnedOrderRepository, _ := repository.NewDividendsReturnedOrderRepository(ptr.transactionContext)
	for i := range estimates {
		item := estimates[i]
		result := response{
			DividendsEstimateId:      item.DividendsEstimateId,
			DividendsAccountStatus:   item.DividendsAccountStatus,
			DividendsAmount:          item.DividendsAmount,
			DividendsParticipateType: item.DividendsParticipateType,
			DividendsType:            item.DividendsType,
			DividendsUser:            item.DividendsUser,
		}
		if item.DividendsType == 1 {
			order, err := dividendsOrderRepository.FindOne(map[string]interface{}{"dividendsOrderNumber": item.OrderOrReturnedOrderNum})
			if err != nil {
				return nil, err
			}
			result.DividendsOrderAmount = order.DividendsOrderAmount
			result.CustomerName = order.CustomerName
		} else if item.DividendsType == 2 {
			order, err := dividendsReturnedOrderRepository.FindOne(map[string]interface{}{"dividendsReturnedOrderNumber": item.OrderOrReturnedOrderNum})
			if err != nil {
				return nil, err
			}
			result.DividendsOrderAmount = order.DividendsReturnedOrderRefund
			result.CustomerName = order.DividendsReturnedCustomerName
		}
		results = append(results, result)
	}
	return results, nil
}