package bid import ( "errors" "fmt" "strings" "zhiyuan/models" "zhiyuan/pkg/app" "zhiyuan/pkg/db" "zhiyuan/pkg/param/material/bid" "zhiyuan/pkg/utils" "zhiyuan/services/form" "zhiyuan/services/structs" ) var MatBid models.MatBid func GetBidList(where map[string]interface{}, fields []string, page app.Page, retVal interface{}) ([]*models.MatBid, error) { if page.PageNum > 0 && page.PageSize > 0 { where["_limit"] = db.GetOffset(uint(page.PageNum), uint(page.PageSize)) } if _, ok := where["deleted_at"]; !ok { where["deleted_at"] = 0 } return MatBid.GetMulti(where, fields, retVal) } func CountBid(where map[string]interface{}) (int64, error) { return db.Count(MatBid.TableName(), where) } func GetBidOne(where map[string]interface{}, fields []string, dest interface{}) (*models.MatBid, error) { return MatBid.GetOne(where, fields, dest) } func GetTypeNames(typeListMap map[int]string, typeIDs string) string { typeNames := "" typeSlice := strings.Split(typeIDs, ",") for _, vv := range typeSlice { typeNames += "/" + typeListMap[utils.ToInt(vv)] } return strings.TrimLeft(typeNames, "/") } func GetTypeIDs(bidList []*structs.MaterialBidList) []int { typeIDs := make([]int, 0) for _, v := range bidList { if v.TypeIDs != "" { typeSlice := strings.Split(v.TypeIDs, ",") for _, vv := range typeSlice { typeIDs = append(typeIDs, utils.ToInt(vv)) } } } return typeIDs } func getBidMap(form form.MaterialBidAdd) (map[string]interface{}, error) { typeID := 0 categoryMap := bid.GetCategoryMap() if categoryMap[form.Category].Level == 1 { if len(form.TypeIDs) == 0 { return nil, errors.New("类别不能为空") } typeID = form.TypeIDs[len(form.TypeIDs)-1] } itemMap := map[string]interface{}{ "pkg_id": form.PkgID, "category": form.Category, "room_type": form.RoomType, "bid_name": form.BidName, "unit": form.Unit, "level": form.Level, "type_id": typeID, "description": form.Description, "type_ids": utils.JoinIntSlice(form.TypeIDs, ","), "price": form.Price, } calcTypeMap := bid.GetCalcTypeMap() calcTypeParam := calcTypeMap[form.CalcType].Param calcParam := make(map[string]interface{}) for _, v := range calcTypeParam { formVal := form.CalcParam[v.Key] if v.DataType == "float" { formVal = utils.ToFloat64(formVal) fmt.Println(formVal) } else if v.DataType == "int" { formVal = utils.ToInt(formVal) } if formVal == "" || formVal == "0" { return nil, errors.New(v.Label + "不能为空") } calcParam[v.Key] = formVal } itemMap["calc_type"] = form.CalcType itemMap["calc_param"] = utils.JsonEncode(calcParam) return itemMap, nil } func AddBid(form form.MaterialBidAdd) (int64, error) { bidMap, err := getBidMap(form) if err != nil { return 0, err } bidID, err := db.InsertOne(MatBid.TableName(), bidMap) if err != nil { return 0, nil } return bidID, nil } func EditBid(form form.MaterialBidAdd, id int) (int64, error) { bidMap, err := getBidMap(form) if err != nil { return 0, err } return db.Update(MatBid.TableName(), map[string]interface{}{"id": id}, bidMap) } func DelBid(id int) (int64, error) { return db.DeleteSoft(MatBid.TableName(), map[string]interface{}{"id": id}) } func CheckBidDuplicate(pkgID int, itemID int, roomType int) bool { typeInfo, err := GetBidOne(map[string]interface{}{"pkg_id": pkgID, "item_id": itemID, "room_type": roomType}, nil, nil) return typeInfo != nil && err == nil } func GetCalcSetting(houseStyle []structs.HouseStyle) structs.MaterialBidCalcSetting { calcSetting := structs.MaterialBidCalcSetting{RoomNum: 0, ToiletNum: 0, RestaurantNum: 0, KitchenNum: 0} for _, v := range houseStyle { switch v.Type { case 1: calcSetting.RoomNum = v.Num case 2: calcSetting.RestaurantNum = v.Num case 3: calcSetting.KitchenNum = v.Num case 4: calcSetting.ToiletNum = v.Num } } return calcSetting } func CalcPackageCostExtra(setting structs.MaterialBidCalcSetting) float64 { packageCostExtra := structs.PackageCostExtra{ Direct: 2500, Valve: 39, Hole: 80, HoleBase: 80, HoleExtra: 30, KitchenPipe: 100, ToiletTopPipe: 200, ToiletWaterPipe: 50, } packageCostExtra.Hole = utils.ToFloat64(packageCostExtra.HoleBase) packageCostExtra.Hole = utils.FloatAdd(packageCostExtra.Hole, utils.FloatMul(packageCostExtra.HoleExtra, utils.ToFloat64(setting.RoomNum), -1), -1) packageCostExtra.Hole = utils.FloatAdd(packageCostExtra.Hole, utils.FloatMul(packageCostExtra.HoleExtra, utils.ToFloat64(setting.ToiletNum), -1), -1) total := utils.FloatAddSlice([]float64{packageCostExtra.Direct, packageCostExtra.Valve, packageCostExtra.Hole, packageCostExtra.KitchenPipe}, -1) total = utils.FloatAdd(total, utils.FloatMul(utils.ToFloat64(setting.ToiletNum), utils.FloatAdd(packageCostExtra.ToiletTopPipe, packageCostExtra.ToiletWaterPipe, -1), -1), 4) return total } func CalcBidCustomizeMoney(num float64, bidItem *structs.MaterialBidList) float64 { switch bidItem.CalcType { case 5: // 可变数*单价 return utils.FloatMulSlice([]float64{num, bidItem.Price}, 4) case 19: // 可变数*损耗系数*单价 return utils.FloatMulSlice([]float64{num, bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4) default: return 0 } } func CalcBidItemMoney(param structs.MaterialBidOrderParam, bidItem *structs.MaterialBidList, setting structs.MaterialBidCalcSetting, form form.MaterialBidDetailCalc) float64 { windowArea := utils.FloatMul(param.Window, bidItem.CalcParamDecode.WindowHeight, -1) holeArea := utils.FloatMul(param.Hole, bidItem.CalcParamDecode.HoleHeight, -1) wallArea := utils.FloatMul(param.Round, bidItem.CalcParamDecode.WallHeight, -1) switch bidItem.CalcType { case 1: // 地面面积*单价 return utils.FloatMul(param.Area, bidItem.Price, 4) case 2: // 固定数*单价 return utils.FloatMul(bidItem.CalcParamDecode.FixNum, bidItem.Price, 4) case 4: // 墙面面积*单价 return utils.FloatMul(utils.FloatSub(wallArea, holeArea, -1), bidItem.Price, 4) case 6: // 地面面积*损耗系数*单价 return utils.FloatMulSlice([]float64{param.Area, bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4) case 7: // 基础房间*房间单价 money := utils.ToFloat64(bidItem.CalcParamDecode.BaseMoney) if setting.RoomNum > bidItem.CalcParamDecode.RoomNum { money = utils.FloatAdd(money, utils.FloatMul(bidItem.CalcParamDecode.AddRoomMoney, utils.ToFloat64(setting.RoomNum-bidItem.CalcParamDecode.RoomNum), -1), -1) } if setting.ToiletNum > bidItem.CalcParamDecode.ToiletNum { money = utils.FloatAdd(money, utils.FloatMul(bidItem.CalcParamDecode.AddToiletMoney, utils.ToFloat64(setting.ToiletNum-bidItem.CalcParamDecode.ToiletNum), -1), -1) } if setting.KitchenNum > bidItem.CalcParamDecode.KitchenNum { money = utils.FloatAdd(money, utils.FloatMul(bidItem.CalcParamDecode.AddKitchenMoney, utils.ToFloat64(setting.KitchenNum-bidItem.CalcParamDecode.KitchenNum), -1), -1) } if setting.RestaurantNum > bidItem.CalcParamDecode.RestaurantNum { money = utils.FloatAdd(money, utils.FloatMul(bidItem.CalcParamDecode.AddRestaurantMoney, utils.ToFloat64(setting.RestaurantNum-bidItem.CalcParamDecode.RestaurantNum), -1), -1) } return utils.FloatRound(money, 4) case 8: // 全房建筑面积*单价 return utils.FloatMul(param.Area, bidItem.Price, 4) case 9: // (地面面积+墙面面积-窗户面积)*单价 if param.RoomType == 1 { wallArea = utils.FloatAdd(wallArea, utils.FloatMul(1.6, bidItem.CalcParamDecode.WallHeight, -1), -1) } return utils.FloatMul(utils.FloatSubSlice([]float64{utils.FloatAdd(param.Area, wallArea, -1), holeArea, windowArea}, -1), bidItem.Price, 4) case 10: // 门洞*单价 return utils.FloatMul(param.Hole, bidItem.Price, 4) case 11: // 地面周长*单价 return utils.FloatMul(utils.FloatSub(param.Round, param.Hole, -1), bidItem.Price, 4) case 12: // 门洞周长*单价 return utils.FloatMul(utils.FloatAddSlice([]float64{bidItem.CalcParamDecode.HoleHeight, bidItem.CalcParamDecode.HoleHeight, param.Hole}, -1), bidItem.Price, 4) case 13: // 门洞面积*单价 return utils.FloatMulSlice([]float64{bidItem.CalcParamDecode.HoleHeight, param.Hole, bidItem.Price}, 4) case 14: // 墙面面积*损耗系数*单价 return utils.FloatMulSlice([]float64{utils.FloatSub(wallArea, holeArea, -1), bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4) case 15: // 窗台石 return utils.FloatMul(utils.FloatAdd(3, utils.FloatMul(utils.ToFloat64(setting.RoomNum), 1.9, -1), -1), bidItem.Price, 4) case 16: // 窗宽*单价 return utils.FloatMul(param.Window, bidItem.Price, 4) case 17: // (地面面积+客餐厅墙面面积-窗面积)*单价 balconyHoleArea := utils.FloatMul(setting.BalconyHole, bidItem.CalcParamDecode.HoleHeight, -1) KitchenHoleArea := utils.FloatMul(setting.KitchenHole, bidItem.CalcParamDecode.HoleHeight, -1) return utils.FloatMul(utils.FloatSubSlice([]float64{utils.FloatAdd(param.Area, wallArea, -1), holeArea, balconyHoleArea, KitchenHoleArea, windowArea}, -1), bidItem.Price, 4) case 18: // 客餐厅地面周长*单价 return utils.FloatMul(utils.FloatSubSlice([]float64{param.Round, param.Hole, setting.KitchenHole, setting.BalconyHole}, -1), bidItem.Price, 4) case 19: // (客餐厅墙面面积-窗面积)*单价 balconyHoleArea := utils.FloatMul(setting.BalconyHole, bidItem.CalcParamDecode.HoleHeight, -1) KitchenHoleArea := utils.FloatMul(setting.KitchenHole, bidItem.CalcParamDecode.HoleHeight, -1) return utils.FloatMul(utils.FloatSubSlice([]float64{wallArea, holeArea, balconyHoleArea, KitchenHoleArea, windowArea}, -1), bidItem.Price, 4) case 20: // 地面周长*损耗系数*单价 return utils.FloatMulSlice([]float64{utils.FloatSub(param.Round, param.Hole, -1), bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4) case 21: // 客餐厅地面周长*损耗系数*单价 return utils.FloatMulSlice([]float64{utils.FloatSubSlice([]float64{param.Round, param.Hole, setting.KitchenHole, setting.BalconyHole}, -1), bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4) case 22: // 定制品面积*单价 return utils.FloatMul(float64(form.InclusiveArea), bidItem.Price, 4) case 23: // 定制品面积*损耗系数*单价 return utils.FloatMulSlice([]float64{float64(form.InclusiveArea), bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4) case 24: // (地面周长-固定数)*损耗系数*单价 return utils.FloatMulSlice([]float64{utils.FloatSubSlice([]float64{param.Round, bidItem.CalcParamDecode.FixNum}, -1), bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4) case 25: // (阳台墙面面积-阳台窗户面积)*单价 balconyWallArea := utils.FloatMul(setting.BalconyRound, bidItem.CalcParamDecode.WallHeight, -1) balconyHoleArea := utils.FloatMul(setting.BalconyHole, bidItem.CalcParamDecode.HoleHeight, -1) balconyWindowArea := utils.FloatMul(setting.BalconyWindow, bidItem.CalcParamDecode.WindowHeight, -1) return utils.FloatMul(utils.FloatSubSlice([]float64{balconyWallArea, balconyHoleArea, balconyWindowArea}, -1), bidItem.Price, 4) case 26: // (墙面面积-窗户面积)*单价 if param.RoomType == 1 { wallArea = utils.FloatAdd(wallArea, utils.FloatMul(1.6, bidItem.CalcParamDecode.WallHeight, -1), -1) } return utils.FloatMul(utils.FloatSubSlice([]float64{wallArea, holeArea, windowArea}, -1), bidItem.Price, 4) case 27: // 阳台地面面积*单价 return utils.FloatMul(setting.BalconyArea, bidItem.Price, 4) case 28: // 阳台门洞周长*单价 return utils.FloatMul(utils.FloatAddSlice([]float64{bidItem.CalcParamDecode.HoleHeight, bidItem.CalcParamDecode.HoleHeight, setting.BalconyHole}, -1), bidItem.Price, 4) case 29: // (墙面面积-窗户面积)*损耗系数*单价 if param.RoomType == 1 { wallArea = utils.FloatAdd(wallArea, utils.FloatMul(1.6, bidItem.CalcParamDecode.WallHeight, -1), -1) } return utils.FloatMulSlice([]float64{utils.FloatSubSlice([]float64{wallArea, holeArea, windowArea}, -1), bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4) case 30: // (地面周长+门洞)*单价 return utils.FloatMul(param.Round, bidItem.Price, 4) case 31: // (阳台墙面面积-阳台窗户面积)*损耗系数*单价 balconyWallArea := utils.FloatMul(setting.BalconyRound, bidItem.CalcParamDecode.WallHeight, -1) balconyHoleArea := utils.FloatMul(setting.BalconyHole, bidItem.CalcParamDecode.HoleHeight, -1) balconyWindowArea := utils.FloatMul(setting.BalconyWindow, bidItem.CalcParamDecode.WindowHeight, -1) return utils.FloatMulSlice([]float64{utils.FloatSubSlice([]float64{balconyWallArea, balconyHoleArea, balconyWindowArea}, -1), bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4) case 32: // 最小地面周长*损耗系数*单价 round := param.Round if round < bidItem.CalcParamDecode.FixNum { round = bidItem.CalcParamDecode.FixNum } return utils.FloatMulSlice([]float64{utils.FloatSub(round, param.Hole, -1), bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4) default: return 0 } }