como criar uma calculadora de tarifas em Django?

votos
0

Basicamente, eu estou criando uma calculadora de tarifas para uma empresa de utilidade no meu país, com base em uma tabela de taxas progressivas, um exemplo dado abaixo

2. (a) Em qualquer mês para menos de 1.001 galões uma taxa de ........................... .. ... $ 9,23

(B) taxa proporcional para cada galão depois até 2.000 litros inclusive à taxa por 1.000 litros de .................. .. $ 15,89

(C) Taxa proporcional para cada galão acima de 2.000 litros e até 3.000 litros inclusive à taxa por 1.000 litros de. ......... .. $ 17,43

(D) taxa proporcional para cada galão acima de 3.000 litros e até 4.000 litros inclusive à taxa por 1.000 litros de. ......... .. $ 18,45

(E) taxa proporcional para cada galão acima de 4.000 litros e até 5.000 litros inclusive à taxa por 1.000 litros de. ......... .. $ 19,48

(F) taxa proporcional para cada galão acima de 5.000 litros e até 6.000 litros inclusive à taxa por 1.000 litros de. ......... .. $ 20,50

(G) Taxa proporcional para cada galão acima de 6.000 litros e até 7.000 litros inclusive à taxa por 1.000 litros de. ......... .. $ 21,01

(H) Taxa proporcional para cada galão acima de 7.000 litros e até 8.000 litros inclusive à taxa por 1.000 litros de. ......... .. $ 21,53

(I) taxa proporcional para cada galão acima de 8000, à taxa por 1.000 litros de ... $ 22.04

Estou pensando em fazer um modelo de tarifa com os seguintes campos:

  1. área de abastecimento
  2. descrição
  3. from_gallons (começando gama de galões)
  4. to_gallons (gama final de galões)
  5. rate_per_1000g

meu ponto de vista aceitaria post de uma forma com a quantidade de galões, área de abastecimento e deve enviar de volta o uso calculado da tabela de taxas.

Gostaria de fazer algo assim na vista

from models import Rate    
def tarrif_calc(request,gallons,area):
    rate = Rate.objects.get(area_of_supply=area, from_gallons >= gallons, to_gallons <= gallons)
    rate_per_gal = rate.rate_per_1000g/1000
    usage = gallons * rate_per_gal
    return usage

este é o exemplo mais simples que posso pensar, no entanto eu não sei como eu iria lidar com as taxas progressivas ... alguma idéia? Estou no caminho certo?

Publicado 06/05/2009 em 04:46
fonte usuário
Em outras línguas...                            


2 respostas

votos
1

As regras de negócios devem ser expressas em código. Mais informações

Depois de ler a sua pergunta um pouco mais perto, Parece possível que você pode ter muitas dessas tabelas que você tem que consultar. Colocando muitas dessas estruturas semelhantes legitimamente vai para um banco de dados. Por agora eu vou assumir que você tem que. Se você realmente só tem uma mesa, uma análise de caso é provavelmente mais concisa.

Em meus próprios aplicativos Django Descobri que um lugar muito natural para colocar lógica de negócios está em formulários. Modelos parecer óbvio, mas raramente têm acesso ao contexto necessário para tomar decisões informadas sobre o que pode ir para onde.

Normalmente eu vou dividir isso em vários aplicativos, dependentes. Um aplicativo fornece nível muito alto, modelos abstratos e formas. Outro aplicativo estende as formas do primeiro com regras de negócio.

O primeiro problema está consultando o modelo Rate. O trecho de código para que não realmente funcionar. Você não pode passar comparações preguiçosos em python. Django tem um mecanismo para que , por desconfiguração os nomes de argumentos.

rate = Rate.objects.get(area_of_supply=area, from_gallons__gte=gallons, to_gallons__lte=gallons)

Não tenho a certeza que o seu db parece, mas certifique-se há um índice em from_gallons e to_gallons, ou esta consulta será muito lenta.

Seu exemplo não soa como ele realmente altera o estado. Se isso for verdade, então você provavelmente deve estar usando uma visão GET em vez de POST.

Em qualquer caso, a primeira parte da lógica é a mesma. Receber um pedido e validar a entrada de formulário.

# in "myproject/businessrules/forms.py"
from django import forms
from myproject.otherapp.models import Area

class RateForm(forms.Form):
    # declare as instance variables the data actually posted
    quantity = forms.DecimalField(label="amount of gallons")
    area = forms.ModelChoiceField(label="area of supply", queryset=Area.objects.all() )
    # now add the business rule!
    def clean(self):
        cleaned_data = self.cleaned_data # quantity and area area already validated 
        rate = Rate.objects.get(
                            area_of_supply=cleaned_data["area"],
                            from_gallons__gte=cleaned_data["gallons"],
                            to_gallons__lte=cleaned_data["gallons"])
        usage = cleaned_data["gallons"] * rate.rate_per_1000g/1000
        cleaned_data["usage"] = usage
        return cleaned_data

Agora todo o preciso é realmente usá-lo.

# in "myproject/myapp/views.py"
from django.shortcuts import render_to_response
from businessrules import RateForm

def tarrif_view(request):
    form = RateForm(request.GET)
    if form.is_valid():
        context = { "form": form, "valid": True, "usage":form.cleaned_data["usage"] }
    else:
        context = { "form": form, "valid": False }
    return render_to_response("tarrif.html", context)

Muito pouco conhecimento do negócio é incorporado na vista. Só o fato de que a forma armazena um resultado de cálculo limpos em sua chave "uso". Mas desde que a vista é precisamente para obter esse valor, isso está fazendo a coisa certa.

