/*
 * @description: 合同数据相关操作
 * @Author: CP
 * @Date: 2020-10-27 11:28:24
 * @FilePath: \construction_management\services\contract_service.go
 */
package services

import (
	"errors"
	"fmt"
	"html"
	"log"
	"strconv"
	"time"

	"github.com/kataras/iris/v12"
	"github.com/leekchan/accounting"
	"go.mod/comm"
	"go.mod/conf"
	"go.mod/dao"
	"go.mod/datasource"
	"go.mod/models"
	"go.mod/web/viewmodels"
)

//定义项目用户Service接口
type ContractService interface {
	ValidRuleDepth(ctx iris.Context) (*viewmodels.TreeSectionContract, error)
	ValidRuleTemplate(ctx iris.Context) (*viewmodels.TreeSectionContract, error)
	ValidRuleSectionAdd(ctx iris.Context) (*viewmodels.TreeSectionContract, error)
	ValidRuleSectionDelete(ctx iris.Context) (*viewmodels.TreeSectionContract, error)
	ValidRuleGet(ctx iris.Context) (*viewmodels.TreeSectionContract, error)
	ValidRuleSerial(ctx iris.Context) (*viewmodels.TreeSectionContract, error)
	ValidRuleContractAdd(ctx iris.Context) (*viewmodels.Contracts, error)
	ValidRuleContractEdi(ctx iris.Context) (*viewmodels.Contracts, error)
	ValidRuleContractDel(ctx iris.Context) (*viewmodels.Contracts, error)
	ValidRuleContractRetrunAdd(ctx iris.Context) (*viewmodels.ContractsReturn, error)
	ValidRuleContractRetrun(ctx iris.Context) (*viewmodels.ContractsReturn, error)
	ValidRuleContractRetrunDel(ctx iris.Context) (*viewmodels.ContractsReturn, error)

	ValidRuleContractPaidAdd(ctx iris.Context) (*viewmodels.ContractsPaid, error)
	ValidRuleContractPaid(ctx iris.Context) (*viewmodels.ContractsPaid, error)
	ValidRuleContractPaidDel(ctx iris.Context) (*viewmodels.ContractsPaid, error)

	Get(treeId int, bidsectionId int, projectId int) *viewmodels.TreeSectionContract
	GetSectionTreeContract(attribution string, bidsectionId int, projectId int, treeType int) []*viewmodels.Contracts
	GetSecionTree(bidsectionId int, projectId int, treeType int) *viewmodels.TreeSectionContract
	SetSection(templateNumber int, bidsectionId int, projectIdInt int, treeType int) error
	SectionAdd(sectionData *viewmodels.TreeSectionContract, bidsectionId int, projectId int, treeType int) error
	SectionSave(sectionData *viewmodels.TreeSectionContract, bidsectionId int, projectId int, treeType int) error
	UpdateSerial(sectionData *viewmodels.TreeSectionContract, bidsectionId int, projectId int, treeType int) error
	SectionDelete(treeId int, bidsectionId int, projectId int, treeType int) error
	MoveDepth(sectionData *viewmodels.TreeSectionContract, bidsectionId int, projectId int, treeType int) error
	MoveSerial(sectionData *viewmodels.TreeSectionContract, bidsectionId int, projectId int, treeType int) error

	GetContract(contractId int) *viewmodels.Contracts
	Add(contractData *viewmodels.Contracts, projectId int, bidsectionId int, treeId int) error
	Update(contractData *viewmodels.Contracts, projectId int, bidsectionId int, treeId int) error
	Delete(projectId int, bidsectionId int, treeId int, id int) error
	Close(projectId int, bidsectionId int, treeId int, id int) error
	Unlock(projectId int, bidsectionId int, treeId int, id int) error
	GetSurvey(bidsectionId int, projectId int, contractsType int) map[string]interface{}

	ReturnCreate(returnData *viewmodels.ContractsReturn, projectId int, bidsectionId int, contractsId int, projectAccountId int) error
	ReturnUpdate(returnData *viewmodels.ContractsReturn, projectId int, bidsectionId int, contractsId int, id int) error
	ReturnAll(projectId int, bidsectionId int, contractsId int, page int) []*viewmodels.ContractsReturn
	ReturnDelete(projectId int, bidsectionId int, contractsId int, id int) error

	//支出合同
	AddExpenditure(contractData *viewmodels.Contracts, projectId int, bidsectionId int, treeId int) error
	UpdateExpenditure(contractData *viewmodels.Contracts, projectId int, bidsectionId int, treeId int) error
	DeleteExpenditure(projectId int, bidsectionId int, treeId int, id int) error

	// 已支付
	PaidAll(projectId int, bidsectionId int, contractsId int, page int) []*viewmodels.ContractsPaid
	PaidCreate(returnData *viewmodels.ContractsPaid, projectId int, bidsectionId int, contractsId int, projectAccountId int) error
	PaidUpdate(returnData *viewmodels.ContractsPaid, projectId int, bidsectionId int, contractsId int, id int) error
	PaidDelete(projectId int, bidsectionId int, contractsId int, id int) error
}

