def create_and_pay_news_order(service_user, news_item_id, order_items_to): """ Creates an order, orderitems, charge and executes the charge. Should be executed in a transaction. Args: service_user (users.User) news_item_id (long) order_items_to (ist of OrderItemTO) Raises: NoCreditCardException ProductNotFoundException """ @db.non_transactional def _get_customer(): return get_customer(service_user) @db.non_transactional def _get_contact(): return Contact.get_one(customer) customer = _get_customer() azzert(customer) contact = _get_contact() azzert(contact) if not customer.stripe_valid: raise NoCreditCardException(customer) extra_city_product_key = Product.create_key(Product.PRODUCT_EXTRA_CITY) news_product_key = Product.create_key(Product.PRODUCT_NEWS_PROMOTION) rmt_key = RegioManagerTeam.create_key(customer.team_id) extra_city_product, news_promotion_product, team = db.get( (extra_city_product_key, news_product_key, rmt_key)) azzert(extra_city_product) azzert(news_promotion_product) azzert(team) new_order_key = Order.create_key(customer.id, OrderNumber.next(team.legal_entity_key)) vat_pct = get_vat_pct(customer, team) total_amount = 0 added_app_ids = [] for order_item in order_items_to: if order_item.product == Product.PRODUCT_EXTRA_CITY: total_amount += extra_city_product.price * order_item.count added_app_ids.append(order_item.app_id) order_item.price = extra_city_product.price elif order_item.product == Product.PRODUCT_NEWS_PROMOTION: total_amount += news_promotion_product.price * order_item.count order_item.price = news_promotion_product.price else: raise BusinessException('Invalid product \'%s\'' % order_item.product) si = get_default_service_identity(users.User(customer.service_email)) if added_app_ids: keys = [App.create_key(app_id) for app_id in added_app_ids] apps = db.get(keys) for app_id, app in zip(added_app_ids, apps): if not app: raise AppNotFoundException(app_id) if app_id in si.appIds: raise BusinessException('Customer %s already has app_id %s' % (customer.id, app_id)) vat = int(round(vat_pct * total_amount / 100)) total_amount_vat_incl = int(round(total_amount + vat)) now_ = now() to_put = [] order = Order(key=new_order_key, date=now_, amount=total_amount, vat_pct=vat_pct, vat=vat, total_amount=total_amount_vat_incl, contact_id=contact.id, status=Order.STATUS_SIGNED, is_subscription_order=False, is_subscription_extension_order=False, date_signed=now_, manager=STORE_MANAGER, team_id=team.id) to_put.append(order) azzert(order.total_amount >= 0) for item in order_items_to: order_item = OrderItem(parent=new_order_key, number=item.number, product_code=item.product, count=item.count, comment=item.comment, price=item.price) order_item.app_id = item.app_id if order_item.product_code == Product.PRODUCT_NEWS_PROMOTION: order_item.news_item_id = news_item_id to_put.append(order_item) db.put(to_put) # Not sure if this is necessary deferred.defer(generate_and_put_order_pdf_and_send_mail, customer, new_order_key, service_user, _transactional=True) # No need for signing here, immediately create a charge. to_put = [] charge = Charge(parent=new_order_key) charge.date = now() charge.type = Charge.TYPE_ORDER_DELIVERY charge.amount = order.amount charge.vat_pct = order.vat_pct charge.vat = order.vat charge.total_amount = order.total_amount charge.manager = order.manager charge.team_id = order.team_id charge.status = Charge.STATUS_PENDING charge.date_executed = now() charge.currency_code = team.legal_entity.currency_code to_put.append(charge) # Update the regiomanager statistics so these kind of orders show up in the monthly statistics deferred.defer(update_regiomanager_statistic, gained_value=order.amount / 100, manager=order.manager, _transactional=True) # Update the customer service si.appIds.extend(added_app_ids) to_put.append(si) # Update the customer object so the newly added apps are added. customer.app_ids.extend(added_app_ids) customer.extra_apps_count += len(added_app_ids) to_put.append(customer) db.put(to_put) deferred.defer(re_index, si.user) # charge the credit card if charge.total_amount > 0: get_payed(customer.id, order, charge) server_settings = get_server_settings() send_to = server_settings.supportWorkers send_to.append(MC_DASHBOARD.email()) channel_data = { 'customer': customer.name, 'no_manager': True, 'amount': charge.amount / 100, 'currency': charge.currency } channel.send_message(map(users.User, send_to), 'shop.monitoring.signed_order', info=channel_data) else: charge.status = Charge.STATUS_EXECUTED charge.date_executed = now() charge.put() channel.send_message(service_user, 'common.billing.orders.update')
def trans(): to_put = list() customer_store_order_key = Order.create_key( customer.id, Order.CUSTOMER_STORE_ORDER_NUMBER) subscription_order_key = Order.create_key( customer.id, customer.subscription_order_number) team_key = RegioManagerTeam.create_key(customer.team_id) product_key = Product.create_key(item.code) if item.app_id is not MISSING: app_key = App.create_key(item.app_id) product, customer_store_order, sub_order, app, team = db.get([ product_key, customer_store_order_key, subscription_order_key, app_key, team_key ]) if sub_order.status != Order.STATUS_SIGNED: raise BusinessException( translate(lang, SOLUTION_COMMON, u'no_unsigned_order')) # check if the provided app does exist azzert(app) else: product, customer_store_order, team = db.get( [product_key, customer_store_order_key, team_key]) # Check if the item has a correct count. # Should never happen unless the user manually recreates the ajax request.. azzert( not product.possible_counts or item.count in product.possible_counts or item.code == Product.PRODUCT_EXTRA_CITY, u'Invalid amount of items supplied') number = 0 existing_order_items = list() vat_pct = get_vat_pct(customer, team) item_already_added = False if not customer_store_order: # create new order customer_store_order = Order(key=customer_store_order_key) customer_store_order.contact_id = contact.key().id() customer_store_order.date = now() customer_store_order.vat_pct = 0 customer_store_order.amount = 0 customer_store_order.vat = 0 customer_store_order.vat_pct = vat_pct customer_store_order.total_amount = 0 customer_store_order.is_subscription_order = False customer_store_order.manager = STORE_MANAGER customer_store_order.team_id = None else: order_items = OrderItem.list_by_order(customer_store_order.key()) for i in order_items: number = i.number if i.number > number else number existing_order_items.append(i) # Check if this city isn't already in the possible pending order. if hasattr(i, 'app_id') and (i.app_id == item.app_id or item.app_id in customer.app_ids): raise BusinessException( translate(lang, SOLUTION_COMMON, u'item_already_added')) else: # Check if there already is an orderitem with the same product code. # If so, add the count of this new item to the existing item. for it in order_items: if it.product_code == item.code and it.product_code not in ( Product.PRODUCT_EXTRA_CITY, Product.PRODUCT_NEWS_PROMOTION): if ( it.count + item.count ) in product.possible_counts or not product.possible_counts: it.count += item.count item_already_added = True to_put.append(it) order_item = it elif len(product.possible_counts) != 0: raise BusinessException( translate( lang, SOLUTION_COMMON, u'cant_order_more_than_specified', allowed_items=max( product.possible_counts))) if item.app_id is not MISSING: remaining_length, _ = get_subscription_order_remaining_length( customer.id, customer.subscription_order_number) subscription_order_charge_date = format_date( datetime.datetime.utcfromtimestamp(sub_order.next_charge_date), locale=lang) total = remaining_length * product.price else: total = product.price * item.count vat = total * vat_pct / 100 total_price = total + vat customer_store_order.amount += total customer_store_order.vat += vat azzert(customer_store_order.total_amount >= 0) customer_store_order.total_amount += total_price service_visible_in_translation = None if not item_already_added: order_item = OrderItem(parent=customer_store_order.key()) order_item.number = number order_item.comment = product.default_comment(customer.language) order_item.product_code = product.code if item.app_id is not MISSING: order_item.count = remaining_length service_visible_in_translation = translate( lang, SOLUTION_COMMON, 'service_visible_in_app', subscription_expiration_date=subscription_order_charge_date, amount_of_months=remaining_length, extra_city_price=product.price_in_euro, app_name=app.name) else: order_item.count = item.count order_item.price = product.price if item.app_id is not MISSING: order_item.app_id = item.app_id to_put.append(order_item) to_put.append(customer_store_order) db.put(to_put) return order_item, service_visible_in_translation