示例#1
0
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')
示例#2
0
    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