//返回service操作类
type contractService struct {
	treeContractDao   *dao.TreeContractDao
	contractDao       *dao.ContractDao
	contractReturnDao *dao.ContractReturnDao
	contractPaidDao   *dao.ContractPaidDao
	treeDao           *dao.TreeDao
	annexDao          *dao.AnnexDao
}

//创建项目用户service
func NewContractService() ContractService {
	return &contractService{
		treeContractDao:   dao.NewTreeContractDao(datasource.InstanceDbMaster()),
		contractDao:       dao.NewContractDao(datasource.InstanceDbMaster()),
		contractReturnDao: dao.NewContractReturnDao(datasource.InstanceDbMaster()),
		contractPaidDao:   dao.NewContractPaidDao(datasource.InstanceDbMaster()),
		treeDao:           dao.NewTreeDao(datasource.InstanceDbMaster()),
		annexDao:          dao.NewAnnexDao(datasource.InstanceDbMaster()),
	}
}

// 升级降级规则验证
func (s *contractService) ValidRuleDepth(ctx iris.Context) (*viewmodels.TreeSectionContract, error) {
	treeSectionVaild := &viewmodels.TreeSectionContract{}
	err := ctx.ReadJSON(treeSectionVaild)
	if err != nil {
		log.Println("folder-ValidRule-ReadForm转换异常, error=", err)
		return treeSectionVaild, err
	}

	err = treeSectionVaild.ValidateDepth()
	if err != nil {
		log.Println("参数验证错误, error=", err)
		return treeSectionVaild, err
	}

	return treeSectionVaild, nil
}

// 模板规则验证
func (s *contractService) ValidRuleTemplate(ctx iris.Context) (*viewmodels.TreeSectionContract, error) {
	treeSectionVaild := &viewmodels.TreeSectionContract{}
	err := ctx.ReadJSON(treeSectionVaild)
	if err != nil {
		log.Println("folder-ValidRule-ReadForm转换异常, error=", err)
		return treeSectionVaild, err
	}

	err = treeSectionVaild.ValidateTemplate()
	if err != nil {
		log.Println("参数验证错误, error=", err)
		return treeSectionVaild, err
	}

	return treeSectionVaild, nil
}

// 模板规则新增项目节
func (s *contractService) ValidRuleSectionAdd(ctx iris.Context) (*viewmodels.TreeSectionContract, error) {
	treeSectionVaild := &viewmodels.TreeSectionContract{}
	err := ctx.ReadJSON(treeSectionVaild)
	if err != nil {
		log.Println("folder-ValidRule-ReadForm转换异常, error=", err)
		return treeSectionVaild, err
	}

	err = treeSectionVaild.ValidateSectionAdd()
	if err != nil {
		log.Println("参数验证错误, error=", err)
		return treeSectionVaild, err
	}

	return treeSectionVaild, nil
}

// 模板规则新增项目节
func (s *contractService) ValidRuleSectionDelete(ctx iris.Context) (*viewmodels.TreeSectionContract, error) {
	treeSectionVaild := &viewmodels.TreeSectionContract{}
	err := ctx.ReadForm(treeSectionVaild)
	if err != nil {
		log.Println("folder-ValidRule-ReadForm转换异常, error=", err)
		return treeSectionVaild, err
	}

	err = treeSectionVaild.ValidateSectionDelete()
	if err != nil {
		log.Println("参数验证错误, error=", err)
		return treeSectionVaild, err
	}

	return treeSectionVaild, nil
}