É também necessário um modelo para usar a forma. (Minha habilidade template Django é apenas por isso. Como eu disse, eu prefiro Jinja2 e assim se você)

Pessoalmente, eu não gosto muito de muck com mover os resultados do formulário individuais em um contexto modelo, eu só usar toda a forma, processado. Eu escrevo meus próprios modelos em Jinja2, embora, por isso, se seus designers de template não são dignos de confiança, você pode querer criar seus contextos um pouco mais de cuidado do que isso.

{# in "myproject/templates/tarrif.html" #}
{% if valid %}
Usage: ` usage ` dollars.
{% else %}
<form action="" method="GET">
    ` form `
    <input type="submit" \>
</form>
{% endif %}

Mais uma vez, não mais lógica de negócios aparece no modelo do que a vista.

Respondeu 06/05/2009 em 04:51
fonte usuário

votos
0

Um exemplo muito completo a partir de @TokenMacGuy acima. e vejo o que dizer sobre a lógica do negócio no formulário. Embora eu acho que você não conta para as taxas progressivas que tornaria muito mais tempo.

Eu estou respondendo a minha própria pergunta depois de ter completado o problema e na esperança de que alguém pode entrar e iluminar usuários Django sobre casos de lógica de negócios.

Então aqui está o que eu fiz:

criada pela primeira vez um modelo para as taxas, para que possa ser armazenado no banco de dados. Marquei cada taxa com um nível de taxa de ser capaz de lidar com a classificação progressiva.

class Rate(models.Model):
    area_of_supply = models.ForeignKey(SupplyArea)
    description = models.TextField()
    rate_level = models.CharField(max_length=2,choices=RATE_LEVEL_CHOICES,)
    rate_per_1k_gallons = models.DecimalField(max_digits=10,decimal_places=2)

Eu, então, criado em meu views.py a visão de que vai lidar com o pedido do formulário, (no meu caso, tanto em ajax e uma forma regular). Bem como a "lógica de negócios", no meu caso o "traffic_calc ()"

def tariff(request):
    if request.method == 'POST':
        form = TariffForm(request.POST)
        if form.is_valid():
            gallons = form.cleaned_data['gallons']
            gallons = int(gallons)
            area_id = form.cleaned_data['tariff']
            area = area_id.name
            usage = tarrif_calc(request, area_id, gallons)    
            response_dict = {'gallons': gallons,'area': area,'usage': usage}
            if request.is_ajax():
                return HttpResponse(simplejson.dumps(response_dict), mimetype='application/json')
            return render_to_response('rates/tariff_form.html', response_dict)
    else:
        form = TariffForm()
    return render_to_response('rates/tariff_form.html', {'form': form})

def tarrif_calc(request, area, gallons):
    r_levels = gallons//1000
    remainder = gallons%1000
    usage = 0
    i = 1

    if r_levels < 1:
        rate = Rate.objects.get(area_of_supply=area,rate_level=1)
        usage = rate.rate_per_1k_gallons    
    else:
        if r_levels >= 8:
            while i <= 9:
                rate = Rate.objects.get(area_of_supply=area,rate_level=i)
                usage += rate.rate_per_1k_gallons
                i += 1

            if gallons > 9000:
                remainder = gallons - 9000
            remainder_rate = Rate.objects.get(area_of_supply=area,rate_level=9)
            usage += remainder * remainder_rate.rate_per_1k_gallons/1000
            usage = round(usage,2)
        else:    
            while i <= r_levels:
                rate = Rate.objects.get(area_of_supply=area,rate_level=i)
                usage += rate.rate_per_1k_gallons
                i += 1
            remainder_level = r_levels+1
            if remainder_level >= 9:
                remainder_rate = Rate.objects.get(area_of_supply=area,rate_level=9)
            else:
                remainder_rate = Rate.objects.get(area_of_supply=area, rate_level=remainder_level)    
                usage += remainder * remainder_rate.rate_per_1k_gallons/1000
                usage = round(usage,2)
    return usage

Concordo com @TokenMacGuy .. eu deveria ter provavelmente usado GET, mas usado post eu acho, porque no caso de js não está disponível sob a forma regular, funciona tão bem. Concordo também que a este nível @TokenMacGuy poderia provavelmente apenas a partir de vistas importar tariff_calc e usá-lo em seu forms.py.

Criei então os formulários e modelos necessários eo javascript que lida com a postagem ajax (embora não seja necessário)

// JavaScript Document
$(document).ready(function()    {

$('#tariff_form').submit(function(event){
    event.preventDefault();  // stop the form from submitting and refreshing the page
    var form = this;               // in jQuery, this refers to the current element, which is #article_form

    // grab each form value
    var data = {};
    gallons = $('#id_gallons').val();
    tariff = $('#id_tariff').val();

    // now send the data to the server via AJAX
    if(gallons && tariff)
    {
        $.ajax({
            type: "POST",
            url: "/tariff-calculator/",
            data: "gallons="+gallons+"&tariff="+tariff,
            dataType: "json",
            success: function(json){
                $('#gallons_cont').html(json['gallons']);
                $('#area_cont').html(json['area']);
                $('#usage_cont').html(json['usage'])
                $('#results_json').show('slow');            
            },
            });
    }
    else
    {
        alert('Please Fill All Fields')
    }
}); 

});

Eu estou supondo que ambos os métodos são semelhantes e ambos trabalham (embora eu havn't tentou @ TokenMacGuy de), exceto para o tariff_calc function (), parece MackGuy resolveu o problema por isso, vou conceder-lhe a resposta correta, embora eu adoraria mais feedback sobre a lógica de negócios em forms.py como eu não estou totalmente convencido, ou acho que há uma enorme diferença.

Respondeu 07/05/2009 em 04:39
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more