package charge_utils import ( "context" "encoding/json" "fmt" "git.getensh.com/common/gopkgs/database" "google.golang.org/grpc/status" "gorm.io/gorm" "property-garden/errors" dbmodel "property-garden/model" "property-garden/parser" "property-garden/pb" pb_v1 "property-garden/pb/v1" "strings" "time" ) func GetGardenInfos(ids []int64) (map[int64]pb_v1.GardenItem, error) { ret := map[int64]pb_v1.GardenItem{} if len(ids) == 0 { return ret, nil } mreq := pb_v1.GardenInfosRequest{Ids: ids} mreply, err := pb.System.GardenInfos(context.Background(), &mreq) if err != nil { return ret, err } for _, v := range mreply.List { ret[v.Id] = *v } return ret, nil } func GetCompanyInfo(id int64) (*pb_v1.CompanyInfoReply, error) { mreq := pb_v1.CompanyInfoRequest{Id: id} mreply, err := pb.Company.CompanyInfo(context.Background(), &mreq) if err != nil { return nil, err } return mreply, nil } func CheckMchPayMode(gardenId int64) (string, error) { infoM, err := GetGardenInfos([]int64{gardenId}) if err != nil { return "", err } info, ok := infoM[gardenId] if !ok { return "", status.Error(10003, "获取小区信息失败") } if info.PayMode == 1 { return "", status.Error(10003, "暂不支持线上缴费") } if info.PayMode == 2 { if info.MchId == "" { return "", status.Error(10003, "暂不支持线上缴费") } return info.MchId, nil } return parser.Conf.ThirdParty.Wx.AppletMchId, nil } func GetHouseInfos(ids []int64, dbname string) (map[int64]dbmodel.THouseUnitBuilding, error) { ret := map[int64]dbmodel.THouseUnitBuilding{} if len(ids) == 0 { return ret, nil } p := dbmodel.NewHouseUnitBuilding(dbname) where := map[string]interface{}{ "id in": ids, } list, err := p.List(database.DB(), where, nil, -1, -1) if err != nil { return nil, errors.DataBaseError } for _, v := range list { ret[v.ID] = v } return ret, nil } func GetChargeInfos(ids []int64, dbname string) (map[int64]dbmodel.TChargeConf, error) { ret := map[int64]dbmodel.TChargeConf{} if len(ids) == 0 { return ret, nil } p := dbmodel.NewChargeConf(dbname) where := map[string]interface{}{ "id in": ids, } list, err := p.List(database.DB(), where, nil, -1, -1) if err != nil { return nil, errors.DataBaseError } for _, v := range list { ret[v.ID] = v } return ret, nil } func GetAllChargeInfos(dbname string) (map[int64]dbmodel.TChargeConf, error) { ret := map[int64]dbmodel.TChargeConf{} p := dbmodel.NewChargeConf(dbname) list, err := p.List(database.DB(), nil, nil, -1, -1) if err != nil { return nil, errors.DataBaseError } for _, v := range list { ret[v.ID] = v } return ret, nil } func IsChargeBindObj(chargeId int64, dbname string) (bool, error) { p := dbmodel.NewChargeBind(dbname) where := map[string]interface{}{ "charge_id": chargeId, } count, err := p.Count(database.DB(), where, nil) if err != nil { return false, errors.DataBaseError } if count > 0 { return true, nil } return false, nil } func IsObjBindCharge(objId int64, objType int32, dbname string) (bool, error) { p := dbmodel.NewChargeBind(dbname) where := map[string]interface{}{ "obj_id": objId, "obj_type": objType, } count, err := p.Count(database.DB(), where, nil) if err != nil { return false, errors.DataBaseError } if count > 0 { return true, nil } return false, nil } func IsObjsBindCharge(objIds []int64, objType int32, dbname string) (bool, error) { p := dbmodel.NewChargeBind(dbname) where := map[string]interface{}{ "obj_id in": objIds, "obj_type": objType, } count, err := p.Count(database.DB(), where, nil) if err != nil { return false, errors.DataBaseError } if count > 0 { return true, nil } return false, nil } func CompanyDealIncrease(gardenId int64, amount int64, timestamp int64) error { mreq := pb_v1.CompanyDealStatisticSetRequest{GardenId: gardenId, Amount: amount, DateTimestamp: timestamp} _, err := pb.Company.CompanyDealStatisticSet(context.Background(), &mreq) return err } /* func IsBillPaying(billId int64, dbname string) (bool, string, error) { p := dbmodel.NewChargeBill(dbname) where := map[string]interface{}{ "id":billId, "status":PayStatusPaying, } err := p.Find(database.DB(), where) if err != nil && err != gorm.ErrRecordNotFound{ return false, "", errors.DataBaseError } if p.ID == 0 { return false, "", nil } return true, p.OrderId, nil } */ /* func IsPowerPaying(powerId int64, dbname string) (bool, string, error) { p := dbmodel.NewChargeBill(dbname) where := map[string]interface{}{ "charge_power_id":powerId, "status":PayStatusPaying, } err := p.Find(database.DB(), where) if err != nil && err != gorm.ErrRecordNotFound{ return false, "", errors.DataBaseError } if p.ID == 0 { return false, "", nil } return true, p.OrderId, nil } */ /* func IsBillsPaying(billIds []int64, dbname string) (bool, string, error) { p := dbmodel.NewChargeBill(dbname) where := map[string]interface{}{ "id in":billIds, "status":PayStatusPaying, } err := p.Find(database.DB(), where) if err != nil && err != gorm.ErrRecordNotFound{ return false, "", errors.DataBaseError } if p.ID == 0 { return false, "", nil } return true, p.OrderId, nil } */ /* func IsChargesPaying(bindIds []int64, dbname string) (bool, string, error) { p := dbmodel.NewChargeBill(dbname) where := map[string]interface{}{ "charge_bind_id in":bindIds, "status":PayStatusPaying, } err := p.Find(database.DB(), where) if err != nil && err != gorm.ErrRecordNotFound{ return false, "", errors.DataBaseError } if p.ID == 0 { return false, "", nil } return true, p.OrderId, nil } */ /* func IsObjPaying(objId int64, objType int32, dbname string) (bool, string, error) { p := dbmodel.NewChargeBill(dbname) where := map[string]interface{}{ "obj_id":objId, "obj_type":objType, "status":PayStatusPaying, } err := p.Find(database.DB(), where) if err != nil && err != gorm.ErrRecordNotFound{ return false, "", errors.DataBaseError } if p.ID == 0 { return false, "", nil } return true, p.OrderId, nil } */ func ThirdpartyCheckPayingOrder(orderNo string, gardenId int64) (string, string, string, int64, int64) { //TODO 当前只有微信小程序,后续会有其他方式 orderId := fmt.Sprintf("%d-%s", gardenId, orderNo) mreq := &pb_v1.WxAppletQueryRequest{Order: orderId} mreply, err := pb.Thirdparty.WxAppletQuery(context.Background(), mreq) if err != nil { return "", "", "", 0, 0 } return mreply.TradeState, mreply.TradeStateDesc, mreply.TransactionId, mreply.PayTime, mreply.Amount } func SetOrderPayingDesc(orderNo string, payingDesc string, dbname string) error { p := dbmodel.NewChargeOrder(dbname) where := map[string]interface{}{ "order_id": orderNo, } values := map[string]interface{}{ "paying_desc": payingDesc, } err := p.Update(database.DB(), where, values) if err != nil { return errors.DataBaseError } return nil } func SetOrderPayed(payTime int64, orderNo string, transId string, dbname string) error { p := dbmodel.NewChargeOrder(dbname) var err error // 更新订单 where := map[string]interface{}{ "order_id": orderNo, } values := map[string]interface{}{ "status": PayStatusPayed, "pay_time": payTime, "transaction_id": transId, } db := database.DB().Begin() defer func() { if err != nil { db.Rollback() } }() err = p.Update(db, where, values) if err != nil { return errors.DataBaseError } // 插入已付费账单表 bill := dbmodel.NewChargeBill(dbname) where = map[string]interface{}{ "order": orderNo, } var list []dbmodel.TChargeBill list, err = bill.List(database.DB(), where, nil, -1, -1, "") if err != nil { return errors.DataBaseError } for i, _ := range list { list[i].Status = PayStatusPayed list[i].PayTime = payTime } bill.SetTablePayed(dbname) err = bill.InsertMulti(db, &list) if err != nil { return errors.DataBaseError } // 删除待缴表中记录 bill.SetTable(dbname) err = bill.Delete(db, where) if err != nil { return errors.DataBaseError } db.Commit() return nil } func IsOrderPaying(orders []string, dbname string, db *gorm.DB) (bool, error) { if len(orders) == 0 { return false, nil } order := dbmodel.NewChargeOrder(dbname) where := map[string]interface{}{ "order_id in": orders, "deleted": 0, } count, err := order.Count(db, where, nil) if err != nil { return false, errors.DataBaseError } return count > 0, nil } /* func CheckPayingOrder(orderNo string, gardenId int64, dbname string) error { p := dbmodel.NewChargeOrder(dbname) where := map[string]interface{}{ "order_id":orderNo, } err := p.Find(database.DB(), where) if err != nil && err != gorm.ErrRecordNotFound{ return errors.DataBaseError } if p.OrderId == "" { return status.Error(10003, "订单不存在") } if p.Status != PayStatusPaying { return nil } if time.Now().Unix() - p.CreatedAt.Unix() < 60 { return nil } state, desc, transId, payTime, amount := ThirdpartyCheckPayingOrder(orderNo, gardenId) if state == "" { return nil } if state != "SUCCESS" { return SetOrderPayingDesc(orderNo, fmt.Sprintf("%s-%s", state, desc), dbname) } if p.Amount != amount { return SetOrderPayingDesc(orderNo, fmt.Sprintf("三方状态已支付,金额不一致%d", amount), dbname) } return SetOrderPayed(payTime, orderNo, transId, dbname) } */ func PrePayInfo(chargeInfo *dbmodel.TChargeConf, bindInfo *dbmodel.TChargeBind, months int64) (int64, string, string) { array := []string{} amount := int64(0) chargeDesc := dbmodel.ChargeDesc{ ChargeBasis: chargeInfo.ChargeBasis, UnitPrice: chargeInfo.UnitPrice, FixAmount: chargeInfo.FixAmount, FixAmountName: chargeInfo.FixAmountName, CustomFee: bindInfo.CustomFee, } switch chargeInfo.ChargeBasis { case ChargeBasisUsedArea: amount += int64(float64(chargeInfo.UnitPrice*months) * bindInfo.ObjArea) array = append(array, fmt.Sprintf("使用面积:%f", bindInfo.ObjArea)) array = append(array, fmt.Sprintf("单价:%.2f元", float64(chargeInfo.UnitPrice)/100.00)) if chargeInfo.FixAmount > 0 { amount += (chargeInfo.FixAmount * months) array = append(array, fmt.Sprintf("附加费用(%s)每月:%.2f元", chargeInfo.FixAmountName, float64(chargeInfo.FixAmount)/100.00)) } case ChargeBasisArea: amount += int64(float64(chargeInfo.UnitPrice*months) * bindInfo.ObjArea) array = append(array, fmt.Sprintf("建筑面积:%f", bindInfo.ObjArea)) array = append(array, fmt.Sprintf("单价:%.2f元", float64(chargeInfo.UnitPrice)/100.00)) if chargeInfo.FixAmount > 0 { amount += (chargeInfo.FixAmount * months) array = append(array, fmt.Sprintf("附加费用(%s)每月:%.2f元", chargeInfo.FixAmountName, float64(chargeInfo.FixAmount)/100.00)) } case ChargeBasisSpaceArea: amount += int64(float64(chargeInfo.UnitPrice*months) * bindInfo.ObjArea) array = append(array, fmt.Sprintf("车位面积:%f", bindInfo.ObjArea)) array = append(array, fmt.Sprintf("单价:%.2f元", float64(chargeInfo.UnitPrice)/100.00)) if chargeInfo.FixAmount > 0 { amount += (chargeInfo.FixAmount * months) array = append(array, fmt.Sprintf("附加费用(%s)每月:%.2f元", chargeInfo.FixAmountName, float64(chargeInfo.FixAmount)/100.00)) } case ChargeBasisFix: amount += (chargeInfo.FixAmount * months) array = append(array, fmt.Sprintf("固定费用(%s)每月:%.2f元", chargeInfo.FixAmountName, float64(chargeInfo.FixAmount)/100.00)) case ChargeBasisSelf: amount += (bindInfo.CustomFee * months) array = append(array, fmt.Sprintf("自定义费用每月:%.2f元", float64(bindInfo.CustomFee)/100.00)) } desc := strings.Join(array, "\n") bytes, _ := json.Marshal(chargeDesc) return amount, desc, string(bytes) } func GetMonths(start int64, end int64) int64 { startT := time.Unix(start, 0) endT := time.Unix(end, 0) startT = time.Date(startT.Year(), startT.Month(), 1, 0, 0, 0, 0, startT.Location()) endT = time.Date(endT.Year(), startT.Month(), 1, 0, 0, 0, 0, endT.Location()) ret := int64(1) for i := 0; i < 1200; i++ { startT = startT.AddDate(0, 1, 0) if startT.Unix() >= endT.Unix() { return ret } ret++ } return ret } func GetChargeDesc(chargeDesc dbmodel.ChargeDesc) string { array := []string{} switch chargeDesc.ChargeBasis { case ChargeBasisArea: array = append(array, fmt.Sprintf("建筑面积:%.2f", chargeDesc.ObjArea)) array = append(array, fmt.Sprintf("单价:%.2f", float64(chargeDesc.UnitPrice)/100.00)) if chargeDesc.FixAmount > 0 { array = append(array, fmt.Sprintf("附加费用(%s)每月:%.2f元", chargeDesc.FixAmountName, float64(chargeDesc.FixAmount)/100.00)) } case ChargeBasisUsedArea: array = append(array, fmt.Sprintf("使用面积:%.2f", chargeDesc.ObjArea)) array = append(array, fmt.Sprintf("单价:%.2f", float64(chargeDesc.UnitPrice)/100.00)) if chargeDesc.FixAmount > 0 { array = append(array, fmt.Sprintf("附加费用(%s)每月:%.2f元", chargeDesc.FixAmountName, float64(chargeDesc.FixAmount)/100.00)) } case ChargeBasisSpaceArea: array = append(array, fmt.Sprintf("车位面积:%.2f", chargeDesc.ObjArea)) array = append(array, fmt.Sprintf("单价:%.2f", float64(chargeDesc.UnitPrice)/100.00)) if chargeDesc.FixAmount > 0 { array = append(array, fmt.Sprintf("附加费用(%s)每月:%.2f元", chargeDesc.FixAmountName, float64(chargeDesc.FixAmount)/100.00)) } case ChargeBasisFix: array = append(array, fmt.Sprintf("固定费用(%s)每月:%.2f元", chargeDesc.FixAmountName, float64(chargeDesc.FixAmount)/100.00)) case ChargeBasisUsed: array = append(array, fmt.Sprintf("上期用量:%.2f", chargeDesc.PowerLastUsed)) array = append(array, fmt.Sprintf("本期用量:%.2f", chargeDesc.PowerCurrentUsed)) array = append(array, fmt.Sprintf("单价:%.2f", float64(chargeDesc.UnitPrice)/100.00)) if chargeDesc.FixAmount > 0 { array = append(array, fmt.Sprintf("附加费用(%s)每月:%.2f元", chargeDesc.FixAmountName, float64(chargeDesc.FixAmount)/100.00)) } case ChargeBasisSelf: array = append(array, fmt.Sprintf("费用每月:%.2f元", float64(chargeDesc.CustomFee)/100.00)) } return strings.Join(array, "\n") } func GetLateFee(amount int64, billTime int64, chargeInfo *dbmodel.TChargeConf) (int64, int64) { if chargeInfo.LateFeeEnable != 1 { return 0, 0 } if chargeInfo.LateFeePercent == 0 { return 0, 0 } now := time.Now() billt := time.Unix(billTime, 0) // 账单日期 billDay := time.Date(billt.Year(), billt.Month(), billt.Day(), 0, 0, 0, 0, billt.Location()) // 当天日期 nowDay := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()) // 超期开始日期 expireDay := billDay.AddDate(0, 0, int(chargeInfo.LateFeeDay)) if expireDay.Unix() >= nowDay.Unix() { return 0, 0 } days := (nowDay.Unix() - expireDay.Unix()) / (3600 * 24) if chargeInfo.LateFeeMaxDays > 0 && days > chargeInfo.LateFeeMaxDays { days = chargeInfo.LateFeeMaxDays } ret := float64(amount*days*chargeInfo.LateFeePercent) / 1000.00 if ret == 0 { return 0, 0 } return int64(ret), days }