func (s *contractService) ValidRuleGet(ctx iris.Context) (*viewmodels.TreeSectionContract, error) {
	treeSectionVaild := &viewmodels.TreeSectionContract{}
	err := ctx.ReadForm(treeSectionVaild)
	if err != nil {
		log.Println("folder-ValidRule-ReadForm转换异常, error=", err)
		return treeSectionVaild, err
	}

	err = treeSectionVaild.ValidateSectionDelete()
	if err != nil {
		log.Println("参数验证错误, error=", err)
		return treeSectionVaild, err
	}
	return treeSectionVaild, nil
}

// 验证序号相关
func (s *contractService) ValidRuleSerial(ctx iris.Context) (*viewmodels.TreeSectionContract, error) {
	treeSectionVaild := &viewmodels.TreeSectionContract{}
	err := ctx.ReadJSON(treeSectionVaild)
	if err != nil {
		log.Println("folder-ValidRule-ReadForm转换异常, error=", err)
		return treeSectionVaild, err
	}

	err = treeSectionVaild.ValidateSectionSerial()
	if err != nil {
		log.Println("参数验证错误, error=", err)
		return treeSectionVaild, err
	}
	return treeSectionVaild, nil
}

// 新增合同参数验证
func (s *contractService) ValidRuleContractAdd(ctx iris.Context) (*viewmodels.Contracts, error) {
	// 创建一个存放前端传过来参数
	contractsVaild := &viewmodels.Contracts{}
	// 存放raw的值，放入到contractsVaild
	err := ctx.ReadJSON(contractsVaild)
	if err != nil {
		log.Println("folder-ValidRule-ReadForm转换异常, error=", err)
		return contractsVaild, err
	}
	// 验证合同传参
	err = contractsVaild.ValidateAdd()
	if err != nil {
		log.Println("参数验证错误, error=", err)
		return contractsVaild, err
	}

	// xss
	contractsVaild.Code = html.EscapeString(contractsVaild.Code)
	contractsVaild.Name = html.EscapeString(contractsVaild.Name)
	contractsVaild.Price = html.EscapeString(contractsVaild.Price)

	return contractsVaild, nil
}

// 校验编辑接口
func (s *contractService) ValidRuleContractEdi(ctx iris.Context) (*viewmodels.Contracts, error) {
	// 创建一个存放前端传过来参数
	contractsVaild := &viewmodels.Contracts{}
	// 存放raw的值，放入到contractsVaild
	err := ctx.ReadJSON(contractsVaild)
	if err != nil {
		log.Println("folder-ValidRule-ReadForm转换异常, error=", err)
		return contractsVaild, err
	}
	// 验证合同传参
	err = contractsVaild.ValidateEdi()
	if err != nil {
		log.Println("参数验证错误, error=", err)
		return contractsVaild, err
	}

	contractsVaild.Content = html.EscapeString(contractsVaild.Content)
	contractsVaild.Name = html.EscapeString(contractsVaild.Name)
	contractsVaild.Price = html.EscapeString(contractsVaild.Price)

	contractsVaild.PartyA = html.EscapeString(contractsVaild.PartyA)
	contractsVaild.PartyASigner = html.EscapeString(contractsVaild.PartyASigner)
	contractsVaild.PartyB = html.EscapeString(contractsVaild.PartyB)
	contractsVaild.PartyBSigner = html.EscapeString(contractsVaild.PartyBSigner)

	return contractsVaild, nil
}

// 校验删除合同参数
func (s *contractService) ValidRuleContractDel(ctx iris.Context) (*viewmodels.Contracts, error) {
	// 创建一个存放前端传过来参数
	contractsVaild := &viewmodels.Contracts{}
	// 存放raw的值，放入到contractsVaild
	err := ctx.ReadForm(contractsVaild)
	if err != nil {
		log.Println("folder-ValidRule-ReadForm转换异常, error=", err)
		return contractsVaild, err
	}
	// 验证合同传参
	err = contractsVaild.ValidateDel()
	if err != nil {
		log.Println("参数验证错误, error=", err)
		return contractsVaild, err
	}

	return contractsVaild, nil
}

