2010-01-21 12 views
5

tengo que calcular un precio basado en una estructura de tarifas a lo largo de estas líneas:base de datos/algoritmo para una estructura de tarifas

$303.00 fixed price up to 500 units 
$0.023 additional per unit from 501-10,000 units 
$0.022 additional per unit from 10,001-25,000 units 
$0.021 additional per unit from 25,001-50,000 units 

estoy un poco perdido en la creación de una estructura de base de datos y el algoritmo (que se pegue más grande punto) para calcular esto. ¿Alguien ha hecho esto? ¿Hay alguna manera agradable y elegante de calcular este tipo de cosas?

edit: Como un ejemplo, una carrera de 25 100 unidad costaría $ 303,00 para los primeros 500 unidades, $ 218.50 para los próximos 9.500 unidades, $ 330.00 para los próximos 15.000 unidades, y $ 2.10 para los próximos 100 unidades, para un total de $ 853.60.

No no sería sea un simple cálculo de 25.100 * $ 0.021 - Estoy muy consciente de cómo seleccionar y calcular eso.

Similar a la forma en que se evalúa el impuesto a la renta - sobre una base marginal.

+0

¿Es esta tarea? –

+0

No, es para un sistema interno en el trabajo. – ceejayoz

Respuesta

-1

Lo que terminé haciendo:

size units  fixed  per 
1  500 303.000 0.000 
1  10000  0.000 0.023 
1  25000  0.000 0.022 
1  50000  0.000 0.021 



function calculate_price($size, $quantity) { 
    global $db; 

    $price = 0; 
    $count = 0; 

    // fetch rates from the database 
    // note: $size is already sanitised by the calling function 
    $query = "SELECT units, flat, per FROM rates WHERE size={$size} ORDER BY units ASC"; 
    $result = $db->query($query); 

    // step through the rates 
    while($rate = $result->fetch_object()) { 
    // figure out how many of our units fall within this tier 
    $tier_count = max(0, min($quantity - $count, $rate->units - $count)); 

    // calculate the price for this tier, including any flat rate 
    $tier_price = $rate->flat + ($rate->per * $tier_count); 

    // add tier price and count to the totals 
    $price += $tier_price; 
    $count += $tier_count; 

    // store the last, largest number of units rate for any leftovers outside our tiers 
    $last_rate = $rate; 
    } 

    // if some of our units fall outside our defined tiers, use the last tier's values for them 
    if($count < $quantity) { 
    $tier_count = $quantity - $count; 
    $tier_price = $last_rate->flat + ($last_rate->per * $tier_count); 
    $price += $tier_price; 
    $count += $tier_count; 
    } 

    return $price; 
} 
0

Algo como esto:

Product 
------- 
[PK] ProductID 


Price 
----- 
[PK] PriceID 
[FK] ProductID 
Price 
QtyMin 
QtyMax 

Así efectivamente un 1-muchos relación entre producto y precio. Puede usar un valor centinela para el máximo si necesita una tarifa fija independientemente de la cantidad.

+0

Eso no cuenta para tener precios fijos y por unidad, y es más el cálculo de los resultados de la base de datos con los que estoy luchando. – ceejayoz

3

Python

from collections import namedtuple 

RateRule= namedtuple('RateRule', ['qty_band','fixed','per_unit'])  

rate_table = [ 
    RateRule(500, 303, None), 
    RateRule(9500, None, 0.023), 
    RateRule(15000, None, 0.022), 
    RateRule(25000, None, 0.021) 
] 

def total_price(units, rate_table): 
    # Base 
    total = rate_table[0].fixed 
    units_purchased_so_far = rate_table[0].qty_band 
    # Whole Price Bands 
    rule = 1 
    while units > units_purchased_so_far + rate_table[rule].qty_band: 
     total += rate_table[rule].qty_band * rate_table[rule].per_unit 
     units_purchased_so_far += rate_table[rule].qty_band 
     rule += 1 
    # Units within the top Price Band 
    if units > units_purchased_so_far: 
     total += (units - units_purchased_so_far) * rate_table[rule].per_unit 
    return total 
+0

Es el cálculo marginal que me está lanzando a un bucle. No puedo hacer algo así de simple. Como ejemplo, una ejecución de 25,100 unidades costaría $ 303.00 para las primeras 500 unidades, $ 218.50 para las próximas 9.500 unidades, $ 330.00 para las siguientes 15.000 unidades y $ 2.10 para las siguientes 100 unidades. – ceejayoz

+0

Eso no está del todo claro en su pregunta original y no se calculan los descuentos por cantidad de manera 'normal'. Los tuyos todavía están en diferentes bandas. –

+0

No dijo eso, yo también pensé que era $ 0.022 por * cada * unidad si el pedido superaba los 10k. Sin embargo, les daré una pista: los primeros 10k siempre costarán el mismo precio, ya ordenen 10,001 o 100,000 unidades. –

0
SELECT 
CASE is_fixed_price 
    WHEN 1 
    THEN unit_price/? 
    ELSE 
    unit_price 
    END 
FROM rate_structure 
WHERE ? BETWEEN min_qty AND max_qty 

Dónde? es la cantidad que su cliente desea pedir. Sintaxis en la parte superior de mi cabeza, para mysql 5.x. El efecto secundario de esto es la posible acumulación de error de redondeo.

+0

A menos que malinterprete algo en la sintaxis aquí, esto parece hacer un cálculo no marginal en un único punto de precio. – ceejayoz

+0

Oh, mi mal; el costo marginal que especificó no tiene sentido para mí, generalmente (en el contexto de un solo negocio abstracto) el costo unitario disminuye y no aumenta cuando se incrementa la cantidad. Pensé que, en su situación hipotética, el pago mínimo es de $ 300 si solicita 1 unidad o 500. No es así y mi código es incorrecto. Sin embargo, aún puedes usar los condicionales como te mostré para hacer los cálculos como los desees. – mst

3

Supongo que quiere algo flexible, de lo contrario sería trivial codificarlo.

se puede utilizar una tabla de precios:

ID MAX FIX UNIT 
1 500 303 0 
2 9500 0  .23 
3 15000 0  .22 
4 25000 0  .21 

entonces se podría calcular de la siguiente manera:

$items = ?; 
$cost = 0; 
$rows = get_rows("select max, fix, unit from pricing order by id asc"); 
foreach ($rows as $r) 
{ 
    if ($items <= 0) 
     break; 
    $cost += $r['fix'] + min($r['max'], $items) * $r['unit']; 
    $items -= $r['max']; 
} 

he asumido que desea que el algoritmo en PHP.

+0

No había pensado en expresar el número de unidades en "número desde el último punto de precio" en lugar de "número desde 0". Daré una oportunidad, ¡gracias! – ceejayoz

Cuestiones relacionadas