0

I am trying to create an invoice/PO Form and need some help. I am using 4 models: Client, Shipping, Billing, and PO models. I have the OneToOne relationship between shipping and billing models to the client model and both as foreign keys (please let me know if this method is still ok) in PO model.

models.py ClientBillingAddress and ShippingAddress are identical, except "billing" is replaced with "shipping"

class ClientBillingAddress(models.Model):
    client = models.OneToOneField(Client, on_delete=models.CASCADE, related_name='billing_address')
    billing_location_name = models.CharField(max_length=255, unique=True)
    address_line_1 = models.CharField(max_length=200, blank=True, null=True)
    address_line_2 = models.CharField(max_length=100, blank=True, null=True)
    address_city = models.CharField(max_length=50, blank=True, null=True)
    address_province = models.CharField(max_length=50, blank=True, null=True)
    address_postal = models.CharField(max_length=15, blank=True, null=True)
    address_country = models.CharField(max_length=50, blank=True, null=True)
    phone = models.CharField(max_length=15, null=True, blank=True)
    email_to  = models.CharField(max_length=150, null=True, blank=True)
    email_cc = models.CharField(max_length=150, null=True, blank=True)
    bill_contact_name = models.CharField(null=True, blank=True, max_length=50)
    is_default = models.BooleanField(default=False)

    def get_formatted_address(self):
        address_lines = [self.billing_location_name, self.address_line_1, self.address_line_2]
        address_city_info = f"{self.address_city}, {self.address_province}, {self.address_postal}"
        address_lines.append(address_city_info)
        address_lines.append(self.address_country)

        return "\n".join(address_lines)

    def __str__(self):
        return self.billing_location_name

class ClientPO(models.Model):
    client_PO_number = models.CharField(max_length=50, unique=True)
    customer_company = models.ForeignKey(Client, on_delete=models.CASCADE, related_name="customer_name_PO")
    order_reserved_total = models.PositiveBigIntegerField(default=0)
    order_total = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True, default=Decimal("0.00"))

    order_line = models.PositiveBigIntegerField(default=0)
    order_product = models.ForeignKey(InventoryItemDetail, on_delete=models.CASCADE, related_name="order_products")
    order_qty = models.PositiveBigIntegerField(default=0)

    order_unit_price = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True, default=Decimal("0.00"))
    order_extended_price = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True, default=Decimal("0.00"))
    order_units = models.CharField(max_length=10, choices=UNIT_TYPES, default='EA')

    order_ship_to = models.ForeignKey(ClientShippingAddress, on_delete=models.CASCADE, related_name="order_shipto")
    order_bill_to = models.ForeignKey(ClientBillingAddress, on_delete=models.CASCADE, related_name="order_billto")
    order_open_qty = models.PositiveBigIntegerField(default=0)
    order_shipped_qty = models.PositiveBigIntegerField(default=0)

    order_status = models.CharField(max_length=2, choices=ORDER_STATUS_CHOICES, default='PN')
    order_delivery_due = models.DateTimeField(auto_now=False)

    date_created = models.DateTimeField(auto_now_add=True)
    last_updated = models.DateTimeField(auto_now=True)

    def calculate_extended_value(self):
        # Calculate total value based on the item cost and quantity
        order_extended_price = self.order_unit_price * self.order_qty
        return order_extended_price


    def __str__(self):
        return self.client_PO_number

forms.py:

class ClientPOForm(forms.ModelForm):
    billing_address = forms.CharField(
        widget=forms.Textarea(attrs={
            'class': 'form-textarea w-full resize-none text-xs rounded-lg border border-slate-300 bg-transparent p-2.5 placeholder:text-slate-400/70 hover:border-slate-400 focus:border-primary dark:border-navy-450 dark:hover:border-navy-400 dark:focus:border-accent',
            'readonly': 'readonly',
        })
    )

    shipping_address = forms.CharField(
        widget=forms.Textarea(attrs={
            'class': 'form-textarea w-full resize-none text-xs rounded-lg border border-slate-300 bg-transparent p-2.5 placeholder:text-slate-400/70 hover:border-slate-400 focus:border-primary dark:border-navy-450 dark:hover:border-navy-400 dark:focus:border-accent',
            'readonly': 'readonly',
        })
    )

    class Meta:
        model = ClientPO
        fields = [
            'client_PO_number', 'order_product','order_qty','order_unit_price','order_units',
            'order_ship_to','order_bill_to','order_delivery_due','customer_company'
        ]

views.py

def customer_add_purchase_order(request):
    if request.method == 'POST':
        customer_po_form = ClientPOForm(request.POST)

        if customer_po_form.is_valid():
            customer_po = customer_po_form.save(commit=False)
            customer_po.customer_company = customer_po_form.cleaned_data['customer_company']
            customer_po.save()

            customer_po.slug = slugify(customer_po.client_PO_number)
            customer_po.save()

            messages.success(request, "Customer PO added successfully.")
            return redirect('customer_orders')
        else:
            print(customer_po_form.errors)
    else:
        customer_po_form = ClientPOForm()

    context = {
        'customer_po_form': customer_po_form,
    }

    return render(request, 'client/add_po.html', context)

I am not sure how to handle it from here. Essentially, "customer_company" has a .pk, and i somehow want to capture that pk and populate it inside textfield in template when the company is selected.

inside here

<textarea
id="customer_bill_to_txt"
rows="5"
class="form-textarea"> 
{{ customer_po_form.order_bill_to }} </textarea>

I have tried to do it from forms.py by attempting to capture billing and shipping information

but this only populates class information inside textarea, nothing from client billing/shipping.

class ClientPOForm(forms.ModelForm):
:
:
def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # Set the initial values for billing_address and shipping_address fields
        if self.instance.pk:
            billing_address = self.instance.order_bill_to.get_formatted_billing_address()
            shipping_address = self.instance.order_ship_to.get_formatted_shipping_address()
            self.initial['billing_address'] = billing_address
            self.initial['shipping_address'] = shipping_address

i also tried using ajax from views and inside template..

views.py
def get_client_addresses(request):
    if request.method == 'POST' and request.is_ajax():
        client_id = request.POST.get('client_id')
        client = get_object_or_404(Client, pk=client_id)
        billing_address = get_object_or_404(ClientBillingAddress, client=client)
        shipping_address = get_object_or_404(ClientShippingAddress, client=client)

        data = {
            'billing_address': billing_address.get_formatted_address(),
            'shipping_address': shipping_address.get_formatted_address(),
        }

        return JsonResponse(data)
    else:
        return JsonResponse({'error': 'Invalid request'})

template.html

$(document).ready(function() {
  // Add an event listener to the customer select field
  $('#id_customer_company').change(function() {
    // Get the selected customer ID
    var customerId = $(this).val();

    // Make an AJAX request to get the billing and shipping addresses for the selected customer
    $.ajax({
      url: `/get_client_addresses/${customerId}/`,
      type: 'GET',
      dataType: 'json',
      success: function(data) {
        // Update the textareas with the retrieved addresses
        $('#customer_bill_to_txt').val(data.billing_address);
        $('#customer_ship_to_txt').val(data.shipping_address);
      },
      error: function(xhr, status, error) {
        console.log(xhr.responseText);
      }
    });
  });
});


I am fairly sure I am missing something, but so far, I wasn't able to get the bill_To and ship_to to populate inside the form when selecting company_name. If anyone can help, I would greatly appreciate it.

  • Are you getting any errors when trying to do this? – Dishan Sachin Aug 02 '23 at 02:24
  • Please trim your code to make it easier to find your problem. Follow these guidelines to create a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Community Aug 02 '23 at 04:11

1 Answers1

0

You are using type: 'GET', in your ajax, but in

if request.method == 'POST' and request.is_ajax():

your view is expecting type: 'POST', (or method: 'POST', if you are using jquery 1.9+)

SamSparx
  • 4,629
  • 1
  • 4
  • 16