//------------------------------------------------------------
// 获得项目节
func (s *contractService) Get(treeId int, bidsectionId int, projectId int) *viewmodels.TreeSectionContract {
	// 1.获得项目节
	section := s.treeContractDao.Get(treeId, bidsectionId, projectId, 0)
	// 2.构造数据
	sectionVM := s.makeSectionView(section)
	// 3.更新 上移和下一的限制
	youngerBrotherList := s.treeContractDao.GetYoungerBrother(section.Serial, section.Depth, section.ParentId, bidsectionId, projectId, 0)
	if len(youngerBrotherList) == 0 {
		sectionVM.IsEnd = true
	}
	sectionVM.ElderBrother = true
	elderBrotherList := s.treeContractDao.GetElderBrother(section.Serial, section.Depth, section.ParentId, bidsectionId, projectId, 0)
	if len(elderBrotherList) == 0 {
		sectionVM.ElderBrother = false
	}
	return sectionVM
}

// 获得合同详情
func (s *contractService) GetContract(contractId int) *viewmodels.Contracts {
	contract := s.contractDao.Get(contractId)
	contractsVM := &viewmodels.Contracts{}

	id, _ := comm.AesEncrypt(strconv.Itoa(contract.Id), conf.SignSecret)
	treeId, _ := comm.AesEncrypt(strconv.Itoa(contract.TreeId), conf.SignSecret)
	bidsectionId, _ := comm.AesEncrypt(strconv.Itoa(contract.BidsectionId), conf.SignSecret)

	contractsVM.Id = id
	contractsVM.TreeId = treeId
	contractsVM.ContractsType = contract.ContractsType
	contractsVM.BidsectionId = bidsectionId

	contractsVM.Name = contract.Name
	contractsVM.Content = contract.Content
	contractsVM.Code = contract.Code
	contractsVM.PartyA = contract.PartyA
	contractsVM.PartyASigner = contract.PartyASigner
	contractsVM.PartyB = contract.PartyB
	contractsVM.PartyBSigner = contract.PartyBSigner
	contractsVM.Remarks = contract.Remarks
	contractsVM.Price = contract.Price
	contractsVM.Returned = contract.Returned
	contractsVM.Paid = contract.Paid
	contractsVM.Status = contract.Status
	contractsVM.Locking = contract.Locking

	contractsVM.CreateTime = contract.CreateTime.Format(conf.SysTimeform)
	contractsVM.UpdateTime = contract.UpdateTime.Format(conf.SysTimeform)
	contractsVM.SignerTime = contract.SignerTime.Format(conf.SysTimeform)

	return contractsVM
}

// 新增合同
func (s *contractService) Add(contractData *viewmodels.Contracts, projectId int, bidsectionId int, treeId int) error {
	// 1. 项目节存在
	contracts := s.treeContractDao.Get(treeId, bidsectionId, projectId, 0)
	if contracts.Id == 0 {
		return errors.New("未找到项目节")
	}
	// k := int32(projectId)
	// 2.项目节是没有合同
	if contracts.ContractId != 0 {
		return errors.New("该项目节上已经存在合同")
	}

	// 3.新增合同 --合计标段上的金额
	contractsCm := &models.CmContracts{}
	contractsCm.Code = contractData.Code
	contractsCm.Name = contractData.Name
	contractsCm.ContractsType = 1
	contractsCm.Price = contractData.Price
	contractsCm.Returned = "0"
	contractsCm.Paid = "0"
	contractsCm.TreeId = treeId
	contractsCm.ProjectId = projectId
	contractsCm.BidsectionId = bidsectionId
	contractsCm.Status = 0
	contractsCm.CreateTime = time.Now()
	contractsCm.UpdateTime = time.Now()

	err := s.contractDao.Add(contractsCm)
	if err != nil {
		return err
	}

	// 3.获得该标段下合同总数 - 总收入金额
	contractTotal, priceTotal := s.getContractTotalAndPrice(bidsectionId, projectId, 0)
	// 更新标段目录上合同金额和总数
	err = s.treeDao.UpdateContractsAndIncomePrice(projectId, bidsectionId, contractTotal, priceTotal)
	if err != nil {
		return err
	}

	return nil
}

