def create_booking(self, order, cart_data, uid, count, comment): brain = get_catalog_brain(self.context, uid) # brain could be None if uid for item in cookie which no longer exists. if not brain: return buyable = brain.getObject() item_state = get_item_state(buyable, self.request) if not item_state.validate_count(count): msg = u'Item no longer available {0}'.format(buyable.id) logger.warning(msg) raise CheckoutError(msg) item_stock = get_item_stock(buyable) # stock not applied, state new if item_stock is None: available = None state = ifaces.STATE_NEW # calculate state from stock else: if item_stock.available is not None: item_stock.available -= float(count) available = item_stock.available state = ifaces.STATE_NEW if available is None or available >= 0.0\ else ifaces.STATE_RESERVED item_data = get_item_data_provider(buyable) vendor = acquire_vendor_or_shop_root(buyable) booking = OOBTNode() booking.attrs['email'] = order.attrs['personal_data.email'] booking.attrs['uid'] = uuid.uuid4() booking.attrs['buyable_uid'] = uid booking.attrs['buyable_count'] = count booking.attrs['buyable_comment'] = comment booking.attrs['order_uid'] = order.attrs['uid'] booking.attrs['vendor_uid'] = uuid.UUID(IUUID(vendor)) booking.attrs['creator'] = order.attrs['creator'] booking.attrs['created'] = order.attrs['created'] booking.attrs['exported'] = False booking.attrs['title'] = brain and brain.Title or 'unknown' booking.attrs['net'] = item_data.net booking.attrs['vat'] = item_data.vat booking.attrs['discount_net'] = item_data.discount_net(count) booking.attrs['currency'] = cart_data.currency booking.attrs['quantity_unit'] = item_data.quantity_unit booking.attrs['remaining_stock_available'] = available booking.attrs['state'] = state booking.attrs['salaried'] = ifaces.SALARIED_NO booking.attrs['tid'] = 'none' shipping_info = queryAdapter(buyable, IShippingItem) if shipping_info: booking.attrs['shippable'] = shipping_info.shippable else: booking.attrs['shippable'] = False trading_info = queryAdapter(buyable, ifaces.ITrading) if trading_info: booking.attrs['item_number'] = trading_info.item_number booking.attrs['gtin'] = trading_info.gtin else: booking.attrs['item_number'] = None booking.attrs['gtin'] = None return booking
def critical_available_message(self): available = self.available if not get_item_data_provider(self.context).quantity_unit_float: available = int(available) message = _(u'critical_available_message', default=u'Just ${available} items(s) left.', mapping={'available': available}) return message
def full_available_message(self): available = self.available if available is None: available = '' else: if not get_item_data_provider(self.context).quantity_unit_float: available = int(available) message = _(u'full_available_message', default=u'${available} items(s) available.', mapping={'available': available}) return message
def item_vat(self, item): """VAT of item. """ uid, count, _ = item try: obj = api.content.get(UID=uid) except ValueError: return Decimal(0) data = get_item_data_provider(obj) discount_net = data.discount_net(count) item_net = Decimal(str(data.net)) - discount_net return (item_net / Decimal(100)) * Decimal(str(data.vat)) * count
def item_vat(self, item): """VAT of item. """ cat = self.catalog uid, count, _ = item brain = cat(UID=uid) if not brain: return Decimal(0) data = get_item_data_provider(brain[0].getObject()) discount_net = data.discount_net(count) item_net = Decimal(str(data.net)) - discount_net return (item_net / Decimal(100)) * Decimal(str(data.vat)) * count
def net(self, items): """Overall net of items. """ cat = self.catalog net = Decimal(0) for uid, count, _ in items: brain = cat(UID=uid) if not brain: continue data = get_item_data_provider(brain[0].getObject()) discount_net = data.discount_net(count) item_net = Decimal(str(data.net)) - discount_net net += item_net * count return net
def vat(self, items): """Overall VAT of items. """ vat = Decimal(0) for uid, count, unused in items: try: obj = api.content.get(UID=uid) except ValueError: continue data = get_item_data_provider(obj) discount_net = data.discount_net(count) item_net = Decimal(str(data.net)) - discount_net vat += (item_net / Decimal(100)) * Decimal(str(data.vat)) * count return vat
def net(self, items): """Overall net of items. """ net = Decimal(0) for uid, count, unused in items: try: obj = api.content.get(UID=uid) except ValueError: continue data = get_item_data_provider(obj) discount_net = data.discount_net(count) item_net = Decimal(str(data.net)) - discount_net net += item_net * count return net
def vat(self, items): """Overall VAT of items. """ cat = self.catalog vat = Decimal(0) for uid, count, _ in items: brain = cat(UID=uid) if not brain: continue data = get_item_data_provider(brain[0].getObject()) discount_net = data.discount_net(count) item_net = Decimal(str(data.net)) - discount_net vat += (item_net / Decimal(100)) * Decimal(str(data.vat)) * count return vat
def getPrice(self, item): if SHOP_AVAILABLE: item_data = get_item_data_provider(item) net_price = Decimal(item_data.net) vat = item_data.vat if vat % 2 != 0: item_vat = Decimal(vat).quantize(Decimal('1.0')) else: item_vat = Decimal(vat) gross_price = net_price + net_price / Decimal(100) * item_vat return gross_price else: return float(0.0)
def validate_count(self, uid, count): """Validate setting cart item count for uid. uid - Is the cart item UID. count - If count is 0, it means that a cart item is going to be deleted, which is always allowed. If count is > 0, it's the aggregated item count in cart. """ count = float(count) # count is 0, return if not count: return {'success': True, 'error': ''} cart_item = get_object_by_uid(self.context, uid) item_data = get_item_data_provider(cart_item) buyable_event = self.acquire_event(cart_item) buyable_event_data = IBuyableEventData(buyable_event) # cart count limit is set for all event tickets if buyable_event_data.cart_count_limit: related_uids = IEventTickets(cart_item).related_uids aggregated_count = count items = extractitems(readcookie(self.request)) for ticket_uid in related_uids: # we already have count for item to validate if uid == ticket_uid: continue aggregated_count += float( aggregate_cart_item_count(ticket_uid, items)) if aggregated_count > buyable_event_data.cart_count_limit: message = translate( _('event_tickets_limit_reached', default="Limit of tickets for this event reached"), context=self.request) return {'success': False, 'error': message} # cart count limit is set for ticket elif item_data.cart_count_limit: if count > item_data.cart_count_limit: message = translate( _('ticket_limit_reached', default="Limit for this ticket reached"), context=self.request) return {'success': False, 'error': message} # stock check item_state = get_item_state(cart_item, self.request) if item_state.validate_count(count): return {'success': True, 'error': ''} # out of stock message = translate(_('trying_to_add_more_tickets_than_available', default="Not enough tickets available, abort."), context=self.request) return {'success': False, 'error': message}
def validate_count(self, uid, count): """Validate setting cart item count for uid. uid - Is the cart item UID. count - If count is 0, it means that a cart item is going to be deleted, which is always allowed. If count is > 0, it's the aggregated item count in cart. """ count = float(count) # count is 0, return if not count: return {'success': True, 'error': ''} cart_item = get_object_by_uid(self.context, uid) item_data = get_item_data_provider(cart_item) buyable_event = self.acquire_event(cart_item) buyable_event_data = IBuyableEventData(buyable_event) # cart count limit is set for all event tickets if buyable_event_data.cart_count_limit: related_uids = IEventTickets(cart_item).related_uids aggregated_count = count items = extractitems(readcookie(self.request)) for ticket_uid in related_uids: # we already have count for item to validate if uid == ticket_uid: continue aggregated_count += float( aggregate_cart_item_count(ticket_uid, items)) if aggregated_count > buyable_event_data.cart_count_limit: message = translate(_( 'event_tickets_limit_reached', default="Limit of tickets for this event reached"), context=self.request) return {'success': False, 'error': message} # cart count limit is set for ticket elif item_data.cart_count_limit: if count > item_data.cart_count_limit: message = translate(_('ticket_limit_reached', default="Limit for this ticket reached"), context=self.request) return {'success': False, 'error': message} # stock check item_state = get_item_state(cart_item, self.request) if item_state.validate_count(count): return {'success': True, 'error': ''} # out of stock message = translate(_('trying_to_add_more_tickets_than_available', default="Not enough tickets available, abort."), context=self.request) return {'success': False, 'error': message}
def overbook_available_message(self): state = get_item_state(self.context, self.request) overbook = self.stock.overbook if overbook is None: reservable = '' else: reservable = overbook - state.reserved if not get_item_data_provider(self.context).quantity_unit_float: reservable = int(reservable) message = _(u'overbook_available_message', default=u'Item is sold out. You can pre-order ' u'${reservable} items. As soon as item is ' u'available again, it gets delivered.', mapping={'reservable': reservable}) return message
def _discounted_items(self, items): # return list of 2-tuples containing (net, vat percent) of discounted # items in cart. count is already considered. # XXX: from gross result = list() cat = api.portal.get_tool(name='portal_catalog') for uid, count, comment in items: brain = cat(UID=uid) if not brain: continue data = get_item_data_provider(brain[0].getObject()) discount_net = data.discount_net(count) item_net = Decimal(str(data.net)) - discount_net result.append((item_net * count, Decimal(str(data.vat)))) return result
def vat(self, items): """Overall VAT of items. """ vat = Decimal(0) for uid, count, unused in items: try: obj = api.content.get(UID=uid) except ValueError: continue if obj is None: continue data = get_item_data_provider(obj) discount_net = data.discount_net(count) item_net = Decimal(str(data.net)) - discount_net vat += (item_net / Decimal(100)) * Decimal(str(data.vat)) * count return vat
def net(self, items): """Overall net of items. """ net = Decimal(0) for uid, count, unused in items: try: obj = api.content.get(UID=uid) except ValueError: continue if obj is None: continue data = get_item_data_provider(obj) discount_net = data.discount_net(count) item_net = Decimal(str(data.net)) - discount_net net += item_net * count return net
def cart_items(self, items): ret = list() sm = getSecurityManager() for uid, count, comment in items: try: obj = api.content.get(UID=uid) except ValueError: remove_item_from_cart(self.request, uid) continue if obj is None: remove_item_from_cart(self.request, uid) continue if not sm.checkPermission(permissions.BuyItems, obj): remove_item_from_cart(self.request, uid) continue buyable_period = queryAdapter(obj, IBuyablePeriod) if buyable_period: now = datetime.now() effective = buyable_period.effective if effective and now < effective: remove_item_from_cart(self.request, uid) continue expires = buyable_period.expires if expires and now > expires: remove_item_from_cart(self.request, uid) continue data = get_item_data_provider(obj) title = data.title discount_net = data.discount_net(count) price = (Decimal(str(data.net)) - discount_net) * count if data.display_gross: price = price + price / Decimal(100) * Decimal(str(data.vat)) url = obj.absolute_url() description = obj.Description() comment_required = data.comment_required quantity_unit_float = data.quantity_unit_float quantity_unit = translate(data.quantity_unit, context=self.request) preview_image_url = get_item_preview(obj).url item_state = get_item_state(obj, self.request) no_longer_available = not item_state.validate_count(count) alert = item_state.alert(count) item = self.item(uid, title, count, price, url, comment, description, comment_required, quantity_unit_float, quantity_unit, preview_image_url, no_longer_available, alert) ret.append(item) return ret
def cart_items(self, items): ret = list() sm = getSecurityManager() for uid, count, comment in items: try: obj = api.content.get(UID=uid) except ValueError: remove_item_from_cart(self.request, uid) continue if obj is None: remove_item_from_cart(self.request, uid) continue if not sm.checkPermission(permissions.BuyItems, obj): remove_item_from_cart(self.request, uid) continue buyable_period = queryAdapter(obj, IBuyablePeriod) if buyable_period: now = datetime.now() effective = buyable_period.effective if effective and now < effective: remove_item_from_cart(self.request, uid) continue expires = buyable_period.expires if expires and now > expires: remove_item_from_cart(self.request, uid) continue data = get_item_data_provider(obj) title = data.title discount_net = data.discount_net(count) price = (Decimal(str(data.net)) - discount_net) * count if data.display_gross: price = price + price / Decimal(100) * Decimal(str(data.vat)) url = obj.absolute_url() description = obj.Description() comment_required = data.comment_required quantity_unit_float = data.quantity_unit_float quantity_unit = translate(data.quantity_unit, context=self.request) preview_image_url = get_item_preview(obj).url item_state = get_item_state(obj, self.request) no_longer_available = not item_state.validate_count(count) alert = item_state.alert(count) item = self.item( uid, title, count, price, url, comment, description, comment_required, quantity_unit_float, quantity_unit, preview_image_url, no_longer_available, alert) ret.append(item) return ret
def alert(self, count): stock = get_item_stock(self.context) # stock not applied if stock is None: return '' available = stock.available # no limitation if available is None: return '' reserved = self.reserved exceed = self.exceed # no reservations and no exceed if not reserved and not exceed: # no message return '' item_data = get_item_data_provider(self.context) quantity_unit = item_data.quantity_unit quantity_unit_float = item_data.quantity_unit_float def display_format(num): if quantity_unit_float: return num return int(num) # exceed if exceed: remaining_available = self.remaining_available # partly exceeded if remaining_available > 0: return self.partly_exceeded_alert(display_format(exceed), quantity_unit) # completely exceeded return self.completely_exceeded_alert # reservations if reserved: aggregated_count = float(self.aggregated_count) count = float(count) # some reservations message if aggregated_count > count: return self.some_reservations_alert # number reservations message else: return self.number_reservations_alert(display_format(reserved), quantity_unit) return ''
def product_price(object, **kw): if SHOP_AVAILABLE: try: item_data = get_item_data_provider(object) net_price = Decimal(item_data.net) vat = item_data.vat if vat % 2 != 0: item_vat = Decimal(vat).quantize(Decimal('1.0')) else: item_vat = Decimal(vat) gross_price = net_price + net_price / Decimal(100) * item_vat gross_final = gross_price.quantize(Decimal('1.0')) return str(gross_final) except: return "" else: return ""
def alert(self, count): stock = get_item_stock(self.context) # stock not applied if stock is None: return '' available = stock.available # no limitation if available is None: return '' reserved = self.reserved exceed = self.exceed # no reservations and no exceed if not reserved and not exceed: # no message return '' item_data = get_item_data_provider(self.context) quantity_unit = item_data.quantity_unit quantity_unit_float = item_data.quantity_unit_float def display_format(num): if quantity_unit_float: return num return int(num) # exceed if exceed: remaining_available = self.remaining_available # partly exceeded if remaining_available > 0: return self.partly_exceeded_alert( display_format(exceed), quantity_unit) # completely exceeded return self.completely_exceeded_alert # reservations if reserved: aggregated_count = float(self.aggregated_count) count = float(count) # some reservations message if aggregated_count > count: return self.some_reservations_alert # number reservations message else: return self.number_reservations_alert( display_format(reserved), quantity_unit) return ''
def create_booking(self, order, cart_data, uid, count, comment): brain = get_catalog_brain(self.context, uid) # brain could be None if uid for item in cookie which no longer exists. if not brain: return buyable = brain.getObject() item_state = get_item_state(buyable, self.request) if not item_state.validate_count(item_state.aggregated_count): raise CheckoutError(u'Item no longer available') item_stock = get_item_stock(buyable) if item_stock.available is not None: item_stock.available -= float(count) available = item_stock.available state = (available is None or available >= 0) and ifaces.STATE_NEW\ or ifaces.STATE_RESERVED item_data = get_item_data_provider(buyable) vendor = acquire_vendor_or_shop_root(buyable) booking = OOBTNode() booking.attrs['uid'] = uuid.uuid4() booking.attrs['buyable_uid'] = uid booking.attrs['buyable_count'] = count booking.attrs['buyable_comment'] = comment booking.attrs['order_uid'] = order.attrs['uid'] booking.attrs['vendor_uid'] = uuid.UUID(IUUID(vendor)) booking.attrs['creator'] = order.attrs['creator'] booking.attrs['created'] = order.attrs['created'] booking.attrs['exported'] = False booking.attrs['title'] = brain and brain.Title or 'unknown' booking.attrs['net'] = item_data.net booking.attrs['vat'] = item_data.vat booking.attrs['discount_net'] = item_data.discount_net(count) booking.attrs['currency'] = cart_data.currency booking.attrs['quantity_unit'] = item_data.quantity_unit booking.attrs['remaining_stock_available'] = available booking.attrs['state'] = state booking.attrs['salaried'] = ifaces.SALARIED_NO booking.attrs['tid'] = 'none' return booking
def _item_data(self): return get_item_data_provider(self.context)
def item_net(obj): item_data = get_item_data_provider(obj) return Decimal(item_data.net)