一:区间find/call选取(重量范围与运费)
二:eval哈希表获取(金额范围与奖金点数)
# 销售金额毛利
# 毛利奖金
三:基于数据库的模型设计(产品包装范围与报价费用)
#数据库序列化字段记录
四:设计一张整表和序列化字段存储的利弊
序列化字段,便于设置和存储。(需要程序代码反解析)
整表便于统计,和配置追加。(extra方案)
#serves记录费用类型,serve_charges记录费用类型区间
#serve_charges:中的nation/zone/danger等字段用serves的extra序列化字段反解析匹配。
PROFIT = {
0...10 => ->(o){ 50 },
10...30 => ->(o){ 40 },
30...50 => ->(o){ o },
50...200 => ->(o){ o * 0.5 },
200...1000 => ->(o){ o * 0.4 },
1000..BigDecimal::INFINITY => ->(o){ o * 0.3 }
}
def compute_profit_price
result = PROFIT.find { |k, _| k.include? import_price }
self.profit_price = result[1].call(import_price).to_d.ceil(2)
self.save
end
二:eval哈希表获取(金额范围与奖金点数)
GROSS_RATE =
{"trader_grade_general" => [[" _ < 10000",0],
["10000 <= _ && _ < 15000",0.03],
["15000 <= _ && _ < 20000",0.05],
["20000 <= _ && _ < 25000",0.07],
["25000 <= _ && _ < 30000",0.09],
["30000 <= _ && _< 35000",0.11],
["35000 <= _ && _< 40000",0.13],
["_ >= 40000",0.05,40000]],
"trader_grade_high" => [[" _ < 10000",0],
["10000 <= _ && _ < 15000",0.04],
["15000 <= _ && _ < 20000",0.06],
["20000 <= _ && _ < 25000",0.08],
["25000 <= _ && _ < 30000",0.1],
["30000 <= _ && _< 35000",0.12],
["35000 <= _ && _< 40000",0.14],
["40000 <= _ && _< 45000",0.16],
["45000 <= _ && _< 50000",0.18],
["_ >= 50000",0.06,50000]] }
AMOUNT_RATE =
[["_ < 500",0.01],
["500 <= _ && _ <2000",0.009],
["2000 <= _ && _ <5000",0.008],
["5000 <= _ && _ < 10000",0.007],
["10000 <= _ && _ <50000",0.006],
["50000 <= _ && _ < 100000",0.005],
["100000 <= _ && _ < 500000",0.004],
["_ > 500000",0.003]]
# 销售金额毛利
def self.get_gross_rate(trader_type,amount)
return_rtb_rate = 0
base_trpe = GROSS_RATE[trader_type] || GROSS_RATE["trader_grade_general"]
base_trpe.each_with_index do |rtb_rate,index|
_ = amount
if eval(rtb_rate[0])
case_amount = (index + 1 == base_trpe.size) ? (amount - rtb_rate[2]) : (amount % 5000)
return_rtb_rate += rtb_rate[1] * case_amount
break
else
return_rtb_rate += rtb_rate[1] * 5000
end
end
return return_rtb_rate
end
# 毛利奖金
def self.get_amount_rate(amount)
return_rtb_rate = 0
AMOUNT_RATE.each do |rtb_rate|
_ = amount
if eval(rtb_rate[0])
return_rtb_rate = amount * rtb_rate[1]
break
end
end
return return_rtb_rate
end
三:基于数据库的模型设计(产品包装范围与报价费用)
#数据库序列化字段记录
{:levels=>"24.999-49.999,49.999-99.999,99.999-199.999,199.999-499.999,499.999-", :prices=>"48,46,42,41,37", :area_prices=>""}
{:levels=>"2.999-99.999,99.999-499.999,499.999-", :prices=>"53,50,46", :area_prices=>"53,50,46"}
def price_of_package(package, package_unit, area = nil)
return nil if self.rules.blank?
return nil if !eval(self.rules).is_a?(Hash)
price = nil
#包装单位转化
converted_package = convert_unit(package, package_unit, self.package_unit, self.direct_ship_chemical&.density)
return nil if converted_package.nil?
arr_levels = eval(self.rules)[:levels].split(',')
arr_prices = eval(self.rules)[:prices].split(',')
if area.present? && self.areas.present? && self.areas.include?(area)
arr_prices = eval(self.rules)[:area_prices].split(',')
end
#散装包装
if self.bulk_package?
arr_levels.each.with_index do |p, i|
arr_p = p.split('-') # 10-20 or 500-
if converted_package > arr_p[0].to_d && ( (arr_p[1].present? && converted_package <= arr_p[1].to_d) || arr_p[1].blank? )
price = arr_prices[i].to_d and break
end
# 如果超出所设置的最大包装,则取最大包装的价格
if p == arr_levels.last
price = arr_prices[i].to_d and break
end
end
elsif self.buyout_package?
#标准包装
ls = arr_levels.sort{|x, y| x.to_f <=> y.to_f }
ps = arr_prices.sort{|x, y| x.to_f <=> y.to_f }
level_prices = ls.map.with_index{|x, i| [x.to_f, ps[i].to_f]}
result = level_prices.select{|p| p[0] >= converted_package }
price = result.present? ? result.first[1] : nil
else
# 1.超过最大包装,且是最大包装整数倍, 取最大包装 * 倍数
# 2.小于最大包装,取区间内最大值的价格
ls = arr_levels.sort{|x, y| x.to_f <=> y.to_f }
ps = arr_prices.sort{|x, y| x.to_f <=> y.to_f }
level_prices = ls.map.with_index{|x, i| [x.to_f, ps[i].to_f]}
min = level_prices.first
max = level_prices.last
if converted_package > max[0]
return nil if max[0] == 0
price = converted_package * (max[1] / max[0])
elsif converted_package < min[0]
price = nil
else
front = level_prices.select{|p| p[0] <= converted_package }.last
back = level_prices.select{|p| p[0] >= converted_package }.first
if front[0] == back[0]
price = front[1]
else
if converted_package <= (front[0] + back[0]) / 2.to_f
price = converted_package * (front[1] / front[0])
else
price = converted_package * (back[1] / back[0])
end
end
end
end
price
end
四:设计一张整表和序列化字段存储的利弊
序列化字段,便于设置和存储。(需要程序代码反解析)
整表便于统计,和配置追加。(extra方案)
serialize :extra, Array
def compute_price(amount, extra_hash = {})
extra_hash.stringify_keys!
if self.contain_max
range = { 'min-lte': amount.to_d, 'max-gte': amount.to_d }
else
range = { 'min-lte': amount.to_d, 'max-gt': amount.to_d }
end
query = range.merge(extra_hash.slice(*extra))
charge = self.charges.default_where(query).first
if charge
charge.subtotal = charge.final_price(amount)
charge.default_subtotal = charge.subtotal
else
charge = self.charges.build
charge.subtotal = 0
end
charge
end
#serves记录费用类型,serve_charges记录费用类型区间
#serve_charges:中的nation/zone/danger等字段用serves的extra序列化字段反解析匹配。
create_table "serve_charges", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.bigint "serve_id"
t.decimal "min", precision: 12, scale: 4, default: "0.0"
t.decimal "max", precision: 12, scale: 4, default: "99999999.9999"
t.decimal "price", precision: 10, scale: 2
t.string "type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "nation"
t.string "zone"
t.string "danger"
t.string "is_use_courier"
t.string "good_type"
t.string "incoterms"
t.decimal "base_price", precision: 10, scale: 2, default: "0.0"
t.index ["serve_id"], name: "index_serve_charges_on_serve_id"
end
create_table "serves", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.string "type"
t.string "unit"
t.string "name"
t.string "scope"
t.boolean "verified", default: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "default", default: false
t.boolean "overall", default: true
t.string "extra"
t.boolean "contain_max", default: false
t.string "deal_type"
t.bigint "deal_id"
t.index ["deal_type", "deal_id"], name: "index_serves_on_deal_type_and_deal_id"
end