// 更新合同
func (s *contractService) Update(contractData *viewmodels.Contracts, projectId int, bidsectionId int, treeId int) error {
	// 1. 项目节存在
	contractsTree := s.treeContractDao.Get(treeId, bidsectionId, projectId, 0)
	if contractsTree.Id == 0 {
		return errors.New("未找到项目节")
	}
	// 2.项目节是没有合同
	if contractsTree.ContractId == 0 {
		return errors.New("该项目节上没有找到合同")
	}

	// 3.合同锁定 不能删除
	if contractsTree.ContractLocking == 1 {
		return errors.New("该合同已锁定")
	}

	contractsCm := &models.CmContracts{}
	contractsCm.Id = contractsTree.ContractId
	contractsCm.Content = contractData.Content
	contractsCm.Name = contractData.Name
	contractsCm.Price = contractData.Price
	contractsCm.PartyA = contractData.PartyA
	contractsCm.PartyASigner = contractData.PartyASigner
	contractsCm.PartyB = contractData.PartyB
	contractsCm.PartyBSigner = contractData.PartyBSigner

	loc, _ := time.LoadLocation("Local")
	SignerTime, err := time.ParseInLocation(conf.SysTimeform, contractData.SignerTime, loc)
	if err != nil {
		return errors.New("签约时间填写异常")
	}
	contractsCm.SignerTime = SignerTime
	contractsCm.Remarks = contractData.Remarks

	columns := []string{"Content", "Name", "Price", "PartyA", "PartyASigner", "PartyB", "PartyBSigner"}
	err = s.contractDao.Update(contractsCm, columns, projectId, bidsectionId, treeId)
	if err != nil {
		return err
	}
	// 3.获得该标段下合同总数 - 总收入金额
	contractTotal, priceTotal := s.getContractTotalAndPrice(bidsectionId, projectId, 0)
	// 更新标段目录上合同金额和总数
	err = s.treeDao.UpdateContractsAndIncomePrice(projectId, bidsectionId, contractTotal, priceTotal)
	if err != nil {
		return err
	}
	return nil
}

// 删除合同
func (s *contractService) Delete(projectId int, bidsectionId int, treeId int, id int) error {
	// 1. 项目节存在
	contractsTree := s.treeContractDao.Get(treeId, bidsectionId, projectId, 0)
	if contractsTree.Id == 0 {
		return errors.New("未找到项目节")
	}
	// 2.项目节是没有合同
	if contractsTree.ContractId == 0 {
		return errors.New("该项目节上没有找到合同")
	}

	// 3.合同锁定 不能删除
	if contractsTree.ContractLocking == 1 {
		return errors.New("该合同已锁定")
	}

	// 删除合同
	err := s.contractDao.Delete(projectId, bidsectionId, treeId, id)
	if err != nil {
		return err
	}
	// 3.获得该标段下合同总数 - 总收入金额
	contractTotal, priceTotal := s.getContractTotalAndPrice(bidsectionId, projectId, 0)
	// 更新标段目录上合同金额和总数
	err = s.treeDao.UpdateContractsAndIncomePrice(projectId, bidsectionId, contractTotal, priceTotal)
	if err != nil {
		return err
	}

	// 4.更新回款总金额
	err = s.contractReturnDao.UpdateTotalPrice(projectId, bidsectionId, id)
	if err != nil {
		return err
	}

	return nil
}

// 关闭合同
func (s *contractService) Close(projectId int, bidsectionId int, treeId int, id int) error {
	// 1. 项目节存在
	contractsTree := s.treeContractDao.Get(treeId, bidsectionId, projectId, 0)
	if contractsTree.Id == 0 {
		return errors.New("未找到项目节")
	}
	// 2.项目节是没有合同
	if contractsTree.ContractId == 0 {
		return errors.New("该项目节上没有找到合同")
	}

	// 3.合同锁定 不能删除
	if contractsTree.ContractLocking == 1 {
		return errors.New("该合同已锁定")
	}

	// 关闭合同
	err := s.contractDao.Close(projectId, bidsectionId, treeId, id)
	if err != nil {
		return err
	}

	return nil
}

// 解锁合同
func (s *contractService) Unlock(projectId int, bidsectionId int, treeId int, id int) error {
	// 1. 项目节存在
	contractsTree := s.treeContractDao.Get(treeId, bidsectionId, projectId, 0)
	if contractsTree.Id == 0 {
		return errors.New("未找到项目节")
	}
	// 2.项目节是没有合同
	if contractsTree.ContractId == 0 {
		return errors.New("该项目节上没有找到合同")
	}

	// 解锁合同
	err := s.contractDao.Unlock(projectId, bidsectionId, treeId, id)
	if err != nil {
		return err
	}

	return nil
}

//获得合同收入概况
func (s *contractService) GetSurvey(bidsectionId int, projectId int, contractsType int) map[string]interface{} {
	// 1.获得收入合同
	year := time.Now().Year()
	incomeList := s.contractDao.GetTypeYear(bidsectionId, projectId, contractsType, year)
	// 2.初始化
	totalContractPrice := 0.00
	totalTypePrice := 0.00
	performNumber := 0
	closeNumber := 0
	uncloseNumber := 0
	// 3.当年数据初始化
	returnDate := map[string]float64{
		fmt.Sprintf("%d-01", year): 0.00,
		fmt.Sprintf("%d-02", year): 0.00,
		fmt.Sprintf("%d-03", year): 0.00,
		fmt.Sprintf("%d-04", year): 0.00,
		fmt.Sprintf("%d-05", year): 0.00,
		fmt.Sprintf("%d-06", year): 0.00,
		fmt.Sprintf("%d-07", year): 0.00,
		fmt.Sprintf("%d-08", year): 0.00,
		fmt.Sprintf("%d-09", year): 0.00,
		fmt.Sprintf("%d-10", year): 0.00,
		fmt.Sprintf("%d-11", year): 0.00,
		fmt.Sprintf("%d-12", year): 0.00,
	}

	for _, item := range incomeList {
		contractPrice, _ := strconv.ParseFloat(item.Price, 64)
		totalContractPrice = totalContractPrice + contractPrice
		typePrice := 0.00
		if contractsType == 1 {
			typePrice, _ = strconv.ParseFloat(item.Returned, 64)
			totalTypePrice = totalTypePrice + typePrice
		} else {
			typePrice, _ = strconv.ParseFloat(item.Paid, 64)
			totalTypePrice = totalTypePrice + typePrice
		}

		if item.Status == 0 {
			performNumber = performNumber + 1
		} else if item.Status == 1 {
			uncloseNumber = uncloseNumber + 1
		} else if item.Status == 2 {
			closeNumber = closeNumber + 1
		}
		returnDate[item.SignerTime.Format(conf.SysTimeformMonth)] = returnDate[item.SignerTime.Format(conf.SysTimeformMonth)] + typePrice
	}
	totalContractPrice, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", totalContractPrice), 64)
	totalTypePrice, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", totalTypePrice), 64)

	ac := accounting.Accounting{Symbol: "", Precision: 2}

	surveryData := map[string]interface{}{
		"totalContractPrice":     totalContractPrice,
		"totalContractPriceShow": ac.FormatMoney(totalContractPrice),
		// "totalReturnPrice":   ac.FormatMoney(totalReturnPrice),
		"performNumber": performNumber,
		"closeNumber":   closeNumber,
		"uncloseNumber": uncloseNumber,
		"returnDate":    returnDate,
	}

	if contractsType == 1 {
		surveryData["totalReturnPriceShow"] = ac.FormatMoney(totalTypePrice)
	} else {
		surveryData["totalPaidPriceShow"] = ac.FormatMoney(totalTypePrice)
	}

	return surveryData
}

// 获得合同总数量和总金额
func (s *contractService) getContractTotalAndPrice(bidsectionId int, projectId int, treeType int) (contractTotal int, priceTotal float64) {

	contractListAll := s.treeContractDao.GetContractAll(bidsectionId, projectId)

	// 获得收入合同
	contractList := s.treeContractDao.GetContract(bidsectionId, projectId, treeType)
	priceTotal = 0.00
	for _, item := range contractList {
		contractPrice, _ := strconv.ParseFloat(item.ContractPrice, 64)
		priceTotal = priceTotal + contractPrice
	}
	// 合同总数
	// contractTotal = len(contractList) + 1
	contractTotal = len(contractListAll)
	// 合同收入总金额
	// price, _ := strconv.ParseFloat(priceString, 64)
	// priceTotal = priceTotal + price
	// 保留2位小数
	priceTotal, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", priceTotal), 64)

	return contractTotal, priceTotal
}
