bid.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. package bid
  2. import (
  3. "errors"
  4. "fmt"
  5. "strings"
  6. "zhiyuan/models"
  7. "zhiyuan/pkg/app"
  8. "zhiyuan/pkg/db"
  9. "zhiyuan/pkg/param/material/bid"
  10. "zhiyuan/pkg/utils"
  11. "zhiyuan/services/form"
  12. "zhiyuan/services/structs"
  13. )
  14. var MatBid models.MatBid
  15. func GetBidList(where map[string]interface{}, fields []string, page app.Page, retVal interface{}) ([]*models.MatBid, error) {
  16. if page.PageNum > 0 && page.PageSize > 0 {
  17. where["_limit"] = db.GetOffset(uint(page.PageNum), uint(page.PageSize))
  18. }
  19. if _, ok := where["deleted_at"]; !ok {
  20. where["deleted_at"] = 0
  21. }
  22. return MatBid.GetMulti(where, fields, retVal)
  23. }
  24. func CountBid(where map[string]interface{}) (int64, error) {
  25. return db.Count(MatBid.TableName(), where)
  26. }
  27. func GetBidOne(where map[string]interface{}, fields []string, dest interface{}) (*models.MatBid, error) {
  28. return MatBid.GetOne(where, fields, dest)
  29. }
  30. func GetTypeNames(typeListMap map[int]string, typeIDs string) string {
  31. typeNames := ""
  32. typeSlice := strings.Split(typeIDs, ",")
  33. for _, vv := range typeSlice {
  34. typeNames += "/" + typeListMap[utils.ToInt(vv)]
  35. }
  36. return strings.TrimLeft(typeNames, "/")
  37. }
  38. func GetTypeIDs(bidList []*structs.MaterialBidList) []int {
  39. typeIDs := make([]int, 0)
  40. for _, v := range bidList {
  41. if v.TypeIDs != "" {
  42. typeSlice := strings.Split(v.TypeIDs, ",")
  43. for _, vv := range typeSlice {
  44. typeIDs = append(typeIDs, utils.ToInt(vv))
  45. }
  46. }
  47. }
  48. return typeIDs
  49. }
  50. func getBidMap(form form.MaterialBidAdd) (map[string]interface{}, error) {
  51. typeID := 0
  52. categoryMap := bid.GetCategoryMap()
  53. if categoryMap[form.Category].Level == 1 {
  54. if len(form.TypeIDs) == 0 {
  55. return nil, errors.New("类别不能为空")
  56. }
  57. typeID = form.TypeIDs[len(form.TypeIDs)-1]
  58. }
  59. itemMap := map[string]interface{}{
  60. "pkg_id": form.PkgID,
  61. "category": form.Category,
  62. "room_type": form.RoomType,
  63. "bid_name": form.BidName,
  64. "unit": form.Unit,
  65. "level": form.Level,
  66. "type_id": typeID,
  67. "description": form.Description,
  68. "type_ids": utils.JoinIntSlice(form.TypeIDs, ","),
  69. "price": form.Price,
  70. }
  71. calcTypeMap := bid.GetCalcTypeMap()
  72. calcTypeParam := calcTypeMap[form.CalcType].Param
  73. calcParam := make(map[string]interface{})
  74. for _, v := range calcTypeParam {
  75. formVal := form.CalcParam[v.Key]
  76. if v.DataType == "float" {
  77. formVal = utils.ToFloat64(formVal)
  78. fmt.Println(formVal)
  79. } else if v.DataType == "int" {
  80. formVal = utils.ToInt(formVal)
  81. }
  82. if formVal == "" || formVal == "0" {
  83. return nil, errors.New(v.Label + "不能为空")
  84. }
  85. calcParam[v.Key] = formVal
  86. }
  87. itemMap["calc_type"] = form.CalcType
  88. itemMap["calc_param"] = utils.JsonEncode(calcParam)
  89. return itemMap, nil
  90. }
  91. func AddBid(form form.MaterialBidAdd) (int64, error) {
  92. bidMap, err := getBidMap(form)
  93. if err != nil {
  94. return 0, err
  95. }
  96. bidID, err := db.InsertOne(MatBid.TableName(), bidMap)
  97. if err != nil {
  98. return 0, nil
  99. }
  100. return bidID, nil
  101. }
  102. func EditBid(form form.MaterialBidAdd, id int) (int64, error) {
  103. bidMap, err := getBidMap(form)
  104. if err != nil {
  105. return 0, err
  106. }
  107. return db.Update(MatBid.TableName(), map[string]interface{}{"id": id}, bidMap)
  108. }
  109. func DelBid(id int) (int64, error) {
  110. return db.DeleteSoft(MatBid.TableName(), map[string]interface{}{"id": id})
  111. }
  112. func CheckBidDuplicate(pkgID int, itemID int, roomType int) bool {
  113. typeInfo, err := GetBidOne(map[string]interface{}{"pkg_id": pkgID, "item_id": itemID, "room_type": roomType}, nil, nil)
  114. return typeInfo != nil && err == nil
  115. }
  116. func GetCalcSetting(houseStyle []structs.HouseStyle) structs.MaterialBidCalcSetting {
  117. calcSetting := structs.MaterialBidCalcSetting{RoomNum: 0, ToiletNum: 0, RestaurantNum: 0, KitchenNum: 0}
  118. for _, v := range houseStyle {
  119. switch v.Type {
  120. case 1:
  121. calcSetting.RoomNum = v.Num
  122. case 2:
  123. calcSetting.RestaurantNum = v.Num
  124. case 3:
  125. calcSetting.KitchenNum = v.Num
  126. case 4:
  127. calcSetting.ToiletNum = v.Num
  128. }
  129. }
  130. return calcSetting
  131. }
  132. func CalcPackageCostExtra(setting structs.MaterialBidCalcSetting) float64 {
  133. packageCostExtra := structs.PackageCostExtra{
  134. Direct: 2500,
  135. Valve: 39,
  136. Hole: 80,
  137. HoleBase: 80,
  138. HoleExtra: 30,
  139. KitchenPipe: 100,
  140. ToiletTopPipe: 200,
  141. ToiletWaterPipe: 50,
  142. }
  143. packageCostExtra.Hole = utils.ToFloat64(packageCostExtra.HoleBase)
  144. packageCostExtra.Hole = utils.FloatAdd(packageCostExtra.Hole, utils.FloatMul(packageCostExtra.HoleExtra, utils.ToFloat64(setting.RoomNum), -1), -1)
  145. packageCostExtra.Hole = utils.FloatAdd(packageCostExtra.Hole, utils.FloatMul(packageCostExtra.HoleExtra, utils.ToFloat64(setting.ToiletNum), -1), -1)
  146. total := utils.FloatAddSlice([]float64{packageCostExtra.Direct, packageCostExtra.Valve, packageCostExtra.Hole, packageCostExtra.KitchenPipe}, -1)
  147. total = utils.FloatAdd(total, utils.FloatMul(utils.ToFloat64(setting.ToiletNum), utils.FloatAdd(packageCostExtra.ToiletTopPipe, packageCostExtra.ToiletWaterPipe, -1), -1), 4)
  148. return total
  149. }
  150. func CalcBidCustomizeMoney(num float64, bidItem *structs.MaterialBidList) float64 {
  151. switch bidItem.CalcType {
  152. case 5: // 可变数*单价
  153. return utils.FloatMulSlice([]float64{num, bidItem.Price}, 4)
  154. case 19: // 可变数*损耗系数*单价
  155. return utils.FloatMulSlice([]float64{num, bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4)
  156. default:
  157. return 0
  158. }
  159. }
  160. func CalcBidItemMoney(param structs.MaterialBidOrderParam, bidItem *structs.MaterialBidList, setting structs.MaterialBidCalcSetting, form form.MaterialBidDetailCalc) float64 {
  161. windowArea := utils.FloatMul(param.Window, bidItem.CalcParamDecode.WindowHeight, -1)
  162. holeArea := utils.FloatMul(param.Hole, bidItem.CalcParamDecode.HoleHeight, -1)
  163. wallArea := utils.FloatMul(param.Round, bidItem.CalcParamDecode.WallHeight, -1)
  164. switch bidItem.CalcType {
  165. case 1: // 地面面积*单价
  166. return utils.FloatMul(param.Area, bidItem.Price, 4)
  167. case 2: // 固定数*单价
  168. return utils.FloatMul(bidItem.CalcParamDecode.FixNum, bidItem.Price, 4)
  169. case 4: // 墙面面积*单价
  170. return utils.FloatMul(utils.FloatSub(wallArea, holeArea, -1), bidItem.Price, 4)
  171. case 6: // 地面面积*损耗系数*单价
  172. return utils.FloatMulSlice([]float64{param.Area, bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4)
  173. case 7: // 基础房间*房间单价
  174. money := utils.ToFloat64(bidItem.CalcParamDecode.BaseMoney)
  175. if setting.RoomNum > bidItem.CalcParamDecode.RoomNum {
  176. money = utils.FloatAdd(money, utils.FloatMul(bidItem.CalcParamDecode.AddRoomMoney, utils.ToFloat64(setting.RoomNum-bidItem.CalcParamDecode.RoomNum), -1), -1)
  177. }
  178. if setting.ToiletNum > bidItem.CalcParamDecode.ToiletNum {
  179. money = utils.FloatAdd(money, utils.FloatMul(bidItem.CalcParamDecode.AddToiletMoney, utils.ToFloat64(setting.ToiletNum-bidItem.CalcParamDecode.ToiletNum), -1), -1)
  180. }
  181. if setting.KitchenNum > bidItem.CalcParamDecode.KitchenNum {
  182. money = utils.FloatAdd(money, utils.FloatMul(bidItem.CalcParamDecode.AddKitchenMoney, utils.ToFloat64(setting.KitchenNum-bidItem.CalcParamDecode.KitchenNum), -1), -1)
  183. }
  184. if setting.RestaurantNum > bidItem.CalcParamDecode.RestaurantNum {
  185. money = utils.FloatAdd(money, utils.FloatMul(bidItem.CalcParamDecode.AddRestaurantMoney, utils.ToFloat64(setting.RestaurantNum-bidItem.CalcParamDecode.RestaurantNum), -1), -1)
  186. }
  187. return utils.FloatRound(money, 4)
  188. case 8: // 全房建筑面积*单价
  189. return utils.FloatMul(param.Area, bidItem.Price, 4)
  190. case 9: // (地面面积+墙面面积-窗户面积)*单价
  191. if param.RoomType == 1 {
  192. wallArea = utils.FloatAdd(wallArea, utils.FloatMul(1.6, bidItem.CalcParamDecode.WallHeight, -1), -1)
  193. }
  194. return utils.FloatMul(utils.FloatSubSlice([]float64{utils.FloatAdd(param.Area, wallArea, -1), holeArea, windowArea}, -1), bidItem.Price, 4)
  195. case 10: // 门洞*单价
  196. return utils.FloatMul(param.Hole, bidItem.Price, 4)
  197. case 11: // 地面周长*单价
  198. return utils.FloatMul(utils.FloatSub(param.Round, param.Hole, -1), bidItem.Price, 4)
  199. case 12: // 门洞周长*单价
  200. return utils.FloatMul(utils.FloatAddSlice([]float64{bidItem.CalcParamDecode.HoleHeight, bidItem.CalcParamDecode.HoleHeight, param.Hole}, -1), bidItem.Price, 4)
  201. case 13: // 门洞面积*单价
  202. return utils.FloatMulSlice([]float64{bidItem.CalcParamDecode.HoleHeight, param.Hole, bidItem.Price}, 4)
  203. case 14: // 墙面面积*损耗系数*单价
  204. return utils.FloatMulSlice([]float64{utils.FloatSub(wallArea, holeArea, -1), bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4)
  205. case 15: // 窗台石
  206. return utils.FloatMul(utils.FloatAdd(3, utils.FloatMul(utils.ToFloat64(setting.RoomNum), 1.9, -1), -1), bidItem.Price, 4)
  207. case 16: // 窗宽*单价
  208. return utils.FloatMul(param.Window, bidItem.Price, 4)
  209. case 17: // (地面面积+客餐厅墙面面积-窗面积)*单价
  210. balconyHoleArea := utils.FloatMul(setting.BalconyHole, bidItem.CalcParamDecode.HoleHeight, -1)
  211. KitchenHoleArea := utils.FloatMul(setting.KitchenHole, bidItem.CalcParamDecode.HoleHeight, -1)
  212. return utils.FloatMul(utils.FloatSubSlice([]float64{utils.FloatAdd(param.Area, wallArea, -1), holeArea, balconyHoleArea, KitchenHoleArea, windowArea}, -1), bidItem.Price, 4)
  213. case 18: // 客餐厅地面周长*单价
  214. return utils.FloatMul(utils.FloatSubSlice([]float64{param.Round, param.Hole, setting.KitchenHole, setting.BalconyHole}, -1), bidItem.Price, 4)
  215. case 19: // (客餐厅墙面面积-窗面积)*单价
  216. balconyHoleArea := utils.FloatMul(setting.BalconyHole, bidItem.CalcParamDecode.HoleHeight, -1)
  217. KitchenHoleArea := utils.FloatMul(setting.KitchenHole, bidItem.CalcParamDecode.HoleHeight, -1)
  218. return utils.FloatMul(utils.FloatSubSlice([]float64{wallArea, holeArea, balconyHoleArea, KitchenHoleArea, windowArea}, -1), bidItem.Price, 4)
  219. case 20: // 地面周长*损耗系数*单价
  220. return utils.FloatMulSlice([]float64{utils.FloatSub(param.Round, param.Hole, -1), bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4)
  221. case 21: // 客餐厅地面周长*损耗系数*单价
  222. return utils.FloatMulSlice([]float64{utils.FloatSubSlice([]float64{param.Round, param.Hole, setting.KitchenHole, setting.BalconyHole}, -1), bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4)
  223. case 22: // 定制品面积*单价
  224. return utils.FloatMul(float64(form.InclusiveArea), bidItem.Price, 4)
  225. case 23: // 定制品面积*损耗系数*单价
  226. return utils.FloatMulSlice([]float64{float64(form.InclusiveArea), bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4)
  227. case 24: // (地面周长-固定数)*损耗系数*单价
  228. return utils.FloatMulSlice([]float64{utils.FloatSubSlice([]float64{param.Round, bidItem.CalcParamDecode.FixNum}, -1), bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4)
  229. case 25: // (阳台墙面面积-阳台窗户面积)*单价
  230. balconyWallArea := utils.FloatMul(setting.BalconyRound, bidItem.CalcParamDecode.WallHeight, -1)
  231. balconyHoleArea := utils.FloatMul(setting.BalconyHole, bidItem.CalcParamDecode.HoleHeight, -1)
  232. balconyWindowArea := utils.FloatMul(setting.BalconyWindow, bidItem.CalcParamDecode.WindowHeight, -1)
  233. return utils.FloatMul(utils.FloatSubSlice([]float64{balconyWallArea, balconyHoleArea, balconyWindowArea}, -1), bidItem.Price, 4)
  234. case 26: // (墙面面积-窗户面积)*单价
  235. if param.RoomType == 1 {
  236. wallArea = utils.FloatAdd(wallArea, utils.FloatMul(1.6, bidItem.CalcParamDecode.WallHeight, -1), -1)
  237. }
  238. return utils.FloatMul(utils.FloatSubSlice([]float64{wallArea, holeArea, windowArea}, -1), bidItem.Price, 4)
  239. case 27: // 阳台地面面积*单价
  240. return utils.FloatMul(setting.BalconyArea, bidItem.Price, 4)
  241. case 28: // 阳台门洞周长*单价
  242. return utils.FloatMul(utils.FloatAddSlice([]float64{bidItem.CalcParamDecode.HoleHeight, bidItem.CalcParamDecode.HoleHeight, setting.BalconyHole}, -1), bidItem.Price, 4)
  243. case 29: // (墙面面积-窗户面积)*损耗系数*单价
  244. if param.RoomType == 1 {
  245. wallArea = utils.FloatAdd(wallArea, utils.FloatMul(1.6, bidItem.CalcParamDecode.WallHeight, -1), -1)
  246. }
  247. return utils.FloatMulSlice([]float64{utils.FloatSubSlice([]float64{wallArea, holeArea, windowArea}, -1), bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4)
  248. case 30: // (地面周长+门洞)*单价
  249. return utils.FloatMul(param.Round, bidItem.Price, 4)
  250. case 31: // (阳台墙面面积-阳台窗户面积)*损耗系数*单价
  251. balconyWallArea := utils.FloatMul(setting.BalconyRound, bidItem.CalcParamDecode.WallHeight, -1)
  252. balconyHoleArea := utils.FloatMul(setting.BalconyHole, bidItem.CalcParamDecode.HoleHeight, -1)
  253. balconyWindowArea := utils.FloatMul(setting.BalconyWindow, bidItem.CalcParamDecode.WindowHeight, -1)
  254. return utils.FloatMulSlice([]float64{utils.FloatSubSlice([]float64{balconyWallArea, balconyHoleArea, balconyWindowArea}, -1), bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4)
  255. case 32: // 最小地面周长*损耗系数*单价
  256. round := param.Round
  257. if round < bidItem.CalcParamDecode.FixNum {
  258. round = bidItem.CalcParamDecode.FixNum
  259. }
  260. return utils.FloatMulSlice([]float64{utils.FloatSub(round, param.Hole, -1), bidItem.CalcParamDecode.LossRate, bidItem.Price}, 4)
  261. default:
  262. return 0
  263. }
  264. }