matthiask / plata

Plata - the lean and mean Django-based Shop
https://plata-django-shop.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
197 stars 63 forks source link

'Contact' object has no attribute 'shipping_same_as_billing' #14

Closed minoxtaurus closed 12 years ago

minoxtaurus commented 12 years ago

using examples/custom raises an error

plata/shop/views.py in init, line 300

Check out, fill form, confirm, back to Cart, checkout again.

matthiask commented 12 years ago

Ah well, that's correct (of course).

For the moment, you'll have to override Shop.checkout_form too and provide your own form:

https://gist.github.com/1834813

I'll have to fix the custom example and document this fact somewhere, too.

Thanks for the report!

matthiask commented 12 years ago

Fixed in af13d74268f7baae6d15c50b6694a9625661dd5e

minoxtaurus commented 12 years ago

The custom example is working fine now. Many thanks. Best regards,

Rob

[ TIP: You have to grap the latest version of plata ]

matthiask commented 12 years ago

Regarding the tip: Yes, of course. We are quickly getting near a 1.0 release containing all these fixes and improvements, though.

minoxtaurus commented 12 years ago

Hi Matthias,

Sounds great. I just switched from Django Shop to Plata because of the strange model DS uses for tax (no tax per product but for the whole order ?????)

Concerning shipping, Im still figuring out how to implement different product classes to distinguish physical products (shippable) from digital products (downloadable) and course like products (attendable) and maybe even a product which grants you something (like pre pay)

Still digging...

Best regards

Robert Slotboom

STUDIO345

Van Berchemstraat 133 6981 JA Doesburg

T 0313 795055 W studio345.nl

Op 15 feb 2012, om 16:08 heeft Matthias Kestenholz het volgende geschreven:

Regarding the tip: Yes, of course. We are quickly getting near a 1.0 release containing all these fixes and improvements, though.


Reply to this email directly or view it on GitHub: https://github.com/matthiask/plata/issues/14#issuecomment-3981816

matthiask commented 12 years ago

You have to add a field to your product to distinguish between these shipping classes; you can of course make this very sophisticated, or very simple:

shipping_class = forms.CharField(choices=(('shippable', 'shippable'), ('downloadable', 'downloadable')), ...)

Your overridden Product.handle_order_item method (yes, you'll have to override this one) should put the shipping class somewhere into the OrderItem.data JSON field:

class Product(...):
    def handle_order_item(self, item):
        super(...)...
        data = item.data.copy()
        data.update({'shipping_class': self.shipping_class})
        item.data = data
        # NOTE: Issue #16 will make this dance unnecessary soon 

Note: This is required because the product model is not guaranteed to stay the same for old orders. The product foreign key on OrderItem can even be NULL -- after all, if the website administrator deletes old products for some reason the orders already in the system must not change.

Next, you'll have to write your own order processor to calculate the shipping total and modify PLATA_ORDER_PROCESSORS to contain your shipping processor instead of the one that comes with stock Plata.

Probably something like this:

class ShippingProcessor(ProcessorBase):
    def process(self, order, items):
        classes = [item.data.get('shipping_class') for item in items]
        if only 'downloadable':
            # set shipping to zero
        else:
            # do something else
        self.set_processor_value('total', 'shipping',
            order.shipping_cost - order.shipping_discount + order.shipping_tax)

Finally, if you need a product which "gives you something" (a voucher?) you want to hook into the plata.shop.signals.order_completed signal which is fired upon order completion (aha! :-) ... meaning that the order has been fully paid for, except if you offer cash-on-delivery) and do something depending on values in OrderItem.data (again, it's your responsibility to fill the JSON field with something you can work with later -- Plata itself does not do anything with the JSON field on order items.)

Hope this helps somewhat.

minoxtaurus commented 12 years ago

Hi Matthias,

Reading and comprehending someone else’s code always takes some time. So I appreciate any help!!!

I was heading for the product subclassing way but adding just an extra field is far more efficient.

The shippingProcessor gets a nice job... Just shippable, just downloadable, just ... or a combination :-) Should be possible to code though.

And regarding the order_completed signal. I already used something similar but for user registration (if user created add userProfile). So this should be fixable too...

There is only one thing that bothers me: class PriceBase "Price for a given product, currency, tax class and time period". I guess tax is related and regulated by the state/country where the shop is located. Shouldn’t the tax field be part of the product then?

(or is this a multi national shopping system :-)

For now I am going to spend my time for some other project (ObjC & iOS) but I’ll return to this matter next week.

Thanks again & have a nice weekend,

Rob

Op 15 feb 2012, om 16:34 heeft Matthias Kestenholz het volgende geschreven:

You have to add a field to your product to distinguish between these shipping classes; you can of course make this very sophisticated, or very simple:

shipping_class = forms.CharField(choices=(('shippable', 'shippable'), ('downloadable', 'downloadable')), ...)

Your overridden Product.handle_order_item method (yes, you'll have to override this one) should put the shipping class somewhere into the OrderItem.data JSON field:

   def handle_order_item(self, item):
       super(...)...
       data = item.data.copy()
       data.update({'shipping_class': self.shipping_class})

Note: This is required because the product model is not guaranteed to stay the same for old orders. The product foreign key on OrderItem can even be NULL -- after all, if the website administrator deletes old products for some reason the orders already in the system must not change.

Next, you'll have to write your own order processor to calculate the shipping total and modify PLATA_ORDER_PROCESSORS to contain your shipping processor instead of the one that comes with stock Plata.

Probably something like this:

   def process(self, order, items):
       classes = [item.data.get('shipping_class') for item in items]
       if only 'downloadable':
           # set shipping to zero
       else:
           # do something else

       self.set_processor_value('total', 'shipping',
           order.shipping_cost - order.shipping_discount + order.shipping_tax)

Finally, if you need a product which "gives you something" (a voucher?) you want to hook into the plata.shop.signals.order_completed signal which is fired upon order completion (aha! :-) ... meaning that the order has been fully paid for, except if you offer cash-on-delivery) and do something depending on values in OrderItem.data (again, it's your responsibility to fill the JSON field with something you can work with later -- Plata itself does not do anything with the JSON field on order items.)

Hope this helps somewhat.


Reply to this email directly or view it on GitHub: https://github.com/matthiask/plata/issues/14#issuecomment-3982307

matthiask commented 12 years ago

Hi Rob

On Thu, Feb 16, 2012 at 14:45, minoxtaurus reply@reply.github.com wrote:

There is only one thing that bothers me: class PriceBase "Price for a given product, currency, tax class and time period". I guess tax is related and regulated by the state/country where the shop is located. Shouldn’t the tax field be part of the product then?

(or is this a multi national shopping system :-)

A product can have several prices, one for every currency / tax system or even one for every country if you add a country field to your concrete price class. If the tax field were part of the product, this flexibility would not be possible.

So yes, the tax class is part of the price because Plata supports more than one currency, more than one taxation system and/or more than one country in the same installation.

Best regards Matthias

minoxtaurus commented 12 years ago

Hi Mattias,

Ok, I got the point.

Just upgraded from python 2.6 to 2.7 and reinstalled all the stuff. My sample-shop isn’t working anymore due to changes.

I can rewrite some parts but I guess tomorrow you add other changes... So can you give me an estimation of when there will be a kind of stable version?

Cheers,

Rob

Op 16 feb 2012, om 14:57 heeft Matthias Kestenholz het volgende geschreven:

Hi Rob

On Thu, Feb 16, 2012 at 14:45, minoxtaurus reply@reply.github.com wrote:

There is only one thing that bothers me: class PriceBase "Price for a given product, currency, tax class and time period". I guess tax is related and regulated by the state/country where the shop is located. Shouldn’t the tax field be part of the product then?

(or is this a multi national shopping system :-)

A product can have several prices, one for every currency / tax system or even one for every country if you add a country field to your concrete price class. If the tax field were part of the product, this flexibility would not be possible.

So yes, the tax class is part of the price because Plata supports more than one currency, more than one taxation system and/or more than one country in the same installation.

Best regards Matthias


Reply to this email directly or view it on GitHub: https://github.com/matthiask/plata/issues/14#issuecomment-4001032

matthiask commented 12 years ago

Hi Rob

I'm really sorry for breaking your code (again). The easiest is to do the following now, after installing South:

'''shell ./manage.py migrate shop 0001 --fake ./manage.py migrate contact 0001 --fake ./manage.py migrate discount 0001 --fake ./manage.py migrate '''

We are only days before a v1.0 release. With the addition of South and with v1.0, backwards-incompatible changes will only happen with very good reasons, with very good documentation and with a big note in the release docs.

minoxtaurus commented 12 years ago

Hi Matthias,

Oh no, no apologies; your code, your work. I only wanted to know when things are settling down a bit.

‘Days before’ sounds great because I’m getting to like Plata :-o

The migrations almost worked, had to change the field name in de db myself (will look at that), but it is working again...

Thanks,

Rob

Op 20 feb 2012, om 17:51 heeft Matthias Kestenholz het volgende geschreven:

Hi Rob

I'm really sorry for breaking your code (again). The easiest is to do the following now, after installing South:

''' ./manage.py migrate shop 0001 --fake ./manage.py migrate contact 0001 --fake ./manage.py migrate discount 0001 --fake ./manage.py migrate '''

We are only days before a v1.0 release. With the addition of South and with v1.0, backwards-incompatible changes will only happen with very good reasons, with very good documentation and with a big note in the release docs.


Reply to this email directly or view it on GitHub: https://github.com/matthiask/plata/issues/14#issuecomment-4057185