jaywink /
kakaravaara3
| 1 | # -*- coding: utf-8 -*- |
||
| 2 | import datetime |
||
| 3 | from decimal import Decimal |
||
| 4 | |||
| 5 | import six |
||
| 6 | from django.db.models import Q |
||
| 7 | from django.utils.translation import ugettext_lazy as _ |
||
| 8 | |||
| 9 | from reservable_pricing.models import PeriodPriceModifier |
||
| 10 | from reservations.utils import get_start_and_end_from_request, get_persons_from_request |
||
| 11 | from shoop.admin.base import AdminModule, MenuEntry |
||
| 12 | from shoop.core.models import ShopProduct |
||
| 13 | from shoop.core.pricing import PriceInfo, PricingContext, PricingModule |
||
| 14 | |||
| 15 | |||
| 16 | class ReservablePricingContext(PricingContext): |
||
| 17 | REQUIRED_VALUES = ("start_date", "end_date", "shop") |
||
| 18 | shop = None |
||
| 19 | |||
| 20 | |||
| 21 | class ReservablePricingModule(PricingModule): |
||
| 22 | identifier = "reservable_pricing" |
||
| 23 | name = _("Reservable Pricing") |
||
| 24 | |||
| 25 | pricing_context_class = ReservablePricingContext |
||
| 26 | |||
| 27 | def get_context_from_request(self, request): |
||
| 28 | start_date, end_date = get_start_and_end_from_request(request) |
||
| 29 | persons = get_persons_from_request(request) |
||
| 30 | |||
| 31 | return self.pricing_context_class( |
||
| 32 | shop=request.shop, |
||
| 33 | start_date=start_date, |
||
| 34 | end_date=end_date, |
||
| 35 | persons=persons, |
||
| 36 | ) |
||
| 37 | |||
| 38 | def get_price_info(self, context, product, quantity=1): |
||
| 39 | shop = context.shop |
||
| 40 | |||
| 41 | if isinstance(product, six.integer_types): |
||
| 42 | product_id = product |
||
| 43 | shop_product = ShopProduct.objects.get(product_id=product_id, shop=shop) |
||
| 44 | else: |
||
| 45 | shop_product = product.get_shop_instance(shop) |
||
| 46 | product_id = product.pk |
||
| 47 | |||
| 48 | base_price = (shop_product.default_price_value or 0) * quantity |
||
| 49 | period_modifiers = self.get_period_modifiers(product_id, quantity, context.start_date, context.end_date) |
||
| 50 | per_person_modifiers = self.get_per_person_modifiers(product, context.persons) * quantity |
||
| 51 | total_price = base_price + period_modifiers + per_person_modifiers |
||
| 52 | |||
| 53 | price_info = PriceInfo( |
||
| 54 | price=shop.create_price(total_price), |
||
| 55 | base_price=shop.create_price(total_price), |
||
| 56 | quantity=quantity, |
||
| 57 | ) |
||
| 58 | # Add some custom information to PriceInfo before returning it |
||
| 59 | price_info.period_modifiers = Decimal(period_modifiers) |
||
| 60 | price_info.per_person_modifiers = Decimal(per_person_modifiers) |
||
| 61 | return price_info |
||
| 62 | |||
| 63 | @staticmethod |
||
| 64 | def get_per_person_modifiers(product, persons): |
||
| 65 | """Get added price for per person priced reservables.""" |
||
| 66 | if not product.type.identifier == "reservable" or not persons: |
||
| 67 | return 0 |
||
| 68 | reservable = product.reservable |
||
| 69 | if not reservable.pricing_per_person: |
||
| 70 | return 0 |
||
| 71 | difference = max(0, persons - reservable.pricing_per_person_included) |
||
| 72 | return difference * reservable.pricing_per_person_price |
||
| 73 | |||
| 74 | @staticmethod |
||
| 75 | def get_period_modifiers(product_id, quantity, start_date, end_date): |
||
| 76 | """Get amount to add to base price from period modifiers.""" |
||
| 77 | modifiers_price = 0 |
||
| 78 | if start_date and end_date: |
||
| 79 | # Get any period modifiers that could affect this period |
||
| 80 | date_filters = Q(start_date__lte=start_date, end_date__gte=start_date) | \ |
||
| 81 | Q(start_date__lte=end_date, end_date__gte=end_date) |
||
| 82 | modifiers = PeriodPriceModifier.objects.filter( |
||
|
0 ignored issues
–
show
|
|||
| 83 | modifier__gt=0, product=product_id |
||
| 84 | ).filter(date_filters) |
||
| 85 | # Add to the total days * modifier value |
||
| 86 | for modifier in modifiers: |
||
| 87 | start_from = max(start_date, modifier.start_date) |
||
| 88 | # We add +1 day to end because end date is always the *next day*, ie the day guest leaves |
||
| 89 | end_on = min(end_date, modifier.end_date + datetime.timedelta(days=1)) |
||
| 90 | days = min((end_on - start_from).days, quantity) |
||
| 91 | modifiers_price += days * modifier.modifier |
||
| 92 | return modifiers_price |
||
| 93 | |||
| 94 | |||
| 95 | class PriceModifierModule(AdminModule): |
||
| 96 | name = _("Price modifiers") |
||
| 97 | category = name |
||
| 98 | |||
| 99 | def get_menu_entries(self, request): |
||
| 100 | return [ |
||
| 101 | MenuEntry( |
||
| 102 | text=_("Period price modifiers"), icon="fa fa-money", |
||
| 103 | url="reservable_pricing:modifiers.list", |
||
| 104 | category=self.category |
||
| 105 | ), |
||
| 106 | ## TODO: immlementation unfinished |
||
| 107 | # MenuEntry( |
||
| 108 | # text=_("Day of Week"), icon="fa fa-money", |
||
| 109 | # url="reservable_pricing:modifiers.list", |
||
| 110 | # category=self.category |
||
| 111 | # ), |
||
| 112 | ] |
||
| 113 |
This check looks for calls to members that are non-existent. These calls will fail.
The member could have been renamed